import { APP_LOCALES } from '../i18n/locale'; import { ROUTE_IDS } from '../routing/route-ids'; import { type SiteContent } from './content.contracts'; import { SITE_CONTENT_DATA } from './site-content'; const TITLE_SUFFIX = ' | Antonio Ledebuhr'; const FORBIDDEN = /lorem|todo|tbd|platzhaltertext|placeholder text|wird derzeit aufgebaut|being built|coming soon|xxx/i; function walkStrings( value: unknown, visit: (text: string, path: string) => void, path = '', skipKeys: ReadonlySet = new Set(), ): void { if (typeof value === 'string') { visit(value, path); return; } if (Array.isArray(value)) { value.forEach((item, index) => walkStrings(item, visit, `${path}[${index}]`, skipKeys)); return; } if (value && typeof value === 'object') { for (const [key, child] of Object.entries(value)) { if (skipKeys.has(key)) { continue; } walkStrings(child, visit, path ? `${path}.${key}` : key, skipKeys); } } } describe('content completeness', () => { it('covers every route in both locales with real page copy', () => { for (const locale of APP_LOCALES) { const site = SITE_CONTENT_DATA[locale]; expect(site.pages.home).toBe(site.home); expect(site.pages.pitch).toBe(site.pitch); expect(site.pages.services).toBe(site.servicesOverview); expect(site.pages.contact).toBe(site.contact); expect(site.pages.projects).toBe(site.projects); expect(site.pages.stack).toBe(site.stack); expect(site.pages.imprint).toBe(site.legal.imprint); expect(site.pages.privacy).toBe(site.legal.privacy); expect(site.pages.servicesAi).toBe(site.services.servicesAi); for (const routeId of ROUTE_IDS) { const page = site.pages[routeId]; expect(page, `${locale}.${routeId}`).toBeTruthy(); expect(page.title.length).toBeGreaterThan(0); expect(page.title.endsWith(TITLE_SUFFIX)).toBe(true); expect(page.description.length).toBeGreaterThanOrEqual(60); expect(page.hero.headline.length).toBeGreaterThan(0); expect(page.hero.headline.includes(TITLE_SUFFIX)).toBe(false); if (routeId !== 'notFound') { const filledSections = page.sections.filter((section) => (section.body ?? []).some((paragraph) => paragraph.trim().length > 0), ); expect(filledSections.length, `${locale}.${routeId} sections`).toBeGreaterThanOrEqual(2); } } } }); it('keeps the content tree free of scaffolding, except legal review fields', () => { const skipped = new Set(['reviewNotice', 'reviewTodos']); for (const locale of APP_LOCALES) { const site = SITE_CONTENT_DATA[locale]; const hits: string[] = []; walkStrings( site, (text, path) => { if (FORBIDDEN.test(text)) { hits.push(`${path}: ${text}`); } }, locale, skipped, ); expect(hits).toEqual([]); for (const legalId of ['imprint', 'privacy'] as const) { const legal = site.legal[legalId]; expect(legal.reviewNotice.trim().length).toBeGreaterThan(20); expect(legal.reviewTodos.length).toBeGreaterThan(0); expect(legal.reviewTodos.every((item) => item.trim().length > 0)).toBe(true); } } }); it('does not treat legal review fields as an implicit skip of the rest of the legal pages', () => { for (const locale of APP_LOCALES) { const site: SiteContent = SITE_CONTENT_DATA[locale]; for (const legalId of ['imprint', 'privacy'] as const) { const legal = site.legal[legalId]; const remainderHits: string[] = []; walkStrings( { hero: legal.hero, sections: legal.sections, legalSections: legal.legalSections }, (text, path) => { if (FORBIDDEN.test(text)) { remainderHits.push(`${path}: ${text}`); } }, `${locale}.${legalId}`, ); expect(remainderHits).toEqual([]); } } }); });