diff --git a/compose/ui/ui/src/webTest/kotlin/androidx/compose/ui/OnCanvasTests.kt b/compose/ui/ui/src/webTest/kotlin/androidx/compose/ui/OnCanvasTests.kt index 6089a74a6311f..61ddb727a3b23 100644 --- a/compose/ui/ui/src/webTest/kotlin/androidx/compose/ui/OnCanvasTests.kt +++ b/compose/ui/ui/src/webTest/kotlin/androidx/compose/ui/OnCanvasTests.kt @@ -76,16 +76,6 @@ internal interface OnCanvasTests { private fun getContainer() = document.getElementById(containerId) ?: error("failed to get canvas with id ${containerId}") - private fun getAppRoot() = getShadowRoot().children[0] as HTMLElement - - fun getA11YContainer(): HTMLElement? { - return if (getAppRoot().children.length < 3) { - null - } else { - // The expected order is: canvas, interop container
, a11y container
- getAppRoot().children[2] as HTMLElement - } - } fun getShadowRoot(): ExtendedShadowRoot = (getContainer().shadowRoot as? ExtendedShadowRoot) ?: error("failed to get shadowRoot") @@ -111,28 +101,6 @@ internal interface OnCanvasTests { } } - suspend fun awaitA11YChanges() { - val a11yContainer = getA11YContainer() ?: return - - fun skipFramesUntil(condition: () -> Boolean, onTrue: () -> Unit) { - window.requestAnimationFrame { - if (!condition()) { - skipFramesUntil(condition, onTrue) - } else { - onTrue() - } - } - } - - suspendCoroutine { continuation -> - val initialContent = a11yContainer.innerHTML - skipFramesUntil( - condition = { a11yContainer.innerHTML != initialContent }, - onTrue = { continuation.resumeWith(Result.success(Unit)) } - ) - } - } - fun dispatchEvents(vararg events: Event) { dispatchEvents(getCanvas(), *events) } diff --git a/compose/ui/ui/src/webTest/kotlin/androidx/compose/ui/platform/a11y/CfWA11YTest.kt b/compose/ui/ui/src/webTest/kotlin/androidx/compose/ui/platform/a11y/CfWA11YTest.kt index 71bcd660cb226..a147e59f0d7e2 100644 --- a/compose/ui/ui/src/webTest/kotlin/androidx/compose/ui/platform/a11y/CfWA11YTest.kt +++ b/compose/ui/ui/src/webTest/kotlin/androidx/compose/ui/platform/a11y/CfWA11YTest.kt @@ -27,7 +27,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.OnCanvasTests import androidx.compose.ui.currentTimeMillis import androidx.compose.ui.platform.testTag -import kotlin.test.Ignore +import kotlin.coroutines.Continuation +import kotlin.coroutines.suspendCoroutine import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFalse @@ -35,7 +36,7 @@ import kotlin.test.assertNotEquals import kotlin.test.assertNotNull import kotlin.test.assertNull import kotlin.test.assertTrue -import kotlinx.browser.document +import kotlinx.browser.window import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -45,6 +46,37 @@ import org.w3c.dom.HTMLElement import org.w3c.dom.get class CfWA11YTest : OnCanvasTests { + private fun getAppRoot() = getShadowRoot().children[0] as HTMLElement + + private suspend fun awaitA11YChanges() { + val a11yContainer = getA11YContainer() ?: return + + fun Continuation.waitUntil(waitUntilCondition: () -> Boolean) { + window.requestAnimationFrame { + if (!waitUntilCondition()) { + waitUntil(waitUntilCondition) + } else { + resumeWith(Result.success(Unit)) + } + } + } + + suspendCoroutine { continuation -> + val initialContent = a11yContainer.innerHTML + continuation.waitUntil { + a11yContainer.innerHTML != initialContent + } + } + } + + private fun getA11YContainer(): HTMLElement? { + return if (getAppRoot().children.length < 3) { + null + } else { + // The expected order is: canvas, interop container
, a11y container
+ getAppRoot().children[2] as HTMLElement + } + } @Test fun a11yButtonClick() = runApplicationTest { @@ -58,6 +90,7 @@ class CfWA11YTest : OnCanvasTests { } } + awaitIdle() val a11yContainer = getA11YContainer() @@ -71,9 +104,10 @@ class CfWA11YTest : OnCanvasTests { assertEquals("button", button1.getAttribute("role")) assertEquals("Button1", button1.innerText) - repeat(3) { + repeat(3) { repeatCounter -> button1.click() - assertEquals(it + 1, clickCounter) + awaitIdle() + assertEquals(repeatCounter + 1, clickCounter) } } @@ -127,11 +161,11 @@ class CfWA11YTest : OnCanvasTests { assertTrue(button2.isConnected) - repeat(3) { + repeat(3) { repeatCounter -> button1.click() button2.click() - assertEquals(it + 1, clickCounter1) - assertEquals(it + 1, clickCounter2) + assertEquals(repeatCounter + 1, clickCounter1) + assertEquals(repeatCounter + 1, clickCounter2) } showButton2 = false @@ -206,7 +240,6 @@ class CfWA11YTest : OnCanvasTests { assertEquals("Button3", buttonsContainer.children[2]!!.innerHTML) } - @Ignore // Sometimes fails on latest firefox FIXME: https://youtrack.jetbrains.com/issue/CMP-8955 @Test fun changesMustBeBatched() = runApplicationTest { var show1 by mutableStateOf(true) @@ -257,7 +290,6 @@ class CfWA11YTest : OnCanvasTests { assertTrue(waitedForChangesMs in 50..150, "Changes must be batched, waited for $waitedForChangesMs ms. Allowed tolerance 50ms was exceeded") } - @Ignore // Sometimes fails on latest firefox FIXME: https://youtrack.jetbrains.com/issue/CMP-8955 @Test fun changesMustBeAppliedDespiteConstantDebounceAfter1Second() = runApplicationTest { var show1 by mutableStateOf(true) @@ -324,7 +356,6 @@ class CfWA11YTest : OnCanvasTests { ) } - @Ignore // Sometimes fails on latest firefox FIXME: https://youtrack.jetbrains.com/issue/CMP-8955 @Test fun noChangesFor1SecondTheDebounceShouldWork() = runApplicationTest { var show by mutableStateOf(true)