mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-26 12:44:38 +00:00
Implement Stories feature behind flag.
Co-Authored-By: Greyson Parrelli <37311915+greyson-signal@users.noreply.github.com> Co-Authored-By: Rashad Sookram <95182499+rashad-signal@users.noreply.github.com>
This commit is contained in:
31
app/src/test/java/org/thoughtcrime/securesms/MockCursor.kt
Normal file
31
app/src/test/java/org/thoughtcrime/securesms/MockCursor.kt
Normal file
@@ -0,0 +1,31 @@
|
||||
package org.thoughtcrime.securesms
|
||||
|
||||
import android.database.Cursor
|
||||
|
||||
abstract class MockCursor : Cursor {
|
||||
|
||||
private var _position: Int = -1
|
||||
private var _count: Int = 0
|
||||
|
||||
override fun getPosition(): Int {
|
||||
return _position
|
||||
}
|
||||
|
||||
override fun moveToPosition(position: Int): Boolean {
|
||||
_position = position
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return _count
|
||||
}
|
||||
|
||||
override fun moveToNext(): Boolean {
|
||||
_position++
|
||||
if (_position >= count) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
package org.thoughtcrime.securesms.contacts.paged
|
||||
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.JUnit4
|
||||
import org.mockito.ArgumentMatchers.any
|
||||
import org.mockito.ArgumentMatchers.anyBoolean
|
||||
import org.mockito.ArgumentMatchers.anyInt
|
||||
import org.mockito.ArgumentMatchers.isNull
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.Mockito.`when`
|
||||
import org.thoughtcrime.securesms.MockCursor
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
|
||||
@RunWith(JUnit4::class)
|
||||
class ContactSearchPagedDataSourceTest {
|
||||
|
||||
private val repository = mock(ContactSearchPagedDataSourceRepository::class.java)
|
||||
private val cursor = mock(MockCursor::class.java)
|
||||
private val groupStoryData = ContactSearchData.Story(Recipient.UNKNOWN, 0)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
`when`(repository.getRecipientFromGroupCursor(cursor)).thenReturn(Recipient.UNKNOWN)
|
||||
`when`(repository.getRecipientFromRecipientCursor(cursor)).thenReturn(Recipient.UNKNOWN)
|
||||
`when`(repository.getRecipientFromThreadCursor(cursor)).thenReturn(Recipient.UNKNOWN)
|
||||
`when`(repository.getRecipientFromDistributionListCursor(cursor)).thenReturn(Recipient.UNKNOWN)
|
||||
`when`(cursor.moveToPosition(anyInt())).thenCallRealMethod()
|
||||
`when`(cursor.moveToNext()).thenCallRealMethod()
|
||||
`when`(cursor.position).thenCallRealMethod()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Given recentsWHeader and individualsWHeaderWExpand, when I size, then I expect 15`() {
|
||||
val testSubject = createTestSubject()
|
||||
Assert.assertEquals(15, testSubject.size())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Given recentsWHeader and individualsWHeaderWExpand, when I load 12, then I expect properly structured output`() {
|
||||
val testSubject = createTestSubject()
|
||||
val result = testSubject.load(0, 12) { false }
|
||||
|
||||
val expected = listOf(
|
||||
ContactSearchKey.Header(ContactSearchConfiguration.SectionKey.RECENTS),
|
||||
ContactSearchKey.KnownRecipient(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.KnownRecipient(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.KnownRecipient(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.KnownRecipient(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.KnownRecipient(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.KnownRecipient(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.KnownRecipient(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.KnownRecipient(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.KnownRecipient(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.KnownRecipient(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.Header(ContactSearchConfiguration.SectionKey.INDIVIDUALS)
|
||||
)
|
||||
|
||||
val resultKeys = result.map { it.contactSearchKey }
|
||||
|
||||
Assert.assertEquals(expected, resultKeys)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Given recentsWHeader and individualsWHeaderWExpand, when I load 10 with offset 5, then I expect properly structured output`() {
|
||||
val testSubject = createTestSubject()
|
||||
val result = testSubject.load(5, 10) { false }
|
||||
|
||||
val expected = listOf(
|
||||
ContactSearchKey.KnownRecipient(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.KnownRecipient(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.KnownRecipient(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.KnownRecipient(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.KnownRecipient(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.KnownRecipient(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.Header(ContactSearchConfiguration.SectionKey.INDIVIDUALS),
|
||||
ContactSearchKey.KnownRecipient(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.KnownRecipient(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.Expand(ContactSearchConfiguration.SectionKey.INDIVIDUALS)
|
||||
)
|
||||
|
||||
val resultKeys = result.map { it.contactSearchKey }
|
||||
|
||||
Assert.assertEquals(expected, resultKeys)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Given storiesWithHeaderAndExtras, when I load 11, then I expect properly structured output`() {
|
||||
val testSubject = createStoriesSubject()
|
||||
val result = testSubject.load(0, 12) { false }
|
||||
|
||||
val expected = listOf(
|
||||
ContactSearchKey.Header(ContactSearchConfiguration.SectionKey.STORIES),
|
||||
ContactSearchKey.Story(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.Story(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.Story(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.Story(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.Story(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.Story(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.Story(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.Story(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.Story(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.Story(RecipientId.UNKNOWN),
|
||||
ContactSearchKey.Story(RecipientId.UNKNOWN),
|
||||
)
|
||||
|
||||
val resultKeys = result.map { it.contactSearchKey }
|
||||
|
||||
Assert.assertEquals(expected, resultKeys)
|
||||
}
|
||||
|
||||
private fun createStoriesSubject(): ContactSearchPagedDataSource {
|
||||
val configuration = ContactSearchConfiguration.build {
|
||||
addSection(
|
||||
ContactSearchConfiguration.Section.Stories(
|
||||
groupStories = setOf(
|
||||
groupStoryData
|
||||
),
|
||||
includeHeader = true,
|
||||
expandConfig = ContactSearchConfiguration.ExpandConfig(isExpanded = true)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
`when`(repository.getStories(any())).thenReturn(cursor)
|
||||
`when`(repository.recipientNameContainsQuery(Recipient.UNKNOWN, null)).thenReturn(true)
|
||||
`when`(cursor.count).thenReturn(10)
|
||||
|
||||
return ContactSearchPagedDataSource(configuration, repository)
|
||||
}
|
||||
|
||||
private fun createTestSubject(): ContactSearchPagedDataSource {
|
||||
val recents = ContactSearchConfiguration.Section.Recents(
|
||||
includeHeader = true
|
||||
)
|
||||
|
||||
val configuration = ContactSearchConfiguration.build {
|
||||
addSection(recents)
|
||||
|
||||
addSection(
|
||||
ContactSearchConfiguration.Section.Individuals(
|
||||
includeHeader = true,
|
||||
includeSelf = false,
|
||||
transportType = ContactSearchConfiguration.TransportType.ALL,
|
||||
expandConfig = ContactSearchConfiguration.ExpandConfig(isExpanded = false)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
`when`(repository.getRecents(recents)).thenReturn(cursor)
|
||||
`when`(repository.queryNonGroupContacts(isNull(), anyBoolean())).thenReturn(cursor)
|
||||
`when`(cursor.count).thenReturn(10)
|
||||
|
||||
return ContactSearchPagedDataSource(configuration, repository)
|
||||
}
|
||||
}
|
||||
@@ -99,6 +99,7 @@ object RecipientDatabaseTestUtils {
|
||||
e164,
|
||||
email,
|
||||
groupId,
|
||||
null,
|
||||
groupType,
|
||||
blocked,
|
||||
muteUntil,
|
||||
@@ -130,6 +131,7 @@ object RecipientDatabaseTestUtils {
|
||||
Recipient.Capability.deserialize(Bitmask.read(capabilities, RecipientDatabase.Capabilities.SENDER_KEY, RecipientDatabase.Capabilities.BIT_LENGTH).toInt()),
|
||||
Recipient.Capability.deserialize(Bitmask.read(capabilities, RecipientDatabase.Capabilities.ANNOUNCEMENT_GROUPS, RecipientDatabase.Capabilities.BIT_LENGTH).toInt()),
|
||||
Recipient.Capability.deserialize(Bitmask.read(capabilities, RecipientDatabase.Capabilities.CHANGE_NUMBER, RecipientDatabase.Capabilities.BIT_LENGTH).toInt()),
|
||||
Recipient.Capability.deserialize(Bitmask.read(capabilities, RecipientDatabase.Capabilities.STORIES, RecipientDatabase.Capabilities.BIT_LENGTH).toInt()),
|
||||
insightBannerTier,
|
||||
storageId,
|
||||
mentionSetting,
|
||||
|
||||
@@ -34,6 +34,8 @@ object TestMms {
|
||||
expiresIn,
|
||||
viewOnce,
|
||||
distributionType,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
emptyList(),
|
||||
emptyList(),
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.thoughtcrime.securesms.payments.Payments;
|
||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
||||
import org.thoughtcrime.securesms.recipients.LiveRecipientCache;
|
||||
import org.thoughtcrime.securesms.revealable.ViewOnceMessageManager;
|
||||
import org.thoughtcrime.securesms.service.ExpiringStoriesManager;
|
||||
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
||||
import org.thoughtcrime.securesms.service.PendingRetryReceiptManager;
|
||||
import org.thoughtcrime.securesms.service.TrimThreadsByDateManager;
|
||||
@@ -121,6 +122,11 @@ public class MockApplicationDependencyProvider implements ApplicationDependencie
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ExpiringStoriesManager provideExpiringStoriesManager() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ExpiringMessageManager provideExpiringMessageManager() {
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user