referee
A collection of assertions to be used with a unit testing framework. referee works well with any CommonJS compliant testing framework out of the box, and can easily be configured to work with most any testing framework. See also expectations if you like the alternative API
(expect(thing).toBe*).
referee contains lots of assertions. We strongly believe that high-level assertions are essential in the interest of producing clear and intent-revealing tests, and they also give you to-the-point failure messages.
Install
npm install @sinonjs/referee --save-dev
Sinon.JS integration
You can extend referee with assertions that integrates with Sinon.JS
See referee-sinon
Assertions and refutations
Unlike most assertion libraries, referee does not have assert.notXyz assertions to refute some fact. Instead, it has refutations, heavily inspired by Ruby's minitest:
var assert = referee.assert;
var refute = referee.refute;
assert.equals(42, 42);
refute.equals(42, 43);
Refutations help express "assert not ..." style verification in a much clearer way. It also brings with it a nice consistency in that any assert.xyz always has a corresponding refute.xyz that does the opposite check.
assert()
assert(actual[, message]);
Fails if actual is falsy (0, "", null, undefined, NaN). Fails with either the provided message or "Expected null to be truthy". This behavior differs from all other assertions, which prepend the optional message argument.
assert({ not: "Falsy" }, "This will pass");
assert(null, "This will fail"); // Fails with custom message
assert(null); // Fails
assert(34); // Passes
refute()
refute(actual[, message])
Fails if actual is truthy. Fails with either the provided message or "Expected null to be falsy". This behavior differs from all other refutations, which prepend the optional message argument.
refute({ not: "Falsy" }, "This will fail"); // Fails with custom message
refute(null, "This will pass");
refute(null); // Passes
refute(34); // Fails
Predefined Assertions
The following assertions can be used with assert and refute. They
are described for assert, but the corresponding failure messages for
refute are also mentioned. For refute the behaviour is exactly
opposed.
All assertions support an optional message argument, which is
prepended to the failure message.
Overview
Any
String
Number
Function
Object
Array and array like
DOM element
Promise
Types and values
These assertions are for checking for built-in types and values.
- isUndefined()
- isNull()
- isArray()
- isArrayBuffer()
- isArrayLike()
- isBoolean()
- isDataView()
- isDate()
- isError()
- isEvalError()
- isFalse()
- isFloat32Array()
- isFloat64Array()
- isFunction()
- isInfinity()
- isIntlCollator()
- isIntlDateTimeFormat()
- isIntlNumberFormat()
- isMap()
- isNaN()
- isNegativeInfinity()
- isNumber()
- isObject()
- isPromise()
- isRangeError()
- isReferenceError()
- isRegExp()
- isSet()
- isString()
- isSymbol()
- isSyntaxError()
- isTrue()
- isTypeError()
- isUint16Array()
- isUint32Array()
- isUint8Array()
- isUint8Array()
- isUint8clampedArray()
- isURIError()
- isWeakMap()
- isWeakSet()
same()
assert.same(actual, expected[, message])
Fails if actual is not the same object (===) as expected. To compare similar objects, such as { name: "Chris", id: 42 } and { id: 42, name: "Chris" } (not the same instance), see equals().
var obj = { id: 42, name: "Chris" };
assert.same(obj, obj); // Passes
assert.same(obj, { id: 42, name: "Chris" }); // Fails
Messages
assert.same.message = "${actual} expected to be the same object as ${expected}";
refute.same.message =
  "${actual} expected not to be the same object as ${expected}";
equals()
assert.equals(actual, expected[, message])
Compares actual to expected property by property. If the property count does not match, or if any of actual‘s properties do not match the corresponding property in expected, the assertion fails. Object properties are verified recursively.
If actual is null or undefined, an exact match is required. Date objects are compared by their getTime method. Regular expressions are compared by their string representations. Primitives are compared using ==, i.e., with coercion.
equals passes when comparing an arguments object to an array if the both contain the same elements.
Objects or arrays may contain the result of calling match to compare a property using a built-in or custom matcher.
assert.equals({ name: "Professor Chaos" }, { name: "Professor Chaos" }); // Passes
assert.equals({ name: "Professor Chaos" }, { name: match.string }); // Passes
assert.equals({ name: "Professor Chaos" }, { name: "Dr Evil" }); // Fails
assert.equals({ name: "Professor Chaos" }, { name: match.number }); // Fails
Messages
assert.equals.message = "${actual} expected to be equal to ${expected}";
refute.equals.message = "${actual} expected not to be equal to ${expected}";
greater()
assert.greater(actual, expected[, message])
Fails if actual is equal to or less than expected.
assert.greater(2, 1); // Passes
assert.greater(1, 1); // Fails
assert.greater(1, 2); // Fails
Messages
assert.greater.message = "Expected ${actual} to be greater than ${expected}";
refute.greater.message =
  "Expected ${actual} to be less than or equal to ${expected}";
less()
assert.less(actual, expected[, message])
Fails if actual is equal to or greater than expected.
assert.less(1, 2); // Passes
assert.less(1, 1); // Fails
assert.less(2, 1); // Fails
Messages
assert.less.message = "Expected ${actual} to be less than ${expected}";
refute.less.message =
  "Expected ${actual} to be greater than or equal to ${expected}";
