tad
Version:
JavaScript test suite
150 lines (127 loc) • 4.03 kB
JavaScript
;
var isFunction = require("es5-ext/function/is-function")
, assign = require("es5-ext/object/assign")
, isValue = require("es5-ext/object/is-value")
, eq = require("es5-ext/object/eq")
, map = require("es5-ext/object/map")
, isRegExp = require("es5-ext/reg-exp/is-reg-exp")
, Assert = require("test/assert").Assert;
var never
, neverBind
, throws
, resolveMessage
, wrapAssert
, lineRe = /(\d+:\d+)\)?$/
, isErrorCode = RegExp.prototype.test.bind(/^[A-Z_]+$/);
require("./fix-test-utils");
never = function (message) {
message = resolveMessage(message);
this.fail({ message: message, operator: "never" });
};
neverBind = function (message) { return never.bind(this, message); };
resolveMessage = function (message) {
var stack, line, match;
if (isValue(message)) return message;
stack = new Error().stack;
if (!stack) return "";
line = stack.split("\n")[3];
if (!line) return "";
match = line.match(lineRe);
if (!match) return "";
return "@" + match[1];
};
throws = function (block, err, message) {
var threw = false, exception = null, failure;
// If third argument is not provided and second argument is a string it
// means that optional `Error` argument was not passed, so we shift
// arguments.
if (message === undefined) {
if (!isFunction(err) && !isErrorCode(err)) {
message = err;
err = null;
}
}
message = resolveMessage(message);
// Executing given `block`.
try {
block();
} catch (e) {
threw = true;
exception = e;
}
// If exception was thrown and `Error` argument was not passed assert is
// passed.
if (
threw &&
(!isValue(err) ||
// If Error is thrown exception
err === exception ||
// If passed `Error` is RegExp using it's test method to
// assert thrown exception message.
(isRegExp(err) && err.test(exception.message)) ||
// If passed `Error` is a constructor function testing if
// thrown exception is an instance of it.
(isFunction(err) && exception instanceof err) ||
err === exception.code)
) {
this.pass(message);
// Otherwise we report assertion failure.
} else {
failure = { message: message, operator: "throws" };
if (exception) failure.actual = exception;
if (err) failure.expected = err;
this.fail(failure);
}
};
wrapAssert = function (assert, context) {
return function (actual, expected, message) {
return assert.call(context, actual, expected, resolveMessage(message));
};
};
module.exports = function (logger) {
var assert, getHeading;
assert = new Assert({
pass: logger.pass.bind(logger),
fail: logger.fail.bind(logger),
error: logger.error.bind(logger)
});
assert = assign(
function (actual, expected, message) {
message = resolveMessage(message);
if (eq(actual, expected)) {
this.pass(message);
return;
}
this.fail({ actual: actual, expected: expected, message: message, operator: "===" });
}.bind(assert),
map(Assert.prototype, function (method) { return method.bind(assert); })
);
assert.strictEqual = assert;
assert.not = assert.notStrictEqual = function (actual, expected, message) {
message = resolveMessage(message);
if (!eq(actual, expected)) {
this.pass(message);
return;
}
this.fail({ actual: actual, expected: expected, message: message, operator: "!==" });
};
assert.deep = assert.deepEqual = wrapAssert(assert.deepEqual, assert);
assert.notDeep = assert.notDeepEqual = wrapAssert(assert.notDeepEqual, assert);
assert.never = never.bind(assert);
assert.never.bind = neverBind.bind(assert);
assert.throws = throws.bind(assert);
getHeading = function (level) {
return function (msg) {
var index = level - 1 + logger.closure;
if (!hasOwnProperty.call(logger.msg, index)) logger.msg[index] = undefined;
logger.msg.splice(index, Infinity, msg);
};
};
assert.h1 = getHeading(1);
assert.h2 = getHeading(2);
assert.h3 = getHeading(3);
assert.h4 = getHeading(4);
assert.h5 = getHeading(5);
assert.h6 = getHeading(6);
return assert;
};