Skip to content

test: add utility and env test coverage (Tier 1)#415

Open
gabitoesmiapodo wants to merge 20 commits intofeat/ai-integrationfrom
test/utils
Open

test: add utility and env test coverage (Tier 1)#415
gabitoesmiapodo wants to merge 20 commits intofeat/ai-integrationfrom
test/utils

Conversation

@gabitoesmiapodo
Copy link
Collaborator

Summary

  • Adds tests for strings.ts, getExplorerLink.ts, address.ts utilities
  • Adds env.ts Zod schema validation tests
  • Creates src/test-utils.tsx with shared test helpers

Test plan

  • pnpm test passes on this branch
  • All new utility tests cover the public API surface used by wagmi/viem-dependent code

Part of test safety net before dependency updates. See plan for full context.

Copilot AI review requested due to automatic review settings March 23, 2026 21:17
@vercel
Copy link

vercel bot commented Mar 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
components.dappbooster Ready Ready Preview, Comment Mar 25, 2026 6:50pm
demo.dappbooster Ready Ready Preview Mar 25, 2026 6:50pm
docs.dappbooster Ready Ready Preview, Comment Mar 25, 2026 6:50pm

Request Review

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a Tier 1 testing safety net around several utility modules and environment parsing so upcoming dependency updates have better regression coverage.

Changes:

  • Added Vitest unit tests for strings, getExplorerLink, and address utilities.
  • Added Vitest coverage for env.ts Zod/@t3-oss/env-core validation behavior using a committed .env.test.
  • Introduced src/test-utils.tsx with shared helpers (providers wrapper + chain/web3 mocks).

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/utils/strings.test.ts Adds unit tests for string truncation helpers.
src/utils/getExplorerLink.test.ts Adds unit tests for explorer URL generation logic.
src/utils/address.test.ts Adds unit tests for native-token address detection (env-driven).
src/test-utils.tsx Adds shared test helpers (render wrapper + mocks).
src/env.test.ts Adds unit tests asserting env schema output under Vitest mode.
.env.test Adds test-mode env vars required by the env schema.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +18 to +21
it('returns tx URL using chain block explorer for a hash', () => {
const url = getExplorerLink({ chain, hashOrAddress: txHash })
expect(url).toBe(`${chain.blockExplorers?.default.url}/tx/${txHash}`)
})
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as the address-case: the assertion uses chain.blockExplorers?.default.url, which would still produce a matching (but broken) undefined/tx/... string if the chain mock lacks a block explorer. Using the explicit mock URL will make this test meaningfully fail on regressions.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed: same as above.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from this comment I think that best is to throw when chain does not exist, so we prevent the undefined/<tx|address> invalid route in runtime and throw.

I mean, this surfaced an issue with the util's implementation.

If !explorerUrl && !chain.blockExplorers?.default then throw. I remember when implementing this I adopted the naïve approach of reviewing the different definitions here: https://github.com/wevm/viem/blob/main/src/chains/index.ts to see if all chains have "default" explorer configured.

That will mean adding a new test for that particular case.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixing the missing-explorer behavior (returning undefined/... vs throwing) is a valid improvement but requires changing getExplorerLink.ts — outside the scope of this test PR. The test at line 42 already documents the safe path when explorerUrl is explicitly provided. A separate fix PR for the implementation is the right place for this.

Copy link
Collaborator Author

@gabitoesmiapodo gabitoesmiapodo Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fernandomg Fixed in #426.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Add test safety net before dependency updates. New files:
- src/test-utils.tsx: renderWithProviders, createMockWeb3Status, createMockChain
- src/utils/strings.test.ts: truncateStringInTheMiddle and getTruncatedHash (13 tests)
- src/utils/getExplorerLink.test.ts: getExplorerLink (6 tests)
- src/utils/address.test.ts: isNativeToken (5 tests)
- src/env.test.ts: Zod-validated env schema (9 tests)
- .env.test: Vitest environment variables for required PUBLIC_ fields
- Fix env.test.ts test names that incorrectly claimed to test defaults
  while .env.test was setting those vars explicitly
- Assert exact value for PUBLIC_WALLETCONNECT_PROJECT_ID (was typeof check)
- Fix createMockWeb3Status shape to match actual Web3Status interface
  (was using isConnected/chainId/publicClient; hook uses isWalletConnected/
  walletChainId/readOnlyClient)
- Hardcode expected explorer URL in getExplorerLink assertions instead of
  deriving from mock chain (prevents false positives if mock misconfigured)
BigNumberInput: add 9 tests covering placeholder, disabled state,
onChange with parsed bigint, onError for min/max violations,
decimal precision enforcement, and input clearing.

HashInput: add 7 tests covering placeholder, typed value reflection,
initial value, clear to null, debounced search callback,
onLoading lifecycle, and custom renderInput.
- Rename misleading test names in BigNumberInput (onError absence test,
  maxUint256 constraint test)
- Add beforeEach mock clear in HashInput to prevent cross-test contamination
  from unconsumed mockResolvedValueOnce calls
- Add debounceTime: 0 to clear test to avoid real-timer dependency
- Rename debounce test to accurately describe what it covers; fake-timer
  debounce testing conflicts with waitFor + userEvent in jsdom
