diff --git a/integration/test/ParseLiveQueryTest.js b/integration/test/ParseLiveQueryTest.js index b97c93b8e..3ac4636e7 100644 --- a/integration/test/ParseLiveQueryTest.js +++ b/integration/test/ParseLiveQueryTest.js @@ -346,8 +346,6 @@ describe('Parse LiveQuery', () => { await obj2.save(); obj2.set('foo', 'bart'); await obj2.save(); - await sleep(1000); - await subscription.unsubscribe(); expect(createSpy).toHaveBeenCalledTimes(1); expect(updateSpy).toHaveBeenCalledTimes(1); }); diff --git a/integration/test/ParseQueryTest.js b/integration/test/ParseQueryTest.js index f2c3c4204..9563c6738 100644 --- a/integration/test/ParseQueryTest.js +++ b/integration/test/ParseQueryTest.js @@ -53,7 +53,13 @@ describe('Parse Query', () => { await object.save(); const query = new Parse.Query(TestObject); - const results = await query.find({ json: true }); + let results = await query.find({ json: true }); + assert.strictEqual(results[0] instanceof Parse.Object, false); + assert.strictEqual(results[0].foo, 'bar'); + assert.strictEqual(results[0].className, 'TestObject'); + assert.strictEqual(results[0].objectId, object.id); + + results = await query.findAll({ json: true }); assert.strictEqual(results[0] instanceof Parse.Object, false); assert.strictEqual(results[0].foo, 'bar'); assert.strictEqual(results[0].className, 'TestObject'); @@ -101,6 +107,25 @@ describe('Parse Query', () => { } }); + it('can do findAll query with count', async () => { + const items = []; + for (let i = 0; i < 4; i++) { + items.push(new TestObject({ countMe: true })); + } + await Parse.Object.saveAll(items); + + const query = new Parse.Query(TestObject); + query.withCount(true); + const { results, count } = await query.findAll(); + + assert.equal(results.length, 4); + assert(typeof count === 'number'); + assert.equal(count, 4); + for (let i = 0; i < 4; i++) { + assert.equal(results[i].className, 'TestObject'); + } + }); + it('can do query withCount set to false', async () => { const items = []; for (let i = 0; i < 4; i++) { @@ -2391,6 +2416,18 @@ describe('Parse Query', () => { assert.equal(indexName, '_id_'); }); + it('can query with explain false', async () => { + const obj1 = new TestObject({ number: 1 }); + const obj2 = new TestObject({ number: 2 }); + const obj3 = new TestObject({ number: 3 }); + await Parse.Object.saveAll([obj1, obj2, obj3]); + + const query = new Parse.Query(TestObject); + query.explain(false); + const results = await query.find(); + expect(results.length).toBe(3); + }); + it('can query with select on null field', async () => { const obj1 = new TestObject({ number: 1, arrayField: [] }); const obj2 = new TestObject({ number: 2, arrayField: [{ subfield: 1 }] }); diff --git a/src/EventuallyQueue.ts b/src/EventuallyQueue.ts index 3659d9d2f..01f3c840c 100644 --- a/src/EventuallyQueue.ts +++ b/src/EventuallyQueue.ts @@ -346,7 +346,7 @@ const EventuallyQueue = { const { sessionToken } = queueObject.serverOptions; const query = new ParseQuery(ObjectType); query.equalTo('hash', queueObject.hash); - const results = await query.find({ sessionToken }); + const results: any = await query.find({ sessionToken }); if (results.length > 0) { return EventuallyQueue.sendQueueCallback(results[0], queueObject); } diff --git a/src/ParseQuery.ts b/src/ParseQuery.ts index 91ece7e39..d3e52d986 100644 --- a/src/ParseQuery.ts +++ b/src/ParseQuery.ts @@ -675,7 +675,7 @@ class ParseQuery { * @returns {Promise} A promise that is resolved with the results when * the query completes. */ - find(options?: QueryOptions): Promise { + find(options?: QueryOptions): Promise { const findOptions = ParseObject._getRequestOptions(options); this._setRequestTask(findOptions); @@ -736,12 +736,15 @@ class ParseQuery { * @returns {Promise} A promise that is resolved with the results when * the query completes. */ - async findAll(options?: BatchOptions): Promise { - let result: T[] = []; + async findAll(options?: BatchOptions): Promise { + let results: T[] = []; await this.eachBatch((objects: T[]) => { - result = [...result, ...objects]; + results = [...results, ...objects]; }, options); - return result; + if (this._count) { + return { results, count: results.length }; + } + return results; } /** @@ -930,10 +933,14 @@ class ParseQuery { return !finished; }, async () => { - const [results] = await Promise.all([ + const [response] = await Promise.all([ query.find(findOptions), Promise.resolve(previousResults.length > 0 && callback(previousResults)), ]); + let results: any = response; + if (results.results) { + results = results.results; + } if (results.length >= query._limit) { if (findOptions.json) { query.greaterThan('objectId', (results[results.length - 1] as any).objectId); diff --git a/src/__tests__/ParseQuery-test.js b/src/__tests__/ParseQuery-test.js index 13e793d57..c493fee7c 100644 --- a/src/__tests__/ParseQuery-test.js +++ b/src/__tests__/ParseQuery-test.js @@ -1897,6 +1897,30 @@ describe('ParseQuery', () => { expect(result.objectId).toBeDefined(); }); }); + + it('Returns all objects with count', async () => { + const findCountMock = jest.fn(); + findCountMock.mockReturnValueOnce( + Promise.resolve({ + results: [{ objectId: 'I92', size: 'medium', name: 'Product 92' }], + count: 1, + }) + ); + CoreManager.setQueryController({ + aggregate() {}, + find: findCountMock, + }); + const q = new ParseQuery('Item'); + q.withCount(); + const { results, count } = await q.findAll(); + expect(results.length).toEqual(1); + expect(count).toEqual(1); + expect(findCountMock).toHaveBeenCalledTimes(1); + CoreManager.setQueryController({ + aggregate() {}, + find: findMock, + }); + }); }); it('can iterate over results with each()', done => { diff --git a/types/ParseQuery.d.ts b/types/ParseQuery.d.ts index fa8e558e8..133180dde 100644 --- a/types/ParseQuery.d.ts +++ b/types/ParseQuery.d.ts @@ -225,7 +225,10 @@ declare class ParseQuery { * @returns {Promise} A promise that is resolved with the results when * the query completes. */ - find(options?: QueryOptions): Promise; + find(options?: QueryOptions): Promise; /** * Retrieves a complete list of ParseObjects that satisfy this query. * Using `eachBatch` under the hood to fetch all the valid objects. @@ -241,7 +244,10 @@ declare class ParseQuery { * @returns {Promise} A promise that is resolved with the results when * the query completes. */ - findAll(options?: BatchOptions): Promise; + findAll(options?: BatchOptions): Promise; /** * Counts the number of objects that match this query. * diff --git a/types/tests.ts b/types/tests.ts index 4421ec84d..75d4e483a 100644 --- a/types/tests.ts +++ b/types/tests.ts @@ -904,7 +904,6 @@ async function test_cancel_query() { query.cancel(); } -/* eslint-disable @typescript-eslint/no-redundant-type-constituents -- object is intentionally included for testing Exclude. */ type FieldType = | string | number @@ -917,7 +916,7 @@ type FieldType = | Parse.Pointer | Parse.Polygon | Parse.Relation; -/* eslint-enable @typescript-eslint/no-redundant-type-constituents */ + async function test_schema( anyField: FieldType, notString: Exclude, @@ -2046,9 +2045,12 @@ function testQuery() { // $ExpectType ParseObject await queryUntyped.get('objectId'); - // $ExpectType ParseObject[] + // $ExpectType ParseObject[] | { results: ParseObject[]; count: number; } await queryUntyped.find(); + // $ExpectType ParseObject[] | { results: ParseObject[]; count: number; } + await queryUntyped.findAll(); + // $ExpectType string[] await queryTyped.distinct('example'); @@ -2058,7 +2060,7 @@ function testQuery() { // $ExpectType ParseObject<{ example: string; }> await queryTyped.get('objectId'); - // $ExpectType ParseObject<{ example: string; }>[] + // $ExpectType ParseObject<{ example: string; }>[] | { results: ParseObject<{ example: string; }>[]; count: number; } await queryTyped.find(); // $ExpectType ParseObject<{ example: string; }> | undefined