Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 33 additions & 31 deletions auth/src/test/java/com/firebase/ui/auth/FirebaseAuthActivityTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -65,35 +65,44 @@ class FirebaseAuthActivityTest {

applicationContext = ApplicationProvider.getApplicationContext()

// Clear any existing Firebase apps
FirebaseApp.getApps(applicationContext).forEach { app ->
app.delete()
}
// Reuse FirebaseApps across tests in this class rather than deleting and
// re-initializing them for every test, to reduce churn on the "[DEFAULT]"
// app name (Robolectric shares statics across test methods in this class).
val secondaryApp = if (FirebaseApp.getApps(applicationContext).isEmpty()) {
FirebaseApp.initializeApp(
applicationContext,
FirebaseOptions.Builder()
.setApiKey("fake-api-key")
.setApplicationId("fake-app-id")
.setProjectId("fake-project-id")
.build()
)

// Initialize default FirebaseApp
FirebaseApp.initializeApp(
applicationContext,
FirebaseOptions.Builder()
.setApiKey("fake-api-key")
.setApplicationId("fake-app-id")
.setProjectId("fake-project-id")
.build()
)
val app = FirebaseApp.initializeApp(
applicationContext,
FirebaseOptions.Builder()
.setApiKey("fake-api-key-2")
.setApplicationId("fake-app-id-2")
.setProjectId("fake-project-id-2")
.build(),
"secondary"
)

val secondaryApp = FirebaseApp.initializeApp(
applicationContext,
FirebaseOptions.Builder()
.setApiKey("fake-api-key-2")
.setApplicationId("fake-app-id-2")
.setProjectId("fake-project-id-2")
.build(),
"secondary"
)
// Other test classes in this module independently delete and recreate
// the "[DEFAULT]" FirebaseApp. Newer firebase-auth releases sometimes
// surface that unrelated churn here as "FirebaseApp was deleted" from
// useEmulator(), even though the app we just initialized is live. This
// call is a defensive safety net (these tests drive UI state through
// mocks, never real network calls), so it's safe to ignore.
runCatching { FirebaseAuthUI.getInstance().auth.useEmulator("127.0.0.1", 9099) }
runCatching { FirebaseAuthUI.getInstance(app).auth.useEmulator("127.0.0.1", 9099) }
app
} else {
FirebaseApp.getInstance("secondary")
}

authUI = FirebaseAuthUI.getInstance()
authUI.auth.useEmulator("127.0.0.1", 9099)
secondaryAuthUI = FirebaseAuthUI.getInstance(secondaryApp)
secondaryAuthUI.auth.useEmulator("127.0.0.1", 9099)

configuration = AuthUIConfiguration(
context = applicationContext,
Expand All @@ -113,13 +122,6 @@ class FirebaseAuthActivityTest {
fun tearDown() {
FirebaseAuthActivity.clearLaunchStateCache()
FirebaseAuthUI.clearInstanceCache()
FirebaseApp.getApps(applicationContext).forEach { app ->
try {
app.delete()
} catch (_: Exception) {
// Ignore if already deleted
}
}
}

// =============================================================================================
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.firebase.ui.auth.testutil

import android.content.Context
import com.firebase.ui.auth.FirebaseAuthUI
import com.google.firebase.FirebaseApp
import com.google.firebase.FirebaseOptions

/**
* Returns the "[DEFAULT]" FirebaseApp used by e2e tests, pointed at the local Auth
* emulator, initializing it once per JVM instead of per test.
*
* Every test class used to delete and re-initialize this app in its own `@Before`.
* Robolectric shares statics across test classes within a run, so that churn raced
* with other classes doing the same thing; newer firebase-auth releases surface the
* loser of that race as "FirebaseApp was deleted" from useEmulator(). Per-test
* isolation is already handled by [EmulatorAuthApi.clearEmulatorData], so the app
* itself doesn't need to be recreated for every test.
*/
fun ensureTestFirebaseApp(context: Context): FirebaseApp {
FirebaseApp.getApps(context).firstOrNull { it.name == FirebaseApp.DEFAULT_APP_NAME }?.let {
return it
}

val app = FirebaseApp.initializeApp(
context,
FirebaseOptions.Builder()
.setApiKey("fake-api-key")
.setApplicationId("fake-app-id")
.setProjectId("fake-project-id")
.build()
)
FirebaseAuthUI.getInstance().auth.useEmulator("127.0.0.1", 9099)
return app
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,8 @@ import com.firebase.ui.auth.configuration.string_provider.DefaultAuthUIStringPro
import com.firebase.ui.auth.testutil.AUTH_STATE_WAIT_TIMEOUT_MS
import com.firebase.ui.auth.testutil.EmulatorAuthApi
import com.firebase.ui.auth.testutil.ensureFreshUser
import com.firebase.ui.auth.testutil.ensureTestFirebaseApp
import com.google.common.truth.Truth.assertThat
import com.google.firebase.FirebaseApp
import com.google.firebase.FirebaseOptions
import org.junit.After
import org.junit.Before
import org.junit.Rule
Expand Down Expand Up @@ -68,23 +67,8 @@ class AnonymousAuthScreenTest {

stringProvider = DefaultAuthUIStringProvider(applicationContext)

// Clear any existing Firebase apps
FirebaseApp.getApps(applicationContext).forEach { app ->
app.delete()
}

// Initialize default FirebaseApp
val firebaseApp = FirebaseApp.initializeApp(
applicationContext,
FirebaseOptions.Builder()
.setApiKey("fake-api-key")
.setApplicationId("fake-app-id")
.setProjectId("fake-project-id")
.build()
)

val firebaseApp = ensureTestFirebaseApp(applicationContext)
authUI = FirebaseAuthUI.getInstance()
authUI.auth.useEmulator("127.0.0.1", 9099)

emulatorApi = EmulatorAuthApi(
projectId = firebaseApp.options.projectId
Expand All @@ -99,7 +83,10 @@ class AnonymousAuthScreenTest {

@After
fun tearDown() {
// Clean up after each test to prevent test pollution
// Clean up after each test to prevent test pollution. The FirebaseApp itself is
// shared across test classes (see ensureTestFirebaseApp), so the client-side
// session must be reset explicitly here rather than relying on app re-creation.
authUI.auth.signOut()
FirebaseAuthUI.clearInstanceCache()

// Clear emulator data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,11 @@ import com.firebase.ui.auth.testutil.EmulatorAuthApi
import com.firebase.ui.auth.testutil.awaitWithLooper
import com.firebase.ui.auth.testutil.ensureFreshUser
import com.firebase.ui.auth.testutil.generateMockGoogleIdToken
import com.firebase.ui.auth.testutil.ensureTestFirebaseApp
import com.firebase.ui.auth.testutil.verifyEmailInEmulator
import com.firebase.ui.auth.util.CountryUtils
import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential
import com.google.common.truth.Truth.assertThat
import com.google.firebase.FirebaseApp
import com.google.firebase.FirebaseOptions
import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Assume
Expand Down Expand Up @@ -89,21 +88,8 @@ class CredentialLinkingScreenTest {
applicationContext = ApplicationProvider.getApplicationContext()
stringProvider = DefaultAuthUIStringProvider(applicationContext)

FirebaseApp.getApps(applicationContext).forEach { app ->
app.delete()
}

val firebaseApp = FirebaseApp.initializeApp(
applicationContext,
FirebaseOptions.Builder()
.setApiKey("fake-api-key")
.setApplicationId("fake-app-id")
.setProjectId("fake-project-id")
.build()
)

val firebaseApp = ensureTestFirebaseApp(applicationContext)
authUI = FirebaseAuthUI.getInstance()
authUI.auth.useEmulator("127.0.0.1", 9099)

authUI.testCredentialManagerProvider = object : AuthProvider.Google.CredentialManagerProvider {
override suspend fun getGoogleCredential(
Expand Down Expand Up @@ -137,6 +123,7 @@ class CredentialLinkingScreenTest {

@After
fun tearDown() {
authUI.auth.signOut()
FirebaseAuthUI.clearInstanceCache()
emulatorApi.clearEmulatorData()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,9 @@ import com.firebase.ui.auth.testutil.AUTH_STATE_WAIT_TIMEOUT_MS
import com.firebase.ui.auth.testutil.EmailLinkTestActivity
import com.firebase.ui.auth.testutil.EmulatorAuthApi
import com.firebase.ui.auth.testutil.ensureFreshUser
import com.firebase.ui.auth.testutil.ensureTestFirebaseApp
import com.firebase.ui.auth.testutil.verifyEmailInEmulator
import com.google.common.truth.Truth.assertThat
import com.google.firebase.FirebaseApp
import com.google.firebase.FirebaseOptions
import com.google.firebase.auth.actionCodeSettings
import kotlinx.coroutines.runBlocking
import org.junit.After
Expand Down Expand Up @@ -97,23 +96,8 @@ class EmailAuthScreenTest {

stringProvider = DefaultAuthUIStringProvider(applicationContext)

// Clear any existing Firebase apps
FirebaseApp.getApps(applicationContext).forEach { app ->
app.delete()
}

// Initialize default FirebaseApp
val firebaseApp = FirebaseApp.initializeApp(
applicationContext,
FirebaseOptions.Builder()
.setApiKey("fake-api-key")
.setApplicationId("fake-app-id")
.setProjectId("fake-project-id")
.build()
)

val firebaseApp = ensureTestFirebaseApp(applicationContext)
authUI = FirebaseAuthUI.getInstance()
authUI.auth.useEmulator("127.0.0.1", 9099)

emulatorApi = EmulatorAuthApi(
projectId = firebaseApp.options.projectId
Expand All @@ -138,7 +122,10 @@ class EmailAuthScreenTest {
fun tearDown() {
closeable.close()

// Clean up after each test to prevent test pollution
// Clean up after each test to prevent test pollution. The FirebaseApp itself is
// shared across test classes (see ensureTestFirebaseApp), so the client-side
// session must be reset explicitly here rather than relying on app re-creation.
authUI.auth.signOut()
FirebaseAuthUI.clearInstanceCache()

// Clear emulator data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,10 @@ import com.firebase.ui.auth.configuration.string_provider.AuthUIStringProvider
import com.firebase.ui.auth.configuration.string_provider.DefaultAuthUIStringProvider
import com.firebase.ui.auth.testutil.AUTH_STATE_WAIT_TIMEOUT_MS
import com.firebase.ui.auth.testutil.EmulatorAuthApi
import com.firebase.ui.auth.testutil.ensureTestFirebaseApp
import com.firebase.ui.auth.testutil.generateMockGoogleIdToken
import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential
import com.google.common.truth.Truth.assertThat
import com.google.firebase.FirebaseApp
import com.google.firebase.FirebaseOptions
import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Before
Expand Down Expand Up @@ -85,23 +84,8 @@ class GoogleAuthScreenTest {

stringProvider = DefaultAuthUIStringProvider(applicationContext)

// Clear any existing Firebase apps
FirebaseApp.getApps(applicationContext).forEach { app ->
app.delete()
}

// Initialize default FirebaseApp
val firebaseApp = FirebaseApp.initializeApp(
applicationContext,
FirebaseOptions.Builder()
.setApiKey("fake-api-key")
.setApplicationId("fake-app-id")
.setProjectId("fake-project-id")
.build()
)

val firebaseApp = ensureTestFirebaseApp(applicationContext)
authUI = FirebaseAuthUI.getInstance()
authUI.auth.useEmulator("127.0.0.1", 9099)

val testCredentialManagerProvider = object : AuthProvider.Google.CredentialManagerProvider {
override suspend fun getGoogleCredential(
Expand Down Expand Up @@ -140,7 +124,10 @@ class GoogleAuthScreenTest {

@After
fun tearDown() {
// Clean up after each test to prevent test pollution
// Clean up after each test to prevent test pollution. The FirebaseApp itself is
// shared across test classes (see ensureTestFirebaseApp), so the client-side
// session must be reset explicitly here rather than relying on app re-creation.
authUI.auth.signOut()
FirebaseAuthUI.clearInstanceCache()

// Clear emulator data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,8 @@ import com.firebase.ui.auth.configuration.string_provider.AuthUIStringProvider
import com.firebase.ui.auth.configuration.string_provider.DefaultAuthUIStringProvider
import com.firebase.ui.auth.configuration.string_provider.LocalAuthUIStringProvider
import com.firebase.ui.auth.mfa.MfaChallengeContentState
import com.firebase.ui.auth.testutil.ensureTestFirebaseApp
import com.google.common.truth.Truth.assertThat
import com.google.firebase.FirebaseApp
import com.google.firebase.FirebaseOptions
import com.google.firebase.auth.MultiFactorInfo
import com.google.firebase.auth.MultiFactorResolver
import com.google.firebase.auth.MultiFactorSession
Expand Down Expand Up @@ -91,23 +90,8 @@ class MfaChallengeScreenTest {
applicationContext = ApplicationProvider.getApplicationContext()
stringProvider = DefaultAuthUIStringProvider(applicationContext)

// Clear any existing Firebase apps
FirebaseApp.getApps(applicationContext).forEach { app ->
app.delete()
}

// Initialize default FirebaseApp
FirebaseApp.initializeApp(
applicationContext,
FirebaseOptions.Builder()
.setApiKey("fake-api-key")
.setApplicationId("fake-app-id")
.setProjectId("fake-project-id")
.build()
)

ensureTestFirebaseApp(applicationContext)
authUI = FirebaseAuthUI.getInstance()
authUI.auth.useEmulator("127.0.0.1", 9099)

// Setup mock resolver
`when`(mockResolver.session).thenReturn(mockSession)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ import com.firebase.ui.auth.configuration.string_provider.AuthUIStringProvider
import com.firebase.ui.auth.configuration.string_provider.DefaultAuthUIStringProvider
import com.firebase.ui.auth.testutil.AUTH_STATE_WAIT_TIMEOUT_MS
import com.firebase.ui.auth.testutil.EmulatorAuthApi
import com.firebase.ui.auth.testutil.ensureTestFirebaseApp
import com.google.common.truth.Truth.assertThat
import com.google.firebase.FirebaseApp
import com.google.firebase.FirebaseOptions
import org.junit.After
import org.junit.Before
import org.junit.Ignore
Expand Down Expand Up @@ -58,23 +57,8 @@ class MfaDisabledTest {
applicationContext = ApplicationProvider.getApplicationContext()
stringProvider = DefaultAuthUIStringProvider(applicationContext)

// Clear any existing Firebase apps
FirebaseApp.getApps(applicationContext).forEach { app ->
app.delete()
}

// Initialize default FirebaseApp
val firebaseApp = FirebaseApp.initializeApp(
applicationContext,
FirebaseOptions.Builder()
.setApiKey("fake-api-key")
.setApplicationId("fake-app-id")
.setProjectId("fake-project-id")
.build()
)

val firebaseApp = ensureTestFirebaseApp(applicationContext)
authUI = FirebaseAuthUI.getInstance()
authUI.auth.useEmulator("127.0.0.1", 9099)

emulatorApi = EmulatorAuthApi(
projectId = firebaseApp.options.projectId
Expand All @@ -89,7 +73,10 @@ class MfaDisabledTest {

@After
fun tearDown() {
// Clean up after each test to prevent test pollution
// Clean up after each test to prevent test pollution. The FirebaseApp itself is
// shared across test classes (see ensureTestFirebaseApp), so the client-side
// session must be reset explicitly here rather than relying on app re-creation.
authUI.auth.signOut()
FirebaseAuthUI.clearInstanceCache()

// Clear emulator data
Expand Down
Loading
Loading