diff --git a/package-lock.json b/package-lock.json index e5f3dc6d35..0c626adea2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9451,9 +9451,9 @@ "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==" }, "mongodb": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.2.tgz", - "integrity": "sha512-sSZOb04w3HcnrrXC82NEh/YGCmBuRgR+C1hZgmmv4L6dBz4BkRse6Y8/q/neXer9i95fKUBbFi4KgeceXmbsOA==", + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.3.tgz", + "integrity": "sha512-rOZuR0QkodZiM+UbQE5kDsJykBqWi0CL4Ec2i1nrGrUI3KO11r6Fbxskqmq3JK2NH7aW4dcccBuUujAP0ERl5w==", "requires": { "bl": "^2.2.1", "bson": "^1.1.4", diff --git a/package.json b/package.json index 4907a417e6..24bbaab042 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "lodash": "4.17.20", "lru-cache": "5.1.1", "mime": "2.4.6", - "mongodb": "3.6.2", + "mongodb": "3.6.3", "parse": "2.18.0", "pg-promise": "10.8.1", "pluralize": "8.0.0", diff --git a/spec/ReadPreferenceOption.spec.js b/spec/ReadPreferenceOption.spec.js index 4328201f1f..d78aa92de9 100644 --- a/spec/ReadPreferenceOption.spec.js +++ b/spec/ReadPreferenceOption.spec.js @@ -5,6 +5,12 @@ const ReadPreference = require('mongodb').ReadPreference; const request = require('../lib/request'); const Config = require('../lib/Config'); +function waitForReplication() { + return new Promise(function (resolve) { + setTimeout(resolve, 300); + }); +} + describe_only_db('mongo')('Read preference option', () => { it('should find in primary by default', done => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; @@ -40,7 +46,7 @@ describe_only_db('mongo')('Read preference option', () => { .catch(done.fail); }); - it('should preserve the read preference set (#4831)', async () => { + xit('should preserve the read preference set (#4831)', async () => { const { MongoStorageAdapter } = require('../lib/Adapters/Storage/Mongo/MongoStorageAdapter'); const adapterOptions = { uri: 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase', @@ -80,7 +86,7 @@ describe_only_db('mongo')('Read preference option', () => { expect(myObjectReadPreference).toBe(true); }); - it('should change read preference in the beforeFind trigger', done => { + it('should change read preference in the beforeFind trigger', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject'); @@ -88,38 +94,32 @@ describe_only_db('mongo')('Read preference option', () => { const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); - Parse.Object.saveAll([obj0, obj1]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - Parse.Cloud.beforeFind('MyObject', req => { - req.readPreference = 'SECONDARY'; - }); - - const query = new Parse.Query('MyObject'); - query.equalTo('boolKey', false); + await Parse.Object.saveAll([obj0, obj1]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - query - .find() - .then(results => { - expect(results.length).toBe(1); - expect(results[0].get('boolKey')).toBe(false); + Parse.Cloud.beforeFind('MyObject', req => { + req.readPreference = 'SECONDARY'; + }); + await waitForReplication(); - let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; - } - }); + const query = new Parse.Query('MyObject'); + query.equalTo('boolKey', false); - expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); + const results = await query.find(); + expect(results.length).toBe(1); + expect(results[0].get('boolKey')).toBe(false); - done(); - }) - .catch(done.fail); + let myObjectReadPreference = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); }); - it('should check read preference as case insensitive', done => { + it('should check read preference as case insensitive', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject'); @@ -127,38 +127,33 @@ describe_only_db('mongo')('Read preference option', () => { const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); - Parse.Object.saveAll([obj0, obj1]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - Parse.Cloud.beforeFind('MyObject', req => { - req.readPreference = 'sEcOnDarY'; - }); + await Parse.Object.saveAll([obj0, obj1]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - const query = new Parse.Query('MyObject'); - query.equalTo('boolKey', false); + Parse.Cloud.beforeFind('MyObject', req => { + req.readPreference = 'sEcOnDarY'; + }); - query - .find() - .then(results => { - expect(results.length).toBe(1); - expect(results[0].get('boolKey')).toBe(false); + await waitForReplication(); - let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; - } - }); + const query = new Parse.Query('MyObject'); + query.equalTo('boolKey', false); - expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); + const results = await query.find(); + expect(results.length).toBe(1); + expect(results[0].get('boolKey')).toBe(false); - done(); - }) - .catch(done.fail); + let myObjectReadPreference = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); }); - it('should change read preference in the beforeFind trigger even changing query', done => { + it('should change read preference in the beforeFind trigger even changing query', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject'); @@ -166,39 +161,33 @@ describe_only_db('mongo')('Read preference option', () => { const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); - Parse.Object.saveAll([obj0, obj1]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - Parse.Cloud.beforeFind('MyObject', req => { - req.query.equalTo('boolKey', true); - req.readPreference = 'SECONDARY'; - }); - - const query = new Parse.Query('MyObject'); - query.equalTo('boolKey', false); + await Parse.Object.saveAll([obj0, obj1]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - query - .find() - .then(results => { - expect(results.length).toBe(1); - expect(results[0].get('boolKey')).toBe(true); + Parse.Cloud.beforeFind('MyObject', req => { + req.query.equalTo('boolKey', true); + req.readPreference = 'SECONDARY'; + }); + await waitForReplication(); - let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; - } - }); + const query = new Parse.Query('MyObject'); + query.equalTo('boolKey', false); - expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); + const results = await query.find(); + expect(results.length).toBe(1); + expect(results[0].get('boolKey')).toBe(true); - done(); - }) - .catch(done.fail); + let myObjectReadPreference = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); }); - it('should change read preference in the beforeFind trigger even returning query', done => { + it('should change read preference in the beforeFind trigger even returning query', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject'); @@ -206,42 +195,37 @@ describe_only_db('mongo')('Read preference option', () => { const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); - Parse.Object.saveAll([obj0, obj1]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - Parse.Cloud.beforeFind('MyObject', req => { - req.readPreference = 'SECONDARY'; + await Parse.Object.saveAll([obj0, obj1]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - const otherQuery = new Parse.Query('MyObject'); - otherQuery.equalTo('boolKey', true); - return otherQuery; - }); + Parse.Cloud.beforeFind('MyObject', req => { + req.readPreference = 'SECONDARY'; - const query = new Parse.Query('MyObject'); - query.equalTo('boolKey', false); + const otherQuery = new Parse.Query('MyObject'); + otherQuery.equalTo('boolKey', true); + return otherQuery; + }); - query - .find() - .then(results => { - expect(results.length).toBe(1); - expect(results[0].get('boolKey')).toBe(true); + await waitForReplication(); - let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; - } - }); + const query = new Parse.Query('MyObject'); + query.equalTo('boolKey', false); - expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); + const results = await query.find(); + expect(results.length).toBe(1); + expect(results[0].get('boolKey')).toBe(true); - done(); - }) - .catch(done.fail); + let myObjectReadPreference = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); }); - it('should change read preference in the beforeFind trigger even returning promise', done => { + it('should change read preference in the beforeFind trigger even returning promise', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject'); @@ -249,42 +233,36 @@ describe_only_db('mongo')('Read preference option', () => { const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); - Parse.Object.saveAll([obj0, obj1]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - Parse.Cloud.beforeFind('MyObject', req => { - req.readPreference = 'SECONDARY'; - - const otherQuery = new Parse.Query('MyObject'); - otherQuery.equalTo('boolKey', true); - return Promise.resolve(otherQuery); - }); + await Parse.Object.saveAll([obj0, obj1]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - const query = new Parse.Query('MyObject'); - query.equalTo('boolKey', false); + Parse.Cloud.beforeFind('MyObject', req => { + req.readPreference = 'SECONDARY'; - query - .find() - .then(results => { - expect(results.length).toBe(1); - expect(results[0].get('boolKey')).toBe(true); + const otherQuery = new Parse.Query('MyObject'); + otherQuery.equalTo('boolKey', true); + return Promise.resolve(otherQuery); + }); + await waitForReplication(); - let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; - } - }); + const query = new Parse.Query('MyObject'); + query.equalTo('boolKey', false); - expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); + const results = await query.find(); + expect(results.length).toBe(1); + expect(results[0].get('boolKey')).toBe(true); - done(); - }) - .catch(done.fail); + let myObjectReadPreference = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); }); - it('should change read preference to PRIMARY_PREFERRED', done => { + it('should change read preference to PRIMARY_PREFERRED', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject'); @@ -292,38 +270,32 @@ describe_only_db('mongo')('Read preference option', () => { const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); - Parse.Object.saveAll([obj0, obj1]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - Parse.Cloud.beforeFind('MyObject', req => { - req.readPreference = 'PRIMARY_PREFERRED'; - }); - - const query = new Parse.Query('MyObject'); - query.equalTo('boolKey', false); + await Parse.Object.saveAll([obj0, obj1]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - query - .find() - .then(results => { - expect(results.length).toBe(1); - expect(results[0].get('boolKey')).toBe(false); + Parse.Cloud.beforeFind('MyObject', req => { + req.readPreference = 'PRIMARY_PREFERRED'; + }); + await waitForReplication(); - let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; - } - }); + const query = new Parse.Query('MyObject'); + query.equalTo('boolKey', false); - expect(myObjectReadPreference).toEqual(ReadPreference.PRIMARY_PREFERRED); + const results = await query.find(); + expect(results.length).toBe(1); + expect(results[0].get('boolKey')).toBe(false); - done(); - }) - .catch(done.fail); + let myObjectReadPreference = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference).toEqual(ReadPreference.PRIMARY_PREFERRED); }); - it('should change read preference to SECONDARY_PREFERRED', done => { + it('should change read preference to SECONDARY_PREFERRED', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject'); @@ -331,38 +303,32 @@ describe_only_db('mongo')('Read preference option', () => { const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); - Parse.Object.saveAll([obj0, obj1]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - Parse.Cloud.beforeFind('MyObject', req => { - req.readPreference = 'SECONDARY_PREFERRED'; - }); - - const query = new Parse.Query('MyObject'); - query.equalTo('boolKey', false); + await Parse.Object.saveAll([obj0, obj1]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - query - .find() - .then(results => { - expect(results.length).toBe(1); - expect(results[0].get('boolKey')).toBe(false); + Parse.Cloud.beforeFind('MyObject', req => { + req.readPreference = 'SECONDARY_PREFERRED'; + }); + await waitForReplication(); - let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; - } - }); + const query = new Parse.Query('MyObject'); + query.equalTo('boolKey', false); - expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY_PREFERRED); + const results = await query.find(); + expect(results.length).toBe(1); + expect(results[0].get('boolKey')).toBe(false); - done(); - }) - .catch(done.fail); + let myObjectReadPreference = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY_PREFERRED); }); - it('should change read preference to NEAREST', done => { + it('should change read preference to NEAREST', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject'); @@ -370,38 +336,32 @@ describe_only_db('mongo')('Read preference option', () => { const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); - Parse.Object.saveAll([obj0, obj1]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - Parse.Cloud.beforeFind('MyObject', req => { - req.readPreference = 'NEAREST'; - }); - - const query = new Parse.Query('MyObject'); - query.equalTo('boolKey', false); + await Parse.Object.saveAll([obj0, obj1]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - query - .find() - .then(results => { - expect(results.length).toBe(1); - expect(results[0].get('boolKey')).toBe(false); + Parse.Cloud.beforeFind('MyObject', req => { + req.readPreference = 'NEAREST'; + }); + await waitForReplication(); - let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; - } - }); + const query = new Parse.Query('MyObject'); + query.equalTo('boolKey', false); - expect(myObjectReadPreference).toEqual(ReadPreference.NEAREST); + const results = await query.find(); + expect(results.length).toBe(1); + expect(results[0].get('boolKey')).toBe(false); - done(); - }) - .catch(done.fail); + let myObjectReadPreference = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference).toEqual(ReadPreference.NEAREST); }); - it('should change read preference for GET', done => { + it('should change read preference for GET', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject'); @@ -409,36 +369,30 @@ describe_only_db('mongo')('Read preference option', () => { const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); - Parse.Object.saveAll([obj0, obj1]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - Parse.Cloud.beforeFind('MyObject', req => { - req.readPreference = 'SECONDARY'; - }); - - const query = new Parse.Query('MyObject'); + await Parse.Object.saveAll([obj0, obj1]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - query - .get(obj0.id) - .then(result => { - expect(result.get('boolKey')).toBe(false); + Parse.Cloud.beforeFind('MyObject', req => { + req.readPreference = 'SECONDARY'; + }); + await waitForReplication(); - let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; - } - }); + const query = new Parse.Query('MyObject'); - expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); + const result = await query.get(obj0.id); + expect(result.get('boolKey')).toBe(false); - done(); - }) - .catch(done.fail); + let myObjectReadPreference = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); }); - it('should change read preference for GET using API', done => { + it('should change read preference for GET using API', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject'); @@ -446,42 +400,37 @@ describe_only_db('mongo')('Read preference option', () => { const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); - Parse.Object.saveAll([obj0, obj1]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - Parse.Cloud.beforeFind('MyObject', req => { - req.readPreference = 'SECONDARY'; - }); - - request({ - method: 'GET', - url: 'http://localhost:8378/1/classes/MyObject/' + obj0.id, - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'rest', - }, - json: true, - }) - .then(response => { - const body = response.data; - expect(body.boolKey).toBe(false); - - let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; - } - }); + await Parse.Object.saveAll([obj0, obj1]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); + Parse.Cloud.beforeFind('MyObject', req => { + req.readPreference = 'SECONDARY'; + }); + await waitForReplication(); + + const response = await request({ + method: 'GET', + url: 'http://localhost:8378/1/classes/MyObject/' + obj0.id, + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }, + json: true, + }); + const body = response.data; + expect(body.boolKey).toBe(false); - done(); - }) - .catch(done.fail); + let myObjectReadPreference = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); }); - it('should change read preference for GET directly from API', done => { + it('should change read preference for GET directly from API', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject'); @@ -489,37 +438,32 @@ describe_only_db('mongo')('Read preference option', () => { const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); - Parse.Object.saveAll([obj0, obj1]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - request({ - method: 'GET', - url: 'http://localhost:8378/1/classes/MyObject/' + obj0.id + '?readPreference=SECONDARY', - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'rest', - }, - json: true, - }) - .then(response => { - expect(response.data.boolKey).toBe(false); - - let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; - } - }); - - expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); + await Parse.Object.saveAll([obj0, obj1]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + await waitForReplication(); + + const response = await request({ + method: 'GET', + url: 'http://localhost:8378/1/classes/MyObject/' + obj0.id + '?readPreference=SECONDARY', + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }, + json: true, + }); + expect(response.data.boolKey).toBe(false); - done(); - }) - .catch(done.fail); + let myObjectReadPreference = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); }); - it('should change read preference for GET using API through the beforeFind overriding API option', done => { + it('should change read preference for GET using API through the beforeFind overriding API option', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject'); @@ -527,41 +471,36 @@ describe_only_db('mongo')('Read preference option', () => { const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); - Parse.Object.saveAll([obj0, obj1]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - Parse.Cloud.beforeFind('MyObject', req => { - req.readPreference = 'SECONDARY_PREFERRED'; - }); - - request({ - method: 'GET', - url: 'http://localhost:8378/1/classes/MyObject/' + obj0.id + '?readPreference=SECONDARY', - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'rest', - }, - json: true, - }) - .then(response => { - expect(response.data.boolKey).toBe(false); - - let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; - } - }); + await Parse.Object.saveAll([obj0, obj1]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY_PREFERRED); + Parse.Cloud.beforeFind('MyObject', req => { + req.readPreference = 'SECONDARY_PREFERRED'; + }); + await waitForReplication(); + + const response = await request({ + method: 'GET', + url: 'http://localhost:8378/1/classes/MyObject/' + obj0.id + '?readPreference=SECONDARY', + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }, + json: true, + }); + expect(response.data.boolKey).toBe(false); - done(); - }) - .catch(done.fail); + let myObjectReadPreference = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY_PREFERRED); }); - it('should change read preference for FIND using API through beforeFind trigger', done => { + it('should change read preference for FIND using API through beforeFind trigger', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject'); @@ -569,41 +508,36 @@ describe_only_db('mongo')('Read preference option', () => { const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); - Parse.Object.saveAll([obj0, obj1]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - Parse.Cloud.beforeFind('MyObject', req => { - req.readPreference = 'SECONDARY'; - }); - - request({ - method: 'GET', - url: 'http://localhost:8378/1/classes/MyObject/', - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'rest', - }, - json: true, - }) - .then(response => { - expect(response.data.results.length).toEqual(2); - - let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; - } - }); + await Parse.Object.saveAll([obj0, obj1]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); + Parse.Cloud.beforeFind('MyObject', req => { + req.readPreference = 'SECONDARY'; + }); + await waitForReplication(); + + const response = await request({ + method: 'GET', + url: 'http://localhost:8378/1/classes/MyObject/', + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }, + json: true, + }); + expect(response.data.results.length).toEqual(2); - done(); - }) - .catch(done.fail); + let myObjectReadPreference = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); }); - it('should change read preference for FIND directly from API', done => { + it('should change read preference for FIND directly from API', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject'); @@ -611,37 +545,32 @@ describe_only_db('mongo')('Read preference option', () => { const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); - Parse.Object.saveAll([obj0, obj1]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - request({ - method: 'GET', - url: 'http://localhost:8378/1/classes/MyObject?readPreference=SECONDARY', - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'rest', - }, - json: true, - }) - .then(response => { - expect(response.data.results.length).toEqual(2); - - let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; - } - }); - - expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); + await Parse.Object.saveAll([obj0, obj1]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + await waitForReplication(); + + const response = await request({ + method: 'GET', + url: 'http://localhost:8378/1/classes/MyObject?readPreference=SECONDARY', + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }, + json: true, + }); + expect(response.data.results.length).toEqual(2); - done(); - }) - .catch(done.fail); + let myObjectReadPreference = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); }); - it('should change read preference for FIND using API through the beforeFind overriding API option', done => { + it('should change read preference for FIND using API through the beforeFind overriding API option', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject'); @@ -649,38 +578,33 @@ describe_only_db('mongo')('Read preference option', () => { const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); - Parse.Object.saveAll([obj0, obj1]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - Parse.Cloud.beforeFind('MyObject', req => { - req.readPreference = 'SECONDARY_PREFERRED'; - }); - - request({ - method: 'GET', - url: 'http://localhost:8378/1/classes/MyObject/?readPreference=SECONDARY', - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'rest', - }, - json: true, - }) - .then(response => { - expect(response.data.results.length).toEqual(2); - - let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; - } - }); + await Parse.Object.saveAll([obj0, obj1]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY_PREFERRED); + Parse.Cloud.beforeFind('MyObject', req => { + req.readPreference = 'SECONDARY_PREFERRED'; + }); + await waitForReplication(); + + const response = await request({ + method: 'GET', + url: 'http://localhost:8378/1/classes/MyObject/?readPreference=SECONDARY', + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }, + json: true, + }); + expect(response.data.results.length).toEqual(2); - done(); - }) - .catch(done.fail); + let myObjectReadPreference = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY_PREFERRED); }); xit('should change read preference for count', done => { @@ -732,6 +656,8 @@ describe_only_db('mongo')('Read preference option', () => { Parse.Cloud.beforeFind('MyObject', req => { req.readPreference = 'SECONDARY'; }); + await waitForReplication(); + // Spy on DB adapter const databaseAdapter = Config.get(Parse.applicationId).database.adapter; spyOn(databaseAdapter.database.serverConfig, 'startSession').and.callThrough(); @@ -756,6 +682,8 @@ describe_only_db('mongo')('Read preference option', () => { const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); await Parse.Object.saveAll([obj0, obj1]); + await waitForReplication(); + // Spy on DB adapter const databaseAdapter = Config.get(Parse.applicationId).database.adapter; spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); @@ -782,6 +710,8 @@ describe_only_db('mongo')('Read preference option', () => { const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); await Parse.Object.saveAll([obj0, obj1]); + await waitForReplication(); + // Spy on DB adapter const databaseAdapter = Config.get(Parse.applicationId).database.adapter; spyOn(databaseAdapter.database.serverConfig, 'startSession').and.callThrough(); @@ -800,7 +730,7 @@ describe_only_db('mongo')('Read preference option', () => { expect(readPreference).toEqual(ReadPreference.SECONDARY); }); - it('should find includes in same replica of readPreference by default', done => { + it('should find includes in same replica of readPreference by default', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject0'); @@ -812,53 +742,47 @@ describe_only_db('mongo')('Read preference option', () => { obj2.set('boolKey', false); obj2.set('myObject1', obj1); - Parse.Object.saveAll([obj0, obj1, obj2]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - Parse.Cloud.beforeFind('MyObject2', req => { - req.readPreference = 'SECONDARY'; - }); - - const query = new Parse.Query('MyObject2'); - query.equalTo('boolKey', false); - query.include('myObject1'); - query.include('myObject1.myObject0'); + await Parse.Object.saveAll([obj0, obj1, obj2]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - query - .find() - .then(results => { - expect(results.length).toBe(1); - const firstResult = results[0]; - expect(firstResult.get('boolKey')).toBe(false); - expect(firstResult.get('myObject1').get('boolKey')).toBe(true); - expect(firstResult.get('myObject1').get('myObject0').get('boolKey')).toBe(false); - - let myObjectReadPreference0 = null; - let myObjectReadPreference1 = null; - let myObjectReadPreference2 = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { - myObjectReadPreference0 = call.args[0].options.readPreference.mode; - } - if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { - myObjectReadPreference1 = call.args[0].options.readPreference.mode; - } - if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { - myObjectReadPreference2 = call.args[0].options.readPreference.mode; - } - }); + Parse.Cloud.beforeFind('MyObject2', req => { + req.readPreference = 'SECONDARY'; + }); + await waitForReplication(); - expect(myObjectReadPreference0).toEqual(ReadPreference.SECONDARY); - expect(myObjectReadPreference1).toEqual(ReadPreference.SECONDARY); - expect(myObjectReadPreference2).toEqual(ReadPreference.SECONDARY); + const query = new Parse.Query('MyObject2'); + query.equalTo('boolKey', false); + query.include('myObject1'); + query.include('myObject1.myObject0'); - done(); - }) - .catch(done.fail); + const results = await query.find(); + expect(results.length).toBe(1); + const firstResult = results[0]; + expect(firstResult.get('boolKey')).toBe(false); + expect(firstResult.get('myObject1').get('boolKey')).toBe(true); + expect(firstResult.get('myObject1').get('myObject0').get('boolKey')).toBe(false); + + let myObjectReadPreference0 = null; + let myObjectReadPreference1 = null; + let myObjectReadPreference2 = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { + myObjectReadPreference0 = call.args[0].options.readPreference.mode; + } + if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { + myObjectReadPreference1 = call.args[0].options.readPreference.mode; + } + if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { + myObjectReadPreference2 = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference0).toEqual(ReadPreference.SECONDARY); + expect(myObjectReadPreference1).toEqual(ReadPreference.SECONDARY); + expect(myObjectReadPreference2).toEqual(ReadPreference.SECONDARY); }); - it('should change includes read preference', done => { + it('should change includes read preference', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject0'); @@ -870,54 +794,48 @@ describe_only_db('mongo')('Read preference option', () => { obj2.set('boolKey', false); obj2.set('myObject1', obj1); - Parse.Object.saveAll([obj0, obj1, obj2]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - Parse.Cloud.beforeFind('MyObject2', req => { - req.readPreference = 'SECONDARY_PREFERRED'; - req.includeReadPreference = 'SECONDARY'; - }); - - const query = new Parse.Query('MyObject2'); - query.equalTo('boolKey', false); - query.include('myObject1'); - query.include('myObject1.myObject0'); + await Parse.Object.saveAll([obj0, obj1, obj2]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - query - .find() - .then(results => { - expect(results.length).toBe(1); - const firstResult = results[0]; - expect(firstResult.get('boolKey')).toBe(false); - expect(firstResult.get('myObject1').get('boolKey')).toBe(true); - expect(firstResult.get('myObject1').get('myObject0').get('boolKey')).toBe(false); - - let myObjectReadPreference0 = null; - let myObjectReadPreference1 = null; - let myObjectReadPreference2 = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { - myObjectReadPreference0 = call.args[0].options.readPreference.mode; - } - if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { - myObjectReadPreference1 = call.args[0].options.readPreference.mode; - } - if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { - myObjectReadPreference2 = call.args[0].options.readPreference.mode; - } - }); + Parse.Cloud.beforeFind('MyObject2', req => { + req.readPreference = 'SECONDARY_PREFERRED'; + req.includeReadPreference = 'SECONDARY'; + }); + await waitForReplication(); - expect(myObjectReadPreference0).toEqual(ReadPreference.SECONDARY); - expect(myObjectReadPreference1).toEqual(ReadPreference.SECONDARY); - expect(myObjectReadPreference2).toEqual(ReadPreference.SECONDARY_PREFERRED); + const query = new Parse.Query('MyObject2'); + query.equalTo('boolKey', false); + query.include('myObject1'); + query.include('myObject1.myObject0'); - done(); - }) - .catch(done.fail); + const results = await query.find(); + expect(results.length).toBe(1); + const firstResult = results[0]; + expect(firstResult.get('boolKey')).toBe(false); + expect(firstResult.get('myObject1').get('boolKey')).toBe(true); + expect(firstResult.get('myObject1').get('myObject0').get('boolKey')).toBe(false); + + let myObjectReadPreference0 = null; + let myObjectReadPreference1 = null; + let myObjectReadPreference2 = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { + myObjectReadPreference0 = call.args[0].options.readPreference.mode; + } + if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { + myObjectReadPreference1 = call.args[0].options.readPreference.mode; + } + if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { + myObjectReadPreference2 = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference0).toEqual(ReadPreference.SECONDARY); + expect(myObjectReadPreference1).toEqual(ReadPreference.SECONDARY); + expect(myObjectReadPreference2).toEqual(ReadPreference.SECONDARY_PREFERRED); }); - it('should change includes read preference when finding through API', done => { + it('should change includes read preference when finding through API', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject0'); @@ -929,55 +847,50 @@ describe_only_db('mongo')('Read preference option', () => { obj2.set('boolKey', false); obj2.set('myObject1', obj1); - Parse.Object.saveAll([obj0, obj1, obj2]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - request({ - method: 'GET', - url: - 'http://localhost:8378/1/classes/MyObject2/' + - obj2.id + - '?include=' + - JSON.stringify(['myObject1', 'myObject1.myObject0']) + - '&readPreference=SECONDARY_PREFERRED&includeReadPreference=SECONDARY', - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'rest', - }, - json: true, - }) - .then(response => { - const firstResult = response.data; - expect(firstResult.boolKey).toBe(false); - expect(firstResult.myObject1.boolKey).toBe(true); - expect(firstResult.myObject1.myObject0.boolKey).toBe(false); - - let myObjectReadPreference0 = null; - let myObjectReadPreference1 = null; - let myObjectReadPreference2 = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { - myObjectReadPreference0 = call.args[0].options.readPreference.mode; - } - if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { - myObjectReadPreference1 = call.args[0].options.readPreference.mode; - } - if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { - myObjectReadPreference2 = call.args[0].options.readPreference.mode; - } - }); - - expect(myObjectReadPreference0).toEqual(ReadPreference.SECONDARY); - expect(myObjectReadPreference1).toEqual(ReadPreference.SECONDARY); - expect(myObjectReadPreference2).toEqual(ReadPreference.SECONDARY_PREFERRED); - - done(); - }) - .catch(done.fail); + await Parse.Object.saveAll([obj0, obj1, obj2]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + await waitForReplication(); + + const response = await request({ + method: 'GET', + url: + 'http://localhost:8378/1/classes/MyObject2/' + + obj2.id + + '?include=' + + JSON.stringify(['myObject1', 'myObject1.myObject0']) + + '&readPreference=SECONDARY_PREFERRED&includeReadPreference=SECONDARY', + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }, + json: true, + }); + const firstResult = response.data; + expect(firstResult.boolKey).toBe(false); + expect(firstResult.myObject1.boolKey).toBe(true); + expect(firstResult.myObject1.myObject0.boolKey).toBe(false); + + let myObjectReadPreference0 = null; + let myObjectReadPreference1 = null; + let myObjectReadPreference2 = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { + myObjectReadPreference0 = call.args[0].options.readPreference.mode; + } + if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { + myObjectReadPreference1 = call.args[0].options.readPreference.mode; + } + if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { + myObjectReadPreference2 = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference0).toEqual(ReadPreference.SECONDARY); + expect(myObjectReadPreference1).toEqual(ReadPreference.SECONDARY); + expect(myObjectReadPreference2).toEqual(ReadPreference.SECONDARY_PREFERRED); }); - it('should change includes read preference when getting through API', done => { + it('should change includes read preference when getting through API', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject0'); @@ -989,56 +902,51 @@ describe_only_db('mongo')('Read preference option', () => { obj2.set('boolKey', false); obj2.set('myObject1', obj1); - Parse.Object.saveAll([obj0, obj1, obj2]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - request({ - method: 'GET', - url: - 'http://localhost:8378/1/classes/MyObject2?where=' + - JSON.stringify({ boolKey: false }) + - '&include=' + - JSON.stringify(['myObject1', 'myObject1.myObject0']) + - '&readPreference=SECONDARY_PREFERRED&includeReadPreference=SECONDARY', - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'rest', - }, - json: true, - }) - .then(response => { - expect(response.data.results.length).toBe(1); - const firstResult = response.data.results[0]; - expect(firstResult.boolKey).toBe(false); - expect(firstResult.myObject1.boolKey).toBe(true); - expect(firstResult.myObject1.myObject0.boolKey).toBe(false); - - let myObjectReadPreference0 = null; - let myObjectReadPreference1 = null; - let myObjectReadPreference2 = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { - myObjectReadPreference0 = call.args[0].options.readPreference.mode; - } - if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { - myObjectReadPreference1 = call.args[0].options.readPreference.mode; - } - if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { - myObjectReadPreference2 = call.args[0].options.readPreference.mode; - } - }); - - expect(myObjectReadPreference0).toEqual(ReadPreference.SECONDARY); - expect(myObjectReadPreference1).toEqual(ReadPreference.SECONDARY); - expect(myObjectReadPreference2).toEqual(ReadPreference.SECONDARY_PREFERRED); - - done(); - }) - .catch(done.fail); + await Parse.Object.saveAll([obj0, obj1, obj2]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + await waitForReplication(); + + const response = await request({ + method: 'GET', + url: + 'http://localhost:8378/1/classes/MyObject2?where=' + + JSON.stringify({ boolKey: false }) + + '&include=' + + JSON.stringify(['myObject1', 'myObject1.myObject0']) + + '&readPreference=SECONDARY_PREFERRED&includeReadPreference=SECONDARY', + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }, + json: true, + }); + expect(response.data.results.length).toBe(1); + const firstResult = response.data.results[0]; + expect(firstResult.boolKey).toBe(false); + expect(firstResult.myObject1.boolKey).toBe(true); + expect(firstResult.myObject1.myObject0.boolKey).toBe(false); + + let myObjectReadPreference0 = null; + let myObjectReadPreference1 = null; + let myObjectReadPreference2 = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { + myObjectReadPreference0 = call.args[0].options.readPreference.mode; + } + if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { + myObjectReadPreference1 = call.args[0].options.readPreference.mode; + } + if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { + myObjectReadPreference2 = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference0).toEqual(ReadPreference.SECONDARY); + expect(myObjectReadPreference1).toEqual(ReadPreference.SECONDARY); + expect(myObjectReadPreference2).toEqual(ReadPreference.SECONDARY_PREFERRED); }); - it('should find subqueries in same replica of readPreference by default', done => { + it('should find subqueries in same replica of readPreference by default', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject0'); @@ -1050,54 +958,48 @@ describe_only_db('mongo')('Read preference option', () => { obj2.set('boolKey', false); obj2.set('myObject1', obj1); - Parse.Object.saveAll([obj0, obj1, obj2]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - Parse.Cloud.beforeFind('MyObject2', req => { - req.readPreference = 'SECONDARY'; - }); - - const query0 = new Parse.Query('MyObject0'); - query0.equalTo('boolKey', false); + await Parse.Object.saveAll([obj0, obj1, obj2]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - const query1 = new Parse.Query('MyObject1'); - query1.matchesQuery('myObject0', query0); + Parse.Cloud.beforeFind('MyObject2', req => { + req.readPreference = 'SECONDARY'; + }); + await waitForReplication(); - const query2 = new Parse.Query('MyObject2'); - query2.matchesQuery('myObject1', query1); + const query0 = new Parse.Query('MyObject0'); + query0.equalTo('boolKey', false); - query2 - .find() - .then(results => { - expect(results.length).toBe(1); - expect(results[0].get('boolKey')).toBe(false); + const query1 = new Parse.Query('MyObject1'); + query1.matchesQuery('myObject0', query0); - let myObjectReadPreference0 = null; - let myObjectReadPreference1 = null; - let myObjectReadPreference2 = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { - myObjectReadPreference0 = call.args[0].options.readPreference.mode; - } - if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { - myObjectReadPreference1 = call.args[0].options.readPreference.mode; - } - if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { - myObjectReadPreference2 = call.args[0].options.readPreference.mode; - } - }); + const query2 = new Parse.Query('MyObject2'); + query2.matchesQuery('myObject1', query1); - expect(myObjectReadPreference0).toEqual(ReadPreference.SECONDARY); - expect(myObjectReadPreference1).toEqual(ReadPreference.SECONDARY); - expect(myObjectReadPreference2).toEqual(ReadPreference.SECONDARY); + const results = await query2.find(); + expect(results.length).toBe(1); + expect(results[0].get('boolKey')).toBe(false); - done(); - }) - .catch(done.fail); + let myObjectReadPreference0 = null; + let myObjectReadPreference1 = null; + let myObjectReadPreference2 = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { + myObjectReadPreference0 = call.args[0].options.readPreference.mode; + } + if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { + myObjectReadPreference1 = call.args[0].options.readPreference.mode; + } + if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { + myObjectReadPreference2 = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference0).toEqual(ReadPreference.SECONDARY); + expect(myObjectReadPreference1).toEqual(ReadPreference.SECONDARY); + expect(myObjectReadPreference2).toEqual(ReadPreference.SECONDARY); }); - it('should change subqueries read preference when using matchesQuery', done => { + it('should change subqueries read preference when using matchesQuery', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject0'); @@ -1109,55 +1011,49 @@ describe_only_db('mongo')('Read preference option', () => { obj2.set('boolKey', false); obj2.set('myObject1', obj1); - Parse.Object.saveAll([obj0, obj1, obj2]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - Parse.Cloud.beforeFind('MyObject2', req => { - req.readPreference = 'SECONDARY_PREFERRED'; - req.subqueryReadPreference = 'SECONDARY'; - }); - - const query0 = new Parse.Query('MyObject0'); - query0.equalTo('boolKey', false); + await Parse.Object.saveAll([obj0, obj1, obj2]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - const query1 = new Parse.Query('MyObject1'); - query1.matchesQuery('myObject0', query0); + Parse.Cloud.beforeFind('MyObject2', req => { + req.readPreference = 'SECONDARY_PREFERRED'; + req.subqueryReadPreference = 'SECONDARY'; + }); + await waitForReplication(); - const query2 = new Parse.Query('MyObject2'); - query2.matchesQuery('myObject1', query1); + const query0 = new Parse.Query('MyObject0'); + query0.equalTo('boolKey', false); - query2 - .find() - .then(results => { - expect(results.length).toBe(1); - expect(results[0].get('boolKey')).toBe(false); + const query1 = new Parse.Query('MyObject1'); + query1.matchesQuery('myObject0', query0); - let myObjectReadPreference0 = null; - let myObjectReadPreference1 = null; - let myObjectReadPreference2 = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { - myObjectReadPreference0 = call.args[0].options.readPreference.mode; - } - if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { - myObjectReadPreference1 = call.args[0].options.readPreference.mode; - } - if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { - myObjectReadPreference2 = call.args[0].options.readPreference.mode; - } - }); + const query2 = new Parse.Query('MyObject2'); + query2.matchesQuery('myObject1', query1); - expect(myObjectReadPreference0).toEqual(ReadPreference.SECONDARY); - expect(myObjectReadPreference1).toEqual(ReadPreference.SECONDARY); - expect(myObjectReadPreference2).toEqual(ReadPreference.SECONDARY_PREFERRED); + const results = await query2.find(); + expect(results.length).toBe(1); + expect(results[0].get('boolKey')).toBe(false); - done(); - }) - .catch(done.fail); + let myObjectReadPreference0 = null; + let myObjectReadPreference1 = null; + let myObjectReadPreference2 = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { + myObjectReadPreference0 = call.args[0].options.readPreference.mode; + } + if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { + myObjectReadPreference1 = call.args[0].options.readPreference.mode; + } + if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { + myObjectReadPreference2 = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference0).toEqual(ReadPreference.SECONDARY); + expect(myObjectReadPreference1).toEqual(ReadPreference.SECONDARY); + expect(myObjectReadPreference2).toEqual(ReadPreference.SECONDARY_PREFERRED); }); - it('should change subqueries read preference when using doesNotMatchQuery', done => { + it('should change subqueries read preference when using doesNotMatchQuery', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject0'); @@ -1169,55 +1065,49 @@ describe_only_db('mongo')('Read preference option', () => { obj2.set('boolKey', false); obj2.set('myObject1', obj1); - Parse.Object.saveAll([obj0, obj1, obj2]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - Parse.Cloud.beforeFind('MyObject2', req => { - req.readPreference = 'SECONDARY_PREFERRED'; - req.subqueryReadPreference = 'SECONDARY'; - }); - - const query0 = new Parse.Query('MyObject0'); - query0.equalTo('boolKey', false); + await Parse.Object.saveAll([obj0, obj1, obj2]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - const query1 = new Parse.Query('MyObject1'); - query1.doesNotMatchQuery('myObject0', query0); + Parse.Cloud.beforeFind('MyObject2', req => { + req.readPreference = 'SECONDARY_PREFERRED'; + req.subqueryReadPreference = 'SECONDARY'; + }); + await waitForReplication(); - const query2 = new Parse.Query('MyObject2'); - query2.doesNotMatchQuery('myObject1', query1); + const query0 = new Parse.Query('MyObject0'); + query0.equalTo('boolKey', false); - query2 - .find() - .then(results => { - expect(results.length).toBe(1); - expect(results[0].get('boolKey')).toBe(false); + const query1 = new Parse.Query('MyObject1'); + query1.doesNotMatchQuery('myObject0', query0); - let myObjectReadPreference0 = null; - let myObjectReadPreference1 = null; - let myObjectReadPreference2 = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { - myObjectReadPreference0 = call.args[0].options.readPreference.mode; - } - if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { - myObjectReadPreference1 = call.args[0].options.readPreference.mode; - } - if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { - myObjectReadPreference2 = call.args[0].options.readPreference.mode; - } - }); + const query2 = new Parse.Query('MyObject2'); + query2.doesNotMatchQuery('myObject1', query1); - expect(myObjectReadPreference0).toEqual(ReadPreference.SECONDARY); - expect(myObjectReadPreference1).toEqual(ReadPreference.SECONDARY); - expect(myObjectReadPreference2).toEqual(ReadPreference.SECONDARY_PREFERRED); + const results = await query2.find(); + expect(results.length).toBe(1); + expect(results[0].get('boolKey')).toBe(false); - done(); - }) - .catch(done.fail); + let myObjectReadPreference0 = null; + let myObjectReadPreference1 = null; + let myObjectReadPreference2 = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { + myObjectReadPreference0 = call.args[0].options.readPreference.mode; + } + if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { + myObjectReadPreference1 = call.args[0].options.readPreference.mode; + } + if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { + myObjectReadPreference2 = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference0).toEqual(ReadPreference.SECONDARY); + expect(myObjectReadPreference1).toEqual(ReadPreference.SECONDARY); + expect(myObjectReadPreference2).toEqual(ReadPreference.SECONDARY_PREFERRED); }); - it('should change subqueries read preference when using matchesKeyInQuery and doesNotMatchKeyInQuery', done => { + it('should change subqueries read preference when using matchesKeyInQuery and doesNotMatchKeyInQuery', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject0'); @@ -1229,56 +1119,50 @@ describe_only_db('mongo')('Read preference option', () => { obj2.set('boolKey', false); obj2.set('myObject1', obj1); - Parse.Object.saveAll([obj0, obj1, obj2]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - Parse.Cloud.beforeFind('MyObject2', req => { - req.readPreference = 'SECONDARY_PREFERRED'; - req.subqueryReadPreference = 'SECONDARY'; - }); - - const query0 = new Parse.Query('MyObject0'); - query0.equalTo('boolKey', false); + await Parse.Object.saveAll([obj0, obj1, obj2]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - const query1 = new Parse.Query('MyObject1'); - query1.equalTo('boolKey', true); + Parse.Cloud.beforeFind('MyObject2', req => { + req.readPreference = 'SECONDARY_PREFERRED'; + req.subqueryReadPreference = 'SECONDARY'; + }); + await waitForReplication(); - const query2 = new Parse.Query('MyObject2'); - query2.matchesKeyInQuery('boolKey', 'boolKey', query0); - query2.doesNotMatchKeyInQuery('boolKey', 'boolKey', query1); + const query0 = new Parse.Query('MyObject0'); + query0.equalTo('boolKey', false); - query2 - .find() - .then(results => { - expect(results.length).toBe(1); - expect(results[0].get('boolKey')).toBe(false); + const query1 = new Parse.Query('MyObject1'); + query1.equalTo('boolKey', true); - let myObjectReadPreference0 = null; - let myObjectReadPreference1 = null; - let myObjectReadPreference2 = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { - myObjectReadPreference0 = call.args[0].options.readPreference.mode; - } - if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { - myObjectReadPreference1 = call.args[0].options.readPreference.mode; - } - if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { - myObjectReadPreference2 = call.args[0].options.readPreference.mode; - } - }); + const query2 = new Parse.Query('MyObject2'); + query2.matchesKeyInQuery('boolKey', 'boolKey', query0); + query2.doesNotMatchKeyInQuery('boolKey', 'boolKey', query1); - expect(myObjectReadPreference0).toEqual(ReadPreference.SECONDARY); - expect(myObjectReadPreference1).toEqual(ReadPreference.SECONDARY); - expect(myObjectReadPreference2).toEqual(ReadPreference.SECONDARY_PREFERRED); + const results = await query2.find(); + expect(results.length).toBe(1); + expect(results[0].get('boolKey')).toBe(false); - done(); - }) - .catch(done.fail); + let myObjectReadPreference0 = null; + let myObjectReadPreference1 = null; + let myObjectReadPreference2 = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { + myObjectReadPreference0 = call.args[0].options.readPreference.mode; + } + if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { + myObjectReadPreference1 = call.args[0].options.readPreference.mode; + } + if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { + myObjectReadPreference2 = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference0).toEqual(ReadPreference.SECONDARY); + expect(myObjectReadPreference1).toEqual(ReadPreference.SECONDARY); + expect(myObjectReadPreference2).toEqual(ReadPreference.SECONDARY_PREFERRED); }); - it('should change subqueries read preference when using matchesKeyInQuery and doesNotMatchKeyInQuery to find through API', done => { + it('should change subqueries read preference when using matchesKeyInQuery and doesNotMatchKeyInQuery to find through API', async () => { const databaseAdapter = Config.get(Parse.applicationId).database.adapter; const obj0 = new Parse.Object('MyObject0'); @@ -1290,66 +1174,61 @@ describe_only_db('mongo')('Read preference option', () => { obj2.set('boolKey', false); obj2.set('myObject1', obj1); - Parse.Object.saveAll([obj0, obj1, obj2]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); - - const whereString = JSON.stringify({ - boolKey: { - $select: { - query: { - className: 'MyObject0', - where: { boolKey: false }, - }, - key: 'boolKey', - }, - $dontSelect: { - query: { - className: 'MyObject1', - where: { boolKey: true }, - }, - key: 'boolKey', + await Parse.Object.saveAll([obj0, obj1, obj2]); + spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + await waitForReplication(); + + const whereString = JSON.stringify({ + boolKey: { + $select: { + query: { + className: 'MyObject0', + where: { boolKey: false }, }, + key: 'boolKey', }, - }); - - request({ - method: 'GET', - url: - 'http://localhost:8378/1/classes/MyObject2/?where=' + - whereString + - '&readPreference=SECONDARY_PREFERRED&subqueryReadPreference=SECONDARY', - headers: { - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'rest', + $dontSelect: { + query: { + className: 'MyObject1', + where: { boolKey: true }, + }, + key: 'boolKey', }, - json: true, - }) - .then(response => { - expect(response.data.results.length).toBe(1); - expect(response.data.results[0].boolKey).toBe(false); - - let myObjectReadPreference0 = null; - let myObjectReadPreference1 = null; - let myObjectReadPreference2 = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { - myObjectReadPreference0 = call.args[0].options.readPreference.mode; - } - if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { - myObjectReadPreference1 = call.args[0].options.readPreference.mode; - } - if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { - myObjectReadPreference2 = call.args[0].options.readPreference.mode; - } - }); + }, + }); - expect(myObjectReadPreference0).toEqual(ReadPreference.SECONDARY); - expect(myObjectReadPreference1).toEqual(ReadPreference.SECONDARY); - expect(myObjectReadPreference2).toEqual(ReadPreference.SECONDARY_PREFERRED); + const response = await request({ + method: 'GET', + url: + 'http://localhost:8378/1/classes/MyObject2/?where=' + + whereString + + '&readPreference=SECONDARY_PREFERRED&subqueryReadPreference=SECONDARY', + headers: { + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }, + json: true, + }); + expect(response.data.results.length).toBe(1); + expect(response.data.results[0].boolKey).toBe(false); - done(); - }) - .catch(done.fail); + let myObjectReadPreference0 = null; + let myObjectReadPreference1 = null; + let myObjectReadPreference2 = null; + databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { + if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { + myObjectReadPreference0 = call.args[0].options.readPreference.mode; + } + if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { + myObjectReadPreference1 = call.args[0].options.readPreference.mode; + } + if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { + myObjectReadPreference2 = call.args[0].options.readPreference.mode; + } }); + + expect(myObjectReadPreference0).toEqual(ReadPreference.SECONDARY); + expect(myObjectReadPreference1).toEqual(ReadPreference.SECONDARY); + expect(myObjectReadPreference2).toEqual(ReadPreference.SECONDARY_PREFERRED); }); });