Files
Jyotisha/frontend/tests/viewport-breakpoint-contract.test.ts
T
jesse-ux 6c748d86b0
Independent Staging Quality Gate / validate (push) Failing after 8m53s
Independent Staging Quality Gate / publish (push) Skipped
fix(ui): 44px coarse hits and align CSS breakpoints
Touch-screen message actions get a 44x44 hit once gap and bottom margin open to 20px; fine-pointer geometry stays 27x34. Tablet CSS cuts at 1023 to match sidebarViewportForWidth. Report centre/reader join the 767 mobile cut; TOC keeps 860. Occupies BUG-695/696/697.
2026-09-15 12:46:59 +08:00

43 lines
1.8 KiB
TypeScript

import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import test from "node:test";
const css = readFileSync(new URL("../src/app/globals.css", import.meta.url), "utf8");
const sidebar = readFileSync(new URL("../src/lib/sidebar-state.ts", import.meta.url), "utf8");
/** Widths that may appear in @media (min-width / max-width). Keep in sync with the comment at the top of globals.css. */
const ALLOWED = new Set([480, 640, 641, 767, 768, 860, 1023, 1024]);
function mediaWidthBreakpoints(source: string): number[] {
const widths = new Set<number>();
for (const block of source.matchAll(/@media[^{]+/g)) {
for (const hit of block[0].matchAll(/\((?:min|max)-width:\s*(\d+)px\)/g)) {
widths.add(Number(hit[1]));
}
}
return [...widths].sort((a, b) => a - b);
}
test("CSS width breakpoints stay on the published allowlist", () => {
assert.deepEqual(mediaWidthBreakpoints(css), [...ALLOWED].sort((a, b) => a - b));
});
test("tablet CSS cuts at 1023 so it matches sidebarViewportForWidth", () => {
assert.doesNotMatch(css, /@media[^{]*max-width:\s*900px/);
assert.match(css, /@media \(max-width: 1023px\)/);
assert.match(sidebar, /if \(width < 768\) return "mobile"/);
assert.match(sidebar, /if \(width < 1024\) return "tablet"/);
});
test("report centre and reader share the global mobile cut", () => {
assert.match(css, /@media \(max-width: 767px\) \{[\s\S]*\.report-center-shell/);
assert.match(css, /@media \(max-width: 767px\) \{[\s\S]*\.personal-report-reader-body/);
assert.doesNotMatch(css, /@media \(max-width: 720px\)/);
assert.doesNotMatch(css, /@media \(max-width: 760px\)/);
});
test("report TOC keeps a content-width exception at 860px", () => {
assert.match(css, /Report TOC is the third column/);
assert.match(css, /@media \(max-width: 860px\) \{[\s\S]*\.personal-report-md-layout/);
});