Skip to content

feat(ui): add "Sign in as a different account" action to sign-in second factor#9190

Open
alexcarpenter wants to merge 2 commits into
mainfrom
back-button-2fa-step
Open

feat(ui): add "Sign in as a different account" action to sign-in second factor#9190
alexcarpenter wants to merge 2 commits into
mainfrom
back-button-2fa-step

Conversation

@alexcarpenter

@alexcarpenter alexcarpenter commented Jul 17, 2026

Copy link
Copy Markdown
Member

Description

Customer feedback:

It'd be great to have a logout button here. I picked the wrong google account on accident and now there's no way for me to go back and sign in.

A user who authenticates on the sign-in two-step verification (second factor) screen with the wrong account — most commonly after signing in with the wrong social/OAuth account — is stuck. The only actions on that screen are Continue (needs a code they can't produce) and Use another method (which just cycles between other 2FA methods, keeping them inside the same locked attempt). Unlike the first-factor screen, there is no way to change who you're signing in as.

This adds a "Sign in as a different account" footer action to the second-factor step. It abandons the current sign-in attempt and returns the user to the sign-in start, where they can re-authenticate with the correct account.

Why not reuse the first-factor "edit identifier" pencil?

The pencil lives on the IdentityPreview and means "edit the identifier I typed". On the second factor there is no account identifier displayed (and for TOTP there is no identifier at all), so the pencil has nothing valid to attach to and the wrong semantics. A distinct footer action ("throw away this attempt and start over") is the correct affordance.

Scope

  • Wired via SignInFactorTwoCodeForm, so it appears on the TOTP, SMS, and email-code second-factor screens (covers the reported TOTP-after-OAuth case).
  • Rendered in the (previously empty) VerificationCodeCard footer, gated behind a new opt-in onDifferentAccountClicked prop so it does not appear on the first factor.
  • New localization key signIn.differentAccountAction ("Sign in as a different account").

Testing

  • e2e (integration/tests/session-tasks-setup-mfa.test.ts): enrolls SMS 2FA, signs out, signs back in to reach the second-factor step, clicks "Sign in as a different account", and asserts the user lands back on the sign-in identifier step.

Note

Getting the user out of Clerk's stuck state is handled here. Fully solving the OAuth "wrong account" case may also want prompt=select_account on the social connection so Google re-shows its account chooser on the retry — that is a separate connection/server-side concern and is not part of this change.

Screenshot 2026-07-17 at 11 33 42 AM

Checklist

  • Changeset added
  • e2e test added

Summary by CodeRabbit

  • New Features

    • Added a “Sign in as a different account” option during two-step verification.
    • Selecting the option returns users to the sign-in start screen.
  • Localization

    • Added localized text for the new account-switching action.
  • Tests

    • Added coverage verifying the option works during MFA sign-in flows.

@changeset-bot

changeset-bot Bot commented Jul 17, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 35f1b84

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 23 packages
Name Type
@clerk/ui Patch
@clerk/localizations Patch
@clerk/shared Patch
@clerk/astro Patch
@clerk/chrome-extension Patch
@clerk/react Patch
@clerk/swingset Patch
@clerk/vue Patch
@clerk/backend Patch
@clerk/clerk-js Patch
@clerk/electron Patch
@clerk/expo-passkeys Patch
@clerk/expo Patch
@clerk/express Patch
@clerk/fastify Patch
@clerk/headless Patch
@clerk/hono Patch
@clerk/msw Patch
@clerk/nextjs Patch
@clerk/nuxt Patch
@clerk/react-router Patch
@clerk/tanstack-react-start Patch
@clerk/testing Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Jul 17, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Jul 17, 2026 3:42pm
swingset Ready Ready Preview, Comment Jul 17, 2026 3:42pm

Request Review

@github-actions github-actions Bot added the ui label Jul 17, 2026
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The sign-in second-factor screen now displays a localized “Sign in as a different account” action. Activating it navigates back to the sign-in start, with integration coverage for the SMS MFA flow.

Changes

Different Account Sign-In

Layer / File(s) Summary
Localization and release contract
.changeset/sign-in-different-account.md, packages/localizations/src/en-US.ts, packages/shared/src/types/localization.ts
Adds the localized action text, its localization type entry, and patch release instructions for the affected packages.
Verification card navigation action
packages/ui/src/elements/VerificationCodeCard.tsx, packages/ui/src/components/SignIn/SignInFactorTwoCodeForm.tsx
Adds an optional callback and conditional footer link, then connects the link to navigation back to the sign-in start.
MFA flow validation
integration/tests/session-tasks-setup-mfa.test.ts
Tests abandoning an SMS MFA attempt and returning to the identifier input.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant VerificationCodeCard
  participant SignInFactorTwoCodeForm
  participant Router
  User->>VerificationCodeCard: Click different account action
  VerificationCodeCard->>SignInFactorTwoCodeForm: Invoke callback
  SignInFactorTwoCodeForm->>Router: navigate('../')
  Router-->>User: Show sign-in start
Loading

Poem

A bunny taps the footer bright,
And hops from second-factor night.
One click, the old attempt is gone,
Back to where a new sign-in dawns.
Localization twinkles too—
Tests hop along to prove it true.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main UI change: adding a “Sign in as a different account” action to second-factor sign-in screens.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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

@macroscopeapp

macroscopeapp Bot commented Jul 17, 2026

Copy link
Copy Markdown

Approvability

Verdict: Approved

This PR adds a simple navigation link to the 2FA screen allowing users to go back and sign in with a different account. The implementation is minimal (navigate('../')), well-tested, and doesn't modify any authentication logic. The unresolved review comments are minor test quality suggestions, not substantive issues.

You can customize Macroscope's approvability policy. Learn more.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/ui/src/components/SignUp/__tests__/SignUpVerifyEmail.test.tsx`:
- Around line 112-126: Restore the existing edit-icon test for SignUpVerifyEmail
while retaining the new back-button navigation test. Ensure both tests verify
their respective controls invoke the expected navigation behavior, using the
existing SignUpVerifyEmail fixture and render setup.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 05844200-3625-445a-b6d9-54a11600e470

📥 Commits

Reviewing files that changed from the base of the PR and between 89916b0 and 842edc4.

📒 Files selected for processing (5)
  • .changeset/two-step-back-button.md
  • packages/ui/src/components/SignIn/SignInFactorTwoCodeForm.tsx
  • packages/ui/src/components/SignIn/__tests__/SignInFactorTwo.test.tsx
  • packages/ui/src/components/SignUp/SignUpVerificationCodeForm.tsx
  • packages/ui/src/components/SignUp/__tests__/SignUpVerifyEmail.test.tsx

Comment on lines +112 to +126
it('clicking on the back button navigates to the previous route', async () => {
const { wrapper, fixtures } = await createFixtures(f => {
f.withEmailAddress({ required: true });
f.startSignUpWithEmailAddress({ emailAddress: 'test@clerk.com' });
});
fixtures.signUp.prepareEmailAddressVerification.mockRejectedValue(null);

const { userEvent } = render(<SignUpVerifyEmail />, { wrapper });
await userEvent.click(
screen.getByRole('button', {
name: /back/i,
}),
);
expect(fixtures.router.navigate).toHaveBeenCalledWith('../', { searchParams: new URLSearchParams() });
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Preserve the existing edit-button test.

This change replaces coverage for the edit icon even though onIdentityPreviewEditClicked={goBack} remains part of the component behavior. Restore the edit-icon test and keep this new back-button test so both controls remain covered.

As per coding guidelines, unit tests are required for all new functionality and should verify component behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/components/SignUp/__tests__/SignUpVerifyEmail.test.tsx`
around lines 112 - 126, Restore the existing edit-icon test for
SignUpVerifyEmail while retaining the new back-button navigation test. Ensure
both tests verify their respective controls invoke the expected navigation
behavior, using the existing SignUpVerifyEmail fixture and render setup.

Source: Coding guidelines

@pkg-pr-new

pkg-pr-new Bot commented Jul 17, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@9190

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@9190

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@9190

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@9190

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@9190

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@9190

@clerk/eslint-plugin

npm i https://pkg.pr.new/@clerk/eslint-plugin@9190

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@9190

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@9190

@clerk/express

npm i https://pkg.pr.new/@clerk/express@9190

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@9190

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@9190

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@9190

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@9190

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@9190

@clerk/react

npm i https://pkg.pr.new/@clerk/react@9190

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@9190

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@9190

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@9190

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@9190

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@9190

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@9190

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@9190

commit: 35f1b84

@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

API Changes Report

Generated by Break Check on 2026-07-17T15:45:03.056Z

Summary

Metric Count
Packages analyzed 19
Packages with changes 1
🔴 Breaking changes 0
🟡 Non-breaking changes 1
🟢 Additions 0

🤖 This report was reviewed by claude-sonnet-4-6.


@clerk/shared

Current version: 4.25.5
Recommended bump: MINOR → 4.26.0

Subpath ./types

🟡 Non-breaking Changes (1)

Modified: __internal_LocalizationResource
// ... 469 unchanged lines elided ...
        formSubtitle: LocalizationValue;
        resendButton: LocalizationValue;
      };
+     differentAccountAction: LocalizationValue;
      newDeviceVerificationNotice: LocalizationValue;
      phoneCodeMfa: {
        title: LocalizationValue;
// ... 1505 unchanged lines elided ...

Static analyzer: Breaking change in type alias __internal_LocalizationResource: Type changed: {locale:string;maintenanceMode:import("@clerk/shared").LocalizationValue;roles:{[r:string]:import("@clerk/shared").Loca…{locale:string;maintenanceMode:import("@clerk/shared").LocalizationValue;roles:{[r:string]:import("@clerk/shared").Loca…

🤖 AI review (reclassified as non-breaking) (60%): The diff shows /* ... 1901 lines elided ... */ vs /* ... 1900 lines elided ... */, indicating one new field was added somewhere in the middle of the type; __internal_LocalizationResource is used only as the source type for LocalizationResource via DeepPartial<DeepLocalizationWithoutObjects<...>>, making it an output/read type that consumers never construct directly, so adding a required property is non-breaking (rule 11).


Report generated by Break Check

Last ran on 35f1b84.

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Jul 17, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@integration/tests/session-tasks-setup-mfa.test.ts`:
- Around line 211-254: Wrap the setup and sign-in flow after createBapiUser in a
try/finally block, keeping user.deleteIfExists() in the finally clause so
cleanup runs on both success and failure. Apply this to the test flow using
createTestUtils and createBapiUser, matching the cleanup pattern used by the
email-code test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: c32bf548-d19a-4c21-b3dd-c19e90223e9c

📥 Commits

Reviewing files that changed from the base of the PR and between 842edc4 and 3d6aa39.

📒 Files selected for processing (4)
  • .changeset/testing-back-link-po.md
  • integration/tests/email-code.test.ts
  • integration/tests/session-tasks-setup-mfa.test.ts
  • packages/testing/src/playwright/unstable/page-objects/common.ts

Comment on lines +211 to +254
const u = createTestUtils({ app, page, context });
const user = u.services.users.createFakeUser({
fictionalEmail: true,
withPhoneNumber: true,
withPassword: true,
});
await u.services.users.createBapiUser(user);

// Enroll SMS as a second factor using the user's existing phone number.
await u.po.signIn.goTo();
await u.po.signIn.waitForMounted();
await u.po.signIn.signInWithEmailAndInstantPassword({ email: user.email, password: user.password });
await u.po.expect.toBeSignedIn();

await u.page.goToRelative('/page-protected');
await u.page.getByText(/set up two-step verification/i).waitFor({ state: 'visible' });
await u.page.getByRole('button', { name: /sms code/i }).click();
const formattedPhoneNumber = stringPhoneNumber(user.phoneNumber);
await u.page.getByRole('button', { name: formattedPhoneNumber }).click();
await u.page.getByText(/save these backup codes/i).waitFor({ state: 'visible', timeout: 10000 });
await u.po.signIn.continue();
await u.page.waitForAppUrl('/page-protected');
await u.po.expect.toBeSignedIn();

// Sign out and back in so the sign-in flow now requires the second factor.
await u.page.signOut();
await u.page.context().clearCookies();

await u.po.signIn.goTo();
await u.po.signIn.waitForMounted();
await u.po.signIn.getIdentifierInput().fill(user.email);
await u.po.signIn.setInstantPassword(user.password);
await u.po.signIn.continue();

// We are now on the two-step verification (second factor) step.
await u.page.getByText(/check your phone/i).waitFor({ state: 'visible' });

await u.po.signIn.getBackLink().click();

// Back returns to the identifier step.
await expect(u.po.signIn.getIdentifierInput()).toBeVisible();

await user.deleteIfExists();
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Guarantee fake-user cleanup on test failures.

A failure after createBapiUser() skips line 253 and leaves the BAPI user behind. Wrap the flow in try/finally, as the email-code test does.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integration/tests/session-tasks-setup-mfa.test.ts` around lines 211 - 254,
Wrap the setup and sign-in flow after createBapiUser in a try/finally block,
keeping user.deleteIfExists() in the finally clause so cleanup runs on both
success and failure. Apply this to the test flow using createTestUtils and
createBapiUser, matching the cleanup pattern used by the email-code test.

@macroscopeapp
macroscopeapp Bot dismissed their stale review July 17, 2026 14:07

Dismissing prior approval to re-evaluate 38b7883

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Jul 17, 2026
@alexcarpenter
alexcarpenter force-pushed the back-button-2fa-step branch from 38b7883 to 2c84e49 Compare July 17, 2026 15:35
@macroscopeapp
macroscopeapp Bot dismissed their stale review July 17, 2026 15:35

Dismissing prior approval to re-evaluate 2c84e49

@alexcarpenter alexcarpenter changed the title feat(ui): add back button to sign-in and sign-up verification steps feat(ui): add "Sign in as a different account" action to sign-in second factor Jul 17, 2026
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Jul 17, 2026
…nd factor

Adds a footer action on the sign-in two-step verification (second factor)
step that abandons the current sign-in attempt and returns to the sign-in
start, so a user who reached 2FA with the wrong account (e.g. wrong social
account) can sign in again instead of being stuck.
@alexcarpenter
alexcarpenter force-pushed the back-button-2fa-step branch from 2c84e49 to b90ea15 Compare July 17, 2026 15:36
@macroscopeapp
macroscopeapp Bot dismissed their stale review July 17, 2026 15:36

Dismissing prior approval to re-evaluate b90ea15

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Jul 17, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
packages/ui/src/elements/VerificationCodeCard.tsx (1)

45-54: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a regression test for the conditional footer action.

Cover the absent-callback case and verify that the localized signIn.differentAccountAction link invokes the supplied callback. This protects the new user-facing rendering and wiring behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/elements/VerificationCodeCard.tsx` around lines 45 - 54,
Update the tests for VerificationCodeCard to cover both footer states: assert
that no action renders when onDifferentAccountClicked is absent, and assert that
the localized signIn.differentAccountAction link renders and invokes the
supplied callback when provided.
packages/ui/src/components/SignIn/SignInFactorTwoCodeForm.tsx (1)

49-49: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add an explicit return type to the new handler.

signInAsDifferentUser currently relies on inference. Annotate it explicitly, for example:

Proposed fix
-  const signInAsDifferentUser = () => navigate('../');
+  const signInAsDifferentUser = (): void => {
+    void navigate('../');
+  };

As per coding guidelines, “Always define explicit return types for functions, especially public APIs.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/components/SignIn/SignInFactorTwoCodeForm.tsx` at line 49,
Update the signInAsDifferentUser handler to declare an explicit void return type
while preserving its existing navigate('../') behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/ui/src/components/SignIn/SignInFactorTwoCodeForm.tsx`:
- Line 49: Update the signInAsDifferentUser handler to declare an explicit void
return type while preserving its existing navigate('../') behavior.

In `@packages/ui/src/elements/VerificationCodeCard.tsx`:
- Around line 45-54: Update the tests for VerificationCodeCard to cover both
footer states: assert that no action renders when onDifferentAccountClicked is
absent, and assert that the localized signIn.differentAccountAction link renders
and invokes the supplied callback when provided.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 59b9554d-4d4d-4ee9-841b-867dca57b6eb

📥 Commits

Reviewing files that changed from the base of the PR and between 38b7883 and 2c84e49.

📒 Files selected for processing (6)
  • .changeset/sign-in-different-account.md
  • packages/clerk-js/sandbox/template.html
  • packages/localizations/src/en-US.ts
  • packages/shared/src/types/localization.ts
  • packages/ui/src/components/SignIn/SignInFactorTwoCodeForm.tsx
  • packages/ui/src/elements/VerificationCodeCard.tsx

@macroscopeapp
macroscopeapp Bot dismissed their stale review July 17, 2026 15:40

Dismissing prior approval to re-evaluate 35f1b84

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@integration/tests/session-tasks-setup-mfa.test.ts`:
- Around line 207-255: Extend the test around “Sign in as a different account”
to cover email-code and TOTP second-factor flows in addition to SMS, preferably
by parameterizing the factor setup and verification-step assertions. Preserve
the existing account-switching assertions while using each factor’s appropriate
enrollment and challenge UI.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 0f5e5a85-5d0f-4044-a0e6-9928d186f636

📥 Commits

Reviewing files that changed from the base of the PR and between 2c84e49 and 35f1b84.

📒 Files selected for processing (6)
  • .changeset/sign-in-different-account.md
  • integration/tests/session-tasks-setup-mfa.test.ts
  • packages/localizations/src/en-US.ts
  • packages/shared/src/types/localization.ts
  • packages/ui/src/components/SignIn/SignInFactorTwoCodeForm.tsx
  • packages/ui/src/elements/VerificationCodeCard.tsx
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/ui/src/components/SignIn/SignInFactorTwoCodeForm.tsx
  • packages/shared/src/types/localization.ts
  • packages/localizations/src/en-US.ts
  • packages/ui/src/elements/VerificationCodeCard.tsx
  • .changeset/sign-in-different-account.md

Comment on lines +207 to +255
test('can sign in as a different account from the two-step verification step', async ({ page, context }) => {
const u = createTestUtils({ app, page, context });
const user = u.services.users.createFakeUser({
fictionalEmail: true,
withPhoneNumber: true,
withPassword: true,
});
await u.services.users.createBapiUser(user);

// Enroll SMS as a second factor using the user's existing phone number.
await u.po.signIn.goTo();
await u.po.signIn.waitForMounted();
await u.po.signIn.signInWithEmailAndInstantPassword({ email: user.email, password: user.password });
await u.po.expect.toBeSignedIn();

await u.page.goToRelative('/page-protected');
await u.page.getByText(/set up two-step verification/i).waitFor({ state: 'visible' });
await u.page.getByRole('button', { name: /sms code/i }).click();
const formattedPhoneNumber = stringPhoneNumber(user.phoneNumber);
await u.page.getByRole('button', { name: formattedPhoneNumber }).click();
await u.page.getByText(/save these backup codes/i).waitFor({ state: 'visible', timeout: 10000 });
await u.po.signIn.continue();
await u.page.waitForAppUrl('/page-protected');
await u.po.expect.toBeSignedIn();

// Sign out and back in so the sign-in flow now requires the second factor.
await u.page.signOut();
await u.page.context().clearCookies();

await u.po.signIn.goTo();
await u.po.signIn.waitForMounted();
await u.po.signIn.getIdentifierInput().fill(user.email);
await u.po.signIn.setInstantPassword(user.password);
await u.po.signIn.continue();

// We are now on the two-step verification (SMS second factor) step, with no way to
// complete it if this is the wrong account.
await u.page.getByText(/check your phone/i).waitFor({ state: 'visible' });

// The "Sign in as a different account" action abandons the attempt and returns to the start.
const differentAccount = u.page.getByRole('link', { name: /sign in as a different account/i });
await expect(differentAccount).toBeVisible();
await differentAccount.click();

// Back on the sign-in start, where a different account can be used.
await expect(u.po.signIn.getIdentifierInput()).toBeVisible();

await user.deleteIfExists();
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Cover the email-code and TOTP variants.

This only exercises SMS, while the feature is introduced for TOTP, SMS, and email-code second-factor screens. Add equivalent coverage, or parameterize this scenario, for the remaining factor types. As per coding guidelines, “Include tests for all new features.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integration/tests/session-tasks-setup-mfa.test.ts` around lines 207 - 255,
Extend the test around “Sign in as a different account” to cover email-code and
TOTP second-factor flows in addition to SMS, preferably by parameterizing the
factor setup and verification-step assertions. Preserve the existing
account-switching assertions while using each factor’s appropriate enrollment
and challenge UI.

Source: Coding guidelines

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.

1 participant