From 52ec48ffe4517e2efca2b60abb40bbc8528771e6 Mon Sep 17 00:00:00 2001 From: simoleo89 Date: Tue, 25 Aug 2026 20:17:45 +0200 Subject: [PATCH] test: harden housekeeping shell contracts --- .../page/housekeeping-page-state.test.tsx | 3 +- .../page/housekeeping-page-state.tsx | 2 +- .../shell/housekeeping-shell.test.tsx | 204 +++++++++++++----- 3 files changed, 154 insertions(+), 55 deletions(-) diff --git a/src/features/housekeeping/foundation/page/housekeeping-page-state.test.tsx b/src/features/housekeeping/foundation/page/housekeeping-page-state.test.tsx index b835b23172..cbb7cd4857 100644 --- a/src/features/housekeeping/foundation/page/housekeeping-page-state.test.tsx +++ b/src/features/housekeeping/foundation/page/housekeeping-page-state.test.tsx @@ -40,7 +40,8 @@ describe("HousekeepingPageState", () => { ); expect(loading).toContain('aria-live="polite"'); - expect(partial).toContain('data-state-tone="warning"'); + expect(partial).toContain("--admin-warning-border"); + expect(partial).toContain("--admin-warning-subtle"); expect(partial).toContain(">Partial title<"); }); diff --git a/src/features/housekeeping/foundation/page/housekeeping-page-state.tsx b/src/features/housekeeping/foundation/page/housekeeping-page-state.tsx index dc2e2a5666..c980e45e3e 100644 --- a/src/features/housekeeping/foundation/page/housekeeping-page-state.tsx +++ b/src/features/housekeeping/foundation/page/housekeeping-page-state.tsx @@ -24,7 +24,7 @@ export function HousekeepingPageState({ isError ? "border-[var(--admin-error)] bg-[var(--admin-surface)]" : isPartial - ? "border-[var(--admin-warning)] bg-[var(--admin-surface)]" + ? "border-[var(--admin-warning-border)] bg-[var(--admin-warning-subtle)]" : "border-[var(--admin-border)] bg-[var(--admin-surface)]" }`} > diff --git a/src/features/housekeeping/foundation/shell/housekeeping-shell.test.tsx b/src/features/housekeeping/foundation/shell/housekeeping-shell.test.tsx index 394a4043db..4277f53165 100644 --- a/src/features/housekeeping/foundation/shell/housekeeping-shell.test.tsx +++ b/src/features/housekeeping/foundation/shell/housekeeping-shell.test.tsx @@ -67,14 +67,73 @@ const domains: readonly HousekeepingNavigationDomain[] = [ }, ]; +const taskFiles = [ + "src/features/housekeeping/foundation/shell/housekeeping-shell.tsx", + "src/features/housekeeping/foundation/shell/domain-rail.tsx", + "src/features/housekeeping/foundation/shell/context-nav.tsx", + "src/features/housekeeping/foundation/shell/command-trigger.tsx", + "src/features/housekeeping/foundation/shell/operator-summary.tsx", + "src/features/housekeeping/foundation/page/housekeeping-page-shell.tsx", + "src/features/housekeeping/foundation/page/housekeeping-page-state.tsx", + "src/features/housekeeping/foundation/shell/housekeeping-shell.test.tsx", + "src/features/housekeeping/foundation/page/housekeeping-page-state.test.tsx", +] as const; + +const componentTaskFiles = taskFiles.slice(0, 7); + +const structuralBoundaryRules = [ + { label: "client directive", pattern: new RegExp("use " + "client") }, + { + label: "palette color", + pattern: + /(?:bg|text|border|from|to)-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-\d{2,3}/, + }, + { label: "hex color", pattern: new RegExp("#" + "[0-9a-fA-F]{3,8}") }, + { + label: "rgb or hsl color", + pattern: new RegExp("(?:r" + "gb|h" + "sl)\\("), + }, +]; + +const componentBoundaryRules = [ + { + label: "React hook", + pattern: + /\buse(?:State|Effect|Memo|Callback|Ref|Reducer|LayoutEffect|Transition)(?:\s*\(|\s*(?:,|}))/, + }, + { label: "click handler", pattern: /\bonClick\s*=/ }, + { label: "keyboard handler", pattern: /\bonKey(?:Down|Up|Press)\s*=/ }, + { label: "event listener", pattern: new RegExp("addEvent" + "Listener") }, + { + label: "database or action import", + pattern: new RegExp( + "(?:from\\s*|import\\s*\\()\\s*['\"][^'\"]*(?:@/lib/" + + "db|drizzle(?:-orm)?|/" + + "actions?)[^'\"]*['\"]", + ), + }, + { label: "command package", pattern: new RegExp("cmd" + "k", "i") }, + { label: "localization import", pattern: new RegExp("next" + "-intl") }, + { + label: "search or mutation runtime", + pattern: /\b(?:fetch|useQuery|useMutation)\s*\(/, + }, + { + label: "persistence storage", + pattern: + /\b(?:localStorage|sessionStorage|indexedDB)\b|\.(?:setItem|getItem|removeItem)\s*\(/, + }, +]; + function renderShell( activeDomainId: HousekeepingNavigationDomain["id"] = "operations", + availableDomains: readonly HousekeepingNavigationDomain[] = domains, ): string { return renderToStaticMarkup(

Deck body

@@ -82,10 +141,30 @@ function renderShell( ); } +function anchors(html: string): readonly string[] { + return html.match(/]*>/g) ?? []; +} + +function anchorForHref(html: string, href: string): string { + const anchor = anchors(html).find((candidate) => + candidate.includes(`href="${href}"`), + ); + if (!anchor) throw new Error(`missing anchor for ${href}`); + return anchor; +} + +function boundaryViolations( + source: string, + rules: readonly { label: string; pattern: RegExp }[], +): readonly string[] { + return rules + .filter((rule) => rule.pattern.test(source)) + .map((rule) => rule.label); +} + describe("HousekeepingShell", () => { it("renders the accessible command deck landmarks and supplied shell content", () => { const html = renderShell(); - expect(html).toContain('href="#housekeeping-content"'); expect(html).toContain(">Skip to housekeeping content<"); expect(html).toContain(" { expect(html).toContain('