feat(audio-recommendation): 오디오 추천 응답 변환을 추가한다
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
package kr.co.vividnext.sodalive.v2.api.audio.recommendation.application
|
||||
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.v2.api.audio.recommendation.dto.AudioRecommendationsResponse
|
||||
import kr.co.vividnext.sodalive.v2.audio.recommendation.application.AudioRecommendationQueryService
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class AudioRecommendationFacade(
|
||||
private val queryService: AudioRecommendationQueryService
|
||||
) {
|
||||
fun getRecommendations(member: Member?): AudioRecommendationsResponse {
|
||||
return AudioRecommendationsResponse.from(queryService.getRecommendations(member))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package kr.co.vividnext.sodalive.v2.api.audio.recommendation.dto
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import kr.co.vividnext.sodalive.v2.api.common.dto.RecommendationBannerResponse
|
||||
import kr.co.vividnext.sodalive.v2.audio.recommendation.domain.AudioCard
|
||||
import kr.co.vividnext.sodalive.v2.audio.recommendation.domain.AudioRecommendations
|
||||
import kr.co.vividnext.sodalive.v2.audio.recommendation.domain.CommentedAudio
|
||||
import kr.co.vividnext.sodalive.v2.audio.recommendation.domain.OriginalSeries
|
||||
|
||||
data class AudioRecommendationsResponse(
|
||||
val banners: List<RecommendationBannerResponse>,
|
||||
val originalSeries: List<OriginalSeriesResponse>,
|
||||
val latestAudios: List<AudioCardResponse>,
|
||||
val newAndHotAudios: List<AudioCardResponse>,
|
||||
val freeAudios: List<AudioCardResponse>,
|
||||
val pointAudios: List<AudioCardResponse>,
|
||||
val mostCommentedAudios: List<CommentedAudioResponse>,
|
||||
val recommendedAudios: List<AudioCardResponse>
|
||||
) {
|
||||
companion object {
|
||||
fun from(recommendations: AudioRecommendations): AudioRecommendationsResponse {
|
||||
return AudioRecommendationsResponse(
|
||||
banners = recommendations.banners.map(RecommendationBannerResponse::from),
|
||||
originalSeries = recommendations.originalSeries.map(OriginalSeriesResponse::from),
|
||||
latestAudios = recommendations.latestAudios.map(AudioCardResponse::from),
|
||||
newAndHotAudios = recommendations.newAndHotAudios.map(AudioCardResponse::from),
|
||||
freeAudios = recommendations.freeAudios.map(AudioCardResponse::from),
|
||||
pointAudios = recommendations.pointAudios.map(AudioCardResponse::from),
|
||||
mostCommentedAudios = recommendations.mostCommentedAudios.map(CommentedAudioResponse::from),
|
||||
recommendedAudios = recommendations.recommendedAudios.map(AudioCardResponse::from)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class OriginalSeriesResponse(
|
||||
val seriesId: Long,
|
||||
val coverImageUrl: String?
|
||||
) {
|
||||
companion object {
|
||||
fun from(series: OriginalSeries): OriginalSeriesResponse {
|
||||
return OriginalSeriesResponse(series.seriesId, series.coverImageUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class AudioCardResponse(
|
||||
val audioContentId: Long,
|
||||
val title: String,
|
||||
val duration: String?,
|
||||
val imageUrl: String?,
|
||||
val price: Int,
|
||||
@JsonProperty("isAdult")
|
||||
val isAdult: Boolean,
|
||||
@JsonProperty("isPointAvailable")
|
||||
val isPointAvailable: Boolean,
|
||||
@JsonProperty("isFirstContent")
|
||||
val isFirstContent: Boolean,
|
||||
@JsonProperty("isOriginalSeries")
|
||||
val isOriginalSeries: Boolean,
|
||||
val creatorNickname: String
|
||||
) {
|
||||
companion object {
|
||||
fun from(audio: AudioCard): AudioCardResponse {
|
||||
return AudioCardResponse(
|
||||
audioContentId = audio.audioContentId,
|
||||
title = audio.title,
|
||||
duration = audio.duration,
|
||||
imageUrl = audio.imageUrl,
|
||||
price = audio.price,
|
||||
isAdult = audio.isAdult,
|
||||
isPointAvailable = audio.isPointAvailable,
|
||||
isFirstContent = audio.isFirstContent,
|
||||
isOriginalSeries = audio.isOriginalSeries,
|
||||
creatorNickname = audio.creatorNickname
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class CommentedAudioResponse(
|
||||
val audioContentId: Long,
|
||||
val title: String,
|
||||
val imageUrl: String?,
|
||||
val latestComment: String,
|
||||
val latestCommentWriterProfileImageUrl: String
|
||||
) {
|
||||
companion object {
|
||||
fun from(audio: CommentedAudio): CommentedAudioResponse {
|
||||
return CommentedAudioResponse(
|
||||
audioContentId = audio.audioContentId,
|
||||
title = audio.title,
|
||||
imageUrl = audio.imageUrl,
|
||||
latestComment = audio.latestComment,
|
||||
latestCommentWriterProfileImageUrl = audio.latestCommentWriterProfileImageUrl
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package kr.co.vividnext.sodalive.v2.api.audio.recommendation.application
|
||||
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import kr.co.vividnext.sodalive.v2.audio.recommendation.application.AudioRecommendationQueryService
|
||||
import kr.co.vividnext.sodalive.v2.audio.recommendation.domain.AudioCard
|
||||
import kr.co.vividnext.sodalive.v2.audio.recommendation.domain.AudioRecommendations
|
||||
import kr.co.vividnext.sodalive.v2.audio.recommendation.domain.CommentedAudio
|
||||
import kr.co.vividnext.sodalive.v2.audio.recommendation.domain.OriginalSeries
|
||||
import kr.co.vividnext.sodalive.v2.common.domain.RecommendationBanner
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.mockito.Mockito
|
||||
|
||||
class AudioRecommendationFacadeTest {
|
||||
private val objectMapper = jacksonObjectMapper()
|
||||
private val queryService = Mockito.mock(AudioRecommendationQueryService::class.java)
|
||||
private val facade = AudioRecommendationFacade(queryService)
|
||||
|
||||
@Test
|
||||
@DisplayName("facade는 도메인 추천 결과를 모든 공개 응답 필드로 변환한다")
|
||||
fun shouldConvertDomainRecommendationsToResponse() {
|
||||
Mockito.doReturn(domain()).`when`(queryService).getRecommendations(null)
|
||||
|
||||
val response = facade.getRecommendations(null)
|
||||
|
||||
assertEquals(1, response.banners.size)
|
||||
assertEquals(1, response.originalSeries.size)
|
||||
assertEquals(1, response.latestAudios.size)
|
||||
assertEquals(1, response.newAndHotAudios.size)
|
||||
assertEquals(1, response.freeAudios.size)
|
||||
assertEquals(1, response.pointAudios.size)
|
||||
assertEquals(1, response.mostCommentedAudios.size)
|
||||
assertEquals(1, response.recommendedAudios.size)
|
||||
assertEquals(false, response.latestAudios[0].isOriginalSeries)
|
||||
|
||||
val json = objectMapper.readTree(objectMapper.writeValueAsString(response))
|
||||
assertEquals(false, json["latestAudios"][0]["isAdult"].asBoolean())
|
||||
assertEquals(true, json["latestAudios"][0]["isPointAvailable"].asBoolean())
|
||||
assertEquals(true, json["latestAudios"][0]["isFirstContent"].asBoolean())
|
||||
assertEquals(false, json["latestAudios"][0]["isOriginalSeries"].asBoolean())
|
||||
assertEquals(false, json["latestAudios"][0].has("adult"))
|
||||
assertEquals(false, json["latestAudios"][0].has("pointAvailable"))
|
||||
assertEquals("latest comment", json["mostCommentedAudios"][0]["latestComment"].asText())
|
||||
}
|
||||
|
||||
private fun domain(): AudioRecommendations {
|
||||
val card = AudioCard(
|
||||
audioContentId = 1L,
|
||||
title = "audio",
|
||||
duration = "00:01",
|
||||
imageUrl = "https://cdn.test/audio.png",
|
||||
price = 0,
|
||||
isAdult = false,
|
||||
isPointAvailable = true,
|
||||
isFirstContent = true,
|
||||
isOriginalSeries = false,
|
||||
creatorNickname = "creator"
|
||||
)
|
||||
return AudioRecommendations(
|
||||
banners = listOf(RecommendationBanner("https://cdn.test/banner.png", null, null, null, "https://link.test")),
|
||||
originalSeries = listOf(OriginalSeries(2L, "https://cdn.test/series.png")),
|
||||
latestAudios = listOf(card),
|
||||
newAndHotAudios = listOf(card.copy(audioContentId = 3L)),
|
||||
freeAudios = listOf(card.copy(audioContentId = 4L)),
|
||||
pointAudios = listOf(card.copy(audioContentId = 5L)),
|
||||
mostCommentedAudios = listOf(
|
||||
CommentedAudio(
|
||||
audioContentId = 6L,
|
||||
title = "commented",
|
||||
imageUrl = "https://cdn.test/commented.png",
|
||||
latestComment = "latest comment",
|
||||
latestCommentWriterProfileImageUrl = "https://cdn.test/profile.png"
|
||||
)
|
||||
),
|
||||
recommendedAudios = listOf(card.copy(audioContentId = 7L))
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user