From ff9aa722c84a7ac49319301840366308750e1901 Mon Sep 17 00:00:00 2001
From: Mohamed Metwalli <mohamed.metwalli@sap.com>
Date: Wed, 13 Jan 2021 15:10:20 +0100
Subject: [PATCH] Create automated app screenshots - Risk calculation screen
 (EXPOSUREAPP-2996) #2052

* Add screenshot test for risk calculation

* Update Todo

* Add name suffix

Co-authored-by: harambasicluka <64483219+harambasicluka@users.noreply.github.com>
Co-authored-by: Ralf Gehrer <ralfgehrer@users.noreply.github.com>
---
 .../coronawarnapp/ui/tracing/TracingData.kt   | 127 +++++++++++++++++
 .../ui/tracing/TracingDetailsFragmentTest.kt  | 132 ++++++++++++++++++
 .../FragmentTestModuleRegistrar.kt            |   5 +-
 3 files changed, 263 insertions(+), 1 deletion(-)
 create mode 100644 Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/tracing/TracingData.kt
 create mode 100644 Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/tracing/TracingDetailsFragmentTest.kt

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 000000000..7679a4aad
--- /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 000000000..0a1084886
--- /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 d8f858652..436786aa9 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
-- 
GitLab