From 53c0546b5c90284cb228d80cc9b31ba189816b9f Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 1 Jun 2026 09:47:32 +0200 Subject: [PATCH] Updated on 2026-08-14 --- .claude/skills/write-ui-test/SKILL.md | 7 +++ .../screens/DeviceSettingsPageObject.kt | 4 -- .../tangem/screens/SecurityModePageObject.kt | 19 ------- .../com/tangem/tests/SecurityModeTest.kt | 55 ------------------- .../ui/cardsettings/CardSettingsScreen.kt | 9 +-- .../ui/securitymode/SecurityModeScreen.kt | 5 +- .../ui/test/DeviceSettingsScreenTestTags.kt | 1 - .../ui/test/SecurityModeScreenTestTags.kt | 5 -- 8 files changed, 9 insertions(+), 96 deletions(-) delete mode 100644 app/src/androidTest/kotlin/com/tangem/screens/SecurityModePageObject.kt delete mode 100644 app/src/androidTest/kotlin/com/tangem/tests/SecurityModeTest.kt delete mode 100644 core/ui/src/main/java/com/tangem/core/ui/test/SecurityModeScreenTestTags.kt diff --git a/.claude/skills/write-ui-test/SKILL.md b/.claude/skills/write-ui-test/SKILL.md index a0322d94b3..11686c0e7c 100644 --- a/.claude/skills/write-ui-test/SKILL.md +++ b/.claude/skills/write-ui-test/SKILL.md @@ -93,6 +93,13 @@ Scenario files orchestrate flows; they must not define page objects or duplicate `com.tangem.core.res.R` or `com.tangem.core.ui.R`. The Detekt rule `UnsafeStringResourceUsage` enforces this for production code; reviewers extend it to test code informally. +### Allure IDs + +- **Every test method gets its own unique `@AllureId`.** Never reuse the same id across two test methods — + not even for two variants of one manual case. If a manual case is split into multiple automated tests + (e.g. a positive and a negative variant), each test must be linked to its own distinct Allure case/id. + (Note: iOS sometimes shares one id across methods — do NOT mirror that here.) + ### Assertions - **Never** use Kotlin's built-in `assert(...)` — Android instrumentation runs don't enable JVM diff --git a/app/src/androidTest/kotlin/com/tangem/screens/DeviceSettingsPageObject.kt b/app/src/androidTest/kotlin/com/tangem/screens/DeviceSettingsPageObject.kt index b59290c76e..7822f4b34e 100644 --- a/app/src/androidTest/kotlin/com/tangem/screens/DeviceSettingsPageObject.kt +++ b/app/src/androidTest/kotlin/com/tangem/screens/DeviceSettingsPageObject.kt @@ -46,10 +46,6 @@ class DeviceSettingsPageObject(semanticsProvider: SemanticsNodeInteractionsProvi useUnmergedTree = true } - val securityModeRow: KNode = child { - hasTestTag(DeviceSettingsScreenTestTags.SECURITY_MODE_ROW) - } - fun resetToFactorySettingsButtonSubtitle(withBackup: Boolean = false): KNode = child { hasTestTag(DeviceSettingsScreenTestTags.ITEM_SUBTITLE) useUnmergedTree = true diff --git a/app/src/androidTest/kotlin/com/tangem/screens/SecurityModePageObject.kt b/app/src/androidTest/kotlin/com/tangem/screens/SecurityModePageObject.kt deleted file mode 100644 index 5d9e137e3d..0000000000 --- a/app/src/androidTest/kotlin/com/tangem/screens/SecurityModePageObject.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.tangem.screens - -import androidx.compose.ui.test.SemanticsNodeInteractionsProvider -import com.tangem.common.BaseTestCase -import com.tangem.core.ui.test.SecurityModeScreenTestTags -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 - -class SecurityModePageObject(semanticsProvider: SemanticsNodeInteractionsProvider) : - ComposeScreen(semanticsProvider = semanticsProvider) { - - val screenContainer: KNode = child { - hasTestTag(SecurityModeScreenTestTags.SCREEN_CONTAINER) - } -} - -internal fun BaseTestCase.onSecurityModeScreen(function: SecurityModePageObject.() -> Unit) = - onComposeScreen(composeTestRule, function) \ No newline at end of file diff --git a/app/src/androidTest/kotlin/com/tangem/tests/SecurityModeTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/SecurityModeTest.kt deleted file mode 100644 index ac7d5fe013..0000000000 --- a/app/src/androidTest/kotlin/com/tangem/tests/SecurityModeTest.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.tangem.tests - -import com.tangem.common.BaseTestCase -import com.tangem.common.extensions.clickWithAssertion -import com.tangem.domain.models.scan.ProductType -import com.tangem.scenarios.openDeviceSettingsScreen -import com.tangem.scenarios.openMainScreen -import com.tangem.screens.* -import dagger.hilt.android.testing.HiltAndroidTest -import io.qameta.allure.kotlin.AllureId -import io.qameta.allure.kotlin.junit4.DisplayName -import org.junit.Test - -@HiltAndroidTest -class SecurityModeTest : BaseTestCase() { - - @AllureId("2267") - @DisplayName("Security Mode: Twin card opens the section") - @Test - fun twinSecurityModeOpensTest() = - setupHooks().run { - step("Open 'Main Screen'") { - openMainScreen(productType = ProductType.Twins, isTwinsCard = true) - } - openDeviceSettingsScreen() - step("Click on 'Scan card or ring' button") { - onDeviceSettingsScreen { scanCardOrRingButton.clickWithAssertion() } - } - step("Assert 'Security Mode' row is enabled") { - onDeviceSettingsScreen { securityModeRow.assertIsEnabled() } - } - step("Click on 'Security Mode' row") { - onDeviceSettingsScreen { securityModeRow.clickWithAssertion() } - } - step("Assert 'Security Mode' screen is displayed") { - onSecurityModeScreen { screenContainer.assertIsDisplayed() } - } - } - - @DisplayName("Security Mode: other cards cannot open the section") - @Test - fun walletSecurityModeDisabledTest() = - setupHooks().run { - step("Open 'Main Screen'") { - openMainScreen() - } - openDeviceSettingsScreen() - step("Click on 'Scan card or ring' button") { - onDeviceSettingsScreen { scanCardOrRingButton.clickWithAssertion() } - } - step("Assert 'Security Mode' row is not clickable") { - onDeviceSettingsScreen { securityModeRow.assertIsNotEnabled() } - } - } -} \ 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 7ab076f209..7cffbf079d 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 @@ -125,7 +125,7 @@ private fun ScanCardContent(onScanCardClick: () -> Unit) { } } -@Suppress("ComplexMethod", "LongMethod") +@Suppress("ComplexMethod") @Composable private fun CardSettings(state: CardSettingsScreenState) { if (state.cardDetails == null) return @@ -156,13 +156,6 @@ private fun CardSettings(state: CardSettingsScreenState) { Column( modifier = Modifier .fillMaxWidth() - .then( - if (cardInfo is CardInfo.SecurityMode) { - Modifier.testTag(DeviceSettingsScreenTestTags.SECURITY_MODE_ROW) - } else { - Modifier - }, - ) .clickable( enabled = cardInfo.isClickable, onClick = { state.onElementClick(cardInfo) }, diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeScreen.kt index c678c825da..981cd1c76a 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/securitymode/SecurityModeScreen.kt @@ -5,11 +5,9 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.testTag import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.tangem.core.ui.extensions.stringResourceSafe -import com.tangem.core.ui.test.SecurityModeScreenTestTags import com.tangem.tap.features.details.redux.SecurityOption import com.tangem.tap.features.details.ui.common.DetailsMainButton import com.tangem.tap.features.details.ui.common.DetailsRadioButtonElement @@ -37,8 +35,7 @@ private fun SecurityModeOptions(state: SecurityModeScreenState) { modifier = Modifier .fillMaxSize() .verticalScroll(rememberScrollState()) - .padding(bottom = 28.dp) - .testTag(SecurityModeScreenTestTags.SCREEN_CONTAINER), + .padding(bottom = 28.dp), verticalArrangement = Arrangement.SpaceBetween, ) { ScreenTitle(titleRes = R.string.card_settings_security_mode, Modifier.padding(bottom = 36.dp)) 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 index a891c43e85..a995632d4f 100644 --- 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 @@ -5,5 +5,4 @@ object DeviceSettingsScreenTestTags { 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" - const val SECURITY_MODE_ROW = "DEVICE_SETTINGS_SCREEN_SECURITY_MODE_ROW" } \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/test/SecurityModeScreenTestTags.kt b/core/ui/src/main/java/com/tangem/core/ui/test/SecurityModeScreenTestTags.kt deleted file mode 100644 index 6c4c3753b6..0000000000 --- a/core/ui/src/main/java/com/tangem/core/ui/test/SecurityModeScreenTestTags.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.tangem.core.ui.test - -object SecurityModeScreenTestTags { - const val SCREEN_CONTAINER = "SECURITY_MODE_SCREEN_CONTAINER" -} \ No newline at end of file