Loading packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt +14 −14 Original line number Diff line number Diff line Loading @@ -95,7 +95,7 @@ import com.android.systemui.bouncer.ui.BouncerDialogFactory import com.android.systemui.bouncer.ui.helper.BouncerSceneLayout import com.android.systemui.bouncer.ui.viewmodel.AuthMethodBouncerViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerMessageViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel import com.android.systemui.bouncer.ui.viewmodel.MessageViewModel import com.android.systemui.bouncer.ui.viewmodel.PasswordBouncerViewModel import com.android.systemui.bouncer.ui.viewmodel.PatternBouncerViewModel Loading @@ -114,7 +114,7 @@ import platform.test.motion.compose.values.motionTestValues @Composable fun BouncerContent( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, dialogFactory: BouncerDialogFactory, modifier: Modifier = Modifier, ) { Loading @@ -128,7 +128,7 @@ fun BouncerContent( @VisibleForTesting fun BouncerContent( layout: BouncerSceneLayout, viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, dialogFactory: BouncerDialogFactory, modifier: Modifier ) { Loading Loading @@ -173,7 +173,7 @@ fun BouncerContent( */ @Composable private fun StandardLayout( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { val isHeightExpanded = Loading Loading @@ -235,7 +235,7 @@ private fun StandardLayout( */ @Composable private fun SplitLayout( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { val authMethod by viewModel.authMethodViewModel.collectAsStateWithLifecycle() Loading Loading @@ -326,7 +326,7 @@ private fun SplitLayout( */ @Composable private fun BesideUserSwitcherLayout( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { val layoutDirection = LocalLayoutDirection.current Loading Loading @@ -461,7 +461,7 @@ private fun BesideUserSwitcherLayout( /** Arranges the bouncer contents and user switcher contents one on top of the other, vertically. */ @Composable private fun BelowUserSwitcherLayout( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { Column( Loading Loading @@ -506,7 +506,7 @@ private fun BelowUserSwitcherLayout( @Composable private fun FoldAware( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, aboveFold: @Composable BoxScope.() -> Unit, belowFold: @Composable BoxScope.() -> Unit, modifier: Modifier = Modifier, Loading Loading @@ -649,7 +649,7 @@ private fun StatusMessage( */ @Composable private fun OutputArea( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { val authMethodViewModel: AuthMethodBouncerViewModel? by Loading Loading @@ -677,7 +677,7 @@ private fun OutputArea( */ @Composable private fun InputArea( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, pinButtonRowVerticalSpacing: Dp, centerPatternDotsVertically: Boolean, modifier: Modifier = Modifier, Loading Loading @@ -706,7 +706,7 @@ private fun InputArea( @Composable private fun ActionArea( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { val actionButton: BouncerActionButtonModel? by Loading Loading @@ -774,7 +774,7 @@ private fun ActionArea( @Composable private fun Dialog( bouncerViewModel: BouncerViewModel, bouncerViewModel: BouncerSceneContentViewModel, dialogFactory: BouncerDialogFactory, ) { val dialogViewModel by bouncerViewModel.dialogViewModel.collectAsStateWithLifecycle() Loading Loading @@ -803,7 +803,7 @@ private fun Dialog( /** Renders the UI of the user switcher that's displayed on large screens next to the bouncer UI. */ @Composable private fun UserSwitcher( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { if (!viewModel.isUserSwitcherVisible) { Loading Loading @@ -884,7 +884,7 @@ private fun UserSwitcher( @Composable private fun UserSwitcherDropdownMenu( isExpanded: Boolean, items: List<BouncerViewModel.UserSwitcherDropdownItemViewModel>, items: List<BouncerSceneContentViewModel.UserSwitcherDropdownItemViewModel>, onDismissed: () -> Unit, ) { val context = LocalContext.current Loading packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt +21 −5 Original line number Diff line number Diff line Loading @@ -27,9 +27,11 @@ import com.android.compose.animation.scene.SceneScope import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult import com.android.systemui.bouncer.ui.BouncerDialogFactory import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneActionsViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel import com.android.systemui.compose.modifiers.sysuiResTag import com.android.systemui.dagger.SysUISingleton import com.android.systemui.lifecycle.rememberViewModel import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.ui.composable.ComposableScene import javax.inject.Inject Loading @@ -51,23 +53,37 @@ object Bouncer { class BouncerScene @Inject constructor( private val viewModel: BouncerViewModel, private val actionsViewModelFactory: BouncerSceneActionsViewModel.Factory, private val contentViewModelFactory: BouncerSceneContentViewModel.Factory, private val dialogFactory: BouncerDialogFactory, ) : ComposableScene { override val key = Scenes.Bouncer private val actionsViewModel: BouncerSceneActionsViewModel by lazy { actionsViewModelFactory.create() } override val destinationScenes: Flow<Map<UserAction, UserActionResult>> = viewModel.destinationScenes actionsViewModel.actions override suspend fun activate() { actionsViewModel.activate() } @Composable override fun SceneScope.Content( modifier: Modifier, ) = BouncerScene(viewModel, dialogFactory, modifier) ) = BouncerScene( viewModel = rememberViewModel { contentViewModelFactory.create() }, dialogFactory = dialogFactory, modifier = modifier, ) } @Composable private fun SceneScope.BouncerScene( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, dialogFactory: BouncerDialogFactory, modifier: Modifier = Modifier, ) { Loading packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt +9 −10 Original line number Diff line number Diff line Loading @@ -22,14 +22,14 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.bouncer.domain.interactor.bouncerInteractor import com.android.systemui.bouncer.domain.interactor.simBouncerInteractor import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope import com.android.systemui.lifecycle.activateIn import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith Loading @@ -39,17 +39,16 @@ class AuthMethodBouncerViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope private val bouncerInteractor by lazy { kosmos.bouncerInteractor } private val underTest by lazy { PinBouncerViewModel( applicationContext = context, viewModelScope = testScope.backgroundScope, interactor = bouncerInteractor, private val underTest = kosmos.pinBouncerViewModelFactory.create( isInputEnabled = MutableStateFlow(true), simBouncerInteractor = kosmos.simBouncerInteractor, authenticationMethod = AuthenticationMethodModel.Pin, onIntentionalUserInput = {}, authenticationMethod = AuthenticationMethodModel.Pin, ) @Before fun setUp() { underTest.activateIn(testScope) } @Test Loading packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelTest.kt +2 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import com.android.systemui.keyguard.shared.model.ErrorFingerprintAuthentication import com.android.systemui.keyguard.shared.model.FailFingerprintAuthenticationStatus import com.android.systemui.keyguard.shared.model.HelpFingerprintAuthenticationStatus import com.android.systemui.kosmos.testScope import com.android.systemui.lifecycle.activateIn import com.android.systemui.res.R import com.android.systemui.testKosmos import com.android.systemui.user.data.repository.fakeUserRepository Loading Loading @@ -87,6 +88,7 @@ class BouncerMessageViewModelTest : SysuiTestCase() { intArrayOf(ignoreHelpMessageId) ) underTest = kosmos.bouncerMessageViewModel underTest.activateIn(testScope) overrideResource(R.string.kg_trust_agent_disabled, "Trust agent is unavailable") kosmos.fakeSystemPropertiesHelper.set( DeviceUnlockedInteractor.SYS_BOOT_REASON_PROP, Loading packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModelTest.kt 0 → 100644 +77 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.bouncer.ui.viewmodel import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.compose.animation.scene.Back import com.android.compose.animation.scene.Swipe import com.android.compose.animation.scene.SwipeDirection import com.android.compose.animation.scene.UserActionResult import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.kosmos.testScope import com.android.systemui.lifecycle.activateIn import com.android.systemui.scene.domain.startable.sceneContainerStartable import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.shared.model.fakeSceneDataSource import com.android.systemui.testKosmos import com.android.systemui.truth.containsEntriesExactly import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) @EnableSceneContainer class BouncerSceneActionsViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope private lateinit var underTest: BouncerSceneActionsViewModel @Before fun setUp() { kosmos.sceneContainerStartable.start() underTest = kosmos.bouncerSceneActionsViewModel underTest.activateIn(testScope) } @Test fun actions() = testScope.runTest { val actions by collectLastValue(underTest.actions) kosmos.fakeSceneDataSource.changeScene(Scenes.QuickSettings) runCurrent() kosmos.fakeSceneDataSource.changeScene(Scenes.Bouncer) runCurrent() assertThat(actions) .containsEntriesExactly( Back to UserActionResult(Scenes.QuickSettings), Swipe(SwipeDirection.Down) to UserActionResult(Scenes.QuickSettings), ) } } Loading
packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt +14 −14 Original line number Diff line number Diff line Loading @@ -95,7 +95,7 @@ import com.android.systemui.bouncer.ui.BouncerDialogFactory import com.android.systemui.bouncer.ui.helper.BouncerSceneLayout import com.android.systemui.bouncer.ui.viewmodel.AuthMethodBouncerViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerMessageViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel import com.android.systemui.bouncer.ui.viewmodel.MessageViewModel import com.android.systemui.bouncer.ui.viewmodel.PasswordBouncerViewModel import com.android.systemui.bouncer.ui.viewmodel.PatternBouncerViewModel Loading @@ -114,7 +114,7 @@ import platform.test.motion.compose.values.motionTestValues @Composable fun BouncerContent( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, dialogFactory: BouncerDialogFactory, modifier: Modifier = Modifier, ) { Loading @@ -128,7 +128,7 @@ fun BouncerContent( @VisibleForTesting fun BouncerContent( layout: BouncerSceneLayout, viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, dialogFactory: BouncerDialogFactory, modifier: Modifier ) { Loading Loading @@ -173,7 +173,7 @@ fun BouncerContent( */ @Composable private fun StandardLayout( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { val isHeightExpanded = Loading Loading @@ -235,7 +235,7 @@ private fun StandardLayout( */ @Composable private fun SplitLayout( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { val authMethod by viewModel.authMethodViewModel.collectAsStateWithLifecycle() Loading Loading @@ -326,7 +326,7 @@ private fun SplitLayout( */ @Composable private fun BesideUserSwitcherLayout( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { val layoutDirection = LocalLayoutDirection.current Loading Loading @@ -461,7 +461,7 @@ private fun BesideUserSwitcherLayout( /** Arranges the bouncer contents and user switcher contents one on top of the other, vertically. */ @Composable private fun BelowUserSwitcherLayout( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { Column( Loading Loading @@ -506,7 +506,7 @@ private fun BelowUserSwitcherLayout( @Composable private fun FoldAware( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, aboveFold: @Composable BoxScope.() -> Unit, belowFold: @Composable BoxScope.() -> Unit, modifier: Modifier = Modifier, Loading Loading @@ -649,7 +649,7 @@ private fun StatusMessage( */ @Composable private fun OutputArea( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { val authMethodViewModel: AuthMethodBouncerViewModel? by Loading Loading @@ -677,7 +677,7 @@ private fun OutputArea( */ @Composable private fun InputArea( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, pinButtonRowVerticalSpacing: Dp, centerPatternDotsVertically: Boolean, modifier: Modifier = Modifier, Loading Loading @@ -706,7 +706,7 @@ private fun InputArea( @Composable private fun ActionArea( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { val actionButton: BouncerActionButtonModel? by Loading Loading @@ -774,7 +774,7 @@ private fun ActionArea( @Composable private fun Dialog( bouncerViewModel: BouncerViewModel, bouncerViewModel: BouncerSceneContentViewModel, dialogFactory: BouncerDialogFactory, ) { val dialogViewModel by bouncerViewModel.dialogViewModel.collectAsStateWithLifecycle() Loading Loading @@ -803,7 +803,7 @@ private fun Dialog( /** Renders the UI of the user switcher that's displayed on large screens next to the bouncer UI. */ @Composable private fun UserSwitcher( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, modifier: Modifier = Modifier, ) { if (!viewModel.isUserSwitcherVisible) { Loading Loading @@ -884,7 +884,7 @@ private fun UserSwitcher( @Composable private fun UserSwitcherDropdownMenu( isExpanded: Boolean, items: List<BouncerViewModel.UserSwitcherDropdownItemViewModel>, items: List<BouncerSceneContentViewModel.UserSwitcherDropdownItemViewModel>, onDismissed: () -> Unit, ) { val context = LocalContext.current Loading
packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt +21 −5 Original line number Diff line number Diff line Loading @@ -27,9 +27,11 @@ import com.android.compose.animation.scene.SceneScope import com.android.compose.animation.scene.UserAction import com.android.compose.animation.scene.UserActionResult import com.android.systemui.bouncer.ui.BouncerDialogFactory import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneActionsViewModel import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel import com.android.systemui.compose.modifiers.sysuiResTag import com.android.systemui.dagger.SysUISingleton import com.android.systemui.lifecycle.rememberViewModel import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.ui.composable.ComposableScene import javax.inject.Inject Loading @@ -51,23 +53,37 @@ object Bouncer { class BouncerScene @Inject constructor( private val viewModel: BouncerViewModel, private val actionsViewModelFactory: BouncerSceneActionsViewModel.Factory, private val contentViewModelFactory: BouncerSceneContentViewModel.Factory, private val dialogFactory: BouncerDialogFactory, ) : ComposableScene { override val key = Scenes.Bouncer private val actionsViewModel: BouncerSceneActionsViewModel by lazy { actionsViewModelFactory.create() } override val destinationScenes: Flow<Map<UserAction, UserActionResult>> = viewModel.destinationScenes actionsViewModel.actions override suspend fun activate() { actionsViewModel.activate() } @Composable override fun SceneScope.Content( modifier: Modifier, ) = BouncerScene(viewModel, dialogFactory, modifier) ) = BouncerScene( viewModel = rememberViewModel { contentViewModelFactory.create() }, dialogFactory = dialogFactory, modifier = modifier, ) } @Composable private fun SceneScope.BouncerScene( viewModel: BouncerViewModel, viewModel: BouncerSceneContentViewModel, dialogFactory: BouncerDialogFactory, modifier: Modifier = Modifier, ) { Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt +9 −10 Original line number Diff line number Diff line Loading @@ -22,14 +22,14 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.bouncer.domain.interactor.bouncerInteractor import com.android.systemui.bouncer.domain.interactor.simBouncerInteractor import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope import com.android.systemui.lifecycle.activateIn import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith Loading @@ -39,17 +39,16 @@ class AuthMethodBouncerViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope private val bouncerInteractor by lazy { kosmos.bouncerInteractor } private val underTest by lazy { PinBouncerViewModel( applicationContext = context, viewModelScope = testScope.backgroundScope, interactor = bouncerInteractor, private val underTest = kosmos.pinBouncerViewModelFactory.create( isInputEnabled = MutableStateFlow(true), simBouncerInteractor = kosmos.simBouncerInteractor, authenticationMethod = AuthenticationMethodModel.Pin, onIntentionalUserInput = {}, authenticationMethod = AuthenticationMethodModel.Pin, ) @Before fun setUp() { underTest.activateIn(testScope) } @Test Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModelTest.kt +2 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import com.android.systemui.keyguard.shared.model.ErrorFingerprintAuthentication import com.android.systemui.keyguard.shared.model.FailFingerprintAuthenticationStatus import com.android.systemui.keyguard.shared.model.HelpFingerprintAuthenticationStatus import com.android.systemui.kosmos.testScope import com.android.systemui.lifecycle.activateIn import com.android.systemui.res.R import com.android.systemui.testKosmos import com.android.systemui.user.data.repository.fakeUserRepository Loading Loading @@ -87,6 +88,7 @@ class BouncerMessageViewModelTest : SysuiTestCase() { intArrayOf(ignoreHelpMessageId) ) underTest = kosmos.bouncerMessageViewModel underTest.activateIn(testScope) overrideResource(R.string.kg_trust_agent_disabled, "Trust agent is unavailable") kosmos.fakeSystemPropertiesHelper.set( DeviceUnlockedInteractor.SYS_BOOT_REASON_PROP, Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModelTest.kt 0 → 100644 +77 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.bouncer.ui.viewmodel import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.compose.animation.scene.Back import com.android.compose.animation.scene.Swipe import com.android.compose.animation.scene.SwipeDirection import com.android.compose.animation.scene.UserActionResult import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.kosmos.testScope import com.android.systemui.lifecycle.activateIn import com.android.systemui.scene.domain.startable.sceneContainerStartable import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.shared.model.fakeSceneDataSource import com.android.systemui.testKosmos import com.android.systemui.truth.containsEntriesExactly import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) @EnableSceneContainer class BouncerSceneActionsViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope private lateinit var underTest: BouncerSceneActionsViewModel @Before fun setUp() { kosmos.sceneContainerStartable.start() underTest = kosmos.bouncerSceneActionsViewModel underTest.activateIn(testScope) } @Test fun actions() = testScope.runTest { val actions by collectLastValue(underTest.actions) kosmos.fakeSceneDataSource.changeScene(Scenes.QuickSettings) runCurrent() kosmos.fakeSceneDataSource.changeScene(Scenes.Bouncer) runCurrent() assertThat(actions) .containsEntriesExactly( Back to UserActionResult(Scenes.QuickSettings), Swipe(SwipeDirection.Down) to UserActionResult(Scenes.QuickSettings), ) } }