#!/usr/bin/env node import fs from 'node:fs/promises' import path from 'node:path' import { fileURLToPath } from 'node:url' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const frontendDir = path.resolve(__dirname, '..') const resultsPath = path.join(frontendDir, 'test-results', 'results.json') const docsDir = path.join(frontendDir, 'docs', 'e2e') const screenshotsDir = path.join(frontendDir, 'tests', 'e2e', 'screenshots') async function main() { // Read results const resultsText = await fs.readFile(resultsPath, 'utf8') const results = JSON.parse(resultsText) // Create output directories await fs.mkdir(docsDir, { recursive: true }) // Extract tests from suites const testDocs = [] for (const suite of results.suites || []) { for (const spec of suite.specs || []) { for (const test of spec.tests || []) { for (const result of test.results || []) { const testInfo = { title: spec.title, specFile: spec.file || suite.file, status: result.status, duration: result.duration, startTime: result.startTime, attachments: result.attachments || [], } testDocs.push(testInfo) } } } } // Generate individual test markdown files for (const test of testDocs) { const slug = slugify(test.title) const mdPath = path.join(docsDir, `${slug}.md`) // Use slug-based screenshot name (matches explicit screenshot in test) let screenshotPath = `${slug}.png` // Also try to find screenshot attachment and use its basename if (test.attachments && test.attachments.length > 0) { for (const attachment of test.attachments) { if (attachment.contentType === 'image/png') { const basename = path.basename(attachment.path) // Prefer explicit screenshot name if it matches our pattern if (basename !== 'test-finished-1.png' && basename !== 'test-finished-2.png') { screenshotPath = basename break } } } } const absoluteScreenshotPath = path.join(screenshotsDir, screenshotPath) const relativeScreenshotPath = path.relative(docsDir, absoluteScreenshotPath) const mdContent = `# ${test.title} [<- Back to index](./README.md) | [Top](../README.md) **File**: \`tests/e2e/${test.specFile}\` **Status**: ${test.status.toUpperCase()} **Duration**: ${test.duration}ms ## Screenshot ![${test.title}](${relativeScreenshotPath}) ## Test Details - Start Time: ${test.startTime || 'N/A'} - Spec File: ${test.specFile} ` await fs.writeFile(mdPath, mdContent) console.log(`Generated: ${path.relative(frontendDir, mdPath)}`) } // Generate index README const indexContent = `# E2E Test Reports [<- Up to docs](../README.md) | Test | Status | Duration | |------|--------|----------| ${testDocs.map(t => `| [${escapeMd(t.title)}](./${slugify(t.title)}.md) | ${t.status.toUpperCase()} | ${t.duration}ms |`).join('\n')} ` await fs.writeFile(path.join(docsDir, 'README.md'), indexContent) console.log(`Generated: ${path.relative(frontendDir, path.join(docsDir, 'README.md'))}`) console.log(`\nGenerated ${testDocs.length} test docs`) } function slugify(str) { return str .toLowerCase() .replace(/[^\w\s-]/g, '') .replace(/[\s_]+/g, '-') .replace(/^-+|-+$/g, '') } function escapeMd(str) { return str.replace(/[|\\\[\]\{\}]/g, '\\$&') } main().catch(err => { console.error('Error:', err) process.exit(1) })