[#1016] Force SecureScreen turned on in UI testing

- After we added the customization of SecureScreen sensitive data mechanism in building and testing the app via Gradle property in #1009, we also need to ensure that the SecureScreen is always on in our automated Android UI tests.
- Closes #1016
This commit is contained in:
Honza Rychnovský 2023-10-23 15:21:00 +02:00 committed by GitHub
parent ab7117e458
commit 2f773b8b0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 53 additions and 12 deletions

View File

@ -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 {

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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()
}

View File

@ -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 = {