github.com/google/go-github/v64@v64.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  	"errors"
    12  	"fmt"
    13  	"net/http"
    14  	"net/url"
    15  	"strings"
    16  	"testing"
    17  	"time"
    18  
    19  	"github.com/google/go-cmp/cmp"
    20  )
    21  
    22  func TestRepositoriesService_ListByAuthenticatedUser(t *testing.T) {
    23  	client, mux, _, teardown := setup()
    24  	defer teardown()
    25  
    26  	mux.HandleFunc("/user/repos", func(w http.ResponseWriter, r *http.Request) {
    27  		testMethod(t, r, "GET")
    28  		fmt.Fprint(w, `[{"id":1},{"id":2}]`)
    29  	})
    30  
    31  	ctx := context.Background()
    32  	got, _, err := client.Repositories.ListByAuthenticatedUser(ctx, nil)
    33  	if err != nil {
    34  		t.Errorf("Repositories.List returned error: %v", err)
    35  	}
    36  
    37  	want := []*Repository{{ID: Int64(1)}, {ID: Int64(2)}}
    38  	if !cmp.Equal(got, want) {
    39  		t.Errorf("Repositories.ListByAuthenticatedUser returned %+v, want %+v", got, want)
    40  	}
    41  
    42  	const methodName = "ListByAuthenticatedUser"
    43  
    44  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
    45  		got, resp, err := client.Repositories.ListByAuthenticatedUser(ctx, nil)
    46  		if got != nil {
    47  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
    48  		}
    49  		return resp, err
    50  	})
    51  }
    52  
    53  func TestRepositoriesService_ListByUser(t *testing.T) {
    54  	client, mux, _, teardown := setup()
    55  	defer teardown()
    56  
    57  	mux.HandleFunc("/users/u/repos", func(w http.ResponseWriter, r *http.Request) {
    58  		testMethod(t, r, "GET")
    59  		testFormValues(t, r, values{
    60  			"sort":      "created",
    61  			"direction": "asc",
    62  			"page":      "2",
    63  		})
    64  		fmt.Fprint(w, `[{"id":1}]`)
    65  	})
    66  
    67  	opt := &RepositoryListByUserOptions{
    68  		Sort:        "created",
    69  		Direction:   "asc",
    70  		ListOptions: ListOptions{Page: 2},
    71  	}
    72  	ctx := context.Background()
    73  	repos, _, err := client.Repositories.ListByUser(ctx, "u", opt)
    74  	if err != nil {
    75  		t.Errorf("Repositories.List returned error: %v", err)
    76  	}
    77  
    78  	want := []*Repository{{ID: Int64(1)}}
    79  	if !cmp.Equal(repos, want) {
    80  		t.Errorf("Repositories.ListByUser returned %+v, want %+v", repos, want)
    81  	}
    82  
    83  	const methodName = "ListByUser"
    84  	testBadOptions(t, methodName, func() (err error) {
    85  		_, _, err = client.Repositories.ListByUser(ctx, "\n", &RepositoryListByUserOptions{})
    86  		return err
    87  	})
    88  
    89  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
    90  		got, resp, err := client.Repositories.ListByUser(ctx, "u", nil)
    91  		if got != nil {
    92  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
    93  		}
    94  		return resp, err
    95  	})
    96  }
    97  
    98  func TestRepositoriesService_ListByUser_type(t *testing.T) {
    99  	client, mux, _, teardown := setup()
   100  	defer teardown()
   101  
   102  	mux.HandleFunc("/users/u/repos", func(w http.ResponseWriter, r *http.Request) {
   103  		testMethod(t, r, "GET")
   104  		testFormValues(t, r, values{
   105  			"type": "owner",
   106  		})
   107  		fmt.Fprint(w, `[{"id":1}]`)
   108  	})
   109  
   110  	opt := &RepositoryListByUserOptions{
   111  		Type: "owner",
   112  	}
   113  	ctx := context.Background()
   114  	repos, _, err := client.Repositories.ListByUser(ctx, "u", opt)
   115  	if err != nil {
   116  		t.Errorf("Repositories.ListByUser returned error: %v", err)
   117  	}
   118  
   119  	want := []*Repository{{ID: Int64(1)}}
   120  	if !cmp.Equal(repos, want) {
   121  		t.Errorf("Repositories.ListByUser returned %+v, want %+v", repos, want)
   122  	}
   123  }
   124  
   125  func TestRepositoriesService_ListByUser_invalidUser(t *testing.T) {
   126  	client, _, _, teardown := setup()
   127  	defer teardown()
   128  
   129  	ctx := context.Background()
   130  	_, _, err := client.Repositories.ListByUser(ctx, "%", 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, mediaTypeRepositoryVisibilityPreview}
   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 !cmp.Equal(got, want) {
   161  		t.Errorf("Repositories.ListByOrg returned %+v, want %+v", got, want)
   162  	}
   163  
   164  	const methodName = "ListByOrg"
   165  	testBadOptions(t, methodName, func() (err error) {
   166  		_, _, err = client.Repositories.ListByOrg(ctx, "\n", opt)
   167  		return err
   168  	})
   169  
   170  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   171  		got, resp, err := client.Repositories.ListByOrg(ctx, "o", opt)
   172  		if got != nil {
   173  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   174  		}
   175  		return resp, err
   176  	})
   177  }
   178  
   179  func TestRepositoriesService_ListByOrg_invalidOrg(t *testing.T) {
   180  	client, _, _, teardown := setup()
   181  	defer teardown()
   182  
   183  	ctx := context.Background()
   184  	_, _, err := client.Repositories.ListByOrg(ctx, "%", nil)
   185  	testURLParseError(t, err)
   186  }
   187  
   188  func TestRepositoriesService_ListAll(t *testing.T) {
   189  	client, mux, _, teardown := setup()
   190  	defer teardown()
   191  
   192  	mux.HandleFunc("/repositories", func(w http.ResponseWriter, r *http.Request) {
   193  		testMethod(t, r, "GET")
   194  		testFormValues(t, r, values{
   195  			"since": "1",
   196  		})
   197  		fmt.Fprint(w, `[{"id":1}]`)
   198  	})
   199  
   200  	ctx := context.Background()
   201  	opt := &RepositoryListAllOptions{1}
   202  	got, _, err := client.Repositories.ListAll(ctx, opt)
   203  	if err != nil {
   204  		t.Errorf("Repositories.ListAll returned error: %v", err)
   205  	}
   206  
   207  	want := []*Repository{{ID: Int64(1)}}
   208  	if !cmp.Equal(got, want) {
   209  		t.Errorf("Repositories.ListAll returned %+v, want %+v", got, want)
   210  	}
   211  
   212  	const methodName = "ListAll"
   213  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   214  		got, resp, err := client.Repositories.ListAll(ctx, &RepositoryListAllOptions{1})
   215  		if got != nil {
   216  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   217  		}
   218  		return resp, err
   219  	})
   220  }
   221  
   222  func TestRepositoriesService_Create_user(t *testing.T) {
   223  	client, mux, _, teardown := setup()
   224  	defer teardown()
   225  
   226  	input := &Repository{
   227  		Name:     String("n"),
   228  		Archived: Bool(true), // not passed along.
   229  	}
   230  
   231  	wantAcceptHeaders := []string{mediaTypeRepositoryTemplatePreview, mediaTypeRepositoryVisibilityPreview}
   232  	mux.HandleFunc("/user/repos", func(w http.ResponseWriter, r *http.Request) {
   233  		v := new(createRepoRequest)
   234  		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
   235  
   236  		testMethod(t, r, "POST")
   237  		testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", "))
   238  		want := &createRepoRequest{Name: String("n")}
   239  		if !cmp.Equal(v, want) {
   240  			t.Errorf("Request body = %+v, want %+v", v, want)
   241  		}
   242  
   243  		fmt.Fprint(w, `{"id":1}`)
   244  	})
   245  
   246  	ctx := context.Background()
   247  	got, _, err := client.Repositories.Create(ctx, "", input)
   248  	if err != nil {
   249  		t.Errorf("Repositories.Create returned error: %v", err)
   250  	}
   251  
   252  	want := &Repository{ID: Int64(1)}
   253  	if !cmp.Equal(got, want) {
   254  		t.Errorf("Repositories.Create returned %+v, want %+v", got, want)
   255  	}
   256  
   257  	const methodName = "Create"
   258  	testBadOptions(t, methodName, func() (err error) {
   259  		_, _, err = client.Repositories.Create(ctx, "\n", input)
   260  		return err
   261  	})
   262  
   263  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   264  		got, resp, err := client.Repositories.Create(ctx, "", input)
   265  		if got != nil {
   266  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   267  		}
   268  		return resp, err
   269  	})
   270  }
   271  
   272  func TestRepositoriesService_Create_org(t *testing.T) {
   273  	client, mux, _, teardown := setup()
   274  	defer teardown()
   275  
   276  	input := &Repository{
   277  		Name:     String("n"),
   278  		Archived: Bool(true), // not passed along.
   279  	}
   280  
   281  	wantAcceptHeaders := []string{mediaTypeRepositoryTemplatePreview, mediaTypeRepositoryVisibilityPreview}
   282  	mux.HandleFunc("/orgs/o/repos", func(w http.ResponseWriter, r *http.Request) {
   283  		v := new(createRepoRequest)
   284  		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
   285  
   286  		testMethod(t, r, "POST")
   287  		testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", "))
   288  		want := &createRepoRequest{Name: String("n")}
   289  		if !cmp.Equal(v, want) {
   290  			t.Errorf("Request body = %+v, want %+v", v, want)
   291  		}
   292  
   293  		fmt.Fprint(w, `{"id":1}`)
   294  	})
   295  
   296  	ctx := context.Background()
   297  	repo, _, err := client.Repositories.Create(ctx, "o", input)
   298  	if err != nil {
   299  		t.Errorf("Repositories.Create returned error: %v", err)
   300  	}
   301  
   302  	want := &Repository{ID: Int64(1)}
   303  	if !cmp.Equal(repo, want) {
   304  		t.Errorf("Repositories.Create returned %+v, want %+v", repo, want)
   305  	}
   306  }
   307  
   308  func TestRepositoriesService_CreateFromTemplate(t *testing.T) {
   309  	client, mux, _, teardown := setup()
   310  	defer teardown()
   311  
   312  	templateRepoReq := &TemplateRepoRequest{
   313  		Name: String("n"),
   314  	}
   315  
   316  	mux.HandleFunc("/repos/to/tr/generate", func(w http.ResponseWriter, r *http.Request) {
   317  		v := new(TemplateRepoRequest)
   318  		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
   319  
   320  		testMethod(t, r, "POST")
   321  		testHeader(t, r, "Accept", mediaTypeRepositoryTemplatePreview)
   322  		want := &TemplateRepoRequest{Name: String("n")}
   323  		if !cmp.Equal(v, want) {
   324  			t.Errorf("Request body = %+v, want %+v", v, want)
   325  		}
   326  
   327  		fmt.Fprint(w, `{"id":1,"name":"n"}`)
   328  	})
   329  
   330  	ctx := context.Background()
   331  	got, _, err := client.Repositories.CreateFromTemplate(ctx, "to", "tr", templateRepoReq)
   332  	if err != nil {
   333  		t.Errorf("Repositories.CreateFromTemplate returned error: %v", err)
   334  	}
   335  
   336  	want := &Repository{ID: Int64(1), Name: String("n")}
   337  	if !cmp.Equal(got, want) {
   338  		t.Errorf("Repositories.CreateFromTemplate returned %+v, want %+v", got, want)
   339  	}
   340  
   341  	const methodName = "CreateFromTemplate"
   342  	testBadOptions(t, methodName, func() (err error) {
   343  		_, _, err = client.Repositories.CreateFromTemplate(ctx, "\n", "\n", templateRepoReq)
   344  		return err
   345  	})
   346  
   347  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   348  		got, resp, err := client.Repositories.CreateFromTemplate(ctx, "to", "tr", templateRepoReq)
   349  		if got != nil {
   350  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   351  		}
   352  		return resp, err
   353  	})
   354  }
   355  
   356  func TestRepositoriesService_Get(t *testing.T) {
   357  	client, mux, _, teardown := setup()
   358  	defer teardown()
   359  
   360  	wantAcceptHeaders := []string{mediaTypeCodesOfConductPreview, mediaTypeTopicsPreview, mediaTypeRepositoryTemplatePreview, mediaTypeRepositoryVisibilityPreview}
   361  	mux.HandleFunc("/repos/o/r", func(w http.ResponseWriter, r *http.Request) {
   362  		testMethod(t, r, "GET")
   363  		testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", "))
   364  		fmt.Fprint(w, `{"id":1,"name":"n","description":"d","owner":{"login":"l"},"license":{"key":"mit"},"security_and_analysis":{"advanced_security":{"status":"enabled"},"secret_scanning":{"status":"enabled"},"secret_scanning_push_protection":{"status":"enabled"},"dependabot_security_updates":{"status": "enabled"}, "secret_scanning_validity_checks":{"status":"enabled"}}}`)
   365  	})
   366  
   367  	ctx := context.Background()
   368  	got, _, err := client.Repositories.Get(ctx, "o", "r")
   369  	if err != nil {
   370  		t.Errorf("Repositories.Get returned error: %v", err)
   371  	}
   372  
   373  	want := &Repository{ID: Int64(1), Name: String("n"), Description: String("d"), Owner: &User{Login: String("l")}, License: &License{Key: String("mit")}, SecurityAndAnalysis: &SecurityAndAnalysis{AdvancedSecurity: &AdvancedSecurity{Status: String("enabled")}, SecretScanning: &SecretScanning{String("enabled")}, SecretScanningPushProtection: &SecretScanningPushProtection{String("enabled")}, DependabotSecurityUpdates: &DependabotSecurityUpdates{String("enabled")}, SecretScanningValidityChecks: &SecretScanningValidityChecks{String("enabled")}}}
   374  	if !cmp.Equal(got, want) {
   375  		t.Errorf("Repositories.Get returned %+v, want %+v", got, want)
   376  	}
   377  
   378  	const methodName = "Get"
   379  	testBadOptions(t, methodName, func() (err error) {
   380  		_, _, err = client.Repositories.Get(ctx, "\n", "\n")
   381  		return err
   382  	})
   383  
   384  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   385  		got, resp, err := client.Repositories.Get(ctx, "o", "r")
   386  		if got != nil {
   387  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   388  		}
   389  		return resp, err
   390  	})
   391  }
   392  
   393  func TestRepositoriesService_GetCodeOfConduct(t *testing.T) {
   394  	client, mux, _, teardown := setup()
   395  	defer teardown()
   396  
   397  	mux.HandleFunc("/repos/o/r", func(w http.ResponseWriter, r *http.Request) {
   398  		testMethod(t, r, "GET")
   399  		testHeader(t, r, "Accept", mediaTypeCodesOfConductPreview)
   400  		fmt.Fprint(w, `{
   401              "code_of_conduct": {
   402    						"key": "key",
   403    						"name": "name",
   404    						"url": "url",
   405    						"body": "body"
   406              }}`,
   407  		)
   408  	})
   409  
   410  	ctx := context.Background()
   411  	got, _, err := client.Repositories.GetCodeOfConduct(ctx, "o", "r")
   412  	if err != nil {
   413  		t.Errorf("Repositories.GetCodeOfConduct returned error: %v", err)
   414  	}
   415  
   416  	want := &CodeOfConduct{
   417  		Key:  String("key"),
   418  		Name: String("name"),
   419  		URL:  String("url"),
   420  		Body: String("body"),
   421  	}
   422  
   423  	if !cmp.Equal(got, want) {
   424  		t.Errorf("Repositories.GetCodeOfConduct returned %+v, want %+v", got, want)
   425  	}
   426  
   427  	const methodName = "GetCodeOfConduct"
   428  	testBadOptions(t, methodName, func() (err error) {
   429  		_, _, err = client.Repositories.GetCodeOfConduct(ctx, "\n", "\n")
   430  		return err
   431  	})
   432  
   433  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   434  		got, resp, err := client.Repositories.GetCodeOfConduct(ctx, "o", "r")
   435  		if got != nil {
   436  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   437  		}
   438  		return resp, err
   439  	})
   440  }
   441  
   442  func TestRepositoriesService_GetByID(t *testing.T) {
   443  	client, mux, _, teardown := setup()
   444  	defer teardown()
   445  
   446  	mux.HandleFunc("/repositories/1", func(w http.ResponseWriter, r *http.Request) {
   447  		testMethod(t, r, "GET")
   448  		fmt.Fprint(w, `{"id":1,"name":"n","description":"d","owner":{"login":"l"},"license":{"key":"mit"}}`)
   449  	})
   450  
   451  	ctx := context.Background()
   452  	got, _, err := client.Repositories.GetByID(ctx, 1)
   453  	if err != nil {
   454  		t.Fatalf("Repositories.GetByID returned error: %v", err)
   455  	}
   456  
   457  	want := &Repository{ID: Int64(1), Name: String("n"), Description: String("d"), Owner: &User{Login: String("l")}, License: &License{Key: String("mit")}}
   458  	if !cmp.Equal(got, want) {
   459  		t.Errorf("Repositories.GetByID returned %+v, want %+v", got, want)
   460  	}
   461  
   462  	const methodName = "GetByID"
   463  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   464  		got, resp, err := client.Repositories.GetByID(ctx, 1)
   465  		if got != nil {
   466  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   467  		}
   468  		return resp, err
   469  	})
   470  }
   471  
   472  func TestRepositoriesService_Edit(t *testing.T) {
   473  	client, mux, _, teardown := setup()
   474  	defer teardown()
   475  
   476  	i := true
   477  	input := &Repository{HasIssues: &i}
   478  
   479  	wantAcceptHeaders := []string{mediaTypeRepositoryTemplatePreview, mediaTypeRepositoryVisibilityPreview}
   480  	mux.HandleFunc("/repos/o/r", func(w http.ResponseWriter, r *http.Request) {
   481  		v := new(Repository)
   482  		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
   483  
   484  		testMethod(t, r, "PATCH")
   485  		testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", "))
   486  		if !cmp.Equal(v, input) {
   487  			t.Errorf("Request body = %+v, want %+v", v, input)
   488  		}
   489  		fmt.Fprint(w, `{"id":1}`)
   490  	})
   491  
   492  	ctx := context.Background()
   493  	got, _, err := client.Repositories.Edit(ctx, "o", "r", input)
   494  	if err != nil {
   495  		t.Errorf("Repositories.Edit returned error: %v", err)
   496  	}
   497  
   498  	want := &Repository{ID: Int64(1)}
   499  	if !cmp.Equal(got, want) {
   500  		t.Errorf("Repositories.Edit returned %+v, want %+v", got, want)
   501  	}
   502  
   503  	const methodName = "Edit"
   504  	testBadOptions(t, methodName, func() (err error) {
   505  		_, _, err = client.Repositories.Edit(ctx, "\n", "\n", input)
   506  		return err
   507  	})
   508  
   509  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   510  		got, resp, err := client.Repositories.Edit(ctx, "o", "r", input)
   511  		if got != nil {
   512  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   513  		}
   514  		return resp, err
   515  	})
   516  }
   517  
   518  func TestRepositoriesService_Delete(t *testing.T) {
   519  	client, mux, _, teardown := setup()
   520  	defer teardown()
   521  
   522  	mux.HandleFunc("/repos/o/r", func(w http.ResponseWriter, r *http.Request) {
   523  		testMethod(t, r, "DELETE")
   524  	})
   525  
   526  	ctx := context.Background()
   527  	_, err := client.Repositories.Delete(ctx, "o", "r")
   528  	if err != nil {
   529  		t.Errorf("Repositories.Delete returned error: %v", err)
   530  	}
   531  
   532  	const methodName = "Delete"
   533  	testBadOptions(t, methodName, func() (err error) {
   534  		_, err = client.Repositories.Delete(ctx, "\n", "\n")
   535  		return err
   536  	})
   537  
   538  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   539  		return client.Repositories.Delete(ctx, "o", "r")
   540  	})
   541  }
   542  
   543  func TestRepositoriesService_Get_invalidOwner(t *testing.T) {
   544  	client, _, _, teardown := setup()
   545  	defer teardown()
   546  
   547  	ctx := context.Background()
   548  	_, _, err := client.Repositories.Get(ctx, "%", "r")
   549  	testURLParseError(t, err)
   550  }
   551  
   552  func TestRepositoriesService_Edit_invalidOwner(t *testing.T) {
   553  	client, _, _, teardown := setup()
   554  	defer teardown()
   555  
   556  	ctx := context.Background()
   557  	_, _, err := client.Repositories.Edit(ctx, "%", "r", nil)
   558  	testURLParseError(t, err)
   559  }
   560  
   561  func TestRepositoriesService_GetVulnerabilityAlerts(t *testing.T) {
   562  	client, mux, _, teardown := setup()
   563  	defer teardown()
   564  
   565  	mux.HandleFunc("/repos/o/r/vulnerability-alerts", func(w http.ResponseWriter, r *http.Request) {
   566  		testMethod(t, r, "GET")
   567  		testHeader(t, r, "Accept", mediaTypeRequiredVulnerabilityAlertsPreview)
   568  
   569  		w.WriteHeader(http.StatusNoContent)
   570  	})
   571  
   572  	ctx := context.Background()
   573  	vulnerabilityAlertsEnabled, _, err := client.Repositories.GetVulnerabilityAlerts(ctx, "o", "r")
   574  	if err != nil {
   575  		t.Errorf("Repositories.GetVulnerabilityAlerts returned error: %v", err)
   576  	}
   577  
   578  	if want := true; vulnerabilityAlertsEnabled != want {
   579  		t.Errorf("Repositories.GetVulnerabilityAlerts returned %+v, want %+v", vulnerabilityAlertsEnabled, want)
   580  	}
   581  
   582  	const methodName = "GetVulnerabilityAlerts"
   583  	testBadOptions(t, methodName, func() (err error) {
   584  		_, _, err = client.Repositories.GetVulnerabilityAlerts(ctx, "\n", "\n")
   585  		return err
   586  	})
   587  
   588  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   589  		got, resp, err := client.Repositories.GetVulnerabilityAlerts(ctx, "o", "r")
   590  		if got {
   591  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want false", methodName, got)
   592  		}
   593  		return resp, err
   594  	})
   595  }
   596  
   597  func TestRepositoriesService_EnableVulnerabilityAlerts(t *testing.T) {
   598  	client, mux, _, teardown := setup()
   599  	defer teardown()
   600  
   601  	mux.HandleFunc("/repos/o/r/vulnerability-alerts", func(w http.ResponseWriter, r *http.Request) {
   602  		testMethod(t, r, "PUT")
   603  		testHeader(t, r, "Accept", mediaTypeRequiredVulnerabilityAlertsPreview)
   604  
   605  		w.WriteHeader(http.StatusNoContent)
   606  	})
   607  
   608  	ctx := context.Background()
   609  	if _, err := client.Repositories.EnableVulnerabilityAlerts(ctx, "o", "r"); err != nil {
   610  		t.Errorf("Repositories.EnableVulnerabilityAlerts returned error: %v", err)
   611  	}
   612  
   613  	const methodName = "EnableVulnerabilityAlerts"
   614  	testBadOptions(t, methodName, func() (err error) {
   615  		_, err = client.Repositories.EnableVulnerabilityAlerts(ctx, "\n", "\n")
   616  		return err
   617  	})
   618  
   619  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   620  		return client.Repositories.EnableVulnerabilityAlerts(ctx, "o", "r")
   621  	})
   622  }
   623  
   624  func TestRepositoriesService_DisableVulnerabilityAlerts(t *testing.T) {
   625  	client, mux, _, teardown := setup()
   626  	defer teardown()
   627  
   628  	mux.HandleFunc("/repos/o/r/vulnerability-alerts", func(w http.ResponseWriter, r *http.Request) {
   629  		testMethod(t, r, "DELETE")
   630  		testHeader(t, r, "Accept", mediaTypeRequiredVulnerabilityAlertsPreview)
   631  
   632  		w.WriteHeader(http.StatusNoContent)
   633  	})
   634  
   635  	ctx := context.Background()
   636  	if _, err := client.Repositories.DisableVulnerabilityAlerts(ctx, "o", "r"); err != nil {
   637  		t.Errorf("Repositories.DisableVulnerabilityAlerts returned error: %v", err)
   638  	}
   639  
   640  	const methodName = "DisableVulnerabilityAlerts"
   641  	testBadOptions(t, methodName, func() (err error) {
   642  		_, err = client.Repositories.DisableVulnerabilityAlerts(ctx, "\n", "\n")
   643  		return err
   644  	})
   645  
   646  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   647  		return client.Repositories.DisableVulnerabilityAlerts(ctx, "o", "r")
   648  	})
   649  }
   650  
   651  func TestRepositoriesService_EnableAutomatedSecurityFixes(t *testing.T) {
   652  	client, mux, _, teardown := setup()
   653  	defer teardown()
   654  
   655  	mux.HandleFunc("/repos/o/r/automated-security-fixes", func(w http.ResponseWriter, r *http.Request) {
   656  		testMethod(t, r, "PUT")
   657  
   658  		w.WriteHeader(http.StatusNoContent)
   659  	})
   660  
   661  	ctx := context.Background()
   662  	if _, err := client.Repositories.EnableAutomatedSecurityFixes(ctx, "o", "r"); err != nil {
   663  		t.Errorf("Repositories.EnableAutomatedSecurityFixes returned error: %v", err)
   664  	}
   665  }
   666  
   667  func TestRepositoriesService_GetAutomatedSecurityFixes(t *testing.T) {
   668  	client, mux, _, teardown := setup()
   669  	defer teardown()
   670  
   671  	mux.HandleFunc("/repos/o/r/automated-security-fixes", func(w http.ResponseWriter, r *http.Request) {
   672  		testMethod(t, r, "GET")
   673  		fmt.Fprint(w, `{"enabled": true, "paused": false}`)
   674  	})
   675  
   676  	ctx := context.Background()
   677  	fixes, _, err := client.Repositories.GetAutomatedSecurityFixes(ctx, "o", "r")
   678  	if err != nil {
   679  		t.Errorf("Repositories.GetAutomatedSecurityFixes returned errpr: #{err}")
   680  	}
   681  
   682  	want := &AutomatedSecurityFixes{
   683  		Enabled: Bool(true),
   684  		Paused:  Bool(false),
   685  	}
   686  	if !cmp.Equal(fixes, want) {
   687  		t.Errorf("Repositories.GetAutomatedSecurityFixes returned #{fixes}, want #{want}")
   688  	}
   689  
   690  	const methodName = "GetAutomatedSecurityFixes"
   691  	testBadOptions(t, methodName, func() (err error) {
   692  		_, _, err = client.Repositories.GetAutomatedSecurityFixes(ctx, "\n", "\n")
   693  		return err
   694  	})
   695  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   696  		got, resp, err := client.Repositories.GetAutomatedSecurityFixes(ctx, "o", "r")
   697  		if got != nil {
   698  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   699  		}
   700  		return resp, err
   701  	})
   702  }
   703  
   704  func TestRepositoriesService_DisableAutomatedSecurityFixes(t *testing.T) {
   705  	client, mux, _, teardown := setup()
   706  	defer teardown()
   707  
   708  	mux.HandleFunc("/repos/o/r/automated-security-fixes", func(w http.ResponseWriter, r *http.Request) {
   709  		testMethod(t, r, "DELETE")
   710  
   711  		w.WriteHeader(http.StatusNoContent)
   712  	})
   713  
   714  	ctx := context.Background()
   715  	if _, err := client.Repositories.DisableAutomatedSecurityFixes(ctx, "o", "r"); err != nil {
   716  		t.Errorf("Repositories.DisableAutomatedSecurityFixes returned error: %v", err)
   717  	}
   718  }
   719  
   720  func TestRepositoriesService_ListContributors(t *testing.T) {
   721  	client, mux, _, teardown := setup()
   722  	defer teardown()
   723  
   724  	mux.HandleFunc("/repos/o/r/contributors", func(w http.ResponseWriter, r *http.Request) {
   725  		testMethod(t, r, "GET")
   726  		testFormValues(t, r, values{
   727  			"anon": "true",
   728  			"page": "2",
   729  		})
   730  		fmt.Fprint(w, `[{"contributions":42}]`)
   731  	})
   732  
   733  	opts := &ListContributorsOptions{Anon: "true", ListOptions: ListOptions{Page: 2}}
   734  	ctx := context.Background()
   735  	contributors, _, err := client.Repositories.ListContributors(ctx, "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 !cmp.Equal(contributors, want) {
   742  		t.Errorf("Repositories.ListContributors returned %+v, want %+v", contributors, want)
   743  	}
   744  
   745  	const methodName = "ListContributors"
   746  	testBadOptions(t, methodName, func() (err error) {
   747  		_, _, err = client.Repositories.ListContributors(ctx, "\n", "\n", opts)
   748  		return err
   749  	})
   750  
   751  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   752  		got, resp, err := client.Repositories.ListContributors(ctx, "o", "r", opts)
   753  		if got != nil {
   754  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   755  		}
   756  		return resp, err
   757  	})
   758  }
   759  
   760  func TestRepositoriesService_ListLanguages(t *testing.T) {
   761  	client, mux, _, teardown := setup()
   762  	defer teardown()
   763  
   764  	mux.HandleFunc("/repos/o/r/languages", func(w http.ResponseWriter, r *http.Request) {
   765  		testMethod(t, r, "GET")
   766  		fmt.Fprint(w, `{"go":1}`)
   767  	})
   768  
   769  	ctx := context.Background()
   770  	languages, _, err := client.Repositories.ListLanguages(ctx, "o", "r")
   771  	if err != nil {
   772  		t.Errorf("Repositories.ListLanguages returned error: %v", err)
   773  	}
   774  
   775  	want := map[string]int{"go": 1}
   776  	if !cmp.Equal(languages, want) {
   777  		t.Errorf("Repositories.ListLanguages returned %+v, want %+v", languages, want)
   778  	}
   779  
   780  	const methodName = "ListLanguages"
   781  	testBadOptions(t, methodName, func() (err error) {
   782  		_, _, err = client.Repositories.ListLanguages(ctx, "\n", "\n")
   783  		return err
   784  	})
   785  
   786  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   787  		got, resp, err := client.Repositories.ListLanguages(ctx, "o", "r")
   788  		if got != nil {
   789  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   790  		}
   791  		return resp, err
   792  	})
   793  }
   794  
   795  func TestRepositoriesService_ListTeams(t *testing.T) {
   796  	client, mux, _, teardown := setup()
   797  	defer teardown()
   798  
   799  	mux.HandleFunc("/repos/o/r/teams", func(w http.ResponseWriter, r *http.Request) {
   800  		testMethod(t, r, "GET")
   801  		testFormValues(t, r, values{"page": "2"})
   802  		fmt.Fprint(w, `[{"id":1}]`)
   803  	})
   804  
   805  	opt := &ListOptions{Page: 2}
   806  	ctx := context.Background()
   807  	teams, _, err := client.Repositories.ListTeams(ctx, "o", "r", opt)
   808  	if err != nil {
   809  		t.Errorf("Repositories.ListTeams returned error: %v", err)
   810  	}
   811  
   812  	want := []*Team{{ID: Int64(1)}}
   813  	if !cmp.Equal(teams, want) {
   814  		t.Errorf("Repositories.ListTeams returned %+v, want %+v", teams, want)
   815  	}
   816  
   817  	const methodName = "ListTeams"
   818  	testBadOptions(t, methodName, func() (err error) {
   819  		_, _, err = client.Repositories.ListTeams(ctx, "\n", "\n", opt)
   820  		return err
   821  	})
   822  
   823  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   824  		got, resp, err := client.Repositories.ListTeams(ctx, "o", "r", opt)
   825  		if got != nil {
   826  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   827  		}
   828  		return resp, err
   829  	})
   830  }
   831  
   832  func TestRepositoriesService_ListTags(t *testing.T) {
   833  	client, mux, _, teardown := setup()
   834  	defer teardown()
   835  
   836  	mux.HandleFunc("/repos/o/r/tags", func(w http.ResponseWriter, r *http.Request) {
   837  		testMethod(t, r, "GET")
   838  		testFormValues(t, r, values{"page": "2"})
   839  		fmt.Fprint(w, `[{"name":"n", "commit" : {"sha" : "s", "url" : "u"}, "zipball_url": "z", "tarball_url": "t"}]`)
   840  	})
   841  
   842  	opt := &ListOptions{Page: 2}
   843  	ctx := context.Background()
   844  	tags, _, err := client.Repositories.ListTags(ctx, "o", "r", opt)
   845  	if err != nil {
   846  		t.Errorf("Repositories.ListTags returned error: %v", err)
   847  	}
   848  
   849  	want := []*RepositoryTag{
   850  		{
   851  			Name: String("n"),
   852  			Commit: &Commit{
   853  				SHA: String("s"),
   854  				URL: String("u"),
   855  			},
   856  			ZipballURL: String("z"),
   857  			TarballURL: String("t"),
   858  		},
   859  	}
   860  	if !cmp.Equal(tags, want) {
   861  		t.Errorf("Repositories.ListTags returned %+v, want %+v", tags, want)
   862  	}
   863  
   864  	const methodName = "ListTags"
   865  	testBadOptions(t, methodName, func() (err error) {
   866  		_, _, err = client.Repositories.ListTags(ctx, "\n", "\n", opt)
   867  		return err
   868  	})
   869  
   870  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   871  		got, resp, err := client.Repositories.ListTags(ctx, "o", "r", opt)
   872  		if got != nil {
   873  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   874  		}
   875  		return resp, err
   876  	})
   877  }
   878  
   879  func TestRepositoriesService_ListBranches(t *testing.T) {
   880  	client, mux, _, teardown := setup()
   881  	defer teardown()
   882  
   883  	mux.HandleFunc("/repos/o/r/branches", func(w http.ResponseWriter, r *http.Request) {
   884  		testMethod(t, r, "GET")
   885  		testFormValues(t, r, values{"page": "2"})
   886  		fmt.Fprint(w, `[{"name":"master", "commit" : {"sha" : "a57781", "url" : "https://api.github.com/repos/o/r/commits/a57781"}}]`)
   887  	})
   888  
   889  	opt := &BranchListOptions{
   890  		Protected:   nil,
   891  		ListOptions: ListOptions{Page: 2},
   892  	}
   893  	ctx := context.Background()
   894  	branches, _, err := client.Repositories.ListBranches(ctx, "o", "r", opt)
   895  	if err != nil {
   896  		t.Errorf("Repositories.ListBranches returned error: %v", err)
   897  	}
   898  
   899  	want := []*Branch{{Name: String("master"), Commit: &RepositoryCommit{SHA: String("a57781"), URL: String("https://api.github.com/repos/o/r/commits/a57781")}}}
   900  	if !cmp.Equal(branches, want) {
   901  		t.Errorf("Repositories.ListBranches returned %+v, want %+v", branches, want)
   902  	}
   903  
   904  	const methodName = "ListBranches"
   905  	testBadOptions(t, methodName, func() (err error) {
   906  		_, _, err = client.Repositories.ListBranches(ctx, "\n", "\n", opt)
   907  		return err
   908  	})
   909  
   910  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   911  		got, resp, err := client.Repositories.ListBranches(ctx, "o", "r", opt)
   912  		if got != nil {
   913  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   914  		}
   915  		return resp, err
   916  	})
   917  }
   918  
   919  func TestRepositoriesService_GetBranch(t *testing.T) {
   920  	client, mux, _, teardown := setup()
   921  	defer teardown()
   922  
   923  	tests := []struct {
   924  		branch  string
   925  		urlPath string
   926  	}{
   927  		{branch: "b", urlPath: "/repos/o/r/branches/b"},
   928  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%"},
   929  	}
   930  
   931  	for _, test := range tests {
   932  		mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
   933  			testMethod(t, r, "GET")
   934  			fmt.Fprint(w, `{"name":"n", "commit":{"sha":"s","commit":{"message":"m"}}, "protected":true, "protection":{"required_status_checks":{"contexts":["c"]}}}`)
   935  		})
   936  
   937  		ctx := context.Background()
   938  		branch, _, err := client.Repositories.GetBranch(ctx, "o", "r", test.branch, 0)
   939  		if err != nil {
   940  			t.Errorf("Repositories.GetBranch returned error: %v", err)
   941  		}
   942  
   943  		want := &Branch{
   944  			Name: String("n"),
   945  			Commit: &RepositoryCommit{
   946  				SHA: String("s"),
   947  				Commit: &Commit{
   948  					Message: String("m"),
   949  				},
   950  			},
   951  			Protected: Bool(true),
   952  			Protection: &Protection{
   953  				RequiredStatusChecks: &RequiredStatusChecks{
   954  					Contexts: &[]string{"c"},
   955  				},
   956  			},
   957  		}
   958  
   959  		if !cmp.Equal(branch, want) {
   960  			t.Errorf("Repositories.GetBranch returned %+v, want %+v", branch, want)
   961  		}
   962  
   963  		const methodName = "GetBranch"
   964  		testBadOptions(t, methodName, func() (err error) {
   965  			_, _, err = client.Repositories.GetBranch(ctx, "\n", "\n", "\n", 0)
   966  			return err
   967  		})
   968  	}
   969  }
   970  
   971  func TestRepositoriesService_GetBranch_BadJSONResponse(t *testing.T) {
   972  	tests := []struct {
   973  		branch  string
   974  		urlPath string
   975  	}{
   976  		{branch: "b", urlPath: "/repos/o/r/branches/b"},
   977  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%"},
   978  	}
   979  
   980  	for _, test := range tests {
   981  		t.Run(test.branch, func(t *testing.T) {
   982  			client, mux, _, teardown := setup()
   983  			defer teardown()
   984  
   985  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
   986  				testMethod(t, r, "GET")
   987  				fmt.Fprint(w, `{"name":"n", "commit":{"sha":...truncated`)
   988  			})
   989  
   990  			ctx := context.Background()
   991  			if _, _, err := client.Repositories.GetBranch(ctx, "o", "r", test.branch, 0); err == nil {
   992  				t.Error("Repositories.GetBranch returned no error; wanted JSON error")
   993  			}
   994  		})
   995  	}
   996  }
   997  
   998  func TestRepositoriesService_GetBranch_StatusMovedPermanently_followRedirects(t *testing.T) {
   999  	client, mux, serverURL, teardown := setup()
  1000  	defer teardown()
  1001  
  1002  	mux.HandleFunc("/repos/o/r/branches/b", func(w http.ResponseWriter, r *http.Request) {
  1003  		testMethod(t, r, "GET")
  1004  		redirectURL, _ := url.Parse(serverURL + baseURLPath + "/repos/o/r/branches/br")
  1005  		http.Redirect(w, r, redirectURL.String(), http.StatusMovedPermanently)
  1006  	})
  1007  	mux.HandleFunc("/repos/o/r/branches/br", func(w http.ResponseWriter, r *http.Request) {
  1008  		testMethod(t, r, "GET")
  1009  		fmt.Fprint(w, `{"name":"n", "commit":{"sha":"s","commit":{"message":"m"}}, "protected":true, "protection":{"required_status_checks":{"contexts":["c"]}}}`)
  1010  	})
  1011  	ctx := context.Background()
  1012  	branch, resp, err := client.Repositories.GetBranch(ctx, "o", "r", "b", 1)
  1013  	if err != nil {
  1014  		t.Errorf("Repositories.GetBranch returned error: %v", err)
  1015  	}
  1016  	if resp.StatusCode != http.StatusOK {
  1017  		t.Errorf("Repositories.GetBranch returned status: %d, want %d", resp.StatusCode, http.StatusOK)
  1018  	}
  1019  
  1020  	want := &Branch{
  1021  		Name: String("n"),
  1022  		Commit: &RepositoryCommit{
  1023  			SHA: String("s"),
  1024  			Commit: &Commit{
  1025  				Message: String("m"),
  1026  			},
  1027  		},
  1028  		Protected: Bool(true),
  1029  		Protection: &Protection{
  1030  			RequiredStatusChecks: &RequiredStatusChecks{
  1031  				Contexts: &[]string{"c"},
  1032  			},
  1033  		},
  1034  	}
  1035  	if !cmp.Equal(branch, want) {
  1036  		t.Errorf("Repositories.GetBranch returned %+v, want %+v", branch, want)
  1037  	}
  1038  }
  1039  
  1040  func TestRepositoriesService_GetBranch_notFound(t *testing.T) {
  1041  	tests := []struct {
  1042  		branch  string
  1043  		urlPath string
  1044  	}{
  1045  		{branch: "b", urlPath: "/repos/o/r/branches/b"},
  1046  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat-branch-50%"},
  1047  	}
  1048  
  1049  	for _, test := range tests {
  1050  		t.Run(test.branch, func(t *testing.T) {
  1051  			client, mux, _, teardown := setup()
  1052  			defer teardown()
  1053  
  1054  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  1055  				testMethod(t, r, "GET")
  1056  				http.Error(w, "branch not found", http.StatusNotFound)
  1057  			})
  1058  			ctx := context.Background()
  1059  			_, resp, err := client.Repositories.GetBranch(ctx, "o", "r", test.branch, 1)
  1060  			if err == nil {
  1061  				t.Error("Repositories.GetBranch returned error: nil")
  1062  			}
  1063  			if resp.StatusCode != http.StatusNotFound {
  1064  				t.Errorf("Repositories.GetBranch returned status: %d, want %d", resp.StatusCode, http.StatusNotFound)
  1065  			}
  1066  
  1067  			// Add custom round tripper
  1068  			client.client.Transport = roundTripperFunc(func(r *http.Request) (*http.Response, error) {
  1069  				return nil, errors.New("failed to get branch")
  1070  			})
  1071  
  1072  			const methodName = "GetBranch"
  1073  			testBadOptions(t, methodName, func() (err error) {
  1074  				_, _, err = client.Repositories.GetBranch(ctx, "\n", "\n", "\n", 1)
  1075  				return err
  1076  			})
  1077  		})
  1078  	}
  1079  }
  1080  
  1081  func TestRepositoriesService_RenameBranch(t *testing.T) {
  1082  	tests := []struct {
  1083  		branch  string
  1084  		urlPath string
  1085  	}{
  1086  		{branch: "b", urlPath: "/repos/o/r/branches/b/rename"},
  1087  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/rename"},
  1088  	}
  1089  
  1090  	for _, test := range tests {
  1091  		t.Run(test.branch, func(t *testing.T) {
  1092  			client, mux, _, teardown := setup()
  1093  			defer teardown()
  1094  
  1095  			renameBranchReq := "nn"
  1096  
  1097  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  1098  				v := new(renameBranchRequest)
  1099  				assertNilError(t, json.NewDecoder(r.Body).Decode(v))
  1100  
  1101  				testMethod(t, r, "POST")
  1102  				want := &renameBranchRequest{NewName: renameBranchReq}
  1103  				if !cmp.Equal(v, want) {
  1104  					t.Errorf("Request body = %+v, want %+v", v, want)
  1105  				}
  1106  
  1107  				fmt.Fprint(w, `{"protected":true,"name":"nn"}`)
  1108  			})
  1109  
  1110  			ctx := context.Background()
  1111  			got, _, err := client.Repositories.RenameBranch(ctx, "o", "r", test.branch, renameBranchReq)
  1112  			if err != nil {
  1113  				t.Errorf("Repositories.RenameBranch returned error: %v", err)
  1114  			}
  1115  
  1116  			want := &Branch{Name: String("nn"), Protected: Bool(true)}
  1117  			if !cmp.Equal(got, want) {
  1118  				t.Errorf("Repositories.RenameBranch returned %+v, want %+v", got, want)
  1119  			}
  1120  
  1121  			const methodName = "RenameBranch"
  1122  			testBadOptions(t, methodName, func() (err error) {
  1123  				_, _, err = client.Repositories.RenameBranch(ctx, "\n", "\n", "\n", renameBranchReq)
  1124  				return err
  1125  			})
  1126  
  1127  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  1128  				got, resp, err := client.Repositories.RenameBranch(ctx, "o", "r", test.branch, renameBranchReq)
  1129  				if got != nil {
  1130  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  1131  				}
  1132  				return resp, err
  1133  			})
  1134  		})
  1135  	}
  1136  }
  1137  
  1138  func TestRepositoriesService_GetBranchProtection(t *testing.T) {
  1139  	tests := []struct {
  1140  		branch               string
  1141  		urlPath              string
  1142  		enforceAdminsURLPath string
  1143  	}{
  1144  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection", enforceAdminsURLPath: "/repos/o/r/branches/b/protection/enforce_admins"},
  1145  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection", enforceAdminsURLPath: "/repos/o/r/branches/feat/branch-50%/protection/enforce_admins"},
  1146  	}
  1147  
  1148  	for _, test := range tests {
  1149  		t.Run(test.branch, func(t *testing.T) {
  1150  			client, mux, _, teardown := setup()
  1151  			defer teardown()
  1152  
  1153  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  1154  				testMethod(t, r, "GET")
  1155  				// TODO: remove custom Accept header when this API fully launches
  1156  				testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  1157  				fmt.Fprintf(w, `{
  1158  						"required_status_checks":{
  1159  							"strict":true,
  1160  							"contexts":["continuous-integration"],
  1161  							"checks": [
  1162  								{
  1163  									"context": "continuous-integration",
  1164  									"app_id": null
  1165  								}
  1166  							]
  1167  						},
  1168  						"required_pull_request_reviews":{
  1169  							"dismissal_restrictions":{
  1170  								"users":[{
  1171  									"id":3,
  1172  									"login":"u"
  1173  								}],
  1174  								"teams":[{
  1175  									"id":4,
  1176  									"slug":"t"
  1177  								}],
  1178  								"apps":[{
  1179  									"id":5,
  1180  									"slug":"a"
  1181  								}]
  1182  							},
  1183  							"dismiss_stale_reviews":true,
  1184  							"require_code_owner_reviews":true,
  1185  							"require_last_push_approval":false,
  1186  							"required_approving_review_count":1
  1187  							},
  1188  							"enforce_admins":{
  1189  								"url":"%s",
  1190  								"enabled":true
  1191  							},
  1192  							"restrictions":{
  1193  								"users":[{"id":1,"login":"u"}],
  1194  								"teams":[{"id":2,"slug":"t"}],
  1195  								"apps":[{"id":3,"slug":"a"}]
  1196  							},
  1197  							"required_conversation_resolution": {
  1198  								"enabled": true
  1199  							},
  1200  							"block_creations": {
  1201  								"enabled": false
  1202  							},
  1203  							"lock_branch": {
  1204  								"enabled": false
  1205  							},
  1206  							"allow_fork_syncing": {
  1207  								"enabled": false
  1208  							}
  1209  						}`, test.enforceAdminsURLPath)
  1210  			})
  1211  
  1212  			ctx := context.Background()
  1213  			protection, _, err := client.Repositories.GetBranchProtection(ctx, "o", "r", test.branch)
  1214  			if err != nil {
  1215  				t.Errorf("Repositories.GetBranchProtection returned error: %v", err)
  1216  			}
  1217  
  1218  			want := &Protection{
  1219  				RequiredStatusChecks: &RequiredStatusChecks{
  1220  					Strict:   true,
  1221  					Contexts: &[]string{"continuous-integration"},
  1222  					Checks: &[]*RequiredStatusCheck{
  1223  						{
  1224  							Context: "continuous-integration",
  1225  						},
  1226  					},
  1227  				},
  1228  				RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
  1229  					DismissStaleReviews: true,
  1230  					DismissalRestrictions: &DismissalRestrictions{
  1231  						Users: []*User{
  1232  							{Login: String("u"), ID: Int64(3)},
  1233  						},
  1234  						Teams: []*Team{
  1235  							{Slug: String("t"), ID: Int64(4)},
  1236  						},
  1237  						Apps: []*App{
  1238  							{Slug: String("a"), ID: Int64(5)},
  1239  						},
  1240  					},
  1241  					RequireCodeOwnerReviews:      true,
  1242  					RequiredApprovingReviewCount: 1,
  1243  					RequireLastPushApproval:      false,
  1244  				},
  1245  				EnforceAdmins: &AdminEnforcement{
  1246  					URL:     String(test.enforceAdminsURLPath),
  1247  					Enabled: true,
  1248  				},
  1249  				Restrictions: &BranchRestrictions{
  1250  					Users: []*User{
  1251  						{Login: String("u"), ID: Int64(1)},
  1252  					},
  1253  					Teams: []*Team{
  1254  						{Slug: String("t"), ID: Int64(2)},
  1255  					},
  1256  					Apps: []*App{
  1257  						{Slug: String("a"), ID: Int64(3)},
  1258  					},
  1259  				},
  1260  				RequiredConversationResolution: &RequiredConversationResolution{
  1261  					Enabled: true,
  1262  				},
  1263  				BlockCreations: &BlockCreations{
  1264  					Enabled: Bool(false),
  1265  				},
  1266  				LockBranch: &LockBranch{
  1267  					Enabled: Bool(false),
  1268  				},
  1269  				AllowForkSyncing: &AllowForkSyncing{
  1270  					Enabled: Bool(false),
  1271  				},
  1272  			}
  1273  			if !cmp.Equal(protection, want) {
  1274  				t.Errorf("Repositories.GetBranchProtection returned %+v, want %+v", protection, want)
  1275  			}
  1276  
  1277  			const methodName = "GetBranchProtection"
  1278  			testBadOptions(t, methodName, func() (err error) {
  1279  				_, _, err = client.Repositories.GetBranchProtection(ctx, "\n", "\n", "\n")
  1280  				return err
  1281  			})
  1282  
  1283  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  1284  				got, resp, err := client.Repositories.GetBranchProtection(ctx, "o", "r", test.branch)
  1285  				if got != nil {
  1286  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  1287  				}
  1288  				return resp, err
  1289  			})
  1290  		})
  1291  	}
  1292  }
  1293  
  1294  func TestRepositoriesService_GetBranchProtection_noDismissalRestrictions(t *testing.T) {
  1295  	client, mux, _, teardown := setup()
  1296  	defer teardown()
  1297  
  1298  	tests := []struct {
  1299  		branch               string
  1300  		urlPath              string
  1301  		enforceAdminsURLPath string
  1302  	}{
  1303  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection", enforceAdminsURLPath: "/repos/o/r/branches/b/protection/enforce_admins"},
  1304  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection", enforceAdminsURLPath: "/repos/o/r/branches/feat/branch-50%/protection/enforce_admins"},
  1305  	}
  1306  
  1307  	for _, test := range tests {
  1308  		mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  1309  			testMethod(t, r, "GET")
  1310  			// TODO: remove custom Accept header when this API fully launches
  1311  			testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  1312  			fmt.Fprintf(w, `{
  1313  					"required_status_checks":{
  1314  						"strict":true,
  1315  						"contexts":["continuous-integration"],
  1316  						"checks": [
  1317  							{
  1318  								"context": "continuous-integration",
  1319  								"app_id": null
  1320  							}
  1321  						]
  1322  					},
  1323  					"required_pull_request_reviews":{
  1324  						"dismiss_stale_reviews":true,
  1325  						"require_code_owner_reviews":true,
  1326  						"required_approving_review_count":1
  1327  						},
  1328  						"enforce_admins":{
  1329  							"url":"%s",
  1330  							"enabled":true
  1331  						},
  1332  						"restrictions":{
  1333  							"users":[{"id":1,"login":"u"}],
  1334  							"teams":[{"id":2,"slug":"t"}]
  1335  						}
  1336  					}`, test.enforceAdminsURLPath)
  1337  		})
  1338  
  1339  		ctx := context.Background()
  1340  		protection, _, err := client.Repositories.GetBranchProtection(ctx, "o", "r", test.branch)
  1341  		if err != nil {
  1342  			t.Errorf("Repositories.GetBranchProtection returned error: %v", err)
  1343  		}
  1344  
  1345  		want := &Protection{
  1346  			RequiredStatusChecks: &RequiredStatusChecks{
  1347  				Strict:   true,
  1348  				Contexts: &[]string{"continuous-integration"},
  1349  				Checks: &[]*RequiredStatusCheck{
  1350  					{
  1351  						Context: "continuous-integration",
  1352  					},
  1353  				},
  1354  			},
  1355  			RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
  1356  				DismissStaleReviews:          true,
  1357  				DismissalRestrictions:        nil,
  1358  				RequireCodeOwnerReviews:      true,
  1359  				RequiredApprovingReviewCount: 1,
  1360  			},
  1361  			EnforceAdmins: &AdminEnforcement{
  1362  				URL:     String(test.enforceAdminsURLPath),
  1363  				Enabled: true,
  1364  			},
  1365  			Restrictions: &BranchRestrictions{
  1366  				Users: []*User{
  1367  					{Login: String("u"), ID: Int64(1)},
  1368  				},
  1369  				Teams: []*Team{
  1370  					{Slug: String("t"), ID: Int64(2)},
  1371  				},
  1372  			},
  1373  		}
  1374  		if !cmp.Equal(protection, want) {
  1375  			t.Errorf("Repositories.GetBranchProtection returned %+v, want %+v", protection, want)
  1376  		}
  1377  	}
  1378  }
  1379  
  1380  func TestRepositoriesService_GetBranchProtection_branchNotProtected(t *testing.T) {
  1381  	tests := []struct {
  1382  		branch  string
  1383  		urlPath string
  1384  	}{
  1385  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection"},
  1386  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection"},
  1387  	}
  1388  
  1389  	for _, test := range tests {
  1390  		t.Run(test.branch, func(t *testing.T) {
  1391  			client, mux, _, teardown := setup()
  1392  			defer teardown()
  1393  
  1394  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  1395  				testMethod(t, r, "GET")
  1396  
  1397  				w.WriteHeader(http.StatusBadRequest)
  1398  				fmt.Fprintf(w, `{
  1399  					"message": %q,
  1400  					"documentation_url": "https://docs.github.com/rest/repos#get-branch-protection"
  1401  					}`, githubBranchNotProtected)
  1402  			})
  1403  
  1404  			ctx := context.Background()
  1405  			protection, _, err := client.Repositories.GetBranchProtection(ctx, "o", "r", test.branch)
  1406  
  1407  			if protection != nil {
  1408  				t.Errorf("Repositories.GetBranchProtection returned non-nil protection data")
  1409  			}
  1410  
  1411  			if err != ErrBranchNotProtected {
  1412  				t.Errorf("Repositories.GetBranchProtection returned an invalid error: %v", err)
  1413  			}
  1414  		})
  1415  	}
  1416  }
  1417  
  1418  func TestRepositoriesService_UpdateBranchProtection_Contexts(t *testing.T) {
  1419  	tests := []struct {
  1420  		branch  string
  1421  		urlPath string
  1422  	}{
  1423  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection"},
  1424  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection"},
  1425  	}
  1426  
  1427  	for _, test := range tests {
  1428  		t.Run(test.branch, func(t *testing.T) {
  1429  			client, mux, _, teardown := setup()
  1430  			defer teardown()
  1431  
  1432  			input := &ProtectionRequest{
  1433  				RequiredStatusChecks: &RequiredStatusChecks{
  1434  					Strict:   true,
  1435  					Contexts: &[]string{"continuous-integration"},
  1436  				},
  1437  				RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{
  1438  					DismissStaleReviews: true,
  1439  					DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
  1440  						Users: &[]string{"uu"},
  1441  						Teams: &[]string{"tt"},
  1442  						Apps:  &[]string{"aa"},
  1443  					},
  1444  					BypassPullRequestAllowancesRequest: &BypassPullRequestAllowancesRequest{
  1445  						Users: []string{"uuu"},
  1446  						Teams: []string{"ttt"},
  1447  						Apps:  []string{"aaa"},
  1448  					},
  1449  				},
  1450  				Restrictions: &BranchRestrictionsRequest{
  1451  					Users: []string{"u"},
  1452  					Teams: []string{"t"},
  1453  					Apps:  []string{"a"},
  1454  				},
  1455  				BlockCreations:   Bool(true),
  1456  				LockBranch:       Bool(true),
  1457  				AllowForkSyncing: Bool(true),
  1458  			}
  1459  
  1460  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  1461  				v := new(ProtectionRequest)
  1462  				assertNilError(t, json.NewDecoder(r.Body).Decode(v))
  1463  
  1464  				testMethod(t, r, "PUT")
  1465  				if !cmp.Equal(v, input) {
  1466  					t.Errorf("Request body = %+v, want %+v", v, input)
  1467  				}
  1468  
  1469  				// TODO: remove custom Accept header when this API fully launches
  1470  				testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  1471  				fmt.Fprintf(w, `{
  1472  					"required_status_checks":{
  1473  						"strict":true,
  1474  						"contexts":["continuous-integration"],
  1475  						"checks": [
  1476  							{
  1477  								"context": "continuous-integration",
  1478  								"app_id": null
  1479  							}
  1480  						]
  1481  					},
  1482  					"required_pull_request_reviews":{
  1483  						"dismissal_restrictions":{
  1484  							"users":[{
  1485  								"id":3,
  1486  								"login":"uu"
  1487  							}],
  1488  							"teams":[{
  1489  								"id":4,
  1490  								"slug":"tt"
  1491  							}],
  1492  							"apps":[{
  1493  								"id":5,
  1494  								"slug":"aa"
  1495  							}]
  1496  						},
  1497  						"dismiss_stale_reviews":true,
  1498  						"require_code_owner_reviews":true,
  1499  						"bypass_pull_request_allowances": {
  1500  							"users":[{"id":10,"login":"uuu"}],
  1501  							"teams":[{"id":20,"slug":"ttt"}],
  1502  							"apps":[{"id":30,"slug":"aaa"}]
  1503  						}
  1504  					},
  1505  					"restrictions":{
  1506  						"users":[{"id":1,"login":"u"}],
  1507  						"teams":[{"id":2,"slug":"t"}],
  1508  						"apps":[{"id":3,"slug":"a"}]
  1509  					},
  1510  					"block_creations": {
  1511  						"enabled": true
  1512  					},
  1513  					"lock_branch": {
  1514  						"enabled": true
  1515  					},
  1516  					"allow_fork_syncing": {
  1517  						"enabled": true
  1518  					}
  1519  				}`)
  1520  			})
  1521  
  1522  			ctx := context.Background()
  1523  			protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input)
  1524  			if err != nil {
  1525  				t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err)
  1526  			}
  1527  
  1528  			want := &Protection{
  1529  				RequiredStatusChecks: &RequiredStatusChecks{
  1530  					Strict:   true,
  1531  					Contexts: &[]string{"continuous-integration"},
  1532  					Checks: &[]*RequiredStatusCheck{
  1533  						{
  1534  							Context: "continuous-integration",
  1535  						},
  1536  					},
  1537  				},
  1538  				RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
  1539  					DismissStaleReviews: true,
  1540  					DismissalRestrictions: &DismissalRestrictions{
  1541  						Users: []*User{
  1542  							{Login: String("uu"), ID: Int64(3)},
  1543  						},
  1544  						Teams: []*Team{
  1545  							{Slug: String("tt"), ID: Int64(4)},
  1546  						},
  1547  						Apps: []*App{
  1548  							{Slug: String("aa"), ID: Int64(5)},
  1549  						},
  1550  					},
  1551  					RequireCodeOwnerReviews: true,
  1552  					BypassPullRequestAllowances: &BypassPullRequestAllowances{
  1553  						Users: []*User{
  1554  							{Login: String("uuu"), ID: Int64(10)},
  1555  						},
  1556  						Teams: []*Team{
  1557  							{Slug: String("ttt"), ID: Int64(20)},
  1558  						},
  1559  						Apps: []*App{
  1560  							{Slug: String("aaa"), ID: Int64(30)},
  1561  						},
  1562  					},
  1563  				},
  1564  				Restrictions: &BranchRestrictions{
  1565  					Users: []*User{
  1566  						{Login: String("u"), ID: Int64(1)},
  1567  					},
  1568  					Teams: []*Team{
  1569  						{Slug: String("t"), ID: Int64(2)},
  1570  					},
  1571  					Apps: []*App{
  1572  						{Slug: String("a"), ID: Int64(3)},
  1573  					},
  1574  				},
  1575  				BlockCreations: &BlockCreations{
  1576  					Enabled: Bool(true),
  1577  				},
  1578  				LockBranch: &LockBranch{
  1579  					Enabled: Bool(true),
  1580  				},
  1581  				AllowForkSyncing: &AllowForkSyncing{
  1582  					Enabled: Bool(true),
  1583  				},
  1584  			}
  1585  			if !cmp.Equal(protection, want) {
  1586  				t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want)
  1587  			}
  1588  
  1589  			const methodName = "UpdateBranchProtection"
  1590  			testBadOptions(t, methodName, func() (err error) {
  1591  				_, _, err = client.Repositories.UpdateBranchProtection(ctx, "\n", "\n", "\n", input)
  1592  				return err
  1593  			})
  1594  
  1595  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  1596  				got, resp, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input)
  1597  				if got != nil {
  1598  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  1599  				}
  1600  				return resp, err
  1601  			})
  1602  		})
  1603  	}
  1604  }
  1605  
  1606  func TestRepositoriesService_UpdateBranchProtection_EmptyContexts(t *testing.T) {
  1607  	tests := []struct {
  1608  		branch  string
  1609  		urlPath string
  1610  	}{
  1611  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection"},
  1612  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection"},
  1613  	}
  1614  
  1615  	for _, test := range tests {
  1616  		t.Run(test.branch, func(t *testing.T) {
  1617  			client, mux, _, teardown := setup()
  1618  			defer teardown()
  1619  
  1620  			input := &ProtectionRequest{
  1621  				RequiredStatusChecks: &RequiredStatusChecks{
  1622  					Strict:   true,
  1623  					Contexts: &[]string{},
  1624  				},
  1625  				RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{
  1626  					DismissStaleReviews: true,
  1627  					DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
  1628  						Users: &[]string{"uu"},
  1629  						Teams: &[]string{"tt"},
  1630  						Apps:  &[]string{"aa"},
  1631  					},
  1632  					BypassPullRequestAllowancesRequest: &BypassPullRequestAllowancesRequest{
  1633  						Users: []string{"uuu"},
  1634  						Teams: []string{"ttt"},
  1635  						Apps:  []string{"aaa"},
  1636  					},
  1637  				},
  1638  				Restrictions: &BranchRestrictionsRequest{
  1639  					Users: []string{"u"},
  1640  					Teams: []string{"t"},
  1641  					Apps:  []string{"a"},
  1642  				},
  1643  				BlockCreations:   Bool(true),
  1644  				LockBranch:       Bool(true),
  1645  				AllowForkSyncing: Bool(true),
  1646  			}
  1647  
  1648  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  1649  				v := new(ProtectionRequest)
  1650  				assertNilError(t, json.NewDecoder(r.Body).Decode(v))
  1651  
  1652  				testMethod(t, r, "PUT")
  1653  				if !cmp.Equal(v, input) {
  1654  					t.Errorf("Request body = %+v, want %+v", v, input)
  1655  				}
  1656  
  1657  				// TODO: remove custom Accept header when this API fully launches
  1658  				testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  1659  				fmt.Fprintf(w, `{
  1660  					"required_status_checks":{
  1661  						"strict":true,
  1662  						"contexts":[],
  1663  						"checks": null
  1664  					},
  1665  					"required_pull_request_reviews":{
  1666  						"dismissal_restrictions":{
  1667  							"users":[{
  1668  								"id":3,
  1669  								"login":"uu"
  1670  							}],
  1671  							"teams":[{
  1672  								"id":4,
  1673  								"slug":"tt"
  1674  							}],
  1675  							"apps":[{
  1676  								"id":5,
  1677  								"slug":"aa"
  1678  							}]
  1679  						},
  1680  						"dismiss_stale_reviews":true,
  1681  						"require_code_owner_reviews":true,
  1682  						"bypass_pull_request_allowances": {
  1683  							"users":[{"id":10,"login":"uuu"}],
  1684  							"teams":[{"id":20,"slug":"ttt"}],
  1685  							"apps":[{"id":30,"slug":"aaa"}]
  1686  						}
  1687  					},
  1688  					"restrictions":{
  1689  						"users":[{"id":1,"login":"u"}],
  1690  						"teams":[{"id":2,"slug":"t"}],
  1691  						"apps":[{"id":3,"slug":"a"}]
  1692  					},
  1693  					"block_creations": {
  1694  						"enabled": true
  1695  					},
  1696  					"lock_branch": {
  1697  						"enabled": true
  1698  					},
  1699  					"allow_fork_syncing": {
  1700  						"enabled": true
  1701  					}
  1702  				}`)
  1703  			})
  1704  
  1705  			ctx := context.Background()
  1706  			protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input)
  1707  			if err != nil {
  1708  				t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err)
  1709  			}
  1710  
  1711  			want := &Protection{
  1712  				RequiredStatusChecks: &RequiredStatusChecks{
  1713  					Strict:   true,
  1714  					Contexts: &[]string{},
  1715  				},
  1716  				RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
  1717  					DismissStaleReviews: true,
  1718  					DismissalRestrictions: &DismissalRestrictions{
  1719  						Users: []*User{
  1720  							{Login: String("uu"), ID: Int64(3)},
  1721  						},
  1722  						Teams: []*Team{
  1723  							{Slug: String("tt"), ID: Int64(4)},
  1724  						},
  1725  						Apps: []*App{
  1726  							{Slug: String("aa"), ID: Int64(5)},
  1727  						},
  1728  					},
  1729  					RequireCodeOwnerReviews: true,
  1730  					BypassPullRequestAllowances: &BypassPullRequestAllowances{
  1731  						Users: []*User{
  1732  							{Login: String("uuu"), ID: Int64(10)},
  1733  						},
  1734  						Teams: []*Team{
  1735  							{Slug: String("ttt"), ID: Int64(20)},
  1736  						},
  1737  						Apps: []*App{
  1738  							{Slug: String("aaa"), ID: Int64(30)},
  1739  						},
  1740  					},
  1741  				},
  1742  				Restrictions: &BranchRestrictions{
  1743  					Users: []*User{
  1744  						{Login: String("u"), ID: Int64(1)},
  1745  					},
  1746  					Teams: []*Team{
  1747  						{Slug: String("t"), ID: Int64(2)},
  1748  					},
  1749  					Apps: []*App{
  1750  						{Slug: String("a"), ID: Int64(3)},
  1751  					},
  1752  				},
  1753  				BlockCreations: &BlockCreations{
  1754  					Enabled: Bool(true),
  1755  				},
  1756  				LockBranch: &LockBranch{
  1757  					Enabled: Bool(true),
  1758  				},
  1759  				AllowForkSyncing: &AllowForkSyncing{
  1760  					Enabled: Bool(true),
  1761  				},
  1762  			}
  1763  			if !cmp.Equal(protection, want) {
  1764  				t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want)
  1765  			}
  1766  
  1767  			const methodName = "UpdateBranchProtection"
  1768  			testBadOptions(t, methodName, func() (err error) {
  1769  				_, _, err = client.Repositories.UpdateBranchProtection(ctx, "\n", "\n", "\n", input)
  1770  				return err
  1771  			})
  1772  
  1773  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  1774  				got, resp, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input)
  1775  				if got != nil {
  1776  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  1777  				}
  1778  				return resp, err
  1779  			})
  1780  		})
  1781  	}
  1782  }
  1783  
  1784  func TestRepositoriesService_UpdateBranchProtection_Checks(t *testing.T) {
  1785  	tests := []struct {
  1786  		branch  string
  1787  		urlPath string
  1788  	}{
  1789  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection"},
  1790  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection"},
  1791  	}
  1792  
  1793  	for _, test := range tests {
  1794  		t.Run(test.branch, func(t *testing.T) {
  1795  			client, mux, _, teardown := setup()
  1796  			defer teardown()
  1797  
  1798  			input := &ProtectionRequest{
  1799  				RequiredStatusChecks: &RequiredStatusChecks{
  1800  					Strict: true,
  1801  					Checks: &[]*RequiredStatusCheck{
  1802  						{
  1803  							Context: "continuous-integration",
  1804  						},
  1805  					},
  1806  				},
  1807  				RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{
  1808  					DismissStaleReviews: true,
  1809  					DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
  1810  						Users: &[]string{"uu"},
  1811  						Teams: &[]string{"tt"},
  1812  						Apps:  &[]string{"aa"},
  1813  					},
  1814  					BypassPullRequestAllowancesRequest: &BypassPullRequestAllowancesRequest{
  1815  						Users: []string{"uuu"},
  1816  						Teams: []string{"ttt"},
  1817  						Apps:  []string{"aaa"},
  1818  					},
  1819  				},
  1820  				Restrictions: &BranchRestrictionsRequest{
  1821  					Users: []string{"u"},
  1822  					Teams: []string{"t"},
  1823  					Apps:  []string{"a"},
  1824  				},
  1825  			}
  1826  
  1827  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  1828  				v := new(ProtectionRequest)
  1829  				assertNilError(t, json.NewDecoder(r.Body).Decode(v))
  1830  
  1831  				testMethod(t, r, "PUT")
  1832  				if !cmp.Equal(v, input) {
  1833  					t.Errorf("Request body = %+v, want %+v", v, input)
  1834  				}
  1835  
  1836  				// TODO: remove custom Accept header when this API fully launches
  1837  				testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  1838  				fmt.Fprintf(w, `{
  1839  					"required_status_checks":{
  1840  						"strict":true,
  1841  						"contexts":["continuous-integration"],
  1842  						"checks": [
  1843  							{
  1844  								"context": "continuous-integration",
  1845  								"app_id": null
  1846  							}
  1847  						]
  1848  					},
  1849  					"required_pull_request_reviews":{
  1850  						"dismissal_restrictions":{
  1851  							"users":[{
  1852  								"id":3,
  1853  								"login":"uu"
  1854  							}],
  1855  							"teams":[{
  1856  								"id":4,
  1857  								"slug":"tt"
  1858  							}],
  1859  							"apps":[{
  1860  								"id":5,
  1861  								"slug":"aa"
  1862  							}]
  1863  						},
  1864  						"dismiss_stale_reviews":true,
  1865  						"require_code_owner_reviews":true,
  1866  						"bypass_pull_request_allowances": {
  1867  							"users":[{"id":10,"login":"uuu"}],
  1868  							"teams":[{"id":20,"slug":"ttt"}],
  1869  							"apps":[{"id":30,"slug":"aaa"}]
  1870  						}
  1871  					},
  1872  					"restrictions":{
  1873  						"users":[{"id":1,"login":"u"}],
  1874  						"teams":[{"id":2,"slug":"t"}],
  1875  						"apps":[{"id":3,"slug":"a"}]
  1876  					}
  1877  				}`)
  1878  			})
  1879  
  1880  			ctx := context.Background()
  1881  			protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input)
  1882  			if err != nil {
  1883  				t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err)
  1884  			}
  1885  
  1886  			want := &Protection{
  1887  				RequiredStatusChecks: &RequiredStatusChecks{
  1888  					Strict:   true,
  1889  					Contexts: &[]string{"continuous-integration"},
  1890  					Checks: &[]*RequiredStatusCheck{
  1891  						{
  1892  							Context: "continuous-integration",
  1893  						},
  1894  					},
  1895  				},
  1896  				RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
  1897  					DismissStaleReviews: true,
  1898  					DismissalRestrictions: &DismissalRestrictions{
  1899  						Users: []*User{
  1900  							{Login: String("uu"), ID: Int64(3)},
  1901  						},
  1902  						Teams: []*Team{
  1903  							{Slug: String("tt"), ID: Int64(4)},
  1904  						},
  1905  						Apps: []*App{
  1906  							{Slug: String("aa"), ID: Int64(5)},
  1907  						},
  1908  					},
  1909  					RequireCodeOwnerReviews: true,
  1910  					BypassPullRequestAllowances: &BypassPullRequestAllowances{
  1911  						Users: []*User{
  1912  							{Login: String("uuu"), ID: Int64(10)},
  1913  						},
  1914  						Teams: []*Team{
  1915  							{Slug: String("ttt"), ID: Int64(20)},
  1916  						},
  1917  						Apps: []*App{
  1918  							{Slug: String("aaa"), ID: Int64(30)},
  1919  						},
  1920  					},
  1921  				},
  1922  				Restrictions: &BranchRestrictions{
  1923  					Users: []*User{
  1924  						{Login: String("u"), ID: Int64(1)},
  1925  					},
  1926  					Teams: []*Team{
  1927  						{Slug: String("t"), ID: Int64(2)},
  1928  					},
  1929  					Apps: []*App{
  1930  						{Slug: String("a"), ID: Int64(3)},
  1931  					},
  1932  				},
  1933  			}
  1934  			if !cmp.Equal(protection, want) {
  1935  				t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want)
  1936  			}
  1937  		})
  1938  	}
  1939  }
  1940  
  1941  func TestRepositoriesService_UpdateBranchProtection_EmptyChecks(t *testing.T) {
  1942  	tests := []struct {
  1943  		branch  string
  1944  		urlPath string
  1945  	}{
  1946  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection"},
  1947  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection"},
  1948  	}
  1949  
  1950  	for _, test := range tests {
  1951  		t.Run(test.branch, func(t *testing.T) {
  1952  			client, mux, _, teardown := setup()
  1953  			defer teardown()
  1954  
  1955  			input := &ProtectionRequest{
  1956  				RequiredStatusChecks: &RequiredStatusChecks{
  1957  					Strict: true,
  1958  					Checks: &[]*RequiredStatusCheck{},
  1959  				},
  1960  				RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{
  1961  					DismissStaleReviews: true,
  1962  					DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
  1963  						Users: &[]string{"uu"},
  1964  						Teams: &[]string{"tt"},
  1965  						Apps:  &[]string{"aa"},
  1966  					},
  1967  					BypassPullRequestAllowancesRequest: &BypassPullRequestAllowancesRequest{
  1968  						Users: []string{"uuu"},
  1969  						Teams: []string{"ttt"},
  1970  						Apps:  []string{"aaa"},
  1971  					},
  1972  				},
  1973  				Restrictions: &BranchRestrictionsRequest{
  1974  					Users: []string{"u"},
  1975  					Teams: []string{"t"},
  1976  					Apps:  []string{"a"},
  1977  				},
  1978  			}
  1979  
  1980  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  1981  				v := new(ProtectionRequest)
  1982  				assertNilError(t, json.NewDecoder(r.Body).Decode(v))
  1983  
  1984  				testMethod(t, r, "PUT")
  1985  				if !cmp.Equal(v, input) {
  1986  					t.Errorf("Request body = %+v, want %+v", v, input)
  1987  				}
  1988  
  1989  				// TODO: remove custom Accept header when this API fully launches
  1990  				testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  1991  				fmt.Fprintf(w, `{
  1992  					"required_status_checks":{
  1993  						"strict":true,
  1994  						"contexts":null,
  1995  						"checks": []
  1996  					},
  1997  					"required_pull_request_reviews":{
  1998  						"dismissal_restrictions":{
  1999  							"users":[{
  2000  								"id":3,
  2001  								"login":"uu"
  2002  							}],
  2003  							"teams":[{
  2004  								"id":4,
  2005  								"slug":"tt"
  2006  							}],
  2007  							"apps":[{
  2008  								"id":5,
  2009  								"slug":"aa"
  2010  							}]
  2011  						},
  2012  						"dismiss_stale_reviews":true,
  2013  						"require_code_owner_reviews":true,
  2014  						"bypass_pull_request_allowances": {
  2015  							"users":[{"id":10,"login":"uuu"}],
  2016  							"teams":[{"id":20,"slug":"ttt"}],
  2017  							"apps":[{"id":30,"slug":"aaa"}]
  2018  						}
  2019  					},
  2020  					"restrictions":{
  2021  						"users":[{"id":1,"login":"u"}],
  2022  						"teams":[{"id":2,"slug":"t"}],
  2023  						"apps":[{"id":3,"slug":"a"}]
  2024  					}
  2025  				}`)
  2026  			})
  2027  
  2028  			ctx := context.Background()
  2029  			protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input)
  2030  			if err != nil {
  2031  				t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err)
  2032  			}
  2033  
  2034  			want := &Protection{
  2035  				RequiredStatusChecks: &RequiredStatusChecks{
  2036  					Strict: true,
  2037  					Checks: &[]*RequiredStatusCheck{},
  2038  				},
  2039  				RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
  2040  					DismissStaleReviews: true,
  2041  					DismissalRestrictions: &DismissalRestrictions{
  2042  						Users: []*User{
  2043  							{Login: String("uu"), ID: Int64(3)},
  2044  						},
  2045  						Teams: []*Team{
  2046  							{Slug: String("tt"), ID: Int64(4)},
  2047  						},
  2048  						Apps: []*App{
  2049  							{Slug: String("aa"), ID: Int64(5)},
  2050  						},
  2051  					},
  2052  					RequireCodeOwnerReviews: true,
  2053  					BypassPullRequestAllowances: &BypassPullRequestAllowances{
  2054  						Users: []*User{
  2055  							{Login: String("uuu"), ID: Int64(10)},
  2056  						},
  2057  						Teams: []*Team{
  2058  							{Slug: String("ttt"), ID: Int64(20)},
  2059  						},
  2060  						Apps: []*App{
  2061  							{Slug: String("aaa"), ID: Int64(30)},
  2062  						},
  2063  					},
  2064  				},
  2065  				Restrictions: &BranchRestrictions{
  2066  					Users: []*User{
  2067  						{Login: String("u"), ID: Int64(1)},
  2068  					},
  2069  					Teams: []*Team{
  2070  						{Slug: String("t"), ID: Int64(2)},
  2071  					},
  2072  					Apps: []*App{
  2073  						{Slug: String("a"), ID: Int64(3)},
  2074  					},
  2075  				},
  2076  			}
  2077  			if !cmp.Equal(protection, want) {
  2078  				t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want)
  2079  			}
  2080  		})
  2081  	}
  2082  }
  2083  
  2084  func TestRepositoriesService_UpdateBranchProtection_StrictNoChecks(t *testing.T) {
  2085  	tests := []struct {
  2086  		branch  string
  2087  		urlPath string
  2088  	}{
  2089  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection"},
  2090  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection"},
  2091  	}
  2092  
  2093  	for _, test := range tests {
  2094  		t.Run(test.branch, func(t *testing.T) {
  2095  			client, mux, _, teardown := setup()
  2096  			defer teardown()
  2097  
  2098  			input := &ProtectionRequest{
  2099  				RequiredStatusChecks: &RequiredStatusChecks{
  2100  					Strict: true,
  2101  				},
  2102  				RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{
  2103  					DismissStaleReviews: true,
  2104  					DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
  2105  						Users: &[]string{"uu"},
  2106  						Teams: &[]string{"tt"},
  2107  						Apps:  &[]string{"aa"},
  2108  					},
  2109  					BypassPullRequestAllowancesRequest: &BypassPullRequestAllowancesRequest{
  2110  						Users: []string{"uuu"},
  2111  						Teams: []string{"ttt"},
  2112  						Apps:  []string{"aaa"},
  2113  					},
  2114  				},
  2115  				Restrictions: &BranchRestrictionsRequest{
  2116  					Users: []string{"u"},
  2117  					Teams: []string{"t"},
  2118  					Apps:  []string{"a"},
  2119  				},
  2120  			}
  2121  
  2122  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  2123  				v := new(ProtectionRequest)
  2124  				assertNilError(t, json.NewDecoder(r.Body).Decode(v))
  2125  
  2126  				testMethod(t, r, "PUT")
  2127  				if !cmp.Equal(v, input) {
  2128  					t.Errorf("Request body = %+v, want %+v", v, input)
  2129  				}
  2130  
  2131  				// TODO: remove custom Accept header when this API fully launches
  2132  				testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  2133  				fmt.Fprintf(w, `{
  2134  					"required_status_checks":{
  2135  						"strict":true,
  2136  						"contexts":[]
  2137  					},
  2138  					"required_pull_request_reviews":{
  2139  						"dismissal_restrictions":{
  2140  							"users":[{
  2141  								"id":3,
  2142  								"login":"uu"
  2143  							}],
  2144  							"teams":[{
  2145  								"id":4,
  2146  								"slug":"tt"
  2147  							}],
  2148  							"apps":[{
  2149  								"id":5,
  2150  								"slug":"aa"
  2151  							}]
  2152  						},
  2153  						"dismiss_stale_reviews":true,
  2154  						"require_code_owner_reviews":true,
  2155  						"require_last_push_approval":false,
  2156  						"bypass_pull_request_allowances": {
  2157  							"users":[{"id":10,"login":"uuu"}],
  2158  							"teams":[{"id":20,"slug":"ttt"}],
  2159  							"apps":[{"id":30,"slug":"aaa"}]
  2160  						}
  2161  					},
  2162  					"restrictions":{
  2163  						"users":[{"id":1,"login":"u"}],
  2164  						"teams":[{"id":2,"slug":"t"}],
  2165  						"apps":[{"id":3,"slug":"a"}]
  2166  					}
  2167  				}`)
  2168  			})
  2169  
  2170  			ctx := context.Background()
  2171  			protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input)
  2172  			if err != nil {
  2173  				t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err)
  2174  			}
  2175  
  2176  			want := &Protection{
  2177  				RequiredStatusChecks: &RequiredStatusChecks{
  2178  					Strict:   true,
  2179  					Contexts: &[]string{},
  2180  				},
  2181  				RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
  2182  					DismissStaleReviews: true,
  2183  					DismissalRestrictions: &DismissalRestrictions{
  2184  						Users: []*User{
  2185  							{Login: String("uu"), ID: Int64(3)},
  2186  						},
  2187  						Teams: []*Team{
  2188  							{Slug: String("tt"), ID: Int64(4)},
  2189  						},
  2190  						Apps: []*App{
  2191  							{Slug: String("aa"), ID: Int64(5)},
  2192  						},
  2193  					},
  2194  					RequireCodeOwnerReviews: true,
  2195  					BypassPullRequestAllowances: &BypassPullRequestAllowances{
  2196  						Users: []*User{
  2197  							{Login: String("uuu"), ID: Int64(10)},
  2198  						},
  2199  						Teams: []*Team{
  2200  							{Slug: String("ttt"), ID: Int64(20)},
  2201  						},
  2202  						Apps: []*App{
  2203  							{Slug: String("aaa"), ID: Int64(30)},
  2204  						},
  2205  					},
  2206  				},
  2207  				Restrictions: &BranchRestrictions{
  2208  					Users: []*User{
  2209  						{Login: String("u"), ID: Int64(1)},
  2210  					},
  2211  					Teams: []*Team{
  2212  						{Slug: String("t"), ID: Int64(2)},
  2213  					},
  2214  					Apps: []*App{
  2215  						{Slug: String("a"), ID: Int64(3)},
  2216  					},
  2217  				},
  2218  			}
  2219  			if !cmp.Equal(protection, want) {
  2220  				t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want)
  2221  			}
  2222  		})
  2223  	}
  2224  }
  2225  
  2226  func TestRepositoriesService_UpdateBranchProtection_RequireLastPushApproval(t *testing.T) {
  2227  	tests := []struct {
  2228  		branch  string
  2229  		urlPath string
  2230  	}{
  2231  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection"},
  2232  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection"},
  2233  	}
  2234  
  2235  	for _, test := range tests {
  2236  		t.Run(test.branch, func(t *testing.T) {
  2237  			client, mux, _, teardown := setup()
  2238  			defer teardown()
  2239  
  2240  			input := &ProtectionRequest{
  2241  				RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{
  2242  					RequireLastPushApproval: Bool(true),
  2243  				},
  2244  			}
  2245  
  2246  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  2247  				v := new(ProtectionRequest)
  2248  				assertNilError(t, json.NewDecoder(r.Body).Decode(v))
  2249  
  2250  				testMethod(t, r, "PUT")
  2251  				if !cmp.Equal(v, input) {
  2252  					t.Errorf("Request body = %+v, want %+v", v, input)
  2253  				}
  2254  
  2255  				fmt.Fprintf(w, `{
  2256  					"required_pull_request_reviews":{
  2257  						"require_last_push_approval":true
  2258  					}
  2259  				}`)
  2260  			})
  2261  
  2262  			ctx := context.Background()
  2263  			protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input)
  2264  			if err != nil {
  2265  				t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err)
  2266  			}
  2267  
  2268  			want := &Protection{
  2269  				RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
  2270  					RequireLastPushApproval: true,
  2271  				},
  2272  			}
  2273  			if !cmp.Equal(protection, want) {
  2274  				t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want)
  2275  			}
  2276  		})
  2277  	}
  2278  }
  2279  
  2280  func TestRepositoriesService_RemoveBranchProtection(t *testing.T) {
  2281  	tests := []struct {
  2282  		branch  string
  2283  		urlPath string
  2284  	}{
  2285  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection"},
  2286  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection"},
  2287  	}
  2288  
  2289  	for _, test := range tests {
  2290  		t.Run(test.branch, func(t *testing.T) {
  2291  			client, mux, _, teardown := setup()
  2292  			defer teardown()
  2293  
  2294  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  2295  				testMethod(t, r, "DELETE")
  2296  				w.WriteHeader(http.StatusNoContent)
  2297  			})
  2298  
  2299  			ctx := context.Background()
  2300  			_, err := client.Repositories.RemoveBranchProtection(ctx, "o", "r", test.branch)
  2301  			if err != nil {
  2302  				t.Errorf("Repositories.RemoveBranchProtection returned error: %v", err)
  2303  			}
  2304  
  2305  			const methodName = "RemoveBranchProtection"
  2306  			testBadOptions(t, methodName, func() (err error) {
  2307  				_, err = client.Repositories.RemoveBranchProtection(ctx, "\n", "\n", "\n")
  2308  				return err
  2309  			})
  2310  
  2311  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  2312  				return client.Repositories.RemoveBranchProtection(ctx, "o", "r", test.branch)
  2313  			})
  2314  		})
  2315  	}
  2316  }
  2317  
  2318  func TestRepositoriesService_ListLanguages_invalidOwner(t *testing.T) {
  2319  	client, _, _, teardown := setup()
  2320  	defer teardown()
  2321  
  2322  	ctx := context.Background()
  2323  	_, _, err := client.Repositories.ListLanguages(ctx, "%", "%")
  2324  	testURLParseError(t, err)
  2325  }
  2326  
  2327  func TestRepositoriesService_License(t *testing.T) {
  2328  	client, mux, _, teardown := setup()
  2329  	defer teardown()
  2330  
  2331  	mux.HandleFunc("/repos/o/r/license", func(w http.ResponseWriter, r *http.Request) {
  2332  		testMethod(t, r, "GET")
  2333  		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}}`)
  2334  	})
  2335  
  2336  	ctx := context.Background()
  2337  	got, _, err := client.Repositories.License(ctx, "o", "r")
  2338  	if err != nil {
  2339  		t.Errorf("Repositories.License returned error: %v", err)
  2340  	}
  2341  
  2342  	want := &RepositoryLicense{
  2343  		Name: String("LICENSE"),
  2344  		Path: String("LICENSE"),
  2345  		License: &License{
  2346  			Name:     String("MIT License"),
  2347  			Key:      String("mit"),
  2348  			SPDXID:   String("MIT"),
  2349  			URL:      String("https://api.github.com/licenses/mit"),
  2350  			Featured: Bool(true),
  2351  		},
  2352  	}
  2353  
  2354  	if !cmp.Equal(got, want) {
  2355  		t.Errorf("Repositories.License returned %+v, want %+v", got, want)
  2356  	}
  2357  
  2358  	const methodName = "License"
  2359  	testBadOptions(t, methodName, func() (err error) {
  2360  		_, _, err = client.Repositories.License(ctx, "\n", "\n")
  2361  		return err
  2362  	})
  2363  
  2364  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  2365  		got, resp, err := client.Repositories.License(ctx, "o", "r")
  2366  		if got != nil {
  2367  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  2368  		}
  2369  		return resp, err
  2370  	})
  2371  }
  2372  
  2373  func TestRepositoriesService_GetRequiredStatusChecks(t *testing.T) {
  2374  	tests := []struct {
  2375  		branch  string
  2376  		urlPath string
  2377  	}{
  2378  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks"},
  2379  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_status_checks"},
  2380  	}
  2381  
  2382  	for _, test := range tests {
  2383  		t.Run(test.branch, func(t *testing.T) {
  2384  			client, mux, _, teardown := setup()
  2385  			defer teardown()
  2386  
  2387  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  2388  				testMethod(t, r, "GET")
  2389  				fmt.Fprint(w, `{
  2390  					"strict": true,
  2391  					"contexts": ["x","y","z"],
  2392  					"checks": [
  2393  						{
  2394  							"context": "x",
  2395  							"app_id": null
  2396  						},
  2397  						{
  2398  							"context": "y",
  2399  							"app_id": null
  2400  						},
  2401  						{
  2402  							"context": "z",
  2403  							"app_id": null
  2404  						}
  2405  					]
  2406  				}`)
  2407  			})
  2408  
  2409  			ctx := context.Background()
  2410  			checks, _, err := client.Repositories.GetRequiredStatusChecks(ctx, "o", "r", test.branch)
  2411  			if err != nil {
  2412  				t.Errorf("Repositories.GetRequiredStatusChecks returned error: %v", err)
  2413  			}
  2414  
  2415  			want := &RequiredStatusChecks{
  2416  				Strict:   true,
  2417  				Contexts: &[]string{"x", "y", "z"},
  2418  				Checks: &[]*RequiredStatusCheck{
  2419  					{
  2420  						Context: "x",
  2421  					},
  2422  					{
  2423  						Context: "y",
  2424  					},
  2425  					{
  2426  						Context: "z",
  2427  					},
  2428  				},
  2429  			}
  2430  			if !cmp.Equal(checks, want) {
  2431  				t.Errorf("Repositories.GetRequiredStatusChecks returned %+v, want %+v", checks, want)
  2432  			}
  2433  
  2434  			const methodName = "GetRequiredStatusChecks"
  2435  			testBadOptions(t, methodName, func() (err error) {
  2436  				_, _, err = client.Repositories.GetRequiredStatusChecks(ctx, "\n", "\n", "\n")
  2437  				return err
  2438  			})
  2439  
  2440  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  2441  				got, resp, err := client.Repositories.GetRequiredStatusChecks(ctx, "o", "r", test.branch)
  2442  				if got != nil {
  2443  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  2444  				}
  2445  				return resp, err
  2446  			})
  2447  		})
  2448  	}
  2449  }
  2450  
  2451  func TestRepositoriesService_GetRequiredStatusChecks_branchNotProtected(t *testing.T) {
  2452  	tests := []struct {
  2453  		branch  string
  2454  		urlPath string
  2455  	}{
  2456  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks"},
  2457  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_status_checks"},
  2458  	}
  2459  
  2460  	for _, test := range tests {
  2461  		t.Run(test.branch, func(t *testing.T) {
  2462  			client, mux, _, teardown := setup()
  2463  			defer teardown()
  2464  
  2465  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  2466  				testMethod(t, r, "GET")
  2467  
  2468  				w.WriteHeader(http.StatusBadRequest)
  2469  				fmt.Fprintf(w, `{
  2470  			"message": %q,
  2471  			"documentation_url": "https://docs.github.com/rest/repos#get-branch-protection"
  2472  			}`, githubBranchNotProtected)
  2473  			})
  2474  
  2475  			ctx := context.Background()
  2476  			checks, _, err := client.Repositories.GetRequiredStatusChecks(ctx, "o", "r", test.branch)
  2477  
  2478  			if checks != nil {
  2479  				t.Errorf("Repositories.GetRequiredStatusChecks returned non-nil status-checks data")
  2480  			}
  2481  
  2482  			if err != ErrBranchNotProtected {
  2483  				t.Errorf("Repositories.GetRequiredStatusChecks returned an invalid error: %v", err)
  2484  			}
  2485  		})
  2486  	}
  2487  }
  2488  
  2489  func TestRepositoriesService_UpdateRequiredStatusChecks_Contexts(t *testing.T) {
  2490  	tests := []struct {
  2491  		branch  string
  2492  		urlPath string
  2493  	}{
  2494  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks"},
  2495  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_status_checks"},
  2496  	}
  2497  
  2498  	for _, test := range tests {
  2499  		t.Run(test.branch, func(t *testing.T) {
  2500  			client, mux, _, teardown := setup()
  2501  			defer teardown()
  2502  
  2503  			input := &RequiredStatusChecksRequest{
  2504  				Strict:   Bool(true),
  2505  				Contexts: []string{"continuous-integration"},
  2506  			}
  2507  
  2508  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  2509  				v := new(RequiredStatusChecksRequest)
  2510  				assertNilError(t, json.NewDecoder(r.Body).Decode(v))
  2511  
  2512  				testMethod(t, r, "PATCH")
  2513  				if !cmp.Equal(v, input) {
  2514  					t.Errorf("Request body = %+v, want %+v", v, input)
  2515  				}
  2516  				testHeader(t, r, "Accept", mediaTypeV3)
  2517  				fmt.Fprintf(w, `{
  2518  					"strict":true,
  2519  					"contexts":["continuous-integration"],
  2520  					"checks": [
  2521  						{
  2522  							"context": "continuous-integration",
  2523  							"app_id": null
  2524  						}
  2525  					]
  2526  				}`)
  2527  			})
  2528  
  2529  			ctx := context.Background()
  2530  			statusChecks, _, err := client.Repositories.UpdateRequiredStatusChecks(ctx, "o", "r", test.branch, input)
  2531  			if err != nil {
  2532  				t.Errorf("Repositories.UpdateRequiredStatusChecks returned error: %v", err)
  2533  			}
  2534  
  2535  			want := &RequiredStatusChecks{
  2536  				Strict:   true,
  2537  				Contexts: &[]string{"continuous-integration"},
  2538  				Checks: &[]*RequiredStatusCheck{
  2539  					{
  2540  						Context: "continuous-integration",
  2541  					},
  2542  				},
  2543  			}
  2544  			if !cmp.Equal(statusChecks, want) {
  2545  				t.Errorf("Repositories.UpdateRequiredStatusChecks returned %+v, want %+v", statusChecks, want)
  2546  			}
  2547  
  2548  			const methodName = "UpdateRequiredStatusChecks"
  2549  			testBadOptions(t, methodName, func() (err error) {
  2550  				_, _, err = client.Repositories.UpdateRequiredStatusChecks(ctx, "\n", "\n", "\n", input)
  2551  				return err
  2552  			})
  2553  
  2554  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  2555  				got, resp, err := client.Repositories.UpdateRequiredStatusChecks(ctx, "o", "r", test.branch, input)
  2556  				if got != nil {
  2557  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  2558  				}
  2559  				return resp, err
  2560  			})
  2561  		})
  2562  	}
  2563  }
  2564  
  2565  func TestRepositoriesService_UpdateRequiredStatusChecks_Checks(t *testing.T) {
  2566  	tests := []struct {
  2567  		branch  string
  2568  		urlPath string
  2569  	}{
  2570  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks"},
  2571  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_status_checks"},
  2572  	}
  2573  
  2574  	for _, test := range tests {
  2575  		t.Run(test.branch, func(t *testing.T) {
  2576  			client, mux, _, teardown := setup()
  2577  			defer teardown()
  2578  
  2579  			appID := int64(123)
  2580  			noAppID := int64(-1)
  2581  			input := &RequiredStatusChecksRequest{
  2582  				Strict: Bool(true),
  2583  				Checks: []*RequiredStatusCheck{
  2584  					{
  2585  						Context: "continuous-integration",
  2586  					},
  2587  					{
  2588  						Context: "continuous-integration2",
  2589  						AppID:   &appID,
  2590  					},
  2591  					{
  2592  						Context: "continuous-integration3",
  2593  						AppID:   &noAppID,
  2594  					},
  2595  				},
  2596  			}
  2597  
  2598  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  2599  				v := new(RequiredStatusChecksRequest)
  2600  				assertNilError(t, json.NewDecoder(r.Body).Decode(v))
  2601  
  2602  				testMethod(t, r, "PATCH")
  2603  				if !cmp.Equal(v, input) {
  2604  					t.Errorf("Request body = %+v, want %+v", v, input)
  2605  				}
  2606  				testHeader(t, r, "Accept", mediaTypeV3)
  2607  				fmt.Fprintf(w, `{
  2608  					"strict":true,
  2609  					"contexts":["continuous-integration"],
  2610  					"checks": [
  2611  						{
  2612  							"context": "continuous-integration",
  2613  							"app_id": null
  2614  						},
  2615  						{
  2616  							"context": "continuous-integration2",
  2617  							"app_id": 123
  2618  						},
  2619  						{
  2620  							"context": "continuous-integration3",
  2621  							"app_id": null
  2622  						}
  2623  					]
  2624  				}`)
  2625  			})
  2626  
  2627  			ctx := context.Background()
  2628  			statusChecks, _, err := client.Repositories.UpdateRequiredStatusChecks(ctx, "o", "r", test.branch, input)
  2629  			if err != nil {
  2630  				t.Errorf("Repositories.UpdateRequiredStatusChecks returned error: %v", err)
  2631  			}
  2632  
  2633  			want := &RequiredStatusChecks{
  2634  				Strict:   true,
  2635  				Contexts: &[]string{"continuous-integration"},
  2636  				Checks: &[]*RequiredStatusCheck{
  2637  					{
  2638  						Context: "continuous-integration",
  2639  					},
  2640  					{
  2641  						Context: "continuous-integration2",
  2642  						AppID:   &appID,
  2643  					},
  2644  					{
  2645  						Context: "continuous-integration3",
  2646  					},
  2647  				},
  2648  			}
  2649  			if !cmp.Equal(statusChecks, want) {
  2650  				t.Errorf("Repositories.UpdateRequiredStatusChecks returned %+v, want %+v", statusChecks, want)
  2651  			}
  2652  		})
  2653  	}
  2654  }
  2655  
  2656  func TestRepositoriesService_RemoveRequiredStatusChecks(t *testing.T) {
  2657  	tests := []struct {
  2658  		branch  string
  2659  		urlPath string
  2660  	}{
  2661  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks"},
  2662  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_status_checks"},
  2663  	}
  2664  
  2665  	for _, test := range tests {
  2666  		t.Run(test.branch, func(t *testing.T) {
  2667  			client, mux, _, teardown := setup()
  2668  			defer teardown()
  2669  
  2670  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  2671  				testMethod(t, r, "DELETE")
  2672  				testHeader(t, r, "Accept", mediaTypeV3)
  2673  				w.WriteHeader(http.StatusNoContent)
  2674  			})
  2675  
  2676  			ctx := context.Background()
  2677  			_, err := client.Repositories.RemoveRequiredStatusChecks(ctx, "o", "r", test.branch)
  2678  			if err != nil {
  2679  				t.Errorf("Repositories.RemoveRequiredStatusChecks returned error: %v", err)
  2680  			}
  2681  
  2682  			const methodName = "RemoveRequiredStatusChecks"
  2683  			testBadOptions(t, methodName, func() (err error) {
  2684  				_, err = client.Repositories.RemoveRequiredStatusChecks(ctx, "\n", "\n", "\n")
  2685  				return err
  2686  			})
  2687  
  2688  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  2689  				return client.Repositories.RemoveRequiredStatusChecks(ctx, "o", "r", test.branch)
  2690  			})
  2691  		})
  2692  	}
  2693  }
  2694  
  2695  func TestRepositoriesService_ListRequiredStatusChecksContexts(t *testing.T) {
  2696  	tests := []struct {
  2697  		branch  string
  2698  		urlPath string
  2699  	}{
  2700  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks/contexts"},
  2701  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_status_checks/contexts"},
  2702  	}
  2703  
  2704  	for _, test := range tests {
  2705  		t.Run(test.branch, func(t *testing.T) {
  2706  			client, mux, _, teardown := setup()
  2707  			defer teardown()
  2708  
  2709  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  2710  				testMethod(t, r, "GET")
  2711  				fmt.Fprint(w, `["x", "y", "z"]`)
  2712  			})
  2713  
  2714  			ctx := context.Background()
  2715  			contexts, _, err := client.Repositories.ListRequiredStatusChecksContexts(ctx, "o", "r", test.branch)
  2716  			if err != nil {
  2717  				t.Errorf("Repositories.ListRequiredStatusChecksContexts returned error: %v", err)
  2718  			}
  2719  
  2720  			want := []string{"x", "y", "z"}
  2721  			if !cmp.Equal(contexts, want) {
  2722  				t.Errorf("Repositories.ListRequiredStatusChecksContexts returned %+v, want %+v", contexts, want)
  2723  			}
  2724  
  2725  			const methodName = "ListRequiredStatusChecksContexts"
  2726  			testBadOptions(t, methodName, func() (err error) {
  2727  				_, _, err = client.Repositories.ListRequiredStatusChecksContexts(ctx, "\n", "\n", "\n")
  2728  				return err
  2729  			})
  2730  
  2731  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  2732  				got, resp, err := client.Repositories.ListRequiredStatusChecksContexts(ctx, "o", "r", test.branch)
  2733  				if got != nil {
  2734  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  2735  				}
  2736  				return resp, err
  2737  			})
  2738  		})
  2739  	}
  2740  }
  2741  
  2742  func TestRepositoriesService_ListRequiredStatusChecksContexts_branchNotProtected(t *testing.T) {
  2743  	tests := []struct {
  2744  		branch  string
  2745  		urlPath string
  2746  	}{
  2747  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks/contexts"},
  2748  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_status_checks/contexts"},
  2749  	}
  2750  
  2751  	for _, test := range tests {
  2752  		t.Run(test.branch, func(t *testing.T) {
  2753  			client, mux, _, teardown := setup()
  2754  			defer teardown()
  2755  
  2756  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  2757  				testMethod(t, r, "GET")
  2758  
  2759  				w.WriteHeader(http.StatusBadRequest)
  2760  				fmt.Fprintf(w, `{
  2761  			"message": %q,
  2762  			"documentation_url": "https://docs.github.com/rest/repos#get-branch-protection"
  2763  			}`, githubBranchNotProtected)
  2764  			})
  2765  
  2766  			ctx := context.Background()
  2767  			contexts, _, err := client.Repositories.ListRequiredStatusChecksContexts(ctx, "o", "r", test.branch)
  2768  
  2769  			if contexts != nil {
  2770  				t.Errorf("Repositories.ListRequiredStatusChecksContexts returned non-nil contexts data")
  2771  			}
  2772  
  2773  			if err != ErrBranchNotProtected {
  2774  				t.Errorf("Repositories.ListRequiredStatusChecksContexts returned an invalid error: %v", err)
  2775  			}
  2776  		})
  2777  	}
  2778  }
  2779  
  2780  func TestRepositoriesService_GetPullRequestReviewEnforcement(t *testing.T) {
  2781  	tests := []struct {
  2782  		branch  string
  2783  		urlPath string
  2784  	}{
  2785  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_pull_request_reviews"},
  2786  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_pull_request_reviews"},
  2787  	}
  2788  
  2789  	for _, test := range tests {
  2790  		t.Run(test.branch, func(t *testing.T) {
  2791  			client, mux, _, teardown := setup()
  2792  			defer teardown()
  2793  
  2794  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  2795  				testMethod(t, r, "GET")
  2796  				// TODO: remove custom Accept header when this API fully launches
  2797  				testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  2798  				fmt.Fprintf(w, `{
  2799  			"dismissal_restrictions":{
  2800  				"users":[{"id":1,"login":"u"}],
  2801  				"teams":[{"id":2,"slug":"t"}],
  2802  				"apps":[{"id":3,"slug":"a"}]
  2803  			},
  2804  			"dismiss_stale_reviews":true,
  2805  			"require_code_owner_reviews":true,
  2806  			"required_approving_review_count":1
  2807  		}`)
  2808  			})
  2809  
  2810  			ctx := context.Background()
  2811  			enforcement, _, err := client.Repositories.GetPullRequestReviewEnforcement(ctx, "o", "r", test.branch)
  2812  			if err != nil {
  2813  				t.Errorf("Repositories.GetPullRequestReviewEnforcement returned error: %v", err)
  2814  			}
  2815  
  2816  			want := &PullRequestReviewsEnforcement{
  2817  				DismissStaleReviews: true,
  2818  				DismissalRestrictions: &DismissalRestrictions{
  2819  					Users: []*User{
  2820  						{Login: String("u"), ID: Int64(1)},
  2821  					},
  2822  					Teams: []*Team{
  2823  						{Slug: String("t"), ID: Int64(2)},
  2824  					},
  2825  					Apps: []*App{
  2826  						{Slug: String("a"), ID: Int64(3)},
  2827  					},
  2828  				},
  2829  				RequireCodeOwnerReviews:      true,
  2830  				RequiredApprovingReviewCount: 1,
  2831  			}
  2832  
  2833  			if !cmp.Equal(enforcement, want) {
  2834  				t.Errorf("Repositories.GetPullRequestReviewEnforcement returned %+v, want %+v", enforcement, want)
  2835  			}
  2836  
  2837  			const methodName = "GetPullRequestReviewEnforcement"
  2838  			testBadOptions(t, methodName, func() (err error) {
  2839  				_, _, err = client.Repositories.GetPullRequestReviewEnforcement(ctx, "\n", "\n", "\n")
  2840  				return err
  2841  			})
  2842  
  2843  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  2844  				got, resp, err := client.Repositories.GetPullRequestReviewEnforcement(ctx, "o", "r", test.branch)
  2845  				if got != nil {
  2846  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  2847  				}
  2848  				return resp, err
  2849  			})
  2850  		})
  2851  	}
  2852  }
  2853  
  2854  func TestRepositoriesService_UpdatePullRequestReviewEnforcement(t *testing.T) {
  2855  	tests := []struct {
  2856  		branch  string
  2857  		urlPath string
  2858  	}{
  2859  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_pull_request_reviews"},
  2860  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_pull_request_reviews"},
  2861  	}
  2862  
  2863  	for _, test := range tests {
  2864  		t.Run(test.branch, func(t *testing.T) {
  2865  			client, mux, _, teardown := setup()
  2866  			defer teardown()
  2867  
  2868  			input := &PullRequestReviewsEnforcementUpdate{
  2869  				DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
  2870  					Users: &[]string{"u"},
  2871  					Teams: &[]string{"t"},
  2872  					Apps:  &[]string{"a"},
  2873  				},
  2874  			}
  2875  
  2876  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  2877  				v := new(PullRequestReviewsEnforcementUpdate)
  2878  				assertNilError(t, json.NewDecoder(r.Body).Decode(v))
  2879  
  2880  				testMethod(t, r, "PATCH")
  2881  				if !cmp.Equal(v, input) {
  2882  					t.Errorf("Request body = %+v, want %+v", v, input)
  2883  				}
  2884  				// TODO: remove custom Accept header when this API fully launches
  2885  				testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  2886  				fmt.Fprintf(w, `{
  2887  					"dismissal_restrictions":{
  2888  						"users":[{"id":1,"login":"u"}],
  2889  						"teams":[{"id":2,"slug":"t"}],
  2890  						"apps":[{"id":3,"slug":"a"}]
  2891  					},
  2892  					"dismiss_stale_reviews":true,
  2893  					"require_code_owner_reviews":true,
  2894  					"required_approving_review_count":3
  2895  				}`)
  2896  			})
  2897  
  2898  			ctx := context.Background()
  2899  			enforcement, _, err := client.Repositories.UpdatePullRequestReviewEnforcement(ctx, "o", "r", test.branch, input)
  2900  			if err != nil {
  2901  				t.Errorf("Repositories.UpdatePullRequestReviewEnforcement returned error: %v", err)
  2902  			}
  2903  
  2904  			want := &PullRequestReviewsEnforcement{
  2905  				DismissStaleReviews: true,
  2906  				DismissalRestrictions: &DismissalRestrictions{
  2907  					Users: []*User{
  2908  						{Login: String("u"), ID: Int64(1)},
  2909  					},
  2910  					Teams: []*Team{
  2911  						{Slug: String("t"), ID: Int64(2)},
  2912  					},
  2913  					Apps: []*App{
  2914  						{Slug: String("a"), ID: Int64(3)},
  2915  					},
  2916  				},
  2917  				RequireCodeOwnerReviews:      true,
  2918  				RequiredApprovingReviewCount: 3,
  2919  			}
  2920  			if !cmp.Equal(enforcement, want) {
  2921  				t.Errorf("Repositories.UpdatePullRequestReviewEnforcement returned %+v, want %+v", enforcement, want)
  2922  			}
  2923  
  2924  			const methodName = "UpdatePullRequestReviewEnforcement"
  2925  			testBadOptions(t, methodName, func() (err error) {
  2926  				_, _, err = client.Repositories.UpdatePullRequestReviewEnforcement(ctx, "\n", "\n", "\n", input)
  2927  				return err
  2928  			})
  2929  
  2930  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  2931  				got, resp, err := client.Repositories.UpdatePullRequestReviewEnforcement(ctx, "o", "r", test.branch, input)
  2932  				if got != nil {
  2933  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  2934  				}
  2935  				return resp, err
  2936  			})
  2937  		})
  2938  	}
  2939  }
  2940  
  2941  func TestRepositoriesService_DisableDismissalRestrictions(t *testing.T) {
  2942  	tests := []struct {
  2943  		branch  string
  2944  		urlPath string
  2945  	}{
  2946  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_pull_request_reviews"},
  2947  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_pull_request_reviews"},
  2948  	}
  2949  
  2950  	for _, test := range tests {
  2951  		t.Run(test.branch, func(t *testing.T) {
  2952  			client, mux, _, teardown := setup()
  2953  			defer teardown()
  2954  
  2955  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  2956  				testMethod(t, r, "PATCH")
  2957  				// TODO: remove custom Accept header when this API fully launches
  2958  				testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
  2959  				testBody(t, r, `{"dismissal_restrictions":{}}`+"\n")
  2960  				fmt.Fprintf(w, `{"dismiss_stale_reviews":true,"require_code_owner_reviews":true,"required_approving_review_count":1}`)
  2961  			})
  2962  
  2963  			ctx := context.Background()
  2964  			enforcement, _, err := client.Repositories.DisableDismissalRestrictions(ctx, "o", "r", test.branch)
  2965  			if err != nil {
  2966  				t.Errorf("Repositories.DisableDismissalRestrictions returned error: %v", err)
  2967  			}
  2968  
  2969  			want := &PullRequestReviewsEnforcement{
  2970  				DismissStaleReviews:          true,
  2971  				DismissalRestrictions:        nil,
  2972  				RequireCodeOwnerReviews:      true,
  2973  				RequiredApprovingReviewCount: 1,
  2974  			}
  2975  			if !cmp.Equal(enforcement, want) {
  2976  				t.Errorf("Repositories.DisableDismissalRestrictions returned %+v, want %+v", enforcement, want)
  2977  			}
  2978  
  2979  			const methodName = "DisableDismissalRestrictions"
  2980  			testBadOptions(t, methodName, func() (err error) {
  2981  				_, _, err = client.Repositories.DisableDismissalRestrictions(ctx, "\n", "\n", "\n")
  2982  				return err
  2983  			})
  2984  
  2985  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  2986  				got, resp, err := client.Repositories.DisableDismissalRestrictions(ctx, "o", "r", test.branch)
  2987  				if got != nil {
  2988  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  2989  				}
  2990  				return resp, err
  2991  			})
  2992  		})
  2993  	}
  2994  }
  2995  
  2996  func TestRepositoriesService_RemovePullRequestReviewEnforcement(t *testing.T) {
  2997  	tests := []struct {
  2998  		branch  string
  2999  		urlPath string
  3000  	}{
  3001  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_pull_request_reviews"},
  3002  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_pull_request_reviews"},
  3003  	}
  3004  
  3005  	for _, test := range tests {
  3006  		t.Run(test.branch, func(t *testing.T) {
  3007  			client, mux, _, teardown := setup()
  3008  			defer teardown()
  3009  
  3010  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  3011  				testMethod(t, r, "DELETE")
  3012  				w.WriteHeader(http.StatusNoContent)
  3013  			})
  3014  
  3015  			ctx := context.Background()
  3016  			_, err := client.Repositories.RemovePullRequestReviewEnforcement(ctx, "o", "r", test.branch)
  3017  			if err != nil {
  3018  				t.Errorf("Repositories.RemovePullRequestReviewEnforcement returned error: %v", err)
  3019  			}
  3020  
  3021  			const methodName = "RemovePullRequestReviewEnforcement"
  3022  			testBadOptions(t, methodName, func() (err error) {
  3023  				_, err = client.Repositories.RemovePullRequestReviewEnforcement(ctx, "\n", "\n", "\n")
  3024  				return err
  3025  			})
  3026  
  3027  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  3028  				return client.Repositories.RemovePullRequestReviewEnforcement(ctx, "o", "r", test.branch)
  3029  			})
  3030  		})
  3031  	}
  3032  }
  3033  
  3034  func TestRepositoriesService_GetAdminEnforcement(t *testing.T) {
  3035  	tests := []struct {
  3036  		branch  string
  3037  		urlPath string
  3038  	}{
  3039  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/enforce_admins"},
  3040  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/enforce_admins"},
  3041  	}
  3042  
  3043  	for _, test := range tests {
  3044  		t.Run(test.branch, func(t *testing.T) {
  3045  			client, mux, _, teardown := setup()
  3046  			defer teardown()
  3047  
  3048  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  3049  				testMethod(t, r, "GET")
  3050  				fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/enforce_admins","enabled":true}`)
  3051  			})
  3052  
  3053  			ctx := context.Background()
  3054  			enforcement, _, err := client.Repositories.GetAdminEnforcement(ctx, "o", "r", test.branch)
  3055  			if err != nil {
  3056  				t.Errorf("Repositories.GetAdminEnforcement returned error: %v", err)
  3057  			}
  3058  
  3059  			want := &AdminEnforcement{
  3060  				URL:     String("/repos/o/r/branches/b/protection/enforce_admins"),
  3061  				Enabled: true,
  3062  			}
  3063  
  3064  			if !cmp.Equal(enforcement, want) {
  3065  				t.Errorf("Repositories.GetAdminEnforcement returned %+v, want %+v", enforcement, want)
  3066  			}
  3067  
  3068  			const methodName = "GetAdminEnforcement"
  3069  			testBadOptions(t, methodName, func() (err error) {
  3070  				_, _, err = client.Repositories.GetAdminEnforcement(ctx, "\n", "\n", "\n")
  3071  				return err
  3072  			})
  3073  
  3074  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  3075  				got, resp, err := client.Repositories.GetAdminEnforcement(ctx, "o", "r", test.branch)
  3076  				if got != nil {
  3077  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  3078  				}
  3079  				return resp, err
  3080  			})
  3081  		})
  3082  	}
  3083  }
  3084  
  3085  func TestRepositoriesService_AddAdminEnforcement(t *testing.T) {
  3086  	tests := []struct {
  3087  		branch  string
  3088  		urlPath string
  3089  	}{
  3090  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/enforce_admins"},
  3091  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/enforce_admins"},
  3092  	}
  3093  
  3094  	for _, test := range tests {
  3095  		t.Run(test.branch, func(t *testing.T) {
  3096  			client, mux, _, teardown := setup()
  3097  			defer teardown()
  3098  
  3099  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  3100  				testMethod(t, r, "POST")
  3101  				fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/enforce_admins","enabled":true}`)
  3102  			})
  3103  
  3104  			ctx := context.Background()
  3105  			enforcement, _, err := client.Repositories.AddAdminEnforcement(ctx, "o", "r", test.branch)
  3106  			if err != nil {
  3107  				t.Errorf("Repositories.AddAdminEnforcement returned error: %v", err)
  3108  			}
  3109  
  3110  			want := &AdminEnforcement{
  3111  				URL:     String("/repos/o/r/branches/b/protection/enforce_admins"),
  3112  				Enabled: true,
  3113  			}
  3114  			if !cmp.Equal(enforcement, want) {
  3115  				t.Errorf("Repositories.AddAdminEnforcement returned %+v, want %+v", enforcement, want)
  3116  			}
  3117  
  3118  			const methodName = "AddAdminEnforcement"
  3119  			testBadOptions(t, methodName, func() (err error) {
  3120  				_, _, err = client.Repositories.AddAdminEnforcement(ctx, "\n", "\n", "\n")
  3121  				return err
  3122  			})
  3123  
  3124  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  3125  				got, resp, err := client.Repositories.AddAdminEnforcement(ctx, "o", "r", test.branch)
  3126  				if got != nil {
  3127  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  3128  				}
  3129  				return resp, err
  3130  			})
  3131  		})
  3132  	}
  3133  }
  3134  
  3135  func TestRepositoriesService_RemoveAdminEnforcement(t *testing.T) {
  3136  	tests := []struct {
  3137  		branch  string
  3138  		urlPath string
  3139  	}{
  3140  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/enforce_admins"},
  3141  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/enforce_admins"},
  3142  	}
  3143  
  3144  	for _, test := range tests {
  3145  		t.Run(test.branch, func(t *testing.T) {
  3146  			client, mux, _, teardown := setup()
  3147  			defer teardown()
  3148  
  3149  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  3150  				testMethod(t, r, "DELETE")
  3151  				w.WriteHeader(http.StatusNoContent)
  3152  			})
  3153  
  3154  			ctx := context.Background()
  3155  			_, err := client.Repositories.RemoveAdminEnforcement(ctx, "o", "r", test.branch)
  3156  			if err != nil {
  3157  				t.Errorf("Repositories.RemoveAdminEnforcement returned error: %v", err)
  3158  			}
  3159  
  3160  			const methodName = "RemoveAdminEnforcement"
  3161  			testBadOptions(t, methodName, func() (err error) {
  3162  				_, err = client.Repositories.RemoveAdminEnforcement(ctx, "\n", "\n", "\n")
  3163  				return err
  3164  			})
  3165  
  3166  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  3167  				return client.Repositories.RemoveAdminEnforcement(ctx, "o", "r", test.branch)
  3168  			})
  3169  		})
  3170  	}
  3171  }
  3172  
  3173  func TestRepositoriesService_GetSignaturesProtectedBranch(t *testing.T) {
  3174  	tests := []struct {
  3175  		branch  string
  3176  		urlPath string
  3177  	}{
  3178  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_signatures"},
  3179  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_signatures"},
  3180  	}
  3181  
  3182  	for _, test := range tests {
  3183  		t.Run(test.branch, func(t *testing.T) {
  3184  			client, mux, _, teardown := setup()
  3185  			defer teardown()
  3186  
  3187  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  3188  				testMethod(t, r, "GET")
  3189  				testHeader(t, r, "Accept", mediaTypeSignaturePreview)
  3190  				fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/required_signatures","enabled":false}`)
  3191  			})
  3192  
  3193  			ctx := context.Background()
  3194  			signature, _, err := client.Repositories.GetSignaturesProtectedBranch(ctx, "o", "r", test.branch)
  3195  			if err != nil {
  3196  				t.Errorf("Repositories.GetSignaturesProtectedBranch returned error: %v", err)
  3197  			}
  3198  
  3199  			want := &SignaturesProtectedBranch{
  3200  				URL:     String("/repos/o/r/branches/b/protection/required_signatures"),
  3201  				Enabled: Bool(false),
  3202  			}
  3203  
  3204  			if !cmp.Equal(signature, want) {
  3205  				t.Errorf("Repositories.GetSignaturesProtectedBranch returned %+v, want %+v", signature, want)
  3206  			}
  3207  
  3208  			const methodName = "GetSignaturesProtectedBranch"
  3209  			testBadOptions(t, methodName, func() (err error) {
  3210  				_, _, err = client.Repositories.GetSignaturesProtectedBranch(ctx, "\n", "\n", "\n")
  3211  				return err
  3212  			})
  3213  
  3214  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  3215  				got, resp, err := client.Repositories.GetSignaturesProtectedBranch(ctx, "o", "r", test.branch)
  3216  				if got != nil {
  3217  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  3218  				}
  3219  				return resp, err
  3220  			})
  3221  		})
  3222  	}
  3223  }
  3224  
  3225  func TestRepositoriesService_RequireSignaturesOnProtectedBranch(t *testing.T) {
  3226  	tests := []struct {
  3227  		branch  string
  3228  		urlPath string
  3229  	}{
  3230  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_signatures"},
  3231  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_signatures"},
  3232  	}
  3233  
  3234  	for _, test := range tests {
  3235  		t.Run(test.branch, func(t *testing.T) {
  3236  			client, mux, _, teardown := setup()
  3237  			defer teardown()
  3238  
  3239  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  3240  				testMethod(t, r, "POST")
  3241  				testHeader(t, r, "Accept", mediaTypeSignaturePreview)
  3242  				fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/required_signatures","enabled":true}`)
  3243  			})
  3244  
  3245  			ctx := context.Background()
  3246  			signature, _, err := client.Repositories.RequireSignaturesOnProtectedBranch(ctx, "o", "r", test.branch)
  3247  			if err != nil {
  3248  				t.Errorf("Repositories.RequireSignaturesOnProtectedBranch returned error: %v", err)
  3249  			}
  3250  
  3251  			want := &SignaturesProtectedBranch{
  3252  				URL:     String("/repos/o/r/branches/b/protection/required_signatures"),
  3253  				Enabled: Bool(true),
  3254  			}
  3255  
  3256  			if !cmp.Equal(signature, want) {
  3257  				t.Errorf("Repositories.RequireSignaturesOnProtectedBranch returned %+v, want %+v", signature, want)
  3258  			}
  3259  
  3260  			const methodName = "RequireSignaturesOnProtectedBranch"
  3261  			testBadOptions(t, methodName, func() (err error) {
  3262  				_, _, err = client.Repositories.RequireSignaturesOnProtectedBranch(ctx, "\n", "\n", "\n")
  3263  				return err
  3264  			})
  3265  
  3266  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  3267  				got, resp, err := client.Repositories.RequireSignaturesOnProtectedBranch(ctx, "o", "r", test.branch)
  3268  				if got != nil {
  3269  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  3270  				}
  3271  				return resp, err
  3272  			})
  3273  		})
  3274  	}
  3275  }
  3276  
  3277  func TestRepositoriesService_OptionalSignaturesOnProtectedBranch(t *testing.T) {
  3278  	tests := []struct {
  3279  		branch  string
  3280  		urlPath string
  3281  	}{
  3282  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_signatures"},
  3283  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/required_signatures"},
  3284  	}
  3285  
  3286  	for _, test := range tests {
  3287  		t.Run(test.branch, func(t *testing.T) {
  3288  			client, mux, _, teardown := setup()
  3289  			defer teardown()
  3290  
  3291  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  3292  				testMethod(t, r, "DELETE")
  3293  				testHeader(t, r, "Accept", mediaTypeSignaturePreview)
  3294  				w.WriteHeader(http.StatusNoContent)
  3295  			})
  3296  
  3297  			ctx := context.Background()
  3298  			_, err := client.Repositories.OptionalSignaturesOnProtectedBranch(ctx, "o", "r", test.branch)
  3299  			if err != nil {
  3300  				t.Errorf("Repositories.OptionalSignaturesOnProtectedBranch returned error: %v", err)
  3301  			}
  3302  
  3303  			const methodName = "OptionalSignaturesOnProtectedBranch"
  3304  			testBadOptions(t, methodName, func() (err error) {
  3305  				_, err = client.Repositories.OptionalSignaturesOnProtectedBranch(ctx, "\n", "\n", "\n")
  3306  				return err
  3307  			})
  3308  
  3309  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  3310  				return client.Repositories.OptionalSignaturesOnProtectedBranch(ctx, "o", "r", test.branch)
  3311  			})
  3312  		})
  3313  	}
  3314  }
  3315  
  3316  func TestPullRequestReviewsEnforcementRequest_MarshalJSON_nilDismissalRestirctions(t *testing.T) {
  3317  	req := PullRequestReviewsEnforcementRequest{}
  3318  
  3319  	got, err := json.Marshal(req)
  3320  	if err != nil {
  3321  		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err)
  3322  	}
  3323  
  3324  	want := `{"dismiss_stale_reviews":false,"require_code_owner_reviews":false,"required_approving_review_count":0}`
  3325  	if want != string(got) {
  3326  		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want)
  3327  	}
  3328  
  3329  	req = PullRequestReviewsEnforcementRequest{
  3330  		DismissalRestrictionsRequest: &DismissalRestrictionsRequest{},
  3331  	}
  3332  
  3333  	got, err = json.Marshal(req)
  3334  	if err != nil {
  3335  		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err)
  3336  	}
  3337  
  3338  	want = `{"dismissal_restrictions":{},"dismiss_stale_reviews":false,"require_code_owner_reviews":false,"required_approving_review_count":0}`
  3339  	if want != string(got) {
  3340  		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want)
  3341  	}
  3342  
  3343  	req = PullRequestReviewsEnforcementRequest{
  3344  		DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
  3345  			Users: &[]string{},
  3346  			Teams: &[]string{},
  3347  			Apps:  &[]string{},
  3348  		},
  3349  		RequireLastPushApproval: Bool(true),
  3350  	}
  3351  
  3352  	got, err = json.Marshal(req)
  3353  	if err != nil {
  3354  		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err)
  3355  	}
  3356  
  3357  	want = `{"dismissal_restrictions":{"users":[],"teams":[],"apps":[]},"dismiss_stale_reviews":false,"require_code_owner_reviews":false,"required_approving_review_count":0,"require_last_push_approval":true}`
  3358  	if want != string(got) {
  3359  		t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want)
  3360  	}
  3361  }
  3362  
  3363  func TestRepositoriesService_ListAllTopics(t *testing.T) {
  3364  	client, mux, _, teardown := setup()
  3365  	defer teardown()
  3366  
  3367  	mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
  3368  		testMethod(t, r, "GET")
  3369  		testHeader(t, r, "Accept", mediaTypeTopicsPreview)
  3370  		fmt.Fprint(w, `{"names":["go", "go-github", "github"]}`)
  3371  	})
  3372  
  3373  	ctx := context.Background()
  3374  	got, _, err := client.Repositories.ListAllTopics(ctx, "o", "r")
  3375  	if err != nil {
  3376  		t.Fatalf("Repositories.ListAllTopics returned error: %v", err)
  3377  	}
  3378  
  3379  	want := []string{"go", "go-github", "github"}
  3380  	if !cmp.Equal(got, want) {
  3381  		t.Errorf("Repositories.ListAllTopics returned %+v, want %+v", got, want)
  3382  	}
  3383  
  3384  	const methodName = "ListAllTopics"
  3385  	testBadOptions(t, methodName, func() (err error) {
  3386  		_, _, err = client.Repositories.ListAllTopics(ctx, "\n", "\n")
  3387  		return err
  3388  	})
  3389  
  3390  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  3391  		got, resp, err := client.Repositories.ListAllTopics(ctx, "o", "r")
  3392  		if got != nil {
  3393  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  3394  		}
  3395  		return resp, err
  3396  	})
  3397  }
  3398  
  3399  func TestRepositoriesService_ListAllTopics_emptyTopics(t *testing.T) {
  3400  	client, mux, _, teardown := setup()
  3401  	defer teardown()
  3402  
  3403  	mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
  3404  		testMethod(t, r, "GET")
  3405  		testHeader(t, r, "Accept", mediaTypeTopicsPreview)
  3406  		fmt.Fprint(w, `{"names":[]}`)
  3407  	})
  3408  
  3409  	ctx := context.Background()
  3410  	got, _, err := client.Repositories.ListAllTopics(ctx, "o", "r")
  3411  	if err != nil {
  3412  		t.Fatalf("Repositories.ListAllTopics returned error: %v", err)
  3413  	}
  3414  
  3415  	want := []string{}
  3416  	if !cmp.Equal(got, want) {
  3417  		t.Errorf("Repositories.ListAllTopics returned %+v, want %+v", got, want)
  3418  	}
  3419  }
  3420  
  3421  func TestRepositoriesService_ReplaceAllTopics(t *testing.T) {
  3422  	client, mux, _, teardown := setup()
  3423  	defer teardown()
  3424  
  3425  	mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
  3426  		testMethod(t, r, "PUT")
  3427  		testHeader(t, r, "Accept", mediaTypeTopicsPreview)
  3428  		fmt.Fprint(w, `{"names":["go", "go-github", "github"]}`)
  3429  	})
  3430  
  3431  	ctx := context.Background()
  3432  	got, _, err := client.Repositories.ReplaceAllTopics(ctx, "o", "r", []string{"go", "go-github", "github"})
  3433  	if err != nil {
  3434  		t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err)
  3435  	}
  3436  
  3437  	want := []string{"go", "go-github", "github"}
  3438  	if !cmp.Equal(got, want) {
  3439  		t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want)
  3440  	}
  3441  
  3442  	const methodName = "ReplaceAllTopics"
  3443  	testBadOptions(t, methodName, func() (err error) {
  3444  		_, _, err = client.Repositories.ReplaceAllTopics(ctx, "\n", "\n", []string{"\n", "\n", "\n"})
  3445  		return err
  3446  	})
  3447  
  3448  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  3449  		got, resp, err := client.Repositories.ReplaceAllTopics(ctx, "o", "r", []string{"go", "go-github", "github"})
  3450  		if got != nil {
  3451  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  3452  		}
  3453  		return resp, err
  3454  	})
  3455  }
  3456  
  3457  func TestRepositoriesService_ReplaceAllTopics_nilSlice(t *testing.T) {
  3458  	client, mux, _, teardown := setup()
  3459  	defer teardown()
  3460  
  3461  	mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
  3462  		testMethod(t, r, "PUT")
  3463  		testHeader(t, r, "Accept", mediaTypeTopicsPreview)
  3464  		testBody(t, r, `{"names":[]}`+"\n")
  3465  		fmt.Fprint(w, `{"names":[]}`)
  3466  	})
  3467  
  3468  	ctx := context.Background()
  3469  	got, _, err := client.Repositories.ReplaceAllTopics(ctx, "o", "r", nil)
  3470  	if err != nil {
  3471  		t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err)
  3472  	}
  3473  
  3474  	want := []string{}
  3475  	if !cmp.Equal(got, want) {
  3476  		t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want)
  3477  	}
  3478  }
  3479  
  3480  func TestRepositoriesService_ReplaceAllTopics_emptySlice(t *testing.T) {
  3481  	client, mux, _, teardown := setup()
  3482  	defer teardown()
  3483  
  3484  	mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) {
  3485  		testMethod(t, r, "PUT")
  3486  		testHeader(t, r, "Accept", mediaTypeTopicsPreview)
  3487  		testBody(t, r, `{"names":[]}`+"\n")
  3488  		fmt.Fprint(w, `{"names":[]}`)
  3489  	})
  3490  
  3491  	ctx := context.Background()
  3492  	got, _, err := client.Repositories.ReplaceAllTopics(ctx, "o", "r", []string{})
  3493  	if err != nil {
  3494  		t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err)
  3495  	}
  3496  
  3497  	want := []string{}
  3498  	if !cmp.Equal(got, want) {
  3499  		t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want)
  3500  	}
  3501  }
  3502  
  3503  func TestRepositoriesService_ListAppRestrictions(t *testing.T) {
  3504  	tests := []struct {
  3505  		branch  string
  3506  		urlPath string
  3507  	}{
  3508  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/apps"},
  3509  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/apps"},
  3510  	}
  3511  
  3512  	for _, test := range tests {
  3513  		t.Run(test.branch, func(t *testing.T) {
  3514  			client, mux, _, teardown := setup()
  3515  			defer teardown()
  3516  
  3517  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  3518  				testMethod(t, r, "GET")
  3519  			})
  3520  
  3521  			ctx := context.Background()
  3522  			_, _, err := client.Repositories.ListAppRestrictions(ctx, "o", "r", test.branch)
  3523  			if err != nil {
  3524  				t.Errorf("Repositories.ListAppRestrictions returned error: %v", err)
  3525  			}
  3526  
  3527  			const methodName = "ListAppRestrictions"
  3528  			testBadOptions(t, methodName, func() (err error) {
  3529  				_, _, err = client.Repositories.ListAppRestrictions(ctx, "\n", "\n", "\n")
  3530  				return err
  3531  			})
  3532  
  3533  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  3534  				got, resp, err := client.Repositories.ListAppRestrictions(ctx, "o", "r", test.branch)
  3535  				if got != nil {
  3536  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  3537  				}
  3538  				return resp, err
  3539  			})
  3540  		})
  3541  	}
  3542  }
  3543  
  3544  func TestRepositoriesService_ReplaceAppRestrictions(t *testing.T) {
  3545  	tests := []struct {
  3546  		branch  string
  3547  		urlPath string
  3548  	}{
  3549  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/apps"},
  3550  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/apps"},
  3551  	}
  3552  
  3553  	for _, test := range tests {
  3554  		t.Run(test.branch, func(t *testing.T) {
  3555  			client, mux, _, teardown := setup()
  3556  			defer teardown()
  3557  
  3558  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  3559  				testMethod(t, r, "PUT")
  3560  				fmt.Fprint(w, `[{
  3561  				"name": "octocat"
  3562  			}]`)
  3563  			})
  3564  			input := []string{"octocat"}
  3565  			ctx := context.Background()
  3566  			got, _, err := client.Repositories.ReplaceAppRestrictions(ctx, "o", "r", test.branch, input)
  3567  			if err != nil {
  3568  				t.Errorf("Repositories.ReplaceAppRestrictions returned error: %v", err)
  3569  			}
  3570  			want := []*App{
  3571  				{Name: String("octocat")},
  3572  			}
  3573  			if !cmp.Equal(got, want) {
  3574  				t.Errorf("Repositories.ReplaceAppRestrictions returned %+v, want %+v", got, want)
  3575  			}
  3576  
  3577  			const methodName = "ReplaceAppRestrictions"
  3578  			testBadOptions(t, methodName, func() (err error) {
  3579  				_, _, err = client.Repositories.ReplaceAppRestrictions(ctx, "\n", "\n", "\n", input)
  3580  				return err
  3581  			})
  3582  
  3583  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  3584  				got, resp, err := client.Repositories.ReplaceAppRestrictions(ctx, "o", "r", test.branch, input)
  3585  				if got != nil {
  3586  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  3587  				}
  3588  				return resp, err
  3589  			})
  3590  		})
  3591  	}
  3592  }
  3593  
  3594  func TestRepositoriesService_AddAppRestrictions(t *testing.T) {
  3595  	tests := []struct {
  3596  		branch  string
  3597  		urlPath string
  3598  	}{
  3599  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/apps"},
  3600  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/apps"},
  3601  	}
  3602  
  3603  	for _, test := range tests {
  3604  		t.Run(test.branch, func(t *testing.T) {
  3605  			client, mux, _, teardown := setup()
  3606  			defer teardown()
  3607  
  3608  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  3609  				testMethod(t, r, "POST")
  3610  				fmt.Fprint(w, `[{
  3611  				"name": "octocat"
  3612  			}]`)
  3613  			})
  3614  			input := []string{"octocat"}
  3615  			ctx := context.Background()
  3616  			got, _, err := client.Repositories.AddAppRestrictions(ctx, "o", "r", test.branch, input)
  3617  			if err != nil {
  3618  				t.Errorf("Repositories.AddAppRestrictions returned error: %v", err)
  3619  			}
  3620  			want := []*App{
  3621  				{Name: String("octocat")},
  3622  			}
  3623  			if !cmp.Equal(got, want) {
  3624  				t.Errorf("Repositories.AddAppRestrictions returned %+v, want %+v", got, want)
  3625  			}
  3626  
  3627  			const methodName = "AddAppRestrictions"
  3628  			testBadOptions(t, methodName, func() (err error) {
  3629  				_, _, err = client.Repositories.AddAppRestrictions(ctx, "\n", "\n", "\n", input)
  3630  				return err
  3631  			})
  3632  
  3633  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  3634  				got, resp, err := client.Repositories.AddAppRestrictions(ctx, "o", "r", test.branch, input)
  3635  				if got != nil {
  3636  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  3637  				}
  3638  				return resp, err
  3639  			})
  3640  		})
  3641  	}
  3642  }
  3643  
  3644  func TestRepositoriesService_RemoveAppRestrictions(t *testing.T) {
  3645  	tests := []struct {
  3646  		branch  string
  3647  		urlPath string
  3648  	}{
  3649  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/apps"},
  3650  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/apps"},
  3651  	}
  3652  
  3653  	for _, test := range tests {
  3654  		t.Run(test.branch, func(t *testing.T) {
  3655  			client, mux, _, teardown := setup()
  3656  			defer teardown()
  3657  
  3658  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  3659  				testMethod(t, r, "DELETE")
  3660  				fmt.Fprint(w, `[]`)
  3661  			})
  3662  			input := []string{"octocat"}
  3663  			ctx := context.Background()
  3664  			got, _, err := client.Repositories.RemoveAppRestrictions(ctx, "o", "r", test.branch, input)
  3665  			if err != nil {
  3666  				t.Errorf("Repositories.RemoveAppRestrictions returned error: %v", err)
  3667  			}
  3668  			want := []*App{}
  3669  			if !cmp.Equal(got, want) {
  3670  				t.Errorf("Repositories.RemoveAppRestrictions returned %+v, want %+v", got, want)
  3671  			}
  3672  
  3673  			const methodName = "RemoveAppRestrictions"
  3674  			testBadOptions(t, methodName, func() (err error) {
  3675  				_, _, err = client.Repositories.RemoveAppRestrictions(ctx, "\n", "\n", "\n", input)
  3676  				return err
  3677  			})
  3678  
  3679  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  3680  				got, resp, err := client.Repositories.RemoveAppRestrictions(ctx, "o", "r", test.branch, input)
  3681  				if got != nil {
  3682  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  3683  				}
  3684  				return resp, err
  3685  			})
  3686  		})
  3687  	}
  3688  }
  3689  
  3690  func TestRepositoriesService_ListTeamRestrictions(t *testing.T) {
  3691  	tests := []struct {
  3692  		branch  string
  3693  		urlPath string
  3694  	}{
  3695  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/teams"},
  3696  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/teams"},
  3697  	}
  3698  
  3699  	for _, test := range tests {
  3700  		t.Run(test.branch, func(t *testing.T) {
  3701  			client, mux, _, teardown := setup()
  3702  			defer teardown()
  3703  
  3704  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  3705  				testMethod(t, r, "GET")
  3706  			})
  3707  
  3708  			ctx := context.Background()
  3709  			_, _, err := client.Repositories.ListTeamRestrictions(ctx, "o", "r", test.branch)
  3710  			if err != nil {
  3711  				t.Errorf("Repositories.ListTeamRestrictions returned error: %v", err)
  3712  			}
  3713  
  3714  			const methodName = "ListTeamRestrictions"
  3715  			testBadOptions(t, methodName, func() (err error) {
  3716  				_, _, err = client.Repositories.ListTeamRestrictions(ctx, "\n", "\n", "\n")
  3717  				return err
  3718  			})
  3719  
  3720  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  3721  				got, resp, err := client.Repositories.ListTeamRestrictions(ctx, "o", "r", test.branch)
  3722  				if got != nil {
  3723  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  3724  				}
  3725  				return resp, err
  3726  			})
  3727  		})
  3728  	}
  3729  }
  3730  
  3731  func TestRepositoriesService_ReplaceTeamRestrictions(t *testing.T) {
  3732  	tests := []struct {
  3733  		branch  string
  3734  		urlPath string
  3735  	}{
  3736  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/teams"},
  3737  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/teams"},
  3738  	}
  3739  
  3740  	for _, test := range tests {
  3741  		t.Run(test.branch, func(t *testing.T) {
  3742  			client, mux, _, teardown := setup()
  3743  			defer teardown()
  3744  
  3745  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  3746  				testMethod(t, r, "PUT")
  3747  				fmt.Fprint(w, `[{
  3748  				"name": "octocat"
  3749  			}]`)
  3750  			})
  3751  			input := []string{"octocat"}
  3752  			ctx := context.Background()
  3753  			got, _, err := client.Repositories.ReplaceTeamRestrictions(ctx, "o", "r", test.branch, input)
  3754  			if err != nil {
  3755  				t.Errorf("Repositories.ReplaceTeamRestrictions returned error: %v", err)
  3756  			}
  3757  			want := []*Team{
  3758  				{Name: String("octocat")},
  3759  			}
  3760  			if !cmp.Equal(got, want) {
  3761  				t.Errorf("Repositories.ReplaceTeamRestrictions returned %+v, want %+v", got, want)
  3762  			}
  3763  
  3764  			const methodName = "ReplaceTeamRestrictions"
  3765  			testBadOptions(t, methodName, func() (err error) {
  3766  				_, _, err = client.Repositories.ReplaceTeamRestrictions(ctx, "\n", "\n", "\n", input)
  3767  				return err
  3768  			})
  3769  
  3770  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  3771  				got, resp, err := client.Repositories.ReplaceTeamRestrictions(ctx, "o", "r", test.branch, input)
  3772  				if got != nil {
  3773  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  3774  				}
  3775  				return resp, err
  3776  			})
  3777  		})
  3778  	}
  3779  }
  3780  
  3781  func TestRepositoriesService_AddTeamRestrictions(t *testing.T) {
  3782  	tests := []struct {
  3783  		branch  string
  3784  		urlPath string
  3785  	}{
  3786  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/teams"},
  3787  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/teams"},
  3788  	}
  3789  
  3790  	for _, test := range tests {
  3791  		t.Run(test.branch, func(t *testing.T) {
  3792  			client, mux, _, teardown := setup()
  3793  			defer teardown()
  3794  
  3795  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  3796  				testMethod(t, r, "POST")
  3797  				fmt.Fprint(w, `[{
  3798  				"name": "octocat"
  3799  			}]`)
  3800  			})
  3801  			input := []string{"octocat"}
  3802  			ctx := context.Background()
  3803  			got, _, err := client.Repositories.AddTeamRestrictions(ctx, "o", "r", test.branch, input)
  3804  			if err != nil {
  3805  				t.Errorf("Repositories.AddTeamRestrictions returned error: %v", err)
  3806  			}
  3807  			want := []*Team{
  3808  				{Name: String("octocat")},
  3809  			}
  3810  			if !cmp.Equal(got, want) {
  3811  				t.Errorf("Repositories.AddTeamRestrictions returned %+v, want %+v", got, want)
  3812  			}
  3813  
  3814  			const methodName = "AddTeamRestrictions"
  3815  			testBadOptions(t, methodName, func() (err error) {
  3816  				_, _, err = client.Repositories.AddTeamRestrictions(ctx, "\n", "\n", "\n", input)
  3817  				return err
  3818  			})
  3819  
  3820  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  3821  				got, resp, err := client.Repositories.AddTeamRestrictions(ctx, "o", "r", test.branch, input)
  3822  				if got != nil {
  3823  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  3824  				}
  3825  				return resp, err
  3826  			})
  3827  		})
  3828  	}
  3829  }
  3830  
  3831  func TestRepositoriesService_RemoveTeamRestrictions(t *testing.T) {
  3832  	tests := []struct {
  3833  		branch  string
  3834  		urlPath string
  3835  	}{
  3836  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/teams"},
  3837  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/teams"},
  3838  	}
  3839  
  3840  	for _, test := range tests {
  3841  		t.Run(test.branch, func(t *testing.T) {
  3842  			client, mux, _, teardown := setup()
  3843  			defer teardown()
  3844  
  3845  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  3846  				testMethod(t, r, "DELETE")
  3847  				fmt.Fprint(w, `[]`)
  3848  			})
  3849  			input := []string{"octocat"}
  3850  			ctx := context.Background()
  3851  			got, _, err := client.Repositories.RemoveTeamRestrictions(ctx, "o", "r", test.branch, input)
  3852  			if err != nil {
  3853  				t.Errorf("Repositories.RemoveTeamRestrictions returned error: %v", err)
  3854  			}
  3855  			want := []*Team{}
  3856  			if !cmp.Equal(got, want) {
  3857  				t.Errorf("Repositories.RemoveTeamRestrictions returned %+v, want %+v", got, want)
  3858  			}
  3859  
  3860  			const methodName = "RemoveTeamRestrictions"
  3861  			testBadOptions(t, methodName, func() (err error) {
  3862  				_, _, err = client.Repositories.RemoveTeamRestrictions(ctx, "\n", "\n", "\n", input)
  3863  				return err
  3864  			})
  3865  
  3866  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  3867  				got, resp, err := client.Repositories.RemoveTeamRestrictions(ctx, "o", "r", test.branch, input)
  3868  				if got != nil {
  3869  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  3870  				}
  3871  				return resp, err
  3872  			})
  3873  		})
  3874  	}
  3875  }
  3876  
  3877  func TestRepositoriesService_ListUserRestrictions(t *testing.T) {
  3878  	tests := []struct {
  3879  		branch  string
  3880  		urlPath string
  3881  	}{
  3882  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/users"},
  3883  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/users"},
  3884  	}
  3885  
  3886  	for _, test := range tests {
  3887  		t.Run(test.branch, func(t *testing.T) {
  3888  			client, mux, _, teardown := setup()
  3889  			defer teardown()
  3890  
  3891  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  3892  				testMethod(t, r, "GET")
  3893  			})
  3894  
  3895  			ctx := context.Background()
  3896  			_, _, err := client.Repositories.ListUserRestrictions(ctx, "o", "r", test.branch)
  3897  			if err != nil {
  3898  				t.Errorf("Repositories.ListUserRestrictions returned error: %v", err)
  3899  			}
  3900  
  3901  			const methodName = "ListUserRestrictions"
  3902  			testBadOptions(t, methodName, func() (err error) {
  3903  				_, _, err = client.Repositories.ListUserRestrictions(ctx, "\n", "\n", "\n")
  3904  				return err
  3905  			})
  3906  
  3907  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  3908  				got, resp, err := client.Repositories.ListUserRestrictions(ctx, "o", "r", test.branch)
  3909  				if got != nil {
  3910  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  3911  				}
  3912  				return resp, err
  3913  			})
  3914  		})
  3915  	}
  3916  }
  3917  
  3918  func TestRepositoriesService_ReplaceUserRestrictions(t *testing.T) {
  3919  	tests := []struct {
  3920  		branch  string
  3921  		urlPath string
  3922  	}{
  3923  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/users"},
  3924  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/users"},
  3925  	}
  3926  
  3927  	for _, test := range tests {
  3928  		t.Run(test.branch, func(t *testing.T) {
  3929  			client, mux, _, teardown := setup()
  3930  			defer teardown()
  3931  
  3932  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  3933  				testMethod(t, r, "PUT")
  3934  				fmt.Fprint(w, `[{
  3935  				"name": "octocat"
  3936  			}]`)
  3937  			})
  3938  			input := []string{"octocat"}
  3939  			ctx := context.Background()
  3940  			got, _, err := client.Repositories.ReplaceUserRestrictions(ctx, "o", "r", test.branch, input)
  3941  			if err != nil {
  3942  				t.Errorf("Repositories.ReplaceUserRestrictions returned error: %v", err)
  3943  			}
  3944  			want := []*User{
  3945  				{Name: String("octocat")},
  3946  			}
  3947  			if !cmp.Equal(got, want) {
  3948  				t.Errorf("Repositories.ReplaceUserRestrictions returned %+v, want %+v", got, want)
  3949  			}
  3950  
  3951  			const methodName = "ReplaceUserRestrictions"
  3952  			testBadOptions(t, methodName, func() (err error) {
  3953  				_, _, err = client.Repositories.ReplaceUserRestrictions(ctx, "\n", "\n", "\n", input)
  3954  				return err
  3955  			})
  3956  
  3957  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  3958  				got, resp, err := client.Repositories.ReplaceUserRestrictions(ctx, "o", "r", test.branch, input)
  3959  				if got != nil {
  3960  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  3961  				}
  3962  				return resp, err
  3963  			})
  3964  		})
  3965  	}
  3966  }
  3967  
  3968  func TestRepositoriesService_AddUserRestrictions(t *testing.T) {
  3969  	tests := []struct {
  3970  		branch  string
  3971  		urlPath string
  3972  	}{
  3973  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/users"},
  3974  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/users"},
  3975  	}
  3976  
  3977  	for _, test := range tests {
  3978  		t.Run(test.branch, func(t *testing.T) {
  3979  			client, mux, _, teardown := setup()
  3980  			defer teardown()
  3981  
  3982  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  3983  				testMethod(t, r, "POST")
  3984  				fmt.Fprint(w, `[{
  3985  				"name": "octocat"
  3986  			}]`)
  3987  			})
  3988  			input := []string{"octocat"}
  3989  			ctx := context.Background()
  3990  			got, _, err := client.Repositories.AddUserRestrictions(ctx, "o", "r", test.branch, input)
  3991  			if err != nil {
  3992  				t.Errorf("Repositories.AddUserRestrictions returned error: %v", err)
  3993  			}
  3994  			want := []*User{
  3995  				{Name: String("octocat")},
  3996  			}
  3997  			if !cmp.Equal(got, want) {
  3998  				t.Errorf("Repositories.AddUserRestrictions returned %+v, want %+v", got, want)
  3999  			}
  4000  
  4001  			const methodName = "AddUserRestrictions"
  4002  			testBadOptions(t, methodName, func() (err error) {
  4003  				_, _, err = client.Repositories.AddUserRestrictions(ctx, "\n", "\n", "\n", input)
  4004  				return err
  4005  			})
  4006  
  4007  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  4008  				got, resp, err := client.Repositories.AddUserRestrictions(ctx, "o", "r", test.branch, input)
  4009  				if got != nil {
  4010  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  4011  				}
  4012  				return resp, err
  4013  			})
  4014  		})
  4015  	}
  4016  }
  4017  
  4018  func TestRepositoriesService_RemoveUserRestrictions(t *testing.T) {
  4019  	tests := []struct {
  4020  		branch  string
  4021  		urlPath string
  4022  	}{
  4023  		{branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/users"},
  4024  		{branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat/branch-50%/protection/restrictions/users"},
  4025  	}
  4026  
  4027  	for _, test := range tests {
  4028  		t.Run(test.branch, func(t *testing.T) {
  4029  			client, mux, _, teardown := setup()
  4030  			defer teardown()
  4031  
  4032  			mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) {
  4033  				testMethod(t, r, "DELETE")
  4034  				fmt.Fprint(w, `[]`)
  4035  			})
  4036  			input := []string{"octocat"}
  4037  			ctx := context.Background()
  4038  			got, _, err := client.Repositories.RemoveUserRestrictions(ctx, "o", "r", test.branch, input)
  4039  			if err != nil {
  4040  				t.Errorf("Repositories.RemoveUserRestrictions returned error: %v", err)
  4041  			}
  4042  			want := []*User{}
  4043  			if !cmp.Equal(got, want) {
  4044  				t.Errorf("Repositories.RemoveUserRestrictions returned %+v, want %+v", got, want)
  4045  			}
  4046  
  4047  			const methodName = "RemoveUserRestrictions"
  4048  			testBadOptions(t, methodName, func() (err error) {
  4049  				_, _, err = client.Repositories.RemoveUserRestrictions(ctx, "\n", "\n", "\n", input)
  4050  				return err
  4051  			})
  4052  
  4053  			testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  4054  				got, resp, err := client.Repositories.RemoveUserRestrictions(ctx, "o", "r", test.branch, input)
  4055  				if got != nil {
  4056  					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  4057  				}
  4058  				return resp, err
  4059  			})
  4060  		})
  4061  	}
  4062  }
  4063  
  4064  func TestRepositoriesService_Transfer(t *testing.T) {
  4065  	client, mux, _, teardown := setup()
  4066  	defer teardown()
  4067  
  4068  	input := TransferRequest{NewOwner: "a", NewName: String("b"), TeamID: []int64{123}}
  4069  
  4070  	mux.HandleFunc("/repos/o/r/transfer", func(w http.ResponseWriter, r *http.Request) {
  4071  		var v TransferRequest
  4072  		assertNilError(t, json.NewDecoder(r.Body).Decode(&v))
  4073  
  4074  		testMethod(t, r, "POST")
  4075  		if !cmp.Equal(v, input) {
  4076  			t.Errorf("Request body = %+v, want %+v", v, input)
  4077  		}
  4078  
  4079  		fmt.Fprint(w, `{"owner":{"login":"a"}}`)
  4080  	})
  4081  
  4082  	ctx := context.Background()
  4083  	got, _, err := client.Repositories.Transfer(ctx, "o", "r", input)
  4084  	if err != nil {
  4085  		t.Errorf("Repositories.Transfer returned error: %v", err)
  4086  	}
  4087  
  4088  	want := &Repository{Owner: &User{Login: String("a")}}
  4089  	if !cmp.Equal(got, want) {
  4090  		t.Errorf("Repositories.Transfer returned %+v, want %+v", got, want)
  4091  	}
  4092  
  4093  	const methodName = "Transfer"
  4094  	testBadOptions(t, methodName, func() (err error) {
  4095  		_, _, err = client.Repositories.Transfer(ctx, "\n", "\n", input)
  4096  		return err
  4097  	})
  4098  
  4099  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  4100  		got, resp, err := client.Repositories.Transfer(ctx, "o", "r", input)
  4101  		if got != nil {
  4102  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  4103  		}
  4104  		return resp, err
  4105  	})
  4106  }
  4107  
  4108  func TestRepositoriesService_Dispatch(t *testing.T) {
  4109  	client, mux, _, teardown := setup()
  4110  	defer teardown()
  4111  
  4112  	var input DispatchRequestOptions
  4113  
  4114  	mux.HandleFunc("/repos/o/r/dispatches", func(w http.ResponseWriter, r *http.Request) {
  4115  		var v DispatchRequestOptions
  4116  		assertNilError(t, json.NewDecoder(r.Body).Decode(&v))
  4117  
  4118  		testMethod(t, r, "POST")
  4119  		if !cmp.Equal(v, input) {
  4120  			t.Errorf("Request body = %+v, want %+v", v, input)
  4121  		}
  4122  
  4123  		fmt.Fprint(w, `{"owner":{"login":"a"}}`)
  4124  	})
  4125  
  4126  	ctx := context.Background()
  4127  
  4128  	testCases := []interface{}{
  4129  		nil,
  4130  		struct {
  4131  			Foo string
  4132  		}{
  4133  			Foo: "test",
  4134  		},
  4135  		struct {
  4136  			Bar int
  4137  		}{
  4138  			Bar: 42,
  4139  		},
  4140  		struct {
  4141  			Foo string
  4142  			Bar int
  4143  			Baz bool
  4144  		}{
  4145  			Foo: "test",
  4146  			Bar: 42,
  4147  			Baz: false,
  4148  		},
  4149  	}
  4150  
  4151  	for _, tc := range testCases {
  4152  		if tc == nil {
  4153  			input = DispatchRequestOptions{EventType: "go"}
  4154  		} else {
  4155  			bytes, _ := json.Marshal(tc)
  4156  			payload := json.RawMessage(bytes)
  4157  			input = DispatchRequestOptions{EventType: "go", ClientPayload: &payload}
  4158  		}
  4159  
  4160  		got, _, err := client.Repositories.Dispatch(ctx, "o", "r", input)
  4161  		if err != nil {
  4162  			t.Errorf("Repositories.Dispatch returned error: %v", err)
  4163  		}
  4164  
  4165  		want := &Repository{Owner: &User{Login: String("a")}}
  4166  		if !cmp.Equal(got, want) {
  4167  			t.Errorf("Repositories.Dispatch returned %+v, want %+v", got, want)
  4168  		}
  4169  	}
  4170  
  4171  	const methodName = "Dispatch"
  4172  	testBadOptions(t, methodName, func() (err error) {
  4173  		_, _, err = client.Repositories.Dispatch(ctx, "\n", "\n", input)
  4174  		return err
  4175  	})
  4176  
  4177  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  4178  		got, resp, err := client.Repositories.Dispatch(ctx, "o", "r", input)
  4179  		if got != nil {
  4180  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  4181  		}
  4182  		return resp, err
  4183  	})
  4184  }
  4185  
  4186  func TestAdvancedSecurity_Marshal(t *testing.T) {
  4187  	testJSONMarshal(t, &AdvancedSecurity{}, "{}")
  4188  
  4189  	u := &AdvancedSecurity{
  4190  		Status: String("status"),
  4191  	}
  4192  
  4193  	want := `{
  4194  		"status": "status"
  4195  	}`
  4196  
  4197  	testJSONMarshal(t, u, want)
  4198  }
  4199  
  4200  func TestAuthorizedActorsOnly_Marshal(t *testing.T) {
  4201  	testJSONMarshal(t, &AuthorizedActorsOnly{}, "{}")
  4202  
  4203  	u := &AuthorizedActorsOnly{
  4204  		From: Bool(true),
  4205  	}
  4206  
  4207  	want := `{
  4208  		"from" : true
  4209  	}`
  4210  
  4211  	testJSONMarshal(t, u, want)
  4212  }
  4213  
  4214  func TestDispatchRequestOptions_Marshal(t *testing.T) {
  4215  	testJSONMarshal(t, &DispatchRequestOptions{}, "{}")
  4216  
  4217  	cp := json.RawMessage(`{"testKey":"testValue"}`)
  4218  	u := &DispatchRequestOptions{
  4219  		EventType:     "test_event_type",
  4220  		ClientPayload: &cp,
  4221  	}
  4222  
  4223  	want := `{
  4224  		"event_type": "test_event_type",
  4225  		"client_payload": {
  4226  		  "testKey": "testValue"
  4227  		}
  4228  	  }`
  4229  
  4230  	testJSONMarshal(t, u, want)
  4231  }
  4232  
  4233  func TestTransferRequest_Marshal(t *testing.T) {
  4234  	testJSONMarshal(t, &TransferRequest{}, "{}")
  4235  
  4236  	u := &TransferRequest{
  4237  		NewOwner: "testOwner",
  4238  		NewName:  String("testName"),
  4239  		TeamID:   []int64{1, 2},
  4240  	}
  4241  
  4242  	want := `{
  4243  		"new_owner": "testOwner",
  4244  		"new_name": "testName",
  4245  		"team_ids": [1,2]
  4246  	}`
  4247  
  4248  	testJSONMarshal(t, u, want)
  4249  }
  4250  
  4251  func TestSignaturesProtectedBranch_Marshal(t *testing.T) {
  4252  	testJSONMarshal(t, &SignaturesProtectedBranch{}, "{}")
  4253  
  4254  	u := &SignaturesProtectedBranch{
  4255  		URL:     String("https://www.testURL.in"),
  4256  		Enabled: Bool(false),
  4257  	}
  4258  
  4259  	want := `{
  4260  		"url": "https://www.testURL.in",
  4261  		"enabled": false
  4262  	}`
  4263  
  4264  	testJSONMarshal(t, u, want)
  4265  
  4266  	u2 := &SignaturesProtectedBranch{
  4267  		URL:     String("testURL"),
  4268  		Enabled: Bool(true),
  4269  	}
  4270  
  4271  	want2 := `{
  4272  		"url": "testURL",
  4273  		"enabled": true
  4274  	}`
  4275  
  4276  	testJSONMarshal(t, u2, want2)
  4277  }
  4278  
  4279  func TestDismissalRestrictionsRequest_Marshal(t *testing.T) {
  4280  	testJSONMarshal(t, &DismissalRestrictionsRequest{}, "{}")
  4281  
  4282  	u := &DismissalRestrictionsRequest{
  4283  		Users: &[]string{"user1", "user2"},
  4284  		Teams: &[]string{"team1", "team2"},
  4285  		Apps:  &[]string{"app1", "app2"},
  4286  	}
  4287  
  4288  	want := `{
  4289  		"users": ["user1","user2"],
  4290  		"teams": ["team1","team2"],
  4291  		"apps": ["app1","app2"]
  4292  	}`
  4293  
  4294  	testJSONMarshal(t, u, want)
  4295  }
  4296  
  4297  func TestAdminEnforcement_Marshal(t *testing.T) {
  4298  	testJSONMarshal(t, &AdminEnforcement{}, "{}")
  4299  
  4300  	u := &AdminEnforcement{
  4301  		URL:     String("https://www.test-url.in"),
  4302  		Enabled: false,
  4303  	}
  4304  
  4305  	want := `{
  4306  		"url": "https://www.test-url.in",
  4307  		"enabled": false
  4308  	}`
  4309  
  4310  	testJSONMarshal(t, u, want)
  4311  }
  4312  
  4313  func TestPullRequestReviewsEnforcementUpdate_Marshal(t *testing.T) {
  4314  	testJSONMarshal(t, &PullRequestReviewsEnforcementUpdate{}, "{}")
  4315  
  4316  	u := &PullRequestReviewsEnforcementUpdate{
  4317  		BypassPullRequestAllowancesRequest: &BypassPullRequestAllowancesRequest{
  4318  			Users: []string{"user1", "user2"},
  4319  			Teams: []string{"team1", "team2"},
  4320  			Apps:  []string{"app1", "app2"},
  4321  		},
  4322  		DismissStaleReviews:          Bool(false),
  4323  		RequireCodeOwnerReviews:      Bool(true),
  4324  		RequiredApprovingReviewCount: 2,
  4325  	}
  4326  
  4327  	want := `{
  4328  		"bypass_pull_request_allowances": {
  4329  			"users": ["user1","user2"],
  4330  			"teams": ["team1","team2"],
  4331  			"apps": ["app1","app2"]
  4332  		},
  4333  		"dismiss_stale_reviews": false,
  4334  		"require_code_owner_reviews": true,
  4335  		"required_approving_review_count": 2
  4336  	}`
  4337  
  4338  	testJSONMarshal(t, u, want)
  4339  }
  4340  
  4341  func TestRequiredStatusCheck_Marshal(t *testing.T) {
  4342  	testJSONMarshal(t, &RequiredStatusCheck{}, "{}")
  4343  
  4344  	u := &RequiredStatusCheck{
  4345  		Context: "ctx",
  4346  		AppID:   Int64(1),
  4347  	}
  4348  
  4349  	want := `{
  4350  		"context": "ctx",
  4351  		"app_id": 1
  4352  	}`
  4353  
  4354  	testJSONMarshal(t, u, want)
  4355  }
  4356  
  4357  func TestRepositoryTag_Marshal(t *testing.T) {
  4358  	testJSONMarshal(t, &RepositoryTag{}, "{}")
  4359  
  4360  	u := &RepositoryTag{
  4361  		Name: String("v0.1"),
  4362  		Commit: &Commit{
  4363  			SHA: String("sha"),
  4364  			URL: String("url"),
  4365  		},
  4366  		ZipballURL: String("zball"),
  4367  		TarballURL: String("tball"),
  4368  	}
  4369  
  4370  	want := `{
  4371  		"name": "v0.1",
  4372  		"commit": {
  4373  			"sha": "sha",
  4374  			"url": "url"
  4375  		},
  4376  		"zipball_url": "zball",
  4377  		"tarball_url": "tball"
  4378  	}`
  4379  
  4380  	testJSONMarshal(t, u, want)
  4381  }
  4382  
  4383  func TestRepositoriesService_EnablePrivateReporting(t *testing.T) {
  4384  	client, mux, _, teardown := setup()
  4385  	defer teardown()
  4386  
  4387  	mux.HandleFunc("/repos/owner/repo/private-vulnerability-reporting", func(w http.ResponseWriter, r *http.Request) {
  4388  		testMethod(t, r, "PUT")
  4389  		w.WriteHeader(http.StatusNoContent)
  4390  	})
  4391  
  4392  	ctx := context.Background()
  4393  	_, err := client.Repositories.EnablePrivateReporting(ctx, "owner", "repo")
  4394  	if err != nil {
  4395  		t.Errorf("Repositories.EnablePrivateReporting returned error: %v", err)
  4396  	}
  4397  
  4398  	const methodName = "EnablePrivateReporting"
  4399  	testBadOptions(t, methodName, func() (err error) {
  4400  		_, err = client.Repositories.EnablePrivateReporting(ctx, "\n", "\n")
  4401  		return err
  4402  	})
  4403  
  4404  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  4405  		return client.Repositories.EnablePrivateReporting(ctx, "owner", "repo")
  4406  	})
  4407  }
  4408  
  4409  func TestRepositoriesService_DisablePrivateReporting(t *testing.T) {
  4410  	client, mux, _, teardown := setup()
  4411  	defer teardown()
  4412  
  4413  	mux.HandleFunc("/repos/owner/repo/private-vulnerability-reporting", func(w http.ResponseWriter, r *http.Request) {
  4414  		testMethod(t, r, "DELETE")
  4415  		w.WriteHeader(http.StatusNoContent)
  4416  	})
  4417  
  4418  	ctx := context.Background()
  4419  	_, err := client.Repositories.DisablePrivateReporting(ctx, "owner", "repo")
  4420  	if err != nil {
  4421  		t.Errorf("Repositories.DisablePrivateReporting returned error: %v", err)
  4422  	}
  4423  
  4424  	const methodName = "DisablePrivateReporting"
  4425  	testBadOptions(t, methodName, func() (err error) {
  4426  		_, err = client.Repositories.DisablePrivateReporting(ctx, "\n", "\n")
  4427  		return err
  4428  	})
  4429  
  4430  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  4431  		return client.Repositories.DisablePrivateReporting(ctx, "owner", "repo")
  4432  	})
  4433  }
  4434  
  4435  func TestRepositoriesService_IsPrivateReportingEnabled(t *testing.T) {
  4436  	client, mux, _, teardown := setup()
  4437  	defer teardown()
  4438  
  4439  	mux.HandleFunc("/repos/owner/repo/private-vulnerability-reporting", func(w http.ResponseWriter, r *http.Request) {
  4440  		testMethod(t, r, "GET")
  4441  		fmt.Fprint(w, `{"enabled": true}`)
  4442  	})
  4443  
  4444  	ctx := context.Background()
  4445  	enabled, _, err := client.Repositories.IsPrivateReportingEnabled(ctx, "owner", "repo")
  4446  	if err != nil {
  4447  		t.Errorf("Repositories.IsPrivateReportingEnabled returned error: %v", err)
  4448  	}
  4449  	if want := true; enabled != want {
  4450  		t.Errorf("Repositories.IsPrivateReportingEnabled returned %+v, want %+v", enabled, want)
  4451  	}
  4452  
  4453  	const methodName = "IsPrivateReportingEnabled"
  4454  	testBadOptions(t, methodName, func() (err error) {
  4455  		_, _, err = client.Repositories.IsPrivateReportingEnabled(ctx, "\n", "\n")
  4456  		return err
  4457  	})
  4458  
  4459  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  4460  		got, resp, err := client.Repositories.IsPrivateReportingEnabled(ctx, "owner", "repo")
  4461  		if got {
  4462  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want false", methodName, got)
  4463  		}
  4464  		return resp, err
  4465  	})
  4466  }
  4467  
  4468  func TestRepository_UnmarshalJSON(t *testing.T) {
  4469  	var testCases = map[string]struct {
  4470  		data           []byte
  4471  		wantRepository Repository
  4472  		wantErr        bool
  4473  	}{
  4474  		"Empty": {
  4475  			data:           []byte("{}"),
  4476  			wantRepository: Repository{},
  4477  			wantErr:        false,
  4478  		},
  4479  		"Invalid JSON": {
  4480  			data:           []byte("{"),
  4481  			wantRepository: Repository{},
  4482  			wantErr:        true,
  4483  		},
  4484  		"Partial project": {
  4485  			data:           []byte(`{"id":10270722,"name":"go-github","private":false,"owner":{"login":"google"},"created_at":"2013-05-24T16:42:58Z","license":{},"topics":["github"],"permissions":{"pull":true},"custom_properties":{},"organization":{"login":"google"}}`),
  4486  			wantRepository: Repository{ID: Int64(10270722), Name: String("go-github"), Private: Bool(false), Owner: &User{Login: String("google")}, CreatedAt: &Timestamp{time.Date(2013, 5, 24, 16, 42, 58, 0, time.UTC)}, License: &License{}, Topics: []string{"github"}, Permissions: map[string]bool{"pull": true}, CustomProperties: map[string]interface{}{}, Organization: &Organization{Login: String("google")}},
  4487  			wantErr:        false,
  4488  		},
  4489  		"With custom properties": {
  4490  			data:           []byte(`{"custom_properties":{"boolean":"false","text":"a","single-select":"a","multi-select":["a","b","c"]}}`),
  4491  			wantRepository: Repository{CustomProperties: map[string]interface{}{"boolean": "false", "text": "a", "single-select": "a", "multi-select": []interface{}{"a", "b", "c"}}},
  4492  			wantErr:        false,
  4493  		},
  4494  	}
  4495  
  4496  	for name, tt := range testCases {
  4497  		tt := tt
  4498  		t.Run(name, func(t *testing.T) {
  4499  			pk := Repository{}
  4500  			err := json.Unmarshal(tt.data, &pk)
  4501  			if err == nil && tt.wantErr {
  4502  				t.Errorf("Repository.UnmarshalJSON returned nil instead of an error")
  4503  			}
  4504  			if err != nil && !tt.wantErr {
  4505  				t.Errorf("Repository.UnmarshalJSON returned an unexpected error: %+v", err)
  4506  			}
  4507  			if !cmp.Equal(tt.wantRepository, pk) {
  4508  				t.Errorf("Repository.UnmarshalJSON expected repository %+v, got %+v", tt.wantRepository, pk)
  4509  			}
  4510  		})
  4511  	}
  4512  }