Files
pbakaus_impeccable/tests/design-parser.test.mjs
T
Paul Bakaus f1e8d4e70e Simplify named rule extraction
AI-assisted by OpenAI Codex under maintainer pbakaus's scheduled-refactor authorization.
2026-08-31 12:59:53 -07:00

343 lines
9.5 KiB
JavaScript

/**
* Tests for design-parser.mjs — frontmatter + body extraction.
* Run with: node --test tests/design-parser.test.mjs
*/
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { assessCoverage, parseDesignMd } from '../skill/scripts/lib/design-parser.mjs';
describe('parseDesignMd frontmatter branch', () => {
it('returns null frontmatter when the file has no YAML header', () => {
const md = `# Design System: Demo
## 1. Overview
Some prose.
`;
const model = parseDesignMd(md);
assert.equal(model.schemaVersion, 2);
assert.equal(model.frontmatter, null);
assert.equal(model.title, 'Design System: Demo');
});
it('parses a Stitch-shaped frontmatter and strips it from the body', () => {
const md = `---
name: Demo System
description: A quiet editorial look.
colors:
primary: "#b8422e"
neutral-bg: "#faf7f2"
typography:
display:
fontFamily: "Cormorant Garamond, Georgia, serif"
fontWeight: 300
lineHeight: 1
body:
fontFamily: "Inter, sans-serif"
rounded:
sm: "4px"
md: "8px"
components:
button-primary:
backgroundColor: "{colors.primary}"
textColor: "{colors.neutral-bg}"
rounded: "{rounded.sm}"
---
# Design System: Demo
## 1. Overview
Opening prose.
`;
const model = parseDesignMd(md);
assert.equal(model.schemaVersion, 2);
assert.equal(model.title, 'Design System: Demo');
assert.ok(model.frontmatter);
assert.equal(model.frontmatter.name, 'Demo System');
assert.equal(model.frontmatter.description, 'A quiet editorial look.');
assert.equal(model.frontmatter.colors.primary, '#b8422e');
assert.equal(model.frontmatter.colors['neutral-bg'], '#faf7f2');
assert.equal(model.frontmatter.typography.display.fontFamily, 'Cormorant Garamond, Georgia, serif');
assert.equal(model.frontmatter.typography.display.fontWeight, 300);
assert.equal(model.frontmatter.typography.display.lineHeight, 1);
assert.equal(model.frontmatter.rounded.md, '8px');
assert.equal(model.frontmatter.components['button-primary'].backgroundColor, '{colors.primary}');
});
it('recovers gracefully when frontmatter has no closing marker', () => {
// No `---` terminator: the whole file is treated as body, not partial
// frontmatter. The H1 title still resolves from the body.
const md = `---
this is not valid yaml : : :
no closing marker
# Design System: Broken
## 1. Overview
Prose.
`;
const model = parseDesignMd(md);
assert.equal(model.frontmatter, null);
assert.equal(model.title, 'Design System: Broken');
});
it('ignores line-only comments but preserves unquoted hex values', () => {
const md = `---
# Top-level comment
colors:
primary: #b8422e
# mid-block comment
accent: "#ec4899"
---
# Design System: Commented
## 1. Overview
Prose.
`;
const model = parseDesignMd(md);
assert.equal(model.frontmatter.colors.primary, '#b8422e');
assert.equal(model.frontmatter.colors.accent, '#ec4899');
});
it('strips inline comments after quoted OKLCH values', () => {
const md = `---
colors:
kinpaku-gold: "oklch(84% 0.19 80.46)" # primary accent
gold-hairline: "oklch(58% 0.065 82 / 0.32)" # default rule
---
# Design System: Kinpaku
## 1. Overview
Prose.
`;
const model = parseDesignMd(md);
assert.equal(model.frontmatter.colors['kinpaku-gold'], 'oklch(84% 0.19 80.46)');
assert.equal(model.frontmatter.colors['gold-hairline'], 'oklch(58% 0.065 82 / 0.32)');
});
it('normalizes quoted YAML keys in token maps', () => {
const md = `---
rounded:
"2xl": "80px"
'3xl': "96px"
colors:
"brand-gold": "#d9a531"
---
# Design System: Quoted Keys
## 1. Overview
Prose.
`;
const model = parseDesignMd(md);
assert.equal(model.frontmatter.rounded['2xl'], '80px');
assert.equal(model.frontmatter.rounded['3xl'], '96px');
assert.equal(model.frontmatter.colors['brand-gold'], '#d9a531');
assert.equal(model.frontmatter.rounded['"2xl"'], undefined);
});
it('unescapes quote escapes inside quoted scalars (issue #428)', () => {
const md = `---
typography:
body:
fontFamily: "\\"IBM Plex Sans\\", system-ui, sans-serif"
name: 'It''s quiet'
empty: "
---
# Design System: Escaped
## 1. Overview
Prose.
`;
const model = parseDesignMd(md);
// YAML double-quoted scalars process backslash escapes.
assert.equal(model.frontmatter.typography.body.fontFamily, '"IBM Plex Sans", system-ui, sans-serif');
// Single-quoted scalars escape the quote by doubling it.
assert.equal(model.frontmatter.name, "It's quiet");
// A lone quote satisfies startsWith and endsWith at once; keep it literal
// instead of slicing it into an empty string.
assert.equal(model.frontmatter.empty, '"');
});
it('decodes hex, Unicode, and whitespace escapes in double-quoted scalars', () => {
const md = `---
colors:
accent: "\\x23b8422e"
typography:
accent:
fontFamily: "S\\u00f6hne, sans-serif"
label:
fontFamily: "IBM\\ Plex\\ Serif, serif"
mono:
fontFamily: "Space\\_Grotesk, sans-serif"
emoji: "\\U0001F44D"
bad-hex: "\\xZZ nope"
bad-range: "\\UFFFFFFFF nope"
---
# Design System: Hex Escapes
## 1. Overview
Prose.
`;
const model = parseDesignMd(md);
assert.equal(model.frontmatter.colors.accent, '#b8422e');
assert.equal(model.frontmatter.typography.accent.fontFamily, 'Söhne, sans-serif');
// \ (escaped space) and \_ (non-breaking space) are valid YAML escapes.
assert.equal(model.frontmatter.typography.label.fontFamily, 'IBM Plex Serif, serif');
assert.equal(model.frontmatter.typography.mono.fontFamily, 'Space\u00a0Grotesk, sans-serif');
assert.equal(model.frontmatter.emoji, '\u{1F44D}');
// Malformed or out-of-range sequences stay literal.
assert.equal(model.frontmatter['bad-hex'], '\\xZZ nope');
assert.equal(model.frontmatter['bad-range'], '\\UFFFFFFFF nope');
});
});
describe('parseDesignMd overview branch', () => {
it('joins wrapped Key Characteristics bullets without leaking continuations into philosophy', () => {
const md = `# Design System: Example
## Overview
**Creative North Star: "Structured clarity"**
**Key Characteristics:**
- Status remains understandable without relying on color
alone.
- Navigation controls remain visible when the viewport becomes
narrow.
`;
const overview = parseDesignMd(md).overview;
assert.deepEqual(overview.keyCharacteristics, [
'Status remains understandable without relying on color alone.',
'Navigation controls remain visible when the viewport becomes narrow.',
]);
assert.deepEqual(overview.philosophy, []);
});
});
describe('parseDesignMd named rules', () => {
it('preserves format precedence while deduplicating later definitions', () => {
const md = `# Design System: Rules
## Layout
### The "Rhythm" Rule
Ignore this duplicate heading definition.
### The Fallback Principle
Use the heading definition.
### Named Rules
- **The Fallback Principle:** Ignore this duplicate bullet definition.
- **The Layering Principle:** Use the bullet definition.
**The Rhythm Rule.** Keep the first definition.
`;
assert.deepEqual(parseDesignMd(md).layout.rules, [
{ name: 'The Rhythm Rule', body: 'Keep the first definition.' },
{ name: 'The Fallback Principle', body: 'Use the heading definition.' },
{ name: 'The Layering Principle', body: 'Use the bullet definition.' },
]);
});
});
describe('parseDesignMd canonical sections', () => {
it('preserves content and named rules from all eight canonical sections', () => {
const md = `# Design System: Complete
## Overview
**Creative North Star: "Structured clarity"**
## Colors
### Primary
- **Ink** (#111111): Primary text.
## Typography
**Body Font:** Inter (with sans-serif)
## Layout: Responsive rhythm
Primary regions use a twelve-column grid that collapses to one column on narrow screens.
### Named Rules
**The Spatial Hierarchy Rule.** Primary content must remain visually dominant.
## Elevation & Depth
Surfaces use tonal layering instead of shadows.
## Shapes
Selected objects use a double outline and clipped corners.
### The "Recognizable Silhouette" Rule
Repeated geometry must remain recognizable without color.
## Components
### Button
- **Primary:** Uses the accent color.
## Do's and Don'ts
### Do
- Preserve the spatial hierarchy.
### Don't
- Flatten every surface.
`;
const model = parseDesignMd(md);
assert.equal(model.layout.subtitle, 'Responsive rhythm');
assert.equal(
model.layout.description,
'Primary regions use a twelve-column grid that collapses to one column on narrow screens.',
);
assert.deepEqual(model.layout.rules, [{
name: 'The Spatial Hierarchy Rule',
body: 'Primary content must remain visually dominant.',
}]);
assert.equal(model.shapes.description, 'Selected objects use a double outline and clipped corners.');
assert.deepEqual(model.shapes.rules, [{
name: 'The Recognizable Silhouette Rule',
body: 'Repeated geometry must remain recognizable without color.',
}]);
const coverage = assessCoverage(model);
assert.deepEqual(
Object.entries(coverage).filter(([, v]) => v === 'missing').map(([k]) => k),
[],
'a section present in the markdown must not be reported as missing',
);
assert.deepEqual(Object.keys(coverage), [
'overview',
'colors',
'typography',
'layout',
'elevation',
'shapes',
'components',
'dosDonts',
]);
assert.deepEqual(coverage.layout, { description: true, rules: 1 });
assert.deepEqual(coverage.shapes, { description: true, rules: 1 });
});
});