diff --git a/test/componentFixtures/cssOrderScan.mts b/test/componentFixtures/cssOrderScan.mts index d6849660267..9cee95dc9cc 100644 --- a/test/componentFixtures/cssOrderScan.mts +++ b/test/componentFixtures/cssOrderScan.mts @@ -20,7 +20,7 @@ * node test/componentFixtures/cssOrderScan.mts [--out ] [--fixture-id-regex ] */ -import { copyFile, mkdir, rm, writeFile } from 'node:fs/promises'; +import { copyFile, mkdir, readFile, rm, writeFile } from 'node:fs/promises'; import { dirname, join, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import { bisectConflict, type FixtureEntry, readServeUrl, Renderer } from './cssOrderShared.mts'; @@ -98,15 +98,23 @@ function slugify(fixtureId: string): string { return fixtureId.replace(/[^a-zA-Z0-9._-]+/g, '_'); } -/** Markdown image source for a captured render, honoring `--image-base-url`. */ -function imageSource(args: Args, hash: string, relativePath: string | undefined): string | undefined { +/** + * A Markdown link (not an embedded image) to a captured render. Honors + * `--image-base-url` when set; otherwise inlines the PNG as a base64 `data:` + * URI so the report stays self-contained without bloating it with ``s. + */ +async function imageLink(args: Args, label: string, hash: string, relativePath: string | undefined): Promise { if (args.imageBaseUrl) { - return `${args.imageBaseUrl.replace(/\/$/, '')}/${hash}`; + return `[${label}](${args.imageBaseUrl.replace(/\/$/, '')}/${hash})`; } - return relativePath; + if (!relativePath) { + return undefined; + } + const bytes = await readFile(join(args.out, relativePath)); + return `[${label}](data:image/png;base64,${bytes.toString('base64')})`; } -function renderMarkdown(args: Args, problems: readonly Problem[], totals: { scanned: number; errored: number }): string { +async function renderMarkdown(args: Args, problems: readonly Problem[], totals: { scanned: number; errored: number }): Promise { const lines: string[] = []; const clean = totals.scanned - problems.length - totals.errored; @@ -177,15 +185,14 @@ function renderMarkdown(args: Args, problems: readonly Problem[], totals: { scan } lines.push(`- Later document (wins): ${fileLink(p.laterFile)} — document #${p.laterIndex}`); lines.push(`- Earlier document (loses): ${fileLink(p.earlierFile)} — document #${p.earlierIndex}`); - lines.push(`- Image hash: \`${p.baselineHash.slice(0, 12)}\` (baseline) → \`${p.reversedHash.slice(0, 12)}\` (reversed)`, ''); + lines.push(`- Image hash: \`${p.baselineHash.slice(0, 12)}\` (baseline) → \`${p.reversedHash.slice(0, 12)}\` (reversed)`); - const baseSrc = imageSource(args, p.baselineHash, p.baselineImage); - const revSrc = imageSource(args, p.reversedHash, p.reversedImage); - if (baseSrc && revSrc) { - lines.push('| Baseline (product order) | Reversed order |'); - lines.push('| --- | --- |'); - lines.push(`| ![baseline](${baseSrc}) | ![reversed](${revSrc}) |`, ''); + const baseLink = await imageLink(args, 'baseline image', p.baselineHash, p.baselineImage); + const revLink = await imageLink(args, 'reversed image', p.reversedHash, p.reversedImage); + if (baseLink && revLink) { + lines.push(`- Images: ${baseLink} (product order) · ${revLink} (reversed order)`); } + lines.push(''); } return lines.join('\n'); @@ -237,6 +244,7 @@ async function main(): Promise { } const n = files.length; process.stdout.write(`\n[${i + 1}/${candidates.length}] Localizing ${base.fixtureId} (${n} documents)...\n`); + process.stdout.write(` hashes: baseline=${base.imageHash} reversed=${rev.imageHash}\n`); let probeCount = 0; const { later, earlier } = await bisectConflict(renderer, base.fixtureId, n, base.imageHash!, ({ fromIndex, toIndex, differs, ms }) => { const verdict = differs ? 'DIFFERS' : 'same'; @@ -274,7 +282,7 @@ async function main(): Promise { process.stdout.write(` → #${earlier} ${fileBaseName(files[earlier] ?? '?')} loses to #${later} ${fileBaseName(files[later] ?? '?')}\n`); } - const markdown = renderMarkdown(args, problems, { scanned: baseline.entries.length, errored }); + const markdown = await renderMarkdown(args, problems, { scanned: baseline.entries.length, errored }); await writeFile(join(args.out, 'report.md'), `${markdown}\n`, 'utf8'); await writeFile(join(args.out, 'report.json'), `${JSON.stringify({ generatedAt: new Date().toISOString(), commit: GITHUB_SHA, scanned: baseline.entries.length, errored, problems }, undefined, '\t')}\n`, 'utf8');