Skip to content

Commit b7acd5b

Browse files
committed
Implement LifecycleOwner in tests
1 parent 3fc27e3 commit b7acd5b

File tree

3 files changed

+82
-4
lines changed

3 files changed

+82
-4
lines changed

compose/ui/ui-test/build.gradle

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,17 @@ if (AndroidXComposePlugin.isMultiplatformEnabled(project)) {
147147
implementation(libs.kotlinTest)
148148
}
149149

150-
skikoMain {
151-
dependsOn(commonMain)
150+
skikoMain.dependencies {
151+
implementation(project(":lifecycle:lifecycle-common"))
152+
implementation(project(":lifecycle:lifecycle-runtime"))
152153
}
153154

155+
skikoTest.dependencies {
156+
implementation(libs.kotlinTest)
157+
implementation(project(":lifecycle:lifecycle-runtime-compose"))
158+
}
159+
160+
skikoMain.dependsOn(commonMain)
154161
desktopMain.dependsOn(skikoMain)
155162
jsNativeMain.dependsOn(skikoMain)
156163
jsMain.dependsOn(jsNativeMain)
@@ -168,6 +175,15 @@ if (AndroidXComposePlugin.isMultiplatformEnabled(project)) {
168175
androidCommonTest.dependsOn(commonTest)
169176
androidTest.dependsOn(androidCommonTest)
170177
androidAndroidTest.dependsOn(androidCommonTest)
178+
179+
desktopTest {
180+
dependsOn(skikoTest)
181+
dependencies {
182+
implementation(libs.skikoCurrentOs)
183+
}
184+
}
185+
nativeTest.dependsOn(skikoTest)
186+
wasmJsTest.dependsOn(skikoTest)
171187
}
172188
}
173189

compose/ui/ui-test/src/skikoMain/kotlin/androidx/compose/ui/test/ComposeUiTest.skikoMain.kt

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package androidx.compose.ui.test
1818

1919
import androidx.compose.runtime.Composable
20+
import androidx.compose.runtime.CompositionLocalProvider
2021
import androidx.compose.runtime.snapshots.Snapshot
2122
import androidx.compose.ui.ExperimentalComposeUiApi
2223
import androidx.compose.ui.InternalComposeUiApi
@@ -26,6 +27,7 @@ import androidx.compose.ui.graphics.asComposeCanvas
2627
import androidx.compose.ui.graphics.toComposeImageBitmap
2728
import androidx.compose.ui.node.RootForTest
2829
import androidx.compose.ui.platform.InfiniteAnimationPolicy
30+
import androidx.compose.ui.platform.LocalLifecycleOwner
2931
import androidx.compose.ui.platform.PlatformContext
3032
import androidx.compose.ui.platform.WindowInfo
3133
import androidx.compose.ui.scene.ComposeScene
@@ -39,6 +41,9 @@ import androidx.compose.ui.text.input.PlatformTextInputService
3941
import androidx.compose.ui.text.input.TextFieldValue
4042
import androidx.compose.ui.unit.Density
4143
import androidx.compose.ui.unit.IntSize
44+
import androidx.lifecycle.Lifecycle
45+
import androidx.lifecycle.LifecycleOwner
46+
import androidx.lifecycle.LifecycleRegistry
4247
import kotlin.coroutines.CoroutineContext
4348
import kotlin.coroutines.EmptyCoroutineContext
4449
import kotlin.coroutines.cancellation.CancellationException
@@ -318,11 +323,14 @@ class SkikoComposeUiTest @InternalTestApi constructor(
318323
}
319324

320325
override fun setContent(composable: @Composable () -> Unit) {
326+
val content: @Composable () -> Unit = {
327+
CompositionLocalProvider(LocalLifecycleOwner provides lifecycleOwner, content = composable)
328+
}
321329
if (isOnUiThread()) {
322-
scene.setContent(content = composable)
330+
scene.setContent(content = content)
323331
} else {
324332
runOnUiThread {
325-
scene.setContent(content = composable)
333+
scene.setContent(content = content)
326334
}
327335

328336
// Only wait for idleness if not on the UI thread. If we are on the UI thread, the
@@ -332,6 +340,10 @@ class SkikoComposeUiTest @InternalTestApi constructor(
332340
}
333341
}
334342

343+
private val lifecycleOwner = TestLifecycleOwner()
344+
override val lifecycleRegistry: LifecycleRegistry
345+
get() = lifecycleOwner.lifecycleRegistry
346+
335347
override fun onNode(
336348
matcher: SemanticsMatcher,
337349
useUnmergedTree: Boolean
@@ -443,4 +455,11 @@ actual sealed interface ComposeUiTest : SemanticsNodeInteractionsProvider {
443455
actual fun registerIdlingResource(idlingResource: IdlingResource)
444456
actual fun unregisterIdlingResource(idlingResource: IdlingResource)
445457
actual fun setContent(composable: @Composable () -> Unit)
458+
val lifecycleRegistry: LifecycleRegistry
446459
}
460+
461+
class TestLifecycleOwner : LifecycleOwner {
462+
override val lifecycle: Lifecycle
463+
get() = lifecycleRegistry
464+
val lifecycleRegistry = LifecycleRegistry(this)
465+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2024 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package androidx.compose.ui.test
18+
19+
import androidx.compose.ui.platform.LocalLifecycleOwner
20+
import androidx.lifecycle.Lifecycle
21+
import androidx.lifecycle.compose.LifecycleEventEffect
22+
import kotlin.test.Test
23+
import kotlin.test.assertEquals
24+
import kotlin.test.assertTrue
25+
26+
@OptIn(ExperimentalTestApi::class)
27+
class LifecycleInTestsTest {
28+
@Test
29+
fun lifecycleInComposeTest() = runComposeUiTest {
30+
var onResumeEffectCalled = false
31+
setContent {
32+
LifecycleEventEffect(Lifecycle.Event.ON_RESUME) {
33+
onResumeEffectCalled = true
34+
}
35+
36+
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
37+
38+
assertEquals(Lifecycle.State.RESUMED, LocalLifecycleOwner.current.lifecycle.currentState)
39+
}
40+
41+
assertTrue(onResumeEffectCalled)
42+
}
43+
}

0 commit comments

Comments
 (0)