Skip to content

Commit e5f03fc

Browse files
committed
Add MarshalJSON tests for RepositoryRulesetRules with full coverage
1 parent 2790da5 commit e5f03fc

File tree

1 file changed

+277
-0
lines changed

1 file changed

+277
-0
lines changed
Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
// Copyright 2024 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+
"encoding/json"
10+
"testing"
11+
)
12+
13+
func TestRepositoryRulesetRules_MarshalJSON(t *testing.T) {
14+
tests := []struct {
15+
name string
16+
input RepositoryRulesetRules
17+
expected string
18+
expectError bool
19+
}{
20+
{
21+
name: "Empty RepositoryRulesetRules returns empty array",
22+
input: RepositoryRulesetRules{},
23+
expected: "[]",
24+
},
25+
{
26+
name: "RepositoryRulesetRules with Creation rule only",
27+
input: RepositoryRulesetRules{
28+
Creation: &EmptyRuleParameters{},
29+
},
30+
expected: `[{"type":"creation"}]`,
31+
},
32+
{
33+
name: "RepositoryRulesetRules with Deletion rule only",
34+
input: RepositoryRulesetRules{
35+
Deletion: &EmptyRuleParameters{},
36+
},
37+
expected: `[{"type":"deletion"}]`,
38+
},
39+
{
40+
name: "RepositoryRulesetRules with basic rules",
41+
input: RepositoryRulesetRules{
42+
Creation: &EmptyRuleParameters{},
43+
Deletion: &EmptyRuleParameters{},
44+
RequiredLinearHistory: &EmptyRuleParameters{},
45+
NonFastForward: &EmptyRuleParameters{},
46+
},
47+
expected: `[{"type":"creation"},{"type":"deletion"},{"type":"required_linear_history"},{"type":"non_fast_forward"}]`,
48+
},
49+
{
50+
name: "RepositoryRulesetRules with Update rule",
51+
input: RepositoryRulesetRules{
52+
Update: &UpdateRuleParameters{
53+
UpdateAllowsFetchAndMerge: true,
54+
},
55+
},
56+
expected: `[{"type":"update","parameters":{"update_allows_fetch_and_merge":true}}]`,
57+
},
58+
{
59+
name: "RepositoryRulesetRules with RequiredDeployments",
60+
input: RepositoryRulesetRules{
61+
RequiredDeployments: &RequiredDeploymentsRuleParameters{
62+
RequiredDeploymentEnvironments: []string{"production", "staging"},
63+
},
64+
},
65+
expected: `[{"type":"required_deployments","parameters":{"required_deployment_environments":["production","staging"]}}]`,
66+
},
67+
{
68+
name: "RepositoryRulesetRules with RequiredSignatures",
69+
input: RepositoryRulesetRules{
70+
RequiredSignatures: &EmptyRuleParameters{},
71+
},
72+
expected: `[{"type":"required_signatures"}]`,
73+
},
74+
{
75+
name: "RepositoryRulesetRules with PullRequest rule",
76+
input: RepositoryRulesetRules{
77+
PullRequest: &PullRequestRuleParameters{
78+
AllowedMergeMethods: []PullRequestMergeMethod{PullRequestMergeMethodRebase, PullRequestMergeMethodSquash},
79+
DismissStaleReviewsOnPush: true,
80+
RequireCodeOwnerReview: true,
81+
RequireLastPushApproval: true,
82+
RequiredApprovingReviewCount: 2,
83+
RequiredReviewThreadResolution: true,
84+
},
85+
},
86+
expected: `[{"type":"pull_request","parameters":{"allowed_merge_methods":["rebase","squash"],"dismiss_stale_reviews_on_push":true,"require_code_owner_review":true,"require_last_push_approval":true,"required_approving_review_count":2,"required_review_thread_resolution":true}}]`,
87+
},
88+
{
89+
name: "RepositoryRulesetRules with RequiredStatusChecks",
90+
input: RepositoryRulesetRules{
91+
RequiredStatusChecks: &RequiredStatusChecksRuleParameters{
92+
DoNotEnforceOnCreate: Ptr(true),
93+
RequiredStatusChecks: []*RuleStatusCheck{
94+
{
95+
Context: "build",
96+
IntegrationID: Ptr(int64(1)),
97+
},
98+
{
99+
Context: "lint",
100+
IntegrationID: Ptr(int64(2)),
101+
},
102+
},
103+
StrictRequiredStatusChecksPolicy: true,
104+
},
105+
},
106+
expected: `[{"type":"required_status_checks","parameters":{"do_not_enforce_on_create":true,"required_status_checks":[{"context":"build","integration_id":1},{"context":"lint","integration_id":2}],"strict_required_status_checks_policy":true}}]`,
107+
},
108+
{
109+
name: "RepositoryRulesetRules with CommitMessagePattern",
110+
input: RepositoryRulesetRules{
111+
CommitMessagePattern: &PatternRuleParameters{
112+
Name: Ptr("avoid test commits"),
113+
Negate: Ptr(true),
114+
Operator: "starts_with",
115+
Pattern: "[test]",
116+
},
117+
},
118+
expected: `[{"type":"commit_message_pattern","parameters":{"name":"avoid test commits","negate":true,"operator":"starts_with","pattern":"[test]"}}]`,
119+
},
120+
{
121+
name: "RepositoryRulesetRules with CommitAuthorEmailPattern",
122+
input: RepositoryRulesetRules{
123+
CommitAuthorEmailPattern: &PatternRuleParameters{
124+
Operator: "contains",
125+
Pattern: "example.com",
126+
},
127+
},
128+
expected: `[{"type":"commit_author_email_pattern","parameters":{"operator":"contains","pattern":"example.com"}}]`,
129+
},
130+
{
131+
name: "RepositoryRulesetRules with CommitterEmailPattern",
132+
input: RepositoryRulesetRules{
133+
CommitterEmailPattern: &PatternRuleParameters{
134+
Name: Ptr("require org email"),
135+
Operator: "ends_with",
136+
Pattern: "@company.com",
137+
},
138+
},
139+
expected: `[{"type":"committer_email_pattern","parameters":{"name":"require org email","operator":"ends_with","pattern":"@company.com"}}]`,
140+
},
141+
{
142+
name: "RepositoryRulesetRules with BranchNamePattern",
143+
input: RepositoryRulesetRules{
144+
BranchNamePattern: &PatternRuleParameters{
145+
Name: Ptr("enforce naming convention"),
146+
Negate: Ptr(false),
147+
Operator: "regex",
148+
Pattern: "^(main|develop|release/)",
149+
},
150+
},
151+
expected: `[{"type":"branch_name_pattern","parameters":{"name":"enforce naming convention","negate":false,"operator":"regex","pattern":"^(main|develop|release/)"}}]`,
152+
},
153+
{
154+
name: "RepositoryRulesetRules with TagNamePattern",
155+
input: RepositoryRulesetRules{
156+
TagNamePattern: &PatternRuleParameters{
157+
Operator: "contains",
158+
Pattern: "v",
159+
},
160+
},
161+
expected: `[{"type":"tag_name_pattern","parameters":{"operator":"contains","pattern":"v"}}]`,
162+
},
163+
{
164+
name: "RepositoryRulesetRules with CodeScanning",
165+
input: RepositoryRulesetRules{
166+
CodeScanning: &CodeScanningRuleParameters{
167+
CodeScanningTools: []*RuleCodeScanningTool{
168+
{
169+
Tool: "CodeQL",
170+
AlertsThreshold: CodeScanningAlertsThresholdErrors,
171+
SecurityAlertsThreshold: CodeScanningSecurityAlertsThresholdHighOrHigher,
172+
},
173+
},
174+
},
175+
},
176+
expected: `[{"type":"code_scanning","parameters":{"code_scanning_tools":[{"tool":"CodeQL","alerts_threshold":"errors","security_alerts_threshold":"high_or_higher"}]}}]`,
177+
},
178+
{
179+
name: "RepositoryRulesetRules with all rules populated",
180+
input: RepositoryRulesetRules{
181+
Creation: &EmptyRuleParameters{},
182+
Update: &UpdateRuleParameters{
183+
UpdateAllowsFetchAndMerge: true,
184+
},
185+
Deletion: &EmptyRuleParameters{},
186+
RequiredLinearHistory: &EmptyRuleParameters{},
187+
RequiredDeployments: &RequiredDeploymentsRuleParameters{
188+
RequiredDeploymentEnvironments: []string{"production"},
189+
},
190+
RequiredSignatures: &EmptyRuleParameters{},
191+
PullRequest: &PullRequestRuleParameters{
192+
AllowedMergeMethods: []PullRequestMergeMethod{PullRequestMergeMethodRebase},
193+
DismissStaleReviewsOnPush: true,
194+
RequireCodeOwnerReview: true,
195+
RequireLastPushApproval: true,
196+
RequiredApprovingReviewCount: 1,
197+
RequiredReviewThreadResolution: true,
198+
},
199+
RequiredStatusChecks: &RequiredStatusChecksRuleParameters{
200+
DoNotEnforceOnCreate: Ptr(true),
201+
RequiredStatusChecks: []*RuleStatusCheck{
202+
{
203+
Context: "build",
204+
IntegrationID: Ptr(int64(1)),
205+
},
206+
},
207+
StrictRequiredStatusChecksPolicy: true,
208+
},
209+
NonFastForward: &EmptyRuleParameters{},
210+
CommitMessagePattern: &PatternRuleParameters{
211+
Name: Ptr("commit message"),
212+
Operator: "contains",
213+
Pattern: "required",
214+
},
215+
CommitAuthorEmailPattern: &PatternRuleParameters{
216+
Operator: "contains",
217+
Pattern: "example.com",
218+
},
219+
CommitterEmailPattern: &PatternRuleParameters{
220+
Operator: "ends_with",
221+
Pattern: "@example.com",
222+
},
223+
BranchNamePattern: &PatternRuleParameters{
224+
Operator: "regex",
225+
Pattern: "^main$",
226+
},
227+
TagNamePattern: &PatternRuleParameters{
228+
Operator: "contains",
229+
Pattern: "v",
230+
},
231+
CodeScanning: &CodeScanningRuleParameters{
232+
CodeScanningTools: []*RuleCodeScanningTool{
233+
{
234+
Tool: "CodeQL",
235+
AlertsThreshold: CodeScanningAlertsThresholdErrors,
236+
SecurityAlertsThreshold: CodeScanningSecurityAlertsThresholdHighOrHigher,
237+
},
238+
},
239+
},
240+
},
241+
expected: `[{"type":"creation"},{"type":"update","parameters":{"update_allows_fetch_and_merge":true}},{"type":"deletion"},{"type":"required_linear_history"},{"type":"required_deployments","parameters":{"required_deployment_environments":["production"]}},{"type":"required_signatures"},{"type":"pull_request","parameters":{"allowed_merge_methods":["rebase"],"dismiss_stale_reviews_on_push":true,"require_code_owner_review":true,"require_last_push_approval":true,"required_approving_review_count":1,"required_review_thread_resolution":true}},{"type":"required_status_checks","parameters":{"do_not_enforce_on_create":true,"required_status_checks":[{"context":"build","integration_id":1}],"strict_required_status_checks_policy":true}},{"type":"non_fast_forward"},{"type":"commit_message_pattern","parameters":{"name":"commit message","operator":"contains","pattern":"required"}},{"type":"commit_author_email_pattern","parameters":{"operator":"contains","pattern":"example.com"}},{"type":"committer_email_pattern","parameters":{"operator":"ends_with","pattern":"@example.com"}},{"type":"branch_name_pattern","parameters":{"operator":"regex","pattern":"^main$"}},{"type":"tag_name_pattern","parameters":{"operator":"contains","pattern":"v"}},{"type":"code_scanning","parameters":{"code_scanning_tools":[{"tool":"CodeQL","alerts_threshold":"errors","security_alerts_threshold":"high_or_higher"}]}}]`,
242+
},
243+
}
244+
245+
for _, tt := range tests {
246+
t.Run(tt.name, func(t *testing.T) {
247+
// Marshal the input to JSON using a pointer to ensure MarshalJSON is called
248+
data, err := json.Marshal(&tt.input)
249+
if (err != nil) != tt.expectError {
250+
t.Errorf("MarshalJSON error = %v, expectError %v", err, tt.expectError)
251+
return
252+
}
253+
254+
if err != nil {
255+
return
256+
}
257+
258+
// Parse both expected and actual as JSON arrays for normalized comparison
259+
var expectedArray, actualArray interface{}
260+
if err := json.Unmarshal([]byte(tt.expected), &expectedArray); err != nil {
261+
t.Fatalf("Failed to unmarshal expected JSON: %v", err)
262+
}
263+
264+
if err := json.Unmarshal(data, &actualArray); err != nil {
265+
t.Fatalf("Failed to unmarshal actual JSON: %v", err)
266+
}
267+
268+
// Convert back to JSON strings for comparison
269+
expectedJSON, _ := json.Marshal(expectedArray)
270+
actualJSON, _ := json.Marshal(actualArray)
271+
272+
if string(expectedJSON) != string(actualJSON) {
273+
t.Errorf("MarshalJSON() = %s, want %s", string(actualJSON), string(expectedJSON))
274+
}
275+
})
276+
}
277+
}

0 commit comments

Comments
 (0)