![avatar](/assets/img/avatar_default.png)
11 changed files with 259 additions and 2 deletions
@ -0,0 +1,13 @@ |
|||||||
|
package example.todo.common.database |
||||||
|
|
||||||
|
import com.squareup.sqldelight.db.SqlDriver |
||||||
|
import com.squareup.sqldelight.sqlite.driver.JdbcSqliteDriver |
||||||
|
import example.todo.database.TodoDatabase |
||||||
|
|
||||||
|
@Suppress("FunctionName") // FactoryFunction |
||||||
|
actual fun TestDatabaseDriver(): SqlDriver { |
||||||
|
val driver = JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY) |
||||||
|
TodoDatabase.Schema.create(driver) |
||||||
|
|
||||||
|
return driver |
||||||
|
} |
@ -0,0 +1,6 @@ |
|||||||
|
package example.todo.common.database |
||||||
|
|
||||||
|
import com.squareup.sqldelight.db.SqlDriver |
||||||
|
|
||||||
|
@Suppress("FunctionName") |
||||||
|
expect fun TestDatabaseDriver(): SqlDriver |
@ -0,0 +1,13 @@ |
|||||||
|
package example.todo.common.database |
||||||
|
|
||||||
|
import com.squareup.sqldelight.db.SqlDriver |
||||||
|
import com.squareup.sqldelight.sqlite.driver.JdbcSqliteDriver |
||||||
|
import example.todo.database.TodoDatabase |
||||||
|
|
||||||
|
@Suppress("FunctionName") // FactoryFunction |
||||||
|
actual fun TestDatabaseDriver(): SqlDriver { |
||||||
|
val driver = JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY) |
||||||
|
TodoDatabase.Schema.create(driver) |
||||||
|
|
||||||
|
return driver |
||||||
|
} |
@ -0,0 +1,103 @@ |
|||||||
|
package example.todo.common.list.integration |
||||||
|
|
||||||
|
import com.arkivanov.decompose.DefaultComponentContext |
||||||
|
import com.arkivanov.decompose.lifecycle.LifecycleRegistry |
||||||
|
import com.arkivanov.mvikotlin.core.store.StoreFactory |
||||||
|
import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory |
||||||
|
import com.badoo.reaktive.base.Consumer |
||||||
|
import com.badoo.reaktive.scheduler.overrideSchedulers |
||||||
|
import com.badoo.reaktive.subject.publish.PublishSubject |
||||||
|
import com.badoo.reaktive.test.observable.assertValue |
||||||
|
import com.badoo.reaktive.test.observable.test |
||||||
|
import com.badoo.reaktive.test.scheduler.TestScheduler |
||||||
|
import example.todo.common.database.TestDatabaseDriver |
||||||
|
import example.todo.common.list.TodoList.Dependencies |
||||||
|
import example.todo.common.list.TodoList.Output |
||||||
|
import example.todo.common.list.store.TodoItem |
||||||
|
import example.todo.database.TodoDatabase |
||||||
|
import kotlin.test.BeforeTest |
||||||
|
import kotlin.test.Test |
||||||
|
import kotlin.test.assertEquals |
||||||
|
import kotlin.test.assertFalse |
||||||
|
import kotlin.test.assertTrue |
||||||
|
|
||||||
|
@Suppress("TestFunctionName") |
||||||
|
class TodoListTest { |
||||||
|
|
||||||
|
private val lifecycle = LifecycleRegistry() |
||||||
|
private val database = TodoDatabase(TestDatabaseDriver()) |
||||||
|
private val outputSubject = PublishSubject<Output>() |
||||||
|
private val output = outputSubject.test() |
||||||
|
|
||||||
|
private val queries = database.todoDatabaseQueries |
||||||
|
|
||||||
|
private val impl by lazy { |
||||||
|
TodoListImpl( |
||||||
|
componentContext = DefaultComponentContext(lifecycle = lifecycle), |
||||||
|
dependencies = object : Dependencies { |
||||||
|
override val storeFactory: StoreFactory = DefaultStoreFactory |
||||||
|
override val database: TodoDatabase = this@TodoListTest.database |
||||||
|
override val listOutput: Consumer<Output> = outputSubject |
||||||
|
} |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
@BeforeTest |
||||||
|
fun before() { |
||||||
|
overrideSchedulers( |
||||||
|
main = { TestScheduler() }, |
||||||
|
io = { TestScheduler() } |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun WHEN_item_added_to_database_THEN_item_displayed() { |
||||||
|
queries.add("Item1") |
||||||
|
|
||||||
|
assertEquals("Item1", firstItem().text) |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun WHEN_item_clicked_THEN_Output_ItemSelected_emitted() { |
||||||
|
queries.add("Item1") |
||||||
|
val id = firstItem().id |
||||||
|
|
||||||
|
impl.onItemClicked(id = id) |
||||||
|
|
||||||
|
output.assertValue(Output.ItemSelected(id = id)) |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun GIVEN_item_isDone_false_WHEN_done_changed_to_true_THEN_item_isDone_true() { |
||||||
|
queries.add("Item1") |
||||||
|
val id = firstItem().id |
||||||
|
queries.setDone(id = id, isDone = false) |
||||||
|
|
||||||
|
impl.onDoneChanged(id = id, isDone = true) |
||||||
|
|
||||||
|
assertTrue(firstItem().isDone) |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun GIVEN_item_isDone_true_WHEN_done_changed_to_false_THEN_item_isDone_false() { |
||||||
|
queries.add("Item1") |
||||||
|
val id = firstItem().id |
||||||
|
queries.setDone(id = id, isDone = true) |
||||||
|
|
||||||
|
impl.onDoneChanged(id = id, isDone = false) |
||||||
|
|
||||||
|
assertFalse(firstItem().isDone) |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun WHEN_item_text_changed_THEN_item_updated() { |
||||||
|
queries.add("Item1") |
||||||
|
val id = firstItem().id |
||||||
|
|
||||||
|
queries.setText(id = id, text = "New text") |
||||||
|
|
||||||
|
assertEquals("New text", firstItem().text) |
||||||
|
} |
||||||
|
|
||||||
|
private fun firstItem(): TodoItem = impl.state.items[0] |
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
package example.todo.common.list.store |
||||||
|
|
||||||
|
import com.badoo.reaktive.completable.Completable |
||||||
|
import com.badoo.reaktive.completable.completableFromFunction |
||||||
|
import com.badoo.reaktive.observable.Observable |
||||||
|
import com.badoo.reaktive.subject.behavior.BehaviorSubject |
||||||
|
import example.todo.common.list.store.TodoListStoreProvider.Database |
||||||
|
|
||||||
|
internal class TestTodoListStoreDatabase : Database { |
||||||
|
|
||||||
|
private val subject = BehaviorSubject<List<TodoItem>>(emptyList()) |
||||||
|
|
||||||
|
var items: List<TodoItem> |
||||||
|
get() = subject.value |
||||||
|
set(value) { |
||||||
|
subject.onNext(value) |
||||||
|
} |
||||||
|
|
||||||
|
override val updates: Observable<List<TodoItem>> = subject |
||||||
|
|
||||||
|
override fun setDone(id: Long, isDone: Boolean): Completable = |
||||||
|
completableFromFunction { |
||||||
|
update(id = id) { copy(isDone = isDone) } |
||||||
|
} |
||||||
|
|
||||||
|
private fun update(id: Long, func: TodoItem.() -> TodoItem) { |
||||||
|
items = items.map { if (it.id == id) it.func() else it } |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,58 @@ |
|||||||
|
package example.todo.common.list.store |
||||||
|
|
||||||
|
import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory |
||||||
|
import com.badoo.reaktive.scheduler.overrideSchedulers |
||||||
|
import com.badoo.reaktive.test.scheduler.TestScheduler |
||||||
|
import kotlin.test.BeforeTest |
||||||
|
import kotlin.test.Test |
||||||
|
import kotlin.test.assertEquals |
||||||
|
import kotlin.test.assertTrue |
||||||
|
|
||||||
|
@Suppress("TestFunctionName") |
||||||
|
class TodoListStoreTest { |
||||||
|
|
||||||
|
private val database = TestTodoListStoreDatabase() |
||||||
|
private val provider = TodoListStoreProvider(storeFactory = DefaultStoreFactory, database = database) |
||||||
|
|
||||||
|
@BeforeTest |
||||||
|
fun before() { |
||||||
|
overrideSchedulers(main = { TestScheduler() }) |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun GIVEN_items_in_database_WHEN_created_THEN_loads_items_from_database() { |
||||||
|
val item1 = TodoItem(id = 1L, order = 2L, text = "item1") |
||||||
|
val item2 = TodoItem(id = 2L, order = 1L, text = "item2", isDone = true) |
||||||
|
val item3 = TodoItem(id = 3L, order = 3L, text = "item3") |
||||||
|
database.items = listOf(item1, item2, item3) |
||||||
|
|
||||||
|
val store = provider.provide() |
||||||
|
|
||||||
|
assertEquals(listOf(item3, item1, item2), store.state.items) |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun WHEN_items_changed_in_database_THEN_contains_new_items() { |
||||||
|
database.items = listOf(TodoItem()) |
||||||
|
val store = provider.provide() |
||||||
|
|
||||||
|
val item1 = TodoItem(id = 1L, order = 2L, text = "item1") |
||||||
|
val item2 = TodoItem(id = 2L, order = 1L, text = "item2", isDone = true) |
||||||
|
val item3 = TodoItem(id = 3L, order = 3L, text = "item3") |
||||||
|
database.items = listOf(item1, item2, item3) |
||||||
|
|
||||||
|
assertEquals(listOf(item3, item1, item2), store.state.items) |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun WHEN_Intent_setDone_THEN_done_changed_in_state() { |
||||||
|
val item1 = TodoItem(id = 1L, text = "item1") |
||||||
|
val item2 = TodoItem(id = 2L, text = "item2", isDone = false) |
||||||
|
database.items = listOf(item1, item2) |
||||||
|
val store = provider.provide() |
||||||
|
|
||||||
|
store.accept(TodoListStore.Intent.SetDone(id = 2L, isDone = true)) |
||||||
|
|
||||||
|
assertTrue(store.state.items.first { it.id == 2L }.isDone) |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue