Untitled

mail@pastecode.io avatar
unknown
plain_text
2 years ago
17 kB
1
Indexable
Never
package com.lgi.connect.android.homescan.presentation.flows.modem.speedtest.presenter

import androidx.lifecycle.Lifecycle
import com.android.lgi.connectivity.modules.analytics.AnalyticsEnums
import com.lgi.connect.android.core.presentation.mvp.presenter.TestLifecycleOwner
import com.lgi.connect.android.domain.common.threading.SchedulersSet
import com.lgi.connect.android.domain.service.analytics.AnalyticsTracker
import com.lgi.connect.android.flow.domain.common.Flow
import com.lgi.connect.android.flow.domain.common.Screen
import com.lgi.connect.android.homeinternet.cloud.domain.CloudConstants
import com.lgi.connect.android.homeinternet.cloud.presentation.common.errorsmapper.CloudErrorsMapper
import com.lgi.connect.android.homeinternet.cloud.presentation.common.errorsmapper.FlowScreen
import com.lgi.connect.android.homeinternet.msa.domain.common.MsaConstants
import com.lgi.connect.android.homeinternet.msa.domain.common.MsaConstants.ModemSpeedTestEntryPoint.Companion.AFTER_DEVICE_TEST
import com.lgi.connect.android.homeinternet.msa.domain.common.MsaConstants.ModemSpeedTestEntryPoint.Companion.MODEM_DETAILS
import com.lgi.connect.android.homeinternet.msa.domain.common.MsaConstants.ModemSpeedTestRetryActions
import com.lgi.connect.android.homescan.presentation.common.errornavigation.FailureNavigationProvider
import com.lgi.connect.android.homescan.presentation.flows.HomeScanSaveResultsDialogViewData
import com.lgi.connect.android.homescan.presentation.flows.device.common.data.SpeedTestResultViewData
import com.lgi.connect.android.homescan.presentation.flows.modem.speedtest.view.ModemSpeedTestView
import com.lgi.connect.android.msa.domain.common.error.MsaErrorHandlingType
import com.lgi.connect.android.testing.livedata.LiveDataTestingSpek
import com.lgi.connect.homescan.domain.exposed.SpeedTestFetchResult
import com.lgi.connect.homescan.domain.exposed.entity.SpeedTestResultEntity
import com.lgi.connect.homescan.domain.flows.common.HomeScanConstants
import com.lgi.connect.homescan.domain.flows.common.saveresults.HomeScanSaveResultsModel
import com.lgi.connect.homescan.domain.flows.device.speedtest.ModemSpeedTestModel
import com.lgi.connect.homescan.domain.flows.device.speedtest.ModemSpeedTestResultState
import com.lgi.connect.multiplatform.mapper.Mapper
import com.nhaarman.mockitokotlin2.any
import com.nhaarman.mockitokotlin2.eq
import com.nhaarman.mockitokotlin2.given
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.times
import com.nhaarman.mockitokotlin2.verify
import io.reactivex.rxjava3.core.Single
import org.jetbrains.spek.api.Spek
import org.jetbrains.spek.api.dsl.context
import org.jetbrains.spek.api.dsl.describe
import org.jetbrains.spek.api.dsl.it
import org.jetbrains.spek.api.include
import org.junit.jupiter.api.Assertions.assertEquals

