|
4 | 4 | This is advanced API. If you are just running tests, you probably don't need this. It is primarily used by library authors.
|
5 | 5 | :::
|
6 | 6 |
|
7 |
| -You can specify a path to your test runner with the `runner` option in your configuration file. This file should have a default export with a class implementing these methods: |
| 7 | +You can specify a path to your test runner with the `runner` option in your configuration file. This file should have a default export with a class constructor implementing these methods: |
8 | 8 |
|
9 | 9 | ```ts
|
10 | 10 | export interface VitestRunner {
|
@@ -106,9 +106,145 @@ Vitest also injects an instance of `ViteNodeRunner` as `__vitest_executor` prope
|
106 | 106 | Snapshot support and some other features depend on the runner. If you don't want to lose it, you can extend your runner from `VitestTestRunner` imported from `vitest/runners`. It also exposes `BenchmarkNodeRunner`, if you want to extend benchmark functionality.
|
107 | 107 | :::
|
108 | 108 |
|
| 109 | +## Tasks |
| 110 | + |
| 111 | +Suites and tests are called `tasks` internally. Vitest runner initiates a `File` task before collecting any tests - this is a superset of `Suite` with a few additional properties. It is available on every task (including `File`) as a `file` property. |
| 112 | + |
| 113 | +```ts |
| 114 | +interface File extends Suite { |
| 115 | + /** |
| 116 | + * The name of the pool that the file belongs to. |
| 117 | + * @default 'forks' |
| 118 | + */ |
| 119 | + pool?: string |
| 120 | + /** |
| 121 | + * The path to the file in UNIX format. |
| 122 | + */ |
| 123 | + filepath: string |
| 124 | + /** |
| 125 | + * The name of the workspace project the file belongs to. |
| 126 | + */ |
| 127 | + projectName: string | undefined |
| 128 | + /** |
| 129 | + * The time it took to collect all tests in the file. |
| 130 | + * This time also includes importing all the file dependencies. |
| 131 | + */ |
| 132 | + collectDuration?: number |
| 133 | + /** |
| 134 | + * The time it took to import the setup file. |
| 135 | + */ |
| 136 | + setupDuration?: number |
| 137 | + /** |
| 138 | + * Whether the file is initiated without running any tests. |
| 139 | + * This is done to populate state on the server side by Vitest. |
| 140 | + */ |
| 141 | + local?: boolean |
| 142 | +} |
| 143 | +``` |
| 144 | + |
| 145 | +Every suite has a `tasks` property that is populated during collection phase. It is useful to traverse the task tree from the top down. |
| 146 | + |
| 147 | +```ts |
| 148 | +interface Suite extends TaskBase { |
| 149 | + type: 'suite' |
| 150 | + /** |
| 151 | + * File task. It's the root task of the file. |
| 152 | + */ |
| 153 | + file: File |
| 154 | + /** |
| 155 | + * An array of tasks that are part of the suite. |
| 156 | + */ |
| 157 | + tasks: Task[] |
| 158 | +} |
| 159 | +``` |
| 160 | + |
| 161 | +Every task has a `suite` property that references a suite it is located in. If `test` or `describe` are initiated at the top level, they will not have a `suite` property (it will **not** be equal to `file`!). `File` also never has a `suite` property. It is useful to travers the tasks from the bottom up. |
| 162 | + |
| 163 | +```ts |
| 164 | +interface Test<ExtraContext = object> extends TaskBase { |
| 165 | + type: 'test' |
| 166 | + /** |
| 167 | + * Test context that will be passed to the test function. |
| 168 | + */ |
| 169 | + context: TaskContext<Test> & ExtraContext & TestContext |
| 170 | + /** |
| 171 | + * File task. It's the root task of the file. |
| 172 | + */ |
| 173 | + file: File |
| 174 | + /** |
| 175 | + * Whether the task was skipped by calling `t.skip()`. |
| 176 | + */ |
| 177 | + pending?: boolean |
| 178 | + /** |
| 179 | + * Whether the task should succeed if it fails. If the task fails, it will be marked as passed. |
| 180 | + */ |
| 181 | + fails?: boolean |
| 182 | + /** |
| 183 | + * Hooks that will run if the task fails. The order depends on the `sequence.hooks` option. |
| 184 | + */ |
| 185 | + onFailed?: OnTestFailedHandler[] |
| 186 | + /** |
| 187 | + * Hooks that will run after the task finishes. The order depends on the `sequence.hooks` option. |
| 188 | + */ |
| 189 | + onFinished?: OnTestFinishedHandler[] |
| 190 | + /** |
| 191 | + * Store promises (from async expects) to wait for them before finishing the test |
| 192 | + */ |
| 193 | + promises?: Promise<any>[] |
| 194 | +} |
| 195 | +``` |
| 196 | + |
| 197 | +Every task can have a `result` field. Suites can only have this field if an error thrown within a suite callback or `beforeAll`/`afterAll` callbacks prevents them from collecting tests. Tests always have this field after their callbacks are called - the `state` and `errors` fields are present depending on the outcome. If an error was thrown in `beforeEach` or `afterEach` callbacks, the thrown error will be present in `task.result.errors`. |
| 198 | + |
| 199 | +```ts |
| 200 | +export interface TaskResult { |
| 201 | + /** |
| 202 | + * State of the task. Inherits the `task.mode` during collection. |
| 203 | + * When the task has finished, it will be changed to `pass` or `fail`. |
| 204 | + * - **pass**: task ran successfully |
| 205 | + * - **fail**: task failed |
| 206 | + */ |
| 207 | + state: TaskState |
| 208 | + /** |
| 209 | + * Errors that occurred during the task execution. It is possible to have several errors |
| 210 | + * if `expect.soft()` failed multiple times. |
| 211 | + */ |
| 212 | + errors?: ErrorWithDiff[] |
| 213 | + /** |
| 214 | + * How long in milliseconds the task took to run. |
| 215 | + */ |
| 216 | + duration?: number |
| 217 | + /** |
| 218 | + * Time in milliseconds when the task started running. |
| 219 | + */ |
| 220 | + startTime?: number |
| 221 | + /** |
| 222 | + * Heap size in bytes after the task finished. |
| 223 | + * Only available if `logHeapUsage` option is set and `process.memoryUsage` is defined. |
| 224 | + */ |
| 225 | + heap?: number |
| 226 | + /** |
| 227 | + * State of related to this task hooks. Useful during reporting. |
| 228 | + */ |
| 229 | + hooks?: Partial<Record<'afterAll' | 'beforeAll' | 'beforeEach' | 'afterEach', TaskState>> |
| 230 | + /** |
| 231 | + * The amount of times the task was retried. The task is retried only if it |
| 232 | + * failed and `retry` option is set. |
| 233 | + */ |
| 234 | + retryCount?: number |
| 235 | + /** |
| 236 | + * The amount of times the task was repeated. The task is repeated only if |
| 237 | + * `repeats` option is set. This number also contains `retryCount`. |
| 238 | + */ |
| 239 | + repeatCount?: number |
| 240 | +} |
| 241 | +``` |
| 242 | + |
109 | 243 | ## Your Task Function
|
110 | 244 |
|
111 |
| -You can extend Vitest task system with your tasks. A task is an object that is part of a suite. It is automatically added to the current suite with a `suite.task` method: |
| 245 | +Vitest exposes a `Custom` task type that allows users to reuse built-int reporters. It is virtually the same as `Test`, but has a type of `'custom'`. |
| 246 | + |
| 247 | +A task is an object that is part of a suite. It is automatically added to the current suite with a `suite.task` method: |
112 | 248 |
|
113 | 249 | ```js
|
114 | 250 | // ./utils/custom.js
|
@@ -167,7 +303,3 @@ vitest ./garden/tasks.test.js
|
167 | 303 | ::: warning
|
168 | 304 | If you don't have a custom runner or didn't define `runTest` method, Vitest will try to retrieve a task automatically. If you didn't add a function with `setFn`, it will fail.
|
169 | 305 | :::
|
170 |
| - |
171 |
| -::: tip |
172 |
| -Custom task system supports hooks and contexts. If you want to support property chaining (like, `only`, `skip`, and your custom ones), you can import `createChainable` from `vitest/suite` and wrap your function with it. You will need to call `custom` as `custom.call(this)`, if you decide to do this. |
173 |
| -::: |
|
0 commit comments