Make test results copyable

Add Markdown formatting utilities for test results, wire up clipboard copy in IntegrationTestRunner, and export new formatters. Introduce formatters.ts, extend index.ts exports, and implement copy all / copy failed / per-test copy functionality with updated UI.
This commit is contained in:
gpt-engineer-app[bot]
2025-11-10 16:48:51 +00:00
parent ad31be1622
commit 3cb0f66064
3 changed files with 135 additions and 6 deletions

View File

@@ -0,0 +1,76 @@
/**
* Test Result Formatters
*
* Utilities for formatting test results into different formats for easy sharing and debugging.
*/
import type { TestResult } from './testRunner';
export function formatResultsAsMarkdown(
results: TestResult[],
summary: { total: number; passed: number; failed: number; skipped: number; totalDuration: number },
failedOnly: boolean = false
): string {
const timestamp = new Date().toISOString();
const title = failedOnly ? 'Failed Test Results' : 'Test Results';
let markdown = `# ${title} - ${timestamp}\n\n`;
// Summary section
markdown += `## Summary\n`;
markdown += `✅ Passed: ${summary.passed}\n`;
markdown += `❌ Failed: ${summary.failed}\n`;
markdown += `⏭️ Skipped: ${summary.skipped}\n`;
markdown += `⏱️ Duration: ${(summary.totalDuration / 1000).toFixed(2)}s\n\n`;
// Results by status
if (!failedOnly && summary.failed > 0) {
markdown += `## Failed Tests\n\n`;
results.filter(r => r.status === 'fail').forEach(result => {
markdown += formatTestResultMarkdown(result);
});
}
if (failedOnly) {
results.forEach(result => {
markdown += formatTestResultMarkdown(result);
});
} else {
// Include passed tests in summary
if (summary.passed > 0) {
markdown += `## Passed Tests\n\n`;
results.filter(r => r.status === 'pass').forEach(result => {
markdown += `### ✅ ${result.name} (${result.suite})\n`;
markdown += `**Duration:** ${result.duration}ms\n\n`;
});
}
}
return markdown;
}
export function formatSingleTestAsMarkdown(result: TestResult): string {
return formatTestResultMarkdown(result);
}
function formatTestResultMarkdown(result: TestResult): string {
const icon = result.status === 'fail' ? '❌' : result.status === 'pass' ? '✅' : '⏭️';
let markdown = `### ${icon} ${result.name} (${result.suite})\n`;
markdown += `**Duration:** ${result.duration}ms\n`;
markdown += `**Status:** ${result.status}\n`;
if (result.error) {
markdown += `**Error:** ${result.error}\n\n`;
}
if (result.stack) {
markdown += `**Stack Trace:**\n\`\`\`\n${result.stack}\n\`\`\`\n\n`;
}
if (result.details) {
markdown += `**Details:**\n\`\`\`json\n${JSON.stringify(result.details, null, 2)}\n\`\`\`\n\n`;
}
return markdown;
}

View File

@@ -6,5 +6,6 @@
export { IntegrationTestRunner } from './testRunner';
export { allTestSuites } from './suites';
export { formatResultsAsMarkdown, formatSingleTestAsMarkdown } from './formatters';
export type { TestResult, Test, TestSuite } from './testRunner';