github.com/google/go-github/v49@v49.1.0/github/orgs_members_test.go (about) 1 // Copyright 2013 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 "testing" 14 "time" 15 16 "github.com/google/go-cmp/cmp" 17 ) 18 19 func TestOrganizationsService_ListMembers(t *testing.T) { 20 client, mux, _, teardown := setup() 21 defer teardown() 22 23 mux.HandleFunc("/orgs/o/members", func(w http.ResponseWriter, r *http.Request) { 24 testMethod(t, r, "GET") 25 testFormValues(t, r, values{ 26 "filter": "2fa_disabled", 27 "role": "admin", 28 "page": "2", 29 }) 30 fmt.Fprint(w, `[{"id":1}]`) 31 }) 32 33 opt := &ListMembersOptions{ 34 PublicOnly: false, 35 Filter: "2fa_disabled", 36 Role: "admin", 37 ListOptions: ListOptions{Page: 2}, 38 } 39 ctx := context.Background() 40 members, _, err := client.Organizations.ListMembers(ctx, "o", opt) 41 if err != nil { 42 t.Errorf("Organizations.ListMembers returned error: %v", err) 43 } 44 45 want := []*User{{ID: Int64(1)}} 46 if !cmp.Equal(members, want) { 47 t.Errorf("Organizations.ListMembers returned %+v, want %+v", members, want) 48 } 49 50 const methodName = "ListMembers" 51 testBadOptions(t, methodName, func() (err error) { 52 _, _, err = client.Organizations.ListMembers(ctx, "\n", opt) 53 return err 54 }) 55 56 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 57 got, resp, err := client.Organizations.ListMembers(ctx, "o", opt) 58 if got != nil { 59 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 60 } 61 return resp, err 62 }) 63 } 64 65 func TestOrganizationsService_ListMembers_invalidOrg(t *testing.T) { 66 client, _, _, teardown := setup() 67 defer teardown() 68 69 ctx := context.Background() 70 _, _, err := client.Organizations.ListMembers(ctx, "%", nil) 71 testURLParseError(t, err) 72 } 73 74 func TestOrganizationsService_ListMembers_public(t *testing.T) { 75 client, mux, _, teardown := setup() 76 defer teardown() 77 78 mux.HandleFunc("/orgs/o/public_members", func(w http.ResponseWriter, r *http.Request) { 79 testMethod(t, r, "GET") 80 fmt.Fprint(w, `[{"id":1}]`) 81 }) 82 83 opt := &ListMembersOptions{PublicOnly: true} 84 ctx := context.Background() 85 members, _, err := client.Organizations.ListMembers(ctx, "o", opt) 86 if err != nil { 87 t.Errorf("Organizations.ListMembers returned error: %v", err) 88 } 89 90 want := []*User{{ID: Int64(1)}} 91 if !cmp.Equal(members, want) { 92 t.Errorf("Organizations.ListMembers returned %+v, want %+v", members, want) 93 } 94 } 95 96 func TestOrganizationsService_IsMember(t *testing.T) { 97 client, mux, _, teardown := setup() 98 defer teardown() 99 100 mux.HandleFunc("/orgs/o/members/u", func(w http.ResponseWriter, r *http.Request) { 101 testMethod(t, r, "GET") 102 w.WriteHeader(http.StatusNoContent) 103 }) 104 105 ctx := context.Background() 106 member, _, err := client.Organizations.IsMember(ctx, "o", "u") 107 if err != nil { 108 t.Errorf("Organizations.IsMember returned error: %v", err) 109 } 110 if want := true; member != want { 111 t.Errorf("Organizations.IsMember returned %+v, want %+v", member, want) 112 } 113 114 const methodName = "IsMember" 115 testBadOptions(t, methodName, func() (err error) { 116 _, _, err = client.Organizations.IsMember(ctx, "\n", "\n") 117 return err 118 }) 119 120 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 121 got, resp, err := client.Organizations.IsMember(ctx, "o", "u") 122 if got { 123 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 124 } 125 return resp, err 126 }) 127 } 128 129 // ensure that a 404 response is interpreted as "false" and not an error 130 func TestOrganizationsService_IsMember_notMember(t *testing.T) { 131 client, mux, _, teardown := setup() 132 defer teardown() 133 134 mux.HandleFunc("/orgs/o/members/u", func(w http.ResponseWriter, r *http.Request) { 135 testMethod(t, r, "GET") 136 w.WriteHeader(http.StatusNotFound) 137 }) 138 139 ctx := context.Background() 140 member, _, err := client.Organizations.IsMember(ctx, "o", "u") 141 if err != nil { 142 t.Errorf("Organizations.IsMember returned error: %+v", err) 143 } 144 if want := false; member != want { 145 t.Errorf("Organizations.IsMember returned %+v, want %+v", member, want) 146 } 147 } 148 149 // ensure that a 400 response is interpreted as an actual error, and not simply 150 // as "false" like the above case of a 404 151 func TestOrganizationsService_IsMember_error(t *testing.T) { 152 client, mux, _, teardown := setup() 153 defer teardown() 154 155 mux.HandleFunc("/orgs/o/members/u", func(w http.ResponseWriter, r *http.Request) { 156 testMethod(t, r, "GET") 157 http.Error(w, "BadRequest", http.StatusBadRequest) 158 }) 159 160 ctx := context.Background() 161 member, _, err := client.Organizations.IsMember(ctx, "o", "u") 162 if err == nil { 163 t.Errorf("Expected HTTP 400 response") 164 } 165 if want := false; member != want { 166 t.Errorf("Organizations.IsMember returned %+v, want %+v", member, want) 167 } 168 } 169 170 func TestOrganizationsService_IsMember_invalidOrg(t *testing.T) { 171 client, _, _, teardown := setup() 172 defer teardown() 173 174 ctx := context.Background() 175 _, _, err := client.Organizations.IsMember(ctx, "%", "u") 176 testURLParseError(t, err) 177 } 178 179 func TestOrganizationsService_IsPublicMember(t *testing.T) { 180 client, mux, _, teardown := setup() 181 defer teardown() 182 183 mux.HandleFunc("/orgs/o/public_members/u", func(w http.ResponseWriter, r *http.Request) { 184 testMethod(t, r, "GET") 185 w.WriteHeader(http.StatusNoContent) 186 }) 187 188 ctx := context.Background() 189 member, _, err := client.Organizations.IsPublicMember(ctx, "o", "u") 190 if err != nil { 191 t.Errorf("Organizations.IsPublicMember returned error: %v", err) 192 } 193 if want := true; member != want { 194 t.Errorf("Organizations.IsPublicMember returned %+v, want %+v", member, want) 195 } 196 197 const methodName = "IsPublicMember" 198 testBadOptions(t, methodName, func() (err error) { 199 _, _, err = client.Organizations.IsPublicMember(ctx, "\n", "\n") 200 return err 201 }) 202 203 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 204 got, resp, err := client.Organizations.IsPublicMember(ctx, "o", "u") 205 if got { 206 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 207 } 208 return resp, err 209 }) 210 } 211 212 // ensure that a 404 response is interpreted as "false" and not an error 213 func TestOrganizationsService_IsPublicMember_notMember(t *testing.T) { 214 client, mux, _, teardown := setup() 215 defer teardown() 216 217 mux.HandleFunc("/orgs/o/public_members/u", func(w http.ResponseWriter, r *http.Request) { 218 testMethod(t, r, "GET") 219 w.WriteHeader(http.StatusNotFound) 220 }) 221 222 ctx := context.Background() 223 member, _, err := client.Organizations.IsPublicMember(ctx, "o", "u") 224 if err != nil { 225 t.Errorf("Organizations.IsPublicMember returned error: %v", err) 226 } 227 if want := false; member != want { 228 t.Errorf("Organizations.IsPublicMember returned %+v, want %+v", member, want) 229 } 230 } 231 232 // ensure that a 400 response is interpreted as an actual error, and not simply 233 // as "false" like the above case of a 404 234 func TestOrganizationsService_IsPublicMember_error(t *testing.T) { 235 client, mux, _, teardown := setup() 236 defer teardown() 237 238 mux.HandleFunc("/orgs/o/public_members/u", func(w http.ResponseWriter, r *http.Request) { 239 testMethod(t, r, "GET") 240 http.Error(w, "BadRequest", http.StatusBadRequest) 241 }) 242 243 ctx := context.Background() 244 member, _, err := client.Organizations.IsPublicMember(ctx, "o", "u") 245 if err == nil { 246 t.Errorf("Expected HTTP 400 response") 247 } 248 if want := false; member != want { 249 t.Errorf("Organizations.IsPublicMember returned %+v, want %+v", member, want) 250 } 251 } 252 253 func TestOrganizationsService_IsPublicMember_invalidOrg(t *testing.T) { 254 client, _, _, teardown := setup() 255 defer teardown() 256 257 ctx := context.Background() 258 _, _, err := client.Organizations.IsPublicMember(ctx, "%", "u") 259 testURLParseError(t, err) 260 } 261 262 func TestOrganizationsService_RemoveMember(t *testing.T) { 263 client, mux, _, teardown := setup() 264 defer teardown() 265 266 mux.HandleFunc("/orgs/o/members/u", func(w http.ResponseWriter, r *http.Request) { 267 testMethod(t, r, "DELETE") 268 }) 269 270 ctx := context.Background() 271 _, err := client.Organizations.RemoveMember(ctx, "o", "u") 272 if err != nil { 273 t.Errorf("Organizations.RemoveMember returned error: %v", err) 274 } 275 276 const methodName = "RemoveMember" 277 testBadOptions(t, methodName, func() (err error) { 278 _, err = client.Organizations.RemoveMember(ctx, "\n", "\n") 279 return err 280 }) 281 282 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 283 return client.Organizations.RemoveMember(ctx, "o", "u") 284 }) 285 } 286 287 func TestOrganizationsService_RemoveMember_invalidOrg(t *testing.T) { 288 client, _, _, teardown := setup() 289 defer teardown() 290 291 ctx := context.Background() 292 _, err := client.Organizations.RemoveMember(ctx, "%", "u") 293 testURLParseError(t, err) 294 } 295 296 func TestOrganizationsService_PublicizeMembership(t *testing.T) { 297 client, mux, _, teardown := setup() 298 defer teardown() 299 300 mux.HandleFunc("/orgs/o/public_members/u", func(w http.ResponseWriter, r *http.Request) { 301 testMethod(t, r, "PUT") 302 }) 303 304 ctx := context.Background() 305 _, err := client.Organizations.PublicizeMembership(ctx, "o", "u") 306 if err != nil { 307 t.Errorf("Organizations.PublicizeMembership returned error: %v", err) 308 } 309 310 const methodName = "PublicizeMembership" 311 testBadOptions(t, methodName, func() (err error) { 312 _, err = client.Organizations.PublicizeMembership(ctx, "\n", "\n") 313 return err 314 }) 315 316 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 317 return client.Organizations.PublicizeMembership(ctx, "o", "u") 318 }) 319 } 320 321 func TestOrganizationsService_ConcealMembership(t *testing.T) { 322 client, mux, _, teardown := setup() 323 defer teardown() 324 325 mux.HandleFunc("/orgs/o/public_members/u", func(w http.ResponseWriter, r *http.Request) { 326 testMethod(t, r, "DELETE") 327 }) 328 329 ctx := context.Background() 330 _, err := client.Organizations.ConcealMembership(ctx, "o", "u") 331 if err != nil { 332 t.Errorf("Organizations.ConcealMembership returned error: %v", err) 333 } 334 335 const methodName = "ConcealMembership" 336 testBadOptions(t, methodName, func() (err error) { 337 _, err = client.Organizations.ConcealMembership(ctx, "\n", "\n") 338 return err 339 }) 340 341 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 342 return client.Organizations.ConcealMembership(ctx, "o", "u") 343 }) 344 } 345 346 func TestOrganizationsService_ListOrgMemberships(t *testing.T) { 347 client, mux, _, teardown := setup() 348 defer teardown() 349 350 mux.HandleFunc("/user/memberships/orgs", func(w http.ResponseWriter, r *http.Request) { 351 testMethod(t, r, "GET") 352 testFormValues(t, r, values{ 353 "state": "active", 354 "page": "2", 355 }) 356 fmt.Fprint(w, `[{"url":"u"}]`) 357 }) 358 359 opt := &ListOrgMembershipsOptions{ 360 State: "active", 361 ListOptions: ListOptions{Page: 2}, 362 } 363 ctx := context.Background() 364 memberships, _, err := client.Organizations.ListOrgMemberships(ctx, opt) 365 if err != nil { 366 t.Errorf("Organizations.ListOrgMemberships returned error: %v", err) 367 } 368 369 want := []*Membership{{URL: String("u")}} 370 if !cmp.Equal(memberships, want) { 371 t.Errorf("Organizations.ListOrgMemberships returned %+v, want %+v", memberships, want) 372 } 373 374 const methodName = "ListOrgMemberships" 375 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 376 got, resp, err := client.Organizations.ListOrgMemberships(ctx, opt) 377 if got != nil { 378 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 379 } 380 return resp, err 381 }) 382 } 383 384 func TestOrganizationsService_GetOrgMembership_AuthenticatedUser(t *testing.T) { 385 client, mux, _, teardown := setup() 386 defer teardown() 387 388 mux.HandleFunc("/user/memberships/orgs/o", func(w http.ResponseWriter, r *http.Request) { 389 testMethod(t, r, "GET") 390 fmt.Fprint(w, `{"url":"u"}`) 391 }) 392 393 ctx := context.Background() 394 membership, _, err := client.Organizations.GetOrgMembership(ctx, "", "o") 395 if err != nil { 396 t.Errorf("Organizations.GetOrgMembership returned error: %v", err) 397 } 398 399 want := &Membership{URL: String("u")} 400 if !cmp.Equal(membership, want) { 401 t.Errorf("Organizations.GetOrgMembership returned %+v, want %+v", membership, want) 402 } 403 404 const methodName = "GetOrgMembership" 405 testBadOptions(t, methodName, func() (err error) { 406 _, _, err = client.Organizations.GetOrgMembership(ctx, "\n", "\n") 407 return err 408 }) 409 410 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 411 got, resp, err := client.Organizations.GetOrgMembership(ctx, "", "o") 412 if got != nil { 413 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 414 } 415 return resp, err 416 }) 417 } 418 419 func TestOrganizationsService_GetOrgMembership_SpecifiedUser(t *testing.T) { 420 client, mux, _, teardown := setup() 421 defer teardown() 422 423 mux.HandleFunc("/orgs/o/memberships/u", func(w http.ResponseWriter, r *http.Request) { 424 testMethod(t, r, "GET") 425 fmt.Fprint(w, `{"url":"u"}`) 426 }) 427 428 ctx := context.Background() 429 membership, _, err := client.Organizations.GetOrgMembership(ctx, "u", "o") 430 if err != nil { 431 t.Errorf("Organizations.GetOrgMembership returned error: %v", err) 432 } 433 434 want := &Membership{URL: String("u")} 435 if !cmp.Equal(membership, want) { 436 t.Errorf("Organizations.GetOrgMembership returned %+v, want %+v", membership, want) 437 } 438 } 439 440 func TestOrganizationsService_EditOrgMembership_AuthenticatedUser(t *testing.T) { 441 client, mux, _, teardown := setup() 442 defer teardown() 443 444 input := &Membership{State: String("active")} 445 446 mux.HandleFunc("/user/memberships/orgs/o", func(w http.ResponseWriter, r *http.Request) { 447 v := new(Membership) 448 json.NewDecoder(r.Body).Decode(v) 449 450 testMethod(t, r, "PATCH") 451 if !cmp.Equal(v, input) { 452 t.Errorf("Request body = %+v, want %+v", v, input) 453 } 454 455 fmt.Fprint(w, `{"url":"u"}`) 456 }) 457 458 ctx := context.Background() 459 membership, _, err := client.Organizations.EditOrgMembership(ctx, "", "o", input) 460 if err != nil { 461 t.Errorf("Organizations.EditOrgMembership returned error: %v", err) 462 } 463 464 want := &Membership{URL: String("u")} 465 if !cmp.Equal(membership, want) { 466 t.Errorf("Organizations.EditOrgMembership returned %+v, want %+v", membership, want) 467 } 468 469 const methodName = "EditOrgMembership" 470 testBadOptions(t, methodName, func() (err error) { 471 _, _, err = client.Organizations.EditOrgMembership(ctx, "\n", "\n", input) 472 return err 473 }) 474 475 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 476 got, resp, err := client.Organizations.EditOrgMembership(ctx, "", "o", input) 477 if got != nil { 478 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 479 } 480 return resp, err 481 }) 482 } 483 484 func TestOrganizationsService_EditOrgMembership_SpecifiedUser(t *testing.T) { 485 client, mux, _, teardown := setup() 486 defer teardown() 487 488 input := &Membership{State: String("active")} 489 490 mux.HandleFunc("/orgs/o/memberships/u", func(w http.ResponseWriter, r *http.Request) { 491 v := new(Membership) 492 json.NewDecoder(r.Body).Decode(v) 493 494 testMethod(t, r, "PUT") 495 if !cmp.Equal(v, input) { 496 t.Errorf("Request body = %+v, want %+v", v, input) 497 } 498 499 fmt.Fprint(w, `{"url":"u"}`) 500 }) 501 502 ctx := context.Background() 503 membership, _, err := client.Organizations.EditOrgMembership(ctx, "u", "o", input) 504 if err != nil { 505 t.Errorf("Organizations.EditOrgMembership returned error: %v", err) 506 } 507 508 want := &Membership{URL: String("u")} 509 if !cmp.Equal(membership, want) { 510 t.Errorf("Organizations.EditOrgMembership returned %+v, want %+v", membership, want) 511 } 512 } 513 514 func TestOrganizationsService_RemoveOrgMembership(t *testing.T) { 515 client, mux, _, teardown := setup() 516 defer teardown() 517 518 mux.HandleFunc("/orgs/o/memberships/u", func(w http.ResponseWriter, r *http.Request) { 519 testMethod(t, r, "DELETE") 520 w.WriteHeader(http.StatusNoContent) 521 }) 522 523 ctx := context.Background() 524 _, err := client.Organizations.RemoveOrgMembership(ctx, "u", "o") 525 if err != nil { 526 t.Errorf("Organizations.RemoveOrgMembership returned error: %v", err) 527 } 528 529 const methodName = "RemoveOrgMembership" 530 testBadOptions(t, methodName, func() (err error) { 531 _, err = client.Organizations.RemoveOrgMembership(ctx, "\n", "\n") 532 return err 533 }) 534 535 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 536 return client.Organizations.RemoveOrgMembership(ctx, "u", "o") 537 }) 538 } 539 540 func TestOrganizationsService_ListPendingOrgInvitations(t *testing.T) { 541 client, mux, _, teardown := setup() 542 defer teardown() 543 544 mux.HandleFunc("/orgs/o/invitations", func(w http.ResponseWriter, r *http.Request) { 545 testMethod(t, r, "GET") 546 testFormValues(t, r, values{"page": "1"}) 547 fmt.Fprint(w, `[ 548 { 549 "id": 1, 550 "login": "monalisa", 551 "email": "octocat@github.com", 552 "role": "direct_member", 553 "created_at": "2017-01-21T00:00:00Z", 554 "inviter": { 555 "login": "other_user", 556 "id": 1, 557 "avatar_url": "https://github.com/images/error/other_user_happy.gif", 558 "gravatar_id": "", 559 "url": "https://api.github.com/users/other_user", 560 "html_url": "https://github.com/other_user", 561 "followers_url": "https://api.github.com/users/other_user/followers", 562 "following_url": "https://api.github.com/users/other_user/following/other_user", 563 "gists_url": "https://api.github.com/users/other_user/gists/gist_id", 564 "starred_url": "https://api.github.com/users/other_user/starred/owner/repo", 565 "subscriptions_url": "https://api.github.com/users/other_user/subscriptions", 566 "organizations_url": "https://api.github.com/users/other_user/orgs", 567 "repos_url": "https://api.github.com/users/other_user/repos", 568 "events_url": "https://api.github.com/users/other_user/events/privacy", 569 "received_events_url": "https://api.github.com/users/other_user/received_events/privacy", 570 "type": "User", 571 "site_admin": false 572 }, 573 "team_count": 2, 574 "invitation_team_url": "https://api.github.com/organizations/2/invitations/1/teams" 575 } 576 ]`) 577 }) 578 579 opt := &ListOptions{Page: 1} 580 ctx := context.Background() 581 invitations, _, err := client.Organizations.ListPendingOrgInvitations(ctx, "o", opt) 582 if err != nil { 583 t.Errorf("Organizations.ListPendingOrgInvitations returned error: %v", err) 584 } 585 586 createdAt := time.Date(2017, time.January, 21, 0, 0, 0, 0, time.UTC) 587 want := []*Invitation{ 588 { 589 ID: Int64(1), 590 Login: String("monalisa"), 591 Email: String("octocat@github.com"), 592 Role: String("direct_member"), 593 CreatedAt: &createdAt, 594 Inviter: &User{ 595 Login: String("other_user"), 596 ID: Int64(1), 597 AvatarURL: String("https://github.com/images/error/other_user_happy.gif"), 598 GravatarID: String(""), 599 URL: String("https://api.github.com/users/other_user"), 600 HTMLURL: String("https://github.com/other_user"), 601 FollowersURL: String("https://api.github.com/users/other_user/followers"), 602 FollowingURL: String("https://api.github.com/users/other_user/following/other_user"), 603 GistsURL: String("https://api.github.com/users/other_user/gists/gist_id"), 604 StarredURL: String("https://api.github.com/users/other_user/starred/owner/repo"), 605 SubscriptionsURL: String("https://api.github.com/users/other_user/subscriptions"), 606 OrganizationsURL: String("https://api.github.com/users/other_user/orgs"), 607 ReposURL: String("https://api.github.com/users/other_user/repos"), 608 EventsURL: String("https://api.github.com/users/other_user/events/privacy"), 609 ReceivedEventsURL: String("https://api.github.com/users/other_user/received_events/privacy"), 610 Type: String("User"), 611 SiteAdmin: Bool(false), 612 }, 613 TeamCount: Int(2), 614 InvitationTeamURL: String("https://api.github.com/organizations/2/invitations/1/teams"), 615 }} 616 617 if !cmp.Equal(invitations, want) { 618 t.Errorf("Organizations.ListPendingOrgInvitations returned %+v, want %+v", invitations, want) 619 } 620 621 const methodName = "ListPendingOrgInvitations" 622 testBadOptions(t, methodName, func() (err error) { 623 _, _, err = client.Organizations.ListPendingOrgInvitations(ctx, "\n", opt) 624 return err 625 }) 626 627 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 628 got, resp, err := client.Organizations.ListPendingOrgInvitations(ctx, "o", opt) 629 if got != nil { 630 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 631 } 632 return resp, err 633 }) 634 } 635 636 func TestOrganizationsService_CreateOrgInvitation(t *testing.T) { 637 client, mux, _, teardown := setup() 638 defer teardown() 639 input := &CreateOrgInvitationOptions{ 640 Email: String("octocat@github.com"), 641 Role: String("direct_member"), 642 TeamID: []int64{ 643 12, 644 26, 645 }, 646 } 647 648 mux.HandleFunc("/orgs/o/invitations", func(w http.ResponseWriter, r *http.Request) { 649 v := new(CreateOrgInvitationOptions) 650 json.NewDecoder(r.Body).Decode(v) 651 652 testMethod(t, r, "POST") 653 if !cmp.Equal(v, input) { 654 t.Errorf("Request body = %+v, want %+v", v, input) 655 } 656 657 fmt.Fprintln(w, `{"email": "octocat@github.com"}`) 658 }) 659 660 ctx := context.Background() 661 invitations, _, err := client.Organizations.CreateOrgInvitation(ctx, "o", input) 662 if err != nil { 663 t.Errorf("Organizations.CreateOrgInvitation returned error: %v", err) 664 } 665 666 want := &Invitation{Email: String("octocat@github.com")} 667 if !cmp.Equal(invitations, want) { 668 t.Errorf("Organizations.ListPendingOrgInvitations returned %+v, want %+v", invitations, want) 669 } 670 671 const methodName = "CreateOrgInvitation" 672 testBadOptions(t, methodName, func() (err error) { 673 _, _, err = client.Organizations.CreateOrgInvitation(ctx, "\n", input) 674 return err 675 }) 676 677 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 678 got, resp, err := client.Organizations.CreateOrgInvitation(ctx, "o", input) 679 if got != nil { 680 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 681 } 682 return resp, err 683 }) 684 } 685 686 func TestOrganizationsService_ListOrgInvitationTeams(t *testing.T) { 687 client, mux, _, teardown := setup() 688 defer teardown() 689 690 mux.HandleFunc("/orgs/o/invitations/22/teams", func(w http.ResponseWriter, r *http.Request) { 691 testMethod(t, r, "GET") 692 testFormValues(t, r, values{"page": "1"}) 693 fmt.Fprint(w, `[ 694 { 695 "id": 1, 696 "url": "https://api.github.com/teams/1", 697 "name": "Justice League", 698 "slug": "justice-league", 699 "description": "A great team.", 700 "privacy": "closed", 701 "permission": "admin", 702 "members_url": "https://api.github.com/teams/1/members{/member}", 703 "repositories_url": "https://api.github.com/teams/1/repos" 704 } 705 ]`) 706 }) 707 708 opt := &ListOptions{Page: 1} 709 ctx := context.Background() 710 invitations, _, err := client.Organizations.ListOrgInvitationTeams(ctx, "o", "22", opt) 711 if err != nil { 712 t.Errorf("Organizations.ListOrgInvitationTeams returned error: %v", err) 713 } 714 715 want := []*Team{ 716 { 717 ID: Int64(1), 718 URL: String("https://api.github.com/teams/1"), 719 Name: String("Justice League"), 720 Slug: String("justice-league"), 721 Description: String("A great team."), 722 Privacy: String("closed"), 723 Permission: String("admin"), 724 MembersURL: String("https://api.github.com/teams/1/members{/member}"), 725 RepositoriesURL: String("https://api.github.com/teams/1/repos"), 726 }, 727 } 728 729 if !cmp.Equal(invitations, want) { 730 t.Errorf("Organizations.ListOrgInvitationTeams returned %+v, want %+v", invitations, want) 731 } 732 733 const methodName = "ListOrgInvitationTeams" 734 testBadOptions(t, methodName, func() (err error) { 735 _, _, err = client.Organizations.ListOrgInvitationTeams(ctx, "\n", "\n", opt) 736 return err 737 }) 738 739 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 740 got, resp, err := client.Organizations.ListOrgInvitationTeams(ctx, "o", "22", opt) 741 if got != nil { 742 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 743 } 744 return resp, err 745 }) 746 } 747 748 func TestOrganizationsService_ListFailedOrgInvitations(t *testing.T) { 749 client, mux, _, teardown := setup() 750 defer teardown() 751 752 mux.HandleFunc("/orgs/o/failed_invitations", func(w http.ResponseWriter, r *http.Request) { 753 testMethod(t, r, "GET") 754 testFormValues(t, r, values{"page": "2", "per_page": "1"}) 755 fmt.Fprint(w, `[ 756 { 757 "id":1, 758 "login":"monalisa", 759 "node_id":"MDQ6VXNlcjE=", 760 "email":"octocat@github.com", 761 "role":"direct_member", 762 "created_at":"2016-11-30T06:46:10Z", 763 "failed_at":"2017-01-02T01:10:00Z", 764 "failed_reason":"the reason", 765 "inviter":{ 766 "login":"other_user", 767 "id":1, 768 "node_id":"MDQ6VXNlcjE=", 769 "avatar_url":"https://github.com/images/error/other_user_happy.gif", 770 "gravatar_id":"", 771 "url":"https://api.github.com/users/other_user", 772 "html_url":"https://github.com/other_user", 773 "followers_url":"https://api.github.com/users/other_user/followers", 774 "following_url":"https://api.github.com/users/other_user/following{/other_user}", 775 "gists_url":"https://api.github.com/users/other_user/gists{/gist_id}", 776 "starred_url":"https://api.github.com/users/other_user/starred{/owner}{/repo}", 777 "subscriptions_url":"https://api.github.com/users/other_user/subscriptions", 778 "organizations_url":"https://api.github.com/users/other_user/orgs", 779 "repos_url":"https://api.github.com/users/other_user/repos", 780 "events_url":"https://api.github.com/users/other_user/events{/privacy}", 781 "received_events_url":"https://api.github.com/users/other_user/received_events", 782 "type":"User", 783 "site_admin":false 784 }, 785 "team_count":2, 786 "invitation_team_url":"https://api.github.com/organizations/2/invitations/1/teams" 787 } 788 ]`) 789 }) 790 791 opts := &ListOptions{Page: 2, PerPage: 1} 792 ctx := context.Background() 793 failedInvitations, _, err := client.Organizations.ListFailedOrgInvitations(ctx, "o", opts) 794 if err != nil { 795 t.Errorf("Organizations.ListFailedOrgInvitations returned error: %v", err) 796 } 797 798 createdAt := time.Date(2016, time.November, 30, 6, 46, 10, 0, time.UTC) 799 want := []*Invitation{ 800 { 801 ID: Int64(1), 802 Login: String("monalisa"), 803 NodeID: String("MDQ6VXNlcjE="), 804 Email: String("octocat@github.com"), 805 Role: String("direct_member"), 806 FailedAt: &Timestamp{time.Date(2017, time.January, 2, 1, 10, 0, 0, time.UTC)}, 807 FailedReason: String("the reason"), 808 CreatedAt: &createdAt, 809 Inviter: &User{ 810 Login: String("other_user"), 811 ID: Int64(1), 812 NodeID: String("MDQ6VXNlcjE="), 813 AvatarURL: String("https://github.com/images/error/other_user_happy.gif"), 814 GravatarID: String(""), 815 URL: String("https://api.github.com/users/other_user"), 816 HTMLURL: String("https://github.com/other_user"), 817 FollowersURL: String("https://api.github.com/users/other_user/followers"), 818 FollowingURL: String("https://api.github.com/users/other_user/following{/other_user}"), 819 GistsURL: String("https://api.github.com/users/other_user/gists{/gist_id}"), 820 StarredURL: String("https://api.github.com/users/other_user/starred{/owner}{/repo}"), 821 SubscriptionsURL: String("https://api.github.com/users/other_user/subscriptions"), 822 OrganizationsURL: String("https://api.github.com/users/other_user/orgs"), 823 ReposURL: String("https://api.github.com/users/other_user/repos"), 824 EventsURL: String("https://api.github.com/users/other_user/events{/privacy}"), 825 ReceivedEventsURL: String("https://api.github.com/users/other_user/received_events"), 826 Type: String("User"), 827 SiteAdmin: Bool(false), 828 }, 829 TeamCount: Int(2), 830 InvitationTeamURL: String("https://api.github.com/organizations/2/invitations/1/teams"), 831 }, 832 } 833 834 if !cmp.Equal(failedInvitations, want) { 835 t.Errorf("Organizations.ListFailedOrgInvitations returned %+v, want %+v", failedInvitations, want) 836 } 837 838 const methodName = "ListFailedOrgInvitations" 839 testBadOptions(t, methodName, func() error { 840 _, _, err := client.Organizations.ListFailedOrgInvitations(ctx, "\n", opts) 841 return err 842 }) 843 844 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 845 got, resp, err := client.Organizations.ListFailedOrgInvitations(ctx, "o", opts) 846 if got != nil { 847 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 848 } 849 return resp, err 850 }) 851 } 852 853 func TestMembership_Marshal(t *testing.T) { 854 testJSONMarshal(t, &Membership{}, "{}") 855 856 u := &Membership{ 857 URL: String("url"), 858 State: String("state"), 859 Role: String("email"), 860 OrganizationURL: String("orgurl"), 861 Organization: &Organization{ 862 BillingEmail: String("be"), 863 Blog: String("b"), 864 Company: String("c"), 865 Email: String("e"), 866 TwitterUsername: String("tu"), 867 Location: String("loc"), 868 Name: String("n"), 869 Description: String("d"), 870 IsVerified: Bool(true), 871 HasOrganizationProjects: Bool(true), 872 HasRepositoryProjects: Bool(true), 873 DefaultRepoPermission: String("drp"), 874 MembersCanCreateRepos: Bool(true), 875 MembersCanCreateInternalRepos: Bool(true), 876 MembersCanCreatePrivateRepos: Bool(true), 877 MembersCanCreatePublicRepos: Bool(false), 878 MembersAllowedRepositoryCreationType: String("marct"), 879 MembersCanCreatePages: Bool(true), 880 MembersCanCreatePublicPages: Bool(false), 881 MembersCanCreatePrivatePages: Bool(true), 882 }, 883 User: &User{ 884 Login: String("l"), 885 ID: Int64(1), 886 NodeID: String("n"), 887 URL: String("u"), 888 ReposURL: String("r"), 889 EventsURL: String("e"), 890 AvatarURL: String("a"), 891 }, 892 } 893 894 want := `{ 895 "url": "url", 896 "state": "state", 897 "role": "email", 898 "organization_url": "orgurl", 899 "organization": { 900 "name": "n", 901 "company": "c", 902 "blog": "b", 903 "location": "loc", 904 "email": "e", 905 "twitter_username": "tu", 906 "description": "d", 907 "billing_email": "be", 908 "is_verified": true, 909 "has_organization_projects": true, 910 "has_repository_projects": true, 911 "default_repository_permission": "drp", 912 "members_can_create_repositories": true, 913 "members_can_create_public_repositories": false, 914 "members_can_create_private_repositories": true, 915 "members_can_create_internal_repositories": true, 916 "members_allowed_repository_creation_type": "marct", 917 "members_can_create_pages": true, 918 "members_can_create_public_pages": false, 919 "members_can_create_private_pages": true 920 }, 921 "user": { 922 "login": "l", 923 "id": 1, 924 "node_id": "n", 925 "avatar_url": "a", 926 "url": "u", 927 "events_url": "e", 928 "repos_url": "r" 929 } 930 }` 931 932 testJSONMarshal(t, u, want) 933 } 934 935 func TestCreateOrgInvitationOptions_Marshal(t *testing.T) { 936 testJSONMarshal(t, &CreateOrgInvitationOptions{}, "{}") 937 938 u := &CreateOrgInvitationOptions{ 939 InviteeID: Int64(1), 940 Email: String("email"), 941 Role: String("role"), 942 TeamID: []int64{1}, 943 } 944 945 want := `{ 946 "invitee_id": 1, 947 "email": "email", 948 "role": "role", 949 "team_ids": [ 950 1 951 ] 952 }` 953 954 testJSONMarshal(t, u, want) 955 }