Skip to content

Commit c9dfac2

Browse files
committed
Add ability to test multiple server configurations
1 parent 19d17d8 commit c9dfac2

File tree

5 files changed

+136
-51
lines changed

5 files changed

+136
-51
lines changed

spec/helper.js

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ var DatabaseAdapter = require('../src/DatabaseAdapter');
77
var express = require('express');
88
var facebook = require('../src/oauth/facebook');
99
var ParseServer = require('../src/index').ParseServer;
10+
var DatabaseAdapter = require('../src/DatabaseAdapter');
1011

1112
var databaseURI = process.env.DATABASE_URI;
1213
var cloudMain = process.env.CLOUD_CODE_MAIN || './cloud/main.js';
1314

14-
// Set up an API server for testing
15-
var api = new ParseServer({
15+
// Default server configuration for tests.
16+
var defaultConfiguration = {
1617
databaseURI: databaseURI,
1718
cloud: cloudMain,
1819
appId: 'test',
@@ -29,13 +30,30 @@ var api = new ParseServer({
2930
module: "../spec/myoauth" // relative path as it's run from src
3031
}
3132
}
32-
});
33+
};
3334

35+
// Set up a default API server for testing with default configuration.
36+
var api = new ParseServer(defaultConfiguration);
3437
var app = express();
3538
app.use('/1', api);
3639
var port = 8378;
3740
var server = app.listen(port);
3841

42+
// Prevent reinitializing the server from clobbering Cloud Code
43+
delete defaultConfiguration.cloud;
44+
45+
// Allows testing specific configurations of Parse Server
46+
var setServerConfiguration = configuration => {
47+
api = new ParseServer(configuration);
48+
app = express();
49+
app.use('/1', api);
50+
cache.clearCache();
51+
server.close();
52+
server = app.listen(port);
53+
}
54+
55+
var restoreServerConfiguration = () => setServerConfiguration(defaultConfiguration);
56+
3957
// Set up a Parse client to talk to our test API server
4058
var Parse = require('parse/node');
4159
Parse.serverURL = 'http://localhost:' + port + '/1';
@@ -51,9 +69,11 @@ beforeEach(function(done) {
5169
});
5270

