Repository navigation
test(ci): run both frontend suites, and repair what that turned up - #201
Merged
Merged
Conversation
Neither apps/dashboard nor apps/checkout ran tests in CI. The dashboard's
suite had been broken on main for some time and the checkout's had never
executed at all, which is how nineteen call sites kept a doubled /v1 prefix
until someone opened a network panel — the assertions that would have caught
it were sitting in files no runner touched.
Both now run in a `test-frontend` job. Three infrastructure faults and four
stale-assertion sites had to be fixed to get there.
Dashboard, infrastructure:
`vitest.config.ts` aliased @useroutr/ui at `../packages/ui/src`, which from
apps/dashboard resolves to apps/packages — one level short. Two suites failed
to collect. The aliases move to array form with regex `find` entries so
subpath imports (@useroutr/ui/globals.css) are not rewritten onto the index
file.
PayoutExportButton's five failures were not an `environment` problem: jsdom
was configured correctly and the sibling suite passed. The test spied on
`document.createElement` with a blanket `mockReturnValue`, so the
`createElement('div')` that testing-library's `render()` makes for its own
container got the fake anchor instead — "Target container is not a DOM
element" was reporting exactly that. Same for `document.body.appendChild`.
Both spies now pass through anything that is not the download anchor, and an
`afterEach` restores them: they wrap the live `document`, so without it each
test layered another spy on the previous test's.
Dashboard, assertions that encoded real behaviour changes:
- PayoutStatusBadge (5): the tone name is no longer emitted as a class.
BrandStatusBadge maps it to Tailwind tokens, so each status now asserts the
pair it actually resolves to — PENDING to `bg-warning/10 text-warning`, and
CANCELLED to `bg-secondary text-muted-foreground`, which it shares with
neutral deliberately.
- usePayouts (4): `/v1/payouts` to `/payouts`. api.ts sets
BASE_URL = ${origin}/v1, so callers pass bare paths. These were the
pre-fix paths.
- BatchGroupHeader (1): `getByText('(1)')` threw on multiple matches — three
payouts with three distinct statuses render three chips. Now asserts all
three, plus each status label. Only surfaced because the suite finally
loaded.
Checkout:
No test script, no runner, no config — vitest, jsdom and testing-library are
added to match the dashboard's versions.
The test file had drifted much further than the missing runner suggested. It
was written against a CryptoPayment with a "Select network" / "Select token"
two-step picker over ETH/BASE/BNB and USDC/USDT/ETH. The current component
has no token picker at all and offers Stellar plus the five CCTP chains under
"Send USDC from". Assertions are rewritten against the shipped component.
QuoteCountdown's three were still accurate and pass unchanged.
The mocks were stale to match: wagmi's useConnect and useBalance and a
`useQuote` hook the component does not use were mocked, while useChainId,
useSendTransaction, @rainbow-me/rainbowkit and next/navigation were not. It
also wrapped renders in WagmiProvider while mocking wagmi without exporting
it, which would have rendered undefined. The provider is dropped since every
wagmi hook is mocked; QueryClientProvider stays and the two crypto hooks are
left real so they exercise their own wiring against a mocked api client.
Not done: packages/types has no test script and no test files on main, so
nothing to wire up. Its tests and a `test-packages` job live on
fix/single-v1-prefix; test-merged against this, the two compose without
conflict.
Verified from a clean `npm ci`: dashboard 38 tests, checkout 8, both green.
Lint clean in both apps (0 errors, pre-existing warnings only) and the
checkout `next build` still passes, since vitest.config.ts lands inside its
tsconfig include glob.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
0xdevcollins
added a commit
that referenced
this pull request
Aug 9, 2026
… dialog Radix renders `AlertDialogDescription` as a `<p>`, and this one held a `<div>` (the payout summary) and another `<p>` (the closing warning). That is invalid HTML: React flags it at runtime, and the browser's parser recovers by closing the paragraph early, which splits the element `aria-describedby` points at. `asChild` renders the description as the `<div>` it always needed to be, with the intro text moved into its own `<p>`. The whole block stays inside the description rather than moving out as a sibling, so the accessible description still covers all of it. Salvaged from #202, whose test and config work was superseded by #201 — this was the one change in it that nothing else carried. Dashboard suite stays at 38/38. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
0xdevcollins
added a commit
that referenced
this pull request
Aug 9, 2026
… dialog (#203) Radix renders `AlertDialogDescription` as a `<p>`, and this one held a `<div>` (the payout summary) and another `<p>` (the closing warning). That is invalid HTML: React flags it at runtime, and the browser's parser recovers by closing the paragraph early, which splits the element `aria-describedby` points at. `asChild` renders the description as the `<div>` it always needed to be, with the intro text moved into its own `<p>`. The whole block stays inside the description rather than moving out as a sibling, so the accessible description still covers all of it. Salvaged from #202, whose test and config work was superseded by #201 — this was the one change in it that nothing else carried. Dashboard suite stays at 38/38. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This branch was successfully deployed
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.
Neither
apps/dashboardnorapps/checkoutran tests in CI. The dashboard's suite had been broken on main for some time and the checkout's had never executed at all — which is how nineteen call sites kept a doubled/v1prefix until someone opened a network panel. The assertions that would have caught it were sitting in files no runner touched.Both now run in a
test-frontendjob. Getting there took three infrastructure fixes and four stale-assertion sites.Dashboard — infrastructure
@useroutr/uifailed to resolve (2 suites never collected). The alias existed but pointed one level short:../packages/ui/srcfromapps/dashboardresolves toapps/packages. Moved to array form with regexfindentries so subpath imports (@useroutr/ui/globals.css) aren't rewritten onto the index file.Target container is not a DOM element(5 tests) was not anenvironmentproblem — jsdom was configured correctly and the sibling suite passed. The test spied ondocument.createElementwith a blanketmockReturnValue, so thecreateElement('div')that testing-library'srender()makes for its own container got the fake anchor instead. Same fordocument.body.appendChild. Both spies now pass through anything that isn't the download anchor, plus anafterEachto restore them — they wrap the livedocument, so without it each test layered another spy on the previous one's.Dashboard — assertions that encoded real behaviour changes
toHaveClass("pending"|"processing"|…)BrandStatusBadgemaps it to Tailwind tokens. Each status asserts the pair it actually resolves to: PENDING →bg-warning/10 text-warning, CANCELLED →bg-secondary text-muted-foreground(shared with neutral, deliberately)./v1/payouts,/v1/payouts/:id/retry|cancel/payouts,/payouts/:id/retry|cancel.api.tssetsBASE_URL = ${origin}/v1, so callers pass bare paths — these were the pre-fix paths.getByText('(1)')Nothing was loosened or skipped.
Checkout
No test script, no runner, no config — vitest, jsdom and testing-library added to match the dashboard's versions.
The test file had drifted much further than the missing runner suggested. It was written against a
CryptoPaymentwith a "Select network" / "Select token" two-step picker overETH/BASE/BNBandUSDC/USDT/ETH. The current component has no token picker at all, and offers Stellar plus the five CCTP chains under "Send USDC from". Assertions rewritten against the shipped component;QuoteCountdown's three were still accurate and pass unchanged.The mocks were stale to match —
wagmi'suseConnect/useBalanceand auseQuotehook the component doesn't use were mocked, whileuseChainId,useSendTransaction,@rainbow-me/rainbowkitandnext/navigationweren't. It also wrapped renders inWagmiProviderwhile mockingwagmiwithout exporting it, which would have renderedundefined. Provider dropped (every wagmi hook is mocked);QueryClientProviderstays and the two crypto hooks are left real so they exercise their own wiring against a mocked api client.Not done
packages/typeshas no test script and no test files on main, so there was nothing to wire up — a job for it would fail immediately. Its tests and atest-packagesjob live onfix/single-v1-prefix(237b615), unmerged. I test-merged that branch against this one: no conflicts, and the two jobs compose.Verification
From a clean
npm ci:apps/dashboard— 6 files, 38 tests, all passingapps/checkout— 1 file, 8 tests, all passingnpm run lintclean in both apps (0 errors; pre-existing warnings only)next buildstill passes for checkout, sincevitest.config.tslands inside its tsconfigincludegloblint, test-api, test-frontend, test-contracts-soroban, buildOne thing left alone:
CancelConfirmationModalnests a<div>and<p>inside Radix's description<p>, which React warns is a hydration risk. The suite passes — it's invalid markup, not a test failure — so it belongs in its own change.🤖 Generated with Claude Code