diff --git a/workflow-core/src/commonTest/kotlin/com/squareup/workflow1/WorkerTest.kt b/workflow-core/src/commonTest/kotlin/com/squareup/workflow1/WorkerTest.kt index 3433783b9..25581e0b8 100644 --- a/workflow-core/src/commonTest/kotlin/com/squareup/workflow1/WorkerTest.kt +++ b/workflow-core/src/commonTest/kotlin/com/squareup/workflow1/WorkerTest.kt @@ -1,5 +1,6 @@ package com.squareup.workflow1 +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.buffer import kotlinx.coroutines.flow.conflate @@ -7,13 +8,14 @@ import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.toList -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.test.runTest import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertNotSame import kotlin.test.assertTrue +@ExperimentalCoroutinesApi @OptIn(ExperimentalStdlibApi::class) class WorkerTest { @@ -62,14 +64,11 @@ class WorkerTest { assertFalse(transformed1.doesSameWorkAs(transformed2)) } - @Test fun transformed_workers_transform_flows() { + @Test fun transformed_workers_transform_flows() = runTest { val source = flowOf(1, 2, 3).asWorker() val transformed = source.transform { flow -> flow.map { it.toString() } } - val transformedValues = runBlocking { - transformed.run() - .toList() - } + val transformedValues = transformed.run().toList() assertEquals(listOf("1", "2", "3"), transformedValues) } diff --git a/workflow-core/src/commonTest/kotlin/com/squareup/workflow1/WorkerWorkflowTest.kt b/workflow-core/src/commonTest/kotlin/com/squareup/workflow1/WorkerWorkflowTest.kt index c42a60644..ff548a2e1 100644 --- a/workflow-core/src/commonTest/kotlin/com/squareup/workflow1/WorkerWorkflowTest.kt +++ b/workflow-core/src/commonTest/kotlin/com/squareup/workflow1/WorkerWorkflowTest.kt @@ -1,29 +1,29 @@ package com.squareup.workflow1 import kotlinx.coroutines.CoroutineName +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.test.runTest import kotlin.coroutines.coroutineContext import kotlin.test.Test import kotlin.test.assertEquals +@ExperimentalCoroutinesApi class WorkerWorkflowTest { - @Test fun runWorker_coroutine_is_named_without_key() { + @Test fun runWorker_coroutine_is_named_without_key() = runTest { val worker = CoroutineNameWorker() - runBlocking { - runWorker(worker, renderKey = "", actionSink = NoopSink) - } + + runWorker(worker, renderKey = "", actionSink = NoopSink) assertEquals("CoroutineNameWorker.toString", worker.recordedName) } - @Test fun runWorker_coroutine_is_named_with_key() { + @Test fun runWorker_coroutine_is_named_with_key() = runTest { val worker = CoroutineNameWorker() - runBlocking { - runWorker(worker, renderKey = "foo", actionSink = NoopSink) - } + + runWorker(worker, renderKey = "foo", actionSink = NoopSink) assertEquals("CoroutineNameWorker.toString:foo", worker.recordedName) } diff --git a/workflow-runtime/src/commonTest/kotlin/com/squareup/workflow1/WorkflowInterceptorTest.kt b/workflow-runtime/src/commonTest/kotlin/com/squareup/workflow1/WorkflowInterceptorTest.kt index 874fd3b0b..0ab204617 100644 --- a/workflow-runtime/src/commonTest/kotlin/com/squareup/workflow1/WorkflowInterceptorTest.kt +++ b/workflow-runtime/src/commonTest/kotlin/com/squareup/workflow1/WorkflowInterceptorTest.kt @@ -7,8 +7,9 @@ import com.squareup.workflow1.WorkflowInterceptor.WorkflowSession import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.advanceUntilIdle +import kotlinx.coroutines.test.runTest import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext.Key import kotlin.test.Test @@ -122,7 +123,7 @@ internal class WorkflowInterceptorTest { ) } - @Test fun intercept_intercepts_side_effects() { + @Test fun intercept_intercepts_side_effects() = runTest { val recorder = RecordingWorkflowInterceptor() val workflow = TestSideEffectWorkflow() val intercepted = recorder.intercept(workflow, workflow.session) @@ -140,7 +141,8 @@ internal class WorkflowInterceptorTest { key: String, sideEffect: suspend CoroutineScope.() -> Unit ) { - runBlocking { sideEffect() } + launch { sideEffect() } + advanceUntilIdle() } } @@ -157,7 +159,7 @@ internal class WorkflowInterceptorTest { ) } - @Test fun intercept_uses_interceptors_context_for_side_effect() { + @Test fun intercept_uses_interceptors_context_for_side_effect() = runTest { val recorder = object : RecordingWorkflowInterceptor() { override fun onRender( renderProps: P, @@ -200,7 +202,8 @@ internal class WorkflowInterceptorTest { key: String, sideEffect: suspend CoroutineScope.() -> Unit ) { - runBlocking { sideEffect() } + launch { sideEffect() } + advanceUntilIdle() } } diff --git a/workflow-runtime/src/commonTest/kotlin/com/squareup/workflow1/internal/ChainedWorkflowInterceptorTest.kt b/workflow-runtime/src/commonTest/kotlin/com/squareup/workflow1/internal/ChainedWorkflowInterceptorTest.kt index 772a6abc9..441687de1 100644 --- a/workflow-runtime/src/commonTest/kotlin/com/squareup/workflow1/internal/ChainedWorkflowInterceptorTest.kt +++ b/workflow-runtime/src/commonTest/kotlin/com/squareup/workflow1/internal/ChainedWorkflowInterceptorTest.kt @@ -18,6 +18,8 @@ import com.squareup.workflow1.rendering import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import kotlin.test.Test import kotlin.test.assertEquals @@ -55,7 +57,7 @@ internal class ChainedWorkflowInterceptorTest { @OptIn(ExperimentalCoroutinesApi::class) @Test - fun chains_calls_to_onInstanceStarted_in_left_to_right_order() { + fun chains_calls_to_onInstanceStarted_in_left_to_right_order() = runTest { val events = mutableListOf() val interceptor1 = object : WorkflowInterceptor { override fun onSessionStarted( @@ -81,9 +83,10 @@ internal class ChainedWorkflowInterceptorTest { } val chained = listOf(interceptor1, interceptor2).chained() - runTest { + launch { chained.onSessionStarted(this, TestSession) } + advanceUntilIdle() assertEquals(listOf("started1", "started2", "cancelled1", "cancelled2"), events) } diff --git a/workflow-runtime/src/commonTest/kotlin/com/squareup/workflow1/internal/SubtreeManagerTest.kt b/workflow-runtime/src/commonTest/kotlin/com/squareup/workflow1/internal/SubtreeManagerTest.kt index f74a6b405..387aa9145 100644 --- a/workflow-runtime/src/commonTest/kotlin/com/squareup/workflow1/internal/SubtreeManagerTest.kt +++ b/workflow-runtime/src/commonTest/kotlin/com/squareup/workflow1/internal/SubtreeManagerTest.kt @@ -13,9 +13,10 @@ import com.squareup.workflow1.applyTo import com.squareup.workflow1.identifier import com.squareup.workflow1.internal.SubtreeManagerTest.TestWorkflow.Rendering import kotlinx.coroutines.Dispatchers.Unconfined +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.async -import kotlinx.coroutines.runBlocking import kotlinx.coroutines.selects.select +import kotlinx.coroutines.test.runTest import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFailsWith @@ -24,6 +25,7 @@ import kotlin.test.fail private typealias StringHandler = (String) -> WorkflowAction +@ExperimentalCoroutinesApi internal class SubtreeManagerTest { private class TestWorkflow : StatefulWorkflow() { @@ -154,7 +156,7 @@ internal class SubtreeManagerTest { assertEquals("initialState:props", composeState) } - @Test fun tick_children_handles_child_output() { + @Test fun tick_children_handles_child_output() = runTest { val manager = subtreeManagerForTest() val workflow = TestWorkflow() val handler: StringHandler = { output -> @@ -166,44 +168,40 @@ internal class SubtreeManagerTest { val (_, _, eventHandler) = manager.render(workflow, "props", key = "", handler = handler) manager.commitRenderedChildren() - runBlocking { - val tickOutput = async { manager.tickAction() } - assertFalse(tickOutput.isCompleted) + val tickOutput = async { manager.tickAction() } + assertFalse(tickOutput.isCompleted) - eventHandler("event!") - val update = tickOutput.await().value!! + eventHandler("event!") + val update = tickOutput.await().value!! - val (_, output) = update.applyTo("props", "state") - assertEquals("case output:workflow output:event!", output?.value) - } + val (_, output) = update.applyTo("props", "state") + assertEquals("case output:workflow output:event!", output?.value) } - @Test fun render_updates_childs_output_handler() { + @Test fun render_updates_childs_output_handler() = runTest { val manager = subtreeManagerForTest() val workflow = TestWorkflow() fun render(handler: StringHandler) = manager.render(workflow, "props", key = "", handler = handler) .also { manager.commitRenderedChildren() } - runBlocking { - // First render + tick pass – uninteresting. - render { action { setOutput("initial handler: $it") } } - .let { rendering -> - rendering.eventHandler("initial output") - val initialAction = manager.tickAction().value - val (_, initialOutput) = initialAction!!.applyTo("", "") - assertEquals("initial handler: workflow output:initial output", initialOutput?.value) - } - - // Do a second render + tick, but with a different handler function. - render { action { setOutput("second handler: $it") } } - .let { rendering -> - rendering.eventHandler("second output") - val secondAction = manager.tickAction().value - val (_, secondOutput) = secondAction!!.applyTo("", "") - assertEquals("second handler: workflow output:second output", secondOutput?.value) - } - } + // First render + tick pass – uninteresting. + render { action { setOutput("initial handler: $it") } } + .let { rendering -> + rendering.eventHandler("initial output") + val initialAction = manager.tickAction().value + val (_, initialOutput) = initialAction!!.applyTo("", "") + assertEquals("initial handler: workflow output:initial output", initialOutput?.value) + } + + // Do a second render + tick, but with a different handler function. + render { action { setOutput("second handler: $it") } } + .let { rendering -> + rendering.eventHandler("second output") + val secondAction = manager.tickAction().value + val (_, secondOutput) = secondAction!!.applyTo("", "") + assertEquals("second handler: workflow output:second output", secondOutput?.value) + } } // See https://github.com/square/workflow/issues/404 diff --git a/workflow-runtime/src/commonTest/kotlin/com/squareup/workflow1/internal/WorkflowNodeTest.kt b/workflow-runtime/src/commonTest/kotlin/com/squareup/workflow1/internal/WorkflowNodeTest.kt index 841285fc6..ca889abfc 100644 --- a/workflow-runtime/src/commonTest/kotlin/com/squareup/workflow1/internal/WorkflowNodeTest.kt +++ b/workflow-runtime/src/commonTest/kotlin/com/squareup/workflow1/internal/WorkflowNodeTest.kt @@ -1118,7 +1118,7 @@ internal class WorkflowNodeTest { ) } - @Test fun actionSink_action_changes_state() { + @Test fun actionSink_action_changes_state() = runTest { val workflow = Workflow.stateful>>( initialState = { "initial" }, render = { _, renderState -> @@ -1138,11 +1138,9 @@ internal class WorkflowNodeTest { sink.send("hello") - runTest { - select { - node.tick(this) - } as WorkflowOutput? - } + select { + node.tick(this) + } as WorkflowOutput? val (state, _) = node.render(workflow.asStatefulWorkflow(), Unit) assertEquals("initial->hello", state) @@ -1196,7 +1194,7 @@ internal class WorkflowNodeTest { } } - @Test fun child_action_changes_state() { + @Test fun child_action_changes_state() = runTest { val workflow = Workflow.stateful( initialState = { "initial" }, render = { _, renderState -> @@ -1215,11 +1213,9 @@ internal class WorkflowNodeTest { ) node.render(workflow.asStatefulWorkflow(), Unit) - runTest { - select { - node.tick(this) - } as WorkflowOutput? - } + select { + node.tick(this) + } as WorkflowOutput? val state = node.render(workflow.asStatefulWorkflow(), Unit) assertEquals("initial->hello", state)