Merge pull request #498 from drew-gross/test-configurations
Add ability to test multiple server configurations
This commit is contained in:
@@ -7,14 +7,17 @@ var DatabaseAdapter = require('../src/DatabaseAdapter');
|
|||||||
var express = require('express');
|
var express = require('express');
|
||||||
var facebook = require('../src/oauth/facebook');
|
var facebook = require('../src/oauth/facebook');
|
||||||
var ParseServer = require('../src/index').ParseServer;
|
var ParseServer = require('../src/index').ParseServer;
|
||||||
|
var DatabaseAdapter = require('../src/DatabaseAdapter');
|
||||||
|
|
||||||
var databaseURI = process.env.DATABASE_URI;
|
var databaseURI = process.env.DATABASE_URI;
|
||||||
var cloudMain = process.env.CLOUD_CODE_MAIN || './cloud/main.js';
|
var cloudMain = process.env.CLOUD_CODE_MAIN || './cloud/main.js';
|
||||||
|
var port = 8378;
|
||||||
|
|
||||||
// Set up an API server for testing
|
// Default server configuration for tests.
|
||||||
var api = new ParseServer({
|
var defaultConfiguration = {
|
||||||
databaseURI: databaseURI,
|
databaseURI: databaseURI,
|
||||||
cloud: cloudMain,
|
cloud: cloudMain,
|
||||||
|
serverURL: 'http://localhost:' + port + '/1',
|
||||||
appId: 'test',
|
appId: 'test',
|
||||||
javascriptKey: 'test',
|
javascriptKey: 'test',
|
||||||
dotNetKey: 'windows',
|
dotNetKey: 'windows',
|
||||||
@@ -29,13 +32,29 @@ var api = new ParseServer({
|
|||||||
module: "../spec/myoauth" // relative path as it's run from src
|
module: "../spec/myoauth" // relative path as it's run from src
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
// Set up a default API server for testing with default configuration.
|
||||||
|
var api = new ParseServer(defaultConfiguration);
|
||||||
var app = express();
|
var app = express();
|
||||||
app.use('/1', api);
|
app.use('/1', api);
|
||||||
var port = 8378;
|
|
||||||
var server = app.listen(port);
|
var server = app.listen(port);
|
||||||
|
|
||||||
|
// Prevent reinitializing the server from clobbering Cloud Code
|
||||||
|
delete defaultConfiguration.cloud;
|
||||||
|
|
||||||
|
// Allows testing specific configurations of Parse Server
|
||||||
|
var setServerConfiguration = configuration => {
|
||||||
|
api = new ParseServer(configuration);
|
||||||
|
app = express();
|
||||||
|
app.use('/1', api);
|
||||||
|
cache.clearCache();
|
||||||
|
server.close();
|
||||||
|
server = app.listen(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
var restoreServerConfiguration = () => setServerConfiguration(defaultConfiguration);
|
||||||
|
|
||||||
// Set up a Parse client to talk to our test API server
|
// Set up a Parse client to talk to our test API server
|
||||||
var Parse = require('parse/node');
|
var Parse = require('parse/node');
|
||||||
Parse.serverURL = 'http://localhost:' + port + '/1';
|
Parse.serverURL = 'http://localhost:' + port + '/1';
|
||||||
@@ -51,9 +70,11 @@ beforeEach(function(done) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function(done) {
|
afterEach(function(done) {
|
||||||
|
restoreServerConfiguration();
|
||||||
Parse.User.logOut().then(() => {
|
Parse.User.logOut().then(() => {
|
||||||
return clearData();
|
return clearData();
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
DatabaseAdapter.clearDatabaseURIs();
|
||||||
done();
|
done();
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
console.log('error in clearData', error);
|
console.log('error in clearData', error);
|
||||||
@@ -221,3 +242,4 @@ global.expectError = expectError;
|
|||||||
global.arrayContains = arrayContains;
|
global.arrayContains = arrayContains;
|
||||||
global.jequal = jequal;
|
global.jequal = jequal;
|
||||||
global.range = range;
|
global.range = range;
|
||||||
|
global.setServerConfiguration = setServerConfiguration;
|
||||||
|
|||||||
39
spec/index.spec.js
Normal file
39
spec/index.spec.js
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
var request = require('request');
|
||||||
|
|
||||||
|
describe('server', () => {
|
||||||
|
it('requires a master key and app id', done => {
|
||||||
|
expect(setServerConfiguration.bind(undefined, { masterKey: 'mykey' })).toThrow('You must provide an appId and masterKey!');
|
||||||
|
expect(setServerConfiguration.bind(undefined, { appId: 'myId' })).toThrow('You must provide an appId and masterKey!');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fails if database is unreachable', done => {
|
||||||
|
setServerConfiguration({
|
||||||
|
databaseURI: 'mongodb://fake:fake@ds043605.mongolab.com:43605/drew3',
|
||||||
|
serverURL: 'http://localhost:8378/1',
|
||||||
|
appId: 'test',
|
||||||
|
javascriptKey: 'test',
|
||||||
|
dotNetKey: 'windows',
|
||||||
|
clientKey: 'client',
|
||||||
|
restAPIKey: 'rest',
|
||||||
|
masterKey: 'test',
|
||||||
|
collectionPrefix: 'test_',
|
||||||
|
fileKey: 'test',
|
||||||
|
});
|
||||||
|
//Need to use rest api because saving via JS SDK results in fail() not getting called
|
||||||
|
request.post({
|
||||||
|
url: 'http://localhost:8378/1/classes/NewClass',
|
||||||
|
headers: {
|
||||||
|
'X-Parse-Application-Id': 'test',
|
||||||
|
'X-Parse-REST-API-Key': 'rest',
|
||||||
|
},
|
||||||
|
body: {},
|
||||||
|
json: true,
|
||||||
|
}, (error, response, body) => {
|
||||||
|
expect(response.statusCode).toEqual(500);
|
||||||
|
expect(body.code).toEqual(1);
|
||||||
|
expect(body.message).toEqual('Internal server error.');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -34,6 +34,12 @@ function setAppDatabaseURI(appId, uri) {
|
|||||||
appDatabaseURIs[appId] = uri;
|
appDatabaseURIs[appId] = uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Used by tests
|
||||||
|
function clearDatabaseURIs() {
|
||||||
|
appDatabaseURIs = {};
|
||||||
|
dbConnections = {};
|
||||||
|
}
|
||||||
|
|
||||||
function getDatabaseConnection(appId) {
|
function getDatabaseConnection(appId) {
|
||||||
if (dbConnections[appId]) {
|
if (dbConnections[appId]) {
|
||||||
return dbConnections[appId];
|
return dbConnections[appId];
|
||||||
@@ -52,5 +58,6 @@ module.exports = {
|
|||||||
getDatabaseConnection: getDatabaseConnection,
|
getDatabaseConnection: getDatabaseConnection,
|
||||||
setAdapter: setAdapter,
|
setAdapter: setAdapter,
|
||||||
setDatabaseURI: setDatabaseURI,
|
setDatabaseURI: setDatabaseURI,
|
||||||
setAppDatabaseURI: setAppDatabaseURI
|
setAppDatabaseURI: setAppDatabaseURI,
|
||||||
|
clearDatabaseURIs: clearDatabaseURIs,
|
||||||
};
|
};
|
||||||
|
|||||||
10
src/cache.js
10
src/cache.js
@@ -25,6 +25,13 @@ function clearUser(sessionToken) {
|
|||||||
delete users[sessionToken];
|
delete users[sessionToken];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//So far used only in tests
|
||||||
|
function clearCache() {
|
||||||
|
apps = {};
|
||||||
|
stats = {};
|
||||||
|
users = {};
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
apps: apps,
|
apps: apps,
|
||||||
stats: stats,
|
stats: stats,
|
||||||
@@ -33,5 +40,6 @@ module.exports = {
|
|||||||
updateStat: updateStat,
|
updateStat: updateStat,
|
||||||
clearUser: clearUser,
|
clearUser: clearUser,
|
||||||
getUser: getUser,
|
getUser: getUser,
|
||||||
setUser: setUser
|
setUser: setUser,
|
||||||
|
clearCache: clearCache,
|
||||||
};
|
};
|
||||||
|
|||||||
101
src/index.js
101
src/index.js
@@ -11,21 +11,21 @@ var batch = require('./batch'),
|
|||||||
PromiseRouter = require('./PromiseRouter'),
|
PromiseRouter = require('./PromiseRouter'),
|
||||||
httpRequest = require('./httpRequest');
|
httpRequest = require('./httpRequest');
|
||||||
|
|
||||||
import { GridStoreAdapter } from './Adapters/Files/GridStoreAdapter';
|
import { GridStoreAdapter } from './Adapters/Files/GridStoreAdapter';
|
||||||
import { S3Adapter } from './Adapters/Files/S3Adapter';
|
import { S3Adapter } from './Adapters/Files/S3Adapter';
|
||||||
import { FilesController } from './Controllers/FilesController';
|
import { FilesController } from './Controllers/FilesController';
|
||||||
|
|
||||||
import ParsePushAdapter from './Adapters/Push/ParsePushAdapter';
|
import ParsePushAdapter from './Adapters/Push/ParsePushAdapter';
|
||||||
import { PushController } from './Controllers/PushController';
|
import { PushController } from './Controllers/PushController';
|
||||||
|
|
||||||
import { ClassesRouter } from './Routers/ClassesRouter';
|
import { ClassesRouter } from './Routers/ClassesRouter';
|
||||||
import { InstallationsRouter } from './Routers/InstallationsRouter';
|
import { InstallationsRouter } from './Routers/InstallationsRouter';
|
||||||
import { UsersRouter } from './Routers/UsersRouter';
|
import { UsersRouter } from './Routers/UsersRouter';
|
||||||
import { SessionsRouter } from './Routers/SessionsRouter';
|
import { SessionsRouter } from './Routers/SessionsRouter';
|
||||||
import { RolesRouter } from './Routers/RolesRouter';
|
import { RolesRouter } from './Routers/RolesRouter';
|
||||||
|
|
||||||
import { FileLoggerAdapter } from './Adapters/Logger/FileLoggerAdapter';
|
import { FileLoggerAdapter } from './Adapters/Logger/FileLoggerAdapter';
|
||||||
import { LoggerController } from './Controllers/LoggerController';
|
import { LoggerController } from './Controllers/LoggerController';
|
||||||
|
|
||||||
// Mutate the Parse object to add the Cloud Code handlers
|
// Mutate the Parse object to add the Cloud Code handlers
|
||||||
addParseCloud();
|
addParseCloud();
|
||||||
@@ -54,20 +54,36 @@ addParseCloud();
|
|||||||
// "javascriptKey": optional key from Parse dashboard
|
// "javascriptKey": optional key from Parse dashboard
|
||||||
// "push": optional key from configure push
|
// "push": optional key from configure push
|
||||||
|
|
||||||
function ParseServer(args) {
|
function ParseServer({
|
||||||
if (!args.appId || !args.masterKey) {
|
appId,
|
||||||
|
masterKey,
|
||||||
|
databaseAdapter,
|
||||||
|
filesAdapter = new GridStoreAdapter(),
|
||||||
|
push,
|
||||||
|
loggerAdapter = new FileLoggerAdapter(),
|
||||||
|
databaseURI,
|
||||||
|
cloud,
|
||||||
|
collectionPrefix = '',
|
||||||
|
clientKey = '',
|
||||||
|
javascriptKey = '',
|
||||||
|
dotNetKey = '',
|
||||||
|
restAPIKey = '',
|
||||||
|
fileKey = 'invalid-file-key',
|
||||||
|
facebookAppIds = [],
|
||||||
|
enableAnonymousUsers = true,
|
||||||
|
oauth = {},
|
||||||
|
serverURL = '',
|
||||||
|
}) {
|
||||||
|
if (!appId || !masterKey) {
|
||||||
throw 'You must provide an appId and masterKey!';
|
throw 'You must provide an appId and masterKey!';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.databaseAdapter) {
|
if (databaseAdapter) {
|
||||||
DatabaseAdapter.setAdapter(args.databaseAdapter);
|
DatabaseAdapter.setAdapter(databaseAdapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make files adapter
|
|
||||||
let filesAdapter = args.filesAdapter || new GridStoreAdapter();
|
|
||||||
|
|
||||||
// Make push adapter
|
// Make push adapter
|
||||||
let pushConfig = args.push;
|
let pushConfig = push;
|
||||||
let pushAdapter;
|
let pushAdapter;
|
||||||
if (pushConfig && pushConfig.adapter) {
|
if (pushConfig && pushConfig.adapter) {
|
||||||
pushAdapter = pushConfig.adapter;
|
pushAdapter = pushConfig.adapter;
|
||||||
@@ -75,48 +91,44 @@ function ParseServer(args) {
|
|||||||
pushAdapter = new ParsePushAdapter(pushConfig)
|
pushAdapter = new ParsePushAdapter(pushConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make logger adapter
|
if (databaseURI) {
|
||||||
let loggerAdapter = args.loggerAdapter || new FileLoggerAdapter();
|
DatabaseAdapter.setAppDatabaseURI(appId, databaseURI);
|
||||||
|
|
||||||
if (args.databaseURI) {
|
|
||||||
DatabaseAdapter.setAppDatabaseURI(args.appId, args.databaseURI);
|
|
||||||
}
|
}
|
||||||
if (args.cloud) {
|
if (cloud) {
|
||||||
addParseCloud();
|
addParseCloud();
|
||||||
if (typeof args.cloud === 'function') {
|
if (typeof cloud === 'function') {
|
||||||
args.cloud(Parse)
|
cloud(Parse)
|
||||||
} else if (typeof args.cloud === 'string') {
|
} else if (typeof cloud === 'string') {
|
||||||
require(args.cloud);
|
require(cloud);
|
||||||
} else {
|
} else {
|
||||||
throw "argument 'cloud' must either be a string or a function";
|
throw "argument 'cloud' must either be a string or a function";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let filesController = new FilesController(filesAdapter);
|
let filesController = new FilesController(filesAdapter);
|
||||||
|
|
||||||
cache.apps[args.appId] = {
|
cache.apps[appId] = {
|
||||||
masterKey: args.masterKey,
|
masterKey: masterKey,
|
||||||
collectionPrefix: args.collectionPrefix || '',
|
collectionPrefix: collectionPrefix,
|
||||||
clientKey: args.clientKey || '',
|
clientKey: clientKey,
|
||||||
javascriptKey: args.javascriptKey || '',
|
javascriptKey: javascriptKey,
|
||||||
dotNetKey: args.dotNetKey || '',
|
dotNetKey: dotNetKey,
|
||||||
restAPIKey: args.restAPIKey || '',
|
restAPIKey: restAPIKey,
|
||||||
fileKey: args.fileKey || 'invalid-file-key',
|
fileKey: fileKey,
|
||||||
facebookAppIds: args.facebookAppIds || [],
|
facebookAppIds: facebookAppIds,
|
||||||
filesController: filesController,
|
filesController: filesController,
|
||||||
enableAnonymousUsers: args.enableAnonymousUsers || true,
|
enableAnonymousUsers: enableAnonymousUsers,
|
||||||
oauth: args.oauth || {},
|
oauth: oauth,
|
||||||
};
|
};
|
||||||
|
|
||||||
// To maintain compatibility. TODO: Remove in v2.1
|
// To maintain compatibility. TODO: Remove in v2.1
|
||||||
if (process.env.FACEBOOK_APP_ID) {
|
if (process.env.FACEBOOK_APP_ID) {
|
||||||
cache.apps[args.appId]['facebookAppIds'].push(process.env.FACEBOOK_APP_ID);
|
cache.apps[appId]['facebookAppIds'].push(process.env.FACEBOOK_APP_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the node client SDK automatically
|
// Initialize the node client SDK automatically
|
||||||
Parse.initialize(args.appId, args.javascriptKey || '', args.masterKey);
|
Parse.initialize(appId, javascriptKey, masterKey);
|
||||||
Parse.serverURL = args.serverURL || '';
|
Parse.serverURL = serverURL;
|
||||||
|
|
||||||
// This app serves the Parse API directly.
|
// This app serves the Parse API directly.
|
||||||
// It's the equivalent of https://api.parse.com/1 in the hosted Parse API.
|
// It's the equivalent of https://api.parse.com/1 in the hosted Parse API.
|
||||||
@@ -127,7 +139,6 @@ function ParseServer(args) {
|
|||||||
|
|
||||||
// TODO: separate this from the regular ParseServer object
|
// TODO: separate this from the regular ParseServer object
|
||||||
if (process.env.TESTING == 1) {
|
if (process.env.TESTING == 1) {
|
||||||
console.log('enabling integration testing-routes');
|
|
||||||
api.use('/', require('./testing-routes').router);
|
api.use('/', require('./testing-routes').router);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user