[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:
Diamond Lewis
2021-03-15 02:04:09 -05:00
committed by GitHub
parent 9563793303
commit 1666c3e382
36 changed files with 688 additions and 700 deletions

View File

@@ -0,0 +1,5 @@
module.exports = function (options) {
return {
options: options,
};
};

View File

@@ -0,0 +1,5 @@
module.exports = {
sendVerificationEmail: () => Promise.resolve(),
sendPasswordResetEmail: () => Promise.resolve(),
sendMail: () => Promise.resolve(),
};

View File

@@ -0,0 +1,21 @@
module.exports = options => {
if (!options) {
throw 'Options were not provided';
}
const adapter = {
sendVerificationEmail: () => Promise.resolve(),
sendPasswordResetEmail: () => Promise.resolve(),
sendMail: () => Promise.resolve(),
};
if (options.sendMail) {
adapter.sendMail = options.sendMail;
}
if (options.sendPasswordResetEmail) {
adapter.sendPasswordResetEmail = options.sendPasswordResetEmail;
}
if (options.sendVerificationEmail) {
adapter.sendVerificationEmail = options.sendVerificationEmail;
}
return adapter;
};

View File

@@ -0,0 +1,54 @@
const ldapjs = require('ldapjs');
const fs = require('fs');
const tlsOptions = {
key: fs.readFileSync(__dirname + '/cert/key.pem'),
certificate: fs.readFileSync(__dirname + '/cert/cert.pem'),
};
function newServer(port, dn, provokeSearchError = false, ssl = false) {
const server = ssl ? ldapjs.createServer(tlsOptions) : ldapjs.createServer();
server.bind('o=example', function (req, res, next) {
if (req.dn.toString() !== dn || req.credentials !== 'secret')
return next(new ldapjs.InvalidCredentialsError());
res.end();
return next();
});
server.search('o=example', function (req, res, next) {
if (provokeSearchError) {
res.end(ldapjs.LDAP_SIZE_LIMIT_EXCEEDED);
return next();
}
const obj = {
dn: req.dn.toString(),
attributes: {
objectclass: ['organization', 'top'],
o: 'example',
},
};
const group = {
dn: req.dn.toString(),
attributes: {
objectClass: ['groupOfUniqueNames', 'top'],
uniqueMember: ['uid=testuser, o=example'],
cn: 'powerusers',
ou: 'powerusers',
},
};
if (req.filter.matches(obj.attributes)) {
res.send(obj);
}
if (req.filter.matches(group.attributes)) {
res.send(group);
}
res.end();
});
return new Promise(resolve => server.listen(port, () => resolve(server)));
}
module.exports = newServer;

View File

@@ -0,0 +1,9 @@
module.exports = function (options) {
return {
options: options,
send: function () {},
getValidPushTypes: function () {
return Object.keys(options.options);
},
};
};

95
spec/support/dev.js Normal file
View File

@@ -0,0 +1,95 @@
const Config = require('../../lib/Config');
const Parse = require('parse/node');
const className = 'AnObject';
const defaultRoleName = 'tester';
let schemaCache;
module.exports = {
/* AnObject */
className,
schemaCache,
/**
* Creates and returns new user.
*
* This method helps to avoid 'User already exists' when re-running/debugging a single test.
* @param {string} username - username base, will be postfixed with current time in millis;
* @param {string} [password='password'] - optional, defaults to "password" if not set;
*/
createUser: async (username, password = 'password') => {
const user = new Parse.User({
username: username + Date.now(),
password,
});
await user.save();
return user;
},
/**
* Logs the user in.
*
* If password not provided, default 'password' is used.
* @param {string} username - username base, will be postfixed with current time in millis;
* @param {string} [password='password'] - optional, defaults to "password" if not set;
*/
logIn: async (userObject, password) => {
return await Parse.User.logIn(userObject.getUsername(), password || 'password');
},
/**
* Sets up Class-Level Permissions for 'AnObject' class.
* @param clp {ClassLevelPermissions}
*/
updateCLP: async (clp, targetClass = className) => {
const config = Config.get(Parse.applicationId);
const schemaController = await config.database.loadSchema();
await schemaController.updateClass(targetClass, {}, clp);
},
/**
* Creates and returns role. Adds user(s) if provided.
*
* This method helps to avoid errors when re-running/debugging a single test.
*
* @param {Parse.User|Parse.User[]} [users] - user or array of users to be related with this role;
* @param {string?} [roleName] - uses this name for role if provided. Generates from datetime if not set;
* @param {string?} [exactName] - sets exact name (no generated part added);
* @param {Parse.Role[]} [roles] - uses this name for role if provided. Generates from datetime if not set;
* @param {boolean} [read] - value for role's acl public read. Defaults to true;
* @param {boolean} [write] - value for role's acl public write. Defaults to true;
*/
createRole: async ({
users = null,
exactName = defaultRoleName + Date.now(),
roleName = null,
roles = null,
read = true,
write = true,
}) => {
const acl = new Parse.ACL();
acl.setPublicReadAccess(read);
acl.setPublicWriteAccess(write);
const role = new Parse.Object('_Role');
role.setACL(acl);
// generate name based on roleName or use exactName (if botth not provided name is generated)
const name = roleName ? roleName + Date.now() : exactName;
role.set('name', name);
if (roles) {
role.relation('roles').add(roles);
}
if (users) {
role.relation('users').add(users);
}
await role.save({ useMasterKey: true });
return role;
},
};

View File

@@ -2,5 +2,5 @@
"spec_dir": "spec",
"spec_files": ["*spec.js"],
"helpers": ["helper.js"],
"random": false
"random": true
}

17
spec/support/myoauth.js Normal file
View File

@@ -0,0 +1,17 @@
// Custom oauth provider by module
// Returns a promise that fulfills iff this user id is valid.
function validateAuthData(authData) {
if (authData.id == '12345' && authData.access_token == '12345') {
return Promise.resolve();
}
return Promise.reject();
}
function validateAppId() {
return Promise.resolve();
}
module.exports = {
validateAppId: validateAppId,
validateAuthData: validateAuthData,
};