Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 752ddbe6 authored by David Saff's avatar David Saff
Browse files

Introduce Kosmos.runTest

Together with an example use in SceneFrameworkIntegrationTest

Bug: 342622417
Test: local
Flag: TEST_ONLY

Change-Id: I95603e5d22b2831346591d4a662ce2fe311a1bca
parent 58f46938
Loading
Loading
Loading
Loading
+120 −122
Original line number Diff line number Diff line
@@ -44,6 +44,8 @@ import com.android.systemui.flags.Flags
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.ui.viewmodel.lockscreenUserActionsViewModel
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.runCurrent
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testScope
import com.android.systemui.lifecycle.activateIn
import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
@@ -70,7 +72,6 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -101,7 +102,6 @@ import org.mockito.Mockito.verify
@EnableSceneContainer
class SceneFrameworkIntegrationTest : SysuiTestCase() {
    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope
    private var bouncerSceneJob: Job? = null

    @Before
@@ -137,151 +137,149 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
                .isTrue()
        }

    @Test
    fun startsInLockscreenScene() =
        testScope.runTest { kosmos.assertCurrentScene(Scenes.Lockscreen) }
    @Test fun startsInLockscreenScene() = kosmos.runTest { assertCurrentScene(Scenes.Lockscreen) }

    @Test
    fun clickLockButtonAndEnterCorrectPin_unlocksDevice() =
        testScope.runTest {
            kosmos.emulateUserDrivenTransition(Scenes.Bouncer)
        kosmos.runTest {
            emulateUserDrivenTransition(Scenes.Bouncer)

            kosmos.fakeSceneDataSource.pause()
            kosmos.enterPin()
            kosmos.emulatePendingTransitionProgress(expectedVisible = false)
            kosmos.assertCurrentScene(Scenes.Gone)
            fakeSceneDataSource.pause()
            enterPin()
            emulatePendingTransitionProgress(expectedVisible = false)
            assertCurrentScene(Scenes.Gone)
        }

    @Test
    fun swipeUpOnLockscreen_enterCorrectPin_unlocksDevice() =
        testScope.runTest {
            val actions by collectLastValue(kosmos.lockscreenUserActionsViewModel.actions)
        kosmos.runTest {
            val actions by testScope.collectLastValue(kosmos.lockscreenUserActionsViewModel.actions)
            val upDestinationSceneKey =
                (actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
            assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
            kosmos.emulateUserDrivenTransition(to = upDestinationSceneKey)
            emulateUserDrivenTransition(to = upDestinationSceneKey)

            kosmos.fakeSceneDataSource.pause()
            kosmos.enterPin()
            kosmos.emulatePendingTransitionProgress(expectedVisible = false)
            kosmos.assertCurrentScene(Scenes.Gone)
            fakeSceneDataSource.pause()
            enterPin()
            emulatePendingTransitionProgress(expectedVisible = false)
            assertCurrentScene(Scenes.Gone)
        }

    @Test
    fun swipeUpOnLockscreen_withAuthMethodSwipe_dismissesLockscreen() =
        testScope.runTest {
            kosmos.setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
        kosmos.runTest {
            setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)

            val actions by collectLastValue(kosmos.lockscreenUserActionsViewModel.actions)
            val actions by testScope.collectLastValue(lockscreenUserActionsViewModel.actions)
            val upDestinationSceneKey =
                (actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
            assertThat(upDestinationSceneKey).isEqualTo(Scenes.Gone)
            kosmos.emulateUserDrivenTransition(to = upDestinationSceneKey)
            emulateUserDrivenTransition(to = upDestinationSceneKey)
        }

    @Test
    fun swipeUpOnShadeScene_withAuthMethodSwipe_lockscreenNotDismissed_goesToLockscreen() =
        testScope.runTest {
            val actions by collectLastValue(kosmos.shadeUserActionsViewModel.actions)
            kosmos.setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
            kosmos.assertCurrentScene(Scenes.Lockscreen)
        kosmos.runTest {
            val actions by testScope.collectLastValue(shadeUserActionsViewModel.actions)
            setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
            assertCurrentScene(Scenes.Lockscreen)

            // Emulate a user swipe to the shade scene.
            kosmos.emulateUserDrivenTransition(to = Scenes.Shade)
            kosmos.assertCurrentScene(Scenes.Shade)
            emulateUserDrivenTransition(to = Scenes.Shade)
            assertCurrentScene(Scenes.Shade)

            val upDestinationSceneKey =
                (actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
            assertThat(upDestinationSceneKey).isEqualTo(Scenes.Lockscreen)
            kosmos.emulateUserDrivenTransition(to = Scenes.Lockscreen)
            emulateUserDrivenTransition(to = Scenes.Lockscreen)
        }

    @Test
    fun swipeUpOnShadeScene_withAuthMethodSwipe_lockscreenDismissed_goesToGone() =
        testScope.runTest {
            val actions by collectLastValue(kosmos.shadeUserActionsViewModel.actions)
            val canSwipeToEnter by collectLastValue(kosmos.deviceEntryInteractor.canSwipeToEnter)
        kosmos.runTest {
            val actions by testScope.collectLastValue(shadeUserActionsViewModel.actions)
            val canSwipeToEnter by testScope.collectLastValue(deviceEntryInteractor.canSwipeToEnter)

            kosmos.setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
            setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)

            assertThat(canSwipeToEnter).isTrue()
            kosmos.assertCurrentScene(Scenes.Lockscreen)
            assertCurrentScene(Scenes.Lockscreen)

            // Emulate a user swipe to dismiss the lockscreen.
            kosmos.emulateUserDrivenTransition(to = Scenes.Gone)
            kosmos.assertCurrentScene(Scenes.Gone)
            emulateUserDrivenTransition(to = Scenes.Gone)
            assertCurrentScene(Scenes.Gone)

            // Emulate a user swipe to the shade scene.
            kosmos.emulateUserDrivenTransition(to = Scenes.Shade)
            kosmos.assertCurrentScene(Scenes.Shade)
            emulateUserDrivenTransition(to = Scenes.Shade)
            assertCurrentScene(Scenes.Shade)

            val upDestinationSceneKey =
                (actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
            assertThat(upDestinationSceneKey).isEqualTo(Scenes.Gone)
            kosmos.emulateUserDrivenTransition(to = Scenes.Gone)
            emulateUserDrivenTransition(to = Scenes.Gone)
        }

    @Test
    fun withAuthMethodNone_deviceWakeUp_skipsLockscreen() =
        testScope.runTest {
            kosmos.setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = false)
            kosmos.putDeviceToSleep()
            kosmos.assertCurrentScene(Scenes.Lockscreen)
        kosmos.runTest {
            setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = false)
            putDeviceToSleep()
            assertCurrentScene(Scenes.Lockscreen)

            kosmos.wakeUpDevice()
            kosmos.assertCurrentScene(Scenes.Gone)
            wakeUpDevice()
            assertCurrentScene(Scenes.Gone)
        }

    @Test
    fun withAuthMethodSwipe_deviceWakeUp_doesNotSkipLockscreen() =
        testScope.runTest {
            kosmos.setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
            kosmos.putDeviceToSleep()
            kosmos.assertCurrentScene(Scenes.Lockscreen)
        kosmos.runTest {
            setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
            putDeviceToSleep()
            assertCurrentScene(Scenes.Lockscreen)

            kosmos.wakeUpDevice()
            kosmos.assertCurrentScene(Scenes.Lockscreen)
            wakeUpDevice()
            assertCurrentScene(Scenes.Lockscreen)
        }

    @Test
    fun lockDeviceLocksDevice() =
        testScope.runTest {
            kosmos.unlockDevice()
            kosmos.assertCurrentScene(Scenes.Gone)
        kosmos.runTest {
            unlockDevice()
            assertCurrentScene(Scenes.Gone)

            kosmos.lockDevice()
            kosmos.assertCurrentScene(Scenes.Lockscreen)
            lockDevice()
            assertCurrentScene(Scenes.Lockscreen)
        }

    @Test
    fun deviceGoesToSleep_switchesToLockscreen() =
        testScope.runTest {
            kosmos.unlockDevice()
            kosmos.assertCurrentScene(Scenes.Gone)
        kosmos.runTest {
            unlockDevice()
            assertCurrentScene(Scenes.Gone)

            kosmos.putDeviceToSleep()
            kosmos.assertCurrentScene(Scenes.Lockscreen)
            putDeviceToSleep()
            assertCurrentScene(Scenes.Lockscreen)
        }

    @Test
    fun deviceGoesToSleep_wakeUp_unlock() =
        testScope.runTest {
            kosmos.unlockDevice()
            kosmos.assertCurrentScene(Scenes.Gone)
            kosmos.putDeviceToSleep()
            kosmos.assertCurrentScene(Scenes.Lockscreen)
            kosmos.wakeUpDevice()
            kosmos.assertCurrentScene(Scenes.Lockscreen)
        kosmos.runTest {
            unlockDevice()
            assertCurrentScene(Scenes.Gone)
            putDeviceToSleep()
            assertCurrentScene(Scenes.Lockscreen)
            wakeUpDevice()
            assertCurrentScene(Scenes.Lockscreen)

            kosmos.unlockDevice()
            kosmos.assertCurrentScene(Scenes.Gone)
            unlockDevice()
            assertCurrentScene(Scenes.Gone)
        }

    @Test
    fun swipeUpOnLockscreenWhileUnlocked_dismissesLockscreen() =
        testScope.runTest {
            kosmos.unlockDevice()
            val actions by collectLastValue(kosmos.lockscreenUserActionsViewModel.actions)
        kosmos.runTest {
            unlockDevice()
            val actions by testScope.collectLastValue(lockscreenUserActionsViewModel.actions)
            val upDestinationSceneKey =
                (actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
            assertThat(upDestinationSceneKey).isEqualTo(Scenes.Gone)
@@ -289,46 +287,46 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {

    @Test
    fun deviceGoesToSleep_withLockTimeout_staysOnLockscreen() =
        testScope.runTest {
            kosmos.unlockDevice()
            kosmos.assertCurrentScene(Scenes.Gone)
            kosmos.putDeviceToSleep()
            kosmos.assertCurrentScene(Scenes.Lockscreen)
        kosmos.runTest {
            unlockDevice()
            assertCurrentScene(Scenes.Gone)
            putDeviceToSleep()
            assertCurrentScene(Scenes.Lockscreen)

            // Pretend like the timeout elapsed and now lock the device.
            kosmos.lockDevice()
            kosmos.assertCurrentScene(Scenes.Lockscreen)
            lockDevice()
            assertCurrentScene(Scenes.Lockscreen)
        }

    @Test
    fun dismissingIme_whileOnPasswordBouncer_navigatesToLockscreen() =
        testScope.runTest {
            kosmos.setAuthMethod(AuthenticationMethodModel.Password)
            val actions by collectLastValue(kosmos.lockscreenUserActionsViewModel.actions)
        kosmos.runTest {
            setAuthMethod(AuthenticationMethodModel.Password)
            val actions by testScope.collectLastValue(lockscreenUserActionsViewModel.actions)
            val upDestinationSceneKey =
                (actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
            assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
            kosmos.emulateUserDrivenTransition(to = upDestinationSceneKey)
            emulateUserDrivenTransition(to = upDestinationSceneKey)

            kosmos.fakeSceneDataSource.pause()
            kosmos.dismissIme()
            fakeSceneDataSource.pause()
            dismissIme()

            kosmos.emulatePendingTransitionProgress()
            kosmos.assertCurrentScene(Scenes.Lockscreen)
            emulatePendingTransitionProgress()
            assertCurrentScene(Scenes.Lockscreen)
        }

    @Test
    fun bouncerActionButtonClick_opensEmergencyServicesDialer() =
        testScope.runTest {
            kosmos.setAuthMethod(AuthenticationMethodModel.Password)
            val actions by collectLastValue(kosmos.lockscreenUserActionsViewModel.actions)
        kosmos.runTest {
            setAuthMethod(AuthenticationMethodModel.Password)
            val actions by testScope.collectLastValue(lockscreenUserActionsViewModel.actions)
            val upDestinationSceneKey =
                (actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
            assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
            kosmos.emulateUserDrivenTransition(to = upDestinationSceneKey)
            emulateUserDrivenTransition(to = upDestinationSceneKey)

            val bouncerActionButton by
                collectLastValue(kosmos.bouncerSceneContentViewModel.actionButton)
                testScope.collectLastValue(bouncerSceneContentViewModel.actionButton)
            assertWithMessage("Bouncer action button not visible")
                .that(bouncerActionButton)
                .isNotNull()
@@ -340,56 +338,56 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {

    @Test
    fun bouncerActionButtonClick_duringCall_returnsToCall() =
        testScope.runTest {
            kosmos.setAuthMethod(AuthenticationMethodModel.Password)
            kosmos.startPhoneCall()
            val actions by collectLastValue(kosmos.lockscreenUserActionsViewModel.actions)
        kosmos.runTest {
            setAuthMethod(AuthenticationMethodModel.Password)
            startPhoneCall()
            val actions by testScope.collectLastValue(lockscreenUserActionsViewModel.actions)
            val upDestinationSceneKey =
                (actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
            assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
            kosmos.emulateUserDrivenTransition(to = upDestinationSceneKey)
            emulateUserDrivenTransition(to = upDestinationSceneKey)

            val bouncerActionButton by
                collectLastValue(kosmos.bouncerSceneContentViewModel.actionButton)
                testScope.collectLastValue(bouncerSceneContentViewModel.actionButton)
            assertWithMessage("Bouncer action button not visible during call")
                .that(bouncerActionButton)
                .isNotNull()
            bouncerActionButton?.onClick?.invoke()
            runCurrent()

            verify(kosmos.mockTelecomManager).showInCallScreen(any())
            verify(mockTelecomManager).showInCallScreen(any())
        }

    @Test
    fun showBouncer_whenLockedSimIntroduced() =
        testScope.runTest {
            kosmos.setAuthMethod(AuthenticationMethodModel.None)
            kosmos.introduceLockedSim()
            kosmos.assertCurrentScene(Scenes.Bouncer)
        kosmos.runTest {
            setAuthMethod(AuthenticationMethodModel.None)
            introduceLockedSim()
            assertCurrentScene(Scenes.Bouncer)
        }

    @Test
    fun goesToGone_whenSimUnlocked_whileDeviceUnlocked() =
        testScope.runTest {
            kosmos.fakeSceneDataSource.pause()
            kosmos.introduceLockedSim()
            kosmos.emulatePendingTransitionProgress(expectedVisible = true)
            kosmos.enterSimPin(
        kosmos.runTest {
            fakeSceneDataSource.pause()
            introduceLockedSim()
            emulatePendingTransitionProgress(expectedVisible = true)
            enterSimPin(
                authMethodAfterSimUnlock = AuthenticationMethodModel.None,
                enableLockscreen = false,
            )

            kosmos.assertCurrentScene(Scenes.Gone)
            assertCurrentScene(Scenes.Gone)
        }

    @Test
    fun showLockscreen_whenSimUnlocked_whileDeviceLocked() =
        testScope.runTest {
            kosmos.fakeSceneDataSource.pause()
            kosmos.introduceLockedSim()
            kosmos.emulatePendingTransitionProgress(expectedVisible = true)
            kosmos.enterSimPin(authMethodAfterSimUnlock = AuthenticationMethodModel.Pin)
            kosmos.assertCurrentScene(Scenes.Lockscreen)
        kosmos.runTest {
            fakeSceneDataSource.pause()
            introduceLockedSim()
            emulatePendingTransitionProgress(expectedVisible = true)
            enterSimPin(authMethodAfterSimUnlock = AuthenticationMethodModel.Pin)
            assertCurrentScene(Scenes.Lockscreen)
        }

    /**
@@ -457,10 +455,10 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
     */
    private fun Kosmos.emulatePendingTransitionProgress(expectedVisible: Boolean = true) {
        assertWithMessage("The FakeSceneDataSource has to be paused for this to do anything.")
            .that(kosmos.fakeSceneDataSource.isPaused)
            .that(fakeSceneDataSource.isPaused)
            .isTrue()

        val to = kosmos.fakeSceneDataSource.pendingScene ?: return
        val to = fakeSceneDataSource.pendingScene ?: return
        val from = getCurrentSceneInUi()

        if (to == from) {
@@ -489,7 +487,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
        // End the transition and report the change.
        transitionState.value = ObservableTransitionState.Idle(to)

        kosmos.fakeSceneDataSource.unpause(force = true)
        fakeSceneDataSource.unpause(force = true)
        testScope.runCurrent()

        assertWithMessage("Visibility mismatch after scene transition from $from to $to!")
@@ -523,7 +521,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
    private fun Kosmos.emulateUserDrivenTransition(to: SceneKey?) {
        checkNotNull(to)

        kosmos.fakeSceneDataSource.pause()
        fakeSceneDataSource.pause()
        sceneInteractor.changeScene(to, "reason")

        emulatePendingTransitionProgress(expectedVisible = to != Scenes.Gone)
@@ -634,7 +632,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
    }

    /** Changes device wakefulness state from awake to asleep, going through intermediary states. */
    private suspend fun Kosmos.putDeviceToSleep() {
    private fun Kosmos.putDeviceToSleep() {
        val wakefulnessModel = powerInteractor.detailedWakefulness.value
        assertWithMessage("Cannot put device to sleep as it's already asleep!")
            .that(wakefulnessModel.isAwake())
+11 −0
Original line number Diff line number Diff line
@@ -6,6 +6,8 @@ import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest

var Kosmos.testDispatcher by Fixture { StandardTestDispatcher() }
var Kosmos.unconfinedTestDispatcher by Fixture { UnconfinedTestDispatcher() }
@@ -17,3 +19,12 @@ var Kosmos.backgroundCoroutineContext: CoroutineContext by Fixture {
    testScope.backgroundScope.coroutineContext
}
var Kosmos.mainCoroutineContext: CoroutineContext by Fixture { testScope.coroutineContext }

/**
 * Run this test body with a [Kosmos] as receiver, and using the [testScope] currently installed in
 * that kosmos instance
 */
fun Kosmos.runTest(testBody: suspend Kosmos.() -> Unit) =
    testScope.runTest { this@runTest.testBody() }

fun Kosmos.runCurrent() = testScope.runCurrent()