class ModemSpeedTestPresenterTest : Spek({

    include(LiveDataTestingSpek)

    val lifecycleOwner by memoized { TestLifecycleOwner() }
    val analyticsTracker by memoized { mock<AnalyticsTracker>() }
    val schedulersSet by memoized { SchedulersSet.test() }
    val errorMapper by memoized { mock<CloudErrorsMapper>() }
    val resultMapper by memoized { mock<Mapper<SpeedTestResultEntity, SpeedTestResultViewData>>() }
    val model by memoized { mock<ModemSpeedTestModel>() }
    val failureNavigationProvider by memoized { mock<FailureNavigationProvider>() }
    val homeScanSaveResultsModel by memoized { mock<HomeScanSaveResultsModel<SpeedTestFetchResult<Unit>>>() }
    val view by memoized { mock<ModemSpeedTestView>() }

    val presenter by memoized {
        ModemSpeedTestPresenter(
            analyticsTracker,
            schedulersSet,
            errorMapper,
            resultMapper,
            model,
            failureNavigationProvider,
            homeScanSaveResultsModel
        )
    }

    val speedTestResultEntity = mock<SpeedTestResultEntity>()
    val speedTestResultViewData = mock<SpeedTestResultViewData>()
    val throwable = Throwable("")
    val defaultErrorType = MsaErrorHandlingType.Default(throwable)

    beforeEachTest {
        presenter.startObserving(lifecycleOwner, view)
    }

    describe("getting screen track name") {
        it("must get screen track name") {
            assertEquals(
                AnalyticsEnums.Screens.HOME_SCAN_MODEM_TEST_LOADING,
                presenter.getScreenTrackName()
            )
        }
    }

    describe("first view attach") {
        context("when state is Success") {
            beforeEachTest {
                given(model.postModemTest())
                    .willReturn(
                        Single.just(
                            SpeedTestFetchResult.Success(Unit)
                        )
                    )
                given(resultMapper.map(speedTestResultEntity))
                    .willReturn(speedTestResultViewData)
            }

            context("and test result is Success") {
                beforeEachTest {
                    given(model.fetchTestResult())
                        .willReturn(
                            Single.just(
                                ModemSpeedTestResultState.Success(
                                    speedTestResultEntity
                                )
                            )
                        )

                    lifecycleOwner.setState(Lifecycle.State.STARTED)
                }

                it("must go to speed test result") {
                    verify(view).goToSpeedTestResult(speedTestResultViewData)
                }
            }

            context("and test result is Failure") {
                beforeEachTest {
                    given(model.fetchTestResult())
                        .willReturn(
                            Single.just(
                                ModemSpeedTestResultState.Failure(
                                    throwable
                                )
                            )
                        )

                    lifecycleOwner.setState(Lifecycle.State.STARTED)
                }

                it("must map MSA error") {
                    verify(errorMapper).mapMsa(
                        errorType = defaultErrorType,
                        action = ModemSpeedTestRetryActions.FETCH_TEST_RESULT,
                        entryPoint = CloudConstants.MsaFailureEntryPoint.DEFAULT,
                        backNavigation = null,
                        isFirstTimeLoading = false
                    )
                }
            }

            context("and test result is NoResult") {
                beforeEachTest {
                    given(model.fetchTestResult())
                        .willReturn(
                            Single.just(
                                ModemSpeedTestResultState.NoResult
                            )
                        )

                    lifecycleOwner.setState(Lifecycle.State.STARTED)
                }

                it("must map MSA error") {
                    verify(errorMapper).mapMsa(
                        errorType = any(),
                        action = eq(ModemSpeedTestRetryActions.POST_TEST_RESULT),
                        entryPoint = eq(CloudConstants.MsaFailureEntryPoint.DEFAULT),
                        backNavigation = eq(null),
                        isFirstTimeLoading = eq(false)
                    )
                }
            }

            context("and test result is error") {
                beforeEachTest {
                    given(model.fetchTestResult())
                        .willReturn(
                            Single.error(
                                throwable
                            )
                        )

                    lifecycleOwner.setState(Lifecycle.State.STARTED)
                }

                it("must map MSA error") {
                    verify(errorMapper).mapMsa(
                        errorType = defaultErrorType,
                        action = ModemSpeedTestRetryActions.FETCH_TEST_RESULT,
                        entryPoint = CloudConstants.MsaFailureEntryPoint.DEFAULT,
                        backNavigation = null,
                        isFirstTimeLoading = false
                    )
                }
            }
        }

        context("when state is Failure") {
            beforeEachTest {
                given(model.postModemTest())
                    .willReturn(
                        Single.just(
                            SpeedTestFetchResult.Failure(throwable)
                        )
                    )

                lifecycleOwner.setState(Lifecycle.State.STARTED)
            }

            it("must map MSA error") {
                verify(errorMapper).mapMsa(
                    errorType = defaultErrorType,
                    action = ModemSpeedTestRetryActions.POST_TEST_RESULT,
                    entryPoint = CloudConstants.MsaFailureEntryPoint.DEFAULT,
                    backNavigation = null,
                    isFirstTimeLoading = false
                )
            }
        }

        context("when state is error") {
            beforeEachTest {
                given(model.postModemTest())
                    .willReturn(
                        Single.error(
                            throwable
                        )
                    )

                lifecycleOwner.setState(Lifecycle.State.STARTED)
            }

            it("must map MSA error") {
                verify(errorMapper).mapMsa(
                    errorType = defaultErrorType,
                    action = ModemSpeedTestRetryActions.POST_TEST_RESULT,
                    entryPoint = CloudConstants.MsaFailureEntryPoint.DEFAULT,
                    backNavigation = null,
                    isFirstTimeLoading = false
                )
            }
        }
    }

    describe("retrying action") {
        context("when action is POST_TEST_RESULT") {
            beforeEachTest {
                given(model.postModemTest())
                    .willReturn(
                        Single.error(
                            throwable
                        )
                    )

                presenter.retryAction(ModemSpeedTestRetryActions.POST_TEST_RESULT)
            }

            it("must post modem test") {
                verify(model).postModemTest()
            }
        }

        context("when action is FETCH_TEST_RESULT") {
            beforeEachTest {
                given(model.fetchTestResult())
                    .willReturn(
                        Single.error(
                            throwable
                        )
                    )

                presenter.retryAction(ModemSpeedTestRetryActions.FETCH_TEST_RESULT)
            }

            it("must fetch test result") {
                verify(model).fetchTestResult()
            }
        }

        context("when action non-existent") {
            beforeEachTest {
                presenter.retryAction(999)
            }

            it("mustn't post modem test") {
                verify(model, times(0)).postModemTest()
            }

            it("mustn't fetch test result") {
                verify(model, times(0)).fetchTestResult()
            }
        }
    }

    describe("on cancel retry action") {
        context("when failure entry point is DASHBOARD") {
            beforeEachTest {
                given(failureNavigationProvider.getFailureEntryPoint())
                    .willReturn(HomeScanConstants.HomeScanFailureEntryPoint.DASHBOARD)
                lifecycleOwner.setState(Lifecycle.State.STARTED)
                presenter.onCancelRetryAction()
            }

            it("should go to dashboard") {
                verify(view).goToDashboard()
            }
        }

        context("when failure entry point is OTHER") {
            val flowScreen = FlowScreen(
                Flow.HOME_SCAN_MODEM_TEST_FLOW,
                Screen.HOME_SCAN_MODEM_TROUBLESHOOT
            )
            beforeEachTest {
                given(failureNavigationProvider.getFailureEntryPoint())
                    .willReturn(HomeScanConstants.HomeScanFailureEntryPoint.OTHER)
                given(failureNavigationProvider.getBackNavigation())
                    .willReturn(flowScreen)
                lifecycleOwner.setState(Lifecycle.State.STARTED)
                presenter.onCancelRetryAction()
            }
            it("should go to received flow, screen") {
                verify(view).goToScreen(flowScreen.flow, flowScreen.screen)
            }
        }
    }

    describe("on soft back pressed") {
        beforeEachTest {
            given(model.postModemTest())
                .willReturn(
                    Single.error(
                        throwable
                    )
                )
            given(model.fetchTestResult())
                .willReturn(
                    Single.error(
                        throwable
                    )
                )
        }

        context("when entryPoint is MODEM_DETAILS and preSelectedRoom is false") {
            beforeEachTest {
                given(model.entryPoint)
                    .willReturn(MODEM_DETAILS)
                given(model.preSelectedRoom)
                    .willReturn(false)

                lifecycleOwner.setState(Lifecycle.State.STARTED)
                presenter.softBackPressed()
            }

            it("must go to modem details") {
                verify(view).goToModemDetails()
            }
        }

        context("when entryPoint is AFTER_DEVICE_TEST and preSelectedRoom is false") {
            beforeEachTest {
                given(model.entryPoint)
                    .willReturn(AFTER_DEVICE_TEST)
                given(model.preSelectedRoom)
                    .willReturn(false)

                lifecycleOwner.setState(Lifecycle.State.STARTED)
                presenter.softBackPressed()
            }

            it("must go to dashboard") {
                verify(view).goToDashboard()
            }
        }

        context("when entryPoint is AFTER_DEVICE_TEST and preSelectedRoom is true") {
            beforeEachTest {
                given(model.entryPoint)
                    .willReturn(AFTER_DEVICE_TEST)
                given(model.preSelectedRoom)
                    .willReturn(true)

                lifecycleOwner.setState(Lifecycle.State.STARTED)
                presenter.softBackPressed()
            }

            it("must show save results modal dialog") {
                verify(view).showSaveResultsModalDialog(HomeScanSaveResultsDialogViewData())
            }
        }
    }

    describe("handle saving scan results") {
        beforeEachTest {
            given(model.postModemTest())
                .willReturn(
                    Single.error(
                        throwable
                    )
                )
        }

        context("when savingResult is Success and entryPoint is MODEM_DETAILS") {
            beforeEachTest {
                given(homeScanSaveResultsModel.saveScanResults())
                    .willReturn(Single.just(SpeedTestFetchResult.Success(Unit)))
                given(model.entryPoint)
                    .willReturn(MODEM_DETAILS)

                lifecycleOwner.setState(Lifecycle.State.STARTED)
                presenter.onSaveDialogClicked()
            }

            it("must go to modem details") {
                verify(view).goToModemDetails()
            }
        }

        context("when savingResult is Failure") {
            beforeEachTest {
                given(homeScanSaveResultsModel.saveScanResults())
                    .willReturn(Single.just(SpeedTestFetchResult.Failure(throwable)))

                lifecycleOwner.setState(Lifecycle.State.STARTED)
                presenter.onSaveDialogClicked()
            }

            it("must map MSA error") {
                verify(errorMapper).mapMsa(
                    errorType = defaultErrorType,
                    action = MsaConstants.SaveSpeedTestResultDialogRetryActions.SAVE_RESULTS,
                    entryPoint = CloudConstants.MsaFailureEntryPoint.DEFAULT,
                    backNavigation = null
                )
            }
        }
    }

    describe("on saving home scan results declined") {
        beforeEachTest {
            given(model.postModemTest())
                .willReturn(
                    Single.error(
                        throwable
                    )
                )
            given(model.entryPoint)
                .willReturn(MODEM_DETAILS)

            lifecycleOwner.setState(Lifecycle.State.STARTED)
            presenter.onContinueWithoutSavingDialogClicked()
        }

        it("must go to modem details") {
            verify(view).goToModemDetails()
        }
    }
})