Initial commit
This commit is contained in:
206
.claude/skills/nuxt-testing/references/unit-helpers.md
Normal file
206
.claude/skills/nuxt-testing/references/unit-helpers.md
Normal file
@@ -0,0 +1,206 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user