import childProcess from 'node:child_process'; import path from 'node:path'; import {fileURLToPath} from 'node:url'; const __dirname = fileURLToPath(new URL('.', import.meta.url)); const cliPath = fileURLToPath(new URL('../../entrypoints/cli.mjs', import.meta.url)); export function execCli(args, options, cb) { let dirname; let env; if (typeof options === 'function') { cb = options; dirname = path.resolve(__dirname, '..', 'fixture'); env = {}; } else { dirname = path.resolve(__dirname, '..', options.dirname ?? 'fixture'); env = options.env ?? {}; } let child; let stdout; let stderr; const processPromise = new Promise(resolve => { child = childProcess.spawn(process.execPath, [cliPath].concat(args), { // eslint-disable-line unicorn/prefer-spread cwd: dirname, env: { AVA_FORCE_CI: 'ci', // Force CI to ensure the correct reporter is selected AVA_FAKE_SCM_ROOT: '.fake-root', // This is an internal test flag. ...env, }, // Env, stdio: [null, 'pipe', 'pipe'], }); child.on('close', (code, signal) => { if (code) { const error = new Error(`test-worker exited with a non-zero exit code: ${code}`); error.code = code; error.signal = signal; resolve(error); return; } resolve(null); }); stdout = child.stdout.toArray().then(chunks => chunks.join('')); stderr = child.stderr.toArray().then(chunks => chunks.join('')); }); Promise.all([processPromise, stdout, stderr]).then(args => { cb(...args); }); return child; }