1414 *
1515 * Can be one of:
1616 *
17- * - `string`: The string is evaluated as an expression and the resulting value is used for substring match against
18- * the contents of the `array`. All strings or objects with string properties in `array` that contain this string
19- * will be returned. The predicate can be negated by prefixing the string with `!`.
17+ * - `string`: The string is used for matching against the contents of the `array`. All strings or
18+ * objects with string properties in `array` that match this string will be returned. This also
19+ * applies to nested object properties.
20+ * The predicate can be negated by prefixing the string with `!`.
2021 *
2122 * - `Object`: A pattern object can be used to filter specific properties on objects contained
2223 * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items
2324 * which have property `name` containing "M" and property `phone` containing "1". A special
2425 * property name `$` can be used (as in `{$:"text"}`) to accept a match against any
25- * property of the object. That's equivalent to the simple substring match with a `string`
26- * as described above. The predicate can be negated by prefixing the string with `!`.
27- * For Example `{name: "!M"}` predicate will return an array of items which have property `name`
26+ * property of the object or its nested object properties. That's equivalent to the simple
27+ * substring match with a `string` as described above. The predicate can be negated by prefixing
28+ * the string with `!`.
29+ * For example `{name: "!M"}` predicate will return an array of items which have property `name`
2830 * not containing "M".
2931 *
32+ * Note that a named property will match properties on the same level only, while the special
33+ * `$` property will match properties on the same level or deeper. E.g. an array item like
34+ * `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but
35+ * **will** be matched by `{$: 'John'}`.
36+ *
3037 * - `function(value, index)`: A predicate function can be used to write arbitrary filters. The
3138 * function is called for each element of `array`. The final result is an array of those
3239 * elements that the predicate returned true for.
3946 *
4047 * - `function(actual, expected)`:
4148 * The function will be given the object value and the predicate value to compare and
42- * should return true if the item should be included in filtered result .
49+ * should return true if both values should be considered equal .
4350 *
44- * - `true`: A shorthand for `function(actual, expected) { return angular.equals(expected, actual )}`.
45- * this is essentially strict comparison of expected and actual.
51+ * - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected )}`.
52+ * This is essentially strict comparison of expected and actual.
4653 *
4754 * - `false|undefined`: A short hand for a function which will look for a substring match in case
4855 * insensitive way.
@@ -173,7 +180,7 @@ function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
173180 return predicateFn ;
174181}
175182
176- function deepCompare ( actual , expected , comparator , matchAgainstAnyProp ) {
183+ function deepCompare ( actual , expected , comparator , matchAgainstAnyProp , dontMatchWholeObject ) {
177184 var actualType = typeof actual ;
178185 var expectedType = typeof expected ;
179186
@@ -192,21 +199,21 @@ function deepCompare(actual, expected, comparator, matchAgainstAnyProp) {
192199 var key ;
193200 if ( matchAgainstAnyProp ) {
194201 for ( key in actual ) {
195- if ( ( key . charAt ( 0 ) !== '$' ) && deepCompare ( actual [ key ] , expected , comparator ) ) {
202+ if ( ( key . charAt ( 0 ) !== '$' ) && deepCompare ( actual [ key ] , expected , comparator , true ) ) {
196203 return true ;
197204 }
198205 }
199- return false ;
206+ return dontMatchWholeObject ? false : deepCompare ( actual , expected , comparator , false ) ;
200207 } else if ( expectedType === 'object' ) {
201208 for ( key in expected ) {
202209 var expectedVal = expected [ key ] ;
203210 if ( isFunction ( expectedVal ) ) {
204211 continue ;
205212 }
206213
207- var keyIsDollar = key === '$' ;
208- var actualVal = keyIsDollar ? actual : actual [ key ] ;
209- if ( ! deepCompare ( actualVal , expectedVal , comparator , keyIsDollar ) ) {
214+ var matchAnyProperty = key === '$' ;
215+ var actualVal = matchAnyProperty ? actual : actual [ key ] ;
216+ if ( ! deepCompare ( actualVal , expectedVal , comparator , matchAnyProperty , matchAnyProperty ) ) {
210217 return false ;
211218 }
212219 }
0 commit comments