github.com/google/go-github/v33@v33.0.0/github/projects_test.go (about)

     1  // Copyright 2016 The go-github AUTHORS. All rights reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style
     4  // license that can be found in the LICENSE file.
     5  
     6  package github
     7  
     8  import (
     9  	"context"
    10  	"encoding/json"
    11  	"fmt"
    12  	"net/http"
    13  	"reflect"
    14  	"strings"
    15  	"testing"
    16  )
    17  
    18  func TestProject_marshall(t *testing.T) {
    19  	testJSONMarshal(t, &Project{}, "{}")
    20  
    21  	u := &Project{
    22  		ID:         Int64(1),
    23  		URL:        String("u"),
    24  		HTMLURL:    String("h"),
    25  		ColumnsURL: String("c"),
    26  		OwnerURL:   String("o"),
    27  		Name:       String("n"),
    28  		Body:       String("b"),
    29  		Number:     Int(1),
    30  		State:      String("s"),
    31  		CreatedAt:  &Timestamp{referenceTime},
    32  		UpdatedAt:  &Timestamp{referenceTime},
    33  		NodeID:     String("n"),
    34  		Creator: &User{
    35  			Login:       String("l"),
    36  			ID:          Int64(1),
    37  			AvatarURL:   String("a"),
    38  			GravatarID:  String("g"),
    39  			Name:        String("n"),
    40  			Company:     String("c"),
    41  			Blog:        String("b"),
    42  			Location:    String("l"),
    43  			Email:       String("e"),
    44  			Hireable:    Bool(true),
    45  			PublicRepos: Int(1),
    46  			Followers:   Int(1),
    47  			Following:   Int(1),
    48  			CreatedAt:   &Timestamp{referenceTime},
    49  			URL:         String("u"),
    50  		},
    51  	}
    52  	want := `{
    53  		"id": 1,
    54  		"url": "u",
    55  		"html_url": "h",
    56  		"columns_url": "c",
    57  		"owner_url": "o",
    58  		"name": "n",
    59  		"body": "b",
    60  		"number": 1,
    61  		"state": "s",
    62  		"created_at": ` + referenceTimeStr + `,
    63  		"updated_at": ` + referenceTimeStr + `,
    64  		"node_id": "n",
    65  		"creator": {
    66  			"login": "l",
    67  			"id": 1,
    68  			"avatar_url": "a",
    69  			"gravatar_id": "g",
    70  			"name": "n",
    71  			"company": "c",
    72  			"blog": "b",
    73  			"location": "l",
    74  			"email": "e",
    75  			"hireable": true,
    76  			"public_repos": 1,
    77  			"followers": 1,
    78  			"following": 1,
    79  			"created_at": ` + referenceTimeStr + `,
    80  			"url": "u"
    81  		}
    82  	}`
    83  	testJSONMarshal(t, u, want)
    84  }
    85  func TestProjectsService_UpdateProject(t *testing.T) {
    86  	client, mux, _, teardown := setup()
    87  	defer teardown()
    88  
    89  	input := &ProjectOptions{
    90  		Name:   String("Project Name"),
    91  		Body:   String("Project body."),
    92  		State:  String("open"),
    93  		Public: Bool(true),
    94  
    95  		OrganizationPermission: String("read"),
    96  	}
    97  
    98  	mux.HandleFunc("/projects/1", func(w http.ResponseWriter, r *http.Request) {
    99  		testMethod(t, r, "PATCH")
   100  		testHeader(t, r, "Accept", mediaTypeProjectsPreview)
   101  
   102  		v := &ProjectOptions{}
   103  		json.NewDecoder(r.Body).Decode(v)
   104  		if !reflect.DeepEqual(v, input) {
   105  			t.Errorf("Request body = %+v, want %+v", v, input)
   106  		}
   107  
   108  		fmt.Fprint(w, `{"id":1}`)
   109  	})
   110  
   111  	project, _, err := client.Projects.UpdateProject(context.Background(), 1, input)
   112  	if err != nil {
   113  		t.Errorf("Projects.UpdateProject returned error: %v", err)
   114  	}
   115  
   116  	want := &Project{ID: Int64(1)}
   117  	if !reflect.DeepEqual(project, want) {
   118  		t.Errorf("Projects.UpdateProject returned %+v, want %+v", project, want)
   119  	}
   120  }
   121  
   122  func TestProjectsService_GetProject(t *testing.T) {
   123  	client, mux, _, teardown := setup()
   124  	defer teardown()
   125  
   126  	mux.HandleFunc("/projects/1", func(w http.ResponseWriter, r *http.Request) {
   127  		testMethod(t, r, "GET")
   128  		testHeader(t, r, "Accept", mediaTypeProjectsPreview)
   129  		fmt.Fprint(w, `{"id":1}`)
   130  	})
   131  
   132  	project, _, err := client.Projects.GetProject(context.Background(), 1)
   133  	if err != nil {
   134  		t.Errorf("Projects.GetProject returned error: %v", err)
   135  	}
   136  
   137  	want := &Project{ID: Int64(1)}
   138  	if !reflect.DeepEqual(project, want) {
   139  		t.Errorf("Projects.GetProject returned %+v, want %+v", project, want)
   140  	}
   141  }
   142  
   143  func TestProjectsService_DeleteProject(t *testing.T) {
   144  	client, mux, _, teardown := setup()
   145  	defer teardown()
   146  
   147  	mux.HandleFunc("/projects/1", func(w http.ResponseWriter, r *http.Request) {
   148  		testMethod(t, r, "DELETE")
   149  		testHeader(t, r, "Accept", mediaTypeProjectsPreview)
   150  	})
   151  
   152  	_, err := client.Projects.DeleteProject(context.Background(), 1)
   153  	if err != nil {
   154  		t.Errorf("Projects.DeleteProject returned error: %v", err)
   155  	}
   156  }
   157  
   158  func TestProjectsService_ListProjectColumns(t *testing.T) {
   159  	client, mux, _, teardown := setup()
   160  	defer teardown()
   161  
   162  	wantAcceptHeaders := []string{mediaTypeProjectsPreview}
   163  	mux.HandleFunc("/projects/1/columns", func(w http.ResponseWriter, r *http.Request) {
   164  		testMethod(t, r, "GET")
   165  		testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", "))
   166  		testFormValues(t, r, values{"page": "2"})
   167  		fmt.Fprint(w, `[{"id":1}]`)
   168  	})
   169  
   170  	opt := &ListOptions{Page: 2}
   171  	columns, _, err := client.Projects.ListProjectColumns(context.Background(), 1, opt)
   172  	if err != nil {
   173  		t.Errorf("Projects.ListProjectColumns returned error: %v", err)
   174  	}
   175  
   176  	want := []*ProjectColumn{{ID: Int64(1)}}
   177  	if !reflect.DeepEqual(columns, want) {
   178  		t.Errorf("Projects.ListProjectColumns returned %+v, want %+v", columns, want)
   179  	}
   180  }
   181  
   182  func TestProjectsService_GetProjectColumn(t *testing.T) {
   183  	client, mux, _, teardown := setup()
   184  	defer teardown()
   185  
   186  	mux.HandleFunc("/projects/columns/1", func(w http.ResponseWriter, r *http.Request) {
   187  		testMethod(t, r, "GET")
   188  		testHeader(t, r, "Accept", mediaTypeProjectsPreview)
   189  		fmt.Fprint(w, `{"id":1}`)
   190  	})
   191  
   192  	column, _, err := client.Projects.GetProjectColumn(context.Background(), 1)
   193  	if err != nil {
   194  		t.Errorf("Projects.GetProjectColumn returned error: %v", err)
   195  	}
   196  
   197  	want := &ProjectColumn{ID: Int64(1)}
   198  	if !reflect.DeepEqual(column, want) {
   199  		t.Errorf("Projects.GetProjectColumn returned %+v, want %+v", column, want)
   200  	}
   201  }
   202  
   203  func TestProjectsService_CreateProjectColumn(t *testing.T) {
   204  	client, mux, _, teardown := setup()
   205  	defer teardown()
   206  
   207  	input := &ProjectColumnOptions{Name: "Column Name"}
   208  
   209  	mux.HandleFunc("/projects/1/columns", func(w http.ResponseWriter, r *http.Request) {
   210  		testMethod(t, r, "POST")
   211  		testHeader(t, r, "Accept", mediaTypeProjectsPreview)
   212  
   213  		v := &ProjectColumnOptions{}
   214  		json.NewDecoder(r.Body).Decode(v)
   215  		if !reflect.DeepEqual(v, input) {
   216  			t.Errorf("Request body = %+v, want %+v", v, input)
   217  		}
   218  
   219  		fmt.Fprint(w, `{"id":1}`)
   220  	})
   221  
   222  	column, _, err := client.Projects.CreateProjectColumn(context.Background(), 1, input)
   223  	if err != nil {
   224  		t.Errorf("Projects.CreateProjectColumn returned error: %v", err)
   225  	}
   226  
   227  	want := &ProjectColumn{ID: Int64(1)}
   228  	if !reflect.DeepEqual(column, want) {
   229  		t.Errorf("Projects.CreateProjectColumn returned %+v, want %+v", column, want)
   230  	}
   231  }
   232  
   233  func TestProjectsService_UpdateProjectColumn(t *testing.T) {
   234  	client, mux, _, teardown := setup()
   235  	defer teardown()
   236  
   237  	input := &ProjectColumnOptions{Name: "Column Name"}
   238  
   239  	mux.HandleFunc("/projects/columns/1", func(w http.ResponseWriter, r *http.Request) {
   240  		testMethod(t, r, "PATCH")
   241  		testHeader(t, r, "Accept", mediaTypeProjectsPreview)
   242  
   243  		v := &ProjectColumnOptions{}
   244  		json.NewDecoder(r.Body).Decode(v)
   245  		if !reflect.DeepEqual(v, input) {
   246  			t.Errorf("Request body = %+v, want %+v", v, input)
   247  		}
   248  
   249  		fmt.Fprint(w, `{"id":1}`)
   250  	})
   251  
   252  	column, _, err := client.Projects.UpdateProjectColumn(context.Background(), 1, input)
   253  	if err != nil {
   254  		t.Errorf("Projects.UpdateProjectColumn returned error: %v", err)
   255  	}
   256  
   257  	want := &ProjectColumn{ID: Int64(1)}
   258  	if !reflect.DeepEqual(column, want) {
   259  		t.Errorf("Projects.UpdateProjectColumn returned %+v, want %+v", column, want)
   260  	}
   261  }
   262  
   263  func TestProjectsService_DeleteProjectColumn(t *testing.T) {
   264  	client, mux, _, teardown := setup()
   265  	defer teardown()
   266  
   267  	mux.HandleFunc("/projects/columns/1", func(w http.ResponseWriter, r *http.Request) {
   268  		testMethod(t, r, "DELETE")
   269  		testHeader(t, r, "Accept", mediaTypeProjectsPreview)
   270  	})
   271  
   272  	_, err := client.Projects.DeleteProjectColumn(context.Background(), 1)
   273  	if err != nil {
   274  		t.Errorf("Projects.DeleteProjectColumn returned error: %v", err)
   275  	}
   276  }
   277  
   278  func TestProjectsService_MoveProjectColumn(t *testing.T) {
   279  	client, mux, _, teardown := setup()
   280  	defer teardown()
   281  
   282  	input := &ProjectColumnMoveOptions{Position: "after:12345"}
   283  
   284  	mux.HandleFunc("/projects/columns/1/moves", func(w http.ResponseWriter, r *http.Request) {
   285  		testMethod(t, r, "POST")
   286  		testHeader(t, r, "Accept", mediaTypeProjectsPreview)
   287  
   288  		v := &ProjectColumnMoveOptions{}
   289  		json.NewDecoder(r.Body).Decode(v)
   290  		if !reflect.DeepEqual(v, input) {
   291  			t.Errorf("Request body = %+v, want %+v", v, input)
   292  		}
   293  	})
   294  
   295  	_, err := client.Projects.MoveProjectColumn(context.Background(), 1, input)
   296  	if err != nil {
   297  		t.Errorf("Projects.MoveProjectColumn returned error: %v", err)
   298  	}
   299  }
   300  
   301  func TestProjectsService_ListProjectCards(t *testing.T) {
   302  	client, mux, _, teardown := setup()
   303  	defer teardown()
   304  
   305  	mux.HandleFunc("/projects/columns/1/cards", func(w http.ResponseWriter, r *http.Request) {
   306  		testMethod(t, r, "GET")
   307  		testHeader(t, r, "Accept", mediaTypeProjectsPreview)
   308  		testFormValues(t, r, values{
   309  			"archived_state": "all",
   310  			"page":           "2"})
   311  		fmt.Fprint(w, `[{"id":1}]`)
   312  	})
   313  
   314  	opt := &ProjectCardListOptions{
   315  		ArchivedState: String("all"),
   316  		ListOptions:   ListOptions{Page: 2}}
   317  	cards, _, err := client.Projects.ListProjectCards(context.Background(), 1, opt)
   318  	if err != nil {
   319  		t.Errorf("Projects.ListProjectCards returned error: %v", err)
   320  	}
   321  
   322  	want := []*ProjectCard{{ID: Int64(1)}}
   323  	if !reflect.DeepEqual(cards, want) {
   324  		t.Errorf("Projects.ListProjectCards returned %+v, want %+v", cards, want)
   325  	}
   326  }
   327  
   328  func TestProjectsService_GetProjectCard(t *testing.T) {
   329  	client, mux, _, teardown := setup()
   330  	defer teardown()
   331  
   332  	mux.HandleFunc("/projects/columns/cards/1", func(w http.ResponseWriter, r *http.Request) {
   333  		testMethod(t, r, "GET")
   334  		testHeader(t, r, "Accept", mediaTypeProjectsPreview)
   335  		fmt.Fprint(w, `{"id":1}`)
   336  	})
   337  
   338  	card, _, err := client.Projects.GetProjectCard(context.Background(), 1)
   339  	if err != nil {
   340  		t.Errorf("Projects.GetProjectCard returned error: %v", err)
   341  	}
   342  
   343  	want := &ProjectCard{ID: Int64(1)}
   344  	if !reflect.DeepEqual(card, want) {
   345  		t.Errorf("Projects.GetProjectCard returned %+v, want %+v", card, want)
   346  	}
   347  }
   348  
   349  func TestProjectsService_CreateProjectCard(t *testing.T) {
   350  	client, mux, _, teardown := setup()
   351  	defer teardown()
   352  
   353  	input := &ProjectCardOptions{
   354  		ContentID:   12345,
   355  		ContentType: "Issue",
   356  	}
   357  
   358  	mux.HandleFunc("/projects/columns/1/cards", func(w http.ResponseWriter, r *http.Request) {
   359  		testMethod(t, r, "POST")
   360  		testHeader(t, r, "Accept", mediaTypeProjectsPreview)
   361  
   362  		v := &ProjectCardOptions{}
   363  		json.NewDecoder(r.Body).Decode(v)
   364  		if !reflect.DeepEqual(v, input) {
   365  			t.Errorf("Request body = %+v, want %+v", v, input)
   366  		}
   367  
   368  		fmt.Fprint(w, `{"id":1}`)
   369  	})
   370  
   371  	card, _, err := client.Projects.CreateProjectCard(context.Background(), 1, input)
   372  	if err != nil {
   373  		t.Errorf("Projects.CreateProjectCard returned error: %v", err)
   374  	}
   375  
   376  	want := &ProjectCard{ID: Int64(1)}
   377  	if !reflect.DeepEqual(card, want) {
   378  		t.Errorf("Projects.CreateProjectCard returned %+v, want %+v", card, want)
   379  	}
   380  }
   381  
   382  func TestProjectsService_UpdateProjectCard(t *testing.T) {
   383  	client, mux, _, teardown := setup()
   384  	defer teardown()
   385  
   386  	input := &ProjectCardOptions{
   387  		ContentID:   12345,
   388  		ContentType: "Issue",
   389  	}
   390  
   391  	mux.HandleFunc("/projects/columns/cards/1", func(w http.ResponseWriter, r *http.Request) {
   392  		testMethod(t, r, "PATCH")
   393  		testHeader(t, r, "Accept", mediaTypeProjectsPreview)
   394  
   395  		v := &ProjectCardOptions{}
   396  		json.NewDecoder(r.Body).Decode(v)
   397  		if !reflect.DeepEqual(v, input) {
   398  			t.Errorf("Request body = %+v, want %+v", v, input)
   399  		}
   400  
   401  		fmt.Fprint(w, `{"id":1, "archived":false}`)
   402  	})
   403  
   404  	card, _, err := client.Projects.UpdateProjectCard(context.Background(), 1, input)
   405  	if err != nil {
   406  		t.Errorf("Projects.UpdateProjectCard returned error: %v", err)
   407  	}
   408  
   409  	want := &ProjectCard{ID: Int64(1), Archived: Bool(false)}
   410  	if !reflect.DeepEqual(card, want) {
   411  		t.Errorf("Projects.UpdateProjectCard returned %+v, want %+v", card, want)
   412  	}
   413  }
   414  
   415  func TestProjectsService_DeleteProjectCard(t *testing.T) {
   416  	client, mux, _, teardown := setup()
   417  	defer teardown()
   418  
   419  	mux.HandleFunc("/projects/columns/cards/1", func(w http.ResponseWriter, r *http.Request) {
   420  		testMethod(t, r, "DELETE")
   421  		testHeader(t, r, "Accept", mediaTypeProjectsPreview)
   422  	})
   423  
   424  	_, err := client.Projects.DeleteProjectCard(context.Background(), 1)
   425  	if err != nil {
   426  		t.Errorf("Projects.DeleteProjectCard returned error: %v", err)
   427  	}
   428  }
   429  
   430  func TestProjectsService_MoveProjectCard(t *testing.T) {
   431  	client, mux, _, teardown := setup()
   432  	defer teardown()
   433  
   434  	input := &ProjectCardMoveOptions{Position: "after:12345"}
   435  
   436  	mux.HandleFunc("/projects/columns/cards/1/moves", func(w http.ResponseWriter, r *http.Request) {
   437  		testMethod(t, r, "POST")
   438  		testHeader(t, r, "Accept", mediaTypeProjectsPreview)
   439  
   440  		v := &ProjectCardMoveOptions{}
   441  		json.NewDecoder(r.Body).Decode(v)
   442  		if !reflect.DeepEqual(v, input) {
   443  			t.Errorf("Request body = %+v, want %+v", v, input)
   444  		}
   445  	})
   446  
   447  	_, err := client.Projects.MoveProjectCard(context.Background(), 1, input)
   448  	if err != nil {
   449  		t.Errorf("Projects.MoveProjectCard returned error: %v", err)
   450  	}
   451  }
   452  
   453  func TestProjectsService_AddProjectCollaborator(t *testing.T) {
   454  	client, mux, _, teardown := setup()
   455  	defer teardown()
   456  
   457  	opt := &ProjectCollaboratorOptions{
   458  		Permission: String("admin"),
   459  	}
   460  
   461  	mux.HandleFunc("/projects/1/collaborators/u", func(w http.ResponseWriter, r *http.Request) {
   462  		testMethod(t, r, "PUT")
   463  		testHeader(t, r, "Accept", mediaTypeProjectsPreview)
   464  
   465  		v := &ProjectCollaboratorOptions{}
   466  		json.NewDecoder(r.Body).Decode(v)
   467  		if !reflect.DeepEqual(v, opt) {
   468  			t.Errorf("Request body = %+v, want %+v", v, opt)
   469  		}
   470  
   471  		w.WriteHeader(http.StatusNoContent)
   472  	})
   473  
   474  	_, err := client.Projects.AddProjectCollaborator(context.Background(), 1, "u", opt)
   475  	if err != nil {
   476  		t.Errorf("Projects.AddProjectCollaborator returned error: %v", err)
   477  	}
   478  }
   479  
   480  func TestProjectsService_AddCollaborator_invalidUser(t *testing.T) {
   481  	client, _, _, teardown := setup()
   482  	defer teardown()
   483  
   484  	_, err := client.Projects.AddProjectCollaborator(context.Background(), 1, "%", nil)
   485  	testURLParseError(t, err)
   486  }
   487  
   488  func TestProjectsService_RemoveCollaborator(t *testing.T) {
   489  	client, mux, _, teardown := setup()
   490  	defer teardown()
   491  
   492  	mux.HandleFunc("/projects/1/collaborators/u", func(w http.ResponseWriter, r *http.Request) {
   493  		testMethod(t, r, "DELETE")
   494  		testHeader(t, r, "Accept", mediaTypeProjectsPreview)
   495  		w.WriteHeader(http.StatusNoContent)
   496  	})
   497  
   498  	_, err := client.Projects.RemoveProjectCollaborator(context.Background(), 1, "u")
   499  	if err != nil {
   500  		t.Errorf("Projects.RemoveProjectCollaborator returned error: %v", err)
   501  	}
   502  }
   503  
   504  func TestProjectsService_RemoveCollaborator_invalidUser(t *testing.T) {
   505  	client, _, _, teardown := setup()
   506  	defer teardown()
   507  
   508  	_, err := client.Projects.RemoveProjectCollaborator(context.Background(), 1, "%")
   509  	testURLParseError(t, err)
   510  }
   511  
   512  func TestProjectsService_ListCollaborators(t *testing.T) {
   513  	client, mux, _, teardown := setup()
   514  	defer teardown()
   515  
   516  	mux.HandleFunc("/projects/1/collaborators", func(w http.ResponseWriter, r *http.Request) {
   517  		testMethod(t, r, "GET")
   518  		testHeader(t, r, "Accept", mediaTypeProjectsPreview)
   519  		testFormValues(t, r, values{"page": "2"})
   520  		fmt.Fprintf(w, `[{"id":1}, {"id":2}]`)
   521  	})
   522  
   523  	opt := &ListCollaboratorOptions{
   524  		ListOptions: ListOptions{Page: 2},
   525  	}
   526  	users, _, err := client.Projects.ListProjectCollaborators(context.Background(), 1, opt)
   527  	if err != nil {
   528  		t.Errorf("Projects.ListProjectCollaborators returned error: %v", err)
   529  	}
   530  
   531  	want := []*User{{ID: Int64(1)}, {ID: Int64(2)}}
   532  	if !reflect.DeepEqual(users, want) {
   533  		t.Errorf("Projects.ListProjectCollaborators returned %+v, want %+v", users, want)
   534  	}
   535  }
   536  
   537  func TestProjectsService_ListCollaborators_withAffiliation(t *testing.T) {
   538  	client, mux, _, teardown := setup()
   539  	defer teardown()
   540  
   541  	mux.HandleFunc("/projects/1/collaborators", func(w http.ResponseWriter, r *http.Request) {
   542  		testMethod(t, r, "GET")
   543  		testHeader(t, r, "Accept", mediaTypeProjectsPreview)
   544  		testFormValues(t, r, values{"affiliation": "all", "page": "2"})
   545  		fmt.Fprintf(w, `[{"id":1}, {"id":2}]`)
   546  	})
   547  
   548  	opt := &ListCollaboratorOptions{
   549  		ListOptions: ListOptions{Page: 2},
   550  		Affiliation: String("all"),
   551  	}
   552  	users, _, err := client.Projects.ListProjectCollaborators(context.Background(), 1, opt)
   553  	if err != nil {
   554  		t.Errorf("Projects.ListProjectCollaborators returned error: %v", err)
   555  	}
   556  
   557  	want := []*User{{ID: Int64(1)}, {ID: Int64(2)}}
   558  	if !reflect.DeepEqual(users, want) {
   559  		t.Errorf("Projects.ListProjectCollaborators returned %+v, want %+v", users, want)
   560  	}
   561  }
   562  
   563  func TestProjectsService_GetPermissionLevel(t *testing.T) {
   564  	client, mux, _, teardown := setup()
   565  	defer teardown()
   566  
   567  	mux.HandleFunc("/projects/1/collaborators/u/permission", func(w http.ResponseWriter, r *http.Request) {
   568  		testMethod(t, r, "GET")
   569  		testHeader(t, r, "Accept", mediaTypeProjectsPreview)
   570  		fmt.Fprintf(w, `{"permission":"admin","user":{"login":"u"}}`)
   571  	})
   572  
   573  	ppl, _, err := client.Projects.ReviewProjectCollaboratorPermission(context.Background(), 1, "u")
   574  	if err != nil {
   575  		t.Errorf("Projects.ReviewProjectCollaboratorPermission returned error: %v", err)
   576  	}
   577  
   578  	want := &ProjectPermissionLevel{
   579  		Permission: String("admin"),
   580  		User: &User{
   581  			Login: String("u"),
   582  		},
   583  	}
   584  
   585  	if !reflect.DeepEqual(ppl, want) {
   586  		t.Errorf("Projects.ReviewProjectCollaboratorPermission returned %+v, want %+v", ppl, want)
   587  	}
   588  }