diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DomainMapping.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DomainMapping.kt index 71285ee5a2b..132ad1eccf5 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DomainMapping.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DomainMapping.kt @@ -37,7 +37,6 @@ import io.getstream.chat.android.client.api2.model.dto.DownstreamModerationDetai import io.getstream.chat.android.client.api2.model.dto.DownstreamModerationDto import io.getstream.chat.android.client.api2.model.dto.DownstreamMuteDto import io.getstream.chat.android.client.api2.model.dto.DownstreamPendingMessageDto -import io.getstream.chat.android.client.api2.model.dto.DownstreamPollDto import io.getstream.chat.android.client.api2.model.dto.DownstreamPushPreferenceDto import io.getstream.chat.android.client.api2.model.dto.DownstreamReactionDto import io.getstream.chat.android.client.api2.model.dto.DownstreamReactionGroupDto @@ -48,7 +47,6 @@ import io.getstream.chat.android.client.api2.model.dto.DownstreamThreadInfoDto import io.getstream.chat.android.client.api2.model.dto.DownstreamUserDto import io.getstream.chat.android.client.api2.model.dto.DownstreamUserGroupDto import io.getstream.chat.android.client.api2.model.dto.DownstreamUserGroupMemberDto -import io.getstream.chat.android.client.api2.model.dto.DownstreamVoteDto import io.getstream.chat.android.client.api2.model.dto.PrivacySettingsDto import io.getstream.chat.android.client.api2.model.dto.ReadReceiptsDto import io.getstream.chat.android.client.api2.model.dto.SearchWarningDto @@ -643,54 +641,6 @@ internal class DomainMapping( endAt = end_at, ) - /** - * Transforms DownstreamPollDto to Poll - * - * @return Poll - */ - internal fun DownstreamPollDto.toDomain(): Poll { - val ownUserId = currentUserIdProvider() ?: own_votes.firstOrNull()?.user?.id - val votes = latest_votes_by_option - ?.values - ?.flatten() - ?.filter { it.isAnswer != true } - ?.map { it.toDomain() } ?: emptyList() - val ownVotes = ( - own_votes - .filter { it.isAnswer != true } - .map { it.toDomain() } + - votes.filter { it.user?.id == ownUserId } - ) - .associateBy { it.id } - .values - .toList() - - val answers = latest_answers?.map { it.toAnswerDomain() } ?: emptyList() - - return Poll( - id = id, - name = name, - description = description, - options = options.map { it.toOption() }, - votingVisibility = voting_visibility.toVotingVisibility(), - enforceUniqueVote = enforce_unique_vote, - maxVotesAllowed = max_votes_allowed, - allowUserSuggestedOptions = allow_user_suggested_options, - allowAnswers = allow_answers, - voteCount = vote_count, - voteCountsByOption = vote_counts_by_option ?: emptyMap(), - votes = votes, - ownVotes = ownVotes, - createdAt = created_at, - updatedAt = updated_at, - closed = is_closed ?: false, - answersCount = answers_count, - answers = answers, - createdBy = created_by?.toDomain(), - extraData = extraData ?: emptyMap(), - ) - } - /** * Transforms [PollResponseData] into [Poll] */ @@ -794,34 +744,6 @@ internal class DomainMapping( extraData = custom.mapNotNull { (key, value) -> value?.let { key to it } }.toMap(), ) - /** - * Transforms DownstreamVoteDto to Vote - * - * @return Vote - */ - internal fun DownstreamVoteDto.toDomain(): Vote = Vote( - id = id, - pollId = poll_id, - optionId = option_id, - createdAt = created_at, - updatedAt = updated_at, - user = user?.toDomain(), - ) - - /** - * Transforms DownstreamVoteDto to Answer - * - * @return Answer - */ - internal fun DownstreamVoteDto.toAnswerDomain(): Answer = Answer( - id = id, - pollId = poll_id, - text = answer_text ?: "", - createdAt = created_at, - updatedAt = updated_at, - user = user?.toDomain(), - ) - /** * Transforms String to VotingVisibility * diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/EventDtos.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/EventDtos.kt index 3b6e81af6e4..cada54b7381 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/EventDtos.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/EventDtos.kt @@ -18,6 +18,8 @@ package io.getstream.chat.android.client.api2.model.dto import com.squareup.moshi.JsonClass import io.getstream.chat.android.client.api2.model.dto.utils.internal.ExactDate +import io.getstream.chat.android.network.models.PollResponseData +import io.getstream.chat.android.network.models.PollVoteResponseData import io.getstream.result.Error import java.util.Date @@ -541,7 +543,7 @@ internal data class PollUpdatedEventDto( val cid: String, val message_id: String?, val created_at: ExactDate, - val poll: DownstreamPollDto, + val poll: PollResponseData, ) : ChatEventDto() @JsonClass(generateAdapter = true) @@ -550,7 +552,7 @@ internal data class PollDeletedEventDto( val cid: String, val message_id: String?, val created_at: ExactDate, - val poll: DownstreamPollDto, + val poll: PollResponseData, ) : ChatEventDto() @JsonClass(generateAdapter = true) @@ -559,7 +561,7 @@ internal data class PollClosedEventDto( val cid: String, val message_id: String?, val created_at: ExactDate, - val poll: DownstreamPollDto, + val poll: PollResponseData, ) : ChatEventDto() @JsonClass(generateAdapter = true) @@ -568,8 +570,8 @@ internal data class VoteCastedEventDto( val cid: String, val message_id: String?, val created_at: ExactDate, - val poll: DownstreamPollDto, - val poll_vote: DownstreamVoteDto, + val poll: PollResponseData, + val poll_vote: PollVoteResponseData, ) : ChatEventDto() @JsonClass(generateAdapter = true) @@ -578,8 +580,8 @@ internal data class AnswerCastedEventDto( val cid: String, val message_id: String?, val created_at: ExactDate, - val poll: DownstreamPollDto, - val poll_vote: DownstreamVoteDto, + val poll: PollResponseData, + val poll_vote: PollVoteResponseData, ) : ChatEventDto() @JsonClass(generateAdapter = true) @@ -588,8 +590,8 @@ internal data class VoteChangedEventDto( val cid: String, val message_id: String?, val created_at: ExactDate, - val poll: DownstreamPollDto, - val poll_vote: DownstreamVoteDto, + val poll: PollResponseData, + val poll_vote: PollVoteResponseData, ) : ChatEventDto() @JsonClass(generateAdapter = true) @@ -598,8 +600,8 @@ internal data class VoteRemovedEventDto( val cid: String, val message_id: String?, val created_at: ExactDate, - val poll: DownstreamPollDto, - val poll_vote: DownstreamVoteDto, + val poll: PollResponseData, + val poll_vote: PollVoteResponseData, ) : ChatEventDto() @JsonClass(generateAdapter = true) diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/PollsDtos.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/PollsDtos.kt deleted file mode 100644 index ecfdb0ba08b..00000000000 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/PollsDtos.kt +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2014-2026 Stream.io Inc. All rights reserved. - * - * Licensed under the Stream License; - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://github.com/GetStream/stream-chat-android/blob/main/LICENSE - * - * 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 io.getstream.chat.android.client.api2.model.dto - -import com.squareup.moshi.JsonClass -import io.getstream.chat.android.network.models.PollOptionResponseData -import io.getstream.chat.android.network.models.PollVoteResponseData -import java.util.Date - -/** - * Represents the DTO for a vote in a poll. - * - * @property id The id of the vote. - * @property poll_id The id of the poll. - * @property option_id The id of the option that was voted for. - * @property created_at The date when the vote was created. - * @property updated_at The date when the vote was last updated. - * @property user The user who voted. - * @property user_id The id of the user who voted. - */ -@JsonClass(generateAdapter = true) -internal data class DownstreamVoteDto( - val id: String, - val poll_id: String, - val option_id: String, - val created_at: Date, - val updated_at: Date, - val user: DownstreamUserDto?, - val user_id: String?, - val is_answer: Boolean?, - val answer_text: String?, -) - -/** - * Represents the DTO for a poll. - * - * @property allow_answers Whether the poll allows answers. - * @property allow_user_suggested_options Whether the poll allows user suggested options. - * @property answers_count The total number of answers in the poll. - * @property created_at The date when the poll was created. - * @property created_by The user who created the poll. - * @property created_by_id The id of the user who created the poll. - * @property description The description of the poll. - * @property enforce_unique_vote Whether the poll enforces unique votes. - * @property id The id of the poll. - * @property is_closed Whether the poll is closed. - * @property latest_answers The latest answers in the poll. - * @property latest_votes_by_option The latest votes for each option in the poll. - * @property max_votes_allowed The maximum number of votes allowed in the poll. - * @property name The name of the poll. - * @property options The options in the poll. - * @property own_votes The votes of the user who requested the poll. - * @property updated_at The date when the poll was last updated. - * @property vote_count The total number of votes in the poll. - * @property vote_counts_by_option The vote counts for each option in the poll. - * @property voting_visibility The visibility of the votes in the poll. Can be "public" or "anonymous". - * @property extraData Any extra data associated with the poll. - */ -@JsonClass(generateAdapter = true) -internal data class DownstreamPollDto( - val allow_answers: Boolean, - val allow_user_suggested_options: Boolean, - val answers_count: Int, - val created_at: Date, - val created_by: DownstreamUserDto?, - val created_by_id: String, - val description: String, - val enforce_unique_vote: Boolean, - val id: String, - val is_closed: Boolean?, - val latest_answers: List?, - val latest_votes_by_option: Map>?, - val max_votes_allowed: Int?, - val name: String, - val options: List, - val own_votes: List, - val updated_at: Date, - val vote_count: Int, - val vote_counts_by_option: Map?, - val voting_visibility: String?, - val extraData: Map?, -) : ExtraDataDto diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/MoshiChatParser.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/MoshiChatParser.kt index 2636db78a98..d9ad421724f 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/MoshiChatParser.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/MoshiChatParser.kt @@ -42,7 +42,6 @@ import io.getstream.chat.android.client.parser2.adapters.DownstreamMemberDtoAdap import io.getstream.chat.android.client.parser2.adapters.DownstreamMemberInfoDtoAdapter import io.getstream.chat.android.client.parser2.adapters.DownstreamMessageDtoAdapter import io.getstream.chat.android.client.parser2.adapters.DownstreamModerationDetailsDtoAdapter -import io.getstream.chat.android.client.parser2.adapters.DownstreamPollDtoAdapter import io.getstream.chat.android.client.parser2.adapters.DownstreamReactionDtoAdapter import io.getstream.chat.android.client.parser2.adapters.DownstreamThreadDtoAdapter import io.getstream.chat.android.client.parser2.adapters.DownstreamThreadInfoDtoAdapter @@ -117,7 +116,6 @@ internal class MoshiChatParser( .add(FlagRequestAdapterFactory) .add(DownstreamThreadDtoAdapter) .add(DownstreamThreadInfoDtoAdapter) - .add(DownstreamPollDtoAdapter) .add(CreatePollRequestAdapter) .add(UpdatePollRequestAdapter) .add(CreatePollOptionRequestAdapter) diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/PollDtoAdapters.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/PollDtoAdapters.kt index 3ed7fb7f00b..b094059af93 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/PollDtoAdapters.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/PollDtoAdapters.kt @@ -21,7 +21,6 @@ import com.squareup.moshi.JsonAdapter import com.squareup.moshi.JsonReader import com.squareup.moshi.JsonWriter import com.squareup.moshi.ToJson -import io.getstream.chat.android.client.api2.model.dto.DownstreamPollDto import io.getstream.chat.android.network.models.CreatePollOptionRequest import io.getstream.chat.android.network.models.CreatePollRequest import io.getstream.chat.android.network.models.PollOptionInput @@ -29,23 +28,6 @@ import io.getstream.chat.android.network.models.PollOptionRequest import io.getstream.chat.android.network.models.UpdatePollOptionRequest import io.getstream.chat.android.network.models.UpdatePollRequest -/** - * Deserializer for [DownstreamPollDto] that handles the [io.getstream.chat.android.client.api2.model.dto.ExtraDataDto] - * implementation. - */ -internal object DownstreamPollDtoAdapter : CustomObjectDtoAdapter(DownstreamPollDto::class) { - - @FromJson - fun fromJson( - jsonReader: JsonReader, - mapAdapter: JsonAdapter>, - pollAdapter: JsonAdapter, - ): DownstreamPollDto? = parseWithExtraData(jsonReader, mapAdapter, pollAdapter) - - @ToJson - fun toJson(jsonWriter: JsonWriter, value: DownstreamPollDto): Unit = error("Can't convert this to Json") -} - // The generated poll write-request models carry custom data in a `custom` field that must be // flattened to the JSON root on the wire; extraDataPropertyName matches their @Json(name = "custom"). diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/EventChatJsonProvider.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/EventChatJsonProvider.kt index 874340a666c..1eeb88ab1c8 100644 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/EventChatJsonProvider.kt +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/EventChatJsonProvider.kt @@ -879,7 +879,7 @@ private fun createMessageAttachmentJsonString() = """.trimIndent() @Language("JSON") -private fun createReactionUserJsonString() = +private fun createNestedUserJsonString() = """ { "id": "bender", @@ -902,7 +902,7 @@ private fun createMessageReactionJsonString() = "message_id": "09afcd85-9dbb-4da8-8d85-5a6b4268d755", "type": "like", "score": 1, - "user": ${createReactionUserJsonString()}, + "user": ${createNestedUserJsonString()}, "user_id": "bender", "created_at": "2020-06-29T06:14:28.000Z", "updated_at": "2020-06-29T06:14:28.000Z" @@ -1033,7 +1033,7 @@ private fun createPollJsonString() = "is_closed": false, "answers_count": 0, "latest_answers": [], - "created_by": ${createUserJsonString()}, + "created_by": ${createNestedUserJsonString()}, "created_by_id": "bender" } """.trimIndent() @@ -1047,7 +1047,7 @@ private fun createPollVoteJsonString() = "option_id": "option-1", "created_at": "2020-06-29T06:14:28.000Z", "updated_at": "2020-06-29T06:14:28.000Z", - "user": ${createUserJsonString()}, + "user": ${createNestedUserJsonString()}, "user_id": "bender" } """.trimIndent() @@ -1061,7 +1061,7 @@ private fun createPollAnswerVoteJsonString() = "option_id": "", "created_at": "2020-06-29T06:14:28.000Z", "updated_at": "2020-06-29T06:14:28.000Z", - "user": ${createUserJsonString()}, + "user": ${createNestedUserJsonString()}, "user_id": "bender", "is_answer": true, "answer_text": "My answer" diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/Mother.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/Mother.kt index 930df6742ff..249be7993c1 100644 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/Mother.kt +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/Mother.kt @@ -39,7 +39,6 @@ import io.getstream.chat.android.client.api2.model.dto.DownstreamModerationDetai import io.getstream.chat.android.client.api2.model.dto.DownstreamModerationDto import io.getstream.chat.android.client.api2.model.dto.DownstreamMuteDto import io.getstream.chat.android.client.api2.model.dto.DownstreamPendingMessageDto -import io.getstream.chat.android.client.api2.model.dto.DownstreamPollDto import io.getstream.chat.android.client.api2.model.dto.DownstreamPushPreferenceDto import io.getstream.chat.android.client.api2.model.dto.DownstreamReactionDto import io.getstream.chat.android.client.api2.model.dto.DownstreamReactionGroupDto @@ -49,7 +48,6 @@ import io.getstream.chat.android.client.api2.model.dto.DownstreamThreadInfoDto import io.getstream.chat.android.client.api2.model.dto.DownstreamUserDto import io.getstream.chat.android.client.api2.model.dto.DownstreamUserGroupDto import io.getstream.chat.android.client.api2.model.dto.DownstreamUserGroupMemberDto -import io.getstream.chat.android.client.api2.model.dto.DownstreamVoteDto import io.getstream.chat.android.client.api2.model.dto.ErrorDetailDto import io.getstream.chat.android.client.api2.model.dto.ErrorDto import io.getstream.chat.android.client.api2.model.dto.PrivacySettingsDto @@ -1214,54 +1212,6 @@ internal object Mother { user = user, ) - fun randomDownstreamPollDto( - id: String = randomString(), - name: String = randomString(), - description: String = randomString(), - votingVisibility: String = "public", - enforceUniqueVote: Boolean = randomBoolean(), - maxVotesAllowed: Int? = randomInt(), - allowUserSuggestedOptions: Boolean = randomBoolean(), - allowAnswers: Boolean = randomBoolean(), - options: List = listOf(randomPollOptionResponseData()), - voteCountsByOption: Map = emptyMap(), - latestVotesByOption: Map> = emptyMap(), - latestAnswers: List = listOf( - randomPollVoteResponseData(isAnswer = true, answerText = randomString()), - ), - createdAt: Date = randomDate(), - createdBy: DownstreamUserDto = randomDownstreamUserDto(), - createdById: String = randomString(), - ownVotes: List = listOf(randomPollVoteResponseData()), - updatedAt: Date = randomDate(), - voteCount: Int = randomInt(), - answersCount: Int = randomInt(), - isClosed: Boolean = randomBoolean(), - extraData: Map = randomExtraData(1), - ): DownstreamPollDto = DownstreamPollDto( - id = id, - name = name, - description = description, - voting_visibility = votingVisibility, - enforce_unique_vote = enforceUniqueVote, - max_votes_allowed = maxVotesAllowed, - allow_user_suggested_options = allowUserSuggestedOptions, - allow_answers = allowAnswers, - options = options, - vote_counts_by_option = voteCountsByOption, - latest_votes_by_option = latestVotesByOption, - latest_answers = latestAnswers, - created_at = createdAt, - created_by = createdBy, - created_by_id = createdById, - own_votes = ownVotes, - updated_at = updatedAt, - vote_count = voteCount, - answers_count = answersCount, - is_closed = isClosed, - extraData = extraData, - ) - fun randomPollOptionResponseData( id: String = randomString(), text: String = randomString(), @@ -1272,26 +1222,6 @@ internal object Mother { custom = custom, ) - fun randomDownstreamVoteDto( - id: String = randomString(), - pollId: String = randomString(), - optionId: String = randomString(), - createdAt: Date = randomDate(), - updatedAt: Date = randomDate(), - userId: String = randomString(), - user: DownstreamUserDto? = randomDownstreamUserDto(id = userId), - ): DownstreamVoteDto = DownstreamVoteDto( - id = id, - poll_id = pollId, - option_id = optionId, - created_at = createdAt, - updated_at = updatedAt, - user = user, - user_id = userId, - is_answer = false, - answer_text = null, - ) - fun randomUpdatePollRequest( id: String = randomString(), name: String = randomString(), @@ -1361,23 +1291,52 @@ internal object Mother { custom = custom, ) + @Suppress("LongParameterList") fun randomPollResponseData( id: String = randomString(), name: String = randomString(), + description: String = randomString(), + votingVisibility: String = "public", + enforceUniqueVote: Boolean = randomBoolean(), + maxVotesAllowed: Int? = randomInt(), + allowUserSuggestedOptions: Boolean = randomBoolean(), + allowAnswers: Boolean = randomBoolean(), + options: List = listOf(randomPollOptionResponseData()), + voteCountsByOption: Map = emptyMap(), + latestVotesByOption: Map> = emptyMap(), + latestAnswers: List = listOf( + randomPollVoteResponseData(isAnswer = true, answerText = randomString()), + ), + createdAt: Date = randomDate(), + createdBy: UserResponse? = randomUserResponse(), + createdById: String = randomString(), + ownVotes: List = listOf(randomPollVoteResponseData()), + updatedAt: Date = randomDate(), + voteCount: Int = randomInt(), + answersCount: Int = randomInt(), + isClosed: Boolean = randomBoolean(), custom: Map = emptyMap(), ): PollResponseData = PollResponseData( id = id, name = name, - description = randomString(), - allowAnswers = randomBoolean(), - allowUserSuggestedOptions = randomBoolean(), - answersCount = randomInt(), - createdAt = randomDate(), - createdById = randomString(), - enforceUniqueVote = randomBoolean(), - updatedAt = randomDate(), - voteCount = randomInt(), - votingVisibility = "public", + description = description, + votingVisibility = votingVisibility, + enforceUniqueVote = enforceUniqueVote, + maxVotesAllowed = maxVotesAllowed, + allowUserSuggestedOptions = allowUserSuggestedOptions, + allowAnswers = allowAnswers, + options = options, + voteCountsByOption = voteCountsByOption, + latestVotesByOption = latestVotesByOption, + latestAnswers = latestAnswers, + createdAt = createdAt, + createdBy = createdBy, + createdById = createdById, + ownVotes = ownVotes, + updatedAt = updatedAt, + voteCount = voteCount, + answersCount = answersCount, + isClosed = isClosed, custom = custom, ) diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/DomainMappingTest.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/DomainMappingTest.kt index 48858e9911b..eb8bab245fa 100644 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/DomainMappingTest.kt +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/DomainMappingTest.kt @@ -43,7 +43,6 @@ import io.getstream.chat.android.client.Mother.randomDownstreamModerationDetails import io.getstream.chat.android.client.Mother.randomDownstreamModerationDto import io.getstream.chat.android.client.Mother.randomDownstreamMuteDto import io.getstream.chat.android.client.Mother.randomDownstreamPendingMessageDto -import io.getstream.chat.android.client.Mother.randomDownstreamPollDto import io.getstream.chat.android.client.Mother.randomDownstreamReactionDto import io.getstream.chat.android.client.Mother.randomDownstreamReactionGroupDto import io.getstream.chat.android.client.Mother.randomDownstreamReminderDto @@ -1032,7 +1031,7 @@ internal class DomainMappingTest { @Test @Suppress("LongMethod") - fun `DownstreamPollDto is correctly mapped to Poll`() { + fun `PollResponseData is correctly mapped to Poll`() { val options = listOf( randomPollOptionResponseData(custom = mapOf("optionKey" to "optionValue")), randomPollOptionResponseData(), @@ -1040,7 +1039,8 @@ internal class DomainMappingTest { val ownVote = randomPollVoteResponseData(user = randomUserResponse()) val otherVote = randomPollVoteResponseData(user = randomUserResponse()) val answer = randomPollVoteResponseData(isAnswer = true, answerText = randomString()) - val pollDto = randomDownstreamPollDto( + val pollDto = randomPollResponseData( + custom = mapOf("pollKey" to "pollValue"), options = options, ownVotes = listOf(ownVote), latestAnswers = listOf(answer), @@ -1060,12 +1060,12 @@ internal class DomainMappingTest { Option(options[1].id, options[1].text, emptyMap()), ), votingVisibility = VotingVisibility.PUBLIC, - enforceUniqueVote = pollDto.enforce_unique_vote, - maxVotesAllowed = pollDto.max_votes_allowed ?: 1, - allowUserSuggestedOptions = pollDto.allow_user_suggested_options, - allowAnswers = pollDto.allow_answers, - voteCount = pollDto.vote_count, - voteCountsByOption = pollDto.vote_counts_by_option ?: emptyMap(), + enforceUniqueVote = pollDto.enforceUniqueVote, + maxVotesAllowed = pollDto.maxVotesAllowed, + allowUserSuggestedOptions = pollDto.allowUserSuggestedOptions, + allowAnswers = pollDto.allowAnswers, + voteCount = pollDto.voteCount, + voteCountsByOption = pollDto.voteCountsByOption, votes = listOf( Vote( id = ownVote.id, @@ -1094,10 +1094,10 @@ internal class DomainMappingTest { user = with(sut) { ownVote.user?.toDomain() }, ), ), - createdAt = pollDto.created_at, - updatedAt = pollDto.updated_at, - closed = pollDto.is_closed ?: false, - answersCount = pollDto.answers_count, + createdAt = pollDto.createdAt, + updatedAt = pollDto.updatedAt, + closed = pollDto.isClosed ?: false, + answersCount = pollDto.answersCount, answers = listOf( Answer( id = answer.id, @@ -1108,8 +1108,8 @@ internal class DomainMappingTest { user = with(sut) { answer.user?.toDomain() }, ), ), - createdBy = with(sut) { pollDto.created_by?.toDomain() }, - extraData = pollDto.extraData ?: emptyMap(), + createdBy = with(sut) { pollDto.createdBy?.toDomain() }, + extraData = mapOf("pollKey" to "pollValue"), ) assertEquals(expected, poll) } diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/EventMappingTestArguments.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/EventMappingTestArguments.kt index f5e9d0fa71c..941dd2f8d15 100644 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/EventMappingTestArguments.kt +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/EventMappingTestArguments.kt @@ -211,8 +211,8 @@ internal object EventMappingTestArguments { private val UNREAD_THREAD_MESSAGES = positiveRandomInt() private val REACTION = Mother.randomDownstreamReactionDto() private val WATCHER_COUNT = positiveRandomInt() - private val POLL = Mother.randomDownstreamPollDto() - private val POLL_VOTE = Mother.randomDownstreamVoteDto() + private val POLL = Mother.randomPollResponseData() + private val POLL_VOTE = Mother.randomPollVoteResponseData() private val REMINDER = Mother.randomDownstreamReminderDto() private val THREAD_INFO = Mother.randomDownstreamThreadInfoDto() private val AI_MESSAGE_ID = randomString() diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser/EventArguments.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser/EventArguments.kt index 3d1df980783..b5c0643c681 100644 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser/EventArguments.kt +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser/EventArguments.kt @@ -268,10 +268,11 @@ internal object EventArguments { ) /** - * A reaction embedded in a message is parsed by the generated model, so its user is the shape the - * wire sends for anyone but the connected user: no unread counts, devices, mutes or `invisible`. + * Reactions and polls embedded in an event are parsed by the generated models, so their users are the + * shape the wire sends for anyone but the connected user: no unread counts, devices, mutes or + * `invisible`. */ - private val reactionUser = User( + private val nestedUser = User( id = "bender", role = "user", language = "en", @@ -288,7 +289,7 @@ internal object EventArguments { messageId = "09afcd85-9dbb-4da8-8d85-5a6b4268d755", type = "like", score = 1, - user = reactionUser, + user = nestedUser, userId = "bender", createdAt = date, updatedAt = date, @@ -342,7 +343,7 @@ internal object EventArguments { closed = false, answersCount = 0, answers = emptyList(), - createdBy = user, + createdBy = nestedUser, ) private val vote = Vote( @@ -351,7 +352,7 @@ internal object EventArguments { optionId = "option-1", createdAt = date, updatedAt = date, - user = user, + user = nestedUser, ) private val answer = Answer( @@ -360,7 +361,7 @@ internal object EventArguments { text = "My answer", createdAt = date, updatedAt = date, - user = user, + user = nestedUser, ) private val draftMessage = DraftMessage( diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/DownstreamPollDtoAdapterTest.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/DownstreamPollDtoAdapterTest.kt deleted file mode 100644 index 4645c502989..00000000000 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/DownstreamPollDtoAdapterTest.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2014-2026 Stream.io Inc. All rights reserved. - * - * Licensed under the Stream License; - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://github.com/GetStream/stream-chat-android/blob/main/LICENSE - * - * 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 io.getstream.chat.android.client.parser2 - -import io.getstream.chat.android.client.api2.model.dto.DownstreamPollDto -import io.getstream.chat.android.client.parser2.testdata.PollDtoTestData -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Test - -internal class DownstreamPollDtoAdapterTest { - private val parser = ParserFactory.createMoshiChatParser() - - @Test - fun `Deserialize JSON poll with custom fields`() { - val poll = parser.fromJson( - PollDtoTestData.downstreamPollJson, - DownstreamPollDto::class.java, - ) - Assertions.assertEquals(PollDtoTestData.downstreamPoll, poll) - } - - @Test - fun `Deserialize JSON poll without custom fields`() { - val poll = parser.fromJson( - PollDtoTestData.downstreamPollJsonWithoutExtraData, - DownstreamPollDto::class.java, - ) - Assertions.assertEquals(PollDtoTestData.downstreamPollWithoutExtraData, poll) - } -} diff --git a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/PollParsingTest.kt b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/PollParsingTest.kt index 514b3233b9e..b0ca849d6e0 100644 --- a/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/PollParsingTest.kt +++ b/stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/PollParsingTest.kt @@ -19,7 +19,6 @@ package io.getstream.chat.android.client.parser2 import com.squareup.moshi.JsonDataException import com.squareup.moshi.Moshi import io.getstream.chat.android.client.api2.mapping.DomainMapping -import io.getstream.chat.android.client.api2.model.dto.DownstreamPollDto import io.getstream.chat.android.client.parser2.direct.DeviceAdapter import io.getstream.chat.android.client.parser2.direct.OptionAdapter import io.getstream.chat.android.client.parser2.direct.PollAdapter @@ -29,7 +28,11 @@ import io.getstream.chat.android.client.parser2.testdata.PollTestData import io.getstream.chat.android.models.NoOpChannelTransformer import io.getstream.chat.android.models.NoOpMessageTransformer import io.getstream.chat.android.models.NoOpUserTransformer +import io.getstream.chat.android.models.Option +import io.getstream.chat.android.models.Vote +import io.getstream.chat.android.models.VotingVisibility import io.getstream.chat.android.network.infrastructure.IsoDateAdapter +import io.getstream.chat.android.network.models.PollResponseData import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows @@ -64,18 +67,18 @@ internal class PollParsingTest { currentUserIdProvider = { null }, ) - // region DTO path (JSON → DownstreamPollDto → Poll) + // region Response path (JSON → PollResponseData → Poll) @Test - fun `DTO path - deserializes all fields`() { - val dto = parser.fromJson(PollTestData.jsonAllFields, DownstreamPollDto::class.java) + fun `Response path - deserializes all fields`() { + val dto = parser.fromJson(PollTestData.jsonAllFields, PollResponseData::class.java) val domain = with(domainMapping) { dto.toDomain() } assertEquals(PollTestData.expectedAllFields, domain) } @Test - fun `DTO path - deserializes with optional fields missing`() { - val dto = parser.fromJson(PollTestData.jsonOptionalFieldsMissing, DownstreamPollDto::class.java) + fun `Response path - deserializes with optional fields missing`() { + val dto = parser.fromJson(PollTestData.jsonOptionalFieldsMissing, PollResponseData::class.java) val domain = with(domainMapping) { dto.toDomain() } assertEquals(PollTestData.expectedOptionalFieldsMissing, domain) } @@ -101,8 +104,8 @@ internal class PollParsingTest { // region Explicit nulls (JSON with explicit null values) @Test - fun `DTO path - deserializes with explicit nulls`() { - val dto = parser.fromJson(PollTestData.jsonWithExplicitNulls, DownstreamPollDto::class.java) + fun `Response path - deserializes with explicit nulls`() { + val dto = parser.fromJson(PollTestData.jsonWithExplicitNulls, PollResponseData::class.java) val domain = with(domainMapping) { dto.toDomain() } assertEquals(PollTestData.expectedWithExplicitNulls, domain) } @@ -118,9 +121,9 @@ internal class PollParsingTest { // region Error message parity @Test - fun `DTO path - throws on missing id`() { + fun `Response path - throws on missing id`() { assertThrows { - parser.fromJson(PollTestData.jsonMissingId, DownstreamPollDto::class.java) + parser.fromJson(PollTestData.jsonMissingId, PollResponseData::class.java) } } @@ -132,9 +135,9 @@ internal class PollParsingTest { } @Test - fun `DTO path - throws on missing name`() { + fun `Response path - throws on missing name`() { assertThrows { - parser.fromJson(PollTestData.jsonMissingName, DownstreamPollDto::class.java) + parser.fromJson(PollTestData.jsonMissingName, PollResponseData::class.java) } } @@ -146,9 +149,9 @@ internal class PollParsingTest { } @Test - fun `DTO path - throws on missing description`() { + fun `Response path - throws on missing description`() { assertThrows { - parser.fromJson(PollTestData.jsonMissingDescription, DownstreamPollDto::class.java) + parser.fromJson(PollTestData.jsonMissingDescription, PollResponseData::class.java) } } @@ -159,24 +162,47 @@ internal class PollParsingTest { } } + /** + * The generated model defaults `options` where `PollAdapter` requires it. The backend always sends + * the key, so only a hand-built payload can tell the two apart. + */ @Test - fun `DTO path - throws on missing options`() { - assertThrows { - parser.fromJson(PollTestData.jsonMissingOptions, DownstreamPollDto::class.java) - } + fun `Missing options is empty on the response path and throws on the direct path`() { + val dto = parser.fromJson(PollTestData.jsonMissingOptions, PollResponseData::class.java) + + assertEquals(emptyList