test #426
@@ -0,0 +1,28 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.creator.channel.live.domain
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaException
|
||||||
|
import org.springframework.stereotype.Component
|
||||||
|
|
||||||
|
@Component
|
||||||
|
class CreatorChannelLiveReplayQueryPolicy {
|
||||||
|
fun createPage(page: Int, size: Int): CreatorChannelPage {
|
||||||
|
if (page < MIN_PAGE || size < MIN_PAGE_SIZE || size > MAX_PAGE_SIZE) {
|
||||||
|
throw SodaException(messageKey = "common.error.invalid_request")
|
||||||
|
}
|
||||||
|
return CreatorChannelPage(page = page, size = size)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> limitItems(fetched: List<T>, page: CreatorChannelPage): List<T> {
|
||||||
|
return fetched.take(page.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hasNext(fetched: List<*>, page: CreatorChannelPage): Boolean {
|
||||||
|
return fetched.size > page.size
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val MIN_PAGE = 0
|
||||||
|
private const val MIN_PAGE_SIZE = 20
|
||||||
|
private const val MAX_PAGE_SIZE = 50
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.creator.channel.live.domain
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.v2.common.domain.ContentSort
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
|
data class CreatorChannelLiveTab(
|
||||||
|
val liveReplayContentCount: Int,
|
||||||
|
val currentLive: CreatorChannelLive?,
|
||||||
|
val liveReplayContents: List<CreatorChannelAudioContent>,
|
||||||
|
val sort: ContentSort,
|
||||||
|
val page: CreatorChannelPage,
|
||||||
|
val hasNext: Boolean
|
||||||
|
)
|
||||||
|
|
||||||
|
data class CreatorChannelLive(
|
||||||
|
val liveId: Long,
|
||||||
|
val title: String,
|
||||||
|
val coverImageUrl: String?,
|
||||||
|
val beginDateTime: LocalDateTime,
|
||||||
|
val price: Int,
|
||||||
|
val isAdult: Boolean
|
||||||
|
)
|
||||||
|
|
||||||
|
data class CreatorChannelAudioContent(
|
||||||
|
val audioContentId: Long,
|
||||||
|
val title: String,
|
||||||
|
val duration: String?,
|
||||||
|
val imageUrl: String?,
|
||||||
|
val price: Int,
|
||||||
|
val isAdult: Boolean,
|
||||||
|
val isPointAvailable: Boolean,
|
||||||
|
val isFirstContent: Boolean,
|
||||||
|
val publishedAt: LocalDateTime,
|
||||||
|
val seriesName: String?,
|
||||||
|
val isOriginalSeries: Boolean?,
|
||||||
|
val isOwned: Boolean,
|
||||||
|
val isRented: Boolean
|
||||||
|
)
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.creator.channel.live.domain
|
||||||
|
|
||||||
|
data class CreatorChannelPage(
|
||||||
|
val page: Int,
|
||||||
|
val size: Int
|
||||||
|
) {
|
||||||
|
val offset: Long = page.toLong() * size
|
||||||
|
val fetchLimit: Int = size + 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.creator.channel.live.domain
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaException
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Assertions.assertThrows
|
||||||
|
import org.junit.jupiter.api.Assertions.assertTrue
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class CreatorChannelLiveReplayQueryPolicyTest {
|
||||||
|
private val policy = CreatorChannelLiveReplayQueryPolicy()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("라이브 다시듣기 page 정책은 offset, fetch limit, items limit, hasNext를 계산한다")
|
||||||
|
fun shouldCalculatePagePolicyForLiveReplayContents() {
|
||||||
|
val page = policy.createPage(page = 0, size = 20)
|
||||||
|
val fetched = (1..21).toList()
|
||||||
|
|
||||||
|
val items = policy.limitItems(fetched, page)
|
||||||
|
|
||||||
|
assertEquals(0L, page.offset)
|
||||||
|
assertEquals(21, page.fetchLimit)
|
||||||
|
assertEquals(20, items.size)
|
||||||
|
assertEquals((1..20).toList(), items)
|
||||||
|
assertTrue(policy.hasNext(fetched, page))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("size가 50이면 fetch limit을 51로 계산한다")
|
||||||
|
fun shouldCalculateFetchLimitWhenSizeIsMaximum() {
|
||||||
|
val page = policy.createPage(page = 1, size = 50)
|
||||||
|
|
||||||
|
assertEquals(50L, page.offset)
|
||||||
|
assertEquals(51, page.fetchLimit)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("page가 0보다 작으면 invalid request 예외를 던진다")
|
||||||
|
fun shouldThrowInvalidRequestWhenPageIsNegative() {
|
||||||
|
val exception = assertThrows(SodaException::class.java) {
|
||||||
|
policy.createPage(page = -1, size = 20)
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals("common.error.invalid_request", exception.messageKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("size가 20보다 작으면 invalid request 예외를 던진다")
|
||||||
|
fun shouldThrowInvalidRequestWhenSizeIsLessThanMinimum() {
|
||||||
|
val exception = assertThrows(SodaException::class.java) {
|
||||||
|
policy.createPage(page = 0, size = 19)
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals("common.error.invalid_request", exception.messageKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("size가 50보다 크면 invalid request 예외를 던진다")
|
||||||
|
fun shouldThrowInvalidRequestWhenSizeIsGreaterThanMaximum() {
|
||||||
|
val exception = assertThrows(SodaException::class.java) {
|
||||||
|
policy.createPage(page = 0, size = 51)
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals("common.error.invalid_request", exception.messageKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("size가 Int 최대값이면 fetch limit overflow 전에 invalid request 예외를 던진다")
|
||||||
|
fun shouldThrowInvalidRequestWhenSizeWouldOverflowFetchLimit() {
|
||||||
|
val exception = assertThrows(SodaException::class.java) {
|
||||||
|
policy.createPage(page = 0, size = Int.MAX_VALUE)
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals("common.error.invalid_request", exception.messageKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user