From c9d7399f0e4a9c4d6c12d925ebd05aa6a3730296 Mon Sep 17 00:00:00 2001 From: Klaus Date: Wed, 24 Jun 2026 12:35:12 +0900 Subject: [PATCH] =?UTF-8?q?feat(content-ranking):=20=EC=98=A4=EB=94=94?= =?UTF-8?q?=EC=98=A4=20=EB=9E=AD=ED=82=B9=20=EC=9D=91=EB=8B=B5=20=EA=B3=84?= =?UTF-8?q?=EC=95=BD=EC=9D=84=20=EC=B6=94=EA=B0=80=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ranking/dto/AudioRankingResponse.kt | 47 ++++++++++++++++++ .../v2/content/ranking/domain/AudioRanking.kt | 17 +++++++ .../ranking/domain/AudioRankingType.kt | 10 ++++ .../ranking/dto/AudioRankingResponseTest.kt | 48 +++++++++++++++++++ 4 files changed, 122 insertions(+) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/v2/api/content/ranking/dto/AudioRankingResponse.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/v2/content/ranking/domain/AudioRanking.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/v2/content/ranking/domain/AudioRankingType.kt create mode 100644 src/test/kotlin/kr/co/vividnext/sodalive/v2/api/content/ranking/dto/AudioRankingResponseTest.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/api/content/ranking/dto/AudioRankingResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/api/content/ranking/dto/AudioRankingResponse.kt new file mode 100644 index 00000000..81926c57 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/api/content/ranking/dto/AudioRankingResponse.kt @@ -0,0 +1,47 @@ +package kr.co.vividnext.sodalive.v2.api.content.ranking.dto + +import com.fasterxml.jackson.annotation.JsonProperty +import kr.co.vividnext.sodalive.v2.content.ranking.domain.AudioRanking +import kr.co.vividnext.sodalive.v2.content.ranking.domain.AudioRankingItem +import kr.co.vividnext.sodalive.v2.content.ranking.domain.AudioRankingType + +data class AudioRankingResponse( + val showRankChange: Boolean, + val type: AudioRankingType, + val items: List +) { + companion object { + fun from(ranking: AudioRanking): AudioRankingResponse { + return AudioRankingResponse( + showRankChange = ranking.showRankChange, + type = ranking.type, + items = ranking.items.map(AudioRankingItemResponse::from) + ) + } + } +} + +data class AudioRankingItemResponse( + val contentId: Long, + val title: String, + val creatorNickname: String, + val rank: Int, + val rankChange: Int?, + @JsonProperty("isNew") + val isNew: Boolean, + val coverImageUrl: String? +) { + companion object { + fun from(item: AudioRankingItem): AudioRankingItemResponse { + return AudioRankingItemResponse( + contentId = item.contentId, + title = item.title, + creatorNickname = item.creatorNickname, + rank = item.rank, + rankChange = item.rankChange, + isNew = item.isNew, + coverImageUrl = item.coverImageUrl + ) + } + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/content/ranking/domain/AudioRanking.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/content/ranking/domain/AudioRanking.kt new file mode 100644 index 00000000..0f488f97 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/content/ranking/domain/AudioRanking.kt @@ -0,0 +1,17 @@ +package kr.co.vividnext.sodalive.v2.content.ranking.domain + +data class AudioRanking( + val showRankChange: Boolean, + val type: AudioRankingType, + val items: List +) + +data class AudioRankingItem( + val contentId: Long, + val title: String, + val creatorNickname: String, + val rank: Int, + val rankChange: Int?, + val isNew: Boolean, + val coverImageUrl: String? +) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/content/ranking/domain/AudioRankingType.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/content/ranking/domain/AudioRankingType.kt new file mode 100644 index 00000000..c6d4d140 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/content/ranking/domain/AudioRankingType.kt @@ -0,0 +1,10 @@ +package kr.co.vividnext.sodalive.v2.content.ranking.domain + +enum class AudioRankingType { + WEEKLY_POPULAR, + RISING, + REVENUE, + SALES_COUNT, + COMMENT_COUNT, + LIKE_COUNT +} diff --git a/src/test/kotlin/kr/co/vividnext/sodalive/v2/api/content/ranking/dto/AudioRankingResponseTest.kt b/src/test/kotlin/kr/co/vividnext/sodalive/v2/api/content/ranking/dto/AudioRankingResponseTest.kt new file mode 100644 index 00000000..65528537 --- /dev/null +++ b/src/test/kotlin/kr/co/vividnext/sodalive/v2/api/content/ranking/dto/AudioRankingResponseTest.kt @@ -0,0 +1,48 @@ +package kr.co.vividnext.sodalive.v2.api.content.ranking.dto + +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import kr.co.vividnext.sodalive.v2.content.ranking.domain.AudioRanking +import kr.co.vividnext.sodalive.v2.content.ranking.domain.AudioRankingItem +import kr.co.vividnext.sodalive.v2.content.ranking.domain.AudioRankingType +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test + +class AudioRankingResponseTest { + private val objectMapper = jacksonObjectMapper() + + @Test + @DisplayName("오디오 랭킹 도메인을 응답 DTO로 변환하고 isNew JSON 필드명을 유지한다") + fun shouldMapAudioRankingToResponseAndSerializeIsNew() { + val ranking = AudioRanking( + showRankChange = true, + type = AudioRankingType.RISING, + items = listOf( + AudioRankingItem( + contentId = 1001L, + title = "rising audio", + creatorNickname = "creator", + rank = 1, + rankChange = 3, + isNew = true, + coverImageUrl = "https://cdn.test/audio.png" + ) + ) + ) + + val response = AudioRankingResponse.from(ranking) + val json = objectMapper.readTree(objectMapper.writeValueAsString(response)) + + assertEquals(true, response.showRankChange) + assertEquals(AudioRankingType.RISING, response.type) + assertEquals(1001L, response.items[0].contentId) + assertEquals("rising audio", response.items[0].title) + assertEquals("creator", response.items[0].creatorNickname) + assertEquals(1, response.items[0].rank) + assertEquals(3, response.items[0].rankChange) + assertEquals(true, response.items[0].isNew) + assertEquals("https://cdn.test/audio.png", response.items[0].coverImageUrl) + assertEquals(true, json["items"][0]["isNew"].asBoolean()) + assertEquals(false, json["items"][0].has("new")) + } +}