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 facebook = require('../src/oauth/facebook');
|
||||
var ParseServer = require('../src/index').ParseServer;
|
||||
var DatabaseAdapter = require('../src/DatabaseAdapter');
|
||||
|
||||
var databaseURI = process.env.DATABASE_URI;
|
||||
var cloudMain = process.env.CLOUD_CODE_MAIN || './cloud/main.js';
|
||||
var port = 8378;
|
||||
|
||||
// Set up an API server for testing
|
||||
var api = new ParseServer({
|
||||
// Default server configuration for tests.
|
||||
var defaultConfiguration = {
|
||||
databaseURI: databaseURI,
|
||||
cloud: cloudMain,
|
||||
serverURL: 'http://localhost:' + port + '/1',
|
||||
appId: 'test',
|
||||
javascriptKey: 'test',
|
||||
dotNetKey: 'windows',
|
||||
@@ -29,13 +32,29 @@ var api = new ParseServer({
|
||||
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();
|
||||
app.use('/1', api);
|
||||
var port = 8378;
|
||||
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
|
||||
var Parse = require('parse/node');
|
||||
Parse.serverURL = 'http://localhost:' + port + '/1';
|
||||
@@ -51,9 +70,11 @@ beforeEach(function(done) {
|
||||
});
|
||||
|
||||
afterEach(function(done) {
|
||||
restoreServerConfiguration();
|
||||
Parse.User.logOut().then(() => {
|
||||
return clearData();
|
||||
}).then(() => {
|
||||
DatabaseAdapter.clearDatabaseURIs();
|
||||
done();
|
||||
}, (error) => {
|
||||
console.log('error in clearData', error);
|
||||
@@ -221,3 +242,4 @@ global.expectError = expectError;
|
||||
global.arrayContains = arrayContains;
|
||||
global.jequal = jequal;
|
||||
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;
|
||||
}
|
||||
|
||||
//Used by tests
|
||||
function clearDatabaseURIs() {
|
||||
appDatabaseURIs = {};
|
||||
dbConnections = {};
|
||||
}
|
||||
|
||||
function getDatabaseConnection(appId) {
|
||||
if (dbConnections[appId]) {
|
||||
return dbConnections[appId];
|
||||
@@ -52,5 +58,6 @@ module.exports = {
|
||||
getDatabaseConnection: getDatabaseConnection,
|
||||
setAdapter: setAdapter,
|
||||
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];
|
||||
}
|
||||
|
||||
//So far used only in tests
|
||||
function clearCache() {
|
||||
apps = {};
|
||||
stats = {};
|
||||
users = {};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
apps: apps,
|
||||
stats: stats,
|
||||
@@ -33,5 +40,6 @@ module.exports = {
|
||||
updateStat: updateStat,
|
||||
clearUser: clearUser,
|
||||
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'),
|
||||
httpRequest = require('./httpRequest');
|
||||
|
||||
import { GridStoreAdapter } from './Adapters/Files/GridStoreAdapter';
|
||||
import { S3Adapter } from './Adapters/Files/S3Adapter';
|
||||
import { FilesController } from './Controllers/FilesController';
|
||||
import { GridStoreAdapter } from './Adapters/Files/GridStoreAdapter';
|
||||
import { S3Adapter } from './Adapters/Files/S3Adapter';
|
||||
import { FilesController } from './Controllers/FilesController';
|
||||
|
||||
import ParsePushAdapter from './Adapters/Push/ParsePushAdapter';
|
||||
import { PushController } from './Controllers/PushController';
|
||||
import ParsePushAdapter from './Adapters/Push/ParsePushAdapter';
|
||||
import { PushController } from './Controllers/PushController';
|
||||
|
||||
import { ClassesRouter } from './Routers/ClassesRouter';
|
||||
import { ClassesRouter } from './Routers/ClassesRouter';
|
||||
import { InstallationsRouter } from './Routers/InstallationsRouter';
|
||||
import { UsersRouter } from './Routers/UsersRouter';
|
||||
import { SessionsRouter } from './Routers/SessionsRouter';
|
||||
import { RolesRouter } from './Routers/RolesRouter';
|
||||
import { UsersRouter } from './Routers/UsersRouter';
|
||||
import { SessionsRouter } from './Routers/SessionsRouter';
|
||||
import { RolesRouter } from './Routers/RolesRouter';
|
||||
|
||||
import { FileLoggerAdapter } from './Adapters/Logger/FileLoggerAdapter';
|
||||
import { LoggerController } from './Controllers/LoggerController';
|
||||
import { FileLoggerAdapter } from './Adapters/Logger/FileLoggerAdapter';
|
||||
import { LoggerController } from './Controllers/LoggerController';
|
||||
|
||||
// Mutate the Parse object to add the Cloud Code handlers
|
||||
addParseCloud();
|
||||
@@ -54,20 +54,36 @@ addParseCloud();
|
||||
// "javascriptKey": optional key from Parse dashboard
|
||||
// "push": optional key from configure push
|
||||
|
||||
function ParseServer(args) {
|
||||
if (!args.appId || !args.masterKey) {
|
||||
function ParseServer({
|
||||
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!';
|
||||
}
|
||||
|
||||
if (args.databaseAdapter) {
|
||||
DatabaseAdapter.setAdapter(args.databaseAdapter);
|
||||
if (databaseAdapter) {
|
||||
DatabaseAdapter.setAdapter(databaseAdapter);
|
||||
}
|
||||
|
||||
// Make files adapter
|
||||
let filesAdapter = args.filesAdapter || new GridStoreAdapter();
|
||||
|
||||
// Make push adapter
|
||||
let pushConfig = args.push;
|
||||
let pushConfig = push;
|
||||
let pushAdapter;
|
||||
if (pushConfig && pushConfig.adapter) {
|
||||
pushAdapter = pushConfig.adapter;
|
||||
@@ -75,48 +91,44 @@ function ParseServer(args) {
|
||||
pushAdapter = new ParsePushAdapter(pushConfig)
|
||||
}
|
||||
|
||||
// Make logger adapter
|
||||
let loggerAdapter = args.loggerAdapter || new FileLoggerAdapter();
|
||||
|
||||
if (args.databaseURI) {
|
||||
DatabaseAdapter.setAppDatabaseURI(args.appId, args.databaseURI);
|
||||
if (databaseURI) {
|
||||
DatabaseAdapter.setAppDatabaseURI(appId, databaseURI);
|
||||
}
|
||||
if (args.cloud) {
|
||||
if (cloud) {
|
||||
addParseCloud();
|
||||
if (typeof args.cloud === 'function') {
|
||||
args.cloud(Parse)
|
||||
} else if (typeof args.cloud === 'string') {
|
||||
require(args.cloud);
|
||||
if (typeof cloud === 'function') {
|
||||
cloud(Parse)
|
||||
} else if (typeof cloud === 'string') {
|
||||
require(cloud);
|
||||
} else {
|
||||
throw "argument 'cloud' must either be a string or a function";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let filesController = new FilesController(filesAdapter);
|
||||
|
||||
cache.apps[args.appId] = {
|
||||
masterKey: args.masterKey,
|
||||
collectionPrefix: args.collectionPrefix || '',
|
||||
clientKey: args.clientKey || '',
|
||||
javascriptKey: args.javascriptKey || '',
|
||||
dotNetKey: args.dotNetKey || '',
|
||||
restAPIKey: args.restAPIKey || '',
|
||||
fileKey: args.fileKey || 'invalid-file-key',
|
||||
facebookAppIds: args.facebookAppIds || [],
|
||||
cache.apps[appId] = {
|
||||
masterKey: masterKey,
|
||||
collectionPrefix: collectionPrefix,
|
||||
clientKey: clientKey,
|
||||
javascriptKey: javascriptKey,
|
||||
dotNetKey: dotNetKey,
|
||||
restAPIKey: restAPIKey,
|
||||
fileKey: fileKey,
|
||||
facebookAppIds: facebookAppIds,
|
||||
filesController: filesController,
|
||||
enableAnonymousUsers: args.enableAnonymousUsers || true,
|
||||
oauth: args.oauth || {},
|
||||
enableAnonymousUsers: enableAnonymousUsers,
|
||||
oauth: oauth,
|
||||
};
|
||||
|
||||
// To maintain compatibility. TODO: Remove in v2.1
|
||||
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
|
||||
Parse.initialize(args.appId, args.javascriptKey || '', args.masterKey);
|
||||
Parse.serverURL = args.serverURL || '';
|
||||
Parse.initialize(appId, javascriptKey, masterKey);
|
||||
Parse.serverURL = serverURL;
|
||||
|
||||
// This app serves the Parse API directly.
|
||||
// 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
|
||||
if (process.env.TESTING == 1) {
|
||||
console.log('enabling integration testing-routes');
|
||||
api.use('/', require('./testing-routes').router);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user