diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/tracing/TracingData.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/tracing/TracingData.kt new file mode 100644 index 0000000000000000000000000000000000000000..7679a4aad617ea733130cd7dc56980c2e6dd463e --- /dev/null +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/tracing/TracingData.kt @@ -0,0 +1,127 @@ +package de.rki.coronawarnapp.ui.tracing + +import de.rki.coronawarnapp.risk.RiskState +import de.rki.coronawarnapp.tracing.GeneralTracingStatus +import de.rki.coronawarnapp.tracing.states.IncreasedRisk +import de.rki.coronawarnapp.tracing.states.LowRisk +import de.rki.coronawarnapp.tracing.states.TracingDisabled +import de.rki.coronawarnapp.tracing.states.TracingFailed +import de.rki.coronawarnapp.tracing.ui.details.TracingDetailsState +import de.rki.coronawarnapp.tracing.ui.details.items.behavior.BehaviorIncreasedRiskBox +import de.rki.coronawarnapp.tracing.ui.details.items.behavior.BehaviorNormalRiskBox +import de.rki.coronawarnapp.tracing.ui.details.items.periodlogged.PeriodLoggedBox +import de.rki.coronawarnapp.tracing.ui.details.items.risk.IncreasedRiskBox +import de.rki.coronawarnapp.tracing.ui.details.items.risk.LowRiskBox +import de.rki.coronawarnapp.tracing.ui.details.items.risk.TracingDisabledBox +import de.rki.coronawarnapp.tracing.ui.details.items.risk.TracingFailedBox +import de.rki.coronawarnapp.tracing.ui.details.items.riskdetails.DetailsFailedCalculationBox +import de.rki.coronawarnapp.tracing.ui.details.items.riskdetails.DetailsIncreasedRiskBox +import de.rki.coronawarnapp.tracing.ui.details.items.riskdetails.DetailsLowRiskBox +import org.joda.time.Duration +import org.joda.time.Instant + +object TracingData { + + val TRACING_DISABLED = Pair( + TracingDetailsState( + tracingStatus = GeneralTracingStatus.Status.TRACING_INACTIVE, + riskState = RiskState.LOW_RISK, + isManualKeyRetrievalEnabled = false + ), + listOf( + TracingDisabledBox.Item( + state = TracingDisabled( + riskState = RiskState.LOW_RISK, + isInDetailsMode = true, + lastExposureDetectionTime = Instant.now() + ) + ), + BehaviorNormalRiskBox.Item( + tracingStatus = GeneralTracingStatus.Status.TRACING_INACTIVE, + riskState = RiskState.LOW_RISK + ), + + PeriodLoggedBox.Item(activeTracingDaysInRetentionPeriod = 0), + DetailsLowRiskBox.Item(riskState = RiskState.LOW_RISK, matchedKeyCount = 0) + ) + ) + + val LOW_RISK = Pair( + TracingDetailsState( + tracingStatus = GeneralTracingStatus.Status.TRACING_ACTIVE, + riskState = RiskState.LOW_RISK, + isManualKeyRetrievalEnabled = false + ), + listOf( + LowRiskBox.Item( + state = LowRisk( + riskState = RiskState.LOW_RISK, + isInDetailsMode = true, + lastExposureDetectionTime = Instant.now(), + allowManualUpdate = false, + daysWithEncounters = 0, + activeTracingDays = 0 + ) + ), + BehaviorNormalRiskBox.Item( + tracingStatus = GeneralTracingStatus.Status.TRACING_ACTIVE, + riskState = RiskState.LOW_RISK + ), + + PeriodLoggedBox.Item(activeTracingDaysInRetentionPeriod = 0), + DetailsLowRiskBox.Item(riskState = RiskState.LOW_RISK, matchedKeyCount = 0) + ) + ) + + val INCREASED_RISK = Pair( + TracingDetailsState( + tracingStatus = GeneralTracingStatus.Status.TRACING_ACTIVE, + riskState = RiskState.INCREASED_RISK, + isManualKeyRetrievalEnabled = false + ), + listOf( + IncreasedRiskBox.Item( + state = IncreasedRisk( + riskState = RiskState.INCREASED_RISK, + isInDetailsMode = true, + lastExposureDetectionTime = Instant.now(), + allowManualUpdate = false, + daysWithEncounters = 1, + activeTracingDays = 5, + lastEncounterAt = Instant.now() + ) + ), + BehaviorIncreasedRiskBox.Item, + PeriodLoggedBox.Item(activeTracingDaysInRetentionPeriod = 5), + DetailsIncreasedRiskBox.Item( + riskState = RiskState.INCREASED_RISK, + lastEncounterDaysAgo = Duration( + Instant.EPOCH, + Instant.now() + ).standardDays.toInt() + ) + ) + ) + + val TRACING_FAILED = Pair( + TracingDetailsState( + tracingStatus = GeneralTracingStatus.Status.TRACING_ACTIVE, + riskState = RiskState.CALCULATION_FAILED, + isManualKeyRetrievalEnabled = true + ), + listOf( + TracingFailedBox.Item( + state = TracingFailed( + riskState = RiskState.CALCULATION_FAILED, + isInDetailsMode = true, + lastExposureDetectionTime = null + ) + ), + BehaviorNormalRiskBox.Item( + tracingStatus = GeneralTracingStatus.Status.TRACING_ACTIVE, + riskState = RiskState.CALCULATION_FAILED + ), + DetailsFailedCalculationBox.Item + ) + ) +} diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/tracing/TracingDetailsFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/tracing/TracingDetailsFragmentTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..0a108488676739c69d7527a0f6676dd6cf002d93 --- /dev/null +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/tracing/TracingDetailsFragmentTest.kt @@ -0,0 +1,132 @@ +package de.rki.coronawarnapp.ui.tracing + +import androidx.fragment.app.testing.launchFragment +import androidx.lifecycle.MutableLiveData +import androidx.test.ext.junit.runners.AndroidJUnit4 +import dagger.Module +import dagger.android.ContributesAndroidInjector +import de.rki.coronawarnapp.risk.storage.RiskLevelStorage +import de.rki.coronawarnapp.storage.TracingRepository +import de.rki.coronawarnapp.tracing.GeneralTracingStatus +import de.rki.coronawarnapp.tracing.states.TracingStateProvider +import de.rki.coronawarnapp.tracing.ui.details.TracingDetailsFragment +import de.rki.coronawarnapp.tracing.ui.details.TracingDetailsFragmentViewModel +import de.rki.coronawarnapp.tracing.ui.details.TracingDetailsItemProvider +import de.rki.coronawarnapp.tracing.ui.details.TracingDetailsState +import de.rki.coronawarnapp.tracing.ui.details.items.DetailsItem +import de.rki.coronawarnapp.util.device.BackgroundModeStatus +import io.mockk.MockKAnnotations +import io.mockk.every +import io.mockk.impl.annotations.MockK +import io.mockk.spyk +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import testhelpers.BaseUITest +import testhelpers.Screenshot +import testhelpers.SystemUIDemoModeRule +import testhelpers.TestDispatcherProvider +import testhelpers.launchFragmentInContainer2 +import tools.fastlane.screengrab.Screengrab +import tools.fastlane.screengrab.locale.LocaleTestRule + +@RunWith(AndroidJUnit4::class) +class TracingDetailsFragmentTest : BaseUITest() { + + @MockK lateinit var tracingStatus: GeneralTracingStatus + @MockK lateinit var backgroundModeStatus: BackgroundModeStatus + @MockK lateinit var riskLevelStorage: RiskLevelStorage + @MockK lateinit var tracingDetailsItemProvider: TracingDetailsItemProvider + @MockK lateinit var tracingStateProviderFactory: TracingStateProvider.Factory + @MockK lateinit var tracingRepository: TracingRepository + + private lateinit var viewModel: TracingDetailsFragmentViewModel + + @Rule + @JvmField + val localeTestRule = LocaleTestRule() + + @get:Rule + val systemUIDemoModeRule = SystemUIDemoModeRule() + + @Before + fun setup() { + MockKAnnotations.init(this, relaxed = true) + + viewModel = spyk( + TracingDetailsFragmentViewModel( + dispatcherProvider = TestDispatcherProvider, + tracingStatus = tracingStatus, + backgroundModeStatus = backgroundModeStatus, + riskLevelStorage = riskLevelStorage, + tracingDetailsItemProvider = tracingDetailsItemProvider, + tracingStateProviderFactory = tracingStateProviderFactory, + tracingRepository = tracingRepository + ) + ) + + setupMockViewModel( + object : TracingDetailsFragmentViewModel.Factory { + override fun create(): TracingDetailsFragmentViewModel = viewModel + } + ) + } + + @After + fun teardown() { + clearAllViewModels() + } + + @Test + fun launch_tracing_details() { + launchFragment<TracingDetailsFragment>() + } + + @Screenshot + @Test + fun capture_screenshot_tracing_low_risk() { + mockData(TracingData.LOW_RISK) + captureScreenshot("tracing_low_risk") + } + + @Screenshot + @Test + fun capture_screenshot_tracing_disabled() { + mockData(TracingData.TRACING_DISABLED) + captureScreenshot("tracing_disabled") + } + + @Screenshot + @Test + fun capture_screenshot_tracing_failed() { + mockData(TracingData.TRACING_FAILED) + captureScreenshot("tracing_failed") + } + + @Screenshot + @Test + fun capture_screenshot_tracing_increased() { + mockData(TracingData.INCREASED_RISK) + captureScreenshot("tracing_increased") + } + + private fun mockData(pair: Pair<TracingDetailsState, List<DetailsItem>>) { + every { viewModel.buttonStates } returns MutableLiveData(pair.first) + every { viewModel.detailsItems } returns MutableLiveData(pair.second) + } + + private fun captureScreenshot(nameSuffix: String) { + val name = TracingDetailsFragment::class.simpleName + "_" + nameSuffix + launchFragmentInContainer2<TracingDetailsFragment>() + Thread.sleep(2000) // TODO use constant when EXPOSUREAPP-2950 is merged + Screengrab.screenshot(name) + } +} + +@Module +abstract class TracingDetailsFragmentTestTestModule { + @ContributesAndroidInjector + abstract fun tracingDetailsFragment(): TracingDetailsFragment +} diff --git a/Corona-Warn-App/src/androidTest/java/testhelpers/FragmentTestModuleRegistrar.kt b/Corona-Warn-App/src/androidTest/java/testhelpers/FragmentTestModuleRegistrar.kt index d8f85865286eebd115ee281a9275e9b678b297d1..436786aa9d80bb70e3c18252fa482ad43eef88c7 100644 --- a/Corona-Warn-App/src/androidTest/java/testhelpers/FragmentTestModuleRegistrar.kt +++ b/Corona-Warn-App/src/androidTest/java/testhelpers/FragmentTestModuleRegistrar.kt @@ -15,6 +15,7 @@ import de.rki.coronawarnapp.ui.submission.SubmissionSymptomIntroFragmentTestModu import de.rki.coronawarnapp.ui.submission.SubmissionTanTestModule import de.rki.coronawarnapp.ui.submission.SubmissionTestResultConsentGivenTestModule import de.rki.coronawarnapp.ui.submission.SubmissionTestResultTestModule +import de.rki.coronawarnapp.ui.tracing.TracingDetailsFragmentTestTestModule @Module( includes = [ @@ -33,7 +34,9 @@ import de.rki.coronawarnapp.ui.submission.SubmissionTestResultTestModule SubmissionTestResultConsentGivenTestModule::class, SubmissionSymptomIntroFragmentTestModule::class, SubmissionContactTestModule::class, - SubmissionQRScanFragmentModule::class + SubmissionQRScanFragmentModule::class, + // Tracing + TracingDetailsFragmentTestTestModule::class ] ) class FragmentTestModuleRegistrar