[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