useOnboardingChecklist.wiring gains three pins the old stubs could not hold:
one loader for the provider's life (refresh and the shared value keep their
identity, no re-read), 'Skip' moving the next step on the next render, and a
change of mode alone reaching the consumers. UsersSettingsPage now commits
its effects, so an effect that read the preference goes red on the
assertion rather than on 'Invalid hook call'. BudgetTable.wiring,
BudgetPage.wiring, AppShell.slot and OnboardingStepCard drop their local
slot copies; OnboardingStepCard plays StrictMode through replayEffects and
runs its effect only on a changed dependency, which now pins location.key.
Refs #409
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
src/test/hookHarness.ts gives the tests that call hooks and components as
plain functions one fake React with React's semantics: state initialized
once with stable setters, the reducer applied with a dispatch spy, refs kept,
memos and callbacks recomputed only on a changed dependency, effects run by
commit() only when a dependency changed (cleanups first), and every hook it
does not cover throws instead of reaching the real React. Each semantic is
proved by hookHarness.test.ts, which also checks that the module imports
React only as a type.
Refs #409
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>