Skip to content

fix(test): type MetricsBar's useAsync mock against the real hook shape (Closes #429) - #437

Open
AnnieIj wants to merge 1 commit into
AnchorNet-Org:mainfrom
AnnieIj:fix/metricsbar-useasync-mock
Open

fix(test): type MetricsBar's useAsync mock against the real hook shape (Closes #429)#437
AnnieIj wants to merge 1 commit into
AnchorNet-Org:mainfrom
AnnieIj:fix/metricsbar-useasync-mock

Conversation

@AnnieIj

@AnnieIj AnnieIj commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes #429 by making MetricsBar.test.tsx mock useAsync against the hook's real return type instead of a fabricated { state, refresh } shape.

The four errors before (and the repo-wide count)

npx tsc --noEmit reported 9 error TS lines on main:

  • src/components/MetricsBar.test.tsx(21,41), (34,41), (47,41), (64,41)TS2345: ... is missing the following properties from type ...: reload, mutate
  • src/components/SettlementTable.test.tsx(72,19), (269,21), (270,21), (271,21), (272,21) — out of scope per the issue

After this PR: 5 errors (repo-wide count drops by exactly 4), and grep MetricsBar on the tsc output is empty. The remaining 5 are the out-of-scope SettlementTable.test.tsx errors.

Which hook members MetricsBar actually uses

Only state and refresh. src/components/MetricsBar.tsx destructures exactly those two (const { state, refresh } = useAsync(load)). The manual "Refresh" button calls refresh(), and the auto-refresh interval drives refresh via useInterval.

Mock-factory decision

Added an in-file mockUseAsync(overrides) factory whose return type is ReturnType<typeof useAsync> — i.e. the full four-member contract (state, reload, refresh, mutate) — with no-op defaults and per-test overrides:

  • A future change to the hook (adding/removing/renaming a member) breaks the factory and every call site at compile time — exactly the acceptance criterion.
  • No as any, @ts-expect-error, or Partial<> cast on the mock was used. The Partial<UseAsyncResult> is only the override input to the factory; the factory always returns the complete, fully-typed result.
  • Kept local to the test file because no other suite mocks useAsync; if that changes, it should be promoted to a shared test util.

Behavioural gap

None found. reload/mutate are legitimately unused by MetricsBar: a manual reload must stay silent (existing data stays visible, per the test suite's contract), which is exactly refresh's job — reload() would flash the loading skeleton, and mutate is for optimistic local updates this component doesn't do. The mock now includes them as no-ops so the component is tested against the contract it actually receives.

Assertion changes

None. Two mock-honesty cleanups only (no assertion semantics changed):

  • Renamed the misnamed mockReload local to mockRefresh (it was always passed as refresh).
  • Added pendingSettlements to the ready-state mock data so it matches the real Metrics shape the component consumes.

Notes

  • The fork's main was ~a month behind the org repo, so the branch was rebased onto the org's current main (feb9b67) before fixing; the diff contains only MetricsBar.test.tsx.
  • CI still has no explicit tsc --noEmit step (the add a typecheck #418 "add a typecheck" change was reverted to unblock merge); this drift was invisible for that reason. This PR fixes the drift itself; a CI typecheck gate remains the separate tracked issue.
  • useAsync's own tests are a separate issue; the factory here pins the four-member contract (state, reload, refresh, mutate) those tests should assert.

Checklist

  • I added a CHANGELOG.md entry under the next ## [x.y.z] section
    (see the Format note at the top of CHANGELOG.md), or this PR
    is docs-only / test-only / internal tooling and doesn't change
    user-facing behavior. — test-only, no entry needed per the changelog's own note.
  • Tests added/updated for the change.

Closes #429

Closes AnchorNet-Org#429)

MetricsBar.test.tsx mocked useAsync with only { state, refresh }, omitting
reload and mutate, so tsc reported TS2345 at all four call sites and the
component was verified against a contract the real hook never returns.

Replace the hand-written mocks with a typed mockUseAsync factory whose
return type is ReturnType<typeof useAsync>; a future change to the hook's
shape now breaks compilation instead of silently testing a fabricated
interface. No as any, @ts-expect-error or Partial cast used.

MetricsBar itself only consumes state and refresh (reload/mutate are
intentionally unused: the manual refresh must stay silent, which is
refresh's contract), so no behavioural gap was found. Repo-wide tsc error
count drops from 9 to 5; the remaining 5 are the out-of-scope
SettlementTable.test.tsx errors.

Generated with Codebuff 🤖
Co-Authored-By: Codebuff <noreply@codebuff.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant