UNPKG

unexpected

Version:
1,147 lines (1,020 loc) 183 kB
/*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