mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-26 05:58:09 +00:00
Implement new Safety Number Changes bottom sheeet.
This commit is contained in:
@@ -5,11 +5,13 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.thoughtcrime.securesms.conversation.ui.error.SafetyNumberChangeDialog
|
||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.profiles.ProfileName
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.safety.SafetyNumberBottomSheet
|
||||
import org.thoughtcrime.securesms.testing.SignalActivityRule
|
||||
|
||||
/**
|
||||
@@ -18,7 +20,7 @@ import org.thoughtcrime.securesms.testing.SignalActivityRule
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class SafetyNumberChangeDialogPreviewer {
|
||||
|
||||
@get:Rule val harness = SignalActivityRule()
|
||||
@get:Rule val harness = SignalActivityRule(othersCount = 10)
|
||||
|
||||
@Test
|
||||
fun testShowLongName() {
|
||||
@@ -31,7 +33,31 @@ class SafetyNumberChangeDialogPreviewer {
|
||||
|
||||
val scenario: ActivityScenario<ConversationActivity> = harness.launchActivity { putExtra("recipient_id", other.id.serialize()) }
|
||||
scenario.onActivity {
|
||||
SafetyNumberChangeDialog.show(it.supportFragmentManager, other.id)
|
||||
SafetyNumberBottomSheet.forRecipientId(other.id).show(it.supportFragmentManager)
|
||||
}
|
||||
|
||||
// Uncomment to make dialog stay on screen, otherwise will show/dismiss immediately
|
||||
// ThreadUtil.sleep(15000)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testShowLargeSheet() {
|
||||
val othersRecipients = harness.others.map { Recipient.resolved(it) }
|
||||
othersRecipients.forEach { other ->
|
||||
SignalDatabase.recipients.setProfileName(other.id, ProfileName.fromParts("My", "Name"))
|
||||
|
||||
harness.setVerified(other, IdentityDatabase.VerifiedStatus.VERIFIED)
|
||||
harness.changeIdentityKey(other)
|
||||
}
|
||||
|
||||
val scenario: ActivityScenario<ConversationActivity> = harness.launchActivity { putExtra("recipient_id", harness.others.first().serialize()) }
|
||||
scenario.onActivity { conversationActivity ->
|
||||
SafetyNumberBottomSheet
|
||||
.forIdentityRecordsAndDestinations(
|
||||
identityRecords = ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecords(othersRecipients).identityRecords,
|
||||
destinations = othersRecipients.map { ContactSearchKey.RecipientSearchKey.KnownRecipient(it.id) }
|
||||
)
|
||||
.show(conversationActivity.supportFragmentManager)
|
||||
}
|
||||
|
||||
// Uncomment to make dialog stay on screen, otherwise will show/dismiss immediately
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
package org.thoughtcrime.securesms.safety
|
||||
|
||||
import io.reactivex.rxjava3.plugins.RxJavaPlugins
|
||||
import io.reactivex.rxjava3.schedulers.TestScheduler
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.testing.SignalActivityRule
|
||||
|
||||
class SafetyNumberBottomSheetRepositoryTest {
|
||||
|
||||
@get:Rule val harness = SignalActivityRule(othersCount = 10)
|
||||
|
||||
private val testScheduler = TestScheduler()
|
||||
private val subjectUnderTest = SafetyNumberBottomSheetRepository()
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
RxJavaPlugins.setInitIoSchedulerHandler { testScheduler }
|
||||
RxJavaPlugins.setIoSchedulerHandler { testScheduler }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenIOnlyHave1to1Destinations_whenIGetBuckets_thenIOnlyHaveContactsBucketContainingAllRecipients() {
|
||||
val recipients = harness.others
|
||||
val destinations = harness.others.map { ContactSearchKey.RecipientSearchKey.KnownRecipient(it) }
|
||||
|
||||
val result = subjectUnderTest.getBuckets(recipients, destinations).test()
|
||||
|
||||
testScheduler.triggerActions()
|
||||
|
||||
result.assertValueAt(1) { map ->
|
||||
assertMatch(map, mapOf(SafetyNumberBucket.ContactsBucket to harness.others))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenIOnlyHaveASingle1to1Destination_whenIGetBuckets_thenIOnlyHaveContactsBucketContainingAllRecipients() {
|
||||
// GIVEN
|
||||
val recipients = harness.others
|
||||
val destination = harness.others.take(1).map { ContactSearchKey.RecipientSearchKey.KnownRecipient(it) }
|
||||
|
||||
// WHEN
|
||||
val result = subjectUnderTest.getBuckets(recipients, destination).test(1)
|
||||
testScheduler.triggerActions()
|
||||
|
||||
// THEN
|
||||
result.assertValue { map ->
|
||||
assertMatch(map, mapOf(SafetyNumberBucket.ContactsBucket to harness.others.take(1)))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenIHaveADistributionListDestination_whenIGetBuckets_thenIOnlyHaveDistributionListDestinationWithCorrespondingMembers() {
|
||||
// GIVEN
|
||||
val distributionListMembers = harness.others.take(5)
|
||||
val distributionList = SignalDatabase.distributionLists.createList("ListA", distributionListMembers)!!
|
||||
val destinationKey = ContactSearchKey.RecipientSearchKey.Story(SignalDatabase.distributionLists.getRecipientId(distributionList)!!)
|
||||
|
||||
// WHEN
|
||||
val result = subjectUnderTest.getBuckets(harness.others, listOf(destinationKey)).test(1)
|
||||
testScheduler.triggerActions()
|
||||
|
||||
// THEN
|
||||
result.assertValue { map ->
|
||||
assertMatch(
|
||||
map,
|
||||
mapOf(
|
||||
SafetyNumberBucket.DistributionListBucket(distributionList, "ListA") to harness.others.take(5)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenIHaveADistributionListDestinationAndIGetBuckets_whenIRemoveFromStories_thenIOnlyHaveDistributionListDestinationWithCorrespondingMembers() {
|
||||
// GIVEN
|
||||
val distributionListMembers = harness.others.take(5)
|
||||
val toRemove = distributionListMembers.last()
|
||||
val distributionList = SignalDatabase.distributionLists.createList("ListA", distributionListMembers)!!
|
||||
val destinationKey = ContactSearchKey.RecipientSearchKey.Story(SignalDatabase.distributionLists.getRecipientId(distributionList)!!)
|
||||
val testSubscriber = subjectUnderTest.getBuckets(distributionListMembers, listOf(destinationKey)).test(2)
|
||||
testScheduler.triggerActions()
|
||||
|
||||
// WHEN
|
||||
subjectUnderTest.removeFromStories(toRemove, listOf(destinationKey)).subscribe()
|
||||
testSubscriber.request(1)
|
||||
testScheduler.triggerActions()
|
||||
testSubscriber.awaitCount(3)
|
||||
|
||||
// THEN
|
||||
testSubscriber.assertValueAt(2) { map ->
|
||||
assertMatch(
|
||||
map,
|
||||
mapOf(
|
||||
SafetyNumberBucket.DistributionListBucket(distributionList, "ListA") to distributionListMembers.dropLast(1)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenIHaveADistributionListDestinationAndIGetBuckets_whenIRemoveAllFromStory_thenINoLongerHaveEntryForThatBucket() {
|
||||
// GIVEN
|
||||
val distributionListMembers = harness.others.take(5)
|
||||
val distributionList = SignalDatabase.distributionLists.createList("ListA", distributionListMembers)!!
|
||||
val destinationKey = ContactSearchKey.RecipientSearchKey.Story(SignalDatabase.distributionLists.getRecipientId(distributionList)!!)
|
||||
val testSubscriber = subjectUnderTest.getBuckets(distributionListMembers, listOf(destinationKey)).test(2)
|
||||
testScheduler.triggerActions()
|
||||
|
||||
// WHEN
|
||||
subjectUnderTest.removeAllFromStory(distributionListMembers, distributionList).subscribe()
|
||||
testSubscriber.request(1)
|
||||
testScheduler.triggerActions()
|
||||
testSubscriber.awaitCount(3)
|
||||
|
||||
// THEN
|
||||
testSubscriber.assertValueAt(2) { map ->
|
||||
assertMatch(map, mapOf())
|
||||
}
|
||||
}
|
||||
|
||||
private fun assertMatch(
|
||||
resultMap: Map<SafetyNumberBucket, List<SafetyNumberRecipient>>,
|
||||
idMap: Map<SafetyNumberBucket, List<RecipientId>>
|
||||
): Boolean {
|
||||
assertEquals("Result and ID Maps had different key sets", idMap.keys, resultMap.keys)
|
||||
|
||||
resultMap.forEach { (bucket, members) ->
|
||||
assertEquals("Mismatch in Bucket $bucket", idMap[bucket], members.map { it.recipient.id })
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import org.whispersystems.signalservice.api.profiles.SignalServiceProfile
|
||||
import org.whispersystems.signalservice.api.push.ACI
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||
import org.whispersystems.signalservice.internal.push.VerifyAccountResponse
|
||||
import java.lang.IllegalArgumentException
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
@@ -38,7 +39,7 @@ import java.util.UUID
|
||||
*
|
||||
* To use: `@get:Rule val harness = SignalActivityRule()`
|
||||
*/
|
||||
class SignalActivityRule : ExternalResource() {
|
||||
class SignalActivityRule(private val othersCount: Int = 4) : ExternalResource() {
|
||||
|
||||
val application: Application = ApplicationDependencies.getApplication()
|
||||
|
||||
@@ -88,9 +89,13 @@ class SignalActivityRule : ExternalResource() {
|
||||
private fun setupOthers(): List<RecipientId> {
|
||||
val others = mutableListOf<RecipientId>()
|
||||
|
||||
for (i in 0..4) {
|
||||
if (othersCount !in 0 until 1000) {
|
||||
throw IllegalArgumentException("$othersCount must be between 0 and 1000")
|
||||
}
|
||||
|
||||
for (i in 0 until othersCount) {
|
||||
val aci = ACI.from(UUID.randomUUID())
|
||||
val recipientId = RecipientId.from(SignalServiceAddress(aci, "+1555555101$i"))
|
||||
val recipientId = RecipientId.from(SignalServiceAddress(aci, "+15555551%03d".format(i)))
|
||||
SignalDatabase.recipients.setProfileName(recipientId, ProfileName.fromParts("Buddy", "#$i"))
|
||||
SignalDatabase.recipients.setProfileKeyIfAbsent(recipientId, ProfileKeyUtil.createNew())
|
||||
SignalDatabase.recipients.setCapabilities(recipientId, SignalServiceProfile.Capabilities(true, true, true, true, true, true, true))
|
||||
|
||||
Reference in New Issue
Block a user