Skip to content

fix(payment): #159 route payment navigations through the base path#177

Merged
TortoiseWolfe merged 1 commit into
mainfrom
fix/159-payment-basepath-nav
Jul 5, 2026
Merged

fix(payment): #159 route payment navigations through the base path#177
TortoiseWolfe merged 1 commit into
mainfrom
fix/159-payment-basepath-nav

Conversation

@TortoiseWolfe

Copy link
Copy Markdown
Owner

What

Fixes the basePath-escape bug class in payment navigation (#159). Routes all five same-class sites through the basePath-aware helpers introduced in #154 — the two window.location.href sites the issue named, plus three raw <a href> anchors found alongside them.

Why

Raw window.location.href and raw <a href> do not get the basePath prepended — only next/link and the next/navigation router do. On a GitHub Pages project-site fork (basePath=/RepoName), these escape the app to the domain root mid-payment. The template itself is immune (custom domain, basePath ''), but a fork silently breaks. Same defect class as #154.

Changes

Hard navigations → getInternalUrl (query URL — no trailing slash added):

  • src/app/payment-result/page.tsx:257 (onRetrySuccess)
  • PaymentStatusDisplay.tsx:436 (SwitchProviderPanel onSwitchSuccess)

Raw <a href>next/link <Link> (auto-prefixes at runtime):

  • PaymentStatusDisplay.tsx — two /contact support links
  • PaymentConsentModal.tsx — the /privacy policy link

Tests (mirror the #154 use-auth vitest pattern):

  • PaymentStatusDisplay.test.tsx — the SwitchProviderPanel stub now exposes a button to fire onSwitchSuccess, so the parent's navigation is actually exercised. Asserts the prefixed href under NEXT_PUBLIC_BASE_PATH=/ScriptHammer and the unprefixed href without it, plus that the support control renders as a next/link.
  • PaymentConsentModal.test.tsx — asserts the privacy link is a next/link anchor.

Coverage note (honest scoping)

getInternalUrl reads process.env at runtime, so the two window.location tests pin the prefix directly. next/link, however, reads the runtime __NEXT_ROUTER_BASEPATH which jsdom doesn't populate — so the <Link> prefix is pinned end-to-end by the basePath E2E project (#157), not the unit layer. page.tsx site 1 uses the byte-identical expression to the pinned site 2; mounting the whole auth+payment tree to re-assert one shared line would add fragility, not coverage.

Verification

  • PaymentStatusDisplay.test.tsx + PaymentConsentModal.test.tsx → 47 pass (incl. the pre-existing "contact support" link assertion, still green after the <Link> conversion).
  • a11y suites → 16 pass. pnpm type-check clean. eslint on all 5 files clean.

Closes #159

🤖 Generated with Claude Code

Raw `window.location.href` and raw `<a href>` do NOT get the basePath
prepended (only next/link and the next/navigation router do). On a GitHub
Pages project-site fork (basePath=/RepoName) these escape the app to the
domain root mid-payment. Fix all five same-class sites (the two named in
#159 plus three raw anchors found alongside them), mirroring the #154 pattern.

Hard navigations -> getInternalUrl (query URL, no trailing slash added):
- src/app/payment-result/page.tsx:257 (onRetrySuccess)
- PaymentStatusDisplay.tsx:436 (SwitchProviderPanel onSwitchSuccess)

Raw <a href> -> next/link <Link> (auto-prefixes at runtime):
- PaymentStatusDisplay.tsx: two /contact support links
- PaymentConsentModal.tsx: the /privacy policy link

Tests (mirror the #154 use-auth vitest pattern):
- PaymentStatusDisplay.test.tsx: the SwitchProviderPanel stub now exposes a
  button to fire onSwitchSuccess, so the parent's navigation is exercised.
  Asserts the prefixed href with NEXT_PUBLIC_BASE_PATH=/ScriptHammer and the
  unprefixed href without it, plus that the support control is a next/link.
- PaymentConsentModal.test.tsx: asserts the privacy link is a next/link anchor.

Note on coverage: getInternalUrl reads process.env at runtime so the two
window.location tests pin the prefix directly; next/link reads the runtime
__NEXT_ROUTER_BASEPATH which jsdom doesn't populate, so the Link prefix is
pinned end-to-end by the basePath E2E project (#157). page.tsx site 1 uses
the byte-identical expression to the pinned site 2 (mounting the whole
auth+payment tree to re-assert one shared line adds fragility, not coverage).

Closes #159

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@TortoiseWolfe TortoiseWolfe merged commit 04fb152 into main Jul 5, 2026
18 checks passed
@TortoiseWolfe TortoiseWolfe deleted the fix/159-payment-basepath-nav branch July 5, 2026 01:04
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.

Payment pages still hard-navigate without basePath (same class as #154)

2 participants