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