github.com/google/go-github/v33@v33.0.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  	"reflect"
    14  	"testing"
    15  	"time"
    16  )
    17  
    18  func TestOrganizationsService_ListMembers(t *testing.T) {
    19  	client, mux, _, teardown := setup()
    20  	defer teardown()
    21  
    22  	mux.HandleFunc("/orgs/o/members", func(w http.ResponseWriter, r *http.Request) {
    23  		testMethod(t, r, "GET")
    24  		testFormValues(t, r, values{
    25  			"filter": "2fa_disabled",
    26  			"role":   "admin",
    27  			"page":   "2",
    28  		})
    29  		fmt.Fprint(w, `[{"id":1}]`)
    30  	})
    31  
    32  	opt := &ListMembersOptions{
    33  		PublicOnly:  false,
    34  		Filter:      "2fa_disabled",
    35  		Role:        "admin",
    36  		ListOptions: ListOptions{Page: 2},
    37  	}
    38  	members, _, err := client.Organizations.ListMembers(context.Background(), "o", opt)
    39  	if err != nil {
    40  		t.Errorf("Organizations.ListMembers returned error: %v", err)
    41  	}
    42  
    43  	want := []*User{{ID: Int64(1)}}
    44  	if !reflect.DeepEqual(members, want) {
    45  		t.Errorf("Organizations.ListMembers returned %+v, want %+v", members, want)
    46  	}
    47  }
    48  
    49  func TestOrganizationsService_ListMembers_invalidOrg(t *testing.T) {
    50  	client, _, _, teardown := setup()
    51  	defer teardown()
    52  
    53  	_, _, err := client.Organizations.ListMembers(context.Background(), "%", nil)
    54  	testURLParseError(t, err)
    55  }
    56  
    57  func TestOrganizationsService_ListMembers_public(t *testing.T) {
    58  	client, mux, _, teardown := setup()
    59  	defer teardown()
    60  
    61  	mux.HandleFunc("/orgs/o/public_members", func(w http.ResponseWriter, r *http.Request) {
    62  		testMethod(t, r, "GET")
    63  		fmt.Fprint(w, `[{"id":1}]`)
    64  	})
    65  
    66  	opt := &ListMembersOptions{PublicOnly: true}
    67  	members, _, err := client.Organizations.ListMembers(context.Background(), "o", opt)
    68  	if err != nil {
    69  		t.Errorf("Organizations.ListMembers returned error: %v", err)
    70  	}
    71  
    72  	want := []*User{{ID: Int64(1)}}
    73  	if !reflect.DeepEqual(members, want) {
    74  		t.Errorf("Organizations.ListMembers returned %+v, want %+v", members, want)
    75  	}
    76  }
    77  
    78  func TestOrganizationsService_IsMember(t *testing.T) {
    79  	client, mux, _, teardown := setup()
    80  	defer teardown()
    81  
    82  	mux.HandleFunc("/orgs/o/members/u", func(w http.ResponseWriter, r *http.Request) {
    83  		testMethod(t, r, "GET")
    84  		w.WriteHeader(http.StatusNoContent)
    85  	})
    86  
    87  	member, _, err := client.Organizations.IsMember(context.Background(), "o", "u")
    88  	if err != nil {
    89  		t.Errorf("Organizations.IsMember returned error: %v", err)
    90  	}
    91  	if want := true; member != want {
    92  		t.Errorf("Organizations.IsMember returned %+v, want %+v", member, want)
    93  	}
    94  }
    95  
    96  // ensure that a 404 response is interpreted as "false" and not an error
    97  func TestOrganizationsService_IsMember_notMember(t *testing.T) {
    98  	client, mux, _, teardown := setup()
    99  	defer teardown()
   100  
   101  	mux.HandleFunc("/orgs/o/members/u", func(w http.ResponseWriter, r *http.Request) {
   102  		testMethod(t, r, "GET")
   103  		w.WriteHeader(http.StatusNotFound)
   104  	})
   105  
   106  	member, _, err := client.Organizations.IsMember(context.Background(), "o", "u")
   107  	if err != nil {
   108  		t.Errorf("Organizations.IsMember returned error: %+v", err)
   109  	}
   110  	if want := false; member != want {
   111  		t.Errorf("Organizations.IsMember returned %+v, want %+v", member, want)
   112  	}
   113  }
   114  
   115  // ensure that a 400 response is interpreted as an actual error, and not simply
   116  // as "false" like the above case of a 404
   117  func TestOrganizationsService_IsMember_error(t *testing.T) {
   118  	client, mux, _, teardown := setup()
   119  	defer teardown()
   120  
   121  	mux.HandleFunc("/orgs/o/members/u", func(w http.ResponseWriter, r *http.Request) {
   122  		testMethod(t, r, "GET")
   123  		http.Error(w, "BadRequest", http.StatusBadRequest)
   124  	})
   125  
   126  	member, _, err := client.Organizations.IsMember(context.Background(), "o", "u")
   127  	if err == nil {
   128  		t.Errorf("Expected HTTP 400 response")
   129  	}
   130  	if want := false; member != want {
   131  		t.Errorf("Organizations.IsMember returned %+v, want %+v", member, want)
   132  	}
   133  }
   134  
   135  func TestOrganizationsService_IsMember_invalidOrg(t *testing.T) {
   136  	client, _, _, teardown := setup()
   137  	defer teardown()
   138  
   139  	_, _, err := client.Organizations.IsMember(context.Background(), "%", "u")
   140  	testURLParseError(t, err)
   141  }
   142  
   143  func TestOrganizationsService_IsPublicMember(t *testing.T) {
   144  	client, mux, _, teardown := setup()
   145  	defer teardown()
   146  
   147  	mux.HandleFunc("/orgs/o/public_members/u", func(w http.ResponseWriter, r *http.Request) {
   148  		testMethod(t, r, "GET")
   149  		w.WriteHeader(http.StatusNoContent)
   150  	})
   151  
   152  	member, _, err := client.Organizations.IsPublicMember(context.Background(), "o", "u")
   153  	if err != nil {
   154  		t.Errorf("Organizations.IsPublicMember returned error: %v", err)
   155  	}
   156  	if want := true; member != want {
   157  		t.Errorf("Organizations.IsPublicMember returned %+v, want %+v", member, want)
   158  	}
   159  }
   160  
   161  // ensure that a 404 response is interpreted as "false" and not an error
   162  func TestOrganizationsService_IsPublicMember_notMember(t *testing.T) {
   163  	client, mux, _, teardown := setup()
   164  	defer teardown()
   165  
   166  	mux.HandleFunc("/orgs/o/public_members/u", func(w http.ResponseWriter, r *http.Request) {
   167  		testMethod(t, r, "GET")
   168  		w.WriteHeader(http.StatusNotFound)
   169  	})
   170  
   171  	member, _, err := client.Organizations.IsPublicMember(context.Background(), "o", "u")
   172  	if err != nil {
   173  		t.Errorf("Organizations.IsPublicMember returned error: %v", err)
   174  	}
   175  	if want := false; member != want {
   176  		t.Errorf("Organizations.IsPublicMember returned %+v, want %+v", member, want)
   177  	}
   178  }
   179  
   180  // ensure that a 400 response is interpreted as an actual error, and not simply
   181  // as "false" like the above case of a 404
   182  func TestOrganizationsService_IsPublicMember_error(t *testing.T) {
   183  	client, mux, _, teardown := setup()
   184  	defer teardown()
   185  
   186  	mux.HandleFunc("/orgs/o/public_members/u", func(w http.ResponseWriter, r *http.Request) {
   187  		testMethod(t, r, "GET")
   188  		http.Error(w, "BadRequest", http.StatusBadRequest)
   189  	})
   190  
   191  	member, _, err := client.Organizations.IsPublicMember(context.Background(), "o", "u")
   192  	if err == nil {
   193  		t.Errorf("Expected HTTP 400 response")
   194  	}
   195  	if want := false; member != want {
   196  		t.Errorf("Organizations.IsPublicMember returned %+v, want %+v", member, want)
   197  	}
   198  }
   199  
   200  func TestOrganizationsService_IsPublicMember_invalidOrg(t *testing.T) {
   201  	client, _, _, teardown := setup()
   202  	defer teardown()
   203  
   204  	_, _, err := client.Organizations.IsPublicMember(context.Background(), "%", "u")
   205  	testURLParseError(t, err)
   206  }
   207  
   208  func TestOrganizationsService_RemoveMember(t *testing.T) {
   209  	client, mux, _, teardown := setup()
   210  	defer teardown()
   211  
   212  	mux.HandleFunc("/orgs/o/members/u", func(w http.ResponseWriter, r *http.Request) {
   213  		testMethod(t, r, "DELETE")
   214  	})
   215  
   216  	_, err := client.Organizations.RemoveMember(context.Background(), "o", "u")
   217  	if err != nil {
   218  		t.Errorf("Organizations.RemoveMember returned error: %v", err)
   219  	}
   220  }
   221  
   222  func TestOrganizationsService_RemoveMember_invalidOrg(t *testing.T) {
   223  	client, _, _, teardown := setup()
   224  	defer teardown()
   225  
   226  	_, err := client.Organizations.RemoveMember(context.Background(), "%", "u")
   227  	testURLParseError(t, err)
   228  }
   229  
   230  func TestOrganizationsService_ListOrgMemberships(t *testing.T) {
   231  	client, mux, _, teardown := setup()
   232  	defer teardown()
   233  
   234  	mux.HandleFunc("/user/memberships/orgs", func(w http.ResponseWriter, r *http.Request) {
   235  		testMethod(t, r, "GET")
   236  		testFormValues(t, r, values{
   237  			"state": "active",
   238  			"page":  "2",
   239  		})
   240  		fmt.Fprint(w, `[{"url":"u"}]`)
   241  	})
   242  
   243  	opt := &ListOrgMembershipsOptions{
   244  		State:       "active",
   245  		ListOptions: ListOptions{Page: 2},
   246  	}
   247  	memberships, _, err := client.Organizations.ListOrgMemberships(context.Background(), opt)
   248  	if err != nil {
   249  		t.Errorf("Organizations.ListOrgMemberships returned error: %v", err)
   250  	}
   251  
   252  	want := []*Membership{{URL: String("u")}}
   253  	if !reflect.DeepEqual(memberships, want) {
   254  		t.Errorf("Organizations.ListOrgMemberships returned %+v, want %+v", memberships, want)
   255  	}
   256  }
   257  
   258  func TestOrganizationsService_GetOrgMembership_AuthenticatedUser(t *testing.T) {
   259  	client, mux, _, teardown := setup()
   260  	defer teardown()
   261  
   262  	mux.HandleFunc("/user/memberships/orgs/o", func(w http.ResponseWriter, r *http.Request) {
   263  		testMethod(t, r, "GET")
   264  		fmt.Fprint(w, `{"url":"u"}`)
   265  	})
   266  
   267  	membership, _, err := client.Organizations.GetOrgMembership(context.Background(), "", "o")
   268  	if err != nil {
   269  		t.Errorf("Organizations.GetOrgMembership returned error: %v", err)
   270  	}
   271  
   272  	want := &Membership{URL: String("u")}
   273  	if !reflect.DeepEqual(membership, want) {
   274  		t.Errorf("Organizations.GetOrgMembership returned %+v, want %+v", membership, want)
   275  	}
   276  }
   277  
   278  func TestOrganizationsService_GetOrgMembership_SpecifiedUser(t *testing.T) {
   279  	client, mux, _, teardown := setup()
   280  	defer teardown()
   281  
   282  	mux.HandleFunc("/orgs/o/memberships/u", func(w http.ResponseWriter, r *http.Request) {
   283  		testMethod(t, r, "GET")
   284  		fmt.Fprint(w, `{"url":"u"}`)
   285  	})
   286  
   287  	membership, _, err := client.Organizations.GetOrgMembership(context.Background(), "u", "o")
   288  	if err != nil {
   289  		t.Errorf("Organizations.GetOrgMembership returned error: %v", err)
   290  	}
   291  
   292  	want := &Membership{URL: String("u")}
   293  	if !reflect.DeepEqual(membership, want) {
   294  		t.Errorf("Organizations.GetOrgMembership returned %+v, want %+v", membership, want)
   295  	}
   296  }
   297  
   298  func TestOrganizationsService_EditOrgMembership_AuthenticatedUser(t *testing.T) {
   299  	client, mux, _, teardown := setup()
   300  	defer teardown()
   301  
   302  	input := &Membership{State: String("active")}
   303  
   304  	mux.HandleFunc("/user/memberships/orgs/o", func(w http.ResponseWriter, r *http.Request) {
   305  		v := new(Membership)
   306  		json.NewDecoder(r.Body).Decode(v)
   307  
   308  		testMethod(t, r, "PATCH")
   309  		if !reflect.DeepEqual(v, input) {
   310  			t.Errorf("Request body = %+v, want %+v", v, input)
   311  		}
   312  
   313  		fmt.Fprint(w, `{"url":"u"}`)
   314  	})
   315  
   316  	membership, _, err := client.Organizations.EditOrgMembership(context.Background(), "", "o", input)
   317  	if err != nil {
   318  		t.Errorf("Organizations.EditOrgMembership returned error: %v", err)
   319  	}
   320  
   321  	want := &Membership{URL: String("u")}
   322  	if !reflect.DeepEqual(membership, want) {
   323  		t.Errorf("Organizations.EditOrgMembership returned %+v, want %+v", membership, want)
   324  	}
   325  }
   326  
   327  func TestOrganizationsService_EditOrgMembership_SpecifiedUser(t *testing.T) {
   328  	client, mux, _, teardown := setup()
   329  	defer teardown()
   330  
   331  	input := &Membership{State: String("active")}
   332  
   333  	mux.HandleFunc("/orgs/o/memberships/u", func(w http.ResponseWriter, r *http.Request) {
   334  		v := new(Membership)
   335  		json.NewDecoder(r.Body).Decode(v)
   336  
   337  		testMethod(t, r, "PUT")
   338  		if !reflect.DeepEqual(v, input) {
   339  			t.Errorf("Request body = %+v, want %+v", v, input)
   340  		}
   341  
   342  		fmt.Fprint(w, `{"url":"u"}`)
   343  	})
   344  
   345  	membership, _, err := client.Organizations.EditOrgMembership(context.Background(), "u", "o", input)
   346  	if err != nil {
   347  		t.Errorf("Organizations.EditOrgMembership returned error: %v", err)
   348  	}
   349  
   350  	want := &Membership{URL: String("u")}
   351  	if !reflect.DeepEqual(membership, want) {
   352  		t.Errorf("Organizations.EditOrgMembership returned %+v, want %+v", membership, want)
   353  	}
   354  }
   355  
   356  func TestOrganizationsService_RemoveOrgMembership(t *testing.T) {
   357  	client, mux, _, teardown := setup()
   358  	defer teardown()
   359  
   360  	mux.HandleFunc("/orgs/o/memberships/u", func(w http.ResponseWriter, r *http.Request) {
   361  		testMethod(t, r, "DELETE")
   362  		w.WriteHeader(http.StatusNoContent)
   363  	})
   364  
   365  	_, err := client.Organizations.RemoveOrgMembership(context.Background(), "u", "o")
   366  	if err != nil {
   367  		t.Errorf("Organizations.RemoveOrgMembership returned error: %v", err)
   368  	}
   369  }
   370  
   371  func TestOrganizationsService_ListPendingOrgInvitations(t *testing.T) {
   372  	client, mux, _, teardown := setup()
   373  	defer teardown()
   374  
   375  	mux.HandleFunc("/orgs/o/invitations", func(w http.ResponseWriter, r *http.Request) {
   376  		testMethod(t, r, "GET")
   377  		testFormValues(t, r, values{"page": "1"})
   378  		fmt.Fprint(w, `[
   379  				{
   380      					"id": 1,
   381      					"login": "monalisa",
   382      					"email": "octocat@github.com",
   383      					"role": "direct_member",
   384  					"created_at": "2017-01-21T00:00:00Z",
   385      					"inviter": {
   386        						"login": "other_user",
   387        						"id": 1,
   388        						"avatar_url": "https://github.com/images/error/other_user_happy.gif",
   389        						"gravatar_id": "",
   390        						"url": "https://api.github.com/users/other_user",
   391        						"html_url": "https://github.com/other_user",
   392        						"followers_url": "https://api.github.com/users/other_user/followers",
   393        						"following_url": "https://api.github.com/users/other_user/following/other_user",
   394        						"gists_url": "https://api.github.com/users/other_user/gists/gist_id",
   395        						"starred_url": "https://api.github.com/users/other_user/starred/owner/repo",
   396        						"subscriptions_url": "https://api.github.com/users/other_user/subscriptions",
   397        						"organizations_url": "https://api.github.com/users/other_user/orgs",
   398        						"repos_url": "https://api.github.com/users/other_user/repos",
   399        						"events_url": "https://api.github.com/users/other_user/events/privacy",
   400        						"received_events_url": "https://api.github.com/users/other_user/received_events/privacy",
   401        						"type": "User",
   402        						"site_admin": false
   403  						},
   404  						"team_count": 2,
   405  						"invitation_team_url": "https://api.github.com/organizations/2/invitations/1/teams"
   406    				}
   407  			]`)
   408  	})
   409  
   410  	opt := &ListOptions{Page: 1}
   411  	invitations, _, err := client.Organizations.ListPendingOrgInvitations(context.Background(), "o", opt)
   412  	if err != nil {
   413  		t.Errorf("Organizations.ListPendingOrgInvitations returned error: %v", err)
   414  	}
   415  
   416  	createdAt := time.Date(2017, time.January, 21, 0, 0, 0, 0, time.UTC)
   417  	want := []*Invitation{
   418  		{
   419  			ID:        Int64(1),
   420  			Login:     String("monalisa"),
   421  			Email:     String("octocat@github.com"),
   422  			Role:      String("direct_member"),
   423  			CreatedAt: &createdAt,
   424  			Inviter: &User{
   425  				Login:             String("other_user"),
   426  				ID:                Int64(1),
   427  				AvatarURL:         String("https://github.com/images/error/other_user_happy.gif"),
   428  				GravatarID:        String(""),
   429  				URL:               String("https://api.github.com/users/other_user"),
   430  				HTMLURL:           String("https://github.com/other_user"),
   431  				FollowersURL:      String("https://api.github.com/users/other_user/followers"),
   432  				FollowingURL:      String("https://api.github.com/users/other_user/following/other_user"),
   433  				GistsURL:          String("https://api.github.com/users/other_user/gists/gist_id"),
   434  				StarredURL:        String("https://api.github.com/users/other_user/starred/owner/repo"),
   435  				SubscriptionsURL:  String("https://api.github.com/users/other_user/subscriptions"),
   436  				OrganizationsURL:  String("https://api.github.com/users/other_user/orgs"),
   437  				ReposURL:          String("https://api.github.com/users/other_user/repos"),
   438  				EventsURL:         String("https://api.github.com/users/other_user/events/privacy"),
   439  				ReceivedEventsURL: String("https://api.github.com/users/other_user/received_events/privacy"),
   440  				Type:              String("User"),
   441  				SiteAdmin:         Bool(false),
   442  			},
   443  			TeamCount:         Int(2),
   444  			InvitationTeamURL: String("https://api.github.com/organizations/2/invitations/1/teams"),
   445  		}}
   446  
   447  	if !reflect.DeepEqual(invitations, want) {
   448  		t.Errorf("Organizations.ListPendingOrgInvitations returned %+v, want %+v", invitations, want)
   449  	}
   450  }
   451  
   452  func TestOrganizationsService_CreateOrgInvitation(t *testing.T) {
   453  	client, mux, _, teardown := setup()
   454  	defer teardown()
   455  	input := &CreateOrgInvitationOptions{
   456  		Email: String("octocat@github.com"),
   457  		Role:  String("direct_member"),
   458  		TeamID: []int64{
   459  			12,
   460  			26,
   461  		},
   462  	}
   463  
   464  	mux.HandleFunc("/orgs/o/invitations", func(w http.ResponseWriter, r *http.Request) {
   465  		v := new(CreateOrgInvitationOptions)
   466  		json.NewDecoder(r.Body).Decode(v)
   467  
   468  		testMethod(t, r, "POST")
   469  		if !reflect.DeepEqual(v, input) {
   470  			t.Errorf("Request body = %+v, want %+v", v, input)
   471  		}
   472  
   473  		fmt.Fprintln(w, `{"email": "octocat@github.com"}`)
   474  
   475  	})
   476  
   477  	invitations, _, err := client.Organizations.CreateOrgInvitation(context.Background(), "o", input)
   478  	if err != nil {
   479  		t.Errorf("Organizations.CreateOrgInvitation returned error: %v", err)
   480  	}
   481  
   482  	want := &Invitation{Email: String("octocat@github.com")}
   483  	if !reflect.DeepEqual(invitations, want) {
   484  		t.Errorf("Organizations.ListPendingOrgInvitations returned %+v, want %+v", invitations, want)
   485  	}
   486  }
   487  
   488  func TestOrganizationsService_ListOrgInvitationTeams(t *testing.T) {
   489  	client, mux, _, teardown := setup()
   490  	defer teardown()
   491  
   492  	mux.HandleFunc("/orgs/o/invitations/22/teams", func(w http.ResponseWriter, r *http.Request) {
   493  		testMethod(t, r, "GET")
   494  		testFormValues(t, r, values{"page": "1"})
   495  		fmt.Fprint(w, `[
   496  			{
   497  				"id": 1,
   498  				"url": "https://api.github.com/teams/1",
   499  				"name": "Justice League",
   500  				"slug": "justice-league",
   501  				"description": "A great team.",
   502  				"privacy": "closed",
   503  				"permission": "admin",
   504  				"members_url": "https://api.github.com/teams/1/members{/member}",
   505  				"repositories_url": "https://api.github.com/teams/1/repos"
   506  			  }
   507  			]`)
   508  	})
   509  
   510  	opt := &ListOptions{Page: 1}
   511  	invitations, _, err := client.Organizations.ListOrgInvitationTeams(context.Background(), "o", "22", opt)
   512  	if err != nil {
   513  		t.Errorf("Organizations.ListOrgInvitationTeams returned error: %v", err)
   514  	}
   515  
   516  	want := []*Team{
   517  		{
   518  			ID:              Int64(1),
   519  			URL:             String("https://api.github.com/teams/1"),
   520  			Name:            String("Justice League"),
   521  			Slug:            String("justice-league"),
   522  			Description:     String("A great team."),
   523  			Privacy:         String("closed"),
   524  			Permission:      String("admin"),
   525  			MembersURL:      String("https://api.github.com/teams/1/members{/member}"),
   526  			RepositoriesURL: String("https://api.github.com/teams/1/repos"),
   527  		},
   528  	}
   529  
   530  	if !reflect.DeepEqual(invitations, want) {
   531  		t.Errorf("Organizations.ListOrgInvitationTeams returned %+v, want %+v", invitations, want)
   532  	}
   533  }