@@ -30,15 +30,60 @@ createEffect(() => {
3030
3131---
3232
33- ## Coming Soon
34-
35- This guide will cover:
36- - Component testing patterns
37- - Testing user interactions
38- - Snapshot testing
39- - Mock strategies
40-
41- ** For now, see:**
42- - ` src/components/ui/Button.test.tsx ` - Example component test
43- - ` src/workspace-config/components/WorkspaceConfigDialog.test.tsx ` - Resource error testing
44- - Run: ` bun run test ` or ` bun run test:watch `
33+ ## Corvu Component Mocks Are Load-Bearing
34+
35+ When a Corvu primitive (Dialog, Popover, Drawer, etc.) is mocked in a test file, the mock's
36+ prop interface becomes part of the test infrastructure. If the real component adds a new event
37+ handler prop — ` onKeyUp ` , ` onFocus ` , ` onPointerDown ` , etc. — and the mock doesn't forward it,
38+ the handler silently disappears. The test won't fail with a clear error; it will just never fire.
39+
40+ ** Symptom:** You add a new event handler to a Corvu component in production code. Tests that
41+ exercise that handler pass zero calls to the mock function, even though the handler works in
42+ the browser.
43+
44+ ** Cause:** The mock ` Dialog.Content ` (or equivalent) only forwards the props it was originally
45+ written to accept. New props are ignored unless explicitly added.
46+
47+ ** Fix:** Keep the mock's prop type in sync with what the component actually uses. When you add
48+ a handler to ` Dialog.Content ` in the component, add the same prop to the mock:
49+
50+ ``` tsx
51+ // In the test file's vi.mock("corvu/dialog", ...) block:
52+ Dialog .Content = (props : {
53+ children: JSX .Element ;
54+ class? : string ;
55+ onKeyDown? : (e : KeyboardEvent ) => void ;
56+ onKeyUp? : (e : KeyboardEvent ) => void ; // ← add when component uses it
57+ }) => (
58+ <div role = " presentation" onKeyDown = { props .onKeyDown } onKeyUp = { props .onKeyUp } >
59+ { props .children }
60+ </div >
61+ );
62+ ```
63+
64+ The mock in ` AgentSearchDialog.test.tsx ` is the canonical reference for this pattern.
65+
66+ ---
67+
68+ ## Test Helper Side Effects
69+
70+ Test files often define small helpers like ` renderDialog() ` that set up shared mutable state
71+ before rendering. If that helper resets state you've already configured, tests silently use the
72+ wrong setup.
73+
74+ ** Symptom:** You set a shared variable (e.g. ` mockModalStack ` ) before calling a render helper,
75+ but the test behaves as if your assignment never happened.
76+
77+ ** Cause:** The render helper resets the variable as a side effect.
78+
79+ ** Fix:** Document the side effects on the helper, and in tests that need non-default state,
80+ set the variable * after* calling the helper:
81+
82+ ``` ts
83+ // renderDialog resets mockModalStack as a side effect — set it after if needed
84+ renderDialog ();
85+ mockModalStack = [{ type: " agent-search" , id: " main" }, { type: " agent" , id: " agent-1" }];
86+ await screen .findByLabelText (" Search agent messages" );
87+ ```
88+
89+ See ` AgentSearchDialog.test.tsx ` for a working example of both patterns.
0 commit comments