From 09a3bb7d576599c6737fba66bed54aa1d955f867 Mon Sep 17 00:00:00 2001 From: dblythy Date: Wed, 18 Aug 2021 04:53:13 +1000 Subject: [PATCH 01/16] fix: allow for descending fullText --- spec/ParseQuery.FullTextSearch.spec.js | 9 +++++++++ src/RestQuery.js | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/spec/ParseQuery.FullTextSearch.spec.js b/spec/ParseQuery.FullTextSearch.spec.js index 99118d106c..0aae3805cc 100644 --- a/spec/ParseQuery.FullTextSearch.spec.js +++ b/spec/ParseQuery.FullTextSearch.spec.js @@ -120,6 +120,15 @@ describe('Parse.Query Full Text Search testing', () => { }, done.fail); }); + it('fulltext descending by $score', async () => { + await fullTextHelper(); + const query = new Parse.Query('TestObject'); + query.fullText('subject', 'coffee'); + query.descending('$score'); + const objects = await query.find(); + expect(objects.length).toBe(3); + }); + it('fullTextSearch: $language', done => { fullTextHelper() .then(() => { diff --git a/src/RestQuery.js b/src/RestQuery.js index 6039084e38..4452a86c22 100644 --- a/src/RestQuery.js +++ b/src/RestQuery.js @@ -143,7 +143,7 @@ function RestQuery( var fields = restOptions.order.split(','); this.findOptions.sort = fields.reduce((sortMap, field) => { field = field.trim(); - if (field === '$score') { + if (field === '$score' || field === '-$score') { sortMap.score = { $meta: 'textScore' }; } else if (field[0] == '-') { sortMap[field.slice(1)] = -1; @@ -866,7 +866,7 @@ function includePath(config, auth, response, path, restOptions = {}) { return set; } } - if (i == (keyPath.length - 1)) { + if (i == keyPath.length - 1) { set.add(keyPath[i]); } return set; From 0a980df9f82116561606c91049b49056f27d7d2a Mon Sep 17 00:00:00 2001 From: dblythy Date: Wed, 18 Aug 2021 05:28:55 +1000 Subject: [PATCH 02/16] Update ParseQuery.FullTextSearch.spec.js --- spec/ParseQuery.FullTextSearch.spec.js | 32 +++++++++++++++++++++----- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/spec/ParseQuery.FullTextSearch.spec.js b/spec/ParseQuery.FullTextSearch.spec.js index 0aae3805cc..bfd3284655 100644 --- a/spec/ParseQuery.FullTextSearch.spec.js +++ b/spec/ParseQuery.FullTextSearch.spec.js @@ -52,7 +52,7 @@ const fullTextHelper = () => { }); }; -describe('Parse.Query Full Text Search testing', () => { +fdescribe('Parse.Query Full Text Search testing', () => { it('fullTextSearch: $search', done => { fullTextHelper() .then(() => { @@ -122,11 +122,31 @@ describe('Parse.Query Full Text Search testing', () => { it('fulltext descending by $score', async () => { await fullTextHelper(); - const query = new Parse.Query('TestObject'); - query.fullText('subject', 'coffee'); - query.descending('$score'); - const objects = await query.find(); - expect(objects.length).toBe(3); + const where = { + subject: { + $text: { + $search: { + $term: 'coffee', + }, + }, + }, + }; + const order = '-$score'; + const keys = '$score'; + const { data } = await request({ + method: 'POST', + url: 'http://localhost:8378/1/classes/TestObject', + body: { where, order, keys, _method: 'GET' }, + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'test', + 'Content-Type': 'application/json', + }, + }); + expect(data.results.length).toBe(3); + expect(data.results[0].score); + expect(data.results[1].score); + expect(data.results[2].score); }); it('fullTextSearch: $language', done => { From c579803809ca54f59e04fa316dd7028a85ddb7ae Mon Sep 17 00:00:00 2001 From: dblythy Date: Wed, 18 Aug 2021 05:29:05 +1000 Subject: [PATCH 03/16] Update ParseQuery.FullTextSearch.spec.js --- spec/ParseQuery.FullTextSearch.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/ParseQuery.FullTextSearch.spec.js b/spec/ParseQuery.FullTextSearch.spec.js index bfd3284655..06bca58e54 100644 --- a/spec/ParseQuery.FullTextSearch.spec.js +++ b/spec/ParseQuery.FullTextSearch.spec.js @@ -52,7 +52,7 @@ const fullTextHelper = () => { }); }; -fdescribe('Parse.Query Full Text Search testing', () => { +describe('Parse.Query Full Text Search testing', () => { it('fullTextSearch: $search', done => { fullTextHelper() .then(() => { From 64a49c7608b247b1eac5b8eac78964d74ab7f88a Mon Sep 17 00:00:00 2001 From: dblythy Date: Sat, 4 Sep 2021 16:32:13 +1000 Subject: [PATCH 04/16] Update RestQuery.js --- src/RestQuery.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RestQuery.js b/src/RestQuery.js index 4452a86c22..a519b09305 100644 --- a/src/RestQuery.js +++ b/src/RestQuery.js @@ -866,7 +866,7 @@ function includePath(config, auth, response, path, restOptions = {}) { return set; } } - if (i == keyPath.length - 1) { + if (i + 1 === keyPath.length) { set.add(keyPath[i]); } return set; From f586feb3b8088a87982adc89c0f435620f36a1a2 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sat, 4 Sep 2021 16:34:32 +1000 Subject: [PATCH 05/16] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 203578e435..3e83d7c570 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -139,6 +139,7 @@ ___ - Fix LiveQuery server crash when using $all query operator on a missing object key (Jason Posthuma) [#7421](https://github.com/parse-community/parse-server/pull/7421) - Added runtime deprecation warnings (Manuel Trezza) [#7451](https://github.com/parse-community/parse-server/pull/7451) - Add ability to pass context of an object via a header, X-Parse-Cloud-Context, for Cloud Code triggers. The header addition allows client SDK's to add context without injecting _context in the body of JSON objects (Corey Baker) [#7437](https://github.com/parse-community/parse-server/pull/7437) +- Allow setting descending sort to full text queries (dblythy) [#7496](https://github.com/parse-community/parse-server/pull/7496) ___ ## 4.5.0 From 9d096d35cc02d4df229eaee944ff44f0c59bba16 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sat, 4 Sep 2021 16:35:30 +1000 Subject: [PATCH 06/16] Revert "Update CHANGELOG.md" This reverts commit f586feb3b8088a87982adc89c0f435620f36a1a2. --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e83d7c570..203578e435 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -139,7 +139,6 @@ ___ - Fix LiveQuery server crash when using $all query operator on a missing object key (Jason Posthuma) [#7421](https://github.com/parse-community/parse-server/pull/7421) - Added runtime deprecation warnings (Manuel Trezza) [#7451](https://github.com/parse-community/parse-server/pull/7451) - Add ability to pass context of an object via a header, X-Parse-Cloud-Context, for Cloud Code triggers. The header addition allows client SDK's to add context without injecting _context in the body of JSON objects (Corey Baker) [#7437](https://github.com/parse-community/parse-server/pull/7437) -- Allow setting descending sort to full text queries (dblythy) [#7496](https://github.com/parse-community/parse-server/pull/7496) ___ ## 4.5.0 From a7cc26f5b57455f13f3d29e9fd76711de674eae7 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sat, 4 Sep 2021 16:38:56 +1000 Subject: [PATCH 07/16] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2f85589f3..ea13313c8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -150,6 +150,7 @@ ___ - Add CI check to add changelog entry (Manuel Trezza) [#7512](https://github.com/parse-community/parse-server/pull/7512) - Refactor: uniform issue templates across repos (Manuel Trezza) [#7528](https://github.com/parse-community/parse-server/pull/7528) - ci: bump ci environment (Manuel Trezza) [#7539](https://github.com/parse-community/parse-server/pull/7539) +- Allow setting descending sort to full text queries (dblythy) [#7496](https://github.com/parse-community/parse-server/pull/7496) ## 4.10.3 [Full Changelog](https://github.com/parse-community/parse-server/compare/4.10.2...4.10.3) @@ -185,6 +186,8 @@ ___ > > You may be also affected if you used the Bitnami image for Parse Server. Bitnami picked up the incorrect version tag `4.9.3` and published a new Bitnami image for Parse Server. > +> You may be also affected if you used the Bitnami image for Parse Server. Bitnami picked up the incorrect version tag `4.9.3` and published a new Bitnami image for Parse Server. +> >**If you are using any of the affected versions, we urgently recommend to upgrade to version `4.10.0`.** ## 4.5.2 From 71cb31edd0dcd0cf2cf67419c3ade72a4945b490 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sat, 4 Sep 2021 16:39:44 +1000 Subject: [PATCH 08/16] Update CHANGELOG.md --- CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea13313c8e..411589cfa5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -184,8 +184,6 @@ ___ > > We have since deleted the incorrect version tags, but they may still show up if your personal fork on GitHub or locally. We do not know when these tags have been pushed to the Parse Server repository, but we first became aware of this issue on July 21, 2021. We are not aware of any malicious code or concerns related to privacy, security or legality (e.g. proprietary code). However, it has been reported that some functionality does not work as expected and the introduction of security vulnerabilities cannot be ruled out. > -> You may be also affected if you used the Bitnami image for Parse Server. Bitnami picked up the incorrect version tag `4.9.3` and published a new Bitnami image for Parse Server. -> > You may be also affected if you used the Bitnami image for Parse Server. Bitnami picked up the incorrect version tag `4.9.3` and published a new Bitnami image for Parse Server. > >**If you are using any of the affected versions, we urgently recommend to upgrade to version `4.10.0`.** From 2e959f18987c89e349f3db869643df0fbed044e5 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sat, 4 Sep 2021 16:40:22 +1000 Subject: [PATCH 09/16] Update CHANGELOG.md --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 411589cfa5..ee53707343 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -177,11 +177,11 @@ ___ *Versions >4.5.2 and <4.10.0 are skipped.* -> ⚠️ A security incident caused a number of incorrect version tags to be pushed to the Parse Server repository. These version tags linked to a personal fork of a contributor who had write access to the repository. The code to which these tags linked has not been reviewed or approved by Parse Platform. Even though no releases were published with these incorrect versions, it was possible to define a Parse Server dependency that pointed to these version tags, for example if you defined this dependency: +> ⚠️ A security incident caused a number of incorrect version tags to be pushed to the Parse Server repository. These version tags linked to a personal fork of a contributor who had write access to the repository. The code to which these tags linked has not been reviewed or approved by Parse Platform. Even though no releases were published with these incorrect versions, it was possible to define a Parse Server dependency that pointed to these version tags, for example if you defined this dependency: > ```js > "parse-server": "git@github.com:parse-community/parse-server.git#4.9.3" > ``` -> +> > We have since deleted the incorrect version tags, but they may still show up if your personal fork on GitHub or locally. We do not know when these tags have been pushed to the Parse Server repository, but we first became aware of this issue on July 21, 2021. We are not aware of any malicious code or concerns related to privacy, security or legality (e.g. proprietary code). However, it has been reported that some functionality does not work as expected and the introduction of security vulnerabilities cannot be ruled out. > > You may be also affected if you used the Bitnami image for Parse Server. Bitnami picked up the incorrect version tag `4.9.3` and published a new Bitnami image for Parse Server. From 736ddf55e4648015c7bcb79be443b3cae24a5cfa Mon Sep 17 00:00:00 2001 From: dblythy Date: Sat, 4 Sep 2021 16:45:07 +1000 Subject: [PATCH 10/16] Update ParseQuery.FullTextSearch.spec.js --- spec/ParseQuery.FullTextSearch.spec.js | 34 +++++++------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/spec/ParseQuery.FullTextSearch.spec.js b/spec/ParseQuery.FullTextSearch.spec.js index 06bca58e54..c4515639b5 100644 --- a/spec/ParseQuery.FullTextSearch.spec.js +++ b/spec/ParseQuery.FullTextSearch.spec.js @@ -122,31 +122,15 @@ describe('Parse.Query Full Text Search testing', () => { it('fulltext descending by $score', async () => { await fullTextHelper(); - const where = { - subject: { - $text: { - $search: { - $term: 'coffee', - }, - }, - }, - }; - const order = '-$score'; - const keys = '$score'; - const { data } = await request({ - method: 'POST', - url: 'http://localhost:8378/1/classes/TestObject', - body: { where, order, keys, _method: 'GET' }, - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'test', - 'Content-Type': 'application/json', - }, - }); - expect(data.results.length).toBe(3); - expect(data.results[0].score); - expect(data.results[1].score); - expect(data.results[2].score); + const query = new Parse.Query('TestObject'); + query.fullText('subject', 'coffee'); + query.descending('$score'); + query.select('$score'); + const results = await query.find(); + expect(results.length).toBe(3); + expect(results[0].get('score')); + expect(results[1].get('score')); + expect(results[2].get('score')); }); it('fullTextSearch: $language', done => { From f52fe08b69cedb04b534c0247c6ee6858e94e240 Mon Sep 17 00:00:00 2001 From: dblythy Date: Wed, 15 Sep 2021 00:28:04 +1000 Subject: [PATCH 11/16] Update RestQuery.js --- src/RestQuery.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RestQuery.js b/src/RestQuery.js index 6461395974..be96683451 100644 --- a/src/RestQuery.js +++ b/src/RestQuery.js @@ -866,7 +866,7 @@ function includePath(config, auth, response, path, restOptions = {}) { return set; } } - if (i + 1 === keyPath.length) { + if (i == keyPath.length - 1) { set.add(keyPath[i]); } return set; From 3c45d279dc7d51a1ec12d97de4ab6021ef4dcdf3 Mon Sep 17 00:00:00 2001 From: dblythy Date: Wed, 15 Sep 2021 10:59:27 +1000 Subject: [PATCH 12/16] Update ParseQuery.FullTextSearch.spec.js --- spec/ParseQuery.FullTextSearch.spec.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/spec/ParseQuery.FullTextSearch.spec.js b/spec/ParseQuery.FullTextSearch.spec.js index c4515639b5..3af2f737f5 100644 --- a/spec/ParseQuery.FullTextSearch.spec.js +++ b/spec/ParseQuery.FullTextSearch.spec.js @@ -126,11 +126,14 @@ describe('Parse.Query Full Text Search testing', () => { query.fullText('subject', 'coffee'); query.descending('$score'); query.select('$score'); - const results = await query.find(); - expect(results.length).toBe(3); - expect(results[0].get('score')); - expect(results[1].get('score')); - expect(results[2].get('score')); + const [first, second, third] = await query.find(); + expect(first).toBeDefined(); + expect(second).toBeDefined(); + expect(third).toBeDefined(); + expect(first.get('score')); + expect(second.get('score')); + expect(third.get('score')); + expect(first.get('score') > second.get('score') > third.get('score')).toBeTrue(); }); it('fullTextSearch: $language', done => { From ef96899c6093cd9a81ff0317eda4dcda11dc6f46 Mon Sep 17 00:00:00 2001 From: dblythy Date: Wed, 15 Sep 2021 11:28:48 +1000 Subject: [PATCH 13/16] add refactor --- spec/ParseQuery.FullTextSearch.spec.js | 428 ++++++------------------- 1 file changed, 102 insertions(+), 326 deletions(-) diff --git a/spec/ParseQuery.FullTextSearch.spec.js b/spec/ParseQuery.FullTextSearch.spec.js index 3af2f737f5..24e7bd79e2 100644 --- a/spec/ParseQuery.FullTextSearch.spec.js +++ b/spec/ParseQuery.FullTextSearch.spec.js @@ -5,10 +5,9 @@ const Parse = require('parse/node'); const request = require('../lib/request'); let databaseAdapter; -const fullTextHelper = () => { +const fullTextHelper = async () => { const config = Config.get('test'); databaseAdapter = config.database.adapter; - const subjects = [ 'coffee', 'Coffee Shopping', @@ -19,105 +18,37 @@ const fullTextHelper = () => { 'coffee and cream', 'Cafe con Leche', ]; - const requests = []; - for (const i in subjects) { - const request = { - method: 'POST', - body: { - subject: subjects[i], - comment: subjects[i], - }, - path: '/1/classes/TestObject', - }; - requests.push(request); - } - return reconfigureServer({ + await reconfigureServer({ appId: 'test', restAPIKey: 'test', publicServerURL: 'http://localhost:8378/1', databaseAdapter, - }).then(() => { - return request({ - method: 'POST', - url: 'http://localhost:8378/1/batch', - body: { - requests, - }, - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'test', - 'Content-Type': 'application/json', - }, - }); }); + await Parse.Object.saveAll( + subjects.map(subject => new Parse.Object('TestObject').set({ subject, comment: subject })) + ); }; describe('Parse.Query Full Text Search testing', () => { - it('fullTextSearch: $search', done => { - fullTextHelper() - .then(() => { - const where = { - subject: { - $text: { - $search: { - $term: 'coffee', - }, - }, - }, - }; - return request({ - method: 'POST', - url: 'http://localhost:8378/1/classes/TestObject', - body: { where, _method: 'GET' }, - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'test', - 'Content-Type': 'application/json', - }, - }); - }) - .then( - resp => { - expect(resp.data.results.length).toBe(3); - done(); - }, - e => done.fail(e) - ); + it('fullTextSearch: $search', async () => { + await fullTextHelper(); + const query = new Parse.Query('TestObject'); + query.fullText('subject', 'coffee'); + const results = await query.find(); + expect(results.length).toBe(3); }); - it('fullTextSearch: $search, sort', done => { - fullTextHelper() - .then(() => { - const where = { - subject: { - $text: { - $search: { - $term: 'coffee', - }, - }, - }, - }; - const order = '$score'; - const keys = '$score'; - return request({ - method: 'POST', - url: 'http://localhost:8378/1/classes/TestObject', - body: { where, order, keys, _method: 'GET' }, - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'test', - 'Content-Type': 'application/json', - }, - }); - }) - .then(response => { - const resp = response.data; - expect(resp.results.length).toBe(3); - expect(resp.results[0].score); - expect(resp.results[1].score); - expect(resp.results[2].score); - done(); - }, done.fail); + it('fullTextSearch: $search, sort', async () => { + await fullTextHelper(); + const query = new Parse.Query('TestObject'); + query.fullText('subject', 'coffee'); + query.select('$score'); + query.ascending('$score'); + const results = await query.find(); + expect(results.length).toBe(3); + expect(results[0].get('score')); + expect(results[1].get('score')); + expect(results[2].get('score')); }); it('fulltext descending by $score', async () => { @@ -136,77 +67,34 @@ describe('Parse.Query Full Text Search testing', () => { expect(first.get('score') > second.get('score') > third.get('score')).toBeTrue(); }); - it('fullTextSearch: $language', done => { - fullTextHelper() - .then(() => { - const where = { - subject: { - $text: { - $search: { - $term: 'leche', - $language: 'spanish', - }, - }, - }, - }; - return request({ - method: 'POST', - url: 'http://localhost:8378/1/classes/TestObject', - body: { where, _method: 'GET' }, - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'test', - 'Content-Type': 'application/json', - }, - }); - }) - .then(resp => { - expect(resp.data.results.length).toBe(2); - done(); - }, done.fail); + it('fullTextSearch: $language', async () => { + await fullTextHelper(); + const query = new Parse.Query('TestObject'); + query.fullText('subject', 'leche', { language: 'spanish' }); + const resp = await query.find(); + expect(resp.length).toBe(2); }); - it('fullTextSearch: $diacriticSensitive', done => { - fullTextHelper() - .then(() => { - const where = { - subject: { - $text: { - $search: { - $term: 'CAFÉ', - $diacriticSensitive: true, - }, - }, - }, - }; - return request({ - method: 'POST', - url: 'http://localhost:8378/1/classes/TestObject', - body: { where, _method: 'GET' }, - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'test', - 'Content-Type': 'application/json', - }, - }); - }) - .then(resp => { - expect(resp.data.results.length).toBe(1); - done(); - }, done.fail); + it('fullTextSearch: $diacriticSensitive', async () => { + await fullTextHelper(); + const query = new Parse.Query('TestObject'); + query.fullText('subject', 'CAFÉ', { diacriticSensitive: true }); + const resp = await query.find(); + expect(resp.length).toBe(1); }); - it('fullTextSearch: $search, invalid input', done => { - fullTextHelper() - .then(() => { - const where = { - subject: { - $text: { - $search: true, - }, + it('fullTextSearch: $search, invalid input', async () => { + await fullTextHelper(); + const invalidQuery = async () => { + const where = { + subject: { + $text: { + $search: true, }, - }; - return request({ + }, + }; + try { + await request({ method: 'POST', url: 'http://localhost:8378/1/classes/TestObject', body: { where, _method: 'GET' }, @@ -216,185 +104,73 @@ describe('Parse.Query Full Text Search testing', () => { 'Content-Type': 'application/json', }, }); - }) - .then(resp => { - fail(`no request should succeed: ${JSON.stringify(resp)}`); - done(); - }) - .catch(err => { - expect(err.data.code).toEqual(Parse.Error.INVALID_JSON); - done(); - }); + } catch (e) { + throw new Parse.Error(e.data.code, e.data.error); + } + }; + await expectAsync(invalidQuery()).toBeRejectedWith( + new Parse.Error(Parse.Error.INVALID_JSON, 'bad $text: $search, should be object') + ); }); - it('fullTextSearch: $language, invalid input', done => { - fullTextHelper() - .then(() => { - const where = { - subject: { - $text: { - $search: { - $term: 'leche', - $language: true, - }, - }, - }, - }; - return request({ - method: 'POST', - url: 'http://localhost:8378/1/classes/TestObject', - body: { where, _method: 'GET' }, - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'test', - 'Content-Type': 'application/json', - }, - }); - }) - .then(resp => { - fail(`no request should succeed: ${JSON.stringify(resp)}`); - done(); - }) - .catch(err => { - expect(err.data.code).toEqual(Parse.Error.INVALID_JSON); - done(); - }); + it('fullTextSearch: $language, invalid input', async () => { + await fullTextHelper(); + const query = new Parse.Query('TestObject'); + query.fullText('subject', 'leche', { language: true }); + await expectAsync(query.find()).toBeRejectedWith( + new Parse.Error(Parse.Error.INVALID_JSON, 'bad $text: $language, should be string') + ); }); - it('fullTextSearch: $caseSensitive, invalid input', done => { - fullTextHelper() - .then(() => { - const where = { - subject: { - $text: { - $search: { - $term: 'Coffee', - $caseSensitive: 'string', - }, - }, - }, - }; - return request({ - method: 'POST', - url: 'http://localhost:8378/1/classes/TestObject', - body: { where, _method: 'GET' }, - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'test', - 'Content-Type': 'application/json', - }, - }); - }) - .then(resp => { - fail(`no request should succeed: ${JSON.stringify(resp)}`); - done(); - }) - .catch(err => { - expect(err.data.code).toEqual(Parse.Error.INVALID_JSON); - done(); - }); + it('fullTextSearch: $caseSensitive, invalid input', async () => { + await fullTextHelper(); + const query = new Parse.Query('TestObject'); + query.fullText('subject', 'leche', { caseSensitive: 'string' }); + await expectAsync(query.find()).toBeRejectedWith( + new Parse.Error(Parse.Error.INVALID_JSON, 'bad $text: $caseSensitive, should be boolean') + ); }); - it('fullTextSearch: $diacriticSensitive, invalid input', done => { - fullTextHelper() - .then(() => { - const where = { - subject: { - $text: { - $search: { - $term: 'CAFÉ', - $diacriticSensitive: 'string', - }, - }, - }, - }; - return request({ - method: 'POST', - url: 'http://localhost:8378/1/classes/TestObject', - body: { where, _method: 'GET' }, - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'test', - 'Content-Type': 'application/json', - }, - }); - }) - .then(resp => { - fail(`no request should succeed: ${JSON.stringify(resp)}`); - done(); - }) - .catch(err => { - expect(err.data.code).toEqual(Parse.Error.INVALID_JSON); - done(); - }); + it('fullTextSearch: $diacriticSensitive, invalid input', async () => { + await fullTextHelper(); + const query = new Parse.Query('TestObject'); + query.fullText('subject', 'leche', { diacriticSensitive: 'string' }); + await expectAsync(query.find()).toBeRejectedWith( + new Parse.Error(Parse.Error.INVALID_JSON, 'bad $text: $diacriticSensitive, should be boolean') + ); }); }); describe_only_db('mongo')('[mongodb] Parse.Query Full Text Search testing', () => { - it('fullTextSearch: does not create text index if compound index exist', done => { - fullTextHelper() - .then(() => { - return databaseAdapter.dropAllIndexes('TestObject'); - }) - .then(() => { - return databaseAdapter.getIndexes('TestObject'); - }) - .then(indexes => { - expect(indexes.length).toEqual(1); - return databaseAdapter.createIndex('TestObject', { - subject: 'text', - comment: 'text', - }); - }) - .then(() => { - return databaseAdapter.getIndexes('TestObject'); - }) - .then(indexes => { - expect(indexes.length).toEqual(2); - const where = { - subject: { - $text: { - $search: { - $term: 'coffee', - }, - }, - }, - }; - return request({ - method: 'POST', - url: 'http://localhost:8378/1/classes/TestObject', - body: { where, _method: 'GET' }, - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'test', - 'Content-Type': 'application/json', - }, - }); - }) - .then(resp => { - expect(resp.data.results.length).toEqual(3); - return databaseAdapter.getIndexes('TestObject'); - }) - .then(indexes => { - expect(indexes.length).toEqual(2); - request({ - url: 'http://localhost:8378/1/schemas/TestObject', - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-Master-Key': 'test', - 'Content-Type': 'application/json', - }, - }).then(response => { - const body = response.data; - expect(body.indexes._id_).toBeDefined(); - expect(body.indexes._id_._id).toEqual(1); - expect(body.indexes.subject_text_comment_text).toBeDefined(); - expect(body.indexes.subject_text_comment_text.subject).toEqual('text'); - expect(body.indexes.subject_text_comment_text.comment).toEqual('text'); - done(); - }); - }) - .catch(done.fail); + it('fullTextSearch: does not create text index if compound index exist', async () => { + await fullTextHelper(); + await databaseAdapter.dropAllIndexes('TestObject'); + let indexes = await databaseAdapter.getIndexes('TestObject'); + expect(indexes.length).toEqual(1); + await databaseAdapter.createIndex('TestObject', { + subject: 'text', + comment: 'text', + }); + indexes = await databaseAdapter.getIndexes('TestObject'); + const query = new Parse.Query('TestObject'); + query.fullText('subject', 'coffee'); + query.select('$score'); + query.ascending('$score'); + const results = await query.find(); + expect(results.length).toBe(3); + expect(results[0].get('score')); + expect(results[1].get('score')); + expect(results[2].get('score')); + + indexes = await databaseAdapter.getIndexes('TestObject'); + expect(indexes.length).toEqual(2); + + const schemas = await new Parse.Schema('TestObject').get(); + expect(schemas.indexes._id_).toBeDefined(); + expect(schemas.indexes._id_._id).toEqual(1); + expect(schemas.indexes.subject_text_comment_text).toBeDefined(); + expect(schemas.indexes.subject_text_comment_text.subject).toEqual('text'); + expect(schemas.indexes.subject_text_comment_text.comment).toEqual('text'); }); it('fullTextSearch: does not create text index if schema compound index exist', done => { From a0a2a7f2908ec5e09eeaa607808646ef12a5574d Mon Sep 17 00:00:00 2001 From: dblythy Date: Wed, 15 Sep 2021 11:31:46 +1000 Subject: [PATCH 14/16] Update ParseQuery.FullTextSearch.spec.js --- spec/ParseQuery.FullTextSearch.spec.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spec/ParseQuery.FullTextSearch.spec.js b/spec/ParseQuery.FullTextSearch.spec.js index 24e7bd79e2..5aefbe2348 100644 --- a/spec/ParseQuery.FullTextSearch.spec.js +++ b/spec/ParseQuery.FullTextSearch.spec.js @@ -29,7 +29,7 @@ const fullTextHelper = async () => { ); }; -describe('Parse.Query Full Text Search testing', () => { +fdescribe('Parse.Query Full Text Search testing', () => { it('fullTextSearch: $search', async () => { await fullTextHelper(); const query = new Parse.Query('TestObject'); @@ -64,7 +64,8 @@ describe('Parse.Query Full Text Search testing', () => { expect(first.get('score')); expect(second.get('score')); expect(third.get('score')); - expect(first.get('score') > second.get('score') > third.get('score')).toBeTrue(); + expect(first.get('score') >= second.get('score')).toBeTrue(); + expect(second.get('score') >= third.get('score')).toBeTrue(); }); it('fullTextSearch: $language', async () => { From bfba08bdcfed25b9d7ed10ad12630ae422a42c18 Mon Sep 17 00:00:00 2001 From: dblythy Date: Wed, 15 Sep 2021 11:37:21 +1000 Subject: [PATCH 15/16] Update ParseQuery.FullTextSearch.spec.js --- spec/ParseQuery.FullTextSearch.spec.js | 68 +++++--------------------- 1 file changed, 12 insertions(+), 56 deletions(-) diff --git a/spec/ParseQuery.FullTextSearch.spec.js b/spec/ParseQuery.FullTextSearch.spec.js index 5aefbe2348..cfbabba710 100644 --- a/spec/ParseQuery.FullTextSearch.spec.js +++ b/spec/ParseQuery.FullTextSearch.spec.js @@ -251,64 +251,20 @@ describe_only_db('mongo')('[mongodb] Parse.Query Full Text Search testing', () = .catch(done.fail); }); - it('fullTextSearch: $diacriticSensitive - false', done => { - fullTextHelper() - .then(() => { - const where = { - subject: { - $text: { - $search: { - $term: 'CAFÉ', - $diacriticSensitive: false, - }, - }, - }, - }; - return request({ - method: 'POST', - url: 'http://localhost:8378/1/classes/TestObject', - body: { where, _method: 'GET' }, - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'test', - 'Content-Type': 'application/json', - }, - }); - }) - .then(resp => { - expect(resp.data.results.length).toBe(2); - done(); - }, done.fail); + it('fullTextSearch: $diacriticSensitive - false', async () => { + await fullTextHelper(); + const query = new Parse.Query('TestObject'); + query.fullText('subject', 'CAFÉ', { diacriticSensitive: false }); + const resp = await query.find(); + expect(resp.length).toBe(2); }); - it('fullTextSearch: $caseSensitive', done => { - fullTextHelper() - .then(() => { - const where = { - subject: { - $text: { - $search: { - $term: 'Coffee', - $caseSensitive: true, - }, - }, - }, - }; - return request({ - method: 'POST', - url: 'http://localhost:8378/1/classes/TestObject', - body: { where, _method: 'GET' }, - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'test', - 'Content-Type': 'application/json', - }, - }); - }) - .then(resp => { - expect(resp.data.results.length).toBe(1); - done(); - }, done.fail); + it('fullTextSearch: $caseSensitive', async () => { + await fullTextHelper(); + const query = new Parse.Query('TestObject'); + query.fullText('subject', 'Coffee', { caseSensitive: true }); + const results = await query.find(); + expect(results.length).toBe(1); }); }); From 545e3c103e6be7f88d36686f1e689aa1a511f4fe Mon Sep 17 00:00:00 2001 From: dblythy Date: Wed, 15 Sep 2021 11:37:47 +1000 Subject: [PATCH 16/16] Update ParseQuery.FullTextSearch.spec.js --- spec/ParseQuery.FullTextSearch.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/ParseQuery.FullTextSearch.spec.js b/spec/ParseQuery.FullTextSearch.spec.js index cfbabba710..e6614e5d81 100644 --- a/spec/ParseQuery.FullTextSearch.spec.js +++ b/spec/ParseQuery.FullTextSearch.spec.js @@ -29,7 +29,7 @@ const fullTextHelper = async () => { ); }; -fdescribe('Parse.Query Full Text Search testing', () => { +describe('Parse.Query Full Text Search testing', () => { it('fullTextSearch: $search', async () => { await fullTextHelper(); const query = new Parse.Query('TestObject');