1
2
3
4
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