import { readdir, readFile, stat } from 'node:fs/promises'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { describe, expect, it } from 'vitest'; declare global { interface ImportMeta { glob(pattern: string, options: { eager: true }): Record; } } type LocalizedContentIds = { skills: string[]; designSystems: string[]; designSystemCategories: string[]; promptTemplates: string[]; promptTemplateCategories: string[]; promptTemplateTags: string[]; }; type LocalizedContentModule = { LOCALIZED_CONTENT_IDS: Record; }; const repoRoot = fileURLToPath(new URL('../../', import.meta.url)); const webContentModules = import.meta.glob( '../../apps/web/src/i18n/content.ts', { eager: true }, ); const localizedContentModule = Object.values(webContentModules)[0]; if (localizedContentModule == null) { throw new Error('Failed to load apps/web localized content ids'); } const { LOCALIZED_CONTENT_IDS } = localizedContentModule; function sorted(values: Iterable): string[] { return [...values].sort((a, b) => a.localeCompare(b)); } async function entriesWithFile(root: string, fileName: string): Promise { const entries = await readdir(root, { withFileTypes: true }); const ids: string[] = []; for (const entry of entries) { if (!entry.isDirectory()) continue; const filePath = path.join(root, entry.name, fileName); try { if ((await stat(filePath)).isFile()) { ids.push(entry.name); } } catch { // Missing optional registry files are ignored, matching resource discovery. } } return sorted(ids); } async function readSkillIds(): Promise { const skillsRoot = path.join(repoRoot, 'skills'); const dirs = await entriesWithFile(skillsRoot, 'SKILL.md'); const ids = await Promise.all( dirs.map(async (dir) => { const raw = await readFile(path.join(skillsRoot, dir, 'SKILL.md'), 'utf8'); return readFrontmatterName(raw) ?? dir; }), ); return sorted(ids); } async function readDesignSystemIds(): Promise { return entriesWithFile(path.join(repoRoot, 'design-systems'), 'DESIGN.md'); } async function readDesignSystemCategories(): Promise { const systemsRoot = path.join(repoRoot, 'design-systems'); const ids = await readDesignSystemIds(); const categories = await Promise.all( ids.map(async (id) => { const raw = await readFile(path.join(systemsRoot, id, 'DESIGN.md'), 'utf8'); return /^>\s*Category:\s*(.+?)\s*$/im.exec(raw)?.[1] ?? 'Uncategorized'; }), ); return sorted(new Set(categories)); } async function readPromptTemplateSummaries(): Promise< Array<{ id: string; category: string; tags: string[] }> > { const templatesRoot = path.join(repoRoot, 'prompt-templates'); const summaries: Array<{ id: string; category: string; tags: string[] }> = []; for (const surface of ['image', 'video']) { const dir = path.join(templatesRoot, surface); const entries = await readdir(dir, { withFileTypes: true }); for (const entry of entries) { if (!entry.isFile() || !entry.name.endsWith('.json')) continue; const raw = JSON.parse(await readFile(path.join(dir, entry.name), 'utf8')) as { id?: unknown; category?: unknown; tags?: unknown; }; if (typeof raw.id !== 'string' || !raw.id) continue; summaries.push({ id: raw.id, category: typeof raw.category === 'string' ? raw.category : 'General', tags: Array.isArray(raw.tags) ? raw.tags.filter((tag): tag is string => typeof tag === 'string') : [], }); } } return summaries; } function readFrontmatterName(src: string): string | null { const text = src.replace(/^\uFEFF/, ''); const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/.exec(text); if (match == null) return null; const nameMatch = /^name:\s*(.*?)\s*$/im.exec(match[1] ?? ''); if (nameMatch == null) return null; const name = unquoteYamlScalar(nameMatch[1] ?? '').trim(); return name || null; } function unquoteYamlScalar(value: string): string { const trimmed = value.trim(); if ( (trimmed.startsWith('"') && trimmed.endsWith('"')) || (trimmed.startsWith("'") && trimmed.endsWith("'")) ) { return trimmed.slice(1, -1); } return trimmed; } describe('localized display content coverage', () => { for (const [locale, ids] of Object.entries(LOCALIZED_CONTENT_IDS)) { it(`covers every curated skill, design system, and prompt template for ${locale}`, async () => { const [skillIds, designSystemIds, promptTemplateSummaries] = await Promise.all([ readSkillIds(), readDesignSystemIds(), readPromptTemplateSummaries(), ]); expect(sorted(ids.skills), 'skills display copy').toEqual(skillIds); expect(sorted(ids.designSystems), 'design-system summaries').toEqual( designSystemIds, ); expect(sorted(ids.promptTemplates), 'prompt-template metadata').toEqual( sorted(promptTemplateSummaries.map((template) => template.id)), ); }); it(`covers every curated display category and prompt tag for ${locale}`, async () => { const [designSystemCategories, promptTemplateSummaries] = await Promise.all([ readDesignSystemCategories(), readPromptTemplateSummaries(), ]); const promptTemplateCategories = new Set( promptTemplateSummaries.map((template) => template.category), ); const promptTemplateTags = new Set( promptTemplateSummaries.flatMap((template) => template.tags), ); expect(sorted(ids.designSystemCategories)).toEqual( expect.arrayContaining(designSystemCategories), ); expect(sorted(ids.promptTemplateCategories)).toEqual( expect.arrayContaining(sorted(promptTemplateCategories)), ); expect(sorted(ids.promptTemplateTags)).toEqual( expect.arrayContaining(sorted(promptTemplateTags)), ); }); } });