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:
79
src/app/shared/contact-briefing/contact-briefing.spec.ts
Normal file
79
src/app/shared/contact-briefing/contact-briefing.spec.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { SITE_CONTENT_DATA } from '../../core/content/site-content';
|
||||
import { SITE_CONFIG } from '../../core/content/site-config';
|
||||
import { ContactBriefing } from './contact-briefing';
|
||||
|
||||
function setControl(root: HTMLElement, id: string, value: string): void {
|
||||
const control = root.querySelector<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>(
|
||||
`#${id}`,
|
||||
);
|
||||
expect(control).toBeTruthy();
|
||||
control!.value = value;
|
||||
control!.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
}
|
||||
|
||||
describe('ContactBriefing', () => {
|
||||
it('binds labels, builds an encoded mailto link and never talks to a server', async () => {
|
||||
const fetchSpy = vi.spyOn(globalThis, 'fetch').mockResolvedValue(new Response());
|
||||
const xhrSpy = vi.spyOn(XMLHttpRequest.prototype, 'send').mockImplementation(() => undefined);
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ContactBriefing],
|
||||
}).compileComponents();
|
||||
|
||||
const fixture = TestBed.createComponent(ContactBriefing);
|
||||
const copy = SITE_CONTENT_DATA.de.contact;
|
||||
fixture.componentRef.setInput('copy', copy);
|
||||
await fixture.whenStable();
|
||||
|
||||
const root = fixture.nativeElement as HTMLElement;
|
||||
|
||||
for (const field of copy.fields) {
|
||||
const controlId = `contact-${field.id}`;
|
||||
const label = root.querySelector(`label[for="${controlId}"]`);
|
||||
const control = root.querySelector(`#${controlId}`);
|
||||
expect(label?.textContent).toContain(field.label);
|
||||
expect(control).toBeTruthy();
|
||||
}
|
||||
|
||||
expect(root.querySelector('form[action]')).toBeNull();
|
||||
expect(root.textContent).toContain(copy.incompleteHint);
|
||||
expect(root.querySelector(`a[href="${SITE_CONFIG.calendarUrl}"]`)).toBeNull();
|
||||
expect(root.textContent).not.toContain(copy.calendarLabel);
|
||||
|
||||
const special = 'Äpfel & Birnen?\nPreis=100';
|
||||
setControl(root, 'contact-name', special);
|
||||
setControl(root, 'contact-email', 'team@example.com');
|
||||
setControl(root, 'contact-company', 'Rösterei & Co');
|
||||
setControl(root, 'contact-projectType', 'software');
|
||||
setControl(root, 'contact-situation', special);
|
||||
setControl(root, 'contact-timeframe', 'Q3');
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(root.textContent).not.toContain(copy.incompleteHint);
|
||||
|
||||
const submit = root.querySelector<HTMLAnchorElement>('a.submit');
|
||||
expect(submit?.getAttribute('href')?.startsWith('mailto:info@antoniolede.de?subject=')).toBe(
|
||||
true,
|
||||
);
|
||||
|
||||
const href = submit?.getAttribute('href') ?? '';
|
||||
expect(href.includes(' ')).toBe(false);
|
||||
expect(href.includes('\n')).toBe(false);
|
||||
|
||||
const query = href.slice(href.indexOf('?') + 1);
|
||||
const [subjectPart, bodyPart] = query.split('&body=');
|
||||
expect(subjectPart.startsWith('subject=')).toBe(true);
|
||||
expect(subjectPart.includes('&')).toBe(false);
|
||||
expect(bodyPart.includes('&')).toBe(false);
|
||||
|
||||
const decodedBody = decodeURIComponent(bodyPart);
|
||||
expect(decodedBody).toContain(special);
|
||||
expect(decodedBody).toContain('team@example.com');
|
||||
expect(decodedBody).toContain('Rösterei & Co');
|
||||
expect(decodeURIComponent(subjectPart.slice('subject='.length))).toBe(copy.mailSubject);
|
||||
|
||||
expect(fetchSpy).not.toHaveBeenCalled();
|
||||
expect(xhrSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user