Updated on 2026-08-14
This commit is contained in:
commit
dc2e0ef506
12 changed files with 193 additions and 53 deletions
|
|
@ -25,6 +25,10 @@ dependencies {
|
|||
implementation(projects.core.utils)
|
||||
// endregion
|
||||
|
||||
// region Libs
|
||||
implementation(projects.libs.crypto)
|
||||
// endregion
|
||||
|
||||
// region Domain
|
||||
api(projects.domain.common)
|
||||
api(projects.domain.tokens)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.domain.addressbook.usecase
|
|||
import com.tangem.domain.addressbook.model.Contact
|
||||
import com.tangem.domain.addressbook.repository.AddressBookRepository
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.lib.crypto.BlockchainUtils
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
|
|
@ -30,8 +31,14 @@ class GetContactsUseCase(
|
|||
private fun Contact.matches(query: String): Boolean {
|
||||
val isNameContaining = name.value.contains(other = query, ignoreCase = true)
|
||||
val isAddressContaining = addresses.any { addressEntry ->
|
||||
addressEntry.address.contains(other = query, ignoreCase = false)
|
||||
val isCaseInsensitiveContractAddress = BlockchainUtils.isCaseInsensitiveContractAddress(
|
||||
networkId = addressEntry.networkId.value,
|
||||
)
|
||||
addressEntry.address.contains(other = query, ignoreCase = isCaseInsensitiveContractAddress)
|
||||
}
|
||||
return isNameContaining || isAddressContaining
|
||||
val isNetworkContaining = addresses.any { addressEntry ->
|
||||
addressEntry.networkId.value.contains(other = query, ignoreCase = true)
|
||||
}
|
||||
return isNameContaining || isAddressContaining || isNetworkContaining
|
||||
}
|
||||
}
|
||||
|
|
@ -54,31 +54,71 @@ class GetContactsUseCaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN address query matching case WHEN invoke THEN returns matching contact`() = runTest {
|
||||
// Arrange
|
||||
val carol = contact(name = "Carol", address = "0xAbCdEf")
|
||||
every { repository.getAllContacts() } returns flowOf(listOf(alice, carol))
|
||||
|
||||
// Act
|
||||
val result = useCase(query = "0xAbCdEf").first()
|
||||
|
||||
// Assert
|
||||
assertThat(result).containsExactly(carol)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN address query with different case WHEN invoke THEN returns empty`() = runTest {
|
||||
// Arrange
|
||||
val carol = contact(name = "Carol", address = "0xAbCdEf")
|
||||
fun `GIVEN EVM address query differing only in case WHEN invoke THEN returns matching contact`() = runTest {
|
||||
// Arrange — EVM (ethereum) addresses are case-insensitive, so a lowercased query matches a checksummed address
|
||||
val carol = contact(name = "Carol", address = "0xAbCdEf", networkId = "ethereum")
|
||||
every { repository.getAllContacts() } returns flowOf(listOf(alice, carol))
|
||||
|
||||
// Act
|
||||
val result = useCase(query = "0xabcdef").first()
|
||||
|
||||
// Assert
|
||||
assertThat(result).containsExactly(carol)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN non-EVM address query differing only in case WHEN invoke THEN returns empty`() = runTest {
|
||||
// Arrange — non-EVM (solana) addresses are case-sensitive, so a differently-cased query must not match
|
||||
val dave = contact(name = "Dave", address = "SoLAnaAddr", networkId = "solana")
|
||||
every { repository.getAllContacts() } returns flowOf(listOf(alice, dave))
|
||||
|
||||
// Act
|
||||
val result = useCase(query = "solanaaddr").first()
|
||||
|
||||
// Assert
|
||||
assertThat(result).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN non-EVM address query with exact case WHEN invoke THEN returns matching contact`() = runTest {
|
||||
// Arrange
|
||||
val dave = contact(name = "Dave", address = "SoLAnaAddr", networkId = "solana")
|
||||
every { repository.getAllContacts() } returns flowOf(listOf(alice, dave))
|
||||
|
||||
// Act
|
||||
val result = useCase(query = "SoLAnaAddr").first()
|
||||
|
||||
// Assert
|
||||
assertThat(result).containsExactly(dave)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN query matches a network id WHEN invoke THEN returns only contacts on that network`() = runTest {
|
||||
// Arrange
|
||||
val ethContact = contact(name = "Eth", address = "0x1", networkId = "ethereum")
|
||||
val tronContact = contact(name = "Tron", address = "T1", networkId = "tron")
|
||||
every { repository.getAllContacts() } returns flowOf(listOf(ethContact, tronContact))
|
||||
|
||||
// Act
|
||||
val result = useCase(query = "tron").first()
|
||||
|
||||
// Assert
|
||||
assertThat(result).containsExactly(tronContact)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN network query with different case WHEN invoke THEN returns matching contact`() = runTest {
|
||||
// Arrange
|
||||
val tronContact = contact(name = "Tron", address = "T1", networkId = "tron")
|
||||
every { repository.getAllContacts() } returns flowOf(listOf(alice, tronContact))
|
||||
|
||||
// Act
|
||||
val result = useCase(query = "TRON").first()
|
||||
|
||||
// Assert
|
||||
assertThat(result).containsExactly(tronContact)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN name query with different case WHEN invoke THEN returns matching contact`() = runTest {
|
||||
// Act
|
||||
|
|
@ -139,6 +179,7 @@ class GetContactsUseCaseTest {
|
|||
name: String,
|
||||
address: String,
|
||||
createdAt: String = "2026-01-01T00:00:00.000Z",
|
||||
networkId: String = "ethereum",
|
||||
): Contact = Contact(
|
||||
id = ContactId("id-$name"),
|
||||
walletId = UserWalletId("011"),
|
||||
|
|
@ -151,7 +192,7 @@ class GetContactsUseCaseTest {
|
|||
AddressEntry(
|
||||
id = AddressEntryId("addr-$name"),
|
||||
address = address,
|
||||
networkId = Network.RawID("ethereum"),
|
||||
networkId = Network.RawID(networkId),
|
||||
memo = null,
|
||||
signature = "sig",
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue