@vitest-agent/mcp 1.1.0 → 1.3.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.
Files changed (209) hide show
  1. package/README.md +1 -2
  2. package/index.d.ts +3 -2
  3. package/index.js +1 -1
  4. package/package.json +1 -1
  5. package/server.js +2 -4
  6. package/tools/run-tests.js +17 -3
  7. package/patterns/_meta.json +0 -67
  8. package/patterns/authoring-a-custom-vitest-agent-reporter.md +0 -82
  9. package/patterns/known-issues-and-caveats.md +0 -52
  10. package/patterns/operating-vitest-agent-as-an-agent.md +0 -62
  11. package/patterns/running-tests-via-mcp.md +0 -103
  12. package/patterns/silencing-leaking-output-in-tests.md +0 -91
  13. package/patterns/testing-effect-schema-definitions.md +0 -71
  14. package/patterns/testing-effect-services-with-mock-layers.md +0 -63
  15. package/resources/index.js +0 -166
  16. package/resources/indexes.js +0 -77
  17. package/resources/manifest-schema.js +0 -46
  18. package/resources/paths.js +0 -20
  19. package/resources/patterns.js +0 -22
  20. package/resources/upstream-docs.js +0 -22
  21. package/vendor/vitest-docs/ATTRIBUTION.md +0 -5
  22. package/vendor/vitest-docs/api/advanced/artifacts.md +0 -189
  23. package/vendor/vitest-docs/api/advanced/metadata.md +0 -68
  24. package/vendor/vitest-docs/api/advanced/plugin.md +0 -168
  25. package/vendor/vitest-docs/api/advanced/reporters.md +0 -342
  26. package/vendor/vitest-docs/api/advanced/runner.md +0 -334
  27. package/vendor/vitest-docs/api/advanced/test-case.md +0 -302
  28. package/vendor/vitest-docs/api/advanced/test-collection.md +0 -89
  29. package/vendor/vitest-docs/api/advanced/test-module.md +0 -140
  30. package/vendor/vitest-docs/api/advanced/test-project.md +0 -321
  31. package/vendor/vitest-docs/api/advanced/test-specification.md +0 -96
  32. package/vendor/vitest-docs/api/advanced/test-suite.md +0 -230
  33. package/vendor/vitest-docs/api/advanced/vitest.md +0 -684
  34. package/vendor/vitest-docs/api/assert-type.md +0 -22
  35. package/vendor/vitest-docs/api/assert.md +0 -1960
  36. package/vendor/vitest-docs/api/browser/assertions.md +0 -1277
  37. package/vendor/vitest-docs/api/browser/commands.md +0 -154
  38. package/vendor/vitest-docs/api/browser/context.md +0 -338
  39. package/vendor/vitest-docs/api/browser/interactivity.md +0 -681
  40. package/vendor/vitest-docs/api/browser/locators.md +0 -1171
  41. package/vendor/vitest-docs/api/browser/react.md +0 -346
  42. package/vendor/vitest-docs/api/browser/svelte.md +0 -292
  43. package/vendor/vitest-docs/api/browser/vue.md +0 -222
  44. package/vendor/vitest-docs/api/describe.md +0 -374
  45. package/vendor/vitest-docs/api/expect-typeof.md +0 -571
  46. package/vendor/vitest-docs/api/expect.md +0 -2304
  47. package/vendor/vitest-docs/api/hooks.md +0 -463
  48. package/vendor/vitest-docs/api/mock.md +0 -701
  49. package/vendor/vitest-docs/api/test.md +0 -926
  50. package/vendor/vitest-docs/api/vi.md +0 -1372
  51. package/vendor/vitest-docs/config/alias.md +0 -13
  52. package/vendor/vitest-docs/config/allowonly.md +0 -32
  53. package/vendor/vitest-docs/config/api.md +0 -27
  54. package/vendor/vitest-docs/config/attachmentsdir.md +0 -6
  55. package/vendor/vitest-docs/config/bail.md +0 -9
  56. package/vendor/vitest-docs/config/benchmark.md +0 -65
  57. package/vendor/vitest-docs/config/browser/api.md +0 -23
  58. package/vendor/vitest-docs/config/browser/commands.md +0 -6
  59. package/vendor/vitest-docs/config/browser/connecttimeout.md +0 -10
  60. package/vendor/vitest-docs/config/browser/detailspanelposition.md +0 -38
  61. package/vendor/vitest-docs/config/browser/enabled.md +0 -40
  62. package/vendor/vitest-docs/config/browser/expect.md +0 -250
  63. package/vendor/vitest-docs/config/browser/headless.md +0 -7
  64. package/vendor/vitest-docs/config/browser/instances.md +0 -47
  65. package/vendor/vitest-docs/config/browser/isolate.md +0 -11
  66. package/vendor/vitest-docs/config/browser/locators.md +0 -24
  67. package/vendor/vitest-docs/config/browser/orchestratorscripts.md +0 -39
  68. package/vendor/vitest-docs/config/browser/playwright.md +0 -214
  69. package/vendor/vitest-docs/config/browser/preview.md +0 -32
  70. package/vendor/vitest-docs/config/browser/provider.md +0 -79
  71. package/vendor/vitest-docs/config/browser/screenshotdirectory.md +0 -6
  72. package/vendor/vitest-docs/config/browser/screenshotfailures.md +0 -6
  73. package/vendor/vitest-docs/config/browser/testerhtmlpath.md +0 -5
  74. package/vendor/vitest-docs/config/browser/trace.md +0 -43
  75. package/vendor/vitest-docs/config/browser/trackunhandlederrors.md +0 -10
  76. package/vendor/vitest-docs/config/browser/ui.md +0 -7
  77. package/vendor/vitest-docs/config/browser/viewport.md +0 -6
  78. package/vendor/vitest-docs/config/browser/webdriverio.md +0 -64
  79. package/vendor/vitest-docs/config/cache.md +0 -26
  80. package/vendor/vitest-docs/config/chaiconfig.md +0 -29
  81. package/vendor/vitest-docs/config/clearmocks.md +0 -22
  82. package/vendor/vitest-docs/config/coverage.md +0 -455
  83. package/vendor/vitest-docs/config/css.md +0 -47
  84. package/vendor/vitest-docs/config/dangerouslyignoreunhandlederrors.md +0 -23
  85. package/vendor/vitest-docs/config/deps.md +0 -127
  86. package/vendor/vitest-docs/config/detectasyncleaks.md +0 -39
  87. package/vendor/vitest-docs/config/diff.md +0 -96
  88. package/vendor/vitest-docs/config/dir.md +0 -7
  89. package/vendor/vitest-docs/config/disableconsoleintercept.md +0 -15
  90. package/vendor/vitest-docs/config/env.md +0 -5
  91. package/vendor/vitest-docs/config/environment.md +0 -96
  92. package/vendor/vitest-docs/config/environmentoptions.md +0 -30
  93. package/vendor/vitest-docs/config/exclude.md +0 -49
  94. package/vendor/vitest-docs/config/execargv.md +0 -10
  95. package/vendor/vitest-docs/config/expandsnapshotdiff.md +0 -7
  96. package/vendor/vitest-docs/config/expect.md +0 -38
  97. package/vendor/vitest-docs/config/experimental.md +0 -510
  98. package/vendor/vitest-docs/config/faketimers.md +0 -51
  99. package/vendor/vitest-docs/config/fileparallelism.md +0 -11
  100. package/vendor/vitest-docs/config/forcereruntriggers.md +0 -19
  101. package/vendor/vitest-docs/config/globals.md +0 -42
  102. package/vendor/vitest-docs/config/globalsetup.md +0 -72
  103. package/vendor/vitest-docs/config/hideskippedtests.md +0 -7
  104. package/vendor/vitest-docs/config/hooktimeout.md +0 -7
  105. package/vendor/vitest-docs/config/include-source.md +0 -115
  106. package/vendor/vitest-docs/config/include.md +0 -71
  107. package/vendor/vitest-docs/config/includetasklocation.md +0 -17
  108. package/vendor/vitest-docs/config/index.md +0 -85
  109. package/vendor/vitest-docs/config/isolate.md +0 -13
  110. package/vendor/vitest-docs/config/logheapusage.md +0 -7
  111. package/vendor/vitest-docs/config/maxconcurrency.md +0 -9
  112. package/vendor/vitest-docs/config/maxworkers.md +0 -49
  113. package/vendor/vitest-docs/config/mockreset.md +0 -22
  114. package/vendor/vitest-docs/config/mode.md +0 -7
  115. package/vendor/vitest-docs/config/name.md +0 -111
  116. package/vendor/vitest-docs/config/onconsolelog.md +0 -25
  117. package/vendor/vitest-docs/config/onstacktrace.md +0 -32
  118. package/vendor/vitest-docs/config/onunhandlederror.md +0 -35
  119. package/vendor/vitest-docs/config/open.md +0 -7
  120. package/vendor/vitest-docs/config/outputfile.md +0 -7
  121. package/vendor/vitest-docs/config/passwithnotests.md +0 -7
  122. package/vendor/vitest-docs/config/pool.md +0 -45
  123. package/vendor/vitest-docs/config/printconsoletrace.md +0 -6
  124. package/vendor/vitest-docs/config/projects.md +0 -6
  125. package/vendor/vitest-docs/config/provide.md +0 -45
  126. package/vendor/vitest-docs/config/reporters.md +0 -69
  127. package/vendor/vitest-docs/config/resolvesnapshotpath.md +0 -36
  128. package/vendor/vitest-docs/config/restoremocks.md +0 -22
  129. package/vendor/vitest-docs/config/retry.md +0 -140
  130. package/vendor/vitest-docs/config/root.md +0 -6
  131. package/vendor/vitest-docs/config/runner.md +0 -6
  132. package/vendor/vitest-docs/config/sequence.md +0 -158
  133. package/vendor/vitest-docs/config/server.md +0 -68
  134. package/vendor/vitest-docs/config/setupfiles.md +0 -40
  135. package/vendor/vitest-docs/config/silent.md +0 -9
  136. package/vendor/vitest-docs/config/slowtestthreshold.md +0 -7
  137. package/vendor/vitest-docs/config/snapshotenvironment.md +0 -27
  138. package/vendor/vitest-docs/config/snapshotformat.md +0 -28
  139. package/vendor/vitest-docs/config/snapshotserializers.md +0 -6
  140. package/vendor/vitest-docs/config/stricttags.md +0 -30
  141. package/vendor/vitest-docs/config/tags.md +0 -141
  142. package/vendor/vitest-docs/config/teardowntimeout.md +0 -7
  143. package/vendor/vitest-docs/config/testnamepattern.md +0 -21
  144. package/vendor/vitest-docs/config/testtimeout.md +0 -7
  145. package/vendor/vitest-docs/config/typecheck.md +0 -77
  146. package/vendor/vitest-docs/config/ui.md +0 -15
  147. package/vendor/vitest-docs/config/unstubenvs.md +0 -20
  148. package/vendor/vitest-docs/config/unstubglobals.md +0 -20
  149. package/vendor/vitest-docs/config/update.md +0 -16
  150. package/vendor/vitest-docs/config/vmmemorylimit.md +0 -30
  151. package/vendor/vitest-docs/config/watch.md +0 -11
  152. package/vendor/vitest-docs/config/watchtriggerpatterns.md +0 -29
  153. package/vendor/vitest-docs/guide/advanced/index.md +0 -147
  154. package/vendor/vitest-docs/guide/advanced/pool.md +0 -148
  155. package/vendor/vitest-docs/guide/advanced/reporters.md +0 -93
  156. package/vendor/vitest-docs/guide/advanced/tests.md +0 -125
  157. package/vendor/vitest-docs/guide/browser/aria-snapshots.md +0 -470
  158. package/vendor/vitest-docs/guide/browser/component-testing.md +0 -571
  159. package/vendor/vitest-docs/guide/browser/index.md +0 -630
  160. package/vendor/vitest-docs/guide/browser/multiple-setups.md +0 -121
  161. package/vendor/vitest-docs/guide/browser/trace-view.md +0 -126
  162. package/vendor/vitest-docs/guide/browser/visual-regression-testing.md +0 -734
  163. package/vendor/vitest-docs/guide/cli-generated.md +0 -972
  164. package/vendor/vitest-docs/guide/cli.md +0 -234
  165. package/vendor/vitest-docs/guide/common-errors.md +0 -163
  166. package/vendor/vitest-docs/guide/coverage.md +0 -515
  167. package/vendor/vitest-docs/guide/debugging.md +0 -127
  168. package/vendor/vitest-docs/guide/environment.md +0 -101
  169. package/vendor/vitest-docs/guide/extending-matchers.md +0 -160
  170. package/vendor/vitest-docs/guide/features.md +0 -310
  171. package/vendor/vitest-docs/guide/filtering.md +0 -175
  172. package/vendor/vitest-docs/guide/ide.md +0 -43
  173. package/vendor/vitest-docs/guide/improving-performance.md +0 -245
  174. package/vendor/vitest-docs/guide/in-source.md +0 -159
  175. package/vendor/vitest-docs/guide/index.md +0 -128
  176. package/vendor/vitest-docs/guide/learn/async.md +0 -147
  177. package/vendor/vitest-docs/guide/learn/debugging-tests.md +0 -210
  178. package/vendor/vitest-docs/guide/learn/matchers.md +0 -277
  179. package/vendor/vitest-docs/guide/learn/mock-functions.md +0 -277
  180. package/vendor/vitest-docs/guide/learn/setup-teardown.md +0 -240
  181. package/vendor/vitest-docs/guide/learn/snapshots.md +0 -166
  182. package/vendor/vitest-docs/guide/learn/testing-in-practice.md +0 -430
  183. package/vendor/vitest-docs/guide/learn/writing-tests-with-ai.md +0 -127
  184. package/vendor/vitest-docs/guide/learn/writing-tests.md +0 -231
  185. package/vendor/vitest-docs/guide/lifecycle.md +0 -379
  186. package/vendor/vitest-docs/guide/migration.md +0 -863
  187. package/vendor/vitest-docs/guide/mocking/classes.md +0 -158
  188. package/vendor/vitest-docs/guide/mocking/dates.md +0 -52
  189. package/vendor/vitest-docs/guide/mocking/file-system.md +0 -74
  190. package/vendor/vitest-docs/guide/mocking/functions.md +0 -61
  191. package/vendor/vitest-docs/guide/mocking/globals.md +0 -20
  192. package/vendor/vitest-docs/guide/mocking/modules.md +0 -414
  193. package/vendor/vitest-docs/guide/mocking/requests.md +0 -114
  194. package/vendor/vitest-docs/guide/mocking/timers.md +0 -48
  195. package/vendor/vitest-docs/guide/mocking.md +0 -239
  196. package/vendor/vitest-docs/guide/open-telemetry.md +0 -156
  197. package/vendor/vitest-docs/guide/parallelism.md +0 -82
  198. package/vendor/vitest-docs/guide/profiling-test-performance.md +0 -243
  199. package/vendor/vitest-docs/guide/projects.md +0 -291
  200. package/vendor/vitest-docs/guide/recipes.md +0 -59
  201. package/vendor/vitest-docs/guide/reporters.md +0 -723
  202. package/vendor/vitest-docs/guide/snapshot.md +0 -620
  203. package/vendor/vitest-docs/guide/test-annotations.md +0 -103
  204. package/vendor/vitest-docs/guide/test-context.md +0 -902
  205. package/vendor/vitest-docs/guide/test-tags.md +0 -314
  206. package/vendor/vitest-docs/guide/testing-types.md +0 -149
  207. package/vendor/vitest-docs/guide/ui.md +0 -160
  208. package/vendor/vitest-docs/guide/using-plugins.md +0 -5
  209. package/vendor/vitest-docs/manifest.json +0 -1691
