const green = (s: string) => `\x1b[32m${s}\x1b[0m` const red = (s: string) => `\x1b[31m${s}\x1b[0m` const gray = (s: string) => `\x1b[90m${s}\x1b[0m` const bold = (s: string) => `\x1b[1m${s}\x1b[0m` const yellow = (s: string) => `\x1b[33m${s}\x1b[0m` export interface TestResult { name: string suite: string tags: string[] passed: boolean duration: number error?: string } export function printHeader(baseUrl: string) { console.log('') console.log(bold(`API Tests — ${baseUrl}`)) console.log('') } export function printSuiteHeader(name: string) { console.log(` ${bold(name)}`) } export function printTestResult(result: TestResult) { const icon = result.passed ? green('✓') : red('✗') const duration = gray(`(${result.duration}ms)`) console.log(` ${icon} ${result.name} ${duration}`) if (result.error) { console.log(` ${red(result.error)}`) } } export function printSummary(results: TestResult[], totalDuration: number) { const passed = results.filter((r) => r.passed).length const failed = results.filter((r) => !r.passed).length const total = results.length console.log('') console.log('─'.repeat(50)) if (failed === 0) { console.log(green(` ${passed} passed`) + gray(` (${(totalDuration / 1000).toFixed(1)}s)`)) } else { console.log( ` ${green(`${passed} passed`)}, ${red(`${failed} failed`)}` + gray(` of ${total} (${(totalDuration / 1000).toFixed(1)}s)`), ) console.log('') console.log(red(' Failed tests:')) for (const r of results.filter((r) => !r.passed)) { console.log(red(` ✗ ${r.suite} > ${r.name}`)) if (r.error) console.log(` ${r.error}`) } } console.log('') } export function printSkipped(reason: string) { console.log(yellow(` ⊘ Skipped: ${reason}`)) }