Skip to content

Commit 0825826

Browse files
authored
Merge pull request #964 from zetamorph/assert-nestedInclude-ownInclude
assert: add nestedInclude, deepNestedInclude, ownInclude and deepOwnInclude
2 parents f3adfd9 + b744130 commit 0825826

File tree

4 files changed

+329
-24
lines changed

4 files changed

+329
-24
lines changed

lib/chai/interface/assert.js

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,197 @@ module.exports = function (chai, util) {
10121012
new Assertion(exp, msg, assert.notDeepInclude, true).not.deep.include(inc);
10131013
};
10141014

1015+
/**
1016+
* ### .nestedInclude(haystack, needle, [message])
1017+
*
1018+
* Asserts that 'haystack' includes 'needle'.
1019+
* Can be used to assert the inclusion of a subset of properties in an
1020+
* object.
1021+
* Enables the use of dot- and bracket-notation for referencing nested
1022+
* properties.
1023+
* '[]' and '.' in property names can be escaped using double backslashes.
1024+
*
1025+
* assert.nestedInclude({'.a': {'b': 'x'}}, {'\\.a.[b]': 'x'});
1026+
* assert.nestedInclude({'a': {'[b]': 'x'}}, {'a.\\[b\\]': 'x'});
1027+
*
1028+
* @name nestedInclude
1029+
* @param {Object} haystack
1030+
* @param {Object} needle
1031+
* @param {String} message
1032+
* @namespace Assert
1033+
* @api public
1034+
*/
1035+
1036+
assert.nestedInclude = function (exp, inc, msg) {
1037+
new Assertion(exp, msg, assert.nestedInclude, true).nested.include(inc);
1038+
};
1039+
1040+
/**
1041+
* ### .notNestedInclude(haystack, needle, [message])
1042+
*
1043+
* Asserts that 'haystack' does not include 'needle'.
1044+
* Can be used to assert the absence of a subset of properties in an
1045+
* object.
1046+
* Enables the use of dot- and bracket-notation for referencing nested
1047+
* properties.
1048+
* '[]' and '.' in property names can be escaped using double backslashes.
1049+
*
1050+
* assert.notNestedInclude({'.a': {'b': 'x'}}, {'\\.a.b': 'y'});
1051+
* assert.notNestedInclude({'a': {'[b]': 'x'}}, {'a.\\[b\\]': 'y'});
1052+
*
1053+
* @name notNestedInclude
1054+
* @param {Object} haystack
1055+
* @param {Object} needle
1056+
* @param {String} message
1057+
* @namespace Assert
1058+
* @api public
1059+
*/
1060+
1061+
assert.notNestedInclude = function (exp, inc, msg) {
1062+
new Assertion(exp, msg, assert.notNestedInclude, true)
1063+
.not.nested.include(inc);
1064+
};
1065+
1066+
/**
1067+
* ### .deepNestedInclude(haystack, needle, [message])
1068+
*
1069+
* Asserts that 'haystack' includes 'needle'.
1070+
* Can be used to assert the inclusion of a subset of properties in an
1071+
* object while checking for deep equality.
1072+
* Enables the use of dot- and bracket-notation for referencing nested
1073+
* properties.
1074+
* '[]' and '.' in property names can be escaped using double backslashes.
1075+
*
1076+
* assert.deepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {x: 1}});
1077+
* assert.deepNestedInclude({'.a': {'[b]': {x: 1}}}, {'\\.a.\\[b\\]': {x: 1}});
1078+
*
1079+
* @name deepNestedInclude
1080+
* @param {Object} haystack
1081+
* @param {Object} needle
1082+
* @param {String} message
1083+
* @namespace Assert
1084+
* @api public
1085+
*/
1086+
1087+
assert.deepNestedInclude = function(exp, inc, msg) {
1088+
new Assertion(exp, msg, assert.deepNestedInclude, true)
1089+
.deep.nested.include(inc);
1090+
};
1091+
1092+
/**
1093+
* ### .notDeepNestedInclude(haystack, needle, [message])
1094+
*
1095+
* Asserts that 'haystack' does not include 'needle'.
1096+
* Can be used to assert the absence of a subset of properties in an
1097+
* object while checking for deep equality.
1098+
* Enables the use of dot- and bracket-notation for referencing nested
1099+
* properties.
1100+
* '[]' and '.' in property names can be escaped using double backslashes.
1101+
*
1102+
* assert.notDeepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {y: 1}})
1103+
* assert.notDeepNestedInclude({'.a': {'[b]': {x: 1}}}, {'\\.a.\\[b\\]': {y: 2}});
1104+
*
1105+
* @name notDeepNestedInclude
1106+
* @param {Object} haystack
1107+
* @param {Object} needle
1108+
* @param {String} message
1109+
* @namespace Assert
1110+
* @api public
1111+
*/
1112+
1113+
assert.notDeepNestedInclude = function(exp, inc, msg) {
1114+
new Assertion(exp, msg, assert.notDeepNestedInclude, true)
1115+
.not.deep.nested.include(inc);
1116+
};
1117+
1118+
/**
1119+
* ### .ownInclude(haystack, needle, [message])
1120+
*
1121+
* Asserts that 'haystack' includes 'needle'.
1122+
* Can be used to assert the inclusion of a subset of properties in an
1123+
* object while ignoring inherited properties.
1124+
*
1125+
* assert.ownInclude({ a: 1 }, { a: 1 });
1126+
*
1127+
* @name ownInclude
1128+
* @param {Object} haystack
1129+
* @param {Object} needle
1130+
* @param {String} message
1131+
* @namespace Assert
1132+
* @api public
1133+
*/
1134+
1135+
assert.ownInclude = function(exp, inc, msg) {
1136+
new Assertion(exp, msg, assert.ownInclude, true).own.include(inc);
1137+
};
1138+
1139+
/**
1140+
* ### .notOwnInclude(haystack, needle, [message])
1141+
*
1142+
* Asserts that 'haystack' includes 'needle'.
1143+
* Can be used to assert the absence of a subset of properties in an
1144+
* object while ignoring inherited properties.
1145+
*
1146+
* Object.prototype.b = 2;
1147+
*
1148+
* assert.notOwnInclude({ a: 1 }, { b: 2 });
1149+
*
1150+
* @name notOwnInclude
1151+
* @param {Object} haystack
1152+
* @param {Object} needle
1153+
* @param {String} message
1154+
* @namespace Assert
1155+
* @api public
1156+
*/
1157+
1158+
assert.notOwnInclude = function(exp, inc, msg) {
1159+
new Assertion(exp, msg, assert.notOwnInclude, true).not.own.include(inc);
1160+
};
1161+
1162+
/**
1163+
* ### .deepOwnInclude(haystack, needle, [message])
1164+
*
1165+
* Asserts that 'haystack' includes 'needle'.
1166+
* Can be used to assert the inclusion of a subset of properties in an
1167+
* object while ignoring inherited properties and checking for deep equality.
1168+
*
1169+
* assert.deepOwnInclude({a: {b: 2}}, {a: {b: 2}});
1170+
*
1171+
* @name deepOwnInclude
1172+
* @param {Object} haystack
1173+
* @param {Object} needle
1174+
* @param {String} message
1175+
* @namespace Assert
1176+
* @api public
1177+
*/
1178+
1179+
assert.deepOwnInclude = function(exp, inc, msg) {
1180+
new Assertion(exp, msg, assert.deepOwnInclude, true)
1181+
.deep.own.include(inc);
1182+
};
1183+
1184+
/**
1185+
* ### .notDeepOwnInclude(haystack, needle, [message])
1186+
*
1187+
* Asserts that 'haystack' includes 'needle'.
1188+
* Can be used to assert the absence of a subset of properties in an
1189+
* object while ignoring inherited properties and checking for deep equality.
1190+
*
1191+
* assert.notDeepOwnInclude({a: {b: 2}}, {a: {c: 3}});
1192+
*
1193+
* @name notDeepOwnInclude
1194+
* @param {Object} haystack
1195+
* @param {Object} needle
1196+
* @param {String} message
1197+
* @namespace Assert
1198+
* @api public
1199+
*/
1200+
1201+
assert.notDeepOwnInclude = function(exp, inc, msg) {
1202+
new Assertion(exp, msg, assert.notDeepOwnInclude, true)
1203+
.not.deep.own.include(inc);
1204+
};
1205+
10151206
/**
10161207
* ### .match(value, regexp, [message])
10171208
*

test/assert.js

Lines changed: 100 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -744,8 +744,106 @@ describe('assert', function () {
744744
}, "blah: expected { foo: { a: 1 }, bar: { b: 2 } } to have deep property 'bar' of { b: 9 }, but got { b: 2 }");
745745

746746
err(function () {
747-
assert.notDeepInclude({foo: obj1, bar: obj2}, {foo: {a: 1}, bar: {b: 2}});
748-
}, "expected { foo: { a: 1 }, bar: { b: 2 } } to not have deep property 'foo' of { a: 1 }");
747+
assert.notDeepInclude({foo: obj1, bar: obj2}, {foo: {a: 1}, bar: {b: 2}}, 'blah');
748+
}, "blah: expected { foo: { a: 1 }, bar: { b: 2 } } to not have deep property 'foo' of { a: 1 }");
749+
});
750+
751+
it('nestedInclude and notNestedInclude', function() {
752+
assert.nestedInclude({a: {b: ['x', 'y']}}, {'a.b[1]': 'y'});
753+
assert.notNestedInclude({a: {b: ['x', 'y']}}, {'a.b[1]': 'x'});
754+
assert.notNestedInclude({a: {b: ['x', 'y']}}, {'a.c': 'y'});
755+
756+
assert.notNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {x: 1}});
757+
758+
assert.nestedInclude({'.a': {'[b]': 'x'}}, {'\\.a.\\[b\\]': 'x'});
759+
assert.notNestedInclude({'.a': {'[b]': 'x'}}, {'\\.a.\\[b\\]': 'y'});
760+
761+
err(function () {
762+
assert.nestedInclude({a: {b: ['x', 'y']}}, {'a.b[1]': 'x'}, 'blah');
763+
}, "blah: expected { a: { b: [ 'x', 'y' ] } } to have nested property 'a.b[1]' of 'x', but got 'y'");
764+
765+
err(function () {
766+
assert.nestedInclude({a: {b: ['x', 'y']}}, {'a.b[1]': 'x'}, 'blah');
767+
}, "blah: expected { a: { b: [ 'x', 'y' ] } } to have nested property 'a.b[1]' of 'x', but got 'y'");
768+
769+
err(function () {
770+
assert.nestedInclude({a: {b: ['x', 'y']}}, {'a.c': 'y'});
771+
}, "expected { a: { b: [ 'x', 'y' ] } } to have nested property 'a.c'");
772+
773+
err(function () {
774+
assert.notNestedInclude({a: {b: ['x', 'y']}}, {'a.b[1]': 'y'}, 'blah');
775+
}, "blah: expected { a: { b: [ 'x', 'y' ] } } to not have nested property 'a.b[1]' of 'y'");
776+
});
777+
778+
it('deepNestedInclude and notDeepNestedInclude', function() {
779+
assert.deepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {x: 1}});
780+
assert.notDeepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {y: 2}});
781+
assert.notDeepNestedInclude({a: {b: [{x: 1}]}}, {'a.c': {x: 1}});
782+
783+
assert.deepNestedInclude({'.a': {'[b]': {x: 1}}}, {'\\.a.\\[b\\]': {x: 1}});
784+
assert.notDeepNestedInclude({'.a': {'[b]': {x: 1}}}, {'\\.a.\\[b\\]': {y: 2}});
785+
786+
err(function () {
787+
assert.deepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {y: 2}}, 'blah');
788+
}, "blah: expected { a: { b: [ [Object] ] } } to have deep nested property 'a.b[0]' of { y: 2 }, but got { x: 1 }");
789+
790+
err(function () {
791+
assert.deepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {y: 2}}, 'blah');
792+
}, "blah: expected { a: { b: [ [Object] ] } } to have deep nested property 'a.b[0]' of { y: 2 }, but got { x: 1 }");
793+
794+
err(function () {
795+
assert.deepNestedInclude({a: {b: [{x: 1}]}}, {'a.c': {x: 1}});
796+
}, "expected { a: { b: [ [Object] ] } } to have deep nested property 'a.c'");
797+
798+
err(function () {
799+
assert.notDeepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {x: 1}}, 'blah');
800+
}, "blah: expected { a: { b: [ [Object] ] } } to not have deep nested property 'a.b[0]' of { x: 1 }");
801+
});
802+
803+
it('ownInclude and notOwnInclude', function() {
804+
assert.ownInclude({a: 1}, {a: 1});
805+
assert.notOwnInclude({a: 1}, {a: 3});
806+
assert.notOwnInclude({a: 1}, {'toString': Object.prototype.toString});
807+
808+
assert.notOwnInclude({a: {b: 2}}, {a: {b: 2}});
809+
810+
err(function () {
811+
assert.ownInclude({a: 1}, {a: 3}, 'blah');
812+
}, "blah: expected { a: 1 } to have own property 'a' of 3, but got 1");
813+
814+
err(function () {
815+
assert.ownInclude({a: 1}, {a: 3}, 'blah');
816+
}, "blah: expected { a: 1 } to have own property 'a' of 3, but got 1");
817+
818+
err(function () {
819+
assert.ownInclude({a: 1}, {'toString': Object.prototype.toString});
820+
}, "expected { a: 1 } to have own property 'toString'");
821+
822+
err(function () {
823+
assert.notOwnInclude({a: 1}, {a: 1}, 'blah');
824+
}, "blah: expected { a: 1 } to not have own property 'a' of 1");
825+
});
826+
827+
it('deepOwnInclude and notDeepOwnInclude', function() {
828+
assert.deepOwnInclude({a: {b: 2}}, {a: {b: 2}});
829+
assert.notDeepOwnInclude({a: {b: 2}}, {a: {c: 3}});
830+
assert.notDeepOwnInclude({a: {b: 2}}, {'toString': Object.prototype.toString});
831+
832+
err(function () {
833+
assert.deepOwnInclude({a: {b: 2}}, {a: {c: 3}}, 'blah');
834+
}, "blah: expected { a: { b: 2 } } to have deep own property 'a' of { c: 3 }, but got { b: 2 }");
835+
836+
err(function () {
837+
assert.deepOwnInclude({a: {b: 2}}, {a: {c: 3}}, 'blah');
838+
}, "blah: expected { a: { b: 2 } } to have deep own property 'a' of { c: 3 }, but got { b: 2 }");
839+
840+
err(function () {
841+
assert.deepOwnInclude({a: {b: 2}}, {'toString': Object.prototype.toString});
842+
}, "expected { a: { b: 2 } } to have deep own property 'toString'");
843+
844+
err(function () {
845+
assert.notDeepOwnInclude({a: {b: 2}}, {a: {b: 2}}, 'blah');
846+
}, "blah: expected { a: { b: 2 } } to not have deep own property 'a' of { b: 2 }");
749847
});
750848

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

test/expect.js

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1797,16 +1797,16 @@ describe('expect', function () {
17971797
}, "blah: expected [ { a: 1 }, { b: 2 } ] to deep include { a: 9 }");
17981798

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

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

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

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

18341834
err(function () {
1835-
expect({a: {b: ['x', 'y']}}).to.not.nested.include({'a.b[1]': 'y'});
1836-
}, "expected { a: { b: [ 'x', 'y' ] } } to not have nested property 'a.b[1]' of 'y'");
1835+
expect({a: {b: ['x', 'y']}}).to.not.nested.include({'a.b[1]': 'y'}, 'blah');
1836+
}, "blah: expected { a: { b: [ 'x', 'y' ] } } to not have nested property 'a.b[1]' of 'y'");
1837+
1838+
err(function () {
1839+
expect({a: {b: ['x', 'y']}}, 'blah').to.not.nested.include({'a.b[1]': 'y'});
1840+
}, "blah: expected { a: { b: [ 'x', 'y' ] } } to not have nested property 'a.b[1]' of 'y'");
18371841
});
18381842

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

18611865
err(function () {
1862-
expect({a: {b: [{x: 1}]}}).to.not.deep.nested.include({'a.b[0]': {x: 1}});
1863-
}, "expected { a: { b: [ [Object] ] } } to not have deep nested property 'a.b[0]' of { x: 1 }");
1866+
expect({a: {b: [{x: 1}]}}).to.not.deep.nested.include({'a.b[0]': {x: 1}}, 'blah');
1867+
}, "blah: expected { a: { b: [ [Object] ] } } to not have deep nested property 'a.b[0]' of { x: 1 }");
1868+
1869+
err(function () {
1870+
expect({a: {b: [{x: 1}]}}, 'blah').to.not.deep.nested.include({'a.b[0]': {x: 1}});
1871+
}, "blah: expected { a: { b: [ [Object] ] } } to not have deep nested property 'a.b[0]' of { x: 1 }");
18641872
});
18651873

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

18851893
err(function () {
1886-
expect({a: 1}).to.not.own.include({a: 1});
1887-
}, "expected { a: 1 } to not have own property 'a' of 1");
1894+
expect({a: 1}).to.not.own.include({a: 1}, 'blah');
1895+
}, "blah: expected { a: 1 } to not have own property 'a' of 1");
1896+
1897+
err(function () {
1898+
expect({a: 1}, 'blah').to.not.own.include({a: 1});
1899+
}, "blah: expected { a: 1 } to not have own property 'a' of 1");
18881900
});
18891901

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

19081920
err(function () {
1909-
expect({a: {b: 2}}).to.not.deep.own.include({a: {b: 2}});
1910-
}, "expected { a: { b: 2 } } to not have deep own property 'a' of { b: 2 }");
1921+
expect({a: {b: 2}}).to.not.deep.own.include({a: {b: 2}}, 'blah');
1922+
}, "blah: expected { a: { b: 2 } } to not have deep own property 'a' of { b: 2 }");
1923+
1924+
err(function () {
1925+
expect({a: {b: 2}}, 'blah').to.not.deep.own.include({a: {b: 2}});
1926+
}, "blah: expected { a: { b: 2 } } to not have deep own property 'a' of { b: 2 }");
19111927
});
19121928

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

0 commit comments

Comments
 (0)