diff --git a/app/src/androidTest/kotlin/com/tangem/scenarios/BaseScenarios.kt b/app/src/androidTest/kotlin/com/tangem/scenarios/BaseScenarios.kt index 9c51a15aa5..272707ea7c 100644 --- a/app/src/androidTest/kotlin/com/tangem/scenarios/BaseScenarios.kt +++ b/app/src/androidTest/kotlin/com/tangem/scenarios/BaseScenarios.kt @@ -49,4 +49,16 @@ fun BaseTestCase.synchronizeAddresses(balance: String) { step("Assert wallet balance = '$balance'") { onMainScreen { walletBalance().assertTextContains(balance) } } +} + +fun BaseTestCase.openDeviceSettingsScreen() { + step("Open wallet details") { + onTopBar { moreButton.clickWithAssertion() } + } + step("Open 'Wallet settings' screen") { + onDetailsScreen { walletNameButton.performClick() } + } + step("Click on 'Device settings' button") { + onWalletSettingsScreen { deviceSettingsButton.clickWithAssertion() } + } } \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/tangem/scenarios/DeviceSetingsScenarios.kt b/app/src/androidTest/kotlin/com/tangem/scenarios/DeviceSetingsScenarios.kt new file mode 100644 index 0000000000..d58f6ba8e3 --- /dev/null +++ b/app/src/androidTest/kotlin/com/tangem/scenarios/DeviceSetingsScenarios.kt @@ -0,0 +1,21 @@ +package com.tangem.scenarios + +import com.tangem.common.BaseTestCase +import com.tangem.common.extensions.clickWithAssertion +import com.tangem.screens.onDeviceSettingsScreen +import io.qameta.allure.kotlin.Allure.step + +fun BaseTestCase.openResetCardScreen(withBackup: Boolean = false) { + step("Click on 'Scan card or ring' button") { + onDeviceSettingsScreen { scanCardOrRingButton.clickWithAssertion() } + } + step("Assert 'Reset to Factory Settings' button title is displayed") { + onDeviceSettingsScreen { resetToFactorySettingsButtonTitle.assertIsDisplayed() } + } + step("Assert 'Reset to Factory Settings' button subtitle is displayed") { + onDeviceSettingsScreen { resetToFactorySettingsButtonSubtitle(withBackup).assertIsDisplayed() } + } + step("Click on 'Reset to Factory Settings' button") { + onDeviceSettingsScreen { resetToFactorySettingsButtonTitle.performClick() } + } +} \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/tangem/scenarios/ResetCardScenarios.kt b/app/src/androidTest/kotlin/com/tangem/scenarios/ResetCardScenarios.kt new file mode 100644 index 0000000000..670cfbce63 --- /dev/null +++ b/app/src/androidTest/kotlin/com/tangem/scenarios/ResetCardScenarios.kt @@ -0,0 +1,80 @@ +package com.tangem.scenarios + +import com.tangem.common.BaseTestCase +import com.tangem.screens.onResetCardScreen +import io.qameta.allure.kotlin.Allure.step + +fun BaseTestCase.checkResetCardScreen(withBackup: Boolean = false) { + step("Assert title is displayed") { + onResetCardScreen { title.assertIsDisplayed() } + } + step("Assert 'Attention' image is displayed") { + onResetCardScreen { attentionImage.assertIsDisplayed() } + } + step("Assert 'Attention' subtitle is displayed") { + onResetCardScreen { subtitle.assertIsDisplayed() } + } + step("Assert description is displayed") { + onResetCardScreen { description.assertIsDisplayed() } + } + step("Assert 'Lost wallet' checkbox is displayed") { + onResetCardScreen { lostWalletAccessCheckBox.assertIsDisplayed() } + } + if (withBackup) { + step("Assert 'Lost password restore' checkbox is displayed") { + onResetCardScreen { lostPasswordRestoreCheckBox.assertIsDisplayed() } + } + } else { + step("Assert 'Lost password restore' checkbox doesn't exist") { + onResetCardScreen { lostPasswordRestoreCheckBox.assertDoesNotExist() } + } + } +} + +fun BaseTestCase.checkCheckBoxLogic(withBackup: Boolean = false) { + if (withBackup) { + step("Click on 'Lost wallet' checkbox") { + onResetCardScreen { lostWalletAccessCheckBox.performClick() } + } + step("Assert 'Lost wallet' checkbox is enabled") { + onResetCardScreen { lostWalletAccessCheckBox.assertIsEnabled() } + } + step("Assert 'Reset the card' button is disabled") { + onResetCardScreen { resetCardButton.assertIsNotEnabled() } + } + step("Click on 'Lost password restore' checkbox") { + onResetCardScreen { lostPasswordRestoreCheckBox.performClick() } + } + step("Assert 'Lost password restore' checkbox is enabled") { + onResetCardScreen { lostPasswordRestoreCheckBox.assertIsEnabled() } + } + step("Assert 'Reset the card' button is enabled") { + onResetCardScreen { resetCardButton.assertIsEnabled() } + } + step("Click on 'Lost password restore' checkbox") { + onResetCardScreen { lostPasswordRestoreCheckBox.performClick() } + } + step("Assert 'Reset the card' button is disabled") { + onResetCardScreen { resetCardButton.assertIsNotEnabled() } + } + step("Click on 'Lost wallet' checkbox") { + onResetCardScreen { lostWalletAccessCheckBox.performClick() } + } + step("Click on 'Lost password restore' checkbox") { + onResetCardScreen { lostPasswordRestoreCheckBox.performClick() } + } + step("Assert 'Reset the card' button is disabled") { + onResetCardScreen { resetCardButton.assertIsNotEnabled() } + } + } else { + step("Click on 'Lost wallet' checkbox") { + onResetCardScreen { lostWalletAccessCheckBox.performClick() } + } + step("Assert 'Lost wallet' checkbox is enabled") { + onResetCardScreen { lostWalletAccessCheckBox.assertIsEnabled() } + } + step("Assert 'Reset the card' button is enabled") { + onResetCardScreen { resetCardButton.assertIsEnabled() } + } + } +} diff --git a/app/src/androidTest/kotlin/com/tangem/screens/DeviceSettingsPageObject.kt b/app/src/androidTest/kotlin/com/tangem/screens/DeviceSettingsPageObject.kt new file mode 100644 index 0000000000..7822f4b34e --- /dev/null +++ b/app/src/androidTest/kotlin/com/tangem/screens/DeviceSettingsPageObject.kt @@ -0,0 +1,61 @@ +package com.tangem.screens + +import androidx.compose.ui.test.SemanticsMatcher +import androidx.compose.ui.test.SemanticsNodeInteractionsProvider +import com.tangem.common.BaseTestCase +import com.tangem.common.utils.LazyListItemNode +import com.tangem.core.ui.test.BaseButtonTestTags +import com.tangem.core.ui.test.DeviceSettingsScreenTestTags +import com.tangem.core.ui.utils.LazyListItemPositionSemantics +import com.tangem.wallet.R +import io.github.kakaocup.compose.node.element.ComposeScreen +import io.github.kakaocup.compose.node.element.ComposeScreen.Companion.onComposeScreen +import io.github.kakaocup.compose.node.element.KNode +import io.github.kakaocup.compose.node.element.lazylist.KLazyListNode +import io.github.kakaocup.kakao.common.utilities.getResourceString + +class DeviceSettingsPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) : + ComposeScreen(semanticsProvider = semanticsProvider) { + + private val lazyList = KLazyListNode( + semanticsProvider = semanticsProvider, + viewBuilderAction = { hasTestTag(DeviceSettingsScreenTestTags.LAZY_LIST) }, + itemTypeBuilder = { itemType(::LazyListItemNode) }, + positionMatcher = { position -> + SemanticsMatcher.expectValue( + LazyListItemPositionSemantics, + position + ) + } + ) + + val imageBlock: KNode = child { + hasTestTag(DeviceSettingsScreenTestTags.IMAGE_BLOCK) + useUnmergedTree = true + } + + val resetToFactorySettingsButtonTitle: KNode = child { + hasTestTag(DeviceSettingsScreenTestTags.ITEM_TITLE) + hasText(getResourceString(R.string.card_settings_reset_card_to_factory)) + useUnmergedTree = true + } + + val scanCardOrRingButton: KNode = child { + hasTestTag(BaseButtonTestTags.TEXT) + hasText(getResourceString(R.string.scan_card_settings_button)) + useUnmergedTree = true + } + + fun resetToFactorySettingsButtonSubtitle(withBackup: Boolean = false): KNode = child { + hasTestTag(DeviceSettingsScreenTestTags.ITEM_SUBTITLE) + useUnmergedTree = true + if (withBackup) { + hasText(getResourceString(R.string.reset_card_with_backup_to_factory_message)) + } else { + hasText(getResourceString(R.string.reset_card_without_backup_to_factory_message)) + } + } +} + +internal fun BaseTestCase.onDeviceSettingsScreen(function: DeviceSettingsPageObject.() -> Unit) = + onComposeScreen(composeTestRule, function) \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/tangem/screens/ResetCardPageObject.kt b/app/src/androidTest/kotlin/com/tangem/screens/ResetCardPageObject.kt new file mode 100644 index 0000000000..9bbb4eccce --- /dev/null +++ b/app/src/androidTest/kotlin/com/tangem/screens/ResetCardPageObject.kt @@ -0,0 +1,65 @@ +package com.tangem.screens + +import androidx.compose.ui.test.SemanticsNodeInteractionsProvider +import com.tangem.common.BaseTestCase +import com.tangem.core.ui.test.BaseButtonTestTags +import com.tangem.core.ui.test.ResetCardScreenTestTags +import com.tangem.wallet.R +import io.github.kakaocup.compose.node.element.ComposeScreen +import io.github.kakaocup.compose.node.element.ComposeScreen.Companion.onComposeScreen +import io.github.kakaocup.compose.node.element.KNode +import io.github.kakaocup.kakao.common.utilities.getResourceString +import androidx.compose.ui.test.hasTestTag as withTestTag +import androidx.compose.ui.test.hasText as withText + +class ResetCardPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) : + ComposeScreen(semanticsProvider = semanticsProvider) { + + val title: KNode = child { + hasTestTag(ResetCardScreenTestTags.TITLE) + hasText(getResourceString(R.string.card_settings_reset_card_to_factory)) + useUnmergedTree = true + } + + val attentionImage: KNode = child { + hasTestTag(ResetCardScreenTestTags.ATTENTION_IMAGE) + useUnmergedTree = true + } + + val subtitle: KNode = child { + hasTestTag(ResetCardScreenTestTags.SUBTITLE) + hasText(getResourceString(R.string.common_attention)) + useUnmergedTree = true + } + + val description: KNode = child { + hasTestTag(ResetCardScreenTestTags.DESCRIPTION) + useUnmergedTree = true + } + + val lostWalletAccessCheckBox: KNode = child { + hasTestTag(ResetCardScreenTestTags.CHECKBOX) + hasAnySibling( + withTestTag(ResetCardScreenTestTags.CHECKBOX_TEXT) and + withText(getResourceString(R.string.reset_card_to_factory_condition_1)) + ) + useUnmergedTree = true + } + + val lostPasswordRestoreCheckBox: KNode = child { + hasTestTag(ResetCardScreenTestTags.CHECKBOX) + hasAnySibling( + withTestTag(ResetCardScreenTestTags.CHECKBOX_TEXT) and + withText(getResourceString(R.string.reset_card_to_factory_condition_2)) + ) + useUnmergedTree = true + } + + val resetCardButton: KNode = child { + hasTestTag(BaseButtonTestTags.BUTTON) + hasText(getResourceString(R.string.reset_card_to_factory_button_title)) + } +} + +internal fun BaseTestCase.onResetCardScreen(function: ResetCardPageObject.() -> Unit) = + onComposeScreen(composeTestRule, function) \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/tangem/screens/WalletSettingsPageObject.kt b/app/src/androidTest/kotlin/com/tangem/screens/WalletSettingsPageObject.kt index 6a2a606ef5..e8b554846b 100644 --- a/app/src/androidTest/kotlin/com/tangem/screens/WalletSettingsPageObject.kt +++ b/app/src/androidTest/kotlin/com/tangem/screens/WalletSettingsPageObject.kt @@ -21,7 +21,7 @@ class WalletSettingsPageObject(semanticsProvider: SemanticsNodeInteractionsProvi val linkMoreCardsButton: KNode = walletSettingsItem.child { hasText(getResourceString(R.string.details_row_title_create_backup)) } - val cardSettingsButton: KNode = walletSettingsItem.child { + val deviceSettingsButton: KNode = walletSettingsItem.child { hasText(getResourceString(R.string.card_settings_title)) } val referralProgramButton: KNode = walletSettingsItem.child { diff --git a/app/src/androidTest/kotlin/com/tangem/tests/DetailsTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/DetailsTest.kt index b60639cf4a..49fe556eba 100644 --- a/app/src/androidTest/kotlin/com/tangem/tests/DetailsTest.kt +++ b/app/src/androidTest/kotlin/com/tangem/tests/DetailsTest.kt @@ -55,7 +55,7 @@ class DetailsTest : BaseTestCase() { linkMoreCardsButton.assertIsDisplayed() } step("Assert 'Card Settings' button is visible") { - cardSettingsButton.assertIsDisplayed() + deviceSettingsButton.assertIsDisplayed() } step("Assert 'Referral program' button is visible") { referralProgramButton.assertIsDisplayed() @@ -105,7 +105,7 @@ class DetailsTest : BaseTestCase() { linkMoreCardsButton.assertIsNotDisplayed() } step("Assert 'Card Settings' button is visible") { - cardSettingsButton.assertIsDisplayed() + deviceSettingsButton.assertIsDisplayed() } step("Assert 'Referral program' button is visible") { referralProgramButton.assertIsDisplayed() @@ -152,7 +152,7 @@ class DetailsTest : BaseTestCase() { } onWalletSettingsScreen { step("Assert 'Card Settings' button is visible") { - cardSettingsButton.assertIsDisplayed() + deviceSettingsButton.assertIsDisplayed() } step("Assert 'Referral program' button does not exist") { referralProgramButton.assertIsNotDisplayed() diff --git a/app/src/androidTest/kotlin/com/tangem/tests/ResetCardTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/ResetCardTest.kt new file mode 100644 index 0000000000..d159dc0eda --- /dev/null +++ b/app/src/androidTest/kotlin/com/tangem/tests/ResetCardTest.kt @@ -0,0 +1,85 @@ +package com.tangem.tests + +import com.tangem.common.BaseTestCase +import com.tangem.domain.models.scan.ProductType +import com.tangem.scenarios.* +import com.tangem.tap.domain.sdk.mocks.content.BackupWalletMockContent +import dagger.hilt.android.testing.HiltAndroidTest +import io.qameta.allure.kotlin.AllureId +import io.qameta.allure.kotlin.junit4.DisplayName +import org.junit.Ignore +import org.junit.Test + +@HiltAndroidTest +class ResetCardTest : BaseTestCase() { + + @AllureId("3988") + @DisplayName("Reset card: reset Wallet 1.0 card without backup") + @Test + fun resetWallet1CardWithoutBackupTest() { + setupHooks().run { + step("Open 'Main Screen'") { + openMainScreen() + } + step("Open 'Device settings' screen") { + openDeviceSettingsScreen() + } + step("Open 'Reset card' screen") { + openResetCardScreen() + } + step("Check 'Reset card' screen") { + checkResetCardScreen() + } + step("Check checkbox logic") { + checkCheckBoxLogic() + } + } + } + + @AllureId("3987") + @DisplayName("Reset card: reset Wallet 1.0 card with backup") + @Test + fun resetWallet1CardWithBackupTest() { + setupHooks().run { + step("Open 'Main Screen'") { + openMainScreen(mockContent = BackupWalletMockContent) + } + step("Open 'Device settings' screen") { + openDeviceSettingsScreen() + } + step("Open 'Reset card' screen") { + openResetCardScreen(withBackup = true) + } + step("Check 'Reset card' screen") { + checkResetCardScreen(withBackup = true) + } + step("Check checkbox logic") { + checkCheckBoxLogic(withBackup = true) + } + } + } + + @AllureId("3974") + @DisplayName("Reset card: reset Wallet 2.0 card with backup") + @Ignore("toDo [REDACTED_TASK_KEY]: On CI Already used wallet dialog doesn't displayed") + @Test + fun resetWallet2CardWithBackupTest() { + setupHooks().run { + step("Open 'Main Screen'") { + openMainScreen(productType = ProductType.Wallet2, alreadyActivatedDialogIsShown = true) + } + step("Open 'Device settings' screen") { + openDeviceSettingsScreen() + } + step("Open 'Reset card' screen") { + openResetCardScreen(withBackup = true) + } + step("Check 'Reset card' screen") { + checkResetCardScreen(withBackup = true) + } + step("Check checkbox logic") { + checkCheckBoxLogic(withBackup = true) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/sdk/mocks/content/BackupWalletMockContent.kt b/app/src/main/java/com/tangem/tap/domain/sdk/mocks/content/BackupWalletMockContent.kt new file mode 100644 index 0000000000..c2c8d9ba23 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/domain/sdk/mocks/content/BackupWalletMockContent.kt @@ -0,0 +1,270 @@ +package com.tangem.tap.domain.sdk.mocks.content + +import com.tangem.common.SuccessResponse +import com.tangem.common.card.* +import com.tangem.common.extensions.ByteArrayKey +import com.tangem.crypto.hdWallet.DerivationPath +import com.tangem.crypto.hdWallet.bip32.ExtendedPublicKey +import com.tangem.domain.models.scan.CardDTO +import com.tangem.domain.models.scan.ProductType +import com.tangem.domain.models.scan.ScanResponse +import com.tangem.operations.attestation.Attestation +import com.tangem.operations.backup.PrimaryCard +import com.tangem.operations.derivation.DerivationTaskResponse +import com.tangem.operations.derivation.ExtendedPublicKeysMap +import com.tangem.operations.wallet.CreateWalletResponse +import com.tangem.sdk.api.CreateProductWalletTaskResponse +import com.tangem.tap.domain.sdk.mocks.MockContent +import java.util.Date + +object BackupWalletMockContent : MockContent { + + private val primaryCard = PrimaryCard( + cardId = "AC05000000086747", + batchId = "AC05", + cardPublicKey = byteArrayOf(2, -120, -3, -32, -122, -127, -120, -104, 59, 72, 76, 114, 94, 75, -37, -55, 55, 99, 66, 123, 85, -87, 80, 106, 105, -116, 87, -83, -12, 70, 108, -68, -39), + linkingKey = byteArrayOf( + 2, 121, 98, 127, -70, 14, 5, -23, -76, 115, -30, -26, 111, 17, 110, 34, -100, -121, + -57, -123, 74, 3, -91, 56, -20, 56, 50, -40, -101, 96, 82, 70, -91, + ), + existingWalletsCount = 3, isHDWalletAllowed = true, + issuer = Card.Issuer( + name = "TANGEM AG", + publicKey = byteArrayOf(3, 86, -25, -61, 55, 99, 41, -33, -82, 115, -120, -33, 22, -107, 103, 3, -122, 16, 60, -110, 72, 106, -121, 100, 79, -87, -27, 18, -55, -49, 78, -110, -2), + ), + manufacturer = Card.Manufacturer( + name = "TANGEM", + manufactureDate = Date(1743759687), + signature = byteArrayOf(), + ), + walletCurves = listOf(EllipticCurve.Secp256k1, EllipticCurve.Ed25519, EllipticCurve.Bls12381G2Aug), + firmwareVersion = FirmwareVersion( + major = 4, + minor = 52, + patch = 0, + type = FirmwareVersion.FirmwareType.Release, + ), + isKeysImportAllowed = false, + certificate = null, + ) + + override val cardDto = CardDTO( + cardId = "AC05000000086747", + batchId = "AC05", + cardPublicKey = byteArrayOf(2, -120, -3, -32, -122, -127, -120, -104, 59, 72, 76, 114, 94, 75, -37, -55, 55, 99, 66, 123, 85, -87, 80, 106, 105, -116, 87, -83, -12, 70, 108, -68, -39), + firmwareVersion = CardDTO.FirmwareVersion( + major = 4, + minor = 52, + patch = 0, + type = FirmwareVersion.FirmwareType.Release, + ), + manufacturer = CardDTO.Manufacturer( + name = "TANGEM", + manufactureDate = Date(1649635200000), + signature = byteArrayOf(-20, 98, -101, 94, -23, 73, 122, -21, 74, 76, 79, -55, -102, -62, -30, 44, -38, 118, 75, 121, -36, 118, -62, 60, -38, -63, 33, -14, -98, -69, 112, 22, 48, -43, 47, 65, -61, -56, 38, -94, -45, 44, 95, -22, 6, -31, -40, -25, 42, 38, 94, -99, 71, 98, -33, 27, -102, 30, 52, -7, 51, -27, 84, 66), + ), + issuer = CardDTO.Issuer( + name = "TANGEM AG", + publicKey = byteArrayOf(3, 86, -25, -61, 55, 99, 41, -33, -82, 115, -120, -33, 22, -107, 103, 3, -122, 16, 60, -110, 72, 106, -121, 100, 79, -87, -27, 18, -55, -49, 78, -110, -2), + ), + settings = CardDTO.Settings( + securityDelay = 15000, + maxWalletsCount = 20, + isSettingAccessCodeAllowed = false, + isSettingPasscodeAllowed = false, + isResettingUserCodesAllowed = true, + isLinkedTerminalEnabled = true, + isBackupAllowed = true, + supportedEncryptionModes = listOf(EncryptionMode.Strong, EncryptionMode.Fast, EncryptionMode.None), + isFilesAllowed = true, + isHDWalletAllowed = true, + isKeysImportAllowed = false, + ), + userSettings = CardDTO.UserSettings(isUserCodeRecoveryAllowed = true), + linkedTerminalStatus = CardDTO.LinkedTerminalStatus.None, + isAccessCodeSet = false, + isPasscodeSet = false, + supportedCurves = listOf( + EllipticCurve.Secp256k1, + EllipticCurve.Ed25519, + EllipticCurve.Secp256r1, + EllipticCurve.Bls12381G2, + EllipticCurve.Bls12381G2Aug, + EllipticCurve.Bls12381G2Pop, + EllipticCurve.Bip0340, + ), + wallets = listOf( + CardDTO.Wallet( + publicKey = byteArrayOf(2, -109, 28, -27, -124, -58, -97, -61, 43, -84, 90, -9, -5, 4, 90, 17, 112, -125, -108, 44, 19, -79, -60, -23, 34, -20, -20, 61, 84, 113, 120, -90, -5), + chainCode = byteArrayOf(80, 13, -8, -108, -35, 116, -92, 125, -65, -28, 85, 72, -113, 59, 83, 13, 5, -83, -102, 123, 124, -22, 94, 108, -71, 95, 65, -2, 38, 38, -108, 14), + curve = EllipticCurve.Secp256k1, + settings = CardWallet.Settings(isPermanent = false), + totalSignedHashes = 0, + remainingSignatures = null, + index = 0, + hasBackup = true, + derivedKeys = mapOf( + DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( + publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52), + chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70), + ), + DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( + publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67), + chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109), + ), + DerivationPath("m/44'/1'/0'/0/0") to ExtendedPublicKey( + publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62), + chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41), + ), + DerivationPath("m/44'/195'/0'/0/0") to ExtendedPublicKey( + publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62), + chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41), + ), + ), + extendedPublicKey = ExtendedPublicKey( + publicKey = byteArrayOf(2, -109, 28, -27, -124, -58, -97, -61, 43, -84, 90, -9, -5, 4, 90, 17, 112, -125, -108, 44, 19, -79, -60, -23, 34, -20, -20, 61, 84, 113, 120, -90, -5), + chainCode = byteArrayOf(80, 13, -8, -108, -35, 116, -92, 125, -65, -28, 85, 72, -113, 59, 83, 13, 5, -83, -102, 123, 124, -22, 94, 108, -71, 95, 65, -2, 38, 38, -108, 14), + ), + isImported = false, + ), + CardDTO.Wallet( + publicKey = byteArrayOf(-65, -53, -62, -12, -57, -32, -38, -9, -128, -52, -83, -61, 73, 39, 41, 15, -74, -97, 38, 52, -101, 63, 74, -56, -20, 15, 57, -127, 114, -93, -17, -109), + chainCode = byteArrayOf(-81, 15, 125, 28, -115, -22, 87, 81, 87, -123, -25, -74, 86, 2, 1, 110, -115, 65, -110, 63, -64, 83, -93, -97, -104, 123, 12, -26, 94, 27, 84, -6), + curve = EllipticCurve.Ed25519, + settings = CardWallet.Settings(isPermanent = false), + totalSignedHashes = 0, + remainingSignatures = null, + index = 1, + hasBackup = true, + derivedKeys = emptyMap(), + extendedPublicKey = ExtendedPublicKey( + publicKey = byteArrayOf(-65, -53, -62, -12, -57, -32, -38, -9, -128, -52, -83, -61, 73, 39, 41, 15, -74, -97, 38, 52, -101, 63, 74, -56, -20, 15, 57, -127, 114, -93, -17, -109), + chainCode = byteArrayOf(-81, 15, 125, 28, -115, -22, 87, 81, 87, -123, -25, -74, 86, 2, 1, 110, -115, 65, -110, 63, -64, 83, -93, -97, -104, 123, 12, -26, 94, 27, 84, -6), + ), + isImported = false, + ), + ), + attestation = Attestation( + cardKeyAttestation = Attestation.Status.Verified, + walletKeysAttestation = Attestation.Status.Skipped, + firmwareAttestation = Attestation.Status.Skipped, + cardUniquenessAttestation = Attestation.Status.Skipped, + ), + backupStatus = CardDTO.BackupStatus.Active(1), + ) + + override val scanResponse = ScanResponse( + card = cardDto, + productType = ProductType.Wallet, + walletData = null, + secondTwinPublicKey = null, + derivedKeys = emptyMap(), + primaryCard = null, + ) + + override val derivationTaskResponse = DerivationTaskResponse( + entries = mapOf( + ByteArrayKey( + byteArrayOf(2, -109, 28, -27, -124, -58, -97, -61, 43, -84, 90, -9, -5, 4, 90, 17, 112, -125, -108, 44, 19, -79, -60, -23, 34, -20, -20, 61, 84, 113, 120, -90, -5), + ) + to + ExtendedPublicKeysMap( + mapOf( + DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc + publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52), + chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70), + depth = 0, + parentFingerprint = byteArrayOf(0, 0, 0, 0), + childNumber = 0, + ), + DerivationPath("m/84'/0'/0'/0/0") to ExtendedPublicKey( // btc + publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52), + chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70), + depth = 0, + parentFingerprint = byteArrayOf(0, 0, 0, 0), + childNumber = 0, + ), + DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth + publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67), + chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109), + depth = 0, + parentFingerprint = byteArrayOf(0, 0, 0, 0), + childNumber = 0, + ), + DerivationPath("m/44'/145'/0'/0/0") to ExtendedPublicKey( // bch + publicKey = byteArrayOf(2, 38, -6, 92, -37, -91, -59, -108, -18, -119, -55, 41, 38, -33, 44, 59, 24, -79, -14, -38, -10, -123, 106, 56, 39, 8, 112, 29, -41, 99, 70, -104, -121), + chainCode = byteArrayOf(105, -21, -61, -50, 68, -89, 119, 53, -96, -40, 119, 77, -122, 121, 16, 40, -50, -48, -105, -101, -74, -7, -94, -59, -90, 96, 59, 99, 43, -91, 115, -29), + depth = 0, + parentFingerprint = byteArrayOf(0, 0, 0, 0), + childNumber = 0, + ), + DerivationPath("m/44'/3'/0'/0/0") to ExtendedPublicKey( // doge + publicKey = byteArrayOf(3, -25, -24, -97, -124, 24, -89, 44, 75, 123, 92, -86, -73, -93, 25, -90, -89, -95, 88, 3, 107, 37, -1, -85, -32, -57, -123, -41, 108, -9, -96, 77, -124), + chainCode = byteArrayOf(119, 3, 41, 112, 71, 54, 72, 30, 39, 25, 25, -104, 92, 46, -109, 63, 93, 67, 43, -102, -87, 39, -95, 106, 45, 67, 109, -29, -35, 10, -107, 104), + depth = 0, + parentFingerprint = byteArrayOf(0, 0, 0, 0), + childNumber = 0, + ), + DerivationPath("m/44'/195'/0'/0/0") to ExtendedPublicKey( + publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62), + chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41), + depth = 0, + parentFingerprint = byteArrayOf(0, 0, 0, 0), + childNumber = 0, + ), + ), + ), + ), + ) + + override val extendedPublicKey = ExtendedPublicKey( + publicKey = byteArrayOf(3, 2, 95, 53, 40, -87, -60, 11, -8, -47, 41, 37, 100, 15, -69, 1, -122, 127, -20, -81, -32, -20, -24, 5, -28, 113, 106, -90, -59, -30, -27, -110, -110), + chainCode = byteArrayOf(-95, -87, -95, -25, 27, 96, -57, -92, -69, -106, -45, 10, 85, 4, -92, -68, 49, -24, -28, -50, -49, -77, -20, 118, -50, -27, 104, -93, 115, -50, -46, -34), + depth = 0, + parentFingerprint = byteArrayOf(0, 0, 0, 0), + childNumber = 0, + ) + + override val successResponse = SuccessResponse(cardId = "AC05000000086747") + + override val createProductWalletTaskResponse = CreateProductWalletTaskResponse( + card = cardDto, + derivedKeys = mapOf( + ByteArrayKey( + byteArrayOf(2, -109, 28, -27, -124, -58, -97, -61, 43, -84, 90, -9, -5, 4, 90, 17, 112, -125, -108, 44, 19, -79, -60, -23, 34, -20, -20, 61, 84, 113, 120, -90, -5), + ) + to + ExtendedPublicKeysMap( + mapOf( + DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc + publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52), + chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70), + depth = 0, + parentFingerprint = byteArrayOf(0, 0, 0, 0), + childNumber = 0, + ), + DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth + publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67), + chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109), + depth = 0, + parentFingerprint = byteArrayOf(0, 0, 0, 0), + childNumber = 0, + ), + ), + ), + ), + primaryCard = primaryCard, + ) + + override val importWalletResponse: CreateProductWalletTaskResponse + get() = error("Available only for Wallet 2") + + override val createFirstTwinResponse: CreateWalletResponse + get() = error("Available only for Twin") + + override val createSecondTwinResponse: CreateWalletResponse + get() = error("Available only for Twin") + + override val finalizeTwinResponse: ScanResponse + get() = error("Available only for Twin") +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsScreen.kt index 44fdad55f0..eb76dc0b7a 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsScreen.kt @@ -13,11 +13,13 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import com.tangem.core.ui.extensions.stringResourceSafe import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.core.ui.test.DeviceSettingsScreenTestTags import com.tangem.tap.features.details.ui.common.DetailsMainButton import com.tangem.tap.features.details.ui.common.SettingsScreensScaffold import com.tangem.wallet.R @@ -49,7 +51,8 @@ private fun CardSettingsReadCard(onScanCardClick: () -> Unit) { Box( modifier = Modifier .fillMaxWidth() - .padding(bottom = TangemTheme.dimens.spacing40), + .padding(bottom = TangemTheme.dimens.spacing40) + .testTag(DeviceSettingsScreenTestTags.IMAGE_BLOCK), ) { Image( modifier = Modifier @@ -116,7 +119,9 @@ private fun CardSettings(state: CardSettingsScreenState) { if (state.cardDetails == null) return LazyColumn( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .fillMaxWidth() + .testTag(DeviceSettingsScreenTestTags.LAZY_LIST), ) { items(state.cardDetails) { val paddingBottom = when (it) { @@ -164,12 +169,14 @@ private fun CardSettings(state: CardSettingsScreenState) { text = it.titleRes.resolveReference(), color = titleColor, style = TangemTheme.typography.subtitle1, + modifier = Modifier.testTag(DeviceSettingsScreenTestTags.ITEM_TITLE), ) Spacer(modifier = Modifier.size(TangemTheme.dimens.size4)) Text( text = it.subtitle.resolveReference(), color = subtitleColor, style = TangemTheme.typography.body2, + modifier = Modifier.testTag(DeviceSettingsScreenTestTags.ITEM_SUBTITLE), ) } } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt index dd3093deb9..e81602a4d2 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/resetcard/ResetCardScreen.kt @@ -9,12 +9,14 @@ import androidx.compose.material3.IconToggleButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import com.tangem.core.ui.components.* import com.tangem.core.ui.extensions.stringResourceSafe import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.core.ui.test.ResetCardScreenTestTags import com.tangem.tap.features.details.ui.cardsettings.TextReference import com.tangem.tap.features.details.ui.cardsettings.resolveReference import com.tangem.tap.features.details.ui.common.DetailsMainButton @@ -74,6 +76,7 @@ private fun Title() { text = stringResourceSafe(id = R.string.card_settings_reset_card_to_factory), style = TangemTheme.typography.h1, color = TangemTheme.colors.text.primary1, + modifier = Modifier.testTag(ResetCardScreenTestTags.TITLE), ) } @@ -82,7 +85,9 @@ private fun AlertImage() { Image( painter = painterResource(id = R.drawable.img_alert_80), contentDescription = null, - modifier = Modifier.size(TangemTheme.dimens.size80), + modifier = Modifier + .size(TangemTheme.dimens.size80) + .testTag(ResetCardScreenTestTags.ATTENTION_IMAGE), ) } @@ -92,6 +97,7 @@ private fun Subtitle() { text = stringResourceSafe(id = R.string.common_attention), style = TangemTheme.typography.h3, color = TangemTheme.colors.text.primary1, + modifier = Modifier.testTag(ResetCardScreenTestTags.SUBTITLE), ) } @@ -101,6 +107,7 @@ private fun Description(text: TextReference) { text = text.resolveReference(), style = TangemTheme.typography.body1, color = TangemTheme.colors.text.secondary, + modifier = Modifier.testTag(ResetCardScreenTestTags.DESCRIPTION), ) } @@ -135,7 +142,11 @@ private fun ConditionCheckBox(checkedState: Boolean, onCheckedChange: (Boolean) .padding(vertical = TangemTheme.dimens.size16), horizontalArrangement = Arrangement.spacedBy(space = TangemTheme.dimens.spacing16), ) { - IconToggleButton(checked = checkedState, onCheckedChange = onCheckedChange) { + IconToggleButton( + checked = checkedState, + onCheckedChange = onCheckedChange, + modifier = Modifier.testTag(ResetCardScreenTestTags.CHECKBOX), + ) { AnimatedContent(targetState = checkedState, label = "Update checked state") { checked -> Icon( painter = painterResource( @@ -159,6 +170,7 @@ private fun ConditionCheckBox(checkedState: Boolean, onCheckedChange: (Boolean) text = description.resolveReference(), style = TangemTheme.typography.body2, color = TangemTheme.colors.text.secondary, + modifier = Modifier.testTag(ResetCardScreenTestTags.CHECKBOX_TEXT), ) } } diff --git a/core/ui/src/main/java/com/tangem/core/ui/test/DeviceSettingsScreenTestTags.kt b/core/ui/src/main/java/com/tangem/core/ui/test/DeviceSettingsScreenTestTags.kt new file mode 100644 index 0000000000..a995632d4f --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/test/DeviceSettingsScreenTestTags.kt @@ -0,0 +1,8 @@ +package com.tangem.core.ui.test + +object DeviceSettingsScreenTestTags { + const val LAZY_LIST = "DEVICE_SETTINGS_SCREEN_LAZY_LIST" + const val IMAGE_BLOCK = "DEVICE_SETTINGS_SCREEN_IMAGE_BLOCK" + const val ITEM_TITLE = "DEVICE_SETTINGS_SCREEN_ITEM_TITLE" + const val ITEM_SUBTITLE = "DEVICE_SETTINGS_SCREEN_ITEM_SUBTITLE" +} \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/test/ResetCardScreenTestTags.kt b/core/ui/src/main/java/com/tangem/core/ui/test/ResetCardScreenTestTags.kt new file mode 100644 index 0000000000..0f0409aba4 --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/test/ResetCardScreenTestTags.kt @@ -0,0 +1,10 @@ +package com.tangem.core.ui.test + +object ResetCardScreenTestTags { + const val TITLE = "RESET_CARD_SCREEN_TITLE" + const val ATTENTION_IMAGE = "RESET_CARD_SCREEN_ATTENTION_IMAGE" + const val SUBTITLE = "RESET_CARD_SCREEN_SUBTITLE" + const val DESCRIPTION = "RESET_CARD_SCREEN_DESCRIPTION" + const val CHECKBOX = "RESET_CARD_SCREEN_CHECKBOX" + const val CHECKBOX_TEXT = "RESET_CARD_SCREEN_CHECKBOX_TEXT" +} \ No newline at end of file