feat(live): 생성 결과 계약을 추가한다
This commit is contained in:
@@ -0,0 +1,22 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.live.action
|
||||||
|
|
||||||
|
sealed interface LiveCreationResult {
|
||||||
|
data object Ignored : LiveCreationResult
|
||||||
|
|
||||||
|
data object Created : LiveCreationResult
|
||||||
|
|
||||||
|
data object RefreshOnly : LiveCreationResult
|
||||||
|
|
||||||
|
data class Enter(val roomId: Long) : LiveCreationResult
|
||||||
|
}
|
||||||
|
|
||||||
|
fun resolveLiveCreationResult(
|
||||||
|
isSuccessful: Boolean,
|
||||||
|
roomId: Long?,
|
||||||
|
channelName: String?
|
||||||
|
): LiveCreationResult = when {
|
||||||
|
!isSuccessful -> LiveCreationResult.Ignored
|
||||||
|
channelName == null -> LiveCreationResult.Created
|
||||||
|
roomId != null && roomId > 0L -> LiveCreationResult.Enter(roomId)
|
||||||
|
else -> LiveCreationResult.RefreshOnly
|
||||||
|
}
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.live.action
|
||||||
|
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Assert.assertFalse
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class LiveActionCoordinatorUiGateTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `ShowDetail은 adult guard와 오디오 중단보다 unavailable을 먼저 실행한다`() {
|
||||||
|
val events = mutableListOf<String>()
|
||||||
|
|
||||||
|
runLiveEntryDecisionFlow(
|
||||||
|
decision = LiveEntryDecision.ShowDetail,
|
||||||
|
onShowDetail = { events += "unavailable" },
|
||||||
|
ensureAdultAccess = { allowed ->
|
||||||
|
events += "adult"
|
||||||
|
allowed()
|
||||||
|
},
|
||||||
|
onAllowedEntry = { events += "entry" }
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(listOf("unavailable"), events)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `입장 가능 결정은 adult guard 이후에만 오디오 중단과 입장 처리를 실행한다`() {
|
||||||
|
val events = mutableListOf<String>()
|
||||||
|
|
||||||
|
runLiveEntryDecisionFlow(
|
||||||
|
decision = LiveEntryDecision.Enter,
|
||||||
|
onShowDetail = { events += "unavailable" },
|
||||||
|
ensureAdultAccess = { allowed ->
|
||||||
|
events += "adult"
|
||||||
|
allowed()
|
||||||
|
},
|
||||||
|
onAllowedEntry = {
|
||||||
|
events += "audio"
|
||||||
|
events += "entry"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(listOf("adult", "audio", "entry"), events)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `adult guard가 거부되면 오디오 중단과 입장 처리를 실행하지 않는다`() {
|
||||||
|
val events = mutableListOf<String>()
|
||||||
|
|
||||||
|
runLiveEntryDecisionFlow(
|
||||||
|
decision = LiveEntryDecision.Enter,
|
||||||
|
onShowDetail = { events += "unavailable" },
|
||||||
|
ensureAdultAccess = { events += "adult" },
|
||||||
|
onAllowedEntry = {
|
||||||
|
events += "audio"
|
||||||
|
events += "entry"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(listOf("adult"), events)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `UI 결과 predicate는 Activity stateSaved 호출 화면 predicate를 모두 결합한다`() {
|
||||||
|
assertFalse(
|
||||||
|
canHandleLiveActionUiResult(
|
||||||
|
isActivityFinishing = true,
|
||||||
|
isActivityDestroyed = false,
|
||||||
|
isStateSaved = false,
|
||||||
|
canHandleResult = { true }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertFalse(
|
||||||
|
canHandleLiveActionUiResult(
|
||||||
|
isActivityFinishing = false,
|
||||||
|
isActivityDestroyed = true,
|
||||||
|
isStateSaved = false,
|
||||||
|
canHandleResult = { true }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertFalse(
|
||||||
|
canHandleLiveActionUiResult(
|
||||||
|
isActivityFinishing = false,
|
||||||
|
isActivityDestroyed = false,
|
||||||
|
isStateSaved = true,
|
||||||
|
canHandleResult = { true }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertFalse(
|
||||||
|
canHandleLiveActionUiResult(
|
||||||
|
isActivityFinishing = false,
|
||||||
|
isActivityDestroyed = false,
|
||||||
|
isStateSaved = false,
|
||||||
|
canHandleResult = { false }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertTrue(
|
||||||
|
canHandleLiveActionUiResult(
|
||||||
|
isActivityFinishing = false,
|
||||||
|
isActivityDestroyed = false,
|
||||||
|
isStateSaved = false,
|
||||||
|
canHandleResult = { true }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `UI side effect는 lifecycle predicate가 실패하면 실행하지 않는다`() {
|
||||||
|
var sideEffectCount = 0
|
||||||
|
|
||||||
|
val executed = runLiveActionUiSideEffect(canHandleResult = { false }) {
|
||||||
|
sideEffectCount += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
assertFalse(executed)
|
||||||
|
assertEquals(0, sideEffectCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `UI side effect는 lifecycle predicate가 통과하면 한 번 실행한다`() {
|
||||||
|
var sideEffectCount = 0
|
||||||
|
|
||||||
|
val executed = runLiveActionUiSideEffect(canHandleResult = { true }) {
|
||||||
|
sideEffectCount += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(executed)
|
||||||
|
assertEquals(1, sideEffectCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `상세 표시는 lifecycle stateSaved 기존 tag fragment를 모두 검사한다`() {
|
||||||
|
assertFalse(
|
||||||
|
canShowLiveRoomDetail(
|
||||||
|
canHandleUiResult = { false },
|
||||||
|
existingDetailFragment = null
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertFalse(
|
||||||
|
canShowLiveRoomDetail(
|
||||||
|
canHandleUiResult = { true },
|
||||||
|
existingDetailFragment = Any()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertTrue(
|
||||||
|
canShowLiveRoomDetail(
|
||||||
|
canHandleUiResult = { true },
|
||||||
|
existingDetailFragment = null
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.live.action
|
||||||
|
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class LiveActionsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `취소 또는 실패한 생성 결과는 무시한다`() {
|
||||||
|
assertEquals(
|
||||||
|
LiveCreationResult.Ignored,
|
||||||
|
resolveLiveCreationResult(isSuccessful = false, roomId = 1L, channelName = "channel")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `channel과 유효한 room ID가 있는 생성 결과는 즉시 입장한다`() {
|
||||||
|
assertEquals(
|
||||||
|
LiveCreationResult.Enter(roomId = 1L),
|
||||||
|
resolveLiveCreationResult(isSuccessful = true, roomId = 1L, channelName = "channel")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `channel이 없으면 생성 완료만 알린다`() {
|
||||||
|
assertEquals(
|
||||||
|
LiveCreationResult.Created,
|
||||||
|
resolveLiveCreationResult(isSuccessful = true, roomId = 1L, channelName = null)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `channel은 있지만 room ID가 유효하지 않은 성공 결과도 Home refresh 대상이다`() {
|
||||||
|
listOf<Long?>(null, 0L, -1L).forEach { roomId ->
|
||||||
|
assertEquals(
|
||||||
|
LiveCreationResult.RefreshOnly,
|
||||||
|
resolveLiveCreationResult(
|
||||||
|
isSuccessful = true,
|
||||||
|
roomId = roomId,
|
||||||
|
channelName = "channel"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user