test #426
@@ -0,0 +1,31 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.api.content.all.application
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
|
import kr.co.vividnext.sodalive.v2.api.content.all.dto.MainContentAllTabResponse
|
||||||
|
import kr.co.vividnext.sodalive.v2.content.all.application.MainContentAllQueryService
|
||||||
|
import org.springframework.stereotype.Component
|
||||||
|
|
||||||
|
@Component
|
||||||
|
class MainContentAllFacade(
|
||||||
|
private val queryService: MainContentAllQueryService
|
||||||
|
) {
|
||||||
|
fun getContents(
|
||||||
|
type: String?,
|
||||||
|
sort: String?,
|
||||||
|
dayOfWeek: String?,
|
||||||
|
page: Int?,
|
||||||
|
size: Int?,
|
||||||
|
member: Member?
|
||||||
|
): MainContentAllTabResponse {
|
||||||
|
return MainContentAllTabResponse.from(
|
||||||
|
queryService.getContents(
|
||||||
|
type = type,
|
||||||
|
sort = sort,
|
||||||
|
dayOfWeek = dayOfWeek,
|
||||||
|
page = page,
|
||||||
|
size = size,
|
||||||
|
member = member
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.api.content.all.dto
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
|
import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesPublishedDaysOfWeek
|
||||||
|
import kr.co.vividnext.sodalive.v2.common.domain.ContentSort
|
||||||
|
import kr.co.vividnext.sodalive.v2.content.all.domain.MainContentAll
|
||||||
|
import kr.co.vividnext.sodalive.v2.content.all.domain.MainContentAllAudio
|
||||||
|
import kr.co.vividnext.sodalive.v2.content.all.domain.MainContentAllSeries
|
||||||
|
import kr.co.vividnext.sodalive.v2.content.all.domain.MainContentAllType
|
||||||
|
|
||||||
|
data class MainContentAllTabResponse(
|
||||||
|
val type: MainContentAllType,
|
||||||
|
val totalCount: Int,
|
||||||
|
val audios: List<MainContentAudioResponse>,
|
||||||
|
val series: List<MainContentSeriesResponse>,
|
||||||
|
val sort: ContentSort,
|
||||||
|
val dayOfWeek: SeriesPublishedDaysOfWeek?,
|
||||||
|
val page: Int,
|
||||||
|
val size: Int,
|
||||||
|
@JsonProperty("hasNext")
|
||||||
|
val hasNext: Boolean
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
fun from(tab: MainContentAll): MainContentAllTabResponse {
|
||||||
|
return MainContentAllTabResponse(
|
||||||
|
type = tab.type,
|
||||||
|
totalCount = tab.totalCount,
|
||||||
|
audios = tab.audios.map(MainContentAudioResponse::from),
|
||||||
|
series = tab.series.map(MainContentSeriesResponse::from),
|
||||||
|
sort = tab.sort,
|
||||||
|
dayOfWeek = tab.dayOfWeek,
|
||||||
|
page = tab.page.page,
|
||||||
|
size = tab.page.size,
|
||||||
|
hasNext = tab.hasNext
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class MainContentAudioResponse(
|
||||||
|
val audioContentId: Long,
|
||||||
|
val title: 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: MainContentAllAudio): MainContentAudioResponse {
|
||||||
|
return MainContentAudioResponse(
|
||||||
|
audioContentId = audio.audioContentId,
|
||||||
|
title = audio.title,
|
||||||
|
imageUrl = audio.imageUrl,
|
||||||
|
price = audio.price,
|
||||||
|
isAdult = audio.isAdult,
|
||||||
|
isPointAvailable = audio.isPointAvailable,
|
||||||
|
isFirstContent = audio.isFirstContent,
|
||||||
|
isOriginalSeries = audio.isOriginalSeries,
|
||||||
|
creatorNickname = audio.creatorNickname
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class MainContentSeriesResponse(
|
||||||
|
val seriesId: Long,
|
||||||
|
val title: String,
|
||||||
|
val coverImageUrl: String?,
|
||||||
|
val creatorNickname: String,
|
||||||
|
@JsonProperty("isOriginal")
|
||||||
|
val isOriginal: Boolean,
|
||||||
|
@JsonProperty("isAdult")
|
||||||
|
val isAdult: Boolean
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
fun from(series: MainContentAllSeries): MainContentSeriesResponse {
|
||||||
|
return MainContentSeriesResponse(
|
||||||
|
seriesId = series.seriesId,
|
||||||
|
title = series.title,
|
||||||
|
coverImageUrl = series.coverImageUrl,
|
||||||
|
creatorNickname = series.creatorNickname,
|
||||||
|
isOriginal = series.isOriginal,
|
||||||
|
isAdult = series.isAdult
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.api.content.all.application
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
|
import kr.co.vividnext.sodalive.member.MemberRole
|
||||||
|
import kr.co.vividnext.sodalive.v2.common.domain.ContentSort
|
||||||
|
import kr.co.vividnext.sodalive.v2.content.all.application.MainContentAllQueryService
|
||||||
|
import kr.co.vividnext.sodalive.v2.content.all.domain.MainContentAll
|
||||||
|
import kr.co.vividnext.sodalive.v2.content.all.domain.MainContentAllType
|
||||||
|
import kr.co.vividnext.sodalive.v2.content.all.domain.MainContentPage
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.mockito.Mockito
|
||||||
|
|
||||||
|
class MainContentAllFacadeTest {
|
||||||
|
private val queryService = Mockito.mock(MainContentAllQueryService::class.java)
|
||||||
|
private val facade = MainContentAllFacade(queryService)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("facade는 문자열 query parameter와 회원을 query service에 그대로 전달하고 응답 DTO로 변환한다")
|
||||||
|
fun shouldDelegateToQueryServiceAndMapResponse() {
|
||||||
|
val member = Member(
|
||||||
|
email = "viewer@test.com",
|
||||||
|
password = "password",
|
||||||
|
nickname = "viewer",
|
||||||
|
role = MemberRole.USER
|
||||||
|
).apply { id = 10L }
|
||||||
|
Mockito.doReturn(
|
||||||
|
MainContentAll(
|
||||||
|
type = MainContentAllType.FREE,
|
||||||
|
totalCount = 0,
|
||||||
|
audios = emptyList(),
|
||||||
|
series = emptyList(),
|
||||||
|
sort = ContentSort.PRICE_LOW,
|
||||||
|
dayOfWeek = null,
|
||||||
|
page = MainContentPage(1, 30),
|
||||||
|
hasNext = false
|
||||||
|
)
|
||||||
|
).`when`(queryService).getContents("FREE", "PRICE_LOW", "MON", 1, 30, member)
|
||||||
|
|
||||||
|
val response = facade.getContents(
|
||||||
|
type = "FREE",
|
||||||
|
sort = "PRICE_LOW",
|
||||||
|
dayOfWeek = "MON",
|
||||||
|
page = 1,
|
||||||
|
size = 30,
|
||||||
|
member = member
|
||||||
|
)
|
||||||
|
|
||||||
|
Mockito.verify(queryService).getContents("FREE", "PRICE_LOW", "MON", 1, 30, member)
|
||||||
|
assertEquals(MainContentAllType.FREE, response.type)
|
||||||
|
assertEquals(ContentSort.PRICE_LOW, response.sort)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.api.content.all.dto
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||||
|
import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesPublishedDaysOfWeek
|
||||||
|
import kr.co.vividnext.sodalive.v2.common.domain.ContentSort
|
||||||
|
import kr.co.vividnext.sodalive.v2.content.all.domain.MainContentAll
|
||||||
|
import kr.co.vividnext.sodalive.v2.content.all.domain.MainContentAllAudio
|
||||||
|
import kr.co.vividnext.sodalive.v2.content.all.domain.MainContentAllSeries
|
||||||
|
import kr.co.vividnext.sodalive.v2.content.all.domain.MainContentAllType
|
||||||
|
import kr.co.vividnext.sodalive.v2.content.all.domain.MainContentPage
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Assertions.assertFalse
|
||||||
|
import org.junit.jupiter.api.Assertions.assertTrue
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class MainContentAllTabResponseTest {
|
||||||
|
private val objectMapper = jacksonObjectMapper()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("전체 탭 도메인을 최소 공개 응답 필드로 변환한다")
|
||||||
|
fun shouldMapDomainToResponseWithMinimalFields() {
|
||||||
|
val response = MainContentAllTabResponse.from(
|
||||||
|
MainContentAll(
|
||||||
|
type = MainContentAllType.SERIES,
|
||||||
|
totalCount = 1,
|
||||||
|
audios = emptyList(),
|
||||||
|
series = listOf(
|
||||||
|
MainContentAllSeries(
|
||||||
|
seriesId = 10L,
|
||||||
|
title = "시리즈",
|
||||||
|
coverImageUrl = "https://cdn/series.jpg",
|
||||||
|
creatorNickname = "creator",
|
||||||
|
isOriginal = true,
|
||||||
|
isAdult = false
|
||||||
|
)
|
||||||
|
),
|
||||||
|
sort = ContentSort.LATEST,
|
||||||
|
dayOfWeek = SeriesPublishedDaysOfWeek.MON,
|
||||||
|
page = MainContentPage(0, 20),
|
||||||
|
hasNext = false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(MainContentAllType.SERIES, response.type)
|
||||||
|
assertEquals(1, response.totalCount)
|
||||||
|
assertTrue(response.audios.isEmpty())
|
||||||
|
assertEquals("creator", response.series.first().creatorNickname)
|
||||||
|
assertEquals(SeriesPublishedDaysOfWeek.MON, response.dayOfWeek)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("boolean 응답 필드는 is prefix를 유지하고 제외 필드는 노출하지 않는다")
|
||||||
|
fun shouldKeepBooleanJsonNamesAndHideExcludedFields() {
|
||||||
|
val response = MainContentAllTabResponse.from(
|
||||||
|
MainContentAll(
|
||||||
|
type = MainContentAllType.AUDIO,
|
||||||
|
totalCount = 1,
|
||||||
|
audios = listOf(
|
||||||
|
MainContentAllAudio(
|
||||||
|
audioContentId = 1L,
|
||||||
|
title = "audio",
|
||||||
|
imageUrl = "https://cdn/audio.jpg",
|
||||||
|
price = 100,
|
||||||
|
isAdult = false,
|
||||||
|
isPointAvailable = true,
|
||||||
|
isFirstContent = true,
|
||||||
|
isOriginalSeries = false,
|
||||||
|
creatorNickname = "creator"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
series = emptyList(),
|
||||||
|
sort = ContentSort.LATEST,
|
||||||
|
dayOfWeek = null,
|
||||||
|
page = MainContentPage(0, 20),
|
||||||
|
hasNext = true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
val json = objectMapper.readTree(objectMapper.writeValueAsString(response))
|
||||||
|
|
||||||
|
assertEquals(false, json["audios"][0]["isAdult"].asBoolean())
|
||||||
|
assertEquals(true, json["audios"][0]["isPointAvailable"].asBoolean())
|
||||||
|
assertEquals(true, json["audios"][0]["isFirstContent"].asBoolean())
|
||||||
|
assertEquals(false, json["audios"][0]["isOriginalSeries"].asBoolean())
|
||||||
|
assertEquals(true, json["hasNext"].asBoolean())
|
||||||
|
assertFalse(json["audios"][0].has("duration"))
|
||||||
|
assertFalse(json["series"].any { it.has("publishedDaysOfWeek") })
|
||||||
|
assertFalse(json["series"].any { it.has("isProceeding") })
|
||||||
|
assertFalse(json["series"].any { it.has("contentCount") })
|
||||||
|
assertFalse(json["series"].any { it.has("paidContentCount") })
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user