Skip to content

Commit 12bc067

Browse files
committed
test: Enhance email link and anonymous user upgrade test coverage
1 parent ba4e145 commit 12bc067

File tree

2 files changed

+80
-59
lines changed

2 files changed

+80
-59
lines changed

packages/firebaseui-core/tests/integration/auth.integration.test.ts

Lines changed: 68 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ import {
99
fuiSignInAnonymously,
1010
fuiSendPasswordResetEmail,
1111
fuiSignInWithOAuth,
12+
fuiCompleteEmailLinkSignIn,
13+
fuiConfirmPhoneNumber,
1214
} from '../../src/auth';
15+
import { FirebaseUIError } from '../../src/errors';
1316

1417
describe('Firebase UI Auth Integration', () => {
1518
let auth: Auth;
@@ -101,24 +104,29 @@ describe('Firebase UI Auth Integration', () => {
101104
});
102105

103106
describe('Email Link Authentication', () => {
104-
it('should initiate email link sign in', async () => {
107+
it('should manage email storage for email link sign in', async () => {
105108
const email = getUniqueEmail();
106-
await expect(fuiSendSignInLinkToEmail(auth, email)).resolves.not.toThrow();
107109

110+
// Should store email
111+
await fuiSendSignInLinkToEmail(auth, email);
108112
expect(window.localStorage.getItem('emailForSignIn')).toBe(email);
109-
});
110113

111-
// Note: Full email link sign-in flow can't be tested in integration tests
112-
// as it requires clicking the email link
113-
});
114+
// Should store anonymous upgrade flag - first sign in anonymously
115+
await fuiSignInAnonymously(auth);
116+
await fuiSendSignInLinkToEmail(auth, email, { enableAutoUpgradeAnonymous: true });
117+
expect(window.localStorage.getItem('emailLinkAnonymousUpgrade')).toBe('true');
114118

115-
describe('OAuth Authentication', () => {
116-
it.skip('should initiate OAuth sign in (skipped - requires user interaction)', async () => {
117-
const provider = new GoogleAuthProvider();
118-
await fuiSignInWithOAuth(auth, provider);
119+
// Should clean up storage after sign in attempt
120+
window.localStorage.setItem('emailForSignIn', email);
121+
window.localStorage.setItem('emailLinkAnonymousUpgrade', 'true');
122+
await fuiSendSignInLinkToEmail(auth, email);
123+
expect(window.localStorage.getItem('emailForSignIn')).toBe(email);
124+
expect(window.localStorage.getItem('emailLinkAnonymousUpgrade')).toBe(null);
119125
});
126+
});
120127

121-
it.skip('should handle OAuth for anonymous upgrade (skipped - requires user interaction)', async () => {
128+
describe('OAuth Authentication', () => {
129+
it.skip('should handle enableAutoUpgradeAnonymous flag for OAuth (skipped - requires user interaction)', async () => {
122130
await fuiSignInAnonymously(auth);
123131
const provider = new GoogleAuthProvider();
124132
await fuiSignInWithOAuth(auth, provider, { enableAutoUpgradeAnonymous: true });
@@ -128,7 +136,6 @@ describe('Firebase UI Auth Integration', () => {
128136
describe('Error Handling', () => {
129137
it('should handle duplicate email registration', async () => {
130138
const email = getUniqueEmail();
131-
132139
await fuiCreateUserWithEmailAndPassword(auth, email, testPassword);
133140
await signOut(auth);
134141

@@ -140,8 +147,6 @@ describe('Firebase UI Auth Integration', () => {
140147
await expect(fuiSignInWithEmailAndPassword(auth, email, 'password')).rejects.toThrow();
141148
});
142149

143-
// Note: Firebase Auth has lenient email validation.
144-
// We test only definitely invalid email formats here.
145150
it('should handle invalid email formats', async () => {
146151
const invalidEmails = [
147152
'invalid', // No @ symbol
@@ -155,15 +160,6 @@ describe('Firebase UI Auth Integration', () => {
155160
}
156161
});
157162

158-
it('should handle password requirements', async () => {
159-
const email = getUniqueEmail();
160-
const weakPasswords = ['', '123', 'short'];
161-
162-
for (const password of weakPasswords) {
163-
await expect(fuiCreateUserWithEmailAndPassword(auth, email, password)).rejects.toThrow();
164-
}
165-
});
166-
167163
it('should handle multiple anonymous account upgrades', async () => {
168164
const email = getUniqueEmail();
169165

@@ -203,4 +199,53 @@ describe('Firebase UI Auth Integration', () => {
203199
expect(results.every((result) => result.user.email === email)).toBe(true);
204200
});
205201
});
202+
203+
describe('Anonymous User Upgrade', () => {
204+
it('should maintain user data when upgrading anonymous account', async () => {
205+
// First create an anonymous user
206+
const anonResult = await fuiSignInAnonymously(auth);
207+
const anonUid = anonResult.user.uid;
208+
209+
// Upgrade to email/password
210+
const email = getUniqueEmail();
211+
const result = await fuiCreateUserWithEmailAndPassword(auth, email, testPassword, {
212+
enableAutoUpgradeAnonymous: true,
213+
});
214+
215+
// Verify it's the same user
216+
expect(result.user.uid).toBe(anonUid);
217+
expect(result.user.email).toBe(email);
218+
expect(result.user.isAnonymous).toBe(false);
219+
});
220+
221+
it('should handle enableAutoUpgradeAnonymous flag correctly', async () => {
222+
// Create an anonymous user
223+
await fuiSignInAnonymously(auth);
224+
const email = getUniqueEmail();
225+
226+
// Try to create new user without upgrade flag
227+
const result = await fuiCreateUserWithEmailAndPassword(auth, email, testPassword, {
228+
enableAutoUpgradeAnonymous: false,
229+
});
230+
231+
// Should be a new user, not an upgrade
232+
expect(result.user.isAnonymous).toBe(false);
233+
expect(result.user.email).toBe(email);
234+
});
235+
});
236+
237+
describe('Email Link Authentication State Management', () => {
238+
it('should handle multiple email link requests properly', async () => {
239+
const email1 = getUniqueEmail();
240+
const email2 = getUniqueEmail();
241+
242+
// First email link request
243+
await fuiSendSignInLinkToEmail(auth, email1);
244+
expect(window.localStorage.getItem('emailForSignIn')).toBe(email1);
245+
246+
// Second email link request should override the first
247+
await fuiSendSignInLinkToEmail(auth, email2);
248+
expect(window.localStorage.getItem('emailForSignIn')).toBe(email2);
249+
});
250+
});
206251
});

packages/firebaseui-core/tests/unit/auth.test.ts

Lines changed: 12 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -96,42 +96,6 @@ describe('Firebase UI Auth', () => {
9696
expect(linkWithCredential).toHaveBeenCalledWith(mockAuth.currentUser, mockCredential);
9797
expect(result).toBe(mockUserCredential);
9898
});
99-
100-
it('should throw FirebaseUIError on error', async () => {
101-
(signInWithCredential as any).mockRejectedValue(mockError);
102-
103-
await expect(fuiSignInWithEmailAndPassword(mockAuth, '[email protected]', 'password')).rejects.toBeInstanceOf(
104-
FirebaseUIError
105-
);
106-
});
107-
108-
it('should handle network errors', async () => {
109-
const networkError = { name: 'FirebaseError', code: 'auth/network-request-failed' };
110-
(signInWithCredential as any).mockRejectedValue(networkError);
111-
112-
await expect(fuiSignInWithEmailAndPassword(mockAuth, '[email protected]', 'password')).rejects.toThrow();
113-
});
114-
115-
it('should handle invalid email format', async () => {
116-
const invalidEmailError = { name: 'FirebaseError', code: 'auth/invalid-email' };
117-
(signInWithCredential as any).mockRejectedValue(invalidEmailError);
118-
119-
await expect(fuiSignInWithEmailAndPassword(mockAuth, 'invalid-email', 'password')).rejects.toThrow();
120-
});
121-
122-
it('should handle too many requests error', async () => {
123-
const tooManyRequestsError = { name: 'FirebaseError', code: 'auth/too-many-requests' };
124-
(signInWithCredential as any).mockRejectedValue(tooManyRequestsError);
125-
126-
await expect(fuiSignInWithEmailAndPassword(mockAuth, '[email protected]', 'password')).rejects.toThrow();
127-
});
128-
129-
it('should handle user disabled error', async () => {
130-
const userDisabledError = { name: 'FirebaseError', code: 'auth/user-disabled' };
131-
(signInWithCredential as any).mockRejectedValue(userDisabledError);
132-
133-
await expect(fuiSignInWithEmailAndPassword(mockAuth, '[email protected]', 'password')).rejects.toThrow();
134-
});
13599
});
136100

137101
describe('fuiCreateUserWithEmailAndPassword', () => {
@@ -347,6 +311,18 @@ describe('Firebase UI Auth', () => {
347311
expect(window.localStorage.getItem('emailForSignIn')).toBeNull();
348312
});
349313

314+
it('should clean up all storage items after sign in attempt', async () => {
315+
(isSignInWithEmailLink as any).mockReturnValue(true);
316+
window.localStorage.setItem('emailForSignIn', '[email protected]');
317+
window.localStorage.setItem('emailLinkAnonymousUpgrade', 'true');
318+
(signInWithCredential as any).mockResolvedValue(mockUserCredential);
319+
320+
await fuiCompleteEmailLinkSignIn(mockAuth, 'mock-url');
321+
322+
expect(window.localStorage.getItem('emailForSignIn')).toBeNull();
323+
expect(window.localStorage.getItem('emailLinkAnonymousUpgrade')).toBeNull();
324+
});
325+
350326
it('should return null when not a valid sign in link', async () => {
351327
(isSignInWithEmailLink as any).mockReturnValue(false);
352328

0 commit comments

Comments
 (0)