diff --git a/examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/TodoRoot.kt b/examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/TodoRoot.kt index 87d977d50c..156280edc6 100644 --- a/examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/TodoRoot.kt +++ b/examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/TodoRoot.kt @@ -4,6 +4,7 @@ import com.arkivanov.decompose.ComponentContext import com.arkivanov.decompose.RouterState import com.arkivanov.decompose.value.Value import com.arkivanov.mvikotlin.core.store.StoreFactory +import com.badoo.reaktive.base.Consumer import example.todo.common.edit.TodoEdit import example.todo.common.main.TodoMain import example.todo.common.root.TodoRoot.Dependencies @@ -27,4 +28,23 @@ interface TodoRoot { @Suppress("FunctionName") // Factory function fun TodoRoot(componentContext: ComponentContext, dependencies: Dependencies): TodoRoot = - TodoRootImpl(componentContext, dependencies) + TodoRootImpl( + componentContext = componentContext, + todoMain = { childContext, output -> + TodoMain( + componentContext = childContext, + dependencies = object : TodoMain.Dependencies, Dependencies by dependencies { + override val mainOutput: Consumer = output + } + ) + }, + todoEdit = { childContext, itemId, output -> + TodoEdit( + componentContext = childContext, + dependencies = object : TodoEdit.Dependencies, Dependencies by dependencies { + override val itemId: Long = itemId + override val editOutput: Consumer = output + } + ) + } + ) diff --git a/examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/integration/TodoRootImpl.kt b/examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/integration/TodoRootImpl.kt index 418ff2af9c..9d69e8c542 100644 --- a/examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/integration/TodoRootImpl.kt +++ b/examples/todoapp/common/root/src/commonMain/kotlin/example/todo/common/root/integration/TodoRootImpl.kt @@ -13,13 +13,13 @@ import example.todo.common.edit.TodoEdit import example.todo.common.main.TodoMain import example.todo.common.root.TodoRoot import example.todo.common.root.TodoRoot.Child -import example.todo.common.root.TodoRoot.Dependencies import example.todo.common.utils.Consumer internal class TodoRootImpl( componentContext: ComponentContext, - dependencies: Dependencies -) : TodoRoot, ComponentContext by componentContext, Dependencies by dependencies { + private val todoMain: (ComponentContext, Consumer) -> TodoMain, + private val todoEdit: (ComponentContext, itemId: Long, Consumer) -> TodoEdit +) : TodoRoot, ComponentContext by componentContext { private val router = router( @@ -32,27 +32,10 @@ internal class TodoRootImpl( private fun createChild(configuration: Configuration, componentContext: ComponentContext): Child = when (configuration) { - is Configuration.Main -> Child.Main(todoMain(componentContext)) - is Configuration.Edit -> Child.Edit(todoEdit(componentContext, itemId = configuration.itemId)) + is Configuration.Main -> Child.Main(todoMain(componentContext, Consumer(::onMainOutput))) + is Configuration.Edit -> Child.Edit(todoEdit(componentContext, configuration.itemId, Consumer(::onEditOutput))) } - private fun todoMain(componentContext: ComponentContext): TodoMain = - TodoMain( - componentContext = componentContext, - dependencies = object : TodoMain.Dependencies, Dependencies by this { - override val mainOutput: Consumer = Consumer(::onMainOutput) - } - ) - - private fun todoEdit(componentContext: ComponentContext, itemId: Long): TodoEdit = - TodoEdit( - componentContext = componentContext, - dependencies = object : TodoEdit.Dependencies, Dependencies by this { - override val itemId: Long = itemId - override val editOutput: Consumer = Consumer(::onEditOutput) - } - ) - private fun onMainOutput(output: TodoMain.Output): Unit = when (output) { is TodoMain.Output.Selected -> router.push(Configuration.Edit(itemId = output.id)) diff --git a/examples/todoapp/common/root/src/commonTest/kotlin/example/todo/common/root/integration/TodoEditFake.kt b/examples/todoapp/common/root/src/commonTest/kotlin/example/todo/common/root/integration/TodoEditFake.kt new file mode 100644 index 0000000000..4ec3c02692 --- /dev/null +++ b/examples/todoapp/common/root/src/commonTest/kotlin/example/todo/common/root/integration/TodoEditFake.kt @@ -0,0 +1,24 @@ +package example.todo.common.root.integration + +import com.arkivanov.decompose.value.Value +import com.badoo.reaktive.base.Consumer +import example.todo.common.edit.TodoEdit +import example.todo.common.edit.TodoEdit.Model +import example.todo.common.edit.TodoEdit.Output + +class TodoEditFake( + val itemId: Long, + val output: Consumer +) : TodoEdit { + + override val models: Value get() = TODO("Not used") + + override fun onTextChanged(text: String) { + } + + override fun onDoneChanged(isDone: Boolean) { + } + + override fun onCloseClicked() { + } +} \ No newline at end of file diff --git a/examples/todoapp/common/root/src/commonTest/kotlin/example/todo/common/root/integration/TodoMainFake.kt b/examples/todoapp/common/root/src/commonTest/kotlin/example/todo/common/root/integration/TodoMainFake.kt new file mode 100644 index 0000000000..7c2ba7e19b --- /dev/null +++ b/examples/todoapp/common/root/src/commonTest/kotlin/example/todo/common/root/integration/TodoMainFake.kt @@ -0,0 +1,29 @@ +package example.todo.common.root.integration + +import com.arkivanov.decompose.value.Value +import com.badoo.reaktive.base.Consumer +import example.todo.common.main.TodoMain +import example.todo.common.main.TodoMain.Model +import example.todo.common.main.TodoMain.Output + +class TodoMainFake( + val output: Consumer +) : TodoMain { + + override val models: Value get() = TODO("Not used") + + override fun onItemClicked(id: Long) { + } + + override fun onItemDoneChanged(id: Long, isDone: Boolean) { + } + + override fun onItemDeleteClicked(id: Long) { + } + + override fun onInputTextChanged(text: String) { + } + + override fun onAddItemClicked() { + } +} \ No newline at end of file diff --git a/examples/todoapp/common/root/src/commonTest/kotlin/example/todo/common/root/integration/TodoRootTest.kt b/examples/todoapp/common/root/src/commonTest/kotlin/example/todo/common/root/integration/TodoRootTest.kt new file mode 100644 index 0000000000..1fa2122987 --- /dev/null +++ b/examples/todoapp/common/root/src/commonTest/kotlin/example/todo/common/root/integration/TodoRootTest.kt @@ -0,0 +1,66 @@ +package example.todo.common.root.integration + +import com.arkivanov.decompose.DefaultComponentContext +import com.arkivanov.decompose.lifecycle.LifecycleRegistry +import com.arkivanov.decompose.lifecycle.resume +import com.badoo.reaktive.base.invoke +import example.todo.common.edit.TodoEdit +import example.todo.common.main.TodoMain +import example.todo.common.root.TodoRoot +import example.todo.common.root.TodoRoot.Child +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +@Suppress("TestFunctionName") +class TodoRootTest { + + private val lifecycle = LifecycleRegistry().apply { resume() } + + @Test + fun WHEN_created_THEN_TodoMain_displayed() { + val root = root() + + assertTrue(root.activeChild is Child.Main) + } + + @Test + fun GIVEN_TodoMain_displayed_WHEN_TodoMain_Output_Selected_THEN_TodoEdit_displayed() { + val root = root() + + root.activeChild.asTodoMain().output(TodoMain.Output.Selected(id = 10L)) + + assertTrue(root.activeChild is Child.Edit) + assertEquals(10L, root.activeChild.asTodoEdit().itemId) + } + + @Test + fun GIVEN_TodoEdit_displayed_WHEN_TodoEdit_Output_Finished_THEN_TodoMain_displayed() { + val root = root() + root.activeChild.asTodoMain().output(TodoMain.Output.Selected(id = 10L)) + + root.activeChild.asTodoEdit().output(TodoEdit.Output.Finished) + + assertTrue(root.activeChild is Child.Main) + } + + private fun root(): TodoRoot = + TodoRootImpl( + componentContext = DefaultComponentContext(lifecycle = lifecycle), + todoMain = { _, output -> TodoMainFake(output) }, + todoEdit = { _, itemId, output -> TodoEditFake(itemId, output) } + ) + + private val TodoRoot.activeChild: Child get() = routerState.value.activeChild.component + + private val Child.component: Any + get() = + when (this) { + is Child.Main -> component + is Child.Edit -> component + } + + private fun Child.asTodoMain(): TodoMainFake = component as TodoMainFake + + private fun Child.asTodoEdit(): TodoEditFake = component as TodoEditFake +}