From b71a5161a75b54599dd7951d1c7017affc147b9a Mon Sep 17 00:00:00 2001 From: Shagen Ogandzhanian Date: Tue, 25 Jan 2022 11:36:37 +0100 Subject: [PATCH] Reuse renderComposable in tests (#1732) This also deprecates renderTestComposable --- .../src/jsTest/kotlin/DomSideEffectTests.kt | 1 - .../InputsGenerateCorrectHtmlTests.kt | 1 - web/test-utils/build.gradle.kts | 1 + .../compose/web/testutils/TestUtils.kt | 73 +++++++------------ 4 files changed, 29 insertions(+), 47 deletions(-) diff --git a/web/core/src/jsTest/kotlin/DomSideEffectTests.kt b/web/core/src/jsTest/kotlin/DomSideEffectTests.kt index 27b47920bc..819c0fbb74 100644 --- a/web/core/src/jsTest/kotlin/DomSideEffectTests.kt +++ b/web/core/src/jsTest/kotlin/DomSideEffectTests.kt @@ -2,7 +2,6 @@ package org.jetbrains.compose.web.core.tests import androidx.compose.runtime.* import org.jetbrains.compose.web.dom.Div -import org.jetbrains.compose.web.renderComposable import kotlinx.browser.document import kotlinx.dom.clear import org.jetbrains.compose.web.testutils.* diff --git a/web/core/src/jsTest/kotlin/elements/InputsGenerateCorrectHtmlTests.kt b/web/core/src/jsTest/kotlin/elements/InputsGenerateCorrectHtmlTests.kt index 79595b1d01..747e2a461d 100644 --- a/web/core/src/jsTest/kotlin/elements/InputsGenerateCorrectHtmlTests.kt +++ b/web/core/src/jsTest/kotlin/elements/InputsGenerateCorrectHtmlTests.kt @@ -5,7 +5,6 @@ import androidx.compose.runtime.setValue import androidx.compose.runtime.getValue import org.jetbrains.compose.web.attributes.* import org.jetbrains.compose.web.dom.* -import org.jetbrains.compose.web.renderComposable import org.w3c.dom.HTMLInputElement import org.w3c.dom.HTMLTextAreaElement import kotlin.test.Test diff --git a/web/test-utils/build.gradle.kts b/web/test-utils/build.gradle.kts index 4ed08e2d61..ccc031bc38 100644 --- a/web/test-utils/build.gradle.kts +++ b/web/test-utils/build.gradle.kts @@ -30,6 +30,7 @@ kotlin { val jsMain by getting { dependencies { implementation(project(":internal-web-core-runtime")) + implementation(project(":web-core")) implementation(kotlin("stdlib-js")) } } diff --git a/web/test-utils/src/jsMain/kotlin/org/jetbrains/compose/web/testutils/TestUtils.kt b/web/test-utils/src/jsMain/kotlin/org/jetbrains/compose/web/testutils/TestUtils.kt index 7a82b3e1d7..7cf4669276 100644 --- a/web/test-utils/src/jsMain/kotlin/org/jetbrains/compose/web/testutils/TestUtils.kt +++ b/web/test-utils/src/jsMain/kotlin/org/jetbrains/compose/web/testutils/TestUtils.kt @@ -1,13 +1,30 @@ package org.jetbrains.compose.web.testutils -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Composition +import androidx.compose.runtime.ControlledComposition +import androidx.compose.runtime.MonotonicFrameClock +import androidx.compose.runtime.Recomposer import kotlinx.browser.document import kotlinx.browser.window -import kotlinx.coroutines.* -import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.CoroutineStart +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.promise import kotlinx.dom.clear -import org.jetbrains.compose.web.internal.runtime.* -import org.w3c.dom.* +import org.jetbrains.compose.web.internal.runtime.ComposeWebInternalApi +import org.jetbrains.compose.web.internal.runtime.DomApplier +import org.jetbrains.compose.web.internal.runtime.DomNodeWrapper +import org.jetbrains.compose.web.internal.runtime.GlobalSnapshotManager +import org.jetbrains.compose.web.internal.runtime.JsMicrotasksDispatcher +import org.jetbrains.compose.web.renderComposable +import org.w3c.dom.Element +import org.w3c.dom.HTMLElement +import org.w3c.dom.MutationObserver +import org.w3c.dom.MutationObserverInit +import org.w3c.dom.asList +import org.w3c.dom.get import kotlin.coroutines.Continuation import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine @@ -27,7 +44,7 @@ class TestScope : CoroutineScope by MainScope() { * It's used as a parent element for the composition. * It's added into the document's body automatically. */ - val root = "div".asHtmlElement() + val root = document.createElement("div") as HTMLElement private var waitForRecompositionCompleteContinuation: Continuation? = null private val childrenIterator = root.children.asList().listIterator() @@ -49,46 +66,15 @@ class TestScope : CoroutineScope by MainScope() { fun composition(content: @Composable () -> Unit) { root.clear() - renderTestComposable(root = root) { + renderComposable( + root = root, monotonicFrameClock = TestMonotonicClockImpl( + onRecomposeComplete = this::onRecompositionComplete + ) + ) { content() } } - /** - * Use this method to test the composition mounted at [root] - * - * @param root - the [Element] that will be the root of the DOM tree managed by Compose - * @param content - the Composable lambda that defines the composition content - * - * @return the instance of the [Composition] - */ - @OptIn(ComposeWebInternalApi::class) - @ComposeWebExperimentalTestsApi - fun renderTestComposable( - root: TElement, - content: @Composable () -> Unit - ): Composition { - GlobalSnapshotManager.ensureStarted() - - val context = TestMonotonicClockImpl( - onRecomposeComplete = this::onRecompositionComplete - ) + JsMicrotasksDispatcher() - - val recomposer = Recomposer(context) - val composition = ControlledComposition( - applier = DomApplier(DomNodeWrapper(root)), - parent = recomposer - ) - composition.setContent @Composable { - content() - } - - CoroutineScope(context).launch(start = CoroutineStart.UNDISPATCHED) { - recomposer.runRecomposeAndApplyChanges() - } - return composition - } - /** * @return a reference to the next child element of the root. * Subsequent calls will return next child reference every time. @@ -177,9 +163,6 @@ fun runTest(block: suspend TestScope.() -> Unit): dynamic { return scope.promise { block(scope) } } -@ComposeWebExperimentalTestsApi -fun String.asHtmlElement() = document.createElement(this) as HTMLElement - private object MutationObserverOptions : MutationObserverInit { override var childList: Boolean? = true override var attributes: Boolean? = true