diff --git a/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/common/ScreenSecurityTest.kt b/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/common/ScreenSecurityTest.kt index 7a6cb973..d3217ee0 100644 --- a/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/common/ScreenSecurityTest.kt +++ b/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/common/ScreenSecurityTest.kt @@ -7,6 +7,7 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.test.junit4.ComposeContentTestRule import androidx.compose.ui.test.junit4.createComposeRule import androidx.test.filters.MediumTest +import androidx.test.filters.SmallTest import co.electriccoin.zcash.test.UiTestPrerequisites import co.electriccoin.zcash.ui.design.theme.ZcashTheme import kotlinx.coroutines.flow.MutableStateFlow @@ -15,11 +16,30 @@ import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test import kotlin.test.assertEquals +import kotlin.test.assertTrue class ScreenSecurityTest : UiTestPrerequisites() { @get:Rule val composeTestRule = createComposeRule() + @Test + @SmallTest + fun sanity_is_running_test_check() { + assertTrue( + actual = isRunningTest, + message = "isRunningTest must always be TRUE while running from an automated Android UI test." + ) + } + + @Test + @SmallTest + fun sanity_should_secure_screen_check() { + assertTrue( + actual = shouldSecureScreen, + message = "shouldSecureScreen must always be TRUE while running from an automated Android UI test." + ) + } + @Test @MediumTest fun acquireAndReleaseScreenSecurity() = runTest { diff --git a/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/seed/view/SeedViewSecuredScreenTest.kt b/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/seed/view/SeedViewSecuredScreenTest.kt index cbf2240a..ede80659 100644 --- a/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/seed/view/SeedViewSecuredScreenTest.kt +++ b/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/seed/view/SeedViewSecuredScreenTest.kt @@ -9,13 +9,11 @@ import co.electriccoin.zcash.test.UiTestPrerequisites import co.electriccoin.zcash.ui.common.LocalScreenSecurity import co.electriccoin.zcash.ui.common.ScreenSecurity import co.electriccoin.zcash.ui.design.theme.ZcashTheme -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test import kotlin.test.assertEquals -@OptIn(ExperimentalCoroutinesApi::class) class SeedViewSecuredScreenTest : UiTestPrerequisites() { @get:Rule val composeTestRule = createComposeRule() diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/common/ScreenSecurity.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/common/ScreenSecurity.kt index 598df750..481562bc 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/common/ScreenSecurity.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/common/ScreenSecurity.kt @@ -3,6 +3,8 @@ package co.electriccoin.zcash.ui.common import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.compositionLocalOf +import co.electriccoin.zcash.spackle.Twig +import co.electriccoin.zcash.ui.BuildConfig import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update @@ -29,6 +31,28 @@ class ScreenSecurity { @Suppress("CompositionLocalAllowlist") val LocalScreenSecurity = compositionLocalOf { ScreenSecurity() } +/** + * Returns true only if it's used from the automated Android UI testing. + */ +val isRunningTest: Boolean by lazy { + runCatching { + Class.forName("androidx.test.espresso.Espresso") + true + }.getOrDefault(false).also { + Twig.debug { "Running in UI test: $it" } + } +} + +/** + * Decides whether the SecureScreen should be activated depending on [isRunningTest] and Gradle + * [BuildConfig.IS_SECURE_SCREEN_ENABLED]. + */ +val shouldSecureScreen: Boolean by lazy { + if (isRunningTest) { + true + } else BuildConfig.IS_SECURE_SCREEN_ENABLED +} + @Composable fun SecureScreen() { val screenSecurity = LocalScreenSecurity.current diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/backup/view/LongNewWalletBackupView.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/backup/view/LongNewWalletBackupView.kt index 80c9ec50..8cfa016f 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/backup/view/LongNewWalletBackupView.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/backup/view/LongNewWalletBackupView.kt @@ -43,9 +43,9 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import cash.z.ecc.android.sdk.model.PersistableWallet import cash.z.ecc.sdk.fixture.PersistableWalletFixture import co.electriccoin.zcash.spackle.model.Index -import co.electriccoin.zcash.ui.BuildConfig import co.electriccoin.zcash.ui.R import co.electriccoin.zcash.ui.common.SecureScreen +import co.electriccoin.zcash.ui.common.shouldSecureScreen import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT import co.electriccoin.zcash.ui.design.component.Body import co.electriccoin.zcash.ui.design.component.CHIP_GRID_ROW_SIZE @@ -203,7 +203,7 @@ private fun EducationRecoveryPhrase() { @Composable private fun SeedPhrase(persistableWallet: PersistableWallet) { - if (BuildConfig.IS_SECURE_SCREEN_ENABLED) { + if (shouldSecureScreen) { SecureScreen() } Column( @@ -235,7 +235,7 @@ private fun TestInProgress( onChoicesChanged: ((choicesCount: Int) -> Unit)?, backupState: BackupState ) { - if (BuildConfig.IS_SECURE_SCREEN_ENABLED) { + if (shouldSecureScreen) { SecureScreen() } val testChoices = splitSeedPhrase diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/backup/view/ShortNewWalletBackupView.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/backup/view/ShortNewWalletBackupView.kt index 9e99165e..9204da9f 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/backup/view/ShortNewWalletBackupView.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/backup/view/ShortNewWalletBackupView.kt @@ -32,9 +32,9 @@ import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Preview import cash.z.ecc.android.sdk.model.PersistableWallet import cash.z.ecc.sdk.fixture.PersistableWalletFixture -import co.electriccoin.zcash.ui.BuildConfig import co.electriccoin.zcash.ui.R import co.electriccoin.zcash.ui.common.SecureScreen +import co.electriccoin.zcash.ui.common.shouldSecureScreen import co.electriccoin.zcash.ui.design.component.Body import co.electriccoin.zcash.ui.design.component.ChipGrid import co.electriccoin.zcash.ui.design.component.GradientSurface @@ -59,7 +59,6 @@ private fun ComposablePreviewShort() { /** * @param onComplete Callback when the user has confirmed viewing the seed phrase. */ -@OptIn(ExperimentalMaterial3Api::class) @Composable fun ShortNewWalletBackup( wallet: PersistableWallet, @@ -112,7 +111,7 @@ private fun ShortNewWalletMainContent( @Composable private fun SeedPhrase(persistableWallet: PersistableWallet) { - if (BuildConfig.IS_SECURE_SCREEN_ENABLED) { + if (shouldSecureScreen) { SecureScreen() } Column { diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/restore/view/RestoreView.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/restore/view/RestoreView.kt index b594f17d..6dfacb9d 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/restore/view/RestoreView.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/restore/view/RestoreView.kt @@ -63,9 +63,9 @@ import cash.z.ecc.android.sdk.model.BlockHeight import cash.z.ecc.android.sdk.model.ZcashNetwork import cash.z.ecc.sdk.model.SeedPhraseValidation import co.electriccoin.zcash.spackle.model.Index -import co.electriccoin.zcash.ui.BuildConfig import co.electriccoin.zcash.ui.R import co.electriccoin.zcash.ui.common.SecureScreen +import co.electriccoin.zcash.ui.common.shouldSecureScreen import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT import co.electriccoin.zcash.ui.design.component.Body import co.electriccoin.zcash.ui.design.component.CHIP_GRID_ROW_SIZE @@ -202,7 +202,7 @@ fun RestoreWallet( when (currentStage) { RestoreStage.Seed -> { - if (BuildConfig.IS_SECURE_SCREEN_ENABLED) { + if (shouldSecureScreen) { SecureScreen() } diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/seed/view/SeedView.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/seed/view/SeedView.kt index 7c987bdb..057fae00 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/seed/view/SeedView.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/seed/view/SeedView.kt @@ -22,9 +22,9 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import cash.z.ecc.android.sdk.model.PersistableWallet import cash.z.ecc.sdk.fixture.PersistableWalletFixture -import co.electriccoin.zcash.ui.BuildConfig import co.electriccoin.zcash.ui.R import co.electriccoin.zcash.ui.common.SecureScreen +import co.electriccoin.zcash.ui.common.shouldSecureScreen import co.electriccoin.zcash.ui.design.component.Body import co.electriccoin.zcash.ui.design.component.ChipGrid import co.electriccoin.zcash.ui.design.component.GradientSurface @@ -56,7 +56,7 @@ fun Seed( onBack: () -> Unit, onCopyToClipboard: () -> Unit ) { - if (BuildConfig.IS_SECURE_SCREEN_ENABLED) { + if (shouldSecureScreen) { SecureScreen() } Scaffold(topBar = {