From 0a2b1f8ad185fc471c15c94d22069a98bdb9df6b Mon Sep 17 00:00:00 2001 From: Maxime NATUREL <46314705+mnaturel@users.noreply.github.com> Date: Fri, 3 Feb 2023 18:01:09 +0100 Subject: [PATCH] Adding unit tests for RoomPollDetailMapper --- .../polls/detail/ui/RoomPollDetailMapper.kt | 1 - .../detail/ui/RoomPollDetailMapperTest.kt | 186 ++++++++++++++++++ .../polls/list/ui/PollSummaryMapperTest.kt | 53 +---- .../app/test/fixtures/RoomPollFixture.kt | 65 ++++++ 4 files changed, 259 insertions(+), 46 deletions(-) create mode 100644 vector/src/test/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailMapperTest.kt create mode 100644 vector/src/test/java/im/vector/app/test/fixtures/RoomPollFixture.kt diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailMapper.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailMapper.kt index 4c4fffc654..8f14118d43 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailMapper.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailMapper.kt @@ -27,7 +27,6 @@ import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import timber.log.Timber import javax.inject.Inject -// TODO add unit tests class RoomPollDetailMapper @Inject constructor( private val pollResponseDataFactory: PollResponseDataFactory, private val pollItemViewStateFactory: PollItemViewStateFactory, diff --git a/vector/src/test/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailMapperTest.kt b/vector/src/test/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailMapperTest.kt new file mode 100644 index 0000000000..780026a4e1 --- /dev/null +++ b/vector/src/test/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailMapperTest.kt @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.roomprofile.polls.detail.ui + +import im.vector.app.features.home.room.detail.timeline.factory.PollItemViewStateFactory +import im.vector.app.features.home.room.detail.timeline.helper.PollResponseDataFactory +import im.vector.app.features.poll.PollItemViewState +import im.vector.app.features.roomprofile.polls.detail.domain.GetEndedPollEventIdUseCase +import im.vector.app.test.fixtures.RoomPollFixture +import io.mockk.every +import io.mockk.mockk +import io.mockk.mockkStatic +import io.mockk.unmockkAll +import org.amshove.kluent.shouldBe +import org.amshove.kluent.shouldBeEqualTo +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent +import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent + +private const val AN_EVENT_ID = "event-id" +private const val A_ROOM_ID = "room-id" +private const val AN_EVENT_TIMESTAMP = 123L + +internal class RoomPollDetailMapperTest { + + private val fakePollResponseDataFactory = mockk() + private val fakePollItemViewStateFactory = mockk() + private val fakeGetEndedPollEventIdUseCase = mockk() + + private val roomPollDetailMapper = RoomPollDetailMapper( + pollResponseDataFactory = fakePollResponseDataFactory, + pollItemViewStateFactory = fakePollItemViewStateFactory, + getEndedPollEventIdUseCase = fakeGetEndedPollEventIdUseCase, + ) + + @Before + fun setup() { + mockkStatic("im.vector.app.core.extensions.TimelineEventKt") + } + + @After + fun tearDown() { + unmockkAll() + } + + @Test + fun `given a not ended poll event when mapping to model then result contains correct poll details`() { + // Given + val aPollItemViewState = givenAPollItemViewState() + val aPollEvent = givenAPollTimelineEvent( + eventId = AN_EVENT_ID, + creationTimestamp = AN_EVENT_TIMESTAMP, + isClosed = false, + pollItemViewState = aPollItemViewState, + ) + val expectedResult = RoomPollDetail( + creationTimestamp = AN_EVENT_TIMESTAMP, + isEnded = false, + endedPollEventId = null, + pollItemViewState = aPollItemViewState, + ) + + // When + val result = roomPollDetailMapper.map(aPollEvent) + + // Then + result shouldBeEqualTo expectedResult + } + + @Test + fun `given an ended poll event when mapping to model then result contains correct poll details`() { + // Given + val aPollItemViewState = givenAPollItemViewState() + val aPollEvent = givenAPollTimelineEvent( + eventId = AN_EVENT_ID, + creationTimestamp = AN_EVENT_TIMESTAMP, + isClosed = true, + pollItemViewState = aPollItemViewState, + ) + val endedPollEventId = givenEndedPollEventId() + val expectedResult = RoomPollDetail( + creationTimestamp = AN_EVENT_TIMESTAMP, + isEnded = true, + endedPollEventId = endedPollEventId, + pollItemViewState = aPollItemViewState, + ) + + // When + val result = roomPollDetailMapper.map(aPollEvent) + + // Then + result shouldBeEqualTo expectedResult + } + + @Test + fun `given missing data in event when mapping to model then result is null`() { + // Given + val aPollItemViewState = givenAPollItemViewState() + val noIdPollEvent = givenAPollTimelineEvent( + eventId = "", + creationTimestamp = AN_EVENT_TIMESTAMP, + isClosed = false, + pollItemViewState = aPollItemViewState, + ) + val noTimestampPollEvent = givenAPollTimelineEvent( + eventId = AN_EVENT_ID, + creationTimestamp = 0, + isClosed = false, + pollItemViewState = aPollItemViewState, + ) + val notAPollEvent = RoomPollFixture.givenATimelineEvent( + eventId = AN_EVENT_ID, + roomId = "room-id", + creationTimestamp = 0, + content = mockk(), + ) + + // When + val result1 = roomPollDetailMapper.map(noIdPollEvent) + val result2 = roomPollDetailMapper.map(noTimestampPollEvent) + val result3 = roomPollDetailMapper.map(notAPollEvent) + + // Then + result1 shouldBe null + result2 shouldBe null + result3 shouldBe null + } + + private fun givenAPollItemViewState(): PollItemViewState { + return PollItemViewState( + question = "", + votesStatus = "", + canVote = true, + optionViewStates = emptyList(), + ) + } + + private fun givenAPollTimelineEvent( + eventId: String, + creationTimestamp: Long, + isClosed: Boolean, + pollItemViewState: PollItemViewState, + ): TimelineEvent { + val pollCreationInfo = RoomPollFixture.givenPollCreationInfo("pollTitle") + val messageContent = RoomPollFixture.givenAMessagePollContent(pollCreationInfo) + val timelineEvent = RoomPollFixture.givenATimelineEvent(eventId, A_ROOM_ID, creationTimestamp, messageContent) + val pollResponseData = RoomPollFixture.givenAPollResponseData(isClosed, totalVotes = 1) + every { fakePollResponseDataFactory.create(timelineEvent) } returns pollResponseData + every { + fakePollItemViewStateFactory.create( + pollContent = messageContent, + pollResponseData = pollResponseData, + isSent = true + ) + } returns pollItemViewState + + return timelineEvent + } + + private fun givenEndedPollEventId(): String { + val eventId = "ended-poll-event-id" + every { + fakeGetEndedPollEventIdUseCase.execute( + startPollEventId = AN_EVENT_ID, + roomId = A_ROOM_ID, + ) + } returns eventId + return eventId + } +} diff --git a/vector/src/test/java/im/vector/app/features/roomprofile/polls/list/ui/PollSummaryMapperTest.kt b/vector/src/test/java/im/vector/app/features/roomprofile/polls/list/ui/PollSummaryMapperTest.kt index 2459e3c8da..3b09cfd957 100644 --- a/vector/src/test/java/im/vector/app/features/roomprofile/polls/list/ui/PollSummaryMapperTest.kt +++ b/vector/src/test/java/im/vector/app/features/roomprofile/polls/list/ui/PollSummaryMapperTest.kt @@ -16,11 +16,10 @@ package im.vector.app.features.roomprofile.polls.list.ui -import im.vector.app.core.extensions.getVectorLastMessageContent import im.vector.app.features.home.room.detail.timeline.factory.PollOptionViewStateFactory import im.vector.app.features.home.room.detail.timeline.helper.PollResponseDataFactory import im.vector.app.features.home.room.detail.timeline.item.PollOptionViewState -import im.vector.app.features.home.room.detail.timeline.item.PollResponseData +import im.vector.app.test.fixtures.RoomPollFixture import io.mockk.every import io.mockk.mockk import io.mockk.mockkStatic @@ -30,11 +29,7 @@ import org.amshove.kluent.shouldBeEqualTo import org.junit.After import org.junit.Before import org.junit.Test -import org.matrix.android.sdk.api.session.room.model.message.MessageContent -import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent -import org.matrix.android.sdk.api.session.room.model.message.PollCreationInfo -import org.matrix.android.sdk.api.session.room.model.message.PollQuestion import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent private const val AN_EVENT_ID = "event-id" @@ -128,10 +123,11 @@ internal class PollSummaryMapperTest { pollTitle = A_POLL_TITLE, isClosed = false, ) - val notAPollEvent = givenATimelineEvent( + val notAPollEvent = RoomPollFixture.givenATimelineEvent( eventId = AN_EVENT_ID, + roomId = "room-id", creationTimestamp = 0, - content = mockk() + content = mockk(), ) // When @@ -145,18 +141,6 @@ internal class PollSummaryMapperTest { result3 shouldBe null } - private fun givenATimelineEvent( - eventId: String, - creationTimestamp: Long, - content: MessageContent, - ): TimelineEvent { - val timelineEvent = mockk() - every { timelineEvent.root.eventId } returns eventId - every { timelineEvent.root.originServerTs } returns creationTimestamp - every { timelineEvent.getVectorLastMessageContent() } returns content - return timelineEvent - } - private fun givenAPollTimelineEvent( eventId: String, creationTimestamp: Long, @@ -165,10 +149,10 @@ internal class PollSummaryMapperTest { totalVotes: Int = 0, winnerOptions: List = emptyList(), ): TimelineEvent { - val pollCreationInfo = givenPollCreationInfo(pollTitle) - val messageContent = givenAMessagePollContent(pollCreationInfo) - val timelineEvent = givenATimelineEvent(eventId, creationTimestamp, messageContent) - val pollResponseData = givenAPollResponseData(isClosed, totalVotes) + val pollCreationInfo = RoomPollFixture.givenPollCreationInfo(pollTitle) + val messageContent = RoomPollFixture.givenAMessagePollContent(pollCreationInfo) + val timelineEvent = RoomPollFixture.givenATimelineEvent(eventId, "room-id", creationTimestamp, messageContent) + val pollResponseData = RoomPollFixture.givenAPollResponseData(isClosed, totalVotes) every { fakePollResponseDataFactory.create(timelineEvent) } returns pollResponseData every { fakePollOptionViewStateFactory.createPollEndedOptions( @@ -180,27 +164,6 @@ internal class PollSummaryMapperTest { return timelineEvent } - private fun givenAMessagePollContent(pollCreationInfo: PollCreationInfo): MessagePollContent { - return MessagePollContent( - unstablePollCreationInfo = pollCreationInfo, - ) - } - - private fun givenPollCreationInfo(pollTitle: String): PollCreationInfo { - return PollCreationInfo( - question = PollQuestion(unstableQuestion = pollTitle), - ) - } - - private fun givenAPollResponseData(isClosed: Boolean, totalVotes: Int): PollResponseData { - return PollResponseData( - myVote = "", - votes = emptyMap(), - isClosed = isClosed, - totalVotes = totalVotes, - ) - } - private fun givenAPollEndedOption(isWinner: Boolean): PollOptionViewState.PollEnded { return mockk().also { every { it.isWinner } returns isWinner diff --git a/vector/src/test/java/im/vector/app/test/fixtures/RoomPollFixture.kt b/vector/src/test/java/im/vector/app/test/fixtures/RoomPollFixture.kt new file mode 100644 index 0000000000..fcba54d1ce --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fixtures/RoomPollFixture.kt @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.test.fixtures + +import im.vector.app.core.extensions.getVectorLastMessageContent +import im.vector.app.features.home.room.detail.timeline.item.PollResponseData +import io.mockk.every +import io.mockk.mockk +import org.matrix.android.sdk.api.session.room.model.message.MessageContent +import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent +import org.matrix.android.sdk.api.session.room.model.message.PollCreationInfo +import org.matrix.android.sdk.api.session.room.model.message.PollQuestion +import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent + +object RoomPollFixture { + + fun givenATimelineEvent( + eventId: String, + roomId: String, + creationTimestamp: Long, + content: MessageContent, + ): TimelineEvent { + val timelineEvent = mockk() + every { timelineEvent.root.eventId } returns eventId + every { timelineEvent.roomId } returns roomId + every { timelineEvent.root.originServerTs } returns creationTimestamp + every { timelineEvent.getVectorLastMessageContent() } returns content + return timelineEvent + } + + fun givenAMessagePollContent(pollCreationInfo: PollCreationInfo): MessagePollContent { + return MessagePollContent( + unstablePollCreationInfo = pollCreationInfo, + ) + } + + fun givenPollCreationInfo(pollTitle: String): PollCreationInfo { + return PollCreationInfo( + question = PollQuestion(unstableQuestion = pollTitle), + ) + } + + fun givenAPollResponseData(isClosed: Boolean, totalVotes: Int): PollResponseData { + return PollResponseData( + myVote = "", + votes = emptyMap(), + isClosed = isClosed, + totalVotes = totalVotes, + ) + } +}