diff --git a/src/index.js b/src/index.js index 2a6301d..ced88a8 100644 --- a/src/index.js +++ b/src/index.js @@ -125,10 +125,12 @@ function setup(ctx, name = '') { export const suite = (name = '', state = {}) => setup(context(state), name); export const test = suite(); +let isRunning = false; export async function exec(bail) { let timer = hrtime(); let done=0, total=0, skips=0, code=0; + isRunning = true; for (let group of UVU_QUEUE) { if (total) write('\n'); @@ -145,6 +147,7 @@ export async function exec(bail) { } } + isRunning = false; write('\n Total: ' + total); write((code ? kleur.red : kleur.green)('\n Passed: ' + done)); write('\n Skipped: ' + (skips ? kleur.yellow(skips) : skips)); @@ -152,3 +155,9 @@ export async function exec(bail) { if (isNode) process.exitCode = code; } + +if (isNode) process.on('exit', () => { + if (!isRunning) return; // okay to exit + process.exitCode = process.exitCode || 1; + console.error('Exiting early before testing is finished.'); +}); diff --git a/test/exit.fails.js b/test/exit.fails.js new file mode 100644 index 0000000..8402c7e --- /dev/null +++ b/test/exit.fails.js @@ -0,0 +1,17 @@ +import { test } from 'uvu'; + +// TODO: test.fail() modifier (see #47) + +// A test that calls process.exit must fail (even if it exits with 0). +// Otherwise all tests might not run, or even all assertions within test. +test('should fail if `process.exit` encountered', async () => { + process.exit(0); +}); + +// This promise will never resolve & the process will exit early. +// This must fail, otherwise all tests/assertions might not run. +test('should fail if Promise never resolves :: GC', async () => { + await new Promise(() => {}); +}); + +test.run(); diff --git a/test/index.js b/test/index.js index 3248360..a85dbdb 100644 --- a/test/index.js +++ b/test/index.js @@ -14,6 +14,22 @@ totalist(__dirname, (rel, abs) => { let pid = spawnSync('node', HOOK.concat(abs)); let file = kleur.bold().underline(rel); + if (rel.endsWith('.fails.js')) { + try { + assert.notEqual(pid.status, 0, 'expected to fail'); + assert.equal(pid.stderr.length > 0, true, 'run w/ stderr'); + assert.equal(pid.stdout.length, 0, 'run w/o stdout'); + console.log(PASS + file); + } catch (err) { + console.error(FAIL + file + ' :: "%s"', err.message); + if (pid.stdout.length) { + console.error(LEFT + '\n' + LEFT + pid.stdout.toString().replace(/(\r?\n)/g, '$1' + LEFT)); + } + code = 1; + } + return; + } + try { assert.equal(pid.status, 0, 'run w/o error code'); assert.equal(pid.stderr.length, 0, 'run w/o stderr');