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