#!/usr/bin/env node /** * cli:run-ui-test — index.ts * * Args: * --project-path Required. Project root. * --frontend-url Required. e.g. http://localhost:5173 * --api-url Required. e.g. http://localhost:5142 * --module Optional filter. * --test-id Optional. Run only one test. * --manifest-path Default: tests/ui-test/manifest.json * --users-path Default: tests/ui-test/test-users.json * --capture-dir Default: tests/ui-test/captures * --timeout-ms Default: 60000 */ import { parseArgs } from 'node:util'; import { validate } from './validate.js'; import { execute } from './execute.js'; import { executeEnvelope, failExecute, printEnvelope } from '../../../../../lib/output.js'; const COMMAND = 'run-ui-test'; async function main(): Promise { const args = parseArgs({ options: { 'project-path': { type: 'string' }, 'frontend-url': { type: 'string' }, 'api-url': { type: 'string' }, module: { type: 'string' }, 'test-id': { type: 'string' }, 'manifest-path': { type: 'string', default: 'tests/ui-test/manifest.json' }, 'users-path': { type: 'string', default: 'tests/ui-test/test-users.json' }, 'capture-dir': { type: 'string', default: 'tests/ui-test/captures' }, 'timeout-ms': { type: 'string', default: '60000' }, }, allowPositionals: false, }); const raw = { projectPath: args.values['project-path'], frontendUrl: args.values['frontend-url'], apiUrl: args.values['api-url'], module: args.values.module, testId: args.values['test-id'], manifestPath: args.values['manifest-path'], usersPath: args.values['users-path'], captureDir: args.values['capture-dir'], timeoutMs: Number.parseInt(args.values['timeout-ms'] ?? '60000', 10), }; const v = await validate(raw); if (!v.valid || !v.data) { printEnvelope(failExecute(COMMAND, v.errors)); process.exit(2); } try { const report = await execute(v.data); const envelope = executeEnvelope(COMMAND, { success: report.failed === 0, report: report as unknown as Record, warnings: v.warnings, nextSteps: report.failed > 0 ? [`${report.failed}/${report.totalTests} test(s) failed. The Studio runner will spawn debug-bug fix loops (max 50 iter per test).`] : ['All tests passed.'], }); printEnvelope(envelope); process.exit(report.failed === 0 ? 0 : 1); } catch (err) { printEnvelope(failExecute(COMMAND, [err instanceof Error ? err.message : String(err)])); process.exit(1); } } main();