UNPKG

vitest

Version:

Next generation testing framework powered by Vite

1,473 lines (1,314 loc) 148 kB
import { getCurrentTest, updateTask, createTaskCollector, getCurrentSuite, getHooks, getFn } from '@vitest/runner'; import { assertTypes, createSimpleStackTrace, createDefer } from '@vitest/utils/helpers'; import { getSafeTimers, delay } from '@vitest/utils/timers'; import { a as getBenchOptions, g as getBenchFn } from './benchmark.CX_oY03V.js'; import { g as getWorkerState, i as isChildProcess, w as waitForImportsToResolve, r as resetModules } from './utils.BX5Fg8C4.js'; import { chai, wrapAssertion, recordAsyncExpect, createAssertionMessage, equals, iterableEquality, subsetEquality, JestExtend, JestChaiExpect, ChaiStyleAssertions, JestAsymmetricMatchers, GLOBAL_EXPECT, ASYMMETRIC_MATCHERS_OBJECT, getState, setState, addCustomEqualityTesters, customMatchers } from '@vitest/expect'; import { getNames, getTests, getTestName, createChainable, matchesTags } from '@vitest/runner/utils'; import { processError } from '@vitest/utils/error'; import { normalize } from 'pathe'; import { stripSnapshotIndentation, addSerializer, SnapshotClient } from '@vitest/snapshot'; import { fn, spyOn, restoreAllMocks, resetAllMocks, clearAllMocks, isMockFunction } from '@vitest/spy'; import '@vitest/utils/offset'; import { parseSingleStack } from '@vitest/utils/source-map'; import { c as commonjsGlobal } from './_commonjsHelpers.D26ty3Ew.js'; import { R as RealDate, b as resetDate, m as mockDate, r as rpc } from './rpc.MzXet3jl.js'; // these matchers are not supported because they don't make sense with poll const unsupported = [ "matchSnapshot", "toMatchSnapshot", "toMatchInlineSnapshot", "toThrowErrorMatchingSnapshot", "toThrowErrorMatchingInlineSnapshot", "throws", "Throw", "throw", "toThrow", "toThrowError" ]; /** * Attaches a `cause` property to the error if missing, copies the stack trace from the source, and throws. * * @param error - The error to throw * @param source - Error to copy the stack trace from * * @throws Always throws the provided error with an amended stack trace */ function throwWithCause(error, source) { if (error.cause == null) error.cause = /* @__PURE__ */ new Error("Matcher did not succeed in time."); throw copyStackTrace$1(error, source); } function createExpectPoll(expect) { return function poll(fn, options = {}) { const defaults = getWorkerState().config.expect?.poll ?? {}; const { interval = defaults.interval ?? 50, timeout = defaults.timeout ?? 1e3, message } = options; // @ts-expect-error private poll access const assertion = expect(null, message).withContext({ poll: true }); fn = fn.bind(assertion); const test = chai.util.flag(assertion, "vitest-test"); if (!test) throw new Error("expect.poll() must be called inside a test"); const proxy = new Proxy(assertion, { get(target, key, receiver) { const assertionFunction = Reflect.get(target, key, receiver); if (typeof assertionFunction !== "function") return assertionFunction instanceof chai.Assertion ? proxy : assertionFunction; if (key === "assert") return assertionFunction; if (typeof key === "string" && unsupported.includes(key)) throw new SyntaxError(`expect.poll() is not supported in combination with .${key}(). Use vi.waitFor() if your assertion condition is unstable.`); return function(...args) { const STACK_TRACE_ERROR = /* @__PURE__ */ new Error("STACK_TRACE_ERROR"); const promise = async () => { const { setTimeout, clearTimeout } = getSafeTimers(); let executionPhase = "fn"; let hasTimedOut = false; const timerId = setTimeout(() => { hasTimedOut = true; }, timeout); chai.util.flag(assertion, "_name", key); const onSettled = chai.util.flag(assertion, "_poll.onSettled"); try { while (true) { const isLastAttempt = hasTimedOut; if (isLastAttempt) chai.util.flag(assertion, "_isLastPollAttempt", true); try { executionPhase = "fn"; const obj = await fn(); chai.util.flag(assertion, "object", obj); executionPhase = "assertion"; const output = await assertionFunction.call(assertion, ...args); await onSettled?.({ assertion, status: "pass" }); return output; } catch (err) { if (isLastAttempt || executionPhase === "assertion" && chai.util.flag(assertion, "_poll.assert_once")) { await onSettled?.({ assertion, status: "fail" }); throwWithCause(err, STACK_TRACE_ERROR); } await delay(interval, setTimeout); } } } finally { clearTimeout(timerId); } }; let awaited = false; test.onFinished ??= []; test.onFinished.push(() => { if (!awaited) { const negated = chai.util.flag(assertion, "negate") ? "not." : ""; const assertionString = `expect.${chai.util.flag(assertion, "_poll.element") ? "element(locator)" : "poll(assertion)"}.${negated}${String(key)}()`; throw copyStackTrace$1(/* @__PURE__ */ new Error(`${assertionString} was not awaited. This assertion is asynchronous and must be awaited; otherwise, it is not executed to avoid unhandled rejections:\n\nawait ${assertionString}\n`), STACK_TRACE_ERROR); } }); let resultPromise; // only .then is enough to check awaited, but we type this as `Promise<void>` in global types // so let's follow it return { then(onFulfilled, onRejected) { awaited = true; return (resultPromise ||= promise()).then(onFulfilled, onRejected); }, catch(onRejected) { awaited = true; return (resultPromise ||= promise()).catch(onRejected); }, finally(onFinally) { awaited = true; return (resultPromise ||= promise()).finally(onFinally); }, [Symbol.toStringTag]: "Promise" }; }; } }); return proxy; }; } function copyStackTrace$1(target, source) { if (source.stack !== void 0) target.stack = source.stack.replace(source.message, target.message); return target; } let _client; function getSnapshotClient() { if (!_client) _client = new SnapshotClient({ isEqual: (received, expected) => { return equals(received, expected, [iterableEquality, subsetEquality]); } }); return _client; } function getError(expected, promise) { if (typeof expected !== "function") { if (!promise) throw new Error(`expected must be a function, received ${typeof expected}`); // when "promised", it receives thrown error return expected; } try { expected(); } catch (e) { return e; } throw new Error("snapshot function didn't throw"); } function getTestNames(test) { return { filepath: test.file.filepath, name: getNames(test).slice(1).join(" > "), testId: test.id }; } const SnapshotPlugin = (chai, utils) => { function getTest(assertionName, obj) { const test = utils.flag(obj, "vitest-test"); if (!test) throw new Error(`'${assertionName}' cannot be used without test context`); return test; } for (const key of ["matchSnapshot", "toMatchSnapshot"]) utils.addMethod(chai.Assertion.prototype, key, wrapAssertion(utils, key, function(properties, message) { utils.flag(this, "_name", key); if (utils.flag(this, "negate")) throw new Error(`${key} cannot be used with "not"`); const expected = utils.flag(this, "object"); const test = getTest(key, this); if (typeof properties === "string" && typeof message === "undefined") { message = properties; properties = void 0; } const errorMessage = utils.flag(this, "message"); getSnapshotClient().assert({ received: expected, message, isInline: false, properties, errorMessage, ...getTestNames(test) }); })); utils.addMethod(chai.Assertion.prototype, "toMatchFileSnapshot", function(file, message) { utils.flag(this, "_name", "toMatchFileSnapshot"); if (utils.flag(this, "negate")) throw new Error("toMatchFileSnapshot cannot be used with \"not\""); const error = /* @__PURE__ */ new Error("resolves"); const expected = utils.flag(this, "object"); const test = getTest("toMatchFileSnapshot", this); const errorMessage = utils.flag(this, "message"); return recordAsyncExpect(test, getSnapshotClient().assertRaw({ received: expected, message, isInline: false, rawSnapshot: { file }, errorMessage, ...getTestNames(test) }), createAssertionMessage(utils, this, true), error, utils.flag(this, "soft")); }); utils.addMethod(chai.Assertion.prototype, "toMatchInlineSnapshot", wrapAssertion(utils, "toMatchInlineSnapshot", function __INLINE_SNAPSHOT_OFFSET_3__(properties, inlineSnapshot, message) { utils.flag(this, "_name", "toMatchInlineSnapshot"); if (utils.flag(this, "negate")) throw new Error("toMatchInlineSnapshot cannot be used with \"not\""); const test = getTest("toMatchInlineSnapshot", this); const expected = utils.flag(this, "object"); const error = utils.flag(this, "error"); if (typeof properties === "string") { message = inlineSnapshot; inlineSnapshot = properties; properties = void 0; } if (inlineSnapshot) inlineSnapshot = stripSnapshotIndentation(inlineSnapshot); const errorMessage = utils.flag(this, "message"); getSnapshotClient().assert({ received: expected, message, isInline: true, properties, inlineSnapshot, error, errorMessage, ...getTestNames(test) }); })); utils.addMethod(chai.Assertion.prototype, "toThrowErrorMatchingSnapshot", wrapAssertion(utils, "toThrowErrorMatchingSnapshot", function(properties, message) { utils.flag(this, "_name", "toThrowErrorMatchingSnapshot"); if (utils.flag(this, "negate")) throw new Error("toThrowErrorMatchingSnapshot cannot be used with \"not\""); const expected = utils.flag(this, "object"); const test = getTest("toThrowErrorMatchingSnapshot", this); const promise = utils.flag(this, "promise"); const errorMessage = utils.flag(this, "message"); getSnapshotClient().assert({ received: getError(expected, promise), message, errorMessage, ...getTestNames(test) }); })); utils.addMethod(chai.Assertion.prototype, "toThrowErrorMatchingInlineSnapshot", wrapAssertion(utils, "toThrowErrorMatchingInlineSnapshot", function __INLINE_SNAPSHOT_OFFSET_3__(inlineSnapshot, message) { if (utils.flag(this, "negate")) throw new Error("toThrowErrorMatchingInlineSnapshot cannot be used with \"not\""); const test = getTest("toThrowErrorMatchingInlineSnapshot", this); const expected = utils.flag(this, "object"); const error = utils.flag(this, "error"); const promise = utils.flag(this, "promise"); const errorMessage = utils.flag(this, "message"); if (inlineSnapshot) inlineSnapshot = stripSnapshotIndentation(inlineSnapshot); getSnapshotClient().assert({ received: getError(expected, promise), message, inlineSnapshot, isInline: true, error, errorMessage, ...getTestNames(test) }); })); utils.addMethod(chai.expect, "addSnapshotSerializer", addSerializer); }; chai.use(JestExtend); chai.use(JestChaiExpect); chai.use(ChaiStyleAssertions); chai.use(SnapshotPlugin); chai.use(JestAsymmetricMatchers); function createExpect(test) { const expect = ((value, message) => { const { assertionCalls } = getState(expect); setState({ assertionCalls: assertionCalls + 1 }, expect); const assert = chai.expect(value, message); const _test = test || getCurrentTest(); if (_test) // @ts-expect-error internal return assert.withTest(_test); else return assert; }); Object.assign(expect, chai.expect); Object.assign(expect, globalThis[ASYMMETRIC_MATCHERS_OBJECT]); expect.getState = () => getState(expect); expect.setState = (state) => setState(state, expect); // @ts-expect-error global is not typed const globalState = getState(globalThis[GLOBAL_EXPECT]) || {}; setState({ ...globalState, assertionCalls: 0, isExpectingAssertions: false, isExpectingAssertionsError: null, expectedAssertionsNumber: null, expectedAssertionsNumberErrorGen: null, get testPath() { return getWorkerState().filepath; }, currentTestName: test ? test.fullTestName ?? "" : globalState.currentTestName }, expect); expect.assert = chai.assert; // @ts-expect-error untyped expect.extend = (matchers) => chai.expect.extend(expect, matchers); expect.addEqualityTesters = (customTesters) => addCustomEqualityTesters(customTesters); expect.soft = (...args) => { // @ts-expect-error private soft access return expect(...args).withContext({ soft: true }); }; expect.poll = createExpectPoll(expect); expect.unreachable = (message) => { chai.assert.fail(`expected${message ? ` "${message}" ` : " "}not to be reached`); }; function assertions(expected) { const errorGen = () => /* @__PURE__ */ new Error(`expected number of assertions to be ${expected}, but got ${expect.getState().assertionCalls}`); if (Error.captureStackTrace) Error.captureStackTrace(errorGen(), assertions); expect.setState({ expectedAssertionsNumber: expected, expectedAssertionsNumberErrorGen: errorGen }); } function hasAssertions() { const error = /* @__PURE__ */ new Error("expected any number of assertion, but got none"); if (Error.captureStackTrace) Error.captureStackTrace(error, hasAssertions); expect.setState({ isExpectingAssertions: true, isExpectingAssertionsError: error }); } chai.util.addMethod(expect, "assertions", assertions); chai.util.addMethod(expect, "hasAssertions", hasAssertions); expect.extend(customMatchers); return expect; } const globalExpect = createExpect(); Object.defineProperty(globalThis, GLOBAL_EXPECT, { value: globalExpect, writable: true, configurable: true }); const assert = chai.assert; const should = chai.should; /** * Gives access to injected context provided from the main thread. * This usually returns a value provided by `globalSetup` or an external library. */ function inject(key) { return getWorkerState().providedContext[key]; } var fakeTimersSrc = {}; var global; var hasRequiredGlobal; function requireGlobal () { if (hasRequiredGlobal) return global; hasRequiredGlobal = 1; /** * A reference to the global object * @type {object} globalObject */ var globalObject; /* istanbul ignore else */ if (typeof commonjsGlobal !== "undefined") { // Node globalObject = commonjsGlobal; } else if (typeof window !== "undefined") { // Browser globalObject = window; } else { // WebWorker globalObject = self; } global = globalObject; return global; } var throwsOnProto_1; var hasRequiredThrowsOnProto; function requireThrowsOnProto () { if (hasRequiredThrowsOnProto) return throwsOnProto_1; hasRequiredThrowsOnProto = 1; /** * Is true when the environment causes an error to be thrown for accessing the * __proto__ property. * This is necessary in order to support `node --disable-proto=throw`. * * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto * @type {boolean} */ let throwsOnProto; try { const object = {}; // eslint-disable-next-line no-proto, no-unused-expressions object.__proto__; throwsOnProto = false; } catch (_) { // This branch is covered when tests are run with `--disable-proto=throw`, // however we can test both branches at the same time, so this is ignored /* istanbul ignore next */ throwsOnProto = true; } throwsOnProto_1 = throwsOnProto; return throwsOnProto_1; } var copyPrototypeMethods; var hasRequiredCopyPrototypeMethods; function requireCopyPrototypeMethods () { if (hasRequiredCopyPrototypeMethods) return copyPrototypeMethods; hasRequiredCopyPrototypeMethods = 1; var call = Function.call; var throwsOnProto = requireThrowsOnProto(); var disallowedProperties = [ // ignore size because it throws from Map "size", "caller", "callee", "arguments", ]; // This branch is covered when tests are run with `--disable-proto=throw`, // however we can test both branches at the same time, so this is ignored /* istanbul ignore next */ if (throwsOnProto) { disallowedProperties.push("__proto__"); } copyPrototypeMethods = function copyPrototypeMethods(prototype) { // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods return Object.getOwnPropertyNames(prototype).reduce(function ( result, name ) { if (disallowedProperties.includes(name)) { return result; } if (typeof prototype[name] !== "function") { return result; } result[name] = call.bind(prototype[name]); return result; }, Object.create(null)); }; return copyPrototypeMethods; } var array; var hasRequiredArray; function requireArray () { if (hasRequiredArray) return array; hasRequiredArray = 1; var copyPrototype = requireCopyPrototypeMethods(); array = copyPrototype(Array.prototype); return array; } var calledInOrder_1; var hasRequiredCalledInOrder; function requireCalledInOrder () { if (hasRequiredCalledInOrder) return calledInOrder_1; hasRequiredCalledInOrder = 1; var every = requireArray().every; /** * @private */ function hasCallsLeft(callMap, spy) { if (callMap[spy.id] === undefined) { callMap[spy.id] = 0; } return callMap[spy.id] < spy.callCount; } /** * @private */ function checkAdjacentCalls(callMap, spy, index, spies) { var calledBeforeNext = true; if (index !== spies.length - 1) { calledBeforeNext = spy.calledBefore(spies[index + 1]); } if (hasCallsLeft(callMap, spy) && calledBeforeNext) { callMap[spy.id] += 1; return true; } return false; } /** * A Sinon proxy object (fake, spy, stub) * @typedef {object} SinonProxy * @property {Function} calledBefore - A method that determines if this proxy was called before another one * @property {string} id - Some id * @property {number} callCount - Number of times this proxy has been called */ /** * Returns true when the spies have been called in the order they were supplied in * @param {SinonProxy[] | SinonProxy} spies An array of proxies, or several proxies as arguments * @returns {boolean} true when spies are called in order, false otherwise */ function calledInOrder(spies) { var callMap = {}; // eslint-disable-next-line no-underscore-dangle var _spies = arguments.length > 1 ? arguments : spies; return every(_spies, checkAdjacentCalls.bind(null, callMap)); } calledInOrder_1 = calledInOrder; return calledInOrder_1; } var className_1; var hasRequiredClassName; function requireClassName () { if (hasRequiredClassName) return className_1; hasRequiredClassName = 1; /** * Returns a display name for a value from a constructor * @param {object} value A value to examine * @returns {(string|null)} A string or null */ function className(value) { const name = value.constructor && value.constructor.name; return name || null; } className_1 = className; return className_1; } var deprecated = {}; /* eslint-disable no-console */ var hasRequiredDeprecated; function requireDeprecated () { if (hasRequiredDeprecated) return deprecated; hasRequiredDeprecated = 1; (function (exports$1) { /** * Returns a function that will invoke the supplied function and print a * deprecation warning to the console each time it is called. * @param {Function} func * @param {string} msg * @returns {Function} */ exports$1.wrap = function (func, msg) { var wrapped = function () { exports$1.printWarning(msg); return func.apply(this, arguments); }; if (func.prototype) { wrapped.prototype = func.prototype; } return wrapped; }; /** * Returns a string which can be supplied to `wrap()` to notify the user that a * particular part of the sinon API has been deprecated. * @param {string} packageName * @param {string} funcName * @returns {string} */ exports$1.defaultMsg = function (packageName, funcName) { return `${packageName}.${funcName} is deprecated and will be removed from the public API in a future version of ${packageName}.`; }; /** * Prints a warning on the console, when it exists * @param {string} msg * @returns {undefined} */ exports$1.printWarning = function (msg) { /* istanbul ignore next */ if (typeof process === "object" && process.emitWarning) { // Emit Warnings in Node process.emitWarning(msg); } else if (console.info) { console.info(msg); } else { console.log(msg); } }; } (deprecated)); return deprecated; } var every; var hasRequiredEvery; function requireEvery () { if (hasRequiredEvery) return every; hasRequiredEvery = 1; /** * Returns true when fn returns true for all members of obj. * This is an every implementation that works for all iterables * @param {object} obj * @param {Function} fn * @returns {boolean} */ every = function every(obj, fn) { var pass = true; try { // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods obj.forEach(function () { if (!fn.apply(this, arguments)) { // Throwing an error is the only way to break `forEach` throw new Error(); } }); } catch (e) { pass = false; } return pass; }; return every; } var functionName; var hasRequiredFunctionName; function requireFunctionName () { if (hasRequiredFunctionName) return functionName; hasRequiredFunctionName = 1; /** * Returns a display name for a function * @param {Function} func * @returns {string} */ functionName = function functionName(func) { if (!func) { return ""; } try { return ( func.displayName || func.name || // Use function decomposition as a last resort to get function // name. Does not rely on function decomposition to work - if it // doesn't debugging will be slightly less informative // (i.e. toString will say 'spy' rather than 'myFunc'). (String(func).match(/function ([^\s(]+)/) || [])[1] ); } catch (e) { // Stringify may fail and we might get an exception, as a last-last // resort fall back to empty string. return ""; } }; return functionName; } var orderByFirstCall_1; var hasRequiredOrderByFirstCall; function requireOrderByFirstCall () { if (hasRequiredOrderByFirstCall) return orderByFirstCall_1; hasRequiredOrderByFirstCall = 1; var sort = requireArray().sort; var slice = requireArray().slice; /** * @private */ function comparator(a, b) { // uuid, won't ever be equal var aCall = a.getCall(0); var bCall = b.getCall(0); var aId = (aCall && aCall.callId) || -1; var bId = (bCall && bCall.callId) || -1; return aId < bId ? -1 : 1; } /** * A Sinon proxy object (fake, spy, stub) * @typedef {object} SinonProxy * @property {Function} getCall - A method that can return the first call */ /** * Sorts an array of SinonProxy instances (fake, spy, stub) by their first call * @param {SinonProxy[] | SinonProxy} spies * @returns {SinonProxy[]} */ function orderByFirstCall(spies) { return sort(slice(spies), comparator); } orderByFirstCall_1 = orderByFirstCall; return orderByFirstCall_1; } var _function; var hasRequired_function; function require_function () { if (hasRequired_function) return _function; hasRequired_function = 1; var copyPrototype = requireCopyPrototypeMethods(); _function = copyPrototype(Function.prototype); return _function; } var map; var hasRequiredMap; function requireMap () { if (hasRequiredMap) return map; hasRequiredMap = 1; var copyPrototype = requireCopyPrototypeMethods(); map = copyPrototype(Map.prototype); return map; } var object; var hasRequiredObject; function requireObject () { if (hasRequiredObject) return object; hasRequiredObject = 1; var copyPrototype = requireCopyPrototypeMethods(); object = copyPrototype(Object.prototype); return object; } var set; var hasRequiredSet; function requireSet () { if (hasRequiredSet) return set; hasRequiredSet = 1; var copyPrototype = requireCopyPrototypeMethods(); set = copyPrototype(Set.prototype); return set; } var string; var hasRequiredString; function requireString () { if (hasRequiredString) return string; hasRequiredString = 1; var copyPrototype = requireCopyPrototypeMethods(); string = copyPrototype(String.prototype); return string; } var prototypes; var hasRequiredPrototypes; function requirePrototypes () { if (hasRequiredPrototypes) return prototypes; hasRequiredPrototypes = 1; prototypes = { array: requireArray(), function: require_function(), map: requireMap(), object: requireObject(), set: requireSet(), string: requireString(), }; return prototypes; } var typeDetect$1 = {exports: {}}; var typeDetect = typeDetect$1.exports; var hasRequiredTypeDetect; function requireTypeDetect () { if (hasRequiredTypeDetect) return typeDetect$1.exports; hasRequiredTypeDetect = 1; (function (module, exports$1) { (function (global, factory) { module.exports = factory() ; }(typeDetect, (function () { /* ! * type-detect * Copyright(c) 2013 jake luer <jake@alogicalparadox.com> * MIT Licensed */ var promiseExists = typeof Promise === 'function'; /* eslint-disable no-undef */ var globalObject = typeof self === 'object' ? self : commonjsGlobal; // eslint-disable-line id-blacklist var symbolExists = typeof Symbol !== 'undefined'; var mapExists = typeof Map !== 'undefined'; var setExists = typeof Set !== 'undefined'; var weakMapExists = typeof WeakMap !== 'undefined'; var weakSetExists = typeof WeakSet !== 'undefined'; var dataViewExists = typeof DataView !== 'undefined'; var symbolIteratorExists = symbolExists && typeof Symbol.iterator !== 'undefined'; var symbolToStringTagExists = symbolExists && typeof Symbol.toStringTag !== 'undefined'; var setEntriesExists = setExists && typeof Set.prototype.entries === 'function'; var mapEntriesExists = mapExists && typeof Map.prototype.entries === 'function'; var setIteratorPrototype = setEntriesExists && Object.getPrototypeOf(new Set().entries()); var mapIteratorPrototype = mapEntriesExists && Object.getPrototypeOf(new Map().entries()); var arrayIteratorExists = symbolIteratorExists && typeof Array.prototype[Symbol.iterator] === 'function'; var arrayIteratorPrototype = arrayIteratorExists && Object.getPrototypeOf([][Symbol.iterator]()); var stringIteratorExists = symbolIteratorExists && typeof String.prototype[Symbol.iterator] === 'function'; var stringIteratorPrototype = stringIteratorExists && Object.getPrototypeOf(''[Symbol.iterator]()); var toStringLeftSliceLength = 8; var toStringRightSliceLength = -1; /** * ### typeOf (obj) * * Uses `Object.prototype.toString` to determine the type of an object, * normalising behaviour across engine versions & well optimised. * * @param {Mixed} object * @return {String} object type * @api public */ function typeDetect(obj) { /* ! Speed optimisation * Pre: * string literal x 3,039,035 ops/sec ±1.62% (78 runs sampled) * boolean literal x 1,424,138 ops/sec ±4.54% (75 runs sampled) * number literal x 1,653,153 ops/sec ±1.91% (82 runs sampled) * undefined x 9,978,660 ops/sec ±1.92% (75 runs sampled) * function x 2,556,769 ops/sec ±1.73% (77 runs sampled) * Post: * string literal x 38,564,796 ops/sec ±1.15% (79 runs sampled) * boolean literal x 31,148,940 ops/sec ±1.10% (79 runs sampled) * number literal x 32,679,330 ops/sec ±1.90% (78 runs sampled) * undefined x 32,363,368 ops/sec ±1.07% (82 runs sampled) * function x 31,296,870 ops/sec ±0.96% (83 runs sampled) */ var typeofObj = typeof obj; if (typeofObj !== 'object') { return typeofObj; } /* ! Speed optimisation * Pre: * null x 28,645,765 ops/sec ±1.17% (82 runs sampled) * Post: * null x 36,428,962 ops/sec ±1.37% (84 runs sampled) */ if (obj === null) { return 'null'; } /* ! Spec Conformance * Test: `Object.prototype.toString.call(window)`` * - Node === "[object global]" * - Chrome === "[object global]" * - Firefox === "[object Window]" * - PhantomJS === "[object Window]" * - Safari === "[object Window]" * - IE 11 === "[object Window]" * - IE Edge === "[object Window]" * Test: `Object.prototype.toString.call(this)`` * - Chrome Worker === "[object global]" * - Firefox Worker === "[object DedicatedWorkerGlobalScope]" * - Safari Worker === "[object DedicatedWorkerGlobalScope]" * - IE 11 Worker === "[object WorkerGlobalScope]" * - IE Edge Worker === "[object WorkerGlobalScope]" */ if (obj === globalObject) { return 'global'; } /* ! Speed optimisation * Pre: * array literal x 2,888,352 ops/sec ±0.67% (82 runs sampled) * Post: * array literal x 22,479,650 ops/sec ±0.96% (81 runs sampled) */ if ( Array.isArray(obj) && (symbolToStringTagExists === false || !(Symbol.toStringTag in obj)) ) { return 'Array'; } // Not caching existence of `window` and related properties due to potential // for `window` to be unset before tests in quasi-browser environments. if (typeof window === 'object' && window !== null) { /* ! Spec Conformance * (https://html.spec.whatwg.org/multipage/browsers.html#location) * WhatWG HTML$7.7.3 - The `Location` interface * Test: `Object.prototype.toString.call(window.location)`` * - IE <=11 === "[object Object]" * - IE Edge <=13 === "[object Object]" */ if (typeof window.location === 'object' && obj === window.location) { return 'Location'; } /* ! Spec Conformance * (https://html.spec.whatwg.org/#document) * WhatWG HTML$3.1.1 - The `Document` object * Note: Most browsers currently adher to the W3C DOM Level 2 spec * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-26809268) * which suggests that browsers should use HTMLTableCellElement for * both TD and TH elements. WhatWG separates these. * WhatWG HTML states: * > For historical reasons, Window objects must also have a * > writable, configurable, non-enumerable property named * > HTMLDocument whose value is the Document interface object. * Test: `Object.prototype.toString.call(document)`` * - Chrome === "[object HTMLDocument]" * - Firefox === "[object HTMLDocument]" * - Safari === "[object HTMLDocument]" * - IE <=10 === "[object Document]" * - IE 11 === "[object HTMLDocument]" * - IE Edge <=13 === "[object HTMLDocument]" */ if (typeof window.document === 'object' && obj === window.document) { return 'Document'; } if (typeof window.navigator === 'object') { /* ! Spec Conformance * (https://html.spec.whatwg.org/multipage/webappapis.html#mimetypearray) * WhatWG HTML$8.6.1.5 - Plugins - Interface MimeTypeArray * Test: `Object.prototype.toString.call(navigator.mimeTypes)`` * - IE <=10 === "[object MSMimeTypesCollection]" */ if (typeof window.navigator.mimeTypes === 'object' && obj === window.navigator.mimeTypes) { return 'MimeTypeArray'; } /* ! Spec Conformance * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) * WhatWG HTML$8.6.1.5 - Plugins - Interface PluginArray * Test: `Object.prototype.toString.call(navigator.plugins)`` * - IE <=10 === "[object MSPluginsCollection]" */ if (typeof window.navigator.plugins === 'object' && obj === window.navigator.plugins) { return 'PluginArray'; } } if ((typeof window.HTMLElement === 'function' || typeof window.HTMLElement === 'object') && obj instanceof window.HTMLElement) { /* ! Spec Conformance * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) * WhatWG HTML$4.4.4 - The `blockquote` element - Interface `HTMLQuoteElement` * Test: `Object.prototype.toString.call(document.createElement('blockquote'))`` * - IE <=10 === "[object HTMLBlockElement]" */ if (obj.tagName === 'BLOCKQUOTE') { return 'HTMLQuoteElement'; } /* ! Spec Conformance * (https://html.spec.whatwg.org/#htmltabledatacellelement) * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableDataCellElement` * Note: Most browsers currently adher to the W3C DOM Level 2 spec * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) * which suggests that browsers should use HTMLTableCellElement for * both TD and TH elements. WhatWG separates these. * Test: Object.prototype.toString.call(document.createElement('td')) * - Chrome === "[object HTMLTableCellElement]" * - Firefox === "[object HTMLTableCellElement]" * - Safari === "[object HTMLTableCellElement]" */ if (obj.tagName === 'TD') { return 'HTMLTableDataCellElement'; } /* ! Spec Conformance * (https://html.spec.whatwg.org/#htmltableheadercellelement) * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableHeaderCellElement` * Note: Most browsers currently adher to the W3C DOM Level 2 spec * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) * which suggests that browsers should use HTMLTableCellElement for * both TD and TH elements. WhatWG separates these. * Test: Object.prototype.toString.call(document.createElement('th')) * - Chrome === "[object HTMLTableCellElement]" * - Firefox === "[object HTMLTableCellElement]" * - Safari === "[object HTMLTableCellElement]" */ if (obj.tagName === 'TH') { return 'HTMLTableHeaderCellElement'; } } } /* ! Speed optimisation * Pre: * Float64Array x 625,644 ops/sec ±1.58% (80 runs sampled) * Float32Array x 1,279,852 ops/sec ±2.91% (77 runs sampled) * Uint32Array x 1,178,185 ops/sec ±1.95% (83 runs sampled) * Uint16Array x 1,008,380 ops/sec ±2.25% (80 runs sampled) * Uint8Array x 1,128,040 ops/sec ±2.11% (81 runs sampled) * Int32Array x 1,170,119 ops/sec ±2.88% (80 runs sampled) * Int16Array x 1,176,348 ops/sec ±5.79% (86 runs sampled) * Int8Array x 1,058,707 ops/sec ±4.94% (77 runs sampled) * Uint8ClampedArray x 1,110,633 ops/sec ±4.20% (80 runs sampled) * Post: * Float64Array x 7,105,671 ops/sec ±13.47% (64 runs sampled) * Float32Array x 5,887,912 ops/sec ±1.46% (82 runs sampled) * Uint32Array x 6,491,661 ops/sec ±1.76% (79 runs sampled) * Uint16Array x 6,559,795 ops/sec ±1.67% (82 runs sampled) * Uint8Array x 6,463,966 ops/sec ±1.43% (85 runs sampled) * Int32Array x 5,641,841 ops/sec ±3.49% (81 runs sampled) * Int16Array x 6,583,511 ops/sec ±1.98% (80 runs sampled) * Int8Array x 6,606,078 ops/sec ±1.74% (81 runs sampled) * Uint8ClampedArray x 6,602,224 ops/sec ±1.77% (83 runs sampled) */ var stringTag = (symbolToStringTagExists && obj[Symbol.toStringTag]); if (typeof stringTag === 'string') { return stringTag; } var objPrototype = Object.getPrototypeOf(obj); /* ! Speed optimisation * Pre: * regex literal x 1,772,385 ops/sec ±1.85% (77 runs sampled) * regex constructor x 2,143,634 ops/sec ±2.46% (78 runs sampled) * Post: * regex literal x 3,928,009 ops/sec ±0.65% (78 runs sampled) * regex constructor x 3,931,108 ops/sec ±0.58% (84 runs sampled) */ if (objPrototype === RegExp.prototype) { return 'RegExp'; } /* ! Speed optimisation * Pre: * date x 2,130,074 ops/sec ±4.42% (68 runs sampled) * Post: * date x 3,953,779 ops/sec ±1.35% (77 runs sampled) */ if (objPrototype === Date.prototype) { return 'Date'; } /* ! Spec Conformance * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-promise.prototype-@@tostringtag) * ES6$25.4.5.4 - Promise.prototype[@@toStringTag] should be "Promise": * Test: `Object.prototype.toString.call(Promise.resolve())`` * - Chrome <=47 === "[object Object]" * - Edge <=20 === "[object Object]" * - Firefox 29-Latest === "[object Promise]" * - Safari 7.1-Latest === "[object Promise]" */ if (promiseExists && objPrototype === Promise.prototype) { return 'Promise'; } /* ! Speed optimisation * Pre: * set x 2,222,186 ops/sec ±1.31% (82 runs sampled) * Post: * set x 4,545,879 ops/sec ±1.13% (83 runs sampled) */ if (setExists && objPrototype === Set.prototype) { return 'Set'; } /* ! Speed optimisation * Pre: * map x 2,396,842 ops/sec ±1.59% (81 runs sampled) * Post: * map x 4,183,945 ops/sec ±6.59% (82 runs sampled) */ if (mapExists && objPrototype === Map.prototype) { return 'Map'; } /* ! Speed optimisation * Pre: * weakset x 1,323,220 ops/sec ±2.17% (76 runs sampled) * Post: * weakset x 4,237,510 ops/sec ±2.01% (77 runs sampled) */ if (weakSetExists && objPrototype === WeakSet.prototype) { return 'WeakSet'; } /* ! Speed optimisation * Pre: * weakmap x 1,500,260 ops/sec ±2.02% (78 runs sampled) * Post: * weakmap x 3,881,384 ops/sec ±1.45% (82 runs sampled) */ if (weakMapExists && objPrototype === WeakMap.prototype) { return 'WeakMap'; } /* ! Spec Conformance * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-dataview.prototype-@@tostringtag) * ES6$24.2.4.21 - DataView.prototype[@@toStringTag] should be "DataView": * Test: `Object.prototype.toString.call(new DataView(new ArrayBuffer(1)))`` * - Edge <=13 === "[object Object]" */ if (dataViewExists && objPrototype === DataView.prototype) { return 'DataView'; } /* ! Spec Conformance * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%mapiteratorprototype%-@@tostringtag) * ES6$23.1.5.2.2 - %MapIteratorPrototype%[@@toStringTag] should be "Map Iterator": * Test: `Object.prototype.toString.call(new Map().entries())`` * - Edge <=13 === "[object Object]" */ if (mapExists && objPrototype === mapIteratorPrototype) { return 'Map Iterator'; } /* ! Spec Conformance * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%setiteratorprototype%-@@tostringtag) * ES6$23.2.5.2.2 - %SetIteratorPrototype%[@@toStringTag] should be "Set Iterator": * Test: `Object.prototype.toString.call(new Set().entries())`` * - Edge <=13 === "[object Object]" */ if (setExists && objPrototype === setIteratorPrototype) { return 'Set Iterator'; } /* ! Spec Conformance * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%arrayiteratorprototype%-@@tostringtag) * ES6$22.1.5.2.2 - %ArrayIteratorPrototype%[@@toStringTag] should be "Array Iterator": * Test: `Object.prototype.toString.call([][Symbol.iterator]())`` * - Edge <=13 === "[object Object]" */ if (arrayIteratorExists && objPrototype === arrayIteratorPrototype) { return 'Array Iterator'; } /* ! Spec Conformance * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%stringiteratorprototype%-@@tostringtag) * ES6$21.1.5.2.2 - %StringIteratorPrototype%[@@toStringTag] should be "String Iterator": * Test: `Object.prototype.toString.call(''[Symbol.iterator]())`` * - Edge <=13 === "[object Object]" */ if (stringIteratorExists && objPrototype === stringIteratorPrototype) { return 'String Iterator'; } /* ! Speed optimisation * Pre: * object from null x 2,424,320 ops/sec ±1.67% (76 runs sampled) * Post: * object from null x 5,838,000 ops/sec ±0.99% (84 runs sampled) */ if (objPrototype === null) { return 'Object'; } return Object .prototype .toString .call(obj) .slice(toStringLeftSliceLength, toStringRightSliceLength); } return typeDetect; }))); } (typeDetect$1)); return typeDetect$1.exports; } var typeOf; var hasRequiredTypeOf; function requireTypeOf () { if (hasRequiredTypeOf) return typeOf; hasRequiredTypeOf = 1; var type = requireTypeDetect(); /** * Returns the lower-case result of running type from type-detect on the value * @param {*} value * @returns {string} */ typeOf = function typeOf(value) { return type(value).toLowerCase(); }; return typeOf; } var valueToString_1; var hasRequiredValueToString; function requireValueToString () { if (hasRequiredValueToString) return valueToString_1; hasRequiredValueToString = 1; /** * Returns a string representation of the value * @param {*} value * @returns {string} */ function valueToString(value) { if (value && value.toString) { // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods return value.toString(); } return String(value); } valueToString_1 = valueToString; return valueToString_1; } var lib; var hasRequiredLib; function requireLib () { if (hasRequiredLib) return lib; hasRequiredLib = 1; lib = { global: requireGlobal(), calledInOrder: requireCalledInOrder(), className: requireClassName(), deprecated: requireDeprecated(), every: requireEvery(), functionName: requireFunctionName(), orderByFirstCall: requireOrderByFirstCall(), prototypes: requirePrototypes(), typeOf: requireTypeOf(), valueToString: requireValueToString(), }; return lib; } var hasRequiredFakeTimersSrc; function requireFakeTimersSrc () { if (hasRequiredFakeTimersSrc) return fakeTimersSrc; hasRequiredFakeTimersSrc = 1; const globalObject = requireLib().global; let timersModule, timersPromisesModule; if (typeof __vitest_required__ !== 'undefined') { try { timersModule = __vitest_required__.timers; } catch (e) { // ignored } try { timersPromisesModule = __vitest_required__.timersPromises; } catch (e) { // ignored } } /** * @typedef {"nextAsync" | "manual" | "interval"} TickMode */ /** * @typedef {object} NextAsyncTickMode * @property {"nextAsync"} mode */ /** * @typedef {object} ManualTickMode * @property {"manual"} mode */ /** * @typedef {object} IntervalTickMode * @property {"interval"} mode * @property {number} [delta] */ /** * @typedef {IntervalTickMode | NextAsyncTickMode | ManualTickMode} TimerTickMode */ /** * @typedef {object} IdleDeadline * @property {boolean} didTimeout - whether or not the callback was called before reaching the optional timeout * @property {function():number} timeRemaining - a floating-point value providing an estimate of the number of milliseconds remaining in the current idle period */ /** * Queues a function to be called during a browser's idle periods * @callback RequestIdleCallback * @param {function(IdleDeadline)} callback * @param {{timeout: number}} options - an options object * @returns {number} the id */ /** * @callback NextTick * @param {VoidVarArgsFunc} callback - the callback to run * @param {...*} args - optional arguments to call the callback with * @returns {void} */ /** * @callback SetImmediate * @param {VoidVarArgsFunc} callback - the callback to run * @param {...*} args - optional arguments to call the callback with * @returns {NodeImmediate} */ /** * @callback VoidVarArgsFunc * @param {...*} callback - the callback to run * @returns {void} */ /** * @typedef RequestAnimationFrame * @property {function(number):void} requestAnimationFrame * @returns {number} - the id */ /** * @typedef Performance * @property {function(): number} now */ /* eslint-disable jsdoc/require-property-description */ /** * @typedef {object} Clock * @property {number} now - the current time * @property {Date} Date - the Date constructor * @property {number} loopLimit - the maximum number of timers before assuming an infinite loop * @property {RequestIdleCallback} requestIdleCallback * @property {function(number):void} cancelIdleCallback * @property {setTimeout} setTimeout * @property {clearTimeout} clearTimeout * @property {NextTick} nextTick * @property {queueMicrotask} queueMicrotask * @property {setInterval} setInterval * @property {clearInterval} clearInterval * @property {SetImmediate} setImmediate * @property {function(NodeImmediate):void} clearImmediate * @property {function():number} countTimers * @property {RequestAnimationFrame} requestAnimationFrame * @property {function(number):void} cancelAnimationFrame * @property {function():void} runMicrotasks * @property {function(string | number): number} tick * @property {function(string | number): Promise<number>} tickAsync * @property {function(): number} next * @property {function(): Promise<number>} nextAsync * @property {function(): number} runAll * @property {function(): number} runToFrame * @property {function(): Promise<number>} runAllAsync * @property {function(): number} runToLast * @property {function(): Promise<number>} runToLastAsync * @property {function(): void} reset * @property {function(number | Date): void} setSystemTime * @property {function(number): void} jump * @property {Performance} performance * @property {function(number[]): number[]} hrtime - process.hrtime (legacy) * @property {function(): void} uninstall Uninstall the clock. * @property {Function[]} methods - the methods that are faked * @property {boolean} [shouldClearNativeTimers] inherited from config * @property {{methodName:string, original:any}[] | undefined} timersModuleMethods * @property {{methodName:string, original:any}[] | undefined} timersPromisesModuleMethods * @property {Map<function(): void, AbortSignal>} abortListenerMap * @property {function(TimerTickMode): void} setTickMode */ /* eslint-enable jsdoc/require-property-description */ /** * Configuration object for the `install` method. * @typedef {object} Config * @property {number|Date} [now] a number (in milliseconds) or a Date object (default epoch) * @property {string[]} [toFake] names of the methods that should be faked. * @property {number} [loopLimit] the maximum number of timers that will be run when calling runAll() * @property {boolean} [shouldAdvanceTime] tells FakeTimers to increment mocked time automatically (default false) * @property {number} [advanceTimeDelta] increment mocked time every <<advanceTimeDelta>> ms (default: 20ms) * @property {boolean} [shouldClearNativeTimers] forwards clear timer calls to native functions if they are not fakes (default: false) * @property {boolean} [ignoreMissingTimers] default is false, meaning asking to fake timers that are not present will throw an error */ /* eslint-disable jsdoc/require-property-description */ /** * The internal structure to describe a scheduled fake timer * @typedef {object} Timer * @property {Function} func * @property {*[]} args * @property {number} delay * @property {number} callAt * @property {number} createdAt * @property {boolean} immediate * @property {number} id * @property {Error} [error] */ /** * A Node timer * @typedef {object} NodeImmediate * @property {function(): boolean} hasRef * @property {function(): NodeImmediate} ref * @property {function(): NodeImmediate} unref */ /* eslint-enable jsdoc/require-property-description */ /* eslint-disable complexity */ /** * Mocks available features in the specified global namespace. * @param {*} _global Namespace to mock (e.g. `window`) * @returns {FakeTimers} */ function withGlobal(_global) { const maxTimeout = Math.pow(2, 31) - 1; //see https://heycam.github.io/webidl/#abstract-opdef-converttoint const idCounterStart = 1e12; // arbitrarily large number to avoid collisions with native timer IDs const NOOP = function () { return undefined; }; const NOOP_ARRAY = function () { return []; }; const isPresent = {}; let timeoutResult, addTimerReturnsObject = false; if (_global.setTimeout) { isPresent.setTimeout = true; timeoutResult = _global.setTimeout(NOOP, 0); addTimerReturnsObject = typeof timeoutResult === "object"; } isPresent.clearTimeout = Boolean(_global.clearTimeout); isPresent.setInterval = Boolean(_global.setInterval); isPresent.clearInterval = Boolean(_global.clearInterval); isPresent.hrtime = _global.process && typeof _global.process.hrtime === "function";