github.com/google/go-github/v65@v65.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 }