@@ -1257,8 +1257,6 @@ describe("completeEmailLinkSignIn", () => {
12571257
12581258 expect ( _isSignInWithEmailLink ) . toHaveBeenCalledWith ( mockUI . auth , currentUrl ) ;
12591259 expect ( result ) . toBeNull ( ) ;
1260-
1261- expect ( vi . mocked ( mockUI . setState ) . mock . calls ) . toEqual ( [ [ "idle" ] ] ) ;
12621260 } ) ;
12631261
12641262 it ( "should return null when no email is stored in localStorage" , async ( ) => {
@@ -1271,7 +1269,6 @@ describe("completeEmailLinkSignIn", () => {
12711269
12721270 expect ( _isSignInWithEmailLink ) . toHaveBeenCalledWith ( mockUI . auth , currentUrl ) ;
12731271 expect ( result ) . toBeNull ( ) ;
1274- expect ( vi . mocked ( mockUI . setState ) . mock . calls ) . toEqual ( [ [ "idle" ] ] ) ;
12751272 } ) ;
12761273
12771274 it ( "should complete email link sign-in with no behavior" , async ( ) => {
@@ -1294,7 +1291,8 @@ describe("completeEmailLinkSignIn", () => {
12941291 expect ( EmailAuthProvider . credentialWithLink ) . toHaveBeenCalledWith ( email , currentUrl ) ;
12951292 expect ( _signInWithCredential ) . toHaveBeenCalledWith ( mockUI . auth , emailLinkCredential ) ;
12961293 expect ( result ) . toBe ( mockCredential ) ;
1297- expect ( vi . mocked ( mockUI . setState ) . mock . calls ) . toEqual ( [ [ "pending" ] , [ "pending" ] , [ "idle" ] , [ "idle" ] ] ) ;
1294+
1295+ expect ( vi . mocked ( mockUI . setState ) . mock . calls ) . toEqual ( [ [ "pending" ] , [ "idle" ] ] ) ;
12981296 expect ( window . localStorage . getItem ( "emailForSignIn" ) ) . toBeNull ( ) ;
12991297 } ) ;
13001298
@@ -1315,16 +1313,18 @@ describe("completeEmailLinkSignIn", () => {
13151313 const result = await completeEmailLinkSignIn ( mockUI , currentUrl ) ;
13161314
13171315 expect ( _isSignInWithEmailLink ) . toHaveBeenCalledWith ( mockUI . auth , currentUrl ) ;
1316+ // Behavior is checked by signInWithCredential (called via signInWithEmailLink)
13181317 expect ( hasBehavior ) . toHaveBeenCalledWith ( mockUI , "autoUpgradeAnonymousCredential" ) ;
13191318 expect ( EmailAuthProvider . credentialWithLink ) . toHaveBeenCalledWith ( email , currentUrl ) ;
13201319 expect ( getBehavior ) . toHaveBeenCalledWith ( mockUI , "autoUpgradeAnonymousCredential" ) ;
13211320 expect ( mockBehavior ) . toHaveBeenCalledWith ( mockUI , emailLinkCredential ) ;
13221321 expect ( result ) . toBe ( mockResult ) ;
1322+ // State is managed by signInWithCredential
13231323 expect ( vi . mocked ( mockUI . setState ) . mock . calls ) . toEqual ( [ [ "pending" ] , [ "idle" ] ] ) ;
13241324 expect ( window . localStorage . getItem ( "emailForSignIn" ) ) . toBeNull ( ) ;
13251325 } ) ;
13261326
1327- it ( "should fall back to signInWithEmailLink when autoUpgradeAnonymousCredential behavior returns undefined" , async ( ) => {
1327+ it ( "should fall back to _signInWithCredential when autoUpgradeAnonymousCredential behavior returns undefined" , async ( ) => {
13281328 const mockUI = createMockUI ( ) ;
13291329 const currentUrl = "https://example.com/auth?oobCode=abc123" ;
13301330 const email = "[email protected] " ; @@ -1342,17 +1342,19 @@ describe("completeEmailLinkSignIn", () => {
13421342 const result = await completeEmailLinkSignIn ( mockUI , currentUrl ) ;
13431343
13441344 expect ( _isSignInWithEmailLink ) . toHaveBeenCalledWith ( mockUI . auth , currentUrl ) ;
1345+ // Behavior is checked by signInWithCredential (called via signInWithEmailLink)
13451346 expect ( hasBehavior ) . toHaveBeenCalledWith ( mockUI , "autoUpgradeAnonymousCredential" ) ;
13461347 expect ( EmailAuthProvider . credentialWithLink ) . toHaveBeenCalledWith ( email , currentUrl ) ;
13471348 expect ( getBehavior ) . toHaveBeenCalledWith ( mockUI , "autoUpgradeAnonymousCredential" ) ;
13481349 expect ( mockBehavior ) . toHaveBeenCalledWith ( mockUI , emailLinkCredential ) ;
13491350 expect ( _signInWithCredential ) . toHaveBeenCalledWith ( mockUI . auth , emailLinkCredential ) ;
13501351 expect ( result ) . toBe ( mockResult ) ;
1351- expect ( vi . mocked ( mockUI . setState ) . mock . calls ) . toEqual ( [ [ "pending" ] , [ "pending" ] , [ "idle" ] , [ "idle" ] ] ) ;
1352+ // State is managed by signInWithCredential
1353+ expect ( vi . mocked ( mockUI . setState ) . mock . calls ) . toEqual ( [ [ "pending" ] , [ "idle" ] ] ) ;
13521354 expect ( window . localStorage . getItem ( "emailForSignIn" ) ) . toBeNull ( ) ;
13531355 } ) ;
13541356
1355- it ( "should call handleFirebaseError if an error is thrown " , async ( ) => {
1357+ it ( "should propagate error from signInWithEmailLink " , async ( ) => {
13561358 const mockUI = createMockUI ( ) ;
13571359 const currentUrl = "https://example.com/auth?oobCode=abc123" ;
13581360 const email = "[email protected] " ; @@ -1364,16 +1366,21 @@ describe("completeEmailLinkSignIn", () => {
13641366 vi . mocked ( hasBehavior ) . mockReturnValue ( false ) ;
13651367 vi . mocked ( EmailAuthProvider . credentialWithLink ) . mockReturnValue ( emailLinkCredential ) ;
13661368 vi . mocked ( _signInWithCredential ) . mockRejectedValue ( error ) ;
1369+ // handleFirebaseError throws, so we need to catch it
1370+ vi . mocked ( handleFirebaseError ) . mockImplementation ( ( ) => {
1371+ throw new Error ( "Handled error" ) ;
1372+ } ) ;
13671373
1368- const result = await completeEmailLinkSignIn ( mockUI , currentUrl ) ;
1374+ await expect ( completeEmailLinkSignIn ( mockUI , currentUrl ) ) . rejects . toThrow ( "Handled error" ) ;
13691375
1376+ // Error is handled by signInWithCredential (called via signInWithEmailLink)
13701377 expect ( handleFirebaseError ) . toHaveBeenCalledWith ( mockUI , error ) ;
1371- expect ( vi . mocked ( mockUI . setState ) . mock . calls ) . toEqual ( [ [ "pending" ] , [ "pending" ] , [ "idle" ] , [ "idle" ] ] ) ;
1378+ // State is managed by signInWithCredential
1379+ expect ( vi . mocked ( mockUI . setState ) . mock . calls ) . toEqual ( [ [ "pending" ] , [ "idle" ] ] ) ;
13721380 expect ( window . localStorage . getItem ( "emailForSignIn" ) ) . toBeNull ( ) ;
1373- expect ( result ) . toBeUndefined ( ) ;
13741381 } ) ;
13751382
1376- it ( "should call handleFirebaseError if autoUpgradeAnonymousCredential behavior throws error " , async ( ) => {
1383+ it ( "should propagate error when autoUpgradeAnonymousCredential behavior throws" , async ( ) => {
13771384 const mockUI = createMockUI ( ) ;
13781385 const currentUrl = "https://example.com/auth?oobCode=abc123" ;
13791386 const email = "[email protected] " ; @@ -1386,13 +1393,18 @@ describe("completeEmailLinkSignIn", () => {
13861393 vi . mocked ( EmailAuthProvider . credentialWithLink ) . mockReturnValue ( emailLinkCredential ) ;
13871394 const mockBehavior = vi . fn ( ) . mockRejectedValue ( error ) ;
13881395 vi . mocked ( getBehavior ) . mockReturnValue ( mockBehavior ) ;
1396+ // handleFirebaseError throws, so we need to catch it
1397+ vi . mocked ( handleFirebaseError ) . mockImplementation ( ( ) => {
1398+ throw new Error ( "Handled error" ) ;
1399+ } ) ;
13891400
1390- const result = await completeEmailLinkSignIn ( mockUI , currentUrl ) ;
1401+ await expect ( completeEmailLinkSignIn ( mockUI , currentUrl ) ) . rejects . toThrow ( "Handled error" ) ;
13911402
1403+ // Error is handled by signInWithCredential (called via signInWithEmailLink)
13921404 expect ( handleFirebaseError ) . toHaveBeenCalledWith ( mockUI , error ) ;
1405+ // State is managed by signInWithCredential
13931406 expect ( vi . mocked ( mockUI . setState ) . mock . calls ) . toEqual ( [ [ "pending" ] , [ "idle" ] ] ) ;
13941407 expect ( window . localStorage . getItem ( "emailForSignIn" ) ) . toBeNull ( ) ;
1395- expect ( result ) . toBeUndefined ( ) ;
13961408 } ) ;
13971409
13981410 it ( "should clear email from localStorage even when error occurs" , async ( ) => {
@@ -1407,9 +1419,14 @@ describe("completeEmailLinkSignIn", () => {
14071419 vi . mocked ( hasBehavior ) . mockReturnValue ( false ) ;
14081420 vi . mocked ( EmailAuthProvider . credentialWithLink ) . mockReturnValue ( emailLinkCredential ) ;
14091421 vi . mocked ( _signInWithCredential ) . mockRejectedValue ( error ) ;
1422+ // handleFirebaseError throws, but finally block should still run
1423+ vi . mocked ( handleFirebaseError ) . mockImplementation ( ( ) => {
1424+ throw new Error ( "Handled error" ) ;
1425+ } ) ;
14101426
1411- await completeEmailLinkSignIn ( mockUI , currentUrl ) ;
1427+ await expect ( completeEmailLinkSignIn ( mockUI , currentUrl ) ) . rejects . toThrow ( "Handled error" ) ;
14121428
1429+ // finally block should still clean up localStorage
14131430 expect ( window . localStorage . getItem ( "emailForSignIn" ) ) . toBeNull ( ) ;
14141431 } ) ;
14151432
0 commit comments