[Pkg-javascript-commits] [node-tap] 09/186: move assertions directly to 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 da56f538c117fa64651998e6db55940c90f271b2
Author: isaacs <i at izs.me>
Date:   Fri Jul 7 23:50:02 2017 -0700

    move assertions directly to Test class
---
 lib/test.js | 540 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 505 insertions(+), 35 deletions(-)

diff --git a/lib/test.js b/lib/test.js
index 86c3eda..6326143 100644
--- a/lib/test.js
+++ b/lib/test.js
@@ -27,12 +27,14 @@ const parseTestArgs = require('./parse-test-args.js')
 const loop = require('function-loop')
 
 const extraFromError = require('./extra-from-error.js')
+const tsame = require('tsame') // same thing, strict or not
+const tmatch = require('tmatch') // ok with partial estimates
 const stack = require('./stack.js')
+const synonyms = require('./synonyms.js')
 const assert = require('assert')
 const util = require('util')
 const ownOr = require('own-or')
 const ownOrEnv = require('own-or-env')
-const tapAsserts = require('./asserts.js')
 const Promise = require('bluebird')
 const bindObj = require('bind-obj-methods')
 
@@ -45,7 +47,6 @@ const EOF = Symbol('EOF')
 
 const _end = Symbol('_end')
 
-
 const hasOwn = (obj, key) =>
   Object.prototype.hasOwnProperty.call(obj, key)
 
@@ -441,37 +442,6 @@ class Test extends Base {
     this[name] = ASSERT
   }
 
