Skip to content

Comments

fix(onboarding): ensures proper returnTo after email validation#2806

Merged
ygrishajev merged 1 commit intomainfrom
feature/auth
Feb 23, 2026
Merged

fix(onboarding): ensures proper returnTo after email validation#2806
ygrishajev merged 1 commit intomainfrom
feature/auth

Conversation

@ygrishajev
Copy link
Contributor

@ygrishajev ygrishajev commented Feb 21, 2026

Why

Users were stuck in a redirect loop after email verification. OnboardingRedirectEffect redirected users from /user/verify-email to onboarding with returnTo set to /user/verify-email?email=.... After completing onboarding, users were sent back to verify-email, which triggered the onboarding redirect again — creating an infinite loop. The root cause was that /user/verify-email was not in the excluded paths list for the onboarding redirect.

What

  • Added /user/verify-email to EXCLUDED_PREFIXES in OnboardingRedirectEffect so the verify-email page is not intercepted by the onboarding redirect
  • Added { returnTo: "/" } to the UrlService.onboarding() call in the verify-email page so users navigate to / after completing onboarding
  • Extracted VerifyEmailPage from the Next.js page file into its own component under components/onboarding/VerifyEmailPage/
  • Added dependency injection to OnboardingRedirectEffect and VerifyEmailPage for testability
  • Added unit tests for OnboardingRedirectEffect (11 tests) and VerifyEmailPage (6 tests)

Summary by CodeRabbit

  • New Features

    • Added a dedicated email verification page to support onboarding email verification.
    • Updated redirect behavior to exclude the verify-email path and handle return-to encoding.
  • Tests

    • Added unit tests covering email verification flows: success, error, loading, and missing params.
    • Added tests for onboarding redirect logic across user/wallet/loading edge cases.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 21, 2026

📝 Walkthrough

Walkthrough

Extracted a VerifyEmailPage component with dependency injection and tests; refactored OnboardingRedirectEffect to accept injected dependencies and export EXCLUDED_PREFIXES (extended with "/user/verify-email"); page layer now re-exports the new VerifyEmailPage; tests added for both components.

Changes

Cohort / File(s) Summary
OnboardingRedirectEffect (refactor & export)
apps/deploy-web/src/components/onboarding/OnboardingRedirectEffect/OnboardingRedirectEffect.tsx
Refactored to accept injected dependencies via OnboardingRedirectEffectProps/DEPENDENCIES; replaced direct hook/service calls with injected variants; EXCLUDED_PREFIXES exported and extended with "/user/verify-email".
OnboardingRedirectEffect tests
apps/deploy-web/src/components/onboarding/OnboardingRedirectEffect/OnboardingRedirectEffect.spec.tsx
New test suite covering redirect logic across user/wallet/loading states, excluded path handling, and return-to encoding. Uses a setup helper to mock hooks/services via the DI props.
VerifyEmailPage (new component)
apps/deploy-web/src/components/onboarding/VerifyEmailPage/VerifyEmailPage.tsx
New page component implementing email verification flow with dependency injection: reads email from search params, calls useVerifyEmail, shows loading/success/error UIs, persists onboarding step, and navigates to onboarding on success.
VerifyEmailPage tests
apps/deploy-web/src/components/onboarding/VerifyEmailPage/VerifyEmailPage.spec.tsx
New tests verifying email extraction, hook invocation, loading state, success/error renderings, and captured callbacks via mocked DI.
Page re-export
apps/deploy-web/src/pages/user/verify-email/index.tsx
Replaced in-file page component with a re-export of the new VerifyEmailPage component (reduces inline logic).
Manifest updates
package.json
Dependency changes recorded (+18/-7 lines in manifest).

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant VerifyEmailPage as VerifyEmailPage (component)
  participant SearchParams as useSearchParams
  participant VerifyHook as useVerifyEmail
  participant Router
  participant UrlService

  Browser->>VerifyEmailPage: request /user/verify-email?email=...
  VerifyEmailPage->>SearchParams: read email
  alt email present
    VerifyEmailPage->>VerifyHook: mutate({ email })
    VerifyHook-->>VerifyEmailPage: onSuccess / onError
    alt onSuccess
      VerifyEmailPage->>UrlService: build onboarding URL (returnTo=/)
      VerifyEmailPage->>Router: push(onboardingUrl)
    else onError
      VerifyEmailPage-->>Browser: render error UI
    end
  else email missing
    VerifyEmailPage-->>Browser: render error UI
  end
Loading
sequenceDiagram
  participant App
  participant OnboardingEffect as OnboardingRedirectEffect
  participant UserHook as useUser
  participant WalletHook as useWallet
  participant Router

  App->>OnboardingEffect: mount
  OnboardingEffect->>UserHook: get userId, loading
  OnboardingEffect->>WalletHook: get wallet, connected, loading
  alt userId && !wallet && !connected && not excludedPath
    OnboardingEffect->>Router: push("/signup?returnTo=encodedPath")
  else
    OnboardingEffect-->>App: no redirect
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A little hop, a tidy tweak,

