Initial commit

This commit is contained in:
2026-04-17 23:26:01 +00:00
commit 2ea4ca5d52
409 changed files with 63459 additions and 0 deletions

76
test/CLAUDE.md Normal file
View File

@@ -0,0 +1,76 @@
# 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:
```ts
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`:
```ts
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:**
```ts
const page = await createPage('/login') // ❌ hangs forever
```
**Correct** — call without a path, then navigate manually:
```ts
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.
```ts
// ❌ 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)
```