5371
afterEach(function(done) {
72+
restoreServerConfiguration();
5473
Parse.User.logOut().then(() => {
5574
return clearData();
5675
}).then(() => {
76+
DatabaseAdapter.clearDatabaseURIs();
5777
done();
5878
}, (error) => {
5979
console.log('error in clearData', error);
@@ -221,3 +241,4 @@ global.expectError = expectError;
221241
global.arrayContains = arrayContains;
222242
global.jequal = jequal;
223243
global.range = range;
244+
global.setServerConfiguration = setServerConfiguration;

spec/index.spec.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
var request = require('request');
2+
3+
describe('server', () => {
4+
it('requires a master key and app id', done => {
5+
expect(setServerConfiguration.bind(undefined, { masterKey: 'mykey' })).toThrow('You must provide an appId and masterKey!');
6+
expect(setServerConfiguration.bind(undefined, { appId: 'myId' })).toThrow('You must provide an appId and masterKey!');
7+
done();
8+
});
9+
10+
it('fails if database is unreachable', done => {
11+
setServerConfiguration({
12+
databaseURI: 'mongodb://fake:[email protected]:43605/drew3',
13+
appId: 'test',
14+
javascriptKey: 'test',
15+
dotNetKey: 'windows',
16+
clientKey: 'client',
17+
restAPIKey: 'rest',
18+
masterKey: 'test',
19+
collectionPrefix: 'test_',
20+
fileKey: 'test',
21+
});
22+
//Need to use rest api because saving via JS SDK results in fail() not getting called
23+
request.post({
24+
url: 'http://localhost:8378/1/classes/NewClass',
25+
headers: {
26+
'X-Parse-Application-Id': 'test',
27+
'X-Parse-REST-API-Key': 'rest',
28+
},
29+
body: {},
30+
json: true,
31+
}, (error, response, body) => {
32+
expect(response.statusCode).toEqual(500);
33+
expect(body.code).toEqual(1);
34+
expect(body.message).toEqual('Internal server error.');
35+
done();
36+
});
37+
});
38+
});

src/DatabaseAdapter.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ function setAppDatabaseURI(appId, uri) {
3434
appDatabaseURIs[appId] = uri;
3535
}
3636

37+
//Used by tests
38+
function clearDatabaseURIs() {
39+
appDatabaseURIs = {};
40+
dbConnections = {};
41+
}
42+
3743
function getDatabaseConnection(appId) {
3844
if (dbConnections[appId]) {
3945
return dbConnections[appId];
@@ -52,5 +58,6 @@ module.exports = {
5258
getDatabaseConnection: getDatabaseConnection,
5359
setAdapter: setAdapter,
5460
setDatabaseURI: setDatabaseURI,
55-
setAppDatabaseURI: setAppDatabaseURI
61+
setAppDatabaseURI: setAppDatabaseURI,
62+
clearDatabaseURIs: clearDatabaseURIs,
5663
};

src/cache.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ function clearUser(sessionToken) {
2525
delete users[sessionToken];
2626
}
2727

28+
//So far used only in tests
29+
function clearCache() {
30+
apps = {};
31+
stats = {};
32+
users = {};
33+
}
34+
2835
module.exports = {
2936
apps: apps,
3037
stats: stats,
@@ -33,5 +40,6 @@ module.exports = {
3340
updateStat: updateStat,
3441
clearUser: clearUser,
3542
getUser: getUser,
36-
setUser: setUser
43+
setUser: setUser,
44+
clearCache: clearCache,
3745
};

src/index.js

Lines changed: 57 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,21 @@ var batch = require('./batch'),
1111
PromiseRouter = require('./PromiseRouter'),
1212
httpRequest = require('./httpRequest');
1313

14-
import { GridStoreAdapter } from './Adapters/Files/GridStoreAdapter';
15-
import { S3Adapter } from './Adapters/Files/S3Adapter';
16-
import { FilesController } from './Controllers/FilesController';
14+
import { GridStoreAdapter } from './Adapters/Files/GridStoreAdapter';
15+
import { S3Adapter } from './Adapters/Files/S3Adapter';
16+
import { FilesController } from './Controllers/FilesController';
1717

18-
import ParsePushAdapter from './Adapters/Push/ParsePushAdapter';
19-
import { PushController } from './Controllers/PushController';
18+
import ParsePushAdapter from './Adapters/Push/ParsePushAdapter';
19+
import { PushController } from './Controllers/PushController';
2020

21-
import { ClassesRouter } from './Routers/ClassesRouter';
21+
import { ClassesRouter } from './Routers/ClassesRouter';
2222
import { InstallationsRouter } from './Routers/InstallationsRouter';
23-
import { UsersRouter } from './Routers/UsersRouter';
24-
import { SessionsRouter } from './Routers/SessionsRouter';
25-
import { RolesRouter } from './Routers/RolesRouter';
23+
import { UsersRouter } from './Routers/UsersRouter';
24+
import { SessionsRouter } from './Routers/SessionsRouter';
25+
import { RolesRouter } from './Routers/RolesRouter';
2626

27-
import { FileLoggerAdapter } from './Adapters/Logger/FileLoggerAdapter';
28-
import { LoggerController } from './Controllers/LoggerController';
27+
import { FileLoggerAdapter } from './Adapters/Logger/FileLoggerAdapter';
28+
import { LoggerController } from './Controllers/LoggerController';
2929

3030
// Mutate the Parse object to add the Cloud Code handlers
3131
addParseCloud();
@@ -54,70 +54,82 @@ addParseCloud();
5454
// "javascriptKey": optional key from Parse dashboard
5555
// "push": optional key from configure push
5656

57-
function ParseServer(args) {
58-
if (!args.appId || !args.masterKey) {
57+
function ParseServer({
58+
appId,
59+
masterKey,
60+
databaseAdapter,
61+
filesAdapter = new GridStoreAdapter(),
62+
push,
63+
loggerAdapter = new FileLoggerAdapter(),
64+
databaseURI,
65+
cloud,
66+
collectionPrefix = '',
67+
clientKey = '',
68+
javascriptKey = '',
69+
dotNetKey = '',
70+
restAPIKey = '',
71+
fileKey = 'invalid-file-key',
72+
facebookAppIds = [],
73+
enableAnonymousUsers = true,
74+
oauth = {},
75+
serverURL,
76+
}) {
77+
if (!appId || !masterKey) {
5978
throw 'You must provide an appId and masterKey!';
6079
}
6180

62-
if (args.databaseAdapter) {
63-
DatabaseAdapter.setAdapter(args.databaseAdapter);
81+
if (databaseAdapter) {
82+
DatabaseAdapter.setAdapter(databaseAdapter);
6483
}
6584

66-
// Make files adapter
67-
let filesAdapter = args.filesAdapter || new GridStoreAdapter();
68-
6985
// Make push adapter
70-
let pushConfig = args.push;
86+
let pushConfig = push;
7187
let pushAdapter;
7288
if (pushConfig && pushConfig.adapter) {
7389
pushAdapter = pushConfig.adapter;
7490
} else if (pushConfig) {
7591
pushAdapter = new ParsePushAdapter(pushConfig)
7692
}
7793

78-
// Make logger adapter
79-
let loggerAdapter = args.loggerAdapter || new FileLoggerAdapter();
80-
81-
if (args.databaseURI) {
82-
DatabaseAdapter.setAppDatabaseURI(args.appId, args.databaseURI);
94+
if (databaseURI) {
95+
DatabaseAdapter.setAppDatabaseURI(appId, databaseURI);
8396
}
84-
if (args.cloud) {
97+
if (cloud) {
8598
addParseCloud();
86-
if (typeof args.cloud === 'function') {
87-
args.cloud(Parse)
88-
} else if (typeof args.cloud === 'string') {
89-
require(args.cloud);
99+
if (typeof cloud === 'function') {
100+
cloud(Parse)
101+
} else if (typeof cloud === 'string') {
102+
require(cloud);
90103
} else {
91104
throw "argument 'cloud' must either be a string or a function";
92105
}
93-
94106
}
95107

96108
let filesController = new FilesController(filesAdapter);
97109

98-
cache.apps[args.appId] = {
99-
masterKey: args.masterKey,
100-
collectionPrefix: args.collectionPrefix || '',
101-
clientKey: args.clientKey || '',
102-
javascriptKey: args.javascriptKey || '',
103-
dotNetKey: args.dotNetKey || '',
104-
restAPIKey: args.restAPIKey || '',
105-
fileKey: args.fileKey || 'invalid-file-key',
106-
facebookAppIds: args.facebookAppIds || [],
110+
cache.apps[appId] = {
111+
masterKey: masterKey,
112+
collectionPrefix: collectionPrefix,
113+
clientKey: clientKey,
114+
javascriptKey: javascriptKey,
115+
dotNetKey: dotNetKey,
116+
restAPIKey: restAPIKey,
117+
fileKey: fileKey,
118+
facebookAppIds: facebookAppIds,
107119
filesController: filesController,
108-
enableAnonymousUsers: args.enableAnonymousUsers || true,
109-
oauth: args.oauth || {},
120+
enableAnonymousUsers: enableAnonymousUsers,
121+
oauth: oauth,
110122
};
111123

112124
// To maintain compatibility. TODO: Remove in v2.1
113125
if (process.env.FACEBOOK_APP_ID) {
114-
cache.apps[args.appId]['facebookAppIds'].push(process.env.FACEBOOK_APP_ID);
126+
cache.apps[appId]['facebookAppIds'].push(process.env.FACEBOOK_APP_ID);
115127
}
116128

117129
// Initialize the node client SDK automatically
118-
Parse.initialize(args.appId, args.javascriptKey || '', args.masterKey);
119-
if(args.serverURL) {
120-
Parse.serverURL = args.serverURL;
130+
Parse.initialize(appId, javascriptKey, masterKey);
131+
if (serverURL) {
132+
Parse.serverURL = serverURL;
121133
}
122134

123135
// This app serves the Parse API directly.
@@ -129,7 +141,6 @@ function ParseServer(args) {
129141

130142
// TODO: separate this from the regular ParseServer object
131143
if (process.env.TESTING == 1) {
132-
console.log('enabling integration testing-routes');
133144
api.use('/', require('./testing-routes').router);
134145
}
135146

0 commit comments

Comments
 (0)