- Use @/src/env alias import in env.test.ts (matches repo convention)
- Rename 'checksummed zero address' test to 'zero address string literal'
  (no checksum casing difference in this value; name was misleading)
- useWeb3Status.test.ts: 8 tests covering disconnected/connected state,
  isWalletSynced, switchingChain, disconnect, switchChain, appChainId
- useWeb3StatusConnected.test.ts: 2 tests (co-located in same file)
  covering throw-on-disconnect and pass-through when connected
- useErc20Balance.test.ts: 5 tests covering missing address/token,
  native token skip, successful balance fetch, and error handling
- useTokenLists.test.ts: 4 tests covering return shape, deduplication,
  native token injection, and schema validation filtering
- Add beforeEach mock clearing in useWeb3Status to prevent shared mock
  call history leaking between tests
- Switch mockReturnValue to mockReturnValueOnce for the connected test in
  useWeb3StatusConnected (hook calls useWeb3Status twice internally)
- Add beforeEach mockReadContract.mockClear() in useErc20Balance to
  prevent cross-test false negatives on not.toHaveBeenCalled assertions
New tests for shared components and utilities:
- TokenLogo: img src/alt/size, IPFS URL conversion, placeholder on error
- TransactionButton: wallet states, pending label, onMined callback
- SwitchNetwork: network display, disabled state, menu item rendering
- WalletStatusVerifier: connect fallback, wrong chain, synced renders children
- withWalletStatusVerifier HOC: fallback and pass-through behavior
- withSuspense/withSuspenseAndRetry: Suspense fallback, error message, retry

Also adds:
- ResizeObserver mock to setupTests.ts (required by @floating-ui in jsdom)
- .env.test and src/test-utils.tsx (shared test utilities from tier 1)
- setupTests.ts: replace vi.fn() ResizeObserver with a real class guarded
  by a conditional check — vi.restoreAllMocks() can no longer clear it
- suspenseWrapper.test.tsx: restore only the console.error spy in afterEach
  instead of vi.restoreAllMocks() which would wipe the ResizeObserver polyfill
- TransactionButton.test.tsx: make useWaitForTransactionReceipt mock hash-aware
  so it only returns the receipt when called with the expected hash
Smoke tests for all demo page components to verify they render
without crashing. Mocks external Web3 deps at module level.

New test files:
- home/index.test.tsx: Home renders Welcome + Examples sections
- NotFound404.test.tsx: 404 page with mocked useNavigate
- demos/ConnectWallet/index.test.tsx: mocked ConnectWalletButton
- demos/EnsName/index.test.tsx: mocked useEnsName
- demos/HashHandling/index.test.tsx: mocked useWeb3Status + detectHash
- demos/SignMessage/index.test.tsx: shows fallback when wallet absent
- demos/SwitchNetwork/index.test.tsx: shows fallback when wallet absent
- demos/TransactionButton/index.test.tsx: shows fallback when wallet absent
- demos/TokenDropdown/index.test.tsx: mocked BaseTokenDropdown
- demos/TokenInput/index.test.tsx: mocked useTokenLists + useTokenSearch

Also adds .env.test and src/test-utils.tsx (shared test utilities).
The module exports detectHash as a default export; the mock only provided
a named export so HashInput would receive undefined and throw on invocation.
Added both default and named exports to the mock factory.
- home/index.test.tsx: use renderWithProviders from test-utils
- TransactionButton demo: use createMockWeb3Status for complete hook shape
- TokenInput demo: fix useTokenInput mock to match the real hook return
  (amount/setAmount/amountError/balance/isLoadingBalance/selectedToken/setTokenSelected)
  and use renderWithProviders + createMockWeb3Status helpers
Copy link
Member

@fernandomg fernandomg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In regard to address.test.ts I would chose another value for the PUBLIC_NATIVE_TOKEN_ADDRESS so it makes the different tests cases valid, or I would just remove those unecessary

Comment on lines +18 to +20
it('returns true for the zero address in lowercase', () => {
expect(isNativeToken(zeroAddress.toLowerCase())).toBe(true)
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't make much sense

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a412c4f. Removed the test — zeroAddress.toLowerCase() equals zeroAddress so it was identical to the first case.

Comment on lines +18 to +21
it('returns tx URL using chain block explorer for a hash', () => {
const url = getExplorerLink({ chain, hashOrAddress: txHash })
expect(url).toBe(`${chain.blockExplorers?.default.url}/tx/${txHash}`)
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from this comment I think that best is to throw when chain does not exist, so we prevent the undefined/<tx|address> invalid route in runtime and throw.

I mean, this surfaced an issue with the util's implementation.

If !explorerUrl && !chain.blockExplorers?.default then throw. I remember when implementing this I adopted the naïve approach of reviewing the different definitions here: https://github.com/wevm/viem/blob/main/src/chains/index.ts to see if all chains have "default" explorer configured.

That will mean adding a new test for that particular case.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

@gabitoesmiapodo
Copy link
Collaborator Author

The missing throw case for getExplorerLink (no block explorer + no explorerUrl) is covered in #426 — both the implementation fix and the test. When both PRs land there will be a conflict in src/utils/getExplorerLink.test.ts that will need to be resolved by merging the two test files.

test: enhance BigNumberInput and HashInput coverage (Tier 2)
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.

3 participants