From 6f751761a8e8baf349ece21a85db917c3c4eedd9 Mon Sep 17 00:00:00 2001
From: Matthias Urhahn <matthias.urhahn@sap.com>
Date: Tue, 3 Nov 2020 12:06:10 +0100
Subject: [PATCH] Show current env when launching app (DEV) (#1515)

* On flavor "deviceForTesters" show a toast to tell the testers/devs which environment is currently activated.

* Add unit tests for new "Current env: ..." toast.

Co-authored-by: Ralf Gehrer <ralfgehrer@users.noreply.github.com>
---
 .../rki/coronawarnapp/ui/main/MainActivity.kt | 17 +++++
 .../ui/main/MainActivityModule.kt             | 12 ++++
 .../ui/main/MainActivityViewModel.kt          | 33 +++++++++
 .../main/MainActivityViewModelTest.kt         | 69 +++++++++++++++++++
 .../main/home/HomeFragmentViewModelTest.kt    |  2 -
 5 files changed, 131 insertions(+), 2 deletions(-)
 create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivityViewModel.kt
 create mode 100644 Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/MainActivityViewModelTest.kt

diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt
index 0abb8c245..4b07eea49 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt
@@ -5,6 +5,7 @@ import android.content.Intent
 import android.net.Uri
 import android.os.Bundle
 import android.provider.Settings
+import android.widget.Toast
 import androidx.appcompat.app.AppCompatActivity
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.FragmentManager
@@ -19,10 +20,14 @@ import de.rki.coronawarnapp.storage.LocalData
 import de.rki.coronawarnapp.ui.base.startActivitySafely
 import de.rki.coronawarnapp.ui.viewmodel.SettingsViewModel
 import de.rki.coronawarnapp.util.BackgroundPrioritization
+import de.rki.coronawarnapp.util.CWADebug
 import de.rki.coronawarnapp.util.ConnectivityHelper
 import de.rki.coronawarnapp.util.DialogHelper
 import de.rki.coronawarnapp.util.device.PowerManagement
 import de.rki.coronawarnapp.util.di.AppInjector
+import de.rki.coronawarnapp.util.ui.observe2
+import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactoryProvider
+import de.rki.coronawarnapp.util.viewmodel.cwaViewModels
 import de.rki.coronawarnapp.worker.BackgroundWorkScheduler
 import kotlinx.coroutines.launch
 import javax.inject.Inject
@@ -47,6 +52,12 @@ class MainActivity : AppCompatActivity(), HasAndroidInjector {
     @Inject lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
     override fun androidInjector(): AndroidInjector<Any> = dispatchingAndroidInjector
 
+    @Inject lateinit var viewModelFactory: CWAViewModelFactoryProvider.Factory
+    private val vm: MainActivityViewModel by cwaViewModels(
+        ownerProducer = { viewModelStore },
+        factoryProducer = { viewModelFactory }
+    )
+
     private val FragmentManager.currentNavigationFragment: Fragment?
         get() = primaryNavigationFragment?.childFragmentManager?.fragments?.first()
 
@@ -76,6 +87,12 @@ class MainActivity : AppCompatActivity(), HasAndroidInjector {
         super.onCreate(savedInstanceState)
         setContentView(R.layout.activity_main)
         settingsViewModel = ViewModelProviders.of(this).get(SettingsViewModel::class.java)
+
+        if (CWADebug.isDeviceForTestersBuild) {
+            vm.showEnvironmentHint.observe2(this) {
+                Toast.makeText(this, "Current environment: $it", Toast.LENGTH_SHORT).show()
+            }
+        }
     }
 
     /**
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivityModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivityModule.kt
index 647f333c8..7a596bfc0 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivityModule.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivityModule.kt
@@ -1,7 +1,9 @@
 package de.rki.coronawarnapp.ui.main
 
+import dagger.Binds
 import dagger.Module
 import dagger.android.ContributesAndroidInjector
+import dagger.multibindings.IntoMap
 import de.rki.coronawarnapp.ui.interoperability.InteroperabilityConfigurationFragment
 import de.rki.coronawarnapp.ui.interoperability.InteroperabilityConfigurationFragmentModule
 import de.rki.coronawarnapp.ui.main.home.HomeFragmentModule
@@ -11,6 +13,9 @@ import de.rki.coronawarnapp.ui.settings.SettingsResetFragment
 import de.rki.coronawarnapp.ui.settings.SettingsResetModule
 import de.rki.coronawarnapp.ui.submission.viewmodel.SubmissionFragmentModule
 import de.rki.coronawarnapp.ui.tracing.details.RiskDetailsFragmentModule
+import de.rki.coronawarnapp.util.viewmodel.CWAViewModel
+import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactory
+import de.rki.coronawarnapp.util.viewmodel.CWAViewModelKey
 
 @Module(
     includes = [
@@ -34,4 +39,11 @@ abstract class MainActivityModule {
 
     @ContributesAndroidInjector(modules = [SettingsResetModule::class])
     abstract fun settingsResetScreen(): SettingsResetFragment
+
+    @Binds
+    @IntoMap
+    @CWAViewModelKey(MainActivityViewModel::class)
+    abstract fun mainActivityViewModel(
+        factory: MainActivityViewModel.Factory
+    ): CWAViewModelFactory<out CWAViewModel>
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivityViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivityViewModel.kt
new file mode 100644
index 000000000..8345f33c5
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivityViewModel.kt
@@ -0,0 +1,33 @@
+package de.rki.coronawarnapp.ui.main
+
+import com.squareup.inject.assisted.AssistedInject
+import de.rki.coronawarnapp.environment.EnvironmentSetup
+import de.rki.coronawarnapp.util.CWADebug
+import de.rki.coronawarnapp.util.coroutine.DispatcherProvider
+import de.rki.coronawarnapp.util.ui.SingleLiveEvent
+import de.rki.coronawarnapp.util.viewmodel.CWAViewModel
+import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory
+
+class MainActivityViewModel @AssistedInject constructor(
+    dispatcherProvider: DispatcherProvider,
+    private val environmentSetup: EnvironmentSetup
+) : CWAViewModel(
+    dispatcherProvider = dispatcherProvider
+) {
+
+    val showEnvironmentHint = SingleLiveEvent<String>()
+
+    init {
+        if (CWADebug.isDeviceForTestersBuild) {
+            launch {
+                val current = environmentSetup.currentEnvironment
+                if (current != EnvironmentSetup.Type.PRODUCTION) {
+                    showEnvironmentHint.postValue(current.rawKey)
+                }
+            }
+        }
+    }
+
+    @AssistedInject.Factory
+    interface Factory : SimpleCWAViewModelFactory<MainActivityViewModel>
+}
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/MainActivityViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/MainActivityViewModelTest.kt
new file mode 100644
index 000000000..e2fd710f0
--- /dev/null
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/MainActivityViewModelTest.kt
@@ -0,0 +1,69 @@
+package de.rki.coronawarnapp.main
+
+import de.rki.coronawarnapp.environment.EnvironmentSetup
+import de.rki.coronawarnapp.ui.main.MainActivityViewModel
+import de.rki.coronawarnapp.util.CWADebug
+import io.kotest.matchers.shouldBe
+import io.mockk.MockKAnnotations
+import io.mockk.clearAllMocks
+import io.mockk.every
+import io.mockk.impl.annotations.MockK
+import io.mockk.mockkObject
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+import testhelpers.BaseTest
+import testhelpers.TestDispatcherProvider
+import testhelpers.extensions.CoroutinesTestExtension
+import testhelpers.extensions.InstantExecutorExtension
+
+@ExtendWith(InstantExecutorExtension::class, CoroutinesTestExtension::class)
+class MainActivityViewModelTest : BaseTest() {
+
+    @MockK lateinit var environmentSetup: EnvironmentSetup
+
+    @BeforeEach
+    fun setup() {
+        MockKAnnotations.init(this)
+
+        mockkObject(CWADebug)
+    }
+
+    @AfterEach
+    fun teardown() {
+        clearAllMocks()
+    }
+
+    private fun createInstance(): MainActivityViewModel = MainActivityViewModel(
+        dispatcherProvider = TestDispatcherProvider,
+        environmentSetup = environmentSetup
+    )
+
+    @Test
+    fun `environment toast is visible test environments`() {
+        every { CWADebug.isDeviceForTestersBuild } returns true
+        every { environmentSetup.currentEnvironment } returns EnvironmentSetup.Type.DEV
+
+        val vm = createInstance()
+        vm.showEnvironmentHint.value shouldBe EnvironmentSetup.Type.DEV.rawKey
+    }
+
+    @Test
+    fun `environment toast is only visible in deviceForTesters flavor`() {
+        every { CWADebug.isDeviceForTestersBuild } returns false
+        every { environmentSetup.currentEnvironment } returns EnvironmentSetup.Type.DEV
+
+        val vm = createInstance()
+        vm.showEnvironmentHint.value shouldBe null
+    }
+
+    @Test
+    fun `environment toast is not visible in production`() {
+        every { CWADebug.isDeviceForTestersBuild } returns true
+        every { environmentSetup.currentEnvironment } returns EnvironmentSetup.Type.PRODUCTION
+
+        val vm = createInstance()
+        vm.showEnvironmentHint.value shouldBe null
+    }
+}
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt
index ccd2091de..91e19f01d 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt
@@ -11,7 +11,6 @@ import de.rki.coronawarnapp.ui.main.home.TracingHeaderState
 import de.rki.coronawarnapp.ui.tracing.card.TracingCardState
 import de.rki.coronawarnapp.ui.tracing.card.TracingCardStateProvider
 import de.rki.coronawarnapp.ui.viewmodel.SettingsViewModel
-import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel
 import de.rki.coronawarnapp.util.security.EncryptionErrorResetTool
 import io.kotest.matchers.shouldBe
 import io.mockk.MockKAnnotations
@@ -39,7 +38,6 @@ class HomeFragmentViewModelTest : BaseTest() {
     @MockK lateinit var context: Context
     @MockK lateinit var errorResetTool: EncryptionErrorResetTool
     @MockK lateinit var settingsViewModel: SettingsViewModel
-    @MockK lateinit var submissionViewModel: SubmissionViewModel
     @MockK lateinit var tracingCardStateProvider: TracingCardStateProvider
     @MockK lateinit var submissionCardsStateProvider: SubmissionCardsStateProvider
     @MockK lateinit var tracingRepository: TracingRepository
-- 
GitLab