diff --git a/sample/src/test/java/com/trendyol/transmission/features/colorpicker/ColorPickerTransformerTest.kt b/sample/src/test/java/com/trendyol/transmission/features/colorpicker/ColorPickerTransformerTest.kt index d25568f..b3e8b1c 100644 --- a/sample/src/test/java/com/trendyol/transmission/features/colorpicker/ColorPickerTransformerTest.kt +++ b/sample/src/test/java/com/trendyol/transmission/features/colorpicker/ColorPickerTransformerTest.kt @@ -3,8 +3,8 @@ package com.trendyol.transmission.features.colorpicker import androidx.compose.ui.graphics.Color import com.trendyol.transmission.transformer.util.TestCoroutineRule import com.trendyol.transmission.ui.ColorPickerUiState -import com.yigitozgumus.transmissiontesting.testWithEffect -import com.yigitozgumus.transmissiontesting.testWithSignal +import com.yigitozgumus.transmissiontesting.attachToRouter +import com.yigitozgumus.transmissiontesting.test import org.junit.Before import org.junit.Rule import org.junit.Test @@ -25,45 +25,49 @@ class ColorPickerTransformerTest { @Test fun `GIVEN transformer, WHEN BackgroundColorUpdate effect is received, THEN color should be changed 1`() { - sut.testWithEffect(effect = ColorPickerEffect.BackgroundColorUpdate(Color.Gray)) { - assertEquals( - ColorPickerUiState(backgroundColor = Color.Gray), - dataStream.last() - ) - } + sut.attachToRouter() + .test(effect = ColorPickerEffect.BackgroundColorUpdate(Color.Gray)) { + assertEquals( + ColorPickerUiState(backgroundColor = Color.Gray), + dataStream.last() + ) + } } @Test fun `GIVEN transformer, WHEN BackgroundColorUpdate effect is received, THEN color should be changed`() = - sut.testWithEffect(effect = ColorPickerEffect.BackgroundColorUpdate(Color.Gray)) { - assertEquals( - ColorPickerUiState(backgroundColor = Color.Gray), - dataStream.last() - ) - } + sut.attachToRouter() + .test(effect = ColorPickerEffect.BackgroundColorUpdate(Color.Gray)) { + assertEquals( + ColorPickerUiState(backgroundColor = Color.Gray), + dataStream.last() + ) + } @Test fun `GIVEN inputTransformer, WHEN SelectColor signal is sent, THEN selectedColorIndex should be updated`() = - sut.testWithSignal(signal = ColorPickerSignal.SelectColor(3, Color.Blue)) { - assertEquals( - 3, - (dataStream.last() as ColorPickerUiState).selectedColorIndex - ) - } + sut.attachToRouter() + .test(ColorPickerSignal.SelectColor(3, Color.Blue)) { + assertEquals( + 3, + (dataStream.last() as ColorPickerUiState).selectedColorIndex + ) + } @Test fun `GIVEN inputTransformer, WHEN SelectColor signal is sent, THEN BackgroundColorUpdate effect should be published`() { - sut.testWithSignal(signal = ColorPickerSignal.SelectColor(3, Color.Blue)) { - assertEquals( - Color.Blue.copy(alpha = 0.1f), - (effectStream.first().effect as ColorPickerEffect.BackgroundColorUpdate).color - ) - } + sut.attachToRouter() + .test(signal = ColorPickerSignal.SelectColor(3, Color.Blue)) { + assertEquals( + Color.Blue.copy(alpha = 0.1f), + (effectStream.first().effect as ColorPickerEffect.BackgroundColorUpdate).color + ) + } } @Test fun `GIVEN inputTransformer, WHEN SelectColor signal is sent, THEN SelectedColorUpdate is sent to MultiOutputTransformer`() { - sut.testWithSignal(signal = ColorPickerSignal.SelectColor(3, Color.Blue)) { + sut.attachToRouter().test(signal = ColorPickerSignal.SelectColor(3, Color.Blue)) { assertTrue { effectStream.last().effect is ColorPickerEffect.SelectedColorUpdate } } } diff --git a/sample/src/test/java/com/trendyol/transmission/features/input/InputTransformerTest.kt b/sample/src/test/java/com/trendyol/transmission/features/input/InputTransformerTest.kt index f8b2cc6..a1ac81b 100644 --- a/sample/src/test/java/com/trendyol/transmission/features/input/InputTransformerTest.kt +++ b/sample/src/test/java/com/trendyol/transmission/features/input/InputTransformerTest.kt @@ -4,8 +4,8 @@ import androidx.compose.ui.graphics.Color import com.trendyol.transmission.features.colorpicker.ColorPickerEffect import com.trendyol.transmission.transformer.util.TestCoroutineRule import com.trendyol.transmission.ui.InputUiState -import com.yigitozgumus.transmissiontesting.testWithEffect -import com.yigitozgumus.transmissiontesting.testWithSignal +import com.yigitozgumus.transmissiontesting.attachToRouter +import com.yigitozgumus.transmissiontesting.test import org.junit.Before import org.junit.Rule import kotlin.test.Test @@ -25,16 +25,18 @@ class InputTransformerTest { @Test fun `GIVEN inputTransformer, WHEN inputUpdate signal is sent, THEN inputUpdate effect is published`() { - sut.testWithSignal(signal = InputSignal.InputUpdate("test")) { - assertEquals(InputEffect.InputUpdate("test"), effectStream.first().effect) - assertEquals(InputUiState("test"), dataStream.last()) - } + sut.attachToRouter() + .test(signal = InputSignal.InputUpdate("test")) { + assertEquals(InputEffect.InputUpdate("test"), effectStream.first().effect) + assertEquals(InputUiState("test"), dataStream.last()) + } } @Test fun `GIVEN inputTransformer, WHEN BackgroundColorUpdate effect is received, THEN color should be changed`() { - sut.testWithEffect(effect = ColorPickerEffect.BackgroundColorUpdate(Color.Gray)) { - assertEquals(InputUiState(backgroundColor = Color.Gray), dataStream.last()) - } + sut.attachToRouter() + .test(effect = ColorPickerEffect.BackgroundColorUpdate(Color.Gray)) { + assertEquals(InputUiState(backgroundColor = Color.Gray), dataStream.last()) + } } } diff --git a/sample/src/test/java/com/trendyol/transmission/features/output/OutputTransformerTest.kt b/sample/src/test/java/com/trendyol/transmission/features/output/OutputTransformerTest.kt index d24e070..39ac5d1 100644 --- a/sample/src/test/java/com/trendyol/transmission/features/output/OutputTransformerTest.kt +++ b/sample/src/test/java/com/trendyol/transmission/features/output/OutputTransformerTest.kt @@ -5,7 +5,8 @@ import com.trendyol.transmission.features.input.InputEffect import com.trendyol.transmission.transformer.util.TestCoroutineRule import com.trendyol.transmission.ui.ColorPickerUiState import com.trendyol.transmission.ui.OutputUiState -import com.yigitozgumus.transmissiontesting.testWithEffect +import com.yigitozgumus.transmissiontesting.attachToRouter +import com.yigitozgumus.transmissiontesting.test import org.junit.Before import org.junit.Rule import org.junit.Test @@ -26,25 +27,29 @@ class OutputTransformerTest { @Test fun `GIVEN sut, WHEN inputUpdate effect comes, THEN, holder should be updated with correct value`() { - sut.testWithEffect(effect = InputEffect.InputUpdate("test")) { - assertEquals(OutputUiState(outputText = "test"), dataStream.last()) - } + sut.attachToRouter() + .test(effect = InputEffect.InputUpdate("test")) { + assertEquals(OutputUiState(outputText = "test"), dataStream.last()) + } } @Test fun `GIVEN sut, WHEN inputUpdate effect comes and no ColorPickerUIState data is present, THEN data should not be updated further`() { - sut.testWithEffect(effect = InputEffect.InputUpdate("test")) { - assertEquals(OutputUiState(outputText = "test"), dataStream.last()) - } + sut.attachToRouter() + .test(effect = InputEffect.InputUpdate("test")) { + assertEquals(OutputUiState(outputText = "test"), dataStream.last()) + } } @Test fun `GIVEN sut, WHEN inputUpdate effect comes and ColorPickerUIState exists, THEN RouterPayloadEffect should be published`() { - sut.testWithEffect(effect = InputEffect.InputUpdate("test"), registry = { - addQueryData(ColorPickerUiState(), key = "ColorPickerUiState") - }) { - assertEquals(OutputUiState(outputText = "test"), dataStream[1]) - assertTrue(effectStream.last().effect is RouterEffect) - } + sut.attachToRouter() + .register { + addQueryData(ColorPickerUiState(), key = "ColorPickerUiState") + } + .test(effect = InputEffect.InputUpdate("test")) { + assertEquals(OutputUiState(outputText = "test"), dataStream[1]) + assertTrue(effectStream.last().effect is RouterEffect) + } } } diff --git a/transmission-test/src/main/java/com/yigitozgumus/transmissiontesting/TestRouter.kt b/transmission-test/src/main/java/com/yigitozgumus/transmissiontesting/TestRouter.kt index 6451ff6..029e2ac 100644 --- a/transmission-test/src/main/java/com/yigitozgumus/transmissiontesting/TestRouter.kt +++ b/transmission-test/src/main/java/com/yigitozgumus/transmissiontesting/TestRouter.kt @@ -17,11 +17,11 @@ import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.launch internal class TestRouter( - private val registry: RegistryScopeImpl, private val transformer: Transformer, dispatcher: CoroutineDispatcher ) { private val testScope = CoroutineScope(dispatcher) + var registry: RegistryScopeImpl = RegistryScopeImpl() private val signalBroadcast = testScope.createBroadcast() private val effectBroadcast = testScope.createBroadcast() diff --git a/transmission-test/src/main/java/com/yigitozgumus/transmissiontesting/TestSuite.kt b/transmission-test/src/main/java/com/yigitozgumus/transmissiontesting/TestSuite.kt new file mode 100644 index 0000000..9a969fc --- /dev/null +++ b/transmission-test/src/main/java/com/yigitozgumus/transmissiontesting/TestSuite.kt @@ -0,0 +1,77 @@ +package com.yigitozgumus.transmissiontesting + +import com.trendyol.transmission.Transmission +import com.trendyol.transmission.effect.EffectWrapper +import com.trendyol.transmission.transformer.Transformer +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.toList +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.UnconfinedTestDispatcher +import kotlinx.coroutines.test.advanceUntilIdle +import kotlinx.coroutines.test.runTest + +class TestSuite { + private var orderedInitialProcessing: List = emptyList() + private var transformer: Transformer? = null + private lateinit var router: TestRouter + + @OptIn(ExperimentalCoroutinesApi::class) + fun initialize(transformer: Transformer): TestSuite { + this.transformer = transformer + router = TestRouter(transformer, UnconfinedTestDispatcher()) + return this + } + + fun register(registry: RegistryScope.() -> Unit = {}): TestSuite { + router.registry = RegistryScopeImpl().apply(registry) + return this + } + + fun processBeforeTesting(vararg transmissions: Transmission): TestSuite { + orderedInitialProcessing = transmissions.toList() + return this + } + + @OptIn(ExperimentalCoroutinesApi::class) + fun runTest( + transmission: Transmission, + scope: suspend TransformerTestScope.(scope: TestScope) -> Unit + ) { + + runTest { + val dataStream: MutableList = mutableListOf() + val effectStream: MutableList = mutableListOf() + try { + backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) { + router.dataStream.toList(dataStream) + } + backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) { + router.effectStream.toList(effectStream) + } + val testScope = object : TransformerTestScope { + override val dataStream: List = dataStream + override val effectStream: List = effectStream + } + orderedInitialProcessing.forEach { + when (it) { + is Transmission.Data -> throw IllegalArgumentException("Transmission.Data should not be sent for processing") + is Transmission.Effect -> router.sendEffect(it) + is Transmission.Signal -> router.sendSignal(it) + } + transformer?.waitProcessingToFinish() + } + if (transmission is Transmission.Signal) { + router.sendSignal(transmission) + } else if (transmission is Transmission.Effect) { + router.sendEffect(transmission) + } + transformer?.waitProcessingToFinish() + testScope.scope(this) + } finally { + advanceUntilIdle() + router.clear() + } + } + } +} diff --git a/transmission-test/src/main/java/com/yigitozgumus/transmissiontesting/TestWithExt.kt b/transmission-test/src/main/java/com/yigitozgumus/transmissiontesting/TestWithExt.kt index cf723eb..ab8edb4 100644 --- a/transmission-test/src/main/java/com/yigitozgumus/transmissiontesting/TestWithExt.kt +++ b/transmission-test/src/main/java/com/yigitozgumus/transmissiontesting/TestWithExt.kt @@ -1,96 +1,25 @@ package com.yigitozgumus.transmissiontesting import com.trendyol.transmission.Transmission -import com.trendyol.transmission.effect.EffectWrapper import com.trendyol.transmission.transformer.Transformer -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.toList -import kotlinx.coroutines.launch import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.UnconfinedTestDispatcher -import kotlinx.coroutines.test.advanceUntilIdle -import kotlinx.coroutines.test.runTest -@OptIn(ExperimentalCoroutinesApi::class) -fun Transformer.testWithEffect( - orderedInitialProcessing: List = emptyList(), +fun Transformer.attachToRouter(): TestSuite { + return TestSuite().initialize(this) +} + +fun TestSuite.test( effect: Transmission.Effect, - registry: RegistryScope.() -> Unit = {}, scope: suspend TransformerTestScope.(scope: TestScope) -> Unit ) { - runTest { - val registryImpl = RegistryScopeImpl().apply(registry) - val testRouter = TestRouter(registryImpl, this@testWithEffect, UnconfinedTestDispatcher()) - val dataStream: MutableList = mutableListOf() - val effectStream: MutableList = mutableListOf() - try { - backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) { - testRouter.dataStream.toList(dataStream) - } - backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) { - testRouter.effectStream.toList(effectStream) - } - val testScope = object : TransformerTestScope { - override val dataStream: List = dataStream - override val effectStream: List = effectStream - } - orderedInitialProcessing.forEach { - when (it) { - is Transmission.Data -> throw IllegalArgumentException("Transmission.Data should not be sent for processing") - is Transmission.Effect -> testRouter.sendEffect(it) - is Transmission.Signal -> testRouter.sendSignal(it) - } - this@testWithEffect.waitProcessingToFinish() - } - testRouter.sendEffect(effect) - this@testWithEffect.waitProcessingToFinish() - testScope.scope(this) - } finally { - advanceUntilIdle() - testRouter.clear() - } - } + this.runTest(effect, scope) } -@OptIn(ExperimentalCoroutinesApi::class) -fun Transformer.testWithSignal( - orderedInitialProcessing: List = emptyList(), +fun TestSuite.test( signal: Transmission.Signal, - registry: RegistryScope.() -> Unit = {}, scope: suspend TransformerTestScope.(scope: TestScope) -> Unit ) { - runTest { - val registryImpl = RegistryScopeImpl().apply(registry) - val testRouter = TestRouter(registryImpl, this@testWithSignal, UnconfinedTestDispatcher()) - val dataStream: MutableList = mutableListOf() - val effectStream: MutableList = mutableListOf() - try { - backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) { - testRouter.dataStream.toList(dataStream) - } - backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) { - testRouter.effectStream.toList(effectStream) - } - val testScope = object : TransformerTestScope { - override val dataStream: List = dataStream - override val effectStream: List = effectStream - } - orderedInitialProcessing.forEach { - when (it) { - is Transmission.Data -> throw IllegalArgumentException("Transmission.Data should not be sent for processing") - is Transmission.Effect -> testRouter.sendEffect(it) - is Transmission.Signal -> testRouter.sendSignal(it) - } - this@testWithSignal.waitProcessingToFinish() - } - testRouter.sendSignal(signal) - this@testWithSignal.waitProcessingToFinish() - testScope.scope(this) - } finally { - advanceUntilIdle() - testRouter.clear() - } - } + this.runTest(signal, scope) } suspend fun Transformer.waitProcessingToFinish() {