test(cli): raise defi-cli coverage 65.78% → 75.72% (lp autopilot, MCP tools, lending collateral, bridge LI.FI, swap/agent)#33
Open
Hiksang wants to merge 6 commits into
Open
Conversation
Adds 14 unit tests for lp.ts:1595-1891 (autopilot handler), which was the largest single uncovered handler in defi-cli at 31.82% line coverage. Coverage: - budget / whitelist validation guards (process.exit intercepted) - per-entry yield scan via mocked adapter constructors (createLending, createMerchantMoeLB, createKittenSwapFarming, createGauge) - dry-run allocation plan: 20% reserve, max_allocation_pct cap, --chain filter, scan_error envelopes - broadcast execution path: buildSupply + executor.execute for lending entries; warning + skip for lb/farming/gauge entries; unknown-chain rows skipped without aborting the loop The new test program omits the root --chain option because the autopilot subcommand defines its own --chain (filters the whitelist, not the executor's target chain) and commander would otherwise let the root flag consume the value before the subcommand sees it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds 24 unit tests for mcp-server.ts tool handler bodies. The pre-existing mcp-server.test.ts only covers the ok/err envelope helpers + the server constructor; the 22 server.tool() handler bodies sat at 21.9% line coverage. Strategy: vi.mock @modelcontextprotocol/sdk/server/mcp.js to intercept server.tool(name, desc, schema, handler) registrations into a module-scoped Map, then invoke each handler directly with the same params shape an MCP transport would deliver. Covered handlers: - defi_status (happy path + default chain + unknown-chain err) - defi_lending_rates (rates round-trip + unknown-protocol err) - defi_lending_supply (executor preview + on_behalf_of forwarding) - defi_lending_withdraw (preview + unknown-chain err) - defi_dex_quote (quote round-trip + unknown-chain err) - defi_lp_positions (empty result + DEFI_WALLET_ADDRESS default + --protocol filter; the largest single uncovered handler at lines 1545-1663) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds 7 unit tests for the Morpho-Blue-only supply-collateral and withdraw-collateral subcommands at lending.ts:289-350. Both sat uncovered at 53.28% line coverage because the existing lending.test.ts stub didn't expose buildSupplyCollateral / buildWithdrawCollateral. Coverage: - supply-collateral happy path: amount echoed through builder, --amount max maps to type(uint256).max, --on-behalf-of forwarding - withdraw-collateral happy path: same shape, --amount max coverage - feature-detection error envelope when the adapter doesn't expose the collateral builders (Aave V3 / Compound V2 etc) — uses vi.mocked.mockReturnValueOnce to swap in an Aave-shaped stub while keeping the default Morpho-shaped stub for happy-path tests Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds 5 unit tests for the LI.FI provider path in bridge.ts:582-622 (the default --provider, which sat at 61.19% line / 9.09% branch coverage because it requires a live HTTPS call to li.quest). Strategy: mock globalThis.fetch with canned quote payloads (per the swap.test.ts pattern) + wrap the Executor in a capture shim so the DeFiTx + approvals[] the handler builds can be asserted. Executor's dry-run result strips approvals[] from its return shape, so the shim records the inbound tx for verification. Coverage: - native input (token = 0x0...0): empty approvals[], value forwarded - ERC20 input: approvals[0] populated with quote.estimate.approvalAddress - approvalAddress missing: spender falls through to transactionRequest.to (pins the ?? expression at bridge.ts:598) - quote missing transactionRequest: "No LI.FI route found" envelope - fetch throws: caught and surfaced as "LI.FI API error" envelope Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two related branch-coverage gaps from the 2026-05-17 sweep, bundled
because they're both single-purpose follow-ups:
1. swap-openocean.test.ts (3 tests) — covers swap.ts:331-365 branch
matrix that the existing swap.test.ts left half-open:
- ERC20 → ERC20 input populates approvals[0] with router as
spender (covers swap.ts:364 — the non-native arm)
- 0x-prefixed --from triggers the address-based registry lookup
at swap.ts:331-332 (existing test only used symbol form)
- 0xeeee... sentinel as --from omits approvals[] (covers the
second arm of isNativeInput at swap.ts:356)
Uses the same capturing-executor shim as bridge-lifi.test.ts.
2. agent.test.ts (15 tests) — walks every handleSchema switch case
so a future schema change can't drop a route silently. The
"price" (lines 214-222) and "bridge" (lines 224-234) cases were
uncovered; agent.ts sat at 63.81% line / 14.28% branch coverage.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous callTool helper returned { ok, payload, isError } where
`ok` was a plain boolean stripped from the discriminated union. That
made test code like `if (!ok) throw …` followed by `payload.data.x`
fail TypeScript narrowing — every `payload.data` access tripped
TS2339 ("Property 'data' does not exist on ErrEnvelope"). Local
vitest still passed (the runtime cast worked) but `tsc --noEmit`
(the lint step in CI) caught 14 errors.
Drop the redundant `ok` field; callers now use `payload.ok` directly,
which TypeScript recognises as the discriminator. Mechanical
replacements applied:
- const { ok, payload, ... } → const { payload, ... }
- expect(ok).toBe(true|false) → expect(payload.ok).toBe(…)
- if (!ok) throw → if (!payload.ok) throw
- if (ok) throw → if (payload.ok) throw
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Test-only PR closing the five highest-leverage coverage gaps in
defi-cliidentified in the 2026-05-17 sweep. No source changes — adds 68 unit tests
across 6 new files.
defi-cli coverage:
What's covered
lp.ts:1595-1891, was 31.82%) — budget/whitelist guards, per-entry yield scan, dry-run allocation plan (20% reserve, max_allocation_pct cap), broadcast executionserver.tool()registrations via vi.mock and invokes handler bodies directly (defi_status / lending_rates / lending_supply / lending_withdraw / dex_quote / lp_positions)lending.ts:289-350, was 53.28%) — Morpho-Blue happy paths + feature-detect error envelope for non-Morpho adaptersbridge.ts:582-622, was 61.19% line / 9.09% branch) — native vs ERC20 approvals branch, approvalAddress fallback, quote/fetch errorsTest plan
pnpm -r buildpassespnpm -r lint(tsc --noEmit) passes across all 3 packagespnpm -r test— 499 tests pass (defi-cli 303/303)🤖 Generated with Claude Code