isUndefined()
assert.isUndefined(object[, message])
Fails if object is not undefined.
assert.isUndefined(undefined); // Passes
assert.isUndefined({}); // Fails
refute.isUndefined({}); // Passes
refute.isUndefined(undefined); // Fails
Messages
assert.isUndefined.message = "Expected ${actual} to be undefined";
refute.isUndefined.message = "Expected not to be undefined";
isNull()
assert.isNull(object[, message])
Fails if object is not null.
assert.isNull(null); // Passes
assert.isNull({}); // Fails
refute.isNull({}); // Passes
refute.isNull(null); // Fails
Messages
assert.isNull.message = "Expected ${actual} to be null";
refute.isNull.message = "Expected not to be null";
match()
assert.match(actual, matcher[, message])
Fails if matcher is not a partial match for actual. Accepts a wide range of input combinations. Note that assert.match is not symmetric - in some cases assert.match(a, b) may pass while assert.match(b, a) fails.
String matcher
In its simplest form, assert.match performs a case insensitive substring match. When the matcher is a string, the actual object is converted to a string, and the assertion passes if actual is a case-insensitive substring of expected as a string.
assert.match("Give me something", "Give"); // Passes
assert.match("Give me something", "sumptn"); // Fails
assert.match(
  {
    toString: function () {
      return "yeah";
    },
  },
  "Yeah!",
); // Passes
The last example is not symmetric. When the matcher is a string, the actual value is coerced to a string - in this case using toString. Changing the order of the arguments would cause the matcher to be an object, in which case different rules apply (see below).
Boolean matcher
Performs a strict (i.e. ===) match with the object. So, only true matches true, and only false matches false.
Regular expression matcher
When the matcher is a regular expression, the assertion will pass if expected.test(actual) is true. assert.match is written in a generic way, so any object with a test method will be used as a matcher this way.
assert.match("Give me something", /^[a-z\s]$/i); // Passes
assert.match("Give me something", /[0-9]/); // Fails
assert.match(
  {
    toString: function () {
      return "yeah!";
    },
  },
  /yeah/,
); // Passes
assert.match(234, /[a-z]/); // Fails
Number matcher
When the matcher is a number, the assertion will pass if matcher == actual.
assert.match("123", 123); // Passes
assert.match("Give me something", 425); // Fails
assert.match(
  {
    toString: function () {
      return "42";
    },
  },
  42,
); // Passes
assert.match(234, 1234); // Fails
Function matcher
When the matcher is a function, it is called with actual as its only argument. The assertion will pass if the function returns true. A strict match is performed against the return value, so a boolean true is required, truthy is not enough.
// Passes
assert.match("123", function (exp) {
  return exp == "123";
});
// Fails
assert.match("Give me something", function () {
  return "ok";
});
// Passes
assert.match(
  {
    toString: function () {
      return "42";
    },
  },
  function () {
    return true;
  },
);
// Fails
assert.match(234, function () {});
Object matcher
As mentioned above, if an object matcher defines a test method the assertion will pass if matcher.test(actual) returns truthy. If the object does not have a test method, a recursive match is performed. If all properties of matcher matches corresponding properties in actual, the assertion passes. Note that the object matcher does not care if the number of properties in the two objects are the same - only if all properties in the matcher recursively “matches” ones in the actual object.
// Passes
assert.match("123", {
  test: function (arg) {
    return arg == 123;
  },
});
// Fails
assert.match({}, { prop: 42 });
// Passes
assert.match(
  {
    name: "Chris",
    profession: "Programmer",
  },
  {
    name: "Chris",
  },
);
// Fails
assert.match(234, {
  name: "Chris",
});
DOM elements
assert.match can be very helpful when asserting on DOM elements, because it allows you to compare several properties with one assertion:
var el = document.getElementById("myEl");
assert.match(el, {
  tagName: "h2",
  className: "item",
  innerHTML: "Howdy",
});
isObject()
assert.isObject(object[, message])
Fails if object is not an object or if it is null.
assert.isObject({}); // Passes
assert.isObject(42); // Fails
assert.isObject([1, 2, 3]); // Passes
assert.isObject(function () {}); // Fails
Messages
assert.isObject.message =
  "${actual} (${actualType}) expected to be object and not null";
refute.isObject.message = "${actual} expected to be null or not an object";
isFunction()
assert.isFunction(actual[, message])
Fails if actual is not a function.
assert.isFunction({}); // Fails
assert.isFunction(42); // Fails
assert.isFunction(function () {}); // Passes
Messages
assert.isFunction.message = "${actual} (${actualType}) expected to be function";
refute.isFunction.message = "${actual} expected not to be function";
isTrue()
assert.isTrue(actual[, message])
Fails if actual is not true.
assert.isTrue("2" == 2); // Passes
assert.isTrue("2" === 2); // Fails
Messages
assert.isTrue.message = "Expected ${actual} to be true";
refute.isTrue.message = "Expected ${actual} to not be true";
isFalse()
assert.isFalse(actual[, message])
Fails if actual is not false.
assert.isFalse("2" === 2); // Passes
assert.isFalse("2" == 2); // Fails
Messages
assert.isFalse.message = "Expected ${actual} to be false";
refute.isFalse.message = "Expected ${actual} to not be false";
isString()
assert.isString(actual[, message])
Fails if the type of actual is not "string".
assert.isString("2"); // Passes
assert.isString(2); // Fails
Messages
assert.isString.message = "Expected ${actual} (${actualType}) to be string";
refute.isString.message = "Expected ${actual} not to be string";
isBoolean()
assert.isBoolean(actual[, message])
Fails if the type of actual is not "boolean".
assert.isBoolean(true); // Passes
assert.isBoolean(2 < 2); // Passes
assert.isBoolean("true"); // Fails
Messages
assert.isBoolean.message = "Expected ${actual} (${actualType}) to be boolean";
refute.isBoolean.message = "Expected ${actual} not to be boolean";
isNumber()
assert.isNumber(actual[, message])
Fails if the type of actual is not "number" or is NaN.
assert.isNumber(12); // Passes
assert.isNumber("12"); // Fails
assert.isNumber(NaN); // Fails
Messages
assert.isNumber.message =
  "Expected ${actual} (${actualType}) to be a non-NaN number";
