@@ -6,6 +6,7 @@ import androidx.compose.runtime.Composable
66import androidx.compose.runtime.collectAsState
77import androidx.compose.runtime.getValue
88import androidx.compose.ui.test.assertIsDisplayed
9+ import androidx.compose.ui.test.assertIsNotDisplayed
910import androidx.compose.ui.test.junit4.createComposeRule
1011import androidx.compose.ui.test.onNodeWithText
1112import androidx.compose.ui.test.performClick
@@ -27,6 +28,7 @@ import com.google.firebase.FirebaseApp
2728import com.google.firebase.FirebaseOptions
2829import com.google.firebase.auth.AuthResult
2930import com.google.firebase.auth.FirebaseUser
31+ import com.google.firebase.auth.actionCodeSettings
3032import org.junit.After
3133import org.junit.Before
3234import org.junit.Rule
@@ -85,6 +87,9 @@ class EmailAuthScreenTest {
8587 fun tearDown () {
8688 // Clean up after each test to prevent test pollution
8789 FirebaseAuthUI .clearInstanceCache()
90+
91+ // Clear emulator data
92+ clearEmulatorData()
8893 }
8994
9095 @Test
@@ -402,10 +407,102 @@ class EmailAuthScreenTest {
402407 assertThat(authUI.auth.currentUser).isNull()
403408 composeTestRule.onNodeWithText(stringProvider.recoverPasswordLinkSentDialogTitle)
404409 .assertIsDisplayed()
410+ composeTestRule.onNodeWithText(stringProvider.recoverPasswordLinkSentDialogBody(email))
411+ .assertIsDisplayed()
412+ composeTestRule.onNodeWithText(stringProvider.dismissAction)
413+ .assertIsDisplayed()
414+ .performClick()
415+ composeTestRule.waitForIdle()
416+ composeTestRule.onNodeWithText(stringProvider.recoverPasswordLinkSentDialogTitle)
417+ .assertIsNotDisplayed()
418+ composeTestRule.onNodeWithText(stringProvider.signInDefault)
419+ .assertIsDisplayed()
420+ }
421+
422+ @Test
423+ fun `email link sign in emits EmailSignInLinkSent auth state and shows dialog` () {
424+ 425+ val password = " test123"
426+
427+ // Setup: Create a fresh user
428+ ensureFreshUser(email, password)
429+
430+ // Sign out
431+ authUI.auth.signOut()
432+ shadowOf(Looper .getMainLooper()).idle()
433+
434+ val configuration = authUIConfiguration {
435+ context = applicationContext
436+ providers {
437+ provider(
438+ AuthProvider .Email (
439+ isEmailLinkSignInEnabled = true ,
440+ isEmailLinkForceSameDeviceEnabled = true ,
441+ emailLinkActionCodeSettings = actionCodeSettings {
442+ // The continue URL - where to redirect after email link is clicked
443+ url = " https://fake-project-id.firebaseapp.com"
444+ handleCodeInApp = true
445+ setAndroidPackageName(
446+ " fake.project.id" ,
447+ true ,
448+ null
449+ )
450+ },
451+ passwordValidationRules = emptyList()
452+ )
453+ )
454+ }
455+ }
456+
457+ // Track auth state changes
458+ var currentAuthState: AuthState = AuthState .Idle
459+
460+ composeTestRule.setContent {
461+ FirebaseAuthScreen (configuration = configuration)
462+ val authState by authUI.authStateFlow().collectAsState(AuthState .Idle )
463+ currentAuthState = authState
464+ }
465+
466+ composeTestRule.onNodeWithText(stringProvider.signInDefault)
467+ .assertIsDisplayed()
468+ composeTestRule.onNodeWithText(stringProvider.emailHint)
469+ .performScrollTo()
470+ .assertIsDisplayed()
471+ .performTextInput(email)
472+ composeTestRule.onNodeWithText(stringProvider.signInDefault.uppercase())
473+ .performScrollTo()
474+ .assertIsDisplayed()
475+ .performClick()
476+
477+ println (" TEST: Pumping looper after click..." )
478+ shadowOf(Looper .getMainLooper()).idle()
479+
480+ // Wait for auth state to transition to EmailSignInLinkSent
481+ println (" TEST: Waiting for auth state change... Current state: $currentAuthState " )
482+ composeTestRule.waitUntil {
483+ shadowOf(Looper .getMainLooper()).idle()
484+ println (" TEST: Auth state during wait: $currentAuthState " )
485+ currentAuthState is AuthState .EmailSignInLinkSent
486+ }
487+
488+ // Ensure final recomposition is complete before assertions
489+ shadowOf(Looper .getMainLooper()).idle()
490+
491+ // Verify the auth state and user properties
492+ println (" TEST: Verifying final auth state: $currentAuthState " )
493+ assertThat(currentAuthState)
494+ .isInstanceOf(AuthState .EmailSignInLinkSent ::class .java)
495+ assertThat(authUI.auth.currentUser).isNull()
496+ composeTestRule.onNodeWithText(stringProvider.emailSignInLinkSentDialogTitle)
497+ .assertIsDisplayed()
498+ composeTestRule.onNodeWithText(stringProvider.emailSignInLinkSentDialogBody(email))
499+ .assertIsDisplayed()
405500 composeTestRule.onNodeWithText(stringProvider.dismissAction)
406501 .assertIsDisplayed()
407502 .performClick()
408503 composeTestRule.waitForIdle()
504+ composeTestRule.onNodeWithText(stringProvider.emailSignInLinkSentDialogTitle)
505+ .assertIsNotDisplayed()
409506 composeTestRule.onNodeWithText(stringProvider.signInDefault)
410507 .assertIsDisplayed()
411508 }
0 commit comments