mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-26 20:55:10 +00:00
Make names in group update descriptions tappable.
This commit is contained in:
committed by
Alex Hart
parent
3b17a41415
commit
e2cb535f3f
@@ -1,13 +1,13 @@
|
||||
package org.thoughtcrime.securesms.database.model;
|
||||
|
||||
import android.app.Application;
|
||||
import android.text.Spannable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
@@ -19,18 +19,18 @@ import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.signal.core.util.ThreadUtil;
|
||||
import org.signal.storageservice.protos.groups.AccessControl;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedGroupChange;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedMember;
|
||||
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -38,8 +38,11 @@ import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.thoughtcrime.securesms.groups.v2.ChangeBuilder.changeBy;
|
||||
import static org.thoughtcrime.securesms.groups.v2.ChangeBuilder.changeByUnknown;
|
||||
import static org.signal.core.util.StringUtil.isolateBidi;
|
||||
@@ -60,18 +63,38 @@ public final class GroupsV2UpdateMessageProducerTest {
|
||||
public MockitoRule rule = MockitoJUnit.rule();
|
||||
|
||||
@Mock
|
||||
public MockedStatic<ThreadUtil> threadUtilMockedStatic;
|
||||
public MockedStatic<Recipient> recipientMockedStatic;
|
||||
|
||||
@Mock
|
||||
public MockedStatic<RecipientId> recipientIdMockedStatic;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
you = UUID.randomUUID();
|
||||
alice = UUID.randomUUID();
|
||||
bob = UUID.randomUUID();
|
||||
GroupsV2UpdateMessageProducer.DescribeMemberStrategy describeMember = createDescriber(ImmutableMap.of(alice, "Alice", bob, "Bob"));
|
||||
producer = new GroupsV2UpdateMessageProducer(ApplicationProvider.getApplicationContext(), describeMember, you);
|
||||
|
||||
threadUtilMockedStatic.when(ThreadUtil::assertMainThread).thenCallRealMethod();
|
||||
threadUtilMockedStatic.when(ThreadUtil::assertNotMainThread).thenCallRealMethod();
|
||||
recipientIdMockedStatic.when(() -> RecipientId.from(anyLong())).thenCallRealMethod();
|
||||
|
||||
RecipientId aliceId = RecipientId.from(1);
|
||||
RecipientId bobId = RecipientId.from(2);
|
||||
|
||||
Recipient aliceRecipient = recipientWithName(aliceId, "Alice");
|
||||
Recipient bobRecipient = recipientWithName(bobId, "Bob");
|
||||
|
||||
producer = new GroupsV2UpdateMessageProducer(ApplicationProvider.getApplicationContext(), you, null);
|
||||
|
||||
recipientIdMockedStatic.when(() -> RecipientId.from(ServiceId.from(alice), null)).thenReturn(aliceId);
|
||||
recipientIdMockedStatic.when(() -> RecipientId.from(ServiceId.from(bob), null)).thenReturn(bobId);
|
||||
recipientMockedStatic.when(() -> Recipient.resolved(aliceId)).thenReturn(aliceRecipient);
|
||||
recipientMockedStatic.when(() -> Recipient.resolved(bobId)).thenReturn(bobRecipient);
|
||||
}
|
||||
|
||||
private static Recipient recipientWithName(RecipientId id, String name) {
|
||||
Recipient recipient = mock(Recipient.class);
|
||||
when(recipient.getId()).thenReturn(id);
|
||||
when(recipient.getDisplayName(any())).thenReturn(name);
|
||||
return recipient;
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1333,11 +1356,11 @@ public final class GroupsV2UpdateMessageProducerTest {
|
||||
}
|
||||
|
||||
private @NonNull List<String> describeChange(@Nullable DecryptedGroup previousGroupState,
|
||||
@NonNull DecryptedGroupChange change)
|
||||
@NonNull DecryptedGroupChange change)
|
||||
{
|
||||
threadUtilMockedStatic.when(ThreadUtil::isMainThread).thenReturn(false);
|
||||
return Stream.of(producer.describeChanges(previousGroupState, change))
|
||||
.map(UpdateDescription::getString)
|
||||
.map(UpdateDescription::getSpannable)
|
||||
.map(Spannable::toString)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@@ -1346,8 +1369,7 @@ public final class GroupsV2UpdateMessageProducerTest {
|
||||
}
|
||||
|
||||
private @NonNull String describeNewGroup(@NonNull DecryptedGroup group, @NonNull DecryptedGroupChange groupChange) {
|
||||
threadUtilMockedStatic.when(ThreadUtil::isMainThread).thenReturn(false);
|
||||
return producer.describeNewGroup(group, groupChange).getString();
|
||||
return producer.describeNewGroup(group, groupChange).getSpannable().toString();
|
||||
}
|
||||
|
||||
private static GroupStateBuilder newGroupBy(UUID foundingMember, int revision) {
|
||||
@@ -1399,12 +1421,4 @@ public final class GroupsV2UpdateMessageProducerTest {
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
||||
private static @NonNull GroupsV2UpdateMessageProducer.DescribeMemberStrategy createDescriber(@NonNull Map<UUID, String> map) {
|
||||
return serviceId -> {
|
||||
String name = map.get(serviceId.uuid());
|
||||
assertNotNull(name);
|
||||
return name;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
package org.thoughtcrime.securesms.database.model;
|
||||
|
||||
import android.app.Application;
|
||||
import android.text.SpannableString;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -13,13 +19,15 @@ import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(manifest = Config.NONE, application = Application.class)
|
||||
public final class UpdateDescriptionTest {
|
||||
|
||||
@Test
|
||||
public void staticDescription_byGetStaticString() {
|
||||
UpdateDescription description = UpdateDescription.staticDescription("update", 0);
|
||||
|
||||
assertEquals("update", description.getStaticString());
|
||||
assertEquals("update", description.getStaticSpannable().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -33,30 +41,30 @@ public final class UpdateDescriptionTest {
|
||||
public void staticDescription_byString() {
|
||||
UpdateDescription description = UpdateDescription.staticDescription("update", 0);
|
||||
|
||||
assertEquals("update", description.getString());
|
||||
assertEquals("update", description.getSpannable().toString());
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void stringFactory_cannot_call_static_string() {
|
||||
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(ServiceId.from(UUID.randomUUID())), () -> "update", 0);
|
||||
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(ServiceId.from(UUID.randomUUID())), () -> new SpannableString("update"), 0);
|
||||
|
||||
description.getStaticString();
|
||||
description.getStaticSpannable();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stringFactory_not_evaluated_until_getString() {
|
||||
AtomicInteger factoryCalls = new AtomicInteger();
|
||||
|
||||
UpdateDescription.StringFactory stringFactory = () -> {
|
||||
UpdateDescription.SpannableFactory stringFactory = () -> {
|
||||
factoryCalls.incrementAndGet();
|
||||
return "update";
|
||||
return new SpannableString("update");
|
||||
};
|
||||
|
||||
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(ServiceId.from(UUID.randomUUID())), stringFactory, 0);
|
||||
|
||||
assertEquals(0, factoryCalls.get());
|
||||
|
||||
String string = description.getString();
|
||||
String string = description.getSpannable().toString();
|
||||
|
||||
assertEquals("update", string);
|
||||
assertEquals(1, factoryCalls.get());
|
||||
@@ -64,13 +72,13 @@ public final class UpdateDescriptionTest {
|
||||
|
||||
@Test
|
||||
public void stringFactory_reevaluated_on_every_call() {
|
||||
AtomicInteger factoryCalls = new AtomicInteger();
|
||||
UpdateDescription.StringFactory stringFactory = () -> "call" + factoryCalls.incrementAndGet();
|
||||
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(ServiceId.from(UUID.randomUUID())), stringFactory, 0);
|
||||
AtomicInteger factoryCalls = new AtomicInteger();
|
||||
UpdateDescription.SpannableFactory stringFactory = () -> new SpannableString( "call" + factoryCalls.incrementAndGet());
|
||||
UpdateDescription description = UpdateDescription.mentioning(Collections.singletonList(ServiceId.from(UUID.randomUUID())), stringFactory, 0);
|
||||
|
||||
assertEquals("call1", description.getString());
|
||||
assertEquals("call2", description.getString());
|
||||
assertEquals("call3", description.getString());
|
||||
assertEquals("call1", description.getSpannable().toString());
|
||||
assertEquals("call2", description.getSpannable().toString());
|
||||
assertEquals("call3", description.getSpannable().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -81,8 +89,8 @@ public final class UpdateDescriptionTest {
|
||||
UpdateDescription description = UpdateDescription.concatWithNewLines(Arrays.asList(description1, description2));
|
||||
|
||||
assertTrue(description.isStringStatic());
|
||||
assertEquals("update1\nupdate2", description.getStaticString());
|
||||
assertEquals("update1\nupdate2", description.getString());
|
||||
assertEquals("update1\nupdate2", description.getStaticSpannable().toString());
|
||||
assertEquals("update1\nupdate2", description.getSpannable().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -96,12 +104,12 @@ public final class UpdateDescriptionTest {
|
||||
|
||||
@Test
|
||||
public void concat_dynamic_lines() {
|
||||
AtomicInteger factoryCalls1 = new AtomicInteger();
|
||||
AtomicInteger factoryCalls2 = new AtomicInteger();
|
||||
UpdateDescription.StringFactory stringFactory1 = () -> "update." + factoryCalls1.incrementAndGet();
|
||||
UpdateDescription.StringFactory stringFactory2 = () -> "update." + factoryCalls2.incrementAndGet();
|
||||
UpdateDescription description1 = UpdateDescription.mentioning(Collections.singletonList(ServiceId.from(UUID.randomUUID())), stringFactory1, 0);
|
||||
UpdateDescription description2 = UpdateDescription.mentioning(Collections.singletonList(ServiceId.from(UUID.randomUUID())), stringFactory2, 0);
|
||||
AtomicInteger factoryCalls1 = new AtomicInteger();
|
||||
AtomicInteger factoryCalls2 = new AtomicInteger();
|
||||
UpdateDescription.SpannableFactory stringFactory1 = () -> new SpannableString("update." + factoryCalls1.incrementAndGet());
|
||||
UpdateDescription.SpannableFactory stringFactory2 = () -> new SpannableString("update." + factoryCalls2.incrementAndGet());
|
||||
UpdateDescription description1 = UpdateDescription.mentioning(Collections.singletonList(ServiceId.from(UUID.randomUUID())), stringFactory1, 0);
|
||||
UpdateDescription description2 = UpdateDescription.mentioning(Collections.singletonList(ServiceId.from(UUID.randomUUID())), stringFactory2, 0);
|
||||
|
||||
factoryCalls1.set(10);
|
||||
factoryCalls2.set(20);
|
||||
@@ -110,20 +118,20 @@ public final class UpdateDescriptionTest {
|
||||
|
||||
assertFalse(description.isStringStatic());
|
||||
|
||||
assertEquals("update.11\nupdate.21", description.getString());
|
||||
assertEquals("update.12\nupdate.22", description.getString());
|
||||
assertEquals("update.13\nupdate.23", description.getString());
|
||||
assertEquals("update.11\nupdate.21", description.getSpannable().toString());
|
||||
assertEquals("update.12\nupdate.22", description.getSpannable().toString());
|
||||
assertEquals("update.13\nupdate.23", description.getSpannable().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void concat_dynamic_lines_and_static_lines() {
|
||||
AtomicInteger factoryCalls1 = new AtomicInteger();
|
||||
AtomicInteger factoryCalls2 = new AtomicInteger();
|
||||
UpdateDescription.StringFactory stringFactory1 = () -> "update." + factoryCalls1.incrementAndGet();
|
||||
UpdateDescription.StringFactory stringFactory2 = () -> "update." + factoryCalls2.incrementAndGet();
|
||||
UpdateDescription description1 = UpdateDescription.mentioning(Collections.singletonList(ServiceId.from(UUID.randomUUID())), stringFactory1, 0);
|
||||
UpdateDescription description2 = UpdateDescription.staticDescription("static", 0);
|
||||
UpdateDescription description3 = UpdateDescription.mentioning(Collections.singletonList(ServiceId.from(UUID.randomUUID())), stringFactory2, 0);
|
||||
AtomicInteger factoryCalls1 = new AtomicInteger();
|
||||
AtomicInteger factoryCalls2 = new AtomicInteger();
|
||||
UpdateDescription.SpannableFactory stringFactory1 = () -> new SpannableString("update." + factoryCalls1.incrementAndGet());
|
||||
UpdateDescription.SpannableFactory stringFactory2 = () -> new SpannableString("update." + factoryCalls2.incrementAndGet());
|
||||
UpdateDescription description1 = UpdateDescription.mentioning(Collections.singletonList(ServiceId.from(UUID.randomUUID())), stringFactory1, 0);
|
||||
UpdateDescription description2 = UpdateDescription.staticDescription("static", 0);
|
||||
UpdateDescription description3 = UpdateDescription.mentioning(Collections.singletonList(ServiceId.from(UUID.randomUUID())), stringFactory2, 0);
|
||||
|
||||
factoryCalls1.set(100);
|
||||
factoryCalls2.set(200);
|
||||
@@ -132,8 +140,8 @@ public final class UpdateDescriptionTest {
|
||||
|
||||
assertFalse(description.isStringStatic());
|
||||
|
||||
assertEquals("update.101\nstatic\nupdate.201", description.getString());
|
||||
assertEquals("update.102\nstatic\nupdate.202", description.getString());
|
||||
assertEquals("update.103\nstatic\nupdate.203", description.getString());
|
||||
assertEquals("update.101\nstatic\nupdate.201", description.getSpannable().toString());
|
||||
assertEquals("update.102\nstatic\nupdate.202", description.getSpannable().toString());
|
||||
assertEquals("update.103\nstatic\nupdate.203", description.getSpannable().toString());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user