Dependencies tucked where tests can peek.
Emails checked, redirects set right,
Green tests blooming in morning light. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main fix: preventing redirect loops after email validation by ensuring proper returnTo handling in the onboarding flow.
Description check ✅ Passed The description provides comprehensive coverage of both Why and What sections with clear problem statement, solution details, and implementation changes including testing additions.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/auth

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Feb 21, 2026

Codecov Report

❌ Patch coverage is 92.00000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 52.98%. Comparing base (c74cbea) to head (9273463).
⚠️ Report is 4 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...nts/onboarding/VerifyEmailPage/VerifyEmailPage.tsx 88.88% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2806      +/-   ##
==========================================
- Coverage   53.73%   52.98%   -0.75%     
==========================================
  Files        1018      983      -35     
  Lines       23586    22756     -830     
  Branches     5757     5664      -93     
==========================================
- Hits        12673    12057     -616     
+ Misses       9510     9308     -202     
+ Partials     1403     1391      -12     
Flag Coverage Δ *Carryforward flag
api 77.25% <ø> (ø) Carriedforward from c74cbea
deploy-web 36.13% <92.00%> (+0.21%) ⬆️
log-collector ?
notifications 85.56% <ø> (ø) Carriedforward from c74cbea
provider-console 81.48% <ø> (ø) Carriedforward from c74cbea
provider-proxy 82.41% <ø> (ø) Carriedforward from c74cbea
tx-signer ?

*This pull request uses carry forward flags. Click here to find out more.

Files with missing lines Coverage Δ
...oardingRedirectEffect/OnboardingRedirectEffect.tsx 100.00% <100.00%> (+100.00%) ⬆️
...nts/onboarding/VerifyEmailPage/VerifyEmailPage.tsx 88.88% <88.88%> (ø)

... and 36 files with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@apps/deploy-web/src/components/onboarding/OnboardingRedirectEffect/OnboardingRedirectEffect.spec.tsx`:
- Line 9: Replace the hardcoded root suite string with the component's runtime
name: change the describe call from "OnboardingRedirectEffect" to
OnboardingRedirectEffect.name in the OnboardingRedirectEffect.spec.tsx test;
ensure the OnboardingRedirectEffect symbol used in the describe is imported or
otherwise available in the test so the .name property resolves at runtime.

In
`@apps/deploy-web/src/components/onboarding/VerifyEmailPage/VerifyEmailPage.spec.tsx`:
- Line 9: Change the root test suite to use the component's .name instead of a
hardcoded string: replace the top-level describe("VerifyEmailPage", ...) with
describe(VerifyEmailPage.name, ...) (ensure the VerifyEmailPage symbol
imported/available in the spec file) so automated refactors can locate the suite
by symbol.
- Around line 22-47: Replace assertions that use screen.getByText and
screen.getByTestId with the non-throwing query variants so tests don't error on
absent nodes: update the expectations in VerifyEmailPage.spec.tsx to use
screen.queryByText for the loading, error and "isVerified is null" cases and use
screen.queryByTestId for the CheckCircleIcon assertion; locate the assertions
around the setup helper and the capturedOnSuccess / capturedOnError interactions
and change getBy* -> queryBy* while keeping the same text and test id values.

In
`@apps/deploy-web/src/components/onboarding/VerifyEmailPage/VerifyEmailPage.tsx`:
- Around line 6-75: The code calls d.useSearchParams().get("email") without
guarding against useSearchParams returning null; update VerifyEmailPage to
handle null by using optional chaining or a null check when obtaining email
(e.g., derive email from d.useSearchParams()?.get("email") or check the result
before calling .get), and ensure subsequent logic (the d.useWhen(email, ...),
state initialization, and verifyEmail usage) gracefully handles email being
null/undefined; locate the reference in VerifyEmailPage where email is assigned
and adjust that line and any dependent usage to be null-safe.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In
`@apps/deploy-web/src/components/onboarding/VerifyEmailPage/VerifyEmailPage.tsx`:
- Around line 70-71: VerifyEmailPage currently calls
d.useSearchParams().get("email") directly which can throw if useSearchParams()
returns null during pre-render; update the code in VerifyEmailPage to first
capture the result of d.useSearchParams(), check for null/undefined, and only
call .get("email") when it's non-null (use a safe fallback like undefined or
empty string for email otherwise) so d.useSearchParams() is null-safe.

@ygrishajev ygrishajev enabled auto-merge February 22, 2026 08:28
@ygrishajev ygrishajev added this pull request to the merge queue Feb 23, 2026
Merged via the queue into main with commit 6b95ff3 Feb 23, 2026
53 of 54 checks passed
@ygrishajev ygrishajev deleted the feature/auth branch February 23, 2026 08:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants