import { expect, test } from '@playwright/test'; import fs from 'node:fs/promises'; import path from 'node:path'; import { createHash } from 'node:crypto'; import { templateFixtures, templateProfile } from './pre-p10-template-fixtures'; const api = 'http://localhost:5302/api'; const baseline = path.resolve('../.artifacts/pre-phase10-ux/templates-legacy'); const output = path.resolve(process.env.CV_TEMPLATE_OUTPUT || '../.artifacts/pre-phase10-ux/templates-revised-01'); const hash = (text: string) => createHash('sha256').update(text).digest('hex'); // The existing avatar endpoint now normalizes image pixels with Skia. Retain font data // verbatim; exclude only embedded image payload bytes when comparing document markup. const normalizeAvatar = (html: string) => html.replace(/data:image\/(?:png|jpeg|webp);base64,[A-Za-z0-9+/=]+/g, 'data:image/normalized-avatar'); test('[PRE-P10 B] existing design-one markup, CSS and source markers survive design-two additions', async ({ request }, info) => { test.setTimeout(180_000); expect((await request.post(`${api}/auth/login`, { data: { email: 'e2e@example.test', password: 'E2ePassword123!' } })).status()).toBe(200); const me = await (await request.get(`${api}/auth/me`)).json(); const headers = { 'X-CSRF-TOKEN': (await request.storageState()).cookies.find(cookie => cookie.name === 'XSRF-TOKEN')!.value, 'X-Session-Context': me.sessionContext as string }; const avatar = await fs.readFile(path.join(baseline, 'synthetic-nonhuman-color-sample.png')); expect((await request.post(`${api}/auth/avatar`, { headers, multipart: { file: { name: 'synthetic-nonhuman.png', mimeType: 'image/png', buffer: avatar } } })).status()).toBe(200); const themes = await (await request.get(`${api}/cv/themes`)).json(); const results = []; await fs.mkdir(path.join(output, 'legacy-current'), { recursive: true }); for (const sample of templateFixtures) { const { profile } = templateProfile(sample); const source = await (await request.get(`${api}/career/profile`)).json(); expect((await request.put(`${api}/career/profile`, { headers, data: { expectedVersion: source.revision, profile } })).status()).toBe(200); for (const theme of themes) { const fixture = `${sample.key}-${theme.id}`; const created = await request.post(`${api}/cv/variants`, { headers, data: { name: fixture, settings: { themeId: theme.id, language: sample.language, showPhoto: true, showIcons: true } } }); expect(created.status(), fixture).toBe(200); const variant = await created.json(); const response = await request.get(`${api}/cv/variants/${variant.id}/preview`); expect(response.status(), fixture).toBe(200); const current = (await response.json()).html as string; const original = await fs.readFile(path.join(baseline, fixture, 'render.html'), 'utf8'); const style = (html: string) => html.match(/