add Android unit test coverage
This commit is contained in:
@@ -23,6 +23,7 @@ This is the canonical working plan and progress log for the project. Use this fi
|
|||||||
- Backend analytics coverage now includes a representative key user flow batch.
|
- Backend analytics coverage now includes a representative key user flow batch.
|
||||||
- iOS project scaffolding now exists as `mobile/ios-app/HermesApp.xcodeproj` with a shared scheme and XCTest target.
|
- iOS project scaffolding now exists as `mobile/ios-app/HermesApp.xcodeproj` with a shared scheme and XCTest target.
|
||||||
- iOS sources and tests build and pass in Xcode on an iPhone simulator, and a standalone localization/error-mapping harness passes.
|
- iOS sources and tests build and pass in Xcode on an iPhone simulator, and a standalone localization/error-mapping harness passes.
|
||||||
|
- Android local unit tests now cover localization, error mapping, and analytics batch conversion, and `./gradlew testDebugUnitTest` passes with the Android SDK installed.
|
||||||
|
|
||||||
### Still Open
|
### Still Open
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ android {
|
|||||||
buildConfig = true
|
buildConfig = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testOptions {
|
||||||
|
unitTests.isIncludeAndroidResources = true
|
||||||
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
targetCompatibility = JavaVersion.VERSION_17
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
@@ -67,4 +71,9 @@ dependencies {
|
|||||||
|
|
||||||
debugImplementation("androidx.compose.ui:ui-tooling")
|
debugImplementation("androidx.compose.ui:ui-tooling")
|
||||||
debugImplementation("androidx.compose.ui:ui-test-manifest")
|
debugImplementation("androidx.compose.ui:ui-test-manifest")
|
||||||
|
|
||||||
|
testImplementation(kotlin("test"))
|
||||||
|
testImplementation("androidx.test:core:1.6.1")
|
||||||
|
testImplementation("junit:junit:4.13.2")
|
||||||
|
testImplementation("org.robolectric:robolectric:4.13")
|
||||||
}
|
}
|
||||||
|
|||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
package com.hermes.app.core.analytics
|
||||||
|
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
import java.util.UUID
|
||||||
|
import kotlinx.datetime.Instant
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.robolectric.RobolectricTestRunner
|
||||||
|
import org.robolectric.annotation.Config
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner::class)
|
||||||
|
@Config(sdk = [34])
|
||||||
|
class HermesAnalyticsTrackerTest {
|
||||||
|
@Test
|
||||||
|
fun convertsPendingEventsToBatchRequest() {
|
||||||
|
val tracker = HermesAnalyticsTracker()
|
||||||
|
val event = HermesTrackedEvent(
|
||||||
|
id = UUID.fromString("00000000-0000-0000-0000-000000000001"),
|
||||||
|
name = "screen_viewed",
|
||||||
|
attributes = mapOf("screen_name" to "feed"),
|
||||||
|
timestamp = Instant.fromEpochMilliseconds(1_000),
|
||||||
|
)
|
||||||
|
|
||||||
|
val batch = tracker.toBatchRequest(listOf(event))
|
||||||
|
|
||||||
|
assertEquals(1, batch.events.size)
|
||||||
|
assertEquals("screen_viewed", batch.events.first().eventName)
|
||||||
|
assertEquals("feed", batch.events.first().attributes!!.first().value)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun marksDeliveredEventsAsRemoved() {
|
||||||
|
val tracker = HermesAnalyticsTracker()
|
||||||
|
|
||||||
|
tracker.track("screen_viewed", mapOf("screen_name" to "feed"))
|
||||||
|
val trackedId = tracker.pendingEventsSnapshot().first().id
|
||||||
|
tracker.markDelivered(setOf(trackedId))
|
||||||
|
|
||||||
|
assertTrue(tracker.pendingEventsSnapshot().isEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
package com.hermes.app.core.errors
|
||||||
|
|
||||||
|
import androidx.test.core.app.ApplicationProvider
|
||||||
|
import com.hermes.app.R
|
||||||
|
import com.hermes.app.core.localization.HermesLocalizationStore
|
||||||
|
import java.io.IOException
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertNull
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.robolectric.RobolectricTestRunner
|
||||||
|
import org.robolectric.annotation.Config
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner::class)
|
||||||
|
@Config(sdk = [34])
|
||||||
|
class HermesErrorMapperTest {
|
||||||
|
private val context = ApplicationProvider.getApplicationContext<android.content.Context>()
|
||||||
|
private val store = HermesLocalizationStore(context)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun mapsNetworkErrorsToLocalizedCopy() {
|
||||||
|
assertEquals(
|
||||||
|
"Nätverksfel. Kontrollera anslutningen.",
|
||||||
|
mapUserFacingError(store, "sv", IOException("boom")),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun mapsGenericErrorsToLocalizedCopy() {
|
||||||
|
assertEquals(
|
||||||
|
"Försök igen.",
|
||||||
|
mapUserFacingError(store, "sv", IllegalStateException("boom")),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun ignoresCancellation() {
|
||||||
|
assertNull(mapUserFacingError(store, "en", kotlinx.coroutines.CancellationException()))
|
||||||
|
}
|
||||||
|
}
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
package com.hermes.app.core.localization
|
||||||
|
|
||||||
|
import androidx.test.core.app.ApplicationProvider
|
||||||
|
import com.hermes.app.R
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import org.robolectric.RobolectricTestRunner
|
||||||
|
import org.robolectric.annotation.Config
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner::class)
|
||||||
|
@Config(sdk = [34])
|
||||||
|
class HermesLocalizationStoreTest {
|
||||||
|
private val context = ApplicationProvider.getApplicationContext<android.content.Context>()
|
||||||
|
private val store = HermesLocalizationStore(context)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun englishStringsLoad() {
|
||||||
|
assertEquals("Settings", store.string("en", R.string.settings_title))
|
||||||
|
assertEquals("Enabled", store.string("en", R.string.settings_enabled))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun swedishStringsLoad() {
|
||||||
|
assertEquals("Inställningar", store.string("sv", R.string.settings_title))
|
||||||
|
assertEquals("Aktiverad", store.string("sv", R.string.settings_enabled))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun unsupportedLocaleFallsBackToEnglish() {
|
||||||
|
store.setLocale("fr")
|
||||||
|
|
||||||
|
assertEquals("en", store.localeCode.value)
|
||||||
|
assertEquals("English", store.localeName("en", "fr"))
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user