Skip to content

Commit 34f4c13

Browse files
authored
Add a findAll method to ParseQuery (#1233)
* Add a findAll method to ParseQuery * Add unit tests for ParseQuery.findAll method
1 parent f2673a7 commit 34f4c13

File tree

3 files changed

+138
-0
lines changed

3 files changed

+138
-0
lines changed

integration/test/ParseQueryTest.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,6 +1223,18 @@ describe('Parse Query', () => {
12231223
});
12241224
});
12251225

1226+
it('can return all objects with findAll', async () => {
1227+
const objs = [...Array(101)].map(() => new Parse.Object('Container'));
1228+
1229+
await Parse.Object.saveAll(objs);
1230+
1231+
const query = new Parse.Query('Container');
1232+
1233+
const result = await query.findAll();
1234+
1235+
assert.equal(result.length, 101);
1236+
});
1237+
12261238
it('can include nested objects via array', (done) => {
12271239
const child = new TestObject();
12281240
const parent = new Parse.Object('Container');

src/ParseQuery.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,28 @@ class ParseQuery {
673673
});
674674
}
675675

676+
/**
677+
* Retrieves a complete list of ParseObjects that satisfy this query.
678+
* Using `eachBatch` under the hood to fetch all the valid objects.
679+
*
680+
* @param {Object} options Valid options are:<ul>
681+
* <li>batchSize: How many objects to yield in each batch (default: 100)
682+
* <li>useMasterKey: In Cloud Code and Node only, causes the Master Key to
683+
* be used for this request.
684+
* <li>sessionToken: A valid session token, used for making a request on
685+
* behalf of a specific user.
686+
* </ul>
687+
* @return {Promise} A promise that is resolved with the results when
688+
* the query completes.
689+
*/
690+
async findAll(options?: BatchOptions): Promise<Array<ParseObject>> {
691+
let result: ParseObject[] = [];
692+
await this.eachBatch((objects: ParseObject[]) => {
693+
result = [...result, ...objects];
694+
}, options);
695+
return result;
696+
}
697+
676698
/**
677699
* Counts the number of objects that match this query.
678700
* Either options.success or options.error is called when the count

src/__tests__/ParseQuery-test.js

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1638,6 +1638,110 @@ describe('ParseQuery', () => {
16381638
});
16391639
});
16401640

1641+
describe('return all objects with .findAll()', () => {
1642+
let findMock;
1643+
beforeEach(() => {
1644+
findMock = jest.fn();
1645+
findMock.mockReturnValueOnce(Promise.resolve({
1646+
results: [
1647+
{ objectId: 'I55', size: 'medium', name: 'Product 55' },
1648+
{ objectId: 'I89', size: 'small', name: 'Product 89' },
1649+
]
1650+
}));
1651+
findMock.mockReturnValueOnce(Promise.resolve({
1652+
results: [
1653+
{ objectId: 'I91', size: 'small', name: 'Product 91' },
1654+
]
1655+
}));
1656+
CoreManager.setQueryController({
1657+
aggregate() {},
1658+
find: findMock,
1659+
});
1660+
});
1661+
1662+
it('passes query attributes through to the REST API', async () => {
1663+
const q = new ParseQuery('Item');
1664+
q.containedIn('size', ['small', 'medium']);
1665+
q.matchesKeyInQuery(
1666+
'name',
1667+
'productName',
1668+
new ParseQuery('Review').equalTo('stars', 5)
1669+
);
1670+
q.equalTo('valid', true);
1671+
q.select('size', 'name');
1672+
q.includeAll();
1673+
q.hint('_id_');
1674+
1675+
await q.findAll();
1676+
expect(findMock).toHaveBeenCalledTimes(1);
1677+
const [className, params, options] = findMock.mock.calls[0];
1678+
expect(className).toBe('Item')
1679+
expect(params).toEqual({
1680+
limit: 100,
1681+
order: 'objectId',
1682+
keys: 'size,name',
1683+
include: '*',
1684+
hint: '_id_',
1685+
where: {
1686+
size: {
1687+
$in: ['small', 'medium']
1688+
},
1689+
name: {
1690+
$select: {
1691+
key: 'productName',
1692+
query: {
1693+
className: 'Review',
1694+
where: {
1695+
stars: 5
1696+
}
1697+
}
1698+
}
1699+
},
1700+
valid: true
1701+
}
1702+
});
1703+
expect(options.requestTask).toBeDefined();
1704+
});
1705+
1706+
it('passes options through to the REST API', async () => {
1707+
const batchOptions = {
1708+
useMasterKey: true,
1709+
sessionToken: '1234',
1710+
batchSize: 50,
1711+
};
1712+
const q = new ParseQuery('Item');
1713+
await q.findAll(batchOptions);
1714+
expect(findMock).toHaveBeenCalledTimes(1);
1715+
const [className, params, options] = findMock.mock.calls[0];
1716+
expect(className).toBe('Item');
1717+
expect(params).toEqual({
1718+
limit: 50,
1719+
order: 'objectId',
1720+
where: {},
1721+
});
1722+
expect(options.useMasterKey).toBe(true);
1723+
expect(options.sessionToken).toEqual('1234');
1724+
});
1725+
1726+
it('only makes one request when the results fit in one page', async () => {
1727+
const q = new ParseQuery('Item');
1728+
await q.findAll();
1729+
expect(findMock).toHaveBeenCalledTimes(1);
1730+
});
1731+
1732+
it('makes more requests when the results do not fit in one page', async () => {
1733+
const q = new ParseQuery('Item');
1734+
await q.findAll({ batchSize: 2 });
1735+
expect(findMock).toHaveBeenCalledTimes(2);
1736+
})
1737+
1738+
it('Returns all objects', async () => {
1739+
const q = new ParseQuery('Item');
1740+
const results = await q.findAll();
1741+
expect(results.map(obj => obj.attributes.size)).toEqual(['medium', 'small']);
1742+
});
1743+
});
1744+
16411745
it('can iterate over results with each()', (done) => {
16421746
CoreManager.setQueryController({
16431747
aggregate() {},

0 commit comments

Comments
 (0)