From e9fac0e50eb8816cc24e00dffa94d7baf2ca18c8 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 27 Mar 2025 21:21:17 +0400 Subject: [PATCH] Updated on 2026-08-14 --- app/build.gradle.kts | 3 +- .../card/DefaultDerivationsRepositoryTest.kt | 18 ++++++----- .../card/MissedDerivationsFinderTest.kt | 28 +++++++++-------- .../BiometricUserWalletsListManagerTest.kt | 4 +-- common/test/.gitignore | 1 + common/test/build.gradle.kts | 25 ++++++++++++++++ .../domain/card/MockScanResponseFactory.kt | 4 +-- .../domain/token/MockCryptoCurrencyFactory.kt | 30 ++++++++++++------- .../tangem/common/test/utils/CoroutineExt.kt | 20 +++++++++++++ settings.gradle.kts | 7 +++-- 10 files changed, 101 insertions(+), 39 deletions(-) create mode 100644 common/test/.gitignore create mode 100644 common/test/build.gradle.kts rename app/src/test/kotlin/com/tangem/tap/domain/card/ScanResponseMockFactory.kt => common/test/src/main/java/com/tangem/common/test/domain/card/MockScanResponseFactory.kt (98%) rename app/src/test/kotlin/com/tangem/tap/domain/card/CryptoCurrenciesMocks.kt => common/test/src/main/java/com/tangem/common/test/domain/token/MockCryptoCurrencyFactory.kt (78%) create mode 100644 common/test/src/main/java/com/tangem/common/test/utils/CoroutineExt.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3312184dff..76ad6c75ba 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,5 +1,5 @@ -import java.util.Properties import com.tangem.plugin.configuration.configurations.extension.kaptForObfuscatingVariants +import java.util.Properties plugins { alias(deps.plugins.android.application) @@ -291,6 +291,7 @@ dependencies { kaptForObfuscatingVariants(deps.retrofit.response.type.keeper) /** Testing libraries */ + testImplementation(projects.common.test) testImplementation(deps.test.coroutine) testImplementation(deps.test.junit) testImplementation(deps.test.mockk) diff --git a/app/src/test/kotlin/com/tangem/tap/domain/card/DefaultDerivationsRepositoryTest.kt b/app/src/test/kotlin/com/tangem/tap/domain/card/DefaultDerivationsRepositoryTest.kt index 095156e1c2..c66581f06d 100644 --- a/app/src/test/kotlin/com/tangem/tap/domain/card/DefaultDerivationsRepositoryTest.kt +++ b/app/src/test/kotlin/com/tangem/tap/domain/card/DefaultDerivationsRepositoryTest.kt @@ -4,6 +4,8 @@ import android.annotation.SuppressLint import com.google.common.truth.Truth import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.common.CompletionResult +import com.tangem.common.test.domain.card.MockScanResponseFactory +import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.card.ScanCardException import com.tangem.domain.common.configs.GenericCardConfig @@ -40,7 +42,7 @@ internal class DefaultDerivationsRepositoryTest { artworkUrl = "", cardsInWallet = setOf(), isMultiCurrency = false, - scanResponse = ScanResponseMockFactory.create(cardConfig = GenericCardConfig(2), derivedKeys = emptyMap()), + scanResponse = MockScanResponseFactory.create(cardConfig = GenericCardConfig(2), derivedKeys = emptyMap()), hasBackupError = false, ) @@ -77,7 +79,7 @@ internal class DefaultDerivationsRepositoryTest { @Test fun `success if currencies is empty`() = runTest { val userWallet = defaultUserWallet.copy( - scanResponse = ScanResponseMockFactory.create(cardConfig = MultiWalletCardConfig, derivedKeys = emptyMap()), + scanResponse = MockScanResponseFactory.create(cardConfig = MultiWalletCardConfig, derivedKeys = emptyMap()), ) coEvery { userWalletsStore.getSyncOrNull(defaultUserWalletId) } returns userWallet @@ -94,7 +96,7 @@ internal class DefaultDerivationsRepositoryTest { @Test fun `success if card already has derivations`() = runTest { val userWallet = defaultUserWallet.copy( - scanResponse = ScanResponseMockFactory.create( + scanResponse = MockScanResponseFactory.create( cardConfig = MultiWalletCardConfig, derivedKeys = DerivedKeysMocks.ethereumDerivedKeys, ), @@ -105,7 +107,7 @@ internal class DefaultDerivationsRepositoryTest { runCatching { repository.derivePublicKeys( userWalletId = defaultUserWalletId, - currencies = CryptoCurrenciesMocks(userWallet.scanResponse).ethereum, + currencies = MockCryptoCurrencyFactory(userWallet.scanResponse).ethereum.let(::listOf), ) } .onSuccess { Truth.assertThat(it) } @@ -119,7 +121,7 @@ internal class DefaultDerivationsRepositoryTest { @Test fun `error if tangemSdkManager throws exception`() = runTest { val userWallet = defaultUserWallet.copy( - scanResponse = ScanResponseMockFactory.create(cardConfig = MultiWalletCardConfig, derivedKeys = emptyMap()), + scanResponse = MockScanResponseFactory.create(cardConfig = MultiWalletCardConfig, derivedKeys = emptyMap()), ) coEvery { userWalletsStore.getSyncOrNull(defaultUserWalletId) } returns userWallet coEvery { tangemSdkManager.derivePublicKeys(null, any(), any()) } throws ScanCardException.UserCancelled @@ -127,7 +129,7 @@ internal class DefaultDerivationsRepositoryTest { runCatching { repository.derivePublicKeys( userWalletId = defaultUserWalletId, - currencies = CryptoCurrenciesMocks(userWallet.scanResponse).ethereum, + currencies = MockCryptoCurrencyFactory(userWallet.scanResponse).ethereum.let(::listOf), ) } .onSuccess { error("Should throws exception") } @@ -142,7 +144,7 @@ internal class DefaultDerivationsRepositoryTest { @Test fun `success case`() = runTest { val userWallet = defaultUserWallet.copy( - scanResponse = ScanResponseMockFactory.create(cardConfig = MultiWalletCardConfig, derivedKeys = emptyMap()), + scanResponse = MockScanResponseFactory.create(cardConfig = MultiWalletCardConfig, derivedKeys = emptyMap()), ) coEvery { userWalletsStore.getSyncOrNull(defaultUserWalletId) } returns userWallet coEvery { tangemSdkManager.derivePublicKeys(null, any(), any()) } returns CompletionResult.Success( @@ -153,7 +155,7 @@ internal class DefaultDerivationsRepositoryTest { runCatching { repository.derivePublicKeys( userWalletId = defaultUserWalletId, - currencies = CryptoCurrenciesMocks(userWallet.scanResponse).ethereum, + currencies = MockCryptoCurrencyFactory(userWallet.scanResponse).ethereum.let(::listOf), ) } .onSuccess { Truth.assertThat(it) } diff --git a/app/src/test/kotlin/com/tangem/tap/domain/card/MissedDerivationsFinderTest.kt b/app/src/test/kotlin/com/tangem/tap/domain/card/MissedDerivationsFinderTest.kt index 7091e26f4f..063a5bc85b 100644 --- a/app/src/test/kotlin/com/tangem/tap/domain/card/MissedDerivationsFinderTest.kt +++ b/app/src/test/kotlin/com/tangem/tap/domain/card/MissedDerivationsFinderTest.kt @@ -6,6 +6,8 @@ import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.derivation.DerivationConfigV2 import com.tangem.common.card.EllipticCurve import com.tangem.common.extensions.ByteArrayKey +import com.tangem.common.test.domain.card.MockScanResponseFactory +import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory import com.tangem.crypto.hdWallet.DerivationPath import com.tangem.domain.common.configs.GenericCardConfig import com.tangem.domain.common.configs.MultiWalletCardConfig @@ -20,7 +22,7 @@ internal class MissedDerivationsFinderTest { @Test fun `empty derivations for empty currencies`() { - val scanResponse = ScanResponseMockFactory.create(cardConfig = GenericCardConfig(2), derivedKeys = emptyMap()) + val scanResponse = MockScanResponseFactory.create(cardConfig = GenericCardConfig(2), derivedKeys = emptyMap()) val finder = MissedDerivationsFinder(scanResponse) val actual = finder.find(emptyList()) @@ -31,10 +33,10 @@ internal class MissedDerivationsFinderTest { @Test fun `empty derivations for non supported blockchains`() { // Bls is not supported - val scanResponse = ScanResponseMockFactory.create(cardConfig = GenericCardConfig(2), derivedKeys = emptyMap()) + val scanResponse = MockScanResponseFactory.create(cardConfig = GenericCardConfig(2), derivedKeys = emptyMap()) val finder = MissedDerivationsFinder(scanResponse) - val currencies = CryptoCurrenciesMocks(scanResponse).chia + val currencies = MockCryptoCurrencyFactory(scanResponse).chia.let(::listOf) val actual = finder.find(currencies) Truth.assertThat(actual).isEmpty() @@ -43,7 +45,7 @@ internal class MissedDerivationsFinderTest { @Test fun `derivations ONLY for supported blockchains`() { // Bls is not supported - val scanResponse = ScanResponseMockFactory.create( + val scanResponse = MockScanResponseFactory.create( cardConfig = GenericCardConfig(2), derivedKeys = emptyMap(), ).let { @@ -55,7 +57,7 @@ internal class MissedDerivationsFinderTest { } val finder = MissedDerivationsFinder(scanResponse) - val currencies = CryptoCurrenciesMocks(scanResponse).chiaAndEthereum + val currencies = MockCryptoCurrencyFactory(scanResponse).chiaAndEthereum val actual = finder.find(currencies) Truth.assertThat(actual).containsExactly( @@ -66,10 +68,10 @@ internal class MissedDerivationsFinderTest { @Test fun `derivations for custom token`() { - val scanResponse = ScanResponseMockFactory.create(cardConfig = MultiWalletCardConfig, derivedKeys = emptyMap()) + val scanResponse = MockScanResponseFactory.create(cardConfig = MultiWalletCardConfig, derivedKeys = emptyMap()) val finder = MissedDerivationsFinder(scanResponse) - val currencies = CryptoCurrenciesMocks(scanResponse).ethereumTokenWithBinanceDerivation + val currencies = MockCryptoCurrencyFactory(scanResponse).ethereumTokenWithBinanceDerivation val actual = finder.find(currencies) Truth.assertThat(actual).containsExactly( @@ -83,10 +85,10 @@ internal class MissedDerivationsFinderTest { @Test fun `derivations for cardano`() { - val scanResponse = ScanResponseMockFactory.create(cardConfig = MultiWalletCardConfig, derivedKeys = emptyMap()) + val scanResponse = MockScanResponseFactory.create(cardConfig = MultiWalletCardConfig, derivedKeys = emptyMap()) val finder = MissedDerivationsFinder(scanResponse) - val currencies = CryptoCurrenciesMocks(scanResponse).cardano + val currencies = MockCryptoCurrencyFactory(scanResponse).cardano.let(::listOf) val actual = finder.find(currencies) Truth.assertThat(actual).containsExactly( @@ -105,13 +107,13 @@ internal class MissedDerivationsFinderTest { @Test fun `empty derivations for already derived currencies`() { - val scanResponse = ScanResponseMockFactory.create( + val scanResponse = MockScanResponseFactory.create( cardConfig = Wallet2CardConfig, derivedKeys = DerivedKeysMocks.ethereumDerivedKeys, ) val finder = MissedDerivationsFinder(scanResponse) - val currencies = CryptoCurrenciesMocks(scanResponse).ethereum + val currencies = MockCryptoCurrencyFactory(scanResponse).ethereum.let(::listOf) val actual = finder.find(currencies) Truth.assertThat(actual).isEmpty() @@ -119,13 +121,13 @@ internal class MissedDerivationsFinderTest { @Test fun `derivations ONLY for never derived currencies`() { - val scanResponse = ScanResponseMockFactory.create( + val scanResponse = MockScanResponseFactory.create( cardConfig = MultiWalletCardConfig, derivedKeys = DerivedKeysMocks.ethereumDerivedKeys, ) val finder = MissedDerivationsFinder(scanResponse) - val currencies = CryptoCurrenciesMocks(scanResponse).ethereumAndStellar + val currencies = MockCryptoCurrencyFactory(scanResponse).ethereumAndStellar val actual = finder.find(currencies) Truth.assertThat(actual).containsExactly( diff --git a/app/src/test/kotlin/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManagerTest.kt b/app/src/test/kotlin/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManagerTest.kt index 6d22031f4c..8180ca85ab 100644 --- a/app/src/test/kotlin/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManagerTest.kt +++ b/app/src/test/kotlin/com/tangem/tap/domain/userWalletList/implementation/BiometricUserWalletsListManagerTest.kt @@ -1,10 +1,10 @@ package com.tangem.tap.domain.userWalletList.implementation import com.google.common.truth.Truth +import com.tangem.common.test.domain.card.MockScanResponseFactory import com.tangem.domain.common.configs.GenericCardConfig import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.tap.domain.card.ScanResponseMockFactory import io.mockk.mockk import org.junit.Test import org.junit.runner.RunWith @@ -198,7 +198,7 @@ internal class BiometricUserWalletsListManagerTest(private val model: Model) { cardsInWallet = emptySet(), isMultiCurrency = true, hasBackupError = false, - scanResponse = ScanResponseMockFactory.create( + scanResponse = MockScanResponseFactory.create( cardConfig = GenericCardConfig(maxWalletCount = 1), derivedKeys = emptyMap(), ).let { diff --git a/common/test/.gitignore b/common/test/.gitignore new file mode 100644 index 0000000000..42afabfd2a --- /dev/null +++ b/common/test/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/common/test/build.gradle.kts b/common/test/build.gradle.kts new file mode 100644 index 0000000000..4fd8c4f361 --- /dev/null +++ b/common/test/build.gradle.kts @@ -0,0 +1,25 @@ +plugins { + alias(deps.plugins.android.library) + alias(deps.plugins.kotlin.android) + id("configuration") +} + +android { + namespace = "com.tangem.common.test" +} + +dependencies { + implementation(projects.data.common) + + implementation(projects.domain.legacy) + implementation(projects.domain.models) + implementation(projects.domain.tokens.models) + + implementation(projects.libs.blockchainSdk) + + implementation(deps.androidx.datastore) + implementation(deps.test.coroutine) + + implementation(tangemDeps.blockchain) + implementation(tangemDeps.card.core) +} \ No newline at end of file diff --git a/app/src/test/kotlin/com/tangem/tap/domain/card/ScanResponseMockFactory.kt b/common/test/src/main/java/com/tangem/common/test/domain/card/MockScanResponseFactory.kt similarity index 98% rename from app/src/test/kotlin/com/tangem/tap/domain/card/ScanResponseMockFactory.kt rename to common/test/src/main/java/com/tangem/common/test/domain/card/MockScanResponseFactory.kt index da79e800f0..54108f07a9 100644 --- a/app/src/test/kotlin/com/tangem/tap/domain/card/ScanResponseMockFactory.kt +++ b/common/test/src/main/java/com/tangem/common/test/domain/card/MockScanResponseFactory.kt @@ -1,4 +1,4 @@ -package com.tangem.tap.domain.card +package com.tangem.common.test.domain.card import com.tangem.common.card.CardWallet import com.tangem.common.card.FirmwareVersion @@ -14,7 +14,7 @@ import java.util.Date /** [REDACTED_AUTHOR] */ -object ScanResponseMockFactory { +object MockScanResponseFactory { private val genericFirmwareVersion = CardDTO.FirmwareVersion( major = 3, diff --git a/app/src/test/kotlin/com/tangem/tap/domain/card/CryptoCurrenciesMocks.kt b/common/test/src/main/java/com/tangem/common/test/domain/token/MockCryptoCurrencyFactory.kt similarity index 78% rename from app/src/test/kotlin/com/tangem/tap/domain/card/CryptoCurrenciesMocks.kt rename to common/test/src/main/java/com/tangem/common/test/domain/token/MockCryptoCurrencyFactory.kt index dceee7e356..9af7183d2a 100644 --- a/app/src/test/kotlin/com/tangem/tap/domain/card/CryptoCurrenciesMocks.kt +++ b/common/test/src/main/java/com/tangem/common/test/domain/token/MockCryptoCurrencyFactory.kt @@ -1,13 +1,15 @@ -package com.tangem.tap.domain.card +package com.tangem.common.test.domain.token import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.FeePaidCurrency import com.tangem.blockchain.common.Token import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.blockchainsdk.utils.toNetworkId +import com.tangem.common.test.domain.card.MockScanResponseFactory import com.tangem.data.common.currency.CryptoCurrencyFactory import com.tangem.data.common.currency.getNetworkDerivationPath import com.tangem.data.common.currency.getNetworkStandardType +import com.tangem.domain.common.configs.GenericCardConfig import com.tangem.domain.common.util.derivationStyleProvider import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.tokens.model.CryptoCurrency @@ -16,13 +18,13 @@ import com.tangem.domain.tokens.model.Network /** [REDACTED_AUTHOR] */ -internal class CryptoCurrenciesMocks(private val scanResponse: ScanResponse) { +class MockCryptoCurrencyFactory(private val scanResponse: ScanResponse = defaultScanResponse) { private val factory = CryptoCurrencyFactory(excludedBlockchains = ExcludedBlockchains()) - val cardano by lazy { listOf(createCoin(blockchain = Blockchain.Cardano)) } - val chia by lazy { listOf(element = createCoin(Blockchain.Chia)) } - val ethereum by lazy { listOf(element = createCoin(Blockchain.Ethereum)) } + val cardano by lazy { createCoin(blockchain = Blockchain.Cardano) } + val chia by lazy { createCoin(Blockchain.Chia) } + val ethereum by lazy { createCoin(Blockchain.Ethereum) } val chiaAndEthereum by lazy { listOf( @@ -44,16 +46,16 @@ internal class CryptoCurrenciesMocks(private val scanResponse: ScanResponse) { ) } - private fun createCoin(blockchain: Blockchain): CryptoCurrency { + fun createCoin(blockchain: Blockchain): CryptoCurrency { val network = Network( id = Network.ID(blockchain.id), backendId = blockchain.toNetworkId(), name = blockchain.fullName, isTestnet = blockchain.isTestnet(), derivationPath = getNetworkDerivationPath( - blockchain, + blockchain = blockchain, extraDerivationPath = null, - scanResponse.derivationStyleProvider, + cardDerivationStyleProvider = scanResponse.derivationStyleProvider, ), currencySymbol = blockchain.currency, standardType = getNetworkStandardType(blockchain), @@ -66,7 +68,7 @@ internal class CryptoCurrenciesMocks(private val scanResponse: ScanResponse) { } // Impossible to create custom token by CryptoCurrencyFactory because it works with URI under the hood - private fun createCustomToken(blockchain: Blockchain, derivationBlockchain: Blockchain): CryptoCurrency { + fun createCustomToken(blockchain: Blockchain, derivationBlockchain: Blockchain): CryptoCurrency { return CryptoCurrency.Token( id = CryptoCurrency.ID( prefix = CryptoCurrency.ID.Prefix.TOKEN_PREFIX, @@ -98,7 +100,7 @@ internal class CryptoCurrenciesMocks(private val scanResponse: ScanResponse) { ) } - private fun createToken(blockchain: Blockchain): CryptoCurrency { + fun createToken(blockchain: Blockchain): CryptoCurrency { return factory.createToken( sdkToken = Token(symbol = "NEVER-MIND", contractAddress = "NEVER-MIND", decimals = 8), blockchain = blockchain, @@ -106,4 +108,12 @@ internal class CryptoCurrenciesMocks(private val scanResponse: ScanResponse) { scanResponse = scanResponse, )!! } + + private companion object { + + val defaultScanResponse = MockScanResponseFactory.create( + cardConfig = GenericCardConfig(2), + derivedKeys = emptyMap(), + ) + } } \ No newline at end of file diff --git a/common/test/src/main/java/com/tangem/common/test/utils/CoroutineExt.kt b/common/test/src/main/java/com/tangem/common/test/utils/CoroutineExt.kt new file mode 100644 index 0000000000..537e01b8f3 --- /dev/null +++ b/common/test/src/main/java/com/tangem/common/test/utils/CoroutineExt.kt @@ -0,0 +1,20 @@ +package com.tangem.common.test.utils + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.toList +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.TestCoroutineScheduler +import kotlinx.coroutines.test.UnconfinedTestDispatcher + +@OptIn(ExperimentalCoroutinesApi::class) +fun CoroutineScope.getEmittedValues(testScheduler: TestCoroutineScheduler, actual: Flow): List { + val values = mutableListOf() + + launch(UnconfinedTestDispatcher(testScheduler)) { + actual.toList(values) + } + + return values +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index f45ec8e8bc..b85da198aa 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -153,10 +153,11 @@ include(":core:error") // region Common modules include(":common") -include(":common:ui-charts") -include(":common:routing") -include(":common:ui") include(":common:google") +include(":common:routing") +include(":common:test") +include(":common:ui") +include(":common:ui-charts") // endregion // region Libs modules