From 8f1d8cdcc12fcf03feb3a95f56b805ab6a57801e Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 12 Oct 2022 19:57:16 +0100 Subject: [PATCH] porting messenger tests to the engine module --- chat-engine/build.gradle | 4 + .../kotlin/app/dapk/st/engine/ChatEngine.kt | 7 +- .../testFixtures/kotlin/fixture/Fixtures.kt | 31 ++++++++ .../kotlin/test}/FlowTestObserver.kt | 2 + .../kotlin/ViewModelTestScopeImpl.kt | 1 + features/messenger/build.gradle | 3 +- .../st/messenger/MessengerViewModelTest.kt | 77 ++++--------------- matrix-chat-engine/build.gradle | 11 +++ .../kotlin/app/dapk/st/engine/MatrixEngine.kt | 4 +- .../app/dapk/st/engine/ReadMarkingTimeline.kt | 26 ++++--- .../dapk/st/engine}/LocalEchoMapperTest.kt | 16 ++-- .../engine}/MergeWithLocalEchosUseCaseTest.kt | 21 +++-- .../app/dapk/st/engine}/MetaMapperTest.kt | 3 +- .../dapk/st/engine}/TimelineUseCaseTest.kt | 39 ++++++++-- .../test/kotlin/fake}/FakeLocalEventMapper.kt | 4 +- .../test/kotlin/fake}/FakeLocalIdFactory.kt | 4 +- .../src/test/kotlin/fake}/FakeMetaMapper.kt | 4 +- .../kotlin/fake/FakeSyncService.kt | 3 +- 18 files changed, 140 insertions(+), 120 deletions(-) create mode 100644 chat-engine/src/testFixtures/kotlin/fixture/Fixtures.kt rename {domains/android/viewmodel/src/testFixtures/kotlin => core/src/testFixtures/kotlin/test}/FlowTestObserver.kt (97%) rename {features/messenger/src/test/kotlin/app/dapk/st/messenger => matrix-chat-engine/src/test/kotlin/app/dapk/st/engine}/LocalEchoMapperTest.kt (82%) rename {features/messenger/src/test/kotlin/app/dapk/st/messenger => matrix-chat-engine/src/test/kotlin/app/dapk/st/engine}/MergeWithLocalEchosUseCaseTest.kt (85%) rename {features/messenger/src/test/kotlin/app/dapk/st/messenger => matrix-chat-engine/src/test/kotlin/app/dapk/st/engine}/MetaMapperTest.kt (96%) rename {features/messenger/src/test/kotlin/app/dapk/st/messenger => matrix-chat-engine/src/test/kotlin/app/dapk/st/engine}/TimelineUseCaseTest.kt (77%) rename {features/messenger/src/test/kotlin/internalfake => matrix-chat-engine/src/test/kotlin/fake}/FakeLocalEventMapper.kt (84%) rename {features/messenger/src/test/kotlin/internalfake => matrix-chat-engine/src/test/kotlin/fake}/FakeLocalIdFactory.kt (77%) rename {features/messenger/src/test/kotlin/internalfake => matrix-chat-engine/src/test/kotlin/fake}/FakeMetaMapper.kt (82%) diff --git a/chat-engine/build.gradle b/chat-engine/build.gradle index 05013e0..8aa6dcf 100644 --- a/chat-engine/build.gradle +++ b/chat-engine/build.gradle @@ -1,8 +1,12 @@ plugins { id 'kotlin' + id 'java-test-fixtures' } dependencies { api Dependencies.mavenCentral.kotlinCoroutinesCore api project(":matrix:common") + + kotlinFixtures(it) + testFixturesImplementation(testFixtures(project(":matrix:common"))) } \ No newline at end of file diff --git a/chat-engine/src/main/kotlin/app/dapk/st/engine/ChatEngine.kt b/chat-engine/src/main/kotlin/app/dapk/st/engine/ChatEngine.kt index 16d4def..605e552 100644 --- a/chat-engine/src/main/kotlin/app/dapk/st/engine/ChatEngine.kt +++ b/chat-engine/src/main/kotlin/app/dapk/st/engine/ChatEngine.kt @@ -7,13 +7,11 @@ import app.dapk.st.matrix.common.RoomMember import kotlinx.coroutines.flow.Flow import java.io.InputStream -interface ChatEngine: TaskRunner { +interface ChatEngine : TaskRunner { fun directory(): Flow - fun invites(): Flow - - suspend fun messages(roomId: RoomId, disableReadReceipts: Boolean): Flow + fun messages(roomId: RoomId, disableReadReceipts: Boolean): Flow suspend fun login(request: LoginRequest): LoginResult @@ -49,7 +47,6 @@ interface TaskRunner { } - data class ChatEngineTask(val type: String, val jsonPayload: String) interface MediaDecrypter { diff --git a/chat-engine/src/testFixtures/kotlin/fixture/Fixtures.kt b/chat-engine/src/testFixtures/kotlin/fixture/Fixtures.kt new file mode 100644 index 0000000..707e318 --- /dev/null +++ b/chat-engine/src/testFixtures/kotlin/fixture/Fixtures.kt @@ -0,0 +1,31 @@ +package fixture + +import app.dapk.st.engine.* +import app.dapk.st.matrix.common.* + +fun aMessengerState( + self: UserId = aUserId(), + roomState: RoomState, + typing: Typing? = null +) = MessengerState(self, roomState, typing) + +fun aRoomOverview( + roomId: RoomId = aRoomId(), + roomCreationUtc: Long = 0L, + roomName: String? = null, + roomAvatarUrl: AvatarUrl? = null, + lastMessage: RoomOverview.LastMessage? = null, + isGroup: Boolean = false, + readMarker: EventId? = null, + isEncrypted: Boolean = false, +) = RoomOverview(roomId, roomCreationUtc, roomName, roomAvatarUrl, lastMessage, isGroup, readMarker, isEncrypted) + +fun anEncryptedRoomMessageEvent( + eventId: EventId = anEventId(), + utcTimestamp: Long = 0L, + content: String = "encrypted-content", + author: RoomMember = aRoomMember(), + meta: MessageMeta = MessageMeta.FromServer, + edited: Boolean = false, + redacted: Boolean = false, +) = RoomEvent.Message(eventId, utcTimestamp, content, author, meta, edited, redacted) diff --git a/domains/android/viewmodel/src/testFixtures/kotlin/FlowTestObserver.kt b/core/src/testFixtures/kotlin/test/FlowTestObserver.kt similarity index 97% rename from domains/android/viewmodel/src/testFixtures/kotlin/FlowTestObserver.kt rename to core/src/testFixtures/kotlin/test/FlowTestObserver.kt index 657f258..3ab82cf 100644 --- a/domains/android/viewmodel/src/testFixtures/kotlin/FlowTestObserver.kt +++ b/core/src/testFixtures/kotlin/test/FlowTestObserver.kt @@ -1,3 +1,5 @@ +package test + import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow diff --git a/domains/android/viewmodel/src/testFixtures/kotlin/ViewModelTestScopeImpl.kt b/domains/android/viewmodel/src/testFixtures/kotlin/ViewModelTestScopeImpl.kt index 83c2e24..d2f0b0f 100644 --- a/domains/android/viewmodel/src/testFixtures/kotlin/ViewModelTestScopeImpl.kt +++ b/domains/android/viewmodel/src/testFixtures/kotlin/ViewModelTestScopeImpl.kt @@ -3,6 +3,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import org.amshove.kluent.internal.assertEquals import test.ExpectTestScope +import test.FlowTestObserver @Suppress("UNCHECKED_CAST") internal class ViewModelTestScopeImpl( diff --git a/features/messenger/build.gradle b/features/messenger/build.gradle index 13f5e1b..f9edf4e 100644 --- a/features/messenger/build.gradle +++ b/features/messenger/build.gradle @@ -13,11 +13,10 @@ dependencies { kotlinTest(it) - androidImportFixturesWorkaround(project, project(":matrix:services:sync")) - androidImportFixturesWorkaround(project, project(":matrix:services:message")) androidImportFixturesWorkaround(project, project(":matrix:common")) androidImportFixturesWorkaround(project, project(":core")) androidImportFixturesWorkaround(project, project(":domains:store")) androidImportFixturesWorkaround(project, project(":domains:android:viewmodel")) androidImportFixturesWorkaround(project, project(":domains:android:stub")) + androidImportFixturesWorkaround(project, project(":chat-engine")) } \ No newline at end of file diff --git a/features/messenger/src/test/kotlin/app/dapk/st/messenger/MessengerViewModelTest.kt b/features/messenger/src/test/kotlin/app/dapk/st/messenger/MessengerViewModelTest.kt index e2449e3..fce4662 100644 --- a/features/messenger/src/test/kotlin/app/dapk/st/messenger/MessengerViewModelTest.kt +++ b/features/messenger/src/test/kotlin/app/dapk/st/messenger/MessengerViewModelTest.kt @@ -2,58 +2,38 @@ package app.dapk.st.messenger import ViewModelTest import app.dapk.st.core.Lce -import app.dapk.st.matrix.common.EventId -import app.dapk.st.matrix.common.RoomId -import app.dapk.st.matrix.common.UserId -import app.dapk.st.matrix.message.MessageService -import app.dapk.st.matrix.message.internal.ImageContentReader -import app.dapk.st.matrix.room.RoomService -import app.dapk.st.matrix.sync.RoomState -import app.dapk.st.matrix.sync.SyncService -import fake.FakeCredentialsStore +import app.dapk.st.engine.* +import app.dapk.st.matrix.common.* import fake.FakeMessageOptionsStore -import fake.FakeRoomStore import fixture.* -import internalfake.FakeLocalIdFactory -import io.mockk.coEvery import io.mockk.every import io.mockk.mockk import kotlinx.coroutines.flow.flowOf import org.junit.Test import test.delegateReturn -import java.time.Clock -import java.time.Instant -import java.time.ZoneOffset -private const val A_CURRENT_TIMESTAMP = 10000L private const val READ_RECEIPTS_ARE_DISABLED = true private val A_ROOM_ID = aRoomId("messenger state room id") private const val A_MESSAGE_CONTENT = "message content" -private const val A_LOCAL_ID = "local.1111-2222-3333" private val AN_EVENT_ID = anEventId("state event") private val A_SELF_ID = aUserId("self") +class FakeChatEngine : ChatEngine by mockk() { + + fun givenMessages(roomId: RoomId, disableReadReceipts: Boolean) = every { messages(roomId, disableReadReceipts) }.delegateReturn() + +} + class MessengerViewModelTest { private val runViewModelTest = ViewModelTest() - private val fakeMessageService = FakeMessageService() - private val fakeRoomService = FakeRoomService() - private val fakeRoomStore = FakeRoomStore() - private val fakeCredentialsStore = FakeCredentialsStore().also { it.givenCredentials().returns(aUserCredentials(userId = A_SELF_ID)) } - private val fakeObserveTimelineUseCase = FakeObserveTimelineUseCase() private val fakeMessageOptionsStore = FakeMessageOptionsStore() + private val fakeChatEngine = FakeChatEngine() private val viewModel = MessengerViewModel( - fakeMessageService, - fakeRoomService, - fakeRoomStore, - fakeCredentialsStore, - fakeObserveTimelineUseCase, - localIdFactory = FakeLocalIdFactory().also { it.givenCreate().returns(A_LOCAL_ID) }.instance, - imageContentReader = FakeImageContentReader(), - messageOptionsStore = fakeMessageOptionsStore.instance, - clock = fixedClock(A_CURRENT_TIMESTAMP), + fakeChatEngine, + fakeMessageOptionsStore.instance, factory = runViewModelTest.testMutableStateFactory(), ) @@ -73,10 +53,8 @@ class MessengerViewModelTest { @Test fun `given timeline emits state, when starting, then updates state and marks room and events as read`() = runViewModelTest { fakeMessageOptionsStore.givenReadReceiptsDisabled().returns(READ_RECEIPTS_ARE_DISABLED) - fakeRoomStore.expectUnit(times = 2) { it.markRead(A_ROOM_ID) } - fakeRoomService.expectUnit { it.markFullyRead(A_ROOM_ID, AN_EVENT_ID, isPrivate = READ_RECEIPTS_ARE_DISABLED) } val state = aMessengerStateWithEvent(AN_EVENT_ID, A_SELF_ID) - fakeObserveTimelineUseCase.given(A_ROOM_ID, A_SELF_ID).returns(flowOf(state)) + fakeChatEngine.givenMessages(A_ROOM_ID, READ_RECEIPTS_ARE_DISABLED).returns(flowOf(state)) viewModel.test().post(MessengerAction.OnMessengerVisible(A_ROOM_ID, attachments = null)) @@ -98,7 +76,7 @@ class MessengerViewModelTest { @Test fun `given composer message state when posting send text, then resets composer state and sends message`() = runViewModelTest { - fakeMessageService.expectUnit { it.scheduleMessage(expectEncryptedMessage(A_ROOM_ID, A_LOCAL_ID, A_CURRENT_TIMESTAMP, A_MESSAGE_CONTENT)) } + fakeChatEngine.expectUnit { it.send(expectTextMessage(A_MESSAGE_CONTENT), aRoomOverview()) } viewModel.test(initialState = initialStateWithComposerMessage(A_ROOM_ID, A_MESSAGE_CONTENT)).post(MessengerAction.ComposerSendText) @@ -114,9 +92,8 @@ class MessengerViewModelTest { return aMessageScreenState(roomId, aMessengerState(roomState = roomState), messageContent) } - private fun expectEncryptedMessage(roomId: RoomId, localId: String, timestamp: Long, messageContent: String): MessageService.Message.TextMessage { - val content = MessageService.Message.Content.TextContent(body = messageContent) - return MessageService.Message.TextMessage(content, sendEncrypted = true, roomId, localId, timestamp) + private fun expectTextMessage(messageContent: String): SendMessage.TextMessage { + return SendMessage.TextMessage(messageContent, reply = null) } private fun aMessengerStateWithEvent(eventId: EventId, selfId: UserId) = aRoomStateWithEventId(eventId).toMessengerState(selfId) @@ -135,27 +112,3 @@ fun aMessageScreenState(roomId: RoomId = aRoomId(), roomState: MessengerState, m roomState = Lce.Content(roomState), composerState = ComposerState.Text(value = messageContent ?: "", reply = null) ) - -fun aMessengerState( - self: UserId = aUserId(), - roomState: RoomState, - typing: SyncService.SyncEvent.Typing? = null -) = MessengerState(self, roomState, typing) - -class FakeObserveTimelineUseCase : ObserveTimelineUseCase by mockk() { - fun given(roomId: RoomId, selfId: UserId) = coEvery { this@FakeObserveTimelineUseCase.invoke(roomId, selfId) }.delegateReturn() -} - -class FakeMessageService : MessageService by mockk() { - - fun givenEchos(roomId: RoomId) = every { localEchos(roomId) }.delegateReturn() - -} - -class FakeRoomService : RoomService by mockk() { - fun givenFindMember(roomId: RoomId, userId: UserId) = coEvery { findMember(roomId, userId) }.delegateReturn() -} - -fun fixedClock(timestamp: Long = 0) = Clock.fixed(Instant.ofEpochMilli(timestamp), ZoneOffset.UTC) - -class FakeImageContentReader : ImageContentReader by mockk() \ No newline at end of file diff --git a/matrix-chat-engine/build.gradle b/matrix-chat-engine/build.gradle index 140832c..7d6b221 100644 --- a/matrix-chat-engine/build.gradle +++ b/matrix-chat-engine/build.gradle @@ -1,4 +1,5 @@ plugins { + id 'java-test-fixtures' id 'kotlin' } @@ -20,4 +21,14 @@ dependencies { implementation project(":matrix:services:device") implementation project(":matrix:services:crypto") implementation project(":matrix:services:profile") + + kotlinTest(it) + kotlinFixtures(it) + + testImplementation(testFixtures(project(":matrix:services:sync"))) + testImplementation(testFixtures(project(":matrix:services:message"))) + testImplementation(testFixtures(project(":matrix:common"))) + testImplementation(testFixtures(project(":core"))) + testImplementation(testFixtures(project(":domains:store"))) + testImplementation(testFixtures(project(":chat-engine"))) } \ No newline at end of file diff --git a/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/MatrixEngine.kt b/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/MatrixEngine.kt index 74386ac..3494ee9 100644 --- a/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/MatrixEngine.kt +++ b/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/MatrixEngine.kt @@ -46,8 +46,8 @@ class MatrixEngine internal constructor( override fun directory() = directoryUseCase.value.state() override fun invites() = inviteUseCase.value.invites() - override suspend fun messages(roomId: RoomId, disableReadReceipts: Boolean): Flow { - return timelineUseCase.value.foo(roomId, isReadReceiptsDisabled = disableReadReceipts) + override fun messages(roomId: RoomId, disableReadReceipts: Boolean): Flow { + return timelineUseCase.value.fetch(roomId, isReadReceiptsDisabled = disableReadReceipts) } override suspend fun login(request: LoginRequest): LoginResult { diff --git a/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/ReadMarkingTimeline.kt b/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/ReadMarkingTimeline.kt index ee1c641..0e0d5f8 100644 --- a/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/ReadMarkingTimeline.kt +++ b/matrix-chat-engine/src/main/kotlin/app/dapk/st/engine/ReadMarkingTimeline.kt @@ -10,9 +10,7 @@ import app.dapk.st.matrix.sync.RoomStore import kotlinx.coroutines.Deferred import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.* class ReadMarkingTimeline( private val roomStore: RoomStore, @@ -21,15 +19,19 @@ class ReadMarkingTimeline( private val roomService: RoomService, ) { - suspend fun foo(roomId: RoomId, isReadReceiptsDisabled: Boolean): Flow { - var lastKnownReadEvent: EventId? = null - val credentials = credentialsStore.credentials()!! - roomStore.markRead(roomId) - return observeTimelineUseCase.invoke(roomId, credentials.userId).distinctUntilChanged().onEach { state -> - state.latestMessageEventFromOthers(self = credentials.userId)?.let { - if (lastKnownReadEvent != it) { - updateRoomReadStateAsync(latestReadEvent = it, state, isReadReceiptsDisabled) - lastKnownReadEvent = it + fun fetch(roomId: RoomId, isReadReceiptsDisabled: Boolean): Flow { + return flow { + val credentials = credentialsStore.credentials()!! + roomStore.markRead(roomId) + emit(credentials) + }.flatMapMerge { credentials -> + var lastKnownReadEvent: EventId? = null + observeTimelineUseCase.invoke(roomId, credentials.userId).distinctUntilChanged().onEach { state -> + state.latestMessageEventFromOthers(self = credentials.userId)?.let { + if (lastKnownReadEvent != it) { + updateRoomReadStateAsync(latestReadEvent = it, state, isReadReceiptsDisabled) + lastKnownReadEvent = it + } } } } diff --git a/features/messenger/src/test/kotlin/app/dapk/st/messenger/LocalEchoMapperTest.kt b/matrix-chat-engine/src/test/kotlin/app/dapk/st/engine/LocalEchoMapperTest.kt similarity index 82% rename from features/messenger/src/test/kotlin/app/dapk/st/messenger/LocalEchoMapperTest.kt rename to matrix-chat-engine/src/test/kotlin/app/dapk/st/engine/LocalEchoMapperTest.kt index 29b8e59..a58e61b 100644 --- a/features/messenger/src/test/kotlin/app/dapk/st/messenger/LocalEchoMapperTest.kt +++ b/matrix-chat-engine/src/test/kotlin/app/dapk/st/engine/LocalEchoMapperTest.kt @@ -1,10 +1,10 @@ -package app.dapk.st.messenger +package app.dapk.st.engine import app.dapk.st.matrix.common.EventId import app.dapk.st.matrix.message.MessageService import app.dapk.st.matrix.sync.MessageMeta +import fake.FakeMetaMapper import fixture.* -import internalfake.FakeMetaMapper import org.amshove.kluent.shouldBeEqualTo import org.junit.Test @@ -28,7 +28,7 @@ class LocalEchoMapperTest { eventId = echo.eventId!!, content = AN_ECHO_CONTENT.content.body, meta = A_META - ) + ).engine() } @Test @@ -41,24 +41,24 @@ class LocalEchoMapperTest { eventId = anEventId(echo.localId), content = AN_ECHO_CONTENT.content.body, meta = A_META - ) + ).engine() } @Test fun `when merging with echo then updates meta with the echos meta`() = runWith(localEchoMapper) { val previousMeta = MessageMeta.LocalEcho("previous", MessageMeta.LocalEcho.State.Sending) - val event = aRoomMessageEvent(meta = previousMeta) + val event = aRoomMessageEvent(meta = previousMeta).engine() val echo = aLocalEcho() - fakeMetaMapper.given(echo).returns(A_META) + fakeMetaMapper.given(echo).returns(A_META.engine() as app.dapk.st.engine.MessageMeta.LocalEcho) val result = event.mergeWith(echo) - result shouldBeEqualTo aRoomMessageEvent(meta = A_META) + result shouldBeEqualTo aRoomMessageEvent(meta = A_META).engine() } private fun givenEcho(eventId: EventId? = null, localId: String = "", meta: MessageMeta.LocalEcho = A_META): MessageService.LocalEcho { return aLocalEcho(eventId = eventId, message = aTextMessage(localId = localId)).also { - fakeMetaMapper.given(it).returns(meta) + fakeMetaMapper.given(it).returns(meta.engine() as app.dapk.st.engine.MessageMeta.LocalEcho) } } } diff --git a/features/messenger/src/test/kotlin/app/dapk/st/messenger/MergeWithLocalEchosUseCaseTest.kt b/matrix-chat-engine/src/test/kotlin/app/dapk/st/engine/MergeWithLocalEchosUseCaseTest.kt similarity index 85% rename from features/messenger/src/test/kotlin/app/dapk/st/messenger/MergeWithLocalEchosUseCaseTest.kt rename to matrix-chat-engine/src/test/kotlin/app/dapk/st/engine/MergeWithLocalEchosUseCaseTest.kt index f5bcdaf..b5edabd 100644 --- a/features/messenger/src/test/kotlin/app/dapk/st/messenger/MergeWithLocalEchosUseCaseTest.kt +++ b/matrix-chat-engine/src/test/kotlin/app/dapk/st/engine/MergeWithLocalEchosUseCaseTest.kt @@ -1,11 +1,8 @@ -package app.dapk.st.messenger +package app.dapk.st.engine import app.dapk.st.matrix.common.EventId -import app.dapk.st.matrix.common.MessageType -import app.dapk.st.matrix.common.RoomId import app.dapk.st.matrix.message.MessageService import fixture.* -import internalfake.FakeLocalEventMapper import org.amshove.kluent.shouldBeEqualTo import org.junit.Test @@ -18,12 +15,12 @@ private val ANOTHER_ROOM_MESSAGE_EVENT = A_ROOM_MESSAGE_EVENT.copy(eventId = anE class MergeWithLocalEchosUseCaseTest { - private val fakeLocalEchoMapper = FakeLocalEventMapper() + private val fakeLocalEchoMapper = fake.FakeLocalEventMapper() private val mergeWithLocalEchosUseCase = MergeWithLocalEchosUseCaseImpl(fakeLocalEchoMapper.instance) @Test fun `given no local echos, when merging text message, then returns original state`() { - val roomState = aRoomState(events = listOf(A_ROOM_MESSAGE_EVENT)) + val roomState = aRoomState(events = listOf(A_ROOM_MESSAGE_EVENT)).engine() val result = mergeWithLocalEchosUseCase.invoke(roomState, A_ROOM_MEMBER, emptyList()) @@ -32,7 +29,7 @@ class MergeWithLocalEchosUseCaseTest { @Test fun `given no local echos, when merging events, then returns original ordered by timestamp descending`() { - val roomState = aRoomState(events = listOf(A_ROOM_IMAGE_MESSAGE_EVENT.copy(utcTimestamp = 1500), A_ROOM_MESSAGE_EVENT.copy(utcTimestamp = 1000))) + val roomState = aRoomState(events = listOf(A_ROOM_IMAGE_MESSAGE_EVENT.copy(utcTimestamp = 1500), A_ROOM_MESSAGE_EVENT.copy(utcTimestamp = 1000))).engine() val result = mergeWithLocalEchosUseCase.invoke(roomState, A_ROOM_MEMBER, emptyList()) @@ -42,15 +39,15 @@ class MergeWithLocalEchosUseCaseTest { @Test fun `given local echo with sending state, when merging then maps to room event with local echo state`() { val second = createLocalEcho(A_LOCAL_ECHO_EVENT_ID, A_LOCAL_ECHO_BODY, state = MessageService.LocalEcho.State.Sending) - fakeLocalEchoMapper.givenMapping(second, A_ROOM_MEMBER).returns(ANOTHER_ROOM_MESSAGE_EVENT) - val roomState = aRoomState(events = listOf(A_ROOM_MESSAGE_EVENT)) + fakeLocalEchoMapper.givenMapping(second, A_ROOM_MEMBER).returns(ANOTHER_ROOM_MESSAGE_EVENT.engine()) + val roomState = aRoomState(events = listOf(A_ROOM_MESSAGE_EVENT)).engine() val result = mergeWithLocalEchosUseCase.invoke(roomState, A_ROOM_MEMBER, listOf(second)) result shouldBeEqualTo roomState.copy( events = listOf( - A_ROOM_MESSAGE_EVENT, - ANOTHER_ROOM_MESSAGE_EVENT, + A_ROOM_MESSAGE_EVENT.engine(), + ANOTHER_ROOM_MESSAGE_EVENT.engine(), ) ) } @@ -60,4 +57,4 @@ class MergeWithLocalEchosUseCaseTest { aTextMessage(aTextContent(body)), state, ) -} +} \ No newline at end of file diff --git a/features/messenger/src/test/kotlin/app/dapk/st/messenger/MetaMapperTest.kt b/matrix-chat-engine/src/test/kotlin/app/dapk/st/engine/MetaMapperTest.kt similarity index 96% rename from features/messenger/src/test/kotlin/app/dapk/st/messenger/MetaMapperTest.kt rename to matrix-chat-engine/src/test/kotlin/app/dapk/st/engine/MetaMapperTest.kt index 27419ce..eb2cda1 100644 --- a/features/messenger/src/test/kotlin/app/dapk/st/messenger/MetaMapperTest.kt +++ b/matrix-chat-engine/src/test/kotlin/app/dapk/st/engine/MetaMapperTest.kt @@ -1,7 +1,6 @@ -package app.dapk.st.messenger +package app.dapk.st.engine import app.dapk.st.matrix.message.MessageService -import app.dapk.st.matrix.sync.MessageMeta import fixture.aLocalEcho import fixture.aTextMessage import org.amshove.kluent.shouldBeEqualTo diff --git a/features/messenger/src/test/kotlin/app/dapk/st/messenger/TimelineUseCaseTest.kt b/matrix-chat-engine/src/test/kotlin/app/dapk/st/engine/TimelineUseCaseTest.kt similarity index 77% rename from features/messenger/src/test/kotlin/app/dapk/st/messenger/TimelineUseCaseTest.kt rename to matrix-chat-engine/src/test/kotlin/app/dapk/st/engine/TimelineUseCaseTest.kt index 8f5447f..4acd7bf 100644 --- a/features/messenger/src/test/kotlin/app/dapk/st/messenger/TimelineUseCaseTest.kt +++ b/matrix-chat-engine/src/test/kotlin/app/dapk/st/engine/TimelineUseCaseTest.kt @@ -1,13 +1,15 @@ -package app.dapk.st.messenger +package app.dapk.st.engine -import FlowTestObserver import app.dapk.st.matrix.common.RoomId import app.dapk.st.matrix.common.RoomMember +import app.dapk.st.matrix.common.UserId import app.dapk.st.matrix.message.MessageService +import app.dapk.st.matrix.room.RoomService import app.dapk.st.matrix.sync.RoomState import app.dapk.st.matrix.sync.SyncService import fake.FakeSyncService import fixture.* +import io.mockk.coEvery import io.mockk.every import io.mockk.mockk import kotlinx.coroutines.CoroutineScope @@ -16,6 +18,7 @@ import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest import org.junit.Test +import test.FlowTestObserver import test.delegateReturn private val A_ROOM_ID = aRoomId() @@ -47,7 +50,7 @@ class TimelineUseCaseTest { .test(this) .assertValues( listOf( - aMessengerState(self = AN_USER_ID, roomState = A_ROOM_STATE) + aMessengerState(self = AN_USER_ID, roomState = A_ROOM_STATE.engine()) ) ) } @@ -57,13 +60,13 @@ class TimelineUseCaseTest { givenSyncEmission(roomState = A_ROOM_STATE, echos = A_LOCAL_ECHOS_LIST) fakeRoomService.givenFindMember(A_ROOM_ID, AN_USER_ID).returns(A_ROOM_MEMBER) - fakeMergeWithLocalEchosUseCase.givenMerging(A_ROOM_STATE, A_ROOM_MEMBER, A_LOCAL_ECHOS_LIST).returns(A_MERGED_ROOM_STATE) + fakeMergeWithLocalEchosUseCase.givenMerging(A_ROOM_STATE, A_ROOM_MEMBER, A_LOCAL_ECHOS_LIST).returns(A_MERGED_ROOM_STATE.engine()) timelineUseCase.invoke(A_ROOM_ID, AN_USER_ID) .test(this) .assertValues( listOf( - aMessengerState(self = AN_USER_ID, roomState = A_MERGED_ROOM_STATE) + aMessengerState(self = AN_USER_ID, roomState = A_MERGED_ROOM_STATE.engine()) ) ) } @@ -81,7 +84,11 @@ class TimelineUseCaseTest { .test(this) .assertValues( listOf( - aMessengerState(self = AN_USER_ID, roomState = A_ROOM_STATE, typing = aTypingSyncEvent(A_ROOM_ID, members = listOf(A_ROOM_MEMBER))) + aMessengerState( + self = AN_USER_ID, + roomState = A_ROOM_STATE.engine(), + typing = aTypingSyncEvent(A_ROOM_ID, members = listOf(A_ROOM_MEMBER)).engine() + ) ) ) } @@ -104,11 +111,27 @@ suspend fun Flow.test(scope: CoroutineScope) = FlowTestObserver(scope, th class FakeMergeWithLocalEchosUseCase : MergeWithLocalEchosUseCase by mockk() { fun givenMerging(roomState: RoomState, roomMember: RoomMember, echos: List) = every { - this@FakeMergeWithLocalEchosUseCase.invoke(roomState, roomMember, echos) + this@FakeMergeWithLocalEchosUseCase.invoke(roomState.engine(), roomMember, echos) }.delegateReturn() } fun aTypingSyncEvent( roomId: RoomId = aRoomId(), members: List = listOf(aRoomMember()) -) = SyncService.SyncEvent.Typing(roomId, members) \ No newline at end of file +) = SyncService.SyncEvent.Typing(roomId, members) + +class FakeMessageService : MessageService by mockk() { + + fun givenEchos(roomId: RoomId) = every { localEchos(roomId) }.delegateReturn() + +} + +class FakeRoomService : RoomService by mockk() { + fun givenFindMember(roomId: RoomId, userId: UserId) = coEvery { findMember(roomId, userId) }.delegateReturn() +} + +fun aMessengerState( + self: UserId = aUserId(), + roomState: app.dapk.st.engine.RoomState, + typing: Typing? = null +) = MessengerState(self, roomState, typing) \ No newline at end of file diff --git a/features/messenger/src/test/kotlin/internalfake/FakeLocalEventMapper.kt b/matrix-chat-engine/src/test/kotlin/fake/FakeLocalEventMapper.kt similarity index 84% rename from features/messenger/src/test/kotlin/internalfake/FakeLocalEventMapper.kt rename to matrix-chat-engine/src/test/kotlin/fake/FakeLocalEventMapper.kt index 7e3d6e1..2365e9d 100644 --- a/features/messenger/src/test/kotlin/internalfake/FakeLocalEventMapper.kt +++ b/matrix-chat-engine/src/test/kotlin/fake/FakeLocalEventMapper.kt @@ -1,8 +1,8 @@ -package internalfake +package fake +import app.dapk.st.engine.LocalEchoMapper import app.dapk.st.matrix.common.RoomMember import app.dapk.st.matrix.message.MessageService -import app.dapk.st.messenger.LocalEchoMapper import io.mockk.every import io.mockk.mockk diff --git a/features/messenger/src/test/kotlin/internalfake/FakeLocalIdFactory.kt b/matrix-chat-engine/src/test/kotlin/fake/FakeLocalIdFactory.kt similarity index 77% rename from features/messenger/src/test/kotlin/internalfake/FakeLocalIdFactory.kt rename to matrix-chat-engine/src/test/kotlin/fake/FakeLocalIdFactory.kt index 6b70cfb..994f22b 100644 --- a/features/messenger/src/test/kotlin/internalfake/FakeLocalIdFactory.kt +++ b/matrix-chat-engine/src/test/kotlin/fake/FakeLocalIdFactory.kt @@ -1,6 +1,6 @@ -package internalfake +package fake -import app.dapk.st.messenger.LocalIdFactory +import app.dapk.st.engine.LocalIdFactory import io.mockk.every import io.mockk.mockk import test.delegateReturn diff --git a/features/messenger/src/test/kotlin/internalfake/FakeMetaMapper.kt b/matrix-chat-engine/src/test/kotlin/fake/FakeMetaMapper.kt similarity index 82% rename from features/messenger/src/test/kotlin/internalfake/FakeMetaMapper.kt rename to matrix-chat-engine/src/test/kotlin/fake/FakeMetaMapper.kt index 6762d99..8722d9a 100644 --- a/features/messenger/src/test/kotlin/internalfake/FakeMetaMapper.kt +++ b/matrix-chat-engine/src/test/kotlin/fake/FakeMetaMapper.kt @@ -1,7 +1,7 @@ -package internalfake +package fake +import app.dapk.st.engine.MetaMapper import app.dapk.st.matrix.message.MessageService -import app.dapk.st.messenger.MetaMapper import io.mockk.every import io.mockk.mockk import test.delegateReturn diff --git a/matrix/services/sync/src/testFixtures/kotlin/fake/FakeSyncService.kt b/matrix/services/sync/src/testFixtures/kotlin/fake/FakeSyncService.kt index 3909f95..2c1b0bf 100644 --- a/matrix/services/sync/src/testFixtures/kotlin/fake/FakeSyncService.kt +++ b/matrix/services/sync/src/testFixtures/kotlin/fake/FakeSyncService.kt @@ -5,11 +5,12 @@ import app.dapk.st.matrix.sync.SyncService import io.mockk.every import io.mockk.mockk import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.flowOf import test.delegateReturn class FakeSyncService : SyncService by mockk() { fun givenStartsSyncing() { - every { startSyncing() }.returns(emptyFlow()) + every { startSyncing() }.returns(flowOf(Unit)) } fun givenRoom(roomId: RoomId) = every { room(roomId) }.delegateReturn()