content: replace scaffolding with bilingual pages and case studies
Ship the final German and English copy, compose every route from shared page primitives, and cover claims, parity and contact briefing in tests. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
82
src/app/core/content/content-claims.spec.ts
Normal file
82
src/app/core/content/content-claims.spec.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
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 runtimeMetrics = allMetrics(site).filter(
|
||||
(metric) => /8/.test(metric.value) && /90/.test(metric.value),
|
||||
);
|
||||
expect(runtimeMetrics).toHaveLength(1);
|
||||
expect(runtimeMetrics[0]?.caseId).toBe('innofocus');
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user