76 lines
2.3 KiB
TypeScript
76 lines
2.3 KiB
TypeScript
import { strict as assert } from 'node:assert';
|
|
|
|
export interface IRunMxCliResult {
|
|
readonly logs: string[];
|
|
readonly errors: string[];
|
|
readonly exitCode: number;
|
|
}
|
|
|
|
async function loadMxCli(): Promise<{ createProgram: () => import('commander').Command }> {
|
|
const mxCliUrl = new URL('../../src/index.ts', import.meta.url).href;
|
|
return await import(`${mxCliUrl}?test=${Date.now()}-${Math.random().toString(16).slice(2)}`);
|
|
}
|
|
|
|
export async function runMxCli(argv: string[], options: { cwd?: string } = {}): Promise<IRunMxCliResult> {
|
|
const logs: string[] = [];
|
|
const errors: string[] = [];
|
|
let exitCode = 0;
|
|
|
|
const originalLog = console.log;
|
|
const originalError = console.error;
|
|
const originalExit = process.exit;
|
|
const originalCwd = process.cwd();
|
|
const { createProgram } = await loadMxCli();
|
|
|
|
console.log = (...args: unknown[]) => {
|
|
logs.push(args.map((arg) => String(arg)).join(' '));
|
|
};
|
|
console.error = (...args: unknown[]) => {
|
|
errors.push(args.map((arg) => String(arg)).join(' '));
|
|
};
|
|
(process as unknown as { exit: (code?: number) => never }).exit = ((code?: number) => {
|
|
exitCode = code ?? 0;
|
|
throw new Error(`process.exit(${exitCode})`);
|
|
}) as never;
|
|
|
|
if (options.cwd) {
|
|
process.chdir(options.cwd);
|
|
}
|
|
|
|
try {
|
|
const program = createProgram();
|
|
await program.parseAsync(argv);
|
|
} catch (err) {
|
|
const message = err instanceof Error ? err.message : String(err);
|
|
if (!message.startsWith('process.exit(')) {
|
|
throw err;
|
|
}
|
|
} finally {
|
|
if (options.cwd) {
|
|
process.chdir(originalCwd);
|
|
}
|
|
console.log = originalLog;
|
|
console.error = originalError;
|
|
(process as unknown as { exit: typeof process.exit }).exit = originalExit;
|
|
}
|
|
|
|
return { logs, errors, exitCode };
|
|
}
|
|
|
|
export function parseLastJson(lines: readonly string[]): unknown {
|
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
const value = lines[i]?.trim() ?? '';
|
|
if (!value) continue;
|
|
try {
|
|
return JSON.parse(value);
|
|
} catch {
|
|
// continue
|
|
}
|
|
}
|
|
throw new Error(`No JSON payload found in output:\n${lines.join('\n')}`);
|
|
}
|
|
|
|
export function assertExitCode(result: IRunMxCliResult, expected: number): void {
|
|
assert.equal(result.exitCode, expected, `Expected exit code ${expected}, got ${result.exitCode}`);
|
|
}
|