generated from grodin/kotlin-android-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Joseph Cooper
committed
Mar 10, 2023
1 parent
608a764
commit 537b985
Showing
7 changed files
with
195 additions
and
53 deletions.
There are no files selected for viewing
12 changes: 12 additions & 0 deletions
12
.../firebase/src/main/kotlin/com/omricat/maplibrarian/firebase/FirebaseEmulatorConnection.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.omricat.maplibrarian.firebase | ||
|
||
object FirebaseEmulatorConnection { | ||
|
||
// Connects to host computer from Android emulator | ||
const val HOST = "10.0.2.2" | ||
|
||
const val AUTH_PORT = 9099 | ||
|
||
const val FIRESTORE_PORT = 8080 | ||
|
||
} |
97 changes: 97 additions & 0 deletions
97
...-tests/firebase/src/main/kotlin/com/omricat/maplibrarian/firebase/FirebaseEndToEndTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package com.omricat.maplibrarian.firebase | ||
|
||
import com.github.michaelbull.result.Ok | ||
import com.github.michaelbull.result.getOrThrow | ||
import com.google.firebase.auth.FirebaseAuth | ||
import com.google.firebase.firestore.FirebaseFirestore | ||
import com.omricat.maplibrarian.auth.EmailPasswordCredential | ||
import com.omricat.maplibrarian.chartlist.FirebaseChartsService | ||
import com.omricat.maplibrarian.firebase.auth.FirebaseAuthEmulatorRestApi | ||
import com.omricat.maplibrarian.firebase.auth.FirebaseAuthService | ||
import com.omricat.maplibrarian.firebase.charts.FirebaseFirestoreRestApi | ||
import com.omricat.maplibrarian.model.DbChartModel | ||
import com.omricat.maplibrarian.model.UnsavedChartModel | ||
import kotlinx.coroutines.ExperimentalCoroutinesApi | ||
import kotlinx.coroutines.test.runTest | ||
import org.junit.Before | ||
import org.junit.BeforeClass | ||
import org.junit.Test | ||
|
||
@OptIn(ExperimentalCoroutinesApi::class) | ||
class FirebaseEndToEndTest { | ||
|
||
@Before | ||
fun clearData() { | ||
authApi.deleteAllUsers() | ||
firestoreApi.deleteAllData() | ||
} | ||
|
||
private val testCredential = EmailPasswordCredential("[email protected]", "password") | ||
|
||
@Test | ||
fun addUser_addCharts_queryCharts() = runTest { | ||
val testDispatcherProvider = TestDispatcherProvider(testScheduler) | ||
val userRepository = FirebaseAuthService(firebaseAuthInstance, testDispatcherProvider) | ||
|
||
val chartsRepository = FirebaseChartsService(firestoreInstance, testDispatcherProvider) | ||
|
||
val createUserResult = userRepository.createUser(testCredential) | ||
|
||
val user = createUserResult.getOrThrow { AssertionError(it) } | ||
|
||
val addChartResult = | ||
chartsRepository.addNewChart(user, UnsavedChartModel(user.id, "New map")) | ||
|
||
assert(addChartResult is Ok<DbChartModel>) | ||
|
||
val queryChartResult = | ||
chartsRepository.chartsListForUser(user) | ||
|
||
queryChartResult.getOrThrow { AssertionError(it) }.run { | ||
assert(size == 1) | ||
assert(first().title == "New map") | ||
} | ||
} | ||
|
||
companion object Fixtures { | ||
|
||
@JvmStatic lateinit var firestoreInstance: FirebaseFirestore | ||
|
||
@JvmStatic lateinit var firestoreApi: FirebaseFirestoreRestApi | ||
|
||
@JvmStatic lateinit var firebaseAuthInstance: FirebaseAuth | ||
|
||
@JvmStatic lateinit var authApi: FirebaseAuthEmulatorRestApi | ||
|
||
@JvmStatic | ||
@BeforeClass | ||
fun setup() { | ||
firestoreInstance = | ||
FirebaseFirestore.getInstance(TestFixtures.app).apply { | ||
useEmulator( | ||
FirebaseEmulatorConnection.HOST, | ||
FirebaseEmulatorConnection.FIRESTORE_PORT | ||
) | ||
} | ||
|
||
firestoreApi = | ||
FirebaseFirestoreRestApi( | ||
TestFixtures.projectId, | ||
TestFixtures.emulatorBaseUrl(FirebaseEmulatorConnection.FIRESTORE_PORT) | ||
) | ||
|
||
firebaseAuthInstance = | ||
FirebaseAuth.getInstance(TestFixtures.app).apply { | ||
useEmulator( | ||
FirebaseEmulatorConnection.HOST, | ||
FirebaseEmulatorConnection.AUTH_PORT | ||
) | ||
} | ||
authApi = | ||
FirebaseAuthEmulatorRestApi( | ||
TestFixtures.projectId, | ||
TestFixtures.emulatorBaseUrl(FirebaseEmulatorConnection.AUTH_PORT) | ||
) | ||
} | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
...ests/firebase/src/main/kotlin/com/omricat/maplibrarian/firebase/TestDispatcherProvider.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package com.omricat.maplibrarian.firebase | ||
|
||
import com.omricat.maplibrarian.utils.DispatcherProvider | ||
import kotlinx.coroutines.CoroutineDispatcher | ||
import kotlinx.coroutines.ExperimentalCoroutinesApi | ||
import kotlinx.coroutines.test.StandardTestDispatcher | ||
import kotlinx.coroutines.test.TestCoroutineScheduler | ||
|
||
@OptIn(ExperimentalCoroutinesApi::class) | ||
class TestDispatcherProvider(scheduler: TestCoroutineScheduler) : DispatcherProvider { | ||
private val dispatcher = StandardTestDispatcher(scheduler) | ||
override val default: CoroutineDispatcher | ||
get() = dispatcher | ||
override val io: CoroutineDispatcher | ||
get() = dispatcher | ||
override val main: CoroutineDispatcher | ||
get() = dispatcher | ||
override val unconfined: CoroutineDispatcher | ||
get() = dispatcher | ||
} |
19 changes: 19 additions & 0 deletions
19
integration-tests/firebase/src/main/kotlin/com/omricat/maplibrarian/firebase/TestFixtures.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package com.omricat.maplibrarian.firebase | ||
|
||
import androidx.test.core.app.ApplicationProvider | ||
import com.google.firebase.FirebaseApp | ||
import okhttp3.HttpUrl | ||
import okhttp3.HttpUrl.Builder | ||
|
||
object TestFixtures { | ||
val app: FirebaseApp by lazy { | ||
FirebaseApp.initializeApp(ApplicationProvider.getApplicationContext()) | ||
?: error("Failed to initialize FirebaseApp") | ||
} | ||
|
||
val projectId: String | ||
get() = app.options.projectId ?: error("Can't get projectId from FirebaseApp options") | ||
|
||
fun emulatorBaseUrl(port: Int): HttpUrl = | ||
Builder().host(FirebaseEmulatorConnection.HOST).port(port).scheme("http").build() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 20 additions & 48 deletions
68
...irebase/src/main/kotlin/com/omricat/maplibrarian/firebase/auth/FirebaseAuthServiceTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,85 +1,57 @@ | ||
package com.omricat.maplibrarian.firebase.auth | ||
|
||
import androidx.test.core.app.ApplicationProvider | ||
import com.github.michaelbull.result.Ok | ||
import com.google.firebase.FirebaseApp | ||
import com.google.firebase.auth.FirebaseAuth | ||
import com.omricat.maplibrarian.auth.EmailPasswordCredential | ||
import com.omricat.maplibrarian.firebase.FirebaseEmulatorConnection | ||
import com.omricat.maplibrarian.firebase.TestDispatcherProvider | ||
import com.omricat.maplibrarian.firebase.TestFixtures | ||
import com.omricat.maplibrarian.model.User | ||
import com.omricat.maplibrarian.utils.DispatcherProvider | ||
import kotlinx.coroutines.CoroutineDispatcher | ||
import kotlinx.coroutines.ExperimentalCoroutinesApi | ||
import kotlinx.coroutines.test.StandardTestDispatcher | ||
import kotlinx.coroutines.test.TestCoroutineScheduler | ||
import kotlinx.coroutines.test.runTest | ||
import okhttp3.HttpUrl | ||
import org.junit.Before | ||
import org.junit.BeforeClass | ||
import org.junit.Test | ||
|
||
// Connects to host computer from Android emulator | ||
private const val FIREBASE_EMULATOR_HOST = "10.0.2.2" | ||
|
||
private const val FIREBASE_EMULATOR_AUTH_PORT = 9099 | ||
|
||
@OptIn(ExperimentalCoroutinesApi::class) | ||
class FirebaseAuthServiceTest { | ||
|
||
@Before | ||
fun clearUsers() { | ||
emulatorAPI.deleteAllUsers() | ||
authApi.deleteAllUsers() | ||
} | ||
|
||
@Test | ||
fun addUserSucceeds() { | ||
val credential = EmailPasswordCredential("[email protected]", "password") | ||
private val testCredential = EmailPasswordCredential("[email protected]", "password") | ||
|
||
runTest { | ||
val repository = | ||
FirebaseAuthService(firebaseAuthInstance, TestDispatcherProvider(testScheduler)) | ||
val createUserResult = repository.createUser(credential) | ||
assert(createUserResult is Ok<User>) | ||
} | ||
@Test | ||
fun addUserSucceeds() = runTest { | ||
val repository = | ||
FirebaseAuthService(firebaseAuthInstance, TestDispatcherProvider(testScheduler)) | ||
val createUserResult = repository.createUser(testCredential) | ||
assert(createUserResult is Ok<User>) | ||
} | ||
|
||
companion object Fixtures { | ||
|
||
@JvmStatic lateinit var firebaseAuthInstance: FirebaseAuth | ||
|
||
@JvmStatic lateinit var emulatorAPI: FirebaseAuthEmulatorRestApi | ||
@JvmStatic lateinit var authApi: FirebaseAuthEmulatorRestApi | ||
|
||
@JvmStatic | ||
@BeforeClass | ||
fun setUp() { | ||
val app: FirebaseApp = | ||
FirebaseApp.initializeApp(ApplicationProvider.getApplicationContext()) | ||
?: error("Failed to initialize FirebaseApp") | ||
firebaseAuthInstance = | ||
FirebaseAuth.getInstance(app).apply { | ||
useEmulator(FIREBASE_EMULATOR_HOST, FIREBASE_EMULATOR_AUTH_PORT) | ||
FirebaseAuth.getInstance(TestFixtures.app).apply { | ||
useEmulator( | ||
FirebaseEmulatorConnection.HOST, | ||
FirebaseEmulatorConnection.AUTH_PORT | ||
) | ||
} | ||
emulatorAPI = | ||
authApi = | ||
FirebaseAuthEmulatorRestApi( | ||
app.options.projectId!!, | ||
HttpUrl.Builder() | ||
.host(FIREBASE_EMULATOR_HOST) | ||
.port(FIREBASE_EMULATOR_AUTH_PORT) | ||
.scheme("http") | ||
.build() | ||
TestFixtures.projectId, | ||
TestFixtures.emulatorBaseUrl(FirebaseEmulatorConnection.AUTH_PORT) | ||
) | ||
} | ||
} | ||
} | ||
|
||
@OptIn(ExperimentalCoroutinesApi::class) | ||
class TestDispatcherProvider(scheduler: TestCoroutineScheduler) : DispatcherProvider { | ||
private val dispatcher = StandardTestDispatcher(scheduler) | ||
override val default: CoroutineDispatcher | ||
get() = dispatcher | ||
override val io: CoroutineDispatcher | ||
get() = dispatcher | ||
override val main: CoroutineDispatcher | ||
get() = dispatcher | ||
override val unconfined: CoroutineDispatcher | ||
get() = dispatcher | ||
} |
23 changes: 23 additions & 0 deletions
23
...base/src/main/kotlin/com/omricat/maplibrarian/firebase/charts/FirebaseFirestoreRestApi.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package com.omricat.maplibrarian.firebase.charts | ||
|
||
import okhttp3.HttpUrl | ||
import retrofit2.Call | ||
import retrofit2.Response | ||
import retrofit2.Retrofit | ||
import retrofit2.create | ||
import retrofit2.http.DELETE | ||
import retrofit2.http.Path | ||
|
||
class FirebaseFirestoreRestApi(private val projectId: String, baseUrl: HttpUrl) { | ||
|
||
private interface FirestoreEmulatorApi { | ||
|
||
@DELETE("/emulator/v1/projects/{project-id}/databases/(default)/documents") | ||
fun deleteDefaultDatabase(@Path("project-id") projectId: String): Call<Unit> | ||
} | ||
|
||
private val wrappedApi: FirestoreEmulatorApi = | ||
Retrofit.Builder().baseUrl(baseUrl).build().create() | ||
|
||
fun deleteAllData(): Response<Unit> = wrappedApi.deleteDefaultDatabase(projectId).execute() | ||
} |