diff --git a/spec/AuthenticationAdapters.spec.js b/spec/AuthenticationAdapters.spec.js index df2363e52e..f7d1d645c1 100644 --- a/spec/AuthenticationAdapters.spec.js +++ b/spec/AuthenticationAdapters.spec.js @@ -301,7 +301,7 @@ describe('AuthenticationProviders', function() { }) }); - it('properly loads custom adapter module object', (done) => { + it('properly loads custom adapter module object (again)', (done) => { const authenticationHandler = authenticationLoader({ customAuthentication: { module: path.resolve('./spec/support/CustomAuthFunction.js'), options: { token: 'valid-token' }} }); diff --git a/spec/HTTPRequest.spec.js b/spec/HTTPRequest.spec.js index 00e8151b4e..80100cdc1e 100644 --- a/spec/HTTPRequest.spec.js +++ b/spec/HTTPRequest.spec.js @@ -132,21 +132,6 @@ describe("httpRequest", () => { }); }) - it("should fail on 404", (done) => { - httpRequest({ - url: httpRequestServer + "/404", - }).then(function(){ - fail("should not succeed"); - done(); - }, function(httpResponse){ - expect(httpResponse.status).toBe(404); - expect(httpResponse.buffer).toEqual(new Buffer('NO')); - expect(httpResponse.text).toEqual('NO'); - expect(httpResponse.data).toBe(undefined); - done(); - }) - }) - it("should post on echo", (done) => { let calls = 0; httpRequest({ diff --git a/spec/JobSchedule.spec.js b/spec/JobSchedule.spec.js index bd8ca3070b..def48e180f 100644 --- a/spec/JobSchedule.spec.js +++ b/spec/JobSchedule.spec.js @@ -50,11 +50,11 @@ describe('JobSchedule', () => { rp.put(Parse.serverURL + '/cloud_code/jobs/jobId', defaultOptions).then(done.fail, () => done()); }); - it('should reject access when not using masterKey (PUT /jobs/id)', (done) => { + it('should reject access when not using masterKey (DELETE /jobs/id)', (done) => { rp.del(Parse.serverURL + '/cloud_code/jobs/jobId', defaultOptions).then(done.fail, () => done()); }); - it('should allow access when using masterKey (/jobs)', (done) => { + it('should allow access when using masterKey (GET /jobs)', (done) => { rp.get(Parse.serverURL + '/cloud_code/jobs', masterKeyOptions).then(done, done.fail); }); diff --git a/spec/LoggerController.spec.js b/spec/LoggerController.spec.js index 3062d76206..36306b662a 100644 --- a/spec/LoggerController.spec.js +++ b/spec/LoggerController.spec.js @@ -2,7 +2,7 @@ const LoggerController = require('../lib/Controllers/LoggerController').LoggerCo const WinstonLoggerAdapter = require('../lib/Adapters/Logger/WinstonLoggerAdapter').WinstonLoggerAdapter; describe('LoggerController', () => { - it('can check process a query without throwing', (done) => { + it('can process an empty query without throwing', (done) => { // Make mock request const query = {}; @@ -37,7 +37,7 @@ describe('LoggerController', () => { done(); }); - it('can process a query without throwing', (done) => { + it('can process an ascending query without throwing', (done) => { // Make mock request const query = { from: "2016-01-01Z00:00:00", @@ -58,7 +58,7 @@ describe('LoggerController', () => { done(); }); - it('can check process a query without throwing', (done) => { + it('can process a descending query without throwing', (done) => { // Make mock request const query = { from: "2016-01-01", diff --git a/spec/MongoStorageAdapter.spec.js b/spec/MongoStorageAdapter.spec.js index 0484b69fcc..d26b822eb7 100644 --- a/spec/MongoStorageAdapter.spec.js +++ b/spec/MongoStorageAdapter.spec.js @@ -9,7 +9,7 @@ const databaseURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDataba describe_only_db('mongo')('MongoStorageAdapter', () => { beforeEach(done => { new MongoStorageAdapter({ uri: databaseURI }) - .dropDatabase() + .deleteAllClasses() .then(done, fail); }); diff --git a/spec/MongoTransform.spec.js b/spec/MongoTransform.spec.js index 2a198e1b5e..c38346c123 100644 --- a/spec/MongoTransform.spec.js +++ b/spec/MongoTransform.spec.js @@ -24,7 +24,7 @@ describe('parseObjectToMongoObjectForCreate', () => { done(); }); - it('built-in timestamps', (done) => { + it('built-in timestamps with date', (done) => { const input = { createdAt: "2015-10-06T21:24:50.332Z", updatedAt: "2015-10-06T21:24:50.332Z" diff --git a/spec/ParseFile.spec.js b/spec/ParseFile.spec.js index 9f19a87119..d5f7d38c7f 100644 --- a/spec/ParseFile.spec.js +++ b/spec/ParseFile.spec.js @@ -632,24 +632,6 @@ describe('Parse.File testing', () => { }); }); - it('fails to upload without a file name', done => { - const headers = { - 'Content-Type': 'application/octet-stream', - 'X-Parse-Application-Id': 'test', - 'X-Parse-REST-API-Key': 'rest' - }; - request.post({ - headers: headers, - url: 'http://localhost:8378/1/files/', - body: 'yolo', - }, (error, response, body) => { - expect(error).toBe(null); - expect(response.statusCode).toBe(400); - expect(body).toEqual('{"code":122,"error":"Filename not provided."}'); - done(); - }); - }); - it('fails to delete an unkown file', done => { const headers = { 'Content-Type': 'application/octet-stream', diff --git a/spec/ParseHooks.spec.js b/spec/ParseHooks.spec.js index 9104a529aa..5b8900395c 100644 --- a/spec/ParseHooks.spec.js +++ b/spec/ParseHooks.spec.js @@ -336,7 +336,7 @@ describe('Hooks', () => { }); }); - it("should run the function on the test server", (done) => { + it("should run the function on the test server (error handling)", (done) => { app.post("/SomeFunctionError", function(req, res) { res.json({error: {code: 1337, error: "hacking that one!"}}); diff --git a/spec/ParsePolygon.spec.js b/spec/ParsePolygon.spec.js index e9932114ff..2527a09e55 100644 --- a/spec/ParsePolygon.spec.js +++ b/spec/ParsePolygon.spec.js @@ -8,6 +8,9 @@ const defaultHeaders = { } describe('Parse.Polygon testing', () => { + + beforeAll(() => require('../lib/TestUtils').destroyAllDataPermanently()); + it('polygon save open path', (done) => { const coords = [[0,0],[0,1],[1,1],[1,0]]; const closed = [[0,0],[0,1],[1,1],[1,0],[0,0]]; @@ -128,144 +131,150 @@ describe('Parse.Polygon testing', () => { }, done.fail); }); - it('polygonContain query', (done) => { - const points1 = [[0,0],[0,1],[1,1],[1,0]]; - const points2 = [[0,0],[0,2],[2,2],[2,0]]; - const points3 = [[10,10],[10,15],[15,15],[15,10],[10,10]]; - const polygon1 = new Parse.Polygon(points1); - const polygon2 = new Parse.Polygon(points2); - const polygon3 = new Parse.Polygon(points3); - const obj1 = new TestObject({location: polygon1}); - const obj2 = new TestObject({location: polygon2}); - const obj3 = new TestObject({location: polygon3}); - Parse.Object.saveAll([obj1, obj2, obj3]).then(() => { - const where = { - location: { - $geoIntersects: { - $point: { __type: 'GeoPoint', latitude: 0.5, longitude: 0.5 } + describe('with location', () => { + beforeAll(() => require('../lib/TestUtils').destroyAllDataPermanently()); + + it('polygonContain query', (done) => { + const points1 = [[0,0],[0,1],[1,1],[1,0]]; + const points2 = [[0,0],[0,2],[2,2],[2,0]]; + const points3 = [[10,10],[10,15],[15,15],[15,10],[10,10]]; + const polygon1 = new Parse.Polygon(points1); + const polygon2 = new Parse.Polygon(points2); + const polygon3 = new Parse.Polygon(points3); + const obj1 = new TestObject({location: polygon1}); + const obj2 = new TestObject({location: polygon2}); + const obj3 = new TestObject({location: polygon3}); + Parse.Object.saveAll([obj1, obj2, obj3]).then(() => { + const where = { + location: { + $geoIntersects: { + $point: { __type: 'GeoPoint', latitude: 0.5, longitude: 0.5 } + } } - } - }; - return rp.post({ - url: Parse.serverURL + '/classes/TestObject', - json: { where, '_method': 'GET' }, - headers: { - 'X-Parse-Application-Id': Parse.applicationId, - 'X-Parse-Javascript-Key': Parse.javaScriptKey - } - }); - }).then((resp) => { - expect(resp.results.length).toBe(2); - done(); - }, done.fail); - }); + }; + return rp.post({ + url: Parse.serverURL + '/classes/TestObject', + json: { where, '_method': 'GET' }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }).then((resp) => { + expect(resp.results.length).toBe(2); + done(); + }, done.fail); + }); - it('polygonContain query no reverse input (Regression test for #4608)', (done) => { - const points1 = [[.25,0],[.25,1.25],[.75,1.25],[.75,0]]; - const points2 = [[0,0],[0,2],[2,2],[2,0]]; - const points3 = [[10,10],[10,15],[15,15],[15,10],[10,10]]; - const polygon1 = new Parse.Polygon(points1); - const polygon2 = new Parse.Polygon(points2); - const polygon3 = new Parse.Polygon(points3); - const obj1 = new TestObject({location: polygon1}); - const obj2 = new TestObject({location: polygon2}); - const obj3 = new TestObject({location: polygon3}); - Parse.Object.saveAll([obj1, obj2, obj3]).then(() => { - const where = { - location: { - $geoIntersects: { - $point: { __type: 'GeoPoint', latitude: 0.5, longitude:1.0 } + it('polygonContain query no reverse input (Regression test for #4608)', (done) => { + const points1 = [[.25,0],[.25,1.25],[.75,1.25],[.75,0]]; + const points2 = [[0,0],[0,2],[2,2],[2,0]]; + const points3 = [[10,10],[10,15],[15,15],[15,10],[10,10]]; + const polygon1 = new Parse.Polygon(points1); + const polygon2 = new Parse.Polygon(points2); + const polygon3 = new Parse.Polygon(points3); + const obj1 = new TestObject({location: polygon1}); + const obj2 = new TestObject({location: polygon2}); + const obj3 = new TestObject({location: polygon3}); + Parse.Object.saveAll([obj1, obj2, obj3]).then(() => { + const where = { + location: { + $geoIntersects: { + $point: { __type: 'GeoPoint', latitude: 0.5, longitude:1.0 } + } } - } - }; - return rp.post({ - url: Parse.serverURL + '/classes/TestObject', - json: { where, '_method': 'GET' }, - headers: { - 'X-Parse-Application-Id': Parse.applicationId, - 'X-Parse-Javascript-Key': Parse.javaScriptKey - } - }); - }).then((resp) => { - expect(resp.results.length).toBe(2); - done(); - }, done.fail); - }); + }; + return rp.post({ + url: Parse.serverURL + '/classes/TestObject', + json: { where, '_method': 'GET' }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }).then((resp) => { + expect(resp.results.length).toBe(2); + done(); + }, done.fail); + }); - it('polygonContain query real data (Regression test for #4608)', (done) => { - const detroit = [[42.631655189280224,-83.78406753121705],[42.633047793854814,-83.75333640366955],[42.61625254348911,-83.75149921669944],[42.61526926650296,-83.78161794858735],[42.631655189280224,-83.78406753121705]]; - const polygon = new Parse.Polygon(detroit); - const obj = new TestObject({location: polygon}); - obj.save().then(() => { - const where = { - location: { - $geoIntersects: { - $point: { __type: 'GeoPoint', latitude: 42.624599, longitude:-83.770162 } + it('polygonContain query real data (Regression test for #4608)', (done) => { + const detroit = [[42.631655189280224,-83.78406753121705],[42.633047793854814,-83.75333640366955],[42.61625254348911,-83.75149921669944],[42.61526926650296,-83.78161794858735],[42.631655189280224,-83.78406753121705]]; + const polygon = new Parse.Polygon(detroit); + const obj = new TestObject({location: polygon}); + obj.save().then(() => { + const where = { + location: { + $geoIntersects: { + $point: { __type: 'GeoPoint', latitude: 42.624599, longitude:-83.770162 } + } } - } - }; - return rp.post({ - url: Parse.serverURL + '/classes/TestObject', - json: { where, '_method': 'GET' }, - headers: { - 'X-Parse-Application-Id': Parse.applicationId, - 'X-Parse-Javascript-Key': Parse.javaScriptKey - } - }); - }).then((resp) => { - expect(resp.results.length).toBe(1); - done(); - }, done.fail); - }); + }; + return rp.post({ + url: Parse.serverURL + '/classes/TestObject', + json: { where, '_method': 'GET' }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }).then((resp) => { + expect(resp.results.length).toBe(1); + done(); + }, done.fail); + }); - it('polygonContain invalid input', (done) => { - const points = [[0,0],[0,1],[1,1],[1,0]]; - const polygon = new Parse.Polygon(points); - const obj = new TestObject({location: polygon}); - obj.save().then(() => { - const where = { - location: { - $geoIntersects: { - $point: { __type: 'GeoPoint', latitude: 181, longitude: 181 } + it('polygonContain invalid input', (done) => { + const points = [[0,0],[0,1],[1,1],[1,0]]; + const polygon = new Parse.Polygon(points); + const obj = new TestObject({location: polygon}); + obj.save().then(() => { + const where = { + location: { + $geoIntersects: { + $point: { __type: 'GeoPoint', latitude: 181, longitude: 181 } + } } - } - }; - return rp.post({ - url: Parse.serverURL + '/classes/TestObject', - json: { where, '_method': 'GET' }, - headers: { - 'X-Parse-Application-Id': Parse.applicationId, - 'X-Parse-Javascript-Key': Parse.javaScriptKey - } - }); - }).then(done.fail, () => done()); - }); + }; + return rp.post({ + url: Parse.serverURL + '/classes/TestObject', + json: { where, '_method': 'GET' }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }).then(done.fail, () => done()); + }); - it('polygonContain invalid geoPoint', (done) => { - const points = [[0,0],[0,1],[1,1],[1,0]]; - const polygon = new Parse.Polygon(points); - const obj = new TestObject({location: polygon}); - obj.save().then(() => { - const where = { - location: { - $geoIntersects: { - $point: [] + it('polygonContain invalid geoPoint', (done) => { + const points = [[0,0],[0,1],[1,1],[1,0]]; + const polygon = new Parse.Polygon(points); + const obj = new TestObject({location: polygon}); + obj.save().then(() => { + const where = { + location: { + $geoIntersects: { + $point: [] + } } - } - }; - return rp.post({ - url: Parse.serverURL + '/classes/TestObject', - json: { where, '_method': 'GET' }, - headers: { - 'X-Parse-Application-Id': Parse.applicationId, - 'X-Parse-Javascript-Key': Parse.javaScriptKey - } - }); - }).then(done.fail, () => done()); + }; + return rp.post({ + url: Parse.serverURL + '/classes/TestObject', + json: { where, '_method': 'GET' }, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Javascript-Key': Parse.javaScriptKey + } + }); + }).then(done.fail, () => done()); + }); }); }); describe_only_db('mongo')('Parse.Polygon testing', () => { + + beforeEach(() => require('../lib/TestUtils').destroyAllDataPermanently()); it('support 2d and 2dsphere', (done) => { const coords = [[0,0],[0,1],[1,1],[1,0],[0,0]]; // testings against REST API, use raw formats diff --git a/spec/ParseUser.spec.js b/spec/ParseUser.spec.js index 1ff4614dc8..1be54817f0 100644 --- a/spec/ParseUser.spec.js +++ b/spec/ParseUser.spec.js @@ -101,7 +101,7 @@ describe('Parse.User testing', () => { }); }); - it('user login with non-string username with REST API', (done) => { + it('user login with non-string username with REST API (again)', (done) => { Parse.User.signUp('asdf', 'zxcv', null, { success: () => { return rp.post({ @@ -1888,7 +1888,7 @@ describe('Parse.User testing', () => { }); }); - it('should fail linking with existing', (done) => { + it('should fail linking with existing through REST', (done) => { const provider = getMockFacebookProvider(); Parse.User._registerAuthenticationProvider(provider); Parse.User._logInWith("facebook", { diff --git a/spec/PostgresStorageAdapter.spec.js b/spec/PostgresStorageAdapter.spec.js index 93389d8fc5..d54cb9f2a8 100644 --- a/spec/PostgresStorageAdapter.spec.js +++ b/spec/PostgresStorageAdapter.spec.js @@ -12,7 +12,7 @@ const dropTable = (client, className) => { describe_only_db('postgres')('PostgresStorageAdapter', () => { const adapter = new PostgresStorageAdapter({ uri: databaseURI }) beforeEach(() => { - return adapter.dropDatabase(); + return adapter.deleteAllClasses(); }); it('schemaUpgrade, upgrade the database schema when schema changes', done => { diff --git a/spec/helper.js b/spec/helper.js index 0398d2fd2e..800536f47d 100644 --- a/spec/helper.js +++ b/spec/helper.js @@ -172,7 +172,7 @@ beforeEach(done => { throw error; } } - TestUtils.destroyAllDataPermanently() + TestUtils.destroyAllDataPermanently(true) .catch(error => { // For tests that connect to their own mongo, there won't be any data to delete. if (error.message === 'ns not found' || error.message.startsWith('connect ECONNREFUSED')) { @@ -196,7 +196,7 @@ afterEach(function(done) { fail('There were open connections to the server left after the test finished'); } on_db('postgres', () => { - TestUtils.destroyAllDataPermanently().then(done, done); + TestUtils.destroyAllDataPermanently(true).then(done, done); }, done); }; Parse.Cloud._removeAllHooks(); diff --git a/spec/schemas.spec.js b/spec/schemas.spec.js index c9edf560c1..8b2417fef4 100644 --- a/spec/schemas.spec.js +++ b/spec/schemas.spec.js @@ -1212,7 +1212,7 @@ describe('schemas', () => { }) }); - it('should throw with invalid * (spaces)', done => { + it('should throw with invalid * (spaces before)', done => { request.post({ url: 'http://localhost:8378/1/schemas/AClass', headers: masterKeyHeaders, @@ -1230,7 +1230,7 @@ describe('schemas', () => { }) }); - it('should throw with invalid * (spaces)', done => { + it('should throw with invalid * (spaces after)', done => { request.post({ url: 'http://localhost:8378/1/schemas/AClass', headers: masterKeyHeaders, @@ -1787,11 +1787,9 @@ describe('schemas', () => { 'delete': {}, 'addField': {}, }); - console.log(res); }).then(done).catch(done.fail); }); - it('regression test for #2246', done => { const profile = new Parse.Object('UserProfile'); const user = new Parse.User(); @@ -1828,165 +1826,132 @@ describe('schemas', () => { }); }); - it('cannot create index if field does not exist', done => { - request.post({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - body: {}, - }, () => { - request.put({ + describe('index management', () => { + beforeEach(() => require('../lib/TestUtils').destroyAllDataPermanently()); + it('cannot create index if field does not exist', done => { + request.post({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, - body: { - indexes: { - name1: { aString: 1}, + body: {}, + }, () => { + request.put({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: { + indexes: { + name1: { aString: 1}, + } } - } - }, (error, response, body) => { - expect(body.code).toBe(Parse.Error.INVALID_QUERY); - expect(body.error).toBe('Field aString does not exist, cannot add index.'); - done(); - }); - }) - }); + }, (error, response, body) => { + expect(body.code).toBe(Parse.Error.INVALID_QUERY); + expect(body.error).toBe('Field aString does not exist, cannot add index.'); + done(); + }); + }) + }); - it('can create index on default field', done => { - request.post({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - body: {}, - }, () => { - request.put({ + it('can create index on default field', done => { + request.post({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, - body: { - indexes: { - name1: { createdAt: 1}, + body: {}, + }, () => { + request.put({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: { + indexes: { + name1: { createdAt: 1}, + } } - } - }, (error, response, body) => { - expect(body.indexes.name1).toEqual({ createdAt: 1}); - done(); - }); - }) - }); + }, (error, response, body) => { + expect(body.indexes.name1).toEqual({ createdAt: 1}); + done(); + }); + }) + }); - it('cannot create compound index if field does not exist', done => { - request.post({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - body: {}, - }, () => { - request.put({ + it('cannot create compound index if field does not exist', done => { + request.post({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, + body: {}, + }, () => { + request.put({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: { + fields: { + aString: {type: 'String'} + }, + indexes: { + name1: { aString: 1, bString: 1}, + } + } + }, (error, response, body) => { + expect(body.code).toBe(Parse.Error.INVALID_QUERY); + expect(body.error).toBe('Field bString does not exist, cannot add index.'); + done(); + }); + }) + }); + + it('allows add index when you create a class', done => { + request.post({ + url: 'http://localhost:8378/1/schemas', + headers: masterKeyHeaders, + json: true, body: { + className: "NewClass", fields: { aString: {type: 'String'} }, indexes: { - name1: { aString: 1, bString: 1}, - } + name1: { aString: 1}, + }, } }, (error, response, body) => { - expect(body.code).toBe(Parse.Error.INVALID_QUERY); - expect(body.error).toBe('Field bString does not exist, cannot add index.'); - done(); - }); - }) - }); - - it('allows add index when you create a class', done => { - request.post({ - url: 'http://localhost:8378/1/schemas', - headers: masterKeyHeaders, - json: true, - body: { - className: "NewClass", - fields: { - aString: {type: 'String'} - }, - indexes: { - name1: { aString: 1}, - }, - } - }, (error, response, body) => { - expect(body).toEqual({ - className: 'NewClass', - fields: { - ACL: {type: 'ACL'}, - createdAt: {type: 'Date'}, - updatedAt: {type: 'Date'}, - objectId: {type: 'String'}, - aString: {type: 'String'} - }, - classLevelPermissions: defaultClassLevelPermissions, - indexes: { - name1: { aString: 1}, - }, - }); - config.database.adapter.getIndexes('NewClass').then((indexes) => { - expect(indexes.length).toBe(2); - done(); - }); - }); - }); - - it('empty index returns nothing', done => { - request.post({ - url: 'http://localhost:8378/1/schemas', - headers: masterKeyHeaders, - json: true, - body: { - className: "NewClass", - fields: { - aString: {type: 'String'} - }, - indexes: {}, - } - }, (error, response, body) => { - expect(body).toEqual({ - className: 'NewClass', - fields: { - ACL: {type: 'ACL'}, - createdAt: {type: 'Date'}, - updatedAt: {type: 'Date'}, - objectId: {type: 'String'}, - aString: {type: 'String'} - }, - classLevelPermissions: defaultClassLevelPermissions, + expect(body).toEqual({ + className: 'NewClass', + fields: { + ACL: {type: 'ACL'}, + createdAt: {type: 'Date'}, + updatedAt: {type: 'Date'}, + objectId: {type: 'String'}, + aString: {type: 'String'} + }, + classLevelPermissions: defaultClassLevelPermissions, + indexes: { + name1: { aString: 1}, + }, + }); + config.database.adapter.getIndexes('NewClass').then((indexes) => { + expect(indexes.length).toBe(2); + done(); + }); }); - done(); }); - }); - it('lets you add indexes', done => { - request.post({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - body: {}, - }, () => { - request.put({ - url: 'http://localhost:8378/1/schemas/NewClass', + it('empty index returns nothing', done => { + request.post({ + url: 'http://localhost:8378/1/schemas', headers: masterKeyHeaders, json: true, body: { + className: "NewClass", fields: { aString: {type: 'String'} }, - indexes: { - name1: { aString: 1}, - }, + indexes: {}, } }, (error, response, body) => { - expect(dd(body, { + expect(body).toEqual({ className: 'NewClass', fields: { ACL: {type: 'ACL'}, @@ -1996,17 +1961,32 @@ describe('schemas', () => { aString: {type: 'String'} }, classLevelPermissions: defaultClassLevelPermissions, - indexes: { - _id_: { _id: 1 }, - name1: { aString: 1 }, - } - })).toEqual(undefined); - request.get({ + }); + done(); + }); + }); + + it('lets you add indexes', done => { + request.post({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: {}, + }, () => { + request.put({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, + body: { + fields: { + aString: {type: 'String'} + }, + indexes: { + name1: { aString: 1}, + }, + } }, (error, response, body) => { - expect(body).toEqual({ + expect(dd(body, { className: 'NewClass', fields: { ACL: {type: 'ACL'}, @@ -2020,67 +2000,62 @@ describe('schemas', () => { _id_: { _id: 1 }, name1: { aString: 1 }, } - }); - config.database.adapter.getIndexes('NewClass').then((indexes) => { - expect(indexes.length).toEqual(2); - done(); + })).toEqual(undefined); + request.get({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + }, (error, response, body) => { + expect(body).toEqual({ + className: 'NewClass', + fields: { + ACL: {type: 'ACL'}, + createdAt: {type: 'Date'}, + updatedAt: {type: 'Date'}, + objectId: {type: 'String'}, + aString: {type: 'String'} + }, + classLevelPermissions: defaultClassLevelPermissions, + indexes: { + _id_: { _id: 1 }, + name1: { aString: 1 }, + } + }); + config.database.adapter.getIndexes('NewClass').then((indexes) => { + expect(indexes.length).toEqual(2); + done(); + }); }); }); - }); - }) - }); + }) + }); - it('lets you add multiple indexes', done => { - request.post({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - body: {}, - }, () => { - request.put({ + it('lets you add multiple indexes', done => { + request.post({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, - body: { - fields: { - aString: {type: 'String'}, - bString: {type: 'String'}, - cString: {type: 'String'}, - dString: {type: 'String'}, - }, - indexes: { - name1: { aString: 1 }, - name2: { bString: 1 }, - name3: { cString: 1, dString: 1 }, - } - } - }, (error, response, body) => { - expect(dd(body, { - className: 'NewClass', - fields: { - ACL: {type: 'ACL'}, - createdAt: {type: 'Date'}, - updatedAt: {type: 'Date'}, - objectId: {type: 'String'}, - aString: {type: 'String'}, - bString: {type: 'String'}, - cString: {type: 'String'}, - dString: {type: 'String'}, - }, - classLevelPermissions: defaultClassLevelPermissions, - indexes: { - _id_: { _id: 1 }, - name1: { aString: 1 }, - name2: { bString: 1 }, - name3: { cString: 1, dString: 1 }, - } - })).toEqual(undefined); - request.get({ + body: {}, + }, () => { + request.put({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, + body: { + fields: { + aString: {type: 'String'}, + bString: {type: 'String'}, + cString: {type: 'String'}, + dString: {type: 'String'}, + }, + indexes: { + name1: { aString: 1 }, + name2: { bString: 1 }, + name3: { cString: 1, dString: 1 }, + } + } }, (error, response, body) => { - expect(body).toEqual({ + expect(dd(body, { className: 'NewClass', fields: { ACL: {type: 'ACL'}, @@ -2098,63 +2073,63 @@ describe('schemas', () => { name1: { aString: 1 }, name2: { bString: 1 }, name3: { cString: 1, dString: 1 }, - }, - }); - config.database.adapter.getIndexes('NewClass').then((indexes) => { - expect(indexes.length).toEqual(4); - done(); - }); - }); - }); - }) - }); - - it('lets you delete indexes', done => { - request.post({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - body: {}, - }, () => { - request.put({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - body: { - fields: { - aString: {type: 'String'}, - }, - indexes: { - name1: { aString: 1 }, - } - } - }, (error, response, body) => { - expect(dd(body, { - className: 'NewClass', - fields: { - ACL: {type: 'ACL'}, - createdAt: {type: 'Date'}, - updatedAt: {type: 'Date'}, - objectId: {type: 'String'}, - aString: {type: 'String'}, - }, - classLevelPermissions: defaultClassLevelPermissions, - indexes: { - _id_: { _id: 1 }, - name1: { aString: 1 }, - } - })).toEqual(undefined); + } + })).toEqual(undefined); + request.get({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + }, (error, response, body) => { + expect(body).toEqual({ + className: 'NewClass', + fields: { + ACL: {type: 'ACL'}, + createdAt: {type: 'Date'}, + updatedAt: {type: 'Date'}, + objectId: {type: 'String'}, + aString: {type: 'String'}, + bString: {type: 'String'}, + cString: {type: 'String'}, + dString: {type: 'String'}, + }, + classLevelPermissions: defaultClassLevelPermissions, + indexes: { + _id_: { _id: 1 }, + name1: { aString: 1 }, + name2: { bString: 1 }, + name3: { cString: 1, dString: 1 }, + }, + }); + config.database.adapter.getIndexes('NewClass').then((indexes) => { + expect(indexes.length).toEqual(4); + done(); + }); + }); + }); + }) + }); + + it('lets you delete indexes', done => { + request.post({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: {}, + }, () => { request.put({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, body: { + fields: { + aString: {type: 'String'}, + }, indexes: { - name1: { __op: 'Delete' } + name1: { aString: 1 }, } } }, (error, response, body) => { - expect(body).toEqual({ + expect(dd(body, { className: 'NewClass', fields: { ACL: {type: 'ACL'}, @@ -2166,72 +2141,67 @@ describe('schemas', () => { classLevelPermissions: defaultClassLevelPermissions, indexes: { _id_: { _id: 1 }, + name1: { aString: 1 }, } - }); - config.database.adapter.getIndexes('NewClass').then((indexes) => { - expect(indexes.length).toEqual(1); - done(); + })).toEqual(undefined); + request.put({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: { + indexes: { + name1: { __op: 'Delete' } + } + } + }, (error, response, body) => { + expect(body).toEqual({ + className: 'NewClass', + fields: { + ACL: {type: 'ACL'}, + createdAt: {type: 'Date'}, + updatedAt: {type: 'Date'}, + objectId: {type: 'String'}, + aString: {type: 'String'}, + }, + classLevelPermissions: defaultClassLevelPermissions, + indexes: { + _id_: { _id: 1 }, + } + }); + config.database.adapter.getIndexes('NewClass').then((indexes) => { + expect(indexes.length).toEqual(1); + done(); + }); }); }); - }); - }) - }); + }) + }); - it('lets you delete multiple indexes', done => { - request.post({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - body: {}, - }, () => { - request.put({ + it('lets you delete multiple indexes', done => { + request.post({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, - body: { - fields: { - aString: {type: 'String'}, - bString: {type: 'String'}, - cString: {type: 'String'}, - }, - indexes: { - name1: { aString: 1 }, - name2: { bString: 1 }, - name3: { cString: 1 }, - } - } - }, (error, response, body) => { - expect(dd(body, { - className: 'NewClass', - fields: { - ACL: {type: 'ACL'}, - createdAt: {type: 'Date'}, - updatedAt: {type: 'Date'}, - objectId: {type: 'String'}, - aString: {type: 'String'}, - bString: {type: 'String'}, - cString: {type: 'String'}, - }, - classLevelPermissions: defaultClassLevelPermissions, - indexes: { - _id_: { _id: 1 }, - name1: { aString: 1 }, - name2: { bString: 1 }, - name3: { cString: 1 }, - } - })).toEqual(undefined); + body: {}, + }, () => { request.put({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, body: { + fields: { + aString: {type: 'String'}, + bString: {type: 'String'}, + cString: {type: 'String'}, + }, indexes: { - name1: { __op: 'Delete' }, - name2: { __op: 'Delete' }, + name1: { aString: 1 }, + name2: { bString: 1 }, + name3: { cString: 1 }, } } }, (error, response, body) => { - expect(body).toEqual({ + expect(dd(body, { className: 'NewClass', fields: { ACL: {type: 'ACL'}, @@ -2245,76 +2215,74 @@ describe('schemas', () => { classLevelPermissions: defaultClassLevelPermissions, indexes: { _id_: { _id: 1 }, + name1: { aString: 1 }, + name2: { bString: 1 }, name3: { cString: 1 }, } - }); - config.database.adapter.getIndexes('NewClass').then((indexes) => { - expect(indexes.length).toEqual(2); - done(); + })).toEqual(undefined); + request.put({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: { + indexes: { + name1: { __op: 'Delete' }, + name2: { __op: 'Delete' }, + } + } + }, (error, response, body) => { + expect(body).toEqual({ + className: 'NewClass', + fields: { + ACL: {type: 'ACL'}, + createdAt: {type: 'Date'}, + updatedAt: {type: 'Date'}, + objectId: {type: 'String'}, + aString: {type: 'String'}, + bString: {type: 'String'}, + cString: {type: 'String'}, + }, + classLevelPermissions: defaultClassLevelPermissions, + indexes: { + _id_: { _id: 1 }, + name3: { cString: 1 }, + } + }); + config.database.adapter.getIndexes('NewClass').then((indexes) => { + expect(indexes.length).toEqual(2); + done(); + }); }); }); - }); - }) - }); + }) + }); - it('lets you add and delete indexes', done => { - request.post({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - body: {}, - }, () => { - request.put({ + it('lets you add and delete indexes', done => { + request.post({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, - body: { - fields: { - aString: {type: 'String'}, - bString: {type: 'String'}, - cString: {type: 'String'}, - dString: {type: 'String'}, - }, - indexes: { - name1: { aString: 1 }, - name2: { bString: 1 }, - name3: { cString: 1 }, - } - } - }, (error, response, body) => { - expect(dd(body, { - className: 'NewClass', - fields: { - ACL: {type: 'ACL'}, - createdAt: {type: 'Date'}, - updatedAt: {type: 'Date'}, - objectId: {type: 'String'}, - aString: {type: 'String'}, - bString: {type: 'String'}, - cString: {type: 'String'}, - dString: {type: 'String'}, - }, - classLevelPermissions: defaultClassLevelPermissions, - indexes: { - _id_: { _id: 1 }, - name1: { aString: 1 }, - name2: { bString: 1 }, - name3: { cString: 1 }, - } - })).toEqual(undefined); + body: {}, + }, () => { request.put({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, body: { + fields: { + aString: {type: 'String'}, + bString: {type: 'String'}, + cString: {type: 'String'}, + dString: {type: 'String'}, + }, indexes: { - name1: { __op: 'Delete' }, - name2: { __op: 'Delete' }, - name4: { dString: 1 }, + name1: { aString: 1 }, + name2: { bString: 1 }, + name3: { cString: 1 }, } } }, (error, response, body) => { - expect(body).toEqual({ + expect(dd(body, { className: 'NewClass', fields: { ACL: {type: 'ACL'}, @@ -2329,150 +2297,183 @@ describe('schemas', () => { classLevelPermissions: defaultClassLevelPermissions, indexes: { _id_: { _id: 1 }, + name1: { aString: 1 }, + name2: { bString: 1 }, name3: { cString: 1 }, - name4: { dString: 1 }, } - }); - config.database.adapter.getIndexes('NewClass').then((indexes) => { - expect(indexes.length).toEqual(3); - done(); + })).toEqual(undefined); + request.put({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: { + indexes: { + name1: { __op: 'Delete' }, + name2: { __op: 'Delete' }, + name4: { dString: 1 }, + } + } + }, (error, response, body) => { + expect(body).toEqual({ + className: 'NewClass', + fields: { + ACL: {type: 'ACL'}, + createdAt: {type: 'Date'}, + updatedAt: {type: 'Date'}, + objectId: {type: 'String'}, + aString: {type: 'String'}, + bString: {type: 'String'}, + cString: {type: 'String'}, + dString: {type: 'String'}, + }, + classLevelPermissions: defaultClassLevelPermissions, + indexes: { + _id_: { _id: 1 }, + name3: { cString: 1 }, + name4: { dString: 1 }, + } + }); + config.database.adapter.getIndexes('NewClass').then((indexes) => { + expect(indexes.length).toEqual(3); + done(); + }); }); }); - }); - }) - }); + }) + }); - it('cannot delete index that does not exist', done => { - request.post({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - body: {}, - }, () => { - request.put({ + it('cannot delete index that does not exist', done => { + request.post({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, - body: { - indexes: { - unknownIndex: { __op: 'Delete' } + body: {}, + }, () => { + request.put({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: { + indexes: { + unknownIndex: { __op: 'Delete' } + } } - } - }, (error, response, body) => { - expect(body.code).toBe(Parse.Error.INVALID_QUERY); - expect(body.error).toBe('Index unknownIndex does not exist, cannot delete.'); - done(); - }); - }) - }); + }, (error, response, body) => { + expect(body.code).toBe(Parse.Error.INVALID_QUERY); + expect(body.error).toBe('Index unknownIndex does not exist, cannot delete.'); + done(); + }); + }) + }); - it('cannot update index that exist', done => { - request.post({ - url: 'http://localhost:8378/1/schemas/NewClass', - headers: masterKeyHeaders, - json: true, - body: {}, - }, () => { - request.put({ + it('cannot update index that exist', done => { + request.post({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, - body: { - fields: { - aString: {type: 'String'}, - }, - indexes: { - name1: { aString: 1 } - } - } + body: {}, }, () => { request.put({ url: 'http://localhost:8378/1/schemas/NewClass', headers: masterKeyHeaders, json: true, body: { + fields: { + aString: {type: 'String'}, + }, indexes: { - name1: { field2: 1 } + name1: { aString: 1 } } } + }, () => { + request.put({ + url: 'http://localhost:8378/1/schemas/NewClass', + headers: masterKeyHeaders, + json: true, + body: { + indexes: { + name1: { field2: 1 } + } + } + }, (error, response, body) => { + expect(body.code).toBe(Parse.Error.INVALID_QUERY); + expect(body.error).toBe('Index name1 exists, cannot update.'); + done(); + }); + }); + }) + }); + + it_exclude_dbs(['postgres'])('get indexes on startup', (done) => { + const obj = new Parse.Object('TestObject'); + obj.save().then(() => { + return reconfigureServer({ + appId: 'test', + restAPIKey: 'test', + publicServerURL: 'http://localhost:8378/1', + }); + }).then(() => { + request.get({ + url: 'http://localhost:8378/1/schemas/TestObject', + headers: masterKeyHeaders, + json: true, }, (error, response, body) => { - expect(body.code).toBe(Parse.Error.INVALID_QUERY); - expect(body.error).toBe('Index name1 exists, cannot update.'); + expect(body.indexes._id_).toBeDefined(); done(); }); }); - }) - }); + }); - it_exclude_dbs(['postgres'])('get indexes on startup', (done) => { - const obj = new Parse.Object('TestObject'); - obj.save().then(() => { - return reconfigureServer({ - appId: 'test', - restAPIKey: 'test', - publicServerURL: 'http://localhost:8378/1', - }); - }).then(() => { - request.get({ - url: 'http://localhost:8378/1/schemas/TestObject', - headers: masterKeyHeaders, - json: true, - }, (error, response, body) => { - expect(body.indexes._id_).toBeDefined(); - done(); + it_exclude_dbs(['postgres'])('get compound indexes on startup', (done) => { + const obj = new Parse.Object('TestObject'); + obj.set('subject', 'subject'); + obj.set('comment', 'comment'); + obj.save().then(() => { + return config.database.adapter.createIndex('TestObject', {subject: 'text', comment: 'text'}); + }).then(() => { + return reconfigureServer({ + appId: 'test', + restAPIKey: 'test', + publicServerURL: 'http://localhost:8378/1', + }); + }).then(() => { + request.get({ + url: 'http://localhost:8378/1/schemas/TestObject', + headers: masterKeyHeaders, + json: true, + }, (error, response, body) => { + 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(); + }); }); }); - }); - it_exclude_dbs(['postgres'])('get compound indexes on startup', (done) => { - const obj = new Parse.Object('TestObject'); - obj.set('subject', 'subject'); - obj.set('comment', 'comment'); - obj.save().then(() => { - return config.database.adapter.createIndex('TestObject', {subject: 'text', comment: 'text'}); - }).then(() => { - return reconfigureServer({ - appId: 'test', - restAPIKey: 'test', - publicServerURL: 'http://localhost:8378/1', - }); - }).then(() => { - request.get({ - url: 'http://localhost:8378/1/schemas/TestObject', - headers: masterKeyHeaders, - json: true, - }, (error, response, body) => { - 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'); + it_exclude_dbs(['postgres'])('cannot update to duplicate value on unique index', (done) => { + const index = { + code: 1 + }; + const obj1 = new Parse.Object('UniqueIndexClass'); + obj1.set('code', 1); + const obj2 = new Parse.Object('UniqueIndexClass'); + obj2.set('code', 2); + const adapter = config.database.adapter; + adapter._adaptiveCollection('UniqueIndexClass').then(collection => { + return collection._ensureSparseUniqueIndexInBackground(index); + }).then(() => { + return obj1.save(); + }).then(() => { + return obj2.save(); + }).then(() => { + obj1.set('code', 2); + return obj1.save(); + }).then(done.fail).catch((error) => { + expect(error.code).toEqual(Parse.Error.DUPLICATE_VALUE); done(); }); }); }); - - it_exclude_dbs(['postgres'])('cannot update to duplicate value on unique index', (done) => { - const index = { - code: 1 - }; - const obj1 = new Parse.Object('UniqueIndexClass'); - obj1.set('code', 1); - const obj2 = new Parse.Object('UniqueIndexClass'); - obj2.set('code', 2); - const adapter = config.database.adapter; - adapter._adaptiveCollection('UniqueIndexClass').then(collection => { - return collection._ensureSparseUniqueIndexInBackground(index); - }).then(() => { - return obj1.save(); - }).then(() => { - return obj2.save(); - }).then(() => { - obj1.set('code', 2); - return obj1.save(); - }).then(done.fail).catch((error) => { - expect(error.code).toEqual(Parse.Error.DUPLICATE_VALUE); - done(); - }); - }); }); diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index ca55e3a904..a150be1a40 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -31,6 +31,22 @@ const MongoClient = mongodb.MongoClient; const ReadPreference = mongodb.ReadPreference; const MongoSchemaCollectionName = '_SCHEMA'; + +const storageAdapterAllCollections = mongoAdapter => { + return mongoAdapter.connect() + .then(() => mongoAdapter.database.collections()) + .then(collections => { + return collections.filter(collection => { + if (collection.namespace.match(/\.system\./)) { + return false; + } + // TODO: If you have one app with a collection prefix that happens to be a prefix of another + // apps prefix, this will go very very badly. We should fix that somehow. + return (collection.collectionName.indexOf(mongoAdapter._collectionPrefix) == 0); + }); + }); +} + const convertParseSchemaToMongoSchema = ({...schema}) => { delete schema.fields._rperm; delete schema.fields._wperm; @@ -297,9 +313,9 @@ export class MongoStorageAdapter implements StorageAdapter { .catch(err => this.handleError(err)); } - dropDatabase() { - if (!this.database) { return Promise.resolve(); } - return this.database.dropDatabase(); + deleteAllClasses(fast: boolean) { + return storageAdapterAllCollections(this) + .then(collections => Promise.all(collections.map(collection => fast ? collection.remove({}) : collection.drop()))); } // Remove the column and all the data. For Relations, the _Join collection is handled diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js index 332c178d1f..2df5abb66d 100644 --- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -959,10 +959,6 @@ export class PostgresStorageAdapter implements StorageAdapter { }); } - dropDatabase() { - return this.deleteAllClasses(); - } - // Remove the column and all the data. For Relations, the _Join collection is handled // specially, this function does not delete _Join columns. It should, however, indicate // that the relation fields does not exist anymore. In mongo, this means removing it from diff --git a/src/Adapters/Storage/StorageAdapter.js b/src/Adapters/Storage/StorageAdapter.js index a5a9b9022c..ed2c2e0701 100644 --- a/src/Adapters/Storage/StorageAdapter.js +++ b/src/Adapters/Storage/StorageAdapter.js @@ -31,7 +31,7 @@ export interface StorageAdapter { createClass(className: string, schema: SchemaType): Promise; addFieldIfNotExists(className: string, fieldName: string, type: any): Promise; deleteClass(className: string): Promise; - dropDatabase(): Promise; + deleteAllClasses(fast: boolean): Promise; deleteFields(className: string, schema: SchemaType, fieldNames: Array): Promise; getAllClasses(): Promise; getClass(className: string): Promise; diff --git a/src/Controllers/DatabaseController.js b/src/Controllers/DatabaseController.js index 7de82a1053..f4e28059ee 100644 --- a/src/Controllers/DatabaseController.js +++ b/src/Controllers/DatabaseController.js @@ -426,7 +426,7 @@ class DatabaseController { throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid field name for update: ${fieldName}`); } }); - for (const updateOperation: any in update) { + for (const updateOperation in update) { if (Object.keys(updateOperation).some(innerKey => innerKey.includes('$') || innerKey.includes('.'))) { throw new Parse.Error(Parse.Error.INVALID_NESTED_KEY, "Nested keys should not contain the '$' or '.' characters"); } @@ -654,11 +654,16 @@ class DatabaseController { } // Won't delete collections in the system namespace - // Returns a promise. - deleteEverything() { + /** + * Delete all classes and clears the schema cache + * + * @param {boolean} fast set to true if it's ok to just delete rows and not indexes + * @returns {Promise} when the deletions completes + */ + deleteEverything(fast: boolean = false): Promise { this.schemaPromise = null; return Promise.all([ - this.adapter.dropDatabase(), + this.adapter.deleteAllClasses(fast), this.schemaCache.clear() ]); } diff --git a/src/TestUtils.js b/src/TestUtils.js index b0ebf4cf5b..ef2fdee81e 100644 --- a/src/TestUtils.js +++ b/src/TestUtils.js @@ -1,14 +1,17 @@ import AppCache from './cache'; -//Used by tests -export function destroyAllDataPermanently() { +/** + * Destroys all data in the database + * @param {boolean} fast set to true if it's ok to just drop objects and not indexes. + */ +export function destroyAllDataPermanently(fast) { if (!process.env.TESTING) { throw 'Only supported in test environment'; } return Promise.all(Object.keys(AppCache.cache).map(appId => { const app = AppCache.get(appId); if (app.databaseController) { - return app.databaseController.deleteEverything(); + return app.databaseController.deleteEverything(fast); } else { return Promise.resolve(); }