github.com/google/go-github/v49@v49.1.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 "strings" 14 "testing" 15 16 "github.com/google/go-cmp/cmp" 17 ) 18 19 func TestProject_Marshal(t *testing.T) { 20 testJSONMarshal(t, &Project{}, "{}") 21 22 u := &Project{ 23 ID: Int64(1), 24 URL: String("u"), 25 HTMLURL: String("h"), 26 ColumnsURL: String("c"), 27 OwnerURL: String("o"), 28 Name: String("n"), 29 Body: String("b"), 30 Number: Int(1), 31 State: String("s"), 32 CreatedAt: &Timestamp{referenceTime}, 33 UpdatedAt: &Timestamp{referenceTime}, 34 NodeID: String("n"), 35 Creator: &User{ 36 Login: String("l"), 37 ID: Int64(1), 38 AvatarURL: String("a"), 39 GravatarID: String("g"), 40 Name: String("n"), 41 Company: String("c"), 42 Blog: String("b"), 43 Location: String("l"), 44 Email: String("e"), 45 Hireable: Bool(true), 46 PublicRepos: Int(1), 47 Followers: Int(1), 48 Following: Int(1), 49 CreatedAt: &Timestamp{referenceTime}, 50 URL: String("u"), 51 }, 52 } 53 want := `{ 54 "id": 1, 55 "url": "u", 56 "html_url": "h", 57 "columns_url": "c", 58 "owner_url": "o", 59 "name": "n", 60 "body": "b", 61 "number": 1, 62 "state": "s", 63 "created_at": ` + referenceTimeStr + `, 64 "updated_at": ` + referenceTimeStr + `, 65 "node_id": "n", 66 "creator": { 67 "login": "l", 68 "id": 1, 69 "avatar_url": "a", 70 "gravatar_id": "g", 71 "name": "n", 72 "company": "c", 73 "blog": "b", 74 "location": "l", 75 "email": "e", 76 "hireable": true, 77 "public_repos": 1, 78 "followers": 1, 79 "following": 1, 80 "created_at": ` + referenceTimeStr + `, 81 "url": "u" 82 } 83 }` 84 testJSONMarshal(t, u, want) 85 } 86 87 func TestProjectsService_UpdateProject(t *testing.T) { 88 client, mux, _, teardown := setup() 89 defer teardown() 90 91 input := &ProjectOptions{ 92 Name: String("Project Name"), 93 Body: String("Project body."), 94 State: String("open"), 95 Private: Bool(false), 96 97 OrganizationPermission: String("read"), 98 } 99 100 mux.HandleFunc("/projects/1", func(w http.ResponseWriter, r *http.Request) { 101 testMethod(t, r, "PATCH") 102 testHeader(t, r, "Accept", mediaTypeProjectsPreview) 103 104 v := &ProjectOptions{} 105 json.NewDecoder(r.Body).Decode(v) 106 if !cmp.Equal(v, input) { 107 t.Errorf("Request body = %+v, want %+v", v, input) 108 } 109 110 fmt.Fprint(w, `{"id":1}`) 111 }) 112 113 ctx := context.Background() 114 project, _, err := client.Projects.UpdateProject(ctx, 1, input) 115 if err != nil { 116 t.Errorf("Projects.UpdateProject returned error: %v", err) 117 } 118 119 want := &Project{ID: Int64(1)} 120 if !cmp.Equal(project, want) { 121 t.Errorf("Projects.UpdateProject returned %+v, want %+v", project, want) 122 } 123 124 const methodName = "UpdateProject" 125 testBadOptions(t, methodName, func() (err error) { 126 _, _, err = client.Projects.UpdateProject(ctx, -1, input) 127 return err 128 }) 129 130 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 131 got, resp, err := client.Projects.UpdateProject(ctx, 1, input) 132 if got != nil { 133 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 134 } 135 return resp, err 136 }) 137 } 138 139 func TestProjectsService_GetProject(t *testing.T) { 140 client, mux, _, teardown := setup() 141 defer teardown() 142 143 mux.HandleFunc("/projects/1", func(w http.ResponseWriter, r *http.Request) { 144 testMethod(t, r, "GET") 145 testHeader(t, r, "Accept", mediaTypeProjectsPreview) 146 fmt.Fprint(w, `{"id":1}`) 147 }) 148 149 ctx := context.Background() 150 project, _, err := client.Projects.GetProject(ctx, 1) 151 if err != nil { 152 t.Errorf("Projects.GetProject returned error: %v", err) 153 } 154 155 want := &Project{ID: Int64(1)} 156 if !cmp.Equal(project, want) { 157 t.Errorf("Projects.GetProject returned %+v, want %+v", project, want) 158 } 159 160 const methodName = "GetProject" 161 testBadOptions(t, methodName, func() (err error) { 162 _, _, err = client.Projects.GetProject(ctx, -1) 163 return err 164 }) 165 166 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 167 got, resp, err := client.Projects.GetProject(ctx, 1) 168 if got != nil { 169 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 170 } 171 return resp, err 172 }) 173 } 174 175 func TestProjectsService_DeleteProject(t *testing.T) { 176 client, mux, _, teardown := setup() 177 defer teardown() 178 179 mux.HandleFunc("/projects/1", func(w http.ResponseWriter, r *http.Request) { 180 testMethod(t, r, "DELETE") 181 testHeader(t, r, "Accept", mediaTypeProjectsPreview) 182 }) 183 184 ctx := context.Background() 185 _, err := client.Projects.DeleteProject(ctx, 1) 186 if err != nil { 187 t.Errorf("Projects.DeleteProject returned error: %v", err) 188 } 189 190 const methodName = "DeleteProject" 191 testBadOptions(t, methodName, func() (err error) { 192 _, err = client.Projects.DeleteProject(ctx, -1) 193 return err 194 }) 195 196 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 197 return client.Projects.DeleteProject(ctx, 1) 198 }) 199 } 200 201 func TestProjectsService_ListProjectColumns(t *testing.T) { 202 client, mux, _, teardown := setup() 203 defer teardown() 204 205 wantAcceptHeaders := []string{mediaTypeProjectsPreview} 206 mux.HandleFunc("/projects/1/columns", func(w http.ResponseWriter, r *http.Request) { 207 testMethod(t, r, "GET") 208 testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", ")) 209 testFormValues(t, r, values{"page": "2"}) 210 fmt.Fprint(w, `[{"id":1}]`) 211 }) 212 213 opt := &ListOptions{Page: 2} 214 ctx := context.Background() 215 columns, _, err := client.Projects.ListProjectColumns(ctx, 1, opt) 216 if err != nil { 217 t.Errorf("Projects.ListProjectColumns returned error: %v", err) 218 } 219 220 want := []*ProjectColumn{{ID: Int64(1)}} 221 if !cmp.Equal(columns, want) { 222 t.Errorf("Projects.ListProjectColumns returned %+v, want %+v", columns, want) 223 } 224 225 const methodName = "ListProjectColumns" 226 testBadOptions(t, methodName, func() (err error) { 227 _, _, err = client.Projects.ListProjectColumns(ctx, -1, opt) 228 return err 229 }) 230 231 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 232 got, resp, err := client.Projects.ListProjectColumns(ctx, 1, opt) 233 if got != nil { 234 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 235 } 236 return resp, err 237 }) 238 } 239 240 func TestProjectsService_GetProjectColumn(t *testing.T) { 241 client, mux, _, teardown := setup() 242 defer teardown() 243 244 mux.HandleFunc("/projects/columns/1", func(w http.ResponseWriter, r *http.Request) { 245 testMethod(t, r, "GET") 246 testHeader(t, r, "Accept", mediaTypeProjectsPreview) 247 fmt.Fprint(w, `{"id":1}`) 248 }) 249 250 ctx := context.Background() 251 column, _, err := client.Projects.GetProjectColumn(ctx, 1) 252 if err != nil { 253 t.Errorf("Projects.GetProjectColumn returned error: %v", err) 254 } 255 256 want := &ProjectColumn{ID: Int64(1)} 257 if !cmp.Equal(column, want) { 258 t.Errorf("Projects.GetProjectColumn returned %+v, want %+v", column, want) 259 } 260 261 const methodName = "GetProjectColumn" 262 testBadOptions(t, methodName, func() (err error) { 263 _, _, err = client.Projects.GetProjectColumn(ctx, -1) 264 return err 265 }) 266 267 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 268 got, resp, err := client.Projects.GetProjectColumn(ctx, 1) 269 if got != nil { 270 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 271 } 272 return resp, err 273 }) 274 } 275 276 func TestProjectsService_CreateProjectColumn(t *testing.T) { 277 client, mux, _, teardown := setup() 278 defer teardown() 279 280 input := &ProjectColumnOptions{Name: "Column Name"} 281 282 mux.HandleFunc("/projects/1/columns", func(w http.ResponseWriter, r *http.Request) { 283 testMethod(t, r, "POST") 284 testHeader(t, r, "Accept", mediaTypeProjectsPreview) 285 286 v := &ProjectColumnOptions{} 287 json.NewDecoder(r.Body).Decode(v) 288 if !cmp.Equal(v, input) { 289 t.Errorf("Request body = %+v, want %+v", v, input) 290 } 291 292 fmt.Fprint(w, `{"id":1}`) 293 }) 294 295 ctx := context.Background() 296 column, _, err := client.Projects.CreateProjectColumn(ctx, 1, input) 297 if err != nil { 298 t.Errorf("Projects.CreateProjectColumn returned error: %v", err) 299 } 300 301 want := &ProjectColumn{ID: Int64(1)} 302 if !cmp.Equal(column, want) { 303 t.Errorf("Projects.CreateProjectColumn returned %+v, want %+v", column, want) 304 } 305 306 const methodName = "CreateProjectColumn" 307 testBadOptions(t, methodName, func() (err error) { 308 _, _, err = client.Projects.CreateProjectColumn(ctx, -1, input) 309 return err 310 }) 311 312 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 313 got, resp, err := client.Projects.CreateProjectColumn(ctx, 1, input) 314 if got != nil { 315 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 316 } 317 return resp, err 318 }) 319 } 320 321 func TestProjectsService_UpdateProjectColumn(t *testing.T) { 322 client, mux, _, teardown := setup() 323 defer teardown() 324 325 input := &ProjectColumnOptions{Name: "Column Name"} 326 327 mux.HandleFunc("/projects/columns/1", func(w http.ResponseWriter, r *http.Request) { 328 testMethod(t, r, "PATCH") 329 testHeader(t, r, "Accept", mediaTypeProjectsPreview) 330 331 v := &ProjectColumnOptions{} 332 json.NewDecoder(r.Body).Decode(v) 333 if !cmp.Equal(v, input) { 334 t.Errorf("Request body = %+v, want %+v", v, input) 335 } 336 337 fmt.Fprint(w, `{"id":1}`) 338 }) 339 340 ctx := context.Background() 341 column, _, err := client.Projects.UpdateProjectColumn(ctx, 1, input) 342 if err != nil { 343 t.Errorf("Projects.UpdateProjectColumn returned error: %v", err) 344 } 345 346 want := &ProjectColumn{ID: Int64(1)} 347 if !cmp.Equal(column, want) { 348 t.Errorf("Projects.UpdateProjectColumn returned %+v, want %+v", column, want) 349 } 350 351 const methodName = "UpdateProjectColumn" 352 testBadOptions(t, methodName, func() (err error) { 353 _, _, err = client.Projects.UpdateProjectColumn(ctx, -1, input) 354 return err 355 }) 356 357 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 358 got, resp, err := client.Projects.UpdateProjectColumn(ctx, 1, input) 359 if got != nil { 360 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 361 } 362 return resp, err 363 }) 364 } 365 366 func TestProjectsService_DeleteProjectColumn(t *testing.T) { 367 client, mux, _, teardown := setup() 368 defer teardown() 369 370 mux.HandleFunc("/projects/columns/1", func(w http.ResponseWriter, r *http.Request) { 371 testMethod(t, r, "DELETE") 372 testHeader(t, r, "Accept", mediaTypeProjectsPreview) 373 }) 374 375 ctx := context.Background() 376 _, err := client.Projects.DeleteProjectColumn(ctx, 1) 377 if err != nil { 378 t.Errorf("Projects.DeleteProjectColumn returned error: %v", err) 379 } 380 381 const methodName = "DeleteProjectColumn" 382 testBadOptions(t, methodName, func() (err error) { 383 _, err = client.Projects.DeleteProjectColumn(ctx, -1) 384 return err 385 }) 386 387 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 388 return client.Projects.DeleteProjectColumn(ctx, 1) 389 }) 390 } 391 392 func TestProjectsService_MoveProjectColumn(t *testing.T) { 393 client, mux, _, teardown := setup() 394 defer teardown() 395 396 input := &ProjectColumnMoveOptions{Position: "after:12345"} 397 398 mux.HandleFunc("/projects/columns/1/moves", func(w http.ResponseWriter, r *http.Request) { 399 testMethod(t, r, "POST") 400 testHeader(t, r, "Accept", mediaTypeProjectsPreview) 401 402 v := &ProjectColumnMoveOptions{} 403 json.NewDecoder(r.Body).Decode(v) 404 if !cmp.Equal(v, input) { 405 t.Errorf("Request body = %+v, want %+v", v, input) 406 } 407 }) 408 409 ctx := context.Background() 410 _, err := client.Projects.MoveProjectColumn(ctx, 1, input) 411 if err != nil { 412 t.Errorf("Projects.MoveProjectColumn returned error: %v", err) 413 } 414 415 const methodName = "MoveProjectColumn" 416 testBadOptions(t, methodName, func() (err error) { 417 _, err = client.Projects.MoveProjectColumn(ctx, -1, input) 418 return err 419 }) 420 421 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 422 return client.Projects.MoveProjectColumn(ctx, 1, input) 423 }) 424 } 425 426 func TestProjectsService_ListProjectCards(t *testing.T) { 427 client, mux, _, teardown := setup() 428 defer teardown() 429 430 mux.HandleFunc("/projects/columns/1/cards", func(w http.ResponseWriter, r *http.Request) { 431 testMethod(t, r, "GET") 432 testHeader(t, r, "Accept", mediaTypeProjectsPreview) 433 testFormValues(t, r, values{ 434 "archived_state": "all", 435 "page": "2"}) 436 fmt.Fprint(w, `[{"id":1}]`) 437 }) 438 439 opt := &ProjectCardListOptions{ 440 ArchivedState: String("all"), 441 ListOptions: ListOptions{Page: 2}} 442 ctx := context.Background() 443 cards, _, err := client.Projects.ListProjectCards(ctx, 1, opt) 444 if err != nil { 445 t.Errorf("Projects.ListProjectCards returned error: %v", err) 446 } 447 448 want := []*ProjectCard{{ID: Int64(1)}} 449 if !cmp.Equal(cards, want) { 450 t.Errorf("Projects.ListProjectCards returned %+v, want %+v", cards, want) 451 } 452 453 const methodName = "ListProjectCards" 454 testBadOptions(t, methodName, func() (err error) { 455 _, _, err = client.Projects.ListProjectCards(ctx, -1, opt) 456 return err 457 }) 458 459 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 460 got, resp, err := client.Projects.ListProjectCards(ctx, 1, opt) 461 if got != nil { 462 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 463 } 464 return resp, err 465 }) 466 } 467 468 func TestProjectsService_GetProjectCard(t *testing.T) { 469 client, mux, _, teardown := setup() 470 defer teardown() 471 472 mux.HandleFunc("/projects/columns/cards/1", func(w http.ResponseWriter, r *http.Request) { 473 testMethod(t, r, "GET") 474 testHeader(t, r, "Accept", mediaTypeProjectsPreview) 475 fmt.Fprint(w, `{"id":1}`) 476 }) 477 478 ctx := context.Background() 479 card, _, err := client.Projects.GetProjectCard(ctx, 1) 480 if err != nil { 481 t.Errorf("Projects.GetProjectCard returned error: %v", err) 482 } 483 484 want := &ProjectCard{ID: Int64(1)} 485 if !cmp.Equal(card, want) { 486 t.Errorf("Projects.GetProjectCard returned %+v, want %+v", card, want) 487 } 488 489 const methodName = "GetProjectCard" 490 testBadOptions(t, methodName, func() (err error) { 491 _, _, err = client.Projects.GetProjectCard(ctx, -1) 492 return err 493 }) 494 495 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 496 got, resp, err := client.Projects.GetProjectCard(ctx, 1) 497 if got != nil { 498 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 499 } 500 return resp, err 501 }) 502 } 503 504 func TestProjectsService_CreateProjectCard(t *testing.T) { 505 client, mux, _, teardown := setup() 506 defer teardown() 507 508 input := &ProjectCardOptions{ 509 ContentID: 12345, 510 ContentType: "Issue", 511 } 512 513 mux.HandleFunc("/projects/columns/1/cards", func(w http.ResponseWriter, r *http.Request) { 514 testMethod(t, r, "POST") 515 testHeader(t, r, "Accept", mediaTypeProjectsPreview) 516 517 v := &ProjectCardOptions{} 518 json.NewDecoder(r.Body).Decode(v) 519 if !cmp.Equal(v, input) { 520 t.Errorf("Request body = %+v, want %+v", v, input) 521 } 522 523 fmt.Fprint(w, `{"id":1}`) 524 }) 525 526 ctx := context.Background() 527 card, _, err := client.Projects.CreateProjectCard(ctx, 1, input) 528 if err != nil { 529 t.Errorf("Projects.CreateProjectCard returned error: %v", err) 530 } 531 532 want := &ProjectCard{ID: Int64(1)} 533 if !cmp.Equal(card, want) { 534 t.Errorf("Projects.CreateProjectCard returned %+v, want %+v", card, want) 535 } 536 537 const methodName = "CreateProjectCard" 538 testBadOptions(t, methodName, func() (err error) { 539 _, _, err = client.Projects.CreateProjectCard(ctx, -1, input) 540 return err 541 }) 542 543 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 544 got, resp, err := client.Projects.CreateProjectCard(ctx, 1, input) 545 if got != nil { 546 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 547 } 548 return resp, err 549 }) 550 } 551 552 func TestProjectsService_UpdateProjectCard(t *testing.T) { 553 client, mux, _, teardown := setup() 554 defer teardown() 555 556 input := &ProjectCardOptions{ 557 ContentID: 12345, 558 ContentType: "Issue", 559 } 560 561 mux.HandleFunc("/projects/columns/cards/1", func(w http.ResponseWriter, r *http.Request) { 562 testMethod(t, r, "PATCH") 563 testHeader(t, r, "Accept", mediaTypeProjectsPreview) 564 565 v := &ProjectCardOptions{} 566 json.NewDecoder(r.Body).Decode(v) 567 if !cmp.Equal(v, input) { 568 t.Errorf("Request body = %+v, want %+v", v, input) 569 } 570 571 fmt.Fprint(w, `{"id":1, "archived":false}`) 572 }) 573 574 ctx := context.Background() 575 card, _, err := client.Projects.UpdateProjectCard(ctx, 1, input) 576 if err != nil { 577 t.Errorf("Projects.UpdateProjectCard returned error: %v", err) 578 } 579 580 want := &ProjectCard{ID: Int64(1), Archived: Bool(false)} 581 if !cmp.Equal(card, want) { 582 t.Errorf("Projects.UpdateProjectCard returned %+v, want %+v", card, want) 583 } 584 585 const methodName = "UpdateProjectCard" 586 testBadOptions(t, methodName, func() (err error) { 587 _, _, err = client.Projects.UpdateProjectCard(ctx, -1, input) 588 return err 589 }) 590 591 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 592 got, resp, err := client.Projects.UpdateProjectCard(ctx, 1, input) 593 if got != nil { 594 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 595 } 596 return resp, err 597 }) 598 } 599 600 func TestProjectsService_DeleteProjectCard(t *testing.T) { 601 client, mux, _, teardown := setup() 602 defer teardown() 603 604 mux.HandleFunc("/projects/columns/cards/1", func(w http.ResponseWriter, r *http.Request) { 605 testMethod(t, r, "DELETE") 606 testHeader(t, r, "Accept", mediaTypeProjectsPreview) 607 }) 608 609 ctx := context.Background() 610 _, err := client.Projects.DeleteProjectCard(ctx, 1) 611 if err != nil { 612 t.Errorf("Projects.DeleteProjectCard returned error: %v", err) 613 } 614 615 const methodName = "DeleteProjectCard" 616 testBadOptions(t, methodName, func() (err error) { 617 _, err = client.Projects.DeleteProjectCard(ctx, -1) 618 return err 619 }) 620 621 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 622 return client.Projects.DeleteProjectCard(ctx, 1) 623 }) 624 } 625 626 func TestProjectsService_MoveProjectCard(t *testing.T) { 627 client, mux, _, teardown := setup() 628 defer teardown() 629 630 input := &ProjectCardMoveOptions{Position: "after:12345"} 631 632 mux.HandleFunc("/projects/columns/cards/1/moves", func(w http.ResponseWriter, r *http.Request) { 633 testMethod(t, r, "POST") 634 testHeader(t, r, "Accept", mediaTypeProjectsPreview) 635 636 v := &ProjectCardMoveOptions{} 637 json.NewDecoder(r.Body).Decode(v) 638 if !cmp.Equal(v, input) { 639 t.Errorf("Request body = %+v, want %+v", v, input) 640 } 641 }) 642 643 ctx := context.Background() 644 _, err := client.Projects.MoveProjectCard(ctx, 1, input) 645 if err != nil { 646 t.Errorf("Projects.MoveProjectCard returned error: %v", err) 647 } 648 649 const methodName = "MoveProjectCard" 650 testBadOptions(t, methodName, func() (err error) { 651 _, err = client.Projects.MoveProjectCard(ctx, -1, input) 652 return err 653 }) 654 655 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 656 return client.Projects.MoveProjectCard(ctx, 1, input) 657 }) 658 } 659 660 func TestProjectsService_AddProjectCollaborator(t *testing.T) { 661 client, mux, _, teardown := setup() 662 defer teardown() 663 664 opt := &ProjectCollaboratorOptions{ 665 Permission: String("admin"), 666 } 667 668 mux.HandleFunc("/projects/1/collaborators/u", func(w http.ResponseWriter, r *http.Request) { 669 testMethod(t, r, "PUT") 670 testHeader(t, r, "Accept", mediaTypeProjectsPreview) 671 672 v := &ProjectCollaboratorOptions{} 673 json.NewDecoder(r.Body).Decode(v) 674 if !cmp.Equal(v, opt) { 675 t.Errorf("Request body = %+v, want %+v", v, opt) 676 } 677 678 w.WriteHeader(http.StatusNoContent) 679 }) 680 681 ctx := context.Background() 682 _, err := client.Projects.AddProjectCollaborator(ctx, 1, "u", opt) 683 if err != nil { 684 t.Errorf("Projects.AddProjectCollaborator returned error: %v", err) 685 } 686 687 const methodName = "AddProjectCollaborator" 688 testBadOptions(t, methodName, func() (err error) { 689 _, err = client.Projects.AddProjectCollaborator(ctx, -1, "\n", opt) 690 return err 691 }) 692 693 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 694 return client.Projects.AddProjectCollaborator(ctx, 1, "u", opt) 695 }) 696 } 697 698 func TestProjectsService_AddCollaborator_invalidUser(t *testing.T) { 699 client, _, _, teardown := setup() 700 defer teardown() 701 702 ctx := context.Background() 703 _, err := client.Projects.AddProjectCollaborator(ctx, 1, "%", nil) 704 testURLParseError(t, err) 705 } 706 707 func TestProjectsService_RemoveCollaborator(t *testing.T) { 708 client, mux, _, teardown := setup() 709 defer teardown() 710 711 mux.HandleFunc("/projects/1/collaborators/u", func(w http.ResponseWriter, r *http.Request) { 712 testMethod(t, r, "DELETE") 713 testHeader(t, r, "Accept", mediaTypeProjectsPreview) 714 w.WriteHeader(http.StatusNoContent) 715 }) 716 717 ctx := context.Background() 718 _, err := client.Projects.RemoveProjectCollaborator(ctx, 1, "u") 719 if err != nil { 720 t.Errorf("Projects.RemoveProjectCollaborator returned error: %v", err) 721 } 722 723 const methodName = "RemoveProjectCollaborator" 724 testBadOptions(t, methodName, func() (err error) { 725 _, err = client.Projects.RemoveProjectCollaborator(ctx, -1, "\n") 726 return err 727 }) 728 729 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 730 return client.Projects.RemoveProjectCollaborator(ctx, 1, "u") 731 }) 732 } 733 734 func TestProjectsService_RemoveCollaborator_invalidUser(t *testing.T) { 735 client, _, _, teardown := setup() 736 defer teardown() 737 738 ctx := context.Background() 739 _, err := client.Projects.RemoveProjectCollaborator(ctx, 1, "%") 740 testURLParseError(t, err) 741 } 742 743 func TestProjectsService_ListCollaborators(t *testing.T) { 744 client, mux, _, teardown := setup() 745 defer teardown() 746 747 mux.HandleFunc("/projects/1/collaborators", func(w http.ResponseWriter, r *http.Request) { 748 testMethod(t, r, "GET") 749 testHeader(t, r, "Accept", mediaTypeProjectsPreview) 750 testFormValues(t, r, values{"page": "2"}) 751 fmt.Fprintf(w, `[{"id":1}, {"id":2}]`) 752 }) 753 754 opt := &ListCollaboratorOptions{ 755 ListOptions: ListOptions{Page: 2}, 756 } 757 ctx := context.Background() 758 users, _, err := client.Projects.ListProjectCollaborators(ctx, 1, opt) 759 if err != nil { 760 t.Errorf("Projects.ListProjectCollaborators returned error: %v", err) 761 } 762 763 want := []*User{{ID: Int64(1)}, {ID: Int64(2)}} 764 if !cmp.Equal(users, want) { 765 t.Errorf("Projects.ListProjectCollaborators returned %+v, want %+v", users, want) 766 } 767 768 const methodName = "ListProjectCollaborators" 769 testBadOptions(t, methodName, func() (err error) { 770 _, _, err = client.Projects.ListProjectCollaborators(ctx, -1, opt) 771 return err 772 }) 773 774 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 775 got, resp, err := client.Projects.ListProjectCollaborators(ctx, 1, opt) 776 if got != nil { 777 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 778 } 779 return resp, err 780 }) 781 } 782 783 func TestProjectsService_ListCollaborators_withAffiliation(t *testing.T) { 784 client, mux, _, teardown := setup() 785 defer teardown() 786 787 mux.HandleFunc("/projects/1/collaborators", func(w http.ResponseWriter, r *http.Request) { 788 testMethod(t, r, "GET") 789 testHeader(t, r, "Accept", mediaTypeProjectsPreview) 790 testFormValues(t, r, values{"affiliation": "all", "page": "2"}) 791 fmt.Fprintf(w, `[{"id":1}, {"id":2}]`) 792 }) 793 794 opt := &ListCollaboratorOptions{ 795 ListOptions: ListOptions{Page: 2}, 796 Affiliation: String("all"), 797 } 798 ctx := context.Background() 799 users, _, err := client.Projects.ListProjectCollaborators(ctx, 1, opt) 800 if err != nil { 801 t.Errorf("Projects.ListProjectCollaborators returned error: %v", err) 802 } 803 804 want := []*User{{ID: Int64(1)}, {ID: Int64(2)}} 805 if !cmp.Equal(users, want) { 806 t.Errorf("Projects.ListProjectCollaborators returned %+v, want %+v", users, want) 807 } 808 } 809 810 func TestProjectsService_ReviewProjectCollaboratorPermission(t *testing.T) { 811 client, mux, _, teardown := setup() 812 defer teardown() 813 814 mux.HandleFunc("/projects/1/collaborators/u/permission", func(w http.ResponseWriter, r *http.Request) { 815 testMethod(t, r, "GET") 816 testHeader(t, r, "Accept", mediaTypeProjectsPreview) 817 fmt.Fprintf(w, `{"permission":"admin","user":{"login":"u"}}`) 818 }) 819 820 ctx := context.Background() 821 ppl, _, err := client.Projects.ReviewProjectCollaboratorPermission(ctx, 1, "u") 822 if err != nil { 823 t.Errorf("Projects.ReviewProjectCollaboratorPermission returned error: %v", err) 824 } 825 826 want := &ProjectPermissionLevel{ 827 Permission: String("admin"), 828 User: &User{ 829 Login: String("u"), 830 }, 831 } 832 833 if !cmp.Equal(ppl, want) { 834 t.Errorf("Projects.ReviewProjectCollaboratorPermission returned %+v, want %+v", ppl, want) 835 } 836 837 const methodName = "ReviewProjectCollaboratorPermission" 838 testBadOptions(t, methodName, func() (err error) { 839 _, _, err = client.Projects.ReviewProjectCollaboratorPermission(ctx, -1, "\n") 840 return err 841 }) 842 843 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 844 got, resp, err := client.Projects.ReviewProjectCollaboratorPermission(ctx, 1, "u") 845 if got != nil { 846 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 847 } 848 return resp, err 849 }) 850 } 851 852 func TestProjectOptions_Marshal(t *testing.T) { 853 testJSONMarshal(t, &ProjectOptions{}, "{}") 854 855 u := &ProjectOptions{ 856 Name: String("name"), 857 Body: String("body"), 858 State: String("state"), 859 OrganizationPermission: String("op"), 860 Private: Bool(false), 861 } 862 863 want := `{ 864 "name": "name", 865 "body": "body", 866 "state": "state", 867 "organization_permission": "op", 868 "private": false 869 }` 870 871 testJSONMarshal(t, u, want) 872 } 873 874 func TestProjectColumn_Marshal(t *testing.T) { 875 testJSONMarshal(t, &ProjectColumn{}, "{}") 876 877 u := &ProjectColumn{ 878 ID: Int64(1), 879 Name: String("name"), 880 URL: String("url"), 881 ProjectURL: String("purl"), 882 CardsURL: String("curl"), 883 CreatedAt: &Timestamp{referenceTime}, 884 UpdatedAt: &Timestamp{referenceTime}, 885 NodeID: String("onidp"), 886 } 887 888 want := `{ 889 "id": 1, 890 "name": "name", 891 "url": "url", 892 "project_url": "purl", 893 "cards_url": "curl", 894 "created_at": ` + referenceTimeStr + `, 895 "updated_at": ` + referenceTimeStr + `, 896 "node_id": "onidp" 897 }` 898 899 testJSONMarshal(t, u, want) 900 } 901 902 func TestProjectColumnOptions_Marshal(t *testing.T) { 903 testJSONMarshal(t, &ProjectColumnOptions{}, "{}") 904 905 u := &ProjectColumnOptions{ 906 Name: "name", 907 } 908 909 want := `{ 910 "name": "name" 911 }` 912 913 testJSONMarshal(t, u, want) 914 } 915 916 func TestProjectColumnMoveOptions_Marshal(t *testing.T) { 917 testJSONMarshal(t, &ProjectColumnMoveOptions{}, "{}") 918 919 u := &ProjectColumnMoveOptions{ 920 Position: "pos", 921 } 922 923 want := `{ 924 "position": "pos" 925 }` 926 927 testJSONMarshal(t, u, want) 928 } 929 930 func TestProjectCard_Marshal(t *testing.T) { 931 testJSONMarshal(t, &ProjectCard{}, "{}") 932 933 u := &ProjectCard{ 934 URL: String("url"), 935 ColumnURL: String("curl"), 936 ContentURL: String("conurl"), 937 ID: Int64(1), 938 Note: String("note"), 939 Creator: &User{ 940 Login: String("l"), 941 ID: Int64(1), 942 URL: String("u"), 943 AvatarURL: String("a"), 944 GravatarID: String("g"), 945 Name: String("n"), 946 Company: String("c"), 947 Blog: String("b"), 948 Location: String("l"), 949 Email: String("e"), 950 Hireable: Bool(true), 951 Bio: String("b"), 952 TwitterUsername: String("t"), 953 PublicRepos: Int(1), 954 Followers: Int(1), 955 Following: Int(1), 956 CreatedAt: &Timestamp{referenceTime}, 957 SuspendedAt: &Timestamp{referenceTime}, 958 }, 959 CreatedAt: &Timestamp{referenceTime}, 960 UpdatedAt: &Timestamp{referenceTime}, 961 NodeID: String("nid"), 962 Archived: Bool(true), 963 ColumnID: Int64(1), 964 ProjectID: Int64(1), 965 ProjectURL: String("purl"), 966 ColumnName: String("cn"), 967 PreviousColumnName: String("pcn"), 968 } 969 970 want := `{ 971 "url": "url", 972 "column_url": "curl", 973 "content_url": "conurl", 974 "id": 1, 975 "note": "note", 976 "creator": { 977 "login": "l", 978 "id": 1, 979 "avatar_url": "a", 980 "gravatar_id": "g", 981 "name": "n", 982 "company": "c", 983 "blog": "b", 984 "location": "l", 985 "email": "e", 986 "hireable": true, 987 "bio": "b", 988 "twitter_username": "t", 989 "public_repos": 1, 990 "followers": 1, 991 "following": 1, 992 "created_at": ` + referenceTimeStr + `, 993 "suspended_at": ` + referenceTimeStr + `, 994 "url": "u" 995 }, 996 "created_at": ` + referenceTimeStr + `, 997 "updated_at": ` + referenceTimeStr + `, 998 "node_id": "nid", 999 "archived": true, 1000 "column_id": 1, 1001 "project_id": 1, 1002 "project_url": "purl", 1003 "column_name": "cn", 1004 "previous_column_name": "pcn" 1005 }` 1006 1007 testJSONMarshal(t, u, want) 1008 } 1009 1010 func TestProjectCardOptions_Marshal(t *testing.T) { 1011 testJSONMarshal(t, &ProjectCardOptions{}, "{}") 1012 1013 u := &ProjectCardOptions{ 1014 Note: "note", 1015 ContentID: 1, 1016 ContentType: "ct", 1017 Archived: Bool(false), 1018 } 1019 1020 want := `{ 1021 "note": "note", 1022 "content_id": 1, 1023 "content_type": "ct", 1024 "archived": false 1025 }` 1026 1027 testJSONMarshal(t, u, want) 1028 } 1029 1030 func TestProjectCardMoveOptions_Marshal(t *testing.T) { 1031 testJSONMarshal(t, &ProjectCardMoveOptions{}, "{}") 1032 1033 u := &ProjectCardMoveOptions{ 1034 Position: "pos", 1035 ColumnID: 1, 1036 } 1037 1038 want := `{ 1039 "position": "pos", 1040 "column_id": 1 1041 }` 1042 1043 testJSONMarshal(t, u, want) 1044 } 1045 1046 func TestProjectCollaboratorOptions_Marshal(t *testing.T) { 1047 testJSONMarshal(t, &ProjectCollaboratorOptions{}, "{}") 1048 1049 u := &ProjectCollaboratorOptions{ 1050 Permission: String("per"), 1051 } 1052 1053 want := `{ 1054 "permission": "per" 1055 }` 1056 1057 testJSONMarshal(t, u, want) 1058 } 1059 1060 func TestProjectPermissionLevel_Marshal(t *testing.T) { 1061 testJSONMarshal(t, &ProjectPermissionLevel{}, "{}") 1062 1063 u := &ProjectPermissionLevel{ 1064 Permission: String("per"), 1065 User: &User{ 1066 Login: String("l"), 1067 ID: Int64(1), 1068 URL: String("u"), 1069 AvatarURL: String("a"), 1070 GravatarID: String("g"), 1071 Name: String("n"), 1072 Company: String("c"), 1073 Blog: String("b"), 1074 Location: String("l"), 1075 Email: String("e"), 1076 Hireable: Bool(true), 1077 Bio: String("b"), 1078 TwitterUsername: String("t"), 1079 PublicRepos: Int(1), 1080 Followers: Int(1), 1081 Following: Int(1), 1082 CreatedAt: &Timestamp{referenceTime}, 1083 SuspendedAt: &Timestamp{referenceTime}, 1084 }, 1085 } 1086 1087 want := `{ 1088 "permission": "per", 1089 "user": { 1090 "login": "l", 1091 "id": 1, 1092 "avatar_url": "a", 1093 "gravatar_id": "g", 1094 "name": "n", 1095 "company": "c", 1096 "blog": "b", 1097 "location": "l", 1098 "email": "e", 1099 "hireable": true, 1100 "bio": "b", 1101 "twitter_username": "t", 1102 "public_repos": 1, 1103 "followers": 1, 1104 "following": 1, 1105 "created_at": ` + referenceTimeStr + `, 1106 "suspended_at": ` + referenceTimeStr + `, 1107 "url": "u" 1108 } 1109 }` 1110 1111 testJSONMarshal(t, u, want) 1112 }