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