Public pages no longer describe their own pipeline, case and service labels are real accessible names, and the contact briefing writes localized fields without empty optional lines. Co-authored-by: Cursor <cursoragent@cursor.com>
88 lines
2.9 KiB
TypeScript
88 lines
2.9 KiB
TypeScript
import { APP_LOCALES } from '../i18n/locale';
|
|
import { ROUTE_IDS } from '../routing/route-ids';
|
|
import { CASE_STUDY_IDS } from './content.contracts';
|
|
import { SITE_CONTENT_DATA } from './site-content';
|
|
|
|
const STRUCTURAL_KEYS = new Set([
|
|
'id',
|
|
'status',
|
|
'control',
|
|
'required',
|
|
'routeId',
|
|
'caseId',
|
|
'referenceCaseId',
|
|
'external',
|
|
]);
|
|
|
|
function assertParity(left: unknown, right: unknown, path: string): void {
|
|
if (Array.isArray(left) || Array.isArray(right)) {
|
|
expect(Array.isArray(left), path).toBe(true);
|
|
expect(Array.isArray(right), path).toBe(true);
|
|
expect((left as unknown[]).length, path).toBe((right as unknown[]).length);
|
|
(left as unknown[]).forEach((item, index) =>
|
|
assertParity(item, (right as unknown[])[index], `${path}[${index}]`),
|
|
);
|
|
return;
|
|
}
|
|
|
|
if (left && right && typeof left === 'object' && typeof right === 'object') {
|
|
const leftKeys = Object.keys(left).sort();
|
|
const rightKeys = Object.keys(right).sort();
|
|
expect(leftKeys, path).toEqual(rightKeys);
|
|
|
|
for (const key of leftKeys) {
|
|
const nextPath = `${path}.${key}`;
|
|
const leftValue = (left as Record<string, unknown>)[key];
|
|
const rightValue = (right as Record<string, unknown>)[key];
|
|
if (STRUCTURAL_KEYS.has(key)) {
|
|
expect(leftValue, nextPath).toEqual(rightValue);
|
|
} else {
|
|
assertParity(leftValue, rightValue, nextPath);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (
|
|
typeof left === 'string' &&
|
|
typeof right === 'string' &&
|
|
(/featuredCaseIds\[\d+\]$/.test(path) || /options\[\d+\]\.value$/.test(path))
|
|
) {
|
|
expect(left, path).toBe(right);
|
|
}
|
|
}
|
|
|
|
describe('content parity', () => {
|
|
it('keeps the German and English trees structurally aligned', () => {
|
|
assertParity(SITE_CONTENT_DATA.de, SITE_CONTENT_DATA.en, 'site');
|
|
});
|
|
|
|
it('uses different long-form copy in German and English', () => {
|
|
for (const routeId of ROUTE_IDS) {
|
|
const german = SITE_CONTENT_DATA.de.pages[routeId];
|
|
const english = SITE_CONTENT_DATA.en.pages[routeId];
|
|
|
|
expect(german.title, routeId).not.toBe(english.title);
|
|
expect(german.description, routeId).not.toBe(english.description);
|
|
expect(german.hero.headline, routeId).not.toBe(english.hero.headline);
|
|
|
|
german.sections.forEach((section, index) => {
|
|
const other = english.sections[index];
|
|
expect(section.body?.join('\n'), `${routeId}.${section.id}`).not.toBe(
|
|
other?.body?.join('\n'),
|
|
);
|
|
});
|
|
}
|
|
|
|
for (const caseId of CASE_STUDY_IDS) {
|
|
const german = SITE_CONTENT_DATA.de.cases[caseId];
|
|
const english = SITE_CONTENT_DATA.en.cases[caseId];
|
|
expect(german.summary, caseId).not.toBe(english.summary);
|
|
expect(german.situation, caseId).not.toBe(english.situation);
|
|
expect(german.linkLabel, caseId).not.toBe(english.linkLabel);
|
|
}
|
|
|
|
expect(APP_LOCALES).toEqual(['de', 'en']);
|
|
});
|
|
});
|