feat(banner): 배너 카운터와 상태 계약을 추가한다
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.widget.banner
|
||||||
|
|
||||||
|
object BannerCounterFormatter {
|
||||||
|
fun format(currentIndex: Int, count: Int): String {
|
||||||
|
return "%02d / %02d".format(currentIndex + 1, count)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.widget.banner
|
||||||
|
|
||||||
|
data class BannerState(
|
||||||
|
val displayMode: BannerDisplayMode,
|
||||||
|
val currentIndex: Int,
|
||||||
|
private val count: Int
|
||||||
|
) {
|
||||||
|
fun nextIndex(): Int = (currentIndex + 1) % count
|
||||||
|
|
||||||
|
fun previousIndex(): Int = (currentIndex - 1 + count) % count
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun from(count: Int, currentIndex: Int): BannerState {
|
||||||
|
val displayMode = when (count) {
|
||||||
|
0 -> BannerDisplayMode.Hidden
|
||||||
|
1 -> BannerDisplayMode.Single
|
||||||
|
else -> BannerDisplayMode.Carousel
|
||||||
|
}
|
||||||
|
val correctedIndex = if (currentIndex in 0 until count) currentIndex else 0
|
||||||
|
return BannerState(
|
||||||
|
displayMode = displayMode,
|
||||||
|
currentIndex = correctedIndex,
|
||||||
|
count = count
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class BannerDisplayMode {
|
||||||
|
Hidden,
|
||||||
|
Single,
|
||||||
|
Carousel
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.widget.banner
|
||||||
|
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class BannerCounterFormatterTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `20개 배너의 첫 번째 아이템은 1부터 시작하는 카운터로 표시한다`() {
|
||||||
|
val text = BannerCounterFormatter.format(currentIndex = 0, count = 20)
|
||||||
|
|
||||||
|
assertEquals("01 / 20", text)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `20개 배너의 열 번째 아이템은 1부터 시작하는 카운터로 표시한다`() {
|
||||||
|
val text = BannerCounterFormatter.format(currentIndex = 9, count = 20)
|
||||||
|
|
||||||
|
assertEquals("10 / 20", text)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `1개 배너도 formatter는 양쪽을 두 자리로 표시한다`() {
|
||||||
|
val text = BannerCounterFormatter.format(currentIndex = 0, count = 1)
|
||||||
|
|
||||||
|
assertEquals("01 / 01", text)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.widget.banner
|
||||||
|
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class BannerStateTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `배너 개수가 0이면 숨김 모드다`() {
|
||||||
|
val state = BannerState.from(count = 0, currentIndex = 0)
|
||||||
|
|
||||||
|
assertEquals(BannerDisplayMode.Hidden, state.displayMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `배너 개수가 1이면 단일 모드다`() {
|
||||||
|
val state = BannerState.from(count = 1, currentIndex = 0)
|
||||||
|
|
||||||
|
assertEquals(BannerDisplayMode.Single, state.displayMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `배너 개수가 2이면 캐러셀 모드다`() {
|
||||||
|
val state = BannerState.from(count = 2, currentIndex = 0)
|
||||||
|
|
||||||
|
assertEquals(BannerDisplayMode.Carousel, state.displayMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `마지막 배너의 다음 index는 첫 번째로 순환한다`() {
|
||||||
|
val state = BannerState.from(count = 3, currentIndex = 2)
|
||||||
|
|
||||||
|
assertEquals(0, state.nextIndex())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `첫 번째 배너의 이전 index는 마지막으로 순환한다`() {
|
||||||
|
val state = BannerState.from(count = 3, currentIndex = 0)
|
||||||
|
|
||||||
|
assertEquals(2, state.previousIndex())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `현재 index가 범위를 벗어나면 첫 번째로 보정한다`() {
|
||||||
|
val state = BannerState.from(count = 3, currentIndex = 3)
|
||||||
|
|
||||||
|
assertEquals(0, state.currentIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user