From 24e755a097a2cfbc2dcc98ce3c0247dbb8f7c8ed Mon Sep 17 00:00:00 2001 From: Pouzor Date: Fri, 10 Jul 2026 03:04:47 +0200 Subject: [PATCH] docs: add frontend test infra README (factories, mocks, split conventions) ha-relevant: yes --- frontend/src/test/README.md | 59 +++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 frontend/src/test/README.md diff --git a/frontend/src/test/README.md b/frontend/src/test/README.md new file mode 100644 index 0000000..10c4461 --- /dev/null +++ b/frontend/src/test/README.md @@ -0,0 +1,59 @@ +# Frontend test infrastructure + +Shared helpers so tests don't re-roll the same boilerplate. Reuse these instead +of redefining a local `makeNode`, sonner mock, or provider wrapper per file. + +## `factories.ts` — fixture builders + +```ts +import { makeNode, makeEdge, makeNodeData, makeDesign } from '@/test/factories' + +makeNode('n1', { type: 'router', ip: '10.0.0.1' }) // React Flow node +makeNode({ data: makeNodeData({ label: 'X' }) }) // partial-node form +makeEdge('e1', 'n1', 'n2', { type: 'wifi' }) // React Flow edge +makeDesign({ name: 'Home' }) // Design row +``` + +Prefer these over an inline `const makeNode = …`. They track the domain types in +`@/types`, so a type change surfaces in one place. + +## `mocks/` — reusable mock builders + +Consume from an **async** `vi.mock` factory via dynamic import. `vi.mock` +factories are hoisted above the file's imports, so a plain top-level +`import { mockSonner }` referenced inside the factory throws "cannot access +before initialization". The dynamic `import()` resolves lazily and sidesteps it: + +```ts +vi.mock('sonner', async () => (await import('@/test/mocks')).mockSonner()) +vi.mock('@xyflow/react', async () => (await import('@/test/mocks')).mockReactFlow()) + +import { toast } from 'sonner' +// …assert vi.mocked(toast.success) etc. +``` + +- `mockSonner()` — full `toast` stub (success/error/info/warning/…). +- `mockReactFlow(extra?)` — the `@xyflow/react` exports most node/edge tests + need; pass `extra` to add or override an export. +- `makeUseCanvasStore(state)` — a `useCanvasStore` replacement for component + tests that read a selected slice. + +## `render.tsx` — provider-wrapped render + +```ts +import { renderWithProviders, screen } from '@/test/render' +renderWithProviders() // wraps TooltipProvider + ReactFlowProvider +``` + +Use the plain `render` from `@testing-library/react` for presentational +components that need no context. + +## Conventions + +- **Store tests are split by concern** under `stores/__tests__/canvasStore/` + (nodes, containers, sizing, edges, selection, grouping, history, clipboard, + customStyle, floorMap). Add new store tests to the matching file; don't grow a + monolith. +- When a component test full-mocks a store (`vi.mock('@/stores/canvasStore')`), + still assert the **state-driven UI branches** (disabled buttons, indicators) — + don't let the mock hide that wiring.