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>
87 lines
3.4 KiB
TypeScript
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);
|
|
}
|
|
});
|
|
});
|