18 lines
1.2 KiB
JavaScript
18 lines
1.2 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import fs from "node:fs";
|
|
|
|
const page = fs.readFileSync("src/features/portal/PortalPage.tsx", "utf8");
|
|
const styles = fs.readFileSync("src/styles/portal.css", "utf8");
|
|
|
|
assert.ok(page.includes("DocumentationHelpLink"), "Portal exposes configured-system help");
|
|
assert.ok(page.includes("ActionBlockerHint"), "Unavailable launches expose the shared structured blocker");
|
|
assert.ok(page.includes("disabledReason={entry.state !== \"available\" ? blocker.summary : undefined}"), "The launch action remains keyboard-explainable");
|
|
assert.ok(page.includes("PageScrollViewport"), "Portal owns bounded directory scrolling");
|
|
assert.ok(page.includes('aria-live="polite"'), "Changing result counts are announced");
|
|
assert.ok(page.includes("useGuardedNavigate"), "Internal launch handoffs respect unsaved-work navigation");
|
|
assert.ok(!page.includes("window.alert("), "Portal must not use browser alerts");
|
|
assert.ok(!/<(div|span|li|tr)\b[^>]*\bonClick\s*=/.test(page), "Portal uses semantic interactive elements");
|
|
assert.ok(styles.includes("@media (max-width: 720px)"), "Portal retains a narrow-viewport toolbar layout");
|
|
|
|
console.log("Portal interface pattern contract passed.");
|