69 lines
2.5 KiB
JavaScript
69 lines
2.5 KiB
JavaScript
import { readFile, stat } from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
import { fail, pass, repositoryRoot } from './lib.mjs';
|
|
|
|
const errors = [];
|
|
const pagePath = path.join(repositoryRoot, 'src/app/[locale]/page.tsx');
|
|
const cssPath = path.join(repositoryRoot, 'src/app/[locale]/page.module.css');
|
|
const modelPath = path.join(repositoryRoot, 'src/content/homepage-model.ts');
|
|
const page = await readFile(pagePath, 'utf8');
|
|
const css = await readFile(cssPath, 'utf8');
|
|
const model = await readFile(modelPath, 'utf8');
|
|
|
|
for (const sectionId of ['product', 'workflow', 'modules', 'pricing', 'faq']) {
|
|
if (!page.includes(`id="${sectionId}"`))
|
|
errors.push(`Homepage section #${sectionId} is missing.`);
|
|
}
|
|
|
|
for (const component of [
|
|
'ActionLink',
|
|
'Accordion',
|
|
'CTA',
|
|
'Comparison',
|
|
'FeatureCard',
|
|
'ProductPreview',
|
|
'SectionHeader',
|
|
'Workflow',
|
|
]) {
|
|
if (!page.includes(component))
|
|
errors.push(`Homepage does not compose the approved ${component}.`);
|
|
}
|
|
|
|
if (!page.includes('buildHomepageContent'))
|
|
errors.push('Homepage does not consume the typed route content model.');
|
|
if (!page.includes("localizedPath('home', locale)"))
|
|
errors.push('Homepage actions do not use the locale route helper.');
|
|
if (page.includes('messages.foundation'))
|
|
errors.push('Phase 11 foundation placeholder remains in the homepage route.');
|
|
if (/href=["']#["']/.test(page)) errors.push('Homepage contains href="#".');
|
|
if (/#[0-9a-f]{3,8}\b|rgba?\(|hsla?\(/i.test(css))
|
|
errors.push('Homepage CSS contains literal colors.');
|
|
if (/var\(--color-(?:blue|orange|gray|green|amber|red|navy)-/i.test(css)) {
|
|
errors.push('Homepage CSS consumes a raw palette token.');
|
|
}
|
|
if (!model.includes('disabledReason'))
|
|
errors.push('Homepage content model does not encode unavailable destinations.');
|
|
if (!model.includes('PreviewRow'))
|
|
errors.push('Homepage content model does not type product preview rows.');
|
|
|
|
for (const artifact of [
|
|
'tests/unit/homepage-content.test.ts',
|
|
'tests/browser/homepage.spec.ts',
|
|
'tests/a11y/homepage.a11y.spec.ts',
|
|
'tests/visual/homepage.visual.spec.ts',
|
|
'docs/phase13/HOMEPAGE_SECTION_MATRIX_v1.0.csv',
|
|
'docs/phase13/HOMEPAGE_CONTENT_MODEL_v1.0.md',
|
|
]) {
|
|
try {
|
|
await stat(path.join(repositoryRoot, artifact));
|
|
} catch {
|
|
errors.push(`Required Phase 13 artifact missing: ${artifact}`);
|
|
}
|
|
}
|
|
|
|
if (errors.length > 0) fail(errors);
|
|
else
|
|
pass(
|
|
'Phase 13 homepage composition, content model, destination gates, and test artifacts satisfy static controls.',
|
|
);
|