Skip to content

Commit 16a9419

Browse files
committed
fix(filterFilter) filter the same level or deeper of $ property.
1 parent 0538dc0 commit 16a9419

File tree

2 files changed

+41
-27
lines changed

2 files changed

+41
-27
lines changed

src/ng/filter/filter.js

+38-24
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ function filterFilter() {
120120
if (!isArray(array)) return array;
121121

122122
var predicateFn;
123-
var matchAgainstAnyProp;
124123

125124
switch (typeof expression) {
126125
case 'function':
@@ -129,11 +128,8 @@ function filterFilter() {
129128
case 'boolean':
130129
case 'number':
131130
case 'string':
132-
matchAgainstAnyProp = true;
133-
//jshint -W086
134131
case 'object':
135-
//jshint +W086
136-
predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp);
132+
predicateFn = createPredicateFn(expression, comparator);
137133
break;
138134
default:
139135
return array;
@@ -144,7 +140,7 @@ function filterFilter() {
144140
}
145141

146142
// Helper functions for `filterFilter`
147-
function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
143+
function createPredicateFn(expression, comparator) {
148144
var predicateFn;
149145

150146
if (comparator === true) {
@@ -163,53 +159,58 @@ function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
163159
}
164160

165161
predicateFn = function(item) {
166-
return deepCompare(item, expression, comparator, matchAgainstAnyProp);
162+
return deepCompare(item, expression, comparator);
167163
};
168164

169165
return predicateFn;
170166
}
171167

172-
function deepCompare(actual, expected, comparator, matchAgainstAnyProp, temporaryAnyProp) {
168+
function deepCompare(actual, expected, comparator) {
173169
var actualType = typeof actual;
174170
var expectedType = typeof expected;
175-
var nextMatchAgainstAnyProp = matchAgainstAnyProp && !temporaryAnyProp;
176171

177172
if ((expectedType === 'string') && (expected.charAt(0) === '!')) {
178-
return !deepCompare(actual, expected.substring(1), comparator, nextMatchAgainstAnyProp);
179-
} else if (actualType === 'array') {
173+
return !deepCompare(actual, expected.substring(1), comparator);
174+
}
175+
176+
if (actualType === 'array') {
180177
// In case `actual` is an array, consider it a match
181178
// if ANY of it's items matches `expected`
182179
return actual.some(function(item) {
183-
return deepCompare(item, expected, comparator, nextMatchAgainstAnyProp);
180+
return deepCompare(item, expected, comparator);
184181
});
185182
}
186183

187184
switch (actualType) {
188185
case 'object':
189186
var key;
190-
if (matchAgainstAnyProp) {
191-
for (key in actual) {
192-
if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, nextMatchAgainstAnyProp)) {
193-
return true;
194-
}
195-
}
196-
return false;
197-
} else if (expectedType === 'object') {
187+
if (expectedType === 'object') {
198188
for (key in expected) {
199189
var expectedVal = expected[key];
200190
if (isFunction(expectedVal)) {
201191
continue;
202192
}
203193

204194
var keyIsDollar = key === '$';
205-
var actualVal = keyIsDollar ? actual : actual[key];
206-
if (!deepCompare(actualVal, expectedVal, comparator, keyIsDollar, keyIsDollar)) {
207-
return false;
195+
if (keyIsDollar) {
196+
if (!matchAnyProp(actual, expectedVal, comparator)) {
197+
return false;
198+
}
199+
} else {
200+
var actualVal = actual[key];
201+
if (!deepCompare(actualVal, expectedVal, comparator)) {
202+
return false;
203+
}
208204
}
209205
}
210206
return true;
211207
} else {
212-
return comparator(actual, expected);
208+
for (key in actual) {
209+
if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator)) {
210+
return true;
211+
}
212+
}
213+
return false;
213214
}
214215
break;
215216
case 'function':
@@ -218,3 +219,16 @@ function deepCompare(actual, expected, comparator, matchAgainstAnyProp, temporar
218219
return comparator(actual, expected);
219220
}
220221
}
222+
223+
function matchAnyProp(actual, expected, comparator) {
224+
if (typeof actual !== 'object') {
225+
throw new Error('actual must be an object but was ' + typeof actual);
226+
}
227+
228+
for (var key in actual) {
229+
if (deepCompare(actual[key], expected, comparator)) {
230+
return true;
231+
}
232+
}
233+
return false;
234+
}

test/ng/filter/filterSpec.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -143,14 +143,14 @@ describe('Filter: filter', function() {
143143
});
144144

145145

146-
it('should respect the depth level of a "$" property', function() {
146+
it('should match the same level and deeper of a "$" property', function() {
147147
var items = [{person: {name: 'Annet', email: 'annet@example.com'}},
148148
{person: {name: 'Billy', email: 'me@billy.com'}},
149149
{person: {name: 'Joan', email: {home: 'me@joan.com', work: 'joan@example.net'}}}];
150150
var expr = {person: {$: 'net'}};
151151

152-
expect(filter(items, expr).length).toBe(1);
153-
expect(filter(items, expr)).toEqual([items[0]]);
152+
expect(filter(items, expr).length).toBe(2);
153+
expect(filter(items, expr)).toEqual([items[0], items[2]]);
154154
});
155155

156156

0 commit comments

Comments
 (0)