github.com/google/go-github/v49@v49.1.0/github/repos_environments_test.go (about) 1 // Copyright 2021 The go-github AUTHORS. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 package github 7 8 import ( 9 "context" 10 "encoding/json" 11 "fmt" 12 "net/http" 13 "testing" 14 15 "github.com/google/go-cmp/cmp" 16 ) 17 18 func TestRequiredReviewer_UnmarshalJSON(t *testing.T) { 19 var testCases = map[string]struct { 20 data []byte 21 wantRule []*RequiredReviewer 22 wantError bool 23 }{ 24 "User Reviewer": { 25 data: []byte(`[{"type": "User", "reviewer": {"id": 1,"login": "octocat"}}]`), 26 wantRule: []*RequiredReviewer{{Type: String("User"), Reviewer: &User{ID: Int64(1), Login: String("octocat")}}}, 27 wantError: false, 28 }, 29 "Team Reviewer": { 30 data: []byte(`[{"type": "Team", "reviewer": {"id": 1, "name": "Justice League"}}]`), 31 wantRule: []*RequiredReviewer{{Type: String("Team"), Reviewer: &Team{ID: Int64(1), Name: String("Justice League")}}}, 32 wantError: false, 33 }, 34 "Both Types Reviewer": { 35 data: []byte(`[{"type": "User", "reviewer": {"id": 1,"login": "octocat"}},{"type": "Team", "reviewer": {"id": 1, "name": "Justice League"}}]`), 36 wantRule: []*RequiredReviewer{{Type: String("User"), Reviewer: &User{ID: Int64(1), Login: String("octocat")}}, {Type: String("Team"), Reviewer: &Team{ID: Int64(1), Name: String("Justice League")}}}, 37 wantError: false, 38 }, 39 "Empty JSON Object": { 40 data: []byte(`[]`), 41 wantRule: []*RequiredReviewer{}, 42 wantError: false, 43 }, 44 "Bad JSON Object": { 45 data: []byte(`[badjson: 1]`), 46 wantRule: []*RequiredReviewer{}, 47 wantError: true, 48 }, 49 "Wrong Type Type in Reviewer Object": { 50 data: []byte(`[{"type": 1, "reviewer": {"id": 1}}]`), 51 wantRule: []*RequiredReviewer{{Type: nil, Reviewer: nil}}, 52 wantError: true, 53 }, 54 "Wrong ID Type in User Object": { 55 data: []byte(`[{"type": "User", "reviewer": {"id": "string"}}]`), 56 wantRule: []*RequiredReviewer{{Type: String("User"), Reviewer: nil}}, 57 wantError: true, 58 }, 59 "Wrong ID Type in Team Object": { 60 data: []byte(`[{"type": "Team", "reviewer": {"id": "string"}}]`), 61 wantRule: []*RequiredReviewer{{Type: String("Team"), Reviewer: nil}}, 62 wantError: true, 63 }, 64 "Wrong Type of Reviewer": { 65 data: []byte(`[{"type": "Cat", "reviewer": {"id": 1,"login": "octocat"}}]`), 66 wantRule: []*RequiredReviewer{{Type: nil, Reviewer: nil}}, 67 wantError: true, 68 }, 69 } 70 71 for name, test := range testCases { 72 t.Run(name, func(t *testing.T) { 73 rule := []*RequiredReviewer{} 74 err := json.Unmarshal(test.data, &rule) 75 if err != nil && !test.wantError { 76 t.Errorf("RequiredReviewer.UnmarshalJSON returned an error when we expected nil") 77 } 78 if err == nil && test.wantError { 79 t.Errorf("RequiredReviewer.UnmarshalJSON returned no error when we expected one") 80 } 81 if !cmp.Equal(test.wantRule, rule) { 82 t.Errorf("RequiredReviewer.UnmarshalJSON expected rule %+v, got %+v", test.wantRule, rule) 83 } 84 }) 85 } 86 } 87 88 func TestCreateUpdateEnvironment_MarshalJSON(t *testing.T) { 89 cu := &CreateUpdateEnvironment{} 90 91 got, err := cu.MarshalJSON() 92 if err != nil { 93 t.Errorf("MarshalJSON: %v", err) 94 } 95 96 want := `{"wait_timer":0,"reviewers":null,"deployment_branch_policy":null}` 97 if string(got) != want { 98 t.Errorf("MarshalJSON = %s, want %v", got, want) 99 } 100 } 101 102 func TestRepositoriesService_ListEnvironments(t *testing.T) { 103 client, mux, _, teardown := setup() 104 defer teardown() 105 106 mux.HandleFunc("/repos/o/r/environments", func(w http.ResponseWriter, r *http.Request) { 107 testMethod(t, r, "GET") 108 fmt.Fprint(w, `{"total_count":1, "environments":[{"id":1}, {"id": 2}]}`) 109 }) 110 111 opt := &EnvironmentListOptions{ 112 ListOptions: ListOptions{ 113 Page: 2, 114 PerPage: 2, 115 }, 116 } 117 ctx := context.Background() 118 environments, _, err := client.Repositories.ListEnvironments(ctx, "o", "r", opt) 119 if err != nil { 120 t.Errorf("Repositories.ListEnvironments returned error: %v", err) 121 } 122 want := &EnvResponse{TotalCount: Int(1), Environments: []*Environment{{ID: Int64(1)}, {ID: Int64(2)}}} 123 if !cmp.Equal(environments, want) { 124 t.Errorf("Repositories.ListEnvironments returned %+v, want %+v", environments, want) 125 } 126 127 const methodName = "ListEnvironments" 128 testBadOptions(t, methodName, func() (err error) { 129 _, _, err = client.Repositories.ListEnvironments(ctx, "\n", "\n", opt) 130 return err 131 }) 132 133 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 134 got, resp, err := client.Repositories.ListEnvironments(ctx, "o", "r", opt) 135 if got != nil { 136 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 137 } 138 return resp, err 139 }) 140 } 141 142 func TestRepositoriesService_GetEnvironment(t *testing.T) { 143 client, mux, _, teardown := setup() 144 defer teardown() 145 146 mux.HandleFunc("/repos/o/r/environments/e", func(w http.ResponseWriter, r *http.Request) { 147 testMethod(t, r, "GET") 148 fmt.Fprint(w, `{"id": 1,"name": "staging", "deployment_branch_policy": {"protected_branches": true, "custom_branch_policies": false}}`) 149 }) 150 151 ctx := context.Background() 152 release, resp, err := client.Repositories.GetEnvironment(ctx, "o", "r", "e") 153 if err != nil { 154 t.Errorf("Repositories.GetEnvironment returned error: %v\n%v", err, resp.Body) 155 } 156 157 want := &Environment{ID: Int64(1), Name: String("staging"), DeploymentBranchPolicy: &BranchPolicy{ProtectedBranches: Bool(true), CustomBranchPolicies: Bool(false)}} 158 if !cmp.Equal(release, want) { 159 t.Errorf("Repositories.GetEnvironment returned %+v, want %+v", release, want) 160 } 161 162 const methodName = "GetEnvironment" 163 testBadOptions(t, methodName, func() (err error) { 164 _, _, err = client.Repositories.GetEnvironment(ctx, "\n", "\n", "\n") 165 return err 166 }) 167 168 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 169 got, resp, err := client.Repositories.GetEnvironment(ctx, "o", "r", "e") 170 if got != nil { 171 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 172 } 173 return resp, err 174 }) 175 } 176 177 func TestRepositoriesService_CreateEnvironment(t *testing.T) { 178 client, mux, _, teardown := setup() 179 defer teardown() 180 181 input := &CreateUpdateEnvironment{ 182 WaitTimer: Int(30), 183 } 184 185 mux.HandleFunc("/repos/o/r/environments/e", func(w http.ResponseWriter, r *http.Request) { 186 v := new(CreateUpdateEnvironment) 187 json.NewDecoder(r.Body).Decode(v) 188 189 testMethod(t, r, "PUT") 190 want := &CreateUpdateEnvironment{WaitTimer: Int(30)} 191 if !cmp.Equal(v, want) { 192 t.Errorf("Request body = %+v, want %+v", v, want) 193 } 194 fmt.Fprint(w, `{"id": 1, "name": "staging", "protection_rules": [{"id": 1, "type": "wait_timer", "wait_timer": 30}]}`) 195 }) 196 197 ctx := context.Background() 198 release, _, err := client.Repositories.CreateUpdateEnvironment(ctx, "o", "r", "e", input) 199 if err != nil { 200 t.Errorf("Repositories.CreateUpdateEnvironment returned error: %v", err) 201 } 202 203 want := &Environment{ID: Int64(1), Name: String("staging"), ProtectionRules: []*ProtectionRule{{ID: Int64(1), Type: String("wait_timer"), WaitTimer: Int(30)}}} 204 if !cmp.Equal(release, want) { 205 t.Errorf("Repositories.CreateUpdateEnvironment returned %+v, want %+v", release, want) 206 } 207 208 const methodName = "CreateUpdateEnvironment" 209 testBadOptions(t, methodName, func() (err error) { 210 _, _, err = client.Repositories.CreateUpdateEnvironment(ctx, "\n", "\n", "\n", input) 211 return err 212 }) 213 214 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 215 got, resp, err := client.Repositories.CreateUpdateEnvironment(ctx, "o", "r", "e", input) 216 if got != nil { 217 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 218 } 219 return resp, err 220 }) 221 } 222 223 func TestRepositoriesService_CreateEnvironment_noEnterprise(t *testing.T) { 224 client, mux, _, teardown := setup() 225 defer teardown() 226 227 input := &CreateUpdateEnvironment{} 228 callCount := 0 229 230 mux.HandleFunc("/repos/o/r/environments/e", func(w http.ResponseWriter, r *http.Request) { 231 v := new(CreateUpdateEnvironment) 232 json.NewDecoder(r.Body).Decode(v) 233 234 testMethod(t, r, "PUT") 235 if callCount == 0 { 236 w.WriteHeader(http.StatusUnprocessableEntity) 237 callCount++ 238 } else { 239 want := &CreateUpdateEnvironment{} 240 if !cmp.Equal(v, want) { 241 t.Errorf("Request body = %+v, want %+v", v, want) 242 } 243 fmt.Fprint(w, `{"id": 1, "name": "staging", "protection_rules": []}`) 244 } 245 }) 246 247 ctx := context.Background() 248 release, _, err := client.Repositories.CreateUpdateEnvironment(ctx, "o", "r", "e", input) 249 if err != nil { 250 t.Errorf("Repositories.CreateUpdateEnvironment returned error: %v", err) 251 } 252 253 want := &Environment{ID: Int64(1), Name: String("staging"), ProtectionRules: []*ProtectionRule{}} 254 if !cmp.Equal(release, want) { 255 t.Errorf("Repositories.CreateUpdateEnvironment returned %+v, want %+v", release, want) 256 } 257 } 258 259 func TestRepositoriesService_createNewEnvNoEnterprise(t *testing.T) { 260 client, mux, _, teardown := setup() 261 defer teardown() 262 263 input := &CreateUpdateEnvironment{ 264 DeploymentBranchPolicy: &BranchPolicy{ 265 ProtectedBranches: Bool(true), 266 CustomBranchPolicies: Bool(false), 267 }, 268 } 269 270 mux.HandleFunc("/repos/o/r/environments/e", func(w http.ResponseWriter, r *http.Request) { 271 v := new(createUpdateEnvironmentNoEnterprise) 272 json.NewDecoder(r.Body).Decode(v) 273 274 testMethod(t, r, "PUT") 275 want := &createUpdateEnvironmentNoEnterprise{ 276 DeploymentBranchPolicy: &BranchPolicy{ 277 ProtectedBranches: Bool(true), 278 CustomBranchPolicies: Bool(false), 279 }, 280 } 281 if !cmp.Equal(v, want) { 282 t.Errorf("Request body = %+v, want %+v", v, want) 283 } 284 fmt.Fprint(w, `{"id": 1, "name": "staging", "protection_rules": [{"id": 1, "node_id": "id", "type": "branch_policy"}], "deployment_branch_policy": {"protected_branches": true, "custom_branch_policies": false}}`) 285 }) 286 287 ctx := context.Background() 288 release, _, err := client.Repositories.createNewEnvNoEnterprise(ctx, "repos/o/r/environments/e", input) 289 if err != nil { 290 t.Errorf("Repositories.createNewEnvNoEnterprise returned error: %v", err) 291 } 292 293 want := &Environment{ 294 ID: Int64(1), 295 Name: String("staging"), 296 ProtectionRules: []*ProtectionRule{ 297 { 298 ID: Int64(1), 299 NodeID: String("id"), 300 Type: String("branch_policy"), 301 }, 302 }, 303 DeploymentBranchPolicy: &BranchPolicy{ 304 ProtectedBranches: Bool(true), 305 CustomBranchPolicies: Bool(false), 306 }, 307 } 308 if !cmp.Equal(release, want) { 309 t.Errorf("Repositories.createNewEnvNoEnterprise returned %+v, want %+v", release, want) 310 } 311 312 const methodName = "createNewEnvNoEnterprise" 313 testBadOptions(t, methodName, func() (err error) { 314 _, _, err = client.Repositories.createNewEnvNoEnterprise(ctx, "\n", input) 315 return err 316 }) 317 318 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 319 got, resp, err := client.Repositories.createNewEnvNoEnterprise(ctx, "repos/o/r/environments/e", input) 320 if got != nil { 321 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 322 } 323 return resp, err 324 }) 325 } 326 327 func TestRepositoriesService_DeleteEnvironment(t *testing.T) { 328 client, mux, _, teardown := setup() 329 defer teardown() 330 331 mux.HandleFunc("/repos/o/r/environments/e", func(w http.ResponseWriter, r *http.Request) { 332 testMethod(t, r, "DELETE") 333 }) 334 335 ctx := context.Background() 336 _, err := client.Repositories.DeleteEnvironment(ctx, "o", "r", "e") 337 if err != nil { 338 t.Errorf("Repositories.DeleteEnvironment returned error: %v", err) 339 } 340 341 const methodName = "DeleteEnvironment" 342 testBadOptions(t, methodName, func() (err error) { 343 _, err = client.Repositories.DeleteEnvironment(ctx, "\n", "\n", "\n") 344 return err 345 }) 346 347 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 348 return client.Repositories.DeleteEnvironment(ctx, "o", "r", "e") 349 }) 350 } 351 352 func TestRepoEnvironment_Marshal(t *testing.T) { 353 testJSONMarshal(t, &EnvResponse{}, "{}") 354 355 repoEnv := &EnvResponse{ 356 TotalCount: Int(1), 357 Environments: []*Environment{ 358 { 359 Owner: String("me"), 360 Repo: String("se"), 361 EnvironmentName: String("dev"), 362 WaitTimer: Int(123), 363 Reviewers: []*EnvReviewers{ 364 { 365 Type: String("main"), 366 ID: Int64(1), 367 }, 368 { 369 Type: String("rev"), 370 ID: Int64(2), 371 }, 372 }, 373 DeploymentBranchPolicy: &BranchPolicy{ 374 ProtectedBranches: Bool(false), 375 CustomBranchPolicies: Bool(false), 376 }, 377 ID: Int64(2), 378 NodeID: String("star"), 379 Name: String("eg"), 380 URL: String("https://hey.in"), 381 HTMLURL: String("htmlurl"), 382 CreatedAt: &Timestamp{referenceTime}, 383 UpdatedAt: &Timestamp{referenceTime}, 384 ProtectionRules: []*ProtectionRule{ 385 { 386 ID: Int64(21), 387 NodeID: String("mnb"), 388 Type: String("ewq"), 389 WaitTimer: Int(9090), 390 }, 391 }, 392 }, 393 }, 394 } 395 396 want := `{ 397 "total_count":1, 398 "environments":[ 399 { 400 "owner":"me", 401 "repo":"se", 402 "environment_name":"dev", 403 "wait_timer":123, 404 "reviewers":[ 405 { 406 "type":"main", 407 "id":1 408 }, 409 { 410 "type":"rev", 411 "id":2 412 } 413 ], 414 "deployment_branch_policy":{ 415 "protected_branches":false, 416 "custom_branch_policies":false 417 }, 418 "id":2, 419 "node_id":"star", 420 "name":"eg", 421 "url":"https://hey.in", 422 "html_url":"htmlurl", 423 "created_at":` + referenceTimeStr + `, 424 "updated_at":` + referenceTimeStr + `, 425 "protection_rules":[ 426 { 427 "id":21, 428 "node_id":"mnb", 429 "type":"ewq", 430 "wait_timer":9090 431 } 432 ] 433 } 434 ] 435 }` 436 437 testJSONMarshal(t, repoEnv, want) 438 } 439 440 func TestEnvReviewers_Marshal(t *testing.T) { 441 testJSONMarshal(t, &EnvReviewers{}, "{}") 442 443 repoEnv := &EnvReviewers{ 444 Type: String("main"), 445 ID: Int64(1), 446 } 447 448 want := `{ 449 "type":"main", 450 "id":1 451 }` 452 453 testJSONMarshal(t, repoEnv, want) 454 } 455 456 func TestEnvironment_Marshal(t *testing.T) { 457 testJSONMarshal(t, &Environment{}, "{}") 458 459 repoEnv := &Environment{ 460 Owner: String("o"), 461 Repo: String("r"), 462 EnvironmentName: String("e"), 463 WaitTimer: Int(123), 464 Reviewers: []*EnvReviewers{ 465 { 466 Type: String("main"), 467 ID: Int64(1), 468 }, 469 { 470 Type: String("rev"), 471 ID: Int64(2), 472 }, 473 }, 474 DeploymentBranchPolicy: &BranchPolicy{ 475 ProtectedBranches: Bool(false), 476 CustomBranchPolicies: Bool(false), 477 }, 478 ID: Int64(2), 479 NodeID: String("star"), 480 Name: String("eg"), 481 URL: String("https://hey.in"), 482 HTMLURL: String("htmlurl"), 483 CreatedAt: &Timestamp{referenceTime}, 484 UpdatedAt: &Timestamp{referenceTime}, 485 ProtectionRules: []*ProtectionRule{ 486 { 487 ID: Int64(21), 488 NodeID: String("mnb"), 489 Type: String("ewq"), 490 WaitTimer: Int(9090), 491 }, 492 }, 493 } 494 495 want := `{ 496 "owner":"o", 497 "repo":"r", 498 "environment_name":"e", 499 "wait_timer":123, 500 "reviewers":[ 501 { 502 "type":"main", 503 "id":1 504 }, 505 { 506 "type":"rev", 507 "id":2 508 } 509 ], 510 "deployment_branch_policy":{ 511 "protected_branches":false, 512 "custom_branch_policies":false 513 }, 514 "id":2, 515 "node_id":"star", 516 "name":"eg", 517 "url":"https://hey.in", 518 "html_url":"htmlurl", 519 "created_at":` + referenceTimeStr + `, 520 "updated_at":` + referenceTimeStr + `, 521 "protection_rules":[ 522 { 523 "id":21, 524 "node_id":"mnb", 525 "type":"ewq", 526 "wait_timer":9090 527 } 528 ] 529 }` 530 531 testJSONMarshal(t, repoEnv, want) 532 } 533 534 func TestBranchPolicy_Marshal(t *testing.T) { 535 testJSONMarshal(t, &BranchPolicy{}, "{}") 536 537 bp := &BranchPolicy{ 538 ProtectedBranches: Bool(false), 539 CustomBranchPolicies: Bool(false), 540 } 541 542 want := `{ 543 "protected_branches": false, 544 "custom_branch_policies": false 545 }` 546 547 testJSONMarshal(t, bp, want) 548 }