Files
mokosh/tests/build/tokens-adopted.test.ts
Mark 34a9ce10d4 test(01-12): wave-0 — scaffold RED unit tests (tokens / fonts / icons / no-remote-fonts / manifest-i18n / locale-parity)
Wave 0 of the design-integration plan. Six new test files at tests/build/
and tests/i18n/ pin the contracts that later waves will GREEN:

- tokens-adopted.test.ts (4 cases): src/shared/tokens.css exists +
  parses; src/popup/style.css @imports it; popup/style.css has zero
  hex literals; welcome.css conditional check.
- fonts-present.test.ts: 7 required WOFF2 faces (Lora normal + Plex Sans
  ×4 + Plex Mono ×2) + LICENSE-Lora + LICENSE-IBM-Plex + README +
  optional Lora-Italic (A5 verify-at-execute).
- icons-present.test.ts (15 cases across 3 sizes): existence, size FLOOR
  per assets-spec.md, PNG signature, dimensions, color-type byte === 6
  (RGBA — RED until Wave 2 rsvg-convert overwrites the 16-bit-RGB
  placeholders).
- no-remote-fonts.test.ts: production dist/ contains zero
  fonts.googleapis.com / https://fonts / googleapis substrings (MV3 CSP
  self-host invariant T-01-12-01).
- manifest-i18n.test.ts (10 cases): manifest:name === '__MSG_extName__',
  :description === '__MSG_extDesc__', :default_locale === 'en',
  :action.default_title === '__MSG_tooltipOff__'; _locales/{en,ru}/
  messages.json carry D-07 + D-08 canonical strings.
- locale-parity.test.ts (4 cases): ru→en parity, en→ru symmetric,
  non-empty .message strings (RESEARCH Pitfall 4 mitigation).

Current polarity: 29 RED + 18 GREEN across the 6 new files (placeholders
already clear dim+size floors; no-remote-fonts vacuous-GREEN since
tokens.css doesn't yet exist with remote URLs). Existing 100/100 vitest
baseline preserved (verified SKIP_BUILD=1 npx vitest run).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 21:56:08 +02:00

78 lines
3.5 KiB
TypeScript

// 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);
});
});