Files
Portfolio/src/app/core/content/content-claims.spec.ts
Antonio Ledebuhr 763bf435c9 content: drop repeated reference headings and land case CTAs on anchors
Service notes now say why the public case fits, the four case CTAs
open the matching project fragment, and the Innofocus run-time figure
is a case metric as well as a home tile.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-25 17:52:37 +02:00

87 lines
3.4 KiB
TypeScript

import { APP_LOCALES } from '../i18n/locale';
import {
CASE_STUDY_IDS,
type CaseStudyCopy,
type MetricCopy,
type OfferingCopy,
type SiteContent,
} from './content.contracts';
import { SITE_CONTENT_DATA } from './site-content';
const DELIVERED_OFFER_WORDING =
/für kunden umgesetzt|im kundeneinsatz|in production for clients|delivered for clients|langjährige erfahrung mit rag|years of rag/i;
function allMetrics(site: SiteContent): readonly MetricCopy[] {
return [...site.home.metrics, ...CASE_STUDY_IDS.flatMap((id) => site.cases[id].metrics)];
}
function allOfferings(site: SiteContent): readonly OfferingCopy[] {
return Object.values(site.services).flatMap((page) => page.offerings);
}
function caseText(caseStudy: CaseStudyCopy): string {
return [
caseStudy.summary,
caseStudy.responsibility,
caseStudy.situation,
...caseStudy.approach,
...caseStudy.outcome,
...caseStudy.metrics.map((metric) => `${metric.value} ${metric.label} ${metric.note ?? ''}`),
].join('\n');
}
describe('content claims and attribution', () => {
it('keeps the four public cases and attributes verified facts to the right ones', () => {
for (const locale of APP_LOCALES) {
const site = SITE_CONTENT_DATA[locale];
expect(Object.keys(site.cases)).toEqual([...CASE_STUDY_IDS]);
expect(CASE_STUDY_IDS).toEqual(['innofocus', 'roesterei', 'myspa', 'hdi']);
const matchesRuntime = (metric: MetricCopy) =>
/8/.test(metric.value) && /90/.test(metric.value);
const runtimeMetrics = allMetrics(site).filter(matchesRuntime);
expect(runtimeMetrics.every((metric) => metric.caseId === 'innofocus')).toBe(true);
expect(site.home.metrics.filter(matchesRuntime)).toHaveLength(1);
expect(site.cases.innofocus.metrics.filter(matchesRuntime)).toHaveLength(1);
for (const caseId of CASE_STUDY_IDS.filter((id) => id !== 'innofocus')) {
expect(site.cases[caseId].metrics.filter(matchesRuntime)).toHaveLength(0);
}
const leadershipMetrics = allMetrics(site).filter(
(metric) =>
metric.caseId === 'myspa' &&
/4/.test(`${metric.value} ${metric.label}`) &&
/2/.test(`${metric.value} ${metric.label}`),
);
expect(leadershipMetrics.length).toBeGreaterThan(0);
const hdiText = caseText(site.cases.hdi);
expect(hdiText).toMatch(/Azure AKS/);
expect(hdiText).toMatch(/Azure App Services/);
for (const caseId of CASE_STUDY_IDS.filter((id) => id !== 'hdi')) {
expect(caseText(site.cases[caseId])).not.toMatch(/Azure App Services/);
}
}
});
it('keeps AI delivery claims limited to the two Rösterei tools', () => {
for (const locale of APP_LOCALES) {
const site = SITE_CONTENT_DATA[locale];
const aiOfferings = site.services.servicesAi.offerings;
const delivered = aiOfferings.filter((offering) => offering.status === 'delivered');
expect(delivered).toHaveLength(2);
expect(delivered.every((offering) => offering.referenceCaseId === 'roesterei')).toBe(true);
const otherOfferings = allOfferings(site).filter((offering) => !delivered.includes(offering));
expect(otherOfferings.every((offering) => offering.status === 'offer')).toBe(true);
expect(
otherOfferings.some((offering) =>
DELIVERED_OFFER_WORDING.test(`${offering.title} ${offering.body}`),
),
).toBe(false);
}
});
});