github.com/google/go-github/v70@v70.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 t.Parallel() 24 client, mux, _ := setup(t) 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: Ptr(int64(1))}, {ID: Ptr(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 t.Parallel() 55 client, mux, _ := setup(t) 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: Ptr(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 t.Parallel() 100 client, mux, _ := setup(t) 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: Ptr(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 t.Parallel() 127 client, _, _ := setup(t) 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 t.Parallel() 136 client, mux, _ := setup(t) 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: Ptr(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 t.Parallel() 181 client, _, _ := setup(t) 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 t.Parallel() 190 client, mux, _ := setup(t) 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: Ptr(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 t.Parallel() 224 client, mux, _ := setup(t) 225 226 input := &Repository{ 227 Name: Ptr("n"), 228 Archived: Ptr(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: Ptr("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: Ptr(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 t.Parallel() 274 client, mux, _ := setup(t) 275 276 input := &Repository{ 277 Name: Ptr("n"), 278 Archived: Ptr(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: Ptr("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: Ptr(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 t.Parallel() 310 client, mux, _ := setup(t) 311 312 templateRepoReq := &TemplateRepoRequest{ 313 Name: Ptr("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: Ptr("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: Ptr(int64(1)), Name: Ptr("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 t.Parallel() 358 client, mux, _ := setup(t) 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: Ptr(int64(1)), Name: Ptr("n"), Description: Ptr("d"), Owner: &User{Login: Ptr("l")}, License: &License{Key: Ptr("mit")}, SecurityAndAnalysis: &SecurityAndAnalysis{AdvancedSecurity: &AdvancedSecurity{Status: Ptr("enabled")}, SecretScanning: &SecretScanning{Ptr("enabled")}, SecretScanningPushProtection: &SecretScanningPushProtection{Ptr("enabled")}, DependabotSecurityUpdates: &DependabotSecurityUpdates{Ptr("enabled")}, SecretScanningValidityChecks: &SecretScanningValidityChecks{Ptr("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 t.Parallel() 395 client, mux, _ := setup(t) 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: Ptr("key"), 418 Name: Ptr("name"), 419 URL: Ptr("url"), 420 Body: Ptr("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 t.Parallel() 444 client, mux, _ := setup(t) 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: Ptr(int64(1)), Name: Ptr("n"), Description: Ptr("d"), Owner: &User{Login: Ptr("l")}, License: &License{Key: Ptr("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 t.Parallel() 474 client, mux, _ := setup(t) 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: Ptr(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 t.Parallel() 520 client, mux, _ := setup(t) 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 t.Parallel() 545 client, _, _ := setup(t) 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 t.Parallel() 554 client, _, _ := setup(t) 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 t.Parallel() 563 client, mux, _ := setup(t) 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 t.Parallel() 599 client, mux, _ := setup(t) 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 t.Parallel() 626 client, mux, _ := setup(t) 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 t.Parallel() 653 client, mux, _ := setup(t) 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 t.Parallel() 669 client, mux, _ := setup(t) 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: Ptr(true), 684 Paused: Ptr(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 t.Parallel() 706 client, mux, _ := setup(t) 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 t.Parallel() 722 client, mux, _ := setup(t) 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: Ptr(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 t.Parallel() 762 client, mux, _ := setup(t) 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 t.Parallel() 797 client, mux, _ := setup(t) 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: Ptr(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 t.Parallel() 834 client, mux, _ := setup(t) 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: Ptr("n"), 852 Commit: &Commit{ 853 SHA: Ptr("s"), 854 URL: Ptr("u"), 855 }, 856 ZipballURL: Ptr("z"), 857 TarballURL: Ptr("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 t.Parallel() 881 client, mux, _ := setup(t) 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: Ptr("master"), Commit: &RepositoryCommit{SHA: Ptr("a57781"), URL: Ptr("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 t.Parallel() 921 client, mux, _ := setup(t) 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%2fbranch-50%25"}, 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: Ptr("n"), 945 Commit: &RepositoryCommit{ 946 SHA: Ptr("s"), 947 Commit: &Commit{ 948 Message: Ptr("m"), 949 }, 950 }, 951 Protected: Ptr(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 t.Parallel() 973 tests := []struct { 974 branch string 975 urlPath string 976 }{ 977 {branch: "b", urlPath: "/repos/o/r/branches/b"}, 978 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25"}, 979 } 980 981 for _, test := range tests { 982 test := test 983 t.Run(test.branch, func(t *testing.T) { 984 t.Parallel() 985 client, mux, _ := setup(t) 986 987 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 988 testMethod(t, r, "GET") 989 fmt.Fprint(w, `{"name":"n", "commit":{"sha":...truncated`) 990 }) 991 992 ctx := context.Background() 993 if _, _, err := client.Repositories.GetBranch(ctx, "o", "r", test.branch, 0); err == nil { 994 t.Error("Repositories.GetBranch returned no error; wanted JSON error") 995 } 996 }) 997 } 998 } 999 1000 func TestRepositoriesService_GetBranch_StatusMovedPermanently_followRedirects(t *testing.T) { 1001 t.Parallel() 1002 client, mux, serverURL := setup(t) 1003 1004 mux.HandleFunc("/repos/o/r/branches/b", func(w http.ResponseWriter, r *http.Request) { 1005 testMethod(t, r, "GET") 1006 redirectURL, _ := url.Parse(serverURL + baseURLPath + "/repos/o/r/branches/br") 1007 http.Redirect(w, r, redirectURL.String(), http.StatusMovedPermanently) 1008 }) 1009 mux.HandleFunc("/repos/o/r/branches/br", func(w http.ResponseWriter, r *http.Request) { 1010 testMethod(t, r, "GET") 1011 fmt.Fprint(w, `{"name":"n", "commit":{"sha":"s","commit":{"message":"m"}}, "protected":true, "protection":{"required_status_checks":{"contexts":["c"]}}}`) 1012 }) 1013 ctx := context.Background() 1014 branch, resp, err := client.Repositories.GetBranch(ctx, "o", "r", "b", 1) 1015 if err != nil { 1016 t.Errorf("Repositories.GetBranch returned error: %v", err) 1017 } 1018 if resp.StatusCode != http.StatusOK { 1019 t.Errorf("Repositories.GetBranch returned status: %d, want %d", resp.StatusCode, http.StatusOK) 1020 } 1021 1022 want := &Branch{ 1023 Name: Ptr("n"), 1024 Commit: &RepositoryCommit{ 1025 SHA: Ptr("s"), 1026 Commit: &Commit{ 1027 Message: Ptr("m"), 1028 }, 1029 }, 1030 Protected: Ptr(true), 1031 Protection: &Protection{ 1032 RequiredStatusChecks: &RequiredStatusChecks{ 1033 Contexts: &[]string{"c"}, 1034 }, 1035 }, 1036 } 1037 if !cmp.Equal(branch, want) { 1038 t.Errorf("Repositories.GetBranch returned %+v, want %+v", branch, want) 1039 } 1040 } 1041 1042 func TestRepositoriesService_GetBranch_notFound(t *testing.T) { 1043 t.Parallel() 1044 tests := []struct { 1045 branch string 1046 urlPath string 1047 }{ 1048 {branch: "b", urlPath: "/repos/o/r/branches/b"}, 1049 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat-branch-50%"}, 1050 } 1051 1052 for _, test := range tests { 1053 test := test 1054 t.Run(test.branch, func(t *testing.T) { 1055 t.Parallel() 1056 client, mux, _ := setup(t) 1057 1058 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 1059 testMethod(t, r, "GET") 1060 http.Error(w, "branch not found", http.StatusNotFound) 1061 }) 1062 ctx := context.Background() 1063 _, resp, err := client.Repositories.GetBranch(ctx, "o", "r", test.branch, 1) 1064 if err == nil { 1065 t.Error("Repositories.GetBranch returned error: nil") 1066 } 1067 if resp.StatusCode != http.StatusNotFound { 1068 t.Errorf("Repositories.GetBranch returned status: %d, want %d", resp.StatusCode, http.StatusNotFound) 1069 } 1070 1071 // Add custom round tripper 1072 client.client.Transport = roundTripperFunc(func(r *http.Request) (*http.Response, error) { 1073 return nil, errors.New("failed to get branch") 1074 }) 1075 1076 const methodName = "GetBranch" 1077 testBadOptions(t, methodName, func() (err error) { 1078 _, _, err = client.Repositories.GetBranch(ctx, "\n", "\n", "\n", 1) 1079 return err 1080 }) 1081 }) 1082 } 1083 } 1084 1085 func TestRepositoriesService_RenameBranch(t *testing.T) { 1086 t.Parallel() 1087 tests := []struct { 1088 branch string 1089 urlPath string 1090 }{ 1091 {branch: "b", urlPath: "/repos/o/r/branches/b/rename"}, 1092 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/rename"}, 1093 } 1094 1095 for _, test := range tests { 1096 test := test 1097 t.Run(test.branch, func(t *testing.T) { 1098 t.Parallel() 1099 client, mux, _ := setup(t) 1100 1101 renameBranchReq := "nn" 1102 1103 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 1104 v := new(renameBranchRequest) 1105 assertNilError(t, json.NewDecoder(r.Body).Decode(v)) 1106 1107 testMethod(t, r, "POST") 1108 want := &renameBranchRequest{NewName: renameBranchReq} 1109 if !cmp.Equal(v, want) { 1110 t.Errorf("Request body = %+v, want %+v", v, want) 1111 } 1112 1113 fmt.Fprint(w, `{"protected":true,"name":"nn"}`) 1114 }) 1115 1116 ctx := context.Background() 1117 got, _, err := client.Repositories.RenameBranch(ctx, "o", "r", test.branch, renameBranchReq) 1118 if err != nil { 1119 t.Errorf("Repositories.RenameBranch returned error: %v", err) 1120 } 1121 1122 want := &Branch{Name: Ptr("nn"), Protected: Ptr(true)} 1123 if !cmp.Equal(got, want) { 1124 t.Errorf("Repositories.RenameBranch returned %+v, want %+v", got, want) 1125 } 1126 1127 const methodName = "RenameBranch" 1128 testBadOptions(t, methodName, func() (err error) { 1129 _, _, err = client.Repositories.RenameBranch(ctx, "\n", "\n", "\n", renameBranchReq) 1130 return err 1131 }) 1132 1133 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 1134 got, resp, err := client.Repositories.RenameBranch(ctx, "o", "r", test.branch, renameBranchReq) 1135 if got != nil { 1136 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 1137 } 1138 return resp, err 1139 }) 1140 }) 1141 } 1142 } 1143 1144 func TestRepositoriesService_GetBranchProtection(t *testing.T) { 1145 t.Parallel() 1146 tests := []struct { 1147 branch string 1148 urlPath string 1149 enforceAdminsURLPath string 1150 }{ 1151 {branch: "b", urlPath: "/repos/o/r/branches/b/protection", enforceAdminsURLPath: "/repos/o/r/branches/b/protection/enforce_admins"}, 1152 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection", enforceAdminsURLPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/enforce_admins"}, 1153 } 1154 1155 for _, test := range tests { 1156 test := test 1157 t.Run(test.branch, func(t *testing.T) { 1158 t.Parallel() 1159 client, mux, _ := setup(t) 1160 1161 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 1162 testMethod(t, r, "GET") 1163 // TODO: remove custom Accept header when this API fully launches 1164 testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) 1165 fmt.Fprintf(w, `{ 1166 "required_status_checks":{ 1167 "strict":true, 1168 "contexts":["continuous-integration"], 1169 "checks": [ 1170 { 1171 "context": "continuous-integration", 1172 "app_id": null 1173 } 1174 ] 1175 }, 1176 "required_pull_request_reviews":{ 1177 "dismissal_restrictions":{ 1178 "users":[{ 1179 "id":3, 1180 "login":"u" 1181 }], 1182 "teams":[{ 1183 "id":4, 1184 "slug":"t" 1185 }], 1186 "apps":[{ 1187 "id":5, 1188 "slug":"a" 1189 }] 1190 }, 1191 "dismiss_stale_reviews":true, 1192 "require_code_owner_reviews":true, 1193 "require_last_push_approval":false, 1194 "required_approving_review_count":1 1195 }, 1196 "enforce_admins":{ 1197 "url":"%s", 1198 "enabled":true 1199 }, 1200 "restrictions":{ 1201 "users":[{"id":1,"login":"u"}], 1202 "teams":[{"id":2,"slug":"t"}], 1203 "apps":[{"id":3,"slug":"a"}] 1204 }, 1205 "required_conversation_resolution": { 1206 "enabled": true 1207 }, 1208 "block_creations": { 1209 "enabled": false 1210 }, 1211 "lock_branch": { 1212 "enabled": false 1213 }, 1214 "allow_fork_syncing": { 1215 "enabled": false 1216 } 1217 }`, test.enforceAdminsURLPath) 1218 }) 1219 1220 ctx := context.Background() 1221 protection, _, err := client.Repositories.GetBranchProtection(ctx, "o", "r", test.branch) 1222 if err != nil { 1223 t.Errorf("Repositories.GetBranchProtection returned error: %v", err) 1224 } 1225 1226 want := &Protection{ 1227 RequiredStatusChecks: &RequiredStatusChecks{ 1228 Strict: true, 1229 Contexts: &[]string{"continuous-integration"}, 1230 Checks: &[]*RequiredStatusCheck{ 1231 { 1232 Context: "continuous-integration", 1233 }, 1234 }, 1235 }, 1236 RequiredPullRequestReviews: &PullRequestReviewsEnforcement{ 1237 DismissStaleReviews: true, 1238 DismissalRestrictions: &DismissalRestrictions{ 1239 Users: []*User{ 1240 {Login: Ptr("u"), ID: Ptr(int64(3))}, 1241 }, 1242 Teams: []*Team{ 1243 {Slug: Ptr("t"), ID: Ptr(int64(4))}, 1244 }, 1245 Apps: []*App{ 1246 {Slug: Ptr("a"), ID: Ptr(int64(5))}, 1247 }, 1248 }, 1249 RequireCodeOwnerReviews: true, 1250 RequiredApprovingReviewCount: 1, 1251 RequireLastPushApproval: false, 1252 }, 1253 EnforceAdmins: &AdminEnforcement{ 1254 URL: Ptr(test.enforceAdminsURLPath), 1255 Enabled: true, 1256 }, 1257 Restrictions: &BranchRestrictions{ 1258 Users: []*User{ 1259 {Login: Ptr("u"), ID: Ptr(int64(1))}, 1260 }, 1261 Teams: []*Team{ 1262 {Slug: Ptr("t"), ID: Ptr(int64(2))}, 1263 }, 1264 Apps: []*App{ 1265 {Slug: Ptr("a"), ID: Ptr(int64(3))}, 1266 }, 1267 }, 1268 RequiredConversationResolution: &RequiredConversationResolution{ 1269 Enabled: true, 1270 }, 1271 BlockCreations: &BlockCreations{ 1272 Enabled: Ptr(false), 1273 }, 1274 LockBranch: &LockBranch{ 1275 Enabled: Ptr(false), 1276 }, 1277 AllowForkSyncing: &AllowForkSyncing{ 1278 Enabled: Ptr(false), 1279 }, 1280 } 1281 if !cmp.Equal(protection, want) { 1282 t.Errorf("Repositories.GetBranchProtection returned %+v, want %+v", protection, want) 1283 } 1284 1285 const methodName = "GetBranchProtection" 1286 testBadOptions(t, methodName, func() (err error) { 1287 _, _, err = client.Repositories.GetBranchProtection(ctx, "\n", "\n", "\n") 1288 return err 1289 }) 1290 1291 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 1292 got, resp, err := client.Repositories.GetBranchProtection(ctx, "o", "r", test.branch) 1293 if got != nil { 1294 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 1295 } 1296 return resp, err 1297 }) 1298 }) 1299 } 1300 } 1301 1302 func TestRepositoriesService_GetBranchProtection_noDismissalRestrictions(t *testing.T) { 1303 t.Parallel() 1304 client, mux, _ := setup(t) 1305 1306 tests := []struct { 1307 branch string 1308 urlPath string 1309 enforceAdminsURLPath string 1310 }{ 1311 {branch: "b", urlPath: "/repos/o/r/branches/b/protection", enforceAdminsURLPath: "/repos/o/r/branches/b/protection/enforce_admins"}, 1312 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection", enforceAdminsURLPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/enforce_admins"}, 1313 } 1314 1315 for _, test := range tests { 1316 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 1317 testMethod(t, r, "GET") 1318 // TODO: remove custom Accept header when this API fully launches 1319 testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) 1320 fmt.Fprintf(w, `{ 1321 "required_status_checks":{ 1322 "strict":true, 1323 "contexts":["continuous-integration"], 1324 "checks": [ 1325 { 1326 "context": "continuous-integration", 1327 "app_id": null 1328 } 1329 ] 1330 }, 1331 "required_pull_request_reviews":{ 1332 "dismiss_stale_reviews":true, 1333 "require_code_owner_reviews":true, 1334 "required_approving_review_count":1 1335 }, 1336 "enforce_admins":{ 1337 "url":"%s", 1338 "enabled":true 1339 }, 1340 "restrictions":{ 1341 "users":[{"id":1,"login":"u"}], 1342 "teams":[{"id":2,"slug":"t"}] 1343 } 1344 }`, test.enforceAdminsURLPath) 1345 }) 1346 1347 ctx := context.Background() 1348 protection, _, err := client.Repositories.GetBranchProtection(ctx, "o", "r", test.branch) 1349 if err != nil { 1350 t.Errorf("Repositories.GetBranchProtection returned error: %v", err) 1351 } 1352 1353 want := &Protection{ 1354 RequiredStatusChecks: &RequiredStatusChecks{ 1355 Strict: true, 1356 Contexts: &[]string{"continuous-integration"}, 1357 Checks: &[]*RequiredStatusCheck{ 1358 { 1359 Context: "continuous-integration", 1360 }, 1361 }, 1362 }, 1363 RequiredPullRequestReviews: &PullRequestReviewsEnforcement{ 1364 DismissStaleReviews: true, 1365 DismissalRestrictions: nil, 1366 RequireCodeOwnerReviews: true, 1367 RequiredApprovingReviewCount: 1, 1368 }, 1369 EnforceAdmins: &AdminEnforcement{ 1370 URL: Ptr(test.enforceAdminsURLPath), 1371 Enabled: true, 1372 }, 1373 Restrictions: &BranchRestrictions{ 1374 Users: []*User{ 1375 {Login: Ptr("u"), ID: Ptr(int64(1))}, 1376 }, 1377 Teams: []*Team{ 1378 {Slug: Ptr("t"), ID: Ptr(int64(2))}, 1379 }, 1380 }, 1381 } 1382 if !cmp.Equal(protection, want) { 1383 t.Errorf("Repositories.GetBranchProtection returned %+v, want %+v", protection, want) 1384 } 1385 } 1386 } 1387 1388 func TestRepositoriesService_GetBranchProtection_branchNotProtected(t *testing.T) { 1389 t.Parallel() 1390 tests := []struct { 1391 branch string 1392 urlPath string 1393 }{ 1394 {branch: "b", urlPath: "/repos/o/r/branches/b/protection"}, 1395 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection"}, 1396 } 1397 1398 for _, test := range tests { 1399 test := test 1400 t.Run(test.branch, func(t *testing.T) { 1401 t.Parallel() 1402 client, mux, _ := setup(t) 1403 1404 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 1405 testMethod(t, r, "GET") 1406 1407 w.WriteHeader(http.StatusBadRequest) 1408 fmt.Fprintf(w, `{ 1409 "message": %q, 1410 "documentation_url": "https://docs.github.com/rest/repos#get-branch-protection" 1411 }`, githubBranchNotProtected) 1412 }) 1413 1414 ctx := context.Background() 1415 protection, _, err := client.Repositories.GetBranchProtection(ctx, "o", "r", test.branch) 1416 1417 if protection != nil { 1418 t.Errorf("Repositories.GetBranchProtection returned non-nil protection data") 1419 } 1420 1421 if err != ErrBranchNotProtected { 1422 t.Errorf("Repositories.GetBranchProtection returned an invalid error: %v", err) 1423 } 1424 }) 1425 } 1426 } 1427 1428 func TestRepositoriesService_UpdateBranchProtection_Contexts(t *testing.T) { 1429 t.Parallel() 1430 tests := []struct { 1431 branch string 1432 urlPath string 1433 }{ 1434 {branch: "b", urlPath: "/repos/o/r/branches/b/protection"}, 1435 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection"}, 1436 } 1437 1438 for _, test := range tests { 1439 test := test 1440 t.Run(test.branch, func(t *testing.T) { 1441 t.Parallel() 1442 client, mux, _ := setup(t) 1443 1444 input := &ProtectionRequest{ 1445 RequiredStatusChecks: &RequiredStatusChecks{ 1446 Strict: true, 1447 Contexts: &[]string{"continuous-integration"}, 1448 }, 1449 RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{ 1450 DismissStaleReviews: true, 1451 DismissalRestrictionsRequest: &DismissalRestrictionsRequest{ 1452 Users: &[]string{"uu"}, 1453 Teams: &[]string{"tt"}, 1454 Apps: &[]string{"aa"}, 1455 }, 1456 BypassPullRequestAllowancesRequest: &BypassPullRequestAllowancesRequest{ 1457 Users: []string{"uuu"}, 1458 Teams: []string{"ttt"}, 1459 Apps: []string{"aaa"}, 1460 }, 1461 }, 1462 Restrictions: &BranchRestrictionsRequest{ 1463 Users: []string{"u"}, 1464 Teams: []string{"t"}, 1465 Apps: []string{"a"}, 1466 }, 1467 BlockCreations: Ptr(true), 1468 LockBranch: Ptr(true), 1469 AllowForkSyncing: Ptr(true), 1470 } 1471 1472 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 1473 v := new(ProtectionRequest) 1474 assertNilError(t, json.NewDecoder(r.Body).Decode(v)) 1475 1476 testMethod(t, r, "PUT") 1477 if !cmp.Equal(v, input) { 1478 t.Errorf("Request body = %+v, want %+v", v, input) 1479 } 1480 1481 // TODO: remove custom Accept header when this API fully launches 1482 testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) 1483 fmt.Fprintf(w, `{ 1484 "required_status_checks":{ 1485 "strict":true, 1486 "contexts":["continuous-integration"], 1487 "checks": [ 1488 { 1489 "context": "continuous-integration", 1490 "app_id": null 1491 } 1492 ] 1493 }, 1494 "required_pull_request_reviews":{ 1495 "dismissal_restrictions":{ 1496 "users":[{ 1497 "id":3, 1498 "login":"uu" 1499 }], 1500 "teams":[{ 1501 "id":4, 1502 "slug":"tt" 1503 }], 1504 "apps":[{ 1505 "id":5, 1506 "slug":"aa" 1507 }] 1508 }, 1509 "dismiss_stale_reviews":true, 1510 "require_code_owner_reviews":true, 1511 "bypass_pull_request_allowances": { 1512 "users":[{"id":10,"login":"uuu"}], 1513 "teams":[{"id":20,"slug":"ttt"}], 1514 "apps":[{"id":30,"slug":"aaa"}] 1515 } 1516 }, 1517 "restrictions":{ 1518 "users":[{"id":1,"login":"u"}], 1519 "teams":[{"id":2,"slug":"t"}], 1520 "apps":[{"id":3,"slug":"a"}] 1521 }, 1522 "block_creations": { 1523 "enabled": true 1524 }, 1525 "lock_branch": { 1526 "enabled": true 1527 }, 1528 "allow_fork_syncing": { 1529 "enabled": true 1530 } 1531 }`) 1532 }) 1533 1534 ctx := context.Background() 1535 protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input) 1536 if err != nil { 1537 t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err) 1538 } 1539 1540 want := &Protection{ 1541 RequiredStatusChecks: &RequiredStatusChecks{ 1542 Strict: true, 1543 Contexts: &[]string{"continuous-integration"}, 1544 Checks: &[]*RequiredStatusCheck{ 1545 { 1546 Context: "continuous-integration", 1547 }, 1548 }, 1549 }, 1550 RequiredPullRequestReviews: &PullRequestReviewsEnforcement{ 1551 DismissStaleReviews: true, 1552 DismissalRestrictions: &DismissalRestrictions{ 1553 Users: []*User{ 1554 {Login: Ptr("uu"), ID: Ptr(int64(3))}, 1555 }, 1556 Teams: []*Team{ 1557 {Slug: Ptr("tt"), ID: Ptr(int64(4))}, 1558 }, 1559 Apps: []*App{ 1560 {Slug: Ptr("aa"), ID: Ptr(int64(5))}, 1561 }, 1562 }, 1563 RequireCodeOwnerReviews: true, 1564 BypassPullRequestAllowances: &BypassPullRequestAllowances{ 1565 Users: []*User{ 1566 {Login: Ptr("uuu"), ID: Ptr(int64(10))}, 1567 }, 1568 Teams: []*Team{ 1569 {Slug: Ptr("ttt"), ID: Ptr(int64(20))}, 1570 }, 1571 Apps: []*App{ 1572 {Slug: Ptr("aaa"), ID: Ptr(int64(30))}, 1573 }, 1574 }, 1575 }, 1576 Restrictions: &BranchRestrictions{ 1577 Users: []*User{ 1578 {Login: Ptr("u"), ID: Ptr(int64(1))}, 1579 }, 1580 Teams: []*Team{ 1581 {Slug: Ptr("t"), ID: Ptr(int64(2))}, 1582 }, 1583 Apps: []*App{ 1584 {Slug: Ptr("a"), ID: Ptr(int64(3))}, 1585 }, 1586 }, 1587 BlockCreations: &BlockCreations{ 1588 Enabled: Ptr(true), 1589 }, 1590 LockBranch: &LockBranch{ 1591 Enabled: Ptr(true), 1592 }, 1593 AllowForkSyncing: &AllowForkSyncing{ 1594 Enabled: Ptr(true), 1595 }, 1596 } 1597 if !cmp.Equal(protection, want) { 1598 t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want) 1599 } 1600 1601 const methodName = "UpdateBranchProtection" 1602 testBadOptions(t, methodName, func() (err error) { 1603 _, _, err = client.Repositories.UpdateBranchProtection(ctx, "\n", "\n", "\n", input) 1604 return err 1605 }) 1606 1607 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 1608 got, resp, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input) 1609 if got != nil { 1610 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 1611 } 1612 return resp, err 1613 }) 1614 }) 1615 } 1616 } 1617 1618 func TestRepositoriesService_UpdateBranchProtection_EmptyContexts(t *testing.T) { 1619 t.Parallel() 1620 tests := []struct { 1621 branch string 1622 urlPath string 1623 }{ 1624 {branch: "b", urlPath: "/repos/o/r/branches/b/protection"}, 1625 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection"}, 1626 } 1627 1628 for _, test := range tests { 1629 test := test 1630 t.Run(test.branch, func(t *testing.T) { 1631 t.Parallel() 1632 client, mux, _ := setup(t) 1633 1634 input := &ProtectionRequest{ 1635 RequiredStatusChecks: &RequiredStatusChecks{ 1636 Strict: true, 1637 Contexts: &[]string{}, 1638 }, 1639 RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{ 1640 DismissStaleReviews: true, 1641 DismissalRestrictionsRequest: &DismissalRestrictionsRequest{ 1642 Users: &[]string{"uu"}, 1643 Teams: &[]string{"tt"}, 1644 Apps: &[]string{"aa"}, 1645 }, 1646 BypassPullRequestAllowancesRequest: &BypassPullRequestAllowancesRequest{ 1647 Users: []string{"uuu"}, 1648 Teams: []string{"ttt"}, 1649 Apps: []string{"aaa"}, 1650 }, 1651 }, 1652 Restrictions: &BranchRestrictionsRequest{ 1653 Users: []string{"u"}, 1654 Teams: []string{"t"}, 1655 Apps: []string{"a"}, 1656 }, 1657 BlockCreations: Ptr(true), 1658 LockBranch: Ptr(true), 1659 AllowForkSyncing: Ptr(true), 1660 } 1661 1662 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 1663 v := new(ProtectionRequest) 1664 assertNilError(t, json.NewDecoder(r.Body).Decode(v)) 1665 1666 testMethod(t, r, "PUT") 1667 if !cmp.Equal(v, input) { 1668 t.Errorf("Request body = %+v, want %+v", v, input) 1669 } 1670 1671 // TODO: remove custom Accept header when this API fully launches 1672 testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) 1673 fmt.Fprintf(w, `{ 1674 "required_status_checks":{ 1675 "strict":true, 1676 "contexts":[], 1677 "checks": null 1678 }, 1679 "required_pull_request_reviews":{ 1680 "dismissal_restrictions":{ 1681 "users":[{ 1682 "id":3, 1683 "login":"uu" 1684 }], 1685 "teams":[{ 1686 "id":4, 1687 "slug":"tt" 1688 }], 1689 "apps":[{ 1690 "id":5, 1691 "slug":"aa" 1692 }] 1693 }, 1694 "dismiss_stale_reviews":true, 1695 "require_code_owner_reviews":true, 1696 "bypass_pull_request_allowances": { 1697 "users":[{"id":10,"login":"uuu"}], 1698 "teams":[{"id":20,"slug":"ttt"}], 1699 "apps":[{"id":30,"slug":"aaa"}] 1700 } 1701 }, 1702 "restrictions":{ 1703 "users":[{"id":1,"login":"u"}], 1704 "teams":[{"id":2,"slug":"t"}], 1705 "apps":[{"id":3,"slug":"a"}] 1706 }, 1707 "block_creations": { 1708 "enabled": true 1709 }, 1710 "lock_branch": { 1711 "enabled": true 1712 }, 1713 "allow_fork_syncing": { 1714 "enabled": true 1715 } 1716 }`) 1717 }) 1718 1719 ctx := context.Background() 1720 protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input) 1721 if err != nil { 1722 t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err) 1723 } 1724 1725 want := &Protection{ 1726 RequiredStatusChecks: &RequiredStatusChecks{ 1727 Strict: true, 1728 Contexts: &[]string{}, 1729 }, 1730 RequiredPullRequestReviews: &PullRequestReviewsEnforcement{ 1731 DismissStaleReviews: true, 1732 DismissalRestrictions: &DismissalRestrictions{ 1733 Users: []*User{ 1734 {Login: Ptr("uu"), ID: Ptr(int64(3))}, 1735 }, 1736 Teams: []*Team{ 1737 {Slug: Ptr("tt"), ID: Ptr(int64(4))}, 1738 }, 1739 Apps: []*App{ 1740 {Slug: Ptr("aa"), ID: Ptr(int64(5))}, 1741 }, 1742 }, 1743 RequireCodeOwnerReviews: true, 1744 BypassPullRequestAllowances: &BypassPullRequestAllowances{ 1745 Users: []*User{ 1746 {Login: Ptr("uuu"), ID: Ptr(int64(10))}, 1747 }, 1748 Teams: []*Team{ 1749 {Slug: Ptr("ttt"), ID: Ptr(int64(20))}, 1750 }, 1751 Apps: []*App{ 1752 {Slug: Ptr("aaa"), ID: Ptr(int64(30))}, 1753 }, 1754 }, 1755 }, 1756 Restrictions: &BranchRestrictions{ 1757 Users: []*User{ 1758 {Login: Ptr("u"), ID: Ptr(int64(1))}, 1759 }, 1760 Teams: []*Team{ 1761 {Slug: Ptr("t"), ID: Ptr(int64(2))}, 1762 }, 1763 Apps: []*App{ 1764 {Slug: Ptr("a"), ID: Ptr(int64(3))}, 1765 }, 1766 }, 1767 BlockCreations: &BlockCreations{ 1768 Enabled: Ptr(true), 1769 }, 1770 LockBranch: &LockBranch{ 1771 Enabled: Ptr(true), 1772 }, 1773 AllowForkSyncing: &AllowForkSyncing{ 1774 Enabled: Ptr(true), 1775 }, 1776 } 1777 if !cmp.Equal(protection, want) { 1778 t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want) 1779 } 1780 1781 const methodName = "UpdateBranchProtection" 1782 testBadOptions(t, methodName, func() (err error) { 1783 _, _, err = client.Repositories.UpdateBranchProtection(ctx, "\n", "\n", "\n", input) 1784 return err 1785 }) 1786 1787 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 1788 got, resp, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input) 1789 if got != nil { 1790 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 1791 } 1792 return resp, err 1793 }) 1794 }) 1795 } 1796 } 1797 1798 func TestRepositoriesService_UpdateBranchProtection_Checks(t *testing.T) { 1799 t.Parallel() 1800 tests := []struct { 1801 branch string 1802 urlPath string 1803 }{ 1804 {branch: "b", urlPath: "/repos/o/r/branches/b/protection"}, 1805 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection"}, 1806 } 1807 1808 for _, test := range tests { 1809 test := test 1810 t.Run(test.branch, func(t *testing.T) { 1811 t.Parallel() 1812 client, mux, _ := setup(t) 1813 1814 input := &ProtectionRequest{ 1815 RequiredStatusChecks: &RequiredStatusChecks{ 1816 Strict: true, 1817 Checks: &[]*RequiredStatusCheck{ 1818 { 1819 Context: "continuous-integration", 1820 }, 1821 }, 1822 }, 1823 RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{ 1824 DismissStaleReviews: true, 1825 DismissalRestrictionsRequest: &DismissalRestrictionsRequest{ 1826 Users: &[]string{"uu"}, 1827 Teams: &[]string{"tt"}, 1828 Apps: &[]string{"aa"}, 1829 }, 1830 BypassPullRequestAllowancesRequest: &BypassPullRequestAllowancesRequest{ 1831 Users: []string{"uuu"}, 1832 Teams: []string{"ttt"}, 1833 Apps: []string{"aaa"}, 1834 }, 1835 }, 1836 Restrictions: &BranchRestrictionsRequest{ 1837 Users: []string{"u"}, 1838 Teams: []string{"t"}, 1839 Apps: []string{"a"}, 1840 }, 1841 } 1842 1843 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 1844 v := new(ProtectionRequest) 1845 assertNilError(t, json.NewDecoder(r.Body).Decode(v)) 1846 1847 testMethod(t, r, "PUT") 1848 if !cmp.Equal(v, input) { 1849 t.Errorf("Request body = %+v, want %+v", v, input) 1850 } 1851 1852 // TODO: remove custom Accept header when this API fully launches 1853 testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) 1854 fmt.Fprintf(w, `{ 1855 "required_status_checks":{ 1856 "strict":true, 1857 "contexts":["continuous-integration"], 1858 "checks": [ 1859 { 1860 "context": "continuous-integration", 1861 "app_id": null 1862 } 1863 ] 1864 }, 1865 "required_pull_request_reviews":{ 1866 "dismissal_restrictions":{ 1867 "users":[{ 1868 "id":3, 1869 "login":"uu" 1870 }], 1871 "teams":[{ 1872 "id":4, 1873 "slug":"tt" 1874 }], 1875 "apps":[{ 1876 "id":5, 1877 "slug":"aa" 1878 }] 1879 }, 1880 "dismiss_stale_reviews":true, 1881 "require_code_owner_reviews":true, 1882 "bypass_pull_request_allowances": { 1883 "users":[{"id":10,"login":"uuu"}], 1884 "teams":[{"id":20,"slug":"ttt"}], 1885 "apps":[{"id":30,"slug":"aaa"}] 1886 } 1887 }, 1888 "restrictions":{ 1889 "users":[{"id":1,"login":"u"}], 1890 "teams":[{"id":2,"slug":"t"}], 1891 "apps":[{"id":3,"slug":"a"}] 1892 } 1893 }`) 1894 }) 1895 1896 ctx := context.Background() 1897 protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input) 1898 if err != nil { 1899 t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err) 1900 } 1901 1902 want := &Protection{ 1903 RequiredStatusChecks: &RequiredStatusChecks{ 1904 Strict: true, 1905 Contexts: &[]string{"continuous-integration"}, 1906 Checks: &[]*RequiredStatusCheck{ 1907 { 1908 Context: "continuous-integration", 1909 }, 1910 }, 1911 }, 1912 RequiredPullRequestReviews: &PullRequestReviewsEnforcement{ 1913 DismissStaleReviews: true, 1914 DismissalRestrictions: &DismissalRestrictions{ 1915 Users: []*User{ 1916 {Login: Ptr("uu"), ID: Ptr(int64(3))}, 1917 }, 1918 Teams: []*Team{ 1919 {Slug: Ptr("tt"), ID: Ptr(int64(4))}, 1920 }, 1921 Apps: []*App{ 1922 {Slug: Ptr("aa"), ID: Ptr(int64(5))}, 1923 }, 1924 }, 1925 RequireCodeOwnerReviews: true, 1926 BypassPullRequestAllowances: &BypassPullRequestAllowances{ 1927 Users: []*User{ 1928 {Login: Ptr("uuu"), ID: Ptr(int64(10))}, 1929 }, 1930 Teams: []*Team{ 1931 {Slug: Ptr("ttt"), ID: Ptr(int64(20))}, 1932 }, 1933 Apps: []*App{ 1934 {Slug: Ptr("aaa"), ID: Ptr(int64(30))}, 1935 }, 1936 }, 1937 }, 1938 Restrictions: &BranchRestrictions{ 1939 Users: []*User{ 1940 {Login: Ptr("u"), ID: Ptr(int64(1))}, 1941 }, 1942 Teams: []*Team{ 1943 {Slug: Ptr("t"), ID: Ptr(int64(2))}, 1944 }, 1945 Apps: []*App{ 1946 {Slug: Ptr("a"), ID: Ptr(int64(3))}, 1947 }, 1948 }, 1949 } 1950 if !cmp.Equal(protection, want) { 1951 t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want) 1952 } 1953 }) 1954 } 1955 } 1956 1957 func TestRepositoriesService_UpdateBranchProtection_EmptyChecks(t *testing.T) { 1958 t.Parallel() 1959 tests := []struct { 1960 branch string 1961 urlPath string 1962 }{ 1963 {branch: "b", urlPath: "/repos/o/r/branches/b/protection"}, 1964 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection"}, 1965 } 1966 1967 for _, test := range tests { 1968 test := test 1969 t.Run(test.branch, func(t *testing.T) { 1970 t.Parallel() 1971 client, mux, _ := setup(t) 1972 1973 input := &ProtectionRequest{ 1974 RequiredStatusChecks: &RequiredStatusChecks{ 1975 Strict: true, 1976 Checks: &[]*RequiredStatusCheck{}, 1977 }, 1978 RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{ 1979 DismissStaleReviews: true, 1980 DismissalRestrictionsRequest: &DismissalRestrictionsRequest{ 1981 Users: &[]string{"uu"}, 1982 Teams: &[]string{"tt"}, 1983 Apps: &[]string{"aa"}, 1984 }, 1985 BypassPullRequestAllowancesRequest: &BypassPullRequestAllowancesRequest{ 1986 Users: []string{"uuu"}, 1987 Teams: []string{"ttt"}, 1988 Apps: []string{"aaa"}, 1989 }, 1990 }, 1991 Restrictions: &BranchRestrictionsRequest{ 1992 Users: []string{"u"}, 1993 Teams: []string{"t"}, 1994 Apps: []string{"a"}, 1995 }, 1996 } 1997 1998 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 1999 v := new(ProtectionRequest) 2000 assertNilError(t, json.NewDecoder(r.Body).Decode(v)) 2001 2002 testMethod(t, r, "PUT") 2003 if !cmp.Equal(v, input) { 2004 t.Errorf("Request body = %+v, want %+v", v, input) 2005 } 2006 2007 // TODO: remove custom Accept header when this API fully launches 2008 testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) 2009 fmt.Fprintf(w, `{ 2010 "required_status_checks":{ 2011 "strict":true, 2012 "contexts":null, 2013 "checks": [] 2014 }, 2015 "required_pull_request_reviews":{ 2016 "dismissal_restrictions":{ 2017 "users":[{ 2018 "id":3, 2019 "login":"uu" 2020 }], 2021 "teams":[{ 2022 "id":4, 2023 "slug":"tt" 2024 }], 2025 "apps":[{ 2026 "id":5, 2027 "slug":"aa" 2028 }] 2029 }, 2030 "dismiss_stale_reviews":true, 2031 "require_code_owner_reviews":true, 2032 "bypass_pull_request_allowances": { 2033 "users":[{"id":10,"login":"uuu"}], 2034 "teams":[{"id":20,"slug":"ttt"}], 2035 "apps":[{"id":30,"slug":"aaa"}] 2036 } 2037 }, 2038 "restrictions":{ 2039 "users":[{"id":1,"login":"u"}], 2040 "teams":[{"id":2,"slug":"t"}], 2041 "apps":[{"id":3,"slug":"a"}] 2042 } 2043 }`) 2044 }) 2045 2046 ctx := context.Background() 2047 protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input) 2048 if err != nil { 2049 t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err) 2050 } 2051 2052 want := &Protection{ 2053 RequiredStatusChecks: &RequiredStatusChecks{ 2054 Strict: true, 2055 Checks: &[]*RequiredStatusCheck{}, 2056 }, 2057 RequiredPullRequestReviews: &PullRequestReviewsEnforcement{ 2058 DismissStaleReviews: true, 2059 DismissalRestrictions: &DismissalRestrictions{ 2060 Users: []*User{ 2061 {Login: Ptr("uu"), ID: Ptr(int64(3))}, 2062 }, 2063 Teams: []*Team{ 2064 {Slug: Ptr("tt"), ID: Ptr(int64(4))}, 2065 }, 2066 Apps: []*App{ 2067 {Slug: Ptr("aa"), ID: Ptr(int64(5))}, 2068 }, 2069 }, 2070 RequireCodeOwnerReviews: true, 2071 BypassPullRequestAllowances: &BypassPullRequestAllowances{ 2072 Users: []*User{ 2073 {Login: Ptr("uuu"), ID: Ptr(int64(10))}, 2074 }, 2075 Teams: []*Team{ 2076 {Slug: Ptr("ttt"), ID: Ptr(int64(20))}, 2077 }, 2078 Apps: []*App{ 2079 {Slug: Ptr("aaa"), ID: Ptr(int64(30))}, 2080 }, 2081 }, 2082 }, 2083 Restrictions: &BranchRestrictions{ 2084 Users: []*User{ 2085 {Login: Ptr("u"), ID: Ptr(int64(1))}, 2086 }, 2087 Teams: []*Team{ 2088 {Slug: Ptr("t"), ID: Ptr(int64(2))}, 2089 }, 2090 Apps: []*App{ 2091 {Slug: Ptr("a"), ID: Ptr(int64(3))}, 2092 }, 2093 }, 2094 } 2095 if !cmp.Equal(protection, want) { 2096 t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want) 2097 } 2098 }) 2099 } 2100 } 2101 2102 func TestRepositoriesService_UpdateBranchProtection_StrictNoChecks(t *testing.T) { 2103 t.Parallel() 2104 tests := []struct { 2105 branch string 2106 urlPath string 2107 }{ 2108 {branch: "b", urlPath: "/repos/o/r/branches/b/protection"}, 2109 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection"}, 2110 } 2111 2112 for _, test := range tests { 2113 test := test 2114 t.Run(test.branch, func(t *testing.T) { 2115 t.Parallel() 2116 client, mux, _ := setup(t) 2117 2118 input := &ProtectionRequest{ 2119 RequiredStatusChecks: &RequiredStatusChecks{ 2120 Strict: true, 2121 }, 2122 RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{ 2123 DismissStaleReviews: true, 2124 DismissalRestrictionsRequest: &DismissalRestrictionsRequest{ 2125 Users: &[]string{"uu"}, 2126 Teams: &[]string{"tt"}, 2127 Apps: &[]string{"aa"}, 2128 }, 2129 BypassPullRequestAllowancesRequest: &BypassPullRequestAllowancesRequest{ 2130 Users: []string{"uuu"}, 2131 Teams: []string{"ttt"}, 2132 Apps: []string{"aaa"}, 2133 }, 2134 }, 2135 Restrictions: &BranchRestrictionsRequest{ 2136 Users: []string{"u"}, 2137 Teams: []string{"t"}, 2138 Apps: []string{"a"}, 2139 }, 2140 } 2141 2142 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 2143 v := new(ProtectionRequest) 2144 assertNilError(t, json.NewDecoder(r.Body).Decode(v)) 2145 2146 testMethod(t, r, "PUT") 2147 if !cmp.Equal(v, input) { 2148 t.Errorf("Request body = %+v, want %+v", v, input) 2149 } 2150 2151 // TODO: remove custom Accept header when this API fully launches 2152 testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) 2153 fmt.Fprintf(w, `{ 2154 "required_status_checks":{ 2155 "strict":true, 2156 "contexts":[] 2157 }, 2158 "required_pull_request_reviews":{ 2159 "dismissal_restrictions":{ 2160 "users":[{ 2161 "id":3, 2162 "login":"uu" 2163 }], 2164 "teams":[{ 2165 "id":4, 2166 "slug":"tt" 2167 }], 2168 "apps":[{ 2169 "id":5, 2170 "slug":"aa" 2171 }] 2172 }, 2173 "dismiss_stale_reviews":true, 2174 "require_code_owner_reviews":true, 2175 "require_last_push_approval":false, 2176 "bypass_pull_request_allowances": { 2177 "users":[{"id":10,"login":"uuu"}], 2178 "teams":[{"id":20,"slug":"ttt"}], 2179 "apps":[{"id":30,"slug":"aaa"}] 2180 } 2181 }, 2182 "restrictions":{ 2183 "users":[{"id":1,"login":"u"}], 2184 "teams":[{"id":2,"slug":"t"}], 2185 "apps":[{"id":3,"slug":"a"}] 2186 } 2187 }`) 2188 }) 2189 2190 ctx := context.Background() 2191 protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input) 2192 if err != nil { 2193 t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err) 2194 } 2195 2196 want := &Protection{ 2197 RequiredStatusChecks: &RequiredStatusChecks{ 2198 Strict: true, 2199 Contexts: &[]string{}, 2200 }, 2201 RequiredPullRequestReviews: &PullRequestReviewsEnforcement{ 2202 DismissStaleReviews: true, 2203 DismissalRestrictions: &DismissalRestrictions{ 2204 Users: []*User{ 2205 {Login: Ptr("uu"), ID: Ptr(int64(3))}, 2206 }, 2207 Teams: []*Team{ 2208 {Slug: Ptr("tt"), ID: Ptr(int64(4))}, 2209 }, 2210 Apps: []*App{ 2211 {Slug: Ptr("aa"), ID: Ptr(int64(5))}, 2212 }, 2213 }, 2214 RequireCodeOwnerReviews: true, 2215 BypassPullRequestAllowances: &BypassPullRequestAllowances{ 2216 Users: []*User{ 2217 {Login: Ptr("uuu"), ID: Ptr(int64(10))}, 2218 }, 2219 Teams: []*Team{ 2220 {Slug: Ptr("ttt"), ID: Ptr(int64(20))}, 2221 }, 2222 Apps: []*App{ 2223 {Slug: Ptr("aaa"), ID: Ptr(int64(30))}, 2224 }, 2225 }, 2226 }, 2227 Restrictions: &BranchRestrictions{ 2228 Users: []*User{ 2229 {Login: Ptr("u"), ID: Ptr(int64(1))}, 2230 }, 2231 Teams: []*Team{ 2232 {Slug: Ptr("t"), ID: Ptr(int64(2))}, 2233 }, 2234 Apps: []*App{ 2235 {Slug: Ptr("a"), ID: Ptr(int64(3))}, 2236 }, 2237 }, 2238 } 2239 if !cmp.Equal(protection, want) { 2240 t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want) 2241 } 2242 }) 2243 } 2244 } 2245 2246 func TestRepositoriesService_UpdateBranchProtection_RequireLastPushApproval(t *testing.T) { 2247 t.Parallel() 2248 tests := []struct { 2249 branch string 2250 urlPath string 2251 }{ 2252 {branch: "b", urlPath: "/repos/o/r/branches/b/protection"}, 2253 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection"}, 2254 } 2255 2256 for _, test := range tests { 2257 test := test 2258 t.Run(test.branch, func(t *testing.T) { 2259 t.Parallel() 2260 client, mux, _ := setup(t) 2261 2262 input := &ProtectionRequest{ 2263 RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{ 2264 RequireLastPushApproval: Ptr(true), 2265 }, 2266 } 2267 2268 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 2269 v := new(ProtectionRequest) 2270 assertNilError(t, json.NewDecoder(r.Body).Decode(v)) 2271 2272 testMethod(t, r, "PUT") 2273 if !cmp.Equal(v, input) { 2274 t.Errorf("Request body = %+v, want %+v", v, input) 2275 } 2276 2277 fmt.Fprintf(w, `{ 2278 "required_pull_request_reviews":{ 2279 "require_last_push_approval":true 2280 } 2281 }`) 2282 }) 2283 2284 ctx := context.Background() 2285 protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", test.branch, input) 2286 if err != nil { 2287 t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err) 2288 } 2289 2290 want := &Protection{ 2291 RequiredPullRequestReviews: &PullRequestReviewsEnforcement{ 2292 RequireLastPushApproval: true, 2293 }, 2294 } 2295 if !cmp.Equal(protection, want) { 2296 t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want) 2297 } 2298 }) 2299 } 2300 } 2301 2302 func TestRepositoriesService_RemoveBranchProtection(t *testing.T) { 2303 t.Parallel() 2304 tests := []struct { 2305 branch string 2306 urlPath string 2307 }{ 2308 {branch: "b", urlPath: "/repos/o/r/branches/b/protection"}, 2309 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection"}, 2310 } 2311 2312 for _, test := range tests { 2313 test := test 2314 t.Run(test.branch, func(t *testing.T) { 2315 t.Parallel() 2316 client, mux, _ := setup(t) 2317 2318 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 2319 testMethod(t, r, "DELETE") 2320 w.WriteHeader(http.StatusNoContent) 2321 }) 2322 2323 ctx := context.Background() 2324 _, err := client.Repositories.RemoveBranchProtection(ctx, "o", "r", test.branch) 2325 if err != nil { 2326 t.Errorf("Repositories.RemoveBranchProtection returned error: %v", err) 2327 } 2328 2329 const methodName = "RemoveBranchProtection" 2330 testBadOptions(t, methodName, func() (err error) { 2331 _, err = client.Repositories.RemoveBranchProtection(ctx, "\n", "\n", "\n") 2332 return err 2333 }) 2334 2335 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 2336 return client.Repositories.RemoveBranchProtection(ctx, "o", "r", test.branch) 2337 }) 2338 }) 2339 } 2340 } 2341 2342 func TestRepositoriesService_ListLanguages_invalidOwner(t *testing.T) { 2343 t.Parallel() 2344 client, _, _ := setup(t) 2345 2346 ctx := context.Background() 2347 _, _, err := client.Repositories.ListLanguages(ctx, "%", "%") 2348 testURLParseError(t, err) 2349 } 2350 2351 func TestRepositoriesService_License(t *testing.T) { 2352 t.Parallel() 2353 client, mux, _ := setup(t) 2354 2355 mux.HandleFunc("/repos/o/r/license", func(w http.ResponseWriter, r *http.Request) { 2356 testMethod(t, r, "GET") 2357 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}}`) 2358 }) 2359 2360 ctx := context.Background() 2361 got, _, err := client.Repositories.License(ctx, "o", "r") 2362 if err != nil { 2363 t.Errorf("Repositories.License returned error: %v", err) 2364 } 2365 2366 want := &RepositoryLicense{ 2367 Name: Ptr("LICENSE"), 2368 Path: Ptr("LICENSE"), 2369 License: &License{ 2370 Name: Ptr("MIT License"), 2371 Key: Ptr("mit"), 2372 SPDXID: Ptr("MIT"), 2373 URL: Ptr("https://api.github.com/licenses/mit"), 2374 Featured: Ptr(true), 2375 }, 2376 } 2377 2378 if !cmp.Equal(got, want) { 2379 t.Errorf("Repositories.License returned %+v, want %+v", got, want) 2380 } 2381 2382 const methodName = "License" 2383 testBadOptions(t, methodName, func() (err error) { 2384 _, _, err = client.Repositories.License(ctx, "\n", "\n") 2385 return err 2386 }) 2387 2388 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 2389 got, resp, err := client.Repositories.License(ctx, "o", "r") 2390 if got != nil { 2391 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 2392 } 2393 return resp, err 2394 }) 2395 } 2396 2397 func TestRepositoriesService_GetRequiredStatusChecks(t *testing.T) { 2398 t.Parallel() 2399 tests := []struct { 2400 branch string 2401 urlPath string 2402 }{ 2403 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks"}, 2404 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/required_status_checks"}, 2405 } 2406 2407 for _, test := range tests { 2408 test := test 2409 t.Run(test.branch, func(t *testing.T) { 2410 t.Parallel() 2411 client, mux, _ := setup(t) 2412 2413 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 2414 testMethod(t, r, "GET") 2415 fmt.Fprint(w, `{ 2416 "strict": true, 2417 "contexts": ["x","y","z"], 2418 "checks": [ 2419 { 2420 "context": "x", 2421 "app_id": null 2422 }, 2423 { 2424 "context": "y", 2425 "app_id": null 2426 }, 2427 { 2428 "context": "z", 2429 "app_id": null 2430 } 2431 ] 2432 }`) 2433 }) 2434 2435 ctx := context.Background() 2436 checks, _, err := client.Repositories.GetRequiredStatusChecks(ctx, "o", "r", test.branch) 2437 if err != nil { 2438 t.Errorf("Repositories.GetRequiredStatusChecks returned error: %v", err) 2439 } 2440 2441 want := &RequiredStatusChecks{ 2442 Strict: true, 2443 Contexts: &[]string{"x", "y", "z"}, 2444 Checks: &[]*RequiredStatusCheck{ 2445 { 2446 Context: "x", 2447 }, 2448 { 2449 Context: "y", 2450 }, 2451 { 2452 Context: "z", 2453 }, 2454 }, 2455 } 2456 if !cmp.Equal(checks, want) { 2457 t.Errorf("Repositories.GetRequiredStatusChecks returned %+v, want %+v", checks, want) 2458 } 2459 2460 const methodName = "GetRequiredStatusChecks" 2461 testBadOptions(t, methodName, func() (err error) { 2462 _, _, err = client.Repositories.GetRequiredStatusChecks(ctx, "\n", "\n", "\n") 2463 return err 2464 }) 2465 2466 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 2467 got, resp, err := client.Repositories.GetRequiredStatusChecks(ctx, "o", "r", test.branch) 2468 if got != nil { 2469 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 2470 } 2471 return resp, err 2472 }) 2473 }) 2474 } 2475 } 2476 2477 func TestRepositoriesService_GetRequiredStatusChecks_branchNotProtected(t *testing.T) { 2478 t.Parallel() 2479 tests := []struct { 2480 branch string 2481 urlPath string 2482 }{ 2483 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks"}, 2484 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/required_status_checks"}, 2485 } 2486 2487 for _, test := range tests { 2488 test := test 2489 t.Run(test.branch, func(t *testing.T) { 2490 t.Parallel() 2491 client, mux, _ := setup(t) 2492 2493 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 2494 testMethod(t, r, "GET") 2495 2496 w.WriteHeader(http.StatusBadRequest) 2497 fmt.Fprintf(w, `{ 2498 "message": %q, 2499 "documentation_url": "https://docs.github.com/rest/repos#get-branch-protection" 2500 }`, githubBranchNotProtected) 2501 }) 2502 2503 ctx := context.Background() 2504 checks, _, err := client.Repositories.GetRequiredStatusChecks(ctx, "o", "r", test.branch) 2505 2506 if checks != nil { 2507 t.Errorf("Repositories.GetRequiredStatusChecks returned non-nil status-checks data") 2508 } 2509 2510 if err != ErrBranchNotProtected { 2511 t.Errorf("Repositories.GetRequiredStatusChecks returned an invalid error: %v", err) 2512 } 2513 }) 2514 } 2515 } 2516 2517 func TestRepositoriesService_UpdateRequiredStatusChecks_Contexts(t *testing.T) { 2518 t.Parallel() 2519 tests := []struct { 2520 branch string 2521 urlPath string 2522 }{ 2523 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks"}, 2524 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/required_status_checks"}, 2525 } 2526 2527 for _, test := range tests { 2528 test := test 2529 t.Run(test.branch, func(t *testing.T) { 2530 t.Parallel() 2531 client, mux, _ := setup(t) 2532 2533 input := &RequiredStatusChecksRequest{ 2534 Strict: Ptr(true), 2535 Contexts: []string{"continuous-integration"}, 2536 } 2537 2538 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 2539 v := new(RequiredStatusChecksRequest) 2540 assertNilError(t, json.NewDecoder(r.Body).Decode(v)) 2541 2542 testMethod(t, r, "PATCH") 2543 if !cmp.Equal(v, input) { 2544 t.Errorf("Request body = %+v, want %+v", v, input) 2545 } 2546 testHeader(t, r, "Accept", mediaTypeV3) 2547 fmt.Fprintf(w, `{ 2548 "strict":true, 2549 "contexts":["continuous-integration"], 2550 "checks": [ 2551 { 2552 "context": "continuous-integration", 2553 "app_id": null 2554 } 2555 ] 2556 }`) 2557 }) 2558 2559 ctx := context.Background() 2560 statusChecks, _, err := client.Repositories.UpdateRequiredStatusChecks(ctx, "o", "r", test.branch, input) 2561 if err != nil { 2562 t.Errorf("Repositories.UpdateRequiredStatusChecks returned error: %v", err) 2563 } 2564 2565 want := &RequiredStatusChecks{ 2566 Strict: true, 2567 Contexts: &[]string{"continuous-integration"}, 2568 Checks: &[]*RequiredStatusCheck{ 2569 { 2570 Context: "continuous-integration", 2571 }, 2572 }, 2573 } 2574 if !cmp.Equal(statusChecks, want) { 2575 t.Errorf("Repositories.UpdateRequiredStatusChecks returned %+v, want %+v", statusChecks, want) 2576 } 2577 2578 const methodName = "UpdateRequiredStatusChecks" 2579 testBadOptions(t, methodName, func() (err error) { 2580 _, _, err = client.Repositories.UpdateRequiredStatusChecks(ctx, "\n", "\n", "\n", input) 2581 return err 2582 }) 2583 2584 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 2585 got, resp, err := client.Repositories.UpdateRequiredStatusChecks(ctx, "o", "r", test.branch, input) 2586 if got != nil { 2587 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 2588 } 2589 return resp, err 2590 }) 2591 }) 2592 } 2593 } 2594 2595 func TestRepositoriesService_UpdateRequiredStatusChecks_Checks(t *testing.T) { 2596 t.Parallel() 2597 tests := []struct { 2598 branch string 2599 urlPath string 2600 }{ 2601 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks"}, 2602 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/required_status_checks"}, 2603 } 2604 2605 for _, test := range tests { 2606 test := test 2607 t.Run(test.branch, func(t *testing.T) { 2608 t.Parallel() 2609 client, mux, _ := setup(t) 2610 2611 appID := int64(123) 2612 noAppID := int64(-1) 2613 input := &RequiredStatusChecksRequest{ 2614 Strict: Ptr(true), 2615 Checks: []*RequiredStatusCheck{ 2616 { 2617 Context: "continuous-integration", 2618 }, 2619 { 2620 Context: "continuous-integration2", 2621 AppID: &appID, 2622 }, 2623 { 2624 Context: "continuous-integration3", 2625 AppID: &noAppID, 2626 }, 2627 }, 2628 } 2629 2630 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 2631 v := new(RequiredStatusChecksRequest) 2632 assertNilError(t, json.NewDecoder(r.Body).Decode(v)) 2633 2634 testMethod(t, r, "PATCH") 2635 if !cmp.Equal(v, input) { 2636 t.Errorf("Request body = %+v, want %+v", v, input) 2637 } 2638 testHeader(t, r, "Accept", mediaTypeV3) 2639 fmt.Fprintf(w, `{ 2640 "strict":true, 2641 "contexts":["continuous-integration"], 2642 "checks": [ 2643 { 2644 "context": "continuous-integration", 2645 "app_id": null 2646 }, 2647 { 2648 "context": "continuous-integration2", 2649 "app_id": 123 2650 }, 2651 { 2652 "context": "continuous-integration3", 2653 "app_id": null 2654 } 2655 ] 2656 }`) 2657 }) 2658 2659 ctx := context.Background() 2660 statusChecks, _, err := client.Repositories.UpdateRequiredStatusChecks(ctx, "o", "r", test.branch, input) 2661 if err != nil { 2662 t.Errorf("Repositories.UpdateRequiredStatusChecks returned error: %v", err) 2663 } 2664 2665 want := &RequiredStatusChecks{ 2666 Strict: true, 2667 Contexts: &[]string{"continuous-integration"}, 2668 Checks: &[]*RequiredStatusCheck{ 2669 { 2670 Context: "continuous-integration", 2671 }, 2672 { 2673 Context: "continuous-integration2", 2674 AppID: &appID, 2675 }, 2676 { 2677 Context: "continuous-integration3", 2678 }, 2679 }, 2680 } 2681 if !cmp.Equal(statusChecks, want) { 2682 t.Errorf("Repositories.UpdateRequiredStatusChecks returned %+v, want %+v", statusChecks, want) 2683 } 2684 }) 2685 } 2686 } 2687 2688 func TestRepositoriesService_RemoveRequiredStatusChecks(t *testing.T) { 2689 t.Parallel() 2690 tests := []struct { 2691 branch string 2692 urlPath string 2693 }{ 2694 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks"}, 2695 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/required_status_checks"}, 2696 } 2697 2698 for _, test := range tests { 2699 test := test 2700 t.Run(test.branch, func(t *testing.T) { 2701 t.Parallel() 2702 client, mux, _ := setup(t) 2703 2704 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 2705 testMethod(t, r, "DELETE") 2706 testHeader(t, r, "Accept", mediaTypeV3) 2707 w.WriteHeader(http.StatusNoContent) 2708 }) 2709 2710 ctx := context.Background() 2711 _, err := client.Repositories.RemoveRequiredStatusChecks(ctx, "o", "r", test.branch) 2712 if err != nil { 2713 t.Errorf("Repositories.RemoveRequiredStatusChecks returned error: %v", err) 2714 } 2715 2716 const methodName = "RemoveRequiredStatusChecks" 2717 testBadOptions(t, methodName, func() (err error) { 2718 _, err = client.Repositories.RemoveRequiredStatusChecks(ctx, "\n", "\n", "\n") 2719 return err 2720 }) 2721 2722 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 2723 return client.Repositories.RemoveRequiredStatusChecks(ctx, "o", "r", test.branch) 2724 }) 2725 }) 2726 } 2727 } 2728 2729 func TestRepositoriesService_ListRequiredStatusChecksContexts(t *testing.T) { 2730 t.Parallel() 2731 tests := []struct { 2732 branch string 2733 urlPath string 2734 }{ 2735 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks/contexts"}, 2736 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/required_status_checks/contexts"}, 2737 } 2738 2739 for _, test := range tests { 2740 test := test 2741 t.Run(test.branch, func(t *testing.T) { 2742 t.Parallel() 2743 client, mux, _ := setup(t) 2744 2745 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 2746 testMethod(t, r, "GET") 2747 fmt.Fprint(w, `["x", "y", "z"]`) 2748 }) 2749 2750 ctx := context.Background() 2751 contexts, _, err := client.Repositories.ListRequiredStatusChecksContexts(ctx, "o", "r", test.branch) 2752 if err != nil { 2753 t.Errorf("Repositories.ListRequiredStatusChecksContexts returned error: %v", err) 2754 } 2755 2756 want := []string{"x", "y", "z"} 2757 if !cmp.Equal(contexts, want) { 2758 t.Errorf("Repositories.ListRequiredStatusChecksContexts returned %+v, want %+v", contexts, want) 2759 } 2760 2761 const methodName = "ListRequiredStatusChecksContexts" 2762 testBadOptions(t, methodName, func() (err error) { 2763 _, _, err = client.Repositories.ListRequiredStatusChecksContexts(ctx, "\n", "\n", "\n") 2764 return err 2765 }) 2766 2767 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 2768 got, resp, err := client.Repositories.ListRequiredStatusChecksContexts(ctx, "o", "r", test.branch) 2769 if got != nil { 2770 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 2771 } 2772 return resp, err 2773 }) 2774 }) 2775 } 2776 } 2777 2778 func TestRepositoriesService_ListRequiredStatusChecksContexts_branchNotProtected(t *testing.T) { 2779 t.Parallel() 2780 tests := []struct { 2781 branch string 2782 urlPath string 2783 }{ 2784 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_status_checks/contexts"}, 2785 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/required_status_checks/contexts"}, 2786 } 2787 2788 for _, test := range tests { 2789 test := test 2790 t.Run(test.branch, func(t *testing.T) { 2791 t.Parallel() 2792 client, mux, _ := setup(t) 2793 2794 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 2795 testMethod(t, r, "GET") 2796 2797 w.WriteHeader(http.StatusBadRequest) 2798 fmt.Fprintf(w, `{ 2799 "message": %q, 2800 "documentation_url": "https://docs.github.com/rest/repos#get-branch-protection" 2801 }`, githubBranchNotProtected) 2802 }) 2803 2804 ctx := context.Background() 2805 contexts, _, err := client.Repositories.ListRequiredStatusChecksContexts(ctx, "o", "r", test.branch) 2806 2807 if contexts != nil { 2808 t.Errorf("Repositories.ListRequiredStatusChecksContexts returned non-nil contexts data") 2809 } 2810 2811 if err != ErrBranchNotProtected { 2812 t.Errorf("Repositories.ListRequiredStatusChecksContexts returned an invalid error: %v", err) 2813 } 2814 }) 2815 } 2816 } 2817 2818 func TestRepositoriesService_GetPullRequestReviewEnforcement(t *testing.T) { 2819 t.Parallel() 2820 tests := []struct { 2821 branch string 2822 urlPath string 2823 }{ 2824 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_pull_request_reviews"}, 2825 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/required_pull_request_reviews"}, 2826 } 2827 2828 for _, test := range tests { 2829 test := test 2830 t.Run(test.branch, func(t *testing.T) { 2831 t.Parallel() 2832 client, mux, _ := setup(t) 2833 2834 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 2835 testMethod(t, r, "GET") 2836 // TODO: remove custom Accept header when this API fully launches 2837 testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) 2838 fmt.Fprintf(w, `{ 2839 "dismissal_restrictions":{ 2840 "users":[{"id":1,"login":"u"}], 2841 "teams":[{"id":2,"slug":"t"}], 2842 "apps":[{"id":3,"slug":"a"}] 2843 }, 2844 "dismiss_stale_reviews":true, 2845 "require_code_owner_reviews":true, 2846 "required_approving_review_count":1 2847 }`) 2848 }) 2849 2850 ctx := context.Background() 2851 enforcement, _, err := client.Repositories.GetPullRequestReviewEnforcement(ctx, "o", "r", test.branch) 2852 if err != nil { 2853 t.Errorf("Repositories.GetPullRequestReviewEnforcement returned error: %v", err) 2854 } 2855 2856 want := &PullRequestReviewsEnforcement{ 2857 DismissStaleReviews: true, 2858 DismissalRestrictions: &DismissalRestrictions{ 2859 Users: []*User{ 2860 {Login: Ptr("u"), ID: Ptr(int64(1))}, 2861 }, 2862 Teams: []*Team{ 2863 {Slug: Ptr("t"), ID: Ptr(int64(2))}, 2864 }, 2865 Apps: []*App{ 2866 {Slug: Ptr("a"), ID: Ptr(int64(3))}, 2867 }, 2868 }, 2869 RequireCodeOwnerReviews: true, 2870 RequiredApprovingReviewCount: 1, 2871 } 2872 2873 if !cmp.Equal(enforcement, want) { 2874 t.Errorf("Repositories.GetPullRequestReviewEnforcement returned %+v, want %+v", enforcement, want) 2875 } 2876 2877 const methodName = "GetPullRequestReviewEnforcement" 2878 testBadOptions(t, methodName, func() (err error) { 2879 _, _, err = client.Repositories.GetPullRequestReviewEnforcement(ctx, "\n", "\n", "\n") 2880 return err 2881 }) 2882 2883 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 2884 got, resp, err := client.Repositories.GetPullRequestReviewEnforcement(ctx, "o", "r", test.branch) 2885 if got != nil { 2886 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 2887 } 2888 return resp, err 2889 }) 2890 }) 2891 } 2892 } 2893 2894 func TestRepositoriesService_UpdatePullRequestReviewEnforcement(t *testing.T) { 2895 t.Parallel() 2896 tests := []struct { 2897 branch string 2898 urlPath string 2899 }{ 2900 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_pull_request_reviews"}, 2901 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/required_pull_request_reviews"}, 2902 } 2903 2904 for _, test := range tests { 2905 test := test 2906 t.Run(test.branch, func(t *testing.T) { 2907 t.Parallel() 2908 client, mux, _ := setup(t) 2909 2910 input := &PullRequestReviewsEnforcementUpdate{ 2911 DismissalRestrictionsRequest: &DismissalRestrictionsRequest{ 2912 Users: &[]string{"u"}, 2913 Teams: &[]string{"t"}, 2914 Apps: &[]string{"a"}, 2915 }, 2916 } 2917 2918 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 2919 v := new(PullRequestReviewsEnforcementUpdate) 2920 assertNilError(t, json.NewDecoder(r.Body).Decode(v)) 2921 2922 testMethod(t, r, "PATCH") 2923 if !cmp.Equal(v, input) { 2924 t.Errorf("Request body = %+v, want %+v", v, input) 2925 } 2926 // TODO: remove custom Accept header when this API fully launches 2927 testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) 2928 fmt.Fprintf(w, `{ 2929 "dismissal_restrictions":{ 2930 "users":[{"id":1,"login":"u"}], 2931 "teams":[{"id":2,"slug":"t"}], 2932 "apps":[{"id":3,"slug":"a"}] 2933 }, 2934 "dismiss_stale_reviews":true, 2935 "require_code_owner_reviews":true, 2936 "required_approving_review_count":3 2937 }`) 2938 }) 2939 2940 ctx := context.Background() 2941 enforcement, _, err := client.Repositories.UpdatePullRequestReviewEnforcement(ctx, "o", "r", test.branch, input) 2942 if err != nil { 2943 t.Errorf("Repositories.UpdatePullRequestReviewEnforcement returned error: %v", err) 2944 } 2945 2946 want := &PullRequestReviewsEnforcement{ 2947 DismissStaleReviews: true, 2948 DismissalRestrictions: &DismissalRestrictions{ 2949 Users: []*User{ 2950 {Login: Ptr("u"), ID: Ptr(int64(1))}, 2951 }, 2952 Teams: []*Team{ 2953 {Slug: Ptr("t"), ID: Ptr(int64(2))}, 2954 }, 2955 Apps: []*App{ 2956 {Slug: Ptr("a"), ID: Ptr(int64(3))}, 2957 }, 2958 }, 2959 RequireCodeOwnerReviews: true, 2960 RequiredApprovingReviewCount: 3, 2961 } 2962 if !cmp.Equal(enforcement, want) { 2963 t.Errorf("Repositories.UpdatePullRequestReviewEnforcement returned %+v, want %+v", enforcement, want) 2964 } 2965 2966 const methodName = "UpdatePullRequestReviewEnforcement" 2967 testBadOptions(t, methodName, func() (err error) { 2968 _, _, err = client.Repositories.UpdatePullRequestReviewEnforcement(ctx, "\n", "\n", "\n", input) 2969 return err 2970 }) 2971 2972 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 2973 got, resp, err := client.Repositories.UpdatePullRequestReviewEnforcement(ctx, "o", "r", test.branch, input) 2974 if got != nil { 2975 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 2976 } 2977 return resp, err 2978 }) 2979 }) 2980 } 2981 } 2982 2983 func TestRepositoriesService_DisableDismissalRestrictions(t *testing.T) { 2984 t.Parallel() 2985 tests := []struct { 2986 branch string 2987 urlPath string 2988 }{ 2989 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_pull_request_reviews"}, 2990 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/required_pull_request_reviews"}, 2991 } 2992 2993 for _, test := range tests { 2994 test := test 2995 t.Run(test.branch, func(t *testing.T) { 2996 t.Parallel() 2997 client, mux, _ := setup(t) 2998 2999 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 3000 testMethod(t, r, "PATCH") 3001 // TODO: remove custom Accept header when this API fully launches 3002 testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview) 3003 testBody(t, r, `{"dismissal_restrictions":{}}`+"\n") 3004 fmt.Fprintf(w, `{"dismiss_stale_reviews":true,"require_code_owner_reviews":true,"required_approving_review_count":1}`) 3005 }) 3006 3007 ctx := context.Background() 3008 enforcement, _, err := client.Repositories.DisableDismissalRestrictions(ctx, "o", "r", test.branch) 3009 if err != nil { 3010 t.Errorf("Repositories.DisableDismissalRestrictions returned error: %v", err) 3011 } 3012 3013 want := &PullRequestReviewsEnforcement{ 3014 DismissStaleReviews: true, 3015 DismissalRestrictions: nil, 3016 RequireCodeOwnerReviews: true, 3017 RequiredApprovingReviewCount: 1, 3018 } 3019 if !cmp.Equal(enforcement, want) { 3020 t.Errorf("Repositories.DisableDismissalRestrictions returned %+v, want %+v", enforcement, want) 3021 } 3022 3023 const methodName = "DisableDismissalRestrictions" 3024 testBadOptions(t, methodName, func() (err error) { 3025 _, _, err = client.Repositories.DisableDismissalRestrictions(ctx, "\n", "\n", "\n") 3026 return err 3027 }) 3028 3029 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 3030 got, resp, err := client.Repositories.DisableDismissalRestrictions(ctx, "o", "r", test.branch) 3031 if got != nil { 3032 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 3033 } 3034 return resp, err 3035 }) 3036 }) 3037 } 3038 } 3039 3040 func TestRepositoriesService_RemovePullRequestReviewEnforcement(t *testing.T) { 3041 t.Parallel() 3042 tests := []struct { 3043 branch string 3044 urlPath string 3045 }{ 3046 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_pull_request_reviews"}, 3047 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/required_pull_request_reviews"}, 3048 } 3049 3050 for _, test := range tests { 3051 test := test 3052 t.Run(test.branch, func(t *testing.T) { 3053 t.Parallel() 3054 client, mux, _ := setup(t) 3055 3056 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 3057 testMethod(t, r, "DELETE") 3058 w.WriteHeader(http.StatusNoContent) 3059 }) 3060 3061 ctx := context.Background() 3062 _, err := client.Repositories.RemovePullRequestReviewEnforcement(ctx, "o", "r", test.branch) 3063 if err != nil { 3064 t.Errorf("Repositories.RemovePullRequestReviewEnforcement returned error: %v", err) 3065 } 3066 3067 const methodName = "RemovePullRequestReviewEnforcement" 3068 testBadOptions(t, methodName, func() (err error) { 3069 _, err = client.Repositories.RemovePullRequestReviewEnforcement(ctx, "\n", "\n", "\n") 3070 return err 3071 }) 3072 3073 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 3074 return client.Repositories.RemovePullRequestReviewEnforcement(ctx, "o", "r", test.branch) 3075 }) 3076 }) 3077 } 3078 } 3079 3080 func TestRepositoriesService_GetAdminEnforcement(t *testing.T) { 3081 t.Parallel() 3082 tests := []struct { 3083 branch string 3084 urlPath string 3085 }{ 3086 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/enforce_admins"}, 3087 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/enforce_admins"}, 3088 } 3089 3090 for _, test := range tests { 3091 test := test 3092 t.Run(test.branch, func(t *testing.T) { 3093 t.Parallel() 3094 client, mux, _ := setup(t) 3095 3096 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 3097 testMethod(t, r, "GET") 3098 fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/enforce_admins","enabled":true}`) 3099 }) 3100 3101 ctx := context.Background() 3102 enforcement, _, err := client.Repositories.GetAdminEnforcement(ctx, "o", "r", test.branch) 3103 if err != nil { 3104 t.Errorf("Repositories.GetAdminEnforcement returned error: %v", err) 3105 } 3106 3107 want := &AdminEnforcement{ 3108 URL: Ptr("/repos/o/r/branches/b/protection/enforce_admins"), 3109 Enabled: true, 3110 } 3111 3112 if !cmp.Equal(enforcement, want) { 3113 t.Errorf("Repositories.GetAdminEnforcement returned %+v, want %+v", enforcement, want) 3114 } 3115 3116 const methodName = "GetAdminEnforcement" 3117 testBadOptions(t, methodName, func() (err error) { 3118 _, _, err = client.Repositories.GetAdminEnforcement(ctx, "\n", "\n", "\n") 3119 return err 3120 }) 3121 3122 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 3123 got, resp, err := client.Repositories.GetAdminEnforcement(ctx, "o", "r", test.branch) 3124 if got != nil { 3125 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 3126 } 3127 return resp, err 3128 }) 3129 }) 3130 } 3131 } 3132 3133 func TestRepositoriesService_AddAdminEnforcement(t *testing.T) { 3134 t.Parallel() 3135 tests := []struct { 3136 branch string 3137 urlPath string 3138 }{ 3139 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/enforce_admins"}, 3140 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/enforce_admins"}, 3141 } 3142 3143 for _, test := range tests { 3144 test := test 3145 t.Run(test.branch, func(t *testing.T) { 3146 t.Parallel() 3147 client, mux, _ := setup(t) 3148 3149 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 3150 testMethod(t, r, "POST") 3151 fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/enforce_admins","enabled":true}`) 3152 }) 3153 3154 ctx := context.Background() 3155 enforcement, _, err := client.Repositories.AddAdminEnforcement(ctx, "o", "r", test.branch) 3156 if err != nil { 3157 t.Errorf("Repositories.AddAdminEnforcement returned error: %v", err) 3158 } 3159 3160 want := &AdminEnforcement{ 3161 URL: Ptr("/repos/o/r/branches/b/protection/enforce_admins"), 3162 Enabled: true, 3163 } 3164 if !cmp.Equal(enforcement, want) { 3165 t.Errorf("Repositories.AddAdminEnforcement returned %+v, want %+v", enforcement, want) 3166 } 3167 3168 const methodName = "AddAdminEnforcement" 3169 testBadOptions(t, methodName, func() (err error) { 3170 _, _, err = client.Repositories.AddAdminEnforcement(ctx, "\n", "\n", "\n") 3171 return err 3172 }) 3173 3174 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 3175 got, resp, err := client.Repositories.AddAdminEnforcement(ctx, "o", "r", test.branch) 3176 if got != nil { 3177 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 3178 } 3179 return resp, err 3180 }) 3181 }) 3182 } 3183 } 3184 3185 func TestRepositoriesService_RemoveAdminEnforcement(t *testing.T) { 3186 t.Parallel() 3187 tests := []struct { 3188 branch string 3189 urlPath string 3190 }{ 3191 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/enforce_admins"}, 3192 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/enforce_admins"}, 3193 } 3194 3195 for _, test := range tests { 3196 test := test 3197 t.Run(test.branch, func(t *testing.T) { 3198 t.Parallel() 3199 client, mux, _ := setup(t) 3200 3201 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 3202 testMethod(t, r, "DELETE") 3203 w.WriteHeader(http.StatusNoContent) 3204 }) 3205 3206 ctx := context.Background() 3207 _, err := client.Repositories.RemoveAdminEnforcement(ctx, "o", "r", test.branch) 3208 if err != nil { 3209 t.Errorf("Repositories.RemoveAdminEnforcement returned error: %v", err) 3210 } 3211 3212 const methodName = "RemoveAdminEnforcement" 3213 testBadOptions(t, methodName, func() (err error) { 3214 _, err = client.Repositories.RemoveAdminEnforcement(ctx, "\n", "\n", "\n") 3215 return err 3216 }) 3217 3218 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 3219 return client.Repositories.RemoveAdminEnforcement(ctx, "o", "r", test.branch) 3220 }) 3221 }) 3222 } 3223 } 3224 3225 func TestRepositoriesService_GetSignaturesProtectedBranch(t *testing.T) { 3226 t.Parallel() 3227 tests := []struct { 3228 branch string 3229 urlPath string 3230 }{ 3231 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_signatures"}, 3232 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/required_signatures"}, 3233 } 3234 3235 for _, test := range tests { 3236 test := test 3237 t.Run(test.branch, func(t *testing.T) { 3238 t.Parallel() 3239 client, mux, _ := setup(t) 3240 3241 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 3242 testMethod(t, r, "GET") 3243 testHeader(t, r, "Accept", mediaTypeSignaturePreview) 3244 fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/required_signatures","enabled":false}`) 3245 }) 3246 3247 ctx := context.Background() 3248 signature, _, err := client.Repositories.GetSignaturesProtectedBranch(ctx, "o", "r", test.branch) 3249 if err != nil { 3250 t.Errorf("Repositories.GetSignaturesProtectedBranch returned error: %v", err) 3251 } 3252 3253 want := &SignaturesProtectedBranch{ 3254 URL: Ptr("/repos/o/r/branches/b/protection/required_signatures"), 3255 Enabled: Ptr(false), 3256 } 3257 3258 if !cmp.Equal(signature, want) { 3259 t.Errorf("Repositories.GetSignaturesProtectedBranch returned %+v, want %+v", signature, want) 3260 } 3261 3262 const methodName = "GetSignaturesProtectedBranch" 3263 testBadOptions(t, methodName, func() (err error) { 3264 _, _, err = client.Repositories.GetSignaturesProtectedBranch(ctx, "\n", "\n", "\n") 3265 return err 3266 }) 3267 3268 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 3269 got, resp, err := client.Repositories.GetSignaturesProtectedBranch(ctx, "o", "r", test.branch) 3270 if got != nil { 3271 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 3272 } 3273 return resp, err 3274 }) 3275 }) 3276 } 3277 } 3278 3279 func TestRepositoriesService_RequireSignaturesOnProtectedBranch(t *testing.T) { 3280 t.Parallel() 3281 tests := []struct { 3282 branch string 3283 urlPath string 3284 }{ 3285 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_signatures"}, 3286 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/required_signatures"}, 3287 } 3288 3289 for _, test := range tests { 3290 test := test 3291 t.Run(test.branch, func(t *testing.T) { 3292 t.Parallel() 3293 client, mux, _ := setup(t) 3294 3295 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 3296 testMethod(t, r, "POST") 3297 testHeader(t, r, "Accept", mediaTypeSignaturePreview) 3298 fmt.Fprintf(w, `{"url":"/repos/o/r/branches/b/protection/required_signatures","enabled":true}`) 3299 }) 3300 3301 ctx := context.Background() 3302 signature, _, err := client.Repositories.RequireSignaturesOnProtectedBranch(ctx, "o", "r", test.branch) 3303 if err != nil { 3304 t.Errorf("Repositories.RequireSignaturesOnProtectedBranch returned error: %v", err) 3305 } 3306 3307 want := &SignaturesProtectedBranch{ 3308 URL: Ptr("/repos/o/r/branches/b/protection/required_signatures"), 3309 Enabled: Ptr(true), 3310 } 3311 3312 if !cmp.Equal(signature, want) { 3313 t.Errorf("Repositories.RequireSignaturesOnProtectedBranch returned %+v, want %+v", signature, want) 3314 } 3315 3316 const methodName = "RequireSignaturesOnProtectedBranch" 3317 testBadOptions(t, methodName, func() (err error) { 3318 _, _, err = client.Repositories.RequireSignaturesOnProtectedBranch(ctx, "\n", "\n", "\n") 3319 return err 3320 }) 3321 3322 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 3323 got, resp, err := client.Repositories.RequireSignaturesOnProtectedBranch(ctx, "o", "r", test.branch) 3324 if got != nil { 3325 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 3326 } 3327 return resp, err 3328 }) 3329 }) 3330 } 3331 } 3332 3333 func TestRepositoriesService_OptionalSignaturesOnProtectedBranch(t *testing.T) { 3334 t.Parallel() 3335 tests := []struct { 3336 branch string 3337 urlPath string 3338 }{ 3339 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/required_signatures"}, 3340 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/required_signatures"}, 3341 } 3342 3343 for _, test := range tests { 3344 test := test 3345 t.Run(test.branch, func(t *testing.T) { 3346 t.Parallel() 3347 client, mux, _ := setup(t) 3348 3349 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 3350 testMethod(t, r, "DELETE") 3351 testHeader(t, r, "Accept", mediaTypeSignaturePreview) 3352 w.WriteHeader(http.StatusNoContent) 3353 }) 3354 3355 ctx := context.Background() 3356 _, err := client.Repositories.OptionalSignaturesOnProtectedBranch(ctx, "o", "r", test.branch) 3357 if err != nil { 3358 t.Errorf("Repositories.OptionalSignaturesOnProtectedBranch returned error: %v", err) 3359 } 3360 3361 const methodName = "OptionalSignaturesOnProtectedBranch" 3362 testBadOptions(t, methodName, func() (err error) { 3363 _, err = client.Repositories.OptionalSignaturesOnProtectedBranch(ctx, "\n", "\n", "\n") 3364 return err 3365 }) 3366 3367 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 3368 return client.Repositories.OptionalSignaturesOnProtectedBranch(ctx, "o", "r", test.branch) 3369 }) 3370 }) 3371 } 3372 } 3373 3374 func TestPullRequestReviewsEnforcementRequest_MarshalJSON_nilDismissalRestirctions(t *testing.T) { 3375 t.Parallel() 3376 req := PullRequestReviewsEnforcementRequest{} 3377 3378 got, err := json.Marshal(req) 3379 if err != nil { 3380 t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err) 3381 } 3382 3383 want := `{"dismiss_stale_reviews":false,"require_code_owner_reviews":false,"required_approving_review_count":0}` 3384 if want != string(got) { 3385 t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want) 3386 } 3387 3388 req = PullRequestReviewsEnforcementRequest{ 3389 DismissalRestrictionsRequest: &DismissalRestrictionsRequest{}, 3390 } 3391 3392 got, err = json.Marshal(req) 3393 if err != nil { 3394 t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err) 3395 } 3396 3397 want = `{"dismissal_restrictions":{},"dismiss_stale_reviews":false,"require_code_owner_reviews":false,"required_approving_review_count":0}` 3398 if want != string(got) { 3399 t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want) 3400 } 3401 3402 req = PullRequestReviewsEnforcementRequest{ 3403 DismissalRestrictionsRequest: &DismissalRestrictionsRequest{ 3404 Users: &[]string{}, 3405 Teams: &[]string{}, 3406 Apps: &[]string{}, 3407 }, 3408 RequireLastPushApproval: Ptr(true), 3409 } 3410 3411 got, err = json.Marshal(req) 3412 if err != nil { 3413 t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned error: %v", err) 3414 } 3415 3416 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}` 3417 if want != string(got) { 3418 t.Errorf("PullRequestReviewsEnforcementRequest.MarshalJSON returned %+v, want %+v", string(got), want) 3419 } 3420 } 3421 3422 func TestRepositoriesService_ListAllTopics(t *testing.T) { 3423 t.Parallel() 3424 client, mux, _ := setup(t) 3425 3426 mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) { 3427 testMethod(t, r, "GET") 3428 testHeader(t, r, "Accept", mediaTypeTopicsPreview) 3429 fmt.Fprint(w, `{"names":["go", "go-github", "github"]}`) 3430 }) 3431 3432 ctx := context.Background() 3433 got, _, err := client.Repositories.ListAllTopics(ctx, "o", "r") 3434 if err != nil { 3435 t.Fatalf("Repositories.ListAllTopics returned error: %v", err) 3436 } 3437 3438 want := []string{"go", "go-github", "github"} 3439 if !cmp.Equal(got, want) { 3440 t.Errorf("Repositories.ListAllTopics returned %+v, want %+v", got, want) 3441 } 3442 3443 const methodName = "ListAllTopics" 3444 testBadOptions(t, methodName, func() (err error) { 3445 _, _, err = client.Repositories.ListAllTopics(ctx, "\n", "\n") 3446 return err 3447 }) 3448 3449 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 3450 got, resp, err := client.Repositories.ListAllTopics(ctx, "o", "r") 3451 if got != nil { 3452 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 3453 } 3454 return resp, err 3455 }) 3456 } 3457 3458 func TestRepositoriesService_ListAllTopics_emptyTopics(t *testing.T) { 3459 t.Parallel() 3460 client, mux, _ := setup(t) 3461 3462 mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) { 3463 testMethod(t, r, "GET") 3464 testHeader(t, r, "Accept", mediaTypeTopicsPreview) 3465 fmt.Fprint(w, `{"names":[]}`) 3466 }) 3467 3468 ctx := context.Background() 3469 got, _, err := client.Repositories.ListAllTopics(ctx, "o", "r") 3470 if err != nil { 3471 t.Fatalf("Repositories.ListAllTopics returned error: %v", err) 3472 } 3473 3474 want := []string{} 3475 if !cmp.Equal(got, want) { 3476 t.Errorf("Repositories.ListAllTopics returned %+v, want %+v", got, want) 3477 } 3478 } 3479 3480 func TestRepositoriesService_ReplaceAllTopics(t *testing.T) { 3481 t.Parallel() 3482 client, mux, _ := setup(t) 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 fmt.Fprint(w, `{"names":["go", "go-github", "github"]}`) 3488 }) 3489 3490 ctx := context.Background() 3491 got, _, err := client.Repositories.ReplaceAllTopics(ctx, "o", "r", []string{"go", "go-github", "github"}) 3492 if err != nil { 3493 t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err) 3494 } 3495 3496 want := []string{"go", "go-github", "github"} 3497 if !cmp.Equal(got, want) { 3498 t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want) 3499 } 3500 3501 const methodName = "ReplaceAllTopics" 3502 testBadOptions(t, methodName, func() (err error) { 3503 _, _, err = client.Repositories.ReplaceAllTopics(ctx, "\n", "\n", []string{"\n", "\n", "\n"}) 3504 return err 3505 }) 3506 3507 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 3508 got, resp, err := client.Repositories.ReplaceAllTopics(ctx, "o", "r", []string{"go", "go-github", "github"}) 3509 if got != nil { 3510 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 3511 } 3512 return resp, err 3513 }) 3514 } 3515 3516 func TestRepositoriesService_ReplaceAllTopics_nilSlice(t *testing.T) { 3517 t.Parallel() 3518 client, mux, _ := setup(t) 3519 3520 mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) { 3521 testMethod(t, r, "PUT") 3522 testHeader(t, r, "Accept", mediaTypeTopicsPreview) 3523 testBody(t, r, `{"names":[]}`+"\n") 3524 fmt.Fprint(w, `{"names":[]}`) 3525 }) 3526 3527 ctx := context.Background() 3528 got, _, err := client.Repositories.ReplaceAllTopics(ctx, "o", "r", nil) 3529 if err != nil { 3530 t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err) 3531 } 3532 3533 want := []string{} 3534 if !cmp.Equal(got, want) { 3535 t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want) 3536 } 3537 } 3538 3539 func TestRepositoriesService_ReplaceAllTopics_emptySlice(t *testing.T) { 3540 t.Parallel() 3541 client, mux, _ := setup(t) 3542 3543 mux.HandleFunc("/repos/o/r/topics", func(w http.ResponseWriter, r *http.Request) { 3544 testMethod(t, r, "PUT") 3545 testHeader(t, r, "Accept", mediaTypeTopicsPreview) 3546 testBody(t, r, `{"names":[]}`+"\n") 3547 fmt.Fprint(w, `{"names":[]}`) 3548 }) 3549 3550 ctx := context.Background() 3551 got, _, err := client.Repositories.ReplaceAllTopics(ctx, "o", "r", []string{}) 3552 if err != nil { 3553 t.Fatalf("Repositories.ReplaceAllTopics returned error: %v", err) 3554 } 3555 3556 want := []string{} 3557 if !cmp.Equal(got, want) { 3558 t.Errorf("Repositories.ReplaceAllTopics returned %+v, want %+v", got, want) 3559 } 3560 } 3561 3562 func TestRepositoriesService_ListAppRestrictions(t *testing.T) { 3563 t.Parallel() 3564 tests := []struct { 3565 branch string 3566 urlPath string 3567 }{ 3568 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/apps"}, 3569 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/restrictions/apps"}, 3570 } 3571 3572 for _, test := range tests { 3573 test := test 3574 t.Run(test.branch, func(t *testing.T) { 3575 t.Parallel() 3576 client, mux, _ := setup(t) 3577 3578 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 3579 testMethod(t, r, "GET") 3580 }) 3581 3582 ctx := context.Background() 3583 _, _, err := client.Repositories.ListAppRestrictions(ctx, "o", "r", test.branch) 3584 if err != nil { 3585 t.Errorf("Repositories.ListAppRestrictions returned error: %v", err) 3586 } 3587 3588 const methodName = "ListAppRestrictions" 3589 testBadOptions(t, methodName, func() (err error) { 3590 _, _, err = client.Repositories.ListAppRestrictions(ctx, "\n", "\n", "\n") 3591 return err 3592 }) 3593 3594 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 3595 got, resp, err := client.Repositories.ListAppRestrictions(ctx, "o", "r", test.branch) 3596 if got != nil { 3597 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 3598 } 3599 return resp, err 3600 }) 3601 }) 3602 } 3603 } 3604 3605 func TestRepositoriesService_ReplaceAppRestrictions(t *testing.T) { 3606 t.Parallel() 3607 tests := []struct { 3608 branch string 3609 urlPath string 3610 }{ 3611 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/apps"}, 3612 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/restrictions/apps"}, 3613 } 3614 3615 for _, test := range tests { 3616 test := test 3617 t.Run(test.branch, func(t *testing.T) { 3618 t.Parallel() 3619 client, mux, _ := setup(t) 3620 3621 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 3622 testMethod(t, r, "PUT") 3623 fmt.Fprint(w, `[{ 3624 "name": "octocat" 3625 }]`) 3626 }) 3627 input := []string{"octocat"} 3628 ctx := context.Background() 3629 got, _, err := client.Repositories.ReplaceAppRestrictions(ctx, "o", "r", test.branch, input) 3630 if err != nil { 3631 t.Errorf("Repositories.ReplaceAppRestrictions returned error: %v", err) 3632 } 3633 want := []*App{ 3634 {Name: Ptr("octocat")}, 3635 } 3636 if !cmp.Equal(got, want) { 3637 t.Errorf("Repositories.ReplaceAppRestrictions returned %+v, want %+v", got, want) 3638 } 3639 3640 const methodName = "ReplaceAppRestrictions" 3641 testBadOptions(t, methodName, func() (err error) { 3642 _, _, err = client.Repositories.ReplaceAppRestrictions(ctx, "\n", "\n", "\n", input) 3643 return err 3644 }) 3645 3646 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 3647 got, resp, err := client.Repositories.ReplaceAppRestrictions(ctx, "o", "r", test.branch, input) 3648 if got != nil { 3649 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 3650 } 3651 return resp, err 3652 }) 3653 }) 3654 } 3655 } 3656 3657 func TestRepositoriesService_AddAppRestrictions(t *testing.T) { 3658 t.Parallel() 3659 tests := []struct { 3660 branch string 3661 urlPath string 3662 }{ 3663 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/apps"}, 3664 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/restrictions/apps"}, 3665 } 3666 3667 for _, test := range tests { 3668 test := test 3669 t.Run(test.branch, func(t *testing.T) { 3670 t.Parallel() 3671 client, mux, _ := setup(t) 3672 3673 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 3674 testMethod(t, r, "POST") 3675 fmt.Fprint(w, `[{ 3676 "name": "octocat" 3677 }]`) 3678 }) 3679 input := []string{"octocat"} 3680 ctx := context.Background() 3681 got, _, err := client.Repositories.AddAppRestrictions(ctx, "o", "r", test.branch, input) 3682 if err != nil { 3683 t.Errorf("Repositories.AddAppRestrictions returned error: %v", err) 3684 } 3685 want := []*App{ 3686 {Name: Ptr("octocat")}, 3687 } 3688 if !cmp.Equal(got, want) { 3689 t.Errorf("Repositories.AddAppRestrictions returned %+v, want %+v", got, want) 3690 } 3691 3692 const methodName = "AddAppRestrictions" 3693 testBadOptions(t, methodName, func() (err error) { 3694 _, _, err = client.Repositories.AddAppRestrictions(ctx, "\n", "\n", "\n", input) 3695 return err 3696 }) 3697 3698 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 3699 got, resp, err := client.Repositories.AddAppRestrictions(ctx, "o", "r", test.branch, input) 3700 if got != nil { 3701 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 3702 } 3703 return resp, err 3704 }) 3705 }) 3706 } 3707 } 3708 3709 func TestRepositoriesService_RemoveAppRestrictions(t *testing.T) { 3710 t.Parallel() 3711 tests := []struct { 3712 branch string 3713 urlPath string 3714 }{ 3715 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/apps"}, 3716 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/restrictions/apps"}, 3717 } 3718 3719 for _, test := range tests { 3720 test := test 3721 t.Run(test.branch, func(t *testing.T) { 3722 t.Parallel() 3723 client, mux, _ := setup(t) 3724 3725 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 3726 testMethod(t, r, "DELETE") 3727 fmt.Fprint(w, `[]`) 3728 }) 3729 input := []string{"octocat"} 3730 ctx := context.Background() 3731 got, _, err := client.Repositories.RemoveAppRestrictions(ctx, "o", "r", test.branch, input) 3732 if err != nil { 3733 t.Errorf("Repositories.RemoveAppRestrictions returned error: %v", err) 3734 } 3735 want := []*App{} 3736 if !cmp.Equal(got, want) { 3737 t.Errorf("Repositories.RemoveAppRestrictions returned %+v, want %+v", got, want) 3738 } 3739 3740 const methodName = "RemoveAppRestrictions" 3741 testBadOptions(t, methodName, func() (err error) { 3742 _, _, err = client.Repositories.RemoveAppRestrictions(ctx, "\n", "\n", "\n", input) 3743 return err 3744 }) 3745 3746 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 3747 got, resp, err := client.Repositories.RemoveAppRestrictions(ctx, "o", "r", test.branch, input) 3748 if got != nil { 3749 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 3750 } 3751 return resp, err 3752 }) 3753 }) 3754 } 3755 } 3756 3757 func TestRepositoriesService_ListTeamRestrictions(t *testing.T) { 3758 t.Parallel() 3759 tests := []struct { 3760 branch string 3761 urlPath string 3762 }{ 3763 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/teams"}, 3764 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/restrictions/teams"}, 3765 } 3766 3767 for _, test := range tests { 3768 test := test 3769 t.Run(test.branch, func(t *testing.T) { 3770 t.Parallel() 3771 client, mux, _ := setup(t) 3772 3773 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 3774 testMethod(t, r, "GET") 3775 }) 3776 3777 ctx := context.Background() 3778 _, _, err := client.Repositories.ListTeamRestrictions(ctx, "o", "r", test.branch) 3779 if err != nil { 3780 t.Errorf("Repositories.ListTeamRestrictions returned error: %v", err) 3781 } 3782 3783 const methodName = "ListTeamRestrictions" 3784 testBadOptions(t, methodName, func() (err error) { 3785 _, _, err = client.Repositories.ListTeamRestrictions(ctx, "\n", "\n", "\n") 3786 return err 3787 }) 3788 3789 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 3790 got, resp, err := client.Repositories.ListTeamRestrictions(ctx, "o", "r", test.branch) 3791 if got != nil { 3792 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 3793 } 3794 return resp, err 3795 }) 3796 }) 3797 } 3798 } 3799 3800 func TestRepositoriesService_ReplaceTeamRestrictions(t *testing.T) { 3801 t.Parallel() 3802 tests := []struct { 3803 branch string 3804 urlPath string 3805 }{ 3806 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/teams"}, 3807 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/restrictions/teams"}, 3808 } 3809 3810 for _, test := range tests { 3811 test := test 3812 t.Run(test.branch, func(t *testing.T) { 3813 t.Parallel() 3814 client, mux, _ := setup(t) 3815 3816 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 3817 testMethod(t, r, "PUT") 3818 fmt.Fprint(w, `[{ 3819 "name": "octocat" 3820 }]`) 3821 }) 3822 input := []string{"octocat"} 3823 ctx := context.Background() 3824 got, _, err := client.Repositories.ReplaceTeamRestrictions(ctx, "o", "r", test.branch, input) 3825 if err != nil { 3826 t.Errorf("Repositories.ReplaceTeamRestrictions returned error: %v", err) 3827 } 3828 want := []*Team{ 3829 {Name: Ptr("octocat")}, 3830 } 3831 if !cmp.Equal(got, want) { 3832 t.Errorf("Repositories.ReplaceTeamRestrictions returned %+v, want %+v", got, want) 3833 } 3834 3835 const methodName = "ReplaceTeamRestrictions" 3836 testBadOptions(t, methodName, func() (err error) { 3837 _, _, err = client.Repositories.ReplaceTeamRestrictions(ctx, "\n", "\n", "\n", input) 3838 return err 3839 }) 3840 3841 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 3842 got, resp, err := client.Repositories.ReplaceTeamRestrictions(ctx, "o", "r", test.branch, input) 3843 if got != nil { 3844 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 3845 } 3846 return resp, err 3847 }) 3848 }) 3849 } 3850 } 3851 3852 func TestRepositoriesService_AddTeamRestrictions(t *testing.T) { 3853 t.Parallel() 3854 tests := []struct { 3855 branch string 3856 urlPath string 3857 }{ 3858 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/teams"}, 3859 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/restrictions/teams"}, 3860 } 3861 3862 for _, test := range tests { 3863 test := test 3864 t.Run(test.branch, func(t *testing.T) { 3865 t.Parallel() 3866 client, mux, _ := setup(t) 3867 3868 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 3869 testMethod(t, r, "POST") 3870 fmt.Fprint(w, `[{ 3871 "name": "octocat" 3872 }]`) 3873 }) 3874 input := []string{"octocat"} 3875 ctx := context.Background() 3876 got, _, err := client.Repositories.AddTeamRestrictions(ctx, "o", "r", test.branch, input) 3877 if err != nil { 3878 t.Errorf("Repositories.AddTeamRestrictions returned error: %v", err) 3879 } 3880 want := []*Team{ 3881 {Name: Ptr("octocat")}, 3882 } 3883 if !cmp.Equal(got, want) { 3884 t.Errorf("Repositories.AddTeamRestrictions returned %+v, want %+v", got, want) 3885 } 3886 3887 const methodName = "AddTeamRestrictions" 3888 testBadOptions(t, methodName, func() (err error) { 3889 _, _, err = client.Repositories.AddTeamRestrictions(ctx, "\n", "\n", "\n", input) 3890 return err 3891 }) 3892 3893 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 3894 got, resp, err := client.Repositories.AddTeamRestrictions(ctx, "o", "r", test.branch, input) 3895 if got != nil { 3896 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 3897 } 3898 return resp, err 3899 }) 3900 }) 3901 } 3902 } 3903 3904 func TestRepositoriesService_RemoveTeamRestrictions(t *testing.T) { 3905 t.Parallel() 3906 tests := []struct { 3907 branch string 3908 urlPath string 3909 }{ 3910 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/teams"}, 3911 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/restrictions/teams"}, 3912 } 3913 3914 for _, test := range tests { 3915 test := test 3916 t.Run(test.branch, func(t *testing.T) { 3917 t.Parallel() 3918 client, mux, _ := setup(t) 3919 3920 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 3921 testMethod(t, r, "DELETE") 3922 fmt.Fprint(w, `[]`) 3923 }) 3924 input := []string{"octocat"} 3925 ctx := context.Background() 3926 got, _, err := client.Repositories.RemoveTeamRestrictions(ctx, "o", "r", test.branch, input) 3927 if err != nil { 3928 t.Errorf("Repositories.RemoveTeamRestrictions returned error: %v", err) 3929 } 3930 want := []*Team{} 3931 if !cmp.Equal(got, want) { 3932 t.Errorf("Repositories.RemoveTeamRestrictions returned %+v, want %+v", got, want) 3933 } 3934 3935 const methodName = "RemoveTeamRestrictions" 3936 testBadOptions(t, methodName, func() (err error) { 3937 _, _, err = client.Repositories.RemoveTeamRestrictions(ctx, "\n", "\n", "\n", input) 3938 return err 3939 }) 3940 3941 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 3942 got, resp, err := client.Repositories.RemoveTeamRestrictions(ctx, "o", "r", test.branch, input) 3943 if got != nil { 3944 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 3945 } 3946 return resp, err 3947 }) 3948 }) 3949 } 3950 } 3951 3952 func TestRepositoriesService_ListUserRestrictions(t *testing.T) { 3953 t.Parallel() 3954 tests := []struct { 3955 branch string 3956 urlPath string 3957 }{ 3958 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/users"}, 3959 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/restrictions/users"}, 3960 } 3961 3962 for _, test := range tests { 3963 test := test 3964 t.Run(test.branch, func(t *testing.T) { 3965 t.Parallel() 3966 client, mux, _ := setup(t) 3967 3968 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 3969 testMethod(t, r, "GET") 3970 }) 3971 3972 ctx := context.Background() 3973 _, _, err := client.Repositories.ListUserRestrictions(ctx, "o", "r", test.branch) 3974 if err != nil { 3975 t.Errorf("Repositories.ListUserRestrictions returned error: %v", err) 3976 } 3977 3978 const methodName = "ListUserRestrictions" 3979 testBadOptions(t, methodName, func() (err error) { 3980 _, _, err = client.Repositories.ListUserRestrictions(ctx, "\n", "\n", "\n") 3981 return err 3982 }) 3983 3984 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 3985 got, resp, err := client.Repositories.ListUserRestrictions(ctx, "o", "r", test.branch) 3986 if got != nil { 3987 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 3988 } 3989 return resp, err 3990 }) 3991 }) 3992 } 3993 } 3994 3995 func TestRepositoriesService_ReplaceUserRestrictions(t *testing.T) { 3996 t.Parallel() 3997 tests := []struct { 3998 branch string 3999 urlPath string 4000 }{ 4001 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/users"}, 4002 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/restrictions/users"}, 4003 } 4004 4005 for _, test := range tests { 4006 test := test 4007 t.Run(test.branch, func(t *testing.T) { 4008 t.Parallel() 4009 client, mux, _ := setup(t) 4010 4011 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 4012 testMethod(t, r, "PUT") 4013 fmt.Fprint(w, `[{ 4014 "name": "octocat" 4015 }]`) 4016 }) 4017 input := []string{"octocat"} 4018 ctx := context.Background() 4019 got, _, err := client.Repositories.ReplaceUserRestrictions(ctx, "o", "r", test.branch, input) 4020 if err != nil { 4021 t.Errorf("Repositories.ReplaceUserRestrictions returned error: %v", err) 4022 } 4023 want := []*User{ 4024 {Name: Ptr("octocat")}, 4025 } 4026 if !cmp.Equal(got, want) { 4027 t.Errorf("Repositories.ReplaceUserRestrictions returned %+v, want %+v", got, want) 4028 } 4029 4030 const methodName = "ReplaceUserRestrictions" 4031 testBadOptions(t, methodName, func() (err error) { 4032 _, _, err = client.Repositories.ReplaceUserRestrictions(ctx, "\n", "\n", "\n", input) 4033 return err 4034 }) 4035 4036 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 4037 got, resp, err := client.Repositories.ReplaceUserRestrictions(ctx, "o", "r", test.branch, input) 4038 if got != nil { 4039 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 4040 } 4041 return resp, err 4042 }) 4043 }) 4044 } 4045 } 4046 4047 func TestRepositoriesService_AddUserRestrictions(t *testing.T) { 4048 t.Parallel() 4049 tests := []struct { 4050 branch string 4051 urlPath string 4052 }{ 4053 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/users"}, 4054 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/restrictions/users"}, 4055 } 4056 4057 for _, test := range tests { 4058 test := test 4059 t.Run(test.branch, func(t *testing.T) { 4060 t.Parallel() 4061 client, mux, _ := setup(t) 4062 4063 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 4064 testMethod(t, r, "POST") 4065 fmt.Fprint(w, `[{ 4066 "name": "octocat" 4067 }]`) 4068 }) 4069 input := []string{"octocat"} 4070 ctx := context.Background() 4071 got, _, err := client.Repositories.AddUserRestrictions(ctx, "o", "r", test.branch, input) 4072 if err != nil { 4073 t.Errorf("Repositories.AddUserRestrictions returned error: %v", err) 4074 } 4075 want := []*User{ 4076 {Name: Ptr("octocat")}, 4077 } 4078 if !cmp.Equal(got, want) { 4079 t.Errorf("Repositories.AddUserRestrictions returned %+v, want %+v", got, want) 4080 } 4081 4082 const methodName = "AddUserRestrictions" 4083 testBadOptions(t, methodName, func() (err error) { 4084 _, _, err = client.Repositories.AddUserRestrictions(ctx, "\n", "\n", "\n", input) 4085 return err 4086 }) 4087 4088 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 4089 got, resp, err := client.Repositories.AddUserRestrictions(ctx, "o", "r", test.branch, input) 4090 if got != nil { 4091 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 4092 } 4093 return resp, err 4094 }) 4095 }) 4096 } 4097 } 4098 4099 func TestRepositoriesService_RemoveUserRestrictions(t *testing.T) { 4100 t.Parallel() 4101 tests := []struct { 4102 branch string 4103 urlPath string 4104 }{ 4105 {branch: "b", urlPath: "/repos/o/r/branches/b/protection/restrictions/users"}, 4106 {branch: "feat/branch-50%", urlPath: "/repos/o/r/branches/feat%2fbranch-50%25/protection/restrictions/users"}, 4107 } 4108 4109 for _, test := range tests { 4110 test := test 4111 t.Run(test.branch, func(t *testing.T) { 4112 t.Parallel() 4113 client, mux, _ := setup(t) 4114 4115 mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { 4116 testMethod(t, r, "DELETE") 4117 fmt.Fprint(w, `[]`) 4118 }) 4119 input := []string{"octocat"} 4120 ctx := context.Background() 4121 got, _, err := client.Repositories.RemoveUserRestrictions(ctx, "o", "r", test.branch, input) 4122 if err != nil { 4123 t.Errorf("Repositories.RemoveUserRestrictions returned error: %v", err) 4124 } 4125 want := []*User{} 4126 if !cmp.Equal(got, want) { 4127 t.Errorf("Repositories.RemoveUserRestrictions returned %+v, want %+v", got, want) 4128 } 4129 4130 const methodName = "RemoveUserRestrictions" 4131 testBadOptions(t, methodName, func() (err error) { 4132 _, _, err = client.Repositories.RemoveUserRestrictions(ctx, "\n", "\n", "\n", input) 4133 return err 4134 }) 4135 4136 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 4137 got, resp, err := client.Repositories.RemoveUserRestrictions(ctx, "o", "r", test.branch, input) 4138 if got != nil { 4139 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 4140 } 4141 return resp, err 4142 }) 4143 }) 4144 } 4145 } 4146 4147 func TestRepositoriesService_Transfer(t *testing.T) { 4148 t.Parallel() 4149 client, mux, _ := setup(t) 4150 4151 input := TransferRequest{NewOwner: "a", NewName: Ptr("b"), TeamID: []int64{123}} 4152 4153 mux.HandleFunc("/repos/o/r/transfer", func(w http.ResponseWriter, r *http.Request) { 4154 var v TransferRequest 4155 assertNilError(t, json.NewDecoder(r.Body).Decode(&v)) 4156 4157 testMethod(t, r, "POST") 4158 if !cmp.Equal(v, input) { 4159 t.Errorf("Request body = %+v, want %+v", v, input) 4160 } 4161 4162 fmt.Fprint(w, `{"owner":{"login":"a"}}`) 4163 }) 4164 4165 ctx := context.Background() 4166 got, _, err := client.Repositories.Transfer(ctx, "o", "r", input) 4167 if err != nil { 4168 t.Errorf("Repositories.Transfer returned error: %v", err) 4169 } 4170 4171 want := &Repository{Owner: &User{Login: Ptr("a")}} 4172 if !cmp.Equal(got, want) { 4173 t.Errorf("Repositories.Transfer returned %+v, want %+v", got, want) 4174 } 4175 4176 const methodName = "Transfer" 4177 testBadOptions(t, methodName, func() (err error) { 4178 _, _, err = client.Repositories.Transfer(ctx, "\n", "\n", input) 4179 return err 4180 }) 4181 4182 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 4183 got, resp, err := client.Repositories.Transfer(ctx, "o", "r", input) 4184 if got != nil { 4185 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 4186 } 4187 return resp, err 4188 }) 4189 } 4190 4191 func TestRepositoriesService_Dispatch(t *testing.T) { 4192 t.Parallel() 4193 client, mux, _ := setup(t) 4194 4195 var input DispatchRequestOptions 4196 4197 mux.HandleFunc("/repos/o/r/dispatches", func(w http.ResponseWriter, r *http.Request) { 4198 var v DispatchRequestOptions 4199 assertNilError(t, json.NewDecoder(r.Body).Decode(&v)) 4200 4201 testMethod(t, r, "POST") 4202 if !cmp.Equal(v, input) { 4203 t.Errorf("Request body = %+v, want %+v", v, input) 4204 } 4205 4206 fmt.Fprint(w, `{"owner":{"login":"a"}}`) 4207 }) 4208 4209 ctx := context.Background() 4210 4211 testCases := []interface{}{ 4212 nil, 4213 struct { 4214 Foo string 4215 }{ 4216 Foo: "test", 4217 }, 4218 struct { 4219 Bar int 4220 }{ 4221 Bar: 42, 4222 }, 4223 struct { 4224 Foo string 4225 Bar int 4226 Baz bool 4227 }{ 4228 Foo: "test", 4229 Bar: 42, 4230 Baz: false, 4231 }, 4232 } 4233 4234 for _, tc := range testCases { 4235 if tc == nil { 4236 input = DispatchRequestOptions{EventType: "go"} 4237 } else { 4238 bytes, _ := json.Marshal(tc) 4239 payload := json.RawMessage(bytes) 4240 input = DispatchRequestOptions{EventType: "go", ClientPayload: &payload} 4241 } 4242 4243 got, _, err := client.Repositories.Dispatch(ctx, "o", "r", input) 4244 if err != nil { 4245 t.Errorf("Repositories.Dispatch returned error: %v", err) 4246 } 4247 4248 want := &Repository{Owner: &User{Login: Ptr("a")}} 4249 if !cmp.Equal(got, want) { 4250 t.Errorf("Repositories.Dispatch returned %+v, want %+v", got, want) 4251 } 4252 } 4253 4254 const methodName = "Dispatch" 4255 testBadOptions(t, methodName, func() (err error) { 4256 _, _, err = client.Repositories.Dispatch(ctx, "\n", "\n", input) 4257 return err 4258 }) 4259 4260 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 4261 got, resp, err := client.Repositories.Dispatch(ctx, "o", "r", input) 4262 if got != nil { 4263 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 4264 } 4265 return resp, err 4266 }) 4267 } 4268 4269 func TestAdvancedSecurity_Marshal(t *testing.T) { 4270 t.Parallel() 4271 testJSONMarshal(t, &AdvancedSecurity{}, "{}") 4272 4273 u := &AdvancedSecurity{ 4274 Status: Ptr("status"), 4275 } 4276 4277 want := `{ 4278 "status": "status" 4279 }` 4280 4281 testJSONMarshal(t, u, want) 4282 } 4283 4284 func TestAuthorizedActorsOnly_Marshal(t *testing.T) { 4285 t.Parallel() 4286 testJSONMarshal(t, &AuthorizedActorsOnly{}, "{}") 4287 4288 u := &AuthorizedActorsOnly{ 4289 From: Ptr(true), 4290 } 4291 4292 want := `{ 4293 "from" : true 4294 }` 4295 4296 testJSONMarshal(t, u, want) 4297 } 4298 4299 func TestDispatchRequestOptions_Marshal(t *testing.T) { 4300 t.Parallel() 4301 testJSONMarshal(t, &DispatchRequestOptions{}, "{}") 4302 4303 cp := json.RawMessage(`{"testKey":"testValue"}`) 4304 u := &DispatchRequestOptions{ 4305 EventType: "test_event_type", 4306 ClientPayload: &cp, 4307 } 4308 4309 want := `{ 4310 "event_type": "test_event_type", 4311 "client_payload": { 4312 "testKey": "testValue" 4313 } 4314 }` 4315 4316 testJSONMarshal(t, u, want) 4317 } 4318 4319 func TestTransferRequest_Marshal(t *testing.T) { 4320 t.Parallel() 4321 testJSONMarshal(t, &TransferRequest{}, "{}") 4322 4323 u := &TransferRequest{ 4324 NewOwner: "testOwner", 4325 NewName: Ptr("testName"), 4326 TeamID: []int64{1, 2}, 4327 } 4328 4329 want := `{ 4330 "new_owner": "testOwner", 4331 "new_name": "testName", 4332 "team_ids": [1,2] 4333 }` 4334 4335 testJSONMarshal(t, u, want) 4336 } 4337 4338 func TestSignaturesProtectedBranch_Marshal(t *testing.T) { 4339 t.Parallel() 4340 testJSONMarshal(t, &SignaturesProtectedBranch{}, "{}") 4341 4342 u := &SignaturesProtectedBranch{ 4343 URL: Ptr("https://www.testURL.in"), 4344 Enabled: Ptr(false), 4345 } 4346 4347 want := `{ 4348 "url": "https://www.testURL.in", 4349 "enabled": false 4350 }` 4351 4352 testJSONMarshal(t, u, want) 4353 4354 u2 := &SignaturesProtectedBranch{ 4355 URL: Ptr("testURL"), 4356 Enabled: Ptr(true), 4357 } 4358 4359 want2 := `{ 4360 "url": "testURL", 4361 "enabled": true 4362 }` 4363 4364 testJSONMarshal(t, u2, want2) 4365 } 4366 4367 func TestDismissalRestrictionsRequest_Marshal(t *testing.T) { 4368 t.Parallel() 4369 testJSONMarshal(t, &DismissalRestrictionsRequest{}, "{}") 4370 4371 u := &DismissalRestrictionsRequest{ 4372 Users: &[]string{"user1", "user2"}, 4373 Teams: &[]string{"team1", "team2"}, 4374 Apps: &[]string{"app1", "app2"}, 4375 } 4376 4377 want := `{ 4378 "users": ["user1","user2"], 4379 "teams": ["team1","team2"], 4380 "apps": ["app1","app2"] 4381 }` 4382 4383 testJSONMarshal(t, u, want) 4384 } 4385 4386 func TestAdminEnforcement_Marshal(t *testing.T) { 4387 t.Parallel() 4388 testJSONMarshal(t, &AdminEnforcement{}, "{}") 4389 4390 u := &AdminEnforcement{ 4391 URL: Ptr("https://www.test-url.in"), 4392 Enabled: false, 4393 } 4394 4395 want := `{ 4396 "url": "https://www.test-url.in", 4397 "enabled": false 4398 }` 4399 4400 testJSONMarshal(t, u, want) 4401 } 4402 4403 func TestPullRequestReviewsEnforcementUpdate_Marshal(t *testing.T) { 4404 t.Parallel() 4405 testJSONMarshal(t, &PullRequestReviewsEnforcementUpdate{}, "{}") 4406 4407 u := &PullRequestReviewsEnforcementUpdate{ 4408 BypassPullRequestAllowancesRequest: &BypassPullRequestAllowancesRequest{ 4409 Users: []string{"user1", "user2"}, 4410 Teams: []string{"team1", "team2"}, 4411 Apps: []string{"app1", "app2"}, 4412 }, 4413 DismissStaleReviews: Ptr(false), 4414 RequireCodeOwnerReviews: Ptr(true), 4415 RequiredApprovingReviewCount: 2, 4416 } 4417 4418 want := `{ 4419 "bypass_pull_request_allowances": { 4420 "users": ["user1","user2"], 4421 "teams": ["team1","team2"], 4422 "apps": ["app1","app2"] 4423 }, 4424 "dismiss_stale_reviews": false, 4425 "require_code_owner_reviews": true, 4426 "required_approving_review_count": 2 4427 }` 4428 4429 testJSONMarshal(t, u, want) 4430 } 4431 4432 func TestRequiredStatusCheck_Marshal(t *testing.T) { 4433 t.Parallel() 4434 testJSONMarshal(t, &RequiredStatusCheck{}, "{}") 4435 4436 u := &RequiredStatusCheck{ 4437 Context: "ctx", 4438 AppID: Ptr(int64(1)), 4439 } 4440 4441 want := `{ 4442 "context": "ctx", 4443 "app_id": 1 4444 }` 4445 4446 testJSONMarshal(t, u, want) 4447 } 4448 4449 func TestRepositoryTag_Marshal(t *testing.T) { 4450 t.Parallel() 4451 testJSONMarshal(t, &RepositoryTag{}, "{}") 4452 4453 u := &RepositoryTag{ 4454 Name: Ptr("v0.1"), 4455 Commit: &Commit{ 4456 SHA: Ptr("sha"), 4457 URL: Ptr("url"), 4458 }, 4459 ZipballURL: Ptr("zball"), 4460 TarballURL: Ptr("tball"), 4461 } 4462 4463 want := `{ 4464 "name": "v0.1", 4465 "commit": { 4466 "sha": "sha", 4467 "url": "url" 4468 }, 4469 "zipball_url": "zball", 4470 "tarball_url": "tball" 4471 }` 4472 4473 testJSONMarshal(t, u, want) 4474 } 4475 4476 func TestRepositoriesService_EnablePrivateReporting(t *testing.T) { 4477 t.Parallel() 4478 client, mux, _ := setup(t) 4479 4480 mux.HandleFunc("/repos/owner/repo/private-vulnerability-reporting", func(w http.ResponseWriter, r *http.Request) { 4481 testMethod(t, r, "PUT") 4482 w.WriteHeader(http.StatusNoContent) 4483 }) 4484 4485 ctx := context.Background() 4486 _, err := client.Repositories.EnablePrivateReporting(ctx, "owner", "repo") 4487 if err != nil { 4488 t.Errorf("Repositories.EnablePrivateReporting returned error: %v", err) 4489 } 4490 4491 const methodName = "EnablePrivateReporting" 4492 testBadOptions(t, methodName, func() (err error) { 4493 _, err = client.Repositories.EnablePrivateReporting(ctx, "\n", "\n") 4494 return err 4495 }) 4496 4497 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 4498 return client.Repositories.EnablePrivateReporting(ctx, "owner", "repo") 4499 }) 4500 } 4501 4502 func TestRepositoriesService_DisablePrivateReporting(t *testing.T) { 4503 t.Parallel() 4504 client, mux, _ := setup(t) 4505 4506 mux.HandleFunc("/repos/owner/repo/private-vulnerability-reporting", func(w http.ResponseWriter, r *http.Request) { 4507 testMethod(t, r, "DELETE") 4508 w.WriteHeader(http.StatusNoContent) 4509 }) 4510 4511 ctx := context.Background() 4512 _, err := client.Repositories.DisablePrivateReporting(ctx, "owner", "repo") 4513 if err != nil { 4514 t.Errorf("Repositories.DisablePrivateReporting returned error: %v", err) 4515 } 4516 4517 const methodName = "DisablePrivateReporting" 4518 testBadOptions(t, methodName, func() (err error) { 4519 _, err = client.Repositories.DisablePrivateReporting(ctx, "\n", "\n") 4520 return err 4521 }) 4522 4523 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 4524 return client.Repositories.DisablePrivateReporting(ctx, "owner", "repo") 4525 }) 4526 } 4527 4528 func TestRepositoriesService_IsPrivateReportingEnabled(t *testing.T) { 4529 t.Parallel() 4530 client, mux, _ := setup(t) 4531 4532 mux.HandleFunc("/repos/owner/repo/private-vulnerability-reporting", func(w http.ResponseWriter, r *http.Request) { 4533 testMethod(t, r, "GET") 4534 fmt.Fprint(w, `{"enabled": true}`) 4535 }) 4536 4537 ctx := context.Background() 4538 enabled, _, err := client.Repositories.IsPrivateReportingEnabled(ctx, "owner", "repo") 4539 if err != nil { 4540 t.Errorf("Repositories.IsPrivateReportingEnabled returned error: %v", err) 4541 } 4542 if want := true; enabled != want { 4543 t.Errorf("Repositories.IsPrivateReportingEnabled returned %+v, want %+v", enabled, want) 4544 } 4545 4546 const methodName = "IsPrivateReportingEnabled" 4547 testBadOptions(t, methodName, func() (err error) { 4548 _, _, err = client.Repositories.IsPrivateReportingEnabled(ctx, "\n", "\n") 4549 return err 4550 }) 4551 4552 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 4553 got, resp, err := client.Repositories.IsPrivateReportingEnabled(ctx, "owner", "repo") 4554 if got { 4555 t.Errorf("testNewRequestAndDoFailure %v = %#v, want false", methodName, got) 4556 } 4557 return resp, err 4558 }) 4559 } 4560 4561 func TestRepository_UnmarshalJSON(t *testing.T) { 4562 t.Parallel() 4563 var testCases = map[string]struct { 4564 data []byte 4565 wantRepository Repository 4566 wantErr bool 4567 }{ 4568 "Empty": { 4569 data: []byte("{}"), 4570 wantRepository: Repository{}, 4571 wantErr: false, 4572 }, 4573 "Invalid JSON": { 4574 data: []byte("{"), 4575 wantRepository: Repository{}, 4576 wantErr: true, 4577 }, 4578 "Partial project": { 4579 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"}}`), 4580 wantRepository: Repository{ID: Ptr(int64(10270722)), Name: Ptr("go-github"), Private: Ptr(false), Owner: &User{Login: Ptr("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: Ptr("google")}}, 4581 wantErr: false, 4582 }, 4583 "With custom properties": { 4584 data: []byte(`{"custom_properties":{"boolean":"false","text":"a","single-select":"a","multi-select":["a","b","c"]}}`), 4585 wantRepository: Repository{CustomProperties: map[string]interface{}{"boolean": "false", "text": "a", "single-select": "a", "multi-select": []interface{}{"a", "b", "c"}}}, 4586 wantErr: false, 4587 }, 4588 } 4589 4590 for name, tt := range testCases { 4591 tt := tt 4592 t.Run(name, func(t *testing.T) { 4593 t.Parallel() 4594 pk := Repository{} 4595 err := json.Unmarshal(tt.data, &pk) 4596 if err == nil && tt.wantErr { 4597 t.Errorf("Repository.UnmarshalJSON returned nil instead of an error") 4598 } 4599 if err != nil && !tt.wantErr { 4600 t.Errorf("Repository.UnmarshalJSON returned an unexpected error: %+v", err) 4601 } 4602 if !cmp.Equal(tt.wantRepository, pk) { 4603 t.Errorf("Repository.UnmarshalJSON expected repository %+v, got %+v", tt.wantRepository, pk) 4604 } 4605 }) 4606 } 4607 }