2.6 KiB
CLAUDE.md — test/
Skill precedence
When writing or modifying tests, load the nuxt-testing skill first:
/nuxt-testing
It takes precedence over other testing skills (vue-testing-best-practices, vitest, etc.) because it covers the exact @nuxt/test-utils setup used here.
Test structure
| Directory | Project | Environment | Purpose |
|---|---|---|---|
test/unit/ |
unit |
node | Pure logic, Zod schemas, utilities |
test/nuxt/ |
nuxt |
nuxt (happy-dom) | Components and composables that need Nuxt runtime |
test/e2e/ |
e2e |
node | Browser tests against the running dev server |
Run a single project: pnpm test --project unit / nuxt / e2e
Known gotchas
Nuxt component tests — mock stores in vi.hoisted, not in it()
Global middleware (e.g. 00.fetchUser.global.ts) runs during mountSuspended before the test body executes. If a mocked store returns undefined at that point, Nuxt throws and the test crashes.
Wrong — mock is set up too late:
const useUserMock = vi.fn()
mockNuxtImport('useUser', () => useUserMock)
it('...', async () => {
useUserMock.mockReturnValue({ isAuthenticated: false, authRefresh: vi.fn() })
// ❌ middleware already ran with undefined
})
Correct — default implementation lives in vi.hoisted:
const { useUserMock } = vi.hoisted(() => ({
useUserMock: vi.fn(() => ({ isAuthenticated: false, user: null, authRefresh: vi.fn() }))
}))
mockNuxtImport('useUser', () => useUserMock)
E2E tests — do not pass a path to createPage() on this SPA
createPage('/some-path') internally calls waitForHydration, which polls
window.useNuxtApp?.().isHydrating === false. Because useNuxtApp is not
exposed on window in SPA mode, this never resolves and the test times out.
Wrong:
const page = await createPage('/login') // ❌ hangs forever
Correct — call without a path, then navigate manually:
const page = await createPage()
await page.goto('http://localhost:3000/login', { waitUntil: 'networkidle' })
E2E tests — use isVisible() + Vitest expect, not Playwright matchers
@playwright/test is not installed (only playwright-core). Playwright's
expect(locator).toBeVisible() is not available.
// ❌ crashes — @playwright/test not installed
import { expect } from '@playwright/test'
await expect(page.locator('input')).toBeVisible()
// ✅ use the async boolean method with Vitest's expect
import { expect } from 'vitest'
expect(await page.locator('input').isVisible()).toBe(true)