earljs
Version:
Ergonomic, modern and type-safe assertion library
130 lines (129 loc) • 4.5 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.mockFn = void 0;
const ts_essentials_1 = require("ts-essentials");
const isEqual_1 = require("../isEqual");
const errors_1 = require("./errors");
function mockFn(defaultImpl) {
let spec = {
type: 'not-ready',
};
let queue = [];
let oneTimeOverrides = [];
function mock(...args) {
for (const override of oneTimeOverrides) {
if ((0, isEqual_1.isEqual)(args, override.args)) {
oneTimeOverrides.splice(oneTimeOverrides.indexOf(override), 1);
return runSpec(override.spec, args);
}
}
const current = queue.shift() || spec;
return runSpec(current, args);
}
mock.calls = [];
mock.isExhausted = function () {
return queue.length === 0 && oneTimeOverrides.length === 0;
};
function runSpec(spec, args) {
switch (spec.type) {
case 'return':
mock.calls.push({ args, result: { type: 'return', value: spec.value } });
return spec.value;
case 'lazy-return':
const value = spec.value();
mock.calls.push({ args, result: { type: 'return', value } });
return value;
case 'throw':
mock.calls.push({ args, result: { type: 'throw', error: spec.error } });
throw spec.error;
case 'exec':
try {
const value = spec.implementation(...args);
mock.calls.push({ args, result: { type: 'return', value } });
return value;
}
catch (error) {
mock.calls.push({ args, result: { type: 'throw', error } });
throw error;
}
case 'not-ready':
throw new errors_1.MockNotConfiguredError();
default:
throw new ts_essentials_1.UnreachableCaseError(spec);
}
}
function reset(newSpec) {
spec = newSpec;
queue = [];
oneTimeOverrides = [];
}
mock.returns = function (value) {
reset({ type: 'return', value });
return mock;
};
mock.returnsOnce = function (value) {
queue.push({ type: 'return', value });
return mock;
};
mock.throws = function (error) {
reset({ type: 'throw', error });
return mock;
};
mock.throwsOnce = function (error) {
queue.push({ type: 'throw', error });
return mock;
};
mock.executes = function (implementation) {
reset({ type: 'exec', implementation });
return mock;
};
mock.executesOnce = function (implementation) {
queue.push({ type: 'exec', implementation });
return mock;
};
mock.resolvesTo = function (value) {
reset({ type: 'return', value: Promise.resolve(value) });
return mock;
};
mock.resolvesToOnce = function (value) {
queue.push({ type: 'return', value: Promise.resolve(value) });
return mock;
};
mock.rejectsWith = function (error) {
reset({ type: 'lazy-return', value: () => Promise.reject(error) });
return mock;
};
mock.rejectsWithOnce = function (error) {
queue.push({ type: 'lazy-return', value: () => Promise.reject(error) });
return mock;
};
mock.given = function (...args) {
return {
returnsOnce(value) {
oneTimeOverrides.push({ args, spec: { type: 'return', value } });
return mock;
},
throwsOnce(error) {
oneTimeOverrides.push({ args, spec: { type: 'throw', error } });
return mock;
},
executesOnce(implementation) {
oneTimeOverrides.push({ args, spec: { type: 'exec', implementation } });
return mock;
},
resolvesToOnce(value) {
oneTimeOverrides.push({ args, spec: { type: 'return', value: Promise.resolve(value) } });
return mock;
},
rejectsWithOnce(error) {
oneTimeOverrides.push({ args, spec: { type: 'lazy-return', value: () => Promise.reject(error) } });
return mock;
},
};
};
if (defaultImpl) {
mock.executes(defaultImpl);
}
return mock;
}
exports.mockFn = mockFn;
;