[Pkg-javascript-commits] [node-tap] 07/186: classy Test class
Bastien Roucariès
rouca at moszumanska.debian.org
Fri Dec 1 16:40:38 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 f7b7aafe9bfa7642a2cb2d994c699c1bf558ea2f
Author: isaacs <i at izs.me>
Date: Thu Jul 6 15:21:01 2017 -0700
classy Test class
---
lib/test.js | 1203 ++++++++++++++++++++---------------------
test/test-test.js | 4 -
test/test/bailout--buffer.tap | 2 +-
test/test/bailout.js | 3 +-
test/test/bailout.tap | 2 +-
5 files changed, 604 insertions(+), 610 deletions(-)
diff --git a/lib/test.js b/lib/test.js
index 27e93a9..86c3eda 100644
--- a/lib/test.js
+++ b/lib/test.js
@@ -30,7 +30,6 @@ const extraFromError = require('./extra-from-error.js')
const stack = require('./stack.js')
const assert = require('assert')
const util = require('util')
-util.inherits(Test, Base)
const ownOr = require('own-or')
const ownOrEnv = require('own-or-env')
const tapAsserts = require('./asserts.js')
@@ -39,693 +38,721 @@ const bindObj = require('bind-obj-methods')
// A sigil object for implicit end() calls that should not
// trigger an error if the user then calls t.end()
-const IMPLICIT = {}
+const IMPLICIT = Symbol('implicit t.end()')
// Sigil to put in the queue to signal the end of all things
-const EOF = { EOF: true }
-
-function hasOwn (obj, key) {
- return Object.prototype.hasOwnProperty.call(obj, key)
-}
+const EOF = Symbol('EOF')
+
+const _end = Symbol('_end')
+
+
+const hasOwn = (obj, key) =>
+ Object.prototype.hasOwnProperty.call(obj, key)
+
+class Test extends Base {
+ constructor (options) {
+ options = options || {}
+ super(options)
+ this.pushedEnd = false
+ this.jobs = ownOr(options, 'jobs', 1)
+ this.subtests = []
+ this.pool = new Pool()
+ this.queue = ['TAP version 13\n']
+ this.noparallel = false
+ this.cb = this.domain.bind(options.cb)
+ this.occupied = false
+ this.currentAssert = null
+ this.count = 0
+ this.n = 0
+ this.ended = false
+ this.explicitEnded = false
+ this.multiEndThrew = false
+ this.currentAssert = null
+ this.assertAt = null
+ this.assertStack = null
+ this.planEnd = -1
+ this.onBeforeEach = []
+ this.onAfterEach = []
+ this.ranAfterEach = false
+
+ // bind all methods to this object, so we can pass t.end as a callback
+ // and do `const test = require('tap').test` like people do.
+ const bound = Object.create(null)
+ bindObj(this, this, bound)
+ bindObj(this, Object.getPrototypeOf(this), bound)
+ bindObj(this, Test.prototype, bound)
+ }
+
+ spawn (cmd, args, options, name) {
+ if (typeof args === 'string') {
+ args = [ args ]
+ }
-module.exports = Test
+ args = args || []
-function Test (options) {
- options = options || {}
- if (!(this instanceof Test))
- return new Test(options)
-
- Base.call(this, options)
- this.pushedEnd = false
- this.jobs = ownOr(options, 'jobs', 1)
- this.subtests = []
- this.pool = new Pool()
- this.queue = ['TAP version 13\n']
- this.noparallel = false
- this.cb = this.domain.bind(options.cb)
- this.occupied = false
- this.currentAssert = null
- this.count = 0
- this.n = 0
- this.ended = false
- this.explicitEnded = false
- this.multiEndThrew = false
- this.currentAssert = null
- this.assertAt = null
- this.assertStack = null
- this.planEnd = -1
- this.onBeforeEach = []
- this.onAfterEach = []
- this.ranAfterEach = false
-
- // bind all methods to this object, so we can pass t.end as a callback
- // and do `const test = require('tap').test` like people do.
- const bound = Object.create(null)
- bindObj(this, this, bound)
- bindObj(this, Object.getPrototypeOf(this), bound)
- bindObj(this, Test.prototype, bound)
-}
+ if (typeof options === 'string') {
+ name = options
+ options = {}
+ }
-Test.prototype.current = function () {
- throw new Error('Test.current() as been removed and is no more')
-}
+ options = options || {}
+ options.name = ownOr(options, 'name', name)
+ options.command = cmd
+ options.args = args
-Test.prototype.spawn = function spawn (cmd, args, options, name) {
- if (typeof args === 'string') {
- args = [ args ]
+ return this.sub(Spawn, options, Test.prototype.spawn)
}
- args = args || []
+ 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
+ if (!match) {
+ const p = 'filter' + (this.grepInvert ? ' out' : '') + ': '
+ extra.skip = p + this.grep[0]
+ }
+ }
- if (typeof options === 'string') {
- name = options
- options = {}
- }
+ if (extra.only && !this.runOnly) {
+ this.comment('%j has `only` set but all tests run', extra.name)
+ }
- options = options || {}
- options.name = ownOr(options, 'name', name)
- options.command = cmd
- options.args = args
+ if (this.runOnly && !extra.only) {
+ extra.skip = 'filter: only'
+ }
- return this.sub(Spawn, options, spawn)
-}
+ if (extra.todo || extra.skip) {
+ this.pass(extra.name, extra)
+ return Promise.resolve(this)
+ }
-Test.prototype.sub = function (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
- if (!match) {
- const p = 'filter' + (this.grepInvert ? ' out' : '') + ': '
- extra.skip = p + this.grep[0]
+ if (!extra.grep) {
+ extra.grep = this.grep.slice(1)
+ extra.grepInvert = this.grepInvert
}
- }
- if (extra.only && !this.runOnly) {
- this.comment('%j has `only` set but all tests run', extra.name)
+ extra.indent = ' '
+ if (this.jobs > 1 && process.env.TAP_BUFFER === undefined)
+ extra.buffered = ownOr(extra, 'buffered', true)
+ else
+ extra.buffered = ownOrEnv(extra, 'buffered', 'TAP_BUFFER', true)
+
+ extra.bail = ownOr(extra, 'bail', this.bail)
+ extra.parent = this
+ extra.stack = stack.captureString(80, caller)
+ const t = new Class(extra)
+
+ this.queue.push(t)
+ this.subtests.push(t)
+
+ const d = new Deferred()
+ t.deferred = d
+ this.process()
+ return d.promise
}
- if (this.runOnly && !extra.only) {
- extra.skip = 'filter: only'
+ only (name, extra, cb) {
+ extra = parseTestArgs(name, extra, cb)
+ extra.only = true
+ return this.sub(Test, extra, Test.prototype.only)
}
- if (extra.todo || extra.skip) {
- this.pass(extra.name, extra)
- return Promise.resolve(this)
+ test (name, extra, cb) {
+ extra = parseTestArgs(name, extra, cb)
+ return this.sub(Test, extra, Test.prototype.test)
}
- if (!extra.grep) {
- extra.grep = this.grep.slice(1)
- extra.grepInvert = this.grepInvert
+ stdin (name, extra) {
+ extra = parseTestArgs(name, extra, () => {}, '/dev/stdin')
+ return this.sub(Stdin, extra || {}, Test.prototype.stdin)
}
- extra.indent = ' '
- if (this.jobs > 1 && process.env.TAP_BUFFER === undefined)
- extra.buffered = ownOr(extra, 'buffered', true)
- else
- extra.buffered = ownOrEnv(extra, 'buffered', 'TAP_BUFFER', true)
+ bailout (message) {
+ if (this.parent && (this.results || this.ended))
+ this.parent.bailout(message)
+ else {
+ this.process()
+ message = message ? ' ' + ('' + message).trim() : ''
+ message = message.replace(/[\r\n]/g, ' ')
+ this.parser.write('Bail out!' + message + '\n')
+ }
+ this.end(IMPLICIT)
+ this.process()
+ }
- extra.bail = ownOr(extra, 'bail', this.bail)
- extra.parent = this
- extra.stack = stack.captureString(80, caller)
- const t = new Class(extra)
+ comment () {
+ const body = util.format.apply(util, arguments)
+ const message = '# ' + body.split(/\r?\n/).join('\n# ') + '\n'
- this.queue.push(t)
- this.subtests.push(t)
+ if (this.results)
+ this.push(message)
+ else
+ this.queue.push(message)
+ this.process()
+ }
- const d = new Deferred()
- t.deferred = d
- this.process()
- return d.promise
-}
+ timeout (options) {
+ options = options || {}
+ options.expired = options.expired || this.name
+ if (this.occupied)
+ this.occupied.timeout(options)
+ else
+ Base.prototype.timeout.call(this, options)
+ this.end(IMPLICIT)
+ }
-Test.prototype.only = function test (name, extra, cb) {
- extra = parseTestArgs(name, extra, cb)
- extra.only = true
- return this.sub(Test, extra, test)
-}
+ main (cb) {
+ this.setTimeout(this.options.timeout)
+ this.debug('MAIN pre', this)
-Test.prototype.test = function test (name, extra, cb) {
- extra = parseTestArgs(name, extra, cb)
- return this.sub(Test, extra, test)
-}
+ const end = () => {
+ this.debug(' > implicit end for promise')
+ this.end(IMPLICIT)
+ done()
+ }
-Test.prototype.stdin = function stdin (name, extra) {
- extra = parseTestArgs(name, extra, function () {}, '/dev/stdin')
- return this.sub(Stdin, extra || {}, stdin)
-}
+ const done = (er) => {
+ if (er)
+ this.threw(er)
-Test.prototype.bailout = function (message) {
- if (this.parent && (this.results || this.ended))
- this.parent.bailout(message)
- else {
- this.process()
- message = message ? ' ' + ('' + message).trim() : ''
- message = message.replace(/[\r\n]/g, ' ')
- this.parser.write('Bail out!' + message + '\n')
- }
- this.end(IMPLICIT)
- this.process()
-}
+ if (this.results || this.bailedOut)
+ cb()
+ else
+ this.ondone = cb
+ }
-Test.prototype.comment = function () {
- const body = util.format.apply(util, arguments)
- const message = '# ' + body.split(/\r?\n/).join('\n# ') + '\n'
+ const ret = (() => {
+ try {
+ return this.cb(this)
+ } catch (er) {
+ this.threw(er)
+ }
+ })()
+
+ if (ret && ret.then) {
+ this.promise = ret
+ ret.tapAbortPromise = done
+ ret.then(end, done)
+ } else
+ done()
+
+
+ this.debug('MAIN post', this)
+ }
+
+ process () {
+ if (this.processing)
+ return this.debug(' < already processing')
+
+ this.debug('\nPROCESSING(%s)', this.name, this.queue.length)
+ this.processing = true
+
+ while (!this.occupied) {
+ const p = this.queue.shift()
+ if (!p)
+ break
+ if (p instanceof Base) {
+ this.processSubtest(p)
+ } else if (p === EOF) {
+ this.debug(' > EOF', this.name)
+ // I AM BECOME EOF, DESTROYER OF STREAMS
+ this.parser.end()
+ } else if (p instanceof TestPoint) {
+ this.debug(' > TESTPOINT')
+ this.parser.write(p.ok + (++this.n) + p.message)
+ } else if (typeof p === 'string') {
+ this.debug(' > STRING')
+ this.parser.write(p)
+ } else if (Array.isArray(p)) {
+ this.debug(' > METHOD')
+ const m = p.shift()
+ this[m].apply(this, p)
+ } else {
+ throw new Error('weird thing got in the queue')
+ }
+ }
- if (this.results)
- this.push(message)
- else
- this.queue.push(message)
- this.process()
-}
+ while (!this.noparallel && this.pool.length < this.jobs) {
+ const p = this.subtests.shift()
+ if (!p)
+ break
-Test.prototype.timeout = function (options) {
- options = options || {}
- options.expired = options.expired || this.name
- if (this.occupied)
- this.occupied.timeout(options)
- else
- Base.prototype.timeout.call(this, options)
- this.end(IMPLICIT)
-}
-
-Test.prototype.main = function (cb) {
- this.setTimeout(this.options.timeout)
- this.debug('MAIN pre', this)
+ if (!p.buffered) {
+ this.noparallel = true
+ break
+ }
- const self = this
- const ret = (() => {
- try {
- return this.cb(this)
- } catch (er) {
- this.threw(er)
+ this.debug('start subtest', p)
+ this.pool.add(p)
+ if (this.bailedOut)
+ this.onbufferedend(p)
+ else
+ this.runBeforeEach(p,
+ p.main.bind(p,
+ this.onbufferedend.bind(this, p)))
}
- })()
-
- if (ret && ret.then) {
- this.promise = ret
- ret.tapAbortPromise = done
- ret.then(end, done)
- } else
- done()
- function end () {
- self.debug(' > implicit end for promise')
- self.end(IMPLICIT)
- done()
- }
+ this.debug('done processing', this.queue, this.occupied)
+ this.processing = false
- function done (er) {
- if (er)
- self.threw(er)
+ // just in case any tests ended, and we have sync stuff still
+ // waiting around in the queue to be processed
+ if (!this.occupied && this.queue.length)
+ this.process()
- if (self.results || self.bailedOut)
- cb()
- else
- self.ondone = cb
+ this.maybeAutoend()
}
- this.debug('MAIN post', this)
-}
-
-Test.prototype.process = function () {
- if (this.processing)
- return this.debug(' < already processing')
-
- this.debug('\nPROCESSING(%s)', this.name, this.queue.length)
- this.processing = true
-
- while (!this.occupied) {
- const p = this.queue.shift()
- if (!p)
- break
- if (p instanceof Base) {
- this.processSubtest(p)
- } else if (p === EOF) {
- this.debug(' > EOF', this.name)
- // I AM BECOME EOF, DESTROYER OF STREAMS
- this.parser.end()
- } else if (p instanceof TestPoint) {
- this.debug(' > TESTPOINT')
- this.parser.write(p.ok + (++this.n) + p.message)
- } else if (typeof p === 'string') {
- this.debug(' > STRING')
- this.parser.write(p)
- } else if (Array.isArray(p)) {
- this.debug(' > METHOD')
- const m = p.shift()
- this[m].apply(this, p)
+ processSubtest (p) {
+ this.debug(' > subtest')
+ this.occupied = p
+ if (!p.buffered) {
+ if (this.bailedOut)
+ return this.onindentedend(p)
+ this.debug(' > subtest indented')
+ p.pipe(this.parser, { end: false })
+ this.runBeforeEach(p,
+ this.writeSubComment.bind(this, p,
+ p.main.bind(p,
+ this.onindentedend.bind(this, p))))
+ } else if (p.readyToProcess) {
+ this.debug(' > subtest buffered, finished')
+ // finished! do the thing!
+ this.occupied = null
+ if (!p.passing() || !p.silent) {
+ this.queue.unshift(['emitSubTeardown', p])
+ this.printResult(p.passing(), p.name, p.options, true)
+ }
} else {
- throw new Error('weird thing got in the queue')
+ this.occupied = p
+ this.debug(' > subtest buffered, unfinished', p)
+ // unfinished buffered test.
+ // nothing to do yet, just leave it there.
+ this.queue.unshift(p)
}
}
- while (!this.noparallel && this.pool.length < this.jobs) {
- const p = this.subtests.shift()
- if (!p)
- break
-
- if (!p.buffered) {
- this.noparallel = true
- break
+ emitSubTeardown (p) {
+ try {
+ p.emit('teardown')
+ } catch (er) {
+ delete p.options.time
+ p.threw(er)
}
-
- this.debug('start subtest', p)
- this.pool.add(p)
- if (this.bailedOut)
- this.onbufferedend(p)
- else
- this.runBeforeEach(p,
- p.main.bind(p,
- this.onbufferedend.bind(this, p)))
}
- this.debug('done processing', this.queue, this.occupied)
- this.processing = false
+ writeSubComment (p, cb) {
+ const comment = '# Subtest' +
+ (p.name ? ': ' + p.name : '') +
+ '\n'
+ this.parser.write(comment)
+ cb()
+ }
- // just in case any tests ended, and we have sync stuff still
- // waiting around in the queue to be processed
- if (!this.occupied && this.queue.length)
+ onbufferedend (p, er) {
+ delete p.ondone
+ p.results = p.results || {}
+ p.readyToProcess = true
+ const to = p.options.timeout
+ const dur = (to && p.passing()) ? Date.now() - p.start : null
+ if (dur && dur > to)
+ p.timeout()
+ else
+ p.setTimeout(false)
+ this.debug('%s.onbufferedend', this.name, p.name, p.results.bailout)
+ this.pool.remove(p)
+ p.options.tapChildBuffer = p.output || ''
+ p.options.stack = ''
+ if (p.time)
+ p.options.time = p.time
+ if (this.occupied === p)
+ this.occupied = null
+ if (er)
+ this.threw(er)
+ p.deferred.resolve(this)
this.process()
+ }
- this.maybeAutoend()
-}
-
-Test.prototype.processSubtest = function (p) {
- this.debug(' > subtest')
- this.occupied = p
- if (!p.buffered) {
- if (this.bailedOut)
- return this.onindentedend(p)
- this.debug(' > subtest indented')
- p.pipe(this.parser, { end: false })
- this.runBeforeEach(p,
- this.writeSubComment.bind(this, p,
- p.main.bind(p,
- this.onindentedend.bind(this, p))))
- } else if (p.readyToProcess) {
- this.debug(' > subtest buffered, finished')
- // finished! do the thing!
+ onindentedend (p, er) {
+ delete p.ondone
+ this.debug('onindentedend', p)
+ this.noparallel = false
+ const sti = this.subtests.indexOf(p)
+ if (sti !== -1)
+ this.subtests.splice(sti, 1)
+ p.readyToProcess = true
+ p.results = p.results || {}
+ if (p.time)
+ p.options.time = p.time
+ const to = p.options.timeout
+ const dur = (to && p.passing()) ? Date.now() - p.start : null
+ if (dur && dur > to)
+ p.timeout()
+ else
+ p.setTimeout(false)
+ this.debug('onindentedend %s(%s)', this.name, p.name, er || 'ok')
+ assert(this.occupied === p)
this.occupied = null
- if (!p.passing() || !p.silent) {
- this.queue.unshift(['emitSubTeardown', p])
- this.printResult(p.passing(), p.name, p.options, true)
- }
- } else {
- this.occupied = p
- this.debug(' > subtest buffered, unfinished', p)
- // unfinished buffered test.
- // nothing to do yet, just leave it there.
- this.queue.unshift(p)
- }
-}
+ this.debug('OIE(%s) b>shift into queue', this.name, this.queue)
+ p.options.stack = ''
-Test.prototype.emitSubTeardown = function (p) {
- try {
- p.emit('teardown')
- } catch (er) {
- delete p.options.time
- p.threw(er)
- }
-}
+ this.queue.unshift(['emitSubTeardown', p])
+ this.printResult(p.passing(), p.name, p.options, true)
-Test.prototype.writeSubComment = function (p, cb) {
- const comment = '# Subtest' +
- (p.name ? ': ' + p.name : '') +
- '\n'
- this.parser.write(comment)
- cb()
-}
+ this.debug('OIE(%s) shifted into queue', this.name, this.queue)
+ if (er)
+ this.threw(er)
+ p.deferred.resolve(this)
+ this.process()
+ }
-Test.prototype.onbufferedend = function (p, er) {
- delete p.ondone
- p.results = p.results || {}
- p.readyToProcess = true
- const to = p.options.timeout
- const dur = (to && p.passing()) ? Date.now() - p.start : null
- if (dur && dur > to)
- p.timeout()
- else
- p.setTimeout(false)
- this.debug('%s.onbufferedend', this.name, p.name, p.results.bailout)
- this.pool.remove(p)
- p.options.tapChildBuffer = p.output || ''
- p.options.stack = ''
- if (p.time)
- p.options.time = p.time
- if (this.occupied === p)
- this.occupied = null
- if (er)
- this.threw(er)
- p.deferred.resolve(this)
- this.process()
-}
+ addAssert (name, length, fn) {
+ if (!name)
+ throw new TypeError('name is required for addAssert')
-Test.prototype.onindentedend = function (p, er) {
- delete p.ondone
- this.debug('onindentedend', p)
- this.noparallel = false
- const sti = this.subtests.indexOf(p)
- if (sti !== -1)
- this.subtests.splice(sti, 1)
- p.readyToProcess = true
- p.results = p.results || {}
- if (p.time)
- p.options.time = p.time
- const to = p.options.timeout
- const dur = (to && p.passing()) ? Date.now() - p.start : null
- if (dur && dur > to)
- p.timeout()
- else
- p.setTimeout(false)
- this.debug('onindentedend %s(%s)', this.name, p.name, er || 'ok')
- assert(this.occupied === p)
- this.occupied = null
- this.debug('OIE(%s) b>shift into queue', this.name, this.queue)
- p.options.stack = ''
-
- this.queue.unshift(['emitSubTeardown', p])
- this.printResult(p.passing(), p.name, p.options, true)
-
- this.debug('OIE(%s) shifted into queue', this.name, this.queue)
- if (er)
- this.threw(er)
- p.deferred.resolve(this)
- this.process()
-}
+ if (!(typeof length === 'number' && length >= 0))
+ throw new TypeError('number of args required')
-Test.prototype.addAssert = function (name, length, fn) {
- if (!name)
- throw new TypeError('name is required for addAssert')
+ if (typeof fn !== 'function')
+ throw new TypeError('function required for addAssert')
- if (!(typeof length === 'number' && length >= 0))
- throw new TypeError('number of args required')
+ if (Test.prototype[name] || this[name])
+ throw new TypeError('attempt to re-define `' + name + '` assert')
- if (typeof fn !== 'function')
- throw new TypeError('function required for addAssert')
+ function ASSERT () {
+ if (!this.currentAssert) {
+ this.currentAssert = ASSERT
+ }
+ const args = new Array(length + 2)
+ for (let i = 0; i < length; i++) {
+ args[i] = arguments[i]
+ }
+ if (typeof arguments[length] === 'object') {
+ args[length] = ''
+ args[length + 1] = arguments[length]
+ } else {
+ args[length] = arguments[length] || ''
+ args[length + 1] = arguments[length + 1] || {}
+ }
- if (Test.prototype[name] || this[name])
- throw new TypeError('attempt to re-define `' + name + '` assert')
+ return fn.apply(this, args)
+ }
+ this[name] = ASSERT
+ }
- this[name] = function ASSERT () {
+ fail (message, extra) {
if (!this.currentAssert) {
- this.currentAssert = ASSERT
- }
- const args = new Array(length + 2)
- for (let i = 0; i < length; i++) {
- args[i] = arguments[i]
+ this.currentAssert = Test.prototype.fail
}
- if (typeof arguments[length] === 'object') {
- args[length] = ''
- args[length + 1] = arguments[length]
+
+ if (message && typeof message === 'object') {
+ extra = message
+ message = ''
} else {
- args[length] = arguments[length] || ''
- args[length + 1] = arguments[length + 1] || {}
+ if (!message) {
+ message = ''
+ }
+ if (!extra) {
+ extra = {}
+ }
}
- return fn.apply(this, args)
- }
-}
+ this.printResult(false, message, extra)
-Test.prototype.fail = function fail (message, extra) {
- if (!this.currentAssert) {
- this.currentAssert = fail
+ // if it's todo or skip, it's still technically passing
+ return !!(extra.todo || extra.skip)
}
- if (message && typeof message === 'object') {
- extra = message
- message = ''
- } else {
- if (!message) {
- message = ''
- }
- if (!extra) {
- extra = {}
+ pass (message, extra) {
+ if (!this.currentAssert) {
+ this.currentAssert = Test.prototype.pass
}
+ this.printResult(true, message || '(unnamed test)', extra)
+ return true
}
- this.printResult(false, message, extra)
-
- // if it's todo or skip, it's still technically passing
- return !!(extra.todo || extra.skip)
-}
+ printResult (ok, message, extra, front) {
+ const n = this.count + 1
+ if (this.planEnd !== -1 && n > this.planEnd) {
+ if (!this.passing())
+ return
-Test.prototype.pass = function pass (message, extra) {
- if (!this.currentAssert) {
- this.currentAssert = pass
- }
- this.printResult(true, message || '(unnamed test)', extra)
- return true
-}
+ const failMessage = this.explicitEnded
+ ? 'test after end() was called'
+ : 'test count exceeds plan'
-Test.prototype.printResult = function pR (ok, message, extra, front) {
- const n = this.count + 1
- if (this.planEnd !== -1 && n > this.planEnd) {
- if (!this.passing())
+ const er = new Error(failMessage)
+ Error.captureStackTrace(er,
+ this.currentAssert || Test.prototype.printResult)
+ er.test = this.name
+ er.plan = this.planEnd
+ this.threw(er)
return
+ }
- const failMessage = this.explicitEnded
- ? 'test after end() was called'
- : 'test count exceeds plan'
+ extra = extra || {}
- const er = new Error(failMessage)
- Error.captureStackTrace(er, this.currentAssert || pR)
- er.test = this.name
- er.plan = this.planEnd
- this.threw(er)
- return
- }
+ if (this.assertAt) {
+ extra.at = this.assertAt
+ this.assertAt = null
+ }
- extra = extra || {}
+ if (this.assertStack) {
+ extra.stack = this.assertStack
+ this.assertStack = null
+ }
- if (this.assertAt) {
- extra.at = this.assertAt
- this.assertAt = null
- }
+ if (hasOwn(extra, 'stack') && !hasOwn(extra, 'at'))
+ extra.at = stack.parseLine(extra.stack.split('\n')[0])
- if (this.assertStack) {
- extra.stack = this.assertStack
- this.assertStack = null
- }
+ const fn = this.currentAssert || Test.prototype.printResult
+ this.currentAssert = null
+ if (!ok && !extra.skip && !hasOwn(extra, 'at')) {
+ assert.equal(typeof fn, 'function')
+ extra.at = stack.at(fn)
+ if (!extra.todo)
+ extra.stack = stack.captureString(80, fn)
+ }
- if (hasOwn(extra, 'stack') && !hasOwn(extra, 'at'))
- extra.at = stack.parseLine(extra.stack.split('\n')[0])
+ const diagnostic =
+ typeof extra.diagnostic === 'boolean' ? extra.diagnostic
+ : process.env.TAP_DIAG === '0' ? false
+ : process.env.TAP_DIAG === '1' ? true
+ : extra.skip ? false
+ : !ok
+
+ if (diagnostic)
+ extra.diagnostic = true
+
+ this.count = n
+ const res = { ok: ok, message: message, extra: extra }
+ const output = new TestPoint(ok, message, extra)
+ // when we jump the queue, skip an extra line
+ if (front)
+ output.message = output.message.trimRight() + '\n\n'
+
+ if (front) {
+ this.emit('result', res)
+ this.parser.write(output.ok + (++this.n) + output.message)
+ } else
+ this.queue.push(['emit', 'result', res], output)
+
+ if (this.planEnd === this.count)
+ this.end(IMPLICIT)
- const fn = this.currentAssert || pR
- this.currentAssert = null
- if (!ok && !extra.skip && !hasOwn(extra, 'at')) {
- assert.equal(typeof fn, 'function')
- extra.at = stack.at(fn)
- if (!extra.todo)
- extra.stack = stack.captureString(80, fn)
+ this.process()
}
- const diagnostic =
- typeof extra.diagnostic === 'boolean' ? extra.diagnostic
- : process.env.TAP_DIAG === '0' ? false
- : process.env.TAP_DIAG === '1' ? true
- : extra.skip ? false
- : !ok
-
- if (diagnostic)
- extra.diagnostic = true
+ pragma (set) {
+ const p = Object.keys(set).reduce((acc, i) =>
+ acc + 'pragma ' + (set[i] ? '+' : '-') + i + '\n', '')
+ this.queue.push(p)
+ this.process()
+ }
- this.count = n
- const res = { ok: ok, message: message, extra: extra }
- const output = new TestPoint(ok, message, extra)
- // when we jump the queue, skip an extra line
- if (front)
- output.message = output.message.trimRight() + '\n\n'
+ plan (n, comment) {
+ if (this.bailedOut)
+ return
- if (front) {
- this.emit('result', res)
- this.parser.write(output.ok + (++this.n) + output.message)
- } else
- this.queue.push(['emit', 'result', res], output)
+ if (this.planEnd !== -1) {
+ throw new Error('Cannot set plan more than once')
+ }
- if (this.planEnd === this.count)
- this.end(IMPLICIT)
+ if (typeof n !== 'number' || n < 0) {
+ throw new TypeError('plan must be a number')
+ }
- this.process()
-}
+ // Cannot get any tests after a trailing plan, or a plan of 0
+ const ending = this.count !== 0 || n === 0
-Test.prototype.pragma = function (set) {
- const p = Object.keys(set).reduce(function (acc, i) {
- return acc + 'pragma ' + (set[i] ? '+' : '-') + i + '\n'
- }, '')
- this.queue.push(p)
- this.process()
-}
+ if (n === 0)
+ this.skip = comment || true
-Test.prototype.plan = function (n, comment) {
- if (this.bailedOut)
- return
+ this.planEnd = n
+ comment = comment ? ' # ' + comment.trim() : ''
+ this.queue.push('1..' + n + comment + '\n')
- if (this.planEnd !== -1) {
- throw new Error('Cannot set plan more than once')
+ if (ending)
+ this.end(IMPLICIT)
+ else
+ this.process()
}
- if (typeof n !== 'number' || n < 0) {
- throw new TypeError('plan must be a number')
- }
+ end (implicit) {
+ this.debug('END implicit=%j', implicit === IMPLICIT)
+ if (this.ended && implicit === IMPLICIT)
+ return
- // Cannot get any tests after a trailing plan, or a plan of 0
- const ending = this.count !== 0 || n === 0
+ // beyond here we have to be actually done with things, or else
+ // the semantic checks on counts and such will be off.
+ if (!queueEmpty(this) || this.occupied) {
+ if (!this.pushedEnd)
+ this.queue.push(['end', implicit])
+ this.pushedEnd = true
+ return this.process()
+ }
- if (n === 0)
- this.skip = comment || true
+ if (!this.ranAfterEach && this.parent) {
+ this.ranAfterEach = true
+ this.parent.runAfterEach(this, () => this[_end](implicit))
+ return
+ } else
+ this[_end](implicit)
+ }
+
+ [_end] (implicit) {
+ this.ended = true
+
+ if (implicit !== IMPLICIT && !this.multiEndThrew) {
+ if (this.explicitEnded) {
+ this.multiEndThrew = true
+ const er = new Error('test end() method called more than once')
+ Error.captureStackTrace(er, this.currentAssert ||
+ Test.prototype[_end])
+ er.test = this.name
+ this.threw(er)
+ return
+ }
+ this.explicitEnded = true
+ }
- this.planEnd = n
- comment = comment ? ' # ' + comment.trim() : ''
- this.queue.push('1..' + n + comment + '\n')
+ if (this.planEnd === -1) {
+ this.debug('END(%s) implicit plan', this.name, this.count)
+ this.plan(this.count)
+ }
- if (ending)
- this.end(IMPLICIT)
- else
+ this.queue.push(EOF)
this.process()
-}
+ }
-Test.prototype.done = Test.prototype.end = function (implicit) {
- this.debug('END implicit=%j', implicit === IMPLICIT)
- if (this.ended && implicit === IMPLICIT)
- return
-
- // beyond here we have to be actually done with things, or else
- // the semantic checks on counts and such will be off.
- if (!queueEmpty(this) || this.occupied) {
- if (!this.pushedEnd)
- this.queue.push(['end', implicit])
- this.pushedEnd = true
- return this.process()
- }
-
- if (!this.ranAfterEach && this.parent) {
- this.ranAfterEach = true
- this.parent.runAfterEach(this, end.bind(this, implicit))
- } else
- end.call(this, implicit)
-}
+ threw (er, extra, proxy) {
+ this.debug('THREW', er.message, extra, proxy)
-function end (implicit) {
- this.ended = true
+ // event emitters 'error' events need to re-throw so that they
+ // can jump out of the flow like a normal throw. They'll just
+ // end up back here once that happens, though, unless there's a
+ // try/catch somewhere in the call stack.
+ if (er.domainEmitter) {
+ delete er.domainEmitter
+ throw er
+ }
- if (implicit !== IMPLICIT && !this.multiEndThrew) {
- if (this.explicitEnded) {
- this.multiEndThrew = true
- const er = new Error('test end() method called more than once')
- Error.captureStackTrace(er, this.currentAssert || end)
+ if (this.name && !proxy)
er.test = this.name
- this.threw(er)
- return
+ if (!proxy)
+ extra = extraFromError(er, extra, this.options)
+ Base.prototype.threw.call(this, er, extra, proxy)
+
+ if (!this.results) {
+ this.fail(extra.message || er.message, extra)
+ if (!proxy)
+ this.end(IMPLICIT)
}
- this.explicitEnded = true
+ this.process()
}
- if (this.planEnd === -1) {
- this.debug('END(%s) implicit plan', this.name, this.count)
- this.plan(this.count)
+ runBeforeEach (who, cb) {
+ if (this.parent)
+ this.parent.runBeforeEach(who, () => {
+ loop(who, this.onBeforeEach, cb, who.threw)
+ })
+ else
+ loop(who, this.onBeforeEach, cb, who.threw)
}
- this.queue.push(EOF)
- this.process()
-}
-
-Test.prototype.threw = function (er, extra, proxy) {
- this.debug('THREW', er.message, extra, proxy)
+ runAfterEach (who, cb) {
+ loop(who, this.onAfterEach, () => {
+ if (this.parent)
+ this.parent.runAfterEach(who, cb)
+ else
+ cb()
+ }, who.threw)
+ }
- // event emitters 'error' events need to re-throw so that they
- // can jump out of the flow like a normal throw. They'll just
- // end up back here once that happens, though, unless there's a
- // try/catch somewhere in the call stack.
- if (er.domainEmitter) {
- delete er.domainEmitter
- throw er
+ beforeEach (fn) {
+ this.onBeforeEach.push(fn)
}
- if (this.name && !proxy)
- er.test = this.name
- if (!proxy)
- extra = extraFromError(er, extra, this.options)
- Base.prototype.threw.call(this, er, extra, proxy)
+ afterEach (fn) {
+ this.onAfterEach.push(fn)
+ }
- if (!this.results) {
- this.fail(extra.message || er.message, extra)
- if (!proxy)
- this.end(IMPLICIT)
+ teardown (fn) {
+ this.on('teardown', fn)
}
- this.process()
-}
-Test.prototype.runBeforeEach = function (who, cb) {
- const self = this
- if (this.parent)
- this.parent.runBeforeEach(who, function () {
- loop(who, self.onBeforeEach, cb, who.threw)
- })
- else
- loop(who, self.onBeforeEach, cb, who.threw)
-}
+ shouldAutoend () {
+ const should = (
+ this.options.autoend &&
+ !this.ended &&
+ !this.occupied &&
+ queueEmpty(this) &&
+ !this.pool.length &&
+ !this.subtests.length &&
+ this.planEnd === -1
+ )
+ return should
+ }
-Test.prototype.runAfterEach = function (who, cb) {
- const self = this
- loop(who, self.onAfterEach, function () {
- if (self.parent)
- self.parent.runAfterEach(who, cb)
- else
- cb()
- }, who.threw)
-}
+ autoend () {
+ this.options.autoend = true
+ this.maybeAutoend()
+ }
-Test.prototype.beforeEach = function (fn) {
- this.onBeforeEach.push(fn)
-}
+ maybeAutoend () {
+ if (this.autoendTimer)
+ clearTimeout(this.autoendTimer)
-Test.prototype.afterEach = function (fn) {
- this.onAfterEach.push(fn)
-}
+ if (this.shouldAutoend()) {
+ this.autoendTimer = setTimeout(() => {
+ if (this.shouldAutoend()) {
+ this.autoendTimer = setTimeout(() => {
+ if (this.shouldAutoend())
+ this.end(IMPLICIT)
+ })
+ }
+ })
+ }
+ }
-Test.prototype.teardown = Test.prototype.tearDown = function (fn) {
- this.on('teardown', fn)
-}
+ endAll (sub) {
+ this.processing = true
+ if (this.occupied) {
+ const p = this.occupied
+ if (p.endAll)
+ p.endAll(true)
+ else {
+ p.parser.abort('test unfinished')
+ }
+ } else if (sub) {
+ this.process()
+ if (queueEmpty(this)) {
+ const options = Object.assign({}, this.options)
+ this.options.at = null
+ this.options.stack = ''
+ options.test = this.name
+ this.fail('test unfinished', options)
+ }
+ }
-Test.prototype.shouldAutoend = function () {
- const should = (
- this.options.autoend &&
- !this.ended &&
- !this.occupied &&
- queueEmpty(this) &&
- !this.pool.length &&
- !this.subtests.length &&
- this.planEnd === -1
- )
- return should
-}
+ if (this.promise && this.promise.tapAbortPromise)
+ this.promise.tapAbortPromise()
-Test.prototype.autoend = function () {
- this.options.autoend = true
- this.maybeAutoend()
-}
+ if (this.occupied) {
+ this.queue.unshift(this.occupied)
+ this.occupied = null
+ }
-Test.prototype.maybeAutoend = function () {
- if (this.autoendTimer)
- clearTimeout(this.autoendTimer)
-
- if (this.shouldAutoend()) {
- const self = this
- self.autoendTimer = setTimeout(function () {
- if (self.shouldAutoend()) {
- self.autoendTimer = setTimeout(function () {
- if (self.shouldAutoend()) {
- self.end(IMPLICIT)
- }
- })
- }
- })
+ endAllQueue(this.queue)
+ this.processing = false
+ this.process()
+ this.parser.end()
}
}
-function endAllQueue (queue) {
- queue.forEach(function (p, i) {
+const endAllQueue = queue => {
+ queue.forEach((p, i) => {
if ((p instanceof Base) && !p.readyToProcess)
queue[i] = new TestPoint(false,
'child test left in queue ' + p.constructor.name + ': ' +
@@ -734,44 +761,14 @@ function endAllQueue (queue) {
queue.push(['end', IMPLICIT])
}
-function queueEmpty (t) {
- return t.queue.length === 0 ||
+const queueEmpty = t =>
+ t.queue.length === 0 ||
t.queue.length === 1 && t.queue[0] === 'TAP version 13\n'
-}
-Test.prototype.endAll = function (sub) {
- this.processing = true
- if (this.occupied) {
- const p = this.occupied
- if (p.endAll)
- p.endAll(true)
- else {
- p.parser.abort('test unfinished')
- }
- } else if (sub) {
- this.process()
- if (queueEmpty(this)) {
- const options = Object.keys(this.options).reduce(function (o, k) {
- o[k] = this.options[k]
- return o
- }.bind(this), {})
- this.options.at = null
- this.options.stack = ''
- options.test = this.name
- this.fail('test unfinished', options)
- }
- }
- if (this.promise && this.promise.tapAbortPromise)
- this.promise.tapAbortPromise()
- if (this.occupied) {
- this.queue.unshift(this.occupied)
- this.occupied = null
- }
- endAllQueue(this.queue)
- this.processing = false
- this.process()
- this.parser.end()
-}
+Test.prototype.done = Test.prototype.end
+Test.prototype.tearDown = Test.prototype.teardown
// Add all the asserts
tapAsserts.decorate(Test.prototype)
+
+module.exports = Test
diff --git a/test/test-test.js b/test/test-test.js
index 7748fda..93ff899 100644
--- a/test/test-test.js
+++ b/test/test-test.js
@@ -156,7 +156,3 @@ t.test('test-point', function (t) {
t.end()
})
-
-t.throws(function () {
- t.current()
-}, new Error('Test.current() as been removed and is no more'))
diff --git a/test/test/bailout--buffer.tap b/test/test/bailout--buffer.tap
index 3481e66..3ec7ec6 100644
--- a/test/test/bailout--buffer.tap
+++ b/test/test/bailout--buffer.tap
@@ -17,7 +17,7 @@ ok 1 - nesting ___/# time=[0-9.]+(ms)?/~~~ {
ok 2 - this passes
not ok 3 - this fails
---
- {"at":{"column":3,"file":"test/test/bailout.js","line":18},"source":"t.fail('this fails')\n"}
+ {"at":{"column":3,"file":"test/test/bailout.js","line":19},"source":"t.fail('this fails')\n"}
...
not ok 4 - async kid ___/# time=[0-9.]+(ms)?/~~~ {
diff --git a/test/test/bailout.js b/test/test/bailout.js
index b71cc8f..3660512 100644
--- a/test/test/bailout.js
+++ b/test/test/bailout.js
@@ -1,4 +1,5 @@
-var t = require('../../lib/test.js')()
+var Test = require('../../lib/test.js')
+var t = new Test()
t.test('nesting', function (t) {
t.plan(2)
diff --git a/test/test/bailout.tap b/test/test/bailout.tap
index a3d3f2e..78ca16c 100644
--- a/test/test/bailout.tap
+++ b/test/test/bailout.tap
@@ -18,7 +18,7 @@ ok 1 - nesting ___/# time=[0-9.]+(ms)?/~~~
ok 2 - this passes
not ok 3 - this fails
---
- {"at":{"column":3,"file":"test/test/bailout.js","line":18},"source":"t.fail('this fails')\n"}
+ {"at":{"column":3,"file":"test/test/bailout.js","line":19},"source":"t.fail('this fails')\n"}
...
# Subtest: async kid
--
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