unexpected
Version:
Extensible BDD assertion toolkit
1,147 lines (1,020 loc) • 183 kB
JavaScript
/*global weknowhow, describe, it, beforeEach, setTimeout, Int8Array, Uint8Array, Uint16Array, Uint32Array*/
var expect = typeof weknowhow === 'undefined' ? require('../lib/') : weknowhow.expect;
// use this instead of Object.create in order to make the tests run in
// browsers that are not es5 compatible.
function create(o) {
function F() {}
F.prototype = o;
return new F();
}
it.skipIf = function (condition) {
(condition ? it.skip : it).apply(it, Array.prototype.slice.call(arguments, 1));
};
var circular = {};
circular.self = circular;
expect.addType({
name: 'magicpen',
identify: function (obj) {
return obj && obj.isMagicPen;
},
inspect: function (pen, depth, output) {
return output.append(pen);
},
equal: function (a, b) {
return a.toString() === b.toString() &&
a.toString('ansi') === b.toString('ansi') &&
a.toString('html') === b.toString('html');
}
});
expect.addAssertion('to have message', function (expect, subject, value) {
// Copied from https://github.com/sindresorhus/ansi-regex
var ansiRegex = /(?:(?:\u001b\[)|\u009b)(?:(?:[0-9]{1,3})?(?:(?:;[0-9]{0,3})*)?[A-M|f-m])|\u001b[A-M]/g;
expect(subject.output.toString(), 'to equal', value);
expect(subject.message.replace(ansiRegex, ''), 'to equal', '\n' + value);
});
describe('unexpected', function () {
describe('argument validation', function () {
it('fails when given no parameters', function () {
expect(function () {
expect();
}, 'to throw', 'The expect function requires at least two parameters.');
});
it('fails when given only one parameter', function () {
expect(function () {
expect({});
}, 'to throw', 'The expect function requires at least two parameters.');
});
it('fails when the second parameter is not a string', function () {
expect(function () {
expect({}, {});
}, 'to throw', 'The expect function requires the second parameter to be a string.');
});
});
describe('ok/truthy/falsy assertion', function () {
it('assert that the value is truthy or not', function () {
expect(1, 'to be ok');
expect(true, 'to be ok');
expect(true, 'not to be falsy');
expect({}, 'to be truthy');
expect(0, 'not to be ok');
expect(0, 'to be falsy');
expect(null, 'to be falsy');
expect(undefined, 'to be falsy');
});
it('throws when the assertion fails', function () {
expect(function () {
expect(0, 'to be ok');
}, 'to throw exception', 'expected 0 to be ok');
});
it('throws with message when the assertion fails', function () {
expect(function () {
expect(4 < 4, 'to be ok', '4 < 4');
}, "to throw exception", "expected false to be ok '4 < 4'");
});
it('formats Error instances correctly when an assertion fails', function () {
expect(function () {
var error = new Error('error message');
error.data = 'extra';
expect(error, 'to be a number');
}, 'to throw', "expected Error({ message: 'error message', data: 'extra' }) to be a number");
});
describe('with Error instances', function () {
it('considers Error instances with different messages to be different', function () {
expect(function () {
expect(new Error('foo'), 'to equal', new Error('bar'));
}, 'to throw exception', function (err) {
expect(err.output.toString(), 'to equal',
"expected Error({ message: 'foo' }) to equal Error({ message: 'bar' })\n" +
"\n" +
"Error({\n" +
" message: 'foo' // should equal 'bar'\n" +
" // -foo\n" +
" // +bar\n" +
"})");
});
});
it('considers Error instances with the same message but different stacks to be equal', function () {
var err1 = new Error('foo'),
err2 = new Error('foo');
expect(err1, 'to equal', err2);
});
it('considers Error instances with the same message and extra properties to be equal', function () {
var err1 = new Error('foo'),
err2 = new Error('foo');
err1.extra = 'foo';
err2.extra = 'foo';
expect(err1, 'to equal', err2);
});
it('considers Error instances with the same message but different extra properties to be different', function () {
var err1 = new Error('foo'),
err2 = new Error('foo');
err1.extra = 'foo';
err2.extra = 'bar';
expect(function () {
expect(err1, 'to equal', err2);
}, 'to throw exception',
"expected Error({ message: 'foo', extra: 'foo' }) to equal Error({ message: 'foo', extra: 'bar' })\n" +
"\n" +
"Error({\n" +
" message: 'foo',\n" +
" extra: 'foo' // should equal 'bar'\n" +
" // -foo\n" +
" // +bar\n" +
"})");
});
it('considers Error instances with the same message and stack to be equal', function () {
var errors = [];
for (var i = 0 ; i < 2 ; i += 1) {
errors.push(new Error('foo'));
}
expect(errors[0], 'to equal', errors[1]);
});
});
it('throws with a stack trace that has the calling function as the top frame when the assertion fails (if the environment supports it)', function () {
if (Error.captureStackTrace || 'stack' in new Error()) {
expect(function TheCallingFunction() {
expect(4 < 4, 'to be ok');
}, 'to throw exception', function (err) {
expect(err.stack.split('\n')[2], 'to match', /TheCallingFunction/);
});
}
});
});
describe('be assertion', function () {
it('assert === equality', function () {
var obj = {};
expect(obj, 'to be', obj);
expect(obj, 'not to be', {});
expect(1, 'to be', 1);
expect(1, 'not to be', true);
expect('1', 'not to be', 1);
expect(null, 'not to be', undefined);
expect(null, 'to be null');
expect(0, 'not to be null');
expect(undefined, 'not to be null');
expect(true, 'to be true');
expect(false, 'not to be true');
expect(false, 'to be false');
expect(true, 'not to be false');
expect(undefined, 'to be undefined');
expect(false, 'to be defined');
expect({}, 'to be defined');
expect('', 'to be defined');
});
it('NaN as equal to NaN', function () {
expect(NaN, 'to be', NaN);
});
it('considers negative zero not to be zero', function () {
expect(-0, 'not to be', 0);
});
it('considers negative zero to be itself', function () {
expect(-0, 'to be', -0);
});
it('considers zero to be itself', function () {
expect(0, 'to be', 0);
});
it.skipIf(typeof Buffer === 'undefined', 'asserts === equality for Buffers', function () {
var buffer = new Buffer([0x45, 0x59]);
expect(buffer, 'to be', buffer);
});
it.skipIf(typeof Uint8Array === 'undefined', 'asserts === equality for Uint8Array', function () {
var uint8Array = new Uint8Array([0x45, 0x59]);
expect(uint8Array, 'to be', uint8Array);
});
it('throws when the assertion fails', function () {
expect(function () {
expect('foo', 'to be', 'bar');
}, 'to throw exception',
"expected 'foo' to be 'bar'\n" +
"\n" +
"-foo\n" +
"+bar");
expect(function () {
expect(true, 'not to be', true);
}, 'to throw exception', "expected true not to be true");
expect(function () {
expect(undefined, 'to be defined');
}, 'to throw exception', "expected undefined to be defined");
});
it('does not provide a diff when comparing against undefined', function () {
expect(function () {
expect('blabla', 'to be undefined');
}, 'to throw', "expected 'blabla' to be undefined");
});
});
describe('a/an assertion', function () {
it('asserts typeof with support for array type and instanceof', function () {
expect(5, 'to be a', 'number');
expect(5, 'to be a number');
expect('abc', 'to be a', 'string');
expect('', 'to be a string');
expect('', 'to be the empty string');
expect('', 'to be an empty string');
expect('abc', 'to be a non-empty string');
expect([], 'to be an', 'array');
expect([], 'to be an array');
expect(['abc'], 'to be an array of strings');
expect([{}], 'to be an array of objects');
expect([{}], 'to be a non-empty array of objects');
expect([/foo/, /bar/], 'to be a non-empty array of regexps');
expect([/foo/, /bar/], 'to be a non-empty array of regexes');
expect([[], [], []], 'to be an array of arrays');
expect(['abc'], 'to be a non-empty array of strings');
expect([], 'to be an empty array');
expect({}, 'to be an', Object);
expect([123], 'to be a non-empty array');
expect([], 'to be an', 'object');
expect([], 'to be an object');
expect([], 'to be an', Array);
expect(/ab/, 'to be a', RegExp);
expect(/ab/, 'to be a regexp');
expect(123, 'not to be a regex');
expect(/ab/, 'to be a regex');
expect(/ab/, 'to be a regular expression');
expect(123, 'not to be a regular expression');
expect(null, 'not to be an', 'object');
expect(null, 'not to be an object');
expect(true, 'to be a', 'boolean');
expect(true, 'to be a boolean');
expect(expect, 'to be a', 'function');
expect(expect, 'to be a function');
expect(circular, 'to be an object');
});
it('throws when the assertion fails', function () {
expect(function () {
expect(5, 'to be an', Array);
}, 'to throw exception', 'expected 5 to be an Array');
expect(function () {
expect([], 'not to be an', 'array');
}, 'to throw exception', "expected [] not to be an array");
expect(function () {
expect(circular, 'not to be an object');
}, 'to throw exception', "expected { self: [Circular] } not to be an object");
});
it("throws an error a diff when comparing string and not negated", function () {
expect(function () {
expect('foo', 'to be', 'bar');
}, 'to throw exception', function (e) {
expect(e.output.toString(), 'to equal',
"expected 'foo' to be 'bar'\n" +
"\n" +
"-foo\n" +
"+bar");
});
});
it("throws an error without actual and expected when comparing string and negated", function () {
expect(function () {
expect('foo', 'not to be', 'foo');
}, 'to throw exception', function (e) {
expect(e, 'not to have property', 'actual');
expect(e, 'not to have property', 'expected');
});
});
it("throws an error without actual and expected when not comparing string and not negated", function () {
expect(function () {
expect('foo', 'to be', {});
}, 'to throw exception', function (e) {
expect(e, 'not to have property', 'actual');
expect(e, 'not to have property', 'expected');
});
});
});
describe('equal assertion', function () {
it('asserts deep equality that works with objects', function () {
expect({ a: 'b' }, 'to equal', { a: 'b' });
expect(1, 'not to equal', '1');
expect({ foo: 1 }, 'not to equal', { foo: '1' });
expect(1, 'to equal', 1);
expect(null, 'not to equal', '1');
var now = new Date();
expect(now, 'to equal', now);
expect(now, 'to equal', new Date(now.getTime()));
expect({ now: now }, 'to equal', { now: now });
expect(null, 'to equal', null);
expect(null, 'not to equal', undefined);
expect(undefined, 'to equal', undefined);
expect(true, 'to equal', true);
expect(false, 'to equal', false);
expect({ a: { b: 'c' } }, 'to equal', { a: { b: 'c' } });
expect({ a: { b: 'c' } }, 'not to equal', { a: { b: 'd' } });
expect({}, 'to equal', { a: undefined });
expect(/foo/, 'to equal', /foo/);
expect(/foo/i, 'not to equal', /foo/);
expect(/foo/gm, 'to equal', /foo/gm);
expect(/foo/m, 'not to equal', /foo/i);
expect(/foo/m, 'to equal', new RegExp('foo', 'm'));
expect([], 'not to equal', 0);
expect(new Error('foo'), 'to equal', new Error('foo'));
});
it('treats NaN as equal to NaN', function () {
expect(NaN, 'to equal', NaN);
});
it('treats negative zero and zero as unequal', function () {
expect(-0, 'not to equal', 0);
});
it('treats negative zero as equal to itself', function () {
expect(-0, 'to equal', -0);
});
it('treats zero as equal to itself', function () {
expect(0, 'to equal', 0);
});
it('treats an arguments object as different from an array', function () {
(function () {
expect(arguments, 'not to equal', ['foo', 'bar', 'baz']);
}('foo', 'bar', 'baz'));
});
it('array should not equal sparse array', function () {
expect(function () {
var sparse = [];
sparse[1] = 2;
expect(sparse, 'to equal', [1, 2]);
}, 'to throw');
expect(function () {
var sparse = [];
sparse[1] = 2;
expect([1, 2], 'to equal', sparse);
}, 'to throw');
});
it('should handle objects with no prototype', function () {
expect(Object.create(null), 'to equal', Object.create(null));
expect(function () {
expect(Object.create(null), 'to equal', {});
}, 'to throw',
"expected {} to equal {}\n" +
"\n" +
"Mismatching constructors undefined should be Object");
expect(function () {
expect({}, 'to equal', Object.create(null));
}, 'to throw',
"expected {} to equal {}\n" +
"\n" +
"Mismatching constructors Object should be undefined");
});
it('should treat properties with a value of undefined as equivalent to missing properties', function () {
expect({foo: undefined, bar: 1}, 'to equal', {bar: 1});
expect({bar: 1}, 'to equal', {foo: undefined, bar: 1});
});
it.skipIf(typeof Buffer === 'undefined', 'asserts equality for Buffer instances', function () {
expect(new Buffer([0x45, 0x59]), 'to equal', new Buffer([0x45, 0x59]));
});
it.skipIf(typeof Uint8Array === 'undefined', 'asserts equality for Uint8Array', function () {
expect(new Uint8Array([0x45, 0x59]), 'to equal', new Uint8Array([0x45, 0x59]));
});
it('fails gracefully when comparing circular structures', function () {
var foo = {},
bar = {};
foo.foo = foo;
bar.foo = bar;
expect(function () {
expect(foo, 'not to equal', bar);
}, 'to throw', 'Cannot compare circular structures');
});
it('fails gracefully when producing a diff based on circular structures', function () {
var foo = { a: 'foo' };
var bar = { a: 'bar' };
foo.b = foo;
bar.b = bar;
expect(function () {
expect(foo, 'to equal', bar);
}, 'to throw', 'Cannot compare circular structures');
});
it('throws when the assertion fails', function () {
expect(function () {
expect({ a: { b: 'c'} }, 'to equal', { a: { b: 'd'} });
}, 'to throw exception', "expected { a: { b: 'c' } } to equal { a: { b: 'd' } }\n" +
"\n" +
"{\n" +
" a: {\n" +
" b: 'c' // should equal 'd'\n" +
" // -c\n" +
" // +d\n" +
" }\n" +
"}");
expect(function () {
expect({ a: 'b' }, 'not to equal', { a: 'b' });
}, 'to throw exception', "expected { a: 'b' } not to equal { a: 'b' }");
expect(function () {
expect(new Error('foo'), 'to equal', new Error('bar'));
}, 'to throw exception', "expected Error({ message: 'foo' }) to equal Error({ message: 'bar' })\n" +
"\n" +
"Error({\n" +
" message: 'foo' // should equal 'bar'\n" +
" // -foo\n" +
" // +bar\n" +
"})");
expect(function () {
(function () {
expect(arguments, 'to equal', ['foo', 'bar', 'baz']);
}('foo', 'bar'));
}, 'to throw exception', "expected arguments( 'foo', 'bar' ) to equal [ 'foo', 'bar', 'baz' ]\n" +
"\n" +
"Mismatching constructors Object should be Array");
});
it("throws an error with a diff when not negated", function () {
expect(function () {
expect('123', 'to equal', '456');
}, 'to throw exception',
"expected '123' to equal '456'\n" +
"\n" +
"-123\n" +
"+456");
});
it("throws an error without a diff when negated", function () {
expect(function () {
expect('123', 'not to equal', '123');
}, 'to throw exception', "expected '123' not to equal '123'");
});
it("throws an error with a diff when comparing arrays and not negated", function () {
expect(function () {
expect([1], 'to equal', [2]);
}, 'to throw exception', "expected [ 1 ] to equal [ 2 ]\n" +
"\n" +
"[\n" +
" 1 // should equal 2\n" +
"]");
expect(function () {
expect([0, { foo: 'bar' }, 1, { bar: 'bar'}, [1, 3, 2], 'bar'],
'to equal',
[0, 1, { foo: 'baz' }, 42, { qux: 'qux' }, [1, 2, 3], 'baz']);
}, 'to throw exception',
"expected [ 0, { foo: 'bar' }, 1, { bar: 'bar' }, [ 1, 3, 2 ], 'bar' ]\n" +
"to equal [ 0, 1, { foo: 'baz' }, 42, { qux: 'qux' }, [ 1, 2, 3 ], 'baz' ]\n" +
"\n" +
"[\n" +
" 0,\n" +
" // missing 1\n" +
" {\n" +
" foo: 'bar' // should equal 'baz'\n" +
" // -bar\n" +
" // +baz\n" +
" },\n" +
" 1, // should be removed\n" +
" // missing 42\n" +
" // missing { qux: 'qux' }\n" +
" { bar: 'bar' }, // should be removed\n" +
" [\n" +
" 1,\n" +
" 3, // should equal 2\n" +
" 2 // should equal 3\n" +
" ],\n" +
" 'bar' // should equal 'baz'\n" +
" // -bar\n" +
" // +baz\n" +
"]");
});
it("throws an error with a diff when comparing objects and not negated", function () {
expect(function () {
expect({foo: 1}, 'to equal', {foo: 2});
}, 'to throw exception', "expected { foo: 1 } to equal { foo: 2 }\n" +
"\n" +
"{\n" +
" foo: 1 // should equal 2\n" +
"}");
});
it("throws an error with a diff when comparing strings and not negated", function () {
expect(function () {
expect('foo', 'to equal', 'bar');
}, 'to throw exception', "expected 'foo' to equal 'bar'\n" +
"\n" +
"-foo\n" +
"+bar");
});
it("throws an error without actual and expected comparing strings and negated", function () {
expect(function () {
expect('foo', 'not to equal', 'foo');
}, 'to throw exception', function (e) {
expect(e, 'not to have property', 'actual');
expect(e, 'not to have property', 'expected');
});
});
it("throws an error without showDiff:true when comparing an object to an array", function () {
expect(function () {
expect({foo: 1}, 'to equal', []);
}, 'to throw exception', function (e) {
expect(e.showDiff, 'not to be ok');
});
});
it("throws an error without showDiff:true when negated", function () {
expect(function () {
expect({foo: 1}, 'not to equal', {foo: 1});
}, 'to throw exception', function (e) {
expect(e.showDiff, 'not to be ok');
});
});
it.skipIf(typeof Buffer === 'undefined', 'produces a hex-diff in JSON when Buffers differ', function () {
expect(function () {
expect(
new Buffer('\x00\x01\x02Here is the thing I was talking about', 'utf-8'),
'to equal',
new Buffer('\x00\x01\x02Here is the thing I was quuxing about', 'utf-8')
);
}, 'to throw',
'expected Buffer([0x00, 0x01, 0x02, 0x48, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74 /* 24 more */ ])\n' +
'to equal Buffer([0x00, 0x01, 0x02, 0x48, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74 /* 24 more */ ])\n' +
'\n' +
' 00 01 02 48 65 72 65 20 69 73 20 74 68 65 20 74 │...Here is the t│\n' +
'-68 69 6E 67 20 49 20 77 61 73 20 74 61 6C 6B 69 │hing I was talki│\n' +
'+68 69 6E 67 20 49 20 77 61 73 20 71 75 75 78 69 │hing I was quuxi│\n' +
' 6E 67 20 61 62 6F 75 74 │ng about│');
});
it.skipIf(typeof Buffer === 'undefined', 'regression test for infinite loop in buffer diff code', function () {
expect(function () {
expect(
new Buffer([0x63, 0x74, 0x3D, 0x54, 0x3B, 0xD4, 0x8C, 0x3B, 0x66, 0x6F, 0x6F, 0x3D, 0x62, 0x61, 0x72, 0x3B]),
'to equal',
Buffer.concat([
new Buffer('ct=T;;'),
new Buffer([0xa3, 0x3b]),
new Buffer(';foo=bar;')
])
);
}, 'to throw');
});
it.skipIf(typeof Buffer === 'undefined', 'suppresses Buffer diff for large buffers', function () {
expect(function () {
var a = new Buffer(1024),
b = new Buffer(1024);
a[0] = 1;
b[0] = 2;
expect(
a,
'to equal',
b
);
}, 'to throw', /Diff suppressed due to size > 512/);
});
it.skipIf(typeof Int8Array === 'undefined' || !Array.prototype.map, 'produces a hex-diff in JSON when Int8Arrays differ', function () {
expect(function () {
expect(
new Int8Array([
0x00, 0x01, 0x02, 0x48, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
0x68, 0x69, 0x6E, 0x67, 0x20, 0x49, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x61, 0x6C, 0x6B, 0x69,
0x6E, 0x67, 0x20, 0x61, 0x62, 0x6F, 0x75, 0x74
]),
'to equal',
new Int8Array([
0x00, 0x01, 0x02, 0x48, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
0x68, 0x69, 0x6E, 0x67, 0x20, 0x49, 0x20, 0x77, 0x61, 0x73, 0x20, 0x71, 0x75, 0x75, 0x78, 0x69,
0x6E, 0x67, 0x20, 0x61, 0x62, 0x6F, 0x75, 0x74
])
);
}, 'to throw',
'expected Int8Array([0x00, 0x01, 0x02, 0x48, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74 /* 24 more */ ])\n' +
'to equal Int8Array([0x00, 0x01, 0x02, 0x48, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74 /* 24 more */ ])\n' +
'\n' +
' 00 01 02 48 65 72 65 20 69 73 20 74 68 65 20 74 │...Here is the t│\n' +
'-68 69 6E 67 20 49 20 77 61 73 20 74 61 6C 6B 69 │hing I was talki│\n' +
'+68 69 6E 67 20 49 20 77 61 73 20 71 75 75 78 69 │hing I was quuxi│\n' +
' 6E 67 20 61 62 6F 75 74 │ng about│');
});
it.skipIf(typeof Uint8Array === 'undefined' || !Array.prototype.map, 'produces a hex-diff in JSON when Uint8Arrays differ', function () {
expect(function () {
expect(
new Uint8Array([
0x00, 0x01, 0x02, 0x48, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
0x68, 0x69, 0x6E, 0x67, 0x20, 0x49, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x61, 0x6C, 0x6B, 0x69,
0x6E, 0x67, 0x20, 0x61, 0x62, 0x6F, 0x75, 0x74
]),
'to equal',
new Uint8Array([
0x00, 0x01, 0x02, 0x48, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
0x68, 0x69, 0x6E, 0x67, 0x20, 0x49, 0x20, 0x77, 0x61, 0x73, 0x20, 0x71, 0x75, 0x75, 0x78, 0x69,
0x6E, 0x67, 0x20, 0x61, 0x62, 0x6F, 0x75, 0x74
])
);
}, 'to throw',
'expected Uint8Array([0x00, 0x01, 0x02, 0x48, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74 /* 24 more */ ])\n' +
'to equal Uint8Array([0x00, 0x01, 0x02, 0x48, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74 /* 24 more */ ])\n' +
'\n' +
' 00 01 02 48 65 72 65 20 69 73 20 74 68 65 20 74 │...Here is the t│\n' +
'-68 69 6E 67 20 49 20 77 61 73 20 74 61 6C 6B 69 │hing I was talki│\n' +
'+68 69 6E 67 20 49 20 77 61 73 20 71 75 75 78 69 │hing I was quuxi│\n' +
' 6E 67 20 61 62 6F 75 74 │ng about│');
});
it.skipIf(typeof Uint16Array === 'undefined', 'produces a hex-diff in JSON when Uint16Arrays differ', function () {
expect(function () {
expect(
new Uint16Array([
0x0001, 0x0248, 0x6572, 0x6520, 0x6973, 0x2074, 0x6865, 0x2074,
0x6869, 0x6E67, 0x2049, 0x2077, 0x6173, 0x2074, 0x616C, 0x6B69,
0x6E67, 0x2061, 0x626F, 0x7574
]),
'to equal',
new Uint16Array([
0x0001, 0x0248, 0x6572, 0x6520, 0x6973, 0x2074, 0x6865, 0x2074,
0x6869, 0x6E67, 0x2049, 0x2077, 0x6173, 0x2071, 0x7575, 0x7869,
0x6E67, 0x2061, 0x626F, 0x7574
])
);
}, 'to throw',
'expected Uint16Array([0x0001, 0x0248, 0x6572, 0x6520, 0x6973, 0x2074, 0x6865, 0x2074 /* 12 more */ ])\n' +
'to equal Uint16Array([0x0001, 0x0248, 0x6572, 0x6520, 0x6973, 0x2074, 0x6865, 0x2074 /* 12 more */ ])\n' +
'\n' +
' 0001 0248 6572 6520 6973 2074 6865 2074\n' +
'-6869 6E67 2049 2077 6173 2074 616C 6B69\n' +
'+6869 6E67 2049 2077 6173 2071 7575 7869\n' +
' 6E67 2061 626F 7574'
);
});
it.skipIf(typeof Uint32Array === 'undefined', 'produces a hex-diff in JSON when Uint32Arrays differ', function () {
expect(function () {
expect(
new Uint32Array([
0x00010248, 0x65726520, 0x69732074, 0x68652074,
0x68696E67, 0x20492077, 0x61732074, 0x616C6B69,
0x6E672061, 0x626F7574
]),
'to equal',
new Uint32Array([
0x00010248, 0x65726520, 0x69732074, 0x68652074,
0x68696E67, 0x20492077, 0x61732071, 0x75757869,
0x6E672061, 0x626F7574
])
);
}, 'to throw',
'expected Uint32Array([0x00010248, 0x65726520, 0x69732074, 0x68652074 /* 6 more */ ])\n' +
'to equal Uint32Array([0x00010248, 0x65726520, 0x69732074, 0x68652074 /* 6 more */ ])\n' +
'\n' +
' 00010248 65726520 69732074 68652074\n' +
'-68696E67 20492077 61732074 616C6B69\n' +
'+68696E67 20492077 61732071 75757869\n' +
' 6E672061 626F7574'
);
});
});
describe('exception assertion', function () {
var phantomJsErrorWeirdness;
try {
throw new Error('foo');
} catch (e) {
phantomJsErrorWeirdness = Object.keys(e).indexOf('sourceURL') >= 0;
}
it.skipIf(phantomJsErrorWeirdness, 'fails if no exception is thrown', function () {
expect(function () {
expect(function () {
// Don't throw
}, 'to throw exception');
}, 'to throw',
'expected\n' +
'function () {\n' +
' // Don\'t throw\n' +
'}\n' +
'to throw exception');
});
it.skipIf(phantomJsErrorWeirdness, 'fails if exception is thrown', function () {
expect(function () {
expect(function testFunction() {
throw new Error('The Error');
}, 'not to throw');
}, 'to throw',
'expected\n' +
'function testFunction() {\n' +
' throw new Error(\'The Error\');\n' +
'}\n' +
'not to throw\n' +
" threw: Error({ message: 'The Error' })");
});
it('fails if the argument is not a function', function () {
expect(function () {
expect(1, 'to throw exception');
}, 'to throw exception',
'The assertion "to throw exception" is not defined for the type "number",\n' +
'but it is defined for the type "function"');
});
it('given a function the function is called with the exception', function () {
expect(function () {
throw new SyntaxError();
}, 'to throw exception', function (e) {
expect(e, 'to be a', SyntaxError);
});
});
it('matches the message against the given regular expression', function () {
expect(function () {
throw new Error('matches the exception message');
}, 'to throw exception', /matches the exception message/);
expect(function () {
throw new Error('Other error');
}, 'not to throw exception', /matches the exception message/);
});
it('provides a diff when the exception message does not match the given string', function () {
expect(function () {
expect(function testFunction() {
throw new Error('bar');
}, 'to throw', 'foo');
}, 'to throw exception',
'expected\n' +
'function testFunction() {\n' +
' throw new Error(\'bar\');\n' +
'}\n' +
'to throw \'foo\'\n' +
' expected \'bar\' to equal \'foo\'\n' +
'\n' +
' -bar\n' +
' +foo');
});
it('exactly matches the message against the given string', function () {
expect(function () {
throw new Error('matches the exception message');
}, 'to throw exception', 'matches the exception message');
expect(function () {
throw new Error('matches the exception message');
}, 'not to throw exception', 'the exception message');
});
it('does not break if null is thrown', function () {
expect(function () {
expect(function () {
throw null;
}, 'not to throw');
}, 'to throw',
'expected\n' +
'function () {\n' +
' throw null;\n' +
'}\n' +
'not to throw\n' +
' threw: null');
});
});
describe('arity assertion', function () {
it('tests that the subject function has the given arity', function () {
expect(function () {}, 'to have arity', 0);
expect(function (a) {}, 'to have arity', 1);
expect(function (a, b) {}, 'to have arity', 2);
/*jshint evil:true*/
expect(new Function('a', 'return 1'), 'to have arity', 1);
/*jshint evil:false*/
});
});
describe('match assertion', function () {
it('tests that the subject matches the given regular expression', function () {
expect('test', 'to match', /.*st/);
expect('test', 'not to match', /foo/);
});
it('does not keep state between invocations', function () {
// This tests that the assertion does not depend on the lastIndex
// property of the regexp:
var regExp = /a/g,
str = 'aa';
expect(str, 'to match', regExp);
expect(str, 'to match', regExp);
expect(str, 'to match', regExp);
});
it('throws when the assertion fails', function () {
expect(function () {
expect('test', 'to match', /foo/);
}, 'to throw exception', "expected 'test' to match /foo/");
});
it('provides a diff when the not flag is set', function () {
expect(function () {
expect('barfooquuxfoobaz', 'not to match', /foo/);
}, 'to throw',
"expected 'barfooquuxfoobaz' not to match /foo/\n" +
'\n' +
'barfooquuxfoobaz');
});
});
describe('contain assertion', function () {
it('asserts indexOf for a string', function () {
expect('hello world', 'to contain', 'world');
});
it('should support searching for a non-string inside a string', function () {
expect('hello null', 'to contain', null);
expect('hello 123', 'to contain', 123);
expect('hello false', 'to contain', false);
expect('hello Infinity', 'to contain', Infinity);
});
it('asserts item equality for an array', function () {
expect([1, 2], 'to contain', 1);
expect([1, 2], 'to contain', 2, 1);
expect([{foo: 123}], 'to contain', {foo: 123});
});
it('throws when the assertion fails', function () {
expect(function () {
expect(null, 'not to contain', 'world');
}, 'to throw',
'The assertion "not to contain" is not defined for the type "null",\n' +
'but it is defined for these types: "string", "array-like"');
expect(function () {
expect('hello world', 'to contain', 'foo');
}, 'to throw exception', "expected 'hello world' to contain 'foo'");
expect(function () {
expect('hello world', 'to contain', 'hello', 'foo');
}, 'to throw exception', "expected 'hello world' to contain 'hello', 'foo'");
expect(function () {
expect([1, 2], 'to contain', 2, 3);
}, 'to throw exception', "expected [ 1, 2 ] to contain 2, 3");
expect(function () {
expect([{foo: 123}], 'to contain', {foo: 123}, {bar: 456});
}, 'to throw exception', "expected [ { foo: 123 } ] to contain { foo: 123 }, { bar: 456 }");
expect(function () {
expect(1, 'to contain', 1);
}, 'to throw exception',
'The assertion "to contain" is not defined for the type "number",\n' +
'but it is defined for these types: "string", "array-like"');
});
it('produces a diff when the array case fails and the not flag is on', function () {
expect(function () {
expect([1, 2, 3], 'not to contain', 2);
}, 'to throw',
'expected [ 1, 2, 3 ] not to contain 2\n' +
'\n' +
'[\n' +
' 1,\n' +
' 2, // should be removed\n' +
' 3\n' +
']');
});
it('produces a diff when the string case fails and the not flag is on', function () {
expect(function () {
expect('foobarquuxfoo', 'not to contain', 'foo');
}, 'to throw',
"expected 'foobarquuxfoo' not to contain 'foo'\n" +
'\n' +
'foobarquuxfoo');
});
});
describe('length assertion', function () {
it('asserts array .length', function () {
expect([], 'to have length', 0);
expect([1, 2, 3], 'to have length', 3);
expect([1, 2, 3], 'not to have length', 4);
expect((function () {
return arguments;
}(1,2,3,4)), 'to have length', 4);
});
it('asserts string .length', function () {
expect('abc', 'to have length', 3);
expect('', 'to have length', 0);
});
it('assert sparse array length', function () {
var sparse = [];
sparse[1] = 'foo';
expect(function () {
expect(sparse, 'to have length', 2);
}, 'not to throw');
});
it.skipIf(typeof Buffer === 'undefined', 'asserts Buffer .length', function () {
expect(new Buffer('æ', 'utf-8'), 'to have length', 2);
expect(new Buffer([]), 'to have length', 0);
});
it.skipIf(typeof Uint8Array === 'undefined', 'asserts length for Uint8Array', function () {
expect(new Uint8Array([0x45, 0x59]), 'to have length', 2);
});
it.skipIf(typeof Uint16Array === 'undefined', 'asserts length for Uint16Array', function () {
expect(new Uint16Array([0x4545, 0x5945]), 'to have length', 2);
});
it('throws when the assertion fails', function () {
expect(function () {
expect([1, 2], 'to have length', 3);
}, 'to throw exception',
"expected [ 1, 2 ] to have length 3\n" +
" expected 2 to be 3");
expect(function () {
expect(null, 'to have length', 4);
}, 'to throw exception',
'The assertion "to have length" is not defined for the type "null",\n' +
'but it is defined for these types: "string", "array-like"');
expect(function () {
expect({ length: 4 }, 'to have length', 4);
}, 'to throw exception',
'The assertion "to have length" is not defined for the type "object",\n' +
'but it is defined for these types: "string", "array-like"');
});
});
describe('property assertion', function () {
it('asserts presence of an own property (and value optionally)', function () {
expect([1, 2], 'to have property', 'length');
expect([1, 2], 'to have property', 'length', 2);
expect({a: 'b'}, 'to have property', 'a');
expect({a: 'b'}, 'to have property', 'a', 'b');
expect({a: 'b'}, 'to have property', 'toString');
expect({a: 'b'}, 'not to have property', 'b');
expect({'"a"': 'b'}, 'to have own property', '"a"');
expect(create({a: 'b'}), 'not to have own property', 'a');
expect(function () {}, 'to have property', 'toString');
});
it('throws when the assertion fails', function () {
expect(function () {
expect({a: 'b'}, 'to have property', 'b');
}, 'to throw exception', "expected { a: 'b' } to have property 'b'");
expect(function () {
expect(null, 'to have property', 'b');
}, 'to throw exception',
'The assertion "to have property" is not defined for the type "null",\n' +
'but it is defined for the type "object"');
expect(function () {
expect({a: 'b'}, 'to have property', 'a', 'c');
}, 'to throw exception',
"expected { a: 'b' } to have property 'a', 'c'\n" +
"\n" +
"-b\n" +
"+c");
expect(function () {
expect({a: 'b'}, 'to have own property', 'a', 'c');
}, 'to throw exception',
"expected { a: 'b' } to have own property 'a', 'c'\n" +
"\n" +
"-b\n" +
"+c");
expect(function () {
// property expectations ignores value if property
expect(null, 'not to have property', 'a', 'b');
}, 'to throw exception',
'The assertion "not to have property" is not defined for the type "null",\n' +
'but it is defined for the type "object"');
expect(function () {
// property expectations on value expects the property to be present
expect(null, 'not to have own property', 'a', 'b');
}, 'to throw exception',
'The assertion "not to have own property" is not defined for the type "null",\n' +
'but it is defined for the type "object"');
});
});
describe('properties assertion', function () {
it('asserts presence of a list of properties', function () {
expect({a: 'foo', b: 'bar'}, 'to have properties', ['a', 'b']);
});
it('asserts presence of a list of own properties', function () {
expect({a: 'foo', b: 'bar'}, 'to have own properties', ['a', 'b']);
expect(function () {
var obj = create({a: 'foo', b: 'bar'});
expect(obj, 'to have properties', ['a', 'b']); // should not fail
expect(obj, 'to have own properties', ['a', 'b']); // should fail
}, 'to throw', "expected {} to have own properties [ 'a', 'b' ]");
});
it('asserts the absence of a property when the RHS object has an undefined value', function () {
expect({}, 'to have properties', { a: undefined });
});
it('asserts absence of a list of properties', function () {
expect({a: 'foo', b: 'bar'}, 'not to have properties', ['c', 'd']);
expect(function () {
expect({a: 'foo', b: 'bar'}, 'not to have properties', ['a', 'd']);
}, 'to throw', "expected { a: 'foo', b: 'bar' } not to have properties [ 'a', 'd' ]");
});
it('asserts absence of a list of own properties', function () {
var obj = create({a: 'foo', b: 'bar'});
expect(obj, 'to have properties', ['a', 'b']);
expect(obj, 'not to have own properties', ['a', 'b']);
expect(function () {
expect({a: 'foo', b: 'bar'}, 'not to have own properties', ['a', 'b']); // should fail
}, 'to throw', "expected { a: 'foo', b: 'bar' } not to have own properties [ 'a', 'b' ]");
});
it('asserts presence and values of an object of properties', function () {
expect({a: 'foo', b: 'bar', c: 'baz', d: { qux: 'qux', quux: 'quux'}}, 'to have properties', {
a: 'foo',
b: 'bar',
d: { qux: 'qux', quux: 'quux'}
});
expect(function () {
expect({a: 'foo', b: 'bar'}, 'to have properties', {c: 'baz'});
}, 'to throw', "expected { a: 'foo', b: 'bar' } to have properties { c: 'baz' }\n" +
"\n" +
"{\n" +
" a: 'foo',\n" +
" b: 'bar',\n" +
" c: undefined // should equal 'baz'\n" +
"}");
expect(function () {
expect({a: 'foo', b: 'bar'}, 'to have properties', {b: 'baz'});
}, 'to throw', "expected { a: 'foo', b: 'bar' } to have properties { b: 'baz' }\n" +
"\n" +
"{\n" +
" a: 'foo',\n" +
" b: 'bar' // should equal 'baz'\n" +
" // -bar\n" +
" // +baz\n" +
"}");
});
it('asserts presence and values of an object of own properties', function () {
expect({a: 'foo', b: 'bar'}, 'to have own properties', {a: 'foo', b: 'bar'});
expect(function () {
var obj = create({a: 'foo', b: 'bar'});
expect(obj, 'to have properties', {a: 'foo', b: 'bar'}); // should not fail
expect(obj, 'to have own properties', {a: 'foo', b: 'bar'}); // should fail
}, 'to throw', "expected {} to have own properties { a: 'foo', b: 'bar' }\n" +
"\n" +
"{\n" +
" a: undefined, // should equal 'foo'\n" +
" b: undefined // should equal 'bar'\n" +
"}");
expect(function () {
expect({a: 'f00', b: 'bar'}, 'to have own properties', {a: 'foo', b: 'bar'}); // should fail
}, 'to throw', "expected { a: 'f00', b: 'bar' } to have own properties { a: 'foo', b: 'bar' }\n" +
"\n" +
"{\n" +
" a: 'f00', // should equal 'foo'\n" +
" // -f00\n" +
" // +foo\n" +
" b: 'bar'\n" +
"}");
});
it('asserts absence and values of an object of own properties', function () {
var obj = create({a: 'foo', b: 'bar'});
expect(obj, 'to have properties', {a: 'foo', b: 'bar'});
expect(obj, 'not to have own properties', ['a', 'b']);
expect(function () {
expect({a: 'foo', b: 'bar'}, 'not to have own properties', ['a', 'b']); // should fail
}, 'to throw', "expected { a: 'foo', b: 'bar' } not to have own properties [ 'a', 'b' ]");
});
it('includes prototype properties in the actual property (#48)', function () {
function Foo() {}
Foo.protot