Even faster tests (#4868)
* Various improvements in test name / de-duplications * Reverts to class by class deletion, introduced fast mode that just delete data for mongo - Speeds up are incredible Executed 1695 of 1713 specs INCOMPLETE (18 PENDING) in 4 mins 19 secs. * Adds documentation about the deleteEverything
This commit is contained in:
@@ -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({
|
const authenticationHandler = authenticationLoader({
|
||||||
customAuthentication: { module: path.resolve('./spec/support/CustomAuthFunction.js'), options: { token: 'valid-token' }}
|
customAuthentication: { module: path.resolve('./spec/support/CustomAuthFunction.js'), options: { token: 'valid-token' }}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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) => {
|
it("should post on echo", (done) => {
|
||||||
let calls = 0;
|
let calls = 0;
|
||||||
httpRequest({
|
httpRequest({
|
||||||
|
|||||||
@@ -50,11 +50,11 @@ describe('JobSchedule', () => {
|
|||||||
rp.put(Parse.serverURL + '/cloud_code/jobs/jobId', defaultOptions).then(done.fail, () => done());
|
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());
|
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);
|
rp.get(Parse.serverURL + '/cloud_code/jobs', masterKeyOptions).then(done, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ const LoggerController = require('../lib/Controllers/LoggerController').LoggerCo
|
|||||||
const WinstonLoggerAdapter = require('../lib/Adapters/Logger/WinstonLoggerAdapter').WinstonLoggerAdapter;
|
const WinstonLoggerAdapter = require('../lib/Adapters/Logger/WinstonLoggerAdapter').WinstonLoggerAdapter;
|
||||||
|
|
||||||
describe('LoggerController', () => {
|
describe('LoggerController', () => {
|
||||||
it('can check process a query without throwing', (done) => {
|
it('can process an empty query without throwing', (done) => {
|
||||||
// Make mock request
|
// Make mock request
|
||||||
const query = {};
|
const query = {};
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ describe('LoggerController', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can process a query without throwing', (done) => {
|
it('can process an ascending query without throwing', (done) => {
|
||||||
// Make mock request
|
// Make mock request
|
||||||
const query = {
|
const query = {
|
||||||
from: "2016-01-01Z00:00:00",
|
from: "2016-01-01Z00:00:00",
|
||||||
@@ -58,7 +58,7 @@ describe('LoggerController', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can check process a query without throwing', (done) => {
|
it('can process a descending query without throwing', (done) => {
|
||||||
// Make mock request
|
// Make mock request
|
||||||
const query = {
|
const query = {
|
||||||
from: "2016-01-01",
|
from: "2016-01-01",
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const databaseURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDataba
|
|||||||
describe_only_db('mongo')('MongoStorageAdapter', () => {
|
describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||||
beforeEach(done => {
|
beforeEach(done => {
|
||||||
new MongoStorageAdapter({ uri: databaseURI })
|
new MongoStorageAdapter({ uri: databaseURI })
|
||||||
.dropDatabase()
|
.deleteAllClasses()
|
||||||
.then(done, fail);
|
.then(done, fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ describe('parseObjectToMongoObjectForCreate', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('built-in timestamps', (done) => {
|
it('built-in timestamps with date', (done) => {
|
||||||
const input = {
|
const input = {
|
||||||
createdAt: "2015-10-06T21:24:50.332Z",
|
createdAt: "2015-10-06T21:24:50.332Z",
|
||||||
updatedAt: "2015-10-06T21:24:50.332Z"
|
updatedAt: "2015-10-06T21:24:50.332Z"
|
||||||
|
|||||||
@@ -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 => {
|
it('fails to delete an unkown file', done => {
|
||||||
const headers = {
|
const headers = {
|
||||||
'Content-Type': 'application/octet-stream',
|
'Content-Type': 'application/octet-stream',
|
||||||
|
|||||||
@@ -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) {
|
app.post("/SomeFunctionError", function(req, res) {
|
||||||
res.json({error: {code: 1337, error: "hacking that one!"}});
|
res.json({error: {code: 1337, error: "hacking that one!"}});
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ const defaultHeaders = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('Parse.Polygon testing', () => {
|
describe('Parse.Polygon testing', () => {
|
||||||
|
|
||||||
|
beforeAll(() => require('../lib/TestUtils').destroyAllDataPermanently());
|
||||||
|
|
||||||
it('polygon save open path', (done) => {
|
it('polygon save open path', (done) => {
|
||||||
const coords = [[0,0],[0,1],[1,1],[1,0]];
|
const coords = [[0,0],[0,1],[1,1],[1,0]];
|
||||||
const closed = [[0,0],[0,1],[1,1],[1,0],[0,0]];
|
const closed = [[0,0],[0,1],[1,1],[1,0],[0,0]];
|
||||||
@@ -128,144 +131,150 @@ describe('Parse.Polygon testing', () => {
|
|||||||
}, done.fail);
|
}, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('polygonContain query', (done) => {
|
describe('with location', () => {
|
||||||
const points1 = [[0,0],[0,1],[1,1],[1,0]];
|
beforeAll(() => require('../lib/TestUtils').destroyAllDataPermanently());
|
||||||
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);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('polygonContain query no reverse input (Regression test for #4608)', (done) => {
|
it('polygonContain query', (done) => {
|
||||||
const points1 = [[.25,0],[.25,1.25],[.75,1.25],[.75,0]];
|
const points1 = [[0,0],[0,1],[1,1],[1,0]];
|
||||||
const points2 = [[0,0],[0,2],[2,2],[2,0]];
|
const points2 = [[0,0],[0,2],[2,2],[2,0]];
|
||||||
const points3 = [[10,10],[10,15],[15,15],[15,10],[10,10]];
|
const points3 = [[10,10],[10,15],[15,15],[15,10],[10,10]];
|
||||||
const polygon1 = new Parse.Polygon(points1);
|
const polygon1 = new Parse.Polygon(points1);
|
||||||
const polygon2 = new Parse.Polygon(points2);
|
const polygon2 = new Parse.Polygon(points2);
|
||||||
const polygon3 = new Parse.Polygon(points3);
|
const polygon3 = new Parse.Polygon(points3);
|
||||||
const obj1 = new TestObject({location: polygon1});
|
const obj1 = new TestObject({location: polygon1});
|
||||||
const obj2 = new TestObject({location: polygon2});
|
const obj2 = new TestObject({location: polygon2});
|
||||||
const obj3 = new TestObject({location: polygon3});
|
const obj3 = new TestObject({location: polygon3});
|
||||||
Parse.Object.saveAll([obj1, obj2, obj3]).then(() => {
|
Parse.Object.saveAll([obj1, obj2, obj3]).then(() => {
|
||||||
const where = {
|
const where = {
|
||||||
location: {
|
location: {
|
||||||
$geoIntersects: {
|
$geoIntersects: {
|
||||||
$point: { __type: 'GeoPoint', latitude: 0.5, longitude:1.0 }
|
$point: { __type: 'GeoPoint', latitude: 0.5, longitude: 0.5 }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
return rp.post({
|
||||||
return rp.post({
|
url: Parse.serverURL + '/classes/TestObject',
|
||||||
url: Parse.serverURL + '/classes/TestObject',
|
json: { where, '_method': 'GET' },
|
||||||
json: { where, '_method': 'GET' },
|
headers: {
|
||||||
headers: {
|
'X-Parse-Application-Id': Parse.applicationId,
|
||||||
'X-Parse-Application-Id': Parse.applicationId,
|
'X-Parse-Javascript-Key': Parse.javaScriptKey
|
||||||
'X-Parse-Javascript-Key': Parse.javaScriptKey
|
}
|
||||||
}
|
});
|
||||||
});
|
}).then((resp) => {
|
||||||
}).then((resp) => {
|
expect(resp.results.length).toBe(2);
|
||||||
expect(resp.results.length).toBe(2);
|
done();
|
||||||
done();
|
}, done.fail);
|
||||||
}, done.fail);
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('polygonContain query real data (Regression test for #4608)', (done) => {
|
it('polygonContain query no reverse input (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 points1 = [[.25,0],[.25,1.25],[.75,1.25],[.75,0]];
|
||||||
const polygon = new Parse.Polygon(detroit);
|
const points2 = [[0,0],[0,2],[2,2],[2,0]];
|
||||||
const obj = new TestObject({location: polygon});
|
const points3 = [[10,10],[10,15],[15,15],[15,10],[10,10]];
|
||||||
obj.save().then(() => {
|
const polygon1 = new Parse.Polygon(points1);
|
||||||
const where = {
|
const polygon2 = new Parse.Polygon(points2);
|
||||||
location: {
|
const polygon3 = new Parse.Polygon(points3);
|
||||||
$geoIntersects: {
|
const obj1 = new TestObject({location: polygon1});
|
||||||
$point: { __type: 'GeoPoint', latitude: 42.624599, longitude:-83.770162 }
|
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({
|
||||||
return rp.post({
|
url: Parse.serverURL + '/classes/TestObject',
|
||||||
url: Parse.serverURL + '/classes/TestObject',
|
json: { where, '_method': 'GET' },
|
||||||
json: { where, '_method': 'GET' },
|
headers: {
|
||||||
headers: {
|
'X-Parse-Application-Id': Parse.applicationId,
|
||||||
'X-Parse-Application-Id': Parse.applicationId,
|
'X-Parse-Javascript-Key': Parse.javaScriptKey
|
||||||
'X-Parse-Javascript-Key': Parse.javaScriptKey
|
}
|
||||||
}
|
});
|
||||||
});
|
}).then((resp) => {
|
||||||
}).then((resp) => {
|
expect(resp.results.length).toBe(2);
|
||||||
expect(resp.results.length).toBe(1);
|
done();
|
||||||
done();
|
}, done.fail);
|
||||||
}, done.fail);
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('polygonContain invalid input', (done) => {
|
it('polygonContain query real data (Regression test for #4608)', (done) => {
|
||||||
const points = [[0,0],[0,1],[1,1],[1,0]];
|
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(points);
|
const polygon = new Parse.Polygon(detroit);
|
||||||
const obj = new TestObject({location: polygon});
|
const obj = new TestObject({location: polygon});
|
||||||
obj.save().then(() => {
|
obj.save().then(() => {
|
||||||
const where = {
|
const where = {
|
||||||
location: {
|
location: {
|
||||||
$geoIntersects: {
|
$geoIntersects: {
|
||||||
$point: { __type: 'GeoPoint', latitude: 181, longitude: 181 }
|
$point: { __type: 'GeoPoint', latitude: 42.624599, longitude:-83.770162 }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
return rp.post({
|
||||||
return rp.post({
|
url: Parse.serverURL + '/classes/TestObject',
|
||||||
url: Parse.serverURL + '/classes/TestObject',
|
json: { where, '_method': 'GET' },
|
||||||
json: { where, '_method': 'GET' },
|
headers: {
|
||||||
headers: {
|
'X-Parse-Application-Id': Parse.applicationId,
|
||||||
'X-Parse-Application-Id': Parse.applicationId,
|
'X-Parse-Javascript-Key': Parse.javaScriptKey
|
||||||
'X-Parse-Javascript-Key': Parse.javaScriptKey
|
}
|
||||||
}
|
});
|
||||||
});
|
}).then((resp) => {
|
||||||
}).then(done.fail, () => done());
|
expect(resp.results.length).toBe(1);
|
||||||
});
|
done();
|
||||||
|
}, done.fail);
|
||||||
|
});
|
||||||
|
|
||||||
it('polygonContain invalid geoPoint', (done) => {
|
it('polygonContain invalid input', (done) => {
|
||||||
const points = [[0,0],[0,1],[1,1],[1,0]];
|
const points = [[0,0],[0,1],[1,1],[1,0]];
|
||||||
const polygon = new Parse.Polygon(points);
|
const polygon = new Parse.Polygon(points);
|
||||||
const obj = new TestObject({location: polygon});
|
const obj = new TestObject({location: polygon});
|
||||||
obj.save().then(() => {
|
obj.save().then(() => {
|
||||||
const where = {
|
const where = {
|
||||||
location: {
|
location: {
|
||||||
$geoIntersects: {
|
$geoIntersects: {
|
||||||
$point: []
|
$point: { __type: 'GeoPoint', latitude: 181, longitude: 181 }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
return rp.post({
|
||||||
return rp.post({
|
url: Parse.serverURL + '/classes/TestObject',
|
||||||
url: Parse.serverURL + '/classes/TestObject',
|
json: { where, '_method': 'GET' },
|
||||||
json: { where, '_method': 'GET' },
|
headers: {
|
||||||
headers: {
|
'X-Parse-Application-Id': Parse.applicationId,
|
||||||
'X-Parse-Application-Id': Parse.applicationId,
|
'X-Parse-Javascript-Key': Parse.javaScriptKey
|
||||||
'X-Parse-Javascript-Key': Parse.javaScriptKey
|
}
|
||||||
}
|
});
|
||||||
});
|
}).then(done.fail, () => done());
|
||||||
}).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: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
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', () => {
|
describe_only_db('mongo')('Parse.Polygon testing', () => {
|
||||||
|
|
||||||
|
beforeEach(() => require('../lib/TestUtils').destroyAllDataPermanently());
|
||||||
it('support 2d and 2dsphere', (done) => {
|
it('support 2d and 2dsphere', (done) => {
|
||||||
const coords = [[0,0],[0,1],[1,1],[1,0],[0,0]];
|
const coords = [[0,0],[0,1],[1,1],[1,0],[0,0]];
|
||||||
// testings against REST API, use raw formats
|
// testings against REST API, use raw formats
|
||||||
|
|||||||
@@ -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, {
|
Parse.User.signUp('asdf', 'zxcv', null, {
|
||||||
success: () => {
|
success: () => {
|
||||||
return rp.post({
|
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();
|
const provider = getMockFacebookProvider();
|
||||||
Parse.User._registerAuthenticationProvider(provider);
|
Parse.User._registerAuthenticationProvider(provider);
|
||||||
Parse.User._logInWith("facebook", {
|
Parse.User._logInWith("facebook", {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const dropTable = (client, className) => {
|
|||||||
describe_only_db('postgres')('PostgresStorageAdapter', () => {
|
describe_only_db('postgres')('PostgresStorageAdapter', () => {
|
||||||
const adapter = new PostgresStorageAdapter({ uri: databaseURI })
|
const adapter = new PostgresStorageAdapter({ uri: databaseURI })
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
return adapter.dropDatabase();
|
return adapter.deleteAllClasses();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('schemaUpgrade, upgrade the database schema when schema changes', done => {
|
it('schemaUpgrade, upgrade the database schema when schema changes', done => {
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ beforeEach(done => {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TestUtils.destroyAllDataPermanently()
|
TestUtils.destroyAllDataPermanently(true)
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
// For tests that connect to their own mongo, there won't be any data to delete.
|
// 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')) {
|
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');
|
fail('There were open connections to the server left after the test finished');
|
||||||
}
|
}
|
||||||
on_db('postgres', () => {
|
on_db('postgres', () => {
|
||||||
TestUtils.destroyAllDataPermanently().then(done, done);
|
TestUtils.destroyAllDataPermanently(true).then(done, done);
|
||||||
}, done);
|
}, done);
|
||||||
};
|
};
|
||||||
Parse.Cloud._removeAllHooks();
|
Parse.Cloud._removeAllHooks();
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,22 @@ const MongoClient = mongodb.MongoClient;
|
|||||||
const ReadPreference = mongodb.ReadPreference;
|
const ReadPreference = mongodb.ReadPreference;
|
||||||
|
|
||||||
const MongoSchemaCollectionName = '_SCHEMA';
|
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}) => {
|
const convertParseSchemaToMongoSchema = ({...schema}) => {
|
||||||
delete schema.fields._rperm;
|
delete schema.fields._rperm;
|
||||||
delete schema.fields._wperm;
|
delete schema.fields._wperm;
|
||||||
@@ -297,9 +313,9 @@ export class MongoStorageAdapter implements StorageAdapter {
|
|||||||
.catch(err => this.handleError(err));
|
.catch(err => this.handleError(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
dropDatabase() {
|
deleteAllClasses(fast: boolean) {
|
||||||
if (!this.database) { return Promise.resolve(); }
|
return storageAdapterAllCollections(this)
|
||||||
return this.database.dropDatabase();
|
.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
|
// Remove the column and all the data. For Relations, the _Join collection is handled
|
||||||
|
|||||||
@@ -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
|
// 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
|
// 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
|
// that the relation fields does not exist anymore. In mongo, this means removing it from
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export interface StorageAdapter {
|
|||||||
createClass(className: string, schema: SchemaType): Promise<void>;
|
createClass(className: string, schema: SchemaType): Promise<void>;
|
||||||
addFieldIfNotExists(className: string, fieldName: string, type: any): Promise<void>;
|
addFieldIfNotExists(className: string, fieldName: string, type: any): Promise<void>;
|
||||||
deleteClass(className: string): Promise<void>;
|
deleteClass(className: string): Promise<void>;
|
||||||
dropDatabase(): Promise<void>;
|
deleteAllClasses(fast: boolean): Promise<void>;
|
||||||
deleteFields(className: string, schema: SchemaType, fieldNames: Array<string>): Promise<void>;
|
deleteFields(className: string, schema: SchemaType, fieldNames: Array<string>): Promise<void>;
|
||||||
getAllClasses(): Promise<StorageClass[]>;
|
getAllClasses(): Promise<StorageClass[]>;
|
||||||
getClass(className: string): Promise<StorageClass>;
|
getClass(className: string): Promise<StorageClass>;
|
||||||
|
|||||||
@@ -426,7 +426,7 @@ class DatabaseController {
|
|||||||
throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid field name for update: ${fieldName}`);
|
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('.'))) {
|
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");
|
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
|
// 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<void>} when the deletions completes
|
||||||
|
*/
|
||||||
|
deleteEverything(fast: boolean = false): Promise<void> {
|
||||||
this.schemaPromise = null;
|
this.schemaPromise = null;
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
this.adapter.dropDatabase(),
|
this.adapter.deleteAllClasses(fast),
|
||||||
this.schemaCache.clear()
|
this.schemaCache.clear()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
import AppCache from './cache';
|
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) {
|
if (!process.env.TESTING) {
|
||||||
throw 'Only supported in test environment';
|
throw 'Only supported in test environment';
|
||||||
}
|
}
|
||||||
return Promise.all(Object.keys(AppCache.cache).map(appId => {
|
return Promise.all(Object.keys(AppCache.cache).map(appId => {
|
||||||
const app = AppCache.get(appId);
|
const app = AppCache.get(appId);
|
||||||
if (app.databaseController) {
|
if (app.databaseController) {
|
||||||
return app.databaseController.deleteEverything();
|
return app.databaseController.deleteEverything(fast);
|
||||||
} else {
|
} else {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user