test-fns
Version:
write usecase driven tests systematically for simpler, safer, and more readable code
77 lines • 4.22 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.then = exports.when = exports.given = exports.getNumberRange = void 0;
const helpful_errors_1 = require("helpful-errors");
const getNumberRange = (input) => {
// Calculate the length of the range
const length = input.end - input.start + 1;
// Create an array with the specified range
return Array.from({ length }, (_, i) => input.start + i);
};
exports.getNumberRange = getNumberRange;
const castToJestTestInput = ({ input, prefix, }) => {
const method = input.length === 3 ? input[2] : input[1]; // its always last
if (input.length === 3)
return [`${prefix}: ${input[0]}`, method]; // we allow users to specify the reason for code readability, but we dont expose this in the test report to decrease noise. folks can look in the code if they want to know "why"
return [`${prefix}: ${input[0]}`, method]; // otherwise, its the normal input
};
const given = (desc, fn) => describe(`given: ${desc}`, fn);
exports.given = given;
exports.given.only = (desc, fn) => describe.only(`given: ${desc}`, fn);
exports.given.skip = (desc, fn) => describe.skip(`given: ${desc}`, fn);
exports.given.skipIf =
(condition) => (desc, fn) => condition ? exports.given.skip(desc, fn) : (0, exports.given)(desc, fn);
exports.given.runIf = (condition) => exports.given.skipIf(!condition);
const when = (desc, fn) => describe(`when: ${desc}`, fn);
exports.when = when;
exports.when.only = (desc, fn) => describe.only(`when: ${desc}`, fn);
exports.when.skip = (desc, fn) => describe.skip(`when: ${desc}`, fn);
exports.when.skipIf =
(condition) => (desc, fn) => condition ? exports.when.skip(desc, fn) : (0, exports.when)(desc, fn);
exports.when.runIf = (condition) => exports.when.skipIf(!condition);
const then = (...input) => test(...castToJestTestInput({ input, prefix: 'then' }));
exports.then = then;
exports.then.only = (...input) => test.only(...castToJestTestInput({ input, prefix: 'then' }));
exports.then.skip = (...input) => test.skip(...castToJestTestInput({ input, prefix: 'then' }));
exports.then.todo = (...input) => test.todo(castToJestTestInput({ input: [input[0]], prefix: 'then' })[0]); // note that we only pass the first input, since jest's .todo function throws an error if you pass an implementation fn
exports.then.skipIf =
(condition) => (...input) => condition ? exports.then.skip(...input) : (0, exports.then)(...input);
exports.then.runIf = (condition) => exports.then.skipIf(!condition);
exports.then.repeatably =
(configuration) => (...input) => {
// validate the input length
if (input.length !== 2 && input.length !== 3)
throw new helpful_errors_1.UnexpectedCodePathError('unsupported input length', {
input,
});
// support the "SOME" criteria
if (configuration.criteria === 'SOME') {
// use the native "retryTimes"
jest.retryTimes(configuration.attempts, { logErrorsBeforeRetry: true });
// track the number of attempts
let attempt = 0;
beforeEach(() => attempt++);
// and run the test
if (input.length === 2)
(0, exports.then)(input[0], () => input[1]({ attempt }));
if (input.length === 3)
(0, exports.then)(input[0], input[1], () => input[2]({ attempt }));
return;
}
// support the "EVERY" criteria
if (configuration.criteria === 'EVERY') {
for (const attempt of (0, exports.getNumberRange)({
start: 1,
end: configuration.attempts,
})) {
if (input.length === 2)
(0, exports.then)(input[0] + `, attempt ${attempt}`, () => input[1]({ attempt }));
if (input.length === 3)
(0, exports.then)(input[0] + `, attempt ${attempt}`, input[1], () => input[2]({ attempt }));
}
return;
}
// throw if neither
throw new helpful_errors_1.UnexpectedCodePathError('configuration.criteria was neither EVERY nor SOME', { configuration });
};
//# sourceMappingURL=givenWhenThen.js.map