Test hotfixes

This commit is contained in:
Milan Cerovsky 2025-03-24 10:55:18 +01:00
parent 9195ebef49
commit 3af7fedd9b
8 changed files with 54 additions and 101 deletions

View File

@ -45,6 +45,7 @@ import kotlinx.coroutines.launch
fun ZashiSeedTextField( fun ZashiSeedTextField(
state: SeedTextFieldState, state: SeedTextFieldState,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
wordModifier: (index: Int) -> Modifier = { Modifier },
handle: SeedTextFieldHandle = rememberSeedTextFieldHandle(), handle: SeedTextFieldHandle = rememberSeedTextFieldHandle(),
) { ) {
val interactions = remember { state.values.map { MutableInteractionSource() } } val interactions = remember { state.values.map { MutableInteractionSource() } }
@ -105,6 +106,7 @@ fun ZashiSeedTextField(
} }
} }
}, },
innerModifier = wordModifier(index),
prefix = (index + 1).toString(), prefix = (index + 1).toString(),
state = state =
wordState.copy( wordState.copy(

View File

@ -29,13 +29,14 @@ fun ZashiSeedWordTextField(
prefix: String, prefix: String,
state: SeedWordTextFieldState, state: SeedWordTextFieldState,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
innerModifier: Modifier = Modifier,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default, keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions.Default, keyboardActions: KeyboardActions = KeyboardActions.Default,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
) { ) {
ZashiTextField( ZashiTextField(
modifier = modifier, modifier = modifier,
innerModifier = Modifier, innerModifier = innerModifier,
shape = RoundedCornerShape(12.dp), shape = RoundedCornerShape(12.dp),
keyboardOptions = keyboardOptions, keyboardOptions = keyboardOptions,
keyboardActions = keyboardActions, keyboardActions = keyboardActions,

View File

@ -0,0 +1,5 @@
package co.electriccoin.zcash.ui.screen.restore.height
object RestoreBDHeightTags {
const val RESTORE_BTN = "RESTORE_BTN"
}

View File

@ -132,7 +132,10 @@ private fun Content(
ZashiButton( ZashiButton(
state.restore, state.restore,
modifier = Modifier.fillMaxWidth(), modifier =
Modifier
.fillMaxWidth()
.testTag(RestoreBDHeightTags.RESTORE_BTN),
) )
} }
} }

View File

@ -108,7 +108,8 @@ private fun Content(
Spacer(Modifier.height(20.dp)) Spacer(Modifier.height(20.dp))
ZashiSeedTextField( ZashiSeedTextField(
state = state.seed, state = state.seed,
handle = handle handle = handle,
wordModifier = { Modifier.testTag(RestoreSeedTag.SEED_WORD_TEXT_FIELD) }
) )
Spacer(Modifier.weight(1f)) Spacer(Modifier.weight(1f))
Spacer(Modifier.height(24.dp)) Spacer(Modifier.height(24.dp))

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="security_warning_header">Advertencia de seguridad:</string>
<string name="security_warning_text" formatted="true">Zashi <xliff:g example="0.2.0" id="version_name">%1$s</xliff:g> es una billetera exclusiva para Zcash, con protección de privacidad — creada por Zcashers para Zcashers. Zashi ha sido diseñada para tu privacidad y seguridad. Al instalar y usar Zashi, aceptas compartir informes de fallos con Electric Coin Co. (el desarrollador de la billetera), lo que nos ayudará a mejorar la experiencia del usuario de Zashi.*\n\nPor favor, confirma y acepta a continuación para continuar.</string>
<string name="security_warning_text_footnote_part_1">*Nota:</string>
<string name="security_warning_text_footnote_part_2">\u0020Los informes de fallos podrían revelar la fecha y hora del fallo y los eventos que ocurrieron, pero no revelarían las claves de gasto o de visualización.</string>
<string name="security_warning_confirm">Confirmar</string>
<string name="security_warning_acknowledge">Acepto</string>
</resources>

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="security_warning_header">Security warning:</string>
<string name="security_warning_text" formatted="true">Zashi <xliff:g example="0.2.0" id="version_name">%1$s
</xliff:g>is a Zcash-only, shielded wallet — built by Zcashers for Zcashers. Zashi has been engineered for your
privacy and safety. By installing and using Zashi, you consent to share crash reports with Electric Coin Co.
(the wallet developer), which will help us improve the Zashi user experience.*\n\nPlease acknowledge and
confirm below to proceed.</string>
<string name="security_warning_text_footnote_part_1">*Note:</string>
<string name="security_warning_text_footnote_part_2">\u0020Crash reports might reveal the timing of the crash and
what events occurred, but it would not reveal spending or viewing keys.</string>
<string name="security_warning_confirm">Confirm</string>
<string name="security_warning_acknowledge">I acknowledge</string>
</resources>

View File

@ -5,14 +5,15 @@ package co.electroniccoin.zcash.ui.screenshot
import android.content.Context import android.content.Context
import android.os.Build import android.os.Build
import android.os.LocaleList import android.os.LocaleList
import androidx.activity.viewModels
import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.SemanticsNodeInteraction import androidx.compose.ui.test.SemanticsNodeInteraction
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.hasTestTag import androidx.compose.ui.test.hasTestTag
import androidx.compose.ui.test.hasText import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.compose.ui.test.junit4.ComposeTestRule import androidx.compose.ui.test.junit4.ComposeTestRule
import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onAllNodesWithTag
import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performClick
@ -29,7 +30,6 @@ import androidx.test.filters.LargeTest
import androidx.test.filters.SdkSuppress import androidx.test.filters.SdkSuppress
import cash.z.ecc.android.sdk.fixture.WalletAddressFixture import cash.z.ecc.android.sdk.fixture.WalletAddressFixture
import cash.z.ecc.android.sdk.model.MonetarySeparators import cash.z.ecc.android.sdk.model.MonetarySeparators
import cash.z.ecc.android.sdk.model.SeedPhrase
import cash.z.ecc.sdk.fixture.MemoFixture import cash.z.ecc.sdk.fixture.MemoFixture
import cash.z.ecc.sdk.fixture.SeedPhraseFixture import cash.z.ecc.sdk.fixture.SeedPhraseFixture
import cash.z.ecc.sdk.type.ZcashCurrency import cash.z.ecc.sdk.type.ZcashCurrency
@ -45,8 +45,8 @@ import co.electriccoin.zcash.ui.design.component.UiMode
import co.electriccoin.zcash.ui.screen.authentication.view.AnimationConstants.WELCOME_ANIM_TEST_TAG import co.electriccoin.zcash.ui.screen.authentication.view.AnimationConstants.WELCOME_ANIM_TEST_TAG
import co.electriccoin.zcash.ui.screen.balances.BalanceTag import co.electriccoin.zcash.ui.screen.balances.BalanceTag
import co.electriccoin.zcash.ui.screen.home.HomeTags import co.electriccoin.zcash.ui.screen.home.HomeTags
import co.electriccoin.zcash.ui.screen.restore.height.RestoreBDHeightTags
import co.electriccoin.zcash.ui.screen.restore.seed.RestoreSeedTag import co.electriccoin.zcash.ui.screen.restore.seed.RestoreSeedTag
import co.electriccoin.zcash.ui.screen.restore.seed.RestoreSeedViewModel
import co.electriccoin.zcash.ui.screen.send.SendTag import co.electriccoin.zcash.ui.screen.send.SendTag
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@ -196,19 +196,22 @@ class ScreenshotTest : UiTestPrerequisites() {
// To ensure that the new screen is available, or wait until it is // To ensure that the new screen is available, or wait until it is
composeTestRule.waitUntilAtLeastOneExists( composeTestRule.waitUntilAtLeastOneExists(
hasText(resContext.getString(R.string.restore_title)), hasText(resContext.getString(R.string.restore_title), ignoreCase = true),
DEFAULT_TIMEOUT_MILLISECONDS DEFAULT_TIMEOUT_MILLISECONDS
) )
composeTestRule.onNodeWithText(resContext.getString(R.string.restore_title)).also { composeTestRule
it.assertExists() .onNodeWithText(
} resContext.getString(R.string.restore_title),
ignoreCase = true
)
.assertExists()
takeScreenshot(tag, "Import 1") takeScreenshot(tag, "Import 1")
val seedPhraseSplitLength = SeedPhraseFixture.new().split.size val seedPhraseSplitLength = SeedPhraseFixture.new().split.size
SeedPhraseFixture.new().split.forEachIndexed { index, string -> SeedPhraseFixture.new().split.forEachIndexed { index, string ->
composeTestRule.onNodeWithTag(RestoreSeedTag.SEED_WORD_TEXT_FIELD).also { composeTestRule.onAllNodesWithTag(RestoreSeedTag.SEED_WORD_TEXT_FIELD)[index].also {
it.performTextInput(string) it.performTextInput(string)
// Take a screenshot half-way through filling in the seed phrase // Take a screenshot half-way through filling in the seed phrase
@ -218,39 +221,39 @@ class ScreenshotTest : UiTestPrerequisites() {
} }
} }
composeTestRule.waitUntil { composeTestRule.onNodeWithText(
composeTestRule.activity.viewModels<RestoreSeedViewModel>().value.suggestionsState.value text = resContext.getString(R.string.restore_button),
?.suggestions ignoreCase = true
?.size == ).also {
SeedPhrase.SEED_PHRASE_SIZE // Even with waiting for the word list in the view model,
// there's some latency before the button is enabled
composeTestRule.waitUntil(5.seconds.inWholeMilliseconds) {
runCatching { it.assertIsEnabled() }.isSuccess
}
it.performScrollTo()
it.performClick()
} }
// composeTestRule.onNodeWithText( composeTestRule
// text = resContext.getString(R.string.restore_seed_button_next), .onNodeWithText(
// ignoreCase = true resContext.getString(R.string.restore_bd_subtitle),
// ).also { ignoreCase = true
// // Even with waiting for the word list in the view model, )
// // there's some latency before the button is enabled .also {
// composeTestRule.waitUntil(5.seconds.inWholeMilliseconds) { it.assertExists()
// runCatching { it.assertIsEnabled() }.isSuccess }
// }
// it.performScrollTo()
// it.performClick()
// }
// composeTestRule.onNodeWithText(resContext.getString(R.string.restore_birthday_header)).also {
// it.assertExists()
// }
takeScreenshot(tag, "Import 3") takeScreenshot(tag, "Import 3")
// composeTestRule.onNodeWithText( composeTestRule.waitUntilAtLeastOneExists(
// text = resContext.getString(R.string.restore_birthday_button_restore), hasTestTag(RestoreBDHeightTags.RESTORE_BTN),
// ignoreCase = true timeoutMillis = DEFAULT_TIMEOUT_MILLISECONDS
// ).also { )
// it.performScrollTo()
// it.performClick() composeTestRule.onNodeWithTag(RestoreBDHeightTags.RESTORE_BTN).also {
// } it.performScrollTo()
it.performClick()
}
composeTestRule.waitUntil(DEFAULT_TIMEOUT_MILLISECONDS) { composeTestRule.waitUntil(DEFAULT_TIMEOUT_MILLISECONDS) {
composeTestRule.onNodeWithText( composeTestRule.onNodeWithText(
@ -404,41 +407,6 @@ private fun onboardingScreenshots(
).also { ).also {
it.performClick() it.performClick()
} }
// Security Warning screen
composeTestRule.onNodeWithText(
text = resContext.getString(R.string.security_warning_acknowledge),
ignoreCase = true,
useUnmergedTree = true
).also {
it.assertExists()
it.performClick()
ScreenshotTest.takeScreenshot(tag, "Security Warning")
}
composeTestRule.onNodeWithText(
text = resContext.getString(R.string.security_warning_confirm),
ignoreCase = true,
useUnmergedTree = true
).performClick()
composeTestRule.waitForIdle()
composeTestRule.waitUntil {
composeTestRule.onNodeWithText(
text = resContext.getString(R.string.seed_recovery_next_button),
ignoreCase = true,
useUnmergedTree = true
).exists()
}
composeTestRule.onNodeWithText(
text = resContext.getString(R.string.seed_recovery_next_button),
ignoreCase = true,
useUnmergedTree = true
).also {
it.performScrollTo()
it.performClick()
}
} }
private fun accountScreenshots( private fun accountScreenshots(