From fcf70aad8582d434658b8d3fe794e6ee463bcd2d Mon Sep 17 00:00:00 2001 From: isaacs Date: Tue, 30 Jan 2018 10:02:54 -0800 Subject: [PATCH] Add support for disabling autoend Discussion: https://twitter.com/izs/status/958397259418238976 CC: @watson --- docs/api/index.md | 18 +++++++++++++- lib/tap.js | 3 ++- lib/test.js | 12 ++++++--- tap-snapshots/test-tap.js-TAP.test.js | 34 ++++++++++++++++++++++++++ tap-snapshots/test-test.js-TAP.test.js | 7 ++++++ test/tap.js | 16 ++++++++++++ test/test.js | 9 +++++++ 7 files changed, 94 insertions(+), 5 deletions(-) diff --git a/docs/api/index.md b/docs/api/index.md index cb623f33e..6f79c4857 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -34,12 +34,18 @@ slight modifications. the main package export. 3. The test ends automatically when `process.on('exit')` fires, so there is no need to call `tap.end()` explicitly. -4. Adding a `tearDown` function triggers `autoend` behavior. +4. Adding a `tearDown` function triggers `autoend` behavior, unless + `autoend` was explicitly set to `false`. + Otherwise, the `end` would potentially never arrive, if for example `tearDown` is used to close a server or cancel some long-running process, because `process.on('exit')` would never fire of its own accord. + If you disable `autoend`, and _also_ use a `teardown()` function on + the main tap instance, you need to either set a `t.plan(n)` or + explicitly call `t.end()` at some point. + ## tap.Test The `Test` class is the main thing you'll be touching when you use @@ -229,3 +235,13 @@ Generally, you never need to worry about this directly. However, this method can also be called explicitly in cases where an error would be handled by something else (for example, a default [Promise](/promises/) `.catch(er)` method.) + +### t.autoend(value) + +If `value` is boolean `false`, then it will disable the `autoend` +behavior. If `value` is anything other than `false`, then it will +cause the test to automatically end when nothing is pending. + +Note that this is triggered by default on the root `tap` instance when +a `teardown()` function is set, unless `autoend` was explicitly +disabled. diff --git a/lib/tap.js b/lib/tap.js index 67effd235..1d9a042e4 100644 --- a/lib/tap.js +++ b/lib/tap.js @@ -84,7 +84,8 @@ class TAP extends Test { // Root test runner doesn't have the 'teardown' event, because it // isn't hooked into any parent Test as a harness. teardown (fn) { - this.autoend() + if (this.options.autoend !== false) + this.autoend(true) return Test.prototype.teardown.apply(this, arguments) } tearDown (fn) { diff --git a/lib/test.js b/lib/test.js index 9968af45b..97ac7e8af 100644 --- a/lib/test.js +++ b/lib/test.js @@ -710,9 +710,15 @@ class Test extends Base { return should } - autoend () { - this.options.autoend = true - this.maybeAutoend() + autoend (value) { + // set to false to NOT trigger autoend + if (value === false) { + this.options.autoend = false + clearTimeout(this.autoendTimer) + } else { + this.options.autoend = true + this.maybeAutoend() + } } maybeAutoend () { diff --git a/tap-snapshots/test-tap.js-TAP.test.js b/tap-snapshots/test-tap.js-TAP.test.js index 1d6060a36..22d2d4ec9 100644 --- a/tap-snapshots/test-tap.js-TAP.test.js +++ b/tap-snapshots/test-tap.js-TAP.test.js @@ -477,3 +477,37 @@ not ok 2 - timeout! exports[`test/tap.js TAP timeout sigterm many times > stderr 1`] = ` ` + +exports[`test/tap.js TAP autoend(false) with teardown > exit status 1`] = ` +{ code: 0, signal: null } +` + +exports[`test/tap.js TAP autoend(false) with teardown > stdout 1`] = ` +TAP version 13 +ok 1 - this is fine +1..1 +# {time} +tear it down + +` + +exports[`test/tap.js TAP autoend(false) with teardown > stderr 1`] = ` + +` + +exports[`test/tap.js TAP autoend=false with teardown > exit status 1`] = ` +{ code: 0, signal: null } +` + +exports[`test/tap.js TAP autoend=false with teardown > stdout 1`] = ` +TAP version 13 +ok 1 - this is fine +1..1 +# {time} +tear it down + +` + +exports[`test/tap.js TAP autoend=false with teardown > stderr 1`] = ` + +` diff --git a/tap-snapshots/test-test.js-TAP.test.js b/tap-snapshots/test-test.js-TAP.test.js index 5a5564ced..f729b9743 100644 --- a/tap-snapshots/test-test.js-TAP.test.js +++ b/tap-snapshots/test-test.js-TAP.test.js @@ -2142,6 +2142,13 @@ not ok 6 - cannot create subtest after parent test end # {time} ` +exports[`test/test.js TAP assertions and weird stuff autoend(false) > autoend(false) 1`] = ` +TAP version 13 +ok 1 - this is fine +1..1 + +` + exports[`test/test.js TAP assertions and weird stuff endAll with test children > endAll with test children 1`] = ` TAP version 13 # Subtest: this is the test that never ends diff --git a/test/tap.js b/test/tap.js index 09ba2cdf1..f404c0441 100644 --- a/test/tap.js +++ b/test/tap.js @@ -103,6 +103,22 @@ const cases = { process.kill(process.pid, 'SIGTERM') process.kill(process.pid, 'SIGTERM') }, + 'autoend(false) with teardown': t => { + t.autoend(false) + t.teardown(() => console.log('tear it down')) + setTimeout(() => { + t.pass('this is fine') + t.end() + }, 50) + }, + 'autoend=false with teardown': t => { + t.options.autoend = false + t.teardown(() => console.log('tear it down')) + setTimeout(() => { + t.pass('this is fine') + t.end() + }, 50) + }, } const main = t => { diff --git a/test/test.js b/test/test.js index 1be4f1fd7..391175c5a 100644 --- a/test/test.js +++ b/test/test.js @@ -642,6 +642,15 @@ t.test('assertions and weird stuff', t => { }, + 'autoend(false)': tt => { + tt.autoend() + tt.autoend(false) + setTimeout(() => { + tt.pass('this is fine') + tt.end() + }, 50) + }, + 'endAll with test children': tt => { tt.test('this is the test that never ends', tt => { tt.test('it goes on and on my friend', tt => {