refute.isNumber.message = "Expected ${actual} to be NaN or a non-number value";
isNaN()
assert.isNaN(actual[, message])
Fails if actual is not NaN. Does not perform coercion in contrast to the standard javascript function isNaN.
assert.isNaN(NaN); // Passes
assert.isNaN("abc" / "def"); // Passes
assert.isNaN(12); // Fails
assert.isNaN({}); // Fails, would pass for standard javascript function isNaN
Messages
assert.isNaN.message = "Expected ${actual} to be NaN";
refute.isNaN.message = "Expected not to be NaN";
isNegativeInfinity()
assert.isNegativeInfinity(actual[, message])
Fails if actual is not -Infinity.
assert.isNegativeInfinity(-Infinity); // Passes
assert.isNegativeInfinity(42); // Fails
isArray()
assert.isArray(actual[, message])
Fails if the object type of actual is not Array.
assert.isArray([1, 2, 3]); // Passes
assert.isArray({}); // Fails
Messages
assert.isArray.message = "Expected ${actual} to be array";
refute.isArray.message = "Expected ${actual} not to be array";
isArrayBuffer()
assert.isArrayBuffer(actual[, message])
Fails if the object type of actual is not ArrayBuffer.
assert.isArrayBuffer(new ArrayBuffer(8)); // Passes
assert.isArrayBuffer({}); // Fails
Messages
assert.isArrayBuffer.message = "Expected ${actual} to be an ArrayBuffer";
refute.isArrayBuffer.message = "Expected ${actual} not to be an ArrayBuffer";
isArrayLike()
assert.isArrayLike(actual[, message])
Fails if none of the following conditions are fulfilled:
- the object type of actualisArray
- actualis an- argumentsobject
- actualis an object providing a property- lengthof type "number" and a- propertysplice of type "function"
assert.isArrayLike([1, 2, 3]); // Passes
assert.isArrayLike(arguments); // Passes
assert.isArrayLike({ length: 0, splice: function () {} }); // Passes
assert.isArrayLike({}); // Fails
Messages
assert.isArrayLike.message = "Expected ${actual} to be array like";
refute.isArrayLike.message = "Expected ${actual} not to be array like";
isDataView()
assert.isDataView(actual[, message])
Fails if the object type of actual is not DataView.
assert.isDataView(new DataView(new ArrayBuffer(16)); // Passes
assert.isDataView({});                               // Fails
Messages
assert.isDataView.message = "Expected ${actual} to be a DataView";
refute.isDataView.message = "Expected ${actual} not to be a DataView";
isDate()
assert.isDate(actual[, message])
Fails if actual is not an instance of Date.
assert.isDate(new Date()); // Passes
assert.isDate(12345678); // Fails
assert.isDate("apple pie"); // Fails
Messages
assert.isDate.message = "Expected ${actual} to be a Date";
refute.isDate.message = "Expected ${actual} not to be a Date";
isError()
assert.isError(actual[, message])
Fails if actual is not an instance of Error.
Passes for all built in error types and errors derived from a built in error type.
assert.isError(new Error("this is an error"); // Passes
assert.isError("this is not an error");       // Fails
Messages
assert.isError.message = "Expected ${actual} to be an Error";
refute.isError.message = "Expected ${actual} not to be an Error";
isEvalError()
assert.isEvalError(actual[, message])
Fails if actual is not an instance of EvalError.
assert.isEvalError(new EvalError("this is an eval error")); // Passes
assert.isEvalError(new Error("this is not an eval error")); // Fails
Messages
assert.isEvalError.message = "Expected ${actual} to be an EvalError";
refute.isEvalError.message = "Expected ${actual} not to be an EvalError";
isFloat32Array()
assert.isFloat32Array(actual[, message])
Fails if actual is not an instance of Float32Array.
assert.isFloat32Array(new Float32Array(2)); // Passes
assert.isFloat32Array(new Float64Array(2)); // Fails
Messages
assert.isFloat32Array.message = "Expected ${actual} to be a Float32Array";
refute.isFloat32Array.message = "Expected ${actual} not to be n Float32Array";
isFloat64Array()
assert.isFloat64Array(actual[, message])
Fails if actual is not an instance of Float64Array.
assert.isFloat64Array(new Float64Array(2)); // Passes
assert.isFloat64Array(new Float32Array(2)); // Fails
Messages
assert.isFloat64Array.message = "Expected ${actual} to be a Float64Array";
refute.isFloat64Array.message = "Expected ${actual} not to be a Float64Array";
isInfinity()
assert.isInfinity(actual[, message])
Fails if actual is not Infinity.
assert.isInfinity(Infinity); // Passes
assert.isInfinity(42); // Fails
Messages
assert.isInfinity.message = "Expected ${actual} to be Infinity";
refute.isInfinity.message = "Expected ${actual} not to be Infinity";
isInt8Array()
assert.isInt8Array(actual[, message])
Fails if actual is not an instance of Int8Array.
assert.isInt8Array(new Int8Array(2)); // Passes
assert.isInt8Array(new Int16Array(2)); // Fails
Messages
assert.isInt8Array.message = "Expected ${actual} to be an Int8Array";
refute.isInt8Array.message = "Expected ${actual} not to be an Int8Array";
isInt16Array()
assert.isInt16Array(actual[, message])
Fails if actual is not an instance of Int16Array.
assert.isInt16Array(new Int16Array(2)); // Passes
assert.isInt16Array(new Int32Array(2)); // Fails
Messages
assert.isInt16Array.message = "Expected ${actual} to be an Int16Array";
refute.isInt16Array.message = "Expected ${actual} not to be an Int16Array";
isInt32Array()
assert.isInt32Array(actual[, message])
Fails if actual is not an instance of Int32Array.
assert.isInt32Array(new Int32Array(2)); // Passes
assert.isInt32Array(new Int16Array(2)); // Fails
Messages
assert.isInt32Array.message = "Expected ${actual} to be an Int32Array";
refute.isInt32Array.message = "Expected ${actual} not to be an Int32Array";
isIntlCollator()
assert.isIntlCollator(actual[, message])
Fails if actual is not an instance of Intl.Collator.
assert.isIntlCollator(new Intl.Collator()); // Passes
assert.isIntlCollator({}); // Fails
Messages
assert.isIntlCollator.message = "Expected ${actual} to be an Intl.Collator";
refute.isIntlCollator.message = "Expected ${actual} not to be an Intl.Collator";
isIntlDateTimeFormat()
assert.isIntlDateTimeFormat(actual[, message])
Fails if actual is not an instance of Intl.DateTimeFormat.
assert.isIntlDateTimeFormat(new Intl.DateTimeFormat()); // Passes
assert.isIntlDateTimeFormat({}); // Fails
Messages
assert.isIntlDateTimeFormat.message =
  "Expected ${actual} to be an Intl.DateTimeFormat";
refute.isIntlDateTimeFormat.message =
  "Expected ${actual} not to be an Intl.DateTimeFormat";
isIntlNumberFormat()
assert.isIntlNumberFormat(actual[, message])
Fails if actual is not an instance of Intl.NumberFormat.
assert.isIntlNumberFormat(new Intl.NumberFormat()); // Passes
assert.isIntlNumberFormat({}); // Fails
Messages
assert.isIntlNumberFormat.message =
  "Expected ${actual} to be an Intl.NumberFormat";
refute.isIntlNumberFormat.message =
  "Expected ${actual} not to be an Intl.NumberFormat";
isMap()
assert.Map(actual[, message])
Fails if actual is not an instance of Map.
assert.isMap(new Map()); // Passes
assert.isMap({}); // Fails
Messages
assert.isMap.message = "Expected ${actual} to be a Map";
refute.isMap.message = "Expected ${actual} not to be a Map";
isPromise()
assert.Promise(actual[, message])
Fails if actual is not an instance of Promise.
assert.isPromise(new Promise()); // Passes
assert.isPromise({}); // Fails
Messages
assert.isPromise.message = "Expected ${actual} to be a Promise";
refute.isPromise.message = "Expected ${actual} not to be a Promise";
isRangeError()
assert.isRangeError(actual[, message])
Fails if actual is not an instance of RangeError.
assert.isRangeError(new RangeError("this is a range error")); // Passes
assert.isRangeError(new Error("this is not a range error")); // Fails
Messages
assert.isRangeError.message = "Expected ${actual} to be an RangeError";
refute.isRangeError.message = "Expected ${actual} not to be an RangeError";
isReferenceError()
assert.isReferenceError(actual[, message])
Fails if actual is not an instance of ReferenceError.
assert.isReferenceError(new ReferenceError("this is a range error")); // Passes
assert.isReferenceError(new Error("this is not a range error")); // Fails
Messages
assert.isReferenceError.message = "Expected ${actual} to be a ReferenceError";
refute.isReferenceError.message =
  "Expected ${actual} not to be a ReferenceError";
isRegExp()
assert.isRegExp(actual[, message])
Fails if actual is not an instance of RegExp.
assert.isRegExp(new RegExp("apple pie")); // Passes
assert.isRegExp(/apple pie/); // Passes
assert.isRegExp("apple pie"); // Fails
Messages
assert.isRegExp.message = "Expected ${actual} to be an RegExp";
refute.isRegExp.message = "Expected ${actual} not to be an RegExp";
isSet()
assert.isSet(actual[, message])
Fails if actual is not an instance of Set.
assert.isSet(new Set()); // Passes
assert.isSet([]); // Fails
Messages
assert.isSet.message = "Expected ${actual} to be a Set";
refute.isSet.message = "Expected ${actual} not to be a Set";
isSymbol()
assert.isSymbol(actual[, message])
Fails if actual is not a value of type Symbol.
assert.isSymbol(Symbol("apple pie")); // Passes
assert.isSymbol("apple pie"); // Fails
Messages
assert.isSymbol.message = "Expected ${actual} to be a Symbol";
refute.isSymbol.message = "Expected ${actual} not to be a Symbol";
isSyntaxError()
assert.isSyntaxError(actual[, message])
Fails if actual is not an instance of SyntaxError.
assert.isSyntaxError(new SyntaxError("this is a syntax error")); // Passes
assert.isSyntaxError(new Error("this is not a syntax error")); // Fails
Messages
assert.isSyntaxError.message = "Expected ${actual} to be a SyntaxError";
refute.isSyntaxError.message = "Expected ${actual} not to be a SyntaxError";
isTypeError()
assert.isTypeError(actual[, message])
Fails if actual is not an instance of TypeError.
assert.isTypeError(new TypeError("this is a type error")); // Passes
assert.isTypeError(new Error("this is not a type error")); // Fails
Messages
assert.isTypeError.message = "Expected ${actual} to be a TypeError";
refute.isTypeError.message = "Expected ${actual} not to be a TypeError";
isURIError()
assert.isURIError(actual[, message])
Fails if actual is not an instance of URIError.
assert.isURIError(new URIError("this is a uri error")); // Passes
assert.isURIError(new Error("this is not a uri error")); // Fails
Messages
assert.isURIError.message = "Expected ${actual} to be a URIError";
refute.isURIError.message = "Expected ${actual} not to be a URIError";
isUint16Array()
assert.isUint16Array(actual[, message])
Fails if actual is not an instance of Uint16Array.
assert.isUint16Array(new Uint16Array()); // Passes
assert.isUint16Array(new Uint32Array()); // Fails
assert.isUint16Array(new Uint8Array()); // Fails
Messages
assert.isUint16Array.message = "Expected ${actual} to be a Uint16Array";
refute.isUint16Array.message = "Expected ${actual} not to be a Uint16Array";
isUint32Array()
assert.isUint32Array(actual[, message])
Fails if actual is not an instance of Uint32Array.
assert.isUint32Array(new Uint16Array()); // Fails
assert.isUint32Array(new Uint32Array()); // Passes
assert.isUint32Array(new Uint8Array()); // Fails
Messages
assert.isUint32Array.message = "Expected ${actual} to be a Uint32Array";
refute.isUint32Array.message = "Expected ${actual} not to be a Uint32Array";
isUint8Array()
assert.isUint8Array(actual[, message])
Fails if actual is not an instance of Uint8Array.
assert.isUint8Array(new Uint16Array()); // Fails
assert.isUint8Array(new Uint32Array()); // Fails
assert.isUint8Array(new Uint8Array()); // Passes
Messages
assert.isUint8Array.message = "Expected ${actual} to be a Uint8Array";
refute.isUint8Array.message = "Expected ${actual} not to be a Uint8Array";
isUint8ClampedArray()
assert.isUint8ClampedArray(actual[, message])
Fails if actual is not an instance of Uint8ClampedArray.
assert.isUint8ClampedArray(new Uint8ClampedArray()); // Passes
assert.isUint8ClampedArray(new Uint8Array()); // Fails
Messages
assert.isUint8ClampedArray.message =
  "Expected ${actual} to be a Uint8ClampedArray";
refute.isUint8ClampedArray.message =
  "Expected ${actual} not to be a Uint8ClampedArray";
isWeakMap()
assert.isWeakMap(actual[, message])
Fails if actual is not an instance of WeakMap.
assert.isWeakMap(new WeakMap()); // Passes
assert.isWeakMap(new Map()); // Fails
Messages
assert.isWeakMap.message = "Expected ${actual} to be a WeakMap";
refute.isWeakMap.message = "Expected ${actual} not to be a WeakMap";
isWeakSet()
assert.isWeakSet(actual[, message])
Fails if actual is not an instance of WeakSet.
assert.isWeakSet(new WeakSet()); // Passes
assert.isWeakSet(new Set()); // Fails
Messages
assert.isWeakSet.message = "Expected ${actual} to be a WeakSet";
refute.isWeakSet.message = "Expected ${actual} not to be a WeakSet";
keys()
assert.keys(object, keyArray[, message])
Fails if object’s own properties are not exactly the same as a given list.
assert.keys({ test1: "t1", test2: "t2" }, ["test1"]); // Fails - 'test2' is unexpected
assert.keys({ test1: "t1", test2: "t2" }, ["test1", "test2", "test3"]); // Fails - 'test3' is not present
assert.keys({ test1: "t1", test2: "t2" }, ["test1", "test2"]); // Passes
Messages
assert.keys.message = "Expected ${actualObject} to have exact keys ${keys}";
refute.keys.message = "Expected not to have exact keys ${keys}";
exception()
assert.exception(callback[, matcher, message])
Fails if callback does not throw an exception. If the optional matcher is provided, the assertion fails if the callback either does not throw an exception, or if the exception does not meet the criterias of the given matcher.
The matcher can be of type object or function. If the matcher is of type object, the captured error object and the matcher are passed to match().
If the matcher is of type function, the captured error object is passed as argument to the matcher function, which has to return true for a matching error object, otherwise false.
// Passes
assert.exception(function () {
  throw new Error("Ooops!");
});
// Fails
assert.exception(function () {});
// Passes
assert.exception(
  function () {
    throw new TypeError("Ooops!");
  },
  { name: "TypeError" },
);
// Fails, wrong exception type
assert.exception(
  function () {
    throw new Error("Aww");
  },
  { name: "TypeError" },
);
// Fails, wrong exception message
assert.exception(
  function () {
    throw new Error("Aww");
  },
  { message: "Ooops!" },
);
// Fails, wrong exception type
assert.exception(
  function () {
    throw new Error("Aww");
  },
  function (err) {
    if (err.name !== "TypeError") {
      return false;
    }
    return true;
  },
  "Type of exception is wrong!",
); // with message to print, if test fails
near()
assert.near(actual, expected, delta[, message])
Fails if the difference between actual and expected is greater than delta.
assert.near(10.3, 10, 0.5); // Passes
assert.near(10.5, 10, 0.5); // Passes
assert.near(10.6, 10, 0.5); // Fails
Messages
assert.near.message =
  "Expected ${actual} to be equal to ${expected} +/- ${delta}";
refute.near.message =
  "Expected ${actual} not to be equal to ${expected} +/- ${delta}";
hasArity()
assert.hasArity(actual, arity[, message])
Fails when actual does not have the desired arity.
assert.hasArity(function (one) {
  return one;
}, 1); // Passes
assert.hasArity(function (one, two) {
  return one + two;
}, 2); // Passes
assert.hasArity(function (one, two) {
  return one + two;
}, 1); // Fails
Messages
assert.hasArity.message =
  "Expected ${name} to have arity of ${1} but was ${arity}";
refute.hasArity.message = "Expected ${name} to not have arity of ${1}";
hasPrototype()
assert.hasPrototype(actual, prototype[, message])
Fails if prototype does not exist in the prototype chain of actual.
assert.hasPrototype(function () {}, Function.prototype); // Passes
assert.hasPrototype(function () {}, Object.prototype); // Passes
assert.hasPrototype({}, Function.prototype); // Fails
Messages
assert.hasPrototype.message =
  "Expected ${actual} to have ${expected} on its prototype chain";
refute.hasPrototype.message =
  "Expected ${actual} not to have ${expected} on its prototype chain";
contains()
assert.contains(haystack, needle[, message])
Fails if the array like object haystack does not contain the needle argument.
assert.contains([1, 2, 3], 2); // Passes
assert.contains([1, 2, 3], 4); // Fails
assert.contains([1, 2, 3], "2"); // Fails
Messages
assert.contains.message = "Expected [${actual}] to contain ${expected}";
refute.contains.message = "Expected [${actual}] not to contain ${expected}";
tagName()
assert.tagName(element, tagName[, message])
Fails if the element either does not specify a tagName property, or if its value is not a case-insensitive match with the expected tagName. Works with any object.
assert.tagName(document.createElement("p"), "p"); // Passes
assert.tagName(document.createElement("h2"), "H2"); // Passes
assert.tagName(document.createElement("p"), "li"); // Fails
className()
assert.className(element, classNames[, message])
Fails if the element either does not specify a className property, or if its value is not a space-separated list of all class names in classNames.
classNames can be either a space-delimited string or an array of class names. Every class specified by classNames must be found in the object’s className property for the assertion to pass, but order does not matter.
var el = document.createElement("p");
el.className = "feed item blog-post";
assert.className(el, "item"); // Passes
assert.className(el, "news"); // Fails
assert.className(el, "blog-post feed"); // Passes
assert.className(el, "feed items"); // Fails, "items" is not a match
assert.className(el, ["item", "feed"]); // Passes
resolves()
assert.resolves(promise[, value])
NOTE: This assertion returns a Promise!
The assertion resolves, if the value resolved from promise
equals the given value.
Furthermore, the assertion rejects if,
- the resolved value from the input promiseis not equal to the givenvalue
- the given promiserejects instead of resolving
- the given input is not a Promise
NOTE: In order to tell the test runner to wait until the assertion has completed, you either need to return the Promise from the assertion:
test("some asynchronous code", function() {
    return assert.resolves(myAsyncFunc(), {...});
});
or use async/await:
test("some asynchronous code", async function() {
    await assert.resolves(myAsyncFunc(), {...});
});
rejects()
assert.rejects(promise[, value])
NOTE: This assertion returns a Promise!
The assertion resolves, if the value rejected from promise
equals the given value.
Furthermore, the assertion rejects if,
- the rejected value from the input promiseis not equal to the givenvalue
- the given promiseresolves instead of rejecting
- the given input is not a Promise
NOTE: In order to tell the test runner to wait until the assertion has completed, you either need to return the Promise from the assertion:
test("some asynchronous code", function() {
    return assert.rejects(myAsyncFunc(), {...});
});
or use async/await:
test("some asynchronous code", async function() {
    await assert.rejects(myAsyncFunc(), {...});
});
json()
assert.json(actual, json[, message])
Fails if actual is not valid JSON or the parsed JSON is not equal to json. Uses the same comparison algorithm as equals().
var serialized = JSON.stringify({ is: 42 });
assert.json(serialized, { is: 42 }); // Passes
assert.json(serialized, { or: 42 }); // Fails
assert.json(serialized, { is: 7 }); // Fails
assert.json("no-json", {}); // Fails
matchJson()
assert.matchJson(actual, json[, message])
Fails if actual is not valid JSON or the parsed JSON does not match json. Uses the same matcher algorithm as match().
var serialized = JSON.stringify({ is: 42, and: 3 });
assert.matchJson(serialized, { is: 42 }); // Passes
assert.matchJson(serialized, { and: 3 }); // Passes
assert.matchJson(serialized, { or: 42 }); // Fails
assert.matchJson(serialized, { is: 7 }); // Fails
assert.matchJson("no-json", {}); // Fails
Custom assertions
Custom, domain-specific assertions help improve clarity and reveal intent in tests. They also facilitate much better feedback when they fail. You can add custom assertions that behave exactly like the built-in ones (i.e. with counting, message formatting, expectations and
more) by using the referee.add method.
Load custom assertions
Custom assertions can be loaded as modules using e.g. mocha to be used in tests.
Custom assertion
./test/assertions/is-prime.js
const referee = require("referee");
// adapted from https://stackoverflow.com/a/40200710
function isPrime(number) {
  for (var i = 2; i < number; i++) {
    if (number % i === 0) {
      return false;
    }
  }
  return number !== 1 && number !== 0;
}
referee.add("isPrime", {
  assert: function assert(actual) {
    if (typeof actual !== "number" || actual < 0) {
      throw new TypeError("'actual' argument should be a non-negative Number");
    }
    this.actual = actual;
    return isPrime(actual);
  },
  assertMessage: "Expected ${actual} to be a prime number",
  refuteMessage: "Expected ${actual} to not be a prime number",
  expectation: "toHaveArity",
});
Test
./test/some.test.js
const { assert, refute } = require("referee");
describe("some", function () {
  it("should have isPrime installed", function () {
    assert.isPrime(5);
    refute.isPrime(6);
  });
});
Execute
mocha -r ./test/assetions/*
This repository hosts the full runnable example from above, as well as demos using other popular test runners.
Overriding assertion messages
The default assertion messages can be overridden. The messages to
overwrite are listed with each assertion. You can use the same keys for
string interpolation (e.g. ${actual}, ${expected}). equals:
var assert = require("referee").assert;
assert.equals.message = "I wanted ${actual} == ${expected}!";
try {
  assert.equals(3, 4);
} catch (e) {
  console.log(e.message);
}
// Prints:
// "I wanted 3 == 4!"
Events
referee is an event-emitter. Listen to events with on:
referee.on("failure", function (err) {
  console.log(err.message);
});
pass event
Signature:
"pass", function () {};
Assertion passed. The callback is invoked with the assertion name, e.g.
"equals", as its only argument. Note that this event is also emitted
when refutations pass.
failure event
Signature:
"failure", function (error) {};
Assertion failed. The callback is invoked with an AssertionError object.
Expectations
All of referee's assertions and refutations are also exposed as "expectations". Expectations is just a slightly different front-end to the same functionality, often preferred by the BDD inclined.
Expectations mirror assertions under different names. Refutations can be expressed using expect(obj).not and then calling either of the expectations on the resulting object.
var expect = require("referee").expect;
expect({ id: 42 }).toBeObject(); // Passes
expect("Somewhere in here").toMatch("in"); // Passes
expect(42).not.toEqual(43); // Passes
expect.toBe()
expect(actual).toBe(expected);
See same()
expect.toEqual()
expect(actual).toEqual(expected);
See equals()
expect.toBeGreaterThan()
expect(actual).toBeGreaterThan(expected);
See greater()
expect.toBeLessThan()
expect(actual).toBeLessThan(expected);
See less()
expect.toBeDefined()
expect(actual).toBeDefined(expected);
See defined()
expect.toBeNull()
expect(actual).toBeNull(expected);
See isNull()
expect.toMatch()
expect(actual).toMatch(expected);
See match()
expect.toBeObject()
expect(actual).toBeObject(expected);
See isObject()
expect.toBeFunction()
expect(actual).toBeFunction(expected);
See isFunction()
expect.toBeTrue()
expect(actual).toBeTrue();
See isTrue()
expect.toBeFalse()
expect(actual).toBeFalse();
See isFalse()
expect.toBeString()
expect(actual).toBeString();
See isString()
expect.toBeBoolean()
expect(actual).toBeBoolean();
See isBoolean()
expect.toBeNumber()
expect(actual).toBeNumber();
See isNumber()
expect.toBeNaN()
expect(actual).toBeNaN();
See isNaN()
expect.toBeArray()
expect(actual).toBeArray();
See isArray()
expect.toBeArrayLike()
expect(actual).toBeArrayLike();
See isArrayLike()
expect.toHaveKeys()
expect(object).toHaveKeys(keyArray);
See keys()
expect.toThrow()
expect(actual).toThrow(expected);
See exception()
expect.toBeNear()
expect(actual).toBeNear(expected, delta);
See near()
expect.toHavePrototype()
expect(actual).toHavePrototype(prototype);
See hasPrototype()
expect.toContain()
expect(haystack).toContain(needle);
See contains()
expect.toHaveTagName()
expect(actual).toHaveTagName(expected);
See tagName()
expect.toHaveClassName()
expect(actual).toHaveClassName(expected);
See className()
expect.toEqualJson()
expect(actual).toEqualJson(expected);
See json()
expect.toMatchJson()
expect(actual).toMatchJson(expected);
See matchJson()
expect.toHaveBeenCalled()
expect(spy).toHaveBeenCalled();
See called()
expect.toHaveBeenCalledOnce()
expect(spy).toHaveBeenCalledOnce(expected);
See calledOnce()
expect.toHaveBeenCalledTwice()
expect(spy).toHaveBeenCalledTwice(expected)
See calledTwice()
expect.toHaveBeenCalledThrice()
expect(spy).toHaveBeenCalledThrice(expected);
See calledThrice()
expect.toHaveBeenCalledWith()
expect(spy).toHaveBeenCalledWith(arg1, arg2, ...)
See calledWith()
expect.toHaveBeenCalledOnceWith()
expect(spy).toHaveBeenCalledOnceWith(arg1, arg2, ...)
See calledOnceWith()
Methods
referee.fail()
referee.fail(message);
When an assertion fails, it calls referee.fail() with the failure message as the only argument. The built-in fail function both throws an AssertionError() and emits it to the failure event. The error can be caught and handled by the test runner. If this behavior is not suitable for your testing framework of choice, you can override referee.fail() to make it do the right thing.
Example: To use referee with JsTestDriver, you can simply configure it as follows:
referee.fail = function (message) {
  fail(message);
};
Where the global fail function is the one provided by JsTestDriver.
It is possible to make the default assert.fail method only emit an event and not throw an error. This may be suitable in asynchronous test runners, where you might not be able to catch exceptions. To silence exceptions, see the throwOnFailure property.
referee.add()
referee.add(name, options);
Add a custom assertion. Using this ‘macro’ to add project specific assertions has a few advantages:
- Assertions will be counted
- Failure messages will have interpolated arguments formatted
- A single function generates both an assertion and a refutation
- If using expectations, an expectation can easily be generated as well
- When failOnNoAssertionsis set totrue, the assertion will behave correctly (may be important for asynchronous tests)
- The assertion will fail if too few arguments are passed
Here’s an example of adding a “foo” assertion, that only passes when its only argument is the string “foo”:
var assert = referee.assert;
var refute = referee.refute;
var expect = referee.expect;
referee.add("isFoo", {
  assert: function (actual) {
    return actual == "foo";
  },
  assertMessage: "Expected ${0} to be foo!",
  refuteMessage: "Expected not to be foo!",
  expectation: "toBeFoo",
});
// Now you can do:
// Passes
assert.isFoo("foo");
// Fails: "[assert.isFoo] Expected { id: 42 } to be foo!"
assert.isFoo({ id: 42 });
// Fails: "[refute.isFoo] Expected not to be foo!"
refute.isFoo("foo");
// Passes
expect("foo").toBeFoo();
// To support custom messages, do this:
referee.add("isFoo", {
  assert: function (actual) {
    return actual == "foo";
  },
  assertMessage: "${1}Expected ${0} to be foo!",
  refuteMessage: "${1}Expected not to be foo!",
  expectation: "toBeFoo",
  values: function (thing, message) {
    return [thing, message ? message + " " : ""];
  },
});
// Fails: "[assert.isFoo] Ouch: Expected { id: 42 } to be foo!"
assert.isFoo({ id: 42 }, "Ouch");
Error message value interpolation
Arguments are available in assertion failure messages using the "${n}" switches, where n is a number. You can also use named variables by setting properties on this in the assertion/refutation function:
referee.add("isString", {
  assert: function (actual) {
    this.actualType = typeof actual;
    return this.actualType == "string";
  },
  assertMessage: "Expected ${0} (${actualType}) to be string",
  refuteMessage: "Expected not to be string",
  expectation: "toBeString",
});
Arguments
- name
- The name of the new assertion/refutation
- options
- 
        - assert
- 
The verification function. Should return truewhen the assertion passes. The generated refutation will pass when the function returnsfalse. In some cases the refutation may not be the exact opposite of the assertion. If that is the case you should provideoptions.refutefor the custom refutation. The number of formal parameters the function accepts determines the number of required arguments to the function. If the assertion is called with less arguments than expected, referee will fail it before your custom function is even called. All arguments are available for interpolation into the resulting error message. The first argument will be available as"${0}", the second as"${1}"and so on. If you want to embed other values than exact arguments into the string, you can set properties on this in the custom assertion, and refer to them as"${name}"in the message.
- refute
- Custom refutation function. Used over !assert()if provided.
- assertMessage
- The error message to use when the assertion fails. The message may refer to arguments through switches like "${0}"and so on (see above, under the assert argument). The message is exposed on the generated assertion as the propertyassert.[name].message.
- refuteMessage
- Like assertMessage, but for refutations. Exposed asrefute.[name].message.
- values
- A function that maps values to be interpolated into the failure messages. This can be used when you need something more/else than the actual argumentsin order.
- expectation
- The name of the assertion as an expectation, e.g. “toBeSomething”. Optional.
 
referee.verifier()
Creates a verifier function with the signature verify([expected]).
It exposes verify.count which is incremented every time referee emits a "pass" or a "failure" event. When called, the function verifies that assertions have been made, throwing an exception if verify.count is zero. When expected is passed, then this is compared with verify.count.
verify() always unsubscribes the event listeners, so that verify.count does not change. This means you have to create a new verifier for each test run.
it("should do something", function () {
  var verify = referee.verifier();
  var limit = 10;
  for (var i = 0; i < 10; i++) {
    console.log(i);
  }
  // this test will fail as no assertions have been made
  verify();
});
it("should do something", function () {
  var verify = referee.verifier();
  var limit = 10;
  for (var i = 0; i < 10; i++) {
    assert.isTrue(true);
  }
  // this will pass because exactly 10 (`limit`) assertions have been made
  verify(limit);
  console.log(verify.count);
  // 10
});
Properties
referee.throwOnFailure
Boolean.
When using the default referee.fail() implementation, this property can be set to false to make assertion failures not throw exceptions (i.e. only emit events). This may be suitable in asynchronous test runners, where you might not be able to catch exceptions.
Supporting objects
class AssertionError()
An exception (specifically, an Error object) whose name property is "AssertionError".