[WIP] Enable test suite to be randomized (#7265)
* initial run * Update ParseGraphQLServer.spec.js * temporarily enable reporter * Bump retry limit * fix undefined database * try to catch error * Handle LiveQueryServers * Update Config.js * fast-fail false * Remove usage of AppCache * oops * Update contributing guide * enable debugger, try network retry attempt 1 * Fix ldap unbinding * move non specs to support * add missing mock adapter * fix Parse.Push * RestController should match batch.spec.js * Remove request attempt limit * handle index.spec.js * Update CHANGELOG.md * Handle error: tuple concurrently updated * test transactions * Clear RedisCache after every test * LoggerController.spec.js * Update schemas.spec.js * finally fix transactions * fix geopoint deadlock * transaction with clean database * batch.spec.js
This commit is contained in:
@@ -6,7 +6,7 @@ const Config = require('../lib/Config');
|
||||
|
||||
describe('AdapterLoader', () => {
|
||||
it('should instantiate an adapter from string in object', done => {
|
||||
const adapterPath = require('path').resolve('./spec/MockAdapter');
|
||||
const adapterPath = require('path').resolve('./spec/support/MockAdapter');
|
||||
|
||||
const adapter = loadAdapter({
|
||||
adapter: adapterPath,
|
||||
@@ -23,7 +23,7 @@ describe('AdapterLoader', () => {
|
||||
});
|
||||
|
||||
it('should instantiate an adapter from string', done => {
|
||||
const adapterPath = require('path').resolve('./spec/MockAdapter');
|
||||
const adapterPath = require('path').resolve('./spec/support/MockAdapter');
|
||||
const adapter = loadAdapter(adapterPath);
|
||||
|
||||
expect(adapter instanceof Object).toBe(true);
|
||||
@@ -119,7 +119,7 @@ describe('AdapterLoader', () => {
|
||||
});
|
||||
|
||||
it('should load custom push adapter from string (#3544)', done => {
|
||||
const adapterPath = require('path').resolve('./spec/MockPushAdapter');
|
||||
const adapterPath = require('path').resolve('./spec/support/MockPushAdapter');
|
||||
const options = {
|
||||
ios: {
|
||||
bundleId: 'bundle.id',
|
||||
|
||||
@@ -227,6 +227,8 @@ describe('execution', () => {
|
||||
'test',
|
||||
'--databaseURI',
|
||||
'mongodb://localhost/test',
|
||||
'--port',
|
||||
'1339',
|
||||
]);
|
||||
childProcess.stdout.on('data', data => {
|
||||
data = data.toString();
|
||||
@@ -247,6 +249,8 @@ describe('execution', () => {
|
||||
'test',
|
||||
'--databaseURI',
|
||||
'mongodb://localhost/test',
|
||||
'--port',
|
||||
'1340',
|
||||
'--mountGraphQL',
|
||||
]);
|
||||
let output = '';
|
||||
@@ -271,6 +275,8 @@ describe('execution', () => {
|
||||
'test',
|
||||
'--databaseURI',
|
||||
'mongodb://localhost/test',
|
||||
'--port',
|
||||
'1341',
|
||||
'--mountGraphQL',
|
||||
'--mountPlayground',
|
||||
]);
|
||||
|
||||
@@ -80,6 +80,9 @@ describe('FilesController', () => {
|
||||
expect(typeof error).toBe('object');
|
||||
expect(error.message.indexOf('biscuit')).toBe(13);
|
||||
expect(error.code).toBe(Parse.Error.INVALID_FILE_NAME);
|
||||
mockAdapter.validateFilename = () => {
|
||||
return null;
|
||||
};
|
||||
done();
|
||||
});
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ const GridFSBucketAdapter = require('../lib/Adapters/Files/GridFSBucketAdapter')
|
||||
const { randomString } = require('../lib/cryptoUtils');
|
||||
const databaseURI = 'mongodb://localhost:27017/parse';
|
||||
const request = require('../lib/request');
|
||||
const Config = require('../lib/Config');
|
||||
|
||||
async function expectMissingFile(gfsAdapter, name) {
|
||||
try {
|
||||
@@ -395,8 +394,9 @@ describe_only_db('mongo')('GridFSBucket and GridStore interop', () => {
|
||||
});
|
||||
|
||||
it('should handle getMetadata error', async () => {
|
||||
const config = Config.get('test');
|
||||
config.filesController.getMetadata = () => Promise.reject();
|
||||
const gfsAdapter = new GridFSBucketAdapter(databaseURI);
|
||||
await reconfigureServer({ filesAdapter: gfsAdapter });
|
||||
gfsAdapter.getMetadata = () => Promise.reject();
|
||||
|
||||
const headers = {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const ldap = require('../lib/Adapters/Auth/ldap');
|
||||
const mockLdapServer = require('./MockLdapServer');
|
||||
const mockLdapServer = require('./support/MockLdapServer');
|
||||
const fs = require('fs');
|
||||
const port = 12345;
|
||||
const sslport = 12346;
|
||||
@@ -19,243 +19,194 @@ describe('Ldap Auth', () => {
|
||||
ldap.validateAppId().then(done).catch(done.fail);
|
||||
});
|
||||
|
||||
it('Should succeed with right credentials', done => {
|
||||
mockLdapServer(port, 'uid=testuser, o=example').then(server => {
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldap://localhost:${port}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
};
|
||||
ldap
|
||||
.validateAuthData({ id: 'testuser', password: 'secret' }, options)
|
||||
.then(done)
|
||||
.catch(done.fail)
|
||||
.finally(() => server.close());
|
||||
});
|
||||
it('Should succeed with right credentials', async done => {
|
||||
const server = await mockLdapServer(port, 'uid=testuser, o=example');
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldap://localhost:${port}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
};
|
||||
await ldap.validateAuthData({ id: 'testuser', password: 'secret' }, options);
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
it('Should succeed with right credentials when LDAPS is used and certifcate is not checked', done => {
|
||||
mockLdapServer(sslport, 'uid=testuser, o=example', false, true).then(server => {
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldaps://localhost:${sslport}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
tlsOptions: { rejectUnauthorized: false },
|
||||
};
|
||||
ldap
|
||||
.validateAuthData({ id: 'testuser', password: 'secret' }, options)
|
||||
.then(done)
|
||||
.catch(done.fail)
|
||||
.finally(() => server.close());
|
||||
});
|
||||
it('Should succeed with right credentials when LDAPS is used and certifcate is not checked', async done => {
|
||||
const server = await mockLdapServer(sslport, 'uid=testuser, o=example', false, true);
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldaps://localhost:${sslport}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
tlsOptions: { rejectUnauthorized: false },
|
||||
};
|
||||
await ldap.validateAuthData({ id: 'testuser', password: 'secret' }, options);
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
it('Should succeed when LDAPS is used and the presented certificate is the expected certificate', done => {
|
||||
mockLdapServer(sslport, 'uid=testuser, o=example', false, true).then(server => {
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldaps://localhost:${sslport}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
tlsOptions: {
|
||||
ca: fs.readFileSync(__dirname + '/support/cert/cert.pem'),
|
||||
rejectUnauthorized: true,
|
||||
},
|
||||
};
|
||||
ldap
|
||||
.validateAuthData({ id: 'testuser', password: 'secret' }, options)
|
||||
.then(done)
|
||||
.catch(done.fail)
|
||||
.finally(() => server.close());
|
||||
});
|
||||
it('Should succeed when LDAPS is used and the presented certificate is the expected certificate', async done => {
|
||||
const server = await mockLdapServer(sslport, 'uid=testuser, o=example', false, true);
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldaps://localhost:${sslport}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
tlsOptions: {
|
||||
ca: fs.readFileSync(__dirname + '/support/cert/cert.pem'),
|
||||
rejectUnauthorized: true,
|
||||
},
|
||||
};
|
||||
await ldap.validateAuthData({ id: 'testuser', password: 'secret' }, options);
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
it('Should fail when LDAPS is used and the presented certificate is not the expected certificate', done => {
|
||||
mockLdapServer(sslport, 'uid=testuser, o=example', false, true).then(server => {
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldaps://localhost:${sslport}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
tlsOptions: {
|
||||
ca: fs.readFileSync(__dirname + '/support/cert/anothercert.pem'),
|
||||
rejectUnauthorized: true,
|
||||
},
|
||||
};
|
||||
ldap
|
||||
.validateAuthData({ id: 'testuser', password: 'secret' }, options)
|
||||
.then(done.fail)
|
||||
.catch(err => {
|
||||
jequal(err.message, 'LDAPS: Certificate mismatch');
|
||||
done();
|
||||
})
|
||||
.finally(() => server.close());
|
||||
});
|
||||
it('Should fail when LDAPS is used and the presented certificate is not the expected certificate', async done => {
|
||||
const server = await mockLdapServer(sslport, 'uid=testuser, o=example', false, true);
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldaps://localhost:${sslport}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
tlsOptions: {
|
||||
ca: fs.readFileSync(__dirname + '/support/cert/anothercert.pem'),
|
||||
rejectUnauthorized: true,
|
||||
},
|
||||
};
|
||||
try {
|
||||
await ldap.validateAuthData({ id: 'testuser', password: 'secret' }, options);
|
||||
fail();
|
||||
} catch (err) {
|
||||
expect(err.message).toBe('LDAPS: Certificate mismatch');
|
||||
}
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
it('Should fail when LDAPS is used certifcate matches but credentials are wrong', done => {
|
||||
mockLdapServer(sslport, 'uid=testuser, o=example', false, true).then(server => {
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldaps://localhost:${sslport}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
tlsOptions: {
|
||||
ca: fs.readFileSync(__dirname + '/support/cert/cert.pem'),
|
||||
rejectUnauthorized: true,
|
||||
},
|
||||
};
|
||||
ldap
|
||||
.validateAuthData({ id: 'testuser', password: 'wrong!' }, options)
|
||||
.then(done.fail)
|
||||
.catch(err => {
|
||||
jequal(err.message, 'LDAP: Wrong username or password');
|
||||
done();
|
||||
})
|
||||
.finally(() => server.close());
|
||||
});
|
||||
it('Should fail when LDAPS is used certifcate matches but credentials are wrong', async done => {
|
||||
const server = await mockLdapServer(sslport, 'uid=testuser, o=example', false, true);
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldaps://localhost:${sslport}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
tlsOptions: {
|
||||
ca: fs.readFileSync(__dirname + '/support/cert/cert.pem'),
|
||||
rejectUnauthorized: true,
|
||||
},
|
||||
};
|
||||
try {
|
||||
await ldap.validateAuthData({ id: 'testuser', password: 'wrong!' }, options);
|
||||
fail();
|
||||
} catch (err) {
|
||||
expect(err.message).toBe('LDAP: Wrong username or password');
|
||||
}
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
it('Should fail with wrong credentials', done => {
|
||||
mockLdapServer(port, 'uid=testuser, o=example').then(server => {
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldap://localhost:${port}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
};
|
||||
ldap
|
||||
.validateAuthData({ id: 'testuser', password: 'wrong!' }, options)
|
||||
.then(done.fail)
|
||||
.catch(err => {
|
||||
jequal(err.message, 'LDAP: Wrong username or password');
|
||||
done();
|
||||
})
|
||||
.finally(() => server.close());
|
||||
});
|
||||
it('Should fail with wrong credentials', async done => {
|
||||
const server = await mockLdapServer(port, 'uid=testuser, o=example');
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldap://localhost:${port}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
};
|
||||
try {
|
||||
await ldap.validateAuthData({ id: 'testuser', password: 'wrong!' }, options);
|
||||
fail();
|
||||
} catch (err) {
|
||||
expect(err.message).toBe('LDAP: Wrong username or password');
|
||||
}
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
it('Should succeed if user is in given group', done => {
|
||||
mockLdapServer(port, 'uid=testuser, o=example').then(server => {
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldap://localhost:${port}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
groupCn: 'powerusers',
|
||||
groupFilter: '(&(uniqueMember=uid={{id}}, o=example)(objectClass=groupOfUniqueNames))',
|
||||
};
|
||||
|
||||
ldap
|
||||
.validateAuthData({ id: 'testuser', password: 'secret' }, options)
|
||||
.then(done)
|
||||
.catch(done.fail)
|
||||
.finally(() => server.close());
|
||||
});
|
||||
it('Should succeed if user is in given group', async done => {
|
||||
const server = await mockLdapServer(port, 'uid=testuser, o=example');
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldap://localhost:${port}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
groupCn: 'powerusers',
|
||||
groupFilter: '(&(uniqueMember=uid={{id}}, o=example)(objectClass=groupOfUniqueNames))',
|
||||
};
|
||||
await ldap.validateAuthData({ id: 'testuser', password: 'secret' }, options);
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
it('Should fail if user is not in given group', done => {
|
||||
mockLdapServer(port, 'uid=testuser, o=example').then(server => {
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldap://localhost:${port}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
groupCn: 'groupTheUserIsNotIn',
|
||||
groupFilter: '(&(uniqueMember=uid={{id}}, o=example)(objectClass=groupOfUniqueNames))',
|
||||
};
|
||||
|
||||
ldap
|
||||
.validateAuthData({ id: 'testuser', password: 'secret' }, options)
|
||||
.then(done.fail)
|
||||
.catch(err => {
|
||||
jequal(err.message, 'LDAP: User not in group');
|
||||
done();
|
||||
})
|
||||
.finally(() => server.close());
|
||||
});
|
||||
it('Should fail if user is not in given group', async done => {
|
||||
const server = await mockLdapServer(port, 'uid=testuser, o=example');
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldap://localhost:${port}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
groupCn: 'groupTheUserIsNotIn',
|
||||
groupFilter: '(&(uniqueMember=uid={{id}}, o=example)(objectClass=groupOfUniqueNames))',
|
||||
};
|
||||
try {
|
||||
await ldap.validateAuthData({ id: 'testuser', password: 'secret' }, options);
|
||||
fail();
|
||||
} catch (err) {
|
||||
expect(err.message).toBe('LDAP: User not in group');
|
||||
}
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
it('Should fail if the LDAP server does not allow searching inside the provided suffix', done => {
|
||||
mockLdapServer(port, 'uid=testuser, o=example').then(server => {
|
||||
const options = {
|
||||
suffix: 'o=invalid',
|
||||
url: `ldap://localhost:${port}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
groupCn: 'powerusers',
|
||||
groupFilter: '(&(uniqueMember=uid={{id}}, o=example)(objectClass=groupOfUniqueNames))',
|
||||
};
|
||||
|
||||
ldap
|
||||
.validateAuthData({ id: 'testuser', password: 'secret' }, options)
|
||||
.then(done.fail)
|
||||
.catch(err => {
|
||||
jequal(err.message, 'LDAP group search failed');
|
||||
done();
|
||||
})
|
||||
.finally(() => server.close());
|
||||
});
|
||||
it('Should fail if the LDAP server does not allow searching inside the provided suffix', async done => {
|
||||
const server = await mockLdapServer(port, 'uid=testuser, o=example');
|
||||
const options = {
|
||||
suffix: 'o=invalid',
|
||||
url: `ldap://localhost:${port}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
groupCn: 'powerusers',
|
||||
groupFilter: '(&(uniqueMember=uid={{id}}, o=example)(objectClass=groupOfUniqueNames))',
|
||||
};
|
||||
try {
|
||||
await ldap.validateAuthData({ id: 'testuser', password: 'secret' }, options);
|
||||
fail();
|
||||
} catch (err) {
|
||||
expect(err.message).toBe('LDAP group search failed');
|
||||
}
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
it('Should fail if the LDAP server encounters an error while searching', done => {
|
||||
mockLdapServer(port, 'uid=testuser, o=example', true).then(server => {
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldap://localhost:${port}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
groupCn: 'powerusers',
|
||||
groupFilter: '(&(uniqueMember=uid={{id}}, o=example)(objectClass=groupOfUniqueNames))',
|
||||
};
|
||||
|
||||
ldap
|
||||
.validateAuthData({ id: 'testuser', password: 'secret' }, options)
|
||||
.then(done.fail)
|
||||
.catch(err => {
|
||||
jequal(err.message, 'LDAP group search failed');
|
||||
done();
|
||||
})
|
||||
.finally(() => server.close());
|
||||
});
|
||||
it('Should fail if the LDAP server encounters an error while searching', async done => {
|
||||
const server = await mockLdapServer(port, 'uid=testuser, o=example', true);
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldap://localhost:${port}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
groupCn: 'powerusers',
|
||||
groupFilter: '(&(uniqueMember=uid={{id}}, o=example)(objectClass=groupOfUniqueNames))',
|
||||
};
|
||||
try {
|
||||
await ldap.validateAuthData({ id: 'testuser', password: 'secret' }, options);
|
||||
fail();
|
||||
} catch (err) {
|
||||
expect(err.message).toBe('LDAP group search failed');
|
||||
}
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
it('Should delete the password from authData after validation', done => {
|
||||
mockLdapServer(port, 'uid=testuser, o=example', true).then(server => {
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldap://localhost:${port}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
};
|
||||
|
||||
const authData = { id: 'testuser', password: 'secret' };
|
||||
|
||||
ldap
|
||||
.validateAuthData(authData, options)
|
||||
.then(() => {
|
||||
expect(authData).toEqual({ id: 'testuser' });
|
||||
done();
|
||||
})
|
||||
.catch(done.fail)
|
||||
.finally(() => server.close());
|
||||
});
|
||||
it('Should delete the password from authData after validation', async done => {
|
||||
const server = await mockLdapServer(port, 'uid=testuser, o=example', true);
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldap://localhost:${port}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
};
|
||||
const authData = { id: 'testuser', password: 'secret' };
|
||||
await ldap.validateAuthData(authData, options);
|
||||
expect(authData).toEqual({ id: 'testuser' });
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
it('Should not save the password in the user record after authentication', done => {
|
||||
mockLdapServer(port, 'uid=testuser, o=example', true).then(server => {
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldap://localhost:${port}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
};
|
||||
reconfigureServer({ auth: { ldap: options } }).then(() => {
|
||||
const authData = { authData: { id: 'testuser', password: 'secret' } };
|
||||
Parse.User.logInWith('ldap', authData).then(returnedUser => {
|
||||
const query = new Parse.Query('User');
|
||||
query
|
||||
.equalTo('objectId', returnedUser.id)
|
||||
.first({ useMasterKey: true })
|
||||
.then(user => {
|
||||
expect(user.get('authData')).toEqual({ ldap: { id: 'testuser' } });
|
||||
expect(user.get('authData').ldap.password).toBeUndefined();
|
||||
done();
|
||||
})
|
||||
.catch(done.fail)
|
||||
.finally(() => server.close());
|
||||
});
|
||||
});
|
||||
});
|
||||
it('Should not save the password in the user record after authentication', async done => {
|
||||
const server = await mockLdapServer(port, 'uid=testuser, o=example', true);
|
||||
const options = {
|
||||
suffix: 'o=example',
|
||||
url: `ldap://localhost:${port}`,
|
||||
dn: 'uid={{id}}, o=example',
|
||||
};
|
||||
await reconfigureServer({ auth: { ldap: options } });
|
||||
const authData = { authData: { id: 'testuser', password: 'secret' } };
|
||||
const returnedUser = await Parse.User.logInWith('ldap', authData);
|
||||
const query = new Parse.Query('User');
|
||||
const user = await query.equalTo('objectId', returnedUser.id).first({ useMasterKey: true });
|
||||
expect(user.get('authData')).toEqual({ ldap: { id: 'testuser' } });
|
||||
expect(user.get('authData').ldap.password).toBeUndefined();
|
||||
server.close(done);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -70,6 +70,7 @@ describe('LoggerController', () => {
|
||||
};
|
||||
|
||||
const loggerController = new LoggerController(new WinstonLoggerAdapter());
|
||||
loggerController.error('can process an ascending query without throwing');
|
||||
|
||||
expect(() => {
|
||||
loggerController
|
||||
@@ -115,6 +116,7 @@ describe('LoggerController', () => {
|
||||
};
|
||||
|
||||
const loggerController = new LoggerController(new WinstonLoggerAdapter());
|
||||
loggerController.error('can process a descending query without throwing');
|
||||
|
||||
expect(() => {
|
||||
loggerController
|
||||
|
||||
@@ -2,10 +2,15 @@
|
||||
|
||||
const request = require('../lib/request');
|
||||
|
||||
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
||||
const pushCompleted = async pushId => {
|
||||
let result = await Parse.Push.getPushStatus(pushId);
|
||||
const query = new Parse.Query('_PushStatus');
|
||||
query.equalTo('objectId', pushId);
|
||||
let result = await query.first({ useMasterKey: true });
|
||||
while (!(result && result.get('status') === 'succeeded')) {
|
||||
result = await Parse.Push.getPushStatus(pushId);
|
||||
await sleep(100);
|
||||
result = await query.first({ useMasterKey: true });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ const fetch = require('node-fetch');
|
||||
const FormData = require('form-data');
|
||||
const ws = require('ws');
|
||||
require('./helper');
|
||||
const { updateCLP } = require('./dev');
|
||||
const { updateCLP } = require('./support/dev');
|
||||
|
||||
const pluralize = require('pluralize');
|
||||
const { getMainDefinition } = require('apollo-utilities');
|
||||
@@ -9033,7 +9033,7 @@ describe('ParseGraphQLServer', () => {
|
||||
|
||||
it('should support object values', async () => {
|
||||
try {
|
||||
const someFieldValue = {
|
||||
const someObjectFieldValue = {
|
||||
foo: { bar: 'baz' },
|
||||
number: 10,
|
||||
};
|
||||
@@ -9048,7 +9048,7 @@ describe('ParseGraphQLServer', () => {
|
||||
`,
|
||||
variables: {
|
||||
schemaFields: {
|
||||
addObjects: [{ name: 'someField' }],
|
||||
addObjects: [{ name: 'someObjectField' }],
|
||||
},
|
||||
},
|
||||
context: {
|
||||
@@ -9057,11 +9057,10 @@ describe('ParseGraphQLServer', () => {
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await parseGraphQLServer.parseGraphQLSchema.databaseController.schemaCache.clear();
|
||||
|
||||
const schema = await new Parse.Schema('SomeClass').get();
|
||||
expect(schema.fields.someField.type).toEqual('Object');
|
||||
expect(schema.fields.someObjectField.type).toEqual('Object');
|
||||
|
||||
const createResult = await apolloClient.mutate({
|
||||
mutation: gql`
|
||||
@@ -9075,13 +9074,13 @@ describe('ParseGraphQLServer', () => {
|
||||
`,
|
||||
variables: {
|
||||
fields: {
|
||||
someField: someFieldValue,
|
||||
someObjectField: someObjectFieldValue,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const where = {
|
||||
someField: {
|
||||
someObjectField: {
|
||||
equalTo: { key: 'foo.bar', value: 'baz' },
|
||||
notEqualTo: { key: 'foo.bar', value: 'bat' },
|
||||
greaterThan: { key: 'number', value: 9 },
|
||||
@@ -9093,13 +9092,13 @@ describe('ParseGraphQLServer', () => {
|
||||
query GetSomeObject($id: ID!, $where: SomeClassWhereInput) {
|
||||
someClass(id: $id) {
|
||||
id
|
||||
someField
|
||||
someObjectField
|
||||
}
|
||||
someClasses(where: $where) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
someField
|
||||
someObjectField
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9113,13 +9112,13 @@ describe('ParseGraphQLServer', () => {
|
||||
|
||||
const { someClass: getResult, someClasses } = queryResult.data;
|
||||
|
||||
const { someField } = getResult;
|
||||
expect(typeof someField).toEqual('object');
|
||||
expect(someField).toEqual(someFieldValue);
|
||||
const { someObjectField } = getResult;
|
||||
expect(typeof someObjectField).toEqual('object');
|
||||
expect(someObjectField).toEqual(someObjectFieldValue);
|
||||
|
||||
// Checks class query results
|
||||
expect(someClasses.edges.length).toEqual(1);
|
||||
expect(someClasses.edges[0].node.someField).toEqual(someFieldValue);
|
||||
expect(someClasses.edges[0].node.someObjectField).toEqual(someObjectFieldValue);
|
||||
} catch (e) {
|
||||
handleError(e);
|
||||
}
|
||||
@@ -9127,11 +9126,11 @@ describe('ParseGraphQLServer', () => {
|
||||
|
||||
it('should support object composed queries', async () => {
|
||||
try {
|
||||
const someFieldValue = {
|
||||
const someObjectFieldValue1 = {
|
||||
lorem: 'ipsum',
|
||||
number: 10,
|
||||
};
|
||||
const someFieldValue2 = {
|
||||
const someObjectFieldValue2 = {
|
||||
foo: {
|
||||
test: 'bar',
|
||||
},
|
||||
@@ -9144,7 +9143,7 @@ describe('ParseGraphQLServer', () => {
|
||||
createClass(
|
||||
input: {
|
||||
name: "SomeClass"
|
||||
schemaFields: { addObjects: [{ name: "someField" }] }
|
||||
schemaFields: { addObjects: [{ name: "someObjectField" }] }
|
||||
}
|
||||
) {
|
||||
clientMutationId
|
||||
@@ -9180,10 +9179,10 @@ describe('ParseGraphQLServer', () => {
|
||||
`,
|
||||
variables: {
|
||||
fields1: {
|
||||
someField: someFieldValue,
|
||||
someObjectField: someObjectFieldValue1,
|
||||
},
|
||||
fields2: {
|
||||
someField: someFieldValue2,
|
||||
someObjectField: someObjectFieldValue2,
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -9191,24 +9190,24 @@ describe('ParseGraphQLServer', () => {
|
||||
const where = {
|
||||
AND: [
|
||||
{
|
||||
someField: {
|
||||
someObjectField: {
|
||||
greaterThan: { key: 'number', value: 9 },
|
||||
},
|
||||
},
|
||||
{
|
||||
someField: {
|
||||
someObjectField: {
|
||||
lessThan: { key: 'number', value: 11 },
|
||||
},
|
||||
},
|
||||
{
|
||||
OR: [
|
||||
{
|
||||
someField: {
|
||||
someObjectField: {
|
||||
equalTo: { key: 'lorem', value: 'ipsum' },
|
||||
},
|
||||
},
|
||||
{
|
||||
someField: {
|
||||
someObjectField: {
|
||||
equalTo: { key: 'foo.test', value: 'bar' },
|
||||
},
|
||||
},
|
||||
@@ -9223,7 +9222,7 @@ describe('ParseGraphQLServer', () => {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
someField
|
||||
someObjectField
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9241,11 +9240,11 @@ describe('ParseGraphQLServer', () => {
|
||||
const { edges } = someClasses;
|
||||
expect(edges.length).toEqual(2);
|
||||
expect(
|
||||
edges.find(result => result.node.id === create1.someClass.id).node.someField
|
||||
).toEqual(someFieldValue);
|
||||
edges.find(result => result.node.id === create1.someClass.id).node.someObjectField
|
||||
).toEqual(someObjectFieldValue1);
|
||||
expect(
|
||||
edges.find(result => result.node.id === create2.someClass.id).node.someField
|
||||
).toEqual(someFieldValue2);
|
||||
edges.find(result => result.node.id === create2.someClass.id).node.someObjectField
|
||||
).toEqual(someObjectFieldValue2);
|
||||
} catch (e) {
|
||||
handleError(e);
|
||||
}
|
||||
@@ -9253,7 +9252,7 @@ describe('ParseGraphQLServer', () => {
|
||||
|
||||
it('should support array values', async () => {
|
||||
try {
|
||||
const someFieldValue = [1, 'foo', ['bar'], { lorem: 'ipsum' }, true];
|
||||
const someArrayFieldValue = [1, 'foo', ['bar'], { lorem: 'ipsum' }, true];
|
||||
|
||||
await apolloClient.mutate({
|
||||
mutation: gql`
|
||||
@@ -9265,7 +9264,7 @@ describe('ParseGraphQLServer', () => {
|
||||
`,
|
||||
variables: {
|
||||
schemaFields: {
|
||||
addArrays: [{ name: 'someField' }],
|
||||
addArrays: [{ name: 'someArrayField' }],
|
||||
},
|
||||
},
|
||||
context: {
|
||||
@@ -9278,7 +9277,7 @@ describe('ParseGraphQLServer', () => {
|
||||
await parseGraphQLServer.parseGraphQLSchema.databaseController.schemaCache.clear();
|
||||
|
||||
const schema = await new Parse.Schema('SomeClass').get();
|
||||
expect(schema.fields.someField.type).toEqual('Array');
|
||||
expect(schema.fields.someArrayField.type).toEqual('Array');
|
||||
|
||||
const createResult = await apolloClient.mutate({
|
||||
mutation: gql`
|
||||
@@ -9292,7 +9291,7 @@ describe('ParseGraphQLServer', () => {
|
||||
`,
|
||||
variables: {
|
||||
fields: {
|
||||
someField: someFieldValue,
|
||||
someArrayField: someArrayFieldValue,
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -9301,17 +9300,17 @@ describe('ParseGraphQLServer', () => {
|
||||
query: gql`
|
||||
query GetSomeObject($id: ID!) {
|
||||
someClass(id: $id) {
|
||||
someField {
|
||||
someArrayField {
|
||||
... on Element {
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
someClasses(where: { someField: { exists: true } }) {
|
||||
someClasses(where: { someArrayField: { exists: true } }) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
someField {
|
||||
someArrayField {
|
||||
... on Element {
|
||||
value
|
||||
}
|
||||
@@ -9326,9 +9325,9 @@ describe('ParseGraphQLServer', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const { someField } = getResult.data.someClass;
|
||||
expect(Array.isArray(someField)).toBeTruthy();
|
||||
expect(someField.map(element => element.value)).toEqual(someFieldValue);
|
||||
const { someArrayField } = getResult.data.someClass;
|
||||
expect(Array.isArray(someArrayField)).toBeTruthy();
|
||||
expect(someArrayField.map(element => element.value)).toEqual(someArrayFieldValue);
|
||||
expect(getResult.data.someClasses.edges.length).toEqual(1);
|
||||
} catch (e) {
|
||||
handleError(e);
|
||||
@@ -10201,101 +10200,99 @@ describe('ParseGraphQLServer', () => {
|
||||
let apolloClient;
|
||||
|
||||
beforeEach(async () => {
|
||||
if (!httpServer) {
|
||||
const expressApp = express();
|
||||
httpServer = http.createServer(expressApp);
|
||||
const TypeEnum = new GraphQLEnumType({
|
||||
name: 'TypeEnum',
|
||||
values: {
|
||||
human: { value: 'human' },
|
||||
robot: { value: 'robot' },
|
||||
},
|
||||
});
|
||||
const SomeClassType = new GraphQLObjectType({
|
||||
name: 'SomeClass',
|
||||
fields: {
|
||||
nameUpperCase: {
|
||||
type: new GraphQLNonNull(GraphQLString),
|
||||
resolve: p => p.name.toUpperCase(),
|
||||
},
|
||||
type: { type: TypeEnum },
|
||||
language: {
|
||||
type: new GraphQLEnumType({
|
||||
name: 'LanguageEnum',
|
||||
values: {
|
||||
fr: { value: 'fr' },
|
||||
en: { value: 'en' },
|
||||
},
|
||||
}),
|
||||
resolve: () => 'fr',
|
||||
},
|
||||
const expressApp = express();
|
||||
httpServer = http.createServer(expressApp);
|
||||
const TypeEnum = new GraphQLEnumType({
|
||||
name: 'TypeEnum',
|
||||
values: {
|
||||
human: { value: 'human' },
|
||||
robot: { value: 'robot' },
|
||||
},
|
||||
});
|
||||
const SomeClassType = new GraphQLObjectType({
|
||||
name: 'SomeClass',
|
||||
fields: {
|
||||
nameUpperCase: {
|
||||
type: new GraphQLNonNull(GraphQLString),
|
||||
resolve: p => p.name.toUpperCase(),
|
||||
},
|
||||
}),
|
||||
parseGraphQLServer = new ParseGraphQLServer(parseServer, {
|
||||
graphQLPath: '/graphql',
|
||||
graphQLCustomTypeDefs: new GraphQLSchema({
|
||||
query: new GraphQLObjectType({
|
||||
name: 'Query',
|
||||
fields: {
|
||||
customQuery: {
|
||||
type: new GraphQLNonNull(GraphQLString),
|
||||
args: {
|
||||
message: { type: new GraphQLNonNull(GraphQLString) },
|
||||
},
|
||||
resolve: (p, { message }) => message,
|
||||
},
|
||||
customQueryWithAutoTypeReturn: {
|
||||
type: SomeClassType,
|
||||
args: {
|
||||
id: { type: new GraphQLNonNull(GraphQLString) },
|
||||
},
|
||||
resolve: async (p, { id }) => {
|
||||
const obj = new Parse.Object('SomeClass');
|
||||
obj.id = id;
|
||||
await obj.fetch();
|
||||
return obj.toJSON();
|
||||
},
|
||||
},
|
||||
type: { type: TypeEnum },
|
||||
language: {
|
||||
type: new GraphQLEnumType({
|
||||
name: 'LanguageEnum',
|
||||
values: {
|
||||
fr: { value: 'fr' },
|
||||
en: { value: 'en' },
|
||||
},
|
||||
}),
|
||||
types: [
|
||||
new GraphQLInputObjectType({
|
||||
name: 'CreateSomeClassFieldsInput',
|
||||
fields: {
|
||||
type: { type: TypeEnum },
|
||||
},
|
||||
}),
|
||||
new GraphQLInputObjectType({
|
||||
name: 'UpdateSomeClassFieldsInput',
|
||||
fields: {
|
||||
type: { type: TypeEnum },
|
||||
},
|
||||
}),
|
||||
SomeClassType,
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
parseGraphQLServer.applyGraphQL(expressApp);
|
||||
await new Promise(resolve => httpServer.listen({ port: 13377 }, resolve));
|
||||
const httpLink = createUploadLink({
|
||||
uri: 'http://localhost:13377/graphql',
|
||||
fetch,
|
||||
headers,
|
||||
});
|
||||
apolloClient = new ApolloClient({
|
||||
link: httpLink,
|
||||
cache: new InMemoryCache(),
|
||||
defaultOptions: {
|
||||
query: {
|
||||
fetchPolicy: 'no-cache',
|
||||
resolve: () => 'fr',
|
||||
},
|
||||
},
|
||||
}),
|
||||
parseGraphQLServer = new ParseGraphQLServer(parseServer, {
|
||||
graphQLPath: '/graphql',
|
||||
graphQLCustomTypeDefs: new GraphQLSchema({
|
||||
query: new GraphQLObjectType({
|
||||
name: 'Query',
|
||||
fields: {
|
||||
customQuery: {
|
||||
type: new GraphQLNonNull(GraphQLString),
|
||||
args: {
|
||||
message: { type: new GraphQLNonNull(GraphQLString) },
|
||||
},
|
||||
resolve: (p, { message }) => message,
|
||||
},
|
||||
customQueryWithAutoTypeReturn: {
|
||||
type: SomeClassType,
|
||||
args: {
|
||||
id: { type: new GraphQLNonNull(GraphQLString) },
|
||||
},
|
||||
resolve: async (p, { id }) => {
|
||||
const obj = new Parse.Object('SomeClass');
|
||||
obj.id = id;
|
||||
await obj.fetch();
|
||||
return obj.toJSON();
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
types: [
|
||||
new GraphQLInputObjectType({
|
||||
name: 'CreateSomeClassFieldsInput',
|
||||
fields: {
|
||||
type: { type: TypeEnum },
|
||||
},
|
||||
}),
|
||||
new GraphQLInputObjectType({
|
||||
name: 'UpdateSomeClassFieldsInput',
|
||||
fields: {
|
||||
type: { type: TypeEnum },
|
||||
},
|
||||
}),
|
||||
SomeClassType,
|
||||
],
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
parseGraphQLServer.applyGraphQL(expressApp);
|
||||
await new Promise(resolve => httpServer.listen({ port: 13377 }, resolve));
|
||||
const httpLink = createUploadLink({
|
||||
uri: 'http://localhost:13377/graphql',
|
||||
fetch,
|
||||
headers,
|
||||
});
|
||||
apolloClient = new ApolloClient({
|
||||
link: httpLink,
|
||||
cache: new InMemoryCache(),
|
||||
defaultOptions: {
|
||||
query: {
|
||||
fetchPolicy: 'no-cache',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
afterEach(async () => {
|
||||
await httpServer.close();
|
||||
});
|
||||
|
||||
|
||||
@@ -8,9 +8,8 @@ const bodyParser = require('body-parser');
|
||||
const auth = require('../lib/Auth');
|
||||
const Config = require('../lib/Config');
|
||||
|
||||
const port = 12345;
|
||||
const port = 34567;
|
||||
const hookServerURL = 'http://localhost:' + port;
|
||||
const AppCache = require('../lib/cache').AppCache;
|
||||
|
||||
describe('Hooks', () => {
|
||||
let server;
|
||||
@@ -19,7 +18,7 @@ describe('Hooks', () => {
|
||||
if (!app) {
|
||||
app = express();
|
||||
app.use(bodyParser.json({ type: '*/*' }));
|
||||
server = app.listen(12345, undefined, done);
|
||||
server = app.listen(port, undefined, done);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
@@ -383,7 +382,7 @@ describe('Hooks', () => {
|
||||
}
|
||||
const hooksController = new HooksController(
|
||||
Parse.applicationId,
|
||||
AppCache.get('test').databaseController
|
||||
Config.get('test').database
|
||||
);
|
||||
return hooksController.load();
|
||||
},
|
||||
|
||||
@@ -127,7 +127,10 @@ describe('ParseLiveQueryServer', function () {
|
||||
serverStartComplete: () => {
|
||||
expect(parseServer.liveQueryServer).not.toBeUndefined();
|
||||
expect(parseServer.liveQueryServer.server).toBe(parseServer.server);
|
||||
parseServer.server.close(done);
|
||||
parseServer.server.close(async () => {
|
||||
await reconfigureServer();
|
||||
done();
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -149,7 +152,10 @@ describe('ParseLiveQueryServer', function () {
|
||||
expect(parseServer.liveQueryServer).not.toBeUndefined();
|
||||
expect(parseServer.liveQueryServer.server).not.toBe(parseServer.server);
|
||||
parseServer.liveQueryServer.server.close(
|
||||
parseServer.server.close.bind(parseServer.server, done)
|
||||
parseServer.server.close.bind(parseServer.server, async () => {
|
||||
await reconfigureServer();
|
||||
done();
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -169,25 +169,25 @@ describe('ParseServerRESTController', () => {
|
||||
process.env.PARSE_SERVER_TEST_DB === 'postgres'
|
||||
) {
|
||||
describe('transactions', () => {
|
||||
let parseServer;
|
||||
beforeEach(async () => {
|
||||
await TestUtils.destroyAllDataPermanently(true);
|
||||
if (
|
||||
semver.satisfies(process.env.MONGODB_VERSION, '>=4.0.4') &&
|
||||
process.env.MONGODB_TOPOLOGY === 'replicaset' &&
|
||||
process.env.MONGODB_STORAGE_ENGINE === 'wiredTiger'
|
||||
) {
|
||||
if (!parseServer) {
|
||||
parseServer = await reconfigureServer({
|
||||
databaseAdapter: undefined,
|
||||
databaseURI:
|
||||
'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase?replicaSet=replicaset',
|
||||
});
|
||||
}
|
||||
await TestUtils.destroyAllDataPermanently(true);
|
||||
await reconfigureServer({
|
||||
databaseAdapter: undefined,
|
||||
databaseURI:
|
||||
'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase?replicaSet=replicaset',
|
||||
});
|
||||
} else {
|
||||
await reconfigureServer();
|
||||
}
|
||||
});
|
||||
|
||||
it('should handle a batch request with transaction = true', done => {
|
||||
it('should handle a batch request with transaction = true', async done => {
|
||||
await reconfigureServer();
|
||||
const myObject = new Parse.Object('MyObject'); // This is important because transaction only works on pre-existing collections
|
||||
myObject
|
||||
.save()
|
||||
@@ -236,117 +236,113 @@ describe('ParseServerRESTController', () => {
|
||||
.catch(done.fail);
|
||||
});
|
||||
|
||||
it('should not save anything when one operation fails in a transaction', done => {
|
||||
it('should not save anything when one operation fails in a transaction', async () => {
|
||||
const myObject = new Parse.Object('MyObject'); // This is important because transaction only works on pre-existing collections
|
||||
myObject
|
||||
.save()
|
||||
.then(() => {
|
||||
return myObject.destroy();
|
||||
})
|
||||
.then(() => {
|
||||
RESTController.request('POST', 'batch', {
|
||||
requests: [
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
],
|
||||
transaction: true,
|
||||
}).catch(error => {
|
||||
expect(error).toBeDefined();
|
||||
const query = new Parse.Query('MyObject');
|
||||
query.find().then(results => {
|
||||
expect(results.length).toBe(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
await myObject.save();
|
||||
await myObject.destroy();
|
||||
try {
|
||||
await RESTController.request('POST', 'batch', {
|
||||
requests: [
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
],
|
||||
transaction: true,
|
||||
});
|
||||
fail();
|
||||
} catch (error) {
|
||||
expect(error).toBeDefined();
|
||||
const query = new Parse.Query('MyObject');
|
||||
const results = await query.find();
|
||||
expect(results.length).toBe(0);
|
||||
}
|
||||
});
|
||||
|
||||
it('should generate separate session for each call', async () => {
|
||||
|
||||
@@ -28,7 +28,7 @@ function createParseServer(options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const parseServer = new ParseServer.default(
|
||||
Object.assign({}, defaultConfiguration, options, {
|
||||
serverURL: 'http://localhost:12666/parse',
|
||||
serverURL: 'http://localhost:12668/parse',
|
||||
serverStartComplete: error => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
@@ -37,8 +37,8 @@ function createParseServer(options) {
|
||||
const app = express();
|
||||
app.use('/parse', parseServer.app);
|
||||
|
||||
const server = app.listen(12666);
|
||||
Parse.serverURL = 'http://localhost:12666/parse';
|
||||
const server = app.listen(12668);
|
||||
Parse.serverURL = 'http://localhost:12668/parse';
|
||||
resolve(server);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const Config = require('../lib/Config');
|
||||
const Parse = require('parse/node');
|
||||
const request = require('../lib/request');
|
||||
const { className, createRole, createUser, logIn, updateCLP } = require('./dev');
|
||||
const { className, createRole, createUser, logIn, updateCLP } = require('./support/dev');
|
||||
|
||||
describe('ProtectedFields', function () {
|
||||
it('should handle and empty protectedFields', async function () {
|
||||
|
||||
@@ -26,10 +26,15 @@ const successfulIOS = function (body, installations) {
|
||||
return Promise.all(promises);
|
||||
};
|
||||
|
||||
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
||||
const pushCompleted = async pushId => {
|
||||
let result = await Parse.Push.getPushStatus(pushId);
|
||||
const query = new Parse.Query('_PushStatus');
|
||||
query.equalTo('objectId', pushId);
|
||||
let result = await query.first({ useMasterKey: true });
|
||||
while (!(result && result.get('status') === 'succeeded')) {
|
||||
result = await Parse.Push.getPushStatus(pushId);
|
||||
await sleep(100);
|
||||
result = await query.first({ useMasterKey: true });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -568,7 +573,7 @@ describe('PushController', () => {
|
||||
await pushCompleted(pushStatusId);
|
||||
});
|
||||
|
||||
it('should properly report failures in _PushStatus', done => {
|
||||
it('should properly report failures in _PushStatus', async () => {
|
||||
const pushAdapter = {
|
||||
send: function (body, installations) {
|
||||
return installations.map(installation => {
|
||||
@@ -593,30 +598,27 @@ describe('PushController', () => {
|
||||
badge: 1,
|
||||
},
|
||||
};
|
||||
const config = Config.get(Parse.applicationId);
|
||||
const auth = {
|
||||
isMaster: true,
|
||||
};
|
||||
const pushController = new PushController();
|
||||
reconfigureServer({
|
||||
await reconfigureServer({
|
||||
push: { adapter: pushAdapter },
|
||||
})
|
||||
.then(() => {
|
||||
return pushController.sendPush(payload, where, config, auth);
|
||||
})
|
||||
.then(() => {
|
||||
fail('should not succeed');
|
||||
done();
|
||||
})
|
||||
.catch(() => {
|
||||
const query = new Parse.Query('_PushStatus');
|
||||
query.find({ useMasterKey: true }).then(results => {
|
||||
expect(results.length).toBe(1);
|
||||
const pushStatus = results[0];
|
||||
expect(pushStatus.get('status')).toBe('failed');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
const config = Config.get(Parse.applicationId);
|
||||
try {
|
||||
await pushController.sendPush(payload, where, config, auth);
|
||||
fail();
|
||||
} catch (e) {
|
||||
const query = new Parse.Query('_PushStatus');
|
||||
let results = await query.find({ useMasterKey: true });
|
||||
while (results.length === 0) {
|
||||
results = await query.find({ useMasterKey: true });
|
||||
}
|
||||
expect(results.length).toBe(1);
|
||||
const pushStatus = results[0];
|
||||
expect(pushStatus.get('status')).toBe('failed');
|
||||
}
|
||||
});
|
||||
|
||||
it('should support full RESTQuery for increment', async () => {
|
||||
@@ -1237,7 +1239,7 @@ describe('PushController', () => {
|
||||
const auth = { isMaster: true };
|
||||
const pushController = new PushController();
|
||||
|
||||
let config = Config.get(Parse.applicationId);
|
||||
let config;
|
||||
|
||||
const pushes = [];
|
||||
const pushAdapter = {
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
const RedisCacheAdapter = require('../lib/Adapters/Cache/RedisCacheAdapter').default;
|
||||
const Config = require('../lib/Config');
|
||||
|
||||
function wait(sleep) {
|
||||
return new Promise(function (resolve) {
|
||||
setTimeout(resolve, sleep);
|
||||
});
|
||||
}
|
||||
/*
|
||||
To run this test part of the complete suite
|
||||
set PARSE_SERVER_TEST_CACHE='redis'
|
||||
@@ -11,31 +16,30 @@ describe_only(() => {
|
||||
})('RedisCacheAdapter', function () {
|
||||
const KEY = 'hello';
|
||||
const VALUE = 'world';
|
||||
let cache;
|
||||
|
||||
function wait(sleep) {
|
||||
return new Promise(function (resolve) {
|
||||
setTimeout(resolve, sleep);
|
||||
});
|
||||
}
|
||||
beforeEach(async () => {
|
||||
cache = new RedisCacheAdapter(null, 100);
|
||||
await cache.clear();
|
||||
});
|
||||
|
||||
it('should get/set/clear', done => {
|
||||
const cache = new RedisCacheAdapter({
|
||||
const cacheNaN = new RedisCacheAdapter({
|
||||
ttl: NaN,
|
||||
});
|
||||
|
||||
cache
|
||||
cacheNaN
|
||||
.put(KEY, VALUE)
|
||||
.then(() => cache.get(KEY))
|
||||
.then(() => cacheNaN.get(KEY))
|
||||
.then(value => expect(value).toEqual(VALUE))
|
||||
.then(() => cache.clear())
|
||||
.then(() => cache.get(KEY))
|
||||
.then(() => cacheNaN.clear())
|
||||
.then(() => cacheNaN.get(KEY))
|
||||
.then(value => expect(value).toEqual(null))
|
||||
.then(() => cacheNaN.clear())
|
||||
.then(done);
|
||||
});
|
||||
|
||||
it('should expire after ttl', done => {
|
||||
const cache = new RedisCacheAdapter(null, 100);
|
||||
|
||||
cache
|
||||
.put(KEY, VALUE)
|
||||
.then(() => cache.get(KEY))
|
||||
@@ -47,8 +51,6 @@ describe_only(() => {
|
||||
});
|
||||
|
||||
it('should not store value for ttl=0', done => {
|
||||
const cache = new RedisCacheAdapter(null, 100);
|
||||
|
||||
cache
|
||||
.put(KEY, VALUE, 0)
|
||||
.then(() => cache.get(KEY))
|
||||
@@ -57,8 +59,6 @@ describe_only(() => {
|
||||
});
|
||||
|
||||
it('should not expire when ttl=Infinity', done => {
|
||||
const cache = new RedisCacheAdapter(null, 100);
|
||||
|
||||
cache
|
||||
.put(KEY, VALUE, Infinity)
|
||||
.then(() => cache.get(KEY))
|
||||
@@ -70,7 +70,6 @@ describe_only(() => {
|
||||
});
|
||||
|
||||
it('should fallback to default ttl', done => {
|
||||
const cache = new RedisCacheAdapter(null, 100);
|
||||
let promise = Promise.resolve();
|
||||
|
||||
[-100, null, undefined, 'not number', true].forEach(ttl => {
|
||||
@@ -89,8 +88,6 @@ describe_only(() => {
|
||||
});
|
||||
|
||||
it('should find un-expired records', done => {
|
||||
const cache = new RedisCacheAdapter(null, 100);
|
||||
|
||||
cache
|
||||
.put(KEY, VALUE)
|
||||
.then(() => cache.get(KEY))
|
||||
@@ -102,8 +99,6 @@ describe_only(() => {
|
||||
});
|
||||
|
||||
it('handleShutdown, close connection', async () => {
|
||||
const cache = new RedisCacheAdapter(null, 100);
|
||||
|
||||
await cache.handleShutdown();
|
||||
setTimeout(() => {
|
||||
expect(cache.client.connected).toBe(false);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const UserController = require('../lib/Controllers/UserController').UserController;
|
||||
const emailAdapter = require('./MockEmailAdapter');
|
||||
const AppCache = require('../lib/cache').AppCache;
|
||||
const emailAdapter = require('./support/MockEmailAdapter');
|
||||
|
||||
describe('UserController', () => {
|
||||
const user = {
|
||||
@@ -11,55 +10,45 @@ describe('UserController', () => {
|
||||
|
||||
describe('sendVerificationEmail', () => {
|
||||
describe('parseFrameURL not provided', () => {
|
||||
it('uses publicServerURL', done => {
|
||||
AppCache.put(
|
||||
defaultConfiguration.appId,
|
||||
Object.assign({}, defaultConfiguration, {
|
||||
publicServerURL: 'http://www.example.com',
|
||||
customPages: {
|
||||
parseFrameURL: undefined,
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
it('uses publicServerURL', async done => {
|
||||
await reconfigureServer({
|
||||
publicServerURL: 'http://www.example.com',
|
||||
customPages: {
|
||||
parseFrameURL: undefined,
|
||||
},
|
||||
});
|
||||
emailAdapter.sendVerificationEmail = options => {
|
||||
expect(options.link).toEqual(
|
||||
'http://www.example.com/apps/test/verify_email?token=testToken&username=testUser'
|
||||
);
|
||||
emailAdapter.sendVerificationEmail = () => Promise.resolve();
|
||||
done();
|
||||
};
|
||||
|
||||
const userController = new UserController(emailAdapter, 'test', {
|
||||
verifyUserEmails: true,
|
||||
});
|
||||
|
||||
userController.sendVerificationEmail(user);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseFrameURL provided', () => {
|
||||
it('uses parseFrameURL and includes the destination in the link parameter', done => {
|
||||
AppCache.put(
|
||||
defaultConfiguration.appId,
|
||||
Object.assign({}, defaultConfiguration, {
|
||||
publicServerURL: 'http://www.example.com',
|
||||
customPages: {
|
||||
parseFrameURL: 'http://someother.example.com/handle-parse-iframe',
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
it('uses parseFrameURL and includes the destination in the link parameter', async done => {
|
||||
await reconfigureServer({
|
||||
publicServerURL: 'http://www.example.com',
|
||||
customPages: {
|
||||
parseFrameURL: 'http://someother.example.com/handle-parse-iframe',
|
||||
},
|
||||
});
|
||||
emailAdapter.sendVerificationEmail = options => {
|
||||
expect(options.link).toEqual(
|
||||
'http://someother.example.com/handle-parse-iframe?link=%2Fapps%2Ftest%2Fverify_email&token=testToken&username=testUser'
|
||||
);
|
||||
emailAdapter.sendVerificationEmail = () => Promise.resolve();
|
||||
done();
|
||||
};
|
||||
|
||||
const userController = new UserController(emailAdapter, 'test', {
|
||||
verifyUserEmails: true,
|
||||
});
|
||||
|
||||
userController.sendVerificationEmail(user);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const MockEmailAdapterWithOptions = require('./MockEmailAdapterWithOptions');
|
||||
const MockEmailAdapterWithOptions = require('./support/MockEmailAdapterWithOptions');
|
||||
const request = require('../lib/request');
|
||||
const Config = require('../lib/Config');
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const request = require('../lib/request');
|
||||
const MockEmailAdapterWithOptions = require('./MockEmailAdapterWithOptions');
|
||||
const MockEmailAdapterWithOptions = require('./support/MockEmailAdapterWithOptions');
|
||||
|
||||
const verifyPassword = function (login, password, isEmail = false) {
|
||||
const body = !isEmail ? { username: login, password } : { email: login, password };
|
||||
|
||||
@@ -175,6 +175,7 @@ describe('batch', () => {
|
||||
) {
|
||||
describe('transactions', () => {
|
||||
beforeEach(async () => {
|
||||
await TestUtils.destroyAllDataPermanently(true);
|
||||
if (
|
||||
semver.satisfies(process.env.MONGODB_VERSION, '>=4.0.4') &&
|
||||
process.env.MONGODB_TOPOLOGY === 'replicaset' &&
|
||||
@@ -185,7 +186,8 @@ describe('batch', () => {
|
||||
databaseURI:
|
||||
'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase?replicaSet=replicaset',
|
||||
});
|
||||
await TestUtils.destroyAllDataPermanently(true);
|
||||
} else {
|
||||
await reconfigureServer();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -243,122 +245,117 @@ describe('batch', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should not save anything when one operation fails in a transaction', done => {
|
||||
it('should not save anything when one operation fails in a transaction', async () => {
|
||||
const myObject = new Parse.Object('MyObject'); // This is important because transaction only works on pre-existing collections
|
||||
myObject
|
||||
.save()
|
||||
.then(() => {
|
||||
return myObject.destroy();
|
||||
})
|
||||
.then(() => {
|
||||
request({
|
||||
method: 'POST',
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/batch',
|
||||
body: JSON.stringify({
|
||||
requests: [
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
],
|
||||
transaction: true,
|
||||
}),
|
||||
}).catch(error => {
|
||||
expect(error.data).toBeDefined();
|
||||
const query = new Parse.Query('MyObject');
|
||||
query.find().then(results => {
|
||||
expect(results.length).toBe(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
await myObject.save();
|
||||
await myObject.destroy();
|
||||
try {
|
||||
await request({
|
||||
method: 'POST',
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/batch',
|
||||
body: JSON.stringify({
|
||||
requests: [
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 'value1' },
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: '/1/classes/MyObject',
|
||||
body: { key: 10 },
|
||||
},
|
||||
],
|
||||
transaction: true,
|
||||
}),
|
||||
});
|
||||
} catch (error) {
|
||||
expect(error).toBeDefined();
|
||||
const query = new Parse.Query('MyObject');
|
||||
const results = await query.find();
|
||||
expect(results.length).toBe(0);
|
||||
}
|
||||
});
|
||||
|
||||
it('should generate separate session for each call', async () => {
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
'use strict';
|
||||
const semver = require('semver');
|
||||
const CurrentSpecReporter = require('./support/CurrentSpecReporter.js');
|
||||
const { SpecReporter } = require('jasmine-spec-reporter');
|
||||
|
||||
// Sets up a Parse API server for testing.
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = process.env.PARSE_SERVER_TEST_TIMEOUT || 10000;
|
||||
jasmine.getEnv().addReporter(new CurrentSpecReporter());
|
||||
if (process.env.PARSE_SERVER_LOG_LEVEL === 'debug') {
|
||||
const { SpecReporter } = require('jasmine-spec-reporter');
|
||||
jasmine.getEnv().addReporter(new SpecReporter());
|
||||
}
|
||||
jasmine.getEnv().addReporter(new SpecReporter());
|
||||
|
||||
global.on_db = (db, callback, elseCallback) => {
|
||||
if (process.env.PARSE_SERVER_TEST_DB == db) {
|
||||
@@ -28,6 +26,7 @@ if (global._babelPolyfill) {
|
||||
process.noDeprecation = true;
|
||||
|
||||
const cache = require('../lib/cache').default;
|
||||
const defaults = require('../lib/defaults').default;
|
||||
const ParseServer = require('../lib/index').ParseServer;
|
||||
const path = require('path');
|
||||
const TestUtils = require('../lib/TestUtils');
|
||||
@@ -113,7 +112,7 @@ const defaultConfiguration = {
|
||||
custom: mockCustom(),
|
||||
facebook: mockFacebook(),
|
||||
myoauth: {
|
||||
module: path.resolve(__dirname, 'myoauth'), // relative path as it's run from src
|
||||
module: path.resolve(__dirname, 'support/myoauth'), // relative path as it's run from src
|
||||
},
|
||||
shortLivedAuth: mockShortLivedAuth(),
|
||||
},
|
||||
@@ -124,6 +123,16 @@ if (process.env.PARSE_SERVER_TEST_CACHE === 'redis') {
|
||||
}
|
||||
|
||||
const openConnections = {};
|
||||
const destroyAliveConnections = function () {
|
||||
for (const socketId in openConnections) {
|
||||
try {
|
||||
openConnections[socketId].destroy();
|
||||
delete openConnections[socketId];
|
||||
} catch (e) {
|
||||
/* */
|
||||
}
|
||||
}
|
||||
};
|
||||
// Set up a default API server for testing with default configuration.
|
||||
let server;
|
||||
|
||||
@@ -146,7 +155,6 @@ const reconfigureServer = (changedConfiguration = {}) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
Parse.CoreManager.set('REQUEST_ATTEMPT_LIMIT', 1);
|
||||
resolve(parseServer);
|
||||
}
|
||||
},
|
||||
@@ -194,8 +202,9 @@ beforeAll(async () => {
|
||||
afterEach(function (done) {
|
||||
const afterLogOut = async () => {
|
||||
if (Object.keys(openConnections).length > 0) {
|
||||
fail('There were open connections to the server left after the test finished');
|
||||
console.warn('There were open connections to the server left after the test finished');
|
||||
}
|
||||
destroyAliveConnections();
|
||||
await TestUtils.destroyAllDataPermanently(true);
|
||||
if (didChangeConfiguration) {
|
||||
await reconfigureServer();
|
||||
@@ -205,6 +214,7 @@ afterEach(function (done) {
|
||||
done();
|
||||
};
|
||||
Parse.Cloud._removeAllHooks();
|
||||
defaults.protectedFields = { _User: { '*': ['email'] } };
|
||||
databaseAdapter
|
||||
.getAllClasses()
|
||||
.then(allSchemas => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
const request = require('../lib/request');
|
||||
const parseServerPackage = require('../package.json');
|
||||
const MockEmailAdapterWithOptions = require('./MockEmailAdapterWithOptions');
|
||||
const MockEmailAdapterWithOptions = require('./support/MockEmailAdapterWithOptions');
|
||||
const ParseServer = require('../lib/index');
|
||||
const Config = require('../lib/Config');
|
||||
const express = require('express');
|
||||
@@ -317,10 +317,16 @@ describe('server', () => {
|
||||
})
|
||||
.then(obj => {
|
||||
expect(obj.id).toEqual(objId);
|
||||
server.close(done);
|
||||
server.close(async () => {
|
||||
await reconfigureServer();
|
||||
done();
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
server.close(done);
|
||||
server.close(async () => {
|
||||
await reconfigureServer();
|
||||
done();
|
||||
});
|
||||
});
|
||||
},
|
||||
})
|
||||
@@ -354,12 +360,18 @@ describe('server', () => {
|
||||
})
|
||||
.then(obj => {
|
||||
expect(obj.id).toEqual(objId);
|
||||
server.close(done);
|
||||
server.close(async () => {
|
||||
await reconfigureServer();
|
||||
done();
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
fail(JSON.stringify(error));
|
||||
if (server) {
|
||||
server.close(done);
|
||||
server.close(async () => {
|
||||
await reconfigureServer();
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
|
||||
@@ -1274,6 +1274,7 @@ describe('schemas', () => {
|
||||
},
|
||||
},
|
||||
}).then(response => {
|
||||
delete response.data.indexes;
|
||||
expect(
|
||||
dd(response.data, {
|
||||
className: '_User',
|
||||
@@ -1302,6 +1303,7 @@ describe('schemas', () => {
|
||||
headers: masterKeyHeaders,
|
||||
json: true,
|
||||
}).then(response => {
|
||||
delete response.data.indexes;
|
||||
expect(
|
||||
dd(response.data, {
|
||||
className: '_User',
|
||||
|
||||
@@ -2,8 +2,8 @@ const ldapjs = require('ldapjs');
|
||||
const fs = require('fs');
|
||||
|
||||
const tlsOptions = {
|
||||
key: fs.readFileSync(__dirname + '/support/cert/key.pem'),
|
||||
certificate: fs.readFileSync(__dirname + '/support/cert/cert.pem'),
|
||||
key: fs.readFileSync(__dirname + '/cert/key.pem'),
|
||||
certificate: fs.readFileSync(__dirname + '/cert/cert.pem'),
|
||||
};
|
||||
|
||||
function newServer(port, dn, provokeSearchError = false, ssl = false) {
|
||||
@@ -1,4 +1,4 @@
|
||||
const Config = require('../lib/Config');
|
||||
const Config = require('../../lib/Config');
|
||||
const Parse = require('parse/node');
|
||||
|
||||
const className = 'AnObject';
|
||||
@@ -2,5 +2,5 @@
|
||||
"spec_dir": "spec",
|
||||
"spec_files": ["*spec.js"],
|
||||
"helpers": ["helper.js"],
|
||||
"random": false
|
||||
"random": true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user