-  fail (message, extra) {
-    if (!this.currentAssert) {
-      this.currentAssert = Test.prototype.fail
-    }
-
-    if (message && typeof message === 'object') {
-      extra = message
-      message = ''
-    } else {
-      if (!message) {
-        message = ''
-      }
-      if (!extra) {
-        extra = {}
-      }
-    }
-
-    this.printResult(false, message, extra)
-
-    // if it's todo or skip, it's still technically passing
-    return !!(extra.todo || extra.skip)
-  }
-
-  pass (message, extra) {
-    if (!this.currentAssert) {
-      this.currentAssert = Test.prototype.pass
-    }
-    this.printResult(true, message || '(unnamed test)', extra)
-    return true
-  }
-
   printResult (ok, message, extra, front) {
     const n = this.count + 1
     if (this.planEnd !== -1 && n > this.planEnd) {
@@ -749,6 +719,499 @@ class Test extends Base {
     this.process()
     this.parser.end()
   }
+
+  pass (message, extra) {
+    if (!this.currentAssert)
+      this.currentAssert = Test.prototype.pass
+
+    if (message && typeof message === 'object')
+      extra = message, message = ''
+
+    if (!extra)
+      extra = {}
+
+    this.printResult(true, message || '(unnamed test)', extra)
+    return true
+  }
+
+  fail (message, extra) {
+    if (!this.currentAssert)
+      this.currentAssert = Test.prototype.fail
+
+    if (message && typeof message === 'object')
+      extra = message, message = ''
+
+    if (!extra)
+      extra = {}
+
+    this.printResult(false, message || '(unnamed test)', extra || {})
+    return !!(extra.todo || extra.skip)
+  }
+
+  ok (obj, message, extra) {
+    if (!this.currentAssert)
+      this.currentAssert = Test.prototype.ok
+
+    if (message && typeof message === 'object')
+      extra = message, message = ''
+
+    if (!extra)
+      extra = {}
+    message = message || 'expect truthy value'
+    return obj ? this.pass(message, extra) : this.fail(message, extra)
+  }
+
+  notOk (obj, message, extra) {
+    if (!this.currentAssert)
+      this.currentAssert = Test.prototype.notOk
+
+    if (message && typeof message === 'object')
+      extra = message, message = ''
+
+    if (!extra)
+      extra = {}
+    message = message || 'expect falsey value'
+    return this.ok(!obj, message, extra)
+  }
+
+  error (er, message, extra) {
+    if (!this.currentAssert)
+      this.currentAssert = Test.prototype.error
+
+    if (message && typeof message === 'object')
+      extra = message, message = ''
+
+    if (!extra)
+      extra = {}
+
+    if (!er) {
+      return this.pass(message || 'should not error', extra)
+    }
+
+    if (!(er instanceof Error)) {
+      extra.found = er
+      return this.fail(message || 'non-Error error encountered', extra)
+    }
+
+    message = message || er.message
+    extra.found = er
+    return this.fail(message, extra)
+  }
+
+  equal (found, wanted, message, extra) {
+    if (!this.currentAssert)
+      this.currentAssert = Test.prototype.equal
+
+    if (message && typeof message === 'object')
+      extra = message, message = ''
+
+    if (!extra)
+      extra = {}
+
+    message = message || 'should be equal'
+    if (found === wanted) {
+      return this.pass(message, extra)
+    }
+
+    extra.found = found
+    extra.wanted = wanted
+    extra.compare = '==='
+
+    if (typeof found === 'object' &&
+        typeof wanted === 'object' &&
+        found &&
+        wanted &&
+        tsame(found, wanted)) {
+      extra.note = 'Objects never === one another'
+    }
+
+    return this.fail(message, extra)
+  }
+
+  not (found, wanted, message, extra) {
+    if (!this.currentAssert)
+      this.currentAssert = Test.prototype.not
+
+    if (message && typeof message === 'object')
+      extra = message, message = ''
+
+    if (!extra)
+      extra = {}
+
+    message = message || 'should not be equal'
+    if (found !== wanted) {
+      return this.pass(message, extra)
+    }
+
+    extra.found = found
+    extra.doNotWant = wanted
+    extra.compare = '!=='
+
+    return this.fail(message, extra)
+  }
+
+  same (found, wanted, message, extra) {
+    if (!this.currentAssert)
+      this.currentAssert = Test.prototype.same
+
+    if (message && typeof message === 'object')
+      extra = message, message = ''
+
+    if (!extra)
+      extra = {}
+
+    message = message || 'should be equivalent'
+    extra.found = found
+    extra.wanted = wanted
+    return this.ok(tsame(found, wanted), message, extra)
+  }
+
+  notSame (found, wanted, message, extra) {
+    if (!this.currentAssert)
+      this.currentAssert = Test.prototype.notSame
+
+    if (message && typeof message === 'object')
+      extra = message, message = ''
+
+    if (!extra)
+      extra = {}
+
+    message = message || 'should not be equivalent'
+    extra.found = found
+    extra.doNotWant = wanted
+    return this.notOk(tsame(found, wanted), message, extra)
+  }
+
+  strictSame (found, wanted, message, extra) {
+    if (!this.currentAssert)
+      this.currentAssert = Test.prototype.strictSame
+
+    if (message && typeof message === 'object')
+      extra = message, message = ''
+
+    if (!extra)
+      extra = {}
+
+    message = message || 'should be equivalent strictly'
+    extra.found = found
+    extra.wanted = wanted
+    return this.ok(tsame.strict(found, wanted), message, extra)
+  }
+
+  strictNotSame (found, wanted, message, extra) {
+    if (!this.currentAssert)
+      this.currentAssert = Test.prototype.strictNotSame
+
+    if (message && typeof message === 'object')
+      extra = message, message = ''
+
+    if (!extra)
+      extra = {}
+
+    message = message || 'should be equivalent strictly'
+    extra.found = found
+    extra.doNotWant = wanted
+    return this.notOk(tsame.strict(found, wanted), message, extra)
+  }
+
+  match (found, wanted, message, extra) {
+    if (!this.currentAssert)
+      this.currentAssert = Test.prototype.match
+
+    if (message && typeof message === 'object')
+      extra = message, message = ''
+
+    if (!extra)
+      extra = {}
+
+    message = message || 'should match pattern provided'
+    extra.found = found
+    extra.pattern = wanted
+    return this.ok(tmatch(found, wanted), message, extra)
+  }
+
+  notMatch (found, wanted, message, extra) {
+    if (!this.currentAssert)
+      this.currentAssert = Test.prototype.notMatch
+
+    if (message && typeof message === 'object')
+      extra = message, message = ''
+
+    if (!extra)
+      extra = {}
+
+    message = message || 'should not match pattern provided'
+    extra.found = found
+    extra.pattern = wanted
+    return this.ok(!tmatch(found, wanted), message, extra)
+  }
+
+  type (obj, klass, message, extra) {
+    if (!this.currentAssert)
+      this.currentAssert = Test.prototype.type
+
+    if (message && typeof message === 'object')
+      extra = message, message = ''
+
+    if (!extra)
+      extra = {}
+
+    const name = typeof klass === 'function' ?
+      klass.name || '(anonymous constructor)'
+      : klass
+
+    message = message || 'type is ' + name
+
+    // simplest case, it literally is the same thing
+    if (obj === klass) {
+      return this.pass(message, extra)
+    }
+
+    const tof = typeof obj
+    const type = (!obj && tof === 'object') ? 'null'
+      // treat as object, but not Object
+      // t.type(() => {}, Function)
+      : (tof === 'function' &&
+        typeof klass === 'function' &&
+        klass !== Object) ? 'object'
+      : tof
+
+    if (type === 'object' && klass !== 'object') {
+      if (typeof klass === 'function') {
+        extra.found = Object.getPrototypeOf(obj).constructor.name
+        extra.wanted = name
+        return this.ok(obj instanceof klass, message, extra)
+      }
+
+      // check prototype chain for name
+      // at this point, we already know klass is not a function
+      // if the klass specified is an obj in the proto chain, pass
+      // if the name specified is the name of a ctor in the chain, pass
+      for (let p = obj; p; p = Object.getPrototypeOf(p)) {
+        const ctor = p.constructor && p.constructor.name
+        if (p === klass || ctor === name) {
+          return this.pass(message, extra)
+        }
+      }
+    }
+
+    return this.equal(type, name, message, extra)
+  }
+
+  throws (_fn, _wanted, _message, _extra) {
+    if (!this.currentAssert)
+      this.currentAssert = Test.prototype.throws
+
+    let fn, wanted, message, extra
+    for (let i = 0; i < arguments.length; i++) {
+      const arg = arguments[i]
+      if (typeof arg === 'function') {
+        if (arg === Error || arg.prototype instanceof Error) {
+          wanted = arg
+        } else if (!fn) {
+          fn = arg
+        }
+      } else if (typeof arg === 'string' && arg) {
+        message = arg
+      } else if (typeof arg === 'object') {
+        if (!wanted) {
+          wanted = arg
+        } else {
+          extra = arg
+        }
+      }
+    }
+
+    if (message && typeof message === 'object')
+      extra = message, message = ''
+
+    if (!extra)
+      extra = {}
+
+    if (!message)
+      message = fn && fn.name || 'expected to throw'
+
+    if (wanted) {
+      if (wanted instanceof Error) {
+        const w = {
+          message: wanted.message
+        }
+        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) {
+          w[i] = wanted[i]
+        }
+        wanted = w
+
+        message += ': ' + (wanted.name || 'Error') + ' ' + wanted.message
+        extra = extra || {}
+        if (extra !== wanted) {
+          extra.wanted = wanted
+        }
+      }
+    }
+
+    if (typeof fn !== 'function') {
+      extra = extra || {}
+      extra.todo = true
+      return this.pass(message, extra)
+    }
+
+    try {
+      fn()
+      return this.fail(message, extra)
+    } catch (er) {
+      // 'name' is a getter.
+      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)
+      }
+    }
+  }
+
+  doesNotThrow (fn, message, extra) {
+    if (!this.currentAssert)
+      this.currentAssert = Test.prototype.doesNotThrow
+
+    if (message && typeof message === 'object')
+      extra = message, message = ''
+
+    if (!extra)
+      extra = {}
+
+    if (typeof fn === 'string') {
+      const x = fn
+      fn = message
+      message = x
+    }
+
+    if (!message) {
+      message = fn && fn.name || 'expected to not throw'
+    }
+
+    if (typeof fn !== 'function') {
+      extra.todo = true
+      return this.pass(message, extra)
+    }
+
+    try {
+      fn()
+      return this.pass(message, extra)
+    } catch (er) {
+      const e = extraFromError(er, extra)
+      e.message = er.message
+      return this.fail(message, e)
+    }
+  }
+
+  // like throws, but rejects a returned promise instead
+  // also, can pass in a promise instead of a function
+  rejects (_fn, _wanted, _message, _extra) {
+    if (!this.currentAssert)
+      this.currentAssert = Test.prototype.rejects
+
+    let fn, wanted, extra, promise, message
+    for (let i = 0; i < arguments.length; i++) {
+      const arg = arguments[i]
+      if (typeof arg === 'function') {
+        if (arg === Error || arg.prototype instanceof Error) {
+          wanted = arg
+        } else if (!fn) {
+          fn = arg
+        }
+      } else if (typeof arg === 'string' && arg) {
+        message = arg
+      } else if (arg && typeof arg.then === 'function' && !promise) {
+        promise = arg
+      } else if (typeof arg === 'object') {
+        if (!wanted) {
+          wanted = arg
+        } else {
+          extra = arg
+        }
+      }
+    }
+
+    if (message && typeof message === 'object')
+      extra = message, message = ''
+
+    if (!extra)
+      extra = {}
+
+    if (!message)
+      message = fn && fn.name || 'expect rejected Promise'
+
+    if (wanted) {
+      if (wanted instanceof Error) {
+        const w = {
+          message: wanted.message
+        }
+        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) {
+          w[i] = wanted[i]
+        }
+        wanted = w
+
+        message += ': ' + (wanted.name || 'Error') + ' ' + wanted.message
+        extra = extra || {}
+        if (extra !== wanted) {
+          extra.wanted = wanted
+        }
+      }
+    }
+
+    if (!promise && typeof fn !== 'function') {
+      extra = extra || {}
+      extra.todo = true
+      return this.pass(message, extra)
+    }
+
+    if (!promise)
+      promise = fn()
+
+    if (!promise || typeof promise.then !== 'function')
+      return this.fail(message, extra)
+
+    // have to do as a subtest, because promises are async
+    extra.at = stack.at(this.currentAssert)
+    this.test(message, { buffered: true }, function (t) {
+      return promise.then(function (value) {
+        extra.found = value
+        t.fail(message, extra)
+      }, function (er) {
+        // 'name' is a getter.
+        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.has(er, wanted, message, extra)
+        } else {
+          return t.pass(message, extra)
+        }
+      })
+    })
+  }
 }
 
 const endAllQueue = queue => {
@@ -768,7 +1231,14 @@ const queueEmpty = t =>
 Test.prototype.done = Test.prototype.end
 Test.prototype.tearDown = Test.prototype.teardown
 
-// Add all the asserts
-tapAsserts.decorate(Test.prototype)
+Object.keys(synonyms)
+  .filter(c => Test.prototype[c])
+  .forEach(c => synonyms[c].forEach(s =>
+    Object.defineProperty(Test.prototype, s, {
+      value: Test.prototype[c],
+      enumerable: false,
+      configurable: true,
+      writable: true
+    })))
 
 module.exports = Test

-- 
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