Add standalone API test runner with accounts and members suites
Custom test framework that starts the backend, creates a test DB, runs migrations, and hits real HTTP endpoints. Supports --suite and --tag filtering. 24 tests covering account CRUD, member inheritance, state normalization, move, search, and auto-generated numbers. Run with bun run api-test.
This commit is contained in:
63
packages/backend/api-tests/lib/reporter.ts
Normal file
63
packages/backend/api-tests/lib/reporter.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
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}`))
|
||||
}
|
||||
Reference in New Issue
Block a user