diff --git a/app/src/test/java/org/thoughtcrime/securesms/database/RecipientDatabaseTestUtils.kt b/app/src/test/java/org/thoughtcrime/securesms/database/RecipientDatabaseTestUtils.kt new file mode 100644 index 0000000000..6e64858c48 --- /dev/null +++ b/app/src/test/java/org/thoughtcrime/securesms/database/RecipientDatabaseTestUtils.kt @@ -0,0 +1,137 @@ +package org.thoughtcrime.securesms.database + +import android.net.Uri +import org.signal.zkgroup.profiles.ProfileKeyCredential +import org.thoughtcrime.securesms.conversation.colors.AvatarColor +import org.thoughtcrime.securesms.conversation.colors.ChatColors +import org.thoughtcrime.securesms.groups.GroupId +import org.thoughtcrime.securesms.profiles.ProfileName +import org.thoughtcrime.securesms.recipients.Recipient +import org.thoughtcrime.securesms.recipients.RecipientDetails +import org.thoughtcrime.securesms.recipients.RecipientId +import org.thoughtcrime.securesms.wallpaper.ChatWallpaper +import org.whispersystems.libsignal.util.guava.Optional +import java.util.UUID +import kotlin.random.Random + +/** + * Test utilities to create recipients in different states. + */ +object RecipientDatabaseTestUtils { + + fun createRecipient( + resolved: Boolean = false, + groupName: String? = null, + groupAvatarId: Optional = Optional.absent(), + systemContact: Boolean = false, + isSelf: Boolean = false, + participants: List = listOf(), + recipientId: RecipientId = RecipientId.from(Random.nextLong()), + uuid: UUID? = UUID.randomUUID(), + username: String? = null, + e164: String? = null, + email: String? = null, + groupId: GroupId? = null, + groupType: RecipientDatabase.GroupType = RecipientDatabase.GroupType.NONE, + blocked: Boolean = false, + muteUntil: Long = -1, + messageVibrateState: RecipientDatabase.VibrateState = RecipientDatabase.VibrateState.DEFAULT, + callVibrateState: RecipientDatabase.VibrateState = RecipientDatabase.VibrateState.DEFAULT, + messageRingtone: Uri = Uri.EMPTY, + callRingtone: Uri = Uri.EMPTY, + defaultSubscriptionId: Int = 0, + expireMessages: Int = 0, + registered: RecipientDatabase.RegisteredState = RecipientDatabase.RegisteredState.REGISTERED, + profileKey: ByteArray = Random.nextBytes(32), + profileKeyCredential: ProfileKeyCredential? = null, + systemProfileName: ProfileName = ProfileName.EMPTY, + systemDisplayName: String? = null, + systemContactPhoto: String? = null, + systemPhoneLabel: String? = null, + systemContactUri: String? = null, + signalProfileName: ProfileName = ProfileName.EMPTY, + signalProfileAvatar: String? = null, + hasProfileImage: Boolean = false, + profileSharing: Boolean = false, + lastProfileFetch: Long = 0L, + notificationChannel: String? = null, + unidentifiedAccessMode: RecipientDatabase.UnidentifiedAccessMode = RecipientDatabase.UnidentifiedAccessMode.UNKNOWN, + forceSmsSelection: Boolean = false, + capabilities: Long = 0L, + insightBannerTier: RecipientDatabase.InsightsBannerTier = RecipientDatabase.InsightsBannerTier.NO_TIER, + storageId: ByteArray? = null, + mentionSetting: RecipientDatabase.MentionSetting = RecipientDatabase.MentionSetting.ALWAYS_NOTIFY, + wallpaper: ChatWallpaper? = null, + chatColors: ChatColors? = null, + avatarColor: AvatarColor = AvatarColor.BLUE, + about: String? = null, + aboutEmoji: String? = null, + syncExtras: RecipientDatabase.RecipientSettings.SyncExtras = RecipientDatabase.RecipientSettings.SyncExtras( + null, + null, + null, + IdentityDatabase.VerifiedStatus.DEFAULT, + false, + false + ), + extras: Recipient.Extras? = null, + hasGroupsInCommon: Boolean = false + ): Recipient = Recipient( + recipientId, + RecipientDetails( + groupName, + systemDisplayName, + groupAvatarId, + systemContact, + isSelf, + registered, + RecipientDatabase.RecipientSettings( + recipientId, + uuid, + username, + e164, + email, + groupId, + groupType, + blocked, + muteUntil, + messageVibrateState, + callVibrateState, + messageRingtone, + callRingtone, + defaultSubscriptionId, + expireMessages, + registered, + profileKey, + profileKeyCredential, + systemProfileName, + systemDisplayName, + systemContactPhoto, + systemPhoneLabel, + systemContactUri, + signalProfileName, + signalProfileAvatar, + hasProfileImage, + profileSharing, + lastProfileFetch, + notificationChannel, + unidentifiedAccessMode, + forceSmsSelection, + capabilities, + insightBannerTier, + storageId, + mentionSetting, + wallpaper, + chatColors, + avatarColor, + about, + aboutEmoji, + syncExtras, + extras, + hasGroupsInCommon + ), + participants + ), + resolved + ) +} diff --git a/app/src/test/java/org/thoughtcrime/securesms/recipients/BaseRecipientTest.kt b/app/src/test/java/org/thoughtcrime/securesms/recipients/BaseRecipientTest.kt new file mode 100644 index 0000000000..393e03a83b --- /dev/null +++ b/app/src/test/java/org/thoughtcrime/securesms/recipients/BaseRecipientTest.kt @@ -0,0 +1,42 @@ +package org.thoughtcrime.securesms.recipients + +import android.app.Application +import androidx.test.core.app.ApplicationProvider +import org.junit.Before +import org.junit.Rule +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers +import org.powermock.api.mockito.PowerMockito +import org.powermock.core.classloader.annotations.PowerMockIgnore +import org.powermock.core.classloader.annotations.PrepareForTest +import org.powermock.modules.junit4.rule.PowerMockRule +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider +import org.thoughtcrime.securesms.dependencies.ApplicationDependencies +import org.thoughtcrime.securesms.keyvalue.ChatColorsValues +import org.thoughtcrime.securesms.keyvalue.SignalStore +import org.thoughtcrime.securesms.keyvalue.WallpaperValues +import java.io.IOException + +@RunWith(RobolectricTestRunner::class) +@Config(manifest = Config.NONE, application = Application::class) +@PowerMockIgnore("org.mockito.*", "org.robolectric.*", "android.*", "androidx.*") +@PrepareForTest(ApplicationDependencies::class, AttachmentSecretProvider::class, SignalStore::class, WallpaperValues::class, ChatColorsValues::class) +abstract class BaseRecipientTest { + @Rule + @JvmField + var rule = PowerMockRule() + + @Before + fun superSetUp() { + val application = ApplicationProvider.getApplicationContext() + + PowerMockito.mockStatic(ApplicationDependencies::class.java) + PowerMockito.`when`(ApplicationDependencies.getApplication()).thenReturn(application) + PowerMockito.mockStatic(AttachmentSecretProvider::class.java) + PowerMockito.`when`(AttachmentSecretProvider.getInstance(ArgumentMatchers.any())).thenThrow(IOException::class.java) + PowerMockito.whenNew(SignalStore::class.java).withAnyArguments().thenReturn(null) + PowerMockito.mockStatic(SignalStore::class.java) + } +} diff --git a/app/src/test/java/org/thoughtcrime/securesms/recipients/Recipient_getChatColorsTest.kt b/app/src/test/java/org/thoughtcrime/securesms/recipients/Recipient_getChatColorsTest.kt new file mode 100644 index 0000000000..fda40dc303 --- /dev/null +++ b/app/src/test/java/org/thoughtcrime/securesms/recipients/Recipient_getChatColorsTest.kt @@ -0,0 +1,219 @@ +package org.thoughtcrime.securesms.recipients + +import android.graphics.Color +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.powermock.api.mockito.PowerMockito +import org.thoughtcrime.securesms.conversation.colors.ChatColors +import org.thoughtcrime.securesms.conversation.colors.ChatColorsPalette +import org.thoughtcrime.securesms.database.RecipientDatabaseTestUtils.createRecipient +import org.thoughtcrime.securesms.keyvalue.ChatColorsValues +import org.thoughtcrime.securesms.keyvalue.SignalStore +import org.thoughtcrime.securesms.keyvalue.WallpaperValues +import org.thoughtcrime.securesms.wallpaper.ChatWallpaper + +@Suppress("ClassName") +class Recipient_getChatColorsTest : BaseRecipientTest() { + + private val defaultChatColors = ChatColorsPalette.Bubbles.default.withId(ChatColors.Id.Auto) + private val globalWallpaperChatColor = ChatColors.forColor(ChatColors.Id.BuiltIn, Color.RED) + private val globalChatColor = ChatColors.forColor(ChatColors.Id.BuiltIn, Color.GREEN) + + private lateinit var wallpaperValues: WallpaperValues + private lateinit var chatColorsValues: ChatColorsValues + + @Before + fun setUp() { + wallpaperValues = PowerMockito.mock(WallpaperValues::class.java) + chatColorsValues = PowerMockito.mock(ChatColorsValues::class.java) + + val globalWallpaper = createWallpaper(globalWallpaperChatColor) + PowerMockito.`when`(wallpaperValues.wallpaper).thenReturn(globalWallpaper) + PowerMockito.`when`(chatColorsValues.chatColors).thenReturn(globalChatColor) + PowerMockito.`when`(SignalStore.wallpaper()).thenReturn(wallpaperValues) + PowerMockito.`when`(SignalStore.chatColorsValues()).thenReturn(chatColorsValues) + } + + @Test + fun `Given recipient has custom chat color set, when I getChatColors, then I expect the custom chat color`() { + // GIVEN + val expected = ChatColors.forColor(ChatColors.Id.Custom(12), Color.BLACK) + val recipient = createRecipient(chatColors = expected) + + // WHEN + val actual = recipient.chatColors + + // THEN + assertEquals(expected, actual) + } + + @Test + fun `Given recipient has built in chat color set, when I getChatColors, then I expect the custom chat color`() { + // GIVEN + val expected = ChatColors.forColor(ChatColors.Id.BuiltIn, Color.BLACK) + val recipient = createRecipient(chatColors = expected) + + // WHEN + val actual = recipient.chatColors + + // THEN + assertEquals(expected, actual) + } + + @Test + fun `Given recipient has auto chat color set and wallpaper set, when I getChatColors, then I expect the wallpaper chat color`() { + // GIVEN + val auto = ChatColors.forColor(ChatColors.Id.Auto, Color.BLACK) + val expected = ChatColors.forColor(ChatColors.Id.BuiltIn, Color.WHITE) + val wallpaper = createWallpaper(chatColors = expected) + val recipient = createRecipient(chatColors = auto, wallpaper = wallpaper) + + // WHEN + val actual = recipient.chatColors + + // THEN + assertEquals(expected, actual) + } + + @Test + fun `Given recipient has auto chat color set and no wallpaper set and global wallpaper set, when I getChatColors, then I expect the global wallpaper chat color`() { + // GIVEN + val auto = ChatColors.forColor(ChatColors.Id.Auto, Color.BLACK) + val recipient = createRecipient(chatColors = auto) + + // WHEN + val actual = recipient.chatColors + + // THEN + assertEquals(globalWallpaperChatColor, actual) + } + + @Test + fun `Given recipient has auto chat color set and no wallpaper set and no global wallpaper set, when I getChatColors, then I expect the default chat color`() { + // GIVEN + PowerMockito.`when`(wallpaperValues.wallpaper).thenReturn(null) + val auto = ChatColors.forColor(ChatColors.Id.Auto, Color.BLACK) + val recipient = createRecipient(chatColors = auto) + + // WHEN + val actual = recipient.chatColors + + // THEN + assertEquals(defaultChatColors, actual) + } + + @Test + fun `Given recipient has no chat color set and there is a custom global chat color, when I getChatColors, then I expect the global chat color`() { + // GIVEN + val expected = globalChatColor.withId(ChatColors.Id.Custom(12)) + PowerMockito.`when`(chatColorsValues.chatColors).thenReturn(expected) + val recipient = createRecipient() + + // WHEN + val actual = recipient.chatColors + + // THEN + assertEquals(expected, actual) + } + + @Test + fun `Given recipient has no chat color set and there is a built in global chat color, when I getChatColors, then I expect the global chat color`() { + // GIVEN + val recipient = createRecipient() + + // WHEN + val actual = recipient.chatColors + + // THEN + assertEquals(globalChatColor, actual) + } + + @Test + fun `Given recipient has no chat color set and there is an auto global chat color and the recipient has a wallpaper, when I getChatColors, then I expect the wallpaper chat color`() { + // GIVEN + PowerMockito.`when`(chatColorsValues.chatColors).thenReturn(globalChatColor.withId(ChatColors.Id.Auto)) + val color = ChatColors.forColor(ChatColors.Id.BuiltIn, Color.CYAN) + val recipient = createRecipient(wallpaper = createWallpaper(color)) + + // WHEN + val actual = recipient.chatColors + + // THEN + assertEquals(color, actual) + } + + @Test + fun `Given recipient has no chat color set and there is no global chat color and the recipient has a wallpaper, when I getChatColors, then I expect the wallpaper chat color`() { + // GIVEN + PowerMockito.`when`(chatColorsValues.chatColors).thenReturn(null) + val color = ChatColors.forColor(ChatColors.Id.BuiltIn, Color.CYAN) + val recipient = createRecipient(wallpaper = createWallpaper(color)) + + // WHEN + val actual = recipient.chatColors + + // THEN + assertEquals(color, actual) + } + + @Test + fun `Given recipient has no chat color set and there is an auto global chat color and the recipient has no wallpaper and global wallpaper set, when I getChatColors, then I expect the global wallpaper chat color`() { + // GIVEN + PowerMockito.`when`(chatColorsValues.chatColors).thenReturn(globalChatColor.withId(ChatColors.Id.Auto)) + val recipient = createRecipient() + + // WHEN + val actual = recipient.chatColors + + // THEN + assertEquals(globalWallpaperChatColor, actual) + } + + @Test + fun `Given recipient has no chat color set and there is no global chat color and the recipient has no wallpaper and global wallpaper set, when I getChatColors, then I expect the global wallpaper chat color`() { + // GIVEN + PowerMockito.`when`(chatColorsValues.chatColors).thenReturn(null) + val recipient = createRecipient() + + // WHEN + val actual = recipient.chatColors + + // THEN + assertEquals(globalWallpaperChatColor, actual) + } + + @Test + fun `Given no recipient colors and auto global colors and no wallpaper set, when I getChatColors, then I expect default blue`() { + // GIVEN + PowerMockito.`when`(wallpaperValues.wallpaper).thenReturn(null) + PowerMockito.`when`(chatColorsValues.chatColors).thenReturn(globalChatColor.withId(ChatColors.Id.Auto)) + val recipient = createRecipient() + + // WHEN + val actual = recipient.chatColors + + // THEN + assertEquals(defaultChatColors, actual) + } + + @Test + fun `Given no colors or wallpaper set, when I getChatColors, then I expect default blue`() { + // GIVEN + PowerMockito.`when`(wallpaperValues.wallpaper).thenReturn(null) + PowerMockito.`when`(chatColorsValues.chatColors).thenReturn(null) + val recipient = createRecipient() + + // WHEN + val actual = recipient.chatColors + + // THEN + assertEquals(defaultChatColors, actual) + } + + private fun createWallpaper( + chatColors: ChatColors? + ): ChatWallpaper = PowerMockito.mock(ChatWallpaper::class.java).apply { + PowerMockito.`when`(autoChatColors).thenReturn(chatColors) + } +}