@@ -1,414 +0,0 @@
1
- # Mocking Modules
2
-
3
- ## Defining a Module
4
-
5
- Before mocking a "module", we should define what it is. In Vitest context, the "module" is a file that exports something. Using [plugins](https://vite.dev/guide/api-plugin.html), any file can be turned into a JavaScript module. The "module object" is a namespace object that holds dynamic references to exported identifiers. Simply put, it's an object with exported methods and properties. In this example, `example.js` is a module that exports `answer` and `variable`:
6
-
7
- ```js [example.js]
8
- export function answer() {
9
- // ...
10
- return 42
11
- }
12
-
13
- export const variable = 'example'
14
- ```
15
-
16
- The `exampleObject` here is a module object:
17
-
18
- ```js [example.test.js]
19
- import * as exampleObject from './example.js'
20
- ```
21
-
22
- The `exampleObject` will always exist even if you imported the example using named imports:
23
-
24
- ```js [example.test.js]
25
- import { answer, variable } from './example.js'
26
- ```
27
-
28
- You can only reference `exampleObject` outside the example module itself. For example, in a test.
29
-
30
- ## Mocking a Module
31
-
32
- For the purpose of this guide, let's introduce some definitions.
33
-
34
- - **Mocked module** is a module that was completely replaced with another one.
35
- - **Spied module** is a mocked module, but its exported methods keep the original implementation. They can also be tracked.
36
- - **Mocked export** is a module export, which invocations can be tracked.
37
- - **Spied export** is a mocked export.
38
-
39
- To mock a module completely, you can use the [`vi.mock` API](/api/vi#vi-mock). You can define a new module dynamically by providing a factory that returns a new module as a second argument:
40
-
41
- ```ts
42
- import { vi } from 'vitest'
43
-
44
- // The ./example.js module will be replaced with
45
- // the result of a factory function, and the
46
- // original ./example.js module will never be called
47
- vi.mock(import('./example.js'), () => {
48
- return {
49
- answer() {
50
- // ...
51
- return 42
52
- },
53
- variable: 'mock',
54
- }
55
- })
56
- ```
57
-
58
- ::: tip
59
- Remember that you can call `vi.mock` in a [setup file](/config/setupfiles) to apply the module mock in every test file automatically.
60
- :::
61
-
62
- ::: tip
63
- Note the usage of dynamic import: `import('./example.ts')`. Vitest will strip it before the code is executed, but it allows TypeScript to properly validate the string and type the `importOriginal` method in your IDE or CLI.
64
- :::
65
-
66
- If your code is trying to access a method that was not returned from this factory, Vitest will throw an error with a helpful message. Note that `answer` is not mocked, i.e. it cannot be tracked. To make it trackable, use `vi.fn()` instead:
67
-
68
- ```ts
69
- import { vi } from 'vitest'
70
-
71
- vi.mock(import('./example.js'), () => {
72
- return {
73
- answer: vi.fn(),
74
- variable: 'mock',
75
- }
76
- })
77
- ```
78
-
79
- The factory method accepts an `importOriginal` function that will execute the original module and return its module object:
80
-
81
- ```ts
82
- import { expect, vi } from 'vitest'
83
- import { answer } from './example.js'
84
-
85
- vi.mock(import('./example.js'), async (importOriginal) => {
86
- const originalModule = await importOriginal()
87
- return {
88
- answer: vi.fn(originalModule.answer),
89
- variable: 'mock',
90
- }
91
- })
92
-
93
- expect(answer()).toBe(42)
94
-
95
- expect(answer).toHaveBeenCalled()
96
- expect(answer).toHaveReturned(42)
97
- ```
98
-
99
- ::: warning
100
- Note that `importOriginal` is asynchronous and needs to be awaited.
101
- :::
102
-
103
- In the above example, we provided the original `answer` to the `vi.fn()` call so it can keep calling it while being tracked at the same time.
104
-
105
- If you require the use of `importOriginal`, consider spying on the export directly via another API: `vi.spyOn`. Instead of replacing the whole module, you can spy only on a single exported method. To do that, you need to import the module as a namespace object:
106
-
107
- ```ts
108
- import { expect, vi } from 'vitest'
109
- import * as exampleObject from './example.js'
110
-
111
- const spy = vi.spyOn(exampleObject, 'answer').mockReturnValue(0)
112
-
113
- expect(exampleObject.answer()).toBe(0)
114
- expect(exampleObject.answer).toHaveBeenCalled()
115
- ```
116
-
117
- ::: danger Browser Mode Support
118
- This will not work in the [Browser Mode](/guide/browser/) because it uses the browser's native ESM support to serve modules. The module namespace object is sealed and can't be reconfigured. To bypass this limitation, Vitest supports `{ spy: true }` option in `vi.mock('./example.js')`. This will automatically spy on every export in the module without replacing them with fake ones.
119
-
120
- ```ts
121
- import { vi } from 'vitest'
122
- import * as exampleObject from './example.js'
123
-
124
- vi.mock('./example.js', { spy: true })
125
-
126
- vi.mocked(exampleObject.answer).mockReturnValue(0)
127
- ```
128
- :::
129
-
130
- ::: warning
131
- You only need to import the module as a namespace object in the file where you are using the `vi.spyOn` utility. If the `answer` is called in another file and is imported there as a named export, Vitest will be able to properly track it as long as the function that called it is called after `vi.spyOn`:
132
-
133
- ```ts [source.js]
134
- import { answer } from './example.js'
135
-
136
- export function question() {
137
- if (answer() === 42) {
138
- return 'Ultimate Question of Life, the Universe, and Everything'
139
- }
140
-
141
- return 'Unknown Question'
142
- }
143
- ```
144
- :::
145
-
146
- Note that `vi.spyOn` will only spy on calls that were done after it spied on the method. So, if the function is executed at the top level during an import or it was called before the spying, `vi.spyOn` will not be able to report on it.
147
-
148
- To automatically mock any module before it is imported, you can call `vi.mock` with a path:
149
-
150
- ```ts
151
- import { vi } from 'vitest'
152
-
153
- vi.mock(import('./example.js'))
154
- ```
155
-
156
- If the file `./__mocks__/example.js` exists, then Vitest will load it instead. Otherwise, Vitest will load the original module and replace everything recursively:
157
-
158
- {#automocking-algorithm}
159
-
160
- - All arrays will be empty
161
- - All primitives will stay untouched
162
- - All getters will return `undefined`
163
- - All methods will return `undefined`
164
- - All objects will be deeply cloned
165
- - All instances of classes and their prototypes will be cloned
166
-
167
- To disable this behavior, you can pass down `spy: true` as the second argument:
168
-
169
- ```ts
170
- import { vi } from 'vitest'
171
-
172
- vi.mock(import('./example.js'), { spy: true })
173
- ```
174
-
175
- Instead of returning `undefined`, all methods will call the original implementation, but you can still keep track of these calls:
176
-
177
- ```ts
178
- import { expect, vi } from 'vitest'
179
- import { answer } from './example.js'
180
-
181
- vi.mock(import('./example.js'), { spy: true })
182
-
183
- // calls the original implementation
184
- expect(answer()).toBe(42)
185
- // vitest can still track the invocations
186
- expect(answer).toHaveBeenCalled()
187
- ```
188
-
189
- One nice thing that mocked modules support is sharing the state between the instance and its prototype. Consider this module:
190
-
191
- ```ts [answer.js]
192
- export class Answer {
193
- constructor(value) {
194
- this._value = value
195
- }
196
-
197
- value() {
198
- return this._value
199
- }
200
- }
201
- ```
202
-
203
- By mocking it, we can keep track of every invocation of `.value()` even without having access to the instance itself:
204
-
205
- ```ts [answer.test.js]
206
- import { expect, test, vi } from 'vitest'
207
- import { Answer } from './answer.js'
208
-
209
- vi.mock(import('./answer.js'), { spy: true })
210
-
211
- test('instance inherits the state', () => {
212
- // these invocations could be private inside another function
213
- // that you don't have access to in your test
214
- const answer1 = new Answer(42)
215
- const answer2 = new Answer(0)
216
-
217
- expect(answer1.value()).toBe(42)
218
- expect(answer1.value).toHaveBeenCalled()
219
- // note that different instances have their own states
220
- expect(answer2.value).not.toHaveBeenCalled()
221
-
222
- expect(answer2.value()).toBe(0)
223
-
224
- // but the prototype state accumulates all calls
225
- expect(Answer.prototype.value).toHaveBeenCalledTimes(2)
226
- expect(Answer.prototype.value).toHaveReturned(42)
227
- expect(Answer.prototype.value).toHaveReturned(0)
228
- })
229
- ```
230
-
231
- This can be very useful to track calls to instances that are never exposed.
232
-
233
- ## Mocking Non-existing Module
234
-
235
- Vitest supports mocking virtual modules. These modules don't exist on the file system, but your code imports them. For example, this can happen when your development environment is different from production. One common example is mocking `vscode` APIs in your unit tests.
236
-
237
- By default, Vitest will fail transforming files if it cannot find the source of the import. To bypass this, you need to specify it in your config. You can either always redirect the import to a file, or just signal Vite to ignore it and use the `vi.mock` factory to define its exports.
238
-
239
- To redirect the import, use [`test.alias`](/config/alias) config option:
240
-
241
- ```ts [vitest.config.ts]
242
- import { defineConfig } from 'vitest/config'
243
- import { resolve } from 'node:path'
244
-
245
- export default defineConfig({
246
- test: {
247
- alias: {
248
- vscode: resolve(import.meta.dirname, './mock/vscode.js'),
249
- },
250
- },
251
- })
252
- ```
253
-
254
- To mark the module as always resolved, return the same string from `resolveId` hook of a plugin:
255
-
256
- ```ts [vitest.config.ts]
257
- import { defineConfig } from 'vitest/config'
258
- import { resolve } from 'node:path'
259
-
260
- export default defineConfig({
261
- plugins: [
262
- {
263
- name: 'virtual-vscode',
264
- resolveId(id) {
265
- if (id === 'vscode') {
266
- return 'vscode'
267
- }
268
- }
269
- }
270
- ]
271
- })
272
- ```
273
-
274
- Now you can use `vi.mock` as usual in your tests:
275
-
276
- ```ts
277
- import { vi } from 'vitest'
278
-
279
- vi.mock(import('vscode'), () => {
280
- return {
281
- window: {
282
- createOutputChannel: vi.fn(),
283
- }
284
- }
285
- })
286
- ```
287
-
288
- ## How it Works
289
-
290
- Vitest implements different module mocking mechanisms depending on the environment. The only feature they share is the plugin transformer. When Vitest sees that a file has `vi.mock` inside, it will transform every static import into a dynamic one and move the `vi.mock` call to the top of the file. This allows Vitest to register the mock before the import happens without breaking the ESM rule of hoisted imports.
291
-
292
- ::: code-group
293
- ```ts [example.js]
294
- import { answer } from './answer.js'
295
-
296
- vi.mock(import('./answer.js'))
297
-
298
- console.log(answer)
299
- ```
300
- ```ts [example.transformed.js]
301
- vi.mock('./answer.js')
302
-
303
- const __vitest_module_0__ = await __handle_mock__(
304
- () => import('./answer.js')
305
- )
306
- // to keep the live binding, we have to access
307
- // the export on the module namespace
308
- console.log(__vitest_module_0__.answer())
309
- ```
310
- :::
311
-
312
- The `__handle_mock__` wrapper just makes sure the mock is resolved before the import is initiated, it doesn't modify the module in any way.
313
-
314
- The module mocking plugins are available in the [`@vitest/mocker` package](https://github.com/vitest-dev/vitest/tree/main/packages/mocker).
315
-
316
- ### JSDOM, happy-dom, Node
317
-
318
- When you run your tests in an emulated environment, Vitest creates a [module runner](https://vite.dev/guide/api-environment-runtimes.html#modulerunner) that can consume Vite code. The module runner is designed in such a way that Vitest can hook into the module evaluation and replace it with the mock, if it was registered. This means that Vitest runs your code in an ESM-like environment, but it doesn't use native ESM mechanism directly. This allows the test runner to bend the rules around ES Modules immutability, allowing users to call `vi.spyOn` on a seemingly ES Module.
319
-
320
- If module runner is [disabled](/config/experimental#experimental-vitemodulerunner) and [node loader](/config/experimental#experimental-nodeloader) is not explicitly disabled, Vitest will [register a loader hook](https://nodejs.org/api/module.html#customization-hooks) that transforms original modules into mocked ones. In this mode users cannot call `vi.spyOn` on an ES Module because Vitest uses a native loader mechanism with all its guard rails. In addition to that, Vitest also has to inject a `mock` query into every mocked module which is visible in the stack trace.
321
-
322
- ### Browser Mode
323
-
324
- Vitest uses native ESM in the Browser Mode. This means that we cannot replace the module so easily. Instead, Vitest intercepts the fetch request (via playwright's `page.route` or a Vite plugin API if using `preview` or `webdriverio`) and serves transformed code, if the module was mocked.
325
-
326
- For example, if the module is automocked, Vitest can parse static exports and create a placeholder module:
327
-
328
- ::: code-group
329
- ```ts [answer.js]
330
- export function answer() {
331
- return 42
332
- }
333
- ```
334
- ```ts [answer.transformed.js]
335
- function answer() {
336
- return 42
337
- }
338
-
339
- const __private_module__ = {
340
- [Symbol.toStringTag]: 'Module',
341
- answer: vi.fn(answer),
342
- }
343
-
344
- export const answer = __private_module__.answer
345
- ```
346
- :::
347
-
348
- The example is simplified for brevity, but the concept is unchanged. We can inject a `__private_module__` variable into the module to hold the mocked values. If the user called `vi.mock` with `spy: true`, we pass down the original value; otherwise, we create a simple `vi.fn()` mock.
349
-
350
- If user defined a custom factory, this makes it harder to inject the code, but not impossible. When the mocked file is served, we first resolve the factory in the browser, then pass down the keys back to the server, and use them to create a placeholder module:
351
-
352
- ```ts
353
- const resolvedFactoryKeys = await resolveBrowserFactory(url)
354
- const mockedModule = `
355
- const __private_module__ = getFactoryReturnValue(${url})
356
- ${resolvedFactoryKeys.map(key => `export const ${key} = __private_module__["${key}"]`).join('\n')}
357
- `
358
- ```
359
-
360
- This module can now be served back to the browser. You can inspect the code in the devtools when you run the tests.
361
-
362
- ## Mocking Modules Pitfalls
363
-
364
- Beware that it is not possible to mock calls to methods that are called inside other methods of the same file. For example, in this code:
365
-
366
- ```ts [foobar.js]
367
- export function foo() {
368
- return 'foo'
369
- }
370
-
371
- export function foobar() {
372
- return `${foo()}bar`
373
- }
374
- ```
375
-
376
- It is not possible to mock the `foo` method from the outside because it is referenced directly. So this code will have no effect on the `foo` call inside `foobar` (but it will affect the `foo` call in other modules):
377
-
378
- ```ts [foobar.test.ts]
379
- import { vi } from 'vitest'
380
- import * as mod from './foobar.js'
381
-
382
- // this will only affect "foo" outside of the original module
383
- vi.spyOn(mod, 'foo')
384
- vi.mock(import('./foobar.js'), async (importOriginal) => {
385
- return {
386
- ...await importOriginal(),
387
- // this will only affect "foo" outside of the original module
388
- foo: () => 'mocked'
389
- }
390
- })
391
- ```
392
-
393
- You can confirm this behavior by providing the implementation to the `foobar` method directly:
394
-
395
- ```ts [foobar.test.js]
396
- import * as mod from './foobar.js'
397
-
398
- vi.spyOn(mod, 'foo')
399
-
400
- // exported foo references mocked method
401
- mod.foobar(mod.foo)
402
- ```
403
-
404
- ```ts [foobar.js]
405
- export function foo() {
406
- return 'foo'
407
- }
408
-
409
- export function foobar(injectedFoo) {
410
- return injectedFoo === foo // false
411
- }
412
- ```
413
-
414
- This is the intended behavior, and we do not plan to implement a workaround. Consider refactoring your code into multiple files or use techniques such as [dependency injection](https://en.wikipedia.org/wiki/Dependency_injection). We believe that making the application testable is not the responsibility of the test runner, but of the application architecture.
@@ -1,114 +0,0 @@
1
- # Mocking Requests
2
-
3
- Because Vitest runs in Node, mocking network requests is tricky; web APIs are not available, so we need something that will mimic network behavior for us. We recommend [Mock Service Worker](https://mswjs.io/) to accomplish this. It allows you to mock `http`, `WebSocket` and `GraphQL` network requests, and is framework agnostic.
4
-
5
- Mock Service Worker (MSW) works by intercepting the requests your tests make, allowing you to use it without changing any of your application code. In-browser, this uses the [Service Worker API](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API). In Node.js, and for Vitest, it uses the [`@mswjs/interceptors`](https://github.com/mswjs/interceptors) library. To learn more about MSW, read their [introduction](https://mswjs.io/docs/)
6
-
7
- ## Configuration
8
-
9
- You can use it like below in your [setup file](/config/setupfiles)
10
-
11
- ::: code-group
12
-
13
- ```js [HTTP Setup]
14
- import { afterAll, afterEach, beforeAll } from 'vitest'
15
- import { setupServer } from 'msw/node'
16
- import { http, HttpResponse } from 'msw'
17
-
18
- const posts = [
19
- {
20
- userId: 1,
21
- id: 1,
22
- title: 'first post title',
23
- body: 'first post body',
24
- },
25
- // ...
26
- ]
27
-
28
- export const restHandlers = [
29
- http.get('https://rest-endpoint.example/path/to/posts', () => {
30
- return HttpResponse.json(posts)
31
- }),
32
- ]
33
-
34
- const server = setupServer(...restHandlers)
35
-
36
- // Start server before all tests
37
- beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
38
-
39
- // Close server after all tests
40
- afterAll(() => server.close())
41
-
42
- // Reset handlers after each test for test isolation
43
- afterEach(() => server.resetHandlers())
44
- ```
45
-
46
- ```js [GraphQL Setup]
47
- import { afterAll, afterEach, beforeAll } from 'vitest'
48
- import { setupServer } from 'msw/node'
49
- import { graphql, HttpResponse } from 'msw'
50
-
51
- const posts = [
52
- {
53
- userId: 1,
54
- id: 1,
55
- title: 'first post title',
56
- body: 'first post body',
57
- },
58
- // ...
59
- ]
60
-
61
- const graphqlHandlers = [
62
- graphql.query('ListPosts', () => {
63
- return HttpResponse.json({
64
- data: { posts },
65
- })
66
- }),
67
- ]
68
-
69
- const server = setupServer(...graphqlHandlers)
70
-
71
- // Start server before all tests
72
- beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
73
-
74
- // Close server after all tests
75
- afterAll(() => server.close())
76
-
77
- // Reset handlers after each test for test isolation
78
- afterEach(() => server.resetHandlers())
79
- ```
80
-
81
- ```js [WebSocket Setup]
82
- import { afterAll, afterEach, beforeAll } from 'vitest'
83
- import { setupServer } from 'msw/node'
84
- import { ws } from 'msw'
85
-
86
- const chat = ws.link('wss://chat.example.com')
87
-
88
- const wsHandlers = [
89
- chat.addEventListener('connection', ({ client }) => {
90
- client.addEventListener('message', (event) => {
91
- console.log('Received message from client:', event.data)
92
- // Echo the received message back to the client
93
- client.send(`Server received: ${event.data}`)
94
- })
95
- }),
96
- ]
97
-
98
- const server = setupServer(...wsHandlers)
99
-
100
- // Start server before all tests
101
- beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
102
-
103
- // Close server after all tests
104
- afterAll(() => server.close())
105
-
106
- // Reset handlers after each test for test isolation
107
- afterEach(() => server.resetHandlers())
108
- ```
109
- :::
110
-
111
- > Configuring the server with `onUnhandledRequest: 'error'` ensures that an error is thrown whenever there is a request that does not have a corresponding request handler.
112
-
113
- ## More
114
- There is much more to MSW. You can access cookies and query parameters, define mock error responses, and much more! To see all you can do with MSW, read [their documentation](https://mswjs.io/docs).
@@ -1,48 +0,0 @@
1
- # Timers
2
-
3
- When we test code that involves timeouts or intervals, instead of having our tests wait it out or timeout, we can speed up our tests by using "fake" timers that mock calls to `setTimeout` and `setInterval`.
4
-
5
- See the [`vi.useFakeTimers` API section](/api/vi#vi-usefaketimers) for a more in depth detailed API description.
6
-
7
- ## Example
8
-
9
- ```js
10
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
11
-
12
- function executeAfterTwoHours(func) {
13
- setTimeout(func, 1000 * 60 * 60 * 2) // 2 hours
14
- }
15
-
16
- function executeEveryMinute(func) {
17
- setInterval(func, 1000 * 60) // 1 minute
18
- }
19
-
20
- const mock = vi.fn(() => console.log('executed'))
21
-
22
- describe('delayed execution', () => {
23
- beforeEach(() => {
24
- vi.useFakeTimers()
25
- })
26
- afterEach(() => {
27
- vi.clearAllMocks()
28
- })
29
- it('should execute the function', () => {
30
- executeAfterTwoHours(mock)
31
- vi.runAllTimers()
32
- expect(mock).toHaveBeenCalledTimes(1)
33
- })
34
- it('should not execute the function', () => {
35
- executeAfterTwoHours(mock)
36
- // advancing by 2ms won't trigger the func
37
- vi.advanceTimersByTime(2)
38
- expect(mock).not.toHaveBeenCalled()
39
- })
40
- it('should execute every minute', () => {
41
- executeEveryMinute(mock)
42
- vi.advanceTimersToNextTimer()
43
- expect(mock).toHaveBeenCalledTimes(1)
44
- vi.advanceTimersToNextTimer()
45
- expect(mock).toHaveBeenCalledTimes(2)
46
- })
47
- })
48
- ```