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