207 lines
4.9 KiB
Markdown
207 lines
4.9 KiB
Markdown
# Test Helpers
|
|
|
|
All helpers are imported from `@nuxt/test-utils/runtime`.
|
|
|
|
## `mountSuspended`
|
|
|
|
Mounts any Vue component within the Nuxt environment, allowing async setup and access to plugin injections. Wraps `@vue/test-utils` `mount` under the hood.
|
|
|
|
```ts
|
|
import { mountSuspended } from '@nuxt/test-utils/runtime'
|
|
import { SomeComponent } from '#components'
|
|
|
|
it('can mount some component', async () => {
|
|
const component = await mountSuspended(SomeComponent)
|
|
expect(component.text()).toMatchInlineSnapshot('"This is an auto-imported component"')
|
|
})
|
|
```
|
|
|
|
Mount with a route:
|
|
|
|
```ts
|
|
import { mountSuspended } from '@nuxt/test-utils/runtime'
|
|
import App from '~/app.vue'
|
|
|
|
it('can mount an app', async () => {
|
|
const component = await mountSuspended(App, { route: '/test' })
|
|
expect(component.html()).toMatchInlineSnapshot(`
|
|
"<div>This is an auto-imported component</div>
|
|
<div> I am a global component </div>
|
|
<div>/</div>
|
|
<a href="/test"> Test link </a>"
|
|
`)
|
|
})
|
|
```
|
|
|
|
**Options:** Accepts all `@vue/test-utils` mount options plus:
|
|
- `route`: initial route string, or `false` to skip initial route change (default: `/`)
|
|
|
|
## `renderSuspended`
|
|
|
|
Renders a component using `@testing-library/vue` within the Nuxt environment. Requires `@testing-library/vue` as a dependency.
|
|
|
|
```ts
|
|
import { renderSuspended } from '@nuxt/test-utils/runtime'
|
|
import { SomeComponent } from '#components'
|
|
import { screen } from '@testing-library/vue'
|
|
|
|
it('can render some component', async () => {
|
|
await renderSuspended(SomeComponent)
|
|
expect(screen.getByText('This is an auto-imported component')).toBeDefined()
|
|
})
|
|
```
|
|
|
|
The component is rendered inside `<div id="test-wrapper"></div>`.
|
|
|
|
**Options:** Accepts all `@testing-library/vue` render options plus:
|
|
- `route`: initial route string, or `false` to skip initial route change (default: `/`)
|
|
|
|
## `mockNuxtImport`
|
|
|
|
Mocks Nuxt auto-imported functions. This is a macro that transforms to `vi.mock` (hoisted).
|
|
|
|
**Can only be used once per mocked import per test file.**
|
|
|
|
```ts
|
|
import { mockNuxtImport } from '@nuxt/test-utils/runtime'
|
|
|
|
mockNuxtImport('useState', () => {
|
|
return () => {
|
|
return { value: 'mocked storage' }
|
|
}
|
|
})
|
|
```
|
|
|
|
### With type safety and original implementation
|
|
|
|
```ts
|
|
import { mockNuxtImport } from '@nuxt/test-utils/runtime'
|
|
|
|
mockNuxtImport<typeof useState>('useState', (original) => {
|
|
return (...args) => {
|
|
return { ...original('some-key'), value: 'mocked state' }
|
|
}
|
|
})
|
|
|
|
// Or pass the function directly
|
|
mockNuxtImport(useState, (original) => {
|
|
return (...args) => {
|
|
return { ...original('some-key'), value: 'mocked state' }
|
|
}
|
|
})
|
|
```
|
|
|
|
### Different implementations per test
|
|
|
|
Use `vi.hoisted` to create mutable mocks:
|
|
|
|
```ts
|
|
import { vi } from 'vitest'
|
|
import { mockNuxtImport } from '@nuxt/test-utils/runtime'
|
|
|
|
const { useStateMock } = vi.hoisted(() => {
|
|
return {
|
|
useStateMock: vi.fn(() => {
|
|
return { value: 'mocked storage' }
|
|
}),
|
|
}
|
|
})
|
|
|
|
mockNuxtImport('useState', () => {
|
|
return useStateMock
|
|
})
|
|
|
|
// In a test:
|
|
useStateMock.mockImplementation(() => {
|
|
return { value: 'something else' }
|
|
})
|
|
```
|
|
|
|
### Alternative: per-test mocking with vi.fn
|
|
|
|
```ts
|
|
import { beforeEach, vi } from 'vitest'
|
|
import { mockNuxtImport } from '@nuxt/test-utils/runtime'
|
|
|
|
mockNuxtImport(useRoute, original => vi.fn(original))
|
|
|
|
beforeEach(() => {
|
|
vi.resetAllMocks()
|
|
})
|
|
|
|
// In a test:
|
|
const useRouteOriginal = vi.mocked(useRoute).getMockImplementation()!
|
|
vi.mocked(useRoute).mockImplementation(
|
|
(...args) => ({ ...useRouteOriginal(...args), path: '/mocked' }),
|
|
)
|
|
```
|
|
|
|
## `mockComponent`
|
|
|
|
Mocks a Nuxt component by PascalCase name or relative path.
|
|
|
|
```ts
|
|
import { mockComponent } from '@nuxt/test-utils/runtime'
|
|
|
|
// By component name
|
|
mockComponent('MyComponent', {
|
|
props: {
|
|
value: String,
|
|
},
|
|
setup(props) {
|
|
// ...
|
|
},
|
|
})
|
|
|
|
// By path with factory function
|
|
mockComponent('~/components/my-component.vue', () => {
|
|
return defineComponent({
|
|
setup(props) {
|
|
// ...
|
|
},
|
|
})
|
|
})
|
|
|
|
// Redirect to a mock SFC
|
|
mockComponent('MyComponent', () => import('./MockComponent.vue'))
|
|
```
|
|
|
|
**Note:** Cannot reference local variables in the factory function (hoisted). Import dependencies inside the factory:
|
|
|
|
```ts
|
|
mockComponent('MyComponent', async () => {
|
|
const { ref, h } = await import('vue')
|
|
|
|
return defineComponent({
|
|
setup(props) {
|
|
const counter = ref(0)
|
|
return () => h('div', null, counter.value)
|
|
},
|
|
})
|
|
})
|
|
```
|
|
|
|
## `registerEndpoint`
|
|
|
|
Creates a mock Nitro endpoint that returns test data.
|
|
|
|
```ts
|
|
import { registerEndpoint } from '@nuxt/test-utils/runtime'
|
|
|
|
// Simple GET endpoint
|
|
registerEndpoint('/test/', () => ({
|
|
test: 'test-field',
|
|
}))
|
|
|
|
// With specific HTTP method
|
|
registerEndpoint('/test/', {
|
|
method: 'POST',
|
|
handler: () => ({ test: 'test-field' }),
|
|
})
|
|
```
|
|
|
|
Options object properties:
|
|
- `handler`: event handler function
|
|
- `method`: (optional) HTTP method to match (e.g., 'GET', 'POST')
|
|
- `once`: (optional) if true, handler is removed after first matching request
|