Skip to content

Instantly share code, notes, and snippets.

@abrkn
Created August 25, 2018 05:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save abrkn/79b9e85bf7ba1f1b4d7dd1e4aa3b1aa4 to your computer and use it in GitHub Desktop.
Save abrkn/79b9e85bf7ba1f1b4d7dd1e4aa3b1aa4 to your computer and use it in GitHub Desktop.
import assert from 'assert';
import createDebug from 'debug';
const debug = createDebug(`sane-jest`);
const theirDescribe = describe;
const theirTest = test;
const defaultTimeout = +(process.env.SANE_JEST_TIMEOUT || 30e3);
const stack = [];
let top;
const push = name => {
top = {
name,
beforeAll: [],
beforeEach: [],
afterEach: [],
afterAll: [],
tests: [],
isFirstTest: true,
};
stack.push(top);
};
push('root');
const ourBeforeAll = (fn) => {
top.beforeAll.push({ fn });
}
const ourAfterAll = (fn) => {
top.afterAll.push({ fn });
};
const ourBeforeEach = (fn) => {
top.beforeEach.push({ fn });
};
const ourAfterEach = (fn) => {
top.afterEach.push({ fn });
};
const ourDescribe = (name, fn) => {
push(name);
theirDescribe(name, fn);
stack.pop();
};
const ourTest = (name, fn) => {
assert(name, 'name');
assert(fn, 'fn');
top.tests.push({ name, fn });
const path = stack.map(_ => _.name).join('/') + '/' + name;
const wrappedFn = async () => {
debug(`${path} entering`);
top.tests.shift();
if (top.beforeAllError) {
debug(`${path} previous beforeAll failed. throwing that error.`);
// TODO: May need to run some version of afterAll (maybe optional to afterAll arg)
// TODO; afterEach may habe same problem
throw top.beforeAllError;
}
if (top.isFirstTest) {
top.isFirstTest = false;
debug(`${path} beforeAll`);
for (const { fn } of top.beforeAll) {
try {
await fn();
} catch (error) {
top.beforeAllError = error;
throw error;
}
}
}
debug(`${path} beforeEach`);
for (const { fn } of top.beforeEach) {
await fn();
}
debug(`${path} test`);
let fnError;
try {
await fn();
} catch (error) {
fnError = error;
}
debug(`${path} afterEach`);
for (const { fn } of top.afterEach) {
await fn({ error: fnError || null });
}
const isLastTest = !top.tests.length;
if (isLastTest) {
debug(`${path} afterAll`);
// TODO: this can throw and we dont throw fnError
for (const { fn } of top.afterAll) {
await fn();
}
}
if (fnError) {
debug(`${path} actual test had an error. throwing`);
throw fnError;
}
};
return theirTest(name, wrappedFn, defaultTimeout);
};
Object.assign(exports, {
beforeAll: ourBeforeAll,
afterAll: ourAfterAll,
beforeEach: ourBeforeEach,
afterEach: ourAfterEach,
describe: ourDescribe,
test: ourTest,
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment