github.com/google/go-github/v33@v33.0.0/github/repos_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  	"strings"
    15  	"testing"
    16  	"time"
    17  )
    18  
    19  func TestRepositoriesService_List_authenticatedUser(t *testing.T) {
    20  	client, mux, _, teardown := setup()
    21  	defer teardown()
    22  
    23  	wantAcceptHeaders := []string{mediaTypeTopicsPreview}
    24  	mux.HandleFunc("/user/repos", func(w http.ResponseWriter, r *http.Request) {
    25  		testMethod(t, r, "GET")
    26  		testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", "))
    27  		fmt.Fprint(w, `[{"id":1},{"id":2}]`)
    28  	})
    29  
    30  	ctx := context.Background()
    31  	got, _, err := client.Repositories.List(ctx, "", nil)
    32  	if err != nil {
    33  		t.Errorf("Repositories.List returned error: %v", err)
    34  	}
    35  
    36  	want := []*Repository{{ID: Int64(1)}, {ID: Int64(2)}}
    37  	if !reflect.DeepEqual(got, want) {
    38  		t.Errorf("Repositories.List returned %+v, want %+v", got, want)
    39  	}
    40  
    41  	// Test addOptions failure
    42  	_, _, err = client.Repositories.List(ctx, "\n", &RepositoryListOptions{})
    43  	if err == nil {
    44  		t.Error("bad options List err = nil, want error")
    45  	}
    46  
    47  	// Test s.client.Do failure
    48  	client.BaseURL.Path = "/api-v3/"
    49  	client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute)
    50  	got, resp, err := client.Repositories.List(ctx, "", nil)
    51  	if got != nil {
    52  		t.Errorf("rate.Reset.Time > now List = %#v, want nil", got)
    53  	}
    54  	if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want {
    55  		t.Errorf("rate.Reset.Time > now List resp = %#v, want StatusCode=%v", resp.Response, want)
    56  	}
    57  	if err == nil {
    58  		t.Error("rate.Reset.Time > now List err = nil, want error")
    59  	}
    60  }
    61  
    62  func TestRepositoriesService_List_specifiedUser(t *testing.T) {
    63  	client, mux, _, teardown := setup()
    64  	defer teardown()
    65  
    66  	wantAcceptHeaders := []string{mediaTypeTopicsPreview}
    67  	mux.HandleFunc("/users/u/repos", func(w http.ResponseWriter, r *http.Request) {
    68  		testMethod(t, r, "GET")
    69  		testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", "))
    70  		testFormValues(t, r, values{
    71  			"visibility":  "public",
    72  			"affiliation": "owner,collaborator",
    73  			"sort":        "created",
    74  			"direction":   "asc",
    75  			"page":        "2",
    76  		})
    77  		fmt.Fprint(w, `[{"id":1}]`)
    78  	})
    79  
    80  	opt := &RepositoryListOptions{
    81  		Visibility:  "public",
    82  		Affiliation: "owner,collaborator",
    83  		Sort:        "created",
    84  		Direction:   "asc",
    85  		ListOptions: ListOptions{Page: 2},
    86  	}
    87  	repos, _, err := client.Repositories.List(context.Background(), "u", opt)
    88  	if err != nil {
    89  		t.Errorf("Repositories.List returned error: %v", err)
    90  	}
    91  
    92  	want := []*Repository{{ID: Int64(1)}}
    93  	if !reflect.DeepEqual(repos, want) {
    94  		t.Errorf("Repositories.List returned %+v, want %+v", repos, want)
    95  	}
    96  }
    97  
    98  func TestRepositoriesService_List_specifiedUser_type(t *testing.T) {
    99  	client, mux, _, teardown := setup()
   100  	defer teardown()
   101  
   102  	wantAcceptHeaders := []string{mediaTypeTopicsPreview}
   103  	mux.HandleFunc("/users/u/repos", func(w http.ResponseWriter, r *http.Request) {
   104  		testMethod(t, r, "GET")
   105  		testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", "))
   106  		testFormValues(t, r, values{
   107  			"type": "owner",
   108  		})
   109  		fmt.Fprint(w, `[{"id":1}]`)
   110  	})
   111  
   112  	opt := &RepositoryListOptions{
   113  		Type: "owner",
   114  	}
   115  	repos, _, err := client.Repositories.List(context.Background(), "u", opt)
   116  	if err != nil {
   117  		t.Errorf("Repositories.List returned error: %v", err)
   118  	}
   119  
   120  	want := []*Repository{{ID: Int64(1)}}
   121  	if !reflect.DeepEqual(repos, want) {
   122  		t.Errorf("Repositories.List returned %+v, want %+v", repos, want)
   123  	}
   124  }
   125  
   126  func TestRepositoriesService_List_invalidUser(t *testing.T) {
   127  	client, _, _, teardown := setup()
   128  	defer teardown()
   129  
   130  	_, _, err := client.Repositories.List(context.Background(), "%", nil)
   131  	testURLParseError(t, err)
   132  }
   133  
   134  func TestRepositoriesService_ListByOrg(t *testing.T) {
   135  	client, mux, _, teardown := setup()
   136  	defer teardown()
   137  
   138  	wantAcceptHeaders := []string{mediaTypeTopicsPreview}
   139  	mux.HandleFunc("/orgs/o/repos", func(w http.ResponseWriter, r *http.Request) {
   140  		testMethod(t, r, "GET")
   141  		testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", "))
   142  		testFormValues(t, r, values{
   143  			"type": "forks",
   144  			"page": "2",
   145  		})
   146  		fmt.Fprint(w, `[{"id":1}]`)
   147  	})
   148  
   149  	ctx := context.Background()
   150  	opt := &RepositoryListByOrgOptions{
   151  		Type:        "forks",
   152  		ListOptions: ListOptions{Page: 2},
   153  	}
   154  	got, _, err := client.Repositories.ListByOrg(ctx, "o", opt)
   155  	if err != nil {
   156  		t.Errorf("Repositories.ListByOrg returned error: %v", err)
   157  	}
   158  
   159  	want := []*Repository{{ID: Int64(1)}}
   160  	if !reflect.DeepEqual(got, want) {
   161  		t.Errorf("Repositories.ListByOrg returned %+v, want %+v", got, want)
   162  	}
   163  
   164  	// Test addOptions failure
   165  	_, _, err = client.Repositories.ListByOrg(ctx, "\n", opt)
   166  	if err == nil {
   167  		t.Error("bad options ListByOrg err = nil, want error")
   168  	}
   169  
   170  	// Test s.client.Do failure
   171  	client.BaseURL.Path = "/api-v3/"
   172  	client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute)
   173  	got, resp, err := client.Repositories.ListByOrg(ctx, "o", opt)
   174  	if got != nil {
   175  		t.Errorf("rate.Reset.Time > now ListByOrg = %#v, want nil", got)
   176  	}
   177  	if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want {
   178  		t.Errorf("rate.Reset.Time > now ListByOrg resp = %#v, want StatusCode=%v", resp.Response, want)
   179  	}
   180  	if err == nil {
   181  		t.Error("rate.Reset.Time > now ListByOrg err = nil, want error")
   182  	}
   183  }
   184  
   185  func TestRepositoriesService_ListByOrg_invalidOrg(t *testing.T) {
   186  	client, _, _, teardown := setup()
   187  	defer teardown()
   188  
   189  	_, _, err := client.Repositories.ListByOrg(context.Background(), "%", nil)
   190  	testURLParseError(t, err)
   191  }
   192  
   193  func TestRepositoriesService_ListAll(t *testing.T) {
   194  	client, mux, _, teardown := setup()
   195  	defer teardown()
   196  
   197  	mux.HandleFunc("/repositories", func(w http.ResponseWriter, r *http.Request) {
   198  		testMethod(t, r, "GET")
   199  		testFormValues(t, r, values{
   200  			"since": "1",
   201  		})
   202  		fmt.Fprint(w, `[{"id":1}]`)
   203  	})
   204  
   205  	ctx := context.Background()
   206  	opt := &RepositoryListAllOptions{1}
   207  	got, _, err := client.Repositories.ListAll(ctx, opt)
   208  	if err != nil {
   209  		t.Errorf("Repositories.ListAll returned error: %v", err)
   210  	}
   211  
   212  	want := []*Repository{{ID: Int64(1)}}
   213  	if !reflect.DeepEqual(got, want) {
   214  		t.Errorf("Repositories.ListAll returned %+v, want %+v", got, want)
   215  	}
   216  
   217  	// Test s.client.NewRequest failure
   218  	client.BaseURL.Path = ""
   219  	got, resp, err := client.Repositories.ListAll(ctx, &RepositoryListAllOptions{1})
   220  	if got != nil {
   221  		t.Errorf("client.BaseURL.Path='' ListAll = %#v, want nil", got)
   222  	}
   223  	if resp != nil {
   224  		t.Errorf("client.BaseURL.Path='' ListAll resp = %#v, want nil", resp)
   225  	}
   226  	if err == nil {
   227  		t.Error("client.BaseURL.Path='' ListAll err = nil, want error")
   228  	}
   229  
   230  	// Test s.client.Do failure
   231  	client.BaseURL.Path = "/api-v3/"
   232  	client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute)
   233  	got, resp, err = client.Repositories.ListAll(ctx, &RepositoryListAllOptions{1})
   234  	if got != nil {
   235  		t.Errorf("rate.Reset.Time > now ListAll = %#v, want nil", got)
   236  	}
   237  	if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want {
   238  		t.Errorf("rate.Reset.Time > now ListAll resp = %#v, want StatusCode=%v", resp.Response, want)
   239  	}
   240  	if err == nil {
   241  		t.Error("rate.Reset.Time > now ListAll err = nil, want error")
   242  	}
   243  }
   244  
   245  func TestRepositoriesService_Create_user(t *testing.T) {
   246  	client, mux, _, teardown := setup()
   247  	defer teardown()
   248  
   249  	input := &Repository{
   250  		Name:     String("n"),
   251  		Archived: Bool(true), // not passed along.
   252  	}
   253  
   254  	wantAcceptHeaders := []string{mediaTypeRepositoryTemplatePreview, mediaTypeRepositoryVisibilityPreview}
   255  	mux.HandleFunc("/user/repos", func(w http.ResponseWriter, r *http.Request) {
   256  		v := new(createRepoRequest)
   257  		json.NewDecoder(r.Body).Decode(v)
   258  
   259  		testMethod(t, r, "POST")
   260  		testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", "))
   261  		want := &createRepoRequest{Name: String("n")}
   262  		if !reflect.DeepEqual(v, want) {
   263  			t.Errorf("Request body = %+v, want %+v", v, want)
   264  		}
   265  
   266  		fmt.Fprint(w, `{"id":1}`)
   267  	})
   268  
   269  	ctx := context.Background()
   270  	got, _, err := client.Repositories.Create(ctx, "", input)
   271  	if err != nil {
   272  		t.Errorf("Repositories.Create returned error: %v", err)
   273  	}
   274  
   275  	want := &Repository{ID: Int64(1)}
   276  	if !reflect.DeepEqual(got, want) {
   277  		t.Errorf("Repositories.Create returned %+v, want %+v", got, want)
   278  	}
   279  
   280  	// Test s.client.NewRequest failure
   281  	client.BaseURL.Path = ""
   282  	got, resp, err := client.Repositories.Create(ctx, "", input)
   283  	if got != nil {
   284  		t.Errorf("client.BaseURL.Path='' Create = %#v, want nil", got)
   285  	}
   286  	if resp != nil {
   287  		t.Errorf("client.BaseURL.Path='' Create resp = %#v, want nil", resp)
   288  	}
   289  	if err == nil {
   290  		t.Error("client.BaseURL.Path='' Create err = nil, want error")
   291  	}
   292  
   293  	// Test s.client.Do failure
   294  	client.BaseURL.Path = "/api-v3/"
   295  	client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute)
   296  	got, resp, err = client.Repositories.Create(ctx, "", input)
   297  	if got != nil {
   298  		t.Errorf("rate.Reset.Time > now Create = %#v, want nil", got)
   299  	}
   300  	if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want {
   301  		t.Errorf("rate.Reset.Time > now Create resp = %#v, want StatusCode=%v", resp.Response, want)
   302  	}
   303  	if err == nil {
   304  		t.Error("rate.Reset.Time > now Create err = nil, want error")
   305  	}
   306  }
   307  
   308  func TestRepositoriesService_Create_org(t *testing.T) {
   309  	client, mux, _, teardown := setup()
   310  	defer teardown()
   311  
   312  	input := &Repository{
   313  		Name:     String("n"),
   314  		Archived: Bool(true), // not passed along.
   315  	}
   316  
   317  	wantAcceptHeaders := []string{mediaTypeRepositoryTemplatePreview, mediaTypeRepositoryVisibilityPreview}
   318  	mux.HandleFunc("/orgs/o/repos", func(w http.ResponseWriter, r *http.Request) {
   319  		v := new(createRepoRequest)
   320  		json.NewDecoder(r.Body).Decode(v)
   321  
   322  		testMethod(t, r, "POST")
   323  		testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", "))
   324  		want := &createRepoRequest{Name: String("n")}
   325  		if !reflect.DeepEqual(v, want) {
   326  			t.Errorf("Request body = %+v, want %+v", v, want)
   327  		}
   328  
   329  		fmt.Fprint(w, `{"id":1}`)
   330  	})
   331  
   332  	repo, _, err := client.Repositories.Create(context.Background(), "o", input)
   333  	if err != nil {
   334  		t.Errorf("Repositories.Create returned error: %v", err)
   335  	}
   336  
   337  	want := &Repository{ID: Int64(1)}
   338  	if !reflect.DeepEqual(repo, want) {
   339  		t.Errorf("Repositories.Create returned %+v, want %+v", repo, want)
   340  	}
   341  }
   342  
   343  func TestRepositoriesService_CreateFromTemplate(t *testing.T) {
   344  	client, mux, _, teardown := setup()
   345  	defer teardown()
   346  
   347  	templateRepoReq := &TemplateRepoRequest{
   348  		Name: String("n"),
   349  	}
   350  
   351  	mux.HandleFunc("/repos/to/tr/generate", func(w http.ResponseWriter, r *http.Request) {
   352  		v := new(TemplateRepoRequest)
   353  		json.NewDecoder(r.Body).Decode(v)
   354  
   355  		testMethod(t, r, "POST")
   356  		testHeader(t, r, "Accept", mediaTypeRepositoryTemplatePreview)
   357  		want := &TemplateRepoRequest{Name: String("n")}
   358  		if !reflect.DeepEqual(v, want) {
   359  			t.Errorf("Request body = %+v, want %+v", v, want)
   360  		}
   361  
   362  		fmt.Fprint(w, `{"id":1,"name":"n"}`)
   363  	})
   364  
   365  	ctx := context.Background()
   366  	got, _, err := client.Repositories.CreateFromTemplate(ctx, "to", "tr", templateRepoReq)
   367  	if err != nil {
   368  		t.Errorf("Repositories.CreateFromTemplate returned error: %v", err)
   369  	}
   370  
   371  	want := &Repository{ID: Int64(1), Name: String("n")}
   372  	if !reflect.DeepEqual(got, want) {
   373  		t.Errorf("Repositories.CreateFromTemplate returned %+v, want %+v", got, want)
   374  	}
   375  
   376  	// Test s.client.NewRequest failure
   377  	client.BaseURL.Path = ""
   378  	got, resp, err := client.Repositories.CreateFromTemplate(ctx, "to", "tr", templateRepoReq)
   379  	if got != nil {
   380  		t.Errorf("client.BaseURL.Path='' CreateFromTemplate = %#v, want nil", got)
   381  	}
   382  	if resp != nil {
   383  		t.Errorf("client.BaseURL.Path='' CreateFromTemplate resp = %#v, want nil", resp)
   384  	}
   385  	if err == nil {
   386  		t.Error("client.BaseURL.Path='' CreateFromTemplate err = nil, want error")
   387  	}
   388  
   389  	// Test s.client.Do failure
   390  	client.BaseURL.Path = "/api-v3/"
   391  	client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute)
   392  	got, resp, err = client.Repositories.CreateFromTemplate(ctx, "to", "tr", templateRepoReq)
   393  	if got != nil {
   394  		t.Errorf("rate.Reset.Time > now CreateFromTemplate = %#v, want nil", got)
   395  	}
   396  	if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want {
   397  		t.Errorf("rate.Reset.Time > now CreateFromTemplate resp = %#v, want StatusCode=%v", resp.Response, want)
   398  	}
   399  	if err == nil {
   400  		t.Error("rate.Reset.Time > now CreateFromTemplate err = nil, want error")
   401  	}
   402  }
   403  
   404  func TestRepositoriesService_Get(t *testing.T) {
   405  	client, mux, _, teardown := setup()
   406  	defer teardown()
   407  
   408  	wantAcceptHeaders := []string{mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview, mediaTypeRepositoryTemplatePreview, mediaTypeRepositoryVisibilityPreview}
   409  	mux.HandleFunc("/repos/o/r", func(w http.ResponseWriter, r *http.Request) {
   410  		testMethod(t, r, "GET")
   411  		testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", "))
   412  		fmt.Fprint(w, `{"id":1,"name":"n","description":"d","owner":{"login":"l"},"license":{"key":"mit"}}`)
   413  	})
   414  
   415  	ctx := context.Background()
   416  	got, _, err := client.Repositories.Get(ctx, "o", "r")
   417  	if err != nil {
   418  		t.Errorf("Repositories.Get returned error: %v", err)
   419  	}
   420  
   421  	want := &Repository{ID: Int64(1), Name: String("n"), Description: String("d"), Owner: &User{Login: String("l")}, License: &License{Key: String("mit")}}
   422  	if !reflect.DeepEqual(got, want) {
   423  		t.Errorf("Repositories.Get returned %+v, want %+v", got, want)
   424  	}
   425  
   426  	// Test s.client.Do failure
   427  	client.BaseURL.Path = "/api-v3/"
   428  	client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute)
   429  	got, resp, err := client.Repositories.Get(ctx, "o", "r")
   430  	if got != nil {
   431  		t.Errorf("rate.Reset.Time > now Get = %#v, want nil", got)
   432  	}
   433  	if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want {
   434  		t.Errorf("rate.Reset.Time > now Get resp = %#v, want StatusCode=%v", resp.Response, want)
   435  	}
   436  	if err == nil {
   437  		t.Error("rate.Reset.Time > now Get err = nil, want error")
   438  	}
   439  }
   440  
   441  func TestRepositoriesService_GetCodeOfConduct(t *testing.T) {
   442  	client, mux, _, teardown := setup()
   443  	defer teardown()
   444  
   445  	mux.HandleFunc("/repos/o/r/community/code_of_conduct", func(w http.ResponseWriter, r *http.Request) {
   446  		testMethod(t, r, "GET")
   447  		testHeader(t, r, "Accept", mediaTypeCodesOfConductPreview)
   448  		fmt.Fprint(w, `{
   449  						"key": "key",
   450  						"name": "name",
   451  						"url": "url",
   452  						"body": "body"}`,
   453  		)
   454  	})
   455  
   456  	ctx := context.Background()
   457  	got, _, err := client.Repositories.GetCodeOfConduct(ctx, "o", "r")
   458  	if err != nil {
   459  		t.Errorf("Repositories.GetCodeOfConduct returned error: %v", err)
   460  	}
   461  
   462  	want := &CodeOfConduct{
   463  		Key:  String("key"),
   464  		Name: String("name"),
   465  		URL:  String("url"),
   466  		Body: String("body"),
   467  	}
   468  
   469  	if !reflect.DeepEqual(got, want) {
   470  		t.Errorf("Repositories.GetCodeOfConduct returned %+v, want %+v", got, want)
   471  	}
   472  
   473  	// Test s.client.NewRequest failure
   474  	client.BaseURL.Path = ""
   475  	got, resp, err := client.Repositories.GetCodeOfConduct(ctx, "o", "r")
   476  	if got != nil {
   477  		t.Errorf("client.BaseURL.Path='' GetCodeOfConduct = %#v, want nil", got)
   478  	}
   479  	if resp != nil {
   480  		t.Errorf("client.BaseURL.Path='' GetCodeOfConduct resp = %#v, want nil", resp)
   481  	}
   482  	if err == nil {
   483  		t.Error("client.BaseURL.Path='' GetCodeOfConduct err = nil, want error")
   484  	}
   485  
   486  	// Test s.client.Do failure
   487  	client.BaseURL.Path = "/api-v3/"
   488  	client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute)
   489  	got, resp, err = client.Repositories.GetCodeOfConduct(ctx, "o", "r")
   490  	if got != nil {
   491  		t.Errorf("rate.Reset.Time > now GetCodeOfConduct = %#v, want nil", got)
   492  	}
   493  	if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want {
   494  		t.Errorf("rate.Reset.Time > now GetCodeOfConduct resp = %#v, want StatusCode=%v", resp.Response, want)
   495  	}
   496  	if err == nil {
   497  		t.Error("rate.Reset.Time > now GetCodeOfConduct err = nil, want error")
   498  	}
   499  }
   500  
   501  func TestRepositoriesService_GetByID(t *testing.T) {
   502  	client, mux, _, teardown := setup()
   503  	defer teardown()
   504  
   505  	mux.HandleFunc("/repositories/1", func(w http.ResponseWriter, r *http.Request) {
   506  		testMethod(t, r, "GET")
   507  		fmt.Fprint(w, `{"id":1,"name":"n","description":"d","owner":{"login":"l"},"license":{"key":"mit"}}`)
   508  	})
   509  
   510  	ctx := context.Background()
   511  	got, _, err := client.Repositories.GetByID(ctx, 1)
   512  	if err != nil {
   513  		t.Fatalf("Repositories.GetByID returned error: %v", err)
   514  	}
   515  
   516  	want := &Repository{ID: Int64(1), Name: String("n"), Description: String("d"), Owner: &User{Login: String("l")}, License: &License{Key: String("mit")}}
   517  	if !reflect.DeepEqual(got, want) {
   518  		t.Errorf("Repositories.GetByID returned %+v, want %+v", got, want)
   519  	}
   520  
   521  	// Test s.client.NewRequest failure
   522  	client.BaseURL.Path = ""
   523  	got, resp, err := client.Repositories.GetByID(ctx, 1)
   524  	if got != nil {
   525  		t.Errorf("client.BaseURL.Path='' GetByID = %#v, want nil", got)
   526  	}
   527  	if resp != nil {
   528  		t.Errorf("client.BaseURL.Path='' GetByID resp = %#v, want nil", resp)
   529  	}
   530  	if err == nil {
   531  		t.Error("client.BaseURL.Path='' GetByID err = nil, want error")
   532  	}
   533  
   534  	// Test s.client.Do failure
   535  	client.BaseURL.Path = "/api-v3/"
   536  	client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute)
   537  	got, resp, err = client.Repositories.GetByID(ctx, 1)
   538  	if got != nil {
   539  		t.Errorf("rate.Reset.Time > now GetByID = %#v, want nil", got)
   540  	}
   541  	if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want {
   542  		t.Errorf("rate.Reset.Time > now GetByID resp = %#v, want StatusCode=%v", resp.Response, want)
   543  	}
   544  	if err == nil {
   545  		t.Error("rate.Reset.Time > now GetByID err = nil, want error")
   546  	}
   547  }
   548  
   549  func TestRepositoriesService_Edit(t *testing.T) {
   550  	client, mux, _, teardown := setup()
   551  	defer teardown()
   552  
   553  	i := true
   554  	input := &Repository{HasIssues: &i}
   555  
   556  	wantAcceptHeaders := []string{mediaTypeRepositoryTemplatePreview, mediaTypeRepositoryVisibilityPreview}
   557  	mux.HandleFunc("/repos/o/r", func(w http.ResponseWriter, r *http.Request) {
   558  		v := new(Repository)
   559  		json.NewDecoder(r.Body).Decode(v)
   560  
   561  		testMethod(t, r, "PATCH")
   562  		testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", "))
   563  		if !reflect.DeepEqual(v, input) {
   564  			t.Errorf("Request body = %+v, want %+v", v, input)
   565  		}
   566  		fmt.Fprint(w, `{"id":1}`)
   567  	})
   568  
   569  	ctx := context.Background()
   570  	got, _, err := client.Repositories.Edit(ctx, "o", "r", input)
   571  	if err != nil {
   572  		t.Errorf("Repositories.Edit returned error: %v", err)
   573  	}
   574  
   575  	want := &Repository{ID: Int64(1)}
   576  	if !reflect.DeepEqual(got, want) {
   577  		t.Errorf("Repositories.Edit returned %+v, want %+v", got, want)
   578  	}
   579  
   580  	// Test s.client.Do failure
   581  	client.BaseURL.Path = "/api-v3/"
   582  	client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute)
   583  	got, resp, err := client.Repositories.Edit(ctx, "o", "r", input)
   584  	if got != nil {
   585  		t.Errorf("rate.Reset.Time > now Edit = %#v, want nil", got)
   586  	}
   587  	if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want {
   588  		t.Errorf("rate.Reset.Time > now Edit resp = %#v, want StatusCode=%v", resp.Response, want)
   589  	}
   590  	if err == nil {
   591  		t.Error("rate.Reset.Time > now Edit err = nil, want error")
   592  	}
   593  }
   594  
   595  func TestRepositoriesService_Delete(t *testing.T) {
   596  	client, mux, _, teardown := setup()
   597  	defer teardown()
   598  
   599  	mux.HandleFunc("/repos/o/r", func(w http.ResponseWriter, r *http.Request) {
   600  		testMethod(t, r, "DELETE")
   601  	})
   602  
   603  	ctx := context.Background()
   604  	_, err := client.Repositories.Delete(ctx, "o", "r")
   605  	if err != nil {
   606  		t.Errorf("Repositories.Delete returned error: %v", err)
   607  	}
   608  
   609  	// Test s.client.NewRequest failure
   610  	client.BaseURL.Path = ""
   611  	resp, err := client.Repositories.Delete(ctx, "o", "r")
   612  	if resp != nil {
   613  		t.Errorf("client.BaseURL.Path='' Delete resp = %#v, want nil", resp)
   614  	}
   615  	if err == nil {
   616  		t.Error("client.BaseURL.Path='' Delete err = nil, want error")
   617  	}
   618  }
   619  
   620  func TestRepositoriesService_Get_invalidOwner(t *testing.T) {
   621  	client, _, _, teardown := setup()
   622  	defer teardown()
   623  
   624  	_, _, err := client.Repositories.Get(context.Background(), "%", "r")
   625  	testURLParseError(t, err)
   626  }
   627  
   628  func TestRepositoriesService_Edit_invalidOwner(t *testing.T) {
   629  	client, _, _, teardown := setup()
   630  	defer teardown()
   631  
   632  	_, _, err := client.Repositories.Edit(context.Background(), "%", "r", nil)
   633  	testURLParseError(t, err)
   634  }
   635  
   636  func TestRepositoriesService_GetVulnerabilityAlerts(t *testing.T) {
   637  	client, mux, _, teardown := setup()
   638  	defer teardown()
   639  
   640  	mux.HandleFunc("/repos/o/r/vulnerability-alerts", func(w http.ResponseWriter, r *http.Request) {
   641  		testMethod(t, r, "GET")
   642  		testHeader(t, r, "Accept", mediaTypeRequiredVulnerabilityAlertsPreview)
   643  
   644  		w.WriteHeader(http.StatusNoContent)
   645  	})
   646  
   647  	vulnerabilityAlertsEnabled, _, err := client.Repositories.GetVulnerabilityAlerts(context.Background(), "o", "r")
   648  	if err != nil {
   649  		t.Errorf("Repositories.GetVulnerabilityAlerts returned error: %v", err)
   650  	}
   651  
   652  	if want := true; vulnerabilityAlertsEnabled != want {
   653  		t.Errorf("Repositories.GetVulnerabilityAlerts returned %+v, want %+v", vulnerabilityAlertsEnabled, want)
   654  	}
   655  }
   656  
   657  func TestRepositoriesService_EnableVulnerabilityAlerts(t *testing.T) {
   658  	client, mux, _, teardown := setup()
   659  	defer teardown()
   660  
   661  	mux.HandleFunc("/repos/o/r/vulnerability-alerts", func(w http.ResponseWriter, r *http.Request) {
   662  		testMethod(t, r, "PUT")
   663  		testHeader(t, r, "Accept", mediaTypeRequiredVulnerabilityAlertsPreview)
   664  
   665  		w.WriteHeader(http.StatusNoContent)
   666  	})
   667  
   668  	if _, err := client.Repositories.EnableVulnerabilityAlerts(context.Background(), "o", "r"); err != nil {
   669  		t.Errorf("Repositories.EnableVulnerabilityAlerts returned error: %v", err)
   670  	}
   671  }
   672  
   673  func TestRepositoriesService_DisableVulnerabilityAlerts(t *testing.T) {
   674  	client, mux, _, teardown := setup()
   675  	defer teardown()
   676  
   677  	mux.HandleFunc("/repos/o/r/vulnerability-alerts", func(w http.ResponseWriter, r *http.Request) {
   678  		testMethod(t, r, "DELETE")
   679  		testHeader(t, r, "Accept", mediaTypeRequiredVulnerabilityAlertsPreview)
   680  
   681  		w.WriteHeader(http.StatusNoContent)
   682  	})
   683  
   684  	if _, err := client.Repositories.DisableVulnerabilityAlerts(context.Background(), "o", "r"); err != nil {
   685  		t.Errorf("Repositories.DisableVulnerabilityAlerts returned error: %v", err)
   686  	}
   687  }
   688  
   689  func TestRepositoriesService_EnableAutomatedSecurityFixes(t *testing.T) {
   690  	client, mux, _, teardown := setup()
   691  	defer teardown()
   692  
   693  	mux.HandleFunc("/repos/o/r/automated-security-fixes", func(w http.ResponseWriter, r *http.Request) {
   694  		testMethod(t, r, "PUT")
   695  		testHeader(t, r, "Accept", mediaTypeRequiredAutomatedSecurityFixesPreview)
   696  
   697  		w.WriteHeader(http.StatusNoContent)
   698  	})
   699  
   700  	if _, err := client.Repositories.EnableAutomatedSecurityFixes(context.Background(), "o", "r"); err != nil {
   701  		t.Errorf("Repositories.EnableAutomatedSecurityFixes returned error: %v", err)
   702  	}
   703  }
   704  
   705  func TestRepositoriesService_DisableAutomatedSecurityFixes(t *testing.T) {
   706  	client, mux, _, teardown := setup()
   707  	defer teardown()
   708  
   709  	mux.HandleFunc("/repos/o/r/automated-security-fixes", func(w http.ResponseWriter, r *http.Request) {
   710  		testMethod(t, r, "DELETE")
   711  		testHeader(t, r, "Accept", mediaTypeRequiredAutomatedSecurityFixesPreview)
   712  
   713  		w.WriteHeader(http.StatusNoContent)
   714  	})
   715  
   716  	if _, err := client.Repositories.DisableAutomatedSecurityFixes(context.Background(), "o", "r"); err != nil {
   717  		t.Errorf("Repositories.DisableAutomatedSecurityFixes returned error: %v", err)
   718  	}
   719  }
   720  
   721  func TestRepositoriesService_ListContributors(t *testing.T) {
   722  	client, mux, _, teardown := setup()
   723  	defer teardown()
   724  
   725  	mux.HandleFunc("/repos/o/r/contributors", func(w http.ResponseWriter, r *http.Request) {
   726  		testMethod(t, r, "GET")
   727  		testFormValues(t, r, values{
   728  			"anon": "true",
   729  			"page": "2",
   730  		})
   731  		fmt.Fprint(w, `[{"contributions":42}]`)
   732  	})
   733  
   734  	opts := &ListContributorsOptions{Anon: "true", ListOptions: ListOptions{Page: 2}}
   735  	contributors, _, err := client.Repositories.ListContributors(context.Background(), "o", "r", opts)
   736  	if err != nil {
   737  		t.Errorf("Repositories.ListContributors returned error: %v", err)
   738  	}
   739  
   740  	want := []*Contributor{{Contributions: Int(42)}}
   741  	if !reflect.DeepEqual(contributors, want) {
   742  		t.Errorf("Repositories.ListContributors returned %+v, want %+v", contributors, want)
   743  	}
   744  }
   745  
   746  func TestRepositoriesService_ListLanguages(t *testing.T) {
   747  	client, mux, _, teardown := setup()
   748  	defer teardown()
   749  
   750  	mux.HandleFunc("/repos/o/r/languages", func(w http.ResponseWriter, r *http.Request) {
   751  		testMethod(t, r, "GET")
   752  		fmt.Fprint(w, `{"go":1}`)
   753  	})
   754  
   755  	languages, _, err := client.Repositories.ListLanguages(context.Background(), "o", "r")
   756  	if err != nil {
   757  		t.Errorf("Repositories.ListLanguages returned error: %v", err)
   758  	}
   759  
   760  	want := map[string]int{"go": 1}
   761  	if !reflect.DeepEqual(languages, want) {
   762  		t.Errorf("Repositories.ListLanguages returned %+v, want %+v", languages, want)
   763  	}
   764  }
   765  
   766  func TestRepositoriesService_ListTeams(t *testing.T) {
   767  	client, mux, _, teardown := setup()
   768  	defer teardown()
   769  
   770  	mux.HandleFunc("/repos/o/r/teams", func(w http.ResponseWriter, r *http.Request) {
   771  		testMethod(t, r, "GET")
   772  		testFormValues(t, r, values{"page": "2"})
   773  		fmt.Fprint(w, `[{"id":1}]`)
   774  	})
   775  
   776  	opt := &ListOptions{Page: 2}
   777  	teams, _, err := client.Repositories.ListTeams(context.Background(), "o", "r", opt)
   778  	if err != nil {
   779  		t.Errorf("Repositories.ListTeams returned error: %v", err)
   780  	}
   781  
   782  	want := []*Team{{ID: Int64(1)}}
   783  	if !reflect.DeepEqual(teams, want) {
   784  		t.Errorf("Repositories.ListTeams returned %+v, want %+v", teams, want)
   785  	}
   786  }
   787  
   788  func TestRepositoriesService_ListTags(t *testing.T) {
   789  	client, mux, _, teardown := setup()
   790  	defer teardown()
   791  
   792  	mux.HandleFunc("/repos/o/r/tags", func(w http.ResponseWriter, r *http.Request) {
   793  		testMethod(t, r, "GET")
   794  		testFormValues(t, r, values{"page": "2"})
   795  		fmt.Fprint(w, `[{"name":"n", "commit" : {"sha" : "s", "url" : "u"}, "zipball_url": "z", "tarball_url": "t"}]`)
   796  	})
   797  
   798  	opt := &ListOptions{Page: 2}
   799  	tags, _, err := client.Repositories.ListTags(context.Background(), "o", "r", opt)
   800  	if err != nil {
   801  		t.Errorf("Repositories.ListTags returned error: %v", err)
   802  	}
   803  
   804  	want := []*RepositoryTag{
   805  		{
   806  			Name: String("n"),
   807  			Commit: &Commit{
   808  				SHA: String("s"),
   809  				URL: String("u"),
   810  			},
   811  			ZipballURL: String("z"),
   812  			TarballURL: String("t"),
   813  		},
   814  	}
   815  	if !reflect.DeepEqual(tags, want) {
   816  		t.Errorf("Repositories.ListTags returned %+v, want %+v", tags, want)
   817  	}
   818  }
   819  
   820  func TestRepositoriesService_ListBranches(t *testing.T) {
   821  	client, mux, _, teardown := setup()
   822  	defer teardown()
   823  
   824  	mux.HandleFunc("/repos/o/r/branches", func(w http.ResponseWriter, r *http.Request) {
   825  		testMethod(t, r, "GET")
   826  		// TODO: remove custom Accept header when this API fully launches
   827  		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
   828  		testFormValues(t, r, values{"page": "2"})
   829  		fmt.Fprint(w, `[{"name":"master", "commit" : {"sha" : "a57781", "url" : "https://api.github.com/repos/o/r/commits/a57781"}}]`)
   830  	})
   831  
   832  	opt := &BranchListOptions{
   833  		Protected:   nil,
   834  		ListOptions: ListOptions{Page: 2},
   835  	}
   836  	branches, _, err := client.Repositories.ListBranches(context.Background(), "o", "r", opt)
   837  	if err != nil {
   838  		t.Errorf("Repositories.ListBranches returned error: %v", err)
   839  	}
   840  
   841  	want := []*Branch{{Name: String("master"), Commit: &RepositoryCommit{SHA: String("a57781"), URL: String("https://api.github.com/repos/o/r/commits/a57781")}}}
   842  	if !reflect.DeepEqual(branches, want) {
   843  		t.Errorf("Repositories.ListBranches returned %+v, want %+v", branches, want)
   844  	}
   845  }
   846  
   847  func TestRepositoriesService_GetBranch(t *testing.T) {
   848  	client, mux, _, teardown := setup()
   849  	defer teardown()
   850  
   851  	mux.HandleFunc("/repos/o/r/branches/b", func(w http.ResponseWriter, r *http.Request) {
   852  		testMethod(t, r, "GET")
   853  		// TODO: remove custom Accept header when this API fully launches
   854  		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
   855  		fmt.Fprint(w, `{"name":"n", "commit":{"sha":"s","commit":{"message":"m"}}, "protected":true}`)
   856  	})
   857  
   858  	branch, _, err := client.Repositories.GetBranch(context.Background(), "o", "r", "b")
   859  	if err != nil {
   860  		t.Errorf("Repositories.GetBranch returned error: %v", err)
   861  	}
   862  
   863  	want := &Branch{
   864  		Name: String("n"),
   865  		Commit: &RepositoryCommit{
   866  			SHA: String("s"),
   867  			Commit: &Commit{
   868  				Message: String("m"),
   869  			},
   870  		},
   871  		Protected: Bool(true),
   872  	}
   873  
   874  	if !reflect.DeepEqual(branch, want) {
   875  		t.Errorf("Repositories.GetBranch returned %+v, want %+v", branch, want)
   876  	}
   877  }
   878  
   879  func TestRepositoriesService_GetBranchProtection(t *testing.T) {
   880  	client, mux, _, teardown := setup()
   881  	defer teardown()
   882  
   883  	mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) {
   884  		v := new(ProtectionRequest)
   885  		json.NewDecoder(r.Body).Decode(v)
   886  
   887  		testMethod(t, r, "GET")
   888  		// TODO: remove custom Accept header when this API fully launches
   889  		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
   890  		fmt.Fprintf(w, `{
   891  				"required_status_checks":{
   892  					"strict":true,
   893  					"contexts":["continuous-integration"]
   894  				},
   895  				"required_pull_request_reviews":{
   896  					"dismissal_restrictions":{
   897  						"users":[{
   898  							"id":3,
   899  							"login":"u"
   900  						}],
   901  						"teams":[{
   902  							"id":4,
   903  							"slug":"t"
   904  						}]
   905  					},
   906  					"dismiss_stale_reviews":true,
   907  					"require_code_owner_reviews":true,
   908  					"required_approving_review_count":1
   909  					},
   910  					"enforce_admins":{
   911  						"url":"/repos/o/r/branches/b/protection/enforce_admins",
   912  						"enabled":true
   913  					},
   914  					"restrictions":{
   915  						"users":[{"id":1,"login":"u"}],
   916  						"teams":[{"id":2,"slug":"t"}]
   917  					}
   918  				}`)
   919  	})
   920  
   921  	protection, _, err := client.Repositories.GetBranchProtection(context.Background(), "o", "r", "b")
   922  	if err != nil {
   923  		t.Errorf("Repositories.GetBranchProtection returned error: %v", err)
   924  	}
   925  
   926  	want := &Protection{
   927  		RequiredStatusChecks: &RequiredStatusChecks{
   928  			Strict:   true,
   929  			Contexts: []string{"continuous-integration"},
   930  		},
   931  		RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
   932  			DismissStaleReviews: true,
   933  			DismissalRestrictions: &DismissalRestrictions{
   934  				Users: []*User{
   935  					{Login: String("u"), ID: Int64(3)},
   936  				},
   937  				Teams: []*Team{
   938  					{Slug: String("t"), ID: Int64(4)},
   939  				},
   940  			},
   941  			RequireCodeOwnerReviews:      true,
   942  			RequiredApprovingReviewCount: 1,
   943  		},
   944  		EnforceAdmins: &AdminEnforcement{
   945  			URL:     String("/repos/o/r/branches/b/protection/enforce_admins"),
   946  			Enabled: true,
   947  		},
   948  		Restrictions: &BranchRestrictions{
   949  			Users: []*User{
   950  				{Login: String("u"), ID: Int64(1)},
   951  			},
   952  			Teams: []*Team{
   953  				{Slug: String("t"), ID: Int64(2)},
   954  			},
   955  		},
   956  	}
   957  	if !reflect.DeepEqual(protection, want) {
   958  		t.Errorf("Repositories.GetBranchProtection returned %+v, want %+v", protection, want)
   959  	}
   960  }
   961  
   962  func TestRepositoriesService_GetBranchProtection_noDismissalRestrictions(t *testing.T) {
   963  	client, mux, _, teardown := setup()
   964  	defer teardown()
   965  
   966  	mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) {
   967  
   968  		testMethod(t, r, "GET")
   969  		// TODO: remove custom Accept header when this API fully launches
   970  		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
   971  		fmt.Fprintf(w, `{
   972  				"required_status_checks":{
   973  					"strict":true,
   974  					"contexts":["continuous-integration"]
   975  				},
   976  				"required_pull_request_reviews":{
   977  					"dismiss_stale_reviews":true,
   978  					"require_code_owner_reviews":true,
   979  					"required_approving_review_count":1
   980  					},
   981  					"enforce_admins":{
   982  						"url":"/repos/o/r/branches/b/protection/enforce_admins",
   983  						"enabled":true
   984  					},
   985  					"restrictions":{
   986  						"users":[{"id":1,"login":"u"}],
   987  						"teams":[{"id":2,"slug":"t"}]
   988  					}
   989  				}`)
   990  	})
   991  
   992  	protection, _, err := client.Repositories.GetBranchProtection(context.Background(), "o", "r", "b")
   993  	if err != nil {
   994  		t.Errorf("Repositories.GetBranchProtection returned error: %v", err)
   995  	}
   996  
   997  	want := &Protection{
   998  		RequiredStatusChecks: &RequiredStatusChecks{
   999  			Strict:   true,
  1000  			Contexts: []string{"continuous-integration"},
  1001  		},
  1002  		RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
  1003  			DismissStaleReviews:          true,
  1004  			DismissalRestrictions:        nil,
  1005  			RequireCodeOwnerReviews:      true,
  1006  			RequiredApprovingReviewCount: 1,
  1007  		},
  1008  		EnforceAdmins: &AdminEnforcement{
  1009  			URL:     String("/repos/o/r/branches/b/protection/enforce_admins"),
  1010  			Enabled: true,
  1011  		},
  1012  		Restrictions: &BranchRestrictions{
  1013  			Users: []*User{
  1014  				{Login: String("u"), ID: Int64(1)},
  1015  			},
  1016  			Teams: []*Team{
  1017  				{Slug: String("t"), ID: Int64(2)},
  1018  			},
  1019  		},
  1020  	}
  1021  	if !reflect.DeepEqual(protection, want) {
  1022  		t.Errorf("Repositories.GetBranchProtection returned %+v, want %+v", protection, want)
  1023  	}
  1024  }
  1025  
  1026  func TestRepositoriesService_UpdateBranchProtection(t *testing.T) {
  1027  	client, mux, _, teardown := setup()
  1028  	defer teardown()
  1029  
  1030  	input := &ProtectionRequest{
  1031  		RequiredStatusChecks: &RequiredStatusChecks{
  1032  			Strict:   true,
  1033  			Contexts: []string{"continuous-integration"},
  1034  		},
  1035  		RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{
  1036  			DismissStaleReviews: true,
  1037  			DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
  1038  				Users: &[]string{"uu"},
  1039  				Teams: &[]string{"tt"},
  1040  			},
  1041  		},
  1042  		Restrictions: &BranchRestrictionsRequest{
  1043  			Users: []string{"u"},
  1044  			Teams: []string{"t"},
  1045  			Apps:  []string{"a"},
  1046  		},
  1047  	}
  1048  
  1049  	mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) {
  1050  		v := new(ProtectionRequest)
  1051  		json.NewDecoder(r.Body).Decode(v)
  1052  
  1053  		testMethod(t, r, "PUT")
  1054  		if !reflect.DeepEqual(v, input) {
  1055  			t.Errorf("Request body = %+v, want %+v", v, input)
  1056  		}
  1057  
  1058  		// TODO: remove custom Accept header when this API fully launches
  1059  		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  1060  		fmt.Fprintf(w, `{
  1061  			"required_status_checks":{
  1062  				"strict":true,
  1063  				"contexts":["continuous-integration"]
  1064  			},
  1065  			"required_pull_request_reviews":{
  1066  				"dismissal_restrictions":{
  1067  					"users":[{
  1068  						"id":3,
  1069  						"login":"uu"
  1070  					}],
  1071  					"teams":[{
  1072  						"id":4,
  1073  						"slug":"tt"
  1074  					}]
  1075  				},
  1076  				"dismiss_stale_reviews":true,
  1077  				"require_code_owner_reviews":true
  1078  			},
  1079  			"restrictions":{
  1080  				"users":[{"id":1,"login":"u"}],
  1081  				"teams":[{"id":2,"slug":"t"}],
  1082  				"apps":[{"id":3,"slug":"a"}]
  1083  			}
  1084  		}`)
  1085  	})
  1086  
  1087  	protection, _, err := client.Repositories.UpdateBranchProtection(context.Background(), "o", "r", "b", input)
  1088  	if err != nil {
  1089  		t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err)
  1090  	}
  1091  
  1092  	want := &Protection{
  1093  		RequiredStatusChecks: &RequiredStatusChecks{
  1094  			Strict:   true,
  1095  			Contexts: []string{"continuous-integration"},
  1096  		},
  1097  		RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
  1098  			DismissStaleReviews: true,
  1099  			DismissalRestrictions: &DismissalRestrictions{
  1100  				Users: []*User{
  1101  					{Login: String("uu"), ID: Int64(3)},
  1102  				},
  1103  				Teams: []*Team{
  1104  					{Slug: String("tt"), ID: Int64(4)},
  1105  				},
  1106  			},
  1107  			RequireCodeOwnerReviews: true,
  1108  		},
  1109  		Restrictions: &BranchRestrictions{
  1110  			Users: []*User{
  1111  				{Login: String("u"), ID: Int64(1)},
  1112  			},
  1113  			Teams: []*Team{
  1114  				{Slug: String("t"), ID: Int64(2)},
  1115  			},
  1116  			Apps: []*App{
  1117  				{Slug: String("a"), ID: Int64(3)},
  1118  			},
  1119  		},
  1120  	}
  1121  	if !reflect.DeepEqual(protection, want) {
  1122  		t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want)
  1123  	}
  1124  }
  1125  
  1126  func TestRepositoriesService_RemoveBranchProtection(t *testing.T) {
  1127  	client, mux, _, teardown := setup()
  1128  	defer teardown()
  1129  
  1130  	mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) {
  1131  		testMethod(t, r, "DELETE")
  1132  		// TODO: remove custom Accept header when this API fully launches
  1133  		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  1134  		w.WriteHeader(http.StatusNoContent)
  1135  	})
  1136  
  1137  	_, err := client.Repositories.RemoveBranchProtection(context.Background(), "o", "r", "b")
  1138  	if err != nil {
  1139  		t.Errorf("Repositories.RemoveBranchProtection returned error: %v", err)
  1140  	}
  1141  }
  1142  
  1143  func TestRepositoriesService_ListLanguages_invalidOwner(t *testing.T) {
  1144  	client, _, _, teardown := setup()
  1145  	defer teardown()
  1146  
  1147  	_, _, err := client.Repositories.ListLanguages(context.Background(), "%", "%")
  1148  	testURLParseError(t, err)
  1149  }
  1150  
  1151  func TestRepositoriesService_License(t *testing.T) {
  1152  	client, mux, _, teardown := setup()
  1153  	defer teardown()
  1154  
  1155  	mux.HandleFunc("/repos/o/r/license", func(w http.ResponseWriter, r *http.Request) {
  1156  		testMethod(t, r, "GET")
  1157  		fmt.Fprint(w, `{"name": "LICENSE", "path": "LICENSE", "license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","featured":true}}`)
  1158  	})
  1159  
  1160  	got, _, err := client.Repositories.License(context.Background(), "o", "r")
  1161  	if err != nil {
  1162  		t.Errorf("Repositories.License returned error: %v", err)
  1163  	}
  1164  
  1165  	want := &RepositoryLicense{
  1166  		Name: String("LICENSE"),
  1167  		Path: String("LICENSE"),
  1168  		License: &License{
  1169  			Name:     String("MIT License"),
  1170  			Key:      String("mit"),
  1171  			SPDXID:   String("MIT"),
  1172  			URL:      String("https://api.github.com/licenses/mit"),
  1173  			Featured: Bool(true),
  1174  		},
  1175  	}
  1176  
  1177  	if !reflect.DeepEqual(got, want) {
  1178  		t.Errorf("Repositories.License returned %+v, want %+v", got, want)
  1179  	}
  1180  }
  1181  
  1182  func TestRepositoriesService_GetRequiredStatusChecks(t *testing.T) {
  1183  	client, mux, _, teardown := setup()
  1184  	defer teardown()
  1185  
  1186  	mux.HandleFunc("/repos/o/r/branches/b/protection/required_status_checks", func(w http.ResponseWriter, r *http.Request) {
  1187  		v := new(ProtectionRequest)
  1188  		json.NewDecoder(r.Body).Decode(v)
  1189  
  1190  		testMethod(t, r, "GET")
  1191  		// TODO: remove custom Accept header when this API fully launches
  1192  		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  1193  		fmt.Fprint(w, `{"strict": true,"contexts": ["x","y","z"]}`)
  1194  	})
  1195  
  1196  	checks, _, err := client.Repositories.GetRequiredStatusChecks(context.Background(), "o", "r", "b")
  1197  	if err != nil {
  1198  		t.Errorf("Repositories.GetRequiredStatusChecks returned error: %v", err)
  1199  	}
  1200  
  1201  	want := &RequiredStatusChecks{
  1202  		Strict:   true,
  1203  		Contexts: []string{"x", "y", "z"},
  1204  	}
  1205  	if !reflect.DeepEqual(checks, want) {
  1206  		t.Errorf("Repositories.GetRequiredStatusChecks returned %+v, want %+v", checks, want)
  1207  	}
  1208  }
  1209  
  1210  func TestRepositoriesService_UpdateRequiredStatusChecks(t *testing.T) {
  1211  	client, mux, _, teardown := setup()
  1212  	defer teardown()
  1213  
  1214  	input := &RequiredStatusChecksRequest{
  1215  		Strict:   Bool(true),
  1216  		Contexts: []string{"continuous-integration"},
  1217  	}
  1218  
  1219  	mux.HandleFunc("/repos/o/r/branches/b/protection/required_status_checks", func(w http.ResponseWriter, r *http.Request) {
  1220  		v := new(RequiredStatusChecksRequest)
  1221  		json.NewDecoder(r.Body).Decode(v)
  1222  
  1223  		testMethod(t, r, "PATCH")
  1224  		if !reflect.DeepEqual(v, input) {
  1225  			t.Errorf("Request body = %+v, want %+v", v, input)
  1226  		}
  1227  		testHeader(t, r, "Accept", mediaTypeV3)
  1228  		fmt.Fprintf(w, `{"strict":true,"contexts":["continuous-integration"]}`)
  1229  	})
  1230  
  1231  	statusChecks, _, err := client.Repositories.UpdateRequiredStatusChecks(context.Background(), "o", "r", "b", input)
  1232  	if err != nil {
  1233  		t.Errorf("Repositories.UpdateRequiredStatusChecks returned error: %v", err)
  1234  	}
  1235  
  1236  	want := &RequiredStatusChecks{
  1237  		Strict:   true,
  1238  		Contexts: []string{"continuous-integration"},
  1239  	}
  1240  	if !reflect.DeepEqual(statusChecks, want) {
  1241  		t.Errorf("Repositories.UpdateRequiredStatusChecks returned %+v, want %+v", statusChecks, want)
  1242  	}
  1243  }
  1244  
  1245  func TestRepositoriesService_ListRequiredStatusChecksContexts(t *testing.T) {
  1246  	client, mux, _, teardown := setup()
  1247  	defer teardown()
  1248  
  1249  	mux.HandleFunc("/repos/o/r/branches/b/protection/required_status_checks/contexts", func(w http.ResponseWriter, r *http.Request) {
  1250  		v := new(ProtectionRequest)
  1251  		json.NewDecoder(r.Body).Decode(v)
  1252  
  1253  		testMethod(t, r, "GET")
  1254  		// TODO: remove custom Accept header when this API fully launches
  1255  		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  1256  		fmt.Fprint(w, `["x", "y", "z"]`)
  1257  	})
  1258  
  1259  	contexts, _, err := client.Repositories.ListRequiredStatusChecksContexts(context.Background(), "o", "r", "b")
  1260  	if err != nil {
  1261  		t.Errorf("Repositories.ListRequiredStatusChecksContexts returned error: %v", err)
  1262  	}
  1263  
  1264  	want := []string{"x", "y", "z"}
  1265  	if !reflect.DeepEqual(contexts, want) {
  1266  		t.Errorf("Repositories.ListRequiredStatusChecksContexts returned %+v, want %+v", contexts, want)
  1267  	}
  1268  }
  1269  
  1270  func TestRepositoriesService_GetPullRequestReviewEnforcement(t *testing.T) {
  1271  	client, mux, _, teardown := setup()
  1272  	defer teardown()
  1273  
  1274  	mux.HandleFunc("/repos/o/r/branches/b/protection/required_pull_request_reviews", func(w http.ResponseWriter, r *http.Request) {
  1275  		testMethod(t, r, "GET")
  1276  		// TODO: remove custom Accept header when this API fully launches
  1277  		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  1278  		fmt.Fprintf(w, `{
  1279  			"dismissal_restrictions":{
  1280  				"users":[{"id":1,"login":"u"}],
  1281  				"teams":[{"id":2,"slug":"t"}]
  1282  			},
  1283  			"dismiss_stale_reviews":true,
  1284  			"require_code_owner_reviews":true,
  1285  			"required_approving_review_count":1
  1286  		}`)
  1287  	})
  1288  
  1289  	enforcement, _, err := client.Repositories.GetPullRequestReviewEnforcement(context.Background(), "o", "r", "b")
  1290  	if err != nil {
  1291  		t.Errorf("Repositories.GetPullRequestReviewEnforcement returned error: %v", err)
  1292  	}
  1293  
  1294  	want := &PullRequestReviewsEnforcement{
  1295  		DismissStaleReviews: true,
  1296  		DismissalRestrictions: &DismissalRestrictions{
  1297  			Users: []*User{
  1298  				{Login: String("u"), ID: Int64(1)},
  1299  			},
  1300  			Teams: []*Team{
  1301  				{Slug: String("t"), ID: Int64(2)},
  1302  			},
  1303  		},
  1304  		RequireCodeOwnerReviews:      true,
  1305  		RequiredApprovingReviewCount: 1,
  1306  	}
  1307  
  1308  	if !reflect.DeepEqual(enforcement, want) {
  1309  		t.Errorf("Repositories.GetPullRequestReviewEnforcement returned %+v, want %+v", enforcement, want)
  1310  	}
  1311  }
  1312  
  1313  func TestRepositoriesService_UpdatePullRequestReviewEnforcement(t *testing.T) {
  1314  	client, mux, _, teardown := setup()
  1315  	defer teardown()
  1316  
  1317  	input := &PullRequestReviewsEnforcementUpdate{
  1318  		DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
  1319  			Users: &[]string{"u"},
  1320  			Teams: &[]string{"t"},
  1321  		},
  1322  	}
  1323  
  1324  	mux.HandleFunc("/repos/o/r/branches/b/protection/required_pull_request_reviews", func(w http.ResponseWriter, r *http.Request) {
  1325  		v := new(PullRequestReviewsEnforcementUpdate)
  1326  		json.NewDecoder(r.Body).Decode(v)
  1327  
  1328  		testMethod(t, r, "PATCH")
  1329  		if !reflect.DeepEqual(v, input) {
  1330  			t.Errorf("Request body = %+v, want %+v", v, input)
  1331  		}
  1332  		// TODO: remove custom Accept header when this API fully launches
  1333  		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  1334  		fmt.Fprintf(w, `{
  1335  			"dismissal_restrictions":{
  1336  				"users":[{"id":1,"login":"u"}],
  1337  				"teams":[{"id":2,"slug":"t"}]
  1338  			},
  1339  			"dismiss_stale_reviews":true,
  1340  			"require_code_owner_reviews":true,
  1341  			"required_approving_review_count":3
  1342  		}`)
  1343  	})
  1344  
  1345  	enforcement, _, err := client.Repositories.UpdatePullRequestReviewEnforcement(context.Background(), "o", "r", "b", input)
  1346  	if err != nil {
  1347  		t.Errorf("Repositories.UpdatePullRequestReviewEnforcement returned error: %v", err)
  1348  	}
  1349  
  1350  	want := &PullRequestReviewsEnforcement{
  1351  		DismissStaleReviews: true,
  1352  		DismissalRestrictions: &DismissalRestrictions{
  1353  			Users: []*User{
  1354  				{Login: String("u"), ID: Int64(1)},
  1355  			},
  1356  			Teams: []*Team{
  1357  				{Slug: String("t"), ID: Int64(2)},
  1358  			},
  1359  		},
  1360  		RequireCodeOwnerReviews:      true,
  1361  		RequiredApprovingReviewCount: 3,
  1362  	}
  1363  	if !reflect.DeepEqual(enforcement, want) {
  1364  		t.Errorf("Repositories.UpdatePullRequestReviewEnforcement returned %+v, want %+v", enforcement, want)
  1365  	}
  1366  }
  1367  
  1368  func TestRepositoriesService_DisableDismissalRestrictions(t *testing.T) {
  1369  	client, mux, _, teardown := setup()
  1370  	defer teardown()
  1371  
  1372  	mux.HandleFunc("/repos/o/r/branches/b/protection/required_pull_request_reviews", func(w http.ResponseWriter, r *http.Request) {
  1373  		testMethod(t, r, "PATCH")
  1374  		// TODO: remove custom Accept header when this API fully launches
  1375  		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  1376  		testBody(t, r, `{"dismissal_restrictions":{}}`+"\n")
  1377  		fmt.Fprintf(w, `{"dismiss_stale_reviews":true,"require_code_owner_reviews":true,"required_approving_review_count":1}`)
  1378  	})
  1379  
  1380  	enforcement, _, err := client.Repositories.DisableDismissalRestrictions(context.Background(), "o", "r", "b")
  1381  	if err != nil {
  1382  		t.Errorf("Repositories.DisableDismissalRestrictions returned error: %v", err)
  1383  	}
  1384  
  1385  	want := &PullRequestReviewsEnforcement{
  1386  		DismissStaleReviews:          true,
  1387  		DismissalRestrictions:        nil,
  1388  		RequireCodeOwnerReviews:      true,
  1389  		RequiredApprovingReviewCount: 1,
  1390  	}
  1391  	if !reflect.DeepEqual(enforcement, want) {
  1392  		t.Errorf("Repositories.DisableDismissalRestrictions returned %+v, want %+v", enforcement, want)
  1393  	}
  1394  }
  1395  
  1396  func TestRepositoriesService_RemovePullRequestReviewEnforcement(t *testing.T) {
  1397  	client, mux, _, teardown := setup()
  1398  	defer teardown()
  1399  
  1400  	mux.HandleFunc("/repos/o/r/branches/b/protection/required_pull_request_reviews", func(w http.ResponseWriter, r *http.Request) {
  1401  		testMethod(t, r, "DELETE")
  1402  		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  1403  		w.WriteHeader(http.StatusNoContent)
  1404  	})
  1405  
  1406  	_, err := client.Repositories.RemovePullRequestReviewEnforcement(context.Background(), "o", "r", "b")
  1407  	if err != nil {
  1408  		t.Errorf("Repositories.RemovePullRequestReviewEnforcement returned error: %v", err)
  1409  	}
  1410  }
  1411  
  1412  func TestRepositoriesService_GetAdminEnforcement(t *testing.T) {
  1413  	client, mux, _, teardown := setup()
  1414  	defer teardown()
  1415  
  1416  	mux.HandleFunc("/repos/o/r/branches/b/protection/enforce_admins", func(w http.ResponseWriter, r *http.Request) {
  1417  		testMethod(t, r, "GET")
  1418  		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  1419  		fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/enforce_admins","enabled":true}`)
  1420  	})
  1421  
  1422  	enforcement, _, err := client.Repositories.GetAdminEnforcement(context.Background(), "o", "r", "b")
  1423  	if err != nil {
  1424  		t.Errorf("Repositories.GetAdminEnforcement returned error: %v", err)
  1425  	}
  1426  
  1427  	want := &AdminEnforcement{
  1428  		URL:     String("/repos/o/r/branches/b/protection/enforce_admins"),
  1429  		Enabled: true,
  1430  	}
  1431  
  1432  	if !reflect.DeepEqual(enforcement, want) {
  1433  		t.Errorf("Repositories.GetAdminEnforcement returned %+v, want %+v", enforcement, want)
  1434  	}
  1435  }
  1436  
  1437  func TestRepositoriesService_AddAdminEnforcement(t *testing.T) {
  1438  	client, mux, _, teardown := setup()
  1439  	defer teardown()
  1440  
  1441  	mux.HandleFunc("/repos/o/r/branches/b/protection/enforce_admins", func(w http.ResponseWriter, r *http.Request) {
  1442  		testMethod(t, r, "POST")
  1443  		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  1444  		fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/enforce_admins","enabled":true}`)
  1445  	})
  1446  
  1447  	enforcement, _, err := client.Repositories.AddAdminEnforcement(context.Background(), "o", "r", "b")
  1448  	if err != nil {
  1449  		t.Errorf("Repositories.AddAdminEnforcement returned error: %v", err)
  1450  	}
  1451  
  1452  	want := &AdminEnforcement{
  1453  		URL:     String("/repos/o/r/branches/b/protection/enforce_admins"),
  1454  		Enabled: true,
  1455  	}
  1456  	if !reflect.DeepEqual(enforcement, want) {
  1457  		t.Errorf("Repositories.AddAdminEnforcement returned %+v, want %+v", enforcement, want)
  1458  	}
  1459  }
  1460  
  1461  func TestRepositoriesService_RemoveAdminEnforcement(t *testing.T) {
  1462  	client, mux, _, teardown := setup()
  1463  	defer teardown()
  1464  
  1465  	mux.HandleFunc("/repos/o/r/branches/b/protection/enforce_admins", func(w http.ResponseWriter, r *http.Request) {
  1466  		testMethod(t, r, "DELETE")
  1467  		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  1468  		w.WriteHeader(http.StatusNoContent)
  1469  	})
  1470  
  1471  	_, err := client.Repositories.RemoveAdminEnforcement(context.Background(), "o", "r", "b")
  1472  	if err != nil {
  1473  		t.Errorf("Repositories.RemoveAdminEnforcement returned error: %v", err)
  1474  	}
  1475  }
  1476  
  1477  func TestRepositoriesService_GetSignaturesProtectedBranch(t *testing.T) {
  1478  	client, mux, _, teardown := setup()
  1479  	defer teardown()
  1480  
  1481  	mux.HandleFunc("/repos/o/r/branches/b/protection/required_signatures", func(w http.ResponseWriter, r *http.Request) {
  1482  		testMethod(t, r, "GET")
  1483  		testHeader(t, r, "Accept", mediaTypeSignaturePreview)
  1484  		fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/required_signatures","enabled":false}`)
  1485  	})
  1486  
  1487  	signature, _, err := client.Repositories.GetSignaturesProtectedBranch(context.Background(), "o", "r", "b")
  1488  	if err != nil {
  1489  		t.Errorf("Repositories.GetSignaturesProtectedBranch returned error: %v", err)
  1490  	}
  1491  
  1492  	want := &SignaturesProtectedBranch{
  1493  		URL:     String("/repos/o/r/branches/b/protection/required_signatures"),
  1494  		Enabled: Bool(false),
  1495  	}
  1496  
  1497  	if !reflect.DeepEqual(signature, want) {
  1498  		t.Errorf("Repositories.GetSignaturesProtectedBranch returned %+v, want %+v", signature, want)
  1499  	}
  1500  }
  1501  
  1502  func TestRepositoriesService_RequireSignaturesOnProtectedBranch(t *testing.T) {
  1503  	client, mux, _, teardown := setup()
  1504  	defer teardown()
  1505  
  1506  	mux.HandleFunc("/repos/o/r/branches/b/protection/required_signatures", func(w http.ResponseWriter, r *http.Request) {
  1507  		testMethod(t, r, "POST")
  1508  		testHeader(t, r, "Accept", mediaTypeSignaturePreview)
  1509  		fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/required_signatures","enabled":true}`)
  1510  	})
  1511  
  1512  	signature, _, err := client.Repositories.RequireSignaturesOnProtectedBranch(context.Background(), "o", "r", "b")
  1513  	if err != nil {
  1514  		t.Errorf("Repositories.RequireSignaturesOnProtectedBranch returned error: %v", err)
  1515  	}
  1516  
  1517  	want := &SignaturesProtectedBranch{
  1518  		URL:     String("/repos/o/r/branches/b/protection/required_signatures"),
  1519  		Enabled: Bool(true),
  1520  	}
  1521  
  1522  	if !reflect.DeepEqual(signature, want) {
  1523  		t.Errorf("Repositories.RequireSignaturesOnProtectedBranch returned %+v, want %+v", signature, want)
  1524  	}
  1525  }
  1526  
  1527  func TestRepositoriesService_OptionalSignaturesOnProtectedBranch(t *testing.T) {
  1528  	client, mux, _, teardown := setup()
  1529  	defer teardown()
  1530  
  1531  	mux.HandleFunc("/repos/o/r/branches/b/protection/required_signatures", func(w http.ResponseWriter, r *http.Request) {
  1532  		testMethod(t, r, "DELETE")
  1533  		testHeader(t, r, "Accept", mediaTypeSignaturePreview)
  1534  		w.WriteHeader(http.StatusNoContent)
  1535  	})
  1536  
  1537  	_, err := client.Repositories.OptionalSignaturesOnProtectedBranch(context.Background(), "o", "r", "b")
  1538  	if err != nil {
  1539  		t.Errorf("Repositories.OptionalSignaturesOnProtectedBranch returned error: %v", err)
  1540  	}
  1541  }
  1542  
  1543  func TestPullRequestReviewsEnforcementRequest_MarshalJSON_nilDismissalRestirctions(t *testing.T) {
  1544  	req := PullRequestReviewsEnforcementRequest{}
  1545  
  1546  	got, err := json.Marshal(req)
  1547  	if err != nil {
  1548  		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err)
  1549  	}
  1550  
  1551  	want := `{"dismiss_stale_reviews":false,"require_code_owner_reviews":false,"required_approving_review_count":0}`
  1552  	if want != string(got) {
  1553  		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want)
  1554  	}
  1555  
  1556  	req = PullRequestReviewsEnforcementRequest{
  1557  		DismissalRestrictionsRequest: &DismissalRestrictionsRequest{},
  1558  	}
  1559  
  1560  	got, err = json.Marshal(req)
  1561  	if err != nil {
  1562  		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err)
  1563  	}
  1564  
  1565  	want = `{"dismissal_restrictions":{},"dismiss_stale_reviews":false,"require_code_owner_reviews":false,"required_approving_review_count":0}`
  1566  	if want != string(got) {
  1567  		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want)
  1568  	}
  1569  
  1570  	req = PullRequestReviewsEnforcementRequest{
  1571  		DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
  1572  			Users: &[]string{},
  1573  			Teams: &[]string{},
  1574  		},
  1575  	}
  1576  
  1577  	got, err = json.Marshal(req)
  1578  	if err != nil {
  1579  		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err)
  1580  	}
  1581  
  1582  	want = `{"dismissal_restrictions":{"users":[],"teams":[]},"dismiss_stale_reviews":false,"require_code_owner_reviews":false,"required_approving_review_count":0}`
  1583  	if want != string(got) {
  1584  		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want)
  1585  	}
  1586  }
  1587  
  1588  func TestRepositoriesService_ListAllTopics(t *testing.T) {
  1589  	client, mux, _, teardown := setup()
  1590  	defer teardown()
  1591  
  1592  	mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
  1593  		testMethod(t, r, "GET")
  1594  		testHeader(t, r, "Accept", mediaTypeTopicsPreview)
  1595  		fmt.Fprint(w, `{"names":["go", "go-github", "github"]}`)
  1596  	})
  1597  
  1598  	got, _, err := client.Repositories.ListAllTopics(context.Background(), "o", "r")
  1599  	if err != nil {
  1600  		t.Fatalf("Repositories.ListAllTopics returned error: %v", err)
  1601  	}
  1602  
  1603  	want := []string{"go", "go-github", "github"}
  1604  	if !reflect.DeepEqual(got, want) {
  1605  		t.Errorf("Repositories.ListAllTopics returned %+v, want %+v", got, want)
  1606  	}
  1607  }
  1608  
  1609  func TestRepositoriesService_ListAllTopics_emptyTopics(t *testing.T) {
  1610  	client, mux, _, teardown := setup()
  1611  	defer teardown()
  1612  
  1613  	mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
  1614  		testMethod(t, r, "GET")
  1615  		testHeader(t, r, "Accept", mediaTypeTopicsPreview)
  1616  		fmt.Fprint(w, `{"names":[]}`)
  1617  	})
  1618  
  1619  	got, _, err := client.Repositories.ListAllTopics(context.Background(), "o", "r")
  1620  	if err != nil {
  1621  		t.Fatalf("Repositories.ListAllTopics returned error: %v", err)
  1622  	}
  1623  
  1624  	want := []string{}
  1625  	if !reflect.DeepEqual(got, want) {
  1626  		t.Errorf("Repositories.ListAllTopics returned %+v, want %+v", got, want)
  1627  	}
  1628  }
  1629  
  1630  func TestRepositoriesService_ReplaceAllTopics(t *testing.T) {
  1631  	client, mux, _, teardown := setup()
  1632  	defer teardown()
  1633  
  1634  	mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
  1635  		testMethod(t, r, "PUT")
  1636  		testHeader(t, r, "Accept", mediaTypeTopicsPreview)
  1637  		fmt.Fprint(w, `{"names":["go", "go-github", "github"]}`)
  1638  	})
  1639  
  1640  	got, _, err := client.Repositories.ReplaceAllTopics(context.Background(), "o", "r", []string{"go", "go-github", "github"})
  1641  	if err != nil {
  1642  		t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err)
  1643  	}
  1644  
  1645  	want := []string{"go", "go-github", "github"}
  1646  	if !reflect.DeepEqual(got, want) {
  1647  		t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want)
  1648  	}
  1649  }
  1650  
  1651  func TestRepositoriesService_ReplaceAllTopics_nilSlice(t *testing.T) {
  1652  	client, mux, _, teardown := setup()
  1653  	defer teardown()
  1654  
  1655  	mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
  1656  		testMethod(t, r, "PUT")
  1657  		testHeader(t, r, "Accept", mediaTypeTopicsPreview)
  1658  		testBody(t, r, `{"names":[]}`+"\n")
  1659  		fmt.Fprint(w, `{"names":[]}`)
  1660  	})
  1661  
  1662  	got, _, err := client.Repositories.ReplaceAllTopics(context.Background(), "o", "r", nil)
  1663  	if err != nil {
  1664  		t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err)
  1665  	}
  1666  
  1667  	want := []string{}
  1668  	if !reflect.DeepEqual(got, want) {
  1669  		t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want)
  1670  	}
  1671  }
  1672  
  1673  func TestRepositoriesService_ReplaceAllTopics_emptySlice(t *testing.T) {
  1674  	client, mux, _, teardown := setup()
  1675  	defer teardown()
  1676  
  1677  	mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
  1678  		testMethod(t, r, "PUT")
  1679  		testHeader(t, r, "Accept", mediaTypeTopicsPreview)
  1680  		testBody(t, r, `{"names":[]}`+"\n")
  1681  		fmt.Fprint(w, `{"names":[]}`)
  1682  	})
  1683  
  1684  	got, _, err := client.Repositories.ReplaceAllTopics(context.Background(), "o", "r", []string{})
  1685  	if err != nil {
  1686  		t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err)
  1687  	}
  1688  
  1689  	want := []string{}
  1690  	if !reflect.DeepEqual(got, want) {
  1691  		t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want)
  1692  	}
  1693  }
  1694  
  1695  func TestRepositoriesService_ListApps(t *testing.T) {
  1696  	client, mux, _, teardown := setup()
  1697  	defer teardown()
  1698  
  1699  	mux.HandleFunc("/repos/o/r/branches/b/protection/restrictions/apps", func(w http.ResponseWriter, r *http.Request) {
  1700  		testMethod(t, r, "GET")
  1701  	})
  1702  
  1703  	_, _, err := client.Repositories.ListApps(context.Background(), "o", "r", "b")
  1704  	if err != nil {
  1705  		t.Errorf("Repositories.ListApps returned error: %v", err)
  1706  	}
  1707  }
  1708  
  1709  func TestRepositoriesService_ReplaceAppRestrictions(t *testing.T) {
  1710  	client, mux, _, teardown := setup()
  1711  	defer teardown()
  1712  
  1713  	mux.HandleFunc("/repos/o/r/branches/b/protection/restrictions/apps", func(w http.ResponseWriter, r *http.Request) {
  1714  		testMethod(t, r, "PUT")
  1715  		fmt.Fprint(w, `[{
  1716  				"name": "octocat"
  1717  			}]`)
  1718  	})
  1719  	input := []string{"octocat"}
  1720  	got, _, err := client.Repositories.ReplaceAppRestrictions(context.Background(), "o", "r", "b", input)
  1721  	if err != nil {
  1722  		t.Errorf("Repositories.ReplaceAppRestrictions returned error: %v", err)
  1723  	}
  1724  	want := []*App{
  1725  		{Name: String("octocat")},
  1726  	}
  1727  	if !reflect.DeepEqual(got, want) {
  1728  		t.Errorf("Repositories.ReplaceAppRestrictions returned %+v, want %+v", got, want)
  1729  	}
  1730  }
  1731  
  1732  func TestRepositoriesService_AddAppRestrictions(t *testing.T) {
  1733  	client, mux, _, teardown := setup()
  1734  	defer teardown()
  1735  
  1736  	mux.HandleFunc("/repos/o/r/branches/b/protection/restrictions/apps", func(w http.ResponseWriter, r *http.Request) {
  1737  		testMethod(t, r, "POST")
  1738  		fmt.Fprint(w, `[{
  1739  				"name": "octocat"
  1740  			}]`)
  1741  	})
  1742  	input := []string{"octocat"}
  1743  	got, _, err := client.Repositories.AddAppRestrictions(context.Background(), "o", "r", "b", input)
  1744  	if err != nil {
  1745  		t.Errorf("Repositories.AddAppRestrictions returned error: %v", err)
  1746  	}
  1747  	want := []*App{
  1748  		{Name: String("octocat")},
  1749  	}
  1750  	if !reflect.DeepEqual(got, want) {
  1751  		t.Errorf("Repositories.AddAppRestrictions returned %+v, want %+v", got, want)
  1752  	}
  1753  }
  1754  
  1755  func TestRepositoriesService_RemoveAppRestrictions(t *testing.T) {
  1756  	client, mux, _, teardown := setup()
  1757  	defer teardown()
  1758  
  1759  	mux.HandleFunc("/repos/o/r/branches/b/protection/restrictions/apps", func(w http.ResponseWriter, r *http.Request) {
  1760  		testMethod(t, r, "DELETE")
  1761  		fmt.Fprint(w, `[]`)
  1762  	})
  1763  	input := []string{"octocat"}
  1764  	got, _, err := client.Repositories.RemoveAppRestrictions(context.Background(), "o", "r", "b", input)
  1765  	if err != nil {
  1766  		t.Errorf("Repositories.RemoveAppRestrictions returned error: %v", err)
  1767  	}
  1768  	want := []*App{}
  1769  	if !reflect.DeepEqual(got, want) {
  1770  		t.Errorf("Repositories.RemoveAppRestrictions returned %+v, want %+v", got, want)
  1771  	}
  1772  }
  1773  
  1774  func TestRepositoriesService_Transfer(t *testing.T) {
  1775  	client, mux, _, teardown := setup()
  1776  	defer teardown()
  1777  
  1778  	input := TransferRequest{NewOwner: "a", TeamID: []int64{123}}
  1779  
  1780  	mux.HandleFunc("/repos/o/r/transfer", func(w http.ResponseWriter, r *http.Request) {
  1781  		var v TransferRequest
  1782  		json.NewDecoder(r.Body).Decode(&v)
  1783  
  1784  		testMethod(t, r, "POST")
  1785  		if !reflect.DeepEqual(v, input) {
  1786  			t.Errorf("Request body = %+v, want %+v", v, input)
  1787  		}
  1788  
  1789  		fmt.Fprint(w, `{"owner":{"login":"a"}}`)
  1790  	})
  1791  
  1792  	got, _, err := client.Repositories.Transfer(context.Background(), "o", "r", input)
  1793  	if err != nil {
  1794  		t.Errorf("Repositories.Transfer returned error: %v", err)
  1795  	}
  1796  
  1797  	want := &Repository{Owner: &User{Login: String("a")}}
  1798  	if !reflect.DeepEqual(got, want) {
  1799  		t.Errorf("Repositories.Transfer returned %+v, want %+v", got, want)
  1800  	}
  1801  }
  1802  
  1803  func TestRepositoriesService_Dispatch(t *testing.T) {
  1804  	client, mux, _, teardown := setup()
  1805  	defer teardown()
  1806  
  1807  	var input DispatchRequestOptions
  1808  
  1809  	mux.HandleFunc("/repos/o/r/dispatches", func(w http.ResponseWriter, r *http.Request) {
  1810  		var v DispatchRequestOptions
  1811  		json.NewDecoder(r.Body).Decode(&v)
  1812  
  1813  		testMethod(t, r, "POST")
  1814  		if !reflect.DeepEqual(v, input) {
  1815  			t.Errorf("Request body = %+v, want %+v", v, input)
  1816  		}
  1817  
  1818  		fmt.Fprint(w, `{"owner":{"login":"a"}}`)
  1819  	})
  1820  
  1821  	ctx := context.Background()
  1822  
  1823  	testCases := []interface{}{
  1824  		nil,
  1825  		struct {
  1826  			Foo string
  1827  		}{
  1828  			Foo: "test",
  1829  		},
  1830  		struct {
  1831  			Bar int
  1832  		}{
  1833  			Bar: 42,
  1834  		},
  1835  		struct {
  1836  			Foo string
  1837  			Bar int
  1838  			Baz bool
  1839  		}{
  1840  			Foo: "test",
  1841  			Bar: 42,
  1842  			Baz: false,
  1843  		},
  1844  	}
  1845  	for _, tc := range testCases {
  1846  
  1847  		if tc == nil {
  1848  			input = DispatchRequestOptions{EventType: "go"}
  1849  		} else {
  1850  			bytes, _ := json.Marshal(tc)
  1851  			payload := json.RawMessage(bytes)
  1852  			input = DispatchRequestOptions{EventType: "go", ClientPayload: &payload}
  1853  		}
  1854  
  1855  		got, _, err := client.Repositories.Dispatch(ctx, "o", "r", input)
  1856  		if err != nil {
  1857  			t.Errorf("Repositories.Dispatch returned error: %v", err)
  1858  		}
  1859  
  1860  		want := &Repository{Owner: &User{Login: String("a")}}
  1861  		if !reflect.DeepEqual(got, want) {
  1862  			t.Errorf("Repositories.Dispatch returned %+v, want %+v", got, want)
  1863  		}
  1864  	}
  1865  
  1866  	// Test s.client.NewRequest failure
  1867  	client.BaseURL.Path = ""
  1868  	got, resp, err := client.Repositories.Dispatch(ctx, "o", "r", input)
  1869  	if got != nil {
  1870  		t.Errorf("client.BaseURL.Path='' Dispatch = %#v, want nil", got)
  1871  	}
  1872  	if resp != nil {
  1873  		t.Errorf("client.BaseURL.Path='' Dispatch resp = %#v, want nil", resp)
  1874  	}
  1875  	if err == nil {
  1876  		t.Error("client.BaseURL.Path='' Dispatch err = nil, want error")
  1877  	}
  1878  
  1879  	// Test s.client.Do failure
  1880  	client.BaseURL.Path = "/api-v3/"
  1881  	client.rateLimits[0].Reset.Time = time.Now().Add(10 * time.Minute)
  1882  	got, resp, err = client.Repositories.Dispatch(ctx, "o", "r", input)
  1883  	if got != nil {
  1884  		t.Errorf("rate.Reset.Time > now Dispatch = %#v, want nil", got)
  1885  	}
  1886  	if want := http.StatusForbidden; resp == nil || resp.Response.StatusCode != want {
  1887  		t.Errorf("rate.Reset.Time > now Dispatch resp = %#v, want StatusCode=%v", resp.Response, want)
  1888  	}
  1889  	if err == nil {
  1890  		t.Error("rate.Reset.Time > now Dispatch err = nil, want error")
  1891  	}
  1892  }