Skip to content

Commit 177da2b

Browse files
committed
refactor: Create multiplatform ui:test module and move UI tests
- Introduce a new `ui:test` Gradle module for multiplatform Compose UI testing, supporting Android, iOS, JVM, and WasmJs. - Move UI test cases, screen objects, and test utilities from `ui:test-jvm` to `ui:test/src/commonMain` to enable shared testing across all platforms. - Make `ui:test-jvm` a JVM-specific utility module that depends on `ui:test` and provides a compatibility bridge (`AbstractJvmUiTests`) between JVM test rules (`ComposeContentTestRule`) and the multiplatform `ComposeUiTest` API. - Replace the now-deleted `TestLifecycleOwner` and `runOnUiThread` utilities from `ui:test-jvm` with official `androidx.lifecycle:lifecycle-runtime-testing` dependency and new `expect/actual` implementations for `runOnUiThread` in `ui:test`. - Update Android and Desktop test app modules to depend on the new `ui:test` module. - Refactor test case classes and screen objects to use the multiplatform `ComposeUiTest` API instead of the JVM-specific `ComposeContentTestRule`. - Update documentation and build scripts to reflect the new `ui:test` module structure and testing strategy.
1 parent 1d8a500 commit 177da2b

File tree

58 files changed

+1072
-652
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1072
-652
lines changed

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
### Project Structure & Module Organization
1111
- Core: `core/domain`, `core/presentation`, `core/data/db-sqldelight` (default), `core/data/db-room` (optional), `core/test`.
12-
- UI: `ui/shared` (common Compose code and resources), `ui/test-jvm` (JVM Compose UI test utilities).
12+
- UI: `ui/shared` (common Compose code and resources), `ui/test` (multiplatform Compose UI tests), `ui/test-jvm` (JVM-specific UI test utilities).
1313
- Apps: `app/android`, `app/desktop`, `app/web`, `app/ios-kit` (CocoaPods framework), `app/iosApp` (Xcode project).
1414
- Tooling: `build-logic` (Gradle conventions), `thirdparty` (vendored modules), `gradle/libs.versions.toml` (versions).
1515
- Switch DB module via `gradle.properties` key `CORE_DATA_DB_MODULE`.

