Skip to content

Commit 954d34f

Browse files
authored
refactor(core,react): signInWithPhoneNumber -> verifyPhoneNumber
2 parents fe9d851 + 85a3792 commit 954d34f

File tree

4 files changed

+120
-108
lines changed

4 files changed

+120
-108
lines changed

packages/core/src/auth.test.ts

Lines changed: 58 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
22
import {
33
signInWithEmailAndPassword,
44
createUserWithEmailAndPassword,
5-
signInWithPhoneNumber,
5+
verifyPhoneNumber,
66
confirmPhoneNumber,
77
sendPasswordResetEmail,
88
sendSignInLinkToEmail,
@@ -16,7 +16,6 @@ import {
1616
vi.mock("firebase/auth", () => ({
1717
signInWithCredential: vi.fn(),
1818
createUserWithEmailAndPassword: vi.fn(),
19-
signInWithPhoneNumber: vi.fn(),
2019
sendPasswordResetEmail: vi.fn(),
2120
sendSignInLinkToEmail: vi.fn(),
2221
signInAnonymously: vi.fn(),
@@ -26,9 +25,9 @@ vi.mock("firebase/auth", () => ({
2625
credential: vi.fn(),
2726
credentialWithLink: vi.fn(),
2827
},
29-
PhoneAuthProvider: {
28+
PhoneAuthProvider: Object.assign(vi.fn(), {
3029
credential: vi.fn(),
31-
},
30+
}),
3231
linkWithCredential: vi.fn(),
3332
}));
3433

@@ -47,15 +46,12 @@ import {
4746
EmailAuthProvider,
4847
PhoneAuthProvider,
4948
createUserWithEmailAndPassword as _createUserWithEmailAndPassword,
50-
signInWithPhoneNumber as _signInWithPhoneNumber,
5149
sendPasswordResetEmail as _sendPasswordResetEmail,
5250
sendSignInLinkToEmail as _sendSignInLinkToEmail,
5351
signInAnonymously as _signInAnonymously,
54-
signInWithRedirect,
5552
isSignInWithEmailLink as _isSignInWithEmailLink,
5653
UserCredential,
5754
Auth,
58-
ConfirmationResult,
5955
AuthProvider,
6056
TotpSecret,
6157
} from "firebase/auth";
@@ -195,7 +191,7 @@ describe("createUserWithEmailAndPassword", () => {
195191
const password = "password123";
196192

197193
const credential = EmailAuthProvider.credential(email, password);
198-
vi.mocked(hasBehavior).mockImplementation((ui, behavior) => {
194+
vi.mocked(hasBehavior).mockImplementation((_, behavior) => {
199195
if (behavior === "autoUpgradeAnonymousCredential") return true;
200196
if (behavior === "requireDisplayName") return false;
201197
return false;
@@ -221,7 +217,7 @@ describe("createUserWithEmailAndPassword", () => {
221217
const password = "password123";
222218

223219
const credential = EmailAuthProvider.credential(email, password);
224-
vi.mocked(hasBehavior).mockImplementation((ui, behavior) => {
220+
vi.mocked(hasBehavior).mockImplementation((_, behavior) => {
225221
if (behavior === "autoUpgradeAnonymousCredential") return true;
226222
if (behavior === "requireDisplayName") return false;
227223
return false;
@@ -380,44 +376,54 @@ describe("createUserWithEmailAndPassword", () => {
380376
});
381377
});
382378

383-
describe("signInWithPhoneNumber", () => {
379+
describe("verifyPhoneNumber", () => {
384380
beforeEach(() => {
385381
vi.clearAllMocks();
386382
});
387383

388-
it("should update state and call signInWithPhoneNumber successfully", async () => {
384+
it("should update state and call PhoneAuthProvider.verifyPhoneNumber successfully", async () => {
389385
const mockUI = createMockUI();
390386
const phoneNumber = "+1234567890";
391-
const mockRecaptchaVerifier = {} as any;
392-
const mockConfirmationResult = {
393-
verificationId: "test-verification-id",
394-
confirm: vi.fn(),
395-
} as any;
396-
397-
vi.mocked(_signInWithPhoneNumber).mockResolvedValue(mockConfirmationResult);
387+
const mockAppVerifier = {} as any;
388+
const mockVerificationId = "test-verification-id";
389+
390+
const mockVerifyPhoneNumber = vi.fn().mockResolvedValue(mockVerificationId);
391+
vi.mocked(PhoneAuthProvider).mockImplementation(
392+
() =>
393+
({
394+
verifyPhoneNumber: mockVerifyPhoneNumber,
395+
}) as any
396+
);
398397

399-
const result = await signInWithPhoneNumber(mockUI, phoneNumber, mockRecaptchaVerifier);
398+
const result = await verifyPhoneNumber(mockUI, phoneNumber, mockAppVerifier);
400399

401400
// Verify state management
402401
expect(vi.mocked(mockUI.setState).mock.calls).toEqual([["pending"], ["idle"]]);
403402

404-
// Verify the Firebase function was called with correct parameters
405-
expect(_signInWithPhoneNumber).toHaveBeenCalledWith(mockUI.auth, phoneNumber, mockRecaptchaVerifier);
406-
expect(_signInWithPhoneNumber).toHaveBeenCalledTimes(1);
403+
// Verify the PhoneAuthProvider was created and verifyPhoneNumber was called
404+
expect(PhoneAuthProvider).toHaveBeenCalledWith(mockUI.auth);
405+
expect(mockVerifyPhoneNumber).toHaveBeenCalledWith(phoneNumber, mockAppVerifier);
406+
expect(mockVerifyPhoneNumber).toHaveBeenCalledTimes(1);
407407

408408
// Verify the result
409-
expect(result).toEqual(mockConfirmationResult);
409+
expect(result).toEqual(mockVerificationId);
410410
});
411411

412412
it("should call handleFirebaseError if an error is thrown", async () => {
413413
const mockUI = createMockUI();
414414
const phoneNumber = "+1234567890";
415-
const mockRecaptchaVerifier = {} as any;
415+
const mockAppVerifier = {} as any;
416416
const error = new FirebaseError("auth/invalid-phone-number", "Invalid phone number");
417417

418-
vi.mocked(_signInWithPhoneNumber).mockRejectedValue(error);
418+
const mockVerifyPhoneNumber = vi.fn().mockRejectedValue(error);
419+
vi.mocked(PhoneAuthProvider).mockImplementation(
420+
() =>
421+
({
422+
verifyPhoneNumber: mockVerifyPhoneNumber,
423+
}) as any
424+
);
419425

420-
await signInWithPhoneNumber(mockUI, phoneNumber, mockRecaptchaVerifier);
426+
await verifyPhoneNumber(mockUI, phoneNumber, mockAppVerifier);
421427

422428
// Verify error handling
423429
expect(handleFirebaseError).toHaveBeenCalledWith(mockUI, error);
@@ -429,12 +435,18 @@ describe("signInWithPhoneNumber", () => {
429435
it("should handle recaptcha verification errors", async () => {
430436
const mockUI = createMockUI();
431437
const phoneNumber = "+1234567890";
432-
const mockRecaptchaVerifier = {} as any;
438+
const mockAppVerifier = {} as any;
433439
const error = new Error("reCAPTCHA verification failed");
434440

435-
vi.mocked(_signInWithPhoneNumber).mockRejectedValue(error);
441+
const mockVerifyPhoneNumber = vi.fn().mockRejectedValue(error);
442+
vi.mocked(PhoneAuthProvider).mockImplementation(
443+
() =>
444+
({
445+
verifyPhoneNumber: mockVerifyPhoneNumber,
446+
}) as any
447+
);
436448

437-
await signInWithPhoneNumber(mockUI, phoneNumber, mockRecaptchaVerifier);
449+
await verifyPhoneNumber(mockUI, phoneNumber, mockAppVerifier);
438450

439451
// Verify error handling
440452
expect(handleFirebaseError).toHaveBeenCalledWith(mockUI, error);
@@ -453,15 +465,15 @@ describe("confirmPhoneNumber", () => {
453465
const mockUI = createMockUI({
454466
auth: { currentUser: null } as Auth,
455467
});
456-
const confirmationResult = { verificationId: "test-verification-id" } as ConfirmationResult;
468+
const verificationId = "test-verification-id";
457469
const verificationCode = "123456";
458470

459-
const credential = PhoneAuthProvider.credential(confirmationResult.verificationId, verificationCode);
471+
const credential = PhoneAuthProvider.credential(verificationId, verificationCode);
460472
vi.mocked(hasBehavior).mockReturnValue(false);
461473
vi.mocked(PhoneAuthProvider.credential).mockReturnValue(credential);
462474
vi.mocked(_signInWithCredential).mockResolvedValue({ providerId: "phone" } as UserCredential);
463475

464-
const result = await confirmPhoneNumber(mockUI, confirmationResult, verificationCode);
476+
const result = await confirmPhoneNumber(mockUI, verificationId, verificationCode);
465477

466478
// Since currentUser is null, the behavior should not called.
467479
expect(hasBehavior).toHaveBeenCalledTimes(0);
@@ -480,16 +492,16 @@ describe("confirmPhoneNumber", () => {
480492
const mockUI = createMockUI({
481493
auth: { currentUser: { isAnonymous: true } } as Auth,
482494
});
483-
const confirmationResult = { verificationId: "test-verification-id" } as ConfirmationResult;
495+
const verificationId = "test-verification-id";
484496
const verificationCode = "123456";
485497

486-
const credential = PhoneAuthProvider.credential(confirmationResult.verificationId, verificationCode);
498+
const credential = PhoneAuthProvider.credential(verificationId, verificationCode);
487499
vi.mocked(hasBehavior).mockReturnValue(true);
488500
vi.mocked(PhoneAuthProvider.credential).mockReturnValue(credential);
489501
const mockBehavior = vi.fn().mockResolvedValue({ providerId: "phone" } as UserCredential);
490502
vi.mocked(getBehavior).mockReturnValue(mockBehavior);
491503

492-
const result = await confirmPhoneNumber(mockUI, confirmationResult, verificationCode);
504+
const result = await confirmPhoneNumber(mockUI, verificationId, verificationCode);
493505

494506
expect(hasBehavior).toHaveBeenCalledWith(mockUI, "autoUpgradeAnonymousCredential");
495507
expect(getBehavior).toHaveBeenCalledWith(mockUI, "autoUpgradeAnonymousCredential");
@@ -505,14 +517,14 @@ describe("confirmPhoneNumber", () => {
505517
const mockUI = createMockUI({
506518
auth: { currentUser: { isAnonymous: false } } as Auth,
507519
});
508-
const confirmationResult = { verificationId: "test-verification-id" } as ConfirmationResult;
520+
const verificationId = "test-verification-id";
509521
const verificationCode = "123456";
510522

511-
const credential = PhoneAuthProvider.credential(confirmationResult.verificationId, verificationCode);
523+
const credential = PhoneAuthProvider.credential(verificationId, verificationCode);
512524
vi.mocked(PhoneAuthProvider.credential).mockReturnValue(credential);
513525
vi.mocked(_signInWithCredential).mockResolvedValue({ providerId: "phone" } as UserCredential);
514526

515-
const result = await confirmPhoneNumber(mockUI, confirmationResult, verificationCode);
527+
const result = await confirmPhoneNumber(mockUI, verificationId, verificationCode);
516528

517529
// Behavior should not be called when user is not anonymous
518530
expect(hasBehavior).not.toHaveBeenCalled();
@@ -527,14 +539,14 @@ describe("confirmPhoneNumber", () => {
527539
const mockUI = createMockUI({
528540
auth: { currentUser: null } as Auth,
529541
});
530-
const confirmationResult = { verificationId: "test-verification-id" } as ConfirmationResult;
542+
const verificationId = "test-verification-id";
531543
const verificationCode = "123456";
532544

533-
const credential = PhoneAuthProvider.credential(confirmationResult.verificationId, verificationCode);
545+
const credential = PhoneAuthProvider.credential(verificationId, verificationCode);
534546
vi.mocked(PhoneAuthProvider.credential).mockReturnValue(credential);
535547
vi.mocked(_signInWithCredential).mockResolvedValue({ providerId: "phone" } as UserCredential);
536548

537-
const result = await confirmPhoneNumber(mockUI, confirmationResult, verificationCode);
549+
const result = await confirmPhoneNumber(mockUI, verificationId, verificationCode);
538550

539551
// Behavior should not be called when user is null
540552
expect(hasBehavior).not.toHaveBeenCalled();
@@ -549,16 +561,16 @@ describe("confirmPhoneNumber", () => {
549561
const mockUI = createMockUI({
550562
auth: { currentUser: { isAnonymous: true } } as Auth,
551563
});
552-
const confirmationResult = { verificationId: "test-verification-id" } as ConfirmationResult;
564+
const verificationId = "test-verification-id";
553565
const verificationCode = "123456";
554566

555-
const credential = PhoneAuthProvider.credential(confirmationResult.verificationId, verificationCode);
567+
const credential = PhoneAuthProvider.credential(verificationId, verificationCode);
556568
vi.mocked(hasBehavior).mockReturnValue(true);
557569
vi.mocked(PhoneAuthProvider.credential).mockReturnValue(credential);
558570
const mockBehavior = vi.fn().mockResolvedValue(undefined);
559571
vi.mocked(getBehavior).mockReturnValue(mockBehavior);
560572

561-
await confirmPhoneNumber(mockUI, confirmationResult, verificationCode);
573+
await confirmPhoneNumber(mockUI, verificationId, verificationCode);
562574

563575
expect(hasBehavior).toHaveBeenCalledWith(mockUI, "autoUpgradeAnonymousCredential");
564576
expect(getBehavior).toHaveBeenCalledWith(mockUI, "autoUpgradeAnonymousCredential");
@@ -576,14 +588,14 @@ describe("confirmPhoneNumber", () => {
576588
const mockUI = createMockUI({
577589
auth: { currentUser: null } as Auth,
578590
});
579-
const confirmationResult = { verificationId: "test-verification-id" } as ConfirmationResult;
591+
const verificationId = "test-verification-id";
580592
const verificationCode = "123456";
581593

582594
const error = new FirebaseError("auth/invalid-verification-code", "Invalid verification code");
583595

584596
vi.mocked(_signInWithCredential).mockRejectedValue(error);
585597

586-
await confirmPhoneNumber(mockUI, confirmationResult, verificationCode);
598+
await confirmPhoneNumber(mockUI, verificationId, verificationCode);
587599

588600
expect(handleFirebaseError).toHaveBeenCalledWith(mockUI, error);
589601
expect(vi.mocked(mockUI.setState).mock.calls).toEqual([["pending"], ["idle"]]);

packages/core/src/auth.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,17 @@ import {
2020
sendPasswordResetEmail as _sendPasswordResetEmail,
2121
sendSignInLinkToEmail as _sendSignInLinkToEmail,
2222
signInAnonymously as _signInAnonymously,
23-
signInWithPhoneNumber as _signInWithPhoneNumber,
2423
signInWithCredential as _signInWithCredential,
2524
ActionCodeSettings,
2625
ApplicationVerifier,
2726
AuthProvider,
28-
ConfirmationResult,
2927
EmailAuthProvider,
3028
linkWithCredential,
3129
PhoneAuthProvider,
3230
UserCredential,
3331
AuthCredential,
3432
TotpSecret,
33+
PhoneInfoOptions,
3534
} from "firebase/auth";
3635
import QRCode from "qrcode-generator";
3736
import { FirebaseUIConfiguration } from "./config";
@@ -121,14 +120,15 @@ export async function createUserWithEmailAndPassword(
121120
}
122121
}
123122

124-
export async function signInWithPhoneNumber(
123+
export async function verifyPhoneNumber(
125124
ui: FirebaseUIConfiguration,
126-
phoneNumber: string,
125+
phoneNumber: PhoneInfoOptions | string,
127126
appVerifier: ApplicationVerifier
128-
): Promise<ConfirmationResult> {
127+
): Promise<string> {
129128
try {
130129
ui.setState("pending");
131-
return await _signInWithPhoneNumber(ui.auth, phoneNumber, appVerifier);
130+
const provider = new PhoneAuthProvider(ui.auth);
131+
return await provider.verifyPhoneNumber(phoneNumber, appVerifier);
132132
} catch (error) {
133133
handleFirebaseError(ui, error);
134134
} finally {
@@ -138,13 +138,13 @@ export async function signInWithPhoneNumber(
138138

139139
export async function confirmPhoneNumber(
140140
ui: FirebaseUIConfiguration,
141-
confirmationResult: ConfirmationResult,
141+
verificationId: string,
142142
verificationCode: string
143143
): Promise<UserCredential> {
144144
try {
145145
ui.setState("pending");
146146
const currentUser = ui.auth.currentUser;
147-
const credential = PhoneAuthProvider.credential(confirmationResult.verificationId, verificationCode);
147+
const credential = PhoneAuthProvider.credential(verificationId, verificationCode);
148148

149149
if (currentUser?.isAnonymous && hasBehavior(ui, "autoUpgradeAnonymousCredential")) {
150150
const result = await getBehavior(ui, "autoUpgradeAnonymousCredential")(ui, credential);

0 commit comments

Comments
 (0)