// tests/build/tokens-adopted.test.ts — Plan 01-12 Wave 0 RED unit test. // // Asserts that the canonical token system (src/shared/tokens.css) exists // and is adopted by src/popup/style.css with ZERO hex literals remaining. // // Polarity at Wave 0 land: // (a) GREEN if src/shared/tokens.css already exists (will be RED until // Wave 1 Task 2 lands the canonical copy). // (b) RED until Wave 4 Task 1 migrates src/popup/style.css to @import // tokens.css and replaces hex literals with var(--mks-*) references. // (c) RED until Wave 4 Task 1 removes every #[0-9a-fA-F]{3,8} match // from src/popup/style.css (loom-palette adoption via tokens). // // References: // - Plan 01-12 §interfaces (.mks-word definition, R2 Lora substitution) // - RESEARCH §1 + §9 (per-surface mini-tokens anti-pattern; collapse // into canonical src/shared/tokens.css) import { describe, expect, it } from 'vitest'; import { existsSync, readFileSync } from 'node:fs'; import { resolve as resolvePath } from 'node:path'; const TOKENS_CSS_PATH = resolvePath(process.cwd(), 'src/shared/tokens.css'); const POPUP_STYLE_PATH = resolvePath(process.cwd(), 'src/popup/style.css'); const WELCOME_STYLE_PATH = resolvePath(process.cwd(), 'src/welcome/welcome.css'); const HEX_LITERAL_REGEX = /#[0-9a-fA-F]{3,8}\b/g; const TOKENS_IMPORT_REGEX = /@import\s+["']\.\.\/shared\/tokens\.css["']/; describe('Plan 01-12: tokens.css adoption (canonical token system)', () => { it('(a) src/shared/tokens.css exists + parses as readable CSS', () => { expect( existsSync(TOKENS_CSS_PATH), `Expected src/shared/tokens.css at ${TOKENS_CSS_PATH} (RED until Wave 1 Task 2)`, ).toBe(true); const css = readFileSync(TOKENS_CSS_PATH, 'utf8'); expect(css.length, 'tokens.css must be non-empty').toBeGreaterThan(100); expect(css, 'tokens.css must declare :root with --mks-* tokens').toMatch(/:root\s*\{/); expect(css, 'tokens.css must include --mks-font-display token').toMatch(/--mks-font-display\s*:/); }); it('(b) src/popup/style.css imports ../shared/tokens.css', () => { expect(existsSync(POPUP_STYLE_PATH), 'src/popup/style.css must exist').toBe(true); const css = readFileSync(POPUP_STYLE_PATH, 'utf8'); expect( TOKENS_IMPORT_REGEX.test(css), `Expected @import '../shared/tokens.css' in src/popup/style.css (RED until Wave 4 Task 1)`, ).toBe(true); }); it('(c) src/popup/style.css has ZERO hex color literals (loom palette via var(--mks-*))', () => { const css = readFileSync(POPUP_STYLE_PATH, 'utf8'); const matches = css.match(HEX_LITERAL_REGEX) ?? []; expect( matches.length, matches.length === 0 ? 'unreachable' : `Expected 0 hex literals in src/popup/style.css; got ${matches.length}: ${matches.join(', ')}\n` + `Replace each with var(--mks-*) per D-04 loom palette (Wave 4 Task 1).`, ).toBe(0); }); it('(d) src/welcome/welcome.css — if present, has ZERO hex literals (Plan 01-10 conditional)', () => { // Conditional: only enforce if Plan 01-10 has landed src/welcome/welcome.css. if (!existsSync(WELCOME_STYLE_PATH)) { // SKIP without failing; documented in plan as conditional artifact. return; } const css = readFileSync(WELCOME_STYLE_PATH, 'utf8'); const matches = css.match(HEX_LITERAL_REGEX) ?? []; expect( matches.length, matches.length === 0 ? 'unreachable' : `Expected 0 hex literals in src/welcome/welcome.css; got ${matches.length}: ${matches.join(', ')}`, ).toBe(0); }); });