feat(creator): 커뮤니티 게시글 UI 모델을 추가한다

This commit is contained in:
2026-06-21 22:32:23 +09:00
parent efe12774f7
commit f9501c156a
5 changed files with 285 additions and 0 deletions

View File

@@ -0,0 +1,166 @@
package kr.co.vividnext.sodalive.v2.creator.channel.community
import android.app.Application
import android.content.Context
import androidx.test.core.app.ApplicationProvider
import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.common.AndroidUtcRelativeTimeTextFormatter
import kr.co.vividnext.sodalive.v2.creator.channel.community.data.CreatorChannelCommunityPostResponse
import kr.co.vividnext.sodalive.v2.creator.channel.community.model.CreatorChannelCommunityImageMode
import kr.co.vividnext.sodalive.v2.creator.channel.community.model.CreatorChannelCommunityViewMode
import kr.co.vividnext.sodalive.v2.creator.channel.community.model.toCommunityPostUiModels
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [28], application = Application::class)
class CreatorChannelCommunityMapperTest {
private val context: Context = ApplicationProvider.getApplicationContext()
private val relativeTimeTextFormatter = AndroidUtcRelativeTimeTextFormatter(context)
@Test
fun `보기 방식은 label과 icon resource를 가진다`() {
assertEquals(R.string.creator_channel_community_view_mode_list, CreatorChannelCommunityViewMode.List.labelResId)
assertEquals(R.drawable.ic_new_list, CreatorChannelCommunityViewMode.List.iconResId)
assertEquals(R.string.creator_channel_community_view_mode_grid, CreatorChannelCommunityViewMode.Grid.labelResId)
assertEquals(R.drawable.ic_new_grid, CreatorChannelCommunityViewMode.Grid.iconResId)
}
@Test
fun `게시글 기본 필드와 상대 시간 notice 댓글 표시 상태를 매핑한다`() {
val item = listOf(
communityPost(
creatorProfileUrl = "profile.png",
createdAtUtc = System.currentTimeMillis().toString(),
isPinned = true,
isCommentAvailable = true
)
).toCommunityPostUiModels(relativeTimeTextFormatter, isOwner = false, currentUserId = 99L).single()
assertEquals(1L, item.postId)
assertEquals(10L, item.creatorId)
assertEquals("creator", item.creatorNickname)
assertEquals("profile.png", item.creatorProfileUrl)
assertEquals(context.getString(R.string.character_comment_time_just_now), item.createdAtText)
assertEquals("hello community", item.content)
assertEquals(3, item.likeCount)
assertEquals(4, item.commentCount)
assertTrue(item.showNotice)
assertTrue(item.showComment)
}
@Test
fun `댓글 불가 게시글은 댓글 표시 상태가 false다`() {
val item = listOf(communityPost(isCommentAvailable = false))
.toCommunityPostUiModels(relativeTimeTextFormatter, isOwner = false, currentUserId = 99L)
.single()
assertFalse(item.showComment)
}
@Test
fun `유료 미구매 타인 게시글은 잠금 상태이고 play button을 숨긴다`() {
val item = listOf(
communityPost(price = 100, existOrdered = false, imageUrl = "image.png", audioUrl = "audio.mp3")
).toCommunityPostUiModels(relativeTimeTextFormatter, isOwner = false, currentUserId = 99L).single()
assertTrue(item.isLocked)
assertEquals(CreatorChannelCommunityImageMode.LockedGray, item.imageMode)
assertFalse(item.showPlayButton)
}
@Test
fun `본인 또는 구매한 사용자는 이미지와 오디오가 있으면 play button을 표시한다`() {
val ownerItem = listOf(
communityPost(price = 100, existOrdered = false, imageUrl = "image.png", audioUrl = "audio.mp3")
).toCommunityPostUiModels(relativeTimeTextFormatter, isOwner = true, currentUserId = 10L).single()
val orderedItem = listOf(
communityPost(price = 100, existOrdered = true, imageUrl = "image.png", audioUrl = "audio.mp3")
).toCommunityPostUiModels(relativeTimeTextFormatter, isOwner = false, currentUserId = 99L).single()
assertFalse(ownerItem.isLocked)
assertTrue(ownerItem.showPlayButton)
assertFalse(orderedItem.isLocked)
assertTrue(orderedItem.showPlayButton)
}
@Test
fun `오디오 또는 이미지가 없으면 play button을 숨긴다`() {
val items = listOf(
communityPost(postId = 1L, imageUrl = null, audioUrl = "audio.mp3"),
communityPost(postId = 2L, imageUrl = "image.png", audioUrl = null),
communityPost(postId = 3L, imageUrl = "image.png", audioUrl = " ")
).toCommunityPostUiModels(relativeTimeTextFormatter, isOwner = false, currentUserId = 99L)
assertEquals(listOf(false, false, false), items.map { it.showPlayButton })
}
@Test
fun `본인 채널에 본인이 쓴 게시글에서만 owner more와 유료 top price를 표시한다`() {
val ownerPaid = listOf(communityPost(price = 100, creatorId = 10L))
.toCommunityPostUiModels(relativeTimeTextFormatter, isOwner = true, currentUserId = 10L)
.single()
val ownerFree = listOf(communityPost(price = 0, creatorId = 10L))
.toCommunityPostUiModels(relativeTimeTextFormatter, isOwner = true, currentUserId = 10L)
.single()
val otherCreator = listOf(communityPost(price = 100, creatorId = 11L))
.toCommunityPostUiModels(relativeTimeTextFormatter, isOwner = true, currentUserId = 10L)
.single()
val otherChannel = listOf(communityPost(price = 100, creatorId = 10L))
.toCommunityPostUiModels(relativeTimeTextFormatter, isOwner = false, currentUserId = 10L)
.single()
assertTrue(ownerPaid.showOwnerMore)
assertTrue(ownerPaid.showOwnerTopPrice)
assertTrue(ownerFree.showOwnerMore)
assertFalse(ownerFree.showOwnerTopPrice)
assertFalse(otherCreator.showOwnerMore)
assertFalse(otherCreator.showOwnerTopPrice)
assertFalse(otherChannel.showOwnerMore)
assertFalse(otherChannel.showOwnerTopPrice)
}
@Test
fun `grid text-only preview는 줄바꿈을 공백으로 바꾸고 trim 후 24자까지만 사용한다`() {
val item = listOf(communityPost(content = "\n123456789012345678901234567890\n"))
.toCommunityPostUiModels(relativeTimeTextFormatter, isOwner = false, currentUserId = 99L)
.single()
assertEquals("123456789012345678901234", item.gridPreviewText)
}
private fun communityPost(
postId: Long = 1L,
creatorId: Long = 10L,
creatorProfileUrl: String = "profile.png",
createdAtUtc: String = "2026-06-21T00:00:00Z",
content: String = "hello community",
imageUrl: String? = null,
audioUrl: String? = null,
price: Int = 0,
existOrdered: Boolean = true,
isCommentAvailable: Boolean = true,
isPinned: Boolean = false
) = CreatorChannelCommunityPostResponse(
postId = postId,
creatorId = creatorId,
creatorNickname = "creator",
creatorProfileUrl = creatorProfileUrl,
createdAtUtc = createdAtUtc,
content = content,
imageUrl = imageUrl,
audioUrl = audioUrl,
price = price,
existOrdered = existOrdered,
isCommentAvailable = isCommentAvailable,
likeCount = 3,
commentCount = 4,
isPinned = isPinned
)
}