[Pkg-javascript-commits] [node-tap] 61/186: Getting closer to 100% on the test unit test

Bastien Roucariès rouca at moszumanska.debian.org
Fri Dec 1 16:40:43 UTC 2017


This is an automated email from the git hooks/post-receive script.

rouca pushed a commit to branch master
in repository node-tap.

commit 3c156af4ff7cb2583581c96fd7478546f52685ca
Author: isaacs <i at izs.me>
Date:   Mon Nov 6 16:05:36 2017 +0000

    Getting closer to 100% on the test unit test
---
 lib/point.js                      |    4 +-
 lib/test.js                       |  120 ++--
 package.json                      |    2 +-
 tap-snapshots/unit-test.js-TAP.js | 1096 ++++++++++++++++++++++++++++++++-----
 unit/point.js                     |   22 +-
 unit/test.js                      |  307 ++++++++++-
 6 files changed, 1343 insertions(+), 208 deletions(-)

diff --git a/lib/point.js b/lib/point.js
index e59a115..0e5c1b4 100644
--- a/lib/point.js
+++ b/lib/point.js
@@ -24,6 +24,7 @@ const tpMessage = (message, extra) => {
   if (message)
     message = ' - ' + message
 
+  // replace \r\n with one space, \t with 2, separately
   message = message.replace(/[\n\r]/g, ' ').replace(/\t/g, '  ')
 
   if (extra.skip) {
@@ -46,8 +47,7 @@ const tpMessage = (message, extra) => {
     message += '{\n' + extra.tapChildBuffer.trimRight() + '\n}\n'
   }
 
-  if (message)
-    message += '\n'
+  message += '\n'
 
   return message
 }
diff --git a/lib/test.js b/lib/test.js
index 8030fb6..2799ace 100644
--- a/lib/test.js
+++ b/lib/test.js
@@ -53,6 +53,9 @@ const Snapshot = require('./snapshot.js')
 const hasOwn = (obj, key) =>
   Object.prototype.hasOwnProperty.call(obj, key)
 
+const isRegExp = re =>
+  Object.prototype.toString.call(re) === '[object RegExp]'
+
 class Test extends Base {
   constructor (options) {
     options = options || {}
@@ -81,7 +84,9 @@ class Test extends Base {
     }
 
     this.noparallel = false
-    this.cb = this.domain.bind(options.cb)
+    if (options.cb)
+      this.cb = this.domain.bind(options.cb)
+
     this.occupied = false
     this.currentAssert = null
     this.count = 0
@@ -89,7 +94,6 @@ class Test extends Base {
     this.ended = false
     this.explicitEnded = false
     this.multiEndThrew = false
-    this.currentAssert = null
     this.assertAt = null
     this.assertStack = null
     this.planEnd = -1
@@ -126,7 +130,6 @@ class Test extends Base {
   }
 
   sub (Class, extra, caller) {
-    extra = extra || {}
     if (!extra.skip && this.grep.length) {
       const m = this.grep[0].test(extra.name)
       const match = this.grepInvert ? !m : m
@@ -136,13 +139,11 @@ class Test extends Base {
       }
     }
 
-    if (extra.only && !this.runOnly) {
+    if (extra.only && !this.runOnly)
       this.comment('%j has `only` set but all tests run', extra.name)
-    }
 
-    if (this.runOnly && !extra.only) {
+    if (this.runOnly && !extra.only)
       extra.skip = 'filter: only'
-    }
 
     if (extra.todo || extra.skip) {
       this.pass(extra.name, extra)
@@ -256,13 +257,7 @@ class Test extends Base {
         this.ondone = cb
     }
 
-    const ret = (() => {
-      try {
-        return this.cb(this)
-      } catch (er) {
-        this.threw(er)
-      }
-    })()
+    const ret = this.cb(this)
 
     if (ret && ret.then) {
       this.promise = ret
@@ -782,7 +777,7 @@ class Test extends Base {
     if (!extra)
       extra = {}
 
-    this.printResult(false, message || '(unnamed test)', extra || {})
+    this.printResult(false, message || '(unnamed test)', extra)
     return !!(extra.todo || extra.skip)
   }
 
@@ -1131,18 +1126,12 @@ class Test extends Base {
       return this.fail(message, extra)
     } catch (er) {
       // 'name' is a getter.
-      if (er.name) {
+      if (er.name)
         er.name = er.name + ''
-      }
 
-      if (wanted) {
-        if (Object.prototype.toString.call(wanted) === '[object RegExp]') {
-          return this.match(er.message, wanted, message, extra)
-        }
-        return this.has(er, wanted, message, extra)
-      } else {
-        return this.pass(message, extra)
-      }
+      const actual = isRegExp(wanted) ? er.message : er
+      return wanted ? this.match(actual, wanted, message, extra)
+        : this.pass(message, extra)
     }
   }
 
@@ -1209,9 +1198,6 @@ class Test extends Base {
       }
     }
 
-    if (message && typeof message === 'object')
-      extra = message, message = ''
-
     if (!extra)
       extra = {}
 
@@ -1223,56 +1209,55 @@ class Test extends Base {
         const w = {
           message: wanted.message
         }
-        if (wanted.name) {
+        if (wanted.name)
           w.name = wanted.name
-        }
 
         // intentionally copying non-local properties, since this
         // is an Error object, and those are funky.
-        for (i in wanted) {
+        for (let i in wanted) {
           w[i] = wanted[i]
         }
         wanted = w
 
         message += ': ' + (wanted.name || 'Error') + ' ' + wanted.message
-        extra = extra || {}
-        if (extra !== wanted) {
-          extra.wanted = wanted
-        }
+        extra.wanted = wanted
       }
     }
 
     if (!promise && typeof fn !== 'function') {
-      extra = extra || {}
       extra.todo = true
-      return Promise.resolve(this.pass(message, extra))
+      this.pass(message, extra)
+      return Promise.resolve(this)
     }
 
     if (!promise)
       promise = fn()
 
+    const textra = {
+      buffered: true,
+      todo: extra.todo,
+      skip: extra.skip
+    }
+
     if (!promise || typeof promise.then !== 'function')
-      return Promise.resolve(this.fail(message, extra))
+      return this.test(message, textra, t => {
+        t.fail(message, extra)
+        t.end()
+      })
 
     // have to do as a subtest, because promises are async
     extra.at = stack.at(this.currentAssert)
-    return this.test(message, { buffered: true }, t => promise.then(value => {
+    return this.test(message, textra, t => promise.then(value => {
       extra.found = value
       t.fail(message, extra)
     }, er => {
       // 'name' is a getter.
-      if (er.name) {
+      if (er.name)
         er.name = er.name + ''
-      }
 
-      if (wanted) {
-        if (Object.prototype.toString.call(wanted) === '[object RegExp]') {
-          return t.match(er.message, wanted, message, extra)
-        }
-        return t.match(er, wanted, message, extra)
-      } else {
-        return t.pass(message, extra)
-      }
+      const actual = isRegExp(wanted) ? er.message : er
+      return wanted ? t.match(actual, wanted, message, extra)
+        : t.pass(message, extra)
     }))
   }
 
@@ -1289,12 +1274,25 @@ class Test extends Base {
     if (!message)
       message = 'expect resolving Promise'
 
-    if (!promise || typeof promise.then !== 'function')
-      return Promise.resolve(this.fail(message, extra))
+    if (typeof promise === 'function')
+      promise = promise()
 
     // have to do as a subtest, because promises are async
     extra.at = stack.at(this.currentAssert)
-    return this.test(message, { buffered: true }, t =>
+
+    const textra = {
+      buffered: true,
+      todo: extra.todo,
+      skip: extra.skip
+    }
+
+    if (!promise || typeof promise.then !== 'function')
+      return this.test(message, textra, t => {
+        t.fail(message, extra)
+        t.end()
+      })
+
+    return this.test(message, textra, t =>
       promise.then(value => {
         extra.found = value
         t.pass(message, extra)
@@ -1314,12 +1312,22 @@ class Test extends Base {
     if (!message)
       message = 'expect resolving Promise'
 
-    if (!promise || typeof promise.then !== 'function')
-      return Promise.resolve(this.fail(message, extra))
-
     // have to do as a subtest, because promises are async
     extra.at = stack.at(this.currentAssert)
-    return this.test(message, { buffered: true }, t =>
+
+    const textra = {
+      buffered: true,
+      todo: extra.todo,
+      skip: extra.skip
+    }
+
+    if (!promise || typeof promise.then !== 'function')
+      return this.test(message, textra, t => {
+        t.fail(message, extra)
+        t.end()
+      })
+
+    return this.test(message, textra, t =>
       promise.then(value => {
         extra.found = value
         t.match(value, wanted, extra)
diff --git a/package.json b/package.json
index ffd3bad..3184bee 100644
--- a/package.json
+++ b/package.json
@@ -50,7 +50,7 @@
   "repository": "https://github.com/tapjs/node-tap.git",
   "scripts": {
     "regen-fixtures": "node scripts/generate-test-test.js test/test/*.js",
-    "unit": "node bin/run.js unit/*.js --100",
+    "unit": "node bin/run.js unit/*.js --100 --nyc-arg=--include=lib/*.js",
     "test": "node bin/run.js test/*.* --coverage -t3600 -sfails",
     "smoke": "node bin/run.js --node-arg=test/test.js test/test/*.js -j2",
     "posttest": "standard lib test",
diff --git a/tap-snapshots/unit-test.js-TAP.js b/tap-snapshots/unit-test.js-TAP.js
index 01d28e2..23b6385 100644
--- a/tap-snapshots/unit-test.js-TAP.js
+++ b/tap-snapshots/unit-test.js-TAP.js
@@ -86,6 +86,7 @@ TAP version 13
 exports[`unit/test.js TAP short output checks pragma no options > pragma 1`] = `
 TAP version 13
 pragma +strict
+pragma -strict
 1..0
 
 `
@@ -93,6 +94,7 @@ pragma +strict
 exports[`unit/test.js TAP short output checks pragma buffered > pragma 1`] = `
 TAP version 13
 pragma +strict
+pragma -strict
 1..0
 
 `
@@ -100,6 +102,7 @@ pragma +strict
 exports[`unit/test.js TAP short output checks pragma bailout > pragma 1`] = `
 TAP version 13
 pragma +strict
+pragma -strict
 1..0
 
 `
@@ -107,6 +110,7 @@ pragma +strict
 exports[`unit/test.js TAP short output checks pragma runOnly > pragma 1`] = `
 TAP version 13
 pragma +strict
+pragma -strict
 1..0
 
 `
@@ -124,11 +128,23 @@ not ok 1 - i will do this later # TODO
     tt.notOk(true, 'i will do this later', { todo: true })
   ...
 
-ok 2 - i will do this later # TODO
-not ok 3 - expect truthy value # SKIP
-ok 4 - i did not do this later # SKIP
-1..4
-# todo: 2
+not ok 2 - expect falsey value # TODO later
+  ---
+  at:
+    line: #
+    column: #
+    file: unit/test.js
+    function: todo
+  source: |
+    tt.notOk(true, { todo: 'later' })
+  ...
+
+ok 3 - expect falsey value
+ok 4 - i will do this later # TODO
+not ok 5 - expect truthy value # SKIP
+ok 6 - i did not do this later # SKIP
+1..6
+# todo: 3
 # skip: 2
 
 `
@@ -146,11 +162,23 @@ not ok 1 - i will do this later # TODO
     tt.notOk(true, 'i will do this later', { todo: true })
   ...
 
-ok 2 - i will do this later # TODO
-not ok 3 - expect truthy value # SKIP
-ok 4 - i did not do this later # SKIP
-1..4
-# todo: 2
+not ok 2 - expect falsey value # TODO later
+  ---
+  at:
+    line: #
+    column: #
+    file: unit/test.js
+    function: todo
+  source: |
+    tt.notOk(true, { todo: 'later' })
+  ...
+
+ok 3 - expect falsey value
+ok 4 - i will do this later # TODO
+not ok 5 - expect truthy value # SKIP
+ok 6 - i did not do this later # SKIP
+1..6
+# todo: 3
 # skip: 2
 
 `
@@ -168,11 +196,23 @@ not ok 1 - i will do this later # TODO
     tt.notOk(true, 'i will do this later', { todo: true })
   ...
 
-ok 2 - i will do this later # TODO
-not ok 3 - expect truthy value # SKIP
-ok 4 - i did not do this later # SKIP
-1..4
-# todo: 2
+not ok 2 - expect falsey value # TODO later
+  ---
+  at:
+    line: #
+    column: #
+    file: unit/test.js
+    function: todo
+  source: |
+    tt.notOk(true, { todo: 'later' })
+  ...
+
+ok 3 - expect falsey value
+ok 4 - i will do this later # TODO
+not ok 5 - expect truthy value # SKIP
+ok 6 - i did not do this later # SKIP
+1..6
+# todo: 3
 # skip: 2
 
 `
@@ -190,11 +230,23 @@ not ok 1 - i will do this later # TODO
     tt.notOk(true, 'i will do this later', { todo: true })
   ...
 
-ok 2 - i will do this later # SKIP filter: only
-not ok 3 - expect truthy value # SKIP
-ok 4 - i did not do this later # SKIP filter: only
-1..4
-# todo: 1
+not ok 2 - expect falsey value # TODO later
+  ---
+  at:
+    line: #
+    column: #
+    file: unit/test.js
+    function: todo
+  source: |
+    tt.notOk(true, { todo: 'later' })
+  ...
+
+ok 3 - expect falsey value
+ok 4 - i will do this later # SKIP filter: only
+not ok 5 - expect truthy value # SKIP
+ok 6 - i did not do this later # SKIP filter: only
+1..6
+# todo: 2
 # skip: 3
 
 `
@@ -282,16 +334,66 @@ ok 3 - run this with a comment # {time}
 exports[`unit/test.js TAP short output checks no plan fail no options > no plan fail 1`] = `
 TAP version 13
 not ok 1 - this is fine
-1..1
-# failed 1 test
+not ok 2 - (unnamed test) # TODO
+  ---
+  at:
+    line: #
+    column: #
+    file: unit/test.js
+    function: no plan fail
+  source: |
+    tt.fail({ todo: true })
+  ...
+
+not ok 3 - this is fine
+  ---
+  at:
+    line: #
+    column: #
+    file: unit/test.js
+    function: no plan fail
+  stack: |
+    {STACK}
+  source: |
+    tt.fail('this is fine')
+  ...
+
+1..3
+# failed 3 of 3 tests
+# todo: 1
 
 `
 
 exports[`unit/test.js TAP short output checks no plan fail buffered > no plan fail 1`] = `
 TAP version 13
 not ok 1 - this is fine
-1..1
-# failed 1 test
+not ok 2 - (unnamed test) # TODO
+  ---
+  at:
+    line: #
+    column: #
+    file: unit/test.js
+    function: no plan fail
+  source: |
+    tt.fail({ todo: true })
+  ...
+
+not ok 3 - this is fine
+  ---
+  at:
+    line: #
+    column: #
+    file: unit/test.js
+    function: no plan fail
+  stack: |
+    {STACK}
+  source: |
+    tt.fail('this is fine')
+  ...
+
+1..3
+# failed 3 of 3 tests
+# todo: 1
 
 `
 
@@ -299,20 +401,45 @@ exports[`unit/test.js TAP short output checks no plan fail bailout > no plan fai
 TAP version 13
 not ok 1 - this is fine
 Bail out! # this is fine
-"# this is fine"
+BAILOUT: "# this is fine"
 `
 
 exports[`unit/test.js TAP short output checks no plan fail runOnly > no plan fail 1`] = `
 TAP version 13
 not ok 1 - this is fine
-1..1
-# failed 1 test
+not ok 2 - (unnamed test) # TODO
+  ---
+  at:
+    line: #
+    column: #
+    file: unit/test.js
+    function: no plan fail
+  source: |
+    tt.fail({ todo: true })
+  ...
+
+not ok 3 - this is fine
+  ---
+  at:
+    line: #
+    column: #
+    file: unit/test.js
+    function: no plan fail
+  stack: |
+    {STACK}
+  source: |
+    tt.fail('this is fine')
+  ...
+
+1..3
+# failed 3 of 3 tests
+# todo: 1
 
 `
 
 exports[`unit/test.js TAP short output checks plan fail no options > plan fail 1`] = `
 TAP version 13
-1..1
+1..1 # expect some failure here
 not ok 1 - this is fine
 # failed 1 test
 
@@ -320,7 +447,7 @@ not ok 1 - this is fine
 
 exports[`unit/test.js TAP short output checks plan fail buffered > plan fail 1`] = `
 TAP version 13
-1..1
+1..1 # expect some failure here
 not ok 1 - this is fine
 # failed 1 test
 
@@ -328,20 +455,100 @@ not ok 1 - this is fine
 
 exports[`unit/test.js TAP short output checks plan fail bailout > plan fail 1`] = `
 TAP version 13
-1..1
+1..1 # expect some failure here
 not ok 1 - this is fine
 Bail out! # this is fine
-"# this is fine"
+BAILOUT: "# this is fine"
 `
 
 exports[`unit/test.js TAP short output checks plan fail runOnly > plan fail 1`] = `
 TAP version 13
-1..1
+1..1 # expect some failure here
 not ok 1 - this is fine
 # failed 1 test
 
 `
 
+exports[`unit/test.js TAP short output checks planned skip no options > planned skip 1`] = `
+TAP version 13
+1..0 # skip this one
+
+`
+
+exports[`unit/test.js TAP short output checks planned skip buffered > planned skip 1`] = `
+TAP version 13
+1..0 # skip this one
+
+`
+
+exports[`unit/test.js TAP short output checks planned skip bailout > planned skip 1`] = `
+TAP version 13
+1..0 # skip this one
+
+`
+
+exports[`unit/test.js TAP short output checks planned skip runOnly > planned skip 1`] = `
+TAP version 13
+1..0 # skip this one
+
+`
+
+exports[`unit/test.js TAP short output checks multi-plan throws no options > multi-plan throws 1`] = `
+TAP version 13
+1..1
+ok 1 - expected to throw
+
+`
+
+exports[`unit/test.js TAP short output checks multi-plan throws buffered > multi-plan throws 1`] = `
+TAP version 13
+1..1
+ok 1 - expected to throw
+
+`
+
+exports[`unit/test.js TAP short output checks multi-plan throws bailout > multi-plan throws 1`] = `
+TAP version 13
+1..1
+ok 1 - expected to throw
+
+`
+
+exports[`unit/test.js TAP short output checks multi-plan throws runOnly > multi-plan throws 1`] = `
+TAP version 13
+1..1
+ok 1 - expected to throw
+
+`
+
+exports[`unit/test.js TAP short output checks negative plan throws no options > negative plan throws 1`] = `
+TAP version 13
+ok 1 - expected to throw
+1..1
+
+`
+
+exports[`unit/test.js TAP short output checks negative plan throws buffered > negative plan throws 1`] = `
+TAP version 13
+ok 1 - expected to throw
+1..1
+
+`
+
+exports[`unit/test.js TAP short output checks negative plan throws bailout > negative plan throws 1`] = `
+TAP version 13
+ok 1 - expected to throw
+1..1
+
+`
+
+exports[`unit/test.js TAP short output checks negative plan throws runOnly > negative plan throws 1`] = `
+TAP version 13
+ok 1 - expected to throw
+1..1
+
+`
+
 exports[`unit/test.js TAP short output checks expect fail no options > expect fail 1`] = `
 TAP version 13
 1..1
@@ -374,7 +581,10 @@ exports[`unit/test.js TAP short output checks sub no options > sub 1`] = `
 TAP version 13
 ok 1 - named child # {time} {
     ok 1 - this is fine
-    1..1
+    ok 2 - (unnamed test)
+    ok 3 - (unnamed test) # TODO
+    1..3
+    # todo: 1
 }
 
 # Subtest: named_function
@@ -395,7 +605,10 @@ exports[`unit/test.js TAP short output checks sub buffered > sub 1`] = `
 TAP version 13
 ok 1 - named child # {time} {
     ok 1 - this is fine
-    1..1
+    ok 2 - (unnamed test)
+    ok 3 - (unnamed test) # TODO
+    1..3
+    # todo: 1
 }
 
 # Subtest: named_function
@@ -416,7 +629,10 @@ exports[`unit/test.js TAP short output checks sub bailout > sub 1`] = `
 TAP version 13
 ok 1 - named child # {time} {
     ok 1 - this is fine
-    1..1
+    ok 2 - (unnamed test)
+    ok 3 - (unnamed test) # TODO
+    1..3
+    # todo: 1
 }
 
 # Subtest: named_function
@@ -460,8 +676,14 @@ ok 1 - slow child # {time}
         type: Timeout
         function: _
         method: _onTimeout
-  stack: |
-{STACK}
+      stack: |
+        {STACK}
+      source: |
+        tt.ok(slowGoing, 'slow is going')
+      ...
+    
+    1..1
+    # failed 1 test
 not ok 2 - fast child # {time}
 
 # failed 1 of 2 tests
@@ -485,8 +707,14 @@ ok 1 - slow child # {time}
         type: Timeout
         function: _
         method: _onTimeout
-  stack: |
-{STACK}
+      stack: |
+        {STACK}
+      source: |
+        tt.ok(slowGoing, 'slow is going')
+      ...
+    
+    1..1
+    # failed 1 test
 not ok 2 - fast child # {time}
 
 # failed 1 of 2 tests
@@ -510,9 +738,14 @@ ok 1 - slow child # {time}
         type: Timeout
         function: _
         method: _onTimeout
-  stack: |
-{STACK}
-"# slow is going"
+      stack: |
+        {STACK}
+      source: |
+        tt.ok(slowGoing, 'slow is going')
+      ...
+    
+    Bail out! # slow is going
+BAILOUT: "# slow is going"
 `
 
 exports[`unit/test.js TAP short output checks parallel sub runOnly > parallel sub 1`] = `
@@ -529,7 +762,7 @@ TAP version 13
 # Subtest: (unnamed test)
     ok 1 - this is fine
     Bail out! not fine
-"not fine"
+BAILOUT: "not fine"
 `
 
 exports[`unit/test.js TAP short output checks reasoned bailout buffered > reasoned bailout 1`] = `
@@ -537,7 +770,7 @@ TAP version 13
 # Subtest: (unnamed test)
     ok 1 - this is fine
     Bail out! not fine
-"not fine"
+BAILOUT: "not fine"
 `
 
 exports[`unit/test.js TAP short output checks reasoned bailout bailout > reasoned bailout 1`] = `
@@ -545,7 +778,7 @@ TAP version 13
 # Subtest: (unnamed test)
     ok 1 - this is fine
     Bail out! not fine
-"not fine"
+BAILOUT: "not fine"
 `
 
 exports[`unit/test.js TAP short output checks reasoned bailout runOnly > reasoned bailout 1`] = `
@@ -594,7 +827,7 @@ TAP version 13
     ok 1 - this is fine
     1..1
 Bail out! not fine
-"not fine"
+BAILOUT: "not fine"
 `
 
 exports[`unit/test.js TAP short output checks bailout after end buffered > bailout after end 1`] = `
@@ -603,7 +836,7 @@ TAP version 13
     ok 1 - this is fine
     1..1
 Bail out! not fine
-"not fine"
+BAILOUT: "not fine"
 `
 
 exports[`unit/test.js TAP short output checks bailout after end bailout > bailout after end 1`] = `
@@ -612,7 +845,7 @@ TAP version 13
     ok 1 - this is fine
     1..1
 Bail out! not fine
-"not fine"
+BAILOUT: "not fine"
 `
 
 exports[`unit/test.js TAP short output checks bailout after end runOnly > bailout after end 1`] = `
@@ -623,6 +856,93 @@ ok 1 - (unnamed test) # SKIP filter: only
 
 `
 
+exports[`unit/test.js TAP short output checks diags no options > diags 1`] = `
+TAP version 13
+ok 1 - has diags
+  ---
+  foo: 1
+  ...
+
+not ok 2 - fails without diag
+ok 3 - has diags
+  ---
+  foo: 1
+  ...
+
+not ok 4 - fails without diag
+ok 5 - has diags
+  ---
+  foo: 1
+  ...
+
+not ok 6 - fails without diag
+1..6
+# failed 3 of 6 tests
+
+`
+
+exports[`unit/test.js TAP short output checks diags buffered > diags 1`] = `
+TAP version 13
+ok 1 - has diags
+  ---
+  foo: 1
+  ...
+
+not ok 2 - fails without diag
+ok 3 - has diags
+  ---
+  foo: 1
+  ...
+
+not ok 4 - fails without diag
+ok 5 - has diags
+  ---
+  foo: 1
+  ...
+
+not ok 6 - fails without diag
+1..6
+# failed 3 of 6 tests
+
+`
+
+exports[`unit/test.js TAP short output checks diags bailout > diags 1`] = `
+TAP version 13
+ok 1 - has diags
+  ---
+  foo: 1
+  ...
+
+not ok 2 - fails without diag
+Bail out! # fails without diag
+BAILOUT: "# fails without diag"
+`
+
+exports[`unit/test.js TAP short output checks diags runOnly > diags 1`] = `
+TAP version 13
+ok 1 - has diags
+  ---
+  foo: 1
+  ...
+
+not ok 2 - fails without diag
+ok 3 - has diags
+  ---
+  foo: 1
+  ...
+
+not ok 4 - fails without diag
+ok 5 - has diags
+  ---
+  foo: 1
+  ...
+
+not ok 6 - fails without diag
+1..6
+# failed 3 of 6 tests
+
+`
+
 exports[`unit/test.js TAP short output checks gentle thrower no options > gentle thrower 1`] = `
 TAP version 13
 not ok 1 - ok
@@ -633,7 +953,7 @@ not ok 1 - ok
     file: unit/test.js
     function: Object.gentle thrower
   stack: |
-{STACK}
+    {STACK}
   source: |
     'gentle thrower': tt => tt.threw(new Error('ok')),
   ...
@@ -653,7 +973,7 @@ not ok 1 - ok
     file: unit/test.js
     function: Object.gentle thrower
   stack: |
-{STACK}
+    {STACK}
   source: |
     'gentle thrower': tt => tt.threw(new Error('ok')),
   ...
@@ -673,13 +993,13 @@ not ok 1 - ok
     file: unit/test.js
     function: Object.gentle thrower
   stack: |
-{STACK}
+    {STACK}
   source: |
     'gentle thrower': tt => tt.threw(new Error('ok')),
   ...
 
 Bail out! # ok
-"# ok"
+BAILOUT: "# ok"
 `
 
 exports[`unit/test.js TAP short output checks gentle thrower runOnly > gentle thrower 1`] = `
@@ -693,7 +1013,7 @@ not ok 1 - ok
     file: unit/test.js
     function: Object.gentle thrower
   stack: |
-{STACK}
+    {STACK}
   source: |
     'gentle thrower': tt => tt.threw(new Error('ok')),
   ...
@@ -703,46 +1023,163 @@ not ok 1 - ok
 
 `
 
-exports[`unit/test.js TAP assertion checks error > error 1`] = `
+exports[`unit/test.js TAP short output checks child thrower no options > child thrower 1`] = `
 TAP version 13
-ok 1 - this is not an error
-not ok 2 - this error is poop
-  ---
-  found:
-    name: Error
-  stack: |
-{STACK}
-  at:
-    line: #
-    column: #
-    file: unit/test.js
-    function: error
-  stack: |
-{STACK}
-  source: |
-    tt.error(new Error('poop'), 'this error is poop')
-  ...
+# Subtest: child test
+    not ok 1 - ok
+      ---
+      stack: |
+        {STACK}
+      at:
+        line: #
+        column: #
+        file: unit/test.js
+        function: Test.tt.test.tt
+      test: child test
+      source: |
+        tt.threw(new Error('ok'))).then(tt.end)
+      ...
+    
+    1..1
+    # failed 1 test
+not ok 1 - child test # {time}
 
-not ok 3 - this error is "poop"
-  ---
-  found: poop
-  at:
-    line: #
-    column: #
-    file: unit/test.js
-    function: error
-  stack: |
-{STACK}
+1..1
+# failed 1 test
+
+`
+
+exports[`unit/test.js TAP short output checks child thrower buffered > child thrower 1`] = `
+TAP version 13
+# Subtest: child test
+    not ok 1 - ok
+      ---
+      stack: |
+        {STACK}
+      at:
+        line: #
+        column: #
+        file: unit/test.js
+        function: Test.tt.test.tt
+      test: child test
+      source: |
+        tt.threw(new Error('ok'))).then(tt.end)
+      ...
+    
+    1..1
+    # failed 1 test
+not ok 1 - child test # {time}
+
+1..1
+# failed 1 test
+
+`
+
+exports[`unit/test.js TAP short output checks child thrower bailout > child thrower 1`] = `
+TAP version 13
+# Subtest: child test
+    not ok 1 - ok
+      ---
+      stack: |
+        {STACK}
+      at:
+        line: #
+        column: #
+        file: unit/test.js
+        function: Test.tt.test.tt
+      test: child test
+      source: |
+        tt.threw(new Error('ok'))).then(tt.end)
+      ...
+    
+    Bail out! # ok
+BAILOUT: "# ok"
+`
+
+exports[`unit/test.js TAP short output checks child thrower runOnly > child thrower 1`] = `
+TAP version 13
+ok 1 - child test # SKIP filter: only
+1..1
+# skip: 1
+
+`
+
+exports[`unit/test.js TAP assertions and weird stuff error > error 1`] = `
+TAP version 13
+ok 1 - this is not an error
+not ok 2 - this error is poop
+  ---
+  found:
+    name: Error
+    stack: |
+      {STACK}
+    message: 'fail: poop'
+  at:
+    line: #
+    column: #
+    file: unit/test.js
+    function: error
+  stack: |
+    {STACK}
   source: |
-    tt.error('poop', 'this error is "poop"')
+    tt.error(new Error('fail: poop'), 'this error is poop')
   ...
 
-1..3
-# failed 2 of 3 tests
+not ok 3 - fail: poop
+  ---
+  found:
+    name: Error
+    stack: |
+      {STACK}
+    message: 'fail: poop'
+  at:
+    line: #
+    column: #
+    file: unit/test.js
+    function: error
+  stack: |
+    {STACK}
+  source: |
+    tt.error(new Error('fail: poop'))
+  ...
+
+not ok 4 - this error is "poop"
+  ---
+  found: 'fail: poop'
+  at:
+    line: #
+    column: #
+    file: unit/test.js
+    function: error
+  stack: |
+    {STACK}
+  source: |
+    tt.error('fail: poop', 'this error is "poop"')
+  ...
+
+not ok 5 - non-Error error encountered
+  ---
+  found: 'fail: poop'
+  at:
+    line: #
+    column: #
+    file: unit/test.js
+    function: error
+  stack: |
+    {STACK}
+  source: |
+    tt.error('fail: poop')
+  ...
+
+ok 6 - should not error # TODO
+ok 7 - should not error
+1..7
+# failed 4 of 7 tests
+# todo: 1
 
 `
 
-exports[`unit/test.js TAP assertion checks equal > equal 1`] = `
+exports[`unit/test.js TAP assertions and weird stuff equal > equal 1`] = `
 TAP version 13
 not ok 1 - should be equal
   ---
@@ -755,7 +1192,7 @@ not ok 1 - should be equal
     file: unit/test.js
     function: equal
   stack: |
-{STACK}
+    {STACK}
   source: |
     tt.equal(1, 2)
   ...
@@ -776,7 +1213,7 @@ not ok 4 - should be equal
     file: unit/test.js
     function: equal
   stack: |
-{STACK}
+    {STACK}
   source: |
     tt.equal({foo: 1}, {foo: 1})
   ...
@@ -787,7 +1224,7 @@ not ok 4 - should be equal
 
 `
 
-exports[`unit/test.js TAP assertion checks not > not 1`] = `
+exports[`unit/test.js TAP assertions and weird stuff not > not 1`] = `
 TAP version 13
 ok 1 - should not be equal
 ok 2 - should not be equal # SKIP
@@ -802,7 +1239,7 @@ not ok 3 - one is not one
     file: unit/test.js
     function: not
   stack: |
-{STACK}
+    {STACK}
   source: |
     tt.not(1, 1, 'one is not one')
   ...
@@ -814,7 +1251,7 @@ ok 4 - should not be equal
 
 `
 
-exports[`unit/test.js TAP assertion checks same > same 1`] = `
+exports[`unit/test.js TAP assertions and weird stuff same > same 1`] = `
 TAP version 13
 ok 1 - should be equivalent
 ok 2 - should be equivalent
@@ -836,7 +1273,7 @@ not ok 7 - this one fails
     file: unit/test.js
     function: same
   stack: |
-{STACK}
+    {STACK}
   source: |
     tt.notSame({ foo: { bar: 2 } }, { foo: { bar: '2' } },
   ...
@@ -858,7 +1295,7 @@ not ok 9 - should be equivalent strictly
     file: unit/test.js
     function: same
   stack: |
-{STACK}
+    {STACK}
   source: |
     tt.strictSame([1, 2, 3], ['1', '2', '3'])
   ...
@@ -882,7 +1319,7 @@ not ok 15 - this one fails
     file: unit/test.js
     function: same
   stack: |
-{STACK}
+    {STACK}
   source: |
     tt.notStrictSame({ foo: { bar: 2 } }, { foo: { bar: 2 } },
   ...
@@ -893,7 +1330,7 @@ not ok 15 - this one fails
 
 `
 
-exports[`unit/test.js TAP assertion checks match > match 1`] = `
+exports[`unit/test.js TAP assertions and weird stuff match > match 1`] = `
 TAP version 13
 ok 1 - should match pattern provided
 not ok 2 - should match pattern provided
@@ -910,7 +1347,7 @@ not ok 2 - should match pattern provided
     file: unit/test.js
     function: match
   stack: |
-{STACK}
+    {STACK}
   source: |
     tt.match({ a: 'b', c: /asdf/ }, { a: 'asdf', c: 1 })
   ...
@@ -947,7 +1384,7 @@ not ok 5 - should not match pattern provided
     file: unit/test.js
     function: match
   stack: |
-{STACK}
+    {STACK}
   source: |
     tt.notMatch({ a: 'b', c: /asdf/ }, { a: String, c: RegExp })
   ...
@@ -967,7 +1404,7 @@ not ok 7 - a message
     file: unit/test.js
     function: match
   stack: |
-{STACK}
+    {STACK}
   source: |
     tt.notMatch({ a: 'b', c: /asdf/ }, { a: String, c: RegExp },
   ...
@@ -979,7 +1416,7 @@ ok 8 - should not match pattern provided # TODO
 
 `
 
-exports[`unit/test.js TAP assertion checks type > type 1`] = `
+exports[`unit/test.js TAP assertions and weird stuff type > type 1`] = `
 TAP version 13
 not ok 1 - this fails
   ---
@@ -992,7 +1429,7 @@ not ok 1 - this fails
     file: unit/test.js
     function: type
   stack: |
-{STACK}
+    {STACK}
   source: |
     tt.type(null, 'object', 'this fails')
   ...
@@ -1010,7 +1447,7 @@ not ok 5 - fails, anonymously
     file: unit/test.js
     function: type
   stack: |
-{STACK}
+    {STACK}
   source: |
     tt.type({}, function () {}, 'fails, anonymously')
   ...
@@ -1029,7 +1466,7 @@ not ok 9 - fail: arrows are not objects
     file: unit/test.js
     function: type
   stack: |
-{STACK}
+    {STACK}
   source: |
     tt.type(() => {}, Object, 'fail: arrows are not objects')
   ...
@@ -1042,56 +1479,461 @@ ok 12 - type is EventEmitter
 
 `
 
-exports[`unit/test.js TAP assertion checks throws > throws 1`] = `
+exports[`unit/test.js TAP assertions and weird stuff throws > throws 1`] = `
 TAP version 13
 ok 1 - expected to throw
 ok 2 - expected to throw
 ok 3 - expected to throw: TypeError x
 ok 4 - expected to throw
-not ok 5 - expected to throw: Error x
+ok 5 - expected to throw: Error x
+ok 6 - expected to throw
+ok 7 - expected to throw
+ok 8 - expected to throw
+ok 9 - expected to throw: Error noent
+not ok 10 - fail: does not throw actually
   ---
-  wanted:
-    message: x
-    name: ''
-  found:
-  stack: |
-{STACK}
-  pattern:
-    message: x
-    name: ''
   at:
     line: #
     column: #
     file: unit/test.js
     function: throws
   stack: |
-{STACK}
+    {STACK}
   source: |
-    tt.throws(() => { throw new Error('x') }, nameless)
+    tt.throws(() => 'doesnt tho', 'fail: does not throw actually')
   ...
 
-ok 6 - expected to throw
-ok 7 - expected to throw
-ok 8 - expected to throw
-ok 9 - expected to throw # SKIP
-ok 10 - expected to throw
-not ok 11 - extra functions are no-ops for bw comp
+ok 11 - expected to throw # SKIP
+ok 12 - expected to throw
+ok 13 - extra functions are no-ops for bw comp
+ok 14 - todo # TODO
+1..14
+# failed 1 of 14 tests
+# todo: 1
+# skip: 1
+
+`
+
+exports[`unit/test.js TAP assertions and weird stuff doesNotThrow > doesNotThrow 1`] = `
+TAP version 13
+ok 1 - this is fine
+ok 2 - expected to not throw # TODO
+ok 3 - reverse args
+ok 4 - this is todo # TODO
+not ok 5 - fail
   ---
   at:
     line: #
     column: #
     file: unit/test.js
-    function: throws
+    function: tt.doesNotThrow
   stack: |
-{STACK}
+    {STACK}
+  message: ouch
   source: |
-    tt.throws(() => {}, () => {}, () => {}, () => {},
+    throw new Error('ouch')
   ...
 
-ok 12 - todo # TODO
-1..12
-# failed 2 of 12 tests
+1..5
+# failed 1 of 5 tests
+# todo: 2
+
+`
+
+exports[`unit/test.js TAP assertions and weird stuff rejects > rejects 1`] = `
+TAP version 13
+ok 1 - promise # {time} {
+    ok 1 - promise
+    1..1
+}
+
+ok 2 - fn returns promise # {time} {
+    ok 1 - fn returns promise
+    1..1
+}
+
+ok 3 - expect rejected Promise # {time} {
+    ok 1 - expect rejected Promise
+    1..1
+}
+
+ok 4 - expect rejected Promise # {time} {
+    ok 1 - expect rejected Promise
+    1..1
+}
+
+ok 5 - todo because no fn/promise # TODO
+# next 2 also todo, no message
+ok 6 - expect rejected Promise # TODO
+ok 7 - expect rejected Promise # TODO
+ok 8 - throws expected error: Error expected # {time} {
+    ok 1 - throws expected error: Error expected
+    1..1
+}
+
+ok 9 - throws expected error type # {time} {
+    ok 1 - throws expected error type
+    1..1
+}
+
+ok 10 - extra functions are no-ops # {time} {
+    ok 1 - extra functions are no-ops
+    1..1
+}
+
+ok 11 - extra args are no-ops # {time} {
+    ok 1 - extra args are no-ops
+    1..1
+}
+
+ok 12 - expect rejected Promise: Error noent # {time} {
+    ok 1 - expect rejected Promise: Error noent
+    1..1
+}
+
+ok 13 - expect rejected Promise: Error x # {time} {
+    ok 1 - expect rejected Promise: Error x
+    1..1
+}
+
+ok 14 - expect rejected Promise # {time} {
+    ok 1 - expect rejected Promise
+    1..1
+}
+
+ok 15 - expect rejected Promise # {time} {
+    ok 1 - expect rejected Promise
+    1..1
+}
+
+ok 16 - expect rejected Promise # {time} {
+    ok 1 - expect rejected Promise
+    1..1
+}
+
+not ok 17 - fail: no promise # {time} {
+    not ok 1 - fail: no promise
+      ---
+      stack: |
+        {STACK}
+      ...
+    
+    1..1
+    # failed 1 test
+}
+
+not ok 18 - fail: no promise # {time} {
+    not ok 1 - fail: no promise
+      ---
+      stack: |
+        {STACK}
+      ...
+    
+    1..1
+    # failed 1 test
+}
+
+not ok 19 - fail: passing promise # {time} {
+    not ok 1 - fail: passing promise
+      ---
+      at:
+        line: #
+        column: #
+        file: unit/test.js
+        function: rejects
+      found: 420
+      source: |
+        tt.rejects(new Promise(r => r(420)), 'fail: passing promise')
+      ...
+    
+    1..1
+    # failed 1 test
+}
+
+1..19
+# failed 3 of 19 tests
+# todo: 3
+
+`
+
+exports[`unit/test.js TAP assertions and weird stuff resolves > resolves 1`] = `
+TAP version 13
+ok 1 - expect resolving Promise # {time} {
+    ok 1 - expect resolving Promise
+    1..1
+}
+
+ok 2 - expect resolving Promise # TODO
+ok 3 - passing promise # {time} {
+    ok 1 - passing promise
+    1..1
+}
+
+ok 4 - passing promise fn # {time} {
+    ok 1 - passing promise fn
+    1..1
+}
+
+not ok 5 - fail: no promise # {time} {
+    not ok 1 - fail: no promise
+      ---
+      at: {}
+      ...
+    
+    1..1
+    # failed 1 test
+}
+
+1..5
+# failed 1 of 5 tests
 # todo: 1
-# skip: 1
+
+`
+
+exports[`unit/test.js TAP assertions and weird stuff resolveMatch > resolveMatch 1`] = `
+TAP version 13
+ok 1 - expect resolving Promise # {time} {
+    ok 1 - should match pattern provided
+    1..1
+}
+
+ok 2 - expect resolving Promise # TODO
+ok 3 - promise # {time} {
+    ok 1 - should match pattern provided
+    1..1
+}
+
+not ok 4 - promise fn # {time} {
+    not ok 1 - promise fn
+      ---
+      at: {}
+      ...
+    
+    1..1
+    # failed 1 test
+}
+
+not ok 5 - fail: no promise # {time} {
+    not ok 1 - fail: no promise
+      ---
+      at: {}
+      ...
+    
+    1..1
+    # failed 1 test
+}
+
+1..5
+# failed 2 of 5 tests
+# todo: 1
+
+`
+
+exports[`unit/test.js TAP assertions and weird stuff test after end fails > test after end fails 1`] = `
+TAP version 13
+1..0
+STDERR:
+Error: test after end() was called
+    {STACK}
+{ test: '', plan: 0 }
+
+`
+
+exports[`unit/test.js TAP assertions and weird stuff plan excess > plan excess 1`] = `
+TAP version 13
+1..1
+ok 1 - fine
+STDERR:
+Error: test count exceeds plan
+    {STACK}
+{ test: '', plan: 1 }
+
+`
+
+exports[`unit/test.js TAP assertions and weird stuff plan excess, ignored when failing > plan excess, ignored when failing 1`] = `
+TAP version 13
+1..1
+not ok 1 - expected fail
+# failed 1 test
+
+`
+
+exports[`unit/test.js TAP assertions and weird stuff using the assertAt field > using the assertAt field 1`] = `
+TAP version 13
+1..1
+not ok 1 - expect fail
+  ---
+  at:
+    line: #
+    column: #
+    file: unit/test.js
+    type: global
+    function: baz
+  source: |
+    const baz = () => { tt.assertAt = stack.at(); bar() }
+  ...
+
+# failed 1 test
+
+`
+
+exports[`unit/test.js TAP assertions and weird stuff using the assertStack field > using the assertStack field 1`] = `
+TAP version 13
+1..1
+not ok 1 - expect fail
+  ---
+  stack: |
+    {STACK}
+  at:
+    line: #
+    column: #
+    file: unit/test.js
+    function: baz
+  source: |
+    const baz = () => { tt.assertStack = stack.captureString(80); bar() }
+  ...
+
+# failed 1 test
+
+`
+
+exports[`unit/test.js TAP assertions and weird stuff printResult > printResult 1`] = `
+TAP version 13
+ok 1 - this is fine
+1..1
+
+`
+
+exports[`unit/test.js TAP assertions and weird stuff printResult after plan end > printResult after plan end 1`] = `
+TAP version 13
+1..0
+STDERR:
+Error: test after end() was called
+    {STACK}
+{ test: '', plan: 0 }
+
+`
+
+exports[`unit/test.js TAP assertions and weird stuff plan, child test, explicit end > plan, child test, explicit end 1`] = `
+TAP version 13
+1..1
+# Subtest: (unnamed test)
+    1..0
+ok 1 - (unnamed test) # {time}
+
+
+`
+
+exports[`unit/test.js TAP assertions and weird stuff end multiple times > end multiple times 1`] = `
+TAP version 13
+1..1
+ok 1 - yes
+STDERR:
+Error: test end() method called more than once
+    {STACK}
+{ test: '' }
+
+`
+
+exports[`unit/test.js TAP assertions and weird stuff error event with domainEmitter re-throws > error event with domainEmitter re-throws 1`] = `
+TAP version 13
+ok 1 - the better to this.threw you with
+1..1
+
+`
+
+exports[`unit/test.js TAP assertions and weird stuff thrower after end > thrower after end 1`] = `
+TAP version 13
+# Subtest: child
+    1..1
+    ok 1 - this is fine
+ok 1 - child # {time}
+
+not ok 2 - catch it in the parent
+  ---
+  stack: |
+    {STACK}
+  at:
+    line: #
+    column: #
+    file: unit/test.js
+    function: Test.tt.test.tt
+  test: child
+  source: |
+    tt.threw(new Error('catch it in the parent'))
+  ...
+
+1..2
+# failed 1 of 2 tests
+
+`
+
+exports[`unit/test.js TAP assertions and weird stuff child breaks a promise > child breaks a promise 1`] = `
+TAP version 13
+# Subtest: child
+    not ok 1 - poop
+      ---
+      stack: |
+        {STACK}
+      at:
+        line: #
+        column: #
+        file: unit/test.js
+        function: Promise
+      test: child
+      source: |
+        tt.test('child', () => new Promise((_, r) => r(new Error('poop'))))
+      ...
+    
+    1..1
+    # failed 1 test
+not ok 1 - child # {time}
+
+1..1
+# failed 1 test
+
+`
+
+exports[`unit/test.js TAP assertions and weird stuff child teardown throw > child teardown throw 1`] = `
+TAP version 13
+# Subtest: child
+    1..0
+ok 1 - child # {time}
+
+not ok 2 - fail
+  ---
+  stack: |
+    {STACK}
+  at:
+    line: #
+    column: #
+    file: unit/test.js
+    function: Test.tt.teardown
+  test: child
+  source: |
+    tt.teardown(() => { throw new Error('fail') })
+  ...
+
+1..2
+# failed 1 of 2 tests
+
+`
+
+exports[` TAP assertions and weird stuff fullname without main > fullname without main 1`] = `
+TAP version 13
+# Subtest: child
+    ok 1 - child
+    1..1
+ok 1 - child # {time}
+
+ok 2
+1..2
+
+`
+
+exports[` TAP assertions and weird stuff comment after end > comment after end 1`] = `
+TAP version 13
+1..0
+# this is fine
 
 `
diff --git a/unit/point.js b/unit/point.js
index 6ec6906..205b0ce 100644
--- a/unit/point.js
+++ b/unit/point.js
@@ -11,39 +11,39 @@ t.throws(_ => new TestPoint(true, Math),
 const cases = [
   [true, 'this is fine', null, {
     ok: 'ok ',
-    message: ' - this is fine'
+    message: ' - this is fine\n'
   }],
   [false, 'this is fine', null, {
     ok: 'not ok ',
-    message: ' - this is fine'
+    message: ' - this is fine\n'
   }],
   [true, '     ', null, {
     ok: 'ok ',
-    message: ''
+    message: '\n'
   }],
   [false, '\n\r\t\n', null, {
     ok: 'not ok ',
-    message: ''
+    message: '\n'
   }],
   [true, 'this is fine        ', { skip: true }, {
     ok: 'ok ',
-    message: ' - this is fine # SKIP'
+    message: ' - this is fine # SKIP\n'
   }],
   [true, 'this is fine', { skip: 'nope' }, {
     ok: 'ok ',
-    message: ' - this is fine # SKIP nope'
+    message: ' - this is fine # SKIP nope\n'
   }],
   [true, 'this is fine', { todo: true }, {
     ok: 'ok ',
-    message: ' - this is fine # TODO'
+    message: ' - this is fine # TODO\n'
   }],
   [true, 'this is fine', { todo: 'later' }, {
     ok: 'ok ',
-    message: ' - this is fine # TODO later'
+    message: ' - this is fine # TODO later\n'
   }],
-  [true, 'time waits for no one', { time: '12345ms' }, {
+  [true, 'time waits for no one', { time: 12345 }, {
     ok: 'ok ',
-    message: 'time waits for no one # time=12345ms'
+    message: 'time waits for no one # time=12345ms\n'
   }],
   [true, 'fine', { foo: 'bar', diagnostic: true }, {
     ok: 'ok ',
@@ -55,7 +55,7 @@ const cases = [
   }],
   [false, 'x\ny\r\nz', {}, {
     ok: 'not ok ',
-    message: 'x y  z'
+    message: 'x y  z\n'
   }],
   [true, '', {
     tapChildBuffer: 'child output',
diff --git a/unit/test.js b/unit/test.js
index b7097f3..a8af382 100644
--- a/unit/test.js
+++ b/unit/test.js
@@ -1,11 +1,18 @@
 const t = require('../')
 const Test = t.Test
+const util = require('util')
 const assert = require('assert')
+const EE = require('events').EventEmitter
+
+// set this forcibly so it doesn't interfere with other tests.
+process.env.TAP_DIAG === ''
 
 const clean = out => out
   .replace(/ # time=[0-9\.]+m?s( \{.*)?\n/g, ' # {time}$1\n')
-  .replace(/\n( {2})+stack: \|-?\n((\1  .*).*\n)+/gm,
-    '\n$1stack: |\n{STACK}\n')
+  .replace(/\n(( {2})+)stack: \|-?\n((\1  .*).*\n)+/gm,
+    '\n$1stack: |\n$1  {STACK}\n')
+  .replace(/\n([a-zA-Z]*Error): (.*)\n((    at .*\n)*)+/gm,
+    '\n$1: $2\n    {STACK}\n')
   .replace(/:[0-9]+:[0-9]+(\)?\n)/g, '#:#$1')
   .replace(/(line|column): [0-9]+/g, '$1: #')
   .split(process.cwd()).join('{CWD}')
@@ -34,11 +41,14 @@ t.test('short output checks', t => {
 
     'pragma': tt => {
       tt.pragma({ strict: true })
+      tt.pragma({ strict: false })
       tt.end()
     },
 
     'todo': tt => {
       tt.notOk(true, 'i will do this later', { todo: true })
+      tt.notOk(true, { todo: 'later' })
+      tt.notOk(false)
       tt.todo('i will do this later', tt => {
         throw 'oh no'
       })
@@ -60,14 +70,30 @@ t.test('short output checks', t => {
 
     'no plan fail': tt => {
       tt.fail('this is fine', { diagnostic: false })
+      tt.fail({ todo: true })
+      tt.fail('this is fine')
       tt.end()
     },
 
     'plan fail': tt => {
-      tt.plan(1)
+      tt.plan(1, 'expect some failure here')
       tt.fail('this is fine', { diagnostic: false })
     },
 
+    'planned skip': tt => {
+      tt.plan(0, 'skip this one')
+    },
+
+    'multi-plan throws': tt => {
+      tt.plan(1)
+      tt.throws(() => tt.plan(1))
+    },
+
+    'negative plan throws': tt => {
+      tt.throws(() => tt.plan(-1))
+      tt.end()
+    },
+
     'expect fail': tt => {
       tt.plan(1)
       tt.fail('this is fine', { expectFail: true })
@@ -76,6 +102,8 @@ t.test('short output checks', t => {
     'sub': tt => {
       tt.test('named child', { buffered: true }, tt => {
         tt.pass('this is fine')
+        tt.pass()
+        tt.pass({ todo: true })
         tt.end()
       })
       tt.test(function named_function (tt) {
@@ -128,9 +156,24 @@ t.test('short output checks', t => {
       tt.end()
     },
 
+    'diags': tt => {
+      tt.pass('has diags', { diagnostic: true, foo: 1 })
+      tt.fail('fails without diag', { diagnostic: false, foo: 1 })
+      process.env.TAP_DIAG = '1'
+      tt.pass('has diags', { foo: 1 })
+      tt.fail('fails without diag', { diagnostic: false, foo: 1 })
+      process.env.TAP_DIAG = '0'
+      tt.pass('has diags', { diagnostic: true, foo: 1 })
+      tt.fail('fails without diag', { foo: 1 })
+      process.env.TAP_DIAG = ''
+      tt.end()
+    },
+
     // _actually_ throwing is only handled by root TAP test
     // using a Domain to catch beyond async stack drops
     'gentle thrower': tt => tt.threw(new Error('ok')),
+    'child thrower': tt => tt.test('child test', tt =>
+      tt.threw(new Error('ok'))).then(tt.end)
   }
 
   const keys = Object.keys(cases)
@@ -153,7 +196,7 @@ t.test('short output checks', t => {
             out = tt.output
 
           if (reason)
-            out = out.trim() + '\n' + JSON.stringify(reason)
+            out = out.trim() + '\nBAILOUT: ' + JSON.stringify(reason)
 
           t.matchSnapshot(clean(out), i)
           resolve()
@@ -176,7 +219,7 @@ t.test('short output checks', t => {
   }
 })
 
-t.test('assertion checks', t => {
+t.test('assertions and weird stuff', t => {
   const env = process.env.TAP_BUFFER
   process.env.TAP_BUFFER = '0'
   t.teardown(_ => process.env.TAP_BUFFER = env)
@@ -184,8 +227,12 @@ t.test('assertion checks', t => {
   const cases = {
     'error': tt => {
       tt.error(null, 'this is not an error')
-      tt.error(new Error('poop'), 'this error is poop')
-      tt.error('poop', 'this error is "poop"')
+      tt.error(new Error('fail: poop'), 'this error is poop')
+      tt.error(new Error('fail: poop'))
+      tt.error('fail: poop', 'this error is "poop"')
+      tt.error('fail: poop')
+      tt.error(null, { todo: true })
+      tt.error(null)
       tt.end()
     },
 
@@ -274,21 +321,237 @@ t.test('assertion checks', t => {
                 { message: 'x' })
 
       const nameless = new Error('x')
-      nameless.name = ''
+      Object.defineProperty(nameless, 'name', {
+        value: undefined
+      })
+      nameless.stack = /^.*$/
       tt.throws(() => { throw new Error('x') }, nameless)
-
       tt.throws(() => { throw nameless }, { message: 'x' })
       tt.throws(() => { throw nameless }, /^.$/)
       tt.throws(() => { throw nameless })
 
+      const prop = new Error('noent')
+      prop.code= 'ENOENT'
+      tt.throws(() => {
+        const er = new Error('noent')
+        er.code = 'ENOENT'
+        er.path = __filename
+        throw er
+      }, prop)
+
+      tt.throws(() => 'doesnt tho', 'fail: does not throw actually')
+
       tt.throws(() => { throw new Error('x') }, {}, { skip: true })
       tt.throws(() => { throw new Error('x') }, {},
                 {}, {}, 1)
-      tt.throws(() => {}, () => {}, () => {}, () => {},
+      tt.throws(() => { throw new Error('x') },
+                () => {}, () => {}, () => {},
                 'extra functions are no-ops for bw comp')
       tt.throws('todo')
       tt.end()
     },
+
+    doesNotThrow: tt => {
+      tt.doesNotThrow(() => {}, 'this is fine')
+      tt.doesNotThrow(() => {}, { todo: true })
+      tt.doesNotThrow('reverse args', () => {})
+      tt.doesNotThrow('this is todo')
+      tt.doesNotThrow('fail', () => {
+        throw new Error('ouch')
+      })
+      tt.end()
+    },
+
+    rejects: tt => {
+      tt.rejects('promise', new Promise((_, reject) => {
+        reject(new Error('expected'))
+      }))
+      tt.rejects(() => new Promise((_, reject) => {
+        reject(new Error('expected'))
+      }), 'fn returns promise')
+      tt.rejects(new Promise((_, reject) => {
+        reject(new Error('expected'))
+      }))
+      tt.rejects(() => new Promise((_, reject) => {
+        reject(new Error('expected'))
+      }))
+      tt.rejects('todo because no fn/promise', { foo: 'bar' })
+      tt.comment('next 2 also todo, no message')
+      tt.rejects({ x: 1 })
+      tt.rejects()
+      tt.rejects(() => new Promise((_, reject) => {
+        reject(new Error('expected'))
+      }), new Error('expected'), 'throws expected error')
+      tt.rejects(() => new Promise((_, reject) => {
+        reject(new TypeError('expected'))
+      }), TypeError, 'throws expected error type')
+      tt.rejects(() => new Promise((_, reject) => {
+        reject(new TypeError('expected'))
+      }), TypeError, ()=>{}, _=>_, 'extra functions are no-ops')
+      tt.rejects(() => new Promise((_, reject) => {
+        reject(new TypeError('expected'))
+      }), TypeError, 1, 2, {}, {}, 'extra args are no-ops')
+
+      const prop = new Error('noent')
+      prop.code= 'ENOENT'
+      tt.rejects(new Promise((_, reject) => {
+        const er = new Error('noent')
+        er.code = 'ENOENT'
+        er.path = __filename
+        reject(er)
+      }), prop)
+
+      const nameless = new Error('x')
+      Object.defineProperty(nameless, 'name', {
+        value: undefined
+      })
+      nameless.stack = /^.*$/
+      tt.rejects(new Promise((_,r) => r(new Error('x'))), nameless)
+      tt.rejects(new Promise((_,r) => r(nameless)), { message: 'x' })
+      tt.rejects(new Promise((_,r) => r(nameless)), /^.$/)
+      tt.rejects(new Promise((_,r) => r(nameless)))
+
+      tt.rejects(() => {}, 'fail: no promise')
+      tt.rejects(() => ({}), 'fail: no promise')
+
+      tt.rejects(new Promise(r => r(420)), 'fail: passing promise')
+
+      tt.end()
+    },
+
+    resolves: tt => {
+      tt.resolves(new Promise(r => r(420)))
+      tt.resolves(new Promise(r => r(420)), { todo: true })
+      tt.resolves(new Promise(r => r(420)), 'passing promise')
+      tt.resolves(() => new Promise(r => r(420)), 'passing promise fn')
+      tt.resolves(() => {}, 'fail: no promise')
+      tt.end()
+    },
+
+    resolveMatch: tt => {
+      tt.resolveMatch(new Promise(r => r(420)), Number)
+      tt.resolveMatch(new Promise(r => r(420)), 'asdf', { todo: true })
+      tt.resolveMatch(new Promise(r => r(420)), 420, 'promise')
+      tt.resolveMatch(() => new Promise(r => r(420)), 420, 'promise fn')
+      tt.resolveMatch(() => {}, {}, 'fail: no promise')
+      tt.end()
+    },
+
+    'test after end fails': tt => {
+      tt.end()
+      tt.pass('failing pass')
+    },
+
+    'plan excess': tt => {
+      tt.plan(1)
+      tt.pass('fine')
+      tt.pass('not fine')
+    },
+
+    'plan excess, ignored when failing': tt => {
+      tt.plan(1)
+      tt.fail('expected fail', { diagnostic: false })
+      tt.pass('not fine')
+    },
+
+    'using the assertAt field': tt => {
+      const stack = require('../lib/stack.js')
+      const foo = () => tt.fail('expect fail')
+      const bar = () => foo()
+      const baz = () => { tt.assertAt = stack.at(); bar() }
+
+      tt.plan(1)
+      baz()
+    },
+
+    'using the assertStack field': tt => {
+      const stack = require('../lib/stack.js')
+      const foo = () => tt.fail('expect fail')
+      const bar = () => foo()
+      const baz = () => { tt.assertStack = stack.captureString(80); bar() }
+
+      tt.plan(1)
+      baz()
+    },
+
+    printResult: tt => {
+      // super low-level
+      tt.printResult(true, 'this is fine')
+      tt.end()
+    },
+
+    'printResult after plan end': tt => {
+      // super low-level
+      tt.end()
+      tt.printResult(true, 'this is fine')
+    },
+
+    'plan, child test, explicit end': tt => {
+      tt.plan(1)
+      tt.test(tt => Promise.resolve('ok'))
+      tt.end()
+    },
+
+    'end multiple times': tt => {
+      tt.plan(1)
+      tt.pass('yes')
+      tt.end()
+      tt.end()
+    },
+
+    'error event with domainEmitter re-throws': tt => {
+      const er = new Error('fail')
+      const d = tt.domain
+      try {
+        d.run(() => {
+          const e = new EE
+          e.emit('error', er)
+          tt.fail('did not throw')
+        })
+      } catch (er) {
+        tt.pass('the better to this.threw you with')
+        tt.end()
+      }
+    },
+
+    'thrower after end': tt => {
+      tt.test('child', tt => {
+        tt.plan(1)
+        tt.pass('this is fine')
+        tt.threw(new Error('catch it in the parent'))
+      })
+      tt.end()
+    },
+
+    'child breaks a promise': tt => {
+      tt.test('child', () => new Promise((_, r) => r(new Error('poop'))))
+      tt.end()
+    },
+
+    'child teardown throw': tt => {
+      tt.test('child', tt => {
+        tt.teardown(() => { throw new Error('fail') })
+        tt.end()
+      })
+      tt.end()
+    },
+
+    'fullname without main': tt => {
+      const main = process.argv[1]
+      tt.teardown(() => process.argv[1] = main)
+      process.argv[1] = ''
+      tt.test('child', tt => {
+        tt.pass(tt.fullname)
+        tt.end()
+      })
+      tt.pass(tt.fullname)
+      tt.end()
+    },
+
+    'comment after end': tt => {
+      tt.end()
+      tt.comment('this is fine')
+    },
   }
 
   const keys = Object.keys(cases)
@@ -297,11 +560,33 @@ t.test('assertion checks', t => {
   for (let i in cases) {
     t.test(i, t => {
       t.plan(1)
+
+      const error = console.error
+      t.teardown(() => console.error = error)
+      let err = ''
+      console.error = function () {
+        err += util.format.apply(util, arguments) + '\n'
+      }
+
       const tt = new Test()
       let out = ''
       tt.on('data', c => out += c)
-      tt.on('end', _ => t.matchSnapshot(clean(out), i))
+      tt.on('end', _ => {
+        setTimeout(() => {
+          if (err)
+            out = out.trim() + '\n' + 'STDERR:\n' + err
+          t.matchSnapshot(clean(out), i)
+        })
+      })
       cases[i](tt)
     })
   }
 })
+
+t.test('autoEnd')
+t.test('endAll')
+t.test('addAssert')
+t.test('snapshots')
+t.test('spawn')
+t.test('stdin')
+t.test('timeout')

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-tap.git



More information about the Pkg-javascript-commits mailing list