Skip to content

Instantly share code, notes, and snippets.

@cellis
Last active May 1, 2020 13:26
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save cellis/08cc332dacf9a548005e8cf35d4b16e2 to your computer and use it in GitHub Desktop.
Save cellis/08cc332dacf9a548005e8cf35d4b16e2 to your computer and use it in GitHub Desktop.
const pg = require('pg');
const PgBricks = require('pg-bricks');
const NodeEnvironment = require('jest-environment-node');
const { range, sample } = require('lodash');
const {
PG_HOST,
PG_USER,
PG_PASSWORD,
PG_PORT,
} = require('../../config/development');
const {
TEST_REPLICA_NAME,
TEST_REPLICAS,
} = require('../../config/test');
/**
*
* @param {Function} createSchemaInVM this function is
* passed from the inner VM to this,
* in order to keep the same graphql version
* equality. This is very bad practice except in this
* instance, necessary, in order to memoize schema gen.
*/
const setupGQLSchema = async createSchemaInVM => {
// try passing in the testqueryschema...
if (!global.schema) {
global.schema = await createSchemaInVM();
}
return global.schema;
};
const setupReplicas = async () => {
const count = TEST_REPLICAS || 1;
const iterator = range(0, count);
const names = iterator.map(num =>
`${TEST_REPLICA_NAME}-${num}`);
const replicas = {};
const connections = {};
names.forEach(name => {
replicas[name] = PgBricks.configure({
user: PG_USER,
password: PG_PASSWORD,
host: PG_HOST,
port: PG_PORT,
database: name,
ssl: false,
idleTimeoutMillis: 500,
}, pg);
});
names.forEach(async name => {
connections[name] = await replicas[name]._pool.connect();
});
global.connections = connections;
global.replicas = replicas;
};
/**
* Each test suite ( file ) will run this code
* before running
*/
class DbEnvironment extends NodeEnvironment {
async setup() {
if (!global.replicas) {
await setupReplicas();
}
const name = sample(Object.keys(global.replicas));
const {
replicas,
schema,
} = global;
const db = replicas[name];
this.global.db = db;
this.global.schema = schema;
this.global.dbName = name;
this.global.getSchema = schemaCreator => setupGQLSchema(schemaCreator);
await this.global.db.query('begin');
await super.setup();
}
async teardown() {
await this.global.db.query('rollback');
await super.teardown();
}
runScript(script) {
return super.runScript(script);
}
}
module.exports = DbEnvironment;
module.exports = {
moduleNameMapper: {
'^.+\\.(css|scss|styl)$': 'identity-obj-proxy',
},
setupFiles: [
'./internal/tools/jest/setup.js'
],
testEnvironment: './internal/tools/jest/dbEnvironment.js',
setupTestFrameworkScriptFile:
'./internal/tools/jest/scriptFile.js',
snapshotSerializers: [
'enzyme-to-json/serializer'
],
globalSetup: './internal/tools/jest/globalSetup.js',
globalTeardown: './internal/tools/jest/globalTeardown.js',
modulePathIgnorePatterns: [
'<rootDir>/src',
'<rootDir>/internal/config',
'<rootDir>/build/',
'<rootDir>/build-staging/',
'<rootDir>/build-development/'
],
};
// nothing in here for now, should probably move setupReplicas / setupGQLSchema here
module.exports = () => {
global.store = 'Starbucks';
};
module.exports = async () => {
console.log('Global Teardown');
const { connections, replicas } = global;
Object.keys(replicas).forEach(name => {
const connection = connections[name];
connection.release();
const pool = replicas[name]._pool;
pool.end();
});
delete global.schema;
delete global.replicas;
delete global.connections;
};
{
"scripts": {
"testdb": "jest --notify --config dbTestConfig.js --forceExit"
}
}
/* globals db */
/**
* This code runs before each individual *test* to keep queries within that test isolated
*/
beforeEach(async done => {
await db.query('begin');
done();
});
afterEach(async done => {
await db.query('rollback');
done();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment