Skip to content

Add Transaction Builder Tests & tRPC Integration Tests #255

@Andre-Diamond

Description

@Andre-Diamond

Add Transaction Builder Tests & tRPC Integration Tests

Background

Two gaps exist in the current test coverage:

  1. Gap 1 — Transaction building is untested. The DRep certificate wiring in registerDrep.tsx, updateDrep.tsx, and retire.tsx is inlined and cannot be exercised without a browser. The staking certificate helpers in stakingCertificates.ts are extracted but have no tests. The proxy contract methods in offchain.ts have no test coverage at all.

  2. Gap 2 — The tRPC persistence path is untested. The browser persists transactions via transaction.createTransaction. A schema mismatch, DB constraint violation, wrong state value, or authorization regression in the tRPC layer is not caught today.

What We're Adding

Option B — Transaction Builder Unit Tests (Jest, no browser)

Extract shared transaction-building logic into testable functions and cover them with Jest tests that run in Node.js using a mock BlockfrostProvider.

Phase 0 — Add cbor-x dev dependency

  • pnpm add -D cbor-x — pure-JS CBOR decoder used in tests to inspect raw transaction structure without WASM

Phase 1 — Test infrastructure (no source changes)

  • src/__tests__/tx-builders/fixtures.ts — synthetic UTxO fixtures, addresses, DRep/staking identifiers (factory pattern, no real preprod data)
  • src/__tests__/tx-builders/mockProvider.tsIFetcher + IEvaluator mock; evaluateTx returns [] so complete() runs offline
  • src/__tests__/tx-builders/testTxBuilder.tsMeshTxBuilder factory using mock provider
  • src/__tests__/tx-builders/cborUtils.tsdecodeTxBody(), getCerts(), getWithdrawals(), CERT_KIND constants
  • src/__tests__/tx-builders/infrastructure.test.ts — smoke test (import + construct, cbor-x round-trip)

Phase 2 — Staking certificate tests (no source changes)

  • src/__tests__/tx-builders/stakingCert.test.ts
    • register, deregister, delegate, register_and_delegate, withdrawal actions
    • Call txBuilder.complete() then decode with cbor-x; assert CERT_KIND and cert count

Phase 3 — DRep certificate extraction + tests

  • src/lib/tx-builders/buildDRepCertTx.ts — new shared applyDRepCert(txBuilder, params) function
  • registerDrep.tsx, updateDrep.tsx, retire.tsx — replace inlined cert blocks with applyDRepCert(...)
  • src/__tests__/tx-builders/drepCert.test.ts
    • register/update with anchor, retire without anchor
    • Missing anchor throws, legacy wallet (same CBOR) avoids double script

Phase 4 — Proxy transaction tests (no source changes)

  • src/__tests__/tx-builders/proxy.test.ts
    • setupProxy: mints auth tokens, sends to proxy address, distributes UTxOs
    • manageProxyDrep: register/update/retire DRep certs, anchor validation, missing auth token
    • voteProxyDrep: single/multiple votes, empty array, invalid proposal ID
    • Pure computations: getAuthTokenPolicyId(), getDrepId(), setProxyAddress()

Phase 5 — CI gate

  • Add pnpm jest --testPathPattern="src/__tests__/tx-builders" step to CI workflow
  • Add 90% line coverage threshold for stakingCertificates.ts and buildDRepCertTx.ts in jest.config.mjs

Option C — tRPC createCaller Integration Tests (Jest, optional real DB)

Test tRPC procedures directly via createCaller — no HTTP server, no browser, no Playwright. No changes to production code.

Phase 1 — Test infrastructure

  • src/__tests__/trpc/helpers.tsmakeWalletCtx, makeSessionCtx, makeAnonymousCtx factories
  • src/__tests__/trpc/fixtures.tsseedWallet, seedUser, cleanupFixtures helpers
    • Real DB tests skip when DATABASE_URL is absent (itWithDb guard)

Phase 2 — Authorization tests (mock DB, always runs)

  • src/__tests__/trpc/transactionAuth.test.ts
    • No auth → UNAUTHORIZED, wallet not found → NOT_FOUND, not a signer → FORBIDDEN, owner passes, signer via sessionWallets passes
  • src/__tests__/trpc/proxyAuth.test.ts
    • No auth, non-signer walletId, user not found, wrong user, valid signer, missing both walletId and userId

Phase 3 — Transaction procedure tests (real DB)

  • src/__tests__/trpc/createTransaction.test.ts
    • Happy path persists row, optional fields (description, txHash), Zod rejects empty txCbor/txJson, FORBIDDEN for non-signer, full row shape returned
  • src/__tests__/trpc/pendingTransactions.test.ts
    • Empty result, one pending returned, completed (state 1) excluded, ordering by createdAt desc, cross-wallet isolation

Phase 4 — Proxy procedure tests (real DB)

  • src/__tests__/trpc/createProxy.test.ts
    • walletId and userId variants, isActive defaults true, optional description, Zod validation, FORBIDDEN cases, read-back via getProxiesByWallet

Phase 5 — CI integration

  • Add test:unit and test:trpc scripts to package.json
  • Add CI steps: unit tests (no DB) + tRPC tests (with TEST_DATABASE_URL secret)

Sequencing

PR Covers Source changes? Risk
1 Option B Phase 0 + 1 + 2 package.json only None
2 Option B Phase 3 Minor (extract inlined cert block) Low
3 Option B Phase 4 None None
4 Option C Phase 1 + 2 None None
5 Option C Phase 3 + 4 None None
6 CI gate (Option B Phase 5 + Option C Phase 5) CI workflow + jest config None

PRs 1–3 and 4–5 are independent and can be merged in parallel.


Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions