Files
enviPy-bayer/static/js/ketcher2/node_modules/tap/lib/asserts.js
2025-06-23 20:13:54 +02:00

390 lines
9.5 KiB
JavaScript

var synonyms = require('./synonyms.js')
var tsame = require('tsame') // same thing, strict or not
var tmatch = require('tmatch') // ok with partial estimates
var extraFromError = require('./extra-from-error.js')
var stack = require('./stack.js')
// Load Buffer the old way for browserify's sake
var Buffer = require('buffer').Buffer // eslint-disable-line
// this is actually the "working half" of the Test class.
// each method figures out if it's a pass or fail, and decorates
// the extra bit, and then calls either pass() or fail() or some
// other assert method.
//
// typically, a plugin would do this on a specific instance, eg on
// the root test harness instance. but we do this here to add some
// useful prototype methods.
exports.decorate = decorate
function decorate (t) {
t.addAssert('ok', 1, function (obj, message, extra) {
message = message || 'expect truthy value'
if (obj) {
return this.pass(message, extra)
}
return this.fail(message, extra)
})
t.addAssert('notOk', 1, function (obj, message, extra) {
message = message || 'expect falsey value'
return this.ok(!obj, message, extra)
})
t.addAssert('error', 1, function (er, message, 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)
})
t.addAssert('equal', 2, function (f, w, m, e) {
m = m || 'should be equal'
if (f === w) {
return this.pass(m, e)
}
e.found = f
e.wanted = w
e.compare = '==='
if (typeof f === 'object' &&
typeof w === 'object' &&
f &&
w &&
tsame(f, w)) {
e.note = 'Objects never === one another'
}
return this.fail(m, e)
})
t.addAssert('not', 2, function (f, w, m, e) {
m = m || 'should not be equal'
if (f !== w) {
return this.pass(m, e)
}
e.found = f
e.doNotWant = w
e.compare = '!=='
return this.fail(m, e)
})
t.addAssert('same', 2, function (f, w, m, e) {
m = m || 'should be equivalent'
e.found = f
e.wanted = w
return this.ok(tsame(f, w), m, e)
})
t.addAssert('notSame', 2, function (f, w, m, e) {
m = m || 'should not be equivalent'
e.found = f
e.doNotWant = w
return this.notOk(tsame(f, w), m, e)
})
t.addAssert('strictSame', 2, function (f, w, m, e) {
m = m || 'should be equivalent strictly'
e.found = f
e.wanted = w
return this.ok(tsame.strict(f, w), m, e)
})
t.addAssert('strictNotSame', 2, function (f, w, m, e) {
m = m || 'should be equivalent strictly'
e.found = f
e.doNotWant = w
return this.notOk(tsame.strict(f, w), m, e)
})
t.addAssert('match', 2, function (f, w, m, e) {
m = m || 'should match pattern provided'
e.found = f
e.pattern = w
return this.ok(tmatch(f, w), m, e)
})
t.addAssert('notMatch', 2, function (f, w, m, e) {
m = m || 'should not match pattern provided'
e.found = f
e.pattern = w
return this.ok(!tmatch(f, w), m, e)
})
t.addAssert('type', 2, function (obj, klass, m, e) {
var name = klass
if (typeof name === 'function') {
name = name.name || '(anonymous constructor)'
}
m = m || 'type is ' + name
// simplest case, it literally is the same thing
if (obj === klass) {
return this.pass(m, e)
}
var type = typeof obj
if (!obj && type === 'object') {
type = 'null'
}
if (type === 'function' &&
typeof klass === 'function' &&
klass !== Object) {
// treat as object, but not Object
// t.type(() => {}, Function)
type = 'object'
}
if (type === 'object' && klass !== 'object') {
if (typeof klass === 'function') {
e.found = Object.getPrototypeOf(obj).constructor.name
e.wanted = name
return this.ok(obj instanceof klass, m, e)
}
// 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
var p = obj
do {
var ctor = p.constructor && p.constructor.name
if (p === klass || ctor === name) {
return this.pass(m, e)
}
p = Object.getPrototypeOf(p)
} while (p)
}
return this.equal(type, name, m, e)
})
t.addAssert('throws', 4, function (fn_, wanted_, m_, e_, m, e__) {
var fn, wanted, e
for (var i = 0; i < arguments.length - 1; i++) {
var 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) {
m = arg
} else if (typeof arg === 'object') {
if (!wanted) {
wanted = arg
} else {
e = arg
}
}
}
// Copy local properties of the 'extra' object, like 'skip' etc
Object.keys(e__).forEach(function (i) {
e[i] = e__[i]
})
if (!m) {
m = fn && fn.name || 'expected to throw'
}
if (wanted) {
if (wanted instanceof Error) {
var 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
m += ': ' + (wanted.name || 'Error') + ' ' + wanted.message
e = e || {}
if (e !== wanted) {
e.wanted = wanted
}
}
}
if (typeof fn !== 'function') {
e = e || {}
e.todo = true
return this.pass(m, e)
}
try {
fn()
return this.fail(m, e)
} 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, m, e)
}
return this.has(er, wanted, m, e)
} else {
return this.pass(m, e)
}
}
})
t.addAssert('doesNotThrow', 1, function (fn, m, e) {
if (typeof fn === 'string') {
var x = fn
fn = m
m = x
}
if (!m) {
m = fn && fn.name || 'expected to not throw'
}
if (typeof fn !== 'function') {
e.todo = true
return this.pass(m, e)
}
try {
fn()
return this.pass(m, e)
} catch (er) {
var extra = extraFromError(er, e)
extra.message = er.message
return this.fail(m, extra)
}
})
// like throws, but rejects a returned promise instead
// also, can pass in a promise instead of a function
t.addAssert('rejects', 4, function (fn_, wanted_, m_, e_, m, e__) {
var fn, wanted, e, promise
for (var i = 0; i < arguments.length - 1; i++) {
var 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) {
m = arg
} else if (arg && typeof arg.then === 'function' && !promise) {
promise = arg
} else if (typeof arg === 'object') {
if (!wanted) {
wanted = arg
} else {
e = arg
}
}
}
// Copy local properties of the 'extra' object, like 'skip' etc
Object.keys(e__).forEach(function (i) {
e[i] = e__[i]
})
if (!m) {
m = fn && fn.name || 'expect rejected Promise'
}
if (wanted) {
if (wanted instanceof Error) {
var 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
m += ': ' + (wanted.name || 'Error') + ' ' + wanted.message
e = e || {}
if (e !== wanted) {
e.wanted = wanted
}
}
}
if (!promise && typeof fn !== 'function') {
e = e || {}
e.todo = true
return this.pass(m, e)
}
if (!promise)
promise = fn()
if (!promise || typeof promise.then !== 'function')
return this.fail(m, e)
// have to do as a subtest, because promises are async
e.at = stack.at(this.currentAssert)
this.test(m, { buffered: true }, function (t) {
return promise.then(function (value) {
e.found = value
t.fail(m, e)
}, 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, m, e)
}
return t.has(er, wanted, m, e)
} else {
return t.pass(m, e)
}
})
})
})
// synonyms are helpful.
Object.keys(synonyms).forEach(function (c) {
if (t[c]) {
synonyms[c].forEach(function (s) {
Object.defineProperty(t, s, {
value: t[c],
enumerable: false,
configurable: true,
writable: true
})
})
}
})
}