Split MatrixRoom into BaseRoom and JoinedRoom (#4561)

`JoinedRoom` will now contain both a mandatory live timeline reference and all the functionality associated to it.

`BaseRoom` on the other hand will contain only functionality that's shared for both joined and not joined rooms.

`NotJoinedRoom` is a wrapper around `RoomPreviewInfo` data and a possible local `BaseRoom`, if it exists.

The `RustRoomFactory` cache is now gone since the persistent event cache should have the same effect.
This commit is contained in:
Jorge Martin Espinosa 2025-04-23 15:53:40 +02:00 committed by GitHub
parent 91cb84ce8d
commit 619aa6f2de
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
193 changed files with 2921 additions and 2567 deletions

View file

@ -69,7 +69,7 @@ import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.api.permalink.PermalinkData
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.alias.matches
import io.element.android.libraries.matrix.api.room.joinedRoomMembers
import io.element.android.libraries.matrix.api.timeline.Timeline
@ -101,7 +101,7 @@ class MessagesFlowNode @AssistedInject constructor(
private val mediaViewerEntryPoint: MediaViewerEntryPoint,
private val analyticsService: AnalyticsService,
private val locationService: LocationService,
private val room: MatrixRoom,
private val room: BaseRoom,
private val roomMemberProfilesCache: RoomMemberProfilesCache,
private val roomNamesCache: RoomNamesCache,
private val mentionSpanUpdater: MentionSpanUpdater,

View file

@ -53,7 +53,7 @@ import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.permalink.PermalinkData
import io.element.android.libraries.matrix.api.permalink.PermalinkParser
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.alias.matches
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
import io.element.android.libraries.mediaplayer.api.MediaPlayer
@ -67,7 +67,7 @@ class MessagesNode @AssistedInject constructor(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
private val coroutineScope: CoroutineScope,
private val room: MatrixRoom,
private val room: BaseRoom,
private val analyticsService: AnalyticsService,
messageComposerPresenterFactory: MessageComposerPresenter.Factory,
timelinePresenterFactory: TimelinePresenter.Factory,

View file

@ -65,10 +65,10 @@ import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import io.element.android.libraries.matrix.api.permalink.PermalinkParser
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.MessageEventType
import io.element.android.libraries.matrix.api.room.RoomInfo
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.isDm
import io.element.android.libraries.matrix.api.room.powerlevels.canPinUnpin
import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOther
@ -90,7 +90,7 @@ import timber.log.Timber
class MessagesPresenter @AssistedInject constructor(
@Assisted private val navigator: MessagesNavigator,
private val room: MatrixRoom,
private val room: JoinedRoom,
@Assisted private val composerPresenter: Presenter<MessageComposerState>,
private val voiceMessageComposerPresenter: Presenter<VoiceMessageComposerState>,
@Assisted private val timelinePresenter: Presenter<TimelineState>,
@ -279,7 +279,7 @@ class MessagesPresenter @AssistedInject constructor(
}
}
private fun MatrixRoomInfo.avatarData(): AvatarData {
private fun RoomInfo.avatarData(): AvatarData {
return AvatarData(
id = id.value,
name = name,
@ -288,7 +288,7 @@ class MessagesPresenter @AssistedInject constructor(
)
}
private fun MatrixRoomInfo.heroes(): List<AvatarData> {
private fun RoomInfo.heroes(): List<AvatarData> {
return heroes.map { user ->
user.getAvatarData(size = AvatarSize.TimelineRoom)
}
@ -382,8 +382,8 @@ class MessagesPresenter @AssistedInject constructor(
inviteProgress.value = AsyncData.Loading()
runCatching {
val memberList = when (val memberState = room.membersStateFlow.value) {
is MatrixRoomMembersState.Ready -> memberState.roomMembers
is MatrixRoomMembersState.Error -> memberState.prevRoomMembers.orEmpty()
is RoomMembersState.Ready -> memberState.roomMembers
is RoomMembersState.Error -> memberState.prevRoomMembers.orEmpty()
else -> emptyList()
}

View file

@ -43,7 +43,7 @@ import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
@ -63,7 +63,7 @@ class DefaultActionListPresenter @AssistedInject constructor(
private val postProcessor: TimelineItemActionPostProcessor,
private val appPreferencesStore: AppPreferencesStore,
private val isPinnedMessagesFeatureEnabled: IsPinnedMessagesFeatureEnabled,
private val room: MatrixRoom,
private val room: BaseRoom,
private val userSendFailureFactory: VerifiedUserSendFailureFactory,
private val featureFlagService: FeatureFlagService,
private val dateFormatter: DateFormatter,

View file

@ -14,7 +14,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.ui.room.observeRoomMemberIdentityStateChange
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.CoroutineScope
@ -23,7 +23,7 @@ import timber.log.Timber
import javax.inject.Inject
class IdentityChangeStatePresenter @Inject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
private val encryptionService: EncryptionService,
) : Presenter<IdentityChangeState> {
@Composable

View file

@ -7,12 +7,12 @@
package io.element.android.features.messages.impl.crypto.sendfailure
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
import javax.inject.Inject
class VerifiedUserSendFailureFactory @Inject constructor(
private val room: MatrixRoom,
private val room: BaseRoom,
) {
suspend fun create(
sendState: LocalEventSendState?,

View file

@ -19,13 +19,13 @@ import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUser
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.architecture.runUpdatingState
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
import kotlinx.coroutines.launch
import javax.inject.Inject
class ResolveVerifiedUserSendFailurePresenter @Inject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
private val verifiedUserSendFailureFactory: VerifiedUserSendFailureFactory,
) : Presenter<ResolveVerifiedUserSendFailureState> {
@Composable

View file

@ -10,7 +10,7 @@ package io.element.android.features.messages.impl.crypto.sendfailure.resolve
import androidx.compose.runtime.mutableStateOf
import io.element.android.libraries.matrix.api.core.SendHandle
import io.element.android.libraries.matrix.api.core.TransactionId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
import timber.log.Timber
@ -21,7 +21,7 @@ import timber.log.Timber
* This way, the user can resolve and resend the message for each user concerned, one by one.
*/
class VerifiedUserSendFailureResolver(
private val room: MatrixRoom,
private val room: JoinedRoom,
private val transactionId: TransactionId,
private val sendHandle: SendHandle,
private val iterator: VerifiedUserSendFailureIterator,

View file

@ -21,7 +21,7 @@ class MatrixComposerDraftStore @Inject constructor(
private val client: MatrixClient,
) : ComposerDraftStore {
override suspend fun loadDraft(roomId: RoomId): ComposerDraft? {
return client.getRoom(roomId)?.let { room ->
return client.getRoom(roomId)?.use { room ->
room.loadComposerDraft()
.onFailure {
Timber.e(it, "Failed to load composer draft for room $roomId")
@ -35,7 +35,7 @@ class MatrixComposerDraftStore @Inject constructor(
}
override suspend fun updateDraft(roomId: RoomId, draft: ComposerDraft?) {
client.getRoom(roomId)?.let { room ->
client.getRoom(roomId)?.use { room ->
val updateDraftResult = if (draft == null) {
room.clearComposerDraft()
} else {

View file

@ -49,7 +49,7 @@ import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder
import io.element.android.libraries.matrix.api.permalink.PermalinkParser
import io.element.android.libraries.matrix.api.room.IntentionalMention
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.draft.ComposerDraft
import io.element.android.libraries.matrix.api.room.draft.ComposerDraftType
import io.element.android.libraries.matrix.api.room.isDm
@ -98,7 +98,7 @@ import io.element.android.libraries.core.mimetype.MimeTypes.Any as AnyMimeTypes
class MessageComposerPresenter @AssistedInject constructor(
@Assisted private val navigator: MessagesNavigator,
private val appCoroutineScope: CoroutineScope,
private val room: MatrixRoom,
private val room: JoinedRoom,
private val mediaPickerProvider: PickerProvider,
private val featureFlagService: FeatureFlagService,
private val sessionPreferencesStore: SessionPreferencesStore,

View file

@ -9,8 +9,8 @@ package io.element.android.features.messages.impl.messagecomposer.suggestions
import io.element.android.libraries.core.data.filterUpTo
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembershipState
import io.element.android.libraries.matrix.api.room.roomMembers
import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion
@ -33,7 +33,7 @@ class SuggestionsProcessor @Inject constructor() {
*/
suspend fun process(
suggestion: Suggestion?,
roomMembersState: MatrixRoomMembersState,
roomMembersState: RoomMembersState,
roomAliasSuggestions: List<RoomAliasSuggestion>,
currentUserId: UserId,
canSendRoomMention: suspend () -> Boolean,

View file

@ -15,7 +15,7 @@ import io.element.android.libraries.di.SingleIn
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.room.CreateTimelineParams
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.sync.SyncService
import io.element.android.libraries.matrix.api.timeline.Timeline
import io.element.android.libraries.matrix.api.timeline.TimelineProvider
@ -33,7 +33,7 @@ import javax.inject.Inject
@SingleIn(RoomScope::class)
class PinnedEventsTimelineProvider @Inject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
private val syncService: SyncService,
private val featureFlagService: FeatureFlagService,
private val dispatchers: CoroutineDispatchers,
@ -62,6 +62,7 @@ class PinnedEventsTimelineProvider @Inject constructor(
}
}
.launchIn(scope)
.invokeOnCompletion { timelineStateFlow.value.dataOrNull()?.close() }
}
private suspend fun onActive() = coroutineScope {

View file

@ -20,7 +20,7 @@ import androidx.compose.runtime.setValue
import io.element.android.features.messages.impl.pinned.PinnedEventsTimelineProvider
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.ExperimentalCoroutinesApi
@ -32,7 +32,7 @@ import kotlinx.coroutines.flow.onEach
import javax.inject.Inject
class PinnedMessagesBannerPresenter @Inject constructor(
private val room: MatrixRoom,
private val room: BaseRoom,
private val itemFactory: PinnedMessagesBannerItemFactory,
private val pinnedEventsTimelineProvider: PinnedEventsTimelineProvider,
) : Presenter<PinnedMessagesBannerState> {

View file

@ -38,7 +38,7 @@ import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.powerlevels.canPinUnpin
import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOther
import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOwn
@ -60,7 +60,7 @@ import timber.log.Timber
class PinnedMessagesListPresenter @AssistedInject constructor(
@Assisted private val navigator: PinnedMessagesListNavigator,
private val room: MatrixRoom,
private val room: JoinedRoom,
timelineItemsFactoryCreator: TimelineItemsFactory.Creator,
private val timelineProvider: PinnedEventsTimelineProvider,
private val timelineProtectionPresenter: Presenter<TimelineProtectionState>,

View file

@ -25,13 +25,13 @@ import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatch
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
class ReportMessagePresenter @AssistedInject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
@Assisted private val inputs: Inputs,
private val snackbarDispatcher: SnackbarDispatcher,
) : Presenter<ReportMessageState> {

View file

@ -12,7 +12,7 @@ import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.di.SingleIn
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.room.CreateTimelineParams
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.Timeline
import io.element.android.libraries.matrix.api.timeline.TimelineProvider
@ -42,7 +42,7 @@ import javax.inject.Inject
@SingleIn(RoomScope::class)
@ContributesBinding(RoomScope::class, boundType = TimelineProvider::class)
class TimelineController @Inject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
) : Closeable, TimelineProvider {
private val coroutineScope = CoroutineScope(SupervisorJob())

View file

@ -38,7 +38,7 @@ import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.MessageEventType
import io.element.android.libraries.matrix.api.room.isDm
import io.element.android.libraries.matrix.api.room.roomMembers
@ -62,7 +62,7 @@ const val FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS = 200L
class TimelinePresenter @AssistedInject constructor(
timelineItemsFactoryCreator: TimelineItemsFactory.Creator,
private val room: MatrixRoom,
private val room: JoinedRoom,
private val dispatchers: CoroutineDispatchers,
private val appScope: CoroutineScope,
@Assisted private val navigator: MessagesNavigator,

View file

@ -15,7 +15,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.roomMembers
import io.element.android.libraries.matrix.api.user.MatrixUser
@ -24,7 +24,7 @@ import kotlinx.collections.immutable.toImmutableList
import javax.inject.Inject
class ReactionSummaryPresenter @Inject constructor(
private val room: MatrixRoom,
private val room: BaseRoom,
) : Presenter<ReactionSummaryState> {
@Composable
override fun present(): ReactionSummaryState {

View file

@ -13,19 +13,18 @@ import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.media.MediaPreviewValue
import io.element.android.libraries.matrix.api.media.isPreviewEnabled
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import kotlinx.collections.immutable.toImmutableSet
import javax.inject.Inject
class TimelineProtectionPresenter @Inject constructor(
private val appPreferencesStore: AppPreferencesStore,
private val room: MatrixRoom,
private val room: BaseRoom,
) : Presenter<TimelineProtectionState> {
private val allowedEvents = mutableStateOf<Set<EventId>>(setOf())

View file

@ -18,7 +18,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.roomMembers
import io.element.android.libraries.preferences.api.store.SessionPreferencesStore
@ -32,7 +32,7 @@ import kotlinx.coroutines.flow.onEach
import javax.inject.Inject
class TypingNotificationPresenter @Inject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
private val sessionPreferencesStore: SessionPreferencesStore,
) : Presenter<TypingNotificationState> {
@Composable

View file

@ -51,9 +51,8 @@ import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.api.permalink.PermalinkParser
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.MessageEventType
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembershipState
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId
@ -70,7 +69,8 @@ import io.element.android.libraries.matrix.test.A_USER_ID_2
import io.element.android.libraries.matrix.test.core.aBuildMeta
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.matrix.test.room.aRoomMember
import io.element.android.libraries.matrix.test.sync.FakeSyncService
@ -128,19 +128,21 @@ class MessagesPresenterTest {
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun `present - check that the room's unread flag is removed`() = runTest {
val room = FakeMatrixRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
),
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
)
assertThat(room.markAsReadCalls).isEmpty()
val presenter = createMessagesPresenter(matrixRoom = room)
assertThat(room.baseRoom.markAsReadCalls).isEmpty()
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
runCurrent()
assertThat(room.setUnreadFlagCalls).isEqualTo(listOf(false))
assertThat(room.baseRoom.setUnreadFlagCalls).isEqualTo(listOf(false))
cancelAndIgnoreRemainingEvents()
}
}
@ -155,16 +157,18 @@ class MessagesPresenterTest {
val timeline = FakeTimeline().apply {
this.toggleReactionLambda = toggleReactionSuccess
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
),
liveTimeline = timeline,
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
)
val presenter = createMessagesPresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers)
val presenter = createMessagesPresenter(joinedRoom = room, coroutineDispatchers = coroutineDispatchers)
presenter.testWithLifecycleOwner {
skipItems(1)
val initialState = awaitItem()
@ -189,16 +193,18 @@ class MessagesPresenterTest {
val timeline = FakeTimeline().apply {
this.toggleReactionLambda = toggleReactionSuccess
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
),
liveTimeline = timeline,
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
)
val presenter = createMessagesPresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers)
val presenter = createMessagesPresenter(joinedRoom = room, coroutineDispatchers = coroutineDispatchers)
presenter.testWithLifecycleOwner {
val initialState = awaitItem()
initialState.eventSink(MessagesEvents.ToggleReaction("👍", AN_EVENT_ID.toEventOrTransactionId()))
@ -245,18 +251,20 @@ class MessagesPresenterTest {
fun `present - handle action copy link`() = runTest {
val clipboardHelper = FakeClipboardHelper()
val event = aMessageEvent()
val matrixRoom = FakeMatrixRoom(
eventPermalinkResult = { Result.success("a link") },
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
eventPermalinkResult = { Result.success("a link") },
),
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
)
val presenter = createMessagesPresenter(
clipboardHelper = clipboardHelper,
matrixRoom = matrixRoom,
joinedRoom = room,
)
presenter.testWithLifecycleOwner {
val initialState = awaitItem()
@ -466,20 +474,22 @@ class MessagesPresenterTest {
val coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
val liveTimeline = FakeTimeline()
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
),
liveTimeline = liveTimeline,
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
)
val redactEventLambda = lambdaRecorder { _: EventOrTransactionId, _: String? -> Result.success(Unit) }
liveTimeline.redactEventLambda = redactEventLambda
val presenter = createMessagesPresenter(
matrixRoom = matrixRoom,
joinedRoom = joinedRoom,
coroutineDispatchers = coroutineDispatchers,
)
presenter.testWithLifecycleOwner {
@ -535,18 +545,19 @@ class MessagesPresenterTest {
@Test
fun `present - shows prompt to reinvite users in DM`() = runTest {
val room = FakeMatrixRoom(
sessionId = A_SESSION_ID,
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(isDirect = true, joinedMembersCount = 1, activeMembersCount = 1))
},
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(isDirect = true, joinedMembersCount = 1, activeMembersCount = 1))
}
val presenter = createMessagesPresenter(matrixRoom = room)
)
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
val initialState = awaitItem()
// Initially the composer doesn't have focus, so we don't show the alert
@ -567,18 +578,19 @@ class MessagesPresenterTest {
@Test
fun `present - doesn't show reinvite prompt in non-direct room`() = runTest {
val room = FakeMatrixRoom(
sessionId = A_SESSION_ID,
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(isDirect = false, joinedMembersCount = 1, activeMembersCount = 1))
},
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(isDirect = false, joinedMembersCount = 1, activeMembersCount = 1))
}
val presenter = createMessagesPresenter(matrixRoom = room)
)
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
val initialState = awaitItem()
assertThat(initialState.showReinvitePrompt).isFalse()
@ -592,18 +604,19 @@ class MessagesPresenterTest {
@Test
fun `present - doesn't show reinvite prompt if other party is present`() = runTest {
val room = FakeMatrixRoom(
sessionId = A_SESSION_ID,
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(isDirect = true, joinedMembersCount = 2, activeMembersCount = 2))
},
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(isDirect = true, joinedMembersCount = 2, activeMembersCount = 2))
}
val presenter = createMessagesPresenter(matrixRoom = room)
)
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
val initialState = awaitItem()
assertThat(initialState.showReinvitePrompt).isFalse()
@ -618,25 +631,26 @@ class MessagesPresenterTest {
@Test
fun `present - handle reinviting other user when memberlist is ready`() = runTest {
val inviteUserResult = lambdaRecorder { _: UserId -> Result.success(Unit) }
val room = FakeMatrixRoom(
sessionId = A_SESSION_ID,
inviteUserResult = inviteUserResult,
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
),
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
inviteUserResult = inviteUserResult,
)
room.givenRoomMembersState(
MatrixRoomMembersState.Ready(
RoomMembersState.Ready(
persistentListOf(
aRoomMember(userId = A_SESSION_ID, membership = RoomMembershipState.JOIN),
aRoomMember(userId = A_SESSION_ID_2, membership = RoomMembershipState.LEAVE),
)
)
)
val presenter = createMessagesPresenter(matrixRoom = room)
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
val initialState = consumeItemsUntilTimeout().last()
initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Invite))
@ -652,18 +666,19 @@ class MessagesPresenterTest {
@Test
fun `present - handle reinviting other user when memberlist is error`() = runTest {
val inviteUserResult = lambdaRecorder { _: UserId -> Result.success(Unit) }
val room = FakeMatrixRoom(
sessionId = A_SESSION_ID,
inviteUserResult = inviteUserResult,
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
),
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
inviteUserResult = inviteUserResult,
)
room.givenRoomMembersState(
MatrixRoomMembersState.Error(
RoomMembersState.Error(
failure = Throwable(),
prevRoomMembers = persistentListOf(
aRoomMember(userId = A_SESSION_ID, membership = RoomMembershipState.JOIN),
@ -671,7 +686,7 @@ class MessagesPresenterTest {
)
)
)
val presenter = createMessagesPresenter(matrixRoom = room)
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
val initialState = consumeItemsUntilTimeout().last()
initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Invite))
@ -688,17 +703,18 @@ class MessagesPresenterTest {
@Test
fun `present - handle reinviting other user when memberlist is not ready`() = runTest {
val room = FakeMatrixRoom(
sessionId = A_SESSION_ID,
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
),
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
)
room.givenRoomMembersState(MatrixRoomMembersState.Unknown)
val presenter = createMessagesPresenter(matrixRoom = room)
room.givenRoomMembersState(RoomMembersState.Unknown)
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
val initialState = consumeItemsUntilTimeout().last()
initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Invite))
@ -712,25 +728,26 @@ class MessagesPresenterTest {
@Test
fun `present - handle reinviting other user when inviting fails`() = runTest {
val room = FakeMatrixRoom(
sessionId = A_SESSION_ID,
inviteUserResult = { Result.failure(Throwable("Oops!")) },
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
),
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
inviteUserResult = { Result.failure(Throwable("Oops!")) },
)
room.givenRoomMembersState(
MatrixRoomMembersState.Ready(
RoomMembersState.Ready(
persistentListOf(
aRoomMember(userId = A_SESSION_ID, membership = RoomMembershipState.JOIN),
aRoomMember(userId = A_SESSION_ID_2, membership = RoomMembershipState.LEAVE),
)
)
)
val presenter = createMessagesPresenter(matrixRoom = room)
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
val initialState = consumeItemsUntilTimeout().last()
initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Invite))
@ -749,21 +766,23 @@ class MessagesPresenterTest {
@Test
fun `present - permission to post`() = runTest {
val matrixRoom = FakeMatrixRoom(
canUserSendMessageResult = { _, messageEventType ->
when (messageEventType) {
MessageEventType.ROOM_MESSAGE -> Result.success(true)
MessageEventType.REACTION -> Result.success(true)
else -> lambdaError()
}
},
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
canUserSendMessageResult = { _, messageEventType ->
when (messageEventType) {
MessageEventType.ROOM_MESSAGE -> Result.success(true)
MessageEventType.REACTION -> Result.success(true)
else -> lambdaError()
}
},
),
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
)
val presenter = createMessagesPresenter(matrixRoom = matrixRoom)
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
skipItems(1)
val state = awaitItem()
@ -773,21 +792,23 @@ class MessagesPresenterTest {
@Test
fun `present - no permission to post`() = runTest {
val matrixRoom = FakeMatrixRoom(
canUserSendMessageResult = { _, messageEventType ->
when (messageEventType) {
MessageEventType.ROOM_MESSAGE -> Result.success(false)
MessageEventType.REACTION -> Result.success(false)
else -> lambdaError()
}
},
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
canUserSendMessageResult = { _, messageEventType ->
when (messageEventType) {
MessageEventType.ROOM_MESSAGE -> Result.success(false)
MessageEventType.REACTION -> Result.success(false)
else -> lambdaError()
}
},
),
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
)
val presenter = createMessagesPresenter(matrixRoom = matrixRoom)
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
// Default value
assertThat(awaitItem().userEventPermissions.canSendMessage).isTrue()
@ -797,15 +818,17 @@ class MessagesPresenterTest {
@Test
fun `present - permission to redact own`() = runTest {
val matrixRoom = FakeMatrixRoom(
canRedactOwnResult = { Result.success(true) },
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOtherResult = { Result.success(false) },
canUserJoinCallResult = { Result.success(true) },
val joinedRoom = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOtherResult = { Result.success(false) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
),
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
)
val presenter = createMessagesPresenter(matrixRoom = matrixRoom)
val presenter = createMessagesPresenter(joinedRoom = joinedRoom)
presenter.testWithLifecycleOwner {
val initialState = consumeItemsUntilPredicate { it.userEventPermissions.canRedactOwn }.last()
assertThat(initialState.userEventPermissions.canRedactOwn).isTrue()
@ -816,15 +839,17 @@ class MessagesPresenterTest {
@Test
fun `present - permission to redact other`() = runTest {
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOtherResult = { Result.success(true) },
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(false) },
canUserJoinCallResult = { Result.success(true) },
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
),
typingNoticeResult = { Result.success(Unit) },
)
val presenter = createMessagesPresenter(matrixRoom = matrixRoom)
val presenter = createMessagesPresenter(joinedRoom = joinedRoom)
presenter.testWithLifecycleOwner {
val initialState = consumeItemsUntilPredicate { it.userEventPermissions.canRedactOther }.last()
assertThat(initialState.userEventPermissions.canRedactOwn).isFalse()
@ -863,16 +888,18 @@ class MessagesPresenterTest {
val failurePinEventLambda = lambdaRecorder { _: EventId -> Result.failure<Boolean>(A_THROWABLE) }
val analyticsService = FakeAnalyticsService()
val timeline = FakeTimeline()
val room = FakeMatrixRoom(
liveTimeline = timeline,
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
),
liveTimeline = timeline,
typingNoticeResult = { Result.success(Unit) },
)
val presenter = createMessagesPresenter(matrixRoom = room, analyticsService = analyticsService)
val presenter = createMessagesPresenter(joinedRoom = room, analyticsService = analyticsService)
presenter.testWithLifecycleOwner {
val messageEvent = aMessageEvent(
content = aTimelineItemTextContent()
@ -901,16 +928,18 @@ class MessagesPresenterTest {
val failureUnpinEventLambda = lambdaRecorder { _: EventId -> Result.failure<Boolean>(A_THROWABLE) }
val timeline = FakeTimeline()
val analyticsService = FakeAnalyticsService()
val room = FakeMatrixRoom(
liveTimeline = timeline,
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
),
liveTimeline = timeline,
typingNoticeResult = { Result.success(Unit) },
)
val presenter = createMessagesPresenter(matrixRoom = room, analyticsService = analyticsService)
val presenter = createMessagesPresenter(joinedRoom = room, analyticsService = analyticsService)
presenter.testWithLifecycleOwner {
val messageEvent = aMessageEvent(
content = aTimelineItemTextContent()
@ -1058,17 +1087,19 @@ class MessagesPresenterTest {
val timeline = FakeTimeline().apply {
this.editCaptionLambda = editCaptionLambda
}
val room = FakeMatrixRoom(
liveTimeline = timeline,
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
),
liveTimeline = timeline,
typingNoticeResult = { Result.success(Unit) },
)
val presenter = createMessagesPresenter(
matrixRoom = room,
joinedRoom = room,
)
presenter.testWithLifecycleOwner {
skipItems(1)
@ -1094,21 +1125,23 @@ class MessagesPresenterTest {
@Test
fun `present - when room is encrypted and a DM, the DM user's identity state is fetched onResume`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
sessionId = A_SESSION_ID,
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
initialRoomInfo = aRoomInfo(isDirect = true, isEncrypted = true)
).apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(persistentListOf(aRoomMember(userId = A_SESSION_ID), aRoomMember(userId = A_USER_ID_2))))
}
givenRoomMembersState(RoomMembersState.Ready(persistentListOf(aRoomMember(userId = A_SESSION_ID), aRoomMember(userId = A_USER_ID_2))))
},
typingNoticeResult = { Result.success(Unit) },
)
val encryptionService = FakeEncryptionService(getUserIdentityResult = { Result.success(IdentityState.Verified) })
val presenter = createMessagesPresenter(matrixRoom = room, encryptionService = encryptionService)
val presenter = createMessagesPresenter(joinedRoom = room, encryptionService = encryptionService)
val lifecycleOwner = FakeLifecycleOwner()
presenter.testWithLifecycleOwner(lifecycleOwner) {
val initialState = awaitItem()
@ -1124,16 +1157,19 @@ class MessagesPresenterTest {
private fun TestScope.createMessagesPresenter(
coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers(),
matrixRoom: MatrixRoom = FakeMatrixRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
joinedRoom: FakeJoinedRoom = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(id = roomId, name = ""))
},
liveTimeline = FakeTimeline(),
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(id = roomId, name = ""))
},
),
navigator: FakeMessagesNavigator = FakeMessagesNavigator(),
featureFlagService: FeatureFlagService = FakeFeatureFlagService(),
clipboardHelper: FakeClipboardHelper = FakeClipboardHelper(),
@ -1150,7 +1186,7 @@ class MessagesPresenterTest {
actionListEventSink: (ActionListEvents) -> Unit = {},
): MessagesPresenter {
return MessagesPresenter(
room = matrixRoom,
room = joinedRoom,
composerPresenter = messageComposerPresenter,
voiceMessageComposerPresenter = { aVoiceMessageComposerState() },
timelinePresenter = { aTimelineState(eventSink = timelineEventSink) },
@ -1171,7 +1207,7 @@ class MessagesPresenterTest {
buildMeta = aBuildMeta(),
dispatchers = coroutineDispatchers,
htmlConverterProvider = FakeHtmlConverterProvider(),
timelineController = TimelineController(matrixRoom),
timelineController = TimelineController(joinedRoom),
permalinkParser = permalinkParser,
encryptionService = encryptionService,
analyticsService = analyticsService,

View file

@ -29,13 +29,13 @@ import io.element.android.features.poll.api.pollcontent.aPollAnswerItemList
import io.element.android.libraries.dateformatter.test.FakeDateFormatter
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_CAPTION
import io.element.android.libraries.matrix.test.A_MESSAGE
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore
import io.element.android.tests.testutils.WarmUpRule
@ -893,7 +893,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute message when event is already pinned`() = runTest {
val room = FakeMatrixRoom().apply {
val room = FakeBaseRoom().apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
}
val presenter = createActionListPresenter(
@ -1251,7 +1251,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for verified user send failure`() = runTest {
val room = FakeMatrixRoom(
val room = FakeBaseRoom(
userDisplayNameResult = { Result.success("Alice") }
)
val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = false, room = room)
@ -1279,7 +1279,7 @@ class ActionListPresenterTest {
private fun createActionListPresenter(
isDeveloperModeEnabled: Boolean,
isPinFeatureEnabled: Boolean,
room: MatrixRoom = FakeMatrixRoom(),
room: BaseRoom = FakeBaseRoom(),
allowCaption: Boolean = true,
): ActionListPresenter {
val preferencesStore = InMemoryAppPreferencesStore(isDeveloperModeEnabled = isDeveloperModeEnabled)

View file

@ -29,12 +29,12 @@ import io.element.android.libraries.matrix.api.media.FileInfo
import io.element.android.libraries.matrix.api.media.ImageInfo
import io.element.android.libraries.matrix.api.media.VideoInfo
import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.message.ReplyParameters
import io.element.android.libraries.matrix.test.A_CAPTION
import io.element.android.libraries.matrix.test.media.FakeMediaUploadHandler
import io.element.android.libraries.matrix.test.permalink.FakePermalinkBuilder
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.mediaupload.api.MediaPreProcessor
import io.element.android.libraries.mediaupload.api.MediaSender
import io.element.android.libraries.mediaupload.api.MediaUploadInfo
@ -110,7 +110,7 @@ class AttachmentsPreviewPresenterTest {
lambdaRecorder<File, FileInfo, String?, String?, ProgressCallback?, ReplyParameters?, Result<FakeMediaUploadHandler>> { _, _, _, _, _, _ ->
Result.success(FakeMediaUploadHandler())
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
progressCallbackValues = listOf(
Pair(0, 10),
Pair(5, 10),
@ -148,7 +148,7 @@ class AttachmentsPreviewPresenterTest {
lambdaRecorder<File, FileInfo, String?, String?, ProgressCallback?, ReplyParameters?, Result<FakeMediaUploadHandler>> { _, _, _, _, _, _ ->
Result.success(FakeMediaUploadHandler())
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
sendFileResult = sendFileResult,
)
val onDoneListener = lambdaRecorder<Unit> { }
@ -184,7 +184,7 @@ class AttachmentsPreviewPresenterTest {
lambdaRecorder<File, FileInfo, String?, String?, ProgressCallback?, ReplyParameters?, Result<FakeMediaUploadHandler>> { _, _, _, _, _, _ ->
Result.success(FakeMediaUploadHandler())
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
sendFileResult = sendFileResult,
)
val onDoneListener = lambdaRecorder<Unit> { }
@ -216,7 +216,7 @@ class AttachmentsPreviewPresenterTest {
@Test
fun `present - send media with pre-processing failure after user sends media`() = runTest {
val room = FakeMatrixRoom()
val room = FakeJoinedRoom()
val onDoneListener = lambdaRecorder<Unit> { }
val processLatch = CompletableDeferred<Unit>()
val presenter = createAttachmentsPreviewPresenter(
@ -242,7 +242,7 @@ class AttachmentsPreviewPresenterTest {
@Test
fun `present - send media with pre-processing failure before user sends media`() = runTest {
val room = FakeMatrixRoom()
val room = FakeJoinedRoom()
val onDoneListener = lambdaRecorder<Unit> { }
val processLatch = CompletableDeferred<Unit>()
val presenter = createAttachmentsPreviewPresenter(
@ -297,7 +297,7 @@ class AttachmentsPreviewPresenterTest {
val mediaPreProcessor = FakeMediaPreProcessor().apply {
givenImageResult()
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
sendImageResult = sendImageResult,
)
val onDoneListener = lambdaRecorder<Unit> { }
@ -339,7 +339,7 @@ class AttachmentsPreviewPresenterTest {
val mediaPreProcessor = FakeMediaPreProcessor().apply {
givenVideoResult()
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
sendVideoResult = sendVideoResult,
)
val onDoneListener = lambdaRecorder<Unit> { }
@ -381,7 +381,7 @@ class AttachmentsPreviewPresenterTest {
val mediaPreProcessor = FakeMediaPreProcessor().apply {
givenAudioResult()
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
sendAudioResult = sendAudioResult,
)
val onDoneListener = lambdaRecorder<Unit> { }
@ -418,7 +418,7 @@ class AttachmentsPreviewPresenterTest {
lambdaRecorder<File, FileInfo, String?, String?, ProgressCallback?, ReplyParameters?, Result<FakeMediaUploadHandler>> { _, _, _, _, _, _ ->
Result.failure(failure)
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
sendFileResult = sendFileResult,
)
val presenter = createAttachmentsPreviewPresenter(room = room, mediaUploadOnSendQueueEnabled = false)
@ -448,7 +448,7 @@ class AttachmentsPreviewPresenterTest {
Result.failure(failure)
}
val onDoneListenerResult = lambdaRecorder<Unit> {}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
sendFileResult = sendFileResult,
)
val presenter = createAttachmentsPreviewPresenter(room = room, mediaUploadOnSendQueueEnabled = true, onDoneListener = onDoneListenerResult)
@ -518,7 +518,7 @@ class AttachmentsPreviewPresenterTest {
localMedia: LocalMedia = aLocalMedia(
uri = mockMediaUrl,
),
room: MatrixRoom = FakeMatrixRoom(),
room: JoinedRoom = FakeJoinedRoom(),
permalinkBuilder: PermalinkBuilder = FakePermalinkBuilder(),
mediaPreProcessor: MediaPreProcessor = FakeMediaPreProcessor(),
temporaryUriDeleter: TemporaryUriDeleter = FakeTemporaryUriDeleter(),

View file

@ -13,12 +13,12 @@ import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import io.element.android.libraries.matrix.api.encryption.identity.IdentityStateChange
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.A_USER_ID_2
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.matrix.test.room.aRoomMember
import io.element.android.tests.testutils.WarmUpRule
@ -26,6 +26,7 @@ import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.lambda.value
import io.element.android.tests.testutils.test
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
@ -45,14 +46,15 @@ class IdentityChangeStatePresenterTest {
@Test
fun `present - when the room emits identity change, the presenter emits new state`() = runTest {
val room = FakeMatrixRoom().apply {
val identityStateChanges = MutableStateFlow(emptyList<IdentityStateChange>())
val room = FakeJoinedRoom(identityStateChangesFlow = identityStateChanges).apply {
givenRoomInfo(aRoomInfo(isEncrypted = true))
}
val presenter = createIdentityChangeStatePresenter(room)
presenter.test {
val initialState = awaitItem()
assertThat(initialState.roomMemberIdentityStateChanges).isEmpty()
room.emitIdentityStateChanges(
identityStateChanges.emit(
listOf(
IdentityStateChange(
userId = A_USER_ID_2,
@ -70,12 +72,16 @@ class IdentityChangeStatePresenterTest {
@Test
fun `present - when the clear room emits identity change, the presenter does not emit new state`() = runTest {
val room = FakeMatrixRoom(enableEncryptionResult = { Result.success(Unit) })
val identityStateChanges = MutableStateFlow(emptyList<IdentityStateChange>())
val room = FakeJoinedRoom(
identityStateChangesFlow = identityStateChanges,
enableEncryptionResult = { Result.success(Unit) }
)
val presenter = createIdentityChangeStatePresenter(room)
presenter.test {
val initialState = awaitItem()
assertThat(initialState.roomMemberIdentityStateChanges).isEmpty()
room.emitIdentityStateChanges(
identityStateChanges.emit(
listOf(
IdentityStateChange(
userId = A_USER_ID_2,
@ -100,9 +106,10 @@ class IdentityChangeStatePresenterTest {
@Test
fun `present - when the room emits identity change, the presenter emits new state with member details`() =
runTest {
val room = FakeMatrixRoom().apply {
val identityStateChanges = MutableStateFlow(emptyList<IdentityStateChange>())
val room = FakeJoinedRoom(identityStateChangesFlow = identityStateChanges).apply {
givenRoomMembersState(
MatrixRoomMembersState.Ready(
RoomMembersState.Ready(
listOf(
aRoomMember(
A_USER_ID_2,
@ -117,7 +124,7 @@ class IdentityChangeStatePresenterTest {
presenter.test {
val initialState = awaitItem()
assertThat(initialState.roomMemberIdentityStateChanges).isEmpty()
room.emitIdentityStateChanges(
identityStateChanges.emit(
listOf(
IdentityStateChange(
userId = A_USER_ID_2,
@ -166,7 +173,7 @@ class IdentityChangeStatePresenterTest {
}
private fun createIdentityChangeStatePresenter(
room: MatrixRoom = FakeMatrixRoom(),
room: JoinedRoom = FakeJoinedRoom(),
encryptionService: EncryptionService = FakeEncryptionService(),
): IdentityChangeStatePresenter {
return IdentityChangeStatePresenter(

View file

@ -13,13 +13,13 @@ import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUser
import io.element.android.features.messages.impl.fixtures.aMessageEvent
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_TRANSACTION_ID
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.A_USER_ID_2
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.test
import kotlinx.coroutines.test.runTest
@ -81,11 +81,13 @@ class ResolveVerifiedUserSendFailurePresenterTest {
@Test
fun `present - verified user unsigned device failure dismiss scenario`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
userDisplayNameResult = { userId ->
Result.success(userId.value)
},
)
)
val presenter = createResolveVerifiedUserSendFailurePresenter(room)
presenter.test {
val failedMessage = aVerifiedUserHasUnsignedDeviceFailedMessage()
@ -107,11 +109,13 @@ class ResolveVerifiedUserSendFailurePresenterTest {
@Test
fun `present - verified user unsigned device failure retry scenario`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
userDisplayNameResult = { userId ->
Result.success(userId.value)
},
)
)
val presenter = createResolveVerifiedUserSendFailurePresenter(room)
presenter.test {
val failedMessage = aVerifiedUserHasUnsignedDeviceFailedMessage()
@ -138,10 +142,12 @@ class ResolveVerifiedUserSendFailurePresenterTest {
@Test
fun `present - verified user unsigned device failure resolve and resend scenario`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
userDisplayNameResult = { userId ->
Result.success(userId.value)
},
),
ignoreDeviceTrustAndResendResult = { _, _ ->
Result.success(Unit)
},
@ -179,10 +185,12 @@ class ResolveVerifiedUserSendFailurePresenterTest {
@Test
fun `present - verified user unsigned device failure resolve and resend scenario with error`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
userDisplayNameResult = { userId ->
Result.success(userId.value)
},
),
ignoreDeviceTrustAndResendResult = { _, _ ->
Result.failure(Exception())
},
@ -212,11 +220,13 @@ class ResolveVerifiedUserSendFailurePresenterTest {
@Test
fun `present - verified user changed identity failure retry scenario`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
userDisplayNameResult = { userId ->
Result.success(userId.value)
},
)
)
val presenter = createResolveVerifiedUserSendFailurePresenter(room)
presenter.test {
val failedMessage = aVerifiedUserChangedIdentityMessage()
@ -243,10 +253,12 @@ class ResolveVerifiedUserSendFailurePresenterTest {
@Test
fun `present - verified user changed identity failure resolve and resend scenario`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
userDisplayNameResult = { userId ->
Result.success(userId.value)
},
),
withdrawVerificationAndResendResult = { _, _ ->
Result.success(Unit)
},
@ -284,10 +296,12 @@ class ResolveVerifiedUserSendFailurePresenterTest {
@Test
fun `present - verified user changed identity failure resolve and resend scenario with error`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
userDisplayNameResult = { userId ->
Result.success(userId.value)
},
),
withdrawVerificationAndResendResult = { _, _ ->
Result.failure(Exception())
},
@ -337,7 +351,7 @@ class ResolveVerifiedUserSendFailurePresenterTest {
}
private fun createResolveVerifiedUserSendFailurePresenter(
room: MatrixRoom = FakeMatrixRoom(),
room: FakeJoinedRoom = FakeJoinedRoom(),
): ResolveVerifiedUserSendFailurePresenter {
return ResolveVerifiedUserSendFailurePresenter(
room = room,

View file

@ -15,7 +15,7 @@ import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomSummary
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
import io.element.android.libraries.matrix.test.timeline.LiveTimelineProvider
@ -49,8 +49,8 @@ class ForwardMessagesPresenterTest {
val timeline = FakeTimeline().apply {
this.forwardEventLambda = forwardEventLambda
}
val room = FakeMatrixRoom(liveTimeline = timeline)
val presenter = aForwardMessagesPresenter(fakeMatrixRoom = room)
val room = FakeJoinedRoom(liveTimeline = timeline)
val presenter = aForwardMessagesPresenter(fakeRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -73,8 +73,8 @@ class ForwardMessagesPresenterTest {
val timeline = FakeTimeline().apply {
this.forwardEventLambda = forwardEventLambda
}
val room = FakeMatrixRoom(liveTimeline = timeline)
val presenter = aForwardMessagesPresenter(fakeMatrixRoom = room)
val room = FakeJoinedRoom(liveTimeline = timeline)
val presenter = aForwardMessagesPresenter(fakeRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -93,11 +93,11 @@ class ForwardMessagesPresenterTest {
private fun CoroutineScope.aForwardMessagesPresenter(
eventId: EventId = AN_EVENT_ID,
fakeMatrixRoom: FakeMatrixRoom = FakeMatrixRoom(),
fakeRoom: FakeJoinedRoom = FakeJoinedRoom(),
coroutineScope: CoroutineScope = this,
) = ForwardMessagesPresenter(
eventId = eventId.value,
timelineProvider = LiveTimelineProvider(fakeMatrixRoom),
timelineProvider = LiveTimelineProvider(fakeRoom),
appCoroutineScope = coroutineScope,
)
}

View file

@ -42,8 +42,8 @@ import io.element.android.libraries.matrix.api.media.VideoInfo
import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder
import io.element.android.libraries.matrix.api.permalink.PermalinkParser
import io.element.android.libraries.matrix.api.room.IntentionalMention
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembershipState
import io.element.android.libraries.matrix.api.room.draft.ComposerDraft
import io.element.android.libraries.matrix.api.room.draft.ComposerDraftType
@ -65,7 +65,8 @@ import io.element.android.libraries.matrix.test.A_USER_ID_3
import io.element.android.libraries.matrix.test.A_USER_ID_4
import io.element.android.libraries.matrix.test.permalink.FakePermalinkBuilder
import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.matrix.test.room.aRoomMember
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
@ -267,13 +268,13 @@ class MessageComposerPresenterTest {
val timeline = FakeTimeline().apply {
this.editCaptionLambda = editCaptionLambda
}
val fakeMatrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = timeline,
typingNoticeResult = { Result.success(Unit) }
)
val presenter = createPresenter(
coroutineScope = this,
room = fakeMatrixRoom,
room = joinedRoom,
isRichTextEditorEnabled = false,
)
val permalinkBuilder = FakePermalinkBuilder(permalinkForUserLambda = { Result.success("") })
@ -382,7 +383,7 @@ class MessageComposerPresenterTest {
fun `present - send message with rich text enabled`() = runTest {
val presenter = createPresenter(
coroutineScope = this,
room = FakeMatrixRoom(
room = FakeJoinedRoom(
sendMessageResult = { _, _, _ -> Result.success(Unit) },
typingNoticeResult = { Result.success(Unit) }
),
@ -416,7 +417,7 @@ class MessageComposerPresenterTest {
val presenter = createPresenter(
coroutineScope = this,
isRichTextEditorEnabled = false,
room = FakeMatrixRoom(
room = FakeJoinedRoom(
sendMessageResult = { _, _, _ -> Result.success(Unit) },
typingNoticeResult = { Result.success(Unit) }
),
@ -454,13 +455,13 @@ class MessageComposerPresenterTest {
val timeline = FakeTimeline().apply {
this.editMessageLambda = editMessageLambda
}
val fakeMatrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = timeline,
typingNoticeResult = { Result.success(Unit) }
)
val presenter = createPresenter(
this,
fakeMatrixRoom,
joinedRoom,
)
moleculeFlow(RecompositionMode.Immediate) {
val state = presenter.present()
@ -509,14 +510,14 @@ class MessageComposerPresenterTest {
val roomEditMessageLambda = lambdaRecorder { _: EventId?, _: String, _: String?, _: List<IntentionalMention> ->
Result.success(Unit)
}
val fakeMatrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = timeline,
typingNoticeResult = { Result.success(Unit) },
editMessageLambda = roomEditMessageLambda,
)
val presenter = createPresenter(
this,
fakeMatrixRoom,
joinedRoom,
)
moleculeFlow(RecompositionMode.Immediate) {
val state = presenter.present()
@ -566,13 +567,13 @@ class MessageComposerPresenterTest {
val timeline = FakeTimeline().apply {
this.editMessageLambda = editMessageLambda
}
val fakeMatrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = timeline,
typingNoticeResult = { Result.success(Unit) },
)
val presenter = createPresenter(
this,
fakeMatrixRoom,
joinedRoom,
)
moleculeFlow(RecompositionMode.Immediate) {
val state = presenter.present()
@ -618,13 +619,13 @@ class MessageComposerPresenterTest {
val timeline = FakeTimeline().apply {
this.replyMessageLambda = replyMessageLambda
}
val fakeMatrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = timeline,
typingNoticeResult = { Result.success(Unit) }
)
val presenter = createPresenter(
this,
fakeMatrixRoom,
joinedRoom,
)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
@ -689,7 +690,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - Pick image from gallery`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
typingNoticeResult = { Result.success(Unit) }
)
val onPreviewAttachmentLambda = lambdaRecorder { _: ImmutableList<Attachment> -> }
@ -730,7 +731,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - Pick video from gallery`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
typingNoticeResult = { Result.success(Unit) }
)
val onPreviewAttachmentLambda = lambdaRecorder { _: ImmutableList<Attachment> -> }
@ -788,7 +789,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - Pick file from storage will open the preview`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
typingNoticeResult = { Result.success(Unit) }
)
val onPreviewAttachmentLambda = lambdaRecorder { _: ImmutableList<Attachment> -> }
@ -811,7 +812,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - create poll`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
typingNoticeResult = { Result.success(Unit) }
)
val presenter = createPresenter(this, room = room)
@ -830,7 +831,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - share location`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
typingNoticeResult = { Result.success(Unit) }
)
val presenter = createPresenter(this, room = room)
@ -849,7 +850,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - Take photo`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
typingNoticeResult = { Result.success(Unit) }
)
val permissionPresenter = FakePermissionsPresenter().apply { setPermissionGranted() }
@ -874,7 +875,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - Take photo with permission request`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
typingNoticeResult = { Result.success(Unit) }
)
val permissionPresenter = FakePermissionsPresenter()
@ -901,7 +902,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - Record video`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
typingNoticeResult = { Result.success(Unit) }
)
val permissionPresenter = FakePermissionsPresenter().apply { setPermissionGranted() }
@ -926,7 +927,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - Record video with permission request`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
typingNoticeResult = { Result.success(Unit) }
)
val permissionPresenter = FakePermissionsPresenter()
@ -1001,12 +1002,12 @@ class MessageComposerPresenterTest {
val bob = aRoomMember(userId = A_USER_ID_2, membership = RoomMembershipState.JOIN)
val david = aRoomMember(userId = A_USER_ID_4, displayName = "Dave", membership = RoomMembershipState.JOIN)
var canUserTriggerRoomNotificationResult = true
val room = FakeMatrixRoom(
canUserTriggerRoomNotificationResult = { Result.success(canUserTriggerRoomNotificationResult) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(canUserTriggerRoomNotificationResult = { Result.success(canUserTriggerRoomNotificationResult) }),
typingNoticeResult = { Result.success(Unit) }
).apply {
givenRoomMembersState(
MatrixRoomMembersState.Ready(
RoomMembersState.Ready(
persistentListOf(currentUser, invitedUser, bob, david),
)
)
@ -1057,12 +1058,12 @@ class MessageComposerPresenterTest {
val invitedUser = aRoomMember(userId = A_USER_ID_3, membership = RoomMembershipState.INVITE)
val bob = aRoomMember(userId = A_USER_ID_2, membership = RoomMembershipState.JOIN)
val david = aRoomMember(userId = A_USER_ID_4, displayName = "Dave", membership = RoomMembershipState.JOIN)
val room = FakeMatrixRoom(
canUserTriggerRoomNotificationResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(canUserTriggerRoomNotificationResult = { Result.success(true) }),
typingNoticeResult = { Result.success(Unit) }
).apply {
givenRoomMembersState(
MatrixRoomMembersState.Ready(
RoomMembersState.Ready(
persistentListOf(currentUser, invitedUser, bob, david),
)
)
@ -1124,7 +1125,7 @@ class MessageComposerPresenterTest {
val sendMessageResult = lambdaRecorder { _: String, _: String?, _: List<IntentionalMention> ->
Result.success(Unit)
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
liveTimeline = timeline,
sendMessageResult = sendMessageResult,
typingNoticeResult = { Result.success(Unit) }
@ -1206,8 +1207,8 @@ class MessageComposerPresenterTest {
@Test
fun `present - handle typing notice event`() = runTest {
val typingNoticeResult = lambdaRecorder<Boolean, Result<Unit>> { Result.success(Unit) }
val room = FakeMatrixRoom(
typingNoticeResult = typingNoticeResult
val room = FakeJoinedRoom(
typingNoticeResult = typingNoticeResult,
)
val presenter = createPresenter(room = room, coroutineScope = this)
moleculeFlow(RecompositionMode.Immediate) {
@ -1217,6 +1218,7 @@ class MessageComposerPresenterTest {
typingNoticeResult.assertions().isNeverCalled()
initialState.eventSink.invoke(MessageComposerEvents.TypingNotice(true))
initialState.eventSink.invoke(MessageComposerEvents.TypingNotice(false))
advanceUntilIdle()
typingNoticeResult.assertions().isCalledExactly(2)
.withSequence(
listOf(value(true)),
@ -1228,7 +1230,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - handle typing notice event when sending typing notice is disabled`() = runTest {
val typingNoticeResult = lambdaRecorder<Boolean, Result<Unit>> { Result.success(Unit) }
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
typingNoticeResult = typingNoticeResult
)
val store = InMemorySessionPreferencesStore(
@ -1383,7 +1385,7 @@ class MessageComposerPresenterTest {
val timeline = FakeTimeline().apply {
this.loadReplyDetailsLambda = loadReplyDetailsLambda
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
liveTimeline = timeline,
typingNoticeResult = { Result.success(Unit) },
)
@ -1524,7 +1526,7 @@ class MessageComposerPresenterTest {
private fun createPresenter(
coroutineScope: CoroutineScope,
room: MatrixRoom = FakeMatrixRoom(
room: JoinedRoom = FakeJoinedRoom(
typingNoticeResult = { Result.success(Unit) }
),
navigator: MessagesNavigator = FakeMessagesNavigator(),

View file

@ -9,7 +9,7 @@ package io.element.android.features.messages.impl.messagecomposer.suggestions
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembershipState
import io.element.android.libraries.matrix.test.A_ROOM_ALIAS
import io.element.android.libraries.matrix.test.A_USER_ID
@ -35,7 +35,7 @@ class SuggestionsProcessorTest {
fun `processing null suggestion will return empty suggestion`() = runTest {
val result = suggestionsProcessor.process(
suggestion = null,
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember())),
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember())),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID,
canSendRoomMention = { true },
@ -47,7 +47,7 @@ class SuggestionsProcessorTest {
fun `processing Command will return empty suggestion`() = runTest {
val result = suggestionsProcessor.process(
suggestion = aCommandSuggestion,
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember())),
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember())),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID,
canSendRoomMention = { true },
@ -59,7 +59,7 @@ class SuggestionsProcessorTest {
fun `processing Custom will return empty suggestion`() = runTest {
val result = suggestionsProcessor.process(
suggestion = aCustomSuggestion,
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember())),
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember())),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID,
canSendRoomMention = { true },
@ -71,7 +71,7 @@ class SuggestionsProcessorTest {
fun `processing Mention suggestion with not loaded members will return empty suggestion`() = runTest {
val result = suggestionsProcessor.process(
suggestion = aMentionSuggestion(""),
roomMembersState = MatrixRoomMembersState.Unknown,
roomMembersState = RoomMembersState.Unknown,
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID,
canSendRoomMention = { true },
@ -83,7 +83,7 @@ class SuggestionsProcessorTest {
fun `processing Mention suggestion with no members will return empty suggestion`() = runTest {
val result = suggestionsProcessor.process(
suggestion = aMentionSuggestion(""),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()),
roomMembersState = RoomMembersState.Ready(persistentListOf()),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID,
canSendRoomMention = { true },
@ -95,7 +95,7 @@ class SuggestionsProcessorTest {
fun `processing Room suggestion with no aliases will return empty suggestion`() = runTest {
val result = suggestionsProcessor.process(
suggestion = aRoomSuggestion(""),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()),
roomMembersState = RoomMembersState.Ready(persistentListOf()),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID,
canSendRoomMention = { true },
@ -108,7 +108,7 @@ class SuggestionsProcessorTest {
val aRoomSummary = aRoomSummary(canonicalAlias = A_ROOM_ALIAS)
val result = suggestionsProcessor.process(
suggestion = aRoomSuggestion("ALI"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()),
roomMembersState = RoomMembersState.Ready(persistentListOf()),
roomAliasSuggestions = listOf(
RoomAliasSuggestion(
roomAlias = A_ROOM_ALIAS,
@ -137,7 +137,7 @@ class SuggestionsProcessorTest {
val aRoomSummary = aRoomSummary(canonicalAlias = A_ROOM_ALIAS)
val result = suggestionsProcessor.process(
suggestion = aRoomSuggestion("ali"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()),
roomMembersState = RoomMembersState.Ready(persistentListOf()),
roomAliasSuggestions = listOf(
RoomAliasSuggestion(
roomAlias = A_ROOM_ALIAS,
@ -166,7 +166,7 @@ class SuggestionsProcessorTest {
val aRoomSummary = aRoomSummary(canonicalAlias = A_ROOM_ALIAS)
val result = suggestionsProcessor.process(
suggestion = aRoomSuggestion("tot"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()),
roomMembersState = RoomMembersState.Ready(persistentListOf()),
roomAliasSuggestions = listOf(
RoomAliasSuggestion(
roomAlias = A_ROOM_ALIAS,
@ -186,7 +186,7 @@ class SuggestionsProcessorTest {
val aRoomSummary = aRoomSummary(canonicalAlias = A_ROOM_ALIAS)
val result = suggestionsProcessor.process(
suggestion = aRoomSuggestion("lement"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()),
roomMembersState = RoomMembersState.Ready(persistentListOf()),
roomAliasSuggestions = listOf(
RoomAliasSuggestion(
roomAlias = A_ROOM_ALIAS,
@ -215,7 +215,7 @@ class SuggestionsProcessorTest {
val aRoomSummary = aRoomSummary(canonicalAlias = A_ROOM_ALIAS)
val result = suggestionsProcessor.process(
suggestion = aRoomSuggestion("lement"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()),
roomMembersState = RoomMembersState.Ready(persistentListOf()),
roomAliasSuggestions = listOf(
RoomAliasSuggestion(
roomAlias = A_ROOM_ALIAS,
@ -235,7 +235,7 @@ class SuggestionsProcessorTest {
val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = null)
val result = suggestionsProcessor.process(
suggestion = aMentionSuggestion("ali"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)),
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember)),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID_2,
canSendRoomMention = { true },
@ -252,7 +252,7 @@ class SuggestionsProcessorTest {
val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = null)
val result = suggestionsProcessor.process(
suggestion = aMentionSuggestion("ali"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)),
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember)),
roomAliasSuggestions = emptyList(),
currentUserId = UserId("@alice:server.org"),
canSendRoomMention = { true },
@ -265,7 +265,7 @@ class SuggestionsProcessorTest {
val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = "alice")
val result = suggestionsProcessor.process(
suggestion = aMentionSuggestion("bo"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)),
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember)),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID_2,
canSendRoomMention = { true },
@ -278,7 +278,7 @@ class SuggestionsProcessorTest {
val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), membership = RoomMembershipState.INVITE)
val result = suggestionsProcessor.process(
suggestion = aMentionSuggestion("ali"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)),
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember)),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID_2,
canSendRoomMention = { true },
@ -291,7 +291,7 @@ class SuggestionsProcessorTest {
val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = "bob")
val result = suggestionsProcessor.process(
suggestion = aMentionSuggestion("bo"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)),
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember)),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID_2,
canSendRoomMention = { true },
@ -308,7 +308,7 @@ class SuggestionsProcessorTest {
val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = "ro")
val result = suggestionsProcessor.process(
suggestion = aMentionSuggestion("ro"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)),
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember)),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID_2,
canSendRoomMention = { true },
@ -326,7 +326,7 @@ class SuggestionsProcessorTest {
val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = "ro")
val result = suggestionsProcessor.process(
suggestion = aMentionSuggestion("ro"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)),
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember)),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID_2,
canSendRoomMention = { false },

View file

@ -12,14 +12,14 @@ import io.element.android.features.messages.impl.pinned.PinnedEventsTimelineProv
import io.element.android.libraries.eventformatter.test.FakePinnedMessagesBannerFormatter
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.sync.SyncService
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.AN_EVENT_ID_2
import io.element.android.libraries.matrix.test.A_UNIQUE_ID
import io.element.android.libraries.matrix.test.A_UNIQUE_ID_2
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.matrix.test.sync.FakeSyncService
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
@ -54,7 +54,7 @@ class PinnedMessagesBannerPresenterTest {
@Test
fun `present - loading state`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
createTimelineResult = { Result.success(FakeTimeline()) }
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
@ -85,7 +85,7 @@ class PinnedMessagesBannerPresenterTest {
)
)
)
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
createTimelineResult = { Result.success(pinnedEventsTimeline) }
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID, AN_EVENT_ID_2)))
@ -124,7 +124,7 @@ class PinnedMessagesBannerPresenterTest {
)
)
)
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
createTimelineResult = { Result.success(pinnedEventsTimeline) }
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID, AN_EVENT_ID_2)))
@ -159,7 +159,7 @@ class PinnedMessagesBannerPresenterTest {
@Test
fun `present - timeline failed`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
createTimelineResult = { Result.failure(Exception()) }
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
@ -179,7 +179,7 @@ class PinnedMessagesBannerPresenterTest {
}
private fun TestScope.createPinnedMessagesBannerPresenter(
room: MatrixRoom = FakeMatrixRoom(),
room: JoinedRoom = FakeJoinedRoom(),
itemFactory: PinnedMessagesBannerItemFactory = PinnedMessagesBannerItemFactory(
coroutineDispatchers = testCoroutineDispatchers(),
formatter = FakePinnedMessagesBannerFormatter(

View file

@ -20,14 +20,15 @@ import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatch
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.sync.SyncService
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_THROWABLE
import io.element.android.libraries.matrix.test.A_UNIQUE_ID
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.matrix.test.sync.FakeSyncService
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
@ -51,11 +52,13 @@ import org.junit.Test
class PinnedMessagesListPresenterTest {
@Test
fun `present - initial state feature disabled`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
)
)
val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = false)
presenter.test {
val initialState = awaitItem()
@ -66,13 +69,15 @@ class PinnedMessagesListPresenterTest {
@Test
fun `present - initial state feature enabled`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
}
)
val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true)
presenter.test {
val initialState = awaitItem()
@ -83,14 +88,16 @@ class PinnedMessagesListPresenterTest {
@Test
fun `present - timeline failure state`() = runTest {
val room = FakeMatrixRoom(
createTimelineResult = { Result.failure(RuntimeException()) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
}
},
createTimelineResult = { Result.failure(RuntimeException()) },
)
val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true)
presenter.test {
skipItems(3)
@ -102,14 +109,16 @@ class PinnedMessagesListPresenterTest {
@Test
fun `present - empty state`() = runTest {
val room = FakeMatrixRoom(
createTimelineResult = { Result.success(FakeTimeline()) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf()))
}
},
createTimelineResult = { Result.success(FakeTimeline()) },
)
val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true)
presenter.test {
skipItems(3)
@ -122,14 +131,16 @@ class PinnedMessagesListPresenterTest {
@Test
fun `present - filled state`() = runTest {
val pinnedEventsTimeline = createPinnedMessagesTimeline()
val room = FakeMatrixRoom(
createTimelineResult = { Result.success(pinnedEventsTimeline) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
}
},
createTimelineResult = { Result.success(pinnedEventsTimeline) },
)
val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true)
presenter.test {
skipItems(3)
@ -149,14 +160,16 @@ class PinnedMessagesListPresenterTest {
val failureUnpinEventLambda = lambdaRecorder { _: EventId? -> Result.failure<Boolean>(A_THROWABLE) }
val pinnedEventsTimeline = createPinnedMessagesTimeline()
val analyticsService = FakeAnalyticsService()
val room = FakeMatrixRoom(
createTimelineResult = { Result.success(pinnedEventsTimeline) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
}
},
createTimelineResult = { Result.success(pinnedEventsTimeline) },
)
val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true, analyticsService = analyticsService)
presenter.test {
skipItems(3)
@ -195,14 +208,16 @@ class PinnedMessagesListPresenterTest {
this.onViewInTimelineClickLambda = onViewInTimelineClickLambda
}
val pinnedEventsTimeline = createPinnedMessagesTimeline()
val room = FakeMatrixRoom(
createTimelineResult = { Result.success(pinnedEventsTimeline) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
}
},
createTimelineResult = { Result.success(pinnedEventsTimeline) },
)
val presenter = createPinnedMessagesListPresenter(room = room, navigator = navigator, isFeatureEnabled = true)
presenter.test {
skipItems(3)
@ -224,14 +239,16 @@ class PinnedMessagesListPresenterTest {
this.onShowEventDebugInfoClickLambda = onShowEventDebugInfoClickLambda
}
val pinnedEventsTimeline = createPinnedMessagesTimeline()
val room = FakeMatrixRoom(
createTimelineResult = { Result.success(pinnedEventsTimeline) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
}
},
createTimelineResult = { Result.success(pinnedEventsTimeline) },
)
val presenter = createPinnedMessagesListPresenter(room = room, navigator = navigator, isFeatureEnabled = true)
presenter.test {
skipItems(3)
@ -253,14 +270,16 @@ class PinnedMessagesListPresenterTest {
this.onForwardEventClickLambda = onForwardEventClickLambda
}
val pinnedEventsTimeline = createPinnedMessagesTimeline()
val room = FakeMatrixRoom(
createTimelineResult = { Result.success(pinnedEventsTimeline) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
}
},
createTimelineResult = { Result.success(pinnedEventsTimeline) },
)
val presenter = createPinnedMessagesListPresenter(room = room, navigator = navigator, isFeatureEnabled = true)
presenter.test {
skipItems(3)
@ -294,7 +313,7 @@ class PinnedMessagesListPresenterTest {
private fun TestScope.createPinnedMessagesListPresenter(
navigator: PinnedMessagesListNavigator = FakePinnedMessagesListNavigator(),
room: MatrixRoom = FakeMatrixRoom(),
room: JoinedRoom = FakeJoinedRoom(),
syncService: SyncService = FakeSyncService(),
isFeatureEnabled: Boolean = true,
analyticsService: AnalyticsService = FakeAnalyticsService(),

View file

@ -15,10 +15,10 @@ import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.lambda.lambdaRecorder
import kotlinx.coroutines.test.runTest
@ -78,10 +78,10 @@ class ReportMessagePresenterTest {
val reportContentResult = lambdaRecorder<EventId, String, UserId?, Result<Unit>> { _, _, _ ->
Result.success(Unit)
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
reportContentResult = reportContentResult
)
val presenter = createReportMessagePresenter(matrixRoom = room)
val presenter = createReportMessagePresenter(joinedRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -100,10 +100,10 @@ class ReportMessagePresenterTest {
val reportContentResult = lambdaRecorder<EventId, String, UserId?, Result<Unit>> { _, _, _ ->
Result.success(Unit)
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
reportContentResult = reportContentResult
)
val presenter = createReportMessagePresenter(matrixRoom = room)
val presenter = createReportMessagePresenter(joinedRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -120,10 +120,10 @@ class ReportMessagePresenterTest {
val reportContentResult = lambdaRecorder<EventId, String, UserId?, Result<Unit>> { _, _, _ ->
Result.failure(Exception("Failed to report content"))
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
reportContentResult = reportContentResult
)
val presenter = createReportMessagePresenter(matrixRoom = room)
val presenter = createReportMessagePresenter(joinedRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -141,11 +141,11 @@ class ReportMessagePresenterTest {
private fun createReportMessagePresenter(
inputs: ReportMessagePresenter.Inputs = ReportMessagePresenter.Inputs(AN_EVENT_ID, A_USER_ID),
matrixRoom: MatrixRoom = FakeMatrixRoom(),
joinedRoom: JoinedRoom = FakeJoinedRoom(),
snackbarDispatcher: SnackbarDispatcher = SnackbarDispatcher(),
) = ReportMessagePresenter(
inputs = inputs,
room = matrixRoom,
room = joinedRoom,
snackbarDispatcher = snackbarDispatcher,
)
}

View file

@ -14,7 +14,7 @@ import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.Timeline
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_UNIQUE_ID
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem
import io.element.android.tests.testutils.lambda.lambdaError
@ -29,11 +29,11 @@ class TimelineControllerTest {
fun `test switching between live and detached timeline`() = runTest {
val liveTimeline = FakeTimeline(name = "live")
val detachedTimeline = FakeTimeline(name = "detached")
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = liveTimeline,
createTimelineResult = { Result.success(detachedTimeline) }
)
val sut = TimelineController(matrixRoom)
val sut = TimelineController(joinedRoom)
sut.activeTimelineFlow().test {
awaitItem().also { state ->
@ -61,7 +61,7 @@ class TimelineControllerTest {
val detachedTimeline1 = FakeTimeline(name = "detached 1")
val detachedTimeline2 = FakeTimeline(name = "detached 2")
var callNumber = 0
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = liveTimeline,
createTimelineResult = {
callNumber++
@ -72,7 +72,7 @@ class TimelineControllerTest {
}
}
)
val sut = TimelineController(matrixRoom)
val sut = TimelineController(joinedRoom)
sut.activeTimelineFlow().test {
awaitItem().also { state ->
@ -97,10 +97,10 @@ class TimelineControllerTest {
@Test
fun `test switching to live when already in live should have no effect`() = runTest {
val liveTimeline = FakeTimeline(name = "live")
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = liveTimeline
)
val sut = TimelineController(matrixRoom)
val sut = TimelineController(joinedRoom)
sut.activeTimelineFlow().test {
awaitItem().also { state ->
assertThat(state).isEqualTo(liveTimeline)
@ -115,11 +115,11 @@ class TimelineControllerTest {
fun `test closing the TimelineController should close the detached timeline`() = runTest {
val liveTimeline = FakeTimeline(name = "live")
val detachedTimeline = FakeTimeline(name = "detached")
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = liveTimeline,
createTimelineResult = { Result.success(detachedTimeline) }
)
val sut = TimelineController(matrixRoom)
val sut = TimelineController(joinedRoom)
sut.activeTimelineFlow().test {
awaitItem().also { state ->
assertThat(state).isEqualTo(liveTimeline)
@ -144,10 +144,10 @@ class TimelineControllerTest {
)
)
)
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = liveTimeline
)
val sut = TimelineController(matrixRoom)
val sut = TimelineController(joinedRoom)
assertThat(sut.timelineItems().first()).hasSize(1)
}
@ -165,11 +165,11 @@ class TimelineControllerTest {
val detachedTimeline = FakeTimeline(name = "detached").apply {
sendMessageLambda = lambdaForDetached
}
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = liveTimeline,
createTimelineResult = { Result.success(detachedTimeline) }
)
val sut = TimelineController(matrixRoom)
val sut = TimelineController(joinedRoom)
sut.activeTimelineFlow().test {
sut.focusOnEvent(AN_EVENT_ID)
awaitItem().also { state ->
@ -190,11 +190,11 @@ class TimelineControllerTest {
fun `test last forward pagination on a detached timeline should switch to live timeline`() = runTest {
val liveTimeline = FakeTimeline(name = "live")
val detachedTimeline = FakeTimeline(name = "detached")
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = liveTimeline,
createTimelineResult = { Result.success(detachedTimeline) }
)
val sut = TimelineController(matrixRoom)
val sut = TimelineController(joinedRoom)
sut.activeTimelineFlow().test {
awaitItem().also { state ->

View file

@ -30,7 +30,7 @@ import io.element.android.features.poll.test.actions.FakeSendPollResponseAction
import io.element.android.features.roomcall.api.aStandByCallState
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.ReceiptType
import io.element.android.libraries.matrix.api.timeline.Timeline
@ -43,7 +43,8 @@ import io.element.android.libraries.matrix.test.AN_EVENT_ID_2
import io.element.android.libraries.matrix.test.A_UNIQUE_ID
import io.element.android.libraries.matrix.test.A_UNIQUE_ID_2
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomMember
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
import io.element.android.libraries.matrix.test.timeline.aMessageContent
@ -128,9 +129,9 @@ import kotlin.time.Duration.Companion.seconds
)
)
)
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
liveTimeline = timeline,
canUserSendMessageResult = { _, _ -> Result.success(true) },
baseRoom = FakeBaseRoom(canUserSendMessageResult = { _, _ -> Result.success(true) })
)
val sessionPreferencesStore = InMemorySessionPreferencesStore(isSendPublicReadReceiptsEnabled = false)
val presenter = createTimelinePresenter(
@ -144,7 +145,7 @@ import kotlin.time.Duration.Companion.seconds
val initialState = awaitFirstItem()
initialState.eventSink.invoke(TimelineEvents.OnScrollFinished(0))
runCurrent()
assertThat(room.markAsReadCalls).isNotEmpty()
assertThat(room.baseRoom.markAsReadCalls).isNotEmpty()
cancelAndIgnoreRemainingEvents()
}
}
@ -481,10 +482,10 @@ import kotlin.time.Duration.Companion.seconds
val liveTimeline = FakeTimeline(
timelineItems = flowOf(emptyList())
)
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
liveTimeline = liveTimeline,
createTimelineResult = { Result.success(detachedTimeline) },
canUserSendMessageResult = { _, _ -> Result.success(true) },
baseRoom = FakeBaseRoom(canUserSendMessageResult = { _, _ -> Result.success(true) }),
)
val presenter = createTimelinePresenter(
room = room,
@ -523,7 +524,7 @@ import kotlin.time.Duration.Companion.seconds
process(listOf(aMessageEvent(eventId = AN_EVENT_ID)))
}
val presenter = createTimelinePresenter(
room = FakeMatrixRoom(
room = FakeJoinedRoom(
liveTimeline = FakeTimeline(
timelineItems = flowOf(
listOf(
@ -534,7 +535,7 @@ import kotlin.time.Duration.Companion.seconds
)
)
),
canUserSendMessageResult = { _, _ -> Result.success(true) },
baseRoom = FakeBaseRoom(canUserSendMessageResult = { _, _ -> Result.success(true) }),
),
timelineItemIndexer = timelineItemIndexer,
)
@ -557,12 +558,12 @@ import kotlin.time.Duration.Companion.seconds
@Test
fun `present - focus on event error case`() = runTest {
val presenter = createTimelinePresenter(
room = FakeMatrixRoom(
room = FakeJoinedRoom(
liveTimeline = FakeTimeline(
timelineItems = flowOf(emptyList()),
),
createTimelineResult = { Result.failure(Throwable("An error")) },
canUserSendMessageResult = { _, _ -> Result.success(true) },
baseRoom = FakeBaseRoom(canUserSendMessageResult = { _, _ -> Result.success(true) }),
)
)
moleculeFlow(RecompositionMode.Immediate) {
@ -628,11 +629,11 @@ import kotlin.time.Duration.Companion.seconds
)
)
)
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
liveTimeline = timeline,
canUserSendMessageResult = { _, _ -> Result.success(true) },
baseRoom = FakeBaseRoom(canUserSendMessageResult = { _, _ -> Result.success(true) }),
).apply {
givenRoomMembersState(MatrixRoomMembersState.Unknown)
givenRoomMembersState(RoomMembersState.Unknown)
}
val avatarUrl = "https://domain.com/avatar.jpg"
@ -647,7 +648,7 @@ import kotlin.time.Duration.Companion.seconds
assertThat(event.readReceiptState.receipts.first().avatarData.url).isNull()
room.givenRoomMembersState(
MatrixRoomMembersState.Ready(
RoomMembersState.Ready(
persistentListOf(aRoomMember(userId = A_USER_ID, avatarUrl = avatarUrl))
)
)
@ -663,9 +664,9 @@ import kotlin.time.Duration.Companion.seconds
private fun TestScope.createTimelinePresenter(
timeline: Timeline = FakeTimeline(),
room: FakeMatrixRoom = FakeMatrixRoom(
room: FakeJoinedRoom = FakeJoinedRoom(
liveTimeline = timeline,
canUserSendMessageResult = { _, _ -> Result.success(true) }
baseRoom = FakeBaseRoom(canUserSendMessageResult = { _, _ -> Result.success(true) }),
),
redactedVoiceMessageManager: RedactedVoiceMessageManager = FakeRedactedVoiceMessageManager(),
messagesNavigator: FakeMessagesNavigator = FakeMessagesNavigator(),

View file

@ -12,12 +12,12 @@ import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.features.messages.impl.timeline.model.anAggregatedReaction
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.A_USER_NAME
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.aRoomMember
import io.element.android.tests.testutils.WarmUpRule
import kotlinx.collections.immutable.persistentListOf
@ -32,8 +32,8 @@ class ReactionSummaryPresenterTest {
private val aggregatedReaction = anAggregatedReaction(userId = A_USER_ID, key = "👍", isHighlighted = true)
private val roomMember = aRoomMember(userId = A_USER_ID, avatarUrl = AN_AVATAR_URL, displayName = A_USER_NAME)
private val summaryEvent = ReactionSummaryEvents.ShowReactionSummary(AN_EVENT_ID, listOf(aggregatedReaction), aggregatedReaction.key)
private val room = FakeMatrixRoom().apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(persistentListOf(roomMember)))
private val room = FakeBaseRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(persistentListOf(roomMember)))
}
private val presenter = ReactionSummaryPresenter(room)

View file

@ -9,10 +9,10 @@ package io.element.android.features.messages.impl.timeline.protection
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.media.MediaPreviewValue
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore
@ -55,7 +55,7 @@ class TimelineProtectionPresenterTest {
@Test
fun `present - media preview value private in public room`() = runTest {
val appPreferencesStore = InMemoryAppPreferencesStore(timelineMediaPreviewValue = MediaPreviewValue.Private)
val room = FakeMatrixRoom(initialRoomInfo = aRoomInfo(joinRule = JoinRule.Public))
val room = FakeBaseRoom(initialRoomInfo = aRoomInfo(joinRule = JoinRule.Public))
val presenter = createPresenter(appPreferencesStore, room)
presenter.test {
skipItems(1)
@ -72,7 +72,7 @@ class TimelineProtectionPresenterTest {
@Test
fun `present - media preview value private in non public room`() = runTest {
val appPreferencesStore = InMemoryAppPreferencesStore(timelineMediaPreviewValue = MediaPreviewValue.Private)
val room = FakeMatrixRoom(initialRoomInfo = aRoomInfo(joinRule = JoinRule.Invite))
val room = FakeBaseRoom(initialRoomInfo = aRoomInfo(joinRule = JoinRule.Invite))
val presenter = createPresenter(appPreferencesStore, room)
presenter.test {
val initialState = awaitItem()
@ -85,7 +85,7 @@ class TimelineProtectionPresenterTest {
private fun createPresenter(
appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore(),
room: MatrixRoom = FakeMatrixRoom(),
room: BaseRoom = FakeBaseRoom(),
) = TimelineProtectionPresenter(
appPreferencesStore = appPreferencesStore,
room = room,

View file

@ -13,19 +13,20 @@ import app.cash.turbine.Event
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.A_USER_ID_2
import io.element.android.libraries.matrix.test.A_USER_ID_3
import io.element.android.libraries.matrix.test.A_USER_ID_4
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.matrix.test.room.aRoomMember
import io.element.android.libraries.preferences.api.store.SessionPreferencesStore
import io.element.android.libraries.preferences.test.InMemorySessionPreferencesStore
import io.element.android.tests.testutils.WarmUpRule
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
@ -50,12 +51,13 @@ class TypingNotificationPresenterTest {
@Test
fun `present - typing notification disabled`() = runTest {
val room = FakeMatrixRoom()
val typingMembersFlow = MutableStateFlow<List<UserId>>(emptyList())
val room = FakeJoinedRoom(roomTypingMembersFlow = typingMembersFlow)
val sessionPreferencesStore = InMemorySessionPreferencesStore(
isRenderTypingNotificationsEnabled = false
isRenderTypingNotificationsEnabled = false,
)
val presenter = createPresenter(
matrixRoom = room,
joinedRoom = room,
sessionPreferencesStore = sessionPreferencesStore,
)
moleculeFlow(RecompositionMode.Immediate) {
@ -65,7 +67,7 @@ class TypingNotificationPresenterTest {
val initialState = awaitItem()
assertThat(initialState.renderTypingNotifications).isFalse()
assertThat(initialState.typingMembers).isEmpty()
room.givenRoomTypingMembers(listOf(A_USER_ID_2))
typingMembersFlow.emit(listOf(A_USER_ID_2))
expectNoEvents()
// Preferences changes
sessionPreferencesStore.setRenderTypingNotifications(true)
@ -89,14 +91,15 @@ class TypingNotificationPresenterTest {
@Test
fun `present - state is updated when a member is typing, member is not known`() = runTest {
val room = FakeMatrixRoom()
val presenter = createPresenter(matrixRoom = room)
val typingMembersFlow = MutableStateFlow<List<UserId>>(emptyList())
val room = FakeJoinedRoom(roomTypingMembersFlow = typingMembersFlow)
val presenter = createPresenter(joinedRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(initialState.typingMembers).isEmpty()
room.givenRoomTypingMembers(listOf(A_USER_ID_2))
typingMembersFlow.emit(listOf(A_USER_ID_2))
val oneMemberTypingState = awaitItem()
assertThat(oneMemberTypingState.typingMembers.size).isEqualTo(1)
assertThat(oneMemberTypingState.typingMembers.first()).isEqualTo(
@ -105,7 +108,7 @@ class TypingNotificationPresenterTest {
)
)
// User stops typing
room.givenRoomTypingMembers(emptyList())
typingMembersFlow.emit(emptyList())
skipItems(1)
val finalState = awaitItem()
assertThat(finalState.typingMembers).isEmpty()
@ -115,9 +118,10 @@ class TypingNotificationPresenterTest {
@Test
fun `present - state is updated when a member is typing, member is known`() = runTest {
val aKnownRoomMember = createKnownRoomMember(userId = A_USER_ID_2)
val room = FakeMatrixRoom().apply {
val typingMembersFlow = MutableStateFlow<List<UserId>>(emptyList())
val room = FakeJoinedRoom(roomTypingMembersFlow = typingMembersFlow).apply {
givenRoomMembersState(
MatrixRoomMembersState.Ready(
RoomMembersState.Ready(
listOf(
createKnownRoomMember(A_USER_ID),
aKnownRoomMember,
@ -127,13 +131,13 @@ class TypingNotificationPresenterTest {
)
)
}
val presenter = createPresenter(matrixRoom = room)
val presenter = createPresenter(joinedRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(initialState.typingMembers).isEmpty()
room.givenRoomTypingMembers(listOf(A_USER_ID_2))
typingMembersFlow.emit(listOf(A_USER_ID_2))
val oneMemberTypingState = awaitItem()
assertThat(oneMemberTypingState.typingMembers.size).isEqualTo(1)
assertThat(oneMemberTypingState.typingMembers.first()).isEqualTo(
@ -142,7 +146,7 @@ class TypingNotificationPresenterTest {
)
)
// User stops typing
room.givenRoomTypingMembers(emptyList())
typingMembersFlow.emit(emptyList())
skipItems(1)
val finalState = awaitItem()
assertThat(finalState.typingMembers).isEmpty()
@ -152,14 +156,15 @@ class TypingNotificationPresenterTest {
@Test
fun `present - state is updated when a member is typing, member is not known, then known`() = runTest {
val aKnownRoomMember = createKnownRoomMember(A_USER_ID_2)
val room = FakeMatrixRoom()
val presenter = createPresenter(matrixRoom = room)
val typingMembersFlow = MutableStateFlow<List<UserId>>(emptyList())
val room = FakeJoinedRoom(roomTypingMembersFlow = typingMembersFlow)
val presenter = createPresenter(joinedRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(initialState.typingMembers).isEmpty()
room.givenRoomTypingMembers(listOf(A_USER_ID_2))
typingMembersFlow.emit(listOf(A_USER_ID_2))
val oneMemberTypingState = awaitItem()
assertThat(oneMemberTypingState.typingMembers.size).isEqualTo(1)
assertThat(oneMemberTypingState.typingMembers.first()).isEqualTo(
@ -169,7 +174,7 @@ class TypingNotificationPresenterTest {
)
// User is getting known
room.givenRoomMembersState(
MatrixRoomMembersState.Ready(
RoomMembersState.Ready(
listOf(aKnownRoomMember).toImmutableList()
)
)
@ -185,19 +190,20 @@ class TypingNotificationPresenterTest {
@Test
fun `present - reserveSpace becomes true once we get the first typing notification with room members`() = runTest {
val room = FakeMatrixRoom()
val presenter = createPresenter(matrixRoom = room)
val typingMembersFlow = MutableStateFlow<List<UserId>>(emptyList())
val room = FakeJoinedRoom(roomTypingMembersFlow = typingMembersFlow)
val presenter = createPresenter(joinedRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(initialState.typingMembers).isEmpty()
room.givenRoomTypingMembers(listOf(A_USER_ID_2))
typingMembersFlow.emit(listOf(A_USER_ID_2))
skipItems(1)
val updatedTypingState = awaitItem()
assertThat(updatedTypingState.reserveSpace).isTrue()
// User stops typing
room.givenRoomTypingMembers(emptyList())
typingMembersFlow.emit(emptyList())
// Is still true for all future events
val futureEvents = cancelAndConsumeRemainingEvents()
for (event in futureEvents) {
@ -209,14 +215,14 @@ class TypingNotificationPresenterTest {
}
private fun createPresenter(
matrixRoom: MatrixRoom = FakeMatrixRoom().apply {
joinedRoom: JoinedRoom = FakeJoinedRoom().apply {
givenRoomInfo(aRoomInfo(id = roomId, name = ""))
},
sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(
isRenderTypingNotificationsEnabled = true
),
) = TypingNotificationPresenter(
room = matrixRoom,
room = joinedRoom,
sessionPreferencesStore = sessionPreferencesStore,
)

View file

@ -23,7 +23,7 @@ import io.element.android.libraries.matrix.api.core.ProgressCallback
import io.element.android.libraries.matrix.api.media.AudioInfo
import io.element.android.libraries.matrix.api.room.message.ReplyParameters
import io.element.android.libraries.matrix.test.media.FakeMediaUploadHandler
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.mediaplayer.test.FakeMediaPlayer
import io.element.android.libraries.mediaupload.api.MediaSender
import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor
@ -64,11 +64,11 @@ class VoiceMessageComposerPresenterTest {
lambdaRecorder<File, AudioInfo, List<Float>, ProgressCallback?, ReplyParameters?, Result<FakeMediaUploadHandler>> { _, _, _, _, _ ->
Result.success(FakeMediaUploadHandler())
}
private val matrixRoom = FakeMatrixRoom(
private val joinedRoom = FakeJoinedRoom(
sendVoiceMessageResult = sendVoiceMessageResult
)
private val mediaPreProcessor = FakeMediaPreProcessor().apply { givenAudioResult() }
private val mediaSender = MediaSender(mediaPreProcessor, matrixRoom, InMemorySessionPreferencesStore())
private val mediaSender = MediaSender(mediaPreProcessor, joinedRoom, InMemorySessionPreferencesStore())
private val messageComposerContext = FakeMessageComposerContext()
companion object {