feat(01-12): wave-6 task-1 — harness A18-A22 (font reachability + icon-distinct + manifest-i18n + Lora-resolved + welcome-tokens)
UAT harness extended with 5 new page-side assertions following the 01-13 Approach B pattern (page-side assertA* + host-side driveA* wrapper + harness.test.ts orchestrator entry): A18 — Lora WOFF2 reachable from harness page (font self-host MV3 CSP invariant). Walks document.styleSheets for the first @font-face rule referencing Lora, resolves the rebased asset URL (handles Vite's content-hashing), fetches, asserts byteLength >= 40_000 (subset Lora is ~49 KB) + WOFF2 signature 'wOF2'. 4 checks. A19 — icons rasterized from Loom mark (not Bug A placeholders). Fetches icon128.png, parses IHDR bytes 24-25 (bit-depth + color-type), asserts (8, 6) RGBA vs the placeholder (16, 2) RGB. 2 checks. A20 — manifest:name resolves via chrome i18n. Reads chrome.runtime.getManifest().name; asserts it matches EN extName 'Mokosh — Session Capture' OR RU 'Mokosh — Запись сессии' (robust to whatever locale Chrome uses); explicitly checks no __MSG_ placeholder leaks. 2 checks. A21 — --mks-font-display resolves to Lora stack. Creates transient .mks-display-1 probe div, reads getComputedStyle.fontFamily, asserts the stack starts with 'Lora' or '"Lora"' (accommodates both quoted + unquoted forms across Chrome versions); explicitly checks no Newsreader leak (R2 substitution complete). 2 checks. A22 — welcome page tokens.css adoption (CONDITIONAL on Plan 01-10). Skip-gate on missing welcome.html: catches both HTTP 404 AND network-layer fetch failure (Chrome extensions throw TypeError 'Failed to fetch' for non-web_accessible_resources paths). On reachable: extracts <link rel=stylesheet> hrefs, fetches each, asserts >= 3 var(--mks-*) usages OR tokens.css reference. 1 check. Companion changes: - tests/uat/extension-page-harness.html gains `<link rel="stylesheet" href="../../src/shared/tokens.css">` so A18 + A21 have the @font-face rules + .mks-display-1 class + CSS custom properties resolvable via document.styleSheets + getComputedStyle. Vite's crxjs plugin handles the asset path rebasing at build:test time. - tests/uat/lib/harness-page-driver.ts: driveA18..driveA22 wrappers following the established driveA8 pattern (page.evaluate → window. __mokoshHarness.assertXX). No new host-side fs/ffprobe primitives; all A18-A22 work is page-side. - tests/uat/harness.test.ts: orchestrator drivers list extended with A18-A22 between A14 and A23. FORBIDDEN_HOOK_STRINGS UNCHANGED at 12 entries post-Plan-01-14 (A18-A22 use production chrome.* + fetch + getComputedStyle exclusively; no new test-mode symbols). Verification (this commit): - npm run test:uat: 21/21 GREEN (was 16/16 post-01-14) - SKIP_BUILD=1 npm test: 147/147 GREEN - Tier-1 grep gate: 13/13 GREEN (no FORBIDDEN_HOOK_STRINGS growth) - npx tsc --noEmit: clean - npm run build + npm run build:test: both succeed The chain of A1..A14 + A18..A22 + A23 runs in ~95 seconds end-to-end under Puppeteer headless mode against the bundled Chrome at ~/.cache/puppeteer/chrome/linux-148.0.7778.167. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -993,6 +993,105 @@ export async function driveA14(page: Page): Promise<AssertionRecord> {
|
||||
}) as AssertionRecord;
|
||||
}
|
||||
|
||||
/* ─── Plan 01-12 Wave 6 — driveA18..A22 (design integration assertions) ─── */
|
||||
|
||||
/**
|
||||
* Drive A18 (Lora WOFF2 reachability + size floor). Standard
|
||||
* page.evaluate wrapper — page side walks document.styleSheets for the
|
||||
* first @font-face rule referencing a Lora WOFF2, resolves the rebased
|
||||
* asset URL, fetches it, and verifies byteLength + 'wOF2' signature.
|
||||
*
|
||||
* The Vite asset pipeline rewrites the @font-face src url() to a
|
||||
* content-hashed path under dist-test/assets/. Walking styleSheets
|
||||
* runtime-side keeps the driver host-agnostic to the hash.
|
||||
*
|
||||
* @param page - The harness page from `launchHarnessBrowser`.
|
||||
* @returns Structured AssertionRecord with up to 4 checks (rule found,
|
||||
* fetch status, byteLength floor, WOFF2 signature).
|
||||
*/
|
||||
export async function driveA18(page: Page): Promise<AssertionRecord> {
|
||||
return await page.evaluate(async () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- evaluate runs in browser context where Window types are loose.
|
||||
const harness = (window as any).__mokoshHarness;
|
||||
const r: AssertionRecord = await harness.assertA18();
|
||||
return r;
|
||||
}) as AssertionRecord;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drive A19 (icons are NOT Bug A placeholders). Standard page.evaluate
|
||||
* wrapper — page side fetches icon128.png, reads IHDR bytes 24-25
|
||||
* (bit-depth + color-type), and asserts (8, 6) RGBA vs the placeholder
|
||||
* (16, 2) RGB.
|
||||
*
|
||||
* @param page - The harness page from `launchHarnessBrowser`.
|
||||
* @returns Structured AssertionRecord with 2 checks (bit-depth + color-type).
|
||||
*/
|
||||
export async function driveA19(page: Page): Promise<AssertionRecord> {
|
||||
return await page.evaluate(async () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- evaluate runs in browser context where Window types are loose.
|
||||
const harness = (window as any).__mokoshHarness;
|
||||
const r: AssertionRecord = await harness.assertA19();
|
||||
return r;
|
||||
}) as AssertionRecord;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drive A20 (manifest:name resolves via chrome i18n). Standard
|
||||
* page.evaluate wrapper — page side reads chrome.runtime.getManifest()
|
||||
* and asserts manifest.name resolved to the EN or RU extName value
|
||||
* (no __MSG_ placeholder leak).
|
||||
*
|
||||
* @param page - The harness page from `launchHarnessBrowser`.
|
||||
* @returns Structured AssertionRecord with 2 checks (resolved value, no __MSG_).
|
||||
*/
|
||||
export async function driveA20(page: Page): Promise<AssertionRecord> {
|
||||
return await page.evaluate(async () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- evaluate runs in browser context where Window types are loose.
|
||||
const harness = (window as any).__mokoshHarness;
|
||||
const r: AssertionRecord = await harness.assertA20();
|
||||
return r;
|
||||
}) as AssertionRecord;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drive A21 (--mks-font-display resolves to Lora). Standard
|
||||
* page.evaluate wrapper — page side creates a transient .mks-display-1
|
||||
* probe div, reads getComputedStyle.fontFamily, and asserts the stack
|
||||
* starts with 'Lora' (no Newsreader leak).
|
||||
*
|
||||
* @param page - The harness page from `launchHarnessBrowser`.
|
||||
* @returns Structured AssertionRecord with 2 checks (Lora prefix, no Newsreader).
|
||||
*/
|
||||
export async function driveA21(page: Page): Promise<AssertionRecord> {
|
||||
return await page.evaluate(async () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- evaluate runs in browser context where Window types are loose.
|
||||
const harness = (window as any).__mokoshHarness;
|
||||
const r: AssertionRecord = await harness.assertA21();
|
||||
return r;
|
||||
}) as AssertionRecord;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drive A22 (welcome page tokens.css adoption — CONDITIONAL on Plan
|
||||
* 01-10 having landed). Standard page.evaluate wrapper — page side
|
||||
* fetches welcome.html; on HTTP 404 PASSES with a 'Plan 01-10 not
|
||||
* landed; skipped' diagnostic. On HTTP 200, extracts stylesheet
|
||||
* <link>s + asserts substantive var(--mks-*) usage OR a tokens.css
|
||||
* reference in the linked CSS files.
|
||||
*
|
||||
* @param page - The harness page from `launchHarnessBrowser`.
|
||||
* @returns Structured AssertionRecord with 1 check (skip or token usage).
|
||||
*/
|
||||
export async function driveA22(page: Page): Promise<AssertionRecord> {
|
||||
return await page.evaluate(async () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- evaluate runs in browser context where Window types are loose.
|
||||
const harness = (window as any).__mokoshHarness;
|
||||
const r: AssertionRecord = await harness.assertA22();
|
||||
return r;
|
||||
}) as AssertionRecord;
|
||||
}
|
||||
|
||||
/* ─── Plan 01-14 — driveA23 (monitorTypeSurfaces picker-narrowing) ─── */
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user