UNPKG

unexpected

Version:

Minimalistic BDD assertion toolkit inspired by [expect.js](https://github.com/LearnBoost/expect.js)

1,137 lines (990 loc) 90.7 kB
/*global weknowhow, describe, it, beforeEach, setTimeout, Uint8Array, Uint16Array*/ 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; describe('unexpected', function () { describe('argument validation', function () { it('fails when given no parameters', function () { expect(function () { expect(); }, 'to throw', 'The expect functions requires at least two parameters.'); }); it('fails when given only one parameter', function () { expect(function () { expect({}); }, 'to throw', 'The expect functions requires at least two parameters.'); }); it('fails when the second parameter is not a string', function () { expect(function () { expect({}, {}); }, 'to throw', 'The expect functions requires 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' }]"); }); }); 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' }]"); }); 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')[1], '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'); }); 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'"); expect(function () { expect(true, 'not to be', true); }, 'to throw exception', "expected true not to be true"); }); }); 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([[], [], []], '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({}, 'to be an empty object'); expect({foo: 123}, 'to be a non-empty object'); expect([123], 'to be a non-empty array'); expect([], 'to be an', 'object'); expect([], 'to be an object'); expect([], 'to be an empty 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 a', Array); }, 'to throw exception', /expected 5 to be a \[Function(: 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 with actual and expected when comparing string and not negated", function () { expect(function () { expect('foo', 'to be', 'bar'); }, 'to throw exception', function (e) { expect(e.actual, 'to be', 'foo'); expect(e.expected, 'to be', '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('handles argument arrays as arrays', function () { (function () { expect(arguments, 'to equal', ['foo', 'bar', 'baz']); }('foo', 'bar', 'baz')); }); 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('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' } }"); 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' }]"); expect(function () { (function () { expect(arguments, 'to equal', ['foo', 'bar', 'baz']); }('foo', 'bar')); }, 'to throw exception', "expected [ 'foo', 'bar' ] to equal [ 'foo', 'bar', 'baz' ]"); }); it("throws an error with 'expected' and 'actual' properties when not negated", function () { var expected = 123, actual = 456; expect(function () { expect(actual, 'to equal', expected); }, 'to throw exception', function (e) { expect(e.expected, 'to equal', expected); expect(e.actual, 'to equal', actual); }); }); it("throws an error without 'expected' and 'actual' properties when negated", function () { expect(function () { expect(123, 'not to equal', 123); }, 'to throw exception', function (e) { expect(e.expected, 'not to be ok'); expect(e.actual, 'not to be ok'); }); }); it("throws an error with showDiff:true when comparing arrays and not negated", function () { expect(function () { expect([1], 'to equal', [2]); }, 'to throw exception', function (e) { expect(e.showDiff, 'to be ok'); }); }); it("throws an error with showDiff:true when comparing objects and not negated", function () { expect(function () { expect({foo: 1}, 'to equal', {foo: 2}); }, 'to throw exception', function (e) { expect(e.showDiff, 'to be ok'); }); }); it("throws an error with actual and expected comparing strings and not negated", function () { expect(function () { expect('foo', 'to equal', 'bar'); }, 'to throw exception', function (e) { expect(e.actual, 'to be', 'foo'); expect(e.expected, 'to be', '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', function (err) { expect(err, 'to have properties', { showDiff: true, actual: { $Buffer: [ '00 01 02 48 65 72 65 20 69 73 20 74 68 65 20 74 |...Here is the t|', '68 69 6E 67 20 49 20 77 61 73 20 74 61 6C 6B 69 |hing I was talki|', '6E 67 20 61 62 6F 75 74 |ng about|' ] }, expected: { $Buffer: [ '00 01 02 48 65 72 65 20 69 73 20 74 68 65 20 74 |...Here is the t|', '68 69 6E 67 20 49 20 77 61 73 20 71 75 75 78 69 |hing I was quuxi|', '6E 67 20 61 62 6F 75 74 |ng about|' ] } }); expect(err.output.toString(), 'to equal', 'expected [Buffer 00 01 02 48 65 72 65 20 69 73 20 74 68 65 20 74 68 69 6E 67 |...Here is the thing| (+20)] to equal [Buffer 00 01 02 48 65 72 65 20 69 73 20 74 68 65 20 74 68 69 6E 67 |...Here is the thing| (+20)]'); }); }); 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', function (err) { expect(err, 'to have properties', { showDiff: true, actual: { $Uint8Array: [ '00 01 02 48 65 72 65 20 69 73 20 74 68 65 20 74 |...Here is the t|', '68 69 6E 67 20 49 20 77 61 73 20 74 61 6C 6B 69 |hing I was talki|', '6E 67 20 61 62 6F 75 74 |ng about|' ] }, expected: { $Uint8Array: [ '00 01 02 48 65 72 65 20 69 73 20 74 68 65 20 74 |...Here is the t|', '68 69 6E 67 20 49 20 77 61 73 20 71 75 75 78 69 |hing I was quuxi|', '6E 67 20 61 62 6F 75 74 |ng about|' ] } }); expect(err.output.toString(), 'to equal', 'expected [Uint8Array 00 01 02 48 65 72 65 20 69 73 20 74 68 65 20 74 68 69 6E 67 |...Here is the thing| (+20)] to equal [Uint8Array 00 01 02 48 65 72 65 20 69 73 20 74 68 65 20 74 68 69 6E 67 |...Here is the thing| (+20)]'); }); }); 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', function (err) { expect(err, 'to have properties', { showDiff: true, actual: { $Uint16Array: [ '0001 0248 6572 6520 6973 2074 6865 2074', '6869 6E67 2049 2077 6173 2074 616C 6B69', '6E67 2061 626F 7574' ] }, expected: { $Uint16Array: [ '0001 0248 6572 6520 6973 2074 6865 2074', '6869 6E67 2049 2077 6173 2071 7575 7869', '6E67 2061 626F 7574' ] } }); expect(err.output.toString(), 'to equal', 'expected [Uint16Array 0001 0248 6572 6520 6973 2074 6865 2074 6869 6E67 2049 2077 6173 2074 616C 6B69 6E67 2061 626F 7574] to equal [Uint16Array 0001 0248 6572 6520 6973 2074 6865 2074 6869 6E67 2049 2077 6173 2071 7575 7869 6E67 2061 626F 7574]'); }); }); }); describe('exception assertion', function () { it('fails if no exception is thrown', function () { expect(function () { expect(function () { // Don't throw }, 'to throw exception'); }, 'to throw', 'expected [Function] 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] not to throw\n' + " threw: The Error"); }); it('fails if the argument is not a function', function () { expect(function () { expect(1, 'to throw exception'); }, 'to throw exception', "Assertion 'to throw exception' only supports functions"); }); 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 actual and expected properties 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', function (err) { expect(err.output.toString(), 'to equal', "expected [Function: testFunction] to throw 'foo'\n" + " expected 'bar' to equal 'foo'"); expect(err, 'to have properties', { actual: 'bar', expected: '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'); }); }); 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/); expect(null, 'not to match', /foo/); }); it('throws when the assertion fails', function () { expect(function () { expect('test', 'to match', /foo/); }, 'to throw exception', "expected 'test' to match /foo/"); }); }); describe('contain assertion', function () { it('asserts indexOf for an array or string', function () { expect([1, 2], 'to contain', 1); expect([1, 2], 'to contain', 2, 1); expect('hello world', 'to contain', 'world'); expect(null, 'not to contain', 'world'); }); it('throws when the assertion fails', function () { 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(1, 'to contain', 1); }, 'to throw exception', "Assertion 'to contain' only supports strings and arrays"); }); }); 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({ length: 4 }, 'to have length', 4); }); 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"); expect(function () { expect(null, 'to have length', 4); }, 'to throw exception', "Assertion 'to have length' only supports array like objects"); expect(function () { expect({ length: 'foo' }, 'to have length', 4); }, 'to throw exception', "Assertion 'to have length' only supports array like objects"); }); }); 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(1, 'not to have property', 'a'); expect(null, 'not to have property', 'a'); expect(undefined, 'not to have property', 'a'); expect(true, 'not to have property', 'a'); expect(false, 'not to have property', 'a'); }); 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', "expected null to have property 'b'"); expect(function () { expect({a: 'b'}, 'to have property', 'a', 'c'); }, 'to throw exception', "expected { a: 'b' } to have property 'a', 'c'"); expect(function () { // property expectations ignores value if property expect(null, 'not to have property', 'a', 'b'); }, 'to throw exception', "expected null not to have property 'a', 'b'"); expect(function () { // property expectations on value expects the property to be present expect(null, 'not to have own property', 'a', 'b'); }, 'to throw exception', "expected null not to have own property 'a', 'b'"); }); }); 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' }"); expect(function () { expect({a: 'foo', b: 'bar'}, 'to have properties', {b: 'baz'}); }, 'to throw', "expected { a: 'foo', b: 'bar' } to have properties { b: 'baz' }"); }); 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' }"); }); it('asserts absence and values of an object of properties', function () { expect({a: 'foo', b: 'bar'}, 'not to have properties', {c: 'baz', d: 'qux'}); expect(function () { expect({a: 'foo', b: 'bar'}, 'not to have properties', {a: 'foo', c: 'baz'}); }, 'to throw', "expected { a: 'foo', b: 'bar' } not to have properties { a: 'foo', c: 'baz' }"); }); 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: 'foo', b: 'bar'}); expect(function () { expect({a: 'foo', b: 'bar'}, 'not to have own properties', {a: 'foo', b: 'bar'}); // should fail }, 'to throw', "expected { a: 'foo', b: 'bar' } not to have own properties { a: 'foo', b: 'bar' }"); }); it('should add showDiff:true and diffable actual and expected properties to the error instance', function () { expect(function () { expect({a: 123, b: 456, c: 789}, 'to have properties', {a: 123, b: 987}); }, 'to throw', function (e) { expect(e.showDiff, 'to be true'); expect(e.actual, 'to equal', {a: 123, b: 456, c: 789}); expect(e.expected, 'to equal', {a: 123, b: 987, c: 789}); }); }); it('includes prototype properties in the actual property (#48)', function () { function Foo() {} Foo.prototype.doSomething = function () {}; expect(function () { expect(new Foo(), 'to have properties', {a: 123}); }, 'to throw', function (e) { expect(e.expected, 'to have property', 'doSomething'); expect(e.actual, 'to have property', 'doSomething'); delete e.expected.a; expect(e.actual, 'to equal', e.expected); }); }); it('throws when the assertion fails', function () { expect(function () { expect({a: 'foo', b: 'bar'}, 'to have properties', ['c', 'd']); }, 'to throw', "expected { a: 'foo', b: 'bar' } to have properties [ 'c', 'd' ]"); expect(function () { expect({a: 'foo'}, 'to have properties', {a: undefined}); }, 'to throw', "expected { a: 'foo' } to have properties { a: undefined }"); }); it('throws when given invalid input', function () { expect(function () { expect({a: 'foo', b: 'bar'}, 'to have properties', 'a', 'b'); }, 'to throw', "Assertion 'to have properties' only supports input in the form of an Array or an Object."); }); }); describe('empty assertion', function () { it('asserts presence of an own property (and value optionally)', function () { expect([], 'to be empty'); expect('', 'to be empty'); expect({}, 'to be empty'); expect({ length: 0, duck: 'typing' }, 'to be empty'); expect({ my: 'object' }, 'not to be empty'); expect({ my: 'object' }, 'to be non-empty'); expect([1, 2, 3], 'not to be empty'); expect([1, 2, 3], 'to be non-empty'); }); it('throws when the assertion fails', function () { expect(function () { expect([1, 2, 3], 'to be empty'); }, 'to throw exception', "expected [ 1, 2, 3 ] to be empty"); expect(function () { expect('', 'to be non-empty'); }, 'to throw exception', "expected '' to be non-empty"); expect(function () { expect(null, 'to be empty'); }, 'to throw exception', "Assertion 'to be empty' only supports strings, arrays and objects"); }); }); describe('key assertion', function () { it('asserts the presence of a key', function () { expect({ a: 'b' }, 'to have key', 'a'); expect({ a: 'b' }, 'not to have key', 'b'); expect({ a: 'b', c: 'd' }, 'not to have key', 'b'); expect({ a: 'b', c: 'd' }, 'to not only have key', 'a'); expect({ a: 'b', c: 'd' }, 'to only have keys', 'a', 'c'); expect({ a: 'b', c: 'd' }, 'to only have keys', ['a', 'c']); expect({ a: 'b', c: 'd', e: 'f' }, 'to not only have keys', ['a', 'c']); expect(null, 'not to have key', 'a'); expect(undefined, 'not to have key', 'a'); expect(true, 'not to have key', 'a'); expect(false, 'not to have key', 'a'); }); it('throws when the assertion fails', function () { expect(function () { expect({ a: 'b', b: 'c' }, 'to have key', 'e'); }, 'to throw exception', "expected { a: 'b', b: 'c' } to have key 'e'"); expect(function () { expect({ a: 'b', b: 'c' }, 'to only have key', 'b'); }, 'to throw exception', "expected { a: 'b', b: 'c' } to only have key 'b'"); expect(function () { expect({ a: 'b', b: 'c' }, 'not to have key', 'b'); }, 'to throw exception', "expected { a: 'b', b: 'c' } not to have key 'b'"); expect(function () { expect({ a: 'b', c: 'd' }, 'to not only have keys', ['a', 'c']); }, 'to throw exception', "expected { a: 'b', c: 'd' } to not only have keys [ 'a', 'c' ]"); expect(function () { expect({ a: 'b', c: 'd' }, 'to only have keys', 'a', 'd'); }, 'to throw exception', "expected { a: 'b', c: 'd' } to only have keys 'a', 'd'"); expect(function () { expect({ a: 'b', c: 'd' }, 'to not only have keys', 'a', 'c'); }, 'to throw exception', "expected { a: 'b', c: 'd' } to not only have keys 'a', 'c'"); }); }); describe('finite assertion', function () { it('asserts a finite number', function () { expect(123, 'to be finite'); expect(0, 'to be finite'); expect(Infinity, 'not to be finite'); expect(-Infinity, 'not to be finite'); expect(NaN, 'not to be finite'); expect(null, 'not to be finite'); expect({}, 'not to be finite'); }); it('throws when the assertion fails', function () { expect(function () { expect(Infinity, 'to be finite'); }, 'to throw exception', 'expected Infinity to be finite'); }); }); describe('finite assertion', function () { it('asserts a infinite number', function () { expect(123, 'not to be infinite'); expect(0, 'not to be infinite'); expect(Infinity, 'to be infinite'); expect(-Infinity, 'to be infinite'); expect(NaN, 'not to be infinite'); expect(null, 'not to be infinite'); expect({}, 'not to be infinite'); }); it('throws when the assertion fails', function () { expect(function () { expect(123, 'to be infinite'); }, 'to throw exception', 'expected 123 to be infinite'); }); }); describe('within assertion', function () { it('asserts a number within a range', function () { expect(0, 'to be within', 0, 4); expect(1, 'to be within', 0, 4); expect(4, 'to be within', 0, 4); expect(-1, 'not to be within', 0, 4); expect(5, 'not to be within', 0, 4); }); it('throws when the assertion fails', function () { expect(function () { expect(4, 'not to be within', 0, 4); }, 'to throw exception', "expected 4 not to be within '0..4'"); expect(function () { expect(null, 'not to be within', 0, 4); }, 'to throw exception', "expected null not to be within '0..4'"); }); }); describe('less than assertion', function () { it('asserts <', function () { expect(0, 'to be less than', 4); expect(0, 'to be below', 1); expect(3, 'to be <', 4); expect(3, '<', 4); }); it('throws when the assertion fails', function () { expect(function () { expect(0, 'to be less than', 0); }, 'to throw exception', "expected 0 to be less than 0"); }); }); describe('less than or equal assertion', function () { it('asserts <=', function () { expect(0, 'to be less than or equal to', 4); expect(4, 'to be <=', 4); expect(3, '<=', 4); }); it('throws when the assertion fails', function () { expect(function () { expect(0, 'to be less than or equal to', -1); }, 'to throw exception', "expected 0 to be less than or equal to -1"); }); }); describe('greater than assertion', function () { it('assert >', function () { expect(3, 'to be greater than', 2); expect(1, 'to be above', 0); expect(4, 'to be >', 3); expect(4, '>', 3); }); it('throws when the assertion fails', function () { expect(function () { expect(0, 'to be greater than', 0); }, 'to throw exception', "expected 0 to be greater than 0"); }); }); describe('greater than or equal assertion', function () { it('assert >=', function () { expect(3, 'to be greater than or equal to', 2); expect(3, 'to be >=', 3); expect(3, '>=', 3); }); it('throws when the assertion fails', function () { expect(function () { expect(-1, 'to be greater than or equal to', 0); }, 'to throw exception', "expected -1 to be greater than or equal to 0"); }); }); describe('positive assertion', function () { it('assert that a number is positive', function () { expect(3, 'to be positive'); }); it('throws when the assertion fails', function () { expect(function () { expect(0, 'to be positive'); }, 'to throw exception', "expected 0 to be positive"); }); }); describe('negative assertion', function () { it('assert that a number is negative', function () { expect(-1, 'to be negative'); }); it('throws when the assertion fails', function () { expect(function () { expect(0, 'to be negative'); }, 'to throw exception', "expected 0 to be negative"); }); }); describe('to be NaN assertion', function () { it('assert that the value is NaN or not', function () { expect(NaN, 'to be NaN'); expect({}, 'to be NaN'); expect(2, 'not to be NaN'); expect(null, 'not to be NaN'); expect(undefined, 'to be NaN'); expect("String", 'to be NaN'); }); it('fails when the assertion fails', function () { expect(function () { expect(0, 'to be NaN'); }, 'to throw', "expected 0 to be NaN"); expect(function () { expect(NaN, 'not to be NaN'); }, 'to throw', "expected NaN not to be NaN"); }); }); describe('ẗo be close to assertion', function () { it('asserts that two numbers differ by at most 1e-9', function () { expect(1.5, 'to be close to', 1.49999999999); expect(1.5, 'to be close to', 1.5000000001); expect(1.5, 'not to be close to', 2); }); it('fails when the assertion fails', function () { expect(function () { expect(1.5, 'to be close to', 1.4999); }, 'to throw exception', 'expected 1.5 to be close to 1.4999 (epsilon: 1e-9)'); expect(function () { expect(1.5, 'to be close to', 1.5001); }, 'to throw exception', 'expected 1.5 to be close to 1.5001 (epsilon: 1e-9)'); }); it('accepts a custom epsilon', function () { expect(1.5, 'to be close to', 1.500001, 1e-3); expect(1.5, 'not to be close to', 1.51, 1e-3); expect(function () { expect(1.5, 'to be close to', 1.51, 1e-3); }, 'to throw exception', 'expected 1.5 to be close to 1.51 (epsilon: 1e-3)'); }); }); describe('fail assertion', function () { it('throws an error', function () { expect(function () { expect.fail(); }, 'to throw exception', "explicit failure"); }); it('sets the error message', function () { var wasCaught = false; try { expect.fail('fail with error message'); } catch (e) { wasCaught = true; expect(e.message, 'to equal', 'fail with error message'); } expect(wasCaught, 'to be true'); }); it('throws an error with a given message', function () { expect(function () { expect.fail('fail with error message'); }, 'to throw exception', "fail with error message"); }); it('supports placeholders', function () { expect(function () { expect.fail('{0} was expected to be {1}', 0, 'zero'); }, 'to throw exception', "0 was expected to be zero"); expect(function () { var output = expect.output.clone().text('zero'); expect.fail('{0} was expected to be {1}', 0, output); }, 'to throw exception', "0 was expected to be zero"); expect(function () { expect.fail('{0} was expected to be {1}', 0); }, 'to throw exception', "0 was expected to be {1}"); }); }); describe('to be an array whose items satisfy assertion', function () { it('requires a function or a string as the third argument', function () { expect(function () { expect([1, 2, 3], 'to be an array whose items satisfy'); }, 'to throw', 'Assertion "to be an array whose items satisfy" expects a function as argument'); expect(function () { expect([1, 2, 3], 'to be an array whose items satisfy', 42); }, 'to throw', 'Assertion "to be an array whose items satisfy" expects a function as argument'); }); it('only accepts arrays as the target object', function () { expect(function () { expect(42, 'to be an array whose items satisfy', function (item) {}); }, 'to throw', /expected 42 to be an array/); }); it('supports the non-empty clause', function () { expect([1], 'to be a non-empty array whose items satisfy', function (item) { expect(item, 'to be a number'); }); }); it('asserts that the given callback does not throw for any items in the array', function () { expect([0, 1, 2, 3], 'to be an array whose items satisfy', function (item, index) { expect(item, 'to be a number'); expect(index, 'to be a number'); }); expect(['0', '1', '2', '3'], 'to be an array whose items satisfy', function (item, index) { expect(item, 'not to be a number'); expect(index, 'to be a number'); }); expect([0, 1, 2, 3], 'to be an array whose items satisfy', 'to be a number'); expect(['0', '1', '2', '3'], 'to be an array whose items satisfy', 'not to be a number'); expect([[1], [2]], 'to be an array whose items satisfy', 'to be an array whose items satisfy', 'to be a number'); }); it('provides the item index to the callback function', function () { var arr = ['0', '1', '2', '3']; expect(arr, 'to be an array whose items satisfy', function (item, index) { expect(index, 'to be a number'); expect(index, 'to be', parseInt(item, 10)); }); }); it('fails when the assertion fails', function () { expect(function () { expect(['0', 1, '2', '3'], 'to be an array whose items satisfy', function (item) {