UNPKG

unexpected

Version:
1,154 lines (1,033 loc) 356 kB
/*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'