feat(creator): 채널 홈 응답 모델을 추가한다
This commit is contained in:
@@ -0,0 +1,231 @@
|
||||
package kr.co.vividnext.sodalive.v2.creator.channel.application
|
||||
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import kr.co.vividnext.sodalive.v2.common.domain.CreatorActivityType
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.domain.CreatorChannelActivity
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.domain.CreatorChannelAudioContent
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.domain.CreatorChannelCommunityPost
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.domain.CreatorChannelCreator
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.domain.CreatorChannelDonation
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.domain.CreatorChannelFanTalk
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.domain.CreatorChannelFanTalkSummary
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.domain.CreatorChannelHome
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.domain.CreatorChannelLive
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.domain.CreatorChannelSchedule
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.domain.CreatorChannelSeries
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.domain.CreatorChannelSns
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.dto.CreatorChannelHomeResponse
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertFalse
|
||||
import org.junit.jupiter.api.Assertions.assertNotNull
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.time.LocalDateTime
|
||||
|
||||
class CreatorChannelHomeQueryServiceTest {
|
||||
private val objectMapper = jacksonObjectMapper()
|
||||
|
||||
@Test
|
||||
@DisplayName("크리에이터 채널 홈 모델은 홈 탭 전체 섹션을 담고 응답 DTO로 변환된다")
|
||||
fun shouldConvertCreatorChannelHomeToResponse() {
|
||||
val home = createHome()
|
||||
|
||||
val response = CreatorChannelHomeResponse.from(home)
|
||||
|
||||
assertEquals(home.creator.creatorId, response.creator.creatorId)
|
||||
assertEquals(home.currentLive?.liveId, response.currentLive?.liveId)
|
||||
assertEquals(home.latestAudioContent?.audioContentId, response.latestAudioContent?.audioContentId)
|
||||
assertEquals(home.channelDonations.first().donationId, response.channelDonations.first().donationId)
|
||||
assertEquals(home.notices.first().postId, response.notices.first().postId)
|
||||
assertEquals(home.schedules.first().targetId, response.schedules.first().targetId)
|
||||
assertEquals(home.audioContents.first().audioContentId, response.audioContents.first().audioContentId)
|
||||
assertEquals(home.series.first().seriesId, response.series.first().seriesId)
|
||||
assertEquals(home.communities.first().postId, response.communities.first().postId)
|
||||
assertEquals(home.fanTalk.latestFanTalk?.fanTalkId, response.fanTalk.latestFanTalk?.fanTalkId)
|
||||
assertEquals(home.introduce, response.introduce)
|
||||
assertEquals(home.activity.liveCount, response.activity.liveCount)
|
||||
assertEquals(home.sns.instagramUrl, response.sns.instagramUrl)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("응답 DTO는 날짜/시간을 UTC ISO-8601 문자열로 변환한다")
|
||||
fun shouldConvertDateTimeFieldsToUtcIsoString() {
|
||||
val response = CreatorChannelHomeResponse.from(createHome())
|
||||
|
||||
assertEquals("2026-06-12T01:00:00Z", response.currentLive?.beginDateTimeUtc)
|
||||
assertEquals("2026-06-12T02:00:00Z", response.channelDonations.first().createdAtUtc)
|
||||
assertEquals("2026-06-12T03:00:00Z", response.schedules.first().scheduledAtUtc)
|
||||
assertEquals("2026-06-12T04:00:00Z", response.notices.first().dateUtc)
|
||||
assertEquals("2026-06-12T05:00:00Z", response.fanTalk.latestFanTalk?.createdAtUtc)
|
||||
assertEquals("2026-06-12T06:00:00Z", response.activity.debutDateUtc)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("응답 DTO는 Boolean 공개 계약 필드를 보존한다")
|
||||
fun shouldPreserveBooleanApiFields() {
|
||||
val response = CreatorChannelHomeResponse.from(createHome())
|
||||
|
||||
assertTrue(response.creator.isAiChatAvailable)
|
||||
assertFalse(response.creator.isDmAvailable)
|
||||
assertTrue(response.creator.isFollow)
|
||||
assertFalse(response.creator.isNotify)
|
||||
assertTrue(response.currentLive?.isAdult == true)
|
||||
assertTrue(response.latestAudioContent?.isPointAvailable == true)
|
||||
assertTrue(response.latestAudioContent?.isFirstContent == true)
|
||||
assertTrue(response.latestAudioContent?.isAdult == true)
|
||||
assertTrue(response.series.first().isOriginal)
|
||||
assertNotNull(response.latestAudioContent?.isOriginalSeries)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("응답 DTO는 Boolean JSON 필드명을 is prefix로 유지한다")
|
||||
fun shouldSerializeBooleanFieldsWithIsPrefix() {
|
||||
val response = CreatorChannelHomeResponse.from(createHome())
|
||||
|
||||
val json = objectMapper.readTree(objectMapper.writeValueAsString(response))
|
||||
|
||||
assertTrue(json["creator"]["isAiChatAvailable"].asBoolean())
|
||||
assertFalse(json["creator"].has("aiChatAvailable"))
|
||||
assertFalse(json["creator"]["isDmAvailable"].asBoolean())
|
||||
assertFalse(json["creator"].has("dmAvailable"))
|
||||
assertTrue(json["latestAudioContent"]["isPointAvailable"].asBoolean())
|
||||
assertFalse(json["latestAudioContent"].has("pointAvailable"))
|
||||
assertTrue(json["latestAudioContent"]["isFirstContent"].asBoolean())
|
||||
assertFalse(json["latestAudioContent"].has("firstContent"))
|
||||
assertTrue(json["latestAudioContent"]["isAdult"].asBoolean())
|
||||
assertFalse(json["latestAudioContent"].has("adult"))
|
||||
assertTrue(json["series"][0]["isOriginal"].asBoolean())
|
||||
assertFalse(json["series"][0].has("original"))
|
||||
}
|
||||
|
||||
private fun createHome(): CreatorChannelHome {
|
||||
val post = CreatorChannelCommunityPost(
|
||||
postId = 301L,
|
||||
creatorId = 1L,
|
||||
creatorNickname = "creator",
|
||||
creatorProfileUrl = "profile.png",
|
||||
imageUrl = "image.png",
|
||||
audioUrl = "audio.mp3",
|
||||
content = "notice",
|
||||
price = 10,
|
||||
date = LocalDateTime.of(2026, 6, 12, 4, 0),
|
||||
existOrdered = true,
|
||||
likeCount = 2,
|
||||
commentCount = 3
|
||||
)
|
||||
|
||||
return CreatorChannelHome(
|
||||
creator = CreatorChannelCreator(
|
||||
creatorId = 1L,
|
||||
nickname = "creator",
|
||||
profileImageUrl = "profile.png",
|
||||
followerCount = 100,
|
||||
isAiChatAvailable = true,
|
||||
isDmAvailable = false,
|
||||
isFollow = true,
|
||||
isNotify = false
|
||||
),
|
||||
currentLive = CreatorChannelLive(
|
||||
liveId = 101L,
|
||||
title = "live",
|
||||
coverImageUrl = "live.png",
|
||||
beginDateTime = LocalDateTime.of(2026, 6, 12, 1, 0),
|
||||
price = 20,
|
||||
isAdult = true
|
||||
),
|
||||
latestAudioContent = CreatorChannelAudioContent(
|
||||
audioContentId = 201L,
|
||||
title = "audio",
|
||||
duration = "00:10:00",
|
||||
imageUrl = "audio.png",
|
||||
price = 30,
|
||||
isAdult = true,
|
||||
isPointAvailable = true,
|
||||
isFirstContent = true,
|
||||
publishedAt = LocalDateTime.of(2026, 6, 11, 1, 0),
|
||||
seriesName = "series",
|
||||
isOriginalSeries = true
|
||||
),
|
||||
channelDonations = listOf(
|
||||
CreatorChannelDonation(
|
||||
donationId = 401L,
|
||||
memberId = 2L,
|
||||
nickname = "fan",
|
||||
profileImageUrl = "fan.png",
|
||||
can = 50,
|
||||
isSecret = false,
|
||||
message = "thanks",
|
||||
createdAt = LocalDateTime.of(2026, 6, 12, 2, 0)
|
||||
)
|
||||
),
|
||||
notices = listOf(post),
|
||||
schedules = listOf(
|
||||
CreatorChannelSchedule(
|
||||
scheduledAt = LocalDateTime.of(2026, 6, 12, 3, 0),
|
||||
title = "schedule",
|
||||
type = CreatorActivityType.LIVE,
|
||||
targetId = 501L
|
||||
)
|
||||
),
|
||||
audioContents = listOf(
|
||||
CreatorChannelAudioContent(
|
||||
audioContentId = 202L,
|
||||
title = "audio2",
|
||||
duration = null,
|
||||
imageUrl = null,
|
||||
price = 0,
|
||||
isAdult = false,
|
||||
isPointAvailable = false,
|
||||
isFirstContent = false,
|
||||
publishedAt = LocalDateTime.of(2026, 6, 10, 1, 0),
|
||||
seriesName = null,
|
||||
isOriginalSeries = null
|
||||
)
|
||||
),
|
||||
series = listOf(
|
||||
CreatorChannelSeries(
|
||||
seriesId = 601L,
|
||||
title = "series",
|
||||
coverImageUrl = "series.png",
|
||||
publishedDaysOfWeek = "MON",
|
||||
isComplete = false,
|
||||
numberOfContent = 3,
|
||||
isNew = true,
|
||||
isPopular = false,
|
||||
isOriginal = true
|
||||
)
|
||||
),
|
||||
communities = listOf(post.copy(postId = 302L, content = "community")),
|
||||
fanTalk = CreatorChannelFanTalkSummary(
|
||||
totalCount = 1,
|
||||
latestFanTalk = CreatorChannelFanTalk(
|
||||
fanTalkId = 701L,
|
||||
memberId = 2L,
|
||||
nickname = "fan",
|
||||
profileImageUrl = "fan.png",
|
||||
content = "hello",
|
||||
languageCode = "ko",
|
||||
createdAt = LocalDateTime.of(2026, 6, 12, 5, 0)
|
||||
)
|
||||
),
|
||||
introduce = "introduce",
|
||||
activity = CreatorChannelActivity(
|
||||
debutDate = LocalDateTime.of(2026, 6, 12, 6, 0),
|
||||
dDay = "D+1",
|
||||
liveCount = 10,
|
||||
liveDurationHours = 20,
|
||||
liveContributorCount = 30,
|
||||
audioContentCount = 40,
|
||||
seriesCount = 50
|
||||
),
|
||||
sns = CreatorChannelSns(
|
||||
instagramUrl = "instagram",
|
||||
fancimmUrl = "fancimm",
|
||||
xUrl = "x",
|
||||
youtubeUrl = "youtube",
|
||||
kakaoOpenChatUrl = "kakao"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user