@vitest/runner
Advanced tools
| import { DiffOptions } from '@vitest/utils/diff'; | ||
| import { TestError, Awaitable } from '@vitest/utils'; | ||
| /** | ||
| * This is a subset of Vitest config that's required for the runner to work. | ||
| */ | ||
| interface VitestRunnerConfig { | ||
| root: string; | ||
| setupFiles: string[]; | ||
| name?: string; | ||
| passWithNoTests: boolean; | ||
| testNamePattern?: RegExp; | ||
| allowOnly?: boolean; | ||
| sequence: { | ||
| shuffle?: boolean; | ||
| concurrent?: boolean; | ||
| seed: number; | ||
| hooks: SequenceHooks; | ||
| setupFiles: SequenceSetupFiles; | ||
| }; | ||
| chaiConfig?: { | ||
| truncateThreshold?: number; | ||
| }; | ||
| maxConcurrency: number; | ||
| testTimeout: number; | ||
| hookTimeout: number; | ||
| retry: SerializableRetry; | ||
| includeTaskLocation?: boolean; | ||
| diffOptions?: DiffOptions; | ||
| tags: TestTagDefinition[]; | ||
| tagsFilter?: string[]; | ||
| strictTags: boolean; | ||
| } | ||
| /** | ||
| * Possible options to run a single file in a test. | ||
| */ | ||
| interface FileSpecification { | ||
| filepath: string; | ||
| fileTags?: string[]; | ||
| testLocations: number[] | undefined; | ||
| testNamePattern: RegExp | undefined; | ||
| testTagsFilter: string[] | undefined; | ||
| testIds: string[] | undefined; | ||
| } | ||
| interface TestTagDefinition extends Omit<TestOptions, "tags" | "shuffle"> { | ||
| /** | ||
| * The name of the tag. This is what you use in the `tags` array in tests. | ||
| */ | ||
| name: keyof TestTags extends never ? string : TestTags[keyof TestTags]; | ||
| /** | ||
| * A description for the tag. This will be shown in the CLI help and UI. | ||
| */ | ||
| description?: string; | ||
| /** | ||
| * Priority for merging options when multiple tags with the same options are applied to a test. | ||
| * | ||
| * Lower number means higher priority. E.g., priority 1 takes precedence over priority 3. | ||
| */ | ||
| priority?: number; | ||
| } | ||
| type VitestRunnerImportSource = "collect" | "setup"; | ||
| interface VitestRunnerConstructor { | ||
| new (config: VitestRunnerConfig): VitestRunner; | ||
| } | ||
| type CancelReason = "keyboard-input" | "test-failure" | (string & Record<string, never>); | ||
| interface VitestRunner { | ||
| /** | ||
| * First thing that's getting called before actually collecting and running tests. | ||
| */ | ||
| onBeforeCollect?: (paths: string[]) => unknown; | ||
| /** | ||
| * Called after the file task was created but not collected yet. | ||
| */ | ||
| onCollectStart?: (file: File) => unknown; | ||
| /** | ||
| * Called after collecting tests and before "onBeforeRun". | ||
| */ | ||
| onCollected?: (files: File[]) => unknown; | ||
| /** | ||
| * Called when test runner should cancel next test runs. | ||
| * Runner should listen for this method and mark tests and suites as skipped in | ||
| * "onBeforeRunSuite" and "onBeforeRunTask" when called. | ||
| */ | ||
| cancel?: (reason: CancelReason) => unknown; | ||
| /** | ||
| * Called before running a single test. Doesn't have "result" yet. | ||
| */ | ||
| onBeforeRunTask?: (test: Test) => unknown; | ||
| /** | ||
| * Called before actually running the test function. Already has "result" with "state" and "startTime". | ||
| */ | ||
| onBeforeTryTask?: (test: Test, options: { | ||
| retry: number; | ||
| repeats: number; | ||
| }) => unknown; | ||
| /** | ||
| * When the task has finished running, but before cleanup hooks are called | ||
| */ | ||
| onTaskFinished?: (test: Test) => unknown; | ||
| /** | ||
| * Called after result and state are set. | ||
| */ | ||
| onAfterRunTask?: (test: Test) => unknown; | ||
| /** | ||
| * Called right after running the test function. Doesn't have new state yet. Will not be called, if the test function throws. | ||
| */ | ||
| onAfterTryTask?: (test: Test, options: { | ||
| retry: number; | ||
| repeats: number; | ||
| }) => unknown; | ||
| /** | ||
| * Called after the retry resolution happend. Unlike `onAfterTryTask`, the test now has a new state. | ||
| * All `after` hooks were also called by this point. | ||
| */ | ||
| onAfterRetryTask?: (test: Test, options: { | ||
| retry: number; | ||
| repeats: number; | ||
| }) => unknown; | ||
| /** | ||
| * Called before running a single suite. Doesn't have "result" yet. | ||
| */ | ||
| onBeforeRunSuite?: (suite: Suite) => unknown; | ||
| /** | ||
| * Called after running a single suite. Has state and result. | ||
| */ | ||
| onAfterRunSuite?: (suite: Suite) => unknown; | ||
| /** | ||
| * If defined, will be called instead of usual Vitest suite partition and handling. | ||
| * "before" and "after" hooks will not be ignored. | ||
| */ | ||
| runSuite?: (suite: Suite) => Promise<void>; | ||
| /** | ||
| * If defined, will be called instead of usual Vitest handling. Useful, if you have your custom test function. | ||
| * "before" and "after" hooks will not be ignored. | ||
| */ | ||
| runTask?: (test: Test) => Promise<void>; | ||
| /** | ||
| * Called, when a task is updated. The same as "onTaskUpdate" in a reporter, but this is running in the same thread as tests. | ||
| */ | ||
| onTaskUpdate?: (task: TaskResultPack[], events: TaskEventPack[]) => Promise<void>; | ||
| /** | ||
| * Called when annotation is added via the `context.annotate` method. | ||
| */ | ||
| onTestAnnotate?: (test: Test, annotation: TestAnnotation) => Promise<TestAnnotation>; | ||
| /** | ||
| * @experimental | ||
| * | ||
| * Called when artifacts are recorded on tests via the `recordArtifact` utility. | ||
| */ | ||
| onTestArtifactRecord?: <Artifact extends TestArtifact>(test: Test, artifact: Artifact) => Promise<Artifact>; | ||
| /** | ||
| * Called before running all tests in collected paths. | ||
| */ | ||
| onBeforeRunFiles?: (files: File[]) => unknown; | ||
| /** | ||
| * Called right after running all tests in collected paths. | ||
| */ | ||
| onAfterRunFiles?: (files: File[]) => unknown; | ||
| /** | ||
| * Called when new context for a test is defined. Useful if you want to add custom properties to the context. | ||
| * If you only want to define custom context, consider using "beforeAll" in "setupFiles" instead. | ||
| * | ||
| * @see https://vitest.dev/advanced/runner#your-task-function | ||
| */ | ||
| extendTaskContext?: (context: TestContext) => TestContext; | ||
| /** | ||
| * Called when test and setup files are imported. Can be called in two situations: when collecting tests and when importing setup files. | ||
| */ | ||
| importFile: (filepath: string, source: VitestRunnerImportSource) => unknown; | ||
| /** | ||
| * Function that is called when the runner attempts to get the value when `test.extend` is used with `{ injected: true }` | ||
| */ | ||
| injectValue?: (key: string) => unknown; | ||
| /** | ||
| * Gets the time spent importing each individual non-externalized file that Vitest collected. | ||
| */ | ||
| getImportDurations?: () => Record<string, ImportDuration>; | ||
| /** | ||
| * Publicly available configuration. | ||
| */ | ||
| config: VitestRunnerConfig; | ||
| /** | ||
| * The name of the current pool. Can affect how stack trace is inferred on the server side. | ||
| */ | ||
| pool?: string; | ||
| /** | ||
| * The current Vite environment that processes the files on the server. | ||
| */ | ||
| viteEnvironment?: string; | ||
| /** | ||
| * Return the worker context for fixtures specified with `scope: 'worker'` | ||
| */ | ||
| getWorkerContext?: () => Record<string, unknown>; | ||
| onCleanupWorkerContext?: (cleanup: () => unknown) => void; | ||
| trace?<T>(name: string, cb: () => T): T; | ||
| trace?<T>(name: string, attributes: Record<string, any>, cb: () => T): T; | ||
| /** @private */ | ||
| _currentTaskStartTime?: number; | ||
| /** @private */ | ||
| _currentTaskTimeout?: number; | ||
| } | ||
| interface FixtureItem extends FixtureOptions { | ||
| prop: string; | ||
| value: any; | ||
| scope: "test" | "file" | "worker"; | ||
| /** | ||
| * Indicates whether the fixture is a function | ||
| */ | ||
| isFn: boolean; | ||
| /** | ||
| * The dependencies(fixtures) of current fixture function. | ||
| */ | ||
| deps?: FixtureItem[]; | ||
| } | ||
| /** | ||
| * Registers a callback function to be executed once before all tests within the current suite. | ||
| * This hook is useful for scenarios where you need to perform setup operations that are common to all tests in a suite, such as initializing a database connection or setting up a test environment. | ||
| * | ||
| * **Note:** The `beforeAll` hooks are executed in the order they are defined one after another. You can configure this by changing the `sequence.hooks` option in the config file. | ||
| * | ||
| * @param {Function} fn - The callback function to be executed before all tests. | ||
| * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used. | ||
| * @returns {void} | ||
| * @example | ||
| * ```ts | ||
| * // Example of using beforeAll to set up a database connection | ||
| * beforeAll(async () => { | ||
| * await database.connect(); | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function beforeAll(fn: BeforeAllListener, timeout?: number): void; | ||
| /** | ||
| * Registers a callback function to be executed once after all tests within the current suite have completed. | ||
| * This hook is useful for scenarios where you need to perform cleanup operations after all tests in a suite have run, such as closing database connections or cleaning up temporary files. | ||
| * | ||
| * **Note:** The `afterAll` hooks are running in reverse order of their registration. You can configure this by changing the `sequence.hooks` option in the config file. | ||
| * | ||
| * @param {Function} fn - The callback function to be executed after all tests. | ||
| * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used. | ||
| * @returns {void} | ||
| * @example | ||
| * ```ts | ||
| * // Example of using afterAll to close a database connection | ||
| * afterAll(async () => { | ||
| * await database.disconnect(); | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function afterAll(fn: AfterAllListener, timeout?: number): void; | ||
| /** | ||
| * Registers a callback function to be executed before each test within the current suite. | ||
| * This hook is useful for scenarios where you need to reset or reinitialize the test environment before each test runs, such as resetting database states, clearing caches, or reinitializing variables. | ||
| * | ||
| * **Note:** The `beforeEach` hooks are executed in the order they are defined one after another. You can configure this by changing the `sequence.hooks` option in the config file. | ||
| * | ||
| * @param {Function} fn - The callback function to be executed before each test. This function receives an `TestContext` parameter if additional test context is needed. | ||
| * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used. | ||
| * @returns {void} | ||
| * @example | ||
| * ```ts | ||
| * // Example of using beforeEach to reset a database state | ||
| * beforeEach(async () => { | ||
| * await database.reset(); | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function beforeEach<ExtraContext = object>(fn: BeforeEachListener<ExtraContext>, timeout?: number): void; | ||
| /** | ||
| * Registers a callback function to be executed after each test within the current suite has completed. | ||
| * This hook is useful for scenarios where you need to clean up or reset the test environment after each test runs, such as deleting temporary files, clearing test-specific database entries, or resetting mocked functions. | ||
| * | ||
| * **Note:** The `afterEach` hooks are running in reverse order of their registration. You can configure this by changing the `sequence.hooks` option in the config file. | ||
| * | ||
| * @param {Function} fn - The callback function to be executed after each test. This function receives an `TestContext` parameter if additional test context is needed. | ||
| * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used. | ||
| * @returns {void} | ||
| * @example | ||
| * ```ts | ||
| * // Example of using afterEach to delete temporary files created during a test | ||
| * afterEach(async () => { | ||
| * await fileSystem.deleteTempFiles(); | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function afterEach<ExtraContext = object>(fn: AfterEachListener<ExtraContext>, timeout?: number): void; | ||
| /** | ||
| * Registers a callback function to be executed when a test fails within the current suite. | ||
| * This function allows for custom actions to be performed in response to test failures, such as logging, cleanup, or additional diagnostics. | ||
| * | ||
| * **Note:** The `onTestFailed` hooks are running in reverse order of their registration. You can configure this by changing the `sequence.hooks` option in the config file. | ||
| * | ||
| * @param {Function} fn - The callback function to be executed upon a test failure. The function receives the test result (including errors). | ||
| * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used. | ||
| * @throws {Error} Throws an error if the function is not called within a test. | ||
| * @returns {void} | ||
| * @example | ||
| * ```ts | ||
| * // Example of using onTestFailed to log failure details | ||
| * onTestFailed(({ errors }) => { | ||
| * console.log(`Test failed: ${test.name}`, errors); | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare const onTestFailed: TaskHook<OnTestFailedHandler>; | ||
| /** | ||
| * Registers a callback function to be executed when the current test finishes, regardless of the outcome (pass or fail). | ||
| * This function is ideal for performing actions that should occur after every test execution, such as cleanup, logging, or resetting shared resources. | ||
| * | ||
| * This hook is useful if you have access to a resource in the test itself and you want to clean it up after the test finishes. It is a more compact way to clean up resources than using the combination of `beforeEach` and `afterEach`. | ||
| * | ||
| * **Note:** The `onTestFinished` hooks are running in reverse order of their registration. You can configure this by changing the `sequence.hooks` option in the config file. | ||
| * | ||
| * **Note:** The `onTestFinished` hook is not called if the test is canceled with a dynamic `ctx.skip()` call. | ||
| * | ||
| * @param {Function} fn - The callback function to be executed after a test finishes. The function can receive parameters providing details about the completed test, including its success or failure status. | ||
| * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used. | ||
| * @throws {Error} Throws an error if the function is not called within a test. | ||
| * @returns {void} | ||
| * @example | ||
| * ```ts | ||
| * // Example of using onTestFinished for cleanup | ||
| * const db = await connectToDatabase(); | ||
| * onTestFinished(async () => { | ||
| * await db.disconnect(); | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare const onTestFinished: TaskHook<OnTestFinishedHandler>; | ||
| type ChainableFunction< | ||
| T extends string, | ||
| F extends (...args: any) => any, | ||
| C = object | ||
| > = F & { [x in T] : ChainableFunction<T, F, C> } & { | ||
| fn: (this: Record<T, any>, ...args: Parameters<F>) => ReturnType<F>; | ||
| } & C; | ||
| declare function createChainable< | ||
| T extends string, | ||
| Args extends any[], | ||
| R = any | ||
| >(keys: T[], fn: (this: Record<T, any>, ...args: Args) => R): ChainableFunction<T, (...args: Args) => R>; | ||
| type RunMode = "run" | "skip" | "only" | "todo" | "queued"; | ||
| type TaskState = RunMode | "pass" | "fail"; | ||
| interface TaskBase { | ||
| /** | ||
| * Unique task identifier. Based on the file id and the position of the task. | ||
| * The id of the file task is based on the file path relative to root and project name. | ||
| * It will not change between runs. | ||
| * @example `1201091390`, `1201091390_0`, `1201091390_0_1` | ||
| */ | ||
| id: string; | ||
| /** | ||
| * Task name provided by the user. If no name was provided, it will be an empty string. | ||
| */ | ||
| name: string; | ||
| /** | ||
| * Full name including the file path, any parent suites, and this task's name. | ||
| * | ||
| * Uses ` > ` as the separator between levels. | ||
| * | ||
| * @example | ||
| * // file | ||
| * 'test/task-names.test.ts' | ||
| * @example | ||
| * // suite | ||
| * 'test/task-names.test.ts > meal planning' | ||
| * 'test/task-names.test.ts > meal planning > grocery lists' | ||
| * @example | ||
| * // test | ||
| * 'test/task-names.test.ts > meal planning > grocery lists > calculates ingredients' | ||
| */ | ||
| fullName: string; | ||
| /** | ||
| * Full name excluding the file path, including any parent suites and this task's name. `undefined` for file tasks. | ||
| * | ||
| * Uses ` > ` as the separator between levels. | ||
| * | ||
| * @example | ||
| * // file | ||
| * undefined | ||
| * @example | ||
| * // suite | ||
| * 'meal planning' | ||
| * 'meal planning > grocery lists' | ||
| * @example | ||
| * // test | ||
| * 'meal planning > grocery lists > calculates ingredients' | ||
| */ | ||
| fullTestName?: string; | ||
| /** | ||
| * Task mode. | ||
| * - **skip**: task is skipped | ||
| * - **only**: only this task and other tasks with `only` mode will run | ||
| * - **todo**: task is marked as a todo, alias for `skip` | ||
| * - **run**: task will run or already ran | ||
| * - **queued**: task will start running next. It can only exist on the File | ||
| */ | ||
| mode: RunMode; | ||
| /** | ||
| * Custom metadata for the task. JSON reporter will save this data. | ||
| */ | ||
| meta: TaskMeta; | ||
| /** | ||
| * Whether the task was produced with `.each()` method. | ||
| */ | ||
| each?: boolean; | ||
| /** | ||
| * Whether the task should run concurrently with other tasks. | ||
| */ | ||
| concurrent?: boolean; | ||
| /** | ||
| * Whether the tasks of the suite run in a random order. | ||
| */ | ||
| shuffle?: boolean; | ||
| /** | ||
| * Suite that this task is part of. File task or the global suite will have no parent. | ||
| */ | ||
| suite?: Suite; | ||
| /** | ||
| * Result of the task. Suite and file tasks will only have the result if there | ||
| * was an error during collection or inside `afterAll`/`beforeAll`. | ||
| */ | ||
| result?: TaskResult; | ||
| /** | ||
| * Retry configuration for the task. | ||
| * - If a number, specifies how many times to retry | ||
| * - If an object, allows fine-grained retry control | ||
| * @default 0 | ||
| */ | ||
| retry?: Retry; | ||
| /** | ||
| * The amount of times the task should be repeated after the successful run. | ||
| * If the task fails, it will not be retried unless `retry` is specified. | ||
| * @default 0 | ||
| */ | ||
| repeats?: number; | ||
| /** | ||
| * Location of the task in the file. This field is populated only if | ||
| * `includeTaskLocation` option is set. It is generated by calling `new Error` | ||
| * and parsing the stack trace, so the location might differ depending on the runtime. | ||
| */ | ||
| location?: { | ||
| line: number; | ||
| column: number; | ||
| }; | ||
| /** | ||
| * If the test was collected by parsing the file AST, and the name | ||
| * is not a static string, this property will be set to `true`. | ||
| * @experimental | ||
| */ | ||
| dynamic?: boolean; | ||
| /** | ||
| * Custom tags of the task. Useful for filtering tasks. | ||
| */ | ||
| tags?: string[]; | ||
| } | ||
| interface TaskPopulated extends TaskBase { | ||
| /** | ||
| * File task. It's the root task of the file. | ||
| */ | ||
| file: File; | ||
| /** | ||
| * Whether the task should succeed if it fails. If the task fails, it will be marked as passed. | ||
| */ | ||
| fails?: boolean; | ||
| /** | ||
| * Store promises (from async expects) to wait for them before finishing the test | ||
| */ | ||
| promises?: Promise<any>[]; | ||
| } | ||
| /** | ||
| * Custom metadata that can be used in reporters. | ||
| */ | ||
| interface TaskMeta {} | ||
| /** | ||
| * The result of calling a task. | ||
| */ | ||
| interface TaskResult { | ||
| /** | ||
| * State of the task. Inherits the `task.mode` during collection. | ||
| * When the task has finished, it will be changed to `pass` or `fail`. | ||
| * - **pass**: task ran successfully | ||
| * - **fail**: task failed | ||
| */ | ||
| state: TaskState; | ||
| /** | ||
| * Errors that occurred during the task execution. It is possible to have several errors | ||
| * if `expect.soft()` failed multiple times or `retry` was triggered. | ||
| */ | ||
| errors?: TestError[]; | ||
| /** | ||
| * How long in milliseconds the task took to run. | ||
| */ | ||
| duration?: number; | ||
| /** | ||
| * Time in milliseconds when the task started running. | ||
| */ | ||
| startTime?: number; | ||
| /** | ||
| * Heap size in bytes after the task finished. | ||
| * Only available if `logHeapUsage` option is set and `process.memoryUsage` is defined. | ||
| */ | ||
| heap?: number; | ||
| /** | ||
| * State of related to this task hooks. Useful during reporting. | ||
| */ | ||
| hooks?: Partial<Record<keyof SuiteHooks, TaskState>>; | ||
| /** | ||
| * The amount of times the task was retried. The task is retried only if it | ||
| * failed and `retry` option is set. | ||
| */ | ||
| retryCount?: number; | ||
| /** | ||
| * The amount of times the task was repeated. The task is repeated only if | ||
| * `repeats` option is set. This number also contains `retryCount`. | ||
| */ | ||
| repeatCount?: number; | ||
| } | ||
| /** The time spent importing & executing a non-externalized file. */ | ||
| interface ImportDuration { | ||
| /** The time spent importing & executing the file itself, not counting all non-externalized imports that the file does. */ | ||
| selfTime: number; | ||
| /** The time spent importing & executing the file and all its imports. */ | ||
| totalTime: number; | ||
| /** Will be set to `true`, if the module was externalized. In this case totalTime and selfTime are identical. */ | ||
| external?: boolean; | ||
| /** Which module imported this module first. All subsequent imports are cached. */ | ||
| importer?: string; | ||
| } | ||
| /** | ||
| * The tuple representing a single task update. | ||
| * Usually reported after the task finishes. | ||
| */ | ||
| type TaskResultPack = [id: string, result: TaskResult | undefined, meta: TaskMeta]; | ||
| interface TaskEventData { | ||
| annotation?: TestAnnotation | undefined; | ||
| artifact?: TestArtifact | undefined; | ||
| } | ||
| type TaskEventPack = [id: string, event: TaskUpdateEvent, data: TaskEventData | undefined]; | ||
| type TaskUpdateEvent = "test-failed-early" | "suite-failed-early" | "test-prepare" | "test-finished" | "test-retried" | "suite-prepare" | "suite-finished" | "before-hook-start" | "before-hook-end" | "after-hook-start" | "after-hook-end" | "test-annotation" | "test-artifact"; | ||
| interface Suite extends TaskBase { | ||
| type: "suite"; | ||
| /** | ||
| * File task. It's the root task of the file. | ||
| */ | ||
| file: File; | ||
| /** | ||
| * An array of tasks that are part of the suite. | ||
| */ | ||
| tasks: Task[]; | ||
| } | ||
| interface File extends Suite { | ||
| /** | ||
| * The name of the pool that the file belongs to. | ||
| * @default 'forks' | ||
| */ | ||
| pool?: string; | ||
| /** | ||
| * The environment that processes the file on the server. | ||
| */ | ||
| viteEnvironment?: string; | ||
| /** | ||
| * The path to the file in UNIX format. | ||
| */ | ||
| filepath: string; | ||
| /** | ||
| * The name of the workspace project the file belongs to. | ||
| */ | ||
| projectName: string | undefined; | ||
| /** | ||
| * The time it took to collect all tests in the file. | ||
| * This time also includes importing all the file dependencies. | ||
| */ | ||
| collectDuration?: number; | ||
| /** | ||
| * The time it took to import the setup file. | ||
| */ | ||
| setupDuration?: number; | ||
| /** The time spent importing every non-externalized dependency that Vitest has processed. */ | ||
| importDurations?: Record<string, ImportDuration>; | ||
| } | ||
| interface Test<ExtraContext = object> extends TaskPopulated { | ||
| type: "test"; | ||
| /** | ||
| * Test context that will be passed to the test function. | ||
| */ | ||
| context: TestContext & ExtraContext; | ||
| /** | ||
| * The test timeout in milliseconds. | ||
| */ | ||
| timeout: number; | ||
| /** | ||
| * An array of custom annotations. | ||
| */ | ||
| annotations: TestAnnotation[]; | ||
| /** | ||
| * An array of artifacts produced by the test. | ||
| * | ||
| * @experimental | ||
| */ | ||
| artifacts: TestArtifact[]; | ||
| fullTestName: string; | ||
| } | ||
| type Task = Test | Suite | File; | ||
| type TestFunction<ExtraContext = object> = (context: TestContext & ExtraContext) => Awaitable<any> | void; | ||
| type ExtractEachCallbackArgs<T extends ReadonlyArray<any>> = { | ||
| 1: [T[0]]; | ||
| 2: [T[0], T[1]]; | ||
| 3: [T[0], T[1], T[2]]; | ||
| 4: [T[0], T[1], T[2], T[3]]; | ||
| 5: [T[0], T[1], T[2], T[3], T[4]]; | ||
| 6: [T[0], T[1], T[2], T[3], T[4], T[5]]; | ||
| 7: [T[0], T[1], T[2], T[3], T[4], T[5], T[6]]; | ||
| 8: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7]]; | ||
| 9: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8]]; | ||
| 10: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9]]; | ||
| fallback: Array<T extends ReadonlyArray<infer U> ? U : any>; | ||
| }[T extends Readonly<[any]> ? 1 : T extends Readonly<[any, any]> ? 2 : T extends Readonly<[any, any, any]> ? 3 : T extends Readonly<[any, any, any, any]> ? 4 : T extends Readonly<[any, any, any, any, any]> ? 5 : T extends Readonly<[any, any, any, any, any, any]> ? 6 : T extends Readonly<[any, any, any, any, any, any, any]> ? 7 : T extends Readonly<[any, any, any, any, any, any, any, any]> ? 8 : T extends Readonly<[any, any, any, any, any, any, any, any, any]> ? 9 : T extends Readonly<[any, any, any, any, any, any, any, any, any, any]> ? 10 : "fallback"]; | ||
| interface EachFunctionReturn<T extends any[]> { | ||
| (name: string | Function, fn: (...args: T) => Awaitable<void>, options?: number): void; | ||
| (name: string | Function, options: TestCollectorOptions, fn: (...args: T) => Awaitable<void>): void; | ||
| } | ||
| interface TestEachFunction { | ||
| <T extends any[] | [any]>(cases: ReadonlyArray<T>): EachFunctionReturn<T>; | ||
| <T extends ReadonlyArray<any>>(cases: ReadonlyArray<T>): EachFunctionReturn<ExtractEachCallbackArgs<T>>; | ||
| <T>(cases: ReadonlyArray<T>): EachFunctionReturn<T[]>; | ||
| (...args: [TemplateStringsArray, ...any]): EachFunctionReturn<any[]>; | ||
| } | ||
| interface TestForFunctionReturn< | ||
| Arg, | ||
| Context | ||
| > { | ||
| (name: string | Function, fn: (arg: Arg, context: Context) => Awaitable<void>): void; | ||
| (name: string | Function, options: TestCollectorOptions, fn: (args: Arg, context: Context) => Awaitable<void>): void; | ||
| } | ||
| interface TestForFunction<ExtraContext> { | ||
| <T>(cases: ReadonlyArray<T>): TestForFunctionReturn<T, TestContext & ExtraContext>; | ||
| (strings: TemplateStringsArray, ...values: any[]): TestForFunctionReturn<any, TestContext & ExtraContext>; | ||
| } | ||
| interface SuiteForFunction { | ||
| <T>(cases: ReadonlyArray<T>): EachFunctionReturn<[T]>; | ||
| (...args: [TemplateStringsArray, ...any]): EachFunctionReturn<any[]>; | ||
| } | ||
| interface TestCollectorCallable<C = object> { | ||
| <ExtraContext extends C>(name: string | Function, fn?: TestFunction<ExtraContext>, options?: number): void; | ||
| <ExtraContext extends C>(name: string | Function, options?: TestCollectorOptions, fn?: TestFunction<ExtraContext>): void; | ||
| } | ||
| type ChainableTestAPI<ExtraContext = object> = ChainableFunction<"concurrent" | "sequential" | "only" | "skip" | "todo" | "fails", TestCollectorCallable<ExtraContext>, { | ||
| each: TestEachFunction; | ||
| for: TestForFunction<ExtraContext>; | ||
| }>; | ||
| type TestCollectorOptions = Omit<TestOptions, "shuffle">; | ||
| /** | ||
| * Retry configuration for tests. | ||
| * Can be a number for simple retry count, or an object for advanced retry control. | ||
| */ | ||
| type Retry = number | { | ||
| /** | ||
| * The number of times to retry the test if it fails. | ||
| * @default 0 | ||
| */ | ||
| count?: number; | ||
| /** | ||
| * Delay in milliseconds between retry attempts. | ||
| * @default 0 | ||
| */ | ||
| delay?: number; | ||
| /** | ||
| * Condition to determine if a test should be retried based on the error. | ||
| * - If a RegExp, it is tested against the error message | ||
| * - If a function, called with the TestError object; return true to retry | ||
| * | ||
| * NOTE: Functions can only be used in test files, not in vitest.config.ts, | ||
| * because the configuration is serialized when passed to worker threads. | ||
| * | ||
| * @default undefined (retry on all errors) | ||
| */ | ||
| condition?: RegExp | ((error: TestError) => boolean); | ||
| }; | ||
| /** | ||
| * Serializable retry configuration (used in config files). | ||
| * Functions cannot be serialized, so only string conditions are allowed. | ||
| */ | ||
| type SerializableRetry = number | { | ||
| /** | ||
| * The number of times to retry the test if it fails. | ||
| * @default 0 | ||
| */ | ||
| count?: number; | ||
| /** | ||
| * Delay in milliseconds between retry attempts. | ||
| * @default 0 | ||
| */ | ||
| delay?: number; | ||
| /** | ||
| * Condition to determine if a test should be retried based on the error. | ||
| * Must be a RegExp tested against the error message. | ||
| * | ||
| * @default undefined (retry on all errors) | ||
| */ | ||
| condition?: RegExp; | ||
| }; | ||
| interface TestOptions { | ||
| /** | ||
| * Test timeout. | ||
| */ | ||
| timeout?: number; | ||
| /** | ||
| * Retry configuration for the test. | ||
| * - If a number, specifies how many times to retry | ||
| * - If an object, allows fine-grained retry control | ||
| * @default 0 | ||
| */ | ||
| retry?: Retry; | ||
| /** | ||
| * How many times the test will run again. | ||
| * Only inner tests will repeat if set on `describe()`, nested `describe()` will inherit parent's repeat by default. | ||
| * | ||
| * @default 0 | ||
| */ | ||
| repeats?: number; | ||
| /** | ||
| * Whether suites and tests run concurrently. | ||
| * Tests inherit `concurrent` from `describe()` and nested `describe()` will inherit from parent's `concurrent`. | ||
| */ | ||
| concurrent?: boolean; | ||
| /** | ||
| * Whether tests run sequentially. | ||
| * Tests inherit `sequential` from `describe()` and nested `describe()` will inherit from parent's `sequential`. | ||
| */ | ||
| sequential?: boolean; | ||
| /** | ||
| * Whether the test should be skipped. | ||
| */ | ||
| skip?: boolean; | ||
| /** | ||
| * Should this test be the only one running in a suite. | ||
| */ | ||
| only?: boolean; | ||
| /** | ||
| * Whether the test should be skipped and marked as a todo. | ||
| */ | ||
| todo?: boolean; | ||
| /** | ||
| * Whether the test is expected to fail. If it does, the test will pass, otherwise it will fail. | ||
| */ | ||
| fails?: boolean; | ||
| /** | ||
| * Custom tags of the test. Useful for filtering tests. | ||
| */ | ||
| tags?: keyof TestTags extends never ? string[] | string : TestTags[keyof TestTags] | TestTags[keyof TestTags][]; | ||
| } | ||
| interface TestTags {} | ||
| interface SuiteOptions extends TestOptions { | ||
| /** | ||
| * Whether the tasks of the suite run in a random order. | ||
| */ | ||
| shuffle?: boolean; | ||
| } | ||
| interface ExtendedAPI<ExtraContext> { | ||
| skipIf: (condition: any) => ChainableTestAPI<ExtraContext>; | ||
| runIf: (condition: any) => ChainableTestAPI<ExtraContext>; | ||
| } | ||
| interface Hooks<ExtraContext> { | ||
| beforeAll: typeof beforeAll; | ||
| afterAll: typeof afterAll; | ||
| beforeEach: typeof beforeEach<ExtraContext>; | ||
| afterEach: typeof afterEach<ExtraContext>; | ||
| } | ||
| type TestAPI<ExtraContext = object> = ChainableTestAPI<ExtraContext> & ExtendedAPI<ExtraContext> & Hooks<ExtraContext> & { | ||
| extend: <T extends Record<string, any> = object>(fixtures: Fixtures<T, ExtraContext>) => TestAPI<{ [K in keyof T | keyof ExtraContext] : K extends keyof T ? T[K] : K extends keyof ExtraContext ? ExtraContext[K] : never }>; | ||
| scoped: (fixtures: Partial<Fixtures<ExtraContext>>) => void; | ||
| }; | ||
| interface FixtureOptions { | ||
| /** | ||
| * Whether to automatically set up current fixture, even though it's not being used in tests. | ||
| * @default false | ||
| */ | ||
| auto?: boolean; | ||
| /** | ||
| * Indicated if the injected value from the config should be preferred over the fixture value | ||
| */ | ||
| injected?: boolean; | ||
| /** | ||
| * When should the fixture be set up. | ||
| * - **test**: fixture will be set up before every test | ||
| * - **worker**: fixture will be set up once per worker | ||
| * - **file**: fixture will be set up once per file | ||
| * | ||
| * **Warning:** The `vmThreads` and `vmForks` pools initiate worker fixtures once per test file. | ||
| * @default 'test' | ||
| */ | ||
| scope?: "test" | "worker" | "file"; | ||
| } | ||
| type Use<T> = (value: T) => Promise<void>; | ||
| type FixtureFn< | ||
| T, | ||
| K extends keyof T, | ||
| ExtraContext | ||
| > = (context: Omit<T, K> & ExtraContext, use: Use<T[K]>) => Promise<void>; | ||
| type Fixture< | ||
| T, | ||
| K extends keyof T, | ||
| ExtraContext = object | ||
| > = ((...args: any) => any) extends T[K] ? T[K] extends any ? FixtureFn<T, K, Omit<ExtraContext, Exclude<keyof T, K>>> : never : T[K] | (T[K] extends any ? FixtureFn<T, K, Omit<ExtraContext, Exclude<keyof T, K>>> : never); | ||
| type Fixtures< | ||
| T, | ||
| ExtraContext = object | ||
| > = { [K in keyof T] : Fixture<T, K, ExtraContext & TestContext> | [Fixture<T, K, ExtraContext & TestContext>, FixtureOptions?] }; | ||
| type InferFixturesTypes<T> = T extends TestAPI<infer C> ? C : T; | ||
| interface SuiteCollectorCallable<ExtraContext = object> { | ||
| <OverrideExtraContext extends ExtraContext = ExtraContext>(name: string | Function, fn?: SuiteFactory<OverrideExtraContext>, options?: number): SuiteCollector<OverrideExtraContext>; | ||
| <OverrideExtraContext extends ExtraContext = ExtraContext>(name: string | Function, options: SuiteOptions, fn?: SuiteFactory<OverrideExtraContext>): SuiteCollector<OverrideExtraContext>; | ||
| } | ||
| type ChainableSuiteAPI<ExtraContext = object> = ChainableFunction<"concurrent" | "sequential" | "only" | "skip" | "todo" | "shuffle", SuiteCollectorCallable<ExtraContext>, { | ||
| each: TestEachFunction; | ||
| for: SuiteForFunction; | ||
| }>; | ||
| type SuiteAPI<ExtraContext = object> = ChainableSuiteAPI<ExtraContext> & { | ||
| skipIf: (condition: any) => ChainableSuiteAPI<ExtraContext>; | ||
| runIf: (condition: any) => ChainableSuiteAPI<ExtraContext>; | ||
| }; | ||
| interface BeforeAllListener { | ||
| (suite: Readonly<Suite | File>): Awaitable<unknown>; | ||
| } | ||
| interface AfterAllListener { | ||
| (suite: Readonly<Suite | File>): Awaitable<unknown>; | ||
| } | ||
| interface BeforeEachListener<ExtraContext = object> { | ||
| (context: TestContext & ExtraContext, suite: Readonly<Suite>): Awaitable<unknown>; | ||
| } | ||
| interface AfterEachListener<ExtraContext = object> { | ||
| (context: TestContext & ExtraContext, suite: Readonly<Suite>): Awaitable<unknown>; | ||
| } | ||
| interface SuiteHooks<ExtraContext = object> { | ||
| beforeAll: BeforeAllListener[]; | ||
| afterAll: AfterAllListener[]; | ||
| beforeEach: BeforeEachListener<ExtraContext>[]; | ||
| afterEach: AfterEachListener<ExtraContext>[]; | ||
| } | ||
| interface TaskCustomOptions extends TestOptions { | ||
| /** | ||
| * Whether the task was produced with `.each()` method. | ||
| */ | ||
| each?: boolean; | ||
| /** | ||
| * Custom metadata for the task that will be assigned to `task.meta`. | ||
| */ | ||
| meta?: Record<string, unknown>; | ||
| /** | ||
| * Task fixtures. | ||
| */ | ||
| fixtures?: FixtureItem[]; | ||
| /** | ||
| * Function that will be called when the task is executed. | ||
| * If nothing is provided, the runner will try to get the function using `getFn(task)`. | ||
| * If the runner cannot find the function, the task will be marked as failed. | ||
| */ | ||
| handler?: (context: TestContext) => Awaitable<void>; | ||
| } | ||
| interface SuiteCollector<ExtraContext = object> { | ||
| readonly name: string; | ||
| readonly mode: RunMode; | ||
| options?: SuiteOptions; | ||
| type: "collector"; | ||
| test: TestAPI<ExtraContext>; | ||
| tasks: (Suite | Test<ExtraContext> | SuiteCollector<ExtraContext>)[]; | ||
| scoped: (fixtures: Fixtures<any, ExtraContext>) => void; | ||
| fixtures: () => FixtureItem[] | undefined; | ||
| file?: File; | ||
| suite?: Suite; | ||
| task: (name: string, options?: TaskCustomOptions) => Test<ExtraContext>; | ||
| collect: (file: File) => Promise<Suite>; | ||
| clear: () => void; | ||
| on: <T extends keyof SuiteHooks<ExtraContext>>(name: T, ...fn: SuiteHooks<ExtraContext>[T]) => void; | ||
| } | ||
| type SuiteFactory<ExtraContext = object> = (test: TestAPI<ExtraContext>) => Awaitable<void>; | ||
| interface RuntimeContext { | ||
| tasks: (SuiteCollector | Test)[]; | ||
| currentSuite: SuiteCollector | null; | ||
| } | ||
| /** | ||
| * User's custom test context. | ||
| */ | ||
| interface TestContext { | ||
| /** | ||
| * Metadata of the current test | ||
| */ | ||
| readonly task: Readonly<Test>; | ||
| /** | ||
| * An [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) that will be aborted if the test times out or | ||
| * the test run was cancelled. | ||
| * @see {@link https://vitest.dev/guide/test-context#signal} | ||
| */ | ||
| readonly signal: AbortSignal; | ||
| /** | ||
| * Register a callback to run when this specific test fails. | ||
| * Useful when tests run concurrently. | ||
| * @see {@link https://vitest.dev/guide/test-context#ontestfailed} | ||
| */ | ||
| readonly onTestFailed: (fn: OnTestFailedHandler, timeout?: number) => void; | ||
| /** | ||
| * Register a callback to run when this specific test finishes. | ||
| * Useful when tests run concurrently. | ||
| * @see {@link https://vitest.dev/guide/test-context#ontestfinished} | ||
| */ | ||
| readonly onTestFinished: (fn: OnTestFinishedHandler, timeout?: number) => void; | ||
| /** | ||
| * Mark tests as skipped. All execution after this call will be skipped. | ||
| * This function throws an error, so make sure you are not catching it accidentally. | ||
| * @see {@link https://vitest.dev/guide/test-context#skip} | ||
| */ | ||
| readonly skip: { | ||
| (note?: string): never; | ||
| (condition: boolean, note?: string): void; | ||
| }; | ||
| /** | ||
| * Add a test annotation that will be displayed by your reporter. | ||
| * @see {@link https://vitest.dev/guide/test-context#annotate} | ||
| */ | ||
| readonly annotate: { | ||
| (message: string, type?: string, attachment?: TestAttachment): Promise<TestAnnotation>; | ||
| (message: string, attachment?: TestAttachment): Promise<TestAnnotation>; | ||
| }; | ||
| } | ||
| type OnTestFailedHandler = (context: TestContext) => Awaitable<void>; | ||
| type OnTestFinishedHandler = (context: TestContext) => Awaitable<void>; | ||
| interface TaskHook<HookListener> { | ||
| (fn: HookListener, timeout?: number): void; | ||
| } | ||
| type SequenceHooks = "stack" | "list" | "parallel"; | ||
| type SequenceSetupFiles = "list" | "parallel"; | ||
| /** | ||
| * Represents a file or data attachment associated with a test artifact. | ||
| * | ||
| * Attachments can be either file-based (via `path`) or inline content (via `body`). | ||
| * The `contentType` helps consumers understand how to interpret the attachment data. | ||
| */ | ||
| interface TestAttachment { | ||
| /** MIME type of the attachment (e.g., 'image/png', 'text/plain') */ | ||
| contentType?: string; | ||
| /** File system path to the attachment */ | ||
| path?: string; | ||
| /** Inline attachment content as a string or raw binary data */ | ||
| body?: string | Uint8Array; | ||
| } | ||
| /** | ||
| * Source code location information for a test artifact. | ||
| * | ||
| * Indicates where in the source code the artifact originated from. | ||
| */ | ||
| interface TestArtifactLocation { | ||
| /** Line number in the source file (1-indexed) */ | ||
| line: number; | ||
| /** Column number in the line (1-indexed) */ | ||
| column: number; | ||
| /** Path to the source file */ | ||
| file: string; | ||
| } | ||
| /** | ||
| * @experimental | ||
| * | ||
| * Base interface for all test artifacts. | ||
| * | ||
| * Extend this interface when creating custom test artifacts. Vitest automatically manages the `attachments` array and injects the `location` property to indicate where the artifact was created in your test code. | ||
| */ | ||
| interface TestArtifactBase { | ||
| /** File or data attachments associated with this artifact */ | ||
| attachments?: TestAttachment[]; | ||
| /** Source location where this artifact was created */ | ||
| location?: TestArtifactLocation; | ||
| } | ||
| /** | ||
| * @deprecated Use {@linkcode TestArtifactLocation} instead. | ||
| * | ||
| * Kept for backwards compatibility. | ||
| */ | ||
| type TestAnnotationLocation = TestArtifactLocation; | ||
| interface TestAnnotation { | ||
| message: string; | ||
| type: string; | ||
| location?: TestArtifactLocation; | ||
| attachment?: TestAttachment; | ||
| } | ||
| /** | ||
| * @experimental | ||
| * | ||
| * Artifact type for test annotations. | ||
| */ | ||
| interface TestAnnotationArtifact extends TestArtifactBase { | ||
| type: "internal:annotation"; | ||
| annotation: TestAnnotation; | ||
| } | ||
| interface VisualRegressionArtifactAttachment extends TestAttachment { | ||
| name: "reference" | "actual" | "diff"; | ||
| width: number; | ||
| height: number; | ||
| } | ||
| /** | ||
| * @experimental | ||
| * | ||
| * Artifact type for visual regressions. | ||
| */ | ||
| interface VisualRegressionArtifact extends TestArtifactBase { | ||
| type: "internal:toMatchScreenshot"; | ||
| kind: "visual-regression"; | ||
| message: string; | ||
| attachments: VisualRegressionArtifactAttachment[]; | ||
| } | ||
| /** | ||
| * @experimental | ||
| * @advanced | ||
| * | ||
| * Registry for custom test artifact types. | ||
| * | ||
| * Augment this interface to register custom artifact types that your tests can produce. | ||
| * | ||
| * Each custom artifact should extend {@linkcode TestArtifactBase} and include a unique `type` discriminator property. | ||
| * | ||
| * @remarks | ||
| * - Use a `Symbol` as the **registry key** to guarantee uniqueness | ||
| * - The `type` property should follow the pattern `'package-name:artifact-name'`, `'internal:'` is a reserved prefix | ||
| * - Use `attachments` to include files or data; extend {@linkcode TestAttachment} for custom metadata | ||
| * - `location` property is automatically injected to indicate where the artifact was created | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * // Define custom attachment type for generated PDF | ||
| * interface PDFAttachment extends TestAttachment { | ||
| * contentType: 'application/pdf' | ||
| * body: Uint8Array | ||
| * pageCount: number | ||
| * fileSize: number | ||
| * } | ||
| * | ||
| * interface PDFGenerationArtifact extends TestArtifactBase { | ||
| * type: 'my-plugin:pdf-generation' | ||
| * templateName: string | ||
| * isValid: boolean | ||
| * attachments: [PDFAttachment] | ||
| * } | ||
| * | ||
| * // Use a symbol to guarantee key uniqueness | ||
| * const pdfKey = Symbol('pdf-generation') | ||
| * | ||
| * declare module 'vitest' { | ||
| * interface TestArtifactRegistry { | ||
| * [pdfKey]: PDFGenerationArtifact | ||
| * } | ||
| * } | ||
| * | ||
| * // Custom assertion for PDF generation | ||
| * async function toGenerateValidPDF( | ||
| * this: MatcherState, | ||
| * actual: PDFTemplate, | ||
| * data: Record<string, unknown> | ||
| * ): AsyncExpectationResult { | ||
| * const pdfBuffer = await actual.render(data) | ||
| * const validation = await validatePDF(pdfBuffer) | ||
| * | ||
| * await recordArtifact(this.task, { | ||
| * type: 'my-plugin:pdf-generation', | ||
| * templateName: actual.name, | ||
| * isValid: validation.success, | ||
| * attachments: [{ | ||
| * contentType: 'application/pdf', | ||
| * body: pdfBuffer, | ||
| * pageCount: validation.pageCount, | ||
| * fileSize: pdfBuffer.byteLength | ||
| * }] | ||
| * }) | ||
| * | ||
| * return { | ||
| * pass: validation.success, | ||
| * message: () => validation.success | ||
| * ? `Generated valid PDF with ${validation.pageCount} pages` | ||
| * : `Invalid PDF: ${validation.error}` | ||
| * } | ||
| * } | ||
| * ``` | ||
| */ | ||
| interface TestArtifactRegistry {} | ||
| /** | ||
| * @experimental | ||
| * | ||
| * Union type of all test artifacts, including built-in and custom registered artifacts. | ||
| * | ||
| * This type automatically includes all artifacts registered via {@link TestArtifactRegistry}. | ||
| */ | ||
| type TestArtifact = TestAnnotationArtifact | VisualRegressionArtifact | TestArtifactRegistry[keyof TestArtifactRegistry]; | ||
| export { createChainable as ab, afterAll as i, afterEach as j, beforeAll as k, beforeEach as l, onTestFinished as m, onTestFailed as o }; | ||
| export type { TestAnnotationLocation as $, AfterAllListener as A, BeforeAllListener as B, CancelReason as C, RunMode as D, RuntimeContext as E, FileSpecification as F, SequenceHooks as G, SequenceSetupFiles as H, ImportDuration as I, SerializableRetry as J, SuiteFactory as K, TaskBase as L, TaskCustomOptions as M, TaskEventPack as N, OnTestFailedHandler as O, TaskHook as P, TaskMeta as Q, Retry as R, Suite as S, TestArtifact as T, TaskPopulated as U, VitestRunner as V, TaskResult as W, TaskResultPack as X, TaskState as Y, TestAnnotation as Z, TestAnnotationArtifact as _, Test as a, TestArtifactBase as a0, TestArtifactLocation as a1, TestArtifactRegistry as a2, TestAttachment as a3, TestContext as a4, TestFunction as a5, TestOptions as a6, TestTags as a7, Use as a8, VisualRegressionArtifact as a9, ChainableFunction as aa, SuiteHooks as b, File as c, TaskUpdateEvent as d, Task as e, TestAPI as f, SuiteAPI as g, SuiteCollector as h, TestTagDefinition as n, VitestRunnerConfig as p, VitestRunnerConstructor as q, VitestRunnerImportSource as r, AfterEachListener as s, BeforeEachListener as t, Fixture as u, FixtureFn as v, FixtureOptions as w, Fixtures as x, InferFixturesTypes as y, OnTestFinishedHandler as z }; |
+240
-2
@@ -37,3 +37,3 @@ import { processError } from '@vitest/utils/error'; | ||
| */ | ||
| function interpretTaskModes(file, namePattern, testLocations, testIds, onlyMode, parentIsOnly, allowOnly) { | ||
| function interpretTaskModes(file, namePattern, testLocations, testIds, testTagsFilter, onlyMode, parentIsOnly, allowOnly) { | ||
| const matchedLocations = []; | ||
@@ -84,2 +84,5 @@ const traverseSuite = (suite, parentIsOnly, parentMatchedWithLocation) => { | ||
| } | ||
| if (testTagsFilter && !testTagsFilter(t.tags || [])) { | ||
| t.mode = "skip"; | ||
| } | ||
| } else if (t.type === "suite") { | ||
@@ -282,2 +285,237 @@ if (t.mode === "skip") { | ||
| function validateTags(config, tags) { | ||
| if (!config.strictTags) { | ||
| return; | ||
| } | ||
| const availableTags = new Set(config.tags.map((tag) => tag.name)); | ||
| for (const tag of tags) { | ||
| if (!availableTags.has(tag)) { | ||
| throw createNoTagsError(config.tags, tag); | ||
| } | ||
| } | ||
| } | ||
| function createNoTagsError(availableTags, tag, prefix = "tag") { | ||
| if (!availableTags.length) { | ||
| throw new Error(`The Vitest config does't define any "tags", cannot apply "${tag}" ${prefix} for this test. See: https://vitest.dev/guide/test-tags`); | ||
| } | ||
| throw new Error(`The ${prefix} "${tag}" is not defined in the configuration. Available tags are:\n${availableTags.map((t) => `- ${t.name}${t.description ? `: ${t.description}` : ""}`).join("\n")}`); | ||
| } | ||
| function createTagsFilter(tagsExpr, availableTags) { | ||
| const matchers = tagsExpr.map((expr) => parseTagsExpression(expr, availableTags)); | ||
| return (testTags) => { | ||
| return matchers.every((matcher) => matcher(testTags)); | ||
| }; | ||
| } | ||
| function parseTagsExpression(expr, availableTags) { | ||
| const tokens = tokenize(expr); | ||
| const stream = new TokenStream(tokens, expr); | ||
| const ast = parseOrExpression(stream, availableTags); | ||
| if (stream.peek().type !== "EOF") { | ||
| throw new Error(`Invalid tags expression: unexpected "${formatToken(stream.peek())}" in "${expr}"`); | ||
| } | ||
| return (tags) => evaluateNode(ast, tags); | ||
| } | ||
| function formatToken(token) { | ||
| switch (token.type) { | ||
| case "TAG": return token.value; | ||
| default: return formatTokenType(token.type); | ||
| } | ||
| } | ||
| function tokenize(expr) { | ||
| const tokens = []; | ||
| let i = 0; | ||
| while (i < expr.length) { | ||
| if (expr[i] === " " || expr[i] === " ") { | ||
| i++; | ||
| continue; | ||
| } | ||
| if (expr[i] === "(") { | ||
| tokens.push({ type: "LPAREN" }); | ||
| i++; | ||
| continue; | ||
| } | ||
| if (expr[i] === ")") { | ||
| tokens.push({ type: "RPAREN" }); | ||
| i++; | ||
| continue; | ||
| } | ||
| if (expr[i] === "!") { | ||
| tokens.push({ type: "NOT" }); | ||
| i++; | ||
| continue; | ||
| } | ||
| if (expr.slice(i, i + 2) === "&&") { | ||
| tokens.push({ type: "AND" }); | ||
| i += 2; | ||
| continue; | ||
| } | ||
| if (expr.slice(i, i + 2) === "||") { | ||
| tokens.push({ type: "OR" }); | ||
| i += 2; | ||
| continue; | ||
| } | ||
| if (/^and(?:\s|\)|$)/i.test(expr.slice(i))) { | ||
| tokens.push({ type: "AND" }); | ||
| i += 3; | ||
| continue; | ||
| } | ||
| if (/^or(?:\s|\)|$)/i.test(expr.slice(i))) { | ||
| tokens.push({ type: "OR" }); | ||
| i += 2; | ||
| continue; | ||
| } | ||
| if (/^not\s/i.test(expr.slice(i))) { | ||
| tokens.push({ type: "NOT" }); | ||
| i += 3; | ||
| continue; | ||
| } | ||
| let tag = ""; | ||
| while (i < expr.length && expr[i] !== " " && expr[i] !== " " && expr[i] !== "(" && expr[i] !== ")" && expr[i] !== "!" && expr[i] !== "&" && expr[i] !== "|") { | ||
| const remaining = expr.slice(i); | ||
| // Only treat and/or/not as operators if we're at the start of a tag (after whitespace) | ||
| // This allows tags like "demand", "editor", "cannot" to work correctly | ||
| if (tag === "" && (/^and(?:\s|\)|$)/i.test(remaining) || /^or(?:\s|\)|$)/i.test(remaining) || /^not\s/i.test(remaining))) { | ||
| break; | ||
| } | ||
| tag += expr[i]; | ||
| i++; | ||
| } | ||
| if (tag) { | ||
| tokens.push({ | ||
| type: "TAG", | ||
| value: tag | ||
| }); | ||
| } | ||
| } | ||
| tokens.push({ type: "EOF" }); | ||
| return tokens; | ||
| } | ||
| class TokenStream { | ||
| pos = 0; | ||
| constructor(tokens, expr) { | ||
| this.tokens = tokens; | ||
| this.expr = expr; | ||
| } | ||
| peek() { | ||
| return this.tokens[this.pos]; | ||
| } | ||
| next() { | ||
| return this.tokens[this.pos++]; | ||
| } | ||
| expect(type) { | ||
| const token = this.next(); | ||
| if (token.type !== type) { | ||
| if (type === "RPAREN" && token.type === "EOF") { | ||
| throw new Error(`Invalid tags expression: missing closing ")" in "${this.expr}"`); | ||
| } | ||
| throw new Error(`Invalid tags expression: expected "${formatTokenType(type)}" but got "${formatToken(token)}" in "${this.expr}"`); | ||
| } | ||
| return token; | ||
| } | ||
| unexpectedToken() { | ||
| const token = this.peek(); | ||
| if (token.type === "EOF") { | ||
| throw new Error(`Invalid tags expression: unexpected end of expression in "${this.expr}"`); | ||
| } | ||
| throw new Error(`Invalid tags expression: unexpected "${formatToken(token)}" in "${this.expr}"`); | ||
| } | ||
| } | ||
| function formatTokenType(type) { | ||
| switch (type) { | ||
| case "TAG": return "tag"; | ||
| case "AND": return "and"; | ||
| case "OR": return "or"; | ||
| case "NOT": return "not"; | ||
| case "LPAREN": return "("; | ||
| case "RPAREN": return ")"; | ||
| case "EOF": return "end of expression"; | ||
| } | ||
| } | ||
| function parseOrExpression(stream, availableTags) { | ||
| let left = parseAndExpression(stream, availableTags); | ||
| while (stream.peek().type === "OR") { | ||
| stream.next(); | ||
| const right = parseAndExpression(stream, availableTags); | ||
| left = { | ||
| type: "or", | ||
| left, | ||
| right | ||
| }; | ||
| } | ||
| return left; | ||
| } | ||
| function parseAndExpression(stream, availableTags) { | ||
| let left = parseUnaryExpression(stream, availableTags); | ||
| while (stream.peek().type === "AND") { | ||
| stream.next(); | ||
| const right = parseUnaryExpression(stream, availableTags); | ||
| left = { | ||
| type: "and", | ||
| left, | ||
| right | ||
| }; | ||
| } | ||
| return left; | ||
| } | ||
| function parseUnaryExpression(stream, availableTags) { | ||
| if (stream.peek().type === "NOT") { | ||
| stream.next(); | ||
| const operand = parseUnaryExpression(stream, availableTags); | ||
| return { | ||
| type: "not", | ||
| operand | ||
| }; | ||
| } | ||
| return parsePrimaryExpression(stream, availableTags); | ||
| } | ||
| function parsePrimaryExpression(stream, availableTags) { | ||
| const token = stream.peek(); | ||
| if (token.type === "LPAREN") { | ||
| stream.next(); | ||
| const expr = parseOrExpression(stream, availableTags); | ||
| stream.expect("RPAREN"); | ||
| return expr; | ||
| } | ||
| if (token.type === "TAG") { | ||
| stream.next(); | ||
| const tagValue = token.value; | ||
| const pattern = resolveTagPattern(tagValue, availableTags); | ||
| return { | ||
| type: "tag", | ||
| value: tagValue, | ||
| pattern | ||
| }; | ||
| } | ||
| stream.unexpectedToken(); | ||
| } | ||
| function createWildcardRegex(pattern) { | ||
| return new RegExp(`^${pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`); | ||
| } | ||
| function resolveTagPattern(tagPattern, availableTags) { | ||
| if (tagPattern.includes("*")) { | ||
| const regex = createWildcardRegex(tagPattern); | ||
| const hasMatch = availableTags.some((tag) => regex.test(tag.name)); | ||
| if (!hasMatch) { | ||
| throw createNoTagsError(availableTags, tagPattern, "tag pattern"); | ||
| } | ||
| return regex; | ||
| } | ||
| if (!availableTags.length || !availableTags.some((tag) => tag.name === tagPattern)) { | ||
| throw createNoTagsError(availableTags, tagPattern, "tag pattern"); | ||
| } | ||
| return null; | ||
| } | ||
| function evaluateNode(node, tags) { | ||
| switch (node.type) { | ||
| case "tag": | ||
| if (node.pattern) { | ||
| return tags.some((tag) => node.pattern.test(tag)); | ||
| } | ||
| return tags.includes(node.value); | ||
| case "not": return !evaluateNode(node.operand, tags); | ||
| case "and": return evaluateNode(node.left, tags) && evaluateNode(node.right, tags); | ||
| case "or": return evaluateNode(node.left, tags) || evaluateNode(node.right, tags); | ||
| } | ||
| } | ||
| function isTestCase(s) { | ||
@@ -346,2 +584,2 @@ return s.type === "test"; | ||
| export { calculateSuiteHash as a, createFileTask as b, createChainable as c, generateHash as d, createTaskName as e, findTestFileStackTrace as f, generateFileHash as g, getFullName as h, interpretTaskModes as i, getNames as j, getSuites as k, limitConcurrency as l, getTasks as m, getTestName as n, getTests as o, partitionSuiteChildren as p, hasFailed as q, hasTests as r, someTasksAreOnly as s, isTestCase as t }; | ||
| export { calculateSuiteHash as a, createFileTask as b, createChainable as c, generateHash as d, createTagsFilter as e, findTestFileStackTrace as f, generateFileHash as g, createTaskName as h, interpretTaskModes as i, getFullName as j, getNames as k, limitConcurrency as l, getSuites as m, getTasks as n, getTestName as o, partitionSuiteChildren as p, getTests as q, hasFailed as r, someTasksAreOnly as s, hasTests as t, isTestCase as u, validateTags as v, createNoTagsError as w }; |
+2
-4
@@ -1,6 +0,4 @@ | ||
| import { b as TestArtifact, a as Test, S as Suite, d as SuiteHooks, F as File, e as TaskUpdateEvent, T as Task, f as TestAPI, g as SuiteAPI, h as SuiteCollector } from './tasks.d-hZ73xajr.js'; | ||
| export { A as AfterAllListener, n as AfterEachListener, B as BeforeAllListener, p as BeforeEachListener, q as Fixture, r as FixtureFn, s as FixtureOptions, t as Fixtures, I as ImportDuration, u as InferFixturesTypes, O as OnTestFailedHandler, v as OnTestFinishedHandler, R as Retry, w as RunMode, x as RuntimeContext, y as SequenceHooks, z as SequenceSetupFiles, D as SerializableRetry, E as SuiteFactory, G as TaskBase, H as TaskCustomOptions, J as TaskEventPack, K as TaskHook, L as TaskMeta, M as TaskPopulated, N as TaskResult, P as TaskResultPack, Q as TaskState, U as TestAnnotation, V as TestAnnotationArtifact, W as TestAnnotationLocation, X as TestArtifactBase, Y as TestArtifactLocation, Z as TestArtifactRegistry, _ as TestAttachment, $ as TestContext, a0 as TestFunction, a1 as TestOptions, a2 as Use, a3 as VisualRegressionArtifact, i as afterAll, j as afterEach, k as beforeAll, l as beforeEach, o as onTestFailed, m as onTestFinished } from './tasks.d-hZ73xajr.js'; | ||
| import { T as TestArtifact, a as Test, S as Suite, b as SuiteHooks, F as FileSpecification, V as VitestRunner, c as File, d as TaskUpdateEvent, e as Task, f as TestAPI, g as SuiteAPI, h as SuiteCollector } from './tasks.d-CLPU8HE4.js'; | ||
| export { A as AfterAllListener, s as AfterEachListener, B as BeforeAllListener, t as BeforeEachListener, C as CancelReason, u as Fixture, v as FixtureFn, w as FixtureOptions, x as Fixtures, I as ImportDuration, y as InferFixturesTypes, O as OnTestFailedHandler, z as OnTestFinishedHandler, R as Retry, D as RunMode, E as RuntimeContext, G as SequenceHooks, H as SequenceSetupFiles, J as SerializableRetry, K as SuiteFactory, L as TaskBase, M as TaskCustomOptions, N as TaskEventPack, P as TaskHook, Q as TaskMeta, U as TaskPopulated, W as TaskResult, X as TaskResultPack, Y as TaskState, Z as TestAnnotation, _ as TestAnnotationArtifact, $ as TestAnnotationLocation, a0 as TestArtifactBase, a1 as TestArtifactLocation, a2 as TestArtifactRegistry, a3 as TestAttachment, a4 as TestContext, a5 as TestFunction, a6 as TestOptions, n as TestTagDefinition, a7 as TestTags, a8 as Use, a9 as VisualRegressionArtifact, p as VitestRunnerConfig, q as VitestRunnerConstructor, r as VitestRunnerImportSource, i as afterAll, j as afterEach, k as beforeAll, l as beforeEach, o as onTestFailed, m as onTestFinished } from './tasks.d-CLPU8HE4.js'; | ||
| import { Awaitable } from '@vitest/utils'; | ||
| import { FileSpecification, VitestRunner } from './types.js'; | ||
| export { CancelReason, VitestRunnerConfig, VitestRunnerConstructor, VitestRunnerImportSource } from './types.js'; | ||
| import '@vitest/utils/diff'; | ||
@@ -7,0 +5,0 @@ |
+2
-184
@@ -1,185 +0,3 @@ | ||
| import { DiffOptions } from '@vitest/utils/diff'; | ||
| import { F as File, a as Test, S as Suite, P as TaskResultPack, J as TaskEventPack, U as TestAnnotation, b as TestArtifact, $ as TestContext, I as ImportDuration, y as SequenceHooks, z as SequenceSetupFiles, D as SerializableRetry } from './tasks.d-hZ73xajr.js'; | ||
| export { A as AfterAllListener, n as AfterEachListener, B as BeforeAllListener, p as BeforeEachListener, q as Fixture, r as FixtureFn, s as FixtureOptions, t as Fixtures, u as InferFixturesTypes, O as OnTestFailedHandler, v as OnTestFinishedHandler, R as Retry, w as RunMode, x as RuntimeContext, g as SuiteAPI, h as SuiteCollector, E as SuiteFactory, d as SuiteHooks, T as Task, G as TaskBase, H as TaskCustomOptions, K as TaskHook, L as TaskMeta, M as TaskPopulated, N as TaskResult, Q as TaskState, e as TaskUpdateEvent, f as TestAPI, V as TestAnnotationArtifact, W as TestAnnotationLocation, X as TestArtifactBase, Y as TestArtifactLocation, Z as TestArtifactRegistry, _ as TestAttachment, a0 as TestFunction, a1 as TestOptions, a2 as Use, a3 as VisualRegressionArtifact } from './tasks.d-hZ73xajr.js'; | ||
| export { A as AfterAllListener, s as AfterEachListener, B as BeforeAllListener, t as BeforeEachListener, C as CancelReason, c as File, F as FileSpecification, u as Fixture, v as FixtureFn, w as FixtureOptions, x as Fixtures, I as ImportDuration, y as InferFixturesTypes, O as OnTestFailedHandler, z as OnTestFinishedHandler, R as Retry, D as RunMode, E as RuntimeContext, G as SequenceHooks, H as SequenceSetupFiles, J as SerializableRetry, S as Suite, g as SuiteAPI, h as SuiteCollector, K as SuiteFactory, b as SuiteHooks, e as Task, L as TaskBase, M as TaskCustomOptions, N as TaskEventPack, P as TaskHook, Q as TaskMeta, U as TaskPopulated, W as TaskResult, X as TaskResultPack, Y as TaskState, d as TaskUpdateEvent, a as Test, f as TestAPI, Z as TestAnnotation, _ as TestAnnotationArtifact, $ as TestAnnotationLocation, T as TestArtifact, a0 as TestArtifactBase, a1 as TestArtifactLocation, a2 as TestArtifactRegistry, a3 as TestAttachment, a4 as TestContext, a5 as TestFunction, a6 as TestOptions, n as TestTagDefinition, a7 as TestTags, a8 as Use, a9 as VisualRegressionArtifact, V as VitestRunner, p as VitestRunnerConfig, q as VitestRunnerConstructor, r as VitestRunnerImportSource } from './tasks.d-CLPU8HE4.js'; | ||
| import '@vitest/utils/diff'; | ||
| import '@vitest/utils'; | ||
| /** | ||
| * This is a subset of Vitest config that's required for the runner to work. | ||
| */ | ||
| interface VitestRunnerConfig { | ||
| root: string; | ||
| setupFiles: string[]; | ||
| name?: string; | ||
| passWithNoTests: boolean; | ||
| testNamePattern?: RegExp; | ||
| allowOnly?: boolean; | ||
| sequence: { | ||
| shuffle?: boolean; | ||
| concurrent?: boolean; | ||
| seed: number; | ||
| hooks: SequenceHooks; | ||
| setupFiles: SequenceSetupFiles; | ||
| }; | ||
| chaiConfig?: { | ||
| truncateThreshold?: number; | ||
| }; | ||
| maxConcurrency: number; | ||
| testTimeout: number; | ||
| hookTimeout: number; | ||
| retry: SerializableRetry; | ||
| includeTaskLocation?: boolean; | ||
| diffOptions?: DiffOptions; | ||
| } | ||
| /** | ||
| * Possible options to run a single file in a test. | ||
| */ | ||
| interface FileSpecification { | ||
| filepath: string; | ||
| testLocations: number[] | undefined; | ||
| testNamePattern: RegExp | undefined; | ||
| testIds: string[] | undefined; | ||
| } | ||
| type VitestRunnerImportSource = "collect" | "setup"; | ||
| interface VitestRunnerConstructor { | ||
| new (config: VitestRunnerConfig): VitestRunner; | ||
| } | ||
| type CancelReason = "keyboard-input" | "test-failure" | (string & Record<string, never>); | ||
| interface VitestRunner { | ||
| /** | ||
| * First thing that's getting called before actually collecting and running tests. | ||
| */ | ||
| onBeforeCollect?: (paths: string[]) => unknown; | ||
| /** | ||
| * Called after the file task was created but not collected yet. | ||
| */ | ||
| onCollectStart?: (file: File) => unknown; | ||
| /** | ||
| * Called after collecting tests and before "onBeforeRun". | ||
| */ | ||
| onCollected?: (files: File[]) => unknown; | ||
| /** | ||
| * Called when test runner should cancel next test runs. | ||
| * Runner should listen for this method and mark tests and suites as skipped in | ||
| * "onBeforeRunSuite" and "onBeforeRunTask" when called. | ||
| */ | ||
| cancel?: (reason: CancelReason) => unknown; | ||
| /** | ||
| * Called before running a single test. Doesn't have "result" yet. | ||
| */ | ||
| onBeforeRunTask?: (test: Test) => unknown; | ||
| /** | ||
| * Called before actually running the test function. Already has "result" with "state" and "startTime". | ||
| */ | ||
| onBeforeTryTask?: (test: Test, options: { | ||
| retry: number; | ||
| repeats: number; | ||
| }) => unknown; | ||
| /** | ||
| * When the task has finished running, but before cleanup hooks are called | ||
| */ | ||
| onTaskFinished?: (test: Test) => unknown; | ||
| /** | ||
| * Called after result and state are set. | ||
| */ | ||
| onAfterRunTask?: (test: Test) => unknown; | ||
| /** | ||
| * Called right after running the test function. Doesn't have new state yet. Will not be called, if the test function throws. | ||
| */ | ||
| onAfterTryTask?: (test: Test, options: { | ||
| retry: number; | ||
| repeats: number; | ||
| }) => unknown; | ||
| /** | ||
| * Called after the retry resolution happend. Unlike `onAfterTryTask`, the test now has a new state. | ||
| * All `after` hooks were also called by this point. | ||
| */ | ||
| onAfterRetryTask?: (test: Test, options: { | ||
| retry: number; | ||
| repeats: number; | ||
| }) => unknown; | ||
| /** | ||
| * Called before running a single suite. Doesn't have "result" yet. | ||
| */ | ||
| onBeforeRunSuite?: (suite: Suite) => unknown; | ||
| /** | ||
| * Called after running a single suite. Has state and result. | ||
| */ | ||
| onAfterRunSuite?: (suite: Suite) => unknown; | ||
| /** | ||
| * If defined, will be called instead of usual Vitest suite partition and handling. | ||
| * "before" and "after" hooks will not be ignored. | ||
| */ | ||
| runSuite?: (suite: Suite) => Promise<void>; | ||
| /** | ||
| * If defined, will be called instead of usual Vitest handling. Useful, if you have your custom test function. | ||
| * "before" and "after" hooks will not be ignored. | ||
| */ | ||
| runTask?: (test: Test) => Promise<void>; | ||
| /** | ||
| * Called, when a task is updated. The same as "onTaskUpdate" in a reporter, but this is running in the same thread as tests. | ||
| */ | ||
| onTaskUpdate?: (task: TaskResultPack[], events: TaskEventPack[]) => Promise<void>; | ||
| /** | ||
| * Called when annotation is added via the `context.annotate` method. | ||
| */ | ||
| onTestAnnotate?: (test: Test, annotation: TestAnnotation) => Promise<TestAnnotation>; | ||
| /** | ||
| * @experimental | ||
| * | ||
| * Called when artifacts are recorded on tests via the `recordArtifact` utility. | ||
| */ | ||
| onTestArtifactRecord?: <Artifact extends TestArtifact>(test: Test, artifact: Artifact) => Promise<Artifact>; | ||
| /** | ||
| * Called before running all tests in collected paths. | ||
| */ | ||
| onBeforeRunFiles?: (files: File[]) => unknown; | ||
| /** | ||
| * Called right after running all tests in collected paths. | ||
| */ | ||
| onAfterRunFiles?: (files: File[]) => unknown; | ||
| /** | ||
| * Called when new context for a test is defined. Useful if you want to add custom properties to the context. | ||
| * If you only want to define custom context, consider using "beforeAll" in "setupFiles" instead. | ||
| * | ||
| * @see https://vitest.dev/advanced/runner#your-task-function | ||
| */ | ||
| extendTaskContext?: (context: TestContext) => TestContext; | ||
| /** | ||
| * Called when test and setup files are imported. Can be called in two situations: when collecting tests and when importing setup files. | ||
| */ | ||
| importFile: (filepath: string, source: VitestRunnerImportSource) => unknown; | ||
| /** | ||
| * Function that is called when the runner attempts to get the value when `test.extend` is used with `{ injected: true }` | ||
| */ | ||
| injectValue?: (key: string) => unknown; | ||
| /** | ||
| * Gets the time spent importing each individual non-externalized file that Vitest collected. | ||
| */ | ||
| getImportDurations?: () => Record<string, ImportDuration>; | ||
| /** | ||
| * Publicly available configuration. | ||
| */ | ||
| config: VitestRunnerConfig; | ||
| /** | ||
| * The name of the current pool. Can affect how stack trace is inferred on the server side. | ||
| */ | ||
| pool?: string; | ||
| /** | ||
| * The current Vite environment that processes the files on the server. | ||
| */ | ||
| viteEnvironment?: string; | ||
| /** | ||
| * Return the worker context for fixtures specified with `scope: 'worker'` | ||
| */ | ||
| getWorkerContext?: () => Record<string, unknown>; | ||
| onCleanupWorkerContext?: (cleanup: () => unknown) => void; | ||
| trace?<T>(name: string, cb: () => T): T; | ||
| trace?<T>(name: string, attributes: Record<string, any>, cb: () => T): T; | ||
| /** @private */ | ||
| _currentTaskStartTime?: number; | ||
| /** @private */ | ||
| _currentTaskTimeout?: number; | ||
| } | ||
| export { File, ImportDuration, SequenceHooks, SequenceSetupFiles, SerializableRetry, Suite, TaskEventPack, TaskResultPack, Test, TestAnnotation, TestArtifact, TestContext }; | ||
| export type { CancelReason, FileSpecification, VitestRunner, VitestRunnerConfig, VitestRunnerConstructor, VitestRunnerImportSource }; |
+8
-4
@@ -1,4 +0,5 @@ | ||
| import { S as Suite, F as File, T as Task, a as Test } from './tasks.d-hZ73xajr.js'; | ||
| export { C as ChainableFunction, c as createChainable } from './tasks.d-hZ73xajr.js'; | ||
| import { S as Suite, c as File, e as Task, n as TestTagDefinition, p as VitestRunnerConfig, a as Test } from './tasks.d-CLPU8HE4.js'; | ||
| export { aa as ChainableFunction, ab as createChainable } from './tasks.d-CLPU8HE4.js'; | ||
| import { ParsedStack, Arrayable } from '@vitest/utils'; | ||
| import '@vitest/utils/diff'; | ||
@@ -8,3 +9,3 @@ /** | ||
| */ | ||
| declare function interpretTaskModes(file: Suite, namePattern?: string | RegExp, testLocations?: number[] | undefined, testIds?: string[] | undefined, onlyMode?: boolean, parentIsOnly?: boolean, allowOnly?: boolean): void; | ||
| declare function interpretTaskModes(file: Suite, namePattern?: string | RegExp, testLocations?: number[] | undefined, testIds?: string[] | undefined, testTagsFilter?: ((testTags: string[]) => boolean) | undefined, onlyMode?: boolean, parentIsOnly?: boolean, allowOnly?: boolean): void; | ||
| declare function someTasksAreOnly(suite: Suite): boolean; | ||
@@ -35,2 +36,5 @@ declare function generateHash(str: string): string; | ||
| declare function validateTags(config: VitestRunnerConfig, tags: string[]): void; | ||
| declare function createTagsFilter(tagsExpr: string[], availableTags: TestTagDefinition[]): (testTags: string[]) => boolean; | ||
| declare function isTestCase(s: Task): s is Test; | ||
@@ -47,2 +51,2 @@ declare function getTests(suite: Arrayable<Task>): Test[]; | ||
| export { calculateSuiteHash, createFileTask, createTaskName, findTestFileStackTrace, generateFileHash, generateHash, getFullName, getNames, getSuites, getTasks, getTestName, getTests, hasFailed, hasTests, interpretTaskModes, isTestCase, limitConcurrency, partitionSuiteChildren, someTasksAreOnly }; | ||
| export { calculateSuiteHash, createFileTask, createTagsFilter, createTaskName, findTestFileStackTrace, generateFileHash, generateHash, getFullName, getNames, getSuites, getTasks, getTestName, getTests, hasFailed, hasTests, interpretTaskModes, isTestCase, limitConcurrency, partitionSuiteChildren, someTasksAreOnly, validateTags }; |
+1
-1
@@ -1,2 +0,2 @@ | ||
| export { a as calculateSuiteHash, c as createChainable, b as createFileTask, e as createTaskName, f as findTestFileStackTrace, g as generateFileHash, d as generateHash, h as getFullName, j as getNames, k as getSuites, m as getTasks, n as getTestName, o as getTests, q as hasFailed, r as hasTests, i as interpretTaskModes, t as isTestCase, l as limitConcurrency, p as partitionSuiteChildren, s as someTasksAreOnly } from './chunk-tasks.js'; | ||
| export { a as calculateSuiteHash, c as createChainable, b as createFileTask, e as createTagsFilter, h as createTaskName, f as findTestFileStackTrace, g as generateFileHash, d as generateHash, j as getFullName, k as getNames, m as getSuites, n as getTasks, o as getTestName, q as getTests, r as hasFailed, t as hasTests, i as interpretTaskModes, u as isTestCase, l as limitConcurrency, p as partitionSuiteChildren, s as someTasksAreOnly, v as validateTags } from './chunk-tasks.js'; | ||
| import '@vitest/utils/error'; | ||
@@ -3,0 +3,0 @@ import '@vitest/utils/source-map'; |
+2
-2
| { | ||
| "name": "@vitest/runner", | ||
| "type": "module", | ||
| "version": "4.1.0-beta.1", | ||
| "version": "4.1.0-beta.2", | ||
| "description": "Vitest test runner", | ||
@@ -42,3 +42,3 @@ "license": "MIT", | ||
| "pathe": "^2.0.3", | ||
| "@vitest/utils": "4.1.0-beta.1" | ||
| "@vitest/utils": "4.1.0-beta.2" | ||
| }, | ||
@@ -45,0 +45,0 @@ "scripts": { |
| import { TestError, Awaitable } from '@vitest/utils'; | ||
| interface FixtureItem extends FixtureOptions { | ||
| prop: string; | ||
| value: any; | ||
| scope: "test" | "file" | "worker"; | ||
| /** | ||
| * Indicates whether the fixture is a function | ||
| */ | ||
| isFn: boolean; | ||
| /** | ||
| * The dependencies(fixtures) of current fixture function. | ||
| */ | ||
| deps?: FixtureItem[]; | ||
| } | ||
| /** | ||
| * Registers a callback function to be executed once before all tests within the current suite. | ||
| * This hook is useful for scenarios where you need to perform setup operations that are common to all tests in a suite, such as initializing a database connection or setting up a test environment. | ||
| * | ||
| * **Note:** The `beforeAll` hooks are executed in the order they are defined one after another. You can configure this by changing the `sequence.hooks` option in the config file. | ||
| * | ||
| * @param {Function} fn - The callback function to be executed before all tests. | ||
| * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used. | ||
| * @returns {void} | ||
| * @example | ||
| * ```ts | ||
| * // Example of using beforeAll to set up a database connection | ||
| * beforeAll(async () => { | ||
| * await database.connect(); | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function beforeAll(fn: BeforeAllListener, timeout?: number): void; | ||
| /** | ||
| * Registers a callback function to be executed once after all tests within the current suite have completed. | ||
| * This hook is useful for scenarios where you need to perform cleanup operations after all tests in a suite have run, such as closing database connections or cleaning up temporary files. | ||
| * | ||
| * **Note:** The `afterAll` hooks are running in reverse order of their registration. You can configure this by changing the `sequence.hooks` option in the config file. | ||
| * | ||
| * @param {Function} fn - The callback function to be executed after all tests. | ||
| * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used. | ||
| * @returns {void} | ||
| * @example | ||
| * ```ts | ||
| * // Example of using afterAll to close a database connection | ||
| * afterAll(async () => { | ||
| * await database.disconnect(); | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function afterAll(fn: AfterAllListener, timeout?: number): void; | ||
| /** | ||
| * Registers a callback function to be executed before each test within the current suite. | ||
| * This hook is useful for scenarios where you need to reset or reinitialize the test environment before each test runs, such as resetting database states, clearing caches, or reinitializing variables. | ||
| * | ||
| * **Note:** The `beforeEach` hooks are executed in the order they are defined one after another. You can configure this by changing the `sequence.hooks` option in the config file. | ||
| * | ||
| * @param {Function} fn - The callback function to be executed before each test. This function receives an `TestContext` parameter if additional test context is needed. | ||
| * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used. | ||
| * @returns {void} | ||
| * @example | ||
| * ```ts | ||
| * // Example of using beforeEach to reset a database state | ||
| * beforeEach(async () => { | ||
| * await database.reset(); | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function beforeEach<ExtraContext = object>(fn: BeforeEachListener<ExtraContext>, timeout?: number): void; | ||
| /** | ||
| * Registers a callback function to be executed after each test within the current suite has completed. | ||
| * This hook is useful for scenarios where you need to clean up or reset the test environment after each test runs, such as deleting temporary files, clearing test-specific database entries, or resetting mocked functions. | ||
| * | ||
| * **Note:** The `afterEach` hooks are running in reverse order of their registration. You can configure this by changing the `sequence.hooks` option in the config file. | ||
| * | ||
| * @param {Function} fn - The callback function to be executed after each test. This function receives an `TestContext` parameter if additional test context is needed. | ||
| * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used. | ||
| * @returns {void} | ||
| * @example | ||
| * ```ts | ||
| * // Example of using afterEach to delete temporary files created during a test | ||
| * afterEach(async () => { | ||
| * await fileSystem.deleteTempFiles(); | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function afterEach<ExtraContext = object>(fn: AfterEachListener<ExtraContext>, timeout?: number): void; | ||
| /** | ||
| * Registers a callback function to be executed when a test fails within the current suite. | ||
| * This function allows for custom actions to be performed in response to test failures, such as logging, cleanup, or additional diagnostics. | ||
| * | ||
| * **Note:** The `onTestFailed` hooks are running in reverse order of their registration. You can configure this by changing the `sequence.hooks` option in the config file. | ||
| * | ||
| * @param {Function} fn - The callback function to be executed upon a test failure. The function receives the test result (including errors). | ||
| * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used. | ||
| * @throws {Error} Throws an error if the function is not called within a test. | ||
| * @returns {void} | ||
| * @example | ||
| * ```ts | ||
| * // Example of using onTestFailed to log failure details | ||
| * onTestFailed(({ errors }) => { | ||
| * console.log(`Test failed: ${test.name}`, errors); | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare const onTestFailed: TaskHook<OnTestFailedHandler>; | ||
| /** | ||
| * Registers a callback function to be executed when the current test finishes, regardless of the outcome (pass or fail). | ||
| * This function is ideal for performing actions that should occur after every test execution, such as cleanup, logging, or resetting shared resources. | ||
| * | ||
| * This hook is useful if you have access to a resource in the test itself and you want to clean it up after the test finishes. It is a more compact way to clean up resources than using the combination of `beforeEach` and `afterEach`. | ||
| * | ||
| * **Note:** The `onTestFinished` hooks are running in reverse order of their registration. You can configure this by changing the `sequence.hooks` option in the config file. | ||
| * | ||
| * **Note:** The `onTestFinished` hook is not called if the test is canceled with a dynamic `ctx.skip()` call. | ||
| * | ||
| * @param {Function} fn - The callback function to be executed after a test finishes. The function can receive parameters providing details about the completed test, including its success or failure status. | ||
| * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used. | ||
| * @throws {Error} Throws an error if the function is not called within a test. | ||
| * @returns {void} | ||
| * @example | ||
| * ```ts | ||
| * // Example of using onTestFinished for cleanup | ||
| * const db = await connectToDatabase(); | ||
| * onTestFinished(async () => { | ||
| * await db.disconnect(); | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare const onTestFinished: TaskHook<OnTestFinishedHandler>; | ||
| type ChainableFunction< | ||
| T extends string, | ||
| F extends (...args: any) => any, | ||
| C = object | ||
| > = F & { [x in T] : ChainableFunction<T, F, C> } & { | ||
| fn: (this: Record<T, any>, ...args: Parameters<F>) => ReturnType<F>; | ||
| } & C; | ||
| declare function createChainable< | ||
| T extends string, | ||
| Args extends any[], | ||
| R = any | ||
| >(keys: T[], fn: (this: Record<T, any>, ...args: Args) => R): ChainableFunction<T, (...args: Args) => R>; | ||
| type RunMode = "run" | "skip" | "only" | "todo" | "queued"; | ||
| type TaskState = RunMode | "pass" | "fail"; | ||
| interface TaskBase { | ||
| /** | ||
| * Unique task identifier. Based on the file id and the position of the task. | ||
| * The id of the file task is based on the file path relative to root and project name. | ||
| * It will not change between runs. | ||
| * @example `1201091390`, `1201091390_0`, `1201091390_0_1` | ||
| */ | ||
| id: string; | ||
| /** | ||
| * Task name provided by the user. If no name was provided, it will be an empty string. | ||
| */ | ||
| name: string; | ||
| /** | ||
| * Full name including the file path, any parent suites, and this task's name. | ||
| * | ||
| * Uses ` > ` as the separator between levels. | ||
| * | ||
| * @example | ||
| * // file | ||
| * 'test/task-names.test.ts' | ||
| * @example | ||
| * // suite | ||
| * 'test/task-names.test.ts > meal planning' | ||
| * 'test/task-names.test.ts > meal planning > grocery lists' | ||
| * @example | ||
| * // test | ||
| * 'test/task-names.test.ts > meal planning > grocery lists > calculates ingredients' | ||
| */ | ||
| fullName: string; | ||
| /** | ||
| * Full name excluding the file path, including any parent suites and this task's name. `undefined` for file tasks. | ||
| * | ||
| * Uses ` > ` as the separator between levels. | ||
| * | ||
| * @example | ||
| * // file | ||
| * undefined | ||
| * @example | ||
| * // suite | ||
| * 'meal planning' | ||
| * 'meal planning > grocery lists' | ||
| * @example | ||
| * // test | ||
| * 'meal planning > grocery lists > calculates ingredients' | ||
| */ | ||
| fullTestName?: string; | ||
| /** | ||
| * Task mode. | ||
| * - **skip**: task is skipped | ||
| * - **only**: only this task and other tasks with `only` mode will run | ||
| * - **todo**: task is marked as a todo, alias for `skip` | ||
| * - **run**: task will run or already ran | ||
| * - **queued**: task will start running next. It can only exist on the File | ||
| */ | ||
| mode: RunMode; | ||
| /** | ||
| * Custom metadata for the task. JSON reporter will save this data. | ||
| */ | ||
| meta: TaskMeta; | ||
| /** | ||
| * Whether the task was produced with `.each()` method. | ||
| */ | ||
| each?: boolean; | ||
| /** | ||
| * Whether the task should run concurrently with other tasks. | ||
| */ | ||
| concurrent?: boolean; | ||
| /** | ||
| * Whether the tasks of the suite run in a random order. | ||
| */ | ||
| shuffle?: boolean; | ||
| /** | ||
| * Suite that this task is part of. File task or the global suite will have no parent. | ||
| */ | ||
| suite?: Suite; | ||
| /** | ||
| * Result of the task. Suite and file tasks will only have the result if there | ||
| * was an error during collection or inside `afterAll`/`beforeAll`. | ||
| */ | ||
| result?: TaskResult; | ||
| /** | ||
| * Retry configuration for the task. | ||
| * - If a number, specifies how many times to retry | ||
| * - If an object, allows fine-grained retry control | ||
| * @default 0 | ||
| */ | ||
| retry?: Retry; | ||
| /** | ||
| * The amount of times the task should be repeated after the successful run. | ||
| * If the task fails, it will not be retried unless `retry` is specified. | ||
| * @default 0 | ||
| */ | ||
| repeats?: number; | ||
| /** | ||
| * Location of the task in the file. This field is populated only if | ||
| * `includeTaskLocation` option is set. It is generated by calling `new Error` | ||
| * and parsing the stack trace, so the location might differ depending on the runtime. | ||
| */ | ||
| location?: { | ||
| line: number; | ||
| column: number; | ||
| }; | ||
| /** | ||
| * If the test was collected by parsing the file AST, and the name | ||
| * is not a static string, this property will be set to `true`. | ||
| * @experimental | ||
| */ | ||
| dynamic?: boolean; | ||
| } | ||
| interface TaskPopulated extends TaskBase { | ||
| /** | ||
| * File task. It's the root task of the file. | ||
| */ | ||
| file: File; | ||
| /** | ||
| * Whether the task should succeed if it fails. If the task fails, it will be marked as passed. | ||
| */ | ||
| fails?: boolean; | ||
| /** | ||
| * Store promises (from async expects) to wait for them before finishing the test | ||
| */ | ||
| promises?: Promise<any>[]; | ||
| } | ||
| /** | ||
| * Custom metadata that can be used in reporters. | ||
| */ | ||
| interface TaskMeta {} | ||
| /** | ||
| * The result of calling a task. | ||
| */ | ||
| interface TaskResult { | ||
| /** | ||
| * State of the task. Inherits the `task.mode` during collection. | ||
| * When the task has finished, it will be changed to `pass` or `fail`. | ||
| * - **pass**: task ran successfully | ||
| * - **fail**: task failed | ||
| */ | ||
| state: TaskState; | ||
| /** | ||
| * Errors that occurred during the task execution. It is possible to have several errors | ||
| * if `expect.soft()` failed multiple times or `retry` was triggered. | ||
| */ | ||
| errors?: TestError[]; | ||
| /** | ||
| * How long in milliseconds the task took to run. | ||
| */ | ||
| duration?: number; | ||
| /** | ||
| * Time in milliseconds when the task started running. | ||
| */ | ||
| startTime?: number; | ||
| /** | ||
| * Heap size in bytes after the task finished. | ||
| * Only available if `logHeapUsage` option is set and `process.memoryUsage` is defined. | ||
| */ | ||
| heap?: number; | ||
| /** | ||
| * State of related to this task hooks. Useful during reporting. | ||
| */ | ||
| hooks?: Partial<Record<keyof SuiteHooks, TaskState>>; | ||
| /** | ||
| * The amount of times the task was retried. The task is retried only if it | ||
| * failed and `retry` option is set. | ||
| */ | ||
| retryCount?: number; | ||
| /** | ||
| * The amount of times the task was repeated. The task is repeated only if | ||
| * `repeats` option is set. This number also contains `retryCount`. | ||
| */ | ||
| repeatCount?: number; | ||
| } | ||
| /** The time spent importing & executing a non-externalized file. */ | ||
| interface ImportDuration { | ||
| /** The time spent importing & executing the file itself, not counting all non-externalized imports that the file does. */ | ||
| selfTime: number; | ||
| /** The time spent importing & executing the file and all its imports. */ | ||
| totalTime: number; | ||
| /** Will be set to `true`, if the module was externalized. In this case totalTime and selfTime are identical. */ | ||
| external?: boolean; | ||
| /** Which module imported this module first. All subsequent imports are cached. */ | ||
| importer?: string; | ||
| } | ||
| /** | ||
| * The tuple representing a single task update. | ||
| * Usually reported after the task finishes. | ||
| */ | ||
| type TaskResultPack = [id: string, result: TaskResult | undefined, meta: TaskMeta]; | ||
| interface TaskEventData { | ||
| annotation?: TestAnnotation | undefined; | ||
| artifact?: TestArtifact | undefined; | ||
| } | ||
| type TaskEventPack = [id: string, event: TaskUpdateEvent, data: TaskEventData | undefined]; | ||
| type TaskUpdateEvent = "test-failed-early" | "suite-failed-early" | "test-prepare" | "test-finished" | "test-retried" | "suite-prepare" | "suite-finished" | "before-hook-start" | "before-hook-end" | "after-hook-start" | "after-hook-end" | "test-annotation" | "test-artifact"; | ||
| interface Suite extends TaskBase { | ||
| type: "suite"; | ||
| /** | ||
| * File task. It's the root task of the file. | ||
| */ | ||
| file: File; | ||
| /** | ||
| * An array of tasks that are part of the suite. | ||
| */ | ||
| tasks: Task[]; | ||
| } | ||
| interface File extends Suite { | ||
| /** | ||
| * The name of the pool that the file belongs to. | ||
| * @default 'forks' | ||
| */ | ||
| pool?: string; | ||
| /** | ||
| * The environment that processes the file on the server. | ||
| */ | ||
| viteEnvironment?: string; | ||
| /** | ||
| * The path to the file in UNIX format. | ||
| */ | ||
| filepath: string; | ||
| /** | ||
| * The name of the workspace project the file belongs to. | ||
| */ | ||
| projectName: string | undefined; | ||
| /** | ||
| * The time it took to collect all tests in the file. | ||
| * This time also includes importing all the file dependencies. | ||
| */ | ||
| collectDuration?: number; | ||
| /** | ||
| * The time it took to import the setup file. | ||
| */ | ||
| setupDuration?: number; | ||
| /** The time spent importing every non-externalized dependency that Vitest has processed. */ | ||
| importDurations?: Record<string, ImportDuration>; | ||
| } | ||
| interface Test<ExtraContext = object> extends TaskPopulated { | ||
| type: "test"; | ||
| /** | ||
| * Test context that will be passed to the test function. | ||
| */ | ||
| context: TestContext & ExtraContext; | ||
| /** | ||
| * The test timeout in milliseconds. | ||
| */ | ||
| timeout: number; | ||
| /** | ||
| * An array of custom annotations. | ||
| */ | ||
| annotations: TestAnnotation[]; | ||
| /** | ||
| * An array of artifacts produced by the test. | ||
| * | ||
| * @experimental | ||
| */ | ||
| artifacts: TestArtifact[]; | ||
| fullTestName: string; | ||
| } | ||
| type Task = Test | Suite | File; | ||
| type TestFunction<ExtraContext = object> = (context: TestContext & ExtraContext) => Awaitable<any> | void; | ||
| type ExtractEachCallbackArgs<T extends ReadonlyArray<any>> = { | ||
| 1: [T[0]]; | ||
| 2: [T[0], T[1]]; | ||
| 3: [T[0], T[1], T[2]]; | ||
| 4: [T[0], T[1], T[2], T[3]]; | ||
| 5: [T[0], T[1], T[2], T[3], T[4]]; | ||
| 6: [T[0], T[1], T[2], T[3], T[4], T[5]]; | ||
| 7: [T[0], T[1], T[2], T[3], T[4], T[5], T[6]]; | ||
| 8: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7]]; | ||
| 9: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8]]; | ||
| 10: [T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9]]; | ||
| fallback: Array<T extends ReadonlyArray<infer U> ? U : any>; | ||
| }[T extends Readonly<[any]> ? 1 : T extends Readonly<[any, any]> ? 2 : T extends Readonly<[any, any, any]> ? 3 : T extends Readonly<[any, any, any, any]> ? 4 : T extends Readonly<[any, any, any, any, any]> ? 5 : T extends Readonly<[any, any, any, any, any, any]> ? 6 : T extends Readonly<[any, any, any, any, any, any, any]> ? 7 : T extends Readonly<[any, any, any, any, any, any, any, any]> ? 8 : T extends Readonly<[any, any, any, any, any, any, any, any, any]> ? 9 : T extends Readonly<[any, any, any, any, any, any, any, any, any, any]> ? 10 : "fallback"]; | ||
| interface EachFunctionReturn<T extends any[]> { | ||
| (name: string | Function, fn: (...args: T) => Awaitable<void>, options?: number): void; | ||
| (name: string | Function, options: TestCollectorOptions, fn: (...args: T) => Awaitable<void>): void; | ||
| } | ||
| interface TestEachFunction { | ||
| <T extends any[] | [any]>(cases: ReadonlyArray<T>): EachFunctionReturn<T>; | ||
| <T extends ReadonlyArray<any>>(cases: ReadonlyArray<T>): EachFunctionReturn<ExtractEachCallbackArgs<T>>; | ||
| <T>(cases: ReadonlyArray<T>): EachFunctionReturn<T[]>; | ||
| (...args: [TemplateStringsArray, ...any]): EachFunctionReturn<any[]>; | ||
| } | ||
| interface TestForFunctionReturn< | ||
| Arg, | ||
| Context | ||
| > { | ||
| (name: string | Function, fn: (arg: Arg, context: Context) => Awaitable<void>): void; | ||
| (name: string | Function, options: TestCollectorOptions, fn: (args: Arg, context: Context) => Awaitable<void>): void; | ||
| } | ||
| interface TestForFunction<ExtraContext> { | ||
| <T>(cases: ReadonlyArray<T>): TestForFunctionReturn<T, TestContext & ExtraContext>; | ||
| (strings: TemplateStringsArray, ...values: any[]): TestForFunctionReturn<any, TestContext & ExtraContext>; | ||
| } | ||
| interface SuiteForFunction { | ||
| <T>(cases: ReadonlyArray<T>): EachFunctionReturn<[T]>; | ||
| (...args: [TemplateStringsArray, ...any]): EachFunctionReturn<any[]>; | ||
| } | ||
| interface TestCollectorCallable<C = object> { | ||
| <ExtraContext extends C>(name: string | Function, fn?: TestFunction<ExtraContext>, options?: number): void; | ||
| <ExtraContext extends C>(name: string | Function, options?: TestCollectorOptions, fn?: TestFunction<ExtraContext>): void; | ||
| } | ||
| type ChainableTestAPI<ExtraContext = object> = ChainableFunction<"concurrent" | "sequential" | "only" | "skip" | "todo" | "fails", TestCollectorCallable<ExtraContext>, { | ||
| each: TestEachFunction; | ||
| for: TestForFunction<ExtraContext>; | ||
| }>; | ||
| type TestCollectorOptions = Omit<TestOptions, "shuffle">; | ||
| /** | ||
| * Retry configuration for tests. | ||
| * Can be a number for simple retry count, or an object for advanced retry control. | ||
| */ | ||
| type Retry = number | { | ||
| /** | ||
| * The number of times to retry the test if it fails. | ||
| * @default 0 | ||
| */ | ||
| count?: number; | ||
| /** | ||
| * Delay in milliseconds between retry attempts. | ||
| * @default 0 | ||
| */ | ||
| delay?: number; | ||
| /** | ||
| * Condition to determine if a test should be retried based on the error. | ||
| * - If a RegExp, it is tested against the error message | ||
| * - If a function, called with the TestError object; return true to retry | ||
| * | ||
| * NOTE: Functions can only be used in test files, not in vitest.config.ts, | ||
| * because the configuration is serialized when passed to worker threads. | ||
| * | ||
| * @default undefined (retry on all errors) | ||
| */ | ||
| condition?: RegExp | ((error: TestError) => boolean); | ||
| }; | ||
| /** | ||
| * Serializable retry configuration (used in config files). | ||
| * Functions cannot be serialized, so only string conditions are allowed. | ||
| */ | ||
| type SerializableRetry = number | { | ||
| /** | ||
| * The number of times to retry the test if it fails. | ||
| * @default 0 | ||
| */ | ||
| count?: number; | ||
| /** | ||
| * Delay in milliseconds between retry attempts. | ||
| * @default 0 | ||
| */ | ||
| delay?: number; | ||
| /** | ||
| * Condition to determine if a test should be retried based on the error. | ||
| * Must be a RegExp tested against the error message. | ||
| * | ||
| * @default undefined (retry on all errors) | ||
| */ | ||
| condition?: RegExp; | ||
| }; | ||
| interface TestOptions { | ||
| /** | ||
| * Test timeout. | ||
| */ | ||
| timeout?: number; | ||
| /** | ||
| * Retry configuration for the test. | ||
| * - If a number, specifies how many times to retry | ||
| * - If an object, allows fine-grained retry control | ||
| * @default 0 | ||
| */ | ||
| retry?: Retry; | ||
| /** | ||
| * How many times the test will run again. | ||
| * Only inner tests will repeat if set on `describe()`, nested `describe()` will inherit parent's repeat by default. | ||
| * | ||
| * @default 0 | ||
| */ | ||
| repeats?: number; | ||
| /** | ||
| * Whether suites and tests run concurrently. | ||
| * Tests inherit `concurrent` from `describe()` and nested `describe()` will inherit from parent's `concurrent`. | ||
| */ | ||
| concurrent?: boolean; | ||
| /** | ||
| * Whether tests run sequentially. | ||
| * Tests inherit `sequential` from `describe()` and nested `describe()` will inherit from parent's `sequential`. | ||
| */ | ||
| sequential?: boolean; | ||
| /** | ||
| * Whether the tasks of the suite run in a random order. | ||
| */ | ||
| shuffle?: boolean; | ||
| /** | ||
| * Whether the test should be skipped. | ||
| */ | ||
| skip?: boolean; | ||
| /** | ||
| * Should this test be the only one running in a suite. | ||
| */ | ||
| only?: boolean; | ||
| /** | ||
| * Whether the test should be skipped and marked as a todo. | ||
| */ | ||
| todo?: boolean; | ||
| /** | ||
| * Whether the test is expected to fail. If it does, the test will pass, otherwise it will fail. | ||
| */ | ||
| fails?: boolean; | ||
| } | ||
| interface ExtendedAPI<ExtraContext> { | ||
| skipIf: (condition: any) => ChainableTestAPI<ExtraContext>; | ||
| runIf: (condition: any) => ChainableTestAPI<ExtraContext>; | ||
| } | ||
| interface Hooks<ExtraContext> { | ||
| beforeAll: typeof beforeAll; | ||
| afterAll: typeof afterAll; | ||
| beforeEach: typeof beforeEach<ExtraContext>; | ||
| afterEach: typeof afterEach<ExtraContext>; | ||
| } | ||
| type TestAPI<ExtraContext = object> = ChainableTestAPI<ExtraContext> & ExtendedAPI<ExtraContext> & Hooks<ExtraContext> & { | ||
| extend: <T extends Record<string, any> = object>(fixtures: Fixtures<T, ExtraContext>) => TestAPI<{ [K in keyof T | keyof ExtraContext] : K extends keyof T ? T[K] : K extends keyof ExtraContext ? ExtraContext[K] : never }>; | ||
| scoped: (fixtures: Partial<Fixtures<ExtraContext>>) => void; | ||
| }; | ||
| interface FixtureOptions { | ||
| /** | ||
| * Whether to automatically set up current fixture, even though it's not being used in tests. | ||
| * @default false | ||
| */ | ||
| auto?: boolean; | ||
| /** | ||
| * Indicated if the injected value from the config should be preferred over the fixture value | ||
| */ | ||
| injected?: boolean; | ||
| /** | ||
| * When should the fixture be set up. | ||
| * - **test**: fixture will be set up before every test | ||
| * - **worker**: fixture will be set up once per worker | ||
| * - **file**: fixture will be set up once per file | ||
| * | ||
| * **Warning:** The `vmThreads` and `vmForks` pools initiate worker fixtures once per test file. | ||
| * @default 'test' | ||
| */ | ||
| scope?: "test" | "worker" | "file"; | ||
| } | ||
| type Use<T> = (value: T) => Promise<void>; | ||
| type FixtureFn< | ||
| T, | ||
| K extends keyof T, | ||
| ExtraContext | ||
| > = (context: Omit<T, K> & ExtraContext, use: Use<T[K]>) => Promise<void>; | ||
| type Fixture< | ||
| T, | ||
| K extends keyof T, | ||
| ExtraContext = object | ||
| > = ((...args: any) => any) extends T[K] ? T[K] extends any ? FixtureFn<T, K, Omit<ExtraContext, Exclude<keyof T, K>>> : never : T[K] | (T[K] extends any ? FixtureFn<T, K, Omit<ExtraContext, Exclude<keyof T, K>>> : never); | ||
| type Fixtures< | ||
| T, | ||
| ExtraContext = object | ||
| > = { [K in keyof T] : Fixture<T, K, ExtraContext & TestContext> | [Fixture<T, K, ExtraContext & TestContext>, FixtureOptions?] }; | ||
| type InferFixturesTypes<T> = T extends TestAPI<infer C> ? C : T; | ||
| interface SuiteCollectorCallable<ExtraContext = object> { | ||
| <OverrideExtraContext extends ExtraContext = ExtraContext>(name: string | Function, fn?: SuiteFactory<OverrideExtraContext>, options?: number): SuiteCollector<OverrideExtraContext>; | ||
| <OverrideExtraContext extends ExtraContext = ExtraContext>(name: string | Function, options: TestOptions, fn?: SuiteFactory<OverrideExtraContext>): SuiteCollector<OverrideExtraContext>; | ||
| } | ||
| type ChainableSuiteAPI<ExtraContext = object> = ChainableFunction<"concurrent" | "sequential" | "only" | "skip" | "todo" | "shuffle", SuiteCollectorCallable<ExtraContext>, { | ||
| each: TestEachFunction; | ||
| for: SuiteForFunction; | ||
| }>; | ||
| type SuiteAPI<ExtraContext = object> = ChainableSuiteAPI<ExtraContext> & { | ||
| skipIf: (condition: any) => ChainableSuiteAPI<ExtraContext>; | ||
| runIf: (condition: any) => ChainableSuiteAPI<ExtraContext>; | ||
| }; | ||
| interface BeforeAllListener { | ||
| (suite: Readonly<Suite | File>): Awaitable<unknown>; | ||
| } | ||
| interface AfterAllListener { | ||
| (suite: Readonly<Suite | File>): Awaitable<unknown>; | ||
| } | ||
| interface BeforeEachListener<ExtraContext = object> { | ||
| (context: TestContext & ExtraContext, suite: Readonly<Suite>): Awaitable<unknown>; | ||
| } | ||
| interface AfterEachListener<ExtraContext = object> { | ||
| (context: TestContext & ExtraContext, suite: Readonly<Suite>): Awaitable<unknown>; | ||
| } | ||
| interface SuiteHooks<ExtraContext = object> { | ||
| beforeAll: BeforeAllListener[]; | ||
| afterAll: AfterAllListener[]; | ||
| beforeEach: BeforeEachListener<ExtraContext>[]; | ||
| afterEach: AfterEachListener<ExtraContext>[]; | ||
| } | ||
| interface TaskCustomOptions extends TestOptions { | ||
| /** | ||
| * Whether the task was produced with `.each()` method. | ||
| */ | ||
| each?: boolean; | ||
| /** | ||
| * Custom metadata for the task that will be assigned to `task.meta`. | ||
| */ | ||
| meta?: Record<string, unknown>; | ||
| /** | ||
| * Task fixtures. | ||
| */ | ||
| fixtures?: FixtureItem[]; | ||
| /** | ||
| * Function that will be called when the task is executed. | ||
| * If nothing is provided, the runner will try to get the function using `getFn(task)`. | ||
| * If the runner cannot find the function, the task will be marked as failed. | ||
| */ | ||
| handler?: (context: TestContext) => Awaitable<void>; | ||
| } | ||
| interface SuiteCollector<ExtraContext = object> { | ||
| readonly name: string; | ||
| readonly mode: RunMode; | ||
| options?: TestOptions; | ||
| type: "collector"; | ||
| test: TestAPI<ExtraContext>; | ||
| tasks: (Suite | Test<ExtraContext> | SuiteCollector<ExtraContext>)[]; | ||
| scoped: (fixtures: Fixtures<any, ExtraContext>) => void; | ||
| fixtures: () => FixtureItem[] | undefined; | ||
| file?: File; | ||
| suite?: Suite; | ||
| task: (name: string, options?: TaskCustomOptions) => Test<ExtraContext>; | ||
| collect: (file: File) => Promise<Suite>; | ||
| clear: () => void; | ||
| on: <T extends keyof SuiteHooks<ExtraContext>>(name: T, ...fn: SuiteHooks<ExtraContext>[T]) => void; | ||
| } | ||
| type SuiteFactory<ExtraContext = object> = (test: TestAPI<ExtraContext>) => Awaitable<void>; | ||
| interface RuntimeContext { | ||
| tasks: (SuiteCollector | Test)[]; | ||
| currentSuite: SuiteCollector | null; | ||
| } | ||
| /** | ||
| * User's custom test context. | ||
| */ | ||
| interface TestContext { | ||
| /** | ||
| * Metadata of the current test | ||
| */ | ||
| readonly task: Readonly<Test>; | ||
| /** | ||
| * An [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) that will be aborted if the test times out or | ||
| * the test run was cancelled. | ||
| * @see {@link https://vitest.dev/guide/test-context#signal} | ||
| */ | ||
| readonly signal: AbortSignal; | ||
| /** | ||
| * Register a callback to run when this specific test fails. | ||
| * Useful when tests run concurrently. | ||
| * @see {@link https://vitest.dev/guide/test-context#ontestfailed} | ||
| */ | ||
| readonly onTestFailed: (fn: OnTestFailedHandler, timeout?: number) => void; | ||
| /** | ||
| * Register a callback to run when this specific test finishes. | ||
| * Useful when tests run concurrently. | ||
| * @see {@link https://vitest.dev/guide/test-context#ontestfinished} | ||
| */ | ||
| readonly onTestFinished: (fn: OnTestFinishedHandler, timeout?: number) => void; | ||
| /** | ||
| * Mark tests as skipped. All execution after this call will be skipped. | ||
| * This function throws an error, so make sure you are not catching it accidentally. | ||
| * @see {@link https://vitest.dev/guide/test-context#skip} | ||
| */ | ||
| readonly skip: { | ||
| (note?: string): never; | ||
| (condition: boolean, note?: string): void; | ||
| }; | ||
| /** | ||
| * Add a test annotation that will be displayed by your reporter. | ||
| * @see {@link https://vitest.dev/guide/test-context#annotate} | ||
| */ | ||
| readonly annotate: { | ||
| (message: string, type?: string, attachment?: TestAttachment): Promise<TestAnnotation>; | ||
| (message: string, attachment?: TestAttachment): Promise<TestAnnotation>; | ||
| }; | ||
| } | ||
| type OnTestFailedHandler = (context: TestContext) => Awaitable<void>; | ||
| type OnTestFinishedHandler = (context: TestContext) => Awaitable<void>; | ||
| interface TaskHook<HookListener> { | ||
| (fn: HookListener, timeout?: number): void; | ||
| } | ||
| type SequenceHooks = "stack" | "list" | "parallel"; | ||
| type SequenceSetupFiles = "list" | "parallel"; | ||
| /** | ||
| * Represents a file or data attachment associated with a test artifact. | ||
| * | ||
| * Attachments can be either file-based (via `path`) or inline content (via `body`). | ||
| * The `contentType` helps consumers understand how to interpret the attachment data. | ||
| */ | ||
| interface TestAttachment { | ||
| /** MIME type of the attachment (e.g., 'image/png', 'text/plain') */ | ||
| contentType?: string; | ||
| /** File system path to the attachment */ | ||
| path?: string; | ||
| /** Inline attachment content as a string or raw binary data */ | ||
| body?: string | Uint8Array; | ||
| } | ||
| /** | ||
| * Source code location information for a test artifact. | ||
| * | ||
| * Indicates where in the source code the artifact originated from. | ||
| */ | ||
| interface TestArtifactLocation { | ||
| /** Line number in the source file (1-indexed) */ | ||
| line: number; | ||
| /** Column number in the line (1-indexed) */ | ||
| column: number; | ||
| /** Path to the source file */ | ||
| file: string; | ||
| } | ||
| /** | ||
| * @experimental | ||
| * | ||
| * Base interface for all test artifacts. | ||
| * | ||
| * Extend this interface when creating custom test artifacts. Vitest automatically manages the `attachments` array and injects the `location` property to indicate where the artifact was created in your test code. | ||
| */ | ||
| interface TestArtifactBase { | ||
| /** File or data attachments associated with this artifact */ | ||
| attachments?: TestAttachment[]; | ||
| /** Source location where this artifact was created */ | ||
| location?: TestArtifactLocation; | ||
| } | ||
| /** | ||
| * @deprecated Use {@linkcode TestArtifactLocation} instead. | ||
| * | ||
| * Kept for backwards compatibility. | ||
| */ | ||
| type TestAnnotationLocation = TestArtifactLocation; | ||
| interface TestAnnotation { | ||
| message: string; | ||
| type: string; | ||
| location?: TestArtifactLocation; | ||
| attachment?: TestAttachment; | ||
| } | ||
| /** | ||
| * @experimental | ||
| * | ||
| * Artifact type for test annotations. | ||
| */ | ||
| interface TestAnnotationArtifact extends TestArtifactBase { | ||
| type: "internal:annotation"; | ||
| annotation: TestAnnotation; | ||
| } | ||
| interface VisualRegressionArtifactAttachment extends TestAttachment { | ||
| name: "reference" | "actual" | "diff"; | ||
| width: number; | ||
| height: number; | ||
| } | ||
| /** | ||
| * @experimental | ||
| * | ||
| * Artifact type for visual regressions. | ||
| */ | ||
| interface VisualRegressionArtifact extends TestArtifactBase { | ||
| type: "internal:toMatchScreenshot"; | ||
| kind: "visual-regression"; | ||
| message: string; | ||
| attachments: VisualRegressionArtifactAttachment[]; | ||
| } | ||
| /** | ||
| * @experimental | ||
| * @advanced | ||
| * | ||
| * Registry for custom test artifact types. | ||
| * | ||
| * Augment this interface to register custom artifact types that your tests can produce. | ||
| * | ||
| * Each custom artifact should extend {@linkcode TestArtifactBase} and include a unique `type` discriminator property. | ||
| * | ||
| * @remarks | ||
| * - Use a `Symbol` as the **registry key** to guarantee uniqueness | ||
| * - The `type` property should follow the pattern `'package-name:artifact-name'`, `'internal:'` is a reserved prefix | ||
| * - Use `attachments` to include files or data; extend {@linkcode TestAttachment} for custom metadata | ||
| * - `location` property is automatically injected to indicate where the artifact was created | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * // Define custom attachment type for generated PDF | ||
| * interface PDFAttachment extends TestAttachment { | ||
| * contentType: 'application/pdf' | ||
| * body: Uint8Array | ||
| * pageCount: number | ||
| * fileSize: number | ||
| * } | ||
| * | ||
| * interface PDFGenerationArtifact extends TestArtifactBase { | ||
| * type: 'my-plugin:pdf-generation' | ||
| * templateName: string | ||
| * isValid: boolean | ||
| * attachments: [PDFAttachment] | ||
| * } | ||
| * | ||
| * // Use a symbol to guarantee key uniqueness | ||
| * const pdfKey = Symbol('pdf-generation') | ||
| * | ||
| * declare module 'vitest' { | ||
| * interface TestArtifactRegistry { | ||
| * [pdfKey]: PDFGenerationArtifact | ||
| * } | ||
| * } | ||
| * | ||
| * // Custom assertion for PDF generation | ||
| * async function toGenerateValidPDF( | ||
| * this: MatcherState, | ||
| * actual: PDFTemplate, | ||
| * data: Record<string, unknown> | ||
| * ): AsyncExpectationResult { | ||
| * const pdfBuffer = await actual.render(data) | ||
| * const validation = await validatePDF(pdfBuffer) | ||
| * | ||
| * await recordArtifact(this.task, { | ||
| * type: 'my-plugin:pdf-generation', | ||
| * templateName: actual.name, | ||
| * isValid: validation.success, | ||
| * attachments: [{ | ||
| * contentType: 'application/pdf', | ||
| * body: pdfBuffer, | ||
| * pageCount: validation.pageCount, | ||
| * fileSize: pdfBuffer.byteLength | ||
| * }] | ||
| * }) | ||
| * | ||
| * return { | ||
| * pass: validation.success, | ||
| * message: () => validation.success | ||
| * ? `Generated valid PDF with ${validation.pageCount} pages` | ||
| * : `Invalid PDF: ${validation.error}` | ||
| * } | ||
| * } | ||
| * ``` | ||
| */ | ||
| interface TestArtifactRegistry {} | ||
| /** | ||
| * @experimental | ||
| * | ||
| * Union type of all test artifacts, including built-in and custom registered artifacts. | ||
| * | ||
| * This type automatically includes all artifacts registered via {@link TestArtifactRegistry}. | ||
| */ | ||
| type TestArtifact = TestAnnotationArtifact | VisualRegressionArtifact | TestArtifactRegistry[keyof TestArtifactRegistry]; | ||
| export { createChainable as c, afterAll as i, afterEach as j, beforeAll as k, beforeEach as l, onTestFinished as m, onTestFailed as o }; | ||
| export type { TestContext as $, AfterAllListener as A, BeforeAllListener as B, ChainableFunction as C, SerializableRetry as D, SuiteFactory as E, File as F, TaskBase as G, TaskCustomOptions as H, ImportDuration as I, TaskEventPack as J, TaskHook as K, TaskMeta as L, TaskPopulated as M, TaskResult as N, OnTestFailedHandler as O, TaskResultPack as P, TaskState as Q, Retry as R, Suite as S, Task as T, TestAnnotation as U, TestAnnotationArtifact as V, TestAnnotationLocation as W, TestArtifactBase as X, TestArtifactLocation as Y, TestArtifactRegistry as Z, TestAttachment as _, Test as a, TestFunction as a0, TestOptions as a1, Use as a2, VisualRegressionArtifact as a3, TestArtifact as b, SuiteHooks as d, TaskUpdateEvent as e, TestAPI as f, SuiteAPI as g, SuiteCollector as h, AfterEachListener as n, BeforeEachListener as p, Fixture as q, FixtureFn as r, FixtureOptions as s, Fixtures as t, InferFixturesTypes as u, OnTestFinishedHandler as v, RunMode as w, RuntimeContext as x, SequenceHooks as y, SequenceSetupFiles as z }; |
Sorry, the diff of this file is too big to display
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
156562
7.05%4099
7.81%18
-5.26%2
100%+ Added
+ Added
- Removed
- Removed
Updated