fix: restore scrolling and validator enforcement
ForgeFlow quality gate / quality (push) Canceled after 0s

This commit is contained in:
NuklearRabbit
2026-08-01 12:44:31 +02:00
parent f8c505e525
commit 258f0b1324
9 changed files with 127 additions and 25 deletions
+33
View File
@@ -60,6 +60,24 @@ async function assertSurface(page) {
expect(audit.headings.length).toBeGreaterThan(0);
}
async function assertScrollableWhenOverflowing(page, selector) {
const target = page.locator(selector);
await expect(target).toBeVisible();
await expect(target).toHaveCSS("overflow-y", /auto|scroll/);
let metrics;
await expect.poll(async () => {
metrics = await target.evaluate((element) => ({
connected: element.isConnected,
clientHeight: element.clientHeight,
scrollHeight: element.scrollHeight,
}));
return metrics.connected && metrics.clientHeight > 0;
}).toBe(true);
if (metrics.scrollHeight > metrics.clientHeight + 1) {
await target.evaluate((element) => { element.scrollTop = element.scrollHeight; });
await expect.poll(() => target.evaluate((element) => element.scrollTop)).toBeGreaterThan(0);
}
}
test("shell, overview, repositories and settings remain responsive and accessible", async ({ page }, testInfo) => {
await assertSurface(page);
for (const view of ["overview", "deployments", "settings"]) {
@@ -86,13 +104,28 @@ test("repository changes, Git tools and Git Validator complete their primary flo
}
await page.locator('[data-action="repo-tab"][data-tab="validator"]').click();
await expect(page.locator(".validator-score")).toBeVisible();
await assertScrollableWhenOverflowing(page, ".validator-page");
await expect(page.locator("#validator-policy")).toBeVisible();
await page.locator("#validator-policy").selectOption("production");
await expect(page.locator(".validator-hero")).toContainText(/Production policy/i);
await expect(page.locator(".validator-hero")).toContainText(/review required/i);
await page.keyboard.press("Tab");
await expect(page.locator(":focus")).toBeVisible();
});
test("every long application surface retains a working vertical scroll owner", async ({ page }) => {
for (const view of ["overview", "deployments", "diagnostics", "settings"]) {
await page.locator(`.nav-button[data-view="${view}"]`).click();
await assertScrollableWhenOverflowing(page, ".main-canvas");
}
await page.locator('[data-action="select-repo"]').first().click();
for (const tab of ["history", "deployments", "gittools", "validator", "settings"]) {
await page.locator(`[data-action="repo-tab"][data-tab="${tab}"]`).click();
const scrollRoot = page.locator(".repo-content > .tab-page, .repo-content > .validator-page");
if (await scrollRoot.count())
await assertScrollableWhenOverflowing(page, ".repo-content > .tab-page, .repo-content > .validator-page");
}
});
test("deployment inventory supports dense workloads without ambiguous blank cards", async ({ page }) => {
await page.locator('.nav-button[data-action="navigate"][data-view="deployments"]').click();
await expect(page.locator(".deploy-card, .server-inventory-panel .tool-row").first()).toBeVisible();
+14
View File
@@ -23,6 +23,20 @@ test("Git Validator policies enforce score, blockers and enabled checks", () =>
assert.equal(governed.checks[0].blocking, true);
});
test("built-in policies enforce their declared blocking severities", () => {
const finding = [{ id: "readme", status: "warning", category: "Documentation", weight: 5 }];
assert.equal(applyPolicy(finding, { id: "minimal" }, []).checks[0].blocking, false);
for (const id of ["standard", "strict", "production"])
assert.equal(applyPolicy(finding, { id }, []).checks[0].blocking, true, `${id} must block active warnings`);
});
test("documented suppressions remove active blockers", () => {
const now = new Date("2026-07-01T00:00:00.000Z");
const suppression = validateSuppression({ checkId: "readme", reason: "Tracked remediation work", author: "Jens", expiresAt: "2026-07-08T00:00:00.000Z", evidence: "ticket:FF-7" }, normalizePolicy({ id: "standard" }), now);
const check = applyPolicy([{ id: "readme", status: "warning", category: "Documentation", weight: 5 }], { id: "standard" }, [suppression], now).checks[0];
assert.equal(check.suppressed, true);
assert.equal(check.blocking, false);
});
test("suppressions require accountable evidence and reactivate after expiry", () => {
const now = new Date("2026-07-01T00:00:00.000Z");
const suppression = validateSuppression({ checkId: "signed-tags", reason: "Tracked under release hardening", author: "Jens", ticket: "FF-42", expiresAt: "2026-07-08T00:00:00.000Z", scope: "repository", evidence: "sha:abc" }, normalizePolicy({ id: "standard" }), now);
+18
View File
@@ -100,6 +100,24 @@ test("Git Validator recognizes remote aliases and secret-shaped tracked paths",
assert.equal(isSensitiveTrackedPath(".env.example"), false);
});
test("Git Validator rejects stale or forged repair requests", async () => {
const validator = new GitValidatorService({ git: new GitService() });
validator.scan = async () => ({
checks: [{ id: "local-safety", fixAction: "configure-local-safety", status: "warning" }],
});
assert.equal(
(await validator.resolveRepairCheck({}, { id: "local-safety", fixAction: "configure-local-safety" })).id,
"local-safety",
);
await assert.rejects(
validator.resolveRepairCheck({}, { id: "local-safety", fixAction: "align-origin" }),
/stale/i,
);
await assert.rejects(
validator.resolveRepairCheck({}, { id: "resolved-check", fixAction: "align-origin" }),
/resolved|no longer repairable/i,
);
});
test("Git Validator reports reproducibility, CI and editor hygiene and creates reviewable defaults", async (t) => {
const root = await mkdtemp(path.join(os.tmpdir(), "forgeflow-hygiene-"));
t.after(() => rm(root, { recursive: true, force: true }));