UNPKG

earljs

Version:

Ergonomic, modern and type-safe assertion library

130 lines (129 loc) 4.5 kB
"use strict"; 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;