Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

assert: add nestedInclude, deepNestedInclude, ownInclude and deepOwnInclude #964

Merged
merged 11 commits into from
May 9, 2017
Merged
191 changes: 191 additions & 0 deletions lib/chai/interface/assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,197 @@ module.exports = function (chai, util) {
new Assertion(exp, msg, assert.notDeepInclude, true).not.deep.include(inc);
};

/**
* ### .nestedInclude(haystack, needle, [message])
*
* Asserts that 'haystack' includes 'needle'.
* Can be used to assert the inclusion of a subset of properties in an
* object.
* Enables the use of dot- and bracket-notation for referencing nested
* properties.
* '[]' and '.' in property names can be escaped using double backslashes.
*
* assert.nestedInclude({'.a': {'b': 'x'}}, {'\\.a.[b]': 'x'});
* assert.nestedInclude({'a': {'[b]': 'x'}}, {'a.\\[b\\]': 'x'});
*
* @name nestedInclude
* @param {Object} haystack
* @param {Object} needle
* @param {String} message
* @namespace Assert
* @api public
*/

assert.nestedInclude = function (exp, inc, msg) {
new Assertion(exp, msg, assert.nestedInclude, true).nested.include(inc);
};

/**
* ### .notNestedInclude(haystack, needle, [message])
*
* Asserts that 'haystack' does not include 'needle'.
* Can be used to assert the absence of a subset of properties in an
* object.
* Enables the use of dot- and bracket-notation for referencing nested
* properties.
* '[]' and '.' in property names can be escaped using double backslashes.
*
* assert.notNestedInclude({'.a': {'b': 'x'}}, {'\\.a.b': 'y'});
* assert.notNestedInclude({'a': {'[b]': 'x'}}, {'a.\\[b\\]': 'y'});
*
* @name notNestedInclude
* @param {Object} haystack
* @param {Object} needle
* @param {String} message
* @namespace Assert
* @api public
*/

assert.notNestedInclude = function (exp, inc, msg) {
new Assertion(exp, msg, assert.notNestedInclude, true)
.not.nested.include(inc);
};

/**
* ### .deepNestedInclude(haystack, needle, [message])
*
* Asserts that 'haystack' includes 'needle'.
* Can be used to assert the inclusion of a subset of properties in an
* object while checking for deep equality.
* Enables the use of dot- and bracket-notation for referencing nested
* properties.
* '[]' and '.' in property names can be escaped using double backslashes.
*
* assert.deepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {x: 1}});
* assert.deepNestedInclude({'.a': {'[b]': {x: 1}}}, {'\\.a.\\[b\\]': {x: 1}});
*
* @name deepNestedInclude
* @param {Object} haystack
* @param {Object} needle
* @param {String} message
* @namespace Assert
* @api public
*/

assert.deepNestedInclude = function(exp, inc, msg) {
new Assertion(exp, msg, assert.deepNestedInclude, true)
.deep.nested.include(inc);
};

/**
* ### .notDeepNestedInclude(haystack, needle, [message])
*
* Asserts that 'haystack' does not include 'needle'.
* Can be used to assert the absence of a subset of properties in an
* object while checking for deep equality.
* Enables the use of dot- and bracket-notation for referencing nested
* properties.
* '[]' and '.' in property names can be escaped using double backslashes.
*
* assert.notDeepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {y: 1}})
* assert.notDeepNestedInclude({'.a': {'[b]': {x: 1}}}, {'\\.a.\\[b\\]': {y: 2}});
*
* @name notDeepNestedInclude
* @param {Object} haystack
* @param {Object} needle
* @param {String} message
* @namespace Assert
* @api public
*/

assert.notDeepNestedInclude = function(exp, inc, msg) {
new Assertion(exp, msg, assert.notDeepNestedInclude, true)
.not.deep.nested.include(inc);
};

/**
* ### .ownInclude(haystack, needle, [message])
*
* Asserts that 'haystack' includes 'needle'.
* Can be used to assert the inclusion of a subset of properties in an
* object while ignoring inherited properties.
*
* assert.ownInclude({ a: 1 }, { a: 1 });
*
* @name ownInclude
* @param {Object} haystack
* @param {Object} needle
* @param {String} message
* @namespace Assert
* @api public
*/

assert.ownInclude = function(exp, inc, msg) {
new Assertion(exp, msg, assert.ownInclude, true).own.include(inc);
};

