...

Source file src/github.com/google/go-github/v55/github/repos_rules_test.go

Documentation: github.com/google/go-github/v55/github

     1  // Copyright 2023 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  	"fmt"
    11  	"net/http"
    12  	"testing"
    13  
    14  	"github.com/google/go-cmp/cmp"
    15  )
    16  
    17  func TestRepositoryRule_UnmarshalJSON(t *testing.T) {
    18  	tests := map[string]struct {
    19  		data    string
    20  		want    *RepositoryRule
    21  		wantErr bool
    22  	}{
    23  		"Invalid JSON": {
    24  			data: `{`,
    25  			want: &RepositoryRule{
    26  				Type:       "",
    27  				Parameters: nil,
    28  			},
    29  			wantErr: true,
    30  		},
    31  		"Valid creation": {
    32  			data: `{"type":"creation"}`,
    33  			want: NewCreationRule(),
    34  		},
    35  		"Valid deletion": {
    36  			data: `{"type":"deletion"}`,
    37  			want: &RepositoryRule{
    38  				Type:       "deletion",
    39  				Parameters: nil,
    40  			},
    41  		},
    42  		"Valid required_linear_history": {
    43  			data: `{"type":"required_linear_history"}`,
    44  			want: &RepositoryRule{
    45  				Type:       "required_linear_history",
    46  				Parameters: nil,
    47  			},
    48  		},
    49  		"Valid required_signatures": {
    50  			data: `{"type":"required_signatures"}`,
    51  			want: &RepositoryRule{
    52  				Type:       "required_signatures",
    53  				Parameters: nil,
    54  			},
    55  		},
    56  		"Valid non_fast_forward": {
    57  			data: `{"type":"non_fast_forward"}`,
    58  			want: &RepositoryRule{
    59  				Type:       "non_fast_forward",
    60  				Parameters: nil,
    61  			},
    62  		},
    63  		"Valid update params": {
    64  			data: `{"type":"update","parameters":{"update_allows_fetch_and_merge":true}}`,
    65  			want: NewUpdateRule(&UpdateAllowsFetchAndMergeRuleParameters{UpdateAllowsFetchAndMerge: true}),
    66  		},
    67  		"Invalid update params": {
    68  			data: `{"type":"update","parameters":{"update_allows_fetch_and_merge":"true"}}`,
    69  			want: &RepositoryRule{
    70  				Type:       "update",
    71  				Parameters: nil,
    72  			},
    73  			wantErr: true,
    74  		},
    75  		"Valid required_deployments params": {
    76  			data: `{"type":"required_deployments","parameters":{"required_deployment_environments":["test"]}}`,
    77  			want: NewRequiredDeploymentsRule(&RequiredDeploymentEnvironmentsRuleParameters{
    78  				RequiredDeploymentEnvironments: []string{"test"},
    79  			}),
    80  		},
    81  		"Invalid required_deployments params": {
    82  			data: `{"type":"required_deployments","parameters":{"required_deployment_environments":true}}`,
    83  			want: &RepositoryRule{
    84  				Type:       "required_deployments",
    85  				Parameters: nil,
    86  			},
    87  			wantErr: true,
    88  		},
    89  		"Valid commit_message_pattern params": {
    90  			data: `{"type":"commit_message_pattern","parameters":{"operator":"starts_with","pattern":"github"}}`,
    91  			want: NewCommitMessagePatternRule(&RulePatternParameters{
    92  				Operator: "starts_with",
    93  				Pattern:  "github",
    94  			}),
    95  		},
    96  		"Invalid commit_message_pattern params": {
    97  			data: `{"type":"commit_message_pattern","parameters":{"operator":"starts_with","pattern":1}}`,
    98  			want: &RepositoryRule{
    99  				Type:       "commit_message_pattern",
   100  				Parameters: nil,
   101  			},
   102  			wantErr: true,
   103  		},
   104  		"Valid commit_author_email_pattern params": {
   105  			data: `{"type":"commit_author_email_pattern","parameters":{"operator":"starts_with","pattern":"github"}}`,
   106  			want: NewCommitAuthorEmailPatternRule(&RulePatternParameters{
   107  				Operator: "starts_with",
   108  				Pattern:  "github",
   109  			}),
   110  		},
   111  		"Invalid commit_author_email_pattern params": {
   112  			data: `{"type":"commit_author_email_pattern","parameters":{"operator":"starts_with","pattern":1}}`,
   113  			want: &RepositoryRule{
   114  				Type:       "commit_author_email_pattern",
   115  				Parameters: nil,
   116  			},
   117  			wantErr: true,
   118  		},
   119  		"Valid committer_email_pattern params": {
   120  			data: `{"type":"committer_email_pattern","parameters":{"operator":"starts_with","pattern":"github"}}`,
   121  			want: NewCommitterEmailPatternRule(&RulePatternParameters{
   122  				Operator: "starts_with",
   123  				Pattern:  "github",
   124  			}),
   125  		},
   126  		"Invalid committer_email_pattern params": {
   127  			data: `{"type":"committer_email_pattern","parameters":{"operator":"starts_with","pattern":1}}`,
   128  			want: &RepositoryRule{
   129  				Type:       "committer_email_pattern",
   130  				Parameters: nil,
   131  			},
   132  			wantErr: true,
   133  		},
   134  		"Valid branch_name_pattern params": {
   135  			data: `{"type":"branch_name_pattern","parameters":{"operator":"starts_with","pattern":"github"}}`,
   136  			want: NewBranchNamePatternRule(&RulePatternParameters{
   137  				Operator: "starts_with",
   138  				Pattern:  "github",
   139  			}),
   140  		},
   141  		"Invalid branch_name_pattern params": {
   142  			data: `{"type":"branch_name_pattern","parameters":{"operator":"starts_with","pattern":1}}`,
   143  			want: &RepositoryRule{
   144  				Type:       "branch_name_pattern",
   145  				Parameters: nil,
   146  			},
   147  			wantErr: true,
   148  		},
   149  		"Valid tag_name_pattern params": {
   150  			data: `{"type":"tag_name_pattern","parameters":{"operator":"starts_with","pattern":"github"}}`,
   151  			want: NewTagNamePatternRule(&RulePatternParameters{
   152  				Operator: "starts_with",
   153  				Pattern:  "github",
   154  			}),
   155  		},
   156  		"Invalid tag_name_pattern params": {
   157  			data: `{"type":"tag_name_pattern","parameters":{"operator":"starts_with","pattern":1}}`,
   158  			want: &RepositoryRule{
   159  				Type:       "tag_name_pattern",
   160  				Parameters: nil,
   161  			},
   162  			wantErr: true,
   163  		},
   164  		"Valid pull_request params": {
   165  			data: `{
   166  				"type":"pull_request",
   167  				"parameters":{
   168  					"dismiss_stale_reviews_on_push": true,
   169  					"require_code_owner_review": true,
   170  					"require_last_push_approval": true,
   171  					"required_approving_review_count": 1,
   172  					"required_review_thread_resolution":true
   173  				}
   174  			}`,
   175  			want: NewPullRequestRule(&PullRequestRuleParameters{
   176  				DismissStaleReviewsOnPush:      true,
   177  				RequireCodeOwnerReview:         true,
   178  				RequireLastPushApproval:        true,
   179  				RequiredApprovingReviewCount:   1,
   180  				RequiredReviewThreadResolution: true,
   181  			}),
   182  		},
   183  		"Invalid pull_request params": {
   184  			data: `{"type":"pull_request","parameters": {"dismiss_stale_reviews_on_push":"true"}}`,
   185  			want: &RepositoryRule{
   186  				Type:       "pull_request",
   187  				Parameters: nil,
   188  			},
   189  			wantErr: true,
   190  		},
   191  		"Valid required_status_checks params": {
   192  			data: `{"type":"required_status_checks","parameters":{"required_status_checks":[{"context":"test","integration_id":1}],"strict_required_status_checks_policy":true}}`,
   193  			want: NewRequiredStatusChecksRule(&RequiredStatusChecksRuleParameters{
   194  				RequiredStatusChecks: []RuleRequiredStatusChecks{
   195  					{
   196  						Context:       "test",
   197  						IntegrationID: Int64(1),
   198  					},
   199  				},
   200  				StrictRequiredStatusChecksPolicy: true,
   201  			}),
   202  		},
   203  		"Invalid required_status_checks params": {
   204  			data: `{"type":"required_status_checks",
   205  			"parameters": {
   206  				"required_status_checks": [
   207  				  {
   208  					"context": 1
   209  				  }
   210  				]
   211  			  }}`,
   212  			want: &RepositoryRule{
   213  				Type:       "required_status_checks",
   214  				Parameters: nil,
   215  			},
   216  			wantErr: true,
   217  		},
   218  		"Invalid type": {
   219  			data: `{"type":"unknown"}`,
   220  			want: &RepositoryRule{
   221  				Type:       "",
   222  				Parameters: nil,
   223  			},
   224  			wantErr: true,
   225  		},
   226  	}
   227  
   228  	for name, tc := range tests {
   229  		rule := &RepositoryRule{}
   230  
   231  		t.Run(name, func(t *testing.T) {
   232  			err := rule.UnmarshalJSON([]byte(tc.data))
   233  			if err == nil && tc.wantErr {
   234  				t.Errorf("RepositoryRule.UnmarshalJSON returned nil instead of an error")
   235  			}
   236  			if err != nil && !tc.wantErr {
   237  				t.Errorf("RepositoryRule.UnmarshalJSON returned an unexpected error: %+v", err)
   238  			}
   239  			if !cmp.Equal(tc.want, rule) {
   240  				t.Errorf("RepositoryRule.UnmarshalJSON expected rule %+v, got %+v", tc.want, rule)
   241  			}
   242  		})
   243  	}
   244  }
   245  
   246  func TestRepositoriesService_GetRulesForBranch(t *testing.T) {
   247  	client, mux, _, teardown := setup()
   248  	defer teardown()
   249  
   250  	mux.HandleFunc("/repos/o/repo/rules/branches/branch", func(w http.ResponseWriter, r *http.Request) {
   251  		testMethod(t, r, "GET")
   252  		fmt.Fprint(w, `[
   253  			{
   254  			  "type": "creation"
   255  			},
   256  			{
   257  			  "type": "update",
   258  			  "parameters": {
   259  			    "update_allows_fetch_and_merge": true
   260  			  }
   261  			}
   262  		]`)
   263  	})
   264  
   265  	ctx := context.Background()
   266  	rules, _, err := client.Repositories.GetRulesForBranch(ctx, "o", "repo", "branch")
   267  	if err != nil {
   268  		t.Errorf("Repositories.GetRulesForBranch returned error: %v", err)
   269  	}
   270  
   271  	creationRule := NewCreationRule()
   272  	updateRule := NewUpdateRule(&UpdateAllowsFetchAndMergeRuleParameters{
   273  		UpdateAllowsFetchAndMerge: true,
   274  	})
   275  
   276  	want := []*RepositoryRule{
   277  		creationRule,
   278  		updateRule,
   279  	}
   280  	if !cmp.Equal(rules, want) {
   281  		t.Errorf("Repositories.GetRulesForBranch returned %+v, want %+v", rules, want)
   282  	}
   283  
   284  	const methodName = "GetRulesForBranch"
   285  
   286  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   287  		got, resp, err := client.Repositories.GetRulesForBranch(ctx, "o", "repo", "branch")
   288  		if got != nil {
   289  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   290  		}
   291  		return resp, err
   292  	})
   293  }
   294  
   295  func TestRepositoriesService_GetRulesForBranchEmptyUpdateRule(t *testing.T) {
   296  	client, mux, _, teardown := setup()
   297  	defer teardown()
   298  
   299  	mux.HandleFunc("/repos/o/repo/rules/branches/branch", func(w http.ResponseWriter, r *http.Request) {
   300  		testMethod(t, r, "GET")
   301  		fmt.Fprint(w, `[
   302  			{
   303  			  "type": "update"
   304  			}
   305  		]`)
   306  	})
   307  
   308  	ctx := context.Background()
   309  	rules, _, err := client.Repositories.GetRulesForBranch(ctx, "o", "repo", "branch")
   310  	if err != nil {
   311  		t.Errorf("Repositories.GetRulesForBranch returned error: %v", err)
   312  	}
   313  
   314  	updateRule := NewUpdateRule(nil)
   315  
   316  	want := []*RepositoryRule{
   317  		updateRule,
   318  	}
   319  	if !cmp.Equal(rules, want) {
   320  		t.Errorf("Repositories.GetRulesForBranch returned %+v, want %+v", Stringify(rules), Stringify(want))
   321  	}
   322  
   323  	const methodName = "GetRulesForBranch"
   324  
   325  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   326  		got, resp, err := client.Repositories.GetRulesForBranch(ctx, "o", "repo", "branch")
   327  		if got != nil {
   328  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   329  		}
   330  		return resp, err
   331  	})
   332  }
   333  
   334  func TestRepositoriesService_GetAllRulesets(t *testing.T) {
   335  	client, mux, _, teardown := setup()
   336  	defer teardown()
   337  
   338  	mux.HandleFunc("/repos/o/repo/rulesets", func(w http.ResponseWriter, r *http.Request) {
   339  		testMethod(t, r, "GET")
   340  		fmt.Fprint(w, `[
   341  			{
   342  			  "id": 42,
   343  			  "name": "ruleset",
   344  			  "source_type": "Repository",
   345  			  "source": "o/repo",
   346  			  "enforcement": "enabled"
   347  			},
   348  			{
   349  			  "id": 314,
   350  			  "name": "Another ruleset",
   351  			  "source_type": "Repository",
   352  			  "source": "o/repo",
   353  			  "enforcement": "enabled"
   354  			}
   355  		]`)
   356  	})
   357  
   358  	ctx := context.Background()
   359  	ruleSet, _, err := client.Repositories.GetAllRulesets(ctx, "o", "repo", false)
   360  	if err != nil {
   361  		t.Errorf("Repositories.GetAllRulesets returned error: %v", err)
   362  	}
   363  
   364  	want := []*Ruleset{
   365  		{
   366  			ID:          Int64(42),
   367  			Name:        "ruleset",
   368  			SourceType:  String("Repository"),
   369  			Source:      "o/repo",
   370  			Enforcement: "enabled",
   371  		},
   372  		{
   373  			ID:          Int64(314),
   374  			Name:        "Another ruleset",
   375  			SourceType:  String("Repository"),
   376  			Source:      "o/repo",
   377  			Enforcement: "enabled",
   378  		},
   379  	}
   380  	if !cmp.Equal(ruleSet, want) {
   381  		t.Errorf("Repositories.GetAllRulesets returned %+v, want %+v", ruleSet, want)
   382  	}
   383  
   384  	const methodName = "GetAllRulesets"
   385  
   386  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   387  		got, resp, err := client.Repositories.GetAllRulesets(ctx, "o", "repo", false)
   388  		if got != nil {
   389  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   390  		}
   391  		return resp, err
   392  	})
   393  }
   394  
   395  func TestRepositoriesService_CreateRuleset(t *testing.T) {
   396  	client, mux, _, teardown := setup()
   397  	defer teardown()
   398  
   399  	mux.HandleFunc("/repos/o/repo/rulesets", func(w http.ResponseWriter, r *http.Request) {
   400  		testMethod(t, r, "POST")
   401  		fmt.Fprint(w, `{
   402  			"id": 42,
   403  			"name": "ruleset",
   404  			"source_type": "Repository",
   405  			"source": "o/repo",
   406  			"enforcement": "enabled"
   407  		}`)
   408  	})
   409  
   410  	ctx := context.Background()
   411  	ruleSet, _, err := client.Repositories.CreateRuleset(ctx, "o", "repo", &Ruleset{
   412  		Name:        "ruleset",
   413  		Enforcement: "enabled",
   414  	})
   415  	if err != nil {
   416  		t.Errorf("Repositories.CreateRuleset returned error: %v", err)
   417  	}
   418  
   419  	want := &Ruleset{
   420  		ID:          Int64(42),
   421  		Name:        "ruleset",
   422  		SourceType:  String("Repository"),
   423  		Source:      "o/repo",
   424  		Enforcement: "enabled",
   425  	}
   426  	if !cmp.Equal(ruleSet, want) {
   427  		t.Errorf("Repositories.CreateRuleset returned %+v, want %+v", ruleSet, want)
   428  	}
   429  
   430  	const methodName = "CreateRuleset"
   431  
   432  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   433  		got, resp, err := client.Repositories.CreateRuleset(ctx, "o", "repo", &Ruleset{})
   434  		if got != nil {
   435  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   436  		}
   437  		return resp, err
   438  	})
   439  }
   440  
   441  func TestRepositoriesService_GetRuleset(t *testing.T) {
   442  	client, mux, _, teardown := setup()
   443  	defer teardown()
   444  
   445  	mux.HandleFunc("/repos/o/repo/rulesets/42", func(w http.ResponseWriter, r *http.Request) {
   446  		testMethod(t, r, "GET")
   447  		fmt.Fprint(w, `{
   448  			"id": 42,
   449  			"name": "ruleset",
   450  			"source_type": "Organization",
   451  			"source": "o",
   452  			"enforcement": "enabled"
   453  		}`)
   454  	})
   455  
   456  	ctx := context.Background()
   457  	ruleSet, _, err := client.Repositories.GetRuleset(ctx, "o", "repo", 42, true)
   458  	if err != nil {
   459  		t.Errorf("Repositories.GetRuleset returned error: %v", err)
   460  	}
   461  
   462  	want := &Ruleset{
   463  		ID:          Int64(42),
   464  		Name:        "ruleset",
   465  		SourceType:  String("Organization"),
   466  		Source:      "o",
   467  		Enforcement: "enabled",
   468  	}
   469  	if !cmp.Equal(ruleSet, want) {
   470  		t.Errorf("Repositories.GetRuleset returned %+v, want %+v", ruleSet, want)
   471  	}
   472  
   473  	const methodName = "GetRuleset"
   474  
   475  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   476  		got, resp, err := client.Repositories.GetRuleset(ctx, "o", "repo", 42, true)
   477  		if got != nil {
   478  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   479  		}
   480  		return resp, err
   481  	})
   482  }
   483  
   484  func TestRepositoriesService_UpdateRuleset(t *testing.T) {
   485  	client, mux, _, teardown := setup()
   486  	defer teardown()
   487  
   488  	mux.HandleFunc("/repos/o/repo/rulesets/42", func(w http.ResponseWriter, r *http.Request) {
   489  		testMethod(t, r, "PUT")
   490  		fmt.Fprint(w, `{
   491  			"id": 42,
   492  			"name": "ruleset",
   493  			"source_type": "Repository",
   494  			"source": "o/repo",
   495  			"enforcement": "enabled"
   496  		}`)
   497  	})
   498  
   499  	ctx := context.Background()
   500  	ruleSet, _, err := client.Repositories.UpdateRuleset(ctx, "o", "repo", 42, &Ruleset{
   501  		Name:        "ruleset",
   502  		Enforcement: "enabled",
   503  	})
   504  	if err != nil {
   505  		t.Errorf("Repositories.UpdateRuleset returned error: %v", err)
   506  	}
   507  
   508  	want := &Ruleset{
   509  		ID:          Int64(42),
   510  		Name:        "ruleset",
   511  		SourceType:  String("Repository"),
   512  		Source:      "o/repo",
   513  		Enforcement: "enabled",
   514  	}
   515  	if !cmp.Equal(ruleSet, want) {
   516  		t.Errorf("Repositories.UpdateRuleset returned %+v, want %+v", ruleSet, want)
   517  	}
   518  
   519  	const methodName = "UpdateRuleset"
   520  
   521  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   522  		got, resp, err := client.Repositories.UpdateRuleset(ctx, "o", "repo", 42, nil)
   523  		if got != nil {
   524  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   525  		}
   526  		return resp, err
   527  	})
   528  }
   529  
   530  func TestRepositoriesService_DeleteRuleset(t *testing.T) {
   531  	client, mux, _, teardown := setup()
   532  	defer teardown()
   533  
   534  	mux.HandleFunc("/repos/o/repo/rulesets/42", func(w http.ResponseWriter, r *http.Request) {
   535  		testMethod(t, r, "DELETE")
   536  	})
   537  
   538  	ctx := context.Background()
   539  	_, err := client.Repositories.DeleteRuleset(ctx, "o", "repo", 42)
   540  	if err != nil {
   541  		t.Errorf("Repositories.DeleteRuleset returned error: %v", err)
   542  	}
   543  
   544  	const methodName = "DeleteRuleset"
   545  
   546  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   547  		return client.Repositories.DeleteRuleset(ctx, "o", "repo", 42)
   548  	})
   549  }
   550  

View as plain text