Skip to content

Commit 11119ae

Browse files
authored
feat(core): signInWithCustomToken
2 parents 7695806 + 5f46b63 commit 11119ae

File tree

2 files changed

+91
-5
lines changed

2 files changed

+91
-5
lines changed

packages/core/src/auth.test.ts

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
signInWithCredential,
1111
signInAnonymously,
1212
signInWithProvider,
13+
signInWithCustomToken,
1314
generateTotpQrCode,
1415
} from "./auth";
1516

@@ -19,6 +20,7 @@ vi.mock("firebase/auth", () => ({
1920
sendPasswordResetEmail: vi.fn(),
2021
sendSignInLinkToEmail: vi.fn(),
2122
signInAnonymously: vi.fn(),
23+
signInWithCustomToken: vi.fn(),
2224
signInWithRedirect: vi.fn(),
2325
isSignInWithEmailLink: vi.fn(),
2426
EmailAuthProvider: {
@@ -49,6 +51,7 @@ import {
4951
sendPasswordResetEmail as _sendPasswordResetEmail,
5052
sendSignInLinkToEmail as _sendSignInLinkToEmail,
5153
signInAnonymously as _signInAnonymously,
54+
signInWithCustomToken as _signInWithCustomToken,
5255
isSignInWithEmailLink as _isSignInWithEmailLink,
5356
UserCredential,
5457
Auth,
@@ -958,14 +961,11 @@ describe("signInAnonymously", () => {
958961

959962
const result = await signInAnonymously(mockUI);
960963

961-
// Verify state management
962964
expect(vi.mocked(mockUI.setState).mock.calls).toEqual([["pending"], ["idle"]]);
963965

964-
// Verify the Firebase function was called with correct parameters
965966
expect(_signInAnonymously).toHaveBeenCalledWith(mockUI.auth);
966967
expect(_signInAnonymously).toHaveBeenCalledTimes(1);
967968

968-
// Verify the result
969969
expect(result).toEqual(mockUserCredential);
970970
});
971971

@@ -977,10 +977,83 @@ describe("signInAnonymously", () => {
977977

978978
await signInAnonymously(mockUI);
979979

980-
// Verify error handling
981980
expect(handleFirebaseError).toHaveBeenCalledWith(mockUI, error);
982981

983-
// Verify state management still happens
982+
expect(vi.mocked(mockUI.setState).mock.calls).toEqual([["pending"], ["idle"]]);
983+
});
984+
});
985+
986+
describe("signInWithCustomToken", () => {
987+
beforeEach(() => {
988+
vi.clearAllMocks();
989+
});
990+
991+
it("should update state and call signInWithCustomToken successfully", async () => {
992+
const mockUI = createMockUI();
993+
const customToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...";
994+
const mockUserCredential = {
995+
user: { uid: "custom-user-uid", email: "user@example.com" },
996+
providerId: "custom",
997+
operationType: "signIn",
998+
} as UserCredential;
999+
1000+
vi.mocked(_signInWithCustomToken).mockResolvedValue(mockUserCredential);
1001+
1002+
const result = await signInWithCustomToken(mockUI, customToken);
1003+
1004+
expect(mockUI.setRedirectError).toHaveBeenCalledWith(undefined);
1005+
expect(vi.mocked(mockUI.setState).mock.calls).toEqual([["pending"], ["idle"]]);
1006+
1007+
expect(_signInWithCustomToken).toHaveBeenCalledWith(mockUI.auth, customToken);
1008+
expect(_signInWithCustomToken).toHaveBeenCalledTimes(1);
1009+
1010+
expect(result).toEqual(mockUserCredential);
1011+
});
1012+
1013+
it("should call handleFirebaseError if an error is thrown", async () => {
1014+
const mockUI = createMockUI();
1015+
const customToken = "invalid-token";
1016+
const error = new FirebaseError("auth/invalid-custom-token", "Invalid custom token");
1017+
1018+
vi.mocked(_signInWithCustomToken).mockRejectedValue(error);
1019+
1020+
await signInWithCustomToken(mockUI, customToken);
1021+
1022+
expect(mockUI.setRedirectError).toHaveBeenCalledWith(undefined);
1023+
expect(handleFirebaseError).toHaveBeenCalledWith(mockUI, error);
1024+
1025+
expect(vi.mocked(mockUI.setState).mock.calls).toEqual([["pending"], ["idle"]]);
1026+
});
1027+
1028+
it("should handle network errors", async () => {
1029+
const mockUI = createMockUI();
1030+
const customToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...";
1031+
const error = new Error("Network error");
1032+
1033+
vi.mocked(_signInWithCustomToken).mockRejectedValue(error);
1034+
1035+
await signInWithCustomToken(mockUI, customToken);
1036+
1037+
// Verify redirect error is cleared even when network error occurs
1038+
expect(mockUI.setRedirectError).toHaveBeenCalledWith(undefined);
1039+
expect(handleFirebaseError).toHaveBeenCalledWith(mockUI, error);
1040+
1041+
expect(vi.mocked(mockUI.setState).mock.calls).toEqual([["pending"], ["idle"]]);
1042+
});
1043+
1044+
it("should handle expired custom token", async () => {
1045+
const mockUI = createMockUI();
1046+
const customToken = "expired-token";
1047+
const error = new FirebaseError("auth/custom-token-mismatch", "Custom token expired");
1048+
1049+
vi.mocked(_signInWithCustomToken).mockRejectedValue(error);
1050+
1051+
await signInWithCustomToken(mockUI, customToken);
1052+
1053+
// Verify redirect error is cleared even when token is expired
1054+
expect(mockUI.setRedirectError).toHaveBeenCalledWith(undefined);
1055+
expect(handleFirebaseError).toHaveBeenCalledWith(mockUI, error);
1056+
9841057
expect(vi.mocked(mockUI.setState).mock.calls).toEqual([["pending"], ["idle"]]);
9851058
});
9861059
});

packages/core/src/auth.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
sendSignInLinkToEmail as _sendSignInLinkToEmail,
2222
signInAnonymously as _signInAnonymously,
2323
signInWithCredential as _signInWithCredential,
24+
signInWithCustomToken as _signInWithCustomToken,
2425
EmailAuthProvider,
2526
linkWithCredential,
2627
PhoneAuthProvider,
@@ -254,6 +255,18 @@ export async function signInWithCredential(ui: FirebaseUI, credential: AuthCrede
254255
}
255256
}
256257

258+
export async function signInWithCustomToken(ui: FirebaseUI, customToken: string): Promise<UserCredential> {
259+
try {
260+
setPendingState(ui);
261+
const result = await _signInWithCustomToken(ui.auth, customToken);
262+
return handlePendingCredential(ui, result);
263+
} catch (error) {
264+
handleFirebaseError(ui, error);
265+
} finally {
266+
ui.setState("idle");
267+
}
268+
}
269+
257270
export async function signInAnonymously(ui: FirebaseUI): Promise<UserCredential> {
258271
try {
259272
setPendingState(ui);

0 commit comments

Comments
 (0)