Skip to content

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

Merged
Jagadeeshftw merged 1 commit into
AnchorNet-Org:mainfrom
AnnieIj:fix/metricsbar-useasync-mock
Aug 29, 2026
Merged

fix(test): type MetricsBar's useAsync mock against the real hook shape (Closes #429)#437
Jagadeeshftw merged 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>
@Jagadeeshftw
Jagadeeshftw merged commit ea7c057 into AnchorNet-Org:main Aug 29, 2026
1 check passed
Jagadeeshftw added a commit that referenced this pull request Aug 29, 2026
* Fix CI typecheck blindspot

Closes #425

* test: use semantic settlement table queries (#439)

Co-authored-by: Jagadeeshftw <92681651+Jagadeeshftw@users.noreply.github.com>

* feat(a11y): add jest-axe and jsx-a11y with baseline for SettlementTable and MetricsBar (#438)

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

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>

* fix(api): enforce idempotent retries and classified failure handling (#436)

* fix(api): enforce bounded idempotent retries

Retry only explicitly idempotent operations for transient failures, preserve abort propagation through response consumption, and expose deterministic attempt and elapsed-time bounds. Cover the status allowlist, jittered backoff, timeout handling, abort races, and non-idempotent exclusions with fake-timer tests.

* fix(ui): integrate API error taxonomy

Route classified API failures through the existing reporter and toast infrastructure, suppress deliberate aborts, and preserve actionable inline states. Document the pre-change audit, defects, retry rationale, elapsed ceiling, coverage, and baseline constraints.

* test: add tests for lib/wallet.ts (#435)

Closes #<n>.

### Coverage Inventory
* **wallet.ts exports**: `saveAccount`, `loadAccount`, `clearAccount`, `truncateAddress`, `mockAddress`, `STORAGE_KEY`.
* **useWallet.test.ts**: Covers *none* of the above. It only tests the `useWallet` hook to ensure it throws when used outside a `WalletProvider`.

### The Defect (Mocking Strategy & Incorrect Assumptions)
The issue description assumed that `wallet.ts` implements a real wallet integration with error paths like "Provider absent", "User rejection", and "Chain mismatch". However, as documented in `wallet.ts`, this module is purely a mock / stand-in that stores a deterministic fake address in `localStorage`.

Since the module does not integrate with any real wallet provider (like Freighter), these assumed error paths and listeners **do not exist** in `wallet.ts`. I have reported these "untested paths" as `.todo()` in the test suite to formally acknowledge them as defects (i.e. the promised feature doesn't exist).

I have written tests for the actual exposed methods, verifying:
- Successful saving, loading, and clearing of accounts from `localStorage`
- The `loadAccount` error paths (invalid JSON, missing address, regex validation failure)
- Address truncation formatting
- Deterministic seed generation in `mockAddress`

---------

Co-authored-by: daveedAJ <davidadegoke055@gmail.com>
Co-authored-by: Jagadeeshftw <92681651+Jagadeeshftw@users.noreply.github.com>
Co-authored-by: Opulence Chuks <162402876+Opulencechuks@users.noreply.github.com>
Co-authored-by: Annie <168873935+AnnieIj@users.noreply.github.com>
Co-authored-by: Codebuff <noreply@codebuff.com>
Co-authored-by: Luis Carlos Fuentes De Avila <125478683+Flames4fun@users.noreply.github.com>
Co-authored-by: ugoocreates-pixel <ugoocreates@gmail.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

2 participants