diff --git a/commonUI/build.gradle.kts b/commonUI/build.gradle.kts index f18853b..cc4d005 100644 --- a/commonUI/build.gradle.kts +++ b/commonUI/build.gradle.kts @@ -1,3 +1,6 @@ +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetTree + plugins { jacoco alias(libs.plugins.kotlin.multiplatform) @@ -10,36 +13,36 @@ kotlin { jvmToolchain(libs.versions.jdk.get().toInt()) jvm() - androidTarget() + androidTarget { + @OptIn(ExperimentalKotlinGradlePluginApi::class) + instrumentedTestVariant.sourceSetTree.set(KotlinSourceSetTree.test) + } sourceSets { - commonMain { - dependencies { - api(projects.domain) + commonMain.dependencies { + api(projects.domain) - implementation(compose.components.resources) - implementation(compose.runtime) - implementation(compose.foundation) - implementation(compose.ui) - implementation(compose.components.uiToolingPreview) + implementation(compose.components.resources) + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.ui) + implementation(compose.components.uiToolingPreview) - implementation(compose.material3) + implementation(compose.material3) - implementation(libs.bundles.logging) - } + implementation(libs.bundles.logging) } - androidMain { - dependencies { - implementation(libs.androidx.compose.foundation) - } + commonTest.dependencies { + implementation(libs.kotlin.test) + implementation(libs.atrium) + + @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class) + implementation(compose.uiTest) } - commonTest { - dependencies { - implementation(libs.kotlin.test) - implementation(libs.atrium) - } + jvmTest.dependencies { + implementation(compose.desktop.currentOs) } } } @@ -48,26 +51,28 @@ android { namespace = "ch.dissem.yaep.common.ui" compileSdk = libs.versions.android.compileSdk.get().toInt() + dependencies { + implementation(libs.androidx.compose.foundation) + debugImplementation(libs.androidx.compose.ui.test.manifest) + debugImplementation(libs.androidx.compose.ui.test.android) + } + defaultConfig { minSdk = libs.versions.android.minSdk.get().toInt() + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } buildFeatures { compose = true } - sourceSets { - getByName("test") { - resources.srcDirs("src/commonTest/resources") - } - } - buildTypes { debug { enableAndroidTestCoverage = true - enableUnitTestCoverage = true } } + + testOptions.unitTests.isIncludeAndroidResources = true } compose.resources { diff --git a/commonUI/src/androidInstrumentedTest/kotlin/ch/dissem/yaep/ui/common/IgnoreAndroidUnitTest.android.kt b/commonUI/src/androidInstrumentedTest/kotlin/ch/dissem/yaep/ui/common/IgnoreAndroidUnitTest.android.kt new file mode 100644 index 0000000..0242032 --- /dev/null +++ b/commonUI/src/androidInstrumentedTest/kotlin/ch/dissem/yaep/ui/common/IgnoreAndroidUnitTest.android.kt @@ -0,0 +1,5 @@ +package ch.dissem.yaep.ui.common + +@Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING") +@Target(allowedTargets = [AnnotationTarget.CLASS, AnnotationTarget.FUNCTION]) +actual annotation class IgnoreAndroidUnitTest actual constructor() \ No newline at end of file diff --git a/commonUI/src/androidUnitTest/kotlin/ch/dissem/yaep/ui/common/IgnoreAndroidUnitTest.android.kt b/commonUI/src/androidUnitTest/kotlin/ch/dissem/yaep/ui/common/IgnoreAndroidUnitTest.android.kt new file mode 100644 index 0000000..07216f3 --- /dev/null +++ b/commonUI/src/androidUnitTest/kotlin/ch/dissem/yaep/ui/common/IgnoreAndroidUnitTest.android.kt @@ -0,0 +1,4 @@ +package ch.dissem.yaep.ui.common + +@Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING") +actual typealias IgnoreAndroidUnitTest = org.junit.Ignore \ No newline at end of file diff --git a/commonUI/src/commonMain/kotlin/ch/dissem/yaep/ui/common/end.kt b/commonUI/src/commonMain/kotlin/ch/dissem/yaep/ui/common/end.kt index cabf2a1..56ad5f9 100644 --- a/commonUI/src/commonMain/kotlin/ch/dissem/yaep/ui/common/end.kt +++ b/commonUI/src/commonMain/kotlin/ch/dissem/yaep/ui/common/end.kt @@ -19,6 +19,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.graphics.BlurEffect import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.platform.testTag import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @@ -42,11 +43,12 @@ fun EndOfGame( exit = fadeOut() ) { val background = MaterialTheme.colorScheme.background - Box(modifier = Modifier - .fillMaxSize() - .drawBehind { - drawRect(color = background.copy(alpha = 0.8f)) - } + Box( + modifier = Modifier + .fillMaxSize() + .drawBehind { + drawRect(color = background.copy(alpha = 0.8f)) + } ) { Column( modifier = Modifier @@ -57,6 +59,7 @@ fun EndOfGame( fontSize = 128.sp, textAlign = TextAlign.Center, modifier = Modifier.fillMaxWidth() + .testTag("EndOfGame.solved_congrats") ) Spacer(modifier = Modifier.height(16.dp)) Text( @@ -64,10 +67,12 @@ fun EndOfGame( fontSize = 64.sp, textAlign = TextAlign.Center, modifier = Modifier.fillMaxWidth() + .testTag("EndOfGame.solved_time") ) Spacer(modifier = Modifier.height(32.dp)) Button( - modifier = Modifier.align(CenterHorizontally), + modifier = Modifier.align(CenterHorizontally) + .testTag("EndOfGame.restart"), onClick = onRestart ) { Text(stringResource(Res.string.restart)) diff --git a/commonUI/src/commonTest/kotlin/ch/dissem/yaep/ui/common/DummyTest.kt b/commonUI/src/commonTest/kotlin/ch/dissem/yaep/ui/common/DummyTest.kt deleted file mode 100644 index 735ad7c..0000000 --- a/commonUI/src/commonTest/kotlin/ch/dissem/yaep/ui/common/DummyTest.kt +++ /dev/null @@ -1,10 +0,0 @@ -import ch.tutteli.atrium.api.fluent.en_GB.toEqual -import ch.tutteli.atrium.api.verbs.expect -import kotlin.test.Test - -class DummyTest { - @Test - fun `ensure there is a test`() { - expect(true).toEqual(true) - } -} \ No newline at end of file diff --git a/commonUI/src/commonTest/kotlin/ch/dissem/yaep/ui/common/EndOfGameTest.kt b/commonUI/src/commonTest/kotlin/ch/dissem/yaep/ui/common/EndOfGameTest.kt new file mode 100644 index 0000000..f093c40 --- /dev/null +++ b/commonUI/src/commonTest/kotlin/ch/dissem/yaep/ui/common/EndOfGameTest.kt @@ -0,0 +1,33 @@ +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.assertTextContains +import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.runComposeUiTest +import ch.dissem.yaep.ui.common.EndOfGame +import ch.dissem.yaep.ui.common.IgnoreAndroidUnitTest +import ch.tutteli.atrium.api.fluent.en_GB.toEqual +import ch.tutteli.atrium.api.verbs.expect +import kotlin.test.Test + +@IgnoreAndroidUnitTest +@OptIn(ExperimentalTestApi::class) +class EndOfGameTest { + + @Test + fun `ensure end of game works correctly`() = runComposeUiTest { + var restart = false + setContent { + EndOfGame( + isSolved = true, + time = "42:42", + onRestart = { restart = true } + ) + } + + onNodeWithTag("EndOfGame.solved_time").assertTextContains(value = "42:42", substring = true) + onNodeWithTag("EndOfGame.restart").performClick() + + expect(restart).toEqual(true) + } + +} \ No newline at end of file diff --git a/commonUI/src/commonTest/kotlin/ch/dissem/yaep/ui/common/IgnoreAndroidUnitTest.kt b/commonUI/src/commonTest/kotlin/ch/dissem/yaep/ui/common/IgnoreAndroidUnitTest.kt new file mode 100644 index 0000000..dd848d2 --- /dev/null +++ b/commonUI/src/commonTest/kotlin/ch/dissem/yaep/ui/common/IgnoreAndroidUnitTest.kt @@ -0,0 +1,5 @@ +package ch.dissem.yaep.ui.common + +@Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING") +@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) +expect annotation class IgnoreAndroidUnitTest() diff --git a/commonUI/src/jvmTest/kotlin/ch/dissem/yaep/ui/common/IgnoreAndroidUnitTest.jvm.kt b/commonUI/src/jvmTest/kotlin/ch/dissem/yaep/ui/common/IgnoreAndroidUnitTest.jvm.kt new file mode 100644 index 0000000..0242032 --- /dev/null +++ b/commonUI/src/jvmTest/kotlin/ch/dissem/yaep/ui/common/IgnoreAndroidUnitTest.jvm.kt @@ -0,0 +1,5 @@ +package ch.dissem.yaep.ui.common + +@Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING") +@Target(allowedTargets = [AnnotationTarget.CLASS, AnnotationTarget.FUNCTION]) +actual annotation class IgnoreAndroidUnitTest actual constructor() \ No newline at end of file diff --git a/domain/src/commonTest/kotlin/ch/dissem/yaep/domain/GameTest.kt b/domain/src/commonTest/kotlin/ch/dissem/yaep/domain/GameTest.kt index d7df4c5..f702475 100644 --- a/domain/src/commonTest/kotlin/ch/dissem/yaep/domain/GameTest.kt +++ b/domain/src/commonTest/kotlin/ch/dissem/yaep/domain/GameTest.kt @@ -37,7 +37,7 @@ class GameTest { log.info { "Puzzle:\n$game" } } expect(solvable).toEqual(SOLVABLE) - expect(time).toBeLessThan(500.milliseconds) + expect(time).toBeLessThan(1000.milliseconds) if (time < fastest) { fastest = time } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 57fc3f7..369319b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,13 +15,17 @@ atrium = "1.2.0" [libraries] androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activityCompose" } +androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "coreKtx" } androidx-tooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "androidx-compose" } androidx-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview", version.ref = "androidx-compose" } androidx-compose-foundation = { module = "androidx.compose.foundation:foundation", version.ref = "androidx-compose" } -kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } +androidx-compose-ui-test-manifest = { module = "androidx.compose.ui:ui-test-manifest", version.ref = "androidx-compose" } +androidx-compose-ui-test-android = { module = "androidx.compose.ui:ui-test-junit4-android", version.ref = "androidx-compose" } + atrium = { module = "ch.tutteli.atrium:atrium-fluent", version.ref = "atrium" } -androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "coreKtx" } -kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version = "1.10.2" } + +kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } + logging-jvm = { module = "io.github.oshai:kotlin-logging-jvm", version = "7.0.13" } logging-slf4j = { module = "org.slf4j:slf4j-simple", version = "2.0.17" }