diff --git a/src/query.ts b/src/query.ts index cd8c1f0..7fa5b93 100644 --- a/src/query.ts +++ b/src/query.ts @@ -82,6 +82,14 @@ export class Query { return false } + /** + * @note Predicate functions receive the actual value as-is, + * including arrays and objects, so check for them first. + */ + if (typeof selector === 'function') { + return selector(actualValue) + } + if (Array.isArray(actualValue)) { return actualValue.every((value) => { return compileCondition(selector)(value) @@ -92,10 +100,6 @@ export class Query { return compileCondition(selector)(actualValue) } - if (typeof selector === 'function') { - return selector(actualValue) - } - return actualValue === selector }) } diff --git a/tests/query.test.ts b/tests/query.test.ts index 1276ac9..3476a91 100644 --- a/tests/query.test.ts +++ b/tests/query.test.ts @@ -60,3 +60,22 @@ it('combines predicates under an AND logic', () => { .test({ id: 456, name: 'Kate' }), ).toBe(false) }) + +it('supports a predicate function against an array property', () => { + const query = new Query<{ petNames: Array }>().where({ + petNames: (petNames) => petNames.includes('wolfy'), + }) + + expect(query.test({ petNames: ['wolfy'] })).toBe(true) + expect(query.test({ petNames: ['rex'] })).toBe(false) + expect(query.test({ petNames: [] })).toBe(false) +}) + +it('supports a condition against an array of objects', () => { + const query = new Query<{ posts: Array<{ title: string }> }>().where({ + posts: { title: 'First' }, + }) + + expect(query.test({ posts: [{ title: 'First' }] })).toBe(true) + expect(query.test({ posts: [{ title: 'Second' }] })).toBe(false) +})