diff options
Diffstat (limited to 'vanilla/node_modules/@vitest/spy/dist/index.js')
| -rw-r--r-- | vanilla/node_modules/@vitest/spy/dist/index.js | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/vanilla/node_modules/@vitest/spy/dist/index.js b/vanilla/node_modules/@vitest/spy/dist/index.js new file mode 100644 index 0000000..96f9784 --- /dev/null +++ b/vanilla/node_modules/@vitest/spy/dist/index.js @@ -0,0 +1,433 @@ +function isMockFunction(fn) { + return typeof fn === "function" && "_isMockFunction" in fn && fn._isMockFunction === true; +} +const MOCK_RESTORE = new Set(); +// Jest keeps the state in a separate WeakMap which is good for memory, +// but it makes the state slower to access and return different values +// if you stored it before calling `mockClear` where it will be recreated +const REGISTERED_MOCKS = new Set(); +const MOCK_CONFIGS = new WeakMap(); +function createMockInstance(options = {}) { + var _ref; + const { originalImplementation, restore, mockImplementation, resetToMockImplementation, resetToMockName } = options; + if (restore) { + MOCK_RESTORE.add(restore); + } + const config = getDefaultConfig(originalImplementation); + const state = getDefaultState(); + const mock = createMock({ + config, + state, + ...options + }); + const mockLength = ((_ref = mockImplementation || originalImplementation) === null || _ref === void 0 ? void 0 : _ref.length) ?? 0; + Object.defineProperty(mock, "length", { + writable: true, + enumerable: false, + value: mockLength, + configurable: true + }); + // inherit the default name so it appears in snapshots and logs + // this is used by `vi.spyOn()` for better debugging. + // when `vi.fn()` is called, we just use the default string + if (resetToMockName) { + config.mockName = mock.name || "vi.fn()"; + } + MOCK_CONFIGS.set(mock, config); + REGISTERED_MOCKS.add(mock); + mock._isMockFunction = true; + mock.getMockImplementation = () => { + // Jest only returns `config.mockImplementation` here, + // but we think it makes sense to return what the next function will be called + return config.onceMockImplementations[0] || config.mockImplementation; + }; + Object.defineProperty(mock, "mock", { + configurable: false, + enumerable: true, + writable: false, + value: state + }); + mock.mockImplementation = function mockImplementation(implementation) { + config.mockImplementation = implementation; + return mock; + }; + mock.mockImplementationOnce = function mockImplementationOnce(implementation) { + config.onceMockImplementations.push(implementation); + return mock; + }; + mock.withImplementation = function withImplementation(implementation, callback) { + const previousImplementation = config.mockImplementation; + const previousOnceImplementations = config.onceMockImplementations; + const reset = () => { + config.mockImplementation = previousImplementation; + config.onceMockImplementations = previousOnceImplementations; + }; + config.mockImplementation = implementation; + config.onceMockImplementations = []; + const returnValue = callback(); + if (typeof returnValue === "object" && typeof (returnValue === null || returnValue === void 0 ? void 0 : returnValue.then) === "function") { + return returnValue.then(() => { + reset(); + return mock; + }); + } else { + reset(); + } + return mock; + }; + mock.mockReturnThis = function mockReturnThis() { + return mock.mockImplementation(function() { + return this; + }); + }; + mock.mockReturnValue = function mockReturnValue(value) { + return mock.mockImplementation(() => value); + }; + mock.mockReturnValueOnce = function mockReturnValueOnce(value) { + return mock.mockImplementationOnce(() => value); + }; + mock.mockResolvedValue = function mockResolvedValue(value) { + return mock.mockImplementation(() => Promise.resolve(value)); + }; + mock.mockResolvedValueOnce = function mockResolvedValueOnce(value) { + return mock.mockImplementationOnce(() => Promise.resolve(value)); + }; + mock.mockRejectedValue = function mockRejectedValue(value) { + return mock.mockImplementation(() => Promise.reject(value)); + }; + mock.mockRejectedValueOnce = function mockRejectedValueOnce(value) { + return mock.mockImplementationOnce(() => Promise.reject(value)); + }; + mock.mockClear = function mockClear() { + state.calls = []; + state.contexts = []; + state.instances = []; + state.invocationCallOrder = []; + state.results = []; + state.settledResults = []; + return mock; + }; + mock.mockReset = function mockReset() { + mock.mockClear(); + config.mockImplementation = resetToMockImplementation ? mockImplementation : undefined; + config.mockName = resetToMockName ? mock.name || "vi.fn()" : "vi.fn()"; + config.onceMockImplementations = []; + return mock; + }; + mock.mockRestore = function mockRestore() { + mock.mockReset(); + return restore === null || restore === void 0 ? void 0 : restore(); + }; + mock.mockName = function mockName(name) { + if (typeof name === "string") { + config.mockName = name; + } + return mock; + }; + mock.getMockName = function getMockName() { + return config.mockName || "vi.fn()"; + }; + if (Symbol.dispose) { + mock[Symbol.dispose] = () => mock.mockRestore(); + } + if (mockImplementation) { + mock.mockImplementation(mockImplementation); + } + return mock; +} +function fn(originalImplementation) { + // if the function is already a mock, just return the same function, + // simillarly to how vi.spyOn() works + if (originalImplementation != null && isMockFunction(originalImplementation)) { + return originalImplementation; + } + return createMockInstance({ + mockImplementation: originalImplementation, + resetToMockImplementation: true + }); +} +function spyOn(object, key, accessor) { + assert(object != null, "The vi.spyOn() function could not find an object to spy upon. The first argument must be defined."); + assert(typeof object === "object" || typeof object === "function", "Vitest cannot spy on a primitive value."); + const [originalDescriptorObject, originalDescriptor] = getDescriptor(object, key) || []; + assert(originalDescriptor || key in object, `The property "${String(key)}" is not defined on the ${typeof object}.`); + let accessType = accessor || "value"; + let ssr = false; + // vite ssr support - actual function is stored inside a getter + if (accessType === "value" && originalDescriptor && originalDescriptor.value == null && originalDescriptor.get) { + accessType = "get"; + ssr = true; + } + let original; + if (originalDescriptor) { + original = originalDescriptor[accessType]; + } else if (accessType !== "value") { + original = () => object[key]; + } else { + original = object[key]; + } + const originalImplementation = ssr && original ? original() : original; + const originalType = typeof originalImplementation; + assert( + // allow only functions + originalType === "function" || accessType !== "value" && original == null, + `vi.spyOn() can only spy on a function. Received ${originalType}.` + ); + if (isMockFunction(originalImplementation)) { + return originalImplementation; + } + const reassign = (cb) => { + const { value, ...desc } = originalDescriptor || { + configurable: true, + writable: true + }; + if (accessType !== "value") { + delete desc.writable; + } + desc[accessType] = cb; + Object.defineProperty(object, key, desc); + }; + const restore = () => { + // if method is defined on the prototype, we can just remove it from + // the current object instead of redefining a copy of it + if (originalDescriptorObject !== object) { + Reflect.deleteProperty(object, key); + } else if (originalDescriptor && !original) { + Object.defineProperty(object, key, originalDescriptor); + } else { + reassign(original); + } + }; + const mock = createMockInstance({ + restore, + originalImplementation, + resetToMockName: true + }); + try { + reassign(ssr ? () => mock : mock); + } catch (error) { + if (error instanceof TypeError && Symbol.toStringTag && object[Symbol.toStringTag] === "Module" && (error.message.includes("Cannot redefine property") || error.message.includes("Cannot replace module namespace") || error.message.includes("can't redefine non-configurable property"))) { + throw new TypeError(`Cannot spy on export "${String(key)}". Module namespace is not configurable in ESM. See: https://vitest.dev/guide/browser/#limitations`, { cause: error }); + } + throw error; + } + return mock; +} +function getDescriptor(obj, method) { + const objDescriptor = Object.getOwnPropertyDescriptor(obj, method); + if (objDescriptor) { + return [obj, objDescriptor]; + } + let currentProto = Object.getPrototypeOf(obj); + while (currentProto !== null) { + const descriptor = Object.getOwnPropertyDescriptor(currentProto, method); + if (descriptor) { + return [currentProto, descriptor]; + } + currentProto = Object.getPrototypeOf(currentProto); + } +} +function assert(condition, message) { + if (!condition) { + throw new Error(message); + } +} +let invocationCallCounter = 1; +function createMock({ state, config, name: mockName, prototypeState, prototypeConfig, keepMembersImplementation, mockImplementation, prototypeMembers = [] }) { + const original = config.mockOriginal; + const pseudoOriginal = mockImplementation; + const name = mockName || (original === null || original === void 0 ? void 0 : original.name) || "Mock"; + const namedObject = { [name]: (function(...args) { + registerCalls(args, state, prototypeState); + registerInvocationOrder(invocationCallCounter++, state, prototypeState); + const result = { + type: "incomplete", + value: undefined + }; + const settledResult = { + type: "incomplete", + value: undefined + }; + registerResult(result, state, prototypeState); + registerSettledResult(settledResult, state, prototypeState); + const context = new.target ? undefined : this; + const [instanceIndex, instancePrototypeIndex] = registerInstance(context, state, prototypeState); + const [contextIndex, contextPrototypeIndex] = registerContext(context, state, prototypeState); + const implementation = config.onceMockImplementations.shift() || config.mockImplementation || (prototypeConfig === null || prototypeConfig === void 0 ? void 0 : prototypeConfig.onceMockImplementations.shift()) || (prototypeConfig === null || prototypeConfig === void 0 ? void 0 : prototypeConfig.mockImplementation) || original || function() {}; + let returnValue; + let thrownValue; + let didThrow = false; + try { + if (new.target) { + returnValue = Reflect.construct(implementation, args, new.target); + // jest calls this before the implementation, but we have to resolve this _after_ + // because we cannot do it before the `Reflect.construct` called the custom implementation. + // fortunetly, the constructor is always an empty functon because `prototypeMethods` + // are only used by the automocker, so this doesn't matter + for (const prop of prototypeMembers) { + const prototypeMock = returnValue[prop]; + // the method was overidden because of inheritence, ignore it + // eslint-disable-next-line ts/no-use-before-define + if (prototypeMock !== mock.prototype[prop]) { + continue; + } + const isMock = isMockFunction(prototypeMock); + const prototypeState = isMock ? prototypeMock.mock : undefined; + const prototypeConfig = isMock ? MOCK_CONFIGS.get(prototypeMock) : undefined; + returnValue[prop] = createMockInstance({ + originalImplementation: keepMembersImplementation ? prototypeConfig === null || prototypeConfig === void 0 ? void 0 : prototypeConfig.mockOriginal : undefined, + prototypeState, + prototypeConfig, + keepMembersImplementation + }); + } + } else { + returnValue = implementation.apply(this, args); + } + } catch (error) { + thrownValue = error; + didThrow = true; + if (error instanceof TypeError && error.message.includes("is not a constructor")) { + console.warn(`[vitest] The ${namedObject[name].getMockName()} mock did not use 'function' or 'class' in its implementation, see https://vitest.dev/api/vi#vi-spyon for examples.`); + } + throw error; + } finally { + if (didThrow) { + result.type = "throw"; + result.value = thrownValue; + settledResult.type = "rejected"; + settledResult.value = thrownValue; + } else { + result.type = "return"; + result.value = returnValue; + if (new.target) { + state.contexts[contextIndex - 1] = returnValue; + state.instances[instanceIndex - 1] = returnValue; + if (contextPrototypeIndex != null && prototypeState) { + prototypeState.contexts[contextPrototypeIndex - 1] = returnValue; + } + if (instancePrototypeIndex != null && prototypeState) { + prototypeState.instances[instancePrototypeIndex - 1] = returnValue; + } + } + if (returnValue instanceof Promise) { + returnValue.then((settledValue) => { + settledResult.type = "fulfilled"; + settledResult.value = settledValue; + }, (rejectedValue) => { + settledResult.type = "rejected"; + settledResult.value = rejectedValue; + }); + } else { + settledResult.type = "fulfilled"; + settledResult.value = returnValue; + } + } + } + return returnValue; + }) }; + const mock = namedObject[name]; + const copyPropertiesFrom = original || pseudoOriginal; + if (copyPropertiesFrom) { + copyOriginalStaticProperties(mock, copyPropertiesFrom); + } + return mock; +} +function registerCalls(args, state, prototypeState) { + state.calls.push(args); + prototypeState === null || prototypeState === void 0 ? void 0 : prototypeState.calls.push(args); +} +function registerInvocationOrder(order, state, prototypeState) { + state.invocationCallOrder.push(order); + prototypeState === null || prototypeState === void 0 ? void 0 : prototypeState.invocationCallOrder.push(order); +} +function registerResult(result, state, prototypeState) { + state.results.push(result); + prototypeState === null || prototypeState === void 0 ? void 0 : prototypeState.results.push(result); +} +function registerSettledResult(result, state, prototypeState) { + state.settledResults.push(result); + prototypeState === null || prototypeState === void 0 ? void 0 : prototypeState.settledResults.push(result); +} +function registerInstance(instance, state, prototypeState) { + const instanceIndex = state.instances.push(instance); + const instancePrototypeIndex = prototypeState === null || prototypeState === void 0 ? void 0 : prototypeState.instances.push(instance); + return [instanceIndex, instancePrototypeIndex]; +} +function registerContext(context, state, prototypeState) { + const contextIndex = state.contexts.push(context); + const contextPrototypeIndex = prototypeState === null || prototypeState === void 0 ? void 0 : prototypeState.contexts.push(context); + return [contextIndex, contextPrototypeIndex]; +} +function copyOriginalStaticProperties(mock, original) { + const { properties, descriptors } = getAllProperties(original); + for (const key of properties) { + const descriptor = descriptors[key]; + const mockDescriptor = getDescriptor(mock, key); + if (mockDescriptor) { + continue; + } + Object.defineProperty(mock, key, descriptor); + } +} +const ignoreProperties = new Set([ + "length", + "name", + "prototype", + Symbol.for("nodejs.util.promisify.custom") +]); +function getAllProperties(original) { + const properties = new Set(); + const descriptors = {}; + while (original && original !== Object.prototype && original !== Function.prototype) { + const ownProperties = [...Object.getOwnPropertyNames(original), ...Object.getOwnPropertySymbols(original)]; + for (const prop of ownProperties) { + if (descriptors[prop] || ignoreProperties.has(prop)) { + continue; + } + properties.add(prop); + descriptors[prop] = Object.getOwnPropertyDescriptor(original, prop); + } + original = Object.getPrototypeOf(original); + } + return { + properties, + descriptors + }; +} +function getDefaultConfig(original) { + return { + mockImplementation: undefined, + mockOriginal: original, + mockName: "vi.fn()", + onceMockImplementations: [] + }; +} +function getDefaultState() { + const state = { + calls: [], + contexts: [], + instances: [], + invocationCallOrder: [], + settledResults: [], + results: [], + get lastCall() { + return state.calls.at(-1); + } + }; + return state; +} +function restoreAllMocks() { + for (const restore of MOCK_RESTORE) { + restore(); + } + MOCK_RESTORE.clear(); +} +function clearAllMocks() { + REGISTERED_MOCKS.forEach((mock) => mock.mockClear()); +} +function resetAllMocks() { + REGISTERED_MOCKS.forEach((mock) => mock.mockReset()); +} + +export { clearAllMocks, createMockInstance, fn, isMockFunction, resetAllMocks, restoreAllMocks, spyOn }; |
