feat(community): 게시물 상세 응답 모델을 추가한다

This commit is contained in:
2026-07-07 11:55:33 +09:00
parent 19ada9e574
commit fe9adf35e7
4 changed files with 292 additions and 0 deletions
@@ -0,0 +1,99 @@
package kr.co.vividnext.sodalive.v2.api.creator.channel.community.dto
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.KotlinModule
import kr.co.vividnext.sodalive.v2.creator.channel.community.domain.CreatorChannelCommunityComment
import kr.co.vividnext.sodalive.v2.creator.channel.community.domain.CreatorChannelCommunityComments
import kr.co.vividnext.sodalive.v2.creator.channel.community.domain.CreatorChannelCommunityPost
import kr.co.vividnext.sodalive.v2.creator.channel.community.domain.CreatorChannelCommunityPostDetail
import kr.co.vividnext.sodalive.v2.creator.channel.community.domain.CreatorChannelCommunityReplies
import kr.co.vividnext.sodalive.v2.creator.channel.community.domain.CreatorChannelCommunityReply
import kr.co.vividnext.sodalive.v2.creator.channel.live.domain.CreatorChannelPage
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import java.time.LocalDateTime
class CreatorChannelCommunityPostDetailResponseTest {
@Test
@DisplayName("상세 응답 DTO는 is prefix boolean 필드명과 댓글/답글 구조를 유지한다")
fun shouldSerializeBooleanFieldsWithIsPrefixAndReuseCommentsResponse() {
val mapper = ObjectMapper().registerModule(KotlinModule.Builder().build())
val response = CreatorChannelCommunityPostDetailResponse.from(createDetail())
val replies = CreatorChannelCommunityRepliesResponse.from(createReplies())
val detailJson = mapper.readTree(mapper.writeValueAsString(response))
val repliesJson = mapper.readTree(mapper.writeValueAsString(replies))
assertTrue(detailJson["isCommentAvailable"].asBoolean())
assertTrue(detailJson["isPinned"].asBoolean())
assertTrue(detailJson["isLiked"].asBoolean())
assertTrue(detailJson["comments"]["hasNext"].asBoolean())
assertTrue(detailJson["comments"]["comments"][0].has("latestReply"))
assertTrue(detailJson["comments"]["comments"][0]["latestReply"].has("commentId"))
assertTrue(repliesJson["hasNext"].asBoolean())
assertFalse(repliesJson["replies"][0].has("latestReply"))
}
private fun createDetail(): CreatorChannelCommunityPostDetail {
val reply = CreatorChannelCommunityReply(
commentId = 2L,
writerProfileImageUrl = "https://cdn.test/reply.png",
writerNickname = "reply-writer",
content = "reply",
createdAt = LocalDateTime.of(2026, 7, 6, 3, 1)
)
return CreatorChannelCommunityPostDetail(
post = CreatorChannelCommunityPost(
postId = 1L,
creatorId = 10L,
creatorNickname = "creator",
creatorProfileUrl = "https://cdn.test/profile.png",
imageUrl = "https://cdn.test/image.png",
audioUrl = null,
content = "content",
price = 0,
createdAt = LocalDateTime.of(2026, 7, 6, 3, 0),
existOrdered = false,
isCommentAvailable = true,
likeCount = 1,
commentCount = 1,
isPinned = true,
isLiked = true
),
comments = CreatorChannelCommunityComments(
commentCount = 1,
comments = listOf(
CreatorChannelCommunityComment(
commentId = 1L,
writerProfileImageUrl = "https://cdn.test/comment.png",
writerNickname = "comment-writer",
content = "comment",
createdAt = LocalDateTime.of(2026, 7, 6, 3, 0),
latestReply = reply
)
),
page = CreatorChannelPage(0, 20),
hasNext = true
)
)
}
private fun createReplies(): CreatorChannelCommunityReplies {
return CreatorChannelCommunityReplies(
replyCount = 1,
replies = listOf(
CreatorChannelCommunityReply(
commentId = 2L,
writerProfileImageUrl = "https://cdn.test/reply.png",
writerNickname = "reply-writer",
content = "reply",
createdAt = LocalDateTime.of(2026, 7, 6, 3, 1)
)
),
page = CreatorChannelPage(0, 20),
hasNext = true
)
}
}
@@ -41,6 +41,20 @@ class CreatorChannelCommunityQueryPolicyTest {
assertEquals(51, maximumPage.fetchLimit)
}
@Test
@DisplayName("커뮤니티 댓글도 커뮤니티 탭과 같은 page fallback 정책을 사용한다")
fun shouldUseSamePageFallbackForCommunityComments() {
val defaultPage = policy.createPage(page = null, size = null)
val boundedPage = policy.createPage(page = -1, size = 100)
assertEquals(0, defaultPage.page)
assertEquals(20, defaultPage.size)
assertEquals(21, defaultPage.fetchLimit)
assertEquals(0, boundedPage.page)
assertEquals(50, boundedPage.size)
assertEquals(51, boundedPage.fetchLimit)
}
@Test
@DisplayName("커뮤니티 탭 목록 정책은 요청 size만 남기고 다음 페이지 여부를 계산한다")
fun shouldLimitItemsAndCalculateHasNext() {