Skip to content

Commit 98fcf9d

Browse files
committed
test: Add common UI tests for KMP targets
- Introduce a new test class `CommonUiTests` to run UI tests on Kotlin Multiplatform targets. - Add `androidx.lifecycle.runtime.compose` and `androidx.lifecycle.runtime.testing` dependencies to `ui/test/build.gradle.kts` for common tests. - Implement test setup and teardown logic within `CommonUiTests`, including Koin module loading/unloading and database initialization. - Utilize `TestLifecycleOwner` to provide a lifecycle for Compose UI tests. - Override test methods from `AbstractUITests` to run them within the `runComposeUiTest` block. - Implement a platform-specific `pressBack` action for the common tests.
1 parent b68e7a6 commit 98fcf9d

File tree

2 files changed

+135
-0
lines changed

2 files changed

+135
-0
lines changed

ui/test/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ kotlin {
5353
val commonTest by getting {
5454
dependencies {
5555
implementation(kotlin("test"))
56+
implementation(libs.androidx.lifecycle.runtime.compose)
57+
implementation(libs.androidx.lifecycle.runtime.testing)
5658
}
5759
}
5860
val jvmTest by getting {
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
@file:OptIn(ExperimentalTestApi::class)
2+
3+
package com.softartdev.notedelight
4+
5+
import androidx.compose.material.icons.Icons
6+
import androidx.compose.material.icons.automirrored.filled.ArrowBack
7+
import androidx.compose.runtime.CompositionLocalProvider
8+
import androidx.compose.ui.test.ComposeUiTest
9+
import androidx.compose.ui.test.ExperimentalTestApi
10+
import androidx.compose.ui.test.assertIsDisplayed
11+
import androidx.compose.ui.test.onNodeWithContentDescription
12+
import androidx.compose.ui.test.performClick
13+
import androidx.compose.ui.test.runComposeUiTest
14+
import androidx.lifecycle.Lifecycle
15+
import androidx.lifecycle.compose.LocalLifecycleOwner
16+
import androidx.lifecycle.testing.TestLifecycleOwner
17+
import co.touchlab.kermit.Logger
18+
import co.touchlab.kermit.platformLogWriter
19+
import com.softartdev.notedelight.db.NoteDAO
20+
import com.softartdev.notedelight.di.sharedModules
21+
import com.softartdev.notedelight.di.uiTestModules
22+
import com.softartdev.notedelight.repository.SafeRepo
23+
import com.softartdev.notedelight.util.kermitLogger
24+
import kotlinx.coroutines.test.TestResult
25+
import org.koin.core.context.loadKoinModules
26+
import org.koin.core.context.startKoin
27+
import org.koin.core.context.unloadKoinModules
28+
import org.koin.mp.KoinPlatformTools
29+
import kotlin.test.Ignore
30+
import kotlin.test.Test
31+
32+
@Ignore
33+
class CommonUiTests : AbstractUITests() {
34+
35+
private var _composeUiTest: ComposeUiTest? = null
36+
37+
override val composeUiTest: ComposeUiTest
38+
get() = requireNotNull(_composeUiTest)
39+
40+
private suspend fun beforeTest() {
41+
Logger.setLogWriters(platformLogWriter())
42+
when (KoinPlatformTools.defaultContext().getOrNull()) {
43+
null -> startKoin {
44+
kermitLogger()
45+
modules(sharedModules + uiTestModules)
46+
}
47+
else -> loadKoinModules(sharedModules + uiTestModules)
48+
}
49+
val safeRepo: SafeRepo = KoinPlatformTools.defaultContext().get().get(SafeRepo::class)
50+
safeRepo.closeDatabase()
51+
safeRepo.buildDbIfNeed()
52+
val noteDAO: NoteDAO = KoinPlatformTools.defaultContext().get().get(NoteDAO::class)
53+
noteDAO.deleteAll()
54+
super.setUp()
55+
val lifecycleOwner = TestLifecycleOwner(initialState = Lifecycle.State.RESUMED)
56+
composeUiTest.setContent {
57+
CompositionLocalProvider(LocalLifecycleOwner provides lifecycleOwner) {
58+
App()
59+
}
60+
}
61+
composeUiTest.waitForIdle()
62+
}
63+
64+
private fun afterTest() {
65+
super.tearDown()
66+
unloadKoinModules(sharedModules + uiTestModules)
67+
Logger.setLogWriters()
68+
}
69+
70+
@Test
71+
override fun crudNoteTest(): TestResult = runComposeUiTest {
72+
_composeUiTest = this
73+
beforeTest()
74+
super.crudNoteTest()
75+
afterTest()
76+
}
77+
78+
@Test
79+
override fun editTitleAfterCreateTest(): TestResult = runComposeUiTest {
80+
_composeUiTest = this
81+
beforeTest()
82+
super.editTitleAfterCreateTest()
83+
afterTest()
84+
}
85+
86+
@Test
87+
override fun editTitleAfterSaveTest(): TestResult = runComposeUiTest {
88+
_composeUiTest = this
89+
beforeTest()
90+
super.editTitleAfterSaveTest()
91+
afterTest()
92+
}
93+
94+
@Test
95+
override fun prepopulateDatabase(): TestResult = runComposeUiTest {
96+
_composeUiTest = this
97+
beforeTest()
98+
super.prepopulateDatabase()
99+
afterTest()
100+
}
101+
102+
@Test
103+
override fun flowAfterCryptTest(): TestResult = runComposeUiTest {
104+
_composeUiTest = this
105+
beforeTest()
106+
super.flowAfterCryptTest()
107+
afterTest()
108+
}
109+
110+
@Test
111+
override fun settingPasswordTest(): TestResult = runComposeUiTest {
112+
_composeUiTest = this
113+
beforeTest()
114+
super.settingPasswordTest()
115+
afterTest()
116+
}
117+
118+
@Test
119+
override fun localeTest(): TestResult = runComposeUiTest {
120+
_composeUiTest = this
121+
beforeTest()
122+
super.localeTest()
123+
afterTest()
124+
}
125+
126+
override fun pressBack() {
127+
composeUiTest.onNodeWithContentDescription(label = Icons.AutoMirrored.Filled.ArrowBack.name)
128+
.assertIsDisplayed()
129+
.performClick()
130+
}
131+
132+
override fun closeSoftKeyboard() = Unit // No-op on web
133+
}

0 commit comments

Comments
 (0)