Skip to content

Commit ce4a169

Browse files
committed
feat: Add comprehensive error handling tests for FirebaseUIError
1 parent 12bc067 commit ce4a169

File tree

3 files changed

+136
-9
lines changed

3 files changed

+136
-9
lines changed

packages/firebaseui-core/src/auth.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,9 @@ import {
1818
RecaptchaVerifier,
1919
AuthProvider,
2020
} from 'firebase/auth';
21-
import { FirebaseUIError } from './errors';
21+
import { handleFirebaseError } from './errors';
2222
import { type TranslationsConfig } from './translations';
2323

24-
function handleFirebaseError(error: any, translations?: TranslationsConfig, language?: string): never {
25-
// TODO: Debug why instanceof FirebaseError is not working
26-
if (error?.name === 'FirebaseError') {
27-
throw new FirebaseUIError(error, translations, language);
28-
}
29-
throw new FirebaseUIError({ code: 'unknown' }, translations, language);
30-
}
31-
3224
export async function fuiSignInWithEmailAndPassword(
3325
auth: Auth,
3426
email: string,

packages/firebaseui-core/src/errors.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,11 @@ export class FirebaseUIError extends Error {
1313
this.code = errorCode;
1414
}
1515
}
16+
17+
export function handleFirebaseError(error: any, translations?: TranslationsConfig, language?: string): never {
18+
// TODO: Debug why instanceof FirebaseError is not working
19+
if (error?.name === 'FirebaseError') {
20+
throw new FirebaseUIError(error, translations, language);
21+
}
22+
throw new FirebaseUIError({ code: 'unknown' }, translations, language);
23+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import { describe, it, expect } from 'vitest';
2+
import { FirebaseUIError, handleFirebaseError } from '../../src/errors';
3+
4+
describe('FirebaseUIError', () => {
5+
describe('constructor', () => {
6+
it('should extract error code from Firebase error message', () => {
7+
const error = new FirebaseUIError({
8+
customData: { message: 'Firebase: Error (auth/user-not-found).' },
9+
});
10+
expect(error.code).toBe('auth/user-not-found');
11+
});
12+
13+
it('should use error code directly if available', () => {
14+
const error = new FirebaseUIError({ code: 'auth/wrong-password' });
15+
expect(error.code).toBe('auth/wrong-password');
16+
});
17+
18+
it('should fallback to unknown if no code is found', () => {
19+
const error = new FirebaseUIError({});
20+
expect(error.code).toBe('unknown');
21+
});
22+
23+
it('should use custom translations if provided', () => {
24+
const error = new FirebaseUIError(
25+
{ code: 'auth/user-not-found' },
26+
{
27+
es: {
28+
errors: {
29+
userNotFound: 'Usuario no encontrado',
30+
},
31+
},
32+
},
33+
'es'
34+
);
35+
expect(error.message).toBe('Usuario no encontrado');
36+
});
37+
38+
it('should fallback to default translation if language is not found', () => {
39+
const error = new FirebaseUIError(
40+
{ code: 'auth/user-not-found' },
41+
{
42+
en: {
43+
errors: {
44+
userNotFound: 'User not found',
45+
},
46+
},
47+
},
48+
'fr'
49+
);
50+
expect(error.message).toBe('User not found');
51+
});
52+
53+
it('should handle malformed error objects gracefully', () => {
54+
const error = new FirebaseUIError(null);
55+
expect(error.code).toBe('unknown');
56+
expect(error.name).toBe('FirebaseUIError');
57+
});
58+
59+
it('should set error name to FirebaseUIError', () => {
60+
const error = new FirebaseUIError({});
61+
expect(error.name).toBe('FirebaseUIError');
62+
});
63+
});
64+
});
65+
66+
describe('handleFirebaseError', () => {
67+
it('should throw FirebaseUIError for Firebase errors', () => {
68+
const firebaseError = {
69+
name: 'FirebaseError',
70+
code: 'auth/user-not-found',
71+
};
72+
73+
expect(() => handleFirebaseError(firebaseError)).toThrow(FirebaseUIError);
74+
});
75+
76+
it('should throw FirebaseUIError with unknown code for non-Firebase errors', () => {
77+
const error = new Error('Random error');
78+
79+
try {
80+
handleFirebaseError(error);
81+
} catch (e) {
82+
expect(e).toBeInstanceOf(FirebaseUIError);
83+
expect(e.code).toBe('unknown');
84+
}
85+
});
86+
87+
it('should pass translations to FirebaseUIError', () => {
88+
const firebaseError = {
89+
name: 'FirebaseError',
90+
code: 'auth/user-not-found',
91+
};
92+
93+
const translations = {
94+
es: {
95+
errors: {
96+
userNotFound: 'Usuario no encontrado',
97+
},
98+
},
99+
};
100+
101+
try {
102+
handleFirebaseError(firebaseError, translations, 'es');
103+
} catch (e) {
104+
expect(e).toBeInstanceOf(FirebaseUIError);
105+
expect(e.message).toBe('Usuario no encontrado');
106+
}
107+
});
108+
109+
it('should handle null/undefined errors', () => {
110+
expect(() => handleFirebaseError(null)).toThrow(FirebaseUIError);
111+
expect(() => handleFirebaseError(undefined)).toThrow(FirebaseUIError);
112+
});
113+
114+
it('should preserve the error code in thrown error', () => {
115+
const firebaseError = {
116+
name: 'FirebaseError',
117+
code: 'auth/wrong-password',
118+
};
119+
120+
try {
121+
handleFirebaseError(firebaseError);
122+
} catch (e) {
123+
expect(e).toBeInstanceOf(FirebaseUIError);
124+
expect(e.code).toBe('auth/wrong-password');
125+
}
126+
});
127+
});

0 commit comments

Comments
 (0)