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 6package github 7 8import ( 9 "context" 10 "encoding/json" 11 "fmt" 12 "net/http" 13 "reflect" 14 "strings" 15 "testing" 16) 17 18func 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} 85func 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 122func 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 143func 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 158func 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 182func 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 203func 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 233func 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 263func 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 278func 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 301func 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 328func 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 349func 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 382func 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 415func 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 430func 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 453func 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 480func 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 488func 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 504func 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 512func 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 537func 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 563func 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} 589