/**
* ### .notOwnInclude(haystack, needle, [message])
*
* Asserts that 'haystack' includes 'needle'.
* Can be used to assert the absence of a subset of properties in an
* object while ignoring inherited properties.
*
* Object.prototype.b = 2;
*
* assert.notOwnInclude({ a: 1 }, { b: 2 });
*
* @name notOwnInclude
* @param {Object} haystack
* @param {Object} needle
* @param {String} message
* @namespace Assert
* @api public
*/

assert.notOwnInclude = function(exp, inc, msg) {
new Assertion(exp, msg, assert.notOwnInclude, true).not.own.include(inc);
};

/**
* ### .deepOwnInclude(haystack, needle, [message])
*
* Asserts that 'haystack' includes 'needle'.
* Can be used to assert the inclusion of a subset of properties in an
* object while ignoring inherited properties and checking for deep equality.
*
* assert.deepOwnInclude({a: {b: 2}}, {a: {b: 2}});
*
* @name deepOwnInclude
* @param {Object} haystack
* @param {Object} needle
* @param {String} message
* @namespace Assert
* @api public
*/

assert.deepOwnInclude = function(exp, inc, msg) {
new Assertion(exp, msg, assert.deepOwnInclude, true)
.deep.own.include(inc);
};

/**
* ### .notDeepOwnInclude(haystack, needle, [message])
*
* Asserts that 'haystack' includes 'needle'.
* Can be used to assert the absence of a subset of properties in an
* object while ignoring inherited properties and checking for deep equality.
*
* assert.notDeepOwnInclude({a: {b: 2}}, {a: {c: 3}});
*
* @name notDeepOwnInclude
* @param {Object} haystack
* @param {Object} needle
* @param {String} message
* @namespace Assert
* @api public
*/

assert.notDeepOwnInclude = function(exp, inc, msg) {
new Assertion(exp, msg, assert.notDeepOwnInclude, true)
.not.deep.own.include(inc);
};

