Skip to content

Commit 000ddbc

Browse files
committed
fix(shadcn): Catch MFA assertion errors in sign up form
1 parent f037fb0 commit 000ddbc

File tree

2 files changed

+104
-5
lines changed

2 files changed

+104
-5
lines changed

packages/shadcn/src/components/sign-up-auth-screen.test.tsx

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { SignUpAuthScreen } from "./sign-up-auth-screen";
2020
import { createMockUI } from "../../tests/utils";
2121
import { registerLocale } from "@firebase-ui/translations";
2222
import { FirebaseUIProvider } from "@firebase-ui/react";
23+
import { MultiFactorResolver } from "firebase/auth";
2324

2425
vi.mock("./sign-up-auth-form", () => ({
2526
SignUpAuthForm: ({ onSignUp, onBackToSignInClick }: any) => (
@@ -31,6 +32,10 @@ vi.mock("./sign-up-auth-form", () => ({
3132
),
3233
}));
3334

35+
vi.mock("./multi-factor-auth-assertion-form", () => ({
36+
MultiFactorAuthAssertionForm: () => <div data-testid="mfa-assertion-form">MFA Assertion Form</div>,
37+
}));
38+
3439
describe("<SignUpAuthScreen />", () => {
3540
beforeEach(() => {
3641
vi.clearAllMocks();
@@ -144,4 +149,89 @@ describe("<SignUpAuthScreen />", () => {
144149
expect(screen.getByTestId("sign-up-auth-form")).toBeInTheDocument();
145150
expect(screen.queryByText("or")).not.toBeInTheDocument();
146151
});
152+
153+
it("should render MultiFactorAuthAssertionForm when multiFactorResolver is present", () => {
154+
const mockResolver = {
155+
auth: {} as any,
156+
session: null,
157+
hints: [],
158+
};
159+
const mockUI = createMockUI({
160+
locale: registerLocale("test", {
161+
labels: {
162+
signUp: "Register",
163+
},
164+
prompts: {
165+
enterDetailsToCreate: "Enter your details to create an account",
166+
},
167+
}),
168+
});
169+
mockUI.get().setMultiFactorResolver(mockResolver as unknown as MultiFactorResolver);
170+
171+
render(
172+
<FirebaseUIProvider ui={mockUI}>
173+
<SignUpAuthScreen />
174+
</FirebaseUIProvider>
175+
);
176+
177+
expect(screen.getByTestId("mfa-assertion-form")).toBeInTheDocument();
178+
expect(screen.queryByTestId("sign-up-auth-form")).not.toBeInTheDocument();
179+
});
180+
181+
it("should not render SignUpAuthForm when MFA resolver exists", () => {
182+
const mockResolver = {
183+
auth: {} as any,
184+
session: null,
185+
hints: [],
186+
};
187+
const mockUI = createMockUI({
188+
locale: registerLocale("test", {
189+
labels: {
190+
signUp: "Register",
191+
},
192+
prompts: {
193+
enterDetailsToCreate: "Enter your details to create an account",
194+
},
195+
messages: {
196+
dividerOr: "or",
197+
},
198+
}),
199+
});
200+
mockUI.get().setMultiFactorResolver(mockResolver as unknown as MultiFactorResolver);
201+
202+
render(
203+
<FirebaseUIProvider ui={mockUI}>
204+
<SignUpAuthScreen>
205+
<div data-testid="child-component">Child Component</div>
206+
</SignUpAuthScreen>
207+
</FirebaseUIProvider>
208+
);
209+
210+
expect(screen.queryByTestId("sign-up-auth-form")).not.toBeInTheDocument();
211+
expect(screen.getByTestId("mfa-assertion-form")).toBeInTheDocument();
212+
expect(screen.queryByText("or")).not.toBeInTheDocument();
213+
expect(screen.queryByTestId("child-component")).not.toBeInTheDocument();
214+
});
215+
216+
it("should render SignUpAuthForm when MFA resolver is not present", () => {
217+
const mockUI = createMockUI({
218+
locale: registerLocale("test", {
219+
labels: {
220+
signUp: "Register",
221+
},
222+
prompts: {
223+
enterDetailsToCreate: "Enter your details to create an account",
224+
},
225+
}),
226+
});
227+
228+
render(
229+
<FirebaseUIProvider ui={mockUI}>
230+
<SignUpAuthScreen />
231+
</FirebaseUIProvider>
232+
);
233+
234+
expect(screen.getByTestId("sign-up-auth-form")).toBeInTheDocument();
235+
expect(screen.queryByTestId("mfa-assertion-form")).not.toBeInTheDocument();
236+
});
147237
});

packages/shadcn/src/components/sign-up-auth-screen.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { useUI, type SignUpAuthScreenProps } from "@firebase-ui/react";
66
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
77
import { Separator } from "@/components/ui/separator";
88
import { SignUpAuthForm } from "@/components/sign-up-auth-form";
9+
import { MultiFactorAuthAssertionForm } from "@/components/multi-factor-auth-assertion-form";
910

1011
export type { SignUpAuthScreenProps };
1112

@@ -15,6 +16,8 @@ export function SignUpAuthScreen({ children, ...props }: SignUpAuthScreenProps)
1516
const titleText = getTranslation(ui, "labels", "signUp");
1617
const subtitleText = getTranslation(ui, "prompts", "enterDetailsToCreate");
1718

19+
const mfaResolver = ui.multiFactorResolver;
20+
1821
return (
1922
<div className="max-w-md mx-auto">
2023
<Card>
@@ -23,13 +26,19 @@ export function SignUpAuthScreen({ children, ...props }: SignUpAuthScreenProps)
2326
<CardDescription>{subtitleText}</CardDescription>
2427
</CardHeader>
2528
<CardContent>
26-
<SignUpAuthForm {...props} />
27-
{children ? (
29+
{mfaResolver ? (
30+
<MultiFactorAuthAssertionForm />
31+
) : (
2832
<>
29-
<Separator>{getTranslation(ui, "messages", "dividerOr")}</Separator>
30-
<div className="space-y-2">{children}</div>
33+
<SignUpAuthForm {...props} />
34+
{children ? (
35+
<>
36+
<Separator>{getTranslation(ui, "messages", "dividerOr")}</Separator>
37+
<div className="space-y-2">{children}</div>
38+
</>
39+
) : null}
3140
</>
32-
) : null}
41+
)}
3342
</CardContent>
3443
</Card>
3544
</div>

0 commit comments

Comments
 (0)