Added some tests
This commit is contained in:
32
tests/node_modules/tape/lib/default_stream.js
generated
vendored
Normal file
32
tests/node_modules/tape/lib/default_stream.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
'use strict';
|
||||
|
||||
var through = require('through');
|
||||
var fs = require('fs');
|
||||
|
||||
module.exports = function () {
|
||||
var line = '';
|
||||
var stream = through(write, flush);
|
||||
return stream;
|
||||
|
||||
function write(buf) {
|
||||
for (var i = 0; i < buf.length; i++) {
|
||||
var c = typeof buf === 'string'
|
||||
? buf.charAt(i)
|
||||
: String.fromCharCode(buf[i])
|
||||
;
|
||||
if (c === '\n') flush();
|
||||
else line += c;
|
||||
}
|
||||
}
|
||||
|
||||
function flush() {
|
||||
if (fs.writeSync && /^win/.test(process.platform)) {
|
||||
try { fs.writeSync(1, line + '\n'); }
|
||||
catch (e) { stream.emit('error', e); }
|
||||
} else {
|
||||
try { console.log(line); }
|
||||
catch (e) { stream.emit('error', e); }
|
||||
}
|
||||
line = '';
|
||||
}
|
||||
};
|
||||
220
tests/node_modules/tape/lib/results.js
generated
vendored
Normal file
220
tests/node_modules/tape/lib/results.js
generated
vendored
Normal file
@@ -0,0 +1,220 @@
|
||||
'use strict';
|
||||
|
||||
var defined = require('defined');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var inherits = require('inherits');
|
||||
var through = require('through');
|
||||
var resumer = require('resumer');
|
||||
var inspect = require('object-inspect');
|
||||
var callBound = require('call-bind/callBound');
|
||||
var has = require('has');
|
||||
var regexpTest = callBound('RegExp.prototype.test');
|
||||
var $split = callBound('String.prototype.split');
|
||||
var $replace = callBound('String.prototype.replace');
|
||||
var $shift = callBound('Array.prototype.shift');
|
||||
var $push = callBound('Array.prototype.push');
|
||||
var yamlIndicators = /:|-|\?/;
|
||||
var nextTick = typeof setImmediate !== 'undefined'
|
||||
? setImmediate
|
||||
: process.nextTick
|
||||
;
|
||||
|
||||
module.exports = Results;
|
||||
inherits(Results, EventEmitter);
|
||||
|
||||
function coalesceWhiteSpaces(str) {
|
||||
return $replace(String(str), /\s+/g, ' ');
|
||||
}
|
||||
|
||||
function Results() {
|
||||
if (!(this instanceof Results)) return new Results;
|
||||
this.count = 0;
|
||||
this.fail = 0;
|
||||
this.pass = 0;
|
||||
this.todo = 0;
|
||||
this._stream = through();
|
||||
this.tests = [];
|
||||
this._only = null;
|
||||
this._isRunning = false;
|
||||
}
|
||||
|
||||
Results.prototype.createStream = function (opts) {
|
||||
if (!opts) opts = {};
|
||||
var self = this;
|
||||
var output, testId = 0;
|
||||
if (opts.objectMode) {
|
||||
output = through();
|
||||
self.on('_push', function ontest(t, extra) {
|
||||
if (!extra) extra = {};
|
||||
var id = testId++;
|
||||
t.once('prerun', function () {
|
||||
var row = {
|
||||
type: 'test',
|
||||
name: t.name,
|
||||
id: id,
|
||||
skip: t._skip,
|
||||
todo: t._todo
|
||||
};
|
||||
if (has(extra, 'parent')) {
|
||||
row.parent = extra.parent;
|
||||
}
|
||||
output.queue(row);
|
||||
});
|
||||
t.on('test', function (st) {
|
||||
ontest(st, { parent: id });
|
||||
});
|
||||
t.on('result', function (res) {
|
||||
if (res && typeof res === 'object') {
|
||||
res.test = id;
|
||||
res.type = 'assert';
|
||||
}
|
||||
output.queue(res);
|
||||
});
|
||||
t.on('end', function () {
|
||||
output.queue({ type: 'end', test: id });
|
||||
});
|
||||
});
|
||||
self.on('done', function () { output.queue(null); });
|
||||
} else {
|
||||
output = resumer();
|
||||
output.queue('TAP version 13\n');
|
||||
self._stream.pipe(output);
|
||||
}
|
||||
|
||||
if (!this._isRunning) {
|
||||
this._isRunning = true;
|
||||
nextTick(function next() {
|
||||
var t;
|
||||
while (t = getNextTest(self)) {
|
||||
t.run();
|
||||
if (!t.ended) return t.once('end', function () { nextTick(next); });
|
||||
}
|
||||
self.emit('done');
|
||||
});
|
||||
}
|
||||
|
||||
return output;
|
||||
};
|
||||
|
||||
Results.prototype.push = function (t) {
|
||||
var self = this;
|
||||
$push(self.tests, t);
|
||||
self._watch(t);
|
||||
self.emit('_push', t);
|
||||
};
|
||||
|
||||
Results.prototype.only = function (t) {
|
||||
this._only = t;
|
||||
};
|
||||
|
||||
Results.prototype._watch = function (t) {
|
||||
var self = this;
|
||||
var write = function (s) { self._stream.queue(s); };
|
||||
t.once('prerun', function () {
|
||||
var premsg = '';
|
||||
if (t._skip) premsg = 'SKIP ';
|
||||
else if (t._todo) premsg = 'TODO ';
|
||||
write('# ' + premsg + coalesceWhiteSpaces(t.name) + '\n');
|
||||
});
|
||||
|
||||
t.on('result', function (res) {
|
||||
if (typeof res === 'string') {
|
||||
write('# ' + res + '\n');
|
||||
return;
|
||||
}
|
||||
write(encodeResult(res, self.count + 1));
|
||||
self.count++;
|
||||
|
||||
if (res.ok || res.todo) self.pass++;
|
||||
else {
|
||||
self.fail++;
|
||||
self.emit('fail');
|
||||
}
|
||||
});
|
||||
|
||||
t.on('test', function (st) { self._watch(st); });
|
||||
};
|
||||
|
||||
Results.prototype.close = function () {
|
||||
var self = this;
|
||||
if (self.closed) self._stream.emit('error', new Error('ALREADY CLOSED'));
|
||||
self.closed = true;
|
||||
var write = function (s) { self._stream.queue(s); };
|
||||
|
||||
write('\n1..' + self.count + '\n');
|
||||
write('# tests ' + self.count + '\n');
|
||||
write('# pass ' + (self.pass + self.todo) + '\n');
|
||||
if (self.todo) write('# todo ' + self.todo + '\n');
|
||||
if (self.fail) write('# fail ' + self.fail + '\n');
|
||||
else write('\n# ok\n');
|
||||
|
||||
self._stream.queue(null);
|
||||
};
|
||||
|
||||
function encodeResult(res, count) {
|
||||
var output = '';
|
||||
output += (res.ok ? 'ok ' : 'not ok ') + count;
|
||||
output += res.name ? ' ' + coalesceWhiteSpaces(res.name) : '';
|
||||
|
||||
if (res.skip) {
|
||||
output += ' # SKIP' + ((typeof res.skip === 'string') ? ' ' + coalesceWhiteSpaces(res.skip) : '');
|
||||
} else if (res.todo) {
|
||||
output += ' # TODO' + ((typeof res.todo === 'string') ? ' ' + coalesceWhiteSpaces(res.todo) : '');
|
||||
};
|
||||
|
||||
output += '\n';
|
||||
if (res.ok) return output;
|
||||
|
||||
var outer = ' ';
|
||||
var inner = outer + ' ';
|
||||
output += outer + '---\n';
|
||||
output += inner + 'operator: ' + res.operator + '\n';
|
||||
|
||||
if (has(res, 'expected') || has(res, 'actual')) {
|
||||
var ex = inspect(res.expected, {depth: res.objectPrintDepth});
|
||||
var ac = inspect(res.actual, {depth: res.objectPrintDepth});
|
||||
|
||||
if (Math.max(ex.length, ac.length) > 65 || invalidYaml(ex) || invalidYaml(ac)) {
|
||||
output += inner + 'expected: |-\n' + inner + ' ' + ex + '\n';
|
||||
output += inner + 'actual: |-\n' + inner + ' ' + ac + '\n';
|
||||
} else {
|
||||
output += inner + 'expected: ' + ex + '\n';
|
||||
output += inner + 'actual: ' + ac + '\n';
|
||||
}
|
||||
}
|
||||
if (res.at) {
|
||||
output += inner + 'at: ' + res.at + '\n';
|
||||
}
|
||||
|
||||
var actualStack = res.actual && (typeof res.actual === 'object' || typeof res.actual === 'function') ? res.actual.stack : undefined;
|
||||
var errorStack = res.error && res.error.stack;
|
||||
var stack = defined(actualStack, errorStack);
|
||||
if (stack) {
|
||||
var lines = $split(String(stack), '\n');
|
||||
output += inner + 'stack: |-\n';
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
output += inner + ' ' + lines[i] + '\n';
|
||||
}
|
||||
}
|
||||
|
||||
output += outer + '...\n';
|
||||
return output;
|
||||
}
|
||||
|
||||
function getNextTest(results) {
|
||||
if (!results._only) {
|
||||
return $shift(results.tests);
|
||||
}
|
||||
|
||||
do {
|
||||
var t = $shift(results.tests);
|
||||
if (!t) continue;
|
||||
if (results._only === t) {
|
||||
return t;
|
||||
}
|
||||
} while (results.tests.length !== 0);
|
||||
}
|
||||
|
||||
function invalidYaml(str) {
|
||||
return regexpTest(yamlIndicators, str);
|
||||
}
|
||||
750
tests/node_modules/tape/lib/test.js
generated
vendored
Normal file
750
tests/node_modules/tape/lib/test.js
generated
vendored
Normal file
@@ -0,0 +1,750 @@
|
||||
'use strict';
|
||||
|
||||
var deepEqual = require('deep-equal');
|
||||
var defined = require('defined');
|
||||
var path = require('path');
|
||||
var inherits = require('inherits');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var has = require('has');
|
||||
var isRegExp = require('is-regex');
|
||||
var trim = require('string.prototype.trim');
|
||||
var callBound = require('call-bind/callBound');
|
||||
var forEach = require('for-each');
|
||||
var inspect = require('object-inspect');
|
||||
var is = require('object-is');
|
||||
var isEnumerable = callBound('Object.prototype.propertyIsEnumerable');
|
||||
var toLowerCase = callBound('String.prototype.toLowerCase');
|
||||
var isProto = callBound('Object.prototype.isPrototypeOf');
|
||||
var $test = callBound('RegExp.prototype.test');
|
||||
var objectToString = callBound('Object.prototype.toString');
|
||||
var $split = callBound('String.prototype.split');
|
||||
var $replace = callBound('String.prototype.replace');
|
||||
var $strSlice = callBound('String.prototype.slice');
|
||||
var $push = callBound('Array.prototype.push');
|
||||
var $shift = callBound('Array.prototype.shift');
|
||||
|
||||
module.exports = Test;
|
||||
|
||||
var nextTick = typeof setImmediate !== 'undefined'
|
||||
? setImmediate
|
||||
: process.nextTick;
|
||||
var safeSetTimeout = setTimeout;
|
||||
var safeClearTimeout = clearTimeout;
|
||||
|
||||
inherits(Test, EventEmitter);
|
||||
|
||||
var getTestArgs = function (name_, opts_, cb_) {
|
||||
var name = '(anonymous)';
|
||||
var opts = {};
|
||||
var cb;
|
||||
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
var arg = arguments[i];
|
||||
var t = typeof arg;
|
||||
if (t === 'string') {
|
||||
name = arg;
|
||||
} else if (t === 'object') {
|
||||
opts = arg || opts;
|
||||
} else if (t === 'function') {
|
||||
cb = arg;
|
||||
}
|
||||
}
|
||||
return { name: name, opts: opts, cb: cb };
|
||||
};
|
||||
|
||||
function Test(name_, opts_, cb_) {
|
||||
if (!(this instanceof Test)) {
|
||||
return new Test(name_, opts_, cb_);
|
||||
}
|
||||
|
||||
var args = getTestArgs(name_, opts_, cb_);
|
||||
|
||||
this.readable = true;
|
||||
this.name = args.name || '(anonymous)';
|
||||
this.assertCount = 0;
|
||||
this.pendingCount = 0;
|
||||
this._skip = args.opts.skip || false;
|
||||
this._todo = args.opts.todo || false;
|
||||
this._timeout = args.opts.timeout;
|
||||
this._plan = undefined;
|
||||
this._cb = args.cb;
|
||||
this._progeny = [];
|
||||
this._teardown = [];
|
||||
this._ok = true;
|
||||
var depthEnvVar = process.env.NODE_TAPE_OBJECT_PRINT_DEPTH;
|
||||
if (args.opts.objectPrintDepth) {
|
||||
this._objectPrintDepth = args.opts.objectPrintDepth;
|
||||
} else if (depthEnvVar) {
|
||||
if (toLowerCase(depthEnvVar) === 'infinity') {
|
||||
this._objectPrintDepth = Infinity;
|
||||
} else {
|
||||
this._objectPrintDepth = depthEnvVar;
|
||||
}
|
||||
} else {
|
||||
this._objectPrintDepth = 5;
|
||||
}
|
||||
|
||||
for (var prop in this) {
|
||||
this[prop] = (function bind(self, val) {
|
||||
if (typeof val === 'function') {
|
||||
return function bound() {
|
||||
return val.apply(self, arguments);
|
||||
};
|
||||
}
|
||||
return val;
|
||||
})(this, this[prop]);
|
||||
}
|
||||
}
|
||||
|
||||
Test.prototype.run = function () {
|
||||
this.emit('prerun');
|
||||
if (!this._cb || this._skip) {
|
||||
return this._end();
|
||||
}
|
||||
if (this._timeout != null) {
|
||||
this.timeoutAfter(this._timeout);
|
||||
}
|
||||
|
||||
var callbackReturn = this._cb(this);
|
||||
|
||||
if (
|
||||
typeof Promise === 'function'
|
||||
&& callbackReturn
|
||||
&& typeof callbackReturn.then === 'function'
|
||||
) {
|
||||
var self = this;
|
||||
Promise.resolve(callbackReturn).then(function onResolve() {
|
||||
if (!self.calledEnd) {
|
||||
self.end();
|
||||
}
|
||||
})['catch'](function onError(err) {
|
||||
if (err instanceof Error || objectToString(err) === '[object Error]') {
|
||||
self.ifError(err);
|
||||
} else {
|
||||
self.fail(err);
|
||||
}
|
||||
self.end();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.emit('run');
|
||||
};
|
||||
|
||||
Test.prototype.test = function (name, opts, cb) {
|
||||
var self = this;
|
||||
var t = new Test(name, opts, cb);
|
||||
$push(this._progeny, t);
|
||||
this.pendingCount++;
|
||||
this.emit('test', t);
|
||||
t.on('prerun', function () {
|
||||
self.assertCount++;
|
||||
});
|
||||
|
||||
if (!self._pendingAsserts()) {
|
||||
nextTick(function () {
|
||||
self._end();
|
||||
});
|
||||
}
|
||||
|
||||
nextTick(function () {
|
||||
if (!self._plan && self.pendingCount == self._progeny.length) {
|
||||
self._end();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Test.prototype.comment = function (msg) {
|
||||
var that = this;
|
||||
forEach($split(trim(msg), '\n'), function (aMsg) {
|
||||
that.emit('result', $replace(trim(aMsg), /^#\s*/, ''));
|
||||
});
|
||||
};
|
||||
|
||||
Test.prototype.plan = function (n) {
|
||||
this._plan = n;
|
||||
this.emit('plan', n);
|
||||
};
|
||||
|
||||
Test.prototype.timeoutAfter = function (ms) {
|
||||
if (!ms) throw new Error('timeoutAfter requires a timespan');
|
||||
var self = this;
|
||||
var timeout = safeSetTimeout(function () {
|
||||
self.fail(self.name + ' timed out after ' + ms + 'ms');
|
||||
self.end();
|
||||
}, ms);
|
||||
this.once('end', function () {
|
||||
safeClearTimeout(timeout);
|
||||
});
|
||||
};
|
||||
|
||||
Test.prototype.end = function (err) {
|
||||
var self = this;
|
||||
if (arguments.length >= 1 && !!err) {
|
||||
this.ifError(err);
|
||||
}
|
||||
|
||||
if (this.calledEnd) {
|
||||
this.fail('.end() already called');
|
||||
}
|
||||
this.calledEnd = true;
|
||||
this._end();
|
||||
};
|
||||
|
||||
Test.prototype.teardown = function (fn) {
|
||||
if (typeof fn !== 'function') {
|
||||
this.fail('teardown: ' + inspect(fn) + ' is not a function');
|
||||
} else {
|
||||
this._teardown.push(fn);
|
||||
}
|
||||
};
|
||||
|
||||
Test.prototype._end = function (err) {
|
||||
var self = this;
|
||||
|
||||
if (!this._cb && !this._todo && !this._skip) this.fail('# TODO ' + this.name);
|
||||
|
||||
if (this._progeny.length) {
|
||||
var t = $shift(this._progeny);
|
||||
t.on('end', function () { self._end(); });
|
||||
t.run();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
function next() {
|
||||
if (self._teardown.length === 0) {
|
||||
completeEnd();
|
||||
return;
|
||||
}
|
||||
var fn = self._teardown.shift();
|
||||
var res;
|
||||
try {
|
||||
res = fn();
|
||||
} catch (e) {
|
||||
self.fail(e);
|
||||
}
|
||||
if (res && typeof res.then === 'function') {
|
||||
res.then(next, function (_err) {
|
||||
err = err || _err;
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
|
||||
function completeEnd() {
|
||||
if (!self.ended) self.emit('end');
|
||||
var pendingAsserts = self._pendingAsserts();
|
||||
if (!self._planError && self._plan !== undefined && pendingAsserts) {
|
||||
self._planError = true;
|
||||
self.fail('plan != count', {
|
||||
expected: self._plan,
|
||||
actual: self.assertCount
|
||||
});
|
||||
}
|
||||
self.ended = true;
|
||||
}
|
||||
};
|
||||
|
||||
Test.prototype._exit = function () {
|
||||
if (this._plan !== undefined && !this._planError && this.assertCount !== this._plan) {
|
||||
this._planError = true;
|
||||
this.fail('plan != count', {
|
||||
expected: this._plan,
|
||||
actual: this.assertCount,
|
||||
exiting: true
|
||||
});
|
||||
} else if (!this.ended) {
|
||||
this.fail('test exited without ending: ' + this.name, {
|
||||
exiting: true
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Test.prototype._pendingAsserts = function () {
|
||||
if (this._plan === undefined) {
|
||||
return 1;
|
||||
}
|
||||
return this._plan - (this._progeny.length + this.assertCount);
|
||||
};
|
||||
|
||||
Test.prototype._assert = function assert(ok, opts) {
|
||||
var self = this;
|
||||
var extra = opts.extra || {};
|
||||
|
||||
ok = !!ok || !!extra.skip;
|
||||
|
||||
var name = defined(extra.message, opts.message, '(unnamed assert)');
|
||||
if (this.calledEnd && opts.operator !== 'fail') {
|
||||
this.fail('.end() already called: ' + name);
|
||||
return;
|
||||
}
|
||||
|
||||
var res = {
|
||||
id: self.assertCount++,
|
||||
ok: ok,
|
||||
skip: defined(extra.skip, opts.skip),
|
||||
todo: defined(extra.todo, opts.todo, self._todo),
|
||||
name: name,
|
||||
operator: defined(extra.operator, opts.operator),
|
||||
objectPrintDepth: self._objectPrintDepth
|
||||
};
|
||||
if (has(opts, 'actual') || has(extra, 'actual')) {
|
||||
res.actual = defined(extra.actual, opts.actual);
|
||||
}
|
||||
if (has(opts, 'expected') || has(extra, 'expected')) {
|
||||
res.expected = defined(extra.expected, opts.expected);
|
||||
}
|
||||
this._ok = !!(this._ok && ok);
|
||||
|
||||
if (!ok && !res.todo) {
|
||||
res.error = defined(extra.error, opts.error, new Error(res.name));
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
var e = new Error('exception');
|
||||
var err = $split(e.stack || '', '\n');
|
||||
var dir = __dirname + path.sep;
|
||||
|
||||
for (var i = 0; i < err.length; i++) {
|
||||
/*
|
||||
Stack trace lines may resemble one of the following. We need
|
||||
to correctly extract a function name (if any) and path / line
|
||||
number for each line.
|
||||
|
||||
at myFunction (/path/to/file.js:123:45)
|
||||
at myFunction (/path/to/file.other-ext:123:45)
|
||||
at myFunction (/path to/file.js:123:45)
|
||||
at myFunction (C:\path\to\file.js:123:45)
|
||||
at myFunction (/path/to/file.js:123)
|
||||
at Test.<anonymous> (/path/to/file.js:123:45)
|
||||
at Test.bound [as run] (/path/to/file.js:123:45)
|
||||
at /path/to/file.js:123:45
|
||||
|
||||
Regex has three parts. First is non-capturing group for 'at '
|
||||
(plus anything preceding it).
|
||||
|
||||
/^(?:[^\s]*\s*\bat\s+)/
|
||||
|
||||
Second captures function call description (optional). This is
|
||||
not necessarily a valid JS function name, but just what the
|
||||
stack trace is using to represent a function call. It may look
|
||||
like `<anonymous>` or 'Test.bound [as run]'.
|
||||
|
||||
For our purposes, we assume that, if there is a function
|
||||
name, it's everything leading up to the first open
|
||||
parentheses (trimmed) before our pathname.
|
||||
|
||||
/(?:(.*)\s+\()?/
|
||||
|
||||
Last part captures file path plus line no (and optional
|
||||
column no).
|
||||
|
||||
/((?:\/|[a-zA-Z]:\\)[^:\)]+:(\d+)(?::(\d+))?)\)?/
|
||||
*/
|
||||
var re = /^(?:[^\s]*\s*\bat\s+)(?:(.*)\s+\()?((?:\/|[a-zA-Z]:\\)[^:)]+:(\d+)(?::(\d+))?)\)?$/;
|
||||
var lineWithTokens = $replace($replace(err[i], process.cwd(), '/$CWD'), __dirname, '/$TEST');
|
||||
var m = re.exec(lineWithTokens);
|
||||
|
||||
if (!m) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var callDescription = m[1] || '<anonymous>';
|
||||
var filePath = $replace($replace(m[2], '/$CWD', process.cwd()), '/$TEST', __dirname);
|
||||
|
||||
if ($strSlice(filePath, 0, dir.length) === dir) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Function call description may not (just) be a function name.
|
||||
// Try to extract function name by looking at first "word" only.
|
||||
res.functionName = $split(callDescription, /\s+/)[0];
|
||||
res.file = filePath;
|
||||
res.line = Number(m[3]);
|
||||
if (m[4]) res.column = Number(m[4]);
|
||||
|
||||
res.at = callDescription + ' (' + filePath + ')';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
self.emit('result', res);
|
||||
|
||||
var pendingAsserts = self._pendingAsserts();
|
||||
if (!pendingAsserts) {
|
||||
if (extra.exiting) {
|
||||
self._end();
|
||||
} else {
|
||||
nextTick(function () {
|
||||
self._end();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!self._planError && pendingAsserts < 0) {
|
||||
self._planError = true;
|
||||
self.fail('plan != count', {
|
||||
expected: self._plan,
|
||||
actual: self._plan - pendingAsserts
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Test.prototype.fail = function (msg, extra) {
|
||||
this._assert(false, {
|
||||
message: msg,
|
||||
operator: 'fail',
|
||||
extra: extra
|
||||
});
|
||||
};
|
||||
|
||||
Test.prototype.pass = function (msg, extra) {
|
||||
this._assert(true, {
|
||||
message: msg,
|
||||
operator: 'pass',
|
||||
extra: extra
|
||||
});
|
||||
};
|
||||
|
||||
Test.prototype.skip = function (msg, extra) {
|
||||
this._assert(true, {
|
||||
message: msg,
|
||||
operator: 'skip',
|
||||
skip: true,
|
||||
extra: extra
|
||||
});
|
||||
};
|
||||
|
||||
function assert(value, msg, extra) {
|
||||
this._assert(value, {
|
||||
message: defined(msg, 'should be truthy'),
|
||||
operator: 'ok',
|
||||
expected: true,
|
||||
actual: value,
|
||||
extra: extra
|
||||
});
|
||||
}
|
||||
Test.prototype.ok
|
||||
= Test.prototype['true']
|
||||
= Test.prototype.assert
|
||||
= assert;
|
||||
|
||||
function notOK(value, msg, extra) {
|
||||
this._assert(!value, {
|
||||
message: defined(msg, 'should be falsy'),
|
||||
operator: 'notOk',
|
||||
expected: false,
|
||||
actual: value,
|
||||
extra: extra
|
||||
});
|
||||
}
|
||||
Test.prototype.notOk
|
||||
= Test.prototype['false']
|
||||
= Test.prototype.notok
|
||||
= notOK;
|
||||
|
||||
function error(err, msg, extra) {
|
||||
this._assert(!err, {
|
||||
message: defined(msg, String(err)),
|
||||
operator: 'error',
|
||||
error: err,
|
||||
extra: extra
|
||||
});
|
||||
}
|
||||
Test.prototype.error
|
||||
= Test.prototype.ifError
|
||||
= Test.prototype.ifErr
|
||||
= Test.prototype.iferror
|
||||
= error;
|
||||
|
||||
function strictEqual(a, b, msg, extra) {
|
||||
if (arguments.length < 2) {
|
||||
throw new TypeError('two arguments must be provided to compare');
|
||||
}
|
||||
this._assert(is(a, b), {
|
||||
message: defined(msg, 'should be strictly equal'),
|
||||
operator: 'equal',
|
||||
actual: a,
|
||||
expected: b,
|
||||
extra: extra
|
||||
});
|
||||
}
|
||||
Test.prototype.equal
|
||||
= Test.prototype.equals
|
||||
= Test.prototype.isEqual
|
||||
= Test.prototype.strictEqual
|
||||
= Test.prototype.strictEquals
|
||||
= Test.prototype.is
|
||||
= strictEqual;
|
||||
|
||||
function notStrictEqual(a, b, msg, extra) {
|
||||
if (arguments.length < 2) {
|
||||
throw new TypeError('two arguments must be provided to compare');
|
||||
}
|
||||
this._assert(!is(a, b), {
|
||||
message: defined(msg, 'should not be strictly equal'),
|
||||
operator: 'notEqual',
|
||||
actual: a,
|
||||
expected: b,
|
||||
extra: extra
|
||||
});
|
||||
}
|
||||
|
||||
Test.prototype.notEqual
|
||||
= Test.prototype.notEquals
|
||||
= Test.prototype.isNotEqual
|
||||
= Test.prototype.doesNotEqual
|
||||
= Test.prototype.isInequal
|
||||
= Test.prototype.notStrictEqual
|
||||
= Test.prototype.notStrictEquals
|
||||
= Test.prototype.isNot
|
||||
= Test.prototype.not
|
||||
= notStrictEqual;
|
||||
|
||||
function looseEqual(a, b, msg, extra) {
|
||||
if (arguments.length < 2) {
|
||||
throw new TypeError('two arguments must be provided to compare');
|
||||
}
|
||||
this._assert(a == b, {
|
||||
message: defined(msg, 'should be loosely equal'),
|
||||
operator: 'looseEqual',
|
||||
actual: a,
|
||||
expected: b,
|
||||
extra: extra
|
||||
});
|
||||
}
|
||||
|
||||
Test.prototype.looseEqual
|
||||
= Test.prototype.looseEquals
|
||||
= looseEqual;
|
||||
|
||||
function notLooseEqual(a, b, msg, extra) {
|
||||
if (arguments.length < 2) {
|
||||
throw new TypeError('two arguments must be provided to compare');
|
||||
}
|
||||
this._assert(a != b, {
|
||||
message: defined(msg, 'should not be loosely equal'),
|
||||
operator: 'notLooseEqual',
|
||||
actual: a,
|
||||
expected: b,
|
||||
extra: extra
|
||||
});
|
||||
}
|
||||
Test.prototype.notLooseEqual
|
||||
= Test.prototype.notLooseEquals
|
||||
= notLooseEqual;
|
||||
|
||||
function tapeDeepEqual(a, b, msg, extra) {
|
||||
if (arguments.length < 2) {
|
||||
throw new TypeError('two arguments must be provided to compare');
|
||||
}
|
||||
this._assert(deepEqual(a, b, { strict: true }), {
|
||||
message: defined(msg, 'should be deeply equivalent'),
|
||||
operator: 'deepEqual',
|
||||
actual: a,
|
||||
expected: b,
|
||||
extra: extra
|
||||
});
|
||||
}
|
||||
Test.prototype.deepEqual
|
||||
= Test.prototype.deepEquals
|
||||
= Test.prototype.isEquivalent
|
||||
= Test.prototype.same
|
||||
= tapeDeepEqual;
|
||||
|
||||
function notDeepEqual(a, b, msg, extra) {
|
||||
if (arguments.length < 2) {
|
||||
throw new TypeError('two arguments must be provided to compare');
|
||||
}
|
||||
this._assert(!deepEqual(a, b, { strict: true }), {
|
||||
message: defined(msg, 'should not be deeply equivalent'),
|
||||
operator: 'notDeepEqual',
|
||||
actual: a,
|
||||
expected: b,
|
||||
extra: extra
|
||||
});
|
||||
}
|
||||
Test.prototype.notDeepEqual
|
||||
= Test.prototype.notDeepEquals
|
||||
= Test.prototype.notEquivalent
|
||||
= Test.prototype.notDeeply
|
||||
= Test.prototype.notSame
|
||||
= Test.prototype.isNotDeepEqual
|
||||
= Test.prototype.isNotDeeply
|
||||
= Test.prototype.isNotEquivalent
|
||||
= Test.prototype.isInequivalent
|
||||
= notDeepEqual;
|
||||
|
||||
function deepLooseEqual(a, b, msg, extra) {
|
||||
if (arguments.length < 2) {
|
||||
throw new TypeError('two arguments must be provided to compare');
|
||||
}
|
||||
this._assert(deepEqual(a, b), {
|
||||
message: defined(msg, 'should be loosely deeply equivalent'),
|
||||
operator: 'deepLooseEqual',
|
||||
actual: a,
|
||||
expected: b,
|
||||
extra: extra
|
||||
});
|
||||
}
|
||||
|
||||
Test.prototype.deepLooseEqual
|
||||
= deepLooseEqual;
|
||||
|
||||
function notDeepLooseEqual(a, b, msg, extra) {
|
||||
if (arguments.length < 2) {
|
||||
throw new TypeError('two arguments must be provided to compare');
|
||||
}
|
||||
this._assert(!deepEqual(a, b), {
|
||||
message: defined(msg, 'should not be loosely deeply equivalent'),
|
||||
operator: 'notDeepLooseEqual',
|
||||
actual: a,
|
||||
expected: b,
|
||||
extra: extra
|
||||
});
|
||||
}
|
||||
Test.prototype.notDeepLooseEqual
|
||||
= notDeepLooseEqual;
|
||||
|
||||
Test.prototype['throws'] = function (fn, expected, msg, extra) {
|
||||
if (typeof expected === 'string') {
|
||||
msg = expected;
|
||||
expected = undefined;
|
||||
}
|
||||
|
||||
var caught = undefined;
|
||||
|
||||
try {
|
||||
fn();
|
||||
} catch (err) {
|
||||
caught = { error: err };
|
||||
if (Object(err) === err && (!isEnumerable(err, 'message') || !has(err, 'message'))) {
|
||||
var message = err.message;
|
||||
delete err.message;
|
||||
err.message = message;
|
||||
}
|
||||
}
|
||||
|
||||
var passed = caught;
|
||||
|
||||
if (caught) {
|
||||
if (typeof expected === 'string' && caught.error && caught.error.message === expected) {
|
||||
throw new TypeError('The "error/message" argument is ambiguous. The error message ' + inspect(expected) + ' is identical to the message.');
|
||||
}
|
||||
if (typeof expected === 'function') {
|
||||
if (typeof expected.prototype !== 'undefined' && caught.error instanceof expected) {
|
||||
passed = true;
|
||||
} else if (isProto(Error, expected)) {
|
||||
passed = false;
|
||||
} else {
|
||||
passed = expected.call({}, caught.error) === true;
|
||||
}
|
||||
} else if (isRegExp(expected)) {
|
||||
passed = expected.test(caught.error);
|
||||
expected = inspect(expected);
|
||||
} else if (expected && typeof expected === 'object') { // Handle validation objects.
|
||||
var keys = Object.keys(expected);
|
||||
// Special handle errors to make sure the name and the message are compared as well.
|
||||
if (expected instanceof Error) {
|
||||
$push(keys, 'name', 'message');
|
||||
} else if (keys.length === 0) {
|
||||
throw new TypeError('`throws` validation object must not be empty');
|
||||
}
|
||||
passed = keys.every(function (key) {
|
||||
if (typeof caught.error[key] === 'string' && isRegExp(expected[key]) && $test(expected[key], caught.error[key])) {
|
||||
return true;
|
||||
}
|
||||
if (key in caught.error && deepEqual(caught.error[key], expected[key], { strict: true })) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this._assert(!!passed, {
|
||||
message: defined(msg, 'should throw'),
|
||||
operator: 'throws',
|
||||
actual: caught && caught.error,
|
||||
expected: expected,
|
||||
error: !passed && caught && caught.error,
|
||||
extra: extra
|
||||
});
|
||||
};
|
||||
|
||||
Test.prototype.doesNotThrow = function (fn, expected, msg, extra) {
|
||||
if (typeof expected === 'string') {
|
||||
msg = expected;
|
||||
expected = undefined;
|
||||
}
|
||||
var caught = undefined;
|
||||
try {
|
||||
fn();
|
||||
}
|
||||
catch (err) {
|
||||
caught = { error: err };
|
||||
}
|
||||
this._assert(!caught, {
|
||||
message: defined(msg, 'should not throw'),
|
||||
operator: 'throws',
|
||||
actual: caught && caught.error,
|
||||
expected: expected,
|
||||
error: caught && caught.error,
|
||||
extra: extra
|
||||
});
|
||||
};
|
||||
|
||||
Test.prototype.match = function match(string, regexp, msg, extra) {
|
||||
if (!isRegExp(regexp)) {
|
||||
throw new TypeError('The "regexp" argument must be an instance of RegExp. Received type ' + typeof regexp + ' (' + inspect(regexp) + ')');
|
||||
}
|
||||
if (typeof string !== 'string') {
|
||||
throw new TypeError('The "string" argument must be of type string. Received type ' + typeof string + ' (' + inspect(string) + ')');
|
||||
}
|
||||
|
||||
var matches = $test(regexp, string);
|
||||
var message = defined(
|
||||
msg,
|
||||
'The input ' + (matches ? 'matched' : 'did not match') + ' the regular expression ' + inspect(regexp) + '. Input: ' + inspect(string)
|
||||
);
|
||||
this._assert(matches, {
|
||||
message: message,
|
||||
operator: 'match',
|
||||
actual: string,
|
||||
expected: regexp,
|
||||
extra: extra
|
||||
});
|
||||
};
|
||||
|
||||
Test.prototype.doesNotMatch = function doesNotMatch(string, regexp, msg, extra) {
|
||||
if (!isRegExp(regexp)) {
|
||||
throw new TypeError('The "regexp" argument must be an instance of RegExp. Received type ' + typeof regexp + ' (' + inspect(regexp) + ')');
|
||||
}
|
||||
if (typeof string !== 'string') {
|
||||
throw new TypeError('The "string" argument must be of type string. Received type ' + typeof string + ' (' + inspect(string) + ')');
|
||||
}
|
||||
var matches = $test(regexp, string);
|
||||
var message = defined(
|
||||
msg,
|
||||
'The input ' + (matches ? 'was expected to not match' : 'did not match') + ' the regular expression ' + inspect(regexp) + '. Input: ' + inspect(string)
|
||||
);
|
||||
this._assert(!matches, {
|
||||
message: message,
|
||||
operator: 'doesNotMatch',
|
||||
actual: string,
|
||||
expected: regexp,
|
||||
extra: extra
|
||||
});
|
||||
};
|
||||
|
||||
Test.skip = function (name_, _opts, _cb) {
|
||||
var args = getTestArgs.apply(null, arguments);
|
||||
args.opts.skip = true;
|
||||
return Test(args.name, args.opts, args.cb);
|
||||
};
|
||||
|
||||
// vim: set softtabstop=4 shiftwidth=4:
|
||||
Reference in New Issue
Block a user