Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | 1x 1x 17x 17x 3x 14x 14x 14x 10x 10x 10x 3x 2x 2x 2x 7x 6x 4x 4x 4x 1x 10x 6x 6x 6x 6x 6x 5x 2x 2x 2x 3x 3x 3x 3x | import { recordAll } from './record.ts';
import { replayAll } from './replay.ts';
import { ALL_HTTP_SCENARIOS } from './scenarios/index.ts';
/**
* Parse argv of the shape:
* oracle-harness record [--target http://...] [--out path]
* oracle-harness replay [--target http://...] [--recorded path]
*
* Returns a normalized object; throws on unknown subcommand or flag.
* Sensible defaults match the repo layout (oracle on :8000, recordings
* in tests/oracle/recorded).
*/
export type CliCommand = 'record' | 'replay';
export interface CliOptions {
readonly command: CliCommand;
readonly targetUrl: string;
readonly dir: string;
}
export const DEFAULT_TARGET = 'http://127.0.0.1:8000';
export const DEFAULT_RECORDED_DIR = 'tests/oracle/recorded';
export function parseArgs(argv: readonly string[]): CliOptions {
const [raw, ...rest] = argv;
if (raw !== 'record' && raw !== 'replay') {
throw new Error(
`unknown command: ${JSON.stringify(raw ?? '')} (expected "record" or "replay")`,
);
}
let targetUrl = DEFAULT_TARGET;
let dir = DEFAULT_RECORDED_DIR;
for (let i = 0; i < rest.length; i++) {
const flag = rest[i];
const value = rest[i + 1];
if (flag === '--target') {
if (value === undefined) throw new Error('--target requires a URL');
targetUrl = value;
i++;
continue;
}
if (flag === '--out' || flag === '--recorded') {
if (value === undefined) throw new Error(`${flag} requires a path`);
dir = value;
i++;
continue;
}
throw new Error(`unknown flag: ${JSON.stringify(flag)}`);
}
return { command: raw as CliCommand, targetUrl, dir };
}
export interface MainDeps {
readonly log?: (line: string) => void;
readonly record?: typeof recordAll;
readonly replay?: typeof replayAll;
readonly scenarios?: typeof ALL_HTTP_SCENARIOS;
}
/** Async entrypoint; returns an exit code. */
export async function main(
argv: readonly string[],
deps: MainDeps = {},
): Promise<number> {
const log = deps.log ?? ((line: string) => process.stdout.write(`${line}\n`));
const record = deps.record ?? recordAll;
const replay = deps.replay ?? replayAll;
const scenarios = deps.scenarios ?? ALL_HTTP_SCENARIOS;
const opts = parseArgs(argv);
if (opts.command === 'record') {
const results = await record(scenarios, {
targetUrl: opts.targetUrl,
outDir: opts.dir,
log,
});
log(`recorded ${results.length} scenarios → ${opts.dir}`);
return 0;
}
const results = await replay({ targetUrl: opts.targetUrl, recordedDir: opts.dir, log });
const failed = results.filter((r) => !r.ok);
log(`replay: ${results.length - failed.length}/${results.length} passed`);
return failed.length === 0 ? 0 : 1;
}
|