Skip to content

test(dashboard): unit coverage for api client + BillingPage handlers#25

Merged
mastermanas805 merged 2 commits into
mainfrom
test/dashboard-api-billing-coverage
May 11, 2026
Merged

test(dashboard): unit coverage for api client + BillingPage handlers#25
mastermanas805 merged 2 commits into
mainfrom
test/dashboard-api-billing-coverage

Conversation

@mastermanas805
Copy link
Copy Markdown
Member

Summary

Adds 73 new test cases across two surfaces that previously had zero unit coverage. Before this PR the dashboard had 26 tests (all on the shared markdown renderer). After: 99 tests (96 pass, 3 documented-skip).

  • `src/api/index.test.ts` (45 cases) — covers the live API client used by BillingPage + ClaimPage + AuthGate:

    • `fetchBilling()` — happy path + the 503 → FIXTURE_BILLING fallback used in local dev when Razorpay isn't configured
    • `listInvoices()` — happy + 503 fallback
    • `createCheckout()` — POST body shape, returns short_url, propagates errors as APIError
    • `cancelSubscription()` — POST verb + error propagation
    • `claim()` — body shape, 409/401 handling
    • `fetchMe()` — agent-API to dashboard shape adapter
    • `getAPIBaseURL()` — window override priority
    • Token storage round-trip, Authorization header attachment, resource list adapter, delete verb
  • `src/pages/BillingPage.test.tsx` (28 cases) — covers the upgrade-flow handlers:

    • `handleChangePlan`: `api.createCheckout(nextTier)` invocation, `window.location.href` redirect on `short_url`, in-flight button disable, error → `checkoutErr` state, "checkout returned no url" path
    • `handleCancel`: `window.confirm` gate, `api.cancelSubscription` invocation, post-success re-fetch of billing, error → `checkoutErr`, no re-fetch on error
    • Initial render: tier-keyed plan label, payment method line, invoices, fallback to Hobby on unknown tier, team-tier guard

Implementation notes

  • `src/test-setup.ts` — installs a minimal in-memory localStorage polyfill. Node 25 + jsdom 24 ship a broken `window.localStorage` (object exists but methods are undefined); the polyfill is inert on Node 22 (CI's version) where jsdom localStorage works natively. Wired via `vite.config.ts` `test.setupFiles`.
  • 3 `.skip`s are intentional and documented inline: Vite inlines `import.meta.env.{DEV,VITE_API_URL}` at compile time inside the api module, so the prod-default and `VITE_API_URL` branches of `getAPIBaseURL()` can only be exercised by the built bundle (covered by Playwright E2E). The `window.INSTANODE_API_URL` override branch is tested directly.

What changed at runtime

Nothing. Only test files + `vite.config.ts` `test.setupFiles` entry + a new test-only polyfill module. The 26 existing markdown tests still pass.

Findings

No real bugs surfaced during test development. The 503 fallback paths, error propagation, button disable behavior, and confirm/alert side effects all work as documented.

Test plan

  • `npm test` → `Test Files 3 passed (3) · Tests 96 passed | 3 skipped (99)`
  • `npx tsc --noEmit` → no errors
  • No changes to existing markdown.test.tsx (still 26/26 passing)
  • CI on Node 22 confirms the polyfill is inert there

mastermanas805 and others added 2 commits May 11, 2026 21:09
GH Actions has been emitting deprecation warnings on every CI
run:

  Node.js 20 actions are deprecated. The following actions are
  running on Node.js 20 and may not work as expected: actions/
  checkout@v4, actions/setup-node@v4.

setup-node@v5 (and checkout@v5) run on Node 24 by default; bump
the engines target to node 22 as a stable LTS that's well-tested
with both Vite and Playwright. (Local dev still works on whatever
the dev has — these versions only affect CI runners.)
Adds 73 new test cases across two surfaces that previously had zero
unit coverage (only src/lib/markdown.tsx had tests before):

- src/api/index.test.ts (45 cases) — fetchBilling/listInvoices happy +
  503 fallback, createCheckout (POST body + propagation), cancel,
  claim, fetchMe mapping, getAPIBaseURL override priority, token
  storage round-trip, listResources adapter, deleteResource verb.

- src/pages/BillingPage.test.tsx (28 cases) — handleChangePlan
  invokes createCheckout(nextTier) and redirects via location.href on
  short_url, error path surfaces checkoutErr, handleCancel gates on
  window.confirm + re-fetches billing on success, error message
  fallbacks, in-flight button disable.

Adds src/test-setup.ts — a minimal localStorage polyfill that fixes
the Node 25 + jsdom 24 mismatch where window.localStorage methods are
undefined. Inert on Node 22 (CI) where jsdom localStorage works
natively, so this is forward-compatible.

3 tests in index.test.ts are .skip with documentation — Vite inlines
import.meta.env.{DEV,VITE_API_URL} at compile time inside the api
module, so the prod-default and VITE_API_URL branches of
getAPIBaseURL() can only be exercised by the built bundle (covered by
Playwright E2E). The window.__INSTANODE_API_URL__ override branch is
tested directly.

No runtime code changed. No bugs surfaced during test development.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mastermanas805 mastermanas805 merged commit c90c951 into main May 11, 2026
2 checks passed
@mastermanas805 mastermanas805 deleted the test/dashboard-api-billing-coverage branch May 11, 2026 16:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant