mirror of https://github.com/webpack/webpack.git
133 lines
3.3 KiB
JavaScript
133 lines
3.3 KiB
JavaScript
"use strict";
|
|
|
|
module.exports = (globalTimeout = 2000, nameSuffix = "") => {
|
|
const state = global.JEST_STATE_SYMBOL;
|
|
let currentDescribeBlock;
|
|
let currentlyRunningTest;
|
|
let runTests = -1;
|
|
const disposables = [];
|
|
|
|
// this function allows to release memory in fn context
|
|
// manually, usually after the suite has been run.
|
|
const createDisposableFn = (fn, isTest) => {
|
|
if (!fn) return null;
|
|
const rfn =
|
|
fn.length >= 1
|
|
? (done) => {
|
|
fn((...args) => {
|
|
if (isTest) runTests++;
|
|
done(...args);
|
|
});
|
|
}
|
|
: () => {
|
|
const r = fn();
|
|
if (isTest) runTests++;
|
|
return r;
|
|
};
|
|
disposables.push(() => {
|
|
fn = null;
|
|
});
|
|
return rfn;
|
|
};
|
|
|
|
describe(
|
|
nameSuffix ? `exported tests ${nameSuffix}` : "exported tests",
|
|
() => {
|
|
// this must have a child to be handled correctly
|
|
it("should run the exported tests", () => {
|
|
runTests++;
|
|
});
|
|
afterAll((done) => {
|
|
for (const dispose of disposables) {
|
|
dispose();
|
|
}
|
|
done();
|
|
});
|
|
currentDescribeBlock = state.currentDescribeBlock;
|
|
currentlyRunningTest = state.currentlyRunningTest;
|
|
}
|
|
);
|
|
let numberOfTests = 0;
|
|
const inSuite = (fn) => {
|
|
const {
|
|
currentDescribeBlock: oldCurrentDescribeBlock,
|
|
currentlyRunningTest: oldCurrentlyRunningTest,
|
|
hasStarted: oldHasStarted
|
|
} = state;
|
|
state.currentDescribeBlock = currentDescribeBlock;
|
|
state.currentlyRunningTest = currentlyRunningTest;
|
|
state.hasStarted = false;
|
|
try {
|
|
fn();
|
|
} catch (err) {
|
|
/* eslint-disable no-unused-expressions */
|
|
// avoid leaking memory
|
|
/** @type {EXPECTED_ANY} */
|
|
(err).stack;
|
|
/* eslint-enable no-unused-expressions */
|
|
throw err;
|
|
}
|
|
state.currentDescribeBlock = oldCurrentDescribeBlock;
|
|
state.currentlyRunningTest = oldCurrentlyRunningTest;
|
|
state.hasStarted = oldHasStarted;
|
|
};
|
|
const fixAsyncError = (block) => {
|
|
// By default jest leaks memory as it stores asyncError
|
|
// for each "it" call to track the origin test suite
|
|
// We want to evaluate this early here to avoid leaking memory
|
|
block.asyncError = {
|
|
stack: block.asyncError.stack
|
|
};
|
|
};
|
|
return {
|
|
/**
|
|
* @param {number} time time
|
|
*/
|
|
setDefaultTimeout(time) {
|
|
globalTimeout = time;
|
|
},
|
|
getNumberOfTests() {
|
|
return numberOfTests;
|
|
},
|
|
it(...args) {
|
|
numberOfTests++;
|
|
if (runTests >= numberOfTests) throw new Error("it called too late");
|
|
args[1] = createDisposableFn(args[1], true);
|
|
args[2] = args[2] || globalTimeout;
|
|
inSuite(() => {
|
|
// @ts-expect-error expected
|
|
it(...args);
|
|
fixAsyncError(
|
|
currentDescribeBlock.tests[currentDescribeBlock.tests.length - 1]
|
|
);
|
|
});
|
|
},
|
|
beforeEach(...args) {
|
|
if (runTests >= numberOfTests) {
|
|
throw new Error("beforeEach called too late");
|
|
}
|
|
args[0] = createDisposableFn(args[0]);
|
|
inSuite(() => {
|
|
// @ts-expect-error expected
|
|
beforeEach(...args);
|
|
fixAsyncError(
|
|
currentDescribeBlock.hooks[currentDescribeBlock.hooks.length - 1]
|
|
);
|
|
});
|
|
},
|
|
afterEach(...args) {
|
|
if (runTests >= numberOfTests) {
|
|
throw new Error("afterEach called too late");
|
|
}
|
|
args[0] = createDisposableFn(args[0]);
|
|
inSuite(() => {
|
|
// @ts-expect-error expected
|
|
afterEach(...args);
|
|
fixAsyncError(
|
|
currentDescribeBlock.hooks[currentDescribeBlock.hooks.length - 1]
|
|
);
|
|
});
|
|
}
|
|
};
|
|
};
|