diff --git a/mvrx/src/main/kotlin/com/airbnb/mvrx/BaseMvRxViewModel.kt b/mvrx/src/main/kotlin/com/airbnb/mvrx/BaseMvRxViewModel.kt index 11b12cae1..5f088783e 100644 --- a/mvrx/src/main/kotlin/com/airbnb/mvrx/BaseMvRxViewModel.kt +++ b/mvrx/src/main/kotlin/com/airbnb/mvrx/BaseMvRxViewModel.kt @@ -152,6 +152,13 @@ abstract class BaseMvRxViewModel( stateReducer: S.(Async) -> S ) = execute({ it }, null, stateReducer) + /** + * Helper to map a Completable to an Async property on the state object. + */ + fun Completable.execute( + stateReducer: S.(Async) -> S + ) = toSingle { Unit }.execute(stateReducer) + /** * Execute an observable and wrap its progression with AsyncData reduced to the global state. * diff --git a/mvrx/src/test/kotlin/com/airbnb/mvrx/ViewModelSubscriberTest.kt b/mvrx/src/test/kotlin/com/airbnb/mvrx/ViewModelSubscriberTest.kt index 219e8c7b7..464bb6798 100644 --- a/mvrx/src/test/kotlin/com/airbnb/mvrx/ViewModelSubscriberTest.kt +++ b/mvrx/src/test/kotlin/com/airbnb/mvrx/ViewModelSubscriberTest.kt @@ -1,6 +1,7 @@ package com.airbnb.mvrx import android.arch.lifecycle.Lifecycle +import io.reactivex.Completable import io.reactivex.Maybe import io.reactivex.Observable import io.reactivex.Single @@ -16,7 +17,10 @@ data class ViewModelTestState( val bar: Int = 0, val bam: Int = 0, val list: List = emptyList(), + // for Single and Observable tests val async: Async = Uninitialized, + // for Completable tests + val asyncUnit: Async = Uninitialized, val prop6: Int = 0, val prop7: Int = 0 ) : MvRxState @@ -60,6 +64,41 @@ class ViewModelTestViewModel(initialState: ViewModelTestState) : TestMvRxViewMod onCleared() } + fun testCompletableSuccess() { + var callCount = 0 + selectSubscribe(ViewModelTestState::asyncUnit) { + callCount++ + assertEquals(when (callCount) { + 1 -> Uninitialized + 2 -> Loading() + 3 -> Success(Unit) + else -> throw IllegalArgumentException("Unexpected call count $callCount") + }, it) + } + Completable.create { emitter -> + emitter.onComplete() + }.execute { copy(asyncUnit = it) } + assertEquals(3, callCount) + } + + fun testCompletableFail() { + var callCount = 0 + val error = IllegalStateException("Fail") + selectSubscribe(ViewModelTestState::asyncUnit) { + callCount++ + assertEquals(when (callCount) { + 1 -> Uninitialized + 2 -> Loading() + 3 -> Fail(error) + else -> throw IllegalArgumentException("Unexpected call count $callCount") + }, it) + } + Completable.create { + throw error + }.execute { copy(asyncUnit = it) } + assertEquals(3, callCount) + } + fun testSingleSuccess() { var callCount = 0 selectSubscribe(ViewModelTestState::async) { @@ -408,6 +447,16 @@ class ViewModelSubscriberTest : BaseTest() { assertTrue(disposable.isDisposed) } + @Test + fun testCompletableSuccess() { + viewModel.testCompletableSuccess() + } + + @Test + fun testCompletableFail() { + viewModel.testCompletableFail() + } + @Test fun testSingleSuccess() { viewModel.testSingleSuccess()