agent-docs 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/plans/OPTIMISE.md +379 -0
- package/.cursor/plans/VERSIONING.md +207 -0
- package/.cursor/rules/IMPORTANT.mdc +97 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +13 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +17 -0
- package/.github/dependabot.yml +38 -0
- package/.github/pull_request_template.md +10 -0
- package/.github/workflows/format.yml +35 -0
- package/CODE_OF_CONDUCT.md +64 -0
- package/CONTRIBUTING.md +52 -0
- package/LICENSE.md +20 -0
- package/PLAN.md +707 -0
- package/README.md +133 -0
- package/SECURITY.md +21 -0
- package/docs/APEXANNOTATIONS.md +472 -0
- package/docs/APEXDOC.md +198 -0
- package/docs/CML.md +877 -0
- package/docs/CODEANALYZER.md +435 -0
- package/docs/CONTEXTDEFINITIONS.md +617 -0
- package/docs/ESLINT.md +827 -0
- package/docs/ESLINTJSDOC.md +520 -0
- package/docs/FIELDSERVICE.md +4452 -0
- package/docs/GRAPHBINARY.md +208 -0
- package/docs/GRAPHENGINE.md +616 -0
- package/docs/GRAPHML.md +337 -0
- package/docs/GRAPHSON.md +302 -0
- package/docs/GREMLIN.md +490 -0
- package/docs/GRYO.md +232 -0
- package/docs/HUSKY.md +106 -0
- package/docs/JEST.md +387 -0
- package/docs/JORJE.md +537 -0
- package/docs/JSDOC.md +621 -0
- package/docs/PMD.md +910 -0
- package/docs/PNPM.md +409 -0
- package/docs/PRETTIER.md +716 -0
- package/docs/PRETTIERAPEX.md +874 -0
- package/docs/REVENUETRANSACTIONMANAGEMENT.md +887 -0
- package/docs/TINKERPOP.md +252 -0
- package/docs/VITEST.md +706 -0
- package/docs/VSCODE.md +231 -0
- package/docs/XPATH31.md +213 -0
- package/package.json +32 -0
- package/postinstall.mjs +51 -0
- package/prettier.config.js +18 -0
package/docs/VITEST.md
ADDED
|
@@ -0,0 +1,706 @@
|
|
|
1
|
+
# VITEST (Vite-native test framework)
|
|
2
|
+
|
|
3
|
+
> **Version**: 1.0.0
|
|
4
|
+
|
|
5
|
+
Requires: Vite≥6.0.0, Node≥20.0.0
|
|
6
|
+
|
|
7
|
+
## CORE FEATURES
|
|
8
|
+
|
|
9
|
+
- Shared Vite config/transformers/resolvers/plugins
|
|
10
|
+
- Watch mode: auto in dev, run in CI (`process.env.CI`); `vitest watch|run`;
|
|
11
|
+
`--standalone` keeps running, waits for changes
|
|
12
|
+
- ES Module/TypeScript/JSX/PostCSS out-of-box
|
|
13
|
+
- Parallelism: `node:child_process` default; `--pool=threads` uses
|
|
14
|
+
`node:worker_threads` (faster, some pkg incompatible); `--no-isolate` disables
|
|
15
|
+
env isolation
|
|
16
|
+
- `.concurrent` runs tests parallel; `.skip`/`.only`/`.todo` modifiers;
|
|
17
|
+
concurrent tests require local `expect` from Test Context
|
|
18
|
+
- Jest-compatible snapshots
|
|
19
|
+
- Chai built-in + Jest `expect` API; `test.globals=true` for better 3rd-party
|
|
20
|
+
matcher compat
|
|
21
|
+
- Tinyspy built-in for mocking via `vi`; jsdom/happy-dom for DOM (install
|
|
22
|
+
separately)
|
|
23
|
+
- Coverage: v8 (native) or istanbul
|
|
24
|
+
- In-source testing via `import.meta.vitest`
|
|
25
|
+
- Benchmarking (experimental) via Tinybench
|
|
26
|
+
- Type testing (experimental) via expect-type
|
|
27
|
+
- Sharding: `--shard`+`--reporter=blob`, merge via `--merge-reports`
|
|
28
|
+
- Env vars: auto-loads `VITE_`-prefixed from .env; use `loadEnv` from vite for
|
|
29
|
+
all
|
|
30
|
+
- Unhandled errors: caught/reported by default; disable with
|
|
31
|
+
`dangerouslyIgnoreUnhandledErrors`
|
|
32
|
+
|
|
33
|
+
## INSTALL
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm i -D vitest
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## BASIC
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { test, expect } from 'vitest';
|
|
43
|
+
test('adds', () => expect(1 + 2).toBe(3));
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Run: `vitest` (watch) | `vitest run` (single)
|
|
47
|
+
|
|
48
|
+
## CONFIG
|
|
49
|
+
|
|
50
|
+
File: `vitest.config.ts` or `test` in `vite.config.ts`
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import { defineConfig } from 'vitest/config';
|
|
54
|
+
export default defineConfig({
|
|
55
|
+
test: {
|
|
56
|
+
/* opts */
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### OPTIONS (format: `name: type` [default] CLI: flags | notes)
|
|
62
|
+
|
|
63
|
+
**Core**
|
|
64
|
+
|
|
65
|
+
- `include: string[]` ['\*_/_.{test,spec}.?(c|m)[jt]s?(x)'] CLI:
|
|
66
|
+
`vitest [...patterns]` | tinyglobby, relative to root
|
|
67
|
+
- `exclude: string[]` ['**/node_modules/**','**/.git/**'] CLI: `--exclude`
|
|
68
|
+
(additive) | use configDefaults to extend
|
|
69
|
+
- `root: string` [process.cwd()] CLI: `-r, --root`
|
|
70
|
+
- `name: string|{label,color?}` | auto-assigns from package.json or folder; must
|
|
71
|
+
be unique
|
|
72
|
+
- `testTimeout: number` [5000, 15000 if browser] CLI: `--test-timeout`;
|
|
73
|
+
0=disable
|
|
74
|
+
- `setupFiles: string|string[]` | runs before each test file; rerun triggers on
|
|
75
|
+
edit
|
|
76
|
+
- `globalSetup: string|string[]` | exports setup/teardown; runs only if tests
|
|
77
|
+
exist; `provide` for data passing
|
|
78
|
+
- `globals: boolean` [false] CLI: `--globals` | add `vitest/globals` to tsconfig
|
|
79
|
+
types
|
|
80
|
+
- `passWithNoTests: boolean` [false] CLI: `--passWithNoTests`
|
|
81
|
+
- `allowOnly: boolean` [!process.env.CI] CLI: `--allowOnly`
|
|
82
|
+
|
|
83
|
+
**Environment**
|
|
84
|
+
|
|
85
|
+
- `environment: 'node'|'jsdom'|'happy-dom'|'edge-runtime'|string` [node] CLI:
|
|
86
|
+
`--environment` | per-file via `@vitest-environment` docblock
|
|
87
|
+
- `environmentOptions: Record<string,unknown>` | keyed by env name (jsdom,
|
|
88
|
+
happyDOM)
|
|
89
|
+
|
|
90
|
+
**Coverage** (CLI prefix: `--coverage.`)
|
|
91
|
+
|
|
92
|
+
- `provider: 'v8'|'istanbul'|'custom'` [v8]
|
|
93
|
+
- `enabled: boolean` [false]
|
|
94
|
+
- `include/exclude: string[]` | glob patterns
|
|
95
|
+
- `clean: boolean` [true] | clear before run
|
|
96
|
+
- `cleanOnRerun: boolean` [true]
|
|
97
|
+
- `reportsDirectory: string` ['./coverage']
|
|
98
|
+
- `reporter: string|string[]|[string,{}][]` [['text','html','clover','json']]
|
|
99
|
+
- `reportOnFailure: boolean` [false]
|
|
100
|
+
- `allowExternal: boolean` [false]
|
|
101
|
+
- `excludeAfterRemap: boolean` [false]
|
|
102
|
+
- `skipFull: boolean` [false]
|
|
103
|
+
- `thresholds: {lines,functions,branches,statements: number, perFile?: boolean, autoUpdate?: boolean|fn, 100?: boolean, [glob]: object}`
|
|
104
|
+
- `ignoreClassMethods: string[]` []
|
|
105
|
+
- `watermarks: {statements,functions,branches,lines: [low,high]}` [[50,80]...]
|
|
106
|
+
- `processingConcurrency: number` [min(20, cpus)]
|
|
107
|
+
- `customProviderModule: string` | for custom provider
|
|
108
|
+
|
|
109
|
+
**Pools**
|
|
110
|
+
|
|
111
|
+
- `pool: 'threads'|'forks'|'vmThreads'|'vmForks'` [forks] CLI: `--pool`
|
|
112
|
+
- `poolOptions.{threads|forks|vmThreads|vmForks}: object`
|
|
113
|
+
- `minThreads/maxThreads: number`
|
|
114
|
+
- `isolate: boolean` [true]
|
|
115
|
+
- `singleThread/singleFork: boolean` [false]
|
|
116
|
+
- `useAtomics: boolean` [false]
|
|
117
|
+
- `execArgv: string[]`
|
|
118
|
+
|
|
119
|
+
**Isolation & Parallelism**
|
|
120
|
+
|
|
121
|
+
- `isolate: boolean` [true] CLI: `--no-isolate`
|
|
122
|
+
- `fileParallelism: boolean` [true] CLI: `--no-file-parallelism`
|
|
123
|
+
|
|
124
|
+
**Reporters** CLI: `--reporter`
|
|
125
|
+
|
|
126
|
+
- Built-in: default, basic, verbose, dot, json, tap, tap-flat, junit,
|
|
127
|
+
hanging-process, github-actions, blob, html, tree
|
|
128
|
+
- `outputFile: string|Record<reporter,path>` | for json/junit/blob/html
|
|
129
|
+
|
|
130
|
+
**Sequence**
|
|
131
|
+
|
|
132
|
+
- `sequence.shuffle: boolean` [false] CLI: `--sequence.shuffle`
|
|
133
|
+
- `sequence.seed: number` CLI: `--sequence.seed`
|
|
134
|
+
- `sequence.concurrent: boolean` [false] CLI: `--sequence.concurrent`
|
|
135
|
+
- `sequence.hooks: 'stack'|'list'|'parallel'` [parallel]
|
|
136
|
+
- `sequence.setupFiles: 'list'|'parallel'` [parallel]
|
|
137
|
+
|
|
138
|
+
**Retry/Repeat**
|
|
139
|
+
|
|
140
|
+
- `retry: number` [0] CLI: `--retry`
|
|
141
|
+
- `repeats: number` [0] CLI: `--repeats`
|
|
142
|
+
|
|
143
|
+
**Deps**
|
|
144
|
+
|
|
145
|
+
- `deps.optimizer.{ssr|client}: {enabled,include,exclude,force}` | Vite dep
|
|
146
|
+
optimization
|
|
147
|
+
- `deps.client.transformAssets/transformCss: boolean` [true] | vmThreads/vmForks
|
|
148
|
+
only
|
|
149
|
+
- `deps.interopDefault: boolean` [true]
|
|
150
|
+
- `deps.moduleDirectories: string[]` ['node_modules']
|
|
151
|
+
|
|
152
|
+
**Mocking**
|
|
153
|
+
|
|
154
|
+
- `clearMocks: boolean` [false] | vi.clearAllMocks before each
|
|
155
|
+
- `mockReset: boolean` [false] | vi.resetAllMocks before each
|
|
156
|
+
- `restoreMocks: boolean` [false] | vi.restoreAllMocks before each
|
|
157
|
+
- `unstubGlobals: boolean` [false]
|
|
158
|
+
- `unstubEnvs: boolean` [false]
|
|
159
|
+
|
|
160
|
+
**Snapshots**
|
|
161
|
+
|
|
162
|
+
- `snapshotFormat: PrettyFormatOptions`
|
|
163
|
+
- `resolveSnapshotPath: (testPath,ext,ctx)=>string`
|
|
164
|
+
- `snapshotSerializers: string[]`
|
|
165
|
+
- `snapshotEnvironment: string` | custom impl
|
|
166
|
+
- `expandSnapshotDiff: boolean` [false] CLI: `--expandSnapshotDiff`
|
|
167
|
+
- `update: boolean` [false] CLI: `-u, --update`
|
|
168
|
+
|
|
169
|
+
**Typecheck** (experimental)
|
|
170
|
+
|
|
171
|
+
- `typecheck.enabled: boolean` [false] CLI: `--typecheck`
|
|
172
|
+
- `typecheck.only: boolean` [false]
|
|
173
|
+
- `typecheck.checker: 'tsc'|'vue-tsc'|string` [tsc]
|
|
174
|
+
- `typecheck.include/exclude: string[]`
|
|
175
|
+
- `typecheck.allowJs: boolean` [false]
|
|
176
|
+
- `typecheck.ignoreSourceErrors: boolean` [false]
|
|
177
|
+
- `typecheck.tsconfig: string`
|
|
178
|
+
|
|
179
|
+
**Fake Timers** (`fakeTimers` for vi.useFakeTimers)
|
|
180
|
+
|
|
181
|
+
- `now: number|Date` [Date.now()]
|
|
182
|
+
- `toFake: string[]` | methods to fake; nextTick not supported in forks pool
|
|
183
|
+
- `loopLimit: number` [10000]
|
|
184
|
+
- `shouldAdvanceTime: boolean` [false]
|
|
185
|
+
- `advanceTimeDelta: number` [20]
|
|
186
|
+
- `shouldClearNativeTimers: boolean` [true]
|
|
187
|
+
|
|
188
|
+
**Expect**
|
|
189
|
+
|
|
190
|
+
- `expect.requireAssertions: boolean` [false]
|
|
191
|
+
- `expect.poll: {interval: number, timeout: number}` [50, 1000]
|
|
192
|
+
|
|
193
|
+
**Chai**
|
|
194
|
+
|
|
195
|
+
- `chaiConfig: {includeStack: boolean, showDiff: boolean, truncateThreshold: number}`
|
|
196
|
+
[false,true,40]
|
|
197
|
+
|
|
198
|
+
**Misc**
|
|
199
|
+
|
|
200
|
+
- `alias: Record<string,string>|Array<{find,replacement,customResolver?}>` |
|
|
201
|
+
merged with resolve.alias
|
|
202
|
+
- `css: boolean|{include?,exclude?,modules?}` [false] | process CSS
|
|
203
|
+
- `logHeapUsage: boolean` [false] CLI: `--logHeapUsage`
|
|
204
|
+
- `dangerouslyIgnoreUnhandledErrors: boolean` [false]
|
|
205
|
+
- `forceRerunTriggers: string[]`
|
|
206
|
+
['**/package.json/**','**/vitest.config.*/**','**/vite.config.*/**']
|
|
207
|
+
- `includeSource: string[]` [] | in-source test globs
|
|
208
|
+
- `server: {deps,sourcemap}` | Vite server options for tests
|
|
209
|
+
- `inspect/inspectBrk: boolean|string` CLI: `--inspect`, `--inspect-brk`
|
|
210
|
+
- `slowTestThreshold: number` [300] | highlight slow tests
|
|
211
|
+
- `bail: number` [0] CLI: `--bail` | stop after N failures
|
|
212
|
+
- `cache: {dir: string}` | cache location
|
|
213
|
+
- `env: Record<string,string>` | process.env vars
|
|
214
|
+
- `attachmentsDir: string` ['.vitest-attachments']
|
|
215
|
+
- `execArgv: string[]` | node args for worker
|
|
216
|
+
|
|
217
|
+
**Experimental**
|
|
218
|
+
|
|
219
|
+
- `experimental.fsModuleCache: boolean` [false] | persistent cache
|
|
220
|
+
- `experimental.fsModuleCachePath: string`
|
|
221
|
+
['node_modules/.experimental-vitest-cache']
|
|
222
|
+
- `experimental.openTelemetry: {enabled,sdkPath?,browserSdkPath?}` | perf
|
|
223
|
+
tracing
|
|
224
|
+
- `experimental.printImportBreakdown: boolean` [false]
|
|
225
|
+
|
|
226
|
+
**UI**
|
|
227
|
+
|
|
228
|
+
- `ui: boolean` [false] CLI: `--ui` | requires @vitest/ui
|
|
229
|
+
- `api: boolean|number|{port,host,strictPort}` [false, port 51204]
|
|
230
|
+
|
|
231
|
+
## CLI
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
vitest [filters] [options]
|
|
235
|
+
vitest run # single run
|
|
236
|
+
vitest watch # watch mode (default in dev)
|
|
237
|
+
vitest bench # benchmarks
|
|
238
|
+
vitest init browser # setup browser mode
|
|
239
|
+
vitest typecheck # type tests only
|
|
240
|
+
vitest list # list tests without running
|
|
241
|
+
|
|
242
|
+
--config/-c <path> --root/-r <path> --project <name>
|
|
243
|
+
--update/-u --watch/-w --run
|
|
244
|
+
--reporter <name> --outputFile <path> --coverage
|
|
245
|
+
--globals --environment <env> --pool <type>
|
|
246
|
+
--browser[=name] --browser.headless --no-isolate
|
|
247
|
+
--no-file-parallelism --test-timeout <ms> --bail <n>
|
|
248
|
+
--retry <n> --repeats <n> --shard <i>/<n>
|
|
249
|
+
--merge-reports --changed [ref] --passWithNoTests
|
|
250
|
+
--sequence.shuffle --sequence.seed <n> --sequence.concurrent
|
|
251
|
+
--inspect-brk --logHeapUsage --clearCache
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## ENVIRONMENTS
|
|
255
|
+
|
|
256
|
+
Built-in: `node` (default), `jsdom`, `happy-dom`, `edge-runtime` Per-file:
|
|
257
|
+
`// @vitest-environment <name>` or `/** @vitest-environment <name> */` Custom:
|
|
258
|
+
export `Environment` object with `{name, viteEnvironment, setup()}`
|
|
259
|
+
|
|
260
|
+
## TEST API
|
|
261
|
+
|
|
262
|
+
```ts
|
|
263
|
+
import {
|
|
264
|
+
describe,
|
|
265
|
+
test,
|
|
266
|
+
it,
|
|
267
|
+
expect,
|
|
268
|
+
vi,
|
|
269
|
+
beforeAll,
|
|
270
|
+
beforeEach,
|
|
271
|
+
afterAll,
|
|
272
|
+
afterEach,
|
|
273
|
+
} from 'vitest';
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Suites
|
|
277
|
+
|
|
278
|
+
```ts
|
|
279
|
+
describe(name, fn, timeout?)
|
|
280
|
+
describe.skip/only/todo/skipIf(cond)/runIf(cond)/shuffle/concurrent/sequential/scoped
|
|
281
|
+
describe.each(table)(name, fn, timeout?) // parametrized: %s %d %i %f %j %o %# %%
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Tests
|
|
285
|
+
|
|
286
|
+
```ts
|
|
287
|
+
test(name, fn, timeout?)
|
|
288
|
+
test.skip/only/todo/skipIf(cond)/runIf(cond)/fails/concurrent/sequential/scoped
|
|
289
|
+
test.each(table)(name, fn, timeout?)
|
|
290
|
+
test.for(cases)(name, fn, timeout?) // parallel-safe alternative to .each
|
|
291
|
+
test.extend({fixtures}) // fixture injection
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Hooks
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
beforeAll(fn, timeout?) afterAll(fn, timeout?)
|
|
298
|
+
beforeEach(fn, timeout?) afterEach(fn, timeout?)
|
|
299
|
+
onTestFinished(fn) onTestFailed(fn)
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Test Context
|
|
303
|
+
|
|
304
|
+
```ts
|
|
305
|
+
test('name', (context) => {
|
|
306
|
+
context.task // current test
|
|
307
|
+
context.expect // bound expect (required for concurrent)
|
|
308
|
+
context.skip() // skip dynamically
|
|
309
|
+
await context.annotate(msg, type?, attachment?)
|
|
310
|
+
})
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
## EXPECT API
|
|
314
|
+
|
|
315
|
+
```ts
|
|
316
|
+
expect(value)
|
|
317
|
+
.toBe(expected) // ===
|
|
318
|
+
.toEqual(expected) // deep equal
|
|
319
|
+
.toStrictEqual(expected) // deep + type
|
|
320
|
+
.toBeCloseTo(num, digits?) // float
|
|
321
|
+
.toBeDefined() / .toBeUndefined()
|
|
322
|
+
.toBeNull() / .toBeTruthy() / .toBeFalsy() / .toBeNaN()
|
|
323
|
+
.toBeTypeOf(type) // typeof
|
|
324
|
+
.toBeInstanceOf(Class)
|
|
325
|
+
.toBeGreaterThan(num) / .toBeGreaterThanOrEqual(num)
|
|
326
|
+
.toBeLessThan(num) / .toBeLessThanOrEqual(num)
|
|
327
|
+
.toContain(item) // array/string
|
|
328
|
+
.toContainEqual(item) // deep
|
|
329
|
+
.toHaveLength(n)
|
|
330
|
+
.toHaveProperty(path, value?)
|
|
331
|
+
.toMatch(regex|string)
|
|
332
|
+
.toMatchObject(obj)
|
|
333
|
+
.toMatchSnapshot(name?) / .toMatchInlineSnapshot(snapshot?)
|
|
334
|
+
.toMatchFileSnapshot(path)
|
|
335
|
+
.toThrow(error?) / .toThrowError(msg|regex|class)
|
|
336
|
+
.resolves / .rejects // promise
|
|
337
|
+
.toHaveBeenCalled() / .toHaveBeenCalledTimes(n)
|
|
338
|
+
.toHaveBeenCalledWith(...args) / .toHaveBeenLastCalledWith(...args)
|
|
339
|
+
.toHaveBeenNthCalledWith(n, ...args)
|
|
340
|
+
.toHaveReturned() / .toHaveReturnedTimes(n)
|
|
341
|
+
.toHaveReturnedWith(value) / .toHaveLastReturnedWith(value)
|
|
342
|
+
.toSatisfy(predicate)
|
|
343
|
+
|
|
344
|
+
.not // negate
|
|
345
|
+
expect.soft(value) // continue on fail
|
|
346
|
+
expect.poll(fn, opts?) // retry until pass
|
|
347
|
+
expect.extend({matchers}) // custom matchers
|
|
348
|
+
expect.assertions(n) // count assertions
|
|
349
|
+
expect.hasAssertions() // at least one
|
|
350
|
+
expect.anything() // any non-null
|
|
351
|
+
expect.any(Class) // instanceof
|
|
352
|
+
expect.arrayContaining(arr)
|
|
353
|
+
expect.objectContaining(obj)
|
|
354
|
+
expect.stringContaining(str)
|
|
355
|
+
expect.stringMatching(regex)
|
|
356
|
+
expect.addSnapshotSerializer(serializer)
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
## VI (Mock Utilities)
|
|
360
|
+
|
|
361
|
+
```ts
|
|
362
|
+
import { vi } from 'vitest'
|
|
363
|
+
|
|
364
|
+
// Functions
|
|
365
|
+
vi.fn(impl?) // create mock fn
|
|
366
|
+
vi.spyOn(obj, method, accessType?) // spy; accessType: 'get'|'set'
|
|
367
|
+
vi.isMockFunction(fn)
|
|
368
|
+
|
|
369
|
+
// Mock methods (on mock fn)
|
|
370
|
+
mock.mockImplementation(fn)
|
|
371
|
+
mock.mockImplementationOnce(fn)
|
|
372
|
+
mock.mockReturnValue(value)
|
|
373
|
+
mock.mockReturnValueOnce(value)
|
|
374
|
+
mock.mockResolvedValue(value)
|
|
375
|
+
mock.mockResolvedValueOnce(value)
|
|
376
|
+
mock.mockRejectedValue(error)
|
|
377
|
+
mock.mockRejectedValueOnce(error)
|
|
378
|
+
mock.mockClear() // clear call history
|
|
379
|
+
mock.mockReset() // + reset impl
|
|
380
|
+
mock.mockRestore() // restore original (spyOn only)
|
|
381
|
+
mock.getMockName() / .mockName(name)
|
|
382
|
+
mock.getMockImplementation()
|
|
383
|
+
mock.mock.calls // [[args], ...]
|
|
384
|
+
mock.mock.results // [{type,value}, ...]
|
|
385
|
+
mock.mock.instances // [this, ...]
|
|
386
|
+
mock.mock.contexts // [context, ...]
|
|
387
|
+
mock.mock.lastCall // last args
|
|
388
|
+
|
|
389
|
+
// Modules
|
|
390
|
+
vi.mock(path, factory?) // mock module; hoisted
|
|
391
|
+
vi.mock(import(path), factory?) // better IDE support
|
|
392
|
+
vi.mock(path, { spy: true }) // automock with spies
|
|
393
|
+
vi.doMock(path, factory?) // not hoisted
|
|
394
|
+
vi.unmock(path) / vi.doUnmock(path)
|
|
395
|
+
vi.importActual(path) // get original in factory
|
|
396
|
+
vi.importMock(path) // get mocked
|
|
397
|
+
vi.mocked(obj, deep?) // TS: typed mock
|
|
398
|
+
vi.hoisted(factory) // hoist to top
|
|
399
|
+
|
|
400
|
+
// Timers
|
|
401
|
+
vi.useFakeTimers(opts?) // enable fake timers
|
|
402
|
+
vi.useRealTimers() // restore
|
|
403
|
+
vi.setSystemTime(date) // set Date.now()
|
|
404
|
+
vi.getMockedSystemTime()
|
|
405
|
+
vi.getRealSystemTime()
|
|
406
|
+
vi.runAllTimers() // run all pending
|
|
407
|
+
vi.runOnlyPendingTimers()
|
|
408
|
+
vi.runAllTimersAsync()
|
|
409
|
+
vi.advanceTimersByTime(ms)
|
|
410
|
+
vi.advanceTimersByTimeAsync(ms)
|
|
411
|
+
vi.advanceTimersToNextTimer(steps?)
|
|
412
|
+
vi.advanceTimersToNextTimerAsync(steps?)
|
|
413
|
+
vi.getTimerCount()
|
|
414
|
+
vi.clearAllTimers()
|
|
415
|
+
|
|
416
|
+
// Globals
|
|
417
|
+
vi.stubGlobal(name, value) // set globalThis[name]
|
|
418
|
+
vi.unstubAllGlobals()
|
|
419
|
+
vi.stubEnv(name, value) // set import.meta.env[name]
|
|
420
|
+
vi.unstubAllEnvs()
|
|
421
|
+
|
|
422
|
+
// Utils
|
|
423
|
+
vi.spyOn(console, 'log') // common pattern
|
|
424
|
+
vi.resetAllMocks()
|
|
425
|
+
vi.restoreAllMocks()
|
|
426
|
+
vi.clearAllMocks()
|
|
427
|
+
vi.dynamicImportSettled() // wait for imports
|
|
428
|
+
vi.waitFor(callback, opts?) // poll until truthy
|
|
429
|
+
vi.waitUntil(callback, opts?) // poll until truthy
|
|
430
|
+
vi.setConfig(opts) // runtime config
|
|
431
|
+
vi.resetConfig()
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
## MOCKING PATTERNS
|
|
435
|
+
|
|
436
|
+
### Module Mock
|
|
437
|
+
|
|
438
|
+
```ts
|
|
439
|
+
vi.mock('./mod', () => ({ fn: vi.fn() }));
|
|
440
|
+
vi.mock(import('./mod'), () => ({ fn: vi.fn() })); // better types
|
|
441
|
+
vi.mock('./mod', { spy: true }); // automock
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
### Partial Mock
|
|
445
|
+
|
|
446
|
+
```ts
|
|
447
|
+
vi.mock('./mod', async (importOriginal) => ({
|
|
448
|
+
...(await importOriginal()),
|
|
449
|
+
fn: vi.fn(),
|
|
450
|
+
}));
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
### Spy on Export
|
|
454
|
+
|
|
455
|
+
```ts
|
|
456
|
+
import * as mod from './mod';
|
|
457
|
+
vi.spyOn(mod, 'fn');
|
|
458
|
+
vi.spyOn(mod, 'value', 'get').mockReturnValue('x');
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### Class Mock
|
|
462
|
+
|
|
463
|
+
```ts
|
|
464
|
+
vi.mock('./mod', () => ({
|
|
465
|
+
MyClass: vi.fn(
|
|
466
|
+
class {
|
|
467
|
+
method = vi.fn();
|
|
468
|
+
},
|
|
469
|
+
),
|
|
470
|
+
}));
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
### Timer Mock
|
|
474
|
+
|
|
475
|
+
```ts
|
|
476
|
+
vi.useFakeTimers();
|
|
477
|
+
vi.setSystemTime(new Date('2024-01-01'));
|
|
478
|
+
vi.advanceTimersByTime(1000);
|
|
479
|
+
vi.runAllTimers();
|
|
480
|
+
vi.useRealTimers();
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
### Request Mock (MSW)
|
|
484
|
+
|
|
485
|
+
```ts
|
|
486
|
+
import { setupServer } from 'msw/node';
|
|
487
|
+
const server = setupServer(...handlers);
|
|
488
|
+
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
|
|
489
|
+
afterEach(() => server.resetHandlers());
|
|
490
|
+
afterAll(() => server.close());
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
### File System Mock (memfs)
|
|
494
|
+
|
|
495
|
+
```ts
|
|
496
|
+
vi.mock('fs', async () => (await import('memfs')).fs);
|
|
497
|
+
vi.mock('fs/promises', async () => (await import('memfs')).fs.promises);
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
## BROWSER MODE
|
|
501
|
+
|
|
502
|
+
Runs tests in real browsers via Playwright/WebdriverIO/preview.
|
|
503
|
+
|
|
504
|
+
### Config
|
|
505
|
+
|
|
506
|
+
```ts
|
|
507
|
+
test: {
|
|
508
|
+
browser: {
|
|
509
|
+
enabled: true,
|
|
510
|
+
provider: playwright({ launch: { headless: true } }), // or webdriverio()
|
|
511
|
+
// provider options: preview (limited), playwright (recommended), webdriverio
|
|
512
|
+
instances: [{ browser: 'chromium' }, { browser: 'firefox' }],
|
|
513
|
+
headless: boolean, // default: process.env.CI
|
|
514
|
+
api: number|{port,host}, // default: 63315
|
|
515
|
+
viewport: { width, height },
|
|
516
|
+
screenshotDirectory: string,
|
|
517
|
+
screenshotFailures: boolean,
|
|
518
|
+
locators: { testIdAttribute: string }
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
### Browser API
|
|
524
|
+
|
|
525
|
+
```ts
|
|
526
|
+
import { page, userEvent, expect, server, commands, cdp } from 'vitest/browser'
|
|
527
|
+
|
|
528
|
+
// Locators
|
|
529
|
+
page.getByRole(role, opts?)
|
|
530
|
+
page.getByText(text, opts?)
|
|
531
|
+
page.getByTestId(id)
|
|
532
|
+
page.getByLabelText(text, opts?)
|
|
533
|
+
page.getByPlaceholder(text, opts?)
|
|
534
|
+
page.getByAltText(text, opts?)
|
|
535
|
+
page.getByTitle(text, opts?)
|
|
536
|
+
page.elementLocator(element)
|
|
537
|
+
|
|
538
|
+
// Locator methods
|
|
539
|
+
locator.click(opts?)
|
|
540
|
+
locator.fill(value)
|
|
541
|
+
locator.clear()
|
|
542
|
+
locator.selectOptions(values)
|
|
543
|
+
locator.screenshot(opts?)
|
|
544
|
+
locator.query() / .all() / .elements()
|
|
545
|
+
locator.nth(n) / .first() / .last()
|
|
546
|
+
locator.element()
|
|
547
|
+
|
|
548
|
+
// User Events (real browser events via CDP/WebDriver)
|
|
549
|
+
userEvent.click(el, opts?)
|
|
550
|
+
userEvent.dblClick(el, opts?)
|
|
551
|
+
userEvent.tripleClick(el, opts?)
|
|
552
|
+
userEvent.fill(el, text, opts?) // fast, clears first
|
|
553
|
+
userEvent.type(el, text, opts?) // slow, keyboard syntax
|
|
554
|
+
userEvent.clear(el)
|
|
555
|
+
userEvent.hover(el) / .unhover(el)
|
|
556
|
+
userEvent.keyboard(text) // {Shift}, {Enter}, etc
|
|
557
|
+
userEvent.tab()
|
|
558
|
+
userEvent.dragAndDrop(src, tgt, opts?)
|
|
559
|
+
userEvent.upload(el, files)
|
|
560
|
+
userEvent.copy() / .cut() / .paste()
|
|
561
|
+
|
|
562
|
+
// Page
|
|
563
|
+
page.screenshot(opts?)
|
|
564
|
+
page.extend({commands})
|
|
565
|
+
page.imageSnapshot(locator?, opts?)
|
|
566
|
+
|
|
567
|
+
// Commands
|
|
568
|
+
commands.readFile(path)
|
|
569
|
+
commands.writeFile(path, data)
|
|
570
|
+
commands.removeFile(path)
|
|
571
|
+
|
|
572
|
+
// CDP (Playwright/WebdriverIO chromium only)
|
|
573
|
+
cdp().send(method, params?)
|
|
574
|
+
cdp().on(event, handler)
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
### Browser Limitations
|
|
578
|
+
|
|
579
|
+
- No `alert`/`confirm`/`prompt` (mocked by default)
|
|
580
|
+
- No `vi.spyOn` on imports (use `vi.mock({spy:true})`)
|
|
581
|
+
- Use `userEvent` not `@testing-library/user-event`
|
|
582
|
+
|
|
583
|
+
## PROJECTS
|
|
584
|
+
|
|
585
|
+
```ts
|
|
586
|
+
export default defineConfig({
|
|
587
|
+
test: {
|
|
588
|
+
projects: [
|
|
589
|
+
'packages/*', // glob
|
|
590
|
+
{ test: { name: 'unit' } }, // inline
|
|
591
|
+
'./e2e/vitest.config.ts', // file
|
|
592
|
+
],
|
|
593
|
+
},
|
|
594
|
+
});
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
- Root config = global opts (reporters, coverage)
|
|
598
|
+
- Filter: `--project <name>`
|
|
599
|
+
- Each project can have own: environment, pool, setupFiles, browser config
|
|
600
|
+
|
|
601
|
+
## COVERAGE
|
|
602
|
+
|
|
603
|
+
### Providers
|
|
604
|
+
|
|
605
|
+
- **v8** (default): Native V8 inspector; faster, lower memory; no pre-transpile;
|
|
606
|
+
AST-based remapping in v3.2+
|
|
607
|
+
- **istanbul**: Instrumentation-based; battle-tested; works everywhere; slower
|
|
608
|
+
due to instrumentation
|
|
609
|
+
|
|
610
|
+
### Ignore Comments
|
|
611
|
+
|
|
612
|
+
```ts
|
|
613
|
+
/* v8 ignore next */
|
|
614
|
+
/* v8 ignore next 3 */
|
|
615
|
+
/* v8 ignore start */ ... /* v8 ignore stop */
|
|
616
|
+
/* v8 ignore if */
|
|
617
|
+
/* v8 ignore else */
|
|
618
|
+
/* v8 ignore file */
|
|
619
|
+
// For esbuild (strips comments), add @preserve:
|
|
620
|
+
/* v8 ignore next -- @preserve */
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
## IN-SOURCE TESTING
|
|
624
|
+
|
|
625
|
+
```ts
|
|
626
|
+
// src/utils.ts
|
|
627
|
+
export const add = (a, b) => a + b;
|
|
628
|
+
|
|
629
|
+
if (import.meta.vitest) {
|
|
630
|
+
const { it, expect } = import.meta.vitest;
|
|
631
|
+
it('adds', () => expect(add(1, 2)).toBe(3));
|
|
632
|
+
}
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
Config: `includeSource: ['src/**/*.ts']` Build:
|
|
636
|
+
`define: { 'import.meta.vitest': 'undefined' }` for dead code elimination
|
|
637
|
+
TypeScript: add `vitest/importMeta` to tsconfig types
|
|
638
|
+
|
|
639
|
+
## SNAPSHOTS
|
|
640
|
+
|
|
641
|
+
```ts
|
|
642
|
+
expect(obj).toMatchSnapshot();
|
|
643
|
+
expect(obj).toMatchInlineSnapshot();
|
|
644
|
+
expect(obj).toMatchFileSnapshot('./snap.txt');
|
|
645
|
+
expect.addSnapshotSerializer({ serialize, test });
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
Update: `vitest -u` or press `u` in watch mode
|
|
649
|
+
|
|
650
|
+
## ANNOTATIONS
|
|
651
|
+
|
|
652
|
+
```ts
|
|
653
|
+
test('name', async ({ annotate }) => {
|
|
654
|
+
await annotate('message', 'notice'); // notice|warning|error
|
|
655
|
+
await annotate('msg', 'info', {
|
|
656
|
+
path: './file.txt',
|
|
657
|
+
contentType: 'text/plain',
|
|
658
|
+
});
|
|
659
|
+
});
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
## SHARDING
|
|
663
|
+
|
|
664
|
+
```bash
|
|
665
|
+
vitest --shard=1/3 --reporter=blob
|
|
666
|
+
vitest --shard=2/3 --reporter=blob
|
|
667
|
+
vitest --shard=3/3 --reporter=blob
|
|
668
|
+
vitest --merge-reports --reporter=default --coverage.reporter=text
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
## PERFORMANCE
|
|
672
|
+
|
|
673
|
+
- `--pool=threads` faster than forks (if compatible)
|
|
674
|
+
- `--no-isolate` if no side effects
|
|
675
|
+
- `--no-file-parallelism` reduces startup
|
|
676
|
+
- `test.dir` limits file search
|
|
677
|
+
- `deps.optimizer` for many imports
|
|
678
|
+
- `vmThreads`/`vmForks` fastest (memory leak risk)
|
|
679
|
+
- `experimental.fsModuleCache` for reruns
|
|
680
|
+
|
|
681
|
+
## DEBUGGING
|
|
682
|
+
|
|
683
|
+
```bash
|
|
684
|
+
vitest --inspect-brk --no-file-parallelism
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
VS Code: JavaScript Debug Terminal or launch.json with
|
|
688
|
+
`program: node_modules/vitest/vitest.mjs`
|
|
689
|
+
|
|
690
|
+
## COMMON ERRORS
|
|
691
|
+
|
|
692
|
+
- **Cannot find module**: Check path; use `vite-tsconfig-paths` for baseUrl;
|
|
693
|
+
avoid relative aliases
|
|
694
|
+
- **Failed to terminate worker**: Switch to `pool: 'forks'` (fetch + threads
|
|
695
|
+
issue)
|
|
696
|
+
- **Segfaults**: Native modules not thread-safe; use `pool: 'forks'`
|
|
697
|
+
|
|
698
|
+
## V4 MIGRATION
|
|
699
|
+
|
|
700
|
+
- Coverage: `coverage.all` removed; define `coverage.include` explicitly
|
|
701
|
+
- `exclude` simplified (only node_modules/.git by default)
|
|
702
|
+
- `vi.fn()`/`vi.spyOn` support constructors (use class/function, not arrow)
|
|
703
|
+
- `vi.restoreAllMocks` only restores `vi.spyOn` mocks (not automocks)
|
|
704
|
+
- `workspace` renamed to `projects`
|
|
705
|
+
- Browser provider: object syntax required (`playwright()` not `'playwright'`)
|
|
706
|
+
- `@vitest/browser/context` → `vitest/browser`
|