Merge pull request #7969 from vector-im/feature/ons/fix_poll_end_reply

Show poll question when rendering reply to a poll end event (PSG-1133)
This commit is contained in:
Maxime NATUREL 2023-02-01 11:22:39 +01:00 committed by GitHub
commit ebd35bdd88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 138 additions and 39 deletions

View File

@ -35,5 +35,6 @@ object RoomSummaryConstants {
EventType.REACTION EventType.REACTION
) + ) +
EventType.POLL_START.values + EventType.POLL_START.values +
EventType.POLL_END.values +
EventType.STATE_ROOM_BEACON_INFO.values EventType.STATE_ROOM_BEACON_INFO.values
} }

View File

@ -320,7 +320,7 @@ internal class LocalEchoEventFactory @Inject constructor(
val permalink = permalinkFactory.createPermalink(roomId, originalEvent.root.eventId ?: "", false) val permalink = permalinkFactory.createPermalink(roomId, originalEvent.root.eventId ?: "", false)
val userLink = originalEvent.root.senderId?.let { permalinkFactory.createPermalink(it, false) } ?: "" val userLink = originalEvent.root.senderId?.let { permalinkFactory.createPermalink(it, false) } ?: ""
val body = bodyForReply(originalEvent.getLastMessageContent(), originalEvent.isReply()) val body = bodyForReply(timelineEvent = originalEvent)
// As we always supply formatted body for replies we should force the MarkdownParser to produce html. // As we always supply formatted body for replies we should force the MarkdownParser to produce html.
val newBodyFormatted = markdownParser.parse(newBodyText, force = true, advanced = autoMarkdown).takeFormatted() val newBodyFormatted = markdownParser.parse(newBodyText, force = true, advanced = autoMarkdown).takeFormatted()
// Body of the original message may not have formatted version, so may also have to convert to html. // Body of the original message may not have formatted version, so may also have to convert to html.
@ -613,7 +613,7 @@ internal class LocalEchoEventFactory @Inject constructor(
val userId = eventReplied.root.senderId ?: return null val userId = eventReplied.root.senderId ?: return null
val userLink = permalinkFactory.createPermalink(userId, false) ?: return null val userLink = permalinkFactory.createPermalink(userId, false) ?: return null
val body = bodyForReply(eventReplied.getLastMessageContent(), eventReplied.isReply(), isRedactedEvent) val body = bodyForReply(timelineEvent = eventReplied, isRedactedEvent = isRedactedEvent)
// As we always supply formatted body for replies we should force the MarkdownParser to produce html. // As we always supply formatted body for replies we should force the MarkdownParser to produce html.
val finalReplyTextFormatted = replyTextFormatted?.toString() ?: markdownParser.parse(replyText, force = true, advanced = autoMarkdown).takeFormatted() val finalReplyTextFormatted = replyTextFormatted?.toString() ?: markdownParser.parse(replyText, force = true, advanced = autoMarkdown).takeFormatted()
@ -725,6 +725,20 @@ internal class LocalEchoEventFactory @Inject constructor(
} }
} }
private fun bodyForReply(timelineEvent: TimelineEvent, isRedactedEvent: Boolean = false): TextContent {
val content = when (timelineEvent.root.getClearType()) {
in EventType.POLL_END.values -> {
// for end poll event, we use the content of the start poll event
localEchoRepository
.getRelatedPollEvent(timelineEvent)
?.getLastMessageContent()
?: timelineEvent.getLastMessageContent()
}
else -> timelineEvent.getLastMessageContent()
}
return bodyForReply(content = content, isReply = timelineEvent.isReply(), isRedactedEvent = isRedactedEvent)
}
/** /**
* Returns a TextContent used for the fallback event representation in a reply message. * Returns a TextContent used for the fallback event representation in a reply message.
* In case of an edit of a reply the last content is not * In case of an edit of a reply the last content is not
@ -755,6 +769,7 @@ internal class LocalEchoEventFactory @Inject constructor(
MessageType.MSGTYPE_POLL_START -> { MessageType.MSGTYPE_POLL_START -> {
return TextContent((content as? MessagePollContent)?.getBestPollCreationInfo()?.question?.getBestQuestion() ?: "") return TextContent((content as? MessagePollContent)?.getBestPollCreationInfo()?.question?.getBestQuestion() ?: "")
} }
MessageType.MSGTYPE_POLL_END -> return TextContent("Ended poll")
else -> { else -> {
return if (isRedactedEvent) { return if (isRedactedEvent) {
TextContent("message removed.") TextContent("message removed.")

View File

@ -25,6 +25,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.model.message.MessageType import org.matrix.android.sdk.api.session.room.model.message.MessageType
import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.room.send.SendState
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.getRelationContent
import org.matrix.android.sdk.internal.database.RealmSessionProvider import org.matrix.android.sdk.internal.database.RealmSessionProvider
import org.matrix.android.sdk.internal.database.asyncTransaction import org.matrix.android.sdk.internal.database.asyncTransaction
import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper
@ -228,4 +229,15 @@ internal class LocalEchoRepository @Inject constructor(
EventEntity.where(realm, eventId = rootThreadEventId).findFirst()?.threadSummaryLatestMessage?.eventId EventEntity.where(realm, eventId = rootThreadEventId).findFirst()?.threadSummaryLatestMessage?.eventId
} ?: rootThreadEventId } ?: rootThreadEventId
} }
fun getRelatedPollEvent(timelineEvent: TimelineEvent): TimelineEvent? {
val roomId = timelineEvent.roomId
val pollEventId = timelineEvent.getRelationContent()?.eventId ?: return null
return realmSessionProvider.withRealm { realm ->
TimelineEventEntity.where(realm, roomId = roomId, eventId = pollEventId).findFirst()?.let {
timelineEventMapper.map(it)
}
}
}
} }

View File

@ -219,6 +219,9 @@ class MessageActionsViewModel @AssistedInject constructor(
(timelineEvent.getVectorLastMessageContent() as? MessagePollContent)?.getBestPollCreationInfo()?.question?.getBestQuestion() (timelineEvent.getVectorLastMessageContent() as? MessagePollContent)?.getBestPollCreationInfo()?.question?.getBestQuestion()
?: stringProvider.getString(R.string.message_reply_to_poll_preview) ?: stringProvider.getString(R.string.message_reply_to_poll_preview)
} }
in EventType.POLL_END.values -> {
stringProvider.getString(R.string.message_reply_to_ended_poll_preview)
}
else -> null else -> null
} }
} }

View File

@ -19,12 +19,13 @@ package im.vector.app.features.home.room.detail.timeline.render
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.getPollQuestion import org.matrix.android.sdk.api.session.events.model.getPollQuestion
import org.matrix.android.sdk.api.session.events.model.getRelationContent
import org.matrix.android.sdk.api.session.events.model.isAudioMessage import org.matrix.android.sdk.api.session.events.model.isAudioMessage
import org.matrix.android.sdk.api.session.events.model.isFileMessage import org.matrix.android.sdk.api.session.events.model.isFileMessage
import org.matrix.android.sdk.api.session.events.model.isImageMessage import org.matrix.android.sdk.api.session.events.model.isImageMessage
import org.matrix.android.sdk.api.session.events.model.isLiveLocation import org.matrix.android.sdk.api.session.events.model.isLiveLocation
import org.matrix.android.sdk.api.session.events.model.isPoll
import org.matrix.android.sdk.api.session.events.model.isPollEnd import org.matrix.android.sdk.api.session.events.model.isPollEnd
import org.matrix.android.sdk.api.session.events.model.isPollStart import org.matrix.android.sdk.api.session.events.model.isPollStart
import org.matrix.android.sdk.api.session.events.model.isSticker import org.matrix.android.sdk.api.session.events.model.isSticker
@ -32,7 +33,9 @@ import org.matrix.android.sdk.api.session.events.model.isVideoMessage
import org.matrix.android.sdk.api.session.events.model.isVoiceMessage import org.matrix.android.sdk.api.session.events.model.isVoiceMessage
import org.matrix.android.sdk.api.session.getRoom import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.getTimelineEvent import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
import org.matrix.android.sdk.api.session.room.model.relation.ReplyToContent import org.matrix.android.sdk.api.session.room.model.relation.ReplyToContent
import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
import javax.inject.Inject import javax.inject.Inject
private const val IN_REPLY_TO = "In reply to" private const val IN_REPLY_TO = "In reply to"
@ -94,16 +97,22 @@ class ProcessBodyOfReplyToEventUseCase @Inject constructor(
stringProvider.getString(R.string.message_reply_to_sender_sent_sticker) stringProvider.getString(R.string.message_reply_to_sender_sent_sticker)
) )
} }
repliedToEvent.isPoll() -> { repliedToEvent.isPollEnd() -> {
val fallbackText = when { val fallbackText = stringProvider.getString(R.string.message_reply_to_sender_ended_poll)
repliedToEvent.isPollStart() -> stringProvider.getString(R.string.message_reply_to_sender_created_poll) val repliedText = getPollQuestionFromPollEnd(repliedToEvent)
repliedToEvent.isPollEnd() -> stringProvider.getString(R.string.message_reply_to_sender_ended_poll)
else -> ""
}
matrixFormattedBody.replaceRange( matrixFormattedBody.replaceRange(
afterBreakingLineIndex, afterBreakingLineIndex,
endOfBlockQuoteIndex, endOfBlockQuoteIndex,
repliedToEvent.getPollQuestion() ?: fallbackText repliedText ?: fallbackText,
)
}
repliedToEvent.isPollStart() -> {
val fallbackText = stringProvider.getString(R.string.message_reply_to_sender_created_poll)
val repliedText = repliedToEvent.getPollQuestion()
matrixFormattedBody.replaceRange(
afterBreakingLineIndex,
endOfBlockQuoteIndex,
repliedText ?: fallbackText,
) )
} }
repliedToEvent.isLiveLocation() -> { repliedToEvent.isLiveLocation() -> {
@ -126,8 +135,25 @@ class ProcessBodyOfReplyToEventUseCase @Inject constructor(
} }
private fun getEvent(eventId: String, roomId: String) = private fun getEvent(eventId: String, roomId: String) =
getTimelineEvent(eventId, roomId)
?.root
private fun getTimelineEvent(eventId: String, roomId: String) =
activeSessionHolder.getSafeActiveSession() activeSessionHolder.getSafeActiveSession()
?.getRoom(roomId) ?.getRoom(roomId)
?.getTimelineEvent(eventId) ?.getTimelineEvent(eventId)
?.root
private fun getPollQuestionFromPollEnd(event: Event): String? {
val eventId = event.getRelationContent()?.eventId.orEmpty()
val roomId = event.roomId.orEmpty()
return if (eventId.isEmpty() || roomId.isEmpty()) {
null
} else {
(getTimelineEvent(eventId, roomId)
?.getLastMessageContent() as? MessagePollContent)
?.getBestPollCreationInfo()
?.question
?.getBestQuestion()
}
}
} }

View File

@ -31,16 +31,23 @@ import org.junit.Test
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.getPollQuestion import org.matrix.android.sdk.api.session.events.model.getPollQuestion
import org.matrix.android.sdk.api.session.events.model.getRelationContent
import org.matrix.android.sdk.api.session.events.model.isAudioMessage import org.matrix.android.sdk.api.session.events.model.isAudioMessage
import org.matrix.android.sdk.api.session.events.model.isFileMessage import org.matrix.android.sdk.api.session.events.model.isFileMessage
import org.matrix.android.sdk.api.session.events.model.isImageMessage import org.matrix.android.sdk.api.session.events.model.isImageMessage
import org.matrix.android.sdk.api.session.events.model.isLiveLocation import org.matrix.android.sdk.api.session.events.model.isLiveLocation
import org.matrix.android.sdk.api.session.events.model.isPoll import org.matrix.android.sdk.api.session.events.model.isPollEnd
import org.matrix.android.sdk.api.session.events.model.isPollStart
import org.matrix.android.sdk.api.session.events.model.isSticker import org.matrix.android.sdk.api.session.events.model.isSticker
import org.matrix.android.sdk.api.session.events.model.isVideoMessage import org.matrix.android.sdk.api.session.events.model.isVideoMessage
import org.matrix.android.sdk.api.session.events.model.isVoiceMessage import org.matrix.android.sdk.api.session.events.model.isVoiceMessage
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.model.relation.RelationDefaultContent
import org.matrix.android.sdk.api.session.room.model.relation.ReplyToContent import org.matrix.android.sdk.api.session.room.model.relation.ReplyToContent
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
private const val A_ROOM_ID = "room-id" private const val A_ROOM_ID = "room-id"
private const val AN_EVENT_ID = "event-id" private const val AN_EVENT_ID = "event-id"
@ -93,6 +100,7 @@ class ProcessBodyOfReplyToEventUseCaseTest {
fun setup() { fun setup() {
givenNewPrefix() givenNewPrefix()
mockkStatic("org.matrix.android.sdk.api.session.events.model.EventKt") mockkStatic("org.matrix.android.sdk.api.session.events.model.EventKt")
mockkStatic("org.matrix.android.sdk.api.session.room.timeline.TimelineEventKt")
} }
@After @After
@ -104,7 +112,7 @@ class ProcessBodyOfReplyToEventUseCaseTest {
fun `given a replied event of type file message when process the formatted body then content is replaced by correct string`() { fun `given a replied event of type file message when process the formatted body then content is replaced by correct string`() {
// Given // Given
givenTypeOfRepliedEvent(isFileMessage = true) givenTypeOfRepliedEvent(isFileMessage = true)
givenNewContentForId(R.string.message_reply_to_sender_sent_file) givenContentForId(R.string.message_reply_to_sender_sent_file, content = A_NEW_CONTENT)
executeAndAssertResult() executeAndAssertResult()
} }
@ -113,7 +121,7 @@ class ProcessBodyOfReplyToEventUseCaseTest {
fun `given a replied event of type voice message when process the formatted body then content is replaced by correct string`() { fun `given a replied event of type voice message when process the formatted body then content is replaced by correct string`() {
// Given // Given
givenTypeOfRepliedEvent(isVoiceMessage = true) givenTypeOfRepliedEvent(isVoiceMessage = true)
givenNewContentForId(R.string.message_reply_to_sender_sent_voice_message) givenContentForId(R.string.message_reply_to_sender_sent_voice_message, content = A_NEW_CONTENT)
executeAndAssertResult() executeAndAssertResult()
} }
@ -122,7 +130,7 @@ class ProcessBodyOfReplyToEventUseCaseTest {
fun `given a replied event of type audio message when process the formatted body then content is replaced by correct string`() { fun `given a replied event of type audio message when process the formatted body then content is replaced by correct string`() {
// Given // Given
givenTypeOfRepliedEvent(isAudioMessage = true) givenTypeOfRepliedEvent(isAudioMessage = true)
givenNewContentForId(R.string.message_reply_to_sender_sent_audio_file) givenContentForId(R.string.message_reply_to_sender_sent_audio_file, content = A_NEW_CONTENT)
executeAndAssertResult() executeAndAssertResult()
} }
@ -131,7 +139,7 @@ class ProcessBodyOfReplyToEventUseCaseTest {
fun `given a replied event of type image message when process the formatted body then content is replaced by correct string`() { fun `given a replied event of type image message when process the formatted body then content is replaced by correct string`() {
// Given // Given
givenTypeOfRepliedEvent(isImageMessage = true) givenTypeOfRepliedEvent(isImageMessage = true)
givenNewContentForId(R.string.message_reply_to_sender_sent_image) givenContentForId(R.string.message_reply_to_sender_sent_image, content = A_NEW_CONTENT)
executeAndAssertResult() executeAndAssertResult()
} }
@ -140,7 +148,7 @@ class ProcessBodyOfReplyToEventUseCaseTest {
fun `given a replied event of type video message when process the formatted body then content is replaced by correct string`() { fun `given a replied event of type video message when process the formatted body then content is replaced by correct string`() {
// Given // Given
givenTypeOfRepliedEvent(isVideoMessage = true) givenTypeOfRepliedEvent(isVideoMessage = true)
givenNewContentForId(R.string.message_reply_to_sender_sent_video) givenContentForId(R.string.message_reply_to_sender_sent_video, content = A_NEW_CONTENT)
executeAndAssertResult() executeAndAssertResult()
} }
@ -149,49 +157,58 @@ class ProcessBodyOfReplyToEventUseCaseTest {
fun `given a replied event of type sticker message when process the formatted body then content is replaced by correct string`() { fun `given a replied event of type sticker message when process the formatted body then content is replaced by correct string`() {
// Given // Given
givenTypeOfRepliedEvent(isStickerMessage = true) givenTypeOfRepliedEvent(isStickerMessage = true)
givenNewContentForId(R.string.message_reply_to_sender_sent_sticker) givenContentForId(R.string.message_reply_to_sender_sent_sticker, content = A_NEW_CONTENT)
executeAndAssertResult() executeAndAssertResult()
} }
@Test @Test
fun `given a replied event of type poll message with null question when process the formatted body then content is replaced by correct string`() { fun `given a replied event of type poll start message with null question when process the formatted body then content is replaced by correct string`() {
// Given // Given
givenTypeOfRepliedEvent(isPollMessage = true) givenTypeOfRepliedEvent(isPollStartMessage = true)
givenNewContentForId(R.string.message_reply_to_sender_created_poll) givenContentForId(R.string.message_reply_to_sender_created_poll, content = A_NEW_CONTENT)
every { fakeRepliedEvent.getClearType() } returns EventType.POLL_START.unstable
every { fakeRepliedEvent.getPollQuestion() } returns null every { fakeRepliedEvent.getPollQuestion() } returns null
executeAndAssertResult() executeAndAssertResult()
} }
@Test @Test
fun `given a replied event of type poll message with existing question when process the formatted body then content is replaced by correct string`() { fun `given a replied event of type poll start message with existing question when process the formatted body then content is replaced by correct string`() {
// Given // Given
givenTypeOfRepliedEvent(isPollMessage = true) givenTypeOfRepliedEvent(isPollStartMessage = true)
givenNewContentForId(R.string.message_reply_to_sender_created_poll) givenContentForId(R.string.message_reply_to_sender_created_poll, content = "")
every { fakeRepliedEvent.getClearType() } returns EventType.POLL_START.unstable
every { fakeRepliedEvent.getPollQuestion() } returns A_NEW_CONTENT every { fakeRepliedEvent.getPollQuestion() } returns A_NEW_CONTENT
executeAndAssertResult() executeAndAssertResult()
} }
@Test @Test
fun `given a replied event of type poll end message when process the formatted body then content is replaced by correct string`() { fun `given a replied event of type poll end message with null question when process the formatted body then content is replaced by correct string`() {
// Given // Given
givenTypeOfRepliedEvent(isPollMessage = true) givenTypeOfRepliedEvent(isPollEndMessage = true)
givenNewContentForId(R.string.message_reply_to_sender_ended_poll) givenContentForId(R.string.message_reply_to_sender_ended_poll, content = A_NEW_CONTENT)
every { fakeRepliedEvent.getClearType() } returns EventType.POLL_END.unstable givenPollQuestionReturns(fakeRepliedEvent, null)
every { fakeRepliedEvent.getPollQuestion() } returns null every { fakeRepliedEvent.getPollQuestion() } returns null
executeAndAssertResult() executeAndAssertResult()
} }
@Test
fun `given a replied event of type poll end message with existing question when process the formatted body then content is replaced by correct string`() {
// Given
givenTypeOfRepliedEvent(isPollEndMessage = true)
givenContentForId(R.string.message_reply_to_sender_ended_poll, content = "")
every { fakeRepliedEvent.getClearType() } returns EventType.POLL_END.unstable
givenPollQuestionReturns(fakeRepliedEvent, A_NEW_CONTENT)
executeAndAssertResult()
}
@Test @Test
fun `given a replied event of type live location message when process the formatted body then content is replaced by correct string`() { fun `given a replied event of type live location message when process the formatted body then content is replaced by correct string`() {
// Given // Given
givenTypeOfRepliedEvent(isLiveLocationMessage = true) givenTypeOfRepliedEvent(isLiveLocationMessage = true)
givenNewContentForId(R.string.live_location_description) givenContentForId(R.string.live_location_description, content = A_NEW_CONTENT)
executeAndAssertResult() executeAndAssertResult()
} }
@ -242,13 +259,16 @@ class ProcessBodyOfReplyToEventUseCaseTest {
private fun givenARepliedEvent(timelineEvent: TimelineEvent? = mockk()): Event { private fun givenARepliedEvent(timelineEvent: TimelineEvent? = mockk()): Event {
val event = mockk<Event>() val event = mockk<Event>()
val eventId = "event-id"
every { event.eventId } returns eventId
every { event.roomId } returns A_ROOM_ID
timelineEvent?.let { every { it.root } returns event } timelineEvent?.let { every { it.root } returns event }
fakeActiveSessionHolder fakeActiveSessionHolder
.fakeSession .fakeSession
.roomService() .roomService()
.getRoom(A_ROOM_ID) .getRoom(A_ROOM_ID)
.timelineService() .timelineService()
.givenTimelineEvent(timelineEvent) .givenTimelineEventReturns(eventId, timelineEvent)
return event return event
} }
@ -259,7 +279,8 @@ class ProcessBodyOfReplyToEventUseCaseTest {
isImageMessage: Boolean = false, isImageMessage: Boolean = false,
isVideoMessage: Boolean = false, isVideoMessage: Boolean = false,
isStickerMessage: Boolean = false, isStickerMessage: Boolean = false,
isPollMessage: Boolean = false, isPollEndMessage: Boolean = false,
isPollStartMessage: Boolean = false,
isLiveLocationMessage: Boolean = false, isLiveLocationMessage: Boolean = false,
) { ) {
every { fakeRepliedEvent.isFileMessage() } returns isFileMessage every { fakeRepliedEvent.isFileMessage() } returns isFileMessage
@ -268,7 +289,8 @@ class ProcessBodyOfReplyToEventUseCaseTest {
every { fakeRepliedEvent.isImageMessage() } returns isImageMessage every { fakeRepliedEvent.isImageMessage() } returns isImageMessage
every { fakeRepliedEvent.isVideoMessage() } returns isVideoMessage every { fakeRepliedEvent.isVideoMessage() } returns isVideoMessage
every { fakeRepliedEvent.isSticker() } returns isStickerMessage every { fakeRepliedEvent.isSticker() } returns isStickerMessage
every { fakeRepliedEvent.isPoll() } returns isPollMessage every { fakeRepliedEvent.isPollEnd() } returns isPollEndMessage
every { fakeRepliedEvent.isPollStart() } returns isPollStartMessage
every { fakeRepliedEvent.isLiveLocation() } returns isLiveLocationMessage every { fakeRepliedEvent.isLiveLocation() } returns isLiveLocationMessage
} }
@ -276,7 +298,27 @@ class ProcessBodyOfReplyToEventUseCaseTest {
fakeStringProvider.given(R.string.message_reply_to_prefix, A_NEW_PREFIX) fakeStringProvider.given(R.string.message_reply_to_prefix, A_NEW_PREFIX)
} }
private fun givenNewContentForId(@StringRes resId: Int) { private fun givenContentForId(@StringRes resId: Int, content: String) {
fakeStringProvider.given(resId, A_NEW_CONTENT) fakeStringProvider.given(resId, content)
}
private fun givenPollQuestionReturns(pollEndEvent: Event, question: String?) {
val eventId = "start-event-id"
val relationContent = mockk<RelationDefaultContent>()
every { relationContent.eventId } returns eventId
every { pollEndEvent.getRelationContent() } returns relationContent
val timelineEvent = mockk<TimelineEvent>()
val messagePollContent = MessagePollContent(
pollCreationInfo = PollCreationInfo(
question = PollQuestion(unstableQuestion = question)
)
)
every { timelineEvent.getLastMessageContent() } returns messagePollContent
fakeActiveSessionHolder
.fakeSession
.roomService()
.getRoom(A_ROOM_ID)
.timelineService()
.givenTimelineEventReturns(eventId, timelineEvent)
} }
} }

View File

@ -68,7 +68,7 @@ class CreatePollViewModelTest {
.roomService() .roomService()
.getRoom(A_FAKE_ROOM_ID) .getRoom(A_FAKE_ROOM_ID)
.timelineService() .timelineService()
.givenTimelineEvent(A_POLL_START_TIMELINE_EVENT) .givenTimelineEventReturns(A_POLL_START_TIMELINE_EVENT.eventId, A_POLL_START_TIMELINE_EVENT)
} }
@After @After

View File

@ -23,7 +23,7 @@ import org.matrix.android.sdk.api.session.room.timeline.TimelineService
class FakeTimelineService : TimelineService by mockk() { class FakeTimelineService : TimelineService by mockk() {
fun givenTimelineEvent(event: TimelineEvent?) { fun givenTimelineEventReturns(eventId: String, event: TimelineEvent?) {
every { getTimelineEvent(any()) } returns event every { getTimelineEvent(eventId) } returns event
} }
} }