tenseleyflow/shithub / fb87e1d

Browse files

repo tests: lock multi-reviewer code, prevent-* gate fire, user-tier Pro copy; fix pre-existing seed fixture

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
fb87e1d0e33832855d9612e277f092dedffdde3f
Parents
23e382a
Tree
e89cd1a

2 changed files

StatusFile+-
M internal/web/handlers/repo/settings_branches_pro07_test.go 65 6
M internal/web/handlers/repo/settings_branches_test.go 8 4
internal/web/handlers/repo/settings_branches_pro07_test.gomodified
@@ -47,7 +47,32 @@ func TestSettingsBranches_UserKindReportOnlyRequiredReviewersAllowsSave(t *testi
47
 	assertBranchProtectionRuleCount(t, f, f.privateRepo.ID, 1)
47
 	assertBranchProtectionRuleCount(t, f, f.privateRepo.ID, 1)
48
 }
48
 }
49
 
49
 
50
-func TestSettingsBranches_UserKindEnforceFlipRequiredReviewersBlocks(t *testing.T) {
50
+func TestSettingsBranches_UserKindEnforceFlipRequiredReviewersBlocksSingle(t *testing.T) {
51
+	t.Parallel()
52
+	f := newRepoFixtureWithEnforce(t, config.EnforceConfig{
53
+		UserRequiredReviewers: true,
54
+	})
55
+	mux := f.branchesSettingsMux(f.owner.ID, f.owner.Username)
56
+
57
+	resp := httptest.NewRecorder()
58
+	req := newFormRequest("POST", "/alice/private-repo/settings/branches", url.Values{
59
+		"pattern":               {"trunk"},
60
+		"required_review_count": {"1"},
61
+	})
62
+	mux.ServeHTTP(resp, req)
63
+	if resp.Code != 303 {
64
+		t.Fatalf("status=%d body=%s", resp.Code, resp.Body.String())
65
+	}
66
+	// PRO08 C3 + C4: count=1 + user kind → single-reviewer Pro copy.
67
+	if got := resp.Header().Get("Location"); got != "/alice/private-repo/settings/branches?notice=required-reviewers-upgrade-pro" {
68
+		t.Fatalf("expected single-reviewer Pro notice, got %q", got)
69
+	}
70
+	assertBranchProtectionRuleCount(t, f, f.privateRepo.ID, 0)
71
+}
72
+
73
+// TestSettingsBranches_UserKindEnforceFlipMultiReviewerBlocks locks
74
+// PRO08 C3's distinct copy variant when count > 1.
75
+func TestSettingsBranches_UserKindEnforceFlipMultiReviewerBlocks(t *testing.T) {
51
 	t.Parallel()
76
 	t.Parallel()
52
 	f := newRepoFixtureWithEnforce(t, config.EnforceConfig{
77
 	f := newRepoFixtureWithEnforce(t, config.EnforceConfig{
53
 		UserRequiredReviewers: true,
78
 		UserRequiredReviewers: true,
@@ -63,8 +88,8 @@ func TestSettingsBranches_UserKindEnforceFlipRequiredReviewersBlocks(t *testing.
63
 	if resp.Code != 303 {
88
 	if resp.Code != 303 {
64
 		t.Fatalf("status=%d body=%s", resp.Code, resp.Body.String())
89
 		t.Fatalf("status=%d body=%s", resp.Code, resp.Body.String())
65
 	}
90
 	}
66
-	if got := resp.Header().Get("Location"); got != "/alice/private-repo/settings/branches?notice=required-reviewers-upgrade" {
91
+	if got := resp.Header().Get("Location"); got != "/alice/private-repo/settings/branches?notice=required-reviewers-multi-upgrade-pro" {
67
-		t.Fatalf("expected upgrade notice, got %q", got)
92
+		t.Fatalf("expected multi-reviewer Pro notice, got %q", got)
68
 	}
93
 	}
69
 	assertBranchProtectionRuleCount(t, f, f.privateRepo.ID, 0)
94
 	assertBranchProtectionRuleCount(t, f, f.privateRepo.ID, 0)
70
 }
95
 }
@@ -85,12 +110,44 @@ func TestSettingsBranches_UserKindEnforceFlipAdvancedChecksBlocks(t *testing.T)
85
 	if resp.Code != 303 {
110
 	if resp.Code != 303 {
86
 		t.Fatalf("status=%d body=%s", resp.Code, resp.Body.String())
111
 		t.Fatalf("status=%d body=%s", resp.Code, resp.Body.String())
87
 	}
112
 	}
88
-	if got := resp.Header().Get("Location"); got != "/alice/private-repo/settings/branches?notice=branch-protection-upgrade" {
113
+	// PRO08 C4: user-kind deny carries the Pro-flavored upgrade copy.
89
-		t.Fatalf("expected upgrade notice, got %q", got)
114
+	if got := resp.Header().Get("Location"); got != "/alice/private-repo/settings/branches?notice=branch-protection-upgrade-pro" {
115
+		t.Fatalf("expected Pro upgrade notice, got %q", got)
90
 	}
116
 	}
91
 	assertBranchProtectionRuleCount(t, f, f.privateRepo.ID, 0)
117
 	assertBranchProtectionRuleCount(t, f, f.privateRepo.ID, 0)
92
 }
118
 }
93
 
119
 
120
+// TestSettingsBranches_UserKindEnforceFlipPreventForcePushBlocks locks
121
+// PRO08 C2: the rewired gate fires on prevent_force_push (NOT just
122
+// required_status_checks like PRO07 mis-wired it). prevent_deletion
123
+// and require_signed_commits behave identically; covered by table.
124
+func TestSettingsBranches_UserKindEnforceFlipPreventForcePushBlocks(t *testing.T) {
125
+	t.Parallel()
126
+	for _, flag := range []string{"prevent_force_push", "prevent_deletion", "require_signed_commits"} {
127
+		flag := flag
128
+		t.Run(flag, func(t *testing.T) {
129
+			t.Parallel()
130
+			f := newRepoFixtureWithEnforce(t, config.EnforceConfig{
131
+				UserAdvancedBranchProtection: true,
132
+			})
133
+			mux := f.branchesSettingsMux(f.owner.ID, f.owner.Username)
134
+			resp := httptest.NewRecorder()
135
+			req := newFormRequest("POST", "/alice/private-repo/settings/branches", url.Values{
136
+				"pattern": {"trunk"},
137
+				flag:      {"on"},
138
+			})
139
+			mux.ServeHTTP(resp, req)
140
+			if resp.Code != 303 {
141
+				t.Fatalf("status=%d body=%s", resp.Code, resp.Body.String())
142
+			}
143
+			if got := resp.Header().Get("Location"); got != "/alice/private-repo/settings/branches?notice=branch-protection-upgrade-pro" {
144
+				t.Fatalf("flag=%s redirect=%q, want Pro upgrade", flag, got)
145
+			}
146
+			assertBranchProtectionRuleCount(t, f, f.privateRepo.ID, 0)
147
+		})
148
+	}
149
+}
150
+
94
 // TestSettingsBranches_UserKindEnforceFlipDoesNotAffectPublicRepos
151
 // TestSettingsBranches_UserKindEnforceFlipDoesNotAffectPublicRepos
95
 // locks the visibility short-circuit: enforce flags fire only on
152
 // locks the visibility short-circuit: enforce flags fire only on
96
 // private personal repos. Public personal repos stay ungated.
153
 // private personal repos. Public personal repos stay ungated.
@@ -166,7 +223,9 @@ func TestSettingsBranches_OrgKindUnchangedByPRO07Flags(t *testing.T) {
166
 		if resp.Code != 303 {
223
 		if resp.Code != 303 {
167
 			t.Fatalf("enforce=%+v status=%d body=%s", enforce, resp.Code, resp.Body.String())
224
 			t.Fatalf("enforce=%+v status=%d body=%s", enforce, resp.Code, resp.Body.String())
168
 		}
225
 		}
169
-		if got := resp.Header().Get("Location"); got != "/acme/private-org-repo/settings/branches?notice=required-reviewers-upgrade" {
226
+		// count=2 ⇒ multi; org-kind keeps the existing copy (no -pro
227
+		// suffix); PRO08 C3 added the multi- variant.
228
+		if got := resp.Header().Get("Location"); got != "/acme/private-org-repo/settings/branches?notice=required-reviewers-multi-upgrade" {
170
 			t.Errorf("enforce=%+v: org redirect=%q, want upgrade notice", enforce, got)
229
 			t.Errorf("enforce=%+v: org redirect=%q, want upgrade notice", enforce, got)
171
 		}
230
 		}
172
 		assertBranchProtectionRuleCount(t, f, repo.ID, 0)
231
 		assertBranchProtectionRuleCount(t, f, repo.ID, 0)
internal/web/handlers/repo/settings_branches_test.gomodified
@@ -36,7 +36,10 @@ func TestSettingsBranchesBlocksRequiredReviewersWithoutEntitlement(t *testing.T)
36
 	if resp.Code != http.StatusSeeOther {
36
 	if resp.Code != http.StatusSeeOther {
37
 		t.Fatalf("POST status=%d body=%s", resp.Code, resp.Body.String())
37
 		t.Fatalf("POST status=%d body=%s", resp.Code, resp.Body.String())
38
 	}
38
 	}
39
-	if got := resp.Header().Get("Location"); got != "/acme/private-org-repo/settings/branches?notice=required-reviewers-upgrade" {
39
+	// PRO08 C3: count=2 is multi-reviewer, so the deny carries the
40
+	// multi-reviewer-specific code. The single-reviewer code is only
41
+	// used when count==1.
42
+	if got := resp.Header().Get("Location"); got != "/acme/private-org-repo/settings/branches?notice=required-reviewers-multi-upgrade" {
40
 		t.Fatalf("redirect location=%q", got)
43
 		t.Fatalf("redirect location=%q", got)
41
 	}
44
 	}
42
 	assertBranchProtectionRuleCount(t, f, repo.ID, 0)
45
 	assertBranchProtectionRuleCount(t, f, repo.ID, 0)
@@ -138,9 +141,10 @@ func TestSettingsBranchesAllowsDowngradedOrgToRemoveAdvancedSettings(t *testing.
138
 	orgID := f.insertOwnedOrg(t, "acme")
141
 	orgID := f.insertOwnedOrg(t, "acme")
139
 	repo := f.insertOrgRepo(t, orgID, "private-org-repo", reposdb.RepoVisibilityPrivate)
142
 	repo := f.insertOrgRepo(t, orgID, "private-org-repo", reposdb.RepoVisibilityPrivate)
140
 	ruleID, err := f.handlers.rq.UpsertBranchProtectionRule(context.Background(), f.pool, reposdb.UpsertBranchProtectionRuleParams{
143
 	ruleID, err := f.handlers.rq.UpsertBranchProtectionRule(context.Background(), f.pool, reposdb.UpsertBranchProtectionRuleParams{
141
-		RepoID:          repo.ID,
144
+		RepoID:               repo.ID,
142
-		Pattern:         "trunk",
145
+		Pattern:              "trunk",
143
-		PreventDeletion: true,
146
+		PreventDeletion:      true,
147
+		AllowedPusherUserIds: []int64{},
144
 	})
148
 	})
145
 	if err != nil {
149
 	if err != nil {
146
 		t.Fatalf("seed branch rule: %v", err)
150
 		t.Fatalf("seed branch rule: %v", err)