diff --git a/CHANGELOG.md b/CHANGELOG.md index a13f476cd07..eaad40b8aea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Next Release +### Internal + +- Migrate alert facility change sheet to use Mobius loop + ### Fixes - Fix app crashing when trying to replacing the last screen during navigation diff --git a/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeEffect.kt b/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeEffect.kt index fb8ad211bea..e5ef00b943d 100644 --- a/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeEffect.kt +++ b/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeEffect.kt @@ -1,3 +1,11 @@ package org.simple.clinic.facility.alertchange -sealed class AlertFacilityChangeEffect +sealed interface AlertFacilityChangeEffect { + data object LoadIsFacilityChangedStatus : AlertFacilityChangeEffect + + data object MarkFacilityChangedAsFalse : AlertFacilityChangeEffect +} + +sealed interface AlertFacilityChangeViewEffect : AlertFacilityChangeEffect { + data object CloseSheetWithContinuation : AlertFacilityChangeViewEffect +} diff --git a/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeEffectHandler.kt b/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeEffectHandler.kt new file mode 100644 index 00000000000..7aa6e075ec7 --- /dev/null +++ b/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeEffectHandler.kt @@ -0,0 +1,54 @@ +package org.simple.clinic.facility.alertchange + +import com.f2prateek.rx.preferences2.Preference +import com.spotify.mobius.functions.Consumer +import com.spotify.mobius.rx2.RxMobius +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import io.reactivex.ObservableTransformer +import org.simple.clinic.facility.alertchange.AlertFacilityChangeEffect.LoadIsFacilityChangedStatus +import org.simple.clinic.facility.alertchange.AlertFacilityChangeEffect.MarkFacilityChangedAsFalse +import org.simple.clinic.facility.alertchange.AlertFacilityChangeEvent.FacilityChangedMarkedAsFalse +import org.simple.clinic.facility.alertchange.AlertFacilityChangeEvent.IsFacilityChangedStatusLoaded +import org.simple.clinic.util.scheduler.SchedulersProvider +import javax.inject.Named + +class AlertFacilityChangeEffectHandler @AssistedInject constructor( + @Named("is_facility_switched") + private val isFacilitySwitchedPreference: Preference, + private val schedulersProvider: SchedulersProvider, + @Assisted private val viewEffectsConsumer: Consumer +) { + + @AssistedFactory + interface Factory { + fun create(viewEffectsConsumer: Consumer) : AlertFacilityChangeEffectHandler + } + + fun build(): ObservableTransformer { + return RxMobius + .subtypeEffectHandler() + .addTransformer(LoadIsFacilityChangedStatus::class.java, loadFacilityChangedStatus()) + .addTransformer(MarkFacilityChangedAsFalse::class.java, markFacilityChangedAsFalse()) + .addConsumer(AlertFacilityChangeViewEffect::class.java, viewEffectsConsumer::accept) + .build() + } + + private fun markFacilityChangedAsFalse(): ObservableTransformer { + return ObservableTransformer { effects -> + effects + .observeOn(schedulersProvider.io()) + .map { isFacilitySwitchedPreference.set(false) } + .map { FacilityChangedMarkedAsFalse } + } + } + + private fun loadFacilityChangedStatus(): ObservableTransformer { + return ObservableTransformer { effects -> + effects + .observeOn(schedulersProvider.io()) + .map { IsFacilityChangedStatusLoaded(isFacilitySwitchedPreference.get()) } + } + } +} diff --git a/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeEvent.kt b/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeEvent.kt index e2fd2bacf8b..ffedb335b53 100644 --- a/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeEvent.kt +++ b/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeEvent.kt @@ -1,3 +1,16 @@ package org.simple.clinic.facility.alertchange -sealed class AlertFacilityChangeEvent +import org.simple.clinic.widgets.UiEvent + +sealed interface AlertFacilityChangeEvent : UiEvent { + + data class IsFacilityChangedStatusLoaded(val isFacilityChanged: Boolean) : AlertFacilityChangeEvent + + data object FacilityChangedMarkedAsFalse : AlertFacilityChangeEvent + + data object YesButtonClicked : AlertFacilityChangeEvent { + override val analyticsName: String = "Alert Facility Changed Sheet:Yes Button Clicked" + } + + data object FacilityChanged : AlertFacilityChangeEvent +} diff --git a/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeInit.kt b/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeInit.kt new file mode 100644 index 00000000000..a420440cc88 --- /dev/null +++ b/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeInit.kt @@ -0,0 +1,13 @@ +package org.simple.clinic.facility.alertchange + +import com.spotify.mobius.First +import com.spotify.mobius.Init +import org.simple.clinic.facility.alertchange.AlertFacilityChangeEffect.LoadIsFacilityChangedStatus +import org.simple.clinic.mobius.first + +class AlertFacilityChangeInit : Init { + + override fun init(model: AlertFacilityChangeModel): First { + return first(model, LoadIsFacilityChangedStatus) + } +} diff --git a/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeModel.kt b/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeModel.kt index 7167b4d26bd..0a47da337aa 100644 --- a/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeModel.kt +++ b/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeModel.kt @@ -4,4 +4,18 @@ import android.os.Parcelable import kotlinx.parcelize.Parcelize @Parcelize -class AlertFacilityChangeModel : Parcelable +data class AlertFacilityChangeModel( + val isFacilityChanged: Boolean +) : Parcelable { + + companion object { + + fun default() = AlertFacilityChangeModel( + isFacilityChanged = false + ) + } + + fun updateIsFacilityChanged(isFacilityChanged: Boolean) = copy( + isFacilityChanged = isFacilityChanged + ) +} diff --git a/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeSheet.kt b/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeSheet.kt index b2cda557a30..bbfd2115f05 100644 --- a/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeSheet.kt +++ b/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeSheet.kt @@ -8,15 +8,21 @@ import android.os.Parcelable import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import com.f2prateek.rx.preferences2.Preference +import com.jakewharton.rxbinding3.view.clicks +import com.spotify.mobius.functions.Consumer +import io.reactivex.Observable +import io.reactivex.rxkotlin.cast +import io.reactivex.subjects.PublishSubject import kotlinx.parcelize.Parcelize import org.simple.clinic.R +import org.simple.clinic.ReportAnalyticsEvents import org.simple.clinic.databinding.SheetAlertFacilityChangeBinding import org.simple.clinic.di.injector +import org.simple.clinic.facility.alertchange.AlertFacilityChangeEvent.FacilityChanged +import org.simple.clinic.facility.alertchange.AlertFacilityChangeEvent.YesButtonClicked import org.simple.clinic.facility.alertchange.Continuation.ContinueToActivity import org.simple.clinic.facility.change.FacilityChangeScreen import org.simple.clinic.feature.Features -import org.simple.clinic.mobius.ViewRenderer import org.simple.clinic.navigation.v2.Router import org.simple.clinic.navigation.v2.ScreenKey import org.simple.clinic.navigation.v2.ScreenResultBus @@ -26,24 +32,18 @@ import org.simple.clinic.util.resolveFloat import org.simple.clinic.util.setFragmentResultListener import java.util.Locale import javax.inject.Inject -import javax.inject.Named -class AlertFacilityChangeSheet : - BaseBottomSheet< - AlertFacilityChangeSheet.Key, - SheetAlertFacilityChangeBinding, - AlertFacilityChangeModel, - AlertFacilityChangeEvent, - AlertFacilityChangeEffect, - Unit>() { +class AlertFacilityChangeSheet : BaseBottomSheet< + AlertFacilityChangeSheet.Key, + SheetAlertFacilityChangeBinding, + AlertFacilityChangeModel, + AlertFacilityChangeEvent, + AlertFacilityChangeEffect, + AlertFacilityChangeViewEffect>(), AlertFacilityChangeUi, UiActions { @Inject lateinit var locale: Locale - @Inject - @Named("is_facility_switched") - lateinit var isFacilitySwitchedPreference: Preference - @Inject lateinit var features: Features @@ -53,25 +53,12 @@ class AlertFacilityChangeSheet : @Inject lateinit var router: Router - override fun defaultModel() = AlertFacilityChangeModel() - - override fun uiRenderer(): ViewRenderer { - return object : ViewRenderer { - override fun render(model: AlertFacilityChangeModel) { - // Nothing to render here - } - } - } - - override fun bindView(inflater: LayoutInflater, container: ViewGroup?) = - SheetAlertFacilityChangeBinding.inflate(inflater, container, false) + @Inject + lateinit var effectHandlerFactory: AlertFacilityChangeEffectHandler.Factory private val currentFacilityName get() = screenKey.currentFacilityName - private val continuation - get() = screenKey.continuation - private val rootView get() = binding.root @@ -84,6 +71,32 @@ class AlertFacilityChangeSheet : private val changeButton get() = binding.changeButton + private val hotEvents = PublishSubject.create() + + override fun defaultModel() = AlertFacilityChangeModel.default() + + override fun events(): Observable = Observable.mergeArray( + yesButtonClicks(), + hotEvents + ) + .compose(ReportAnalyticsEvents()) + .cast() + + override fun createInit() = AlertFacilityChangeInit() + + override fun createUpdate() = AlertFacilityChangeUpdate() + + override fun uiRenderer() = AlertFacilityChangeUiRenderer(this) + + override fun createEffectHandler(viewEffectsConsumer: Consumer) = effectHandlerFactory + .create(viewEffectsConsumer) + .build() + + override fun viewEffectsHandler() = AlertFacilityChangeViewEffectHandler(this) + + override fun bindView(inflater: LayoutInflater, container: ViewGroup?) = + SheetAlertFacilityChangeBinding.inflate(inflater, container, false) + override fun onAttach(context: Context) { super.onAttach(context) context.injector().inject(this) @@ -92,7 +105,7 @@ class AlertFacilityChangeSheet : override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setFragmentResultListener(ChangeCurrentFacility) { _, result -> - if (result is Succeeded) proceedToNextScreen() + if (result is Succeeded) hotEvents.onNext(FacilityChanged) } } @@ -104,61 +117,50 @@ class AlertFacilityChangeSheet : override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + facilityName.text = getString(R.string.alertfacilitychange_facility_name, currentFacilityName) - if (isFacilitySwitchedPreference.get().not()) { - rootView.postDelayed(::closeSheetWithContinuation, 100) - } else { - showDialogUi() - - facilityName.text = getString(R.string.alertfacilitychange_facility_name, currentFacilityName) - yesButton.setOnClickListener { - proceedToNextScreen() - } - - changeButton.setOnClickListener { - openFacilityChangeScreen() - } + changeButton.setOnClickListener { + openFacilityChangeScreen() } } - override fun onDestroyView() { - rootView.removeCallbacks(::closeSheetWithContinuation) - super.onDestroyView() - } - - private fun showDialogUi() { + override fun showFacilityChangeAlert() { val backgroundDimAmount = requireContext().resolveFloat(android.R.attr.backgroundDimAmount) requireDialog().window!!.setDimAmount(backgroundDimAmount) - binding.root.visibility = View.VISIBLE + rootView.visibility = View.VISIBLE } - private fun proceedToNextScreen() { - isFacilitySwitchedPreference.set(false) - closeSheetWithContinuation() + override fun hideFacilityChangeAlert() { + rootView.visibility = View.GONE } - private fun closeSheetWithContinuation() { - when (continuation) { + override fun closeSheetWithContinuation() { + when (val continuation = screenKey.continuation) { is ContinueToActivity -> { - val (intent, requestCode) = (continuation as ContinueToActivity).run { + val (intent, requestCode) = continuation.run { intent to requestCode } requireActivity().startActivityForResult(intent, requestCode) router.pop() } + is Continuation.ContinueToScreen -> { - val screenKey = (continuation as Continuation.ContinueToScreen).screenKey - router.replaceTop(screenKey) + router.replaceTop(continuation.screenKey) } + is Continuation.ContinueToScreenExpectingResult -> { - val screenKey = (continuation as Continuation.ContinueToScreenExpectingResult).screenKey - val requestType = (continuation as Continuation.ContinueToScreenExpectingResult).requestType + val screenKey = continuation.screenKey + val requestType = continuation.requestType router.replaceTopExpectingResult(requestType, screenKey) } } } + private fun yesButtonClicks() = yesButton + .clicks() + .map { YesButtonClicked } + private fun openFacilityChangeScreen() { router.pushExpectingResult(ChangeCurrentFacility, FacilityChangeScreen.Key()) } diff --git a/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeUi.kt b/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeUi.kt new file mode 100644 index 00000000000..1c9bcd75728 --- /dev/null +++ b/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeUi.kt @@ -0,0 +1,6 @@ +package org.simple.clinic.facility.alertchange + +interface AlertFacilityChangeUi { + fun showFacilityChangeAlert() + fun hideFacilityChangeAlert() +} diff --git a/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeUiRenderer.kt b/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeUiRenderer.kt new file mode 100644 index 00000000000..3d70608167a --- /dev/null +++ b/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeUiRenderer.kt @@ -0,0 +1,16 @@ +package org.simple.clinic.facility.alertchange + +import org.simple.clinic.mobius.ViewRenderer + +class AlertFacilityChangeUiRenderer( + private val ui: AlertFacilityChangeUi +) : ViewRenderer { + + override fun render(model: AlertFacilityChangeModel) { + if (model.isFacilityChanged) { + ui.showFacilityChangeAlert() + } else { + ui.hideFacilityChangeAlert() + } + } +} diff --git a/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeUpdate.kt b/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeUpdate.kt new file mode 100644 index 00000000000..2eb3b066a03 --- /dev/null +++ b/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeUpdate.kt @@ -0,0 +1,40 @@ +package org.simple.clinic.facility.alertchange + +import com.spotify.mobius.Next +import com.spotify.mobius.Next.next +import com.spotify.mobius.Update +import org.simple.clinic.facility.alertchange.AlertFacilityChangeEffect.MarkFacilityChangedAsFalse +import org.simple.clinic.facility.alertchange.AlertFacilityChangeEvent.FacilityChanged +import org.simple.clinic.facility.alertchange.AlertFacilityChangeEvent.FacilityChangedMarkedAsFalse +import org.simple.clinic.facility.alertchange.AlertFacilityChangeEvent.IsFacilityChangedStatusLoaded +import org.simple.clinic.facility.alertchange.AlertFacilityChangeEvent.YesButtonClicked +import org.simple.clinic.facility.alertchange.AlertFacilityChangeViewEffect.CloseSheetWithContinuation +import org.simple.clinic.mobius.dispatch + +class AlertFacilityChangeUpdate : Update { + + override fun update(model: AlertFacilityChangeModel, event: AlertFacilityChangeEvent): Next { + return when (event) { + is IsFacilityChangedStatusLoaded -> isFacilityChangeStatusLoaded(event, model) + FacilityChangedMarkedAsFalse -> dispatch(CloseSheetWithContinuation) + YesButtonClicked -> dispatch(MarkFacilityChangedAsFalse) + FacilityChanged -> dispatch(MarkFacilityChangedAsFalse) + } + } + + private fun isFacilityChangeStatusLoaded( + event: IsFacilityChangedStatusLoaded, + model: AlertFacilityChangeModel + ): Next { + val effects: Set = if (event.isFacilityChanged) { + emptySet() + } else { + setOf(CloseSheetWithContinuation) + } + + return next( + model.updateIsFacilityChanged(isFacilityChanged = event.isFacilityChanged), + effects + ) + } +} diff --git a/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeViewEffectHandler.kt b/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeViewEffectHandler.kt new file mode 100644 index 00000000000..3e5d9097da7 --- /dev/null +++ b/app/src/main/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeViewEffectHandler.kt @@ -0,0 +1,15 @@ +package org.simple.clinic.facility.alertchange + +import org.simple.clinic.facility.alertchange.AlertFacilityChangeViewEffect.CloseSheetWithContinuation +import org.simple.clinic.mobius.ViewEffectsHandler + +class AlertFacilityChangeViewEffectHandler( + private val uiAction: UiActions +) : ViewEffectsHandler { + + override fun handle(viewEffect: AlertFacilityChangeViewEffect) { + when (viewEffect) { + CloseSheetWithContinuation -> uiAction.closeSheetWithContinuation() + } + } +} diff --git a/app/src/main/java/org/simple/clinic/facility/alertchange/UiActions.kt b/app/src/main/java/org/simple/clinic/facility/alertchange/UiActions.kt new file mode 100644 index 00000000000..81eb041d0af --- /dev/null +++ b/app/src/main/java/org/simple/clinic/facility/alertchange/UiActions.kt @@ -0,0 +1,5 @@ +package org.simple.clinic.facility.alertchange + +interface UiActions { + fun closeSheetWithContinuation() +} diff --git a/app/src/test/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeEffectHandlerTest.kt b/app/src/test/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeEffectHandlerTest.kt new file mode 100644 index 00000000000..5486ed8779a --- /dev/null +++ b/app/src/test/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeEffectHandlerTest.kt @@ -0,0 +1,52 @@ +package org.simple.clinic.facility.alertchange + +import com.f2prateek.rx.preferences2.Preference +import org.junit.Test +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock +import org.mockito.kotlin.verify +import org.mockito.kotlin.verifyNoMoreInteractions +import org.mockito.kotlin.whenever +import org.simple.clinic.facility.alertchange.AlertFacilityChangeEffect.LoadIsFacilityChangedStatus +import org.simple.clinic.facility.alertchange.AlertFacilityChangeEvent.IsFacilityChangedStatusLoaded +import org.simple.clinic.facility.alertchange.AlertFacilityChangeViewEffect.CloseSheetWithContinuation +import org.simple.clinic.mobius.EffectHandlerTestCase +import org.simple.clinic.util.scheduler.TestSchedulersProvider + +class AlertFacilityChangeEffectHandlerTest { + + private val uiActions = mock() + private val isFacilitySwitchedPreference = mock>() + private val effectHandlerTestCase = EffectHandlerTestCase( + AlertFacilityChangeEffectHandler( + isFacilitySwitchedPreference = isFacilitySwitchedPreference, + schedulersProvider = TestSchedulersProvider.trampoline(), + viewEffectsConsumer = AlertFacilityChangeViewEffectHandler(uiActions)::handle, + ).build() + ) + + @Test + fun `when load facility changed effect is received, then load if facility is changed`() { + // given + whenever(isFacilitySwitchedPreference.get()) doReturn true + + // when + effectHandlerTestCase.dispatch(LoadIsFacilityChangedStatus) + + // then + verify(isFacilitySwitchedPreference).get() + verifyNoMoreInteractions(isFacilitySwitchedPreference) + + effectHandlerTestCase.assertOutgoingEvents(IsFacilityChangedStatusLoaded(isFacilityChanged = true)) + } + + @Test + fun `when close sheet with continuation view effect is received, then close sheet with continuation`() { + // when + effectHandlerTestCase.dispatch(CloseSheetWithContinuation) + + // then + verify(uiActions).closeSheetWithContinuation() + verifyNoMoreInteractions(uiActions) + } +} diff --git a/app/src/test/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeInitTest.kt b/app/src/test/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeInitTest.kt new file mode 100644 index 00000000000..b6aff20def1 --- /dev/null +++ b/app/src/test/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeInitTest.kt @@ -0,0 +1,23 @@ +package org.simple.clinic.facility.alertchange + +import com.spotify.mobius.test.InitSpec +import com.spotify.mobius.test.InitSpec.assertThatFirst +import com.spotify.mobius.test.FirstMatchers.hasEffects +import com.spotify.mobius.test.FirstMatchers.hasModel +import org.junit.Test +import org.simple.clinic.facility.alertchange.AlertFacilityChangeEffect.LoadIsFacilityChangedStatus + +class AlertFacilityChangeInitTest { + + @Test + fun `when screen is created, then load if facility is changed`() { + val model = AlertFacilityChangeModel.default() + + InitSpec(AlertFacilityChangeInit()) + .whenInit(model) + .then(assertThatFirst( + hasModel(model), + hasEffects(LoadIsFacilityChangedStatus) + )) + } +} diff --git a/app/src/test/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeUiRendererTest.kt b/app/src/test/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeUiRendererTest.kt new file mode 100644 index 00000000000..9691999eab8 --- /dev/null +++ b/app/src/test/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeUiRendererTest.kt @@ -0,0 +1,39 @@ +package org.simple.clinic.facility.alertchange + +import org.junit.Test +import org.mockito.kotlin.mock +import org.mockito.kotlin.verify + +class AlertFacilityChangeUiRendererTest { + + private val ui = mock() + private val uiRenderer = AlertFacilityChangeUiRenderer(ui = ui) + + @Test + fun `when facility is changed, then show facility change alert`() { + // given + val model = AlertFacilityChangeModel + .default() + .updateIsFacilityChanged(isFacilityChanged = true) + + // when + uiRenderer.render(model) + + // then + verify(ui).showFacilityChangeAlert() + } + + @Test + fun `when facility is not changed, then hide facility change alert`() { + // given + val model = AlertFacilityChangeModel + .default() + .updateIsFacilityChanged(isFacilityChanged = false) + + // when + uiRenderer.render(model) + + // then + verify(ui).hideFacilityChangeAlert() + } +} diff --git a/app/src/test/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeUpdateTest.kt b/app/src/test/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeUpdateTest.kt new file mode 100644 index 00000000000..9a84949a045 --- /dev/null +++ b/app/src/test/java/org/simple/clinic/facility/alertchange/AlertFacilityChangeUpdateTest.kt @@ -0,0 +1,84 @@ +package org.simple.clinic.facility.alertchange + +import com.spotify.mobius.test.NextMatchers.hasEffects +import com.spotify.mobius.test.NextMatchers.hasModel +import com.spotify.mobius.test.NextMatchers.hasNoEffects +import com.spotify.mobius.test.NextMatchers.hasNoModel +import com.spotify.mobius.test.UpdateSpec +import com.spotify.mobius.test.UpdateSpec.assertThatNext +import org.junit.Test +import org.simple.clinic.facility.alertchange.AlertFacilityChangeEffect.MarkFacilityChangedAsFalse +import org.simple.clinic.facility.alertchange.AlertFacilityChangeEvent.FacilityChanged +import org.simple.clinic.facility.alertchange.AlertFacilityChangeEvent.FacilityChangedMarkedAsFalse +import org.simple.clinic.facility.alertchange.AlertFacilityChangeEvent.IsFacilityChangedStatusLoaded +import org.simple.clinic.facility.alertchange.AlertFacilityChangeEvent.YesButtonClicked +import org.simple.clinic.facility.alertchange.AlertFacilityChangeViewEffect.CloseSheetWithContinuation + +class AlertFacilityChangeUpdateTest { + + private val defaultModel = AlertFacilityChangeModel.default() + private val updateSpec = UpdateSpec(AlertFacilityChangeUpdate()) + + @Test + fun `when facility changed status is loaded and facility is changed, then update model`() { + updateSpec + .given(defaultModel) + .whenEvent(IsFacilityChangedStatusLoaded(isFacilityChanged = true)) + .then(assertThatNext( + hasModel(defaultModel.copy(isFacilityChanged = true)), + hasNoEffects() + )) + } + + @Test + fun `when facility changed status is loaded and facility is not changed, then update model and close sheet`() { + val model = AlertFacilityChangeModel.default() + + updateSpec + .given(defaultModel) + .whenEvent(IsFacilityChangedStatusLoaded(isFacilityChanged = false)) + .then(assertThatNext( + hasModel(defaultModel.copy(isFacilityChanged = false)), + hasEffects(CloseSheetWithContinuation) + )) + } + + @Test + fun `when yes button is clicked, then mark facility changed as false`() { + val model = defaultModel.updateIsFacilityChanged(isFacilityChanged = true) + + updateSpec + .given(model) + .whenEvent(YesButtonClicked) + .then(assertThatNext( + hasNoModel(), + hasEffects(MarkFacilityChangedAsFalse) + )) + } + + @Test + fun `when facility changed status is marked as false, then close sheet`() { + val model = defaultModel.updateIsFacilityChanged(isFacilityChanged = true) + + updateSpec + .given(model) + .whenEvent(FacilityChangedMarkedAsFalse) + .then(assertThatNext( + hasNoModel(), + hasEffects(CloseSheetWithContinuation) + )) + } + + @Test + fun `when facility is changed, then mark facility changed as false`() { + val model = defaultModel.updateIsFacilityChanged(isFacilityChanged = true) + + updateSpec + .given(model) + .whenEvent(FacilityChanged) + .then(assertThatNext( + hasNoModel(), + hasEffects(MarkFacilityChangedAsFalse) + )) + } +}