/**
* ### .match(value, regexp, [message])
*
Expand Down
102 changes: 100 additions & 2 deletions test/assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -744,8 +744,106 @@ describe('assert', function () {
}, "blah: expected { foo: { a: 1 }, bar: { b: 2 } } to have deep property 'bar' of { b: 9 }, but got { b: 2 }");

err(function () {
assert.notDeepInclude({foo: obj1, bar: obj2}, {foo: {a: 1}, bar: {b: 2}});
}, "expected { foo: { a: 1 }, bar: { b: 2 } } to not have deep property 'foo' of { a: 1 }");
assert.notDeepInclude({foo: obj1, bar: obj2}, {foo: {a: 1}, bar: {b: 2}}, 'blah');
}, "blah: expected { foo: { a: 1 }, bar: { b: 2 } } to not have deep property 'foo' of { a: 1 }");
});

it('nestedInclude and notNestedInclude', function() {
assert.nestedInclude({a: {b: ['x', 'y']}}, {'a.b[1]': 'y'});
assert.notNestedInclude({a: {b: ['x', 'y']}}, {'a.b[1]': 'x'});
assert.notNestedInclude({a: {b: ['x', 'y']}}, {'a.c': 'y'});

assert.notNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {x: 1}});

assert.nestedInclude({'.a': {'[b]': 'x'}}, {'\\.a.\\[b\\]': 'x'});
assert.notNestedInclude({'.a': {'[b]': 'x'}}, {'\\.a.\\[b\\]': 'y'});

err(function () {
assert.nestedInclude({a: {b: ['x', 'y']}}, {'a.b[1]': 'x'}, 'blah');
}, "blah: expected { a: { b: [ 'x', 'y' ] } } to have nested property 'a.b[1]' of 'x', but got 'y'");

err(function () {
assert.nestedInclude({a: {b: ['x', 'y']}}, {'a.b[1]': 'x'}, 'blah');
}, "blah: expected { a: { b: [ 'x', 'y' ] } } to have nested property 'a.b[1]' of 'x', but got 'y'");

err(function () {
assert.nestedInclude({a: {b: ['x', 'y']}}, {'a.c': 'y'});
}, "expected { a: { b: [ 'x', 'y' ] } } to have nested property 'a.c'");

err(function () {
assert.notNestedInclude({a: {b: ['x', 'y']}}, {'a.b[1]': 'y'}, 'blah');
}, "blah: expected { a: { b: [ 'x', 'y' ] } } to not have nested property 'a.b[1]' of 'y'");
});

it('deepNestedInclude and notDeepNestedInclude', function() {
assert.deepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {x: 1}});
assert.notDeepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {y: 2}});
assert.notDeepNestedInclude({a: {b: [{x: 1}]}}, {'a.c': {x: 1}});

assert.deepNestedInclude({'.a': {'[b]': {x: 1}}}, {'\\.a.\\[b\\]': {x: 1}});
assert.notDeepNestedInclude({'.a': {'[b]': {x: 1}}}, {'\\.a.\\[b\\]': {y: 2}});

err(function () {
assert.deepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {y: 2}}, 'blah');
}, "blah: expected { a: { b: [ [Object] ] } } to have deep nested property 'a.b[0]' of { y: 2 }, but got { x: 1 }");

err(function () {
assert.deepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {y: 2}}, 'blah');
}, "blah: expected { a: { b: [ [Object] ] } } to have deep nested property 'a.b[0]' of { y: 2 }, but got { x: 1 }");

err(function () {
assert.deepNestedInclude({a: {b: [{x: 1}]}}, {'a.c': {x: 1}});
}, "expected { a: { b: [ [Object] ] } } to have deep nested property 'a.c'");

err(function () {
assert.notDeepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {x: 1}}, 'blah');
}, "blah: expected { a: { b: [ [Object] ] } } to not have deep nested property 'a.b[0]' of { x: 1 }");
});

it('ownInclude and notOwnInclude', function() {
assert.ownInclude({a: 1}, {a: 1});
assert.notOwnInclude({a: 1}, {a: 3});
assert.notOwnInclude({a: 1}, {'toString': Object.prototype.toString});

assert.notOwnInclude({a: {b: 2}}, {a: {b: 2}});

err(function () {
assert.ownInclude({a: 1}, {a: 3}, 'blah');
}, "blah: expected { a: 1 } to have own property 'a' of 3, but got 1");

err(function () {
assert.ownInclude({a: 1}, {a: 3}, 'blah');
}, "blah: expected { a: 1 } to have own property 'a' of 3, but got 1");

err(function () {
assert.ownInclude({a: 1}, {'toString': Object.prototype.toString});
}, "expected { a: 1 } to have own property 'toString'");

err(function () {
assert.notOwnInclude({a: 1}, {a: 1}, 'blah');
}, "blah: expected { a: 1 } to not have own property 'a' of 1");
});

it('deepOwnInclude and notDeepOwnInclude', function() {
assert.deepOwnInclude({a: {b: 2}}, {a: {b: 2}});
assert.notDeepOwnInclude({a: {b: 2}}, {a: {c: 3}});
assert.notDeepOwnInclude({a: {b: 2}}, {'toString': Object.prototype.toString});

err(function () {
assert.deepOwnInclude({a: {b: 2}}, {a: {c: 3}}, 'blah');
}, "blah: expected { a: { b: 2 } } to have deep own property 'a' of { c: 3 }, but got { b: 2 }");

err(function () {
assert.deepOwnInclude({a: {b: 2}}, {a: {c: 3}}, 'blah');
}, "blah: expected { a: { b: 2 } } to have deep own property 'a' of { c: 3 }, but got { b: 2 }");

err(function () {
assert.deepOwnInclude({a: {b: 2}}, {'toString': Object.prototype.toString});
}, "expected { a: { b: 2 } } to have deep own property 'toString'");

err(function () {
assert.notDeepOwnInclude({a: {b: 2}}, {a: {b: 2}}, 'blah');
}, "blah: expected { a: { b: 2 } } to not have deep own property 'a' of { b: 2 }");
});

it('keys(array|Object|arguments)', function(){
Expand Down
40 changes: 28 additions & 12 deletions test/expect.js
Original file line number Diff line number Diff line change
Expand Up @@ -1797,16 +1797,16 @@ describe('expect', function () {
}, "blah: expected [ { a: 1 }, { b: 2 } ] to deep include { a: 9 }");

err(function () {
expect([obj1, obj2]).to.not.deep.include({a: 1});
}, "expected [ { a: 1 }, { b: 2 } ] to not deep include { a: 1 }");
expect([obj1, obj2], 'blah').to.not.deep.include({a: 1});
}, "blah: expected [ { a: 1 }, { b: 2 } ] to not deep include { a: 1 }");

err(function () {
expect({foo: obj1, bar: obj2}).to.deep.include({foo: {a: 1}, bar: {b: 9}});
}, "expected { foo: { a: 1 }, bar: { b: 2 } } to have deep property 'bar' of { b: 9 }, but got { b: 2 }");

err(function () {
expect({foo: obj1, bar: obj2}).to.not.deep.include({foo: {a: 1}, bar: {b: 2}});
}, "expected { foo: { a: 1 }, bar: { b: 2 } } to not have deep property 'foo' of { a: 1 }");
expect({foo: obj1, bar: obj2}).to.not.deep.include({foo: {a: 1}, bar: {b: 2}}, 'blah');
}, "blah: expected { foo: { a: 1 }, bar: { b: 2 } } to not have deep property 'foo' of { a: 1 }");
});

it('nested.include()', function () {
Expand All @@ -1832,8 +1832,12 @@ describe('expect', function () {
}, "expected { a: { b: [ 'x', 'y' ] } } to have nested property 'a.c'");

err(function () {
expect({a: {b: ['x', 'y']}}).to.not.nested.include({'a.b[1]': 'y'});
}, "expected { a: { b: [ 'x', 'y' ] } } to not have nested property 'a.b[1]' of 'y'");
expect({a: {b: ['x', 'y']}}).to.not.nested.include({'a.b[1]': 'y'}, 'blah');
}, "blah: expected { a: { b: [ 'x', 'y' ] } } to not have nested property 'a.b[1]' of 'y'");

err(function () {
expect({a: {b: ['x', 'y']}}, 'blah').to.not.nested.include({'a.b[1]': 'y'});
}, "blah: expected { a: { b: [ 'x', 'y' ] } } to not have nested property 'a.b[1]' of 'y'");
});

it('deep.nested.include()', function () {
Expand All @@ -1859,8 +1863,12 @@ describe('expect', function () {
}, "expected { a: { b: [ [Object] ] } } to have deep nested property 'a.c'");

err(function () {
expect({a: {b: [{x: 1}]}}).to.not.deep.nested.include({'a.b[0]': {x: 1}});
}, "expected { a: { b: [ [Object] ] } } to not have deep nested property 'a.b[0]' of { x: 1 }");
expect({a: {b: [{x: 1}]}}).to.not.deep.nested.include({'a.b[0]': {x: 1}}, 'blah');
}, "blah: expected { a: { b: [ [Object] ] } } to not have deep nested property 'a.b[0]' of { x: 1 }");

err(function () {
expect({a: {b: [{x: 1}]}}, 'blah').to.not.deep.nested.include({'a.b[0]': {x: 1}});
}, "blah: expected { a: { b: [ [Object] ] } } to not have deep nested property 'a.b[0]' of { x: 1 }");
});

it('own.include()', function () {
Expand All @@ -1883,8 +1891,12 @@ describe('expect', function () {
}, "expected { a: 1 } to have own property 'toString'");

err(function () {
expect({a: 1}).to.not.own.include({a: 1});
}, "expected { a: 1 } to not have own property 'a' of 1");
expect({a: 1}).to.not.own.include({a: 1}, 'blah');
}, "blah: expected { a: 1 } to not have own property 'a' of 1");

err(function () {
expect({a: 1}, 'blah').to.not.own.include({a: 1});
}, "blah: expected { a: 1 } to not have own property 'a' of 1");
});

it('deep.own.include()', function () {
Expand All @@ -1906,8 +1918,12 @@ describe('expect', function () {
}, "expected { a: { b: 2 } } to have deep own property 'toString'");

err(function () {
expect({a: {b: 2}}).to.not.deep.own.include({a: {b: 2}});
}, "expected { a: { b: 2 } } to not have deep own property 'a' of { b: 2 }");
expect({a: {b: 2}}).to.not.deep.own.include({a: {b: 2}}, 'blah');
}, "blah: expected { a: { b: 2 } } to not have deep own property 'a' of { b: 2 }");

err(function () {
expect({a: {b: 2}}, 'blah').to.not.deep.own.include({a: {b: 2}});
}, "blah: expected { a: { b: 2 } } to not have deep own property 'a' of { b: 2 }");
});

it('keys(array|Object|arguments)', function(){
Expand Down