unexpected
Version:
Extensible BDD assertion toolkit
1,154 lines (1,033 loc) • 356 kB
JavaScript
/*global unexpected, xdescribe, xit, beforeAll, afterAll, before:true, after:true*/
if (!it.skip && xit) {
it.skip = function () {
xit.apply(it, arguments);
};
}
if (!describe.skip && xdescribe) {
describe.skip = function () {
xdescribe.apply(describe, arguments, 1);
};
}
before = typeof before === 'function' ? before : beforeAll;
after = typeof after === 'function' ? after : afterAll;
it.skipIf = function (condition) {
(condition ? it.skip : it).apply(it, Array.prototype.slice.call(arguments, 1));
};
describe.skipIf = function (condition) {
(condition ? describe.skip : describe).apply(describe, Array.prototype.slice.call(arguments, 1));
};
function toArguments() {
return arguments;
}
describe('unexpected', function () {
var workQueue = typeof weknowhow === 'undefined' ? require('../lib/workQueue') : null;
var expect = unexpected.clone();
expect.output.preferredWidth = 80;
var circular = {};
circular.self = circular;
expect.addAssertion('when delayed a little bit', function (expect, subject) {
return expect.promise(function (run) {
setTimeout(run(function () {
return expect.shift(subject, 0);
}), 1);
});
}).addAssertion('when delayed', function (expect, subject, value) {
return expect.promise(function (run) {
setTimeout(run(function () {
return expect.shift(subject, 1);
}), value);
});
}).addAssertion('to inspect as', function (expect, subject, value) {
expect(expect.inspect(subject).toString(), 'to equal', value);
});
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('magicpen type', function () {
describe('#inspect', function () {
it('should find two pens with different formats to not to be identical', function () {
var MagicPen = expect.output.constructor;
expect(new MagicPen('text').text('foo'), 'not to equal', new MagicPen('ansi').text('foo'));
});
it('should find two format-less pens with the same contents to be identical', function () {
var MagicPen = expect.output.constructor;
expect(new MagicPen().text('foo'), 'to equal', new MagicPen().text('foo'));
});
describe('with a pen in text format', function () {
var pen = expect.createOutput('text').green('abc').nl().text('def').block(function () {
this.text('foo').nl().text('bar');
});
it('should inspect correctly', function () {
expect(pen, 'to inspect as',
"magicpen('text') // abc\n" +
" .green('abc').nl() // deffoo\n" +
" .text('def') // bar\n" +
" .block(function () {\n" +
" this\n" +
" .text('foo').nl()\n" +
" .text('bar');\n" +
" })"
);
});
});
describe('with a pen in ansi format', function () {
var pen = expect.createOutput('ansi').green('abc').text('def').block(function () {
this.text('foo');
});
it('should inspect correctly', function () {
expect(pen, 'to inspect as',
"magicpen('ansi')\n" +
" .green('abc')\n" +
" .text('def')\n" +
" .block(function () {\n" +
" this.text('foo');\n" +
" })"
);
});
});
describe('with a pen in ansi format', function () {
var pen = expect.createOutput('html').green('abc').text('def').block(function () {
this.text('foo');
});
it('should inspect correctly', function () {
expect(pen, 'to inspect as',
"magicpen('html')\n" +
" .green('abc')\n" +
" .text('def')\n" +
" .block(function () {\n" +
" this.text('foo');\n" +
" })"
);
});
});
});
});
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',
"expected Error('foo') to equal Error('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' })\n" +
"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('ignores blacklisted properties in the diff', function () {
var error = new Error('foo');
error.description = 'qux';
expect(function () {
expect(error, 'to satisfy', new Error('bar'));
}, 'to throw',
"expected Error('foo') to satisfy Error('bar')\n" +
"\n" +
"Error({\n" +
" message: 'foo' // should equal 'bar'\n" +
" // -foo\n" +
" // +bar\n" +
"})");
});
});
});
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([], '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('should support type objects', function () {
expect('foo', 'to be a', expect.getType('string'));
});
describe('with a type name', function () {
it('should succeed when the subject is recognized as having the type', function () {
expect(new Error('foo'), 'to be an', 'Error');
});
it('should fail when the subject is not recognized as having the type', function () {
expect(function () {
expect(123, 'to be an', 'Error');
}, 'to throw', 'expected 123 to be an Error');
});
// Maybe better: throw a non-Unexpected error
it('should fail when the type is not defined', function () {
expect(function () {
expect(123, 'to be a', 'FoopQuuxDoop');
}, 'to throw', 'expected 123 to be a FoopQuuxDoop');
});
});
it('should fail with the correct error message if the type is given as an anonymous function', function () {
expect(function () {
expect('foo', 'to be a', function () {});
}, 'to throw', "expected 'foo' to be a function () {}");
});
it('should throw when the type is specified as undefined', function () {
expect(function () {
expect('foo', 'to be an', undefined);
}, 'to throw', "The 'to be an' assertion requires either a string (type name), a type object, or function argument");
});
it('should throw when the type is specified as null', function () {
expect(function () {
expect('foo', 'to be a', null);
}, 'to throw', "The 'to be a' assertion requires either a string (type name), a type object, or function argument");
});
it('should not consider a string a to be an instance of an object without a name property', function () {
expect(function () {
expect('foo', 'to be a', {});
}, 'to throw', "The 'to be a' assertion requires either a string (type name), a type object, or function argument");
});
it('should throw when the type is specified as an object without an identify function', function () {
expect(function () {
expect('foo', 'to be a', { name: 'bar' });
}, 'to throw', "The 'to be a' assertion requires either a string (type name), a type object, or function argument");
});
it('should throw when the type is specified as an object with an identify function, but without a name property', function () {
expect(function () {
expect('foo', 'to be a', { identify: function () { return true; } });
}, 'to throw', "The 'to be a' assertion requires either a string (type name), a type object, or function argument");
});
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',
"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 () {
expect(toArguments('foo', 'bar', 'baz'), 'not to equal', ['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('foo') to equal Error('bar')\n" +
"\n" +
"Error({\n" +
" message: 'foo' // should equal 'bar'\n" +
" // -foo\n" +
" // +bar\n" +
"})");
expect(function () {
expect(toArguments('foo', 'bar'), 'to equal', ['foo', 'bar', 'baz']);
}, '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\t \u0558\x09', 'to equal', 'bar Ѿ\u0559\x08');
}, 'to throw exception',
"expected 'foo\\t \u0558\\t' to equal 'bar Ѿՙ\\b'\n" +
"\n" +
"-foo\\t \\u0558\\t\n" +
"+bar Ѿՙ\\x08");
});
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 () {
it('fails if no exception is thrown', function () {
expect(function () {
expect(function () {
// Don't throw
}, 'to throw exception');
}, 'to throw', function (err) {
var message = err.getErrorMessage({ format: 'text' }).toString();
// PhantomJS adds a semicolon after the comment
message = message.replace(';', '');
expect(message, 'to equal',
'expected\n' +
'function () {\n' +
' // Don\'t throw\n' +
'}\n' +
'to throw exception');
});
});
it('fails if exception is thrown', function () {
expect(function () {
expect(function testFunction() {
throw new Error('The Error');
}, 'not to throw');
}, 'to throw',
"expected function testFunction() { throw new Error('The Error'); } not to throw\n" +
" threw: Error('The Error')");
});
it('fails with the correct message when an Unexpected error is thrown', function () {
expect(function () {
expect(function testFunction() {
expect.fail(function (output) {
output.text('foo').block(function () {
this.text('bar').nl().text('baz');
}).text('quux');
});
}, 'not to throw');
}, 'to throw',
'expected\n' +
'function testFunction() {\n' +
" expect.fail(function (output) {\n" +
" output.text('foo').block(function () {\n" +
" this.text('bar').nl().text('baz');\n" +
" }).text('quux');\n" +
" });\n" +
'}\n' +
'not to throw\n' +
" threw: foobarquux\n" +
" baz");
});
it('fails if the argument is not a function', function () {
expect(function () {
expect(1, 'to throw exception');
}, 'to throw exception',
"expected 1 to throw exception\n" +
" 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/);
});
it('does not support the not-flag in combination with an argument', function () {
expect(function () {
expect(function () {
throw new Error('matches the exception message');
}, 'not to throw', /matches the exception message/);
}, 'to throw', "The 'not to throw' assertion does not support arguments");
});
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 function testFunction() { throw new Error(\'bar\'); } to throw \'foo\'\n' +
" expected Error('bar') to satisfy 'foo'\n" +
'\n' +
' -bar\n' +
' +foo');
});
it('matches the error against the given error instance', function () {
expect(function () {
throw new Error('matches the exception message');
}, 'to throw exception', new Error('matches the exception message'));
});
it('provides a diff when the thrown error does not match the given error instance', function () {
expect(function () {
expect(function testFunction() {
throw new Error('Custom error');
}, 'to throw exception', new Error('My error'));
}, 'to throw',
'expected\n' +
'function testFunction() {\n' +
' throw new Error(\'Custom error\');\n' +
'}\n' +
"to throw exception Error('My error')\n" +
" expected Error('Custom error') to satisfy Error('My error')\n" +
"\n" +
" Error({\n" +
" message: 'Custom error' // should equal 'My error'\n" +
" // -Custom error\n" +
" // +My error\n" +
" })");
});
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');
});
it('does not break if null is thrown', function () {
expect(function () {
expect(function () {
throw null;
}, 'not to throw');
}, 'to throw',
'expected function () { throw null; } not to throw\n' +
' threw: null');
});
});
describe('to error assertion', function () {
describe('with a function that throws', function () {
describe('with the "not" flag', function () {
it('should indicate that the function threw', function () {
expect(function () {
expect(function () {
throw new Error('yikes');
}, 'not to error');
}, 'to throw',
"expected function () { throw new Error('yikes'); } not to error\n" +
" threw: Error('yikes')"
);
});
});
});
describe('with a function that returns a promise that is rejected', function () {
describe('with the "not" flag', function () {
it('should indicate that the function returned a rejected promise', function () {
return expect(
expect(function () {
return expect.promise(function (resolve, reject) {
setTimeout(function () {
reject(new Error('wat'));
}, 1);
});
}, 'not to error'),
'to be rejected with',
"expected\n" +
"function () {\n" +
" return expect.promise(function (resolve, reject) {\n" +
" setTimeout(function () {\n" +
" reject(new Error('wat'));\n" +
" }, 1);\n" +
" });\n" +
"}\n" +
"not to error\n" +
" returned promise rejected with: Error('wat')"
);
});
});
});
});
describe('object type', function () {
describe('#diff', function () {
it('should show identical multiline values correctly in diffs', function () {
var clonedExpect = expect.clone().addType({
name: 'numberNine',
identify: function (obj) {
return obj === 9;
},
inspect: function (value, depth, output) {
output.block(function () {
this.text('NUMBER').nl().text(' NINE ');
});
}
});
expect(function () {
clonedExpect({a: 123, b: 9}, 'to equal', {a: 456, b: 9});
}, 'to throw',
'expected\n' +
'{\n' +
' a: 123,\n' +
' b:\n' +
' NUMBER\n' +
' NINE \n' +
'}\n' +
'to equal\n' +
'{\n' +
' a: 456,\n' +
' b:\n' +
' NUMBER\n' +
' NINE \n' +
'}\n' +
'\n' +
'{\n' +
' a: 123, // should equal 456\n' +
' b:\n' +
' NUMBER\n' +
' NINE \n' +
'}'
);
});
});
});
describe('array type', function () {
it('should find an array instance identical to itself', function () {
var arr = [1, 2, 3];
expect(arr, 'to equal', arr);
});
});
describe('Error type', function () {
it('should inspect the constructor name correctly', function () {
expect(new TypeError('foo'), 'to inspect as', "TypeError('foo')");
});
it('should inspect correctly when the message is not set and there are no other properties', function () {
expect(new Error(), 'to inspect as', 'Error()');
});
it('should inspect correctly when the message is set and there are no other properties', function () {
expect(new Error('foo'), 'to inspect as', "Error('foo')");
});
it('should inspect correctly when the message is set and there are other properties', function () {
var err = new Error('foo');
err.bar = 123;
expect(err, 'to inspect as', "Error({ message: 'foo', bar: 123 })");
});
it('should inspect correctly when the message is not set and there are other properties', function () {
var err = new Error();
err.bar = 123;
expect(err, 'to inspect as', "Error({ message: '', bar: 123 })");
});
it('should diff instances with unwrapped values that do not produce a diff', function () {
var clonedExpect = expect.clone().addType({
name: 'numericalError',
base: 'Error',
identify: function (obj) {
return this.baseType.identify(obj) && /^\d+$/.test(obj.message);
},
inspect: function (err, depth, output) {
output.text('Error#' + err.message);
},
unwrap: function (obj) {
return parseInt(obj.message, 10);
}
});
expect(function () {
clonedExpect(new Error('1'), 'to equal', new Error('2'));
}, 'to throw',
'expected Error#1 to equal Error#2'
);
});
describe('with a custom Error class inheriting from Error', function () {
function inherits(ctor, superCtor) {
ctor.super_ = superCtor;
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
}
function MyError(message) {
Error.call(this);
this.message = message;
}
inherits(MyError, Error);
it('should consider identical instances to be identical', function () {
expect(new MyError('foo'), 'to equal', new MyError('foo'));
});
it('should consider an instance of the custom error different from an otherwise identical Error instance', function () {
expect(function () {
expect(new MyError('foo'), 'to equal', new Error('foo'));
}, 'to throw'