import {stripVTControlCharacters} from 'node:util'; import test from 'ava'; import {setFixtureDirectory} from '../helpers/fixtures-directory.js'; import {foobarString} from '../helpers/input.js'; import {nestedSubprocess} from '../helpers/nested.js'; import { runErrorSubprocess, runWarningSubprocess, runEarlyErrorSubprocess, getCompletionLine, getCompletionLines, testTimestamp, getVerboseOption, stdoutNoneOption, stdoutShortOption, stdoutFullOption, stderrNoneOption, stderrShortOption, stderrFullOption, fd3NoneOption, fd3ShortOption, fd3FullOption, ipcNoneOption, ipcShortOption, ipcFullOption, } from '../helpers/verbose.js'; setFixtureDirectory(); const testPrintCompletion = async (t, verbose, isSync) => { const {stderr} = await nestedSubprocess('noop.js', [foobarString], {verbose, isSync}); t.is(getCompletionLine(stderr), `${testTimestamp} [0] √ (done in 0ms)`); }; test('Prints completion, verbose "short"', testPrintCompletion, 'short', false); test('Prints completion, verbose "full"', testPrintCompletion, 'full', false); test('Prints completion, verbose "short", fd-specific stdout', testPrintCompletion, stdoutShortOption, false); test('Prints completion, verbose "full", fd-specific stdout', testPrintCompletion, stdoutFullOption, false); test('Prints completion, verbose "short", fd-specific stderr', testPrintCompletion, stderrShortOption, false); test('Prints completion, verbose "full", fd-specific stderr', testPrintCompletion, stderrFullOption, false); test('Prints completion, verbose "short", fd-specific fd3', testPrintCompletion, fd3ShortOption, false); test('Prints completion, verbose "full", fd-specific fd3', testPrintCompletion, fd3FullOption, false); test('Prints completion, verbose "short", fd-specific ipc', testPrintCompletion, ipcShortOption, false); test('Prints completion, verbose "full", fd-specific ipc', testPrintCompletion, ipcFullOption, false); test('Prints completion, verbose "short", sync', testPrintCompletion, 'short', true); test('Prints completion, verbose "full", sync', testPrintCompletion, 'full', true); test('Prints completion, verbose "short", fd-specific stdout, sync', testPrintCompletion, stdoutShortOption, true); test('Prints completion, verbose "full", fd-specific stdout, sync', testPrintCompletion, stdoutFullOption, true); test('Prints completion, verbose "short", fd-specific stderr, sync', testPrintCompletion, stderrShortOption, true); test('Prints completion, verbose "full", fd-specific stderr, sync', testPrintCompletion, stderrFullOption, true); test('Prints completion, verbose "short", fd-specific fd3, sync', testPrintCompletion, fd3ShortOption, true); test('Prints completion, verbose "full", fd-specific fd3, sync', testPrintCompletion, fd3FullOption, true); test('Prints completion, verbose "short", fd-specific ipc, sync', testPrintCompletion, ipcShortOption, true); test('Prints completion, verbose "full", fd-specific ipc, sync', testPrintCompletion, ipcFullOption, true); const testNoPrintCompletion = async (t, verbose, isSync) => { const {stderr} = await nestedSubprocess('noop.js', [foobarString], {verbose, isSync}); t.is(stderr, ''); }; test('Does not print completion, verbose "none"', testNoPrintCompletion, 'none', false); test('Does not print completion, verbose default"', testNoPrintCompletion, undefined, false); test('Does not print completion, verbose "none", fd-specific stdout', testNoPrintCompletion, stdoutNoneOption, false); test('Does not print completion, verbose "none", fd-specific stderr', testNoPrintCompletion, stderrNoneOption, false); test('Does not print completion, verbose "none", fd-specific fd3', testNoPrintCompletion, fd3NoneOption, false); test('Does not print completion, verbose "none", fd-specific ipc', testNoPrintCompletion, ipcNoneOption, false); test('Does not print completion, verbose default", fd-specific', testNoPrintCompletion, {}, false); test('Does not print completion, verbose "none", sync', testNoPrintCompletion, 'none', true); test('Does not print completion, verbose default", sync', testNoPrintCompletion, undefined, true); test('Does not print completion, verbose "none", fd-specific stdout, sync', testNoPrintCompletion, stdoutNoneOption, true); test('Does not print completion, verbose "none", fd-specific stderr, sync', testNoPrintCompletion, stderrNoneOption, true); test('Does not print completion, verbose "none", fd-specific fd3, sync', testNoPrintCompletion, fd3NoneOption, true); test('Does not print completion, verbose "none", fd-specific ipc, sync', testNoPrintCompletion, ipcNoneOption, true); test('Does not print completion, verbose default", fd-specific, sync', testNoPrintCompletion, {}, true); const testPrintCompletionError = async (t, isSync) => { const stderr = await runErrorSubprocess(t, 'short', isSync); t.is(getCompletionLine(stderr), `${testTimestamp} [0] × (done in 0ms)`); }; test('Prints completion after errors', testPrintCompletionError, false); test('Prints completion after errors, sync', testPrintCompletionError, true); const testPrintCompletionWarning = async (t, isSync) => { const stderr = await runWarningSubprocess(t, isSync); t.is(getCompletionLine(stderr), `${testTimestamp} [0] ‼ (done in 0ms)`); }; test('Prints completion after errors, "reject" false', testPrintCompletionWarning, false); test('Prints completion after errors, "reject" false, sync', testPrintCompletionWarning, true); const testPrintCompletionEarly = async (t, isSync) => { const stderr = await runEarlyErrorSubprocess(t, isSync); t.is(getCompletionLine(stderr), undefined); }; test('Prints completion after early validation errors', testPrintCompletionEarly, false); test('Prints completion after early validation errors, sync', testPrintCompletionEarly, true); test.serial('Prints duration', async t => { const {stderr} = await nestedSubprocess('delay.js', ['1000'], {verbose: 'short'}); t.regex(stripVTControlCharacters(stderr).split('\n').at(-1), /\(done in [\d.]+s\)/); }); const testPipeDuration = async (t, parentFixture, sourceVerbose, destinationVerbose) => { const {stderr} = await nestedSubprocess('noop.js', [foobarString], { parentFixture, sourceOptions: getVerboseOption(sourceVerbose), destinationFile: 'stdin.js', destinationOptions: getVerboseOption(destinationVerbose), }); const lines = getCompletionLines(stderr); t.is(lines.includes(`${testTimestamp} [0] √ (done in 0ms)`), sourceVerbose || destinationVerbose); t.is(lines.includes(`${testTimestamp} [1] √ (done in 0ms)`), sourceVerbose && destinationVerbose); }; test('Prints both durations piped with .pipe("file")', testPipeDuration, 'nested-pipe-file.js', true, true); test('Prints both durations piped with .pipe`command`', testPipeDuration, 'nested-pipe-script.js', true, true); test('Prints both durations piped with .pipe(subprocess)', testPipeDuration, 'nested-pipe-subprocesses.js', true, true); test('Prints first duration piped with .pipe("file")', testPipeDuration, 'nested-pipe-file.js', true, false); test('Prints first duration piped with .pipe`command`', testPipeDuration, 'nested-pipe-script.js', true, false); test('Prints first duration piped with .pipe(subprocess)', testPipeDuration, 'nested-pipe-subprocesses.js', true, false); test('Prints second duration piped with .pipe("file")', testPipeDuration, 'nested-pipe-file.js', false, true); test('Prints second duration piped with .pipe`command`', testPipeDuration, 'nested-pipe-script.js', false, true); test('Prints second duration piped with .pipe(subprocess)', testPipeDuration, 'nested-pipe-subprocesses.js', false, true); test('Prints neither durations piped with .pipe("file")', testPipeDuration, 'nested-pipe-file.js', false, false); test('Prints neither durations piped with .pipe`command`', testPipeDuration, 'nested-pipe-script.js', false, false); test('Prints neither durations piped with .pipe(subprocess)', testPipeDuration, 'nested-pipe-subprocesses.js', false, false);