test #426
@@ -0,0 +1,38 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.api.content.overview.application
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.v2.api.content.overview.dto.ContentOverviewType
|
||||||
|
|
||||||
|
data class ContentOverviewPage(
|
||||||
|
val page: Int,
|
||||||
|
val size: Int
|
||||||
|
) {
|
||||||
|
val offset: Long = page.toLong() * size
|
||||||
|
}
|
||||||
|
|
||||||
|
class ContentOverviewQueryPolicy {
|
||||||
|
fun resolveType(type: String?): ContentOverviewType {
|
||||||
|
return ContentOverviewType.from(type)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createPage(page: Int?, size: Int?): ContentOverviewPage {
|
||||||
|
val resolvedPage = (page ?: DEFAULT_PAGE).coerceAtLeast(DEFAULT_PAGE)
|
||||||
|
val requestedSize = size ?: DEFAULT_SIZE
|
||||||
|
val resolvedSize = if (requestedSize < MIN_SIZE) DEFAULT_SIZE else minOf(requestedSize, MAX_SIZE)
|
||||||
|
return ContentOverviewPage(page = resolvedPage, size = resolvedSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> pageItems(items: List<T>, page: ContentOverviewPage): List<T> {
|
||||||
|
return items.take(page.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> hasNext(items: List<T>, page: ContentOverviewPage): Boolean {
|
||||||
|
return items.size > page.size
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val DEFAULT_PAGE = 0
|
||||||
|
const val DEFAULT_SIZE = 20
|
||||||
|
const val MIN_SIZE = 20
|
||||||
|
const val MAX_SIZE = 50
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.api.content.overview.application
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.v2.api.content.overview.dto.ContentOverviewType
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class ContentOverviewQueryPolicyTest {
|
||||||
|
private val policy = ContentOverviewQueryPolicy()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("콘텐츠 전체보기 type은 null 또는 invalid 값을 기본 타입으로 보정한다")
|
||||||
|
fun shouldResolveTypeWithDefaultFallback() {
|
||||||
|
assertEquals(ContentOverviewType.NEW_AND_HOT_AUDIO, policy.resolveType(null))
|
||||||
|
assertEquals(ContentOverviewType.NEW_AND_HOT_AUDIO, policy.resolveType("UNKNOWN"))
|
||||||
|
assertEquals(ContentOverviewType.FIRST_AUDIO_CONTENT, policy.resolveType("FIRST_AUDIO_CONTENT"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("콘텐츠 전체보기 page와 size를 기본값과 최대값으로 보정한다")
|
||||||
|
fun shouldNormalizePageAndSize() {
|
||||||
|
assertEquals(ContentOverviewPage(page = 0, size = 20), policy.createPage(null, null))
|
||||||
|
assertEquals(ContentOverviewPage(page = 0, size = 20), policy.createPage(-1, 0))
|
||||||
|
assertEquals(ContentOverviewPage(page = 0, size = 20), policy.createPage(0, 19))
|
||||||
|
assertEquals(ContentOverviewPage(page = 2, size = 50), policy.createPage(2, 100))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("콘텐츠 전체보기 offset은 큰 page 입력에서도 Int overflow 없이 계산한다")
|
||||||
|
fun shouldCalculateOffsetWithoutIntOverflow() {
|
||||||
|
val page = policy.createPage(Int.MAX_VALUE, 50)
|
||||||
|
|
||||||
|
assertEquals(Int.MAX_VALUE.toLong() * 50, page.offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("콘텐츠 전체보기 응답 목록과 hasNext는 size + 1 조회 결과로 계산한다")
|
||||||
|
fun shouldCalculatePageItemsAndHasNext() {
|
||||||
|
val page = ContentOverviewPage(page = 0, size = 2)
|
||||||
|
val items = listOf(1, 2, 3)
|
||||||
|
|
||||||
|
assertEquals(listOf(1, 2), policy.pageItems(items, page))
|
||||||
|
assertEquals(true, policy.hasNext(items, page))
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user