@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,571 +0,0 @@
1
- # Component Testing
2
-
3
- Component testing is a testing strategy that focuses on testing individual UI components in isolation. Unlike end-to-end tests that test entire user flows, component tests verify that each component works correctly on its own, making them faster to run and easier to debug.
4
-
5
- Vitest provides comprehensive support for component testing across multiple frameworks including Vue, React, Svelte, Lit, Preact, Qwik, Solid, Marko, and more. This guide covers the specific patterns, tools, and best practices for testing components effectively with Vitest.
6
-
7
- ## Why Component Testing?
8
-
9
- Component testing sits between unit tests and end-to-end tests, offering several advantages:
10
-
11
- - **Faster feedback** - Test individual components without loading entire applications
12
- - **Isolated testing** - Focus on component behavior without external dependencies
13
- - **Better debugging** - Easier to pinpoint issues in specific components
14
- - **Comprehensive coverage** - Test edge cases and error states more easily
15
-
16
- ## Browser Mode for Component Testing
17
-
18
- Component testing in Vitest uses **Browser Mode** to run tests in real browser environments using Playwright, WebdriverIO, or preview mode. This provides the most accurate testing environment as your components run in real browsers with actual DOM implementations, CSS rendering, and browser APIs.
19
-
20
- ### Why Browser Mode?
21
-
22
- Browser Mode is the recommended approach for component testing because it provides the most accurate testing environment. Unlike DOM simulation libraries, Browser Mode catches real-world issues that can affect your users.
23
-
24
- ::: tip
25
- Browser Mode catches issues that DOM simulation libraries might miss, including:
26
- - CSS layout and styling problems
27
- - Real browser API behavior
28
- - Accurate event handling and propagation
29
- - Proper focus management and accessibility features
30
-
31
- :::
32
-
33
- ### Purpose of This Guide
34
-
35
- This guide focuses specifically on **component testing patterns and best practices** using Vitest's capabilities. While many examples use Browser Mode (as it's the recommended approach), the focus here is on component-specific testing strategies rather than browser configuration details.
36
-
37
- For detailed browser setup, configuration options, and advanced browser features, refer to the [Browser Mode documentation](/guide/browser/).
38
-
39
- ## What Makes a Good Component Test
40
-
41
- Good component tests focus on **behavior and user experience** rather than implementation details:
42
-
43
- - **Test the contract** - How components receive inputs (props) and produce outputs (events, renders)
44
- - **Test user interactions** - Clicks, form submissions, keyboard navigation
45
- - **Test edge cases** - Error states, loading states, empty states
46
- - **Avoid testing internals** - State variables, private methods, CSS classes
47
-
48
- ### Component Testing Hierarchy
49
-
50
- ```
51
- 1. Critical User Paths → Always test these
52
- 2. Error Handling → Test failure scenarios
53
- 3. Edge Cases → Empty data, extreme values
54
- 4. Accessibility → Screen readers, keyboard nav
55
- 5. Performance → Large datasets, animations
56
- ```
57
-
58
- ## Component Testing Strategies
59
-
60
- ### Isolation Strategy
61
-
62
- Test components in isolation by mocking dependencies:
63
-
64
- ```tsx
65
- // For API requests, we recommend MSW (Mock Service Worker)
66
- // See: https://vitest.dev/guide/mocking/requests
67
- //
68
- // vi.mock(import('../api/userService'), () => ({
69
- // fetchUser: vi.fn().mockResolvedValue({ name: 'John' })
70
- // }))
71
-
72
- // Mock child components to focus on parent logic
73
- vi.mock(import('../components/UserCard'), () => ({
74
- default: vi.fn(({ user }) => `<div>User: ${user.name}</div>`)
75
- }))
76
-
77
- test('UserProfile handles loading and data states', async () => {
78
- const { getByText } = render(<UserProfile userId="123" />)
79
-
80
- // Test loading state
81
- await expect.element(getByText('Loading...')).toBeInTheDocument()
82
-
83
- // Test for data to load (expect.element auto-retries)
84
- await expect.element(getByText('User: John')).toBeInTheDocument()
85
- })
86
- ```
87
-
88
- ### Integration Strategy
89
-
90
- Test component collaboration and data flow:
91
-
92
- ```tsx
93
- test('ProductList filters and displays products correctly', async () => {
94
- const mockProducts = [
95
- { id: 1, name: 'Laptop', category: 'Electronics', price: 999 },
96
- { id: 2, name: 'Book', category: 'Education', price: 29 }
97
- ]
98
-
99
- const { getByLabelText, getByText } = render(
100
- <ProductList products={mockProducts} />
101
- )
102
-
103
- // Initially shows all products
104
- await expect.element(getByText('Laptop')).toBeInTheDocument()
105
- await expect.element(getByText('Book')).toBeInTheDocument()
106
-
107
- // Filter by category
108
- await userEvent.selectOptions(
109
- getByLabelText(/category/i),
110
- 'Electronics'
111
- )
112
-
113
- // Only electronics should remain
114
- await expect.element(getByText('Laptop')).toBeInTheDocument()
115
- await expect.element(queryByText('Book')).not.toBeInTheDocument()
116
- })
117
- ```
118
-
119
- ## Testing Library Integration
120
-
121
- While Vitest provides official packages for popular frameworks ([`vitest-browser-vue`](https://npmx.dev/package/vitest-browser-vue), [`vitest-browser-react`](https://npmx.dev/package/vitest-browser-react), [`vitest-browser-svelte`](https://npmx.dev/package/vitest-browser-svelte)), you can integrate with [Testing Library](https://testing-library.com/) for frameworks not yet officially supported.
122
-
123
- ### When to Use Testing Library
124
-
125
- - Your framework doesn't have an official Vitest browser package yet
126
- - You're migrating existing tests that use Testing Library
127
- - You prefer Testing Library's API for specific testing scenarios
128
-
129
- ### Integration Pattern
130
-
131
- The key is using `page.elementLocator()` to bridge Testing Library's DOM output with Vitest's browser mode APIs:
132
-
133
- ```jsx
134
- // For Solid.js components
135
- import { render } from '@testing-library/solid'
136
- import { page } from 'vitest/browser'
137
-
138
- test('Solid component handles user interaction', async () => {
139
- // Use Testing Library to render the component
140
- const { baseElement, getByRole } = render(() =>
141
- <Counter initialValue={0} />
142
- )
143
-
144
- // Bridge to Vitest's browser mode for interactions and assertions
145
- const screen = page.elementLocator(baseElement)
146
-
147
- // Use Vitest's page queries for finding elements
148
- const incrementButton = screen.getByRole('button', { name: /increment/i })
149
-
150
- // Use Vitest's assertions and interactions
151
- await expect.element(screen.getByText('Count: 0')).toBeInTheDocument()
152
-
153
- // Trigger user interaction using Vitest's page API
154
- await incrementButton.click()
155
-
156
- await expect.element(screen.getByText('Count: 1')).toBeInTheDocument()
157
- })
158
- ```
159
-
160
- ### Available Testing Library Packages
161
-
162
- Popular Testing Library packages that work well with Vitest:
163
-
164
- - [`@testing-library/solid`](https://github.com/solidjs/solid-testing-library) - For Solid.js
165
- - [`@marko/testing-library`](https://testing-library.com/docs/marko-testing-library/intro) - For Marko
166
- - [`@testing-library/svelte`](https://testing-library.com/docs/svelte-testing-library/intro) - Alternative to [`vitest-browser-svelte`](https://npmx.dev/package/vitest-browser-svelte)
167
- - [`@testing-library/vue`](https://testing-library.com/docs/vue-testing-library/intro) - Alternative to [`vitest-browser-vue`](https://npmx.dev/package/vitest-browser-vue)
168
-
169
- ::: tip Migration Path
170
- If your framework gets official Vitest support later, you can gradually migrate by replacing Testing Library's `render` function while keeping most of your test logic intact.
171
- :::
172
-
173
- ## Best Practices
174
-
175
- ### 1. Use Browser Mode for CI/CD
176
- Ensure tests run in real browser environments for the most accurate testing. Browser Mode provides accurate CSS rendering, real browser APIs, and proper event handling.
177
-
178
- ### 2. Test User Interactions
179
- Simulate real user behavior using Vitest's [Interactivity API](/api/browser/interactivity). Use `page.getByRole()` and `userEvent` methods as shown in our [Advanced Testing Patterns](#advanced-testing-patterns):
180
-
181
- ```tsx
182
- // Good: Test actual user interactions
183
- await page.getByRole('button', { name: /submit/i }).click()
184
- await page.getByLabelText(/email/i).fill('user@example.com')
185
-
186
- // Avoid: Testing implementation details
187
- // component.setState({ email: 'user@example.com' })
188
- ```
189
-
190
- ### 3. Test Accessibility
191
- Ensure components work for all users by testing keyboard navigation, focus management, and ARIA attributes. See our [Testing Accessibility](#testing-accessibility) example for practical patterns:
192
-
193
- ```tsx
194
- // Test keyboard navigation
195
- await userEvent.keyboard('{Tab}')
196
- await expect.element(document.activeElement).toHaveFocus()
197
-
198
- // Test ARIA attributes
199
- await expect.element(modal).toHaveAttribute('aria-modal', 'true')
200
- ```
201
-
202
- ### 4. Mock External Dependencies
203
- Focus tests on component logic by mocking APIs and external services. This makes tests faster and more reliable. See our [Isolation Strategy](#isolation-strategy) for examples:
204
-
205
- ```tsx
206
- // For API requests, we recommend using MSW (Mock Service Worker)
207
- // See: https://vitest.dev/guide/mocking/requests
208
- // This provides more realistic request/response mocking
209
-
210
- // For module mocking, use the import() syntax
211
- vi.mock(import('../components/UserCard'), () => ({
212
- default: vi.fn(() => <div>Mocked UserCard</div>)
213
- }))
214
- ```
215
-
216
- ### 5. Use Meaningful Test Descriptions
217
- Write test descriptions that explain the expected behavior, not implementation details:
218
-
219
- ```tsx
220
- // Good: Describes user-facing behavior
221
- test('shows error message when email format is invalid')
222
- test('disables submit button while form is submitting')
223
-
224
- // Avoid: Implementation-focused descriptions
225
- test('calls validateEmail function')
226
- test('sets isSubmitting state to true')
227
- ```
228
-
229
- ## Advanced Testing Patterns
230
-
231
- ### Testing Component State Management
232
-
233
- ```tsx
234
- // Testing stateful components and state transitions
235
- test('ShoppingCart manages items correctly', async () => {
236
- const { getByText, getByTestId } = render(<ShoppingCart />)
237
-
238
- // Initially empty
239
- await expect.element(getByText('Your cart is empty')).toBeInTheDocument()
240
-
241
- // Add item
242
- await page.getByRole('button', { name: /add laptop/i }).click()
243
-
244
- // Verify state change
245
- await expect.element(getByText('1 item')).toBeInTheDocument()
246
- await expect.element(getByText('Laptop - $999')).toBeInTheDocument()
247
-
248
- // Test quantity updates
249
- await page.getByRole('button', { name: /increase quantity/i }).click()
250
- await expect.element(getByText('2 items')).toBeInTheDocument()
251
- })
252
- ```
253
-
254
- ### Testing Async Components with Data Fetching
255
-
256
- ```tsx
257
- // Option 1: Recommended - Use MSW (Mock Service Worker) for API mocking
258
- import { http, HttpResponse } from 'msw'
259
- import { setupWorker } from 'msw/browser'
260
-
261
- // Set up MSW worker with API handlers
262
- const worker = setupWorker(
263
- http.get('/api/users/:id', ({ params }) => {
264
- // Describe the happy path
265
- return HttpResponse.json({ id: params.id, name: 'John Doe', email: 'john@example.com' })
266
- })
267
- )
268
-
269
- // Start the worker before all tests
270
- beforeAll(() => worker.start())
271
- afterEach(() => worker.resetHandlers())
272
- afterAll(() => worker.stop())
273
-
274
- test('UserProfile handles loading, success, and error states', async () => {
275
- // Test success state
276
- const { getByText } = render(<UserProfile userId="123" />)
277
- // expect.element auto-retries until elements are found
278
- await expect.element(getByText('John Doe')).toBeInTheDocument()
279
- await expect.element(getByText('john@example.com')).toBeInTheDocument()
280
-
281
- // Test error state by overriding the handler for this test
282
- worker.use(
283
- http.get('/api/users/:id', () => {
284
- return HttpResponse.json({ error: 'User not found' }, { status: 404 })
285
- })
286
- )
287
-
288
- const { getByText: getErrorText } = render(<UserProfile userId="999" />)
289
- await expect.element(getErrorText('Error: User not found')).toBeInTheDocument()
290
- })
291
- ```
292
-
293
- ::: tip
294
- See more details on [using MSW in the browser](https://mswjs.io/docs/integrations/browser).
295
- :::
296
-
297
- ### Testing Component Communication
298
-
299
- ```tsx
300
- // Test parent-child component interaction
301
- test('parent and child components communicate correctly', async () => {
302
- const mockOnSelectionChange = vi.fn()
303
-
304
- const { getByText } = render(
305
- <ProductCatalog onSelectionChange={mockOnSelectionChange}>
306
- <ProductFilter />
307
- <ProductGrid />
308
- </ProductCatalog>
309
- )
310
-
311
- // Interact with child component
312
- await page.getByRole('checkbox', { name: /electronics/i }).click()
313
-
314
- // Verify parent receives the communication
315
- expect(mockOnSelectionChange).toHaveBeenCalledWith({
316
- category: 'electronics',
317
- filters: ['electronics']
318
- })
319
-
320
- // Verify other child component updates (expect.element auto-retries)
321
- await expect.element(getByText('Showing Electronics products')).toBeInTheDocument()
322
- })
323
- ```
324
-
325
- ### Testing Complex Forms with Validation
326
-
327
- ```tsx
328
- test('ContactForm handles complex validation scenarios', async () => {
329
- const mockSubmit = vi.fn()
330
- const { getByLabelText, getByText } = render(
331
- <ContactForm onSubmit={mockSubmit} />
332
- )
333
-
334
- const nameInput = page.getByLabelText(/full name/i)
335
- const emailInput = page.getByLabelText(/email/i)
336
- const messageInput = page.getByLabelText(/message/i)
337
- const submitButton = page.getByRole('button', { name: /send message/i })
338
-
339
- // Test validation triggers
340
- await submitButton.click()
341
-
342
- await expect.element(getByText('Name is required')).toBeInTheDocument()
343
- await expect.element(getByText('Email is required')).toBeInTheDocument()
344
- await expect.element(getByText('Message is required')).toBeInTheDocument()
345
-
346
- // Test partial validation
347
- await nameInput.fill('John Doe')
348
- await submitButton.click()
349
-
350
- await expect.element(getByText('Name is required')).not.toBeInTheDocument()
351
- await expect.element(getByText('Email is required')).toBeInTheDocument()
352
-
353
- // Test email format validation
354
- await emailInput.fill('invalid-email')
355
- await submitButton.click()
356
-
357
- await expect.element(getByText('Please enter a valid email')).toBeInTheDocument()
358
-
359
- // Test successful submission
360
- await emailInput.fill('john@example.com')
361
- await messageInput.fill('Hello, this is a test message.')
362
- await submitButton.click()
363
-
364
- expect(mockSubmit).toHaveBeenCalledWith({
365
- name: 'John Doe',
366
- email: 'john@example.com',
367
- message: 'Hello, this is a test message.'
368
- })
369
- })
370
- ```
371
-
372
- ### Testing Error Boundaries
373
-
374
- ```tsx
375
- // Test how components handle and recover from errors
376
- function ThrowError({ shouldThrow }: { shouldThrow: boolean }) {
377
- if (shouldThrow) {
378
- throw new Error('Component error!')
379
- }
380
- return <div>Component working fine</div>
381
- }
382
-
383
- test('ErrorBoundary catches and displays errors gracefully', async () => {
384
- const { getByText, rerender } = render(
385
- <ErrorBoundary fallback={<div>Something went wrong</div>}>
386
- <ThrowError shouldThrow={false} />
387
- </ErrorBoundary>
388
- )
389
-
390
- // Initially working
391
- await expect.element(getByText('Component working fine')).toBeInTheDocument()
392
-
393
- // Trigger error
394
- rerender(
395
- <ErrorBoundary fallback={<div>Something went wrong</div>}>
396
- <ThrowError shouldThrow={true} />
397
- </ErrorBoundary>
398
- )
399
-
400
- // Error boundary should catch it
401
- await expect.element(getByText('Something went wrong')).toBeInTheDocument()
402
- })
403
- ```
404
-
405
- ### Testing Accessibility
406
-
407
- ```tsx
408
- test('Modal component is accessible', async () => {
409
- const { getByRole, getByLabelText } = render(
410
- <Modal isOpen={true} title="Settings">
411
- <SettingsForm />
412
- </Modal>
413
- )
414
-
415
- // Test focus management - modal should receive focus when opened
416
- // This is crucial for screen reader users to know a modal opened
417
- const modal = getByRole('dialog')
418
- await expect.element(modal).toHaveFocus()
419
-
420
- // Test ARIA attributes - these provide semantic information to screen readers
421
- await expect.element(modal).toHaveAttribute('aria-labelledby') // Links to title element
422
- await expect.element(modal).toHaveAttribute('aria-modal', 'true') // Indicates modal behavior
423
-
424
- // Test keyboard navigation - Escape key should close modal
425
- // This is required by ARIA authoring practices
426
- await userEvent.keyboard('{Escape}')
427
- // expect.element auto-retries until modal is removed
428
- await expect.element(modal).not.toBeInTheDocument()
429
-
430
- // Test focus trap - tab navigation should cycle within modal
431
- // This prevents users from tabbing to content behind the modal
432
- const firstInput = getByLabelText(/username/i)
433
- const lastButton = getByRole('button', { name: /save/i })
434
-
435
- // Use click to focus on the first input, then test tab navigation
436
- await firstInput.click()
437
- await userEvent.keyboard('{Shift>}{Tab}{/Shift}') // Shift+Tab goes backwards
438
- await expect.element(lastButton).toHaveFocus() // Should wrap to last element
439
- })
440
- ```
441
-
442
- ## Debugging Component Tests
443
-
444
- ### 1. Use Browser Dev Tools
445
-
446
- Browser Mode runs tests in real browsers, giving you access to full developer tools. When tests fail, you can:
447
-
448
- - **Open browser dev tools** during test execution (F12 or right-click → Inspect)
449
- - **Set breakpoints** in your test code or component code
450
- - **Inspect the DOM** to see the actual rendered output
451
- - **Check console errors** for JavaScript errors or warnings
452
- - **Monitor network requests** to debug API calls
453
-
454
- For headful mode debugging, add `headless: false` to your browser config temporarily.
455
-
456
- ### 2. Add Debug Statements
457
-
458
- Use strategic logging to understand test failures:
459
-
460
- ```tsx
461
- test('debug form validation', async () => {
462
- render(<ContactForm />)
463
-
464
- const submitButton = page.getByRole('button', { name: /submit/i })
465
- await submitButton.click()
466
-
467
- // Debug: Check if element exists with different query
468
- const errorElement = page.getByText('Email is required')
469
- console.log('Error element found:', errorElement.length)
470
-
471
- await expect.element(errorElement).toBeInTheDocument()
472
- })
473
- ```
474
-
475
- ### 3. Inspect Rendered Output
476
-
477
- When components don't render as expected, investigate systematically:
478
-
479
- **Use Vitest's browser UI:**
480
- - Run tests with browser mode enabled
481
- - Open the browser URL shown in the terminal to see tests running
482
- - Visual inspection helps identify CSS issues, layout problems, or missing elements
483
-
484
- **Test element queries:**
485
- ```tsx
486
- // Debug why elements can't be found
487
- const button = page.getByRole('button', { name: /submit/i })
488
- console.log('Button count:', button.length) // Should be 1
489
-
490
- // Try alternative queries if the first one fails
491
- if (button.length === 0) {
492
- console.log('All buttons:', page.getByRole('button').length)
493
- console.log('By test ID:', page.getByTestId('submit-btn').length)
494
- }
495
- ```
496
-
497
- ### 4. Verify Selectors
498
-
499
- Selector issues are common causes of test failures. Debug them systematically:
500
-
501
- **Check accessible names:**
502
- ```tsx
503
- // If getByRole fails, check what roles/names are available
504
- const buttons = page.getByRole('button').all()
505
- for (const button of buttons) {
506
- // Use element() to get the DOM element and access native properties
507
- const element = button.element()
508
- const accessibleName = element.getAttribute('aria-label') || element.textContent
509
- console.log(`Button: "${accessibleName}"`)
510
- }
511
- ```
512
-
513
- **Test different query strategies:**
514
- ```tsx
515
- // Multiple ways to find the same element using .or for auto-retrying
516
- const submitButton = page.getByRole('button', { name: /submit/i }) // By accessible name
517
- .or(page.getByTestId('submit-button')) // By test ID
518
- .or(page.getByText('Submit')) // By exact text
519
- // Note: Vitest doesn't have page.locator(), use specific getBy* methods instead
520
- ```
521
-
522
- **Common selector debugging patterns:**
523
- ```tsx
524
- test('debug element queries', async () => {
525
- render(<LoginForm />)
526
-
527
- // Check if element is visible and enabled
528
- const emailInput = page.getByLabelText(/email/i)
529
- await expect.element(emailInput).toBeVisible() // Will show if element is visible and print DOM if not
530
- })
531
- ```
532
-
533
- ### 5. Debugging Async Issues
534
-
535
- Component tests often involve timing issues:
536
-
537
- ```tsx
538
- test('debug async component behavior', async () => {
539
- render(<AsyncUserProfile userId="123" />)
540
-
541
- // expect.element will automatically retry and show helpful error messages
542
- await expect.element(page.getByText('John Doe')).toBeInTheDocument()
543
- })
544
- ```
545
-
546
- ## Migration from Other Testing Frameworks
547
-
548
- ### From Jest + Testing Library
549
-
550
- Most Jest + Testing Library tests work with minimal changes:
551
-
552
- ```ts
553
- // Before (Jest)
554
- import { render, screen } from '@testing-library/react' // [!code --]
555
-
556
- // After (Vitest)
557
- import { render } from 'vitest-browser-react' // [!code ++]
558
- ```
559
-
560
- ### Key Differences
561
-
562
- - Use `await expect.element()` instead of `expect()` for DOM assertions
563
- - Use `vitest/browser` for user interactions instead of `@testing-library/user-event`
564
- - Browser Mode provides real browser environment for accurate testing
565
-
566
- ## Learn More
567
-
568
- - [Browser Mode Documentation](/guide/browser/)
569
- - [Assertion API](/api/browser/assertions)
570
- - [Interactivity API](/api/browser/interactivity)
571
- - [Example Repository](https://github.com/vitest-tests/browser-examples)