feat(creator-channel): 커뮤니티 상세 조회 계약을 추가한다

This commit is contained in:
2026-07-09 00:52:59 +09:00
parent e0dc0c2cb7
commit 9e524d626a
4 changed files with 252 additions and 0 deletions

View File

@@ -0,0 +1,135 @@
package kr.co.vividnext.sodalive.v2.creator.channel.community
import com.google.gson.annotations.SerializedName
import io.reactivex.rxjava3.core.Single
import kr.co.vividnext.sodalive.v2.creator.channel.community.detail.data.CreatorChannelCommunityCommentResponse
import kr.co.vividnext.sodalive.v2.creator.channel.community.detail.data.CreatorChannelCommunityCommentsResponse
import kr.co.vividnext.sodalive.v2.creator.channel.community.detail.data.CreatorChannelCommunityPostDetailResponse
import kr.co.vividnext.sodalive.v2.creator.channel.community.detail.data.CreatorChannelCommunityRepliesResponse
import kr.co.vividnext.sodalive.v2.creator.channel.community.detail.data.CreatorChannelCommunityReplyResponse
import kr.co.vividnext.sodalive.v2.creator.channel.data.CreatorChannelApi
import kr.co.vividnext.sodalive.v2.creator.channel.data.CreatorChannelRepository
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import org.junit.Test
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import java.io.File
class CreatorChannelCommunityDetailContractTest {
@Test
fun `커뮤니티 상세 API source는 신규 v2 endpoint와 ApiResponse Single 계약을 제공한다`() {
val api = projectFile(
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelApi.kt"
).readText()
assertTrue(api.contains("@GET(\"/api/v2/creator-channels/community-posts/{postId}\")"))
assertTrue(api.contains("@GET(\"/api/v2/creator-channels/community-posts/{postId}/comments\")"))
assertTrue(api.contains("@GET(\"/api/v2/creator-channels/community-comments/{commentId}/replies\")"))
assertTrue(api.contains("Single<ApiResponse<CreatorChannelCommunityPostDetailResponse>>"))
assertTrue(api.contains("Single<ApiResponse<CreatorChannelCommunityCommentsResponse>>"))
assertTrue(api.contains("Single<ApiResponse<CreatorChannelCommunityRepliesResponse>>"))
}
@Test
fun `커뮤니티 상세 repository는 댓글과 답글 기본 page 0 size 20 계약을 제공한다`() {
val api = mock<CreatorChannelApi>()
val repository = CreatorChannelRepository(api, mock(), mock(), mock(), mock())
whenever(api.getCommunityPostDetail(11L, "Bearer token")).thenReturn(Single.never())
whenever(api.getCommunityPostComments(11L, 0, 20, "Bearer token")).thenReturn(Single.never())
whenever(api.getCommunityCommentReplies(22L, 0, 20, "Bearer token")).thenReturn(Single.never())
repository.getCommunityPostDetail(11L, "Bearer token")
repository.getCommunityPostComments(11L, token = "Bearer token")
repository.getCommunityCommentReplies(22L, token = "Bearer token")
verify(api).getCommunityPostDetail(11L, "Bearer token")
verify(api).getCommunityPostComments(11L, 0, 20, "Bearer token")
verify(api).getCommunityCommentReplies(22L, 0, 20, "Bearer token")
}
@Test
fun `커뮤니티 상세 응답 모델은 SerializedName과 nullable latestReply 계약을 제공한다`() {
val reply = CreatorChannelCommunityReplyResponse(
commentId = 44L,
writerId = 55L,
writerProfileImageUrl = "reply.png",
writerNickname = "reply member",
content = "reply",
createdAtUtc = "2026-07-08T00:02:00Z"
)
val comment = CreatorChannelCommunityCommentResponse(
commentId = 22L,
writerId = 33L,
writerProfileImageUrl = "member.png",
writerNickname = "member",
content = "comment",
isSecret = false,
createdAtUtc = "2026-07-08T00:01:00Z",
latestReply = reply
)
val comments = CreatorChannelCommunityCommentsResponse(
commentCount = 1,
comments = listOf(comment),
page = 0,
size = 20,
hasNext = false
)
val detail = CreatorChannelCommunityPostDetailResponse(
postId = 11L,
creatorId = 100L,
creatorNickname = "creator",
creatorProfileUrl = null,
createdAtUtc = "2026-07-08T00:00:00Z",
content = "content",
imageUrl = null,
audioUrl = null,
price = 0,
existOrdered = true,
isCommentAvailable = true,
likeCount = 1,
commentCount = 2,
isLiked = false,
isPinned = false,
comments = comments
)
assertEquals(11L, detail.postId)
assertEquals(comments, detail.comments)
assertEquals(reply, comment.latestReply)
assertEquals(44L, reply.commentId)
assertNotNull(
CreatorChannelCommunityPostDetailResponse::class.java.getDeclaredField("postId")
.getAnnotation(SerializedName::class.java)
)
assertNotNull(
CreatorChannelCommunityPostDetailResponse::class.java.getDeclaredField("comments")
.getAnnotation(SerializedName::class.java)
)
assertNotNull(
CreatorChannelCommunityCommentResponse::class.java.getDeclaredField("latestReply")
.getAnnotation(SerializedName::class.java)
)
assertNotNull(
CreatorChannelCommunityCommentResponse::class.java.getDeclaredField("writerId")
.getAnnotation(SerializedName::class.java)
)
assertNotNull(
CreatorChannelCommunityReplyResponse::class.java.getDeclaredField("writerId")
.getAnnotation(SerializedName::class.java)
)
assertEquals(CreatorChannelCommunityCommentsResponse(1, listOf(comment), 0, 20, false).comments.first(), comment)
assertEquals(CreatorChannelCommunityRepliesResponse(listOf(reply), 0, 20, false).replies.first(), reply)
}
private fun projectFile(path: String): File {
var current = File(checkNotNull(System.getProperty("user.dir"))).absoluteFile
while (current.parentFile != null && !File(current, "settings.gradle").exists()) {
current = checkNotNull(current.parentFile)
}
return File(current, path)
}
}