@@ -21,53 +21,46 @@ import androidx.compose.ui.sendFromScope
21
21
import androidx.lifecycle.Lifecycle
22
22
import androidx.lifecycle.LifecycleEventObserver
23
23
import androidx.lifecycle.LifecycleOwner
24
- import kotlin.test.Ignore
24
+ import androidx.lifecycle.compose.LocalLifecycleOwner
25
25
import kotlin.test.Test
26
26
import kotlin.test.assertEquals
27
- import kotlin.test.assertTrue
28
- import kotlinx.browser.document
29
27
import kotlinx.browser.window
30
28
import kotlinx.coroutines.channels.Channel
31
29
import kotlinx.coroutines.test.runTest
32
- import org.w3c.dom.HTMLDivElement
30
+ import org.w3c.dom.events.Event
33
31
34
32
class ComposeWindowLifecycleTest : OnCanvasTests {
35
33
@Test
36
- @Ignore // ignored while investigating CI issues: this test opens a new browser window which can be the cause
37
34
fun allEvents () = runTest {
38
- val canvas = getCanvas()
39
- canvas.focus()
40
-
41
- val lifecycleOwner = ComposeWindow (
42
- canvas = canvas,
43
- interopContainerElement = document.createElement(" div" ) as HTMLDivElement ,
44
- a11yContainerElement = null ,
45
- content = {},
46
- configuration = ComposeViewportConfiguration (),
47
- state = DefaultWindowState (document.documentElement!! )
48
- )
49
-
50
35
val eventsChannel = Channel <Lifecycle .Event >(10 )
51
-
52
- lifecycleOwner.lifecycle.addObserver(object : LifecycleEventObserver {
53
- override fun onStateChanged (source : LifecycleOwner , event : Lifecycle .Event ) {
54
- eventsChannel.sendFromScope(event)
55
- }
56
- })
36
+ createComposeWindow {
37
+ val lifecycle = LocalLifecycleOwner .current.lifecycle
38
+ lifecycle.addObserver(object : LifecycleEventObserver {
39
+ override fun onStateChanged (source : LifecycleOwner , event : Lifecycle .Event ) {
40
+ eventsChannel.sendFromScope(event)
41
+ }
42
+ })
43
+ }
57
44
58
45
assertEquals(Lifecycle .State .CREATED , eventsChannel.receive().targetState)
59
46
assertEquals(Lifecycle .State .STARTED , eventsChannel.receive().targetState)
60
- assertEquals(Lifecycle .State .RESUMED , eventsChannel.receive().targetState)
61
47
62
- // Browsers don't allow to blur the window from code:
63
- // https://developer.mozilla.org/en-US/docs/Web/API/Window/blur
64
- // So we simulate a new tab being open:
65
- val anotherWindow = window.open(" about:config" )
66
- assertTrue(anotherWindow != null )
48
+ // Dispatch artificial events that would be sent when the window gains and loses focus.
49
+ // Starting with a focus event before checking for the initial RESUMED makes this test
50
+ // robust in the face of both an already-focused window and a non-focused window. Then,
51
+ // a blur plus focus cycle simulates losing focus and regaining it.
52
+ window.dispatchEvent(Event (" focus" ))
53
+ assertEquals(Lifecycle .State .RESUMED , eventsChannel.receive().targetState)
54
+ window.dispatchEvent(Event (" blur" ))
67
55
assertEquals(Lifecycle .State .STARTED , eventsChannel.receive().targetState)
68
-
69
- // Now go back to the original window
70
- anotherWindow.close()
56
+ window.dispatchEvent(Event (" focus" ))
71
57
assertEquals(Lifecycle .State .RESUMED , eventsChannel.receive().targetState)
58
+
59
+ // Destroy the ComposeWindow by removing its host container from the DOM.
60
+ val host = getShadowRoot().host
61
+ host.parentNode?.removeChild(host)
62
+ assertEquals(Lifecycle .State .STARTED , eventsChannel.receive().targetState)
63
+ assertEquals(Lifecycle .State .CREATED , eventsChannel.receive().targetState)
64
+ assertEquals(Lifecycle .State .DESTROYED , eventsChannel.receive().targetState)
72
65
}
73
66
}
0 commit comments