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