app/android/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ dependencies {
9696
coreLibraryDesugaring(libs.desugar)
9797
testImplementation(libs.junit)
9898
testImplementation(libs.bundles.mockito)
99+
androidTestImplementation(projects.ui.test)
99100
androidTestImplementation(projects.ui.testJvm) {
100101
exclude(group = "org.jetbrains.runtime", module = "jbr-api")
101102
}

app/android/src/androidTest/java/com/softartdev/notedelight/ui/AndroidUiTests.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import org.junit.runner.RunWith
1414

1515
@LargeTest
1616
@RunWith(AndroidJUnit4::class)
17-
class AndroidUiTests : AbstractUiTests() {
17+
class AndroidUiTests : AbstractJvmUiTests() {
1818

1919
override val composeTestRule = createAndroidComposeRule<MainActivity>()
2020

app/android/src/androidTest/java/com/softartdev/notedelight/ui/SignInTest.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1+
@file:OptIn(ExperimentalTestApi::class)
2+
13
package com.softartdev.notedelight.ui
24

5+
import androidx.compose.ui.test.ComposeUiTest
6+
import androidx.compose.ui.test.ExperimentalTestApi
37
import androidx.test.espresso.Espresso
48
import androidx.test.ext.junit.runners.AndroidJUnit4
59
import androidx.test.filters.FlakyTest
610
import com.softartdev.notedelight.DbTestEncryptor
711
import com.softartdev.notedelight.MainActivity
12+
import com.softartdev.notedelight.reflect
813
import com.softartdev.notedelight.ui.cases.SignInTestCase
914
import leakcanary.DetectLeaksAfterTestSuccess
1015
import leakcanary.TestDescriptionHolder
@@ -26,6 +31,8 @@ class SignInTest {
2631
.around(DetectLeaksAfterTestSuccess())
2732
.around(composeTestRule)
2833

34+
private val composeUiTest: ComposeUiTest = reflect(composeTestRule)
35+
2936
@Test
30-
fun signInTest() = SignInTestCase(composeTestRule, Espresso::closeSoftKeyboard).invoke()
37+
fun signInTest() = SignInTestCase(composeUiTest, Espresso::closeSoftKeyboard).invoke()
3138
}

app/android/src/androidTest/java/com/softartdev/notedelight/ui/SignInToSettingsTest.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1+
@file:OptIn(ExperimentalTestApi::class)
2+
13
package com.softartdev.notedelight.ui
24

5+
import androidx.compose.ui.test.ComposeUiTest
6+
import androidx.compose.ui.test.ExperimentalTestApi
37
import androidx.test.espresso.Espresso
48
import androidx.test.ext.junit.runners.AndroidJUnit4
59
import androidx.test.filters.FlakyTest
610
import com.softartdev.notedelight.DbTestEncryptor
711
import com.softartdev.notedelight.MainActivity
12+
import com.softartdev.notedelight.reflect
813
import com.softartdev.notedelight.ui.cases.SignInToSettingsTestCase
914
import leakcanary.DetectLeaksAfterTestSuccess
1015
import leakcanary.TestDescriptionHolder
@@ -26,7 +31,9 @@ class SignInToSettingsTest {
2631
.around(DetectLeaksAfterTestSuccess())
2732
.around(composeTestRule)
2833

34+
private val composeUiTest: ComposeUiTest = reflect(composeTestRule)
35+
2936
@Test
30-
fun signInToSettingsTest() = SignInToSettingsTestCase(composeTestRule, Espresso::closeSoftKeyboard).invoke()
37+
fun signInToSettingsTest() = SignInToSettingsTestCase(composeUiTest, Espresso::closeSoftKeyboard).invoke()
3138
}
3239

app/desktop/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@ kotlin {
3535
implementation(libs.kermit)
3636
}
3737
jvmTest.dependencies {
38+
implementation(projects.ui.test)
3839
implementation(projects.ui.testJvm)
3940
implementation(kotlin("test"))
4041
implementation(compose.desktop.uiTestJUnit4)
4142
implementation(compose.desktop.currentOs)
4243
implementation(libs.koin.compose)
4344
implementation(libs.kotlinx.datetime)
45+
implementation(libs.androidx.lifecycle.runtime.testing)
4446
}
4547
}
4648
}

app/desktop/src/jvmTest/kotlin/com/softartdev/notedelight/ui/DesktopUiTests.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ import androidx.compose.ui.test.onNodeWithContentDescription
1313
import androidx.compose.ui.test.performClick
1414
import androidx.lifecycle.Lifecycle
1515
import androidx.lifecycle.compose.LocalLifecycleOwner
16+
import androidx.lifecycle.testing.TestLifecycleOwner
1617
import co.touchlab.kermit.Logger
1718
import co.touchlab.kermit.platformLogWriter
1819
import com.softartdev.notedelight.App
19-
import com.softartdev.notedelight.TestLifecycleOwner
2020
import com.softartdev.notedelight.db.NoteDAO
2121
import com.softartdev.notedelight.di.sharedModules
2222
import com.softartdev.notedelight.di.uiTestModules
@@ -36,7 +36,7 @@ import org.koin.core.context.unloadKoinModules
3636
import org.koin.java.KoinJavaComponent.get
3737
import java.io.File
3838

39-
class DesktopUiTests : AbstractUiTests() {
39+
class DesktopUiTests : AbstractJvmUiTests() {
4040

4141
@get:Rule
4242
override val composeTestRule: ComposeContentTestRule = createComposeRule()

app/desktop/src/jvmTest/kotlin/com/softartdev/notedelight/ui/ScreenshootPreviewTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import androidx.compose.ui.test.junit4.createComposeRule
99
import androidx.compose.ui.test.onRoot
1010
import androidx.lifecycle.Lifecycle
1111
import androidx.lifecycle.compose.LocalLifecycleOwner
12+
import androidx.lifecycle.testing.TestLifecycleOwner
1213
import co.touchlab.kermit.Logger
1314
import co.touchlab.kermit.platformLogWriter
1415
import com.softartdev.notedelight.App
15-
import com.softartdev.notedelight.TestLifecycleOwner
1616
import com.softartdev.notedelight.db.NoteDAO
1717
import com.softartdev.notedelight.di.sharedModules
1818
import com.softartdev.notedelight.di.uiTestModules

docs/AI_AGENT_GUIDE.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ Level 3 (Depends on presentation/data):
5252
└── core:test
5353
5454
Level 4 (Integration):
55+
├── ui:test
5556
├── ui:test-jvm
5657
└── app:ios-kit
5758
@@ -509,7 +510,8 @@ Let Kotlin's type system guide you:
509510
### Read Tests
510511
Tests often show how to use code correctly. Look at:
511512
- `core/presentation/src/androidUnitTest/` for ViewModel examples
512-
- `ui/test-jvm/src/main/kotlin/ui/cases/` for UI test examples
513+
- `ui/test/src/commonMain/kotlin/ui/cases/` for multiplatform UI test examples
514+
- `ui/test-jvm/src/main/kotlin/` for JVM-specific test utilities
513515

514516
## Getting Unstuck
515517

docs/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ Each module has its own detailed README.md:
2525

2626
#### UI Modules
2727
- **[ui/shared/README.md](../ui/shared/README.md)** - Shared Compose UI
28-
- **[ui/test-jvm/README.md](../ui/test-jvm/README.md)** - UI testing framework (Kaspresso-inspired)
28+
- **[ui/test/README.md](../ui/test/README.md)** - Multiplatform Compose UI tests
29+
- **[ui/test-jvm/README.md](../ui/test-jvm/README.md)** - JVM-specific UI test utilities (Kaspresso-inspired)
2930

3031
#### App Modules
3132
- **[app/android/README.md](../app/android/README.md)** - Android application
@@ -68,7 +69,8 @@ NoteDelight/
6869
│ └── test/ # Shared test utilities
6970
├── ui/ # User interface
7071
│ ├── shared/ # 100% shared Compose UI
71-
│ └── test-jvm/ # UI testing framework
72+
│ ├── test/ # Multiplatform Compose UI tests
73+
│ └── test-jvm/ # JVM-specific UI test utilities
7274
├── app/ # Platform-specific applications
7375
│ ├── android/ # Android app
7476
│ ├── desktop/ # Desktop app

0 commit comments

Comments
 (0)