Skip to content

Commit 6142c8a

Browse files
committed
feat(core): signInWithCustomToken
1 parent 99753d9 commit 6142c8a

File tree

2 files changed

+85
-5
lines changed

2 files changed

+85
-5
lines changed

packages/core/src/auth.test.ts

Lines changed: 72 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,77 @@ 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(vi.mocked(mockUI.setState).mock.calls).toEqual([["pending"], ["idle"]]);
1005+
1006+
expect(_signInWithCustomToken).toHaveBeenCalledWith(mockUI.auth, customToken);
1007+
expect(_signInWithCustomToken).toHaveBeenCalledTimes(1);
1008+
1009+
expect(result).toEqual(mockUserCredential);
1010+
});
1011+
1012+
it("should call handleFirebaseError if an error is thrown", async () => {
1013+
const mockUI = createMockUI();
1014+
const customToken = "invalid-token";
1015+
const error = new FirebaseError("auth/invalid-custom-token", "Invalid custom token");
1016+
1017+
vi.mocked(_signInWithCustomToken).mockRejectedValue(error);
1018+
1019+
await signInWithCustomToken(mockUI, customToken);
1020+
1021+
expect(handleFirebaseError).toHaveBeenCalledWith(mockUI, error);
1022+
1023+
expect(vi.mocked(mockUI.setState).mock.calls).toEqual([["pending"], ["idle"]]);
1024+
});
1025+
1026+
it("should handle network errors", async () => {
1027+
const mockUI = createMockUI();
1028+
const customToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...";
1029+
const error = new Error("Network error");
1030+
1031+
vi.mocked(_signInWithCustomToken).mockRejectedValue(error);
1032+
1033+
await signInWithCustomToken(mockUI, customToken);
1034+
1035+
expect(handleFirebaseError).toHaveBeenCalledWith(mockUI, error);
1036+
1037+
expect(vi.mocked(mockUI.setState).mock.calls).toEqual([["pending"], ["idle"]]);
1038+
});
1039+
1040+
it("should handle expired custom token", async () => {
1041+
const mockUI = createMockUI();
1042+
const customToken = "expired-token";
1043+
const error = new FirebaseError("auth/custom-token-mismatch", "Custom token expired");
1044+
1045+
vi.mocked(_signInWithCustomToken).mockRejectedValue(error);
1046+
1047+
await signInWithCustomToken(mockUI, customToken);
1048+
1049+
expect(handleFirebaseError).toHaveBeenCalledWith(mockUI, error);
1050+
9841051
expect(vi.mocked(mockUI.setState).mock.calls).toEqual([["pending"], ["idle"]]);
9851052
});
9861053
});

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,
@@ -220,6 +221,18 @@ export async function signInWithCredential(ui: FirebaseUI, credential: AuthCrede
220221
}
221222
}
222223

224+
export async function signInWithCustomToken(ui: FirebaseUI, customToken: string): Promise<UserCredential> {
225+
try {
226+
ui.setState("pending");
227+
const result = await _signInWithCustomToken(ui.auth, customToken);
228+
return handlePendingCredential(ui, result);
229+
} catch (error) {
230+
handleFirebaseError(ui, error);
231+
} finally {
232+
ui.setState("idle");
233+
}
234+
}
235+
223236
export async function signInAnonymously(ui: FirebaseUI): Promise<UserCredential> {
224237
try {
225238
ui.setState("pending");

0 commit comments

Comments
 (0)