From 081c464bb6d4ff5976055ed257c7de74cd9b6b4e Mon Sep 17 00:00:00 2001 From: Juraj Kusnier <jurajkusnier@users.noreply.github.com> Date: Wed, 27 Jan 2021 17:10:06 +0100 Subject: [PATCH] Update automatic screenshot behaviour for statistics (EXPOSUREAPP-4622) #2206 * fix tests * Implement StatisticsExplanationFragmentTest * Implement StatisticsTest * Fix old tests * Rename StatisticsTest > StatisticsCardsTest * Fix marge Co-authored-by: harambasicluka <64483219+harambasicluka@users.noreply.github.com> Co-authored-by: Ralf Gehrer <ralfgehrer@users.noreply.github.com> --- .../ui/statistics/StatisticsCardsTest.kt | 220 ++++++++++++++++++ .../StatisticsExplanationFragmentTest.kt | 37 +++ .../FragmentTestModuleRegistrar.kt | 5 +- 3 files changed, 261 insertions(+), 1 deletion(-) create mode 100644 Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/statistics/StatisticsCardsTest.kt create mode 100644 Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/statistics/StatisticsExplanationFragmentTest.kt diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/statistics/StatisticsCardsTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/statistics/StatisticsCardsTest.kt new file mode 100644 index 000000000..5d9afd0ba --- /dev/null +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/statistics/StatisticsCardsTest.kt @@ -0,0 +1,220 @@ +package de.rki.coronawarnapp.ui.statistics + +import android.content.Context +import android.content.SharedPreferences +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.ext.junit.runners.AndroidJUnit4 +import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.appconfig.AppConfigProvider +import de.rki.coronawarnapp.environment.EnvironmentSetup +import de.rki.coronawarnapp.environment.download.DownloadCDNModule +import de.rki.coronawarnapp.http.HttpModule +import de.rki.coronawarnapp.main.CWASettings +import de.rki.coronawarnapp.notification.ShareTestResultNotificationService +import de.rki.coronawarnapp.statistics.StatisticsData +import de.rki.coronawarnapp.statistics.StatisticsModule +import de.rki.coronawarnapp.statistics.source.StatisticsParser +import de.rki.coronawarnapp.statistics.source.StatisticsProvider +import de.rki.coronawarnapp.statistics.source.StatisticsServer +import de.rki.coronawarnapp.statistics.ui.homecards.StatisticsHomeCard +import de.rki.coronawarnapp.storage.TracingRepository +import de.rki.coronawarnapp.submission.SubmissionRepository +import de.rki.coronawarnapp.submission.ui.homecards.SubmissionStateProvider +import de.rki.coronawarnapp.submission.ui.homecards.TestPositiveCard +import de.rki.coronawarnapp.submission.ui.homecards.TestResultItem +import de.rki.coronawarnapp.submission.ui.homecards.TestSubmissionDoneCard +import de.rki.coronawarnapp.tracing.GeneralTracingStatus +import de.rki.coronawarnapp.tracing.states.TracingStateProvider +import de.rki.coronawarnapp.tracing.ui.homecards.TracingStateItem +import de.rki.coronawarnapp.tracing.ui.statusbar.TracingHeaderState +import de.rki.coronawarnapp.ui.main.home.HomeData +import de.rki.coronawarnapp.ui.main.home.HomeFragment +import de.rki.coronawarnapp.ui.main.home.HomeFragmentViewModel +import de.rki.coronawarnapp.ui.main.home.items.DiaryCard +import de.rki.coronawarnapp.ui.main.home.items.FAQCard +import de.rki.coronawarnapp.ui.main.home.items.HomeItem +import de.rki.coronawarnapp.util.security.EncryptionErrorResetTool +import de.rki.coronawarnapp.util.security.VerificationKeys +import de.rki.coronawarnapp.util.serialization.SerializationModule +import de.rki.coronawarnapp.util.ui.SingleLiveEvent +import io.mockk.MockKAnnotations +import io.mockk.Runs +import io.mockk.every +import io.mockk.impl.annotations.MockK +import io.mockk.just +import io.mockk.spyk +import kotlinx.coroutines.runBlocking +import okhttp3.Cache +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import retrofit2.converter.gson.GsonConverterFactory +import testhelpers.BaseUITest +import testhelpers.SCREENSHOT_DELAY_TIME +import testhelpers.Screenshot +import testhelpers.SystemUIDemoModeRule +import testhelpers.TestDispatcherProvider +import testhelpers.launchFragmentInContainer2 +import testhelpers.recyclerScrollTo +import timber.log.Timber +import tools.fastlane.screengrab.Screengrab +import tools.fastlane.screengrab.locale.LocaleTestRule + +@RunWith(AndroidJUnit4::class) +class StatisticsCardsTest : BaseUITest() { + + @MockK lateinit var errorResetTool: EncryptionErrorResetTool + @MockK lateinit var tracingStatus: GeneralTracingStatus + @MockK lateinit var tracingStateProviderFactory: TracingStateProvider.Factory + @MockK lateinit var submissionStateProvider: SubmissionStateProvider + @MockK lateinit var tracingRepository: TracingRepository + @MockK lateinit var shareTestResultNotificationService: ShareTestResultNotificationService + @MockK lateinit var submissionRepository: SubmissionRepository + @MockK lateinit var cwaSettings: CWASettings + @MockK lateinit var appConfigProvider: AppConfigProvider + @MockK lateinit var cache: Cache + @MockK lateinit var context: Context + @MockK lateinit var preferences: SharedPreferences + @MockK lateinit var statisticsProvider: StatisticsProvider + + private lateinit var viewModel: HomeFragmentViewModel + + @Rule + @JvmField + val localeTestRule = LocaleTestRule() + + @get:Rule + val systemUIDemoModeRule = SystemUIDemoModeRule() + + @Before + fun setup() { + MockKAnnotations.init(this, relaxed = true) + + if (statisticsData == null) { + statisticsData = loadRealStatisticsData() + } + + viewModel = homeFragmentViewModelSpy() + with(viewModel) { + every { observeTestResultToSchedulePositiveTestResultReminder() } just Runs + every { refreshRequiredData() } just Runs + every { tracingHeaderState } returns MutableLiveData(TracingHeaderState.TracingActive) + every { showLoweredRiskLevelDialog } returns MutableLiveData() + every { popupEvents } returns SingleLiveEvent() + every { homeItems } returns itemsLiveData(HomeData.Tracing.LOW_RISK_ITEM, statsData = statisticsData) + } + + setupMockViewModel( + object : HomeFragmentViewModel.Factory { + override fun create(): HomeFragmentViewModel = viewModel + } + ) + } + + @After + fun teardown() { + clearAllViewModels() + } + + @Screenshot + @Test + fun capture_screenshot() { + launchFragmentInContainer2<HomeFragment>() + Thread.sleep(SCREENSHOT_DELAY_TIME) + onView(withId(R.id.recycler_view)).perform(recyclerScrollTo(3)) + + for (i in 0 until (statisticsData?.items?.size ?: 0)) { + onView(withId(R.id.statistics_recyclerview)).perform(recyclerScrollTo(i)) + Thread.sleep(SCREENSHOT_DELAY_TIME) + Screengrab.screenshot(HomeFragment::class.simpleName.plus("_statistics_card_$i")) + } + } + + private fun itemsLiveData( + tracingStateItem: TracingStateItem = HomeData.Tracing.LOW_RISK_ITEM, + submissionTestResultItem: TestResultItem = HomeData.Submission.TEST_UNREGISTERED_ITEM, + statsData: StatisticsData? = null + ): LiveData<List<HomeItem>> = + MutableLiveData( + mutableListOf<HomeItem>().apply { + when (submissionTestResultItem) { + is TestSubmissionDoneCard.Item, + is TestPositiveCard.Item -> { + Timber.d("Tracing item is not added, submission:$submissionTestResultItem") + } + else -> add(tracingStateItem) + } + + add(submissionTestResultItem) + + if (statsData != null) { + add(StatisticsHomeCard.Item(data = statsData, onHelpAction = { })) + } + + add(DiaryCard.Item {}) + add(FAQCard.Item {}) + } + ) + + private fun homeFragmentViewModelSpy() = spyk( + HomeFragmentViewModel( + dispatcherProvider = TestDispatcherProvider(), + errorResetTool = errorResetTool, + tracingRepository = tracingRepository, + tracingStateProviderFactory = tracingStateProviderFactory, + shareTestResultNotificationService = shareTestResultNotificationService, + appConfigProvider = appConfigProvider, + tracingStatus = tracingStatus, + submissionRepository = submissionRepository, + submissionStateProvider = submissionStateProvider, + cwaSettings = cwaSettings, + statisticsProvider = statisticsProvider + ) + ) + + private fun loadRealStatisticsData(): StatisticsData? { + every { preferences.getString(any(), any()) } returns null + every { context.getSharedPreferences(any(), any()) } returns preferences + + val cdnModule = DownloadCDNModule() + val baseGson = SerializationModule().baseGson() + val environmentSetup = EnvironmentSetup(context = context, gson = baseGson) + val httpClient = HttpModule().defaultHttpClient() + val cdnClient = cdnModule.cdnHttpClient(httpClient) + val url = cdnModule.provideDownloadServerUrl(environmentSetup) + val verificationKeys = VerificationKeys(environmentSetup) + val gsonFactory = GsonConverterFactory.create() + + val statisticsServer = StatisticsServer( + api = { + StatisticsModule().api( + client = cdnClient, + url = url, + gsonConverterFactory = gsonFactory, + cache = cache + ) + }, + cache = cache, + verificationKeys = verificationKeys + ) + + return runBlocking { + try { + val rawData = statisticsServer.getRawStatistics() + StatisticsParser().parse(rawData) + } catch (e: Exception) { + Timber.e(e, "Can't download statistics data. Check your internet connection.") + null + } + } + } + + companion object { + private var statisticsData: StatisticsData? = null + } +} diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/statistics/StatisticsExplanationFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/statistics/StatisticsExplanationFragmentTest.kt new file mode 100644 index 000000000..7553d59da --- /dev/null +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/statistics/StatisticsExplanationFragmentTest.kt @@ -0,0 +1,37 @@ +package de.rki.coronawarnapp.ui.statistics + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import dagger.Module +import dagger.android.ContributesAndroidInjector +import de.rki.coronawarnapp.statistics.ui.StatisticsExplanationFragment +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import testhelpers.BaseUITest +import testhelpers.Screenshot +import testhelpers.SystemUIDemoModeRule +import testhelpers.captureScreenshot +import tools.fastlane.screengrab.locale.LocaleTestRule + +@RunWith(AndroidJUnit4::class) +class StatisticsExplanationFragmentTest : BaseUITest() { + + @Rule + @JvmField + val localeTestRule = LocaleTestRule() + + @get:Rule + val systemUIDemoModeRule = SystemUIDemoModeRule() + + @Screenshot + @Test + fun capture_screenshot() { + captureScreenshot<StatisticsExplanationFragment>() + } +} + +@Module +abstract class StatisticsExplanationFragmentTestModule { + @ContributesAndroidInjector + abstract fun statisticsExplanationFragmentTest(): StatisticsExplanationFragmentTest +} diff --git a/Corona-Warn-App/src/androidTest/java/testhelpers/FragmentTestModuleRegistrar.kt b/Corona-Warn-App/src/androidTest/java/testhelpers/FragmentTestModuleRegistrar.kt index 78cd37014..76df52f04 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.onboarding.OnboardingNotificationsTestModule import de.rki.coronawarnapp.ui.onboarding.OnboardingPrivacyTestModule import de.rki.coronawarnapp.ui.onboarding.OnboardingTestFragmentModule import de.rki.coronawarnapp.ui.onboarding.OnboardingTracingFragmentTestModule +import de.rki.coronawarnapp.ui.statistics.StatisticsExplanationFragmentTestModule import de.rki.coronawarnapp.ui.submission.SubmissionConsentFragmentTestModule import de.rki.coronawarnapp.ui.submission.SubmissionContactTestModule import de.rki.coronawarnapp.ui.submission.SubmissionDispatcherTestModule @@ -64,7 +65,9 @@ import de.rki.coronawarnapp.ui.tracing.TracingDetailsFragmentTestTestModule ContactDiaryPersonListFragmentTestModule::class, ContactDiaryLocationListFragmentTestModule::class, ContactDiaryEditLocationsFragmentTestModule::class, - ContactDiaryEditPersonsFragmentTestModule::class + ContactDiaryEditPersonsFragmentTestModule::class, + // Statistics + StatisticsExplanationFragmentTestModule::class ] ) class FragmentTestModuleRegistrar -- GitLab