Loading packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt +40 −322 Original line number Diff line number Diff line Loading @@ -19,11 +19,12 @@ package com.android.systemui.shade.domain.interactor import android.app.StatusBarManager.DISABLE2_NONE import android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE import android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS import androidx.test.ext.junit.runners.AndroidJUnit4 import android.platform.test.flag.junit.FlagsParameterization import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.andSceneContainer import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.DozeStateModel Loading @@ -36,9 +37,7 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.power.data.repository.fakePowerRepository import com.android.systemui.power.shared.model.WakeSleepReason import com.android.systemui.power.shared.model.WakefulnessState import com.android.systemui.res.R import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.shade.data.repository.fakeShadeRepository import com.android.systemui.shade.shadeTestUtil import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository import com.android.systemui.statusbar.phone.dozeParameters Loading @@ -52,28 +51,47 @@ 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 import platform.test.runner.parameterized.ParameterizedAndroidJunit4 import platform.test.runner.parameterized.Parameters @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) class ShadeInteractorImplTest : SysuiTestCase() { @RunWith(ParameterizedAndroidJunit4::class) class ShadeInteractorImplTest(flags: FlagsParameterization?) : SysuiTestCase() { val kosmos = testKosmos() val testScope = kosmos.testScope val configurationRepository = kosmos.fakeConfigurationRepository val deviceProvisioningRepository = kosmos.fakeDeviceProvisioningRepository val disableFlagsRepository = kosmos.fakeDisableFlagsRepository val keyguardRepository = kosmos.fakeKeyguardRepository val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository val powerRepository = kosmos.fakePowerRepository val sceneInteractor = kosmos.sceneInteractor val shadeRepository = kosmos.fakeShadeRepository val userRepository = kosmos.fakeUserRepository val userSetupRepository = kosmos.fakeUserSetupRepository val dozeParameters = kosmos.dozeParameters val underTest = kosmos.shadeInteractorImpl val configurationRepository by lazy { kosmos.fakeConfigurationRepository } val deviceProvisioningRepository by lazy { kosmos.fakeDeviceProvisioningRepository } val disableFlagsRepository by lazy { kosmos.fakeDisableFlagsRepository } val keyguardRepository by lazy { kosmos.fakeKeyguardRepository } val keyguardTransitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository } val powerRepository by lazy { kosmos.fakePowerRepository } val shadeTestUtil by lazy { kosmos.shadeTestUtil } val userRepository by lazy { kosmos.fakeUserRepository } val userSetupRepository by lazy { kosmos.fakeUserSetupRepository } val dozeParameters by lazy { kosmos.dozeParameters } lateinit var underTest: ShadeInteractorImpl companion object { @JvmStatic @Parameters(name = "{0}") fun getParams(): List<FlagsParameterization> { return FlagsParameterization.allCombinationsOf().andSceneContainer() } } init { mSetFlagsRule.setFlagsParameterization(flags!!) } @Before fun setup() { underTest = kosmos.shadeInteractorImpl } @Test fun isShadeEnabled_matchesDisableFlagsRepo() = Loading Loading @@ -283,80 +301,6 @@ class ShadeInteractorImplTest : SysuiTestCase() { assertThat(actual).isTrue() } @Test fun fullShadeExpansionWhenShadeLocked() = testScope.runTest { val actual by collectLastValue(underTest.shadeExpansion) keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED) shadeRepository.setLockscreenShadeExpansion(0.5f) assertThat(actual).isEqualTo(1f) } @Test fun fullShadeExpansionWhenStatusBarStateIsNotShadeLocked() = testScope.runTest { val actual by collectLastValue(underTest.shadeExpansion) keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD) shadeRepository.setLockscreenShadeExpansion(0.5f) assertThat(actual).isEqualTo(0.5f) shadeRepository.setLockscreenShadeExpansion(0.8f) assertThat(actual).isEqualTo(0.8f) } @Test fun shadeExpansionWhenInSplitShadeAndQsExpanded() = testScope.runTest { val actual by collectLastValue(underTest.shadeExpansion) // WHEN split shade is enabled and QS is expanded keyguardRepository.setStatusBarState(StatusBarState.SHADE) overrideResource(R.bool.config_use_split_notification_shade, true) configurationRepository.onAnyConfigurationChange() shadeRepository.setQsExpansion(.5f) shadeRepository.setLegacyShadeExpansion(.7f) runCurrent() // THEN legacy shade expansion is passed through assertThat(actual).isEqualTo(.7f) } @Test fun shadeExpansionWhenNotInSplitShadeAndQsPartiallyExpanded() = testScope.runTest { val actual by collectLastValue(underTest.shadeExpansion) // WHEN split shade is not enabled and QS is expanded keyguardRepository.setStatusBarState(StatusBarState.SHADE) overrideResource(R.bool.config_use_split_notification_shade, false) shadeRepository.setQsExpansion(.5f) shadeRepository.setLegacyShadeExpansion(1f) runCurrent() // THEN shade expansion is zero assertThat(actual).isEqualTo(.5f) } @Test fun shadeExpansionWhenNotInSplitShadeAndQsFullyExpanded() = testScope.runTest { val actual by collectLastValue(underTest.shadeExpansion) // WHEN split shade is not enabled and QS is expanded keyguardRepository.setStatusBarState(StatusBarState.SHADE) overrideResource(R.bool.config_use_split_notification_shade, false) shadeRepository.setQsExpansion(1f) shadeRepository.setLegacyShadeExpansion(1f) runCurrent() // THEN shade expansion is zero assertThat(actual).isEqualTo(0f) } @Test fun shadeExpansionWhenNotInSplitShadeAndQsCollapsed() = testScope.runTest { Loading @@ -364,8 +308,7 @@ class ShadeInteractorImplTest : SysuiTestCase() { // WHEN split shade is not enabled and QS is expanded keyguardRepository.setStatusBarState(StatusBarState.SHADE) shadeRepository.setQsExpansion(0f) shadeRepository.setLegacyShadeExpansion(.6f) shadeTestUtil.setShadeAndQsExpansion(.6f, 0f) // THEN shade expansion is zero assertThat(actual).isEqualTo(.6f) Loading @@ -375,8 +318,7 @@ class ShadeInteractorImplTest : SysuiTestCase() { fun anyExpansion_shadeGreater() = testScope.runTest() { // WHEN shade is more expanded than QS shadeRepository.setLegacyShadeExpansion(.5f) shadeRepository.setQsExpansion(0f) shadeTestUtil.setShadeAndQsExpansion(.5f, 0f) runCurrent() // THEN anyExpansion is .5f Loading @@ -387,237 +329,13 @@ class ShadeInteractorImplTest : SysuiTestCase() { fun anyExpansion_qsGreater() = testScope.runTest() { // WHEN qs is more expanded than shade shadeRepository.setLegacyShadeExpansion(0f) shadeRepository.setQsExpansion(.5f) shadeTestUtil.setShadeAndQsExpansion(0f, .5f) runCurrent() // THEN anyExpansion is .5f assertThat(underTest.anyExpansion.value).isEqualTo(.5f) } @Test fun userInteractingWithShade_shadeDraggedUpAndDown() = testScope.runTest() { val actual by collectLastValue(underTest.isUserInteractingWithShade) // GIVEN shade collapsed and not tracking input shadeRepository.setLegacyShadeExpansion(0f) shadeRepository.setLegacyShadeTracking(false) runCurrent() // THEN user is not interacting assertThat(actual).isFalse() // WHEN shade tracking starts shadeRepository.setLegacyShadeTracking(true) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade dragged down halfway shadeRepository.setLegacyShadeExpansion(.5f) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade fully expanded but tracking is not stopped shadeRepository.setLegacyShadeExpansion(1f) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade fully collapsed but tracking is not stopped shadeRepository.setLegacyShadeExpansion(0f) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade dragged halfway and tracking is stopped shadeRepository.setLegacyShadeExpansion(.6f) shadeRepository.setLegacyShadeTracking(false) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade completes expansion stopped shadeRepository.setLegacyShadeExpansion(1f) runCurrent() // THEN user is not interacting assertThat(actual).isFalse() } @Test fun userInteractingWithShade_shadeExpanded() = testScope.runTest() { val actual by collectLastValue(underTest.isUserInteractingWithShade) // GIVEN shade collapsed and not tracking input shadeRepository.setLegacyShadeExpansion(0f) shadeRepository.setLegacyShadeTracking(false) runCurrent() // THEN user is not interacting assertThat(actual).isFalse() // WHEN shade tracking starts shadeRepository.setLegacyShadeTracking(true) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade dragged down halfway shadeRepository.setLegacyShadeExpansion(.5f) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade fully expanded and tracking is stopped shadeRepository.setLegacyShadeExpansion(1f) shadeRepository.setLegacyShadeTracking(false) runCurrent() // THEN user is not interacting assertThat(actual).isFalse() } @Test fun userInteractingWithShade_shadePartiallyExpanded() = testScope.runTest() { val actual by collectLastValue(underTest.isUserInteractingWithShade) // GIVEN shade collapsed and not tracking input shadeRepository.setLegacyShadeExpansion(0f) shadeRepository.setLegacyShadeTracking(false) runCurrent() // THEN user is not interacting assertThat(actual).isFalse() // WHEN shade tracking starts shadeRepository.setLegacyShadeTracking(true) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade partially expanded shadeRepository.setLegacyShadeExpansion(.4f) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN tracking is stopped shadeRepository.setLegacyShadeTracking(false) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade goes back to collapsed shadeRepository.setLegacyShadeExpansion(0f) runCurrent() // THEN user is not interacting assertThat(actual).isFalse() } @Test fun userInteractingWithShade_shadeCollapsed() = testScope.runTest() { val actual by collectLastValue(underTest.isUserInteractingWithShade) // GIVEN shade expanded and not tracking input shadeRepository.setLegacyShadeExpansion(1f) shadeRepository.setLegacyShadeTracking(false) runCurrent() // THEN user is not interacting assertThat(actual).isFalse() // WHEN shade tracking starts shadeRepository.setLegacyShadeTracking(true) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade dragged up halfway shadeRepository.setLegacyShadeExpansion(.5f) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade fully collapsed and tracking is stopped shadeRepository.setLegacyShadeExpansion(0f) shadeRepository.setLegacyShadeTracking(false) runCurrent() // THEN user is not interacting assertThat(actual).isFalse() } @Test fun userInteractingWithQs_qsDraggedUpAndDown() = testScope.runTest() { val actual by collectLastValue(underTest.isUserInteractingWithQs) // GIVEN qs collapsed and not tracking input shadeRepository.setQsExpansion(0f) shadeRepository.setLegacyQsTracking(false) runCurrent() // THEN user is not interacting assertThat(actual).isFalse() // WHEN qs tracking starts shadeRepository.setLegacyQsTracking(true) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN qs dragged down halfway shadeRepository.setQsExpansion(.5f) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN qs fully expanded but tracking is not stopped shadeRepository.setQsExpansion(1f) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN qs fully collapsed but tracking is not stopped shadeRepository.setQsExpansion(0f) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN qs dragged halfway and tracking is stopped shadeRepository.setQsExpansion(.6f) shadeRepository.setLegacyQsTracking(false) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN qs completes expansion stopped shadeRepository.setQsExpansion(1f) runCurrent() // THEN user is not interacting assertThat(actual).isFalse() } @Test fun isShadeTouchable_isFalse_whenDeviceAsleepAndNotPulsing() = testScope.runTest { Loading packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImplTest.kt +18 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.DisableSceneContainer import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.StatusBarState Loading @@ -40,6 +41,7 @@ import org.junit.runner.RunWith @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) @DisableSceneContainer class ShadeInteractorLegacyImplTest : SysuiTestCase() { val kosmos = testKosmos() val testScope = kosmos.testScope Loading Loading @@ -94,6 +96,22 @@ class ShadeInteractorLegacyImplTest : SysuiTestCase() { assertThat(actual).isEqualTo(.7f) } @Test fun shadeExpansionWhenNotInSplitShadeAndQsPartiallyExpanded() = testScope.runTest { val actual by collectLastValue(underTest.shadeExpansion) // WHEN split shade is not enabled and QS is expanded keyguardRepository.setStatusBarState(StatusBarState.SHADE) overrideResource(R.bool.config_use_split_notification_shade, false) shadeRepository.setQsExpansion(.5f) shadeRepository.setLegacyShadeExpansion(1f) runCurrent() // THEN shade expansion is zero assertThat(actual).isEqualTo(.5f) } @Test fun shadeExpansionWhenNotInSplitShadeAndQsFullyExpanded() = testScope.runTest { Loading packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt +0 −4 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.coroutines.collectLastValue import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.kosmos.testScope import com.android.systemui.res.R Loading @@ -32,7 +31,6 @@ import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.data.repository.shadeRepository import com.android.systemui.shade.shared.model.ShadeMode import com.android.systemui.testKosmos import com.android.systemui.user.data.repository.userRepository import com.google.common.truth.Truth import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi Loading @@ -52,9 +50,7 @@ class ShadeInteractorSceneContainerImplTest : SysuiTestCase() { private val testScope = kosmos.testScope private val configurationRepository = kosmos.fakeConfigurationRepository private val keyguardRepository = kosmos.fakeKeyguardRepository private val keyguardTransitionRepository = kosmos.keyguardTransitionRepository private val sceneInteractor = kosmos.sceneInteractor private val userRepository = kosmos.userRepository private val shadeRepository = kosmos.shadeRepository private val underTest = kosmos.shadeInteractorSceneContainerImpl Loading packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt 0 → 100644 +100 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.shade import com.android.compose.animation.scene.ObservableTransitionState import com.android.compose.animation.scene.SceneKey import com.android.systemui.scene.domain.interactor.SceneInteractor import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.data.repository.FakeShadeRepository import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import org.junit.Assert /** Sets up shade state for tests for either value of the scene container flag. */ class ShadeTestUtil constructor(val delegate: ShadeTestUtilDelegate) { /** Sets both shade and QS expansion. One value must be zero or values must add up to 1f. */ fun setShadeAndQsExpansion(shadeExpansion: Float, qsExpansion: Float) { Assert.assertTrue( "One expansion must be zero or both must add up to 1", shadeExpansion == 0f || qsExpansion == 0f || shadeExpansion + qsExpansion == 1f, ) delegate.assertFlagValid() delegate.setShadeAndQsExpansionInternal(shadeExpansion, qsExpansion) } } /** Sets up shade state for tests for a specific value of the scene container flag. */ interface ShadeTestUtilDelegate { /** Sets both shade and QS expansion. One value must be zero or values must add up to 1f. */ fun setShadeAndQsExpansionInternal(shadeExpansion: Float, qsExpansion: Float) /** Asserts that the scene container flag matches this implementation. */ fun assertFlagValid() } /** Sets up shade state for tests when the scene container flag is disabled. */ class ShadeTestUtilLegacyImpl(val testScope: TestScope, val shadeRepository: FakeShadeRepository) : ShadeTestUtilDelegate { override fun setShadeAndQsExpansionInternal(shadeExpansion: Float, qsExpansion: Float) { shadeRepository.setLegacyShadeExpansion(shadeExpansion) shadeRepository.setQsExpansion(qsExpansion) testScope.runCurrent() } override fun assertFlagValid() { Assert.assertFalse(SceneContainerFlag.isEnabled) } } /** Sets up shade state for tests when the scene container flag is disabled. */ class ShadeTestUtilSceneImpl(val testScope: TestScope, val sceneInteractor: SceneInteractor) : ShadeTestUtilDelegate { override fun setShadeAndQsExpansionInternal(shadeExpansion: Float, qsExpansion: Float) { if (shadeExpansion == 0f) { setTransitionProgress(Scenes.Lockscreen, Scenes.QuickSettings, qsExpansion) } else if (qsExpansion == 0f) { setTransitionProgress(Scenes.Lockscreen, Scenes.Shade, shadeExpansion) } else { setTransitionProgress(Scenes.Shade, Scenes.QuickSettings, qsExpansion) } } private fun setTransitionProgress(from: SceneKey, to: SceneKey, progress: Float) { sceneInteractor.changeScene(from, "test") val transitionState = MutableStateFlow<ObservableTransitionState>( ObservableTransitionState.Transition( fromScene = from, toScene = to, progress = MutableStateFlow(progress), isInitiatedByUserInput = false, isUserInputOngoing = flowOf(false), ) ) sceneInteractor.setTransitionState(transitionState) testScope.runCurrent() } override fun assertFlagValid() { Assert.assertTrue(SceneContainerFlag.isEnabled) } } packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtilKosmos.kt 0 → 100644 +34 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.shade import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testScope import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.shade.data.repository.fakeShadeRepository var Kosmos.shadeTestUtil: ShadeTestUtil by Kosmos.Fixture { ShadeTestUtil( if (SceneContainerFlag.isEnabled) { ShadeTestUtilSceneImpl(testScope, sceneInteractor) } else { ShadeTestUtilLegacyImpl(testScope, fakeShadeRepository) } ) } Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt +40 −322 Original line number Diff line number Diff line Loading @@ -19,11 +19,12 @@ package com.android.systemui.shade.domain.interactor import android.app.StatusBarManager.DISABLE2_NONE import android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE import android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS import androidx.test.ext.junit.runners.AndroidJUnit4 import android.platform.test.flag.junit.FlagsParameterization import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.andSceneContainer import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.DozeStateModel Loading @@ -36,9 +37,7 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.power.data.repository.fakePowerRepository import com.android.systemui.power.shared.model.WakeSleepReason import com.android.systemui.power.shared.model.WakefulnessState import com.android.systemui.res.R import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.shade.data.repository.fakeShadeRepository import com.android.systemui.shade.shadeTestUtil import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository import com.android.systemui.statusbar.phone.dozeParameters Loading @@ -52,28 +51,47 @@ 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 import platform.test.runner.parameterized.ParameterizedAndroidJunit4 import platform.test.runner.parameterized.Parameters @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) class ShadeInteractorImplTest : SysuiTestCase() { @RunWith(ParameterizedAndroidJunit4::class) class ShadeInteractorImplTest(flags: FlagsParameterization?) : SysuiTestCase() { val kosmos = testKosmos() val testScope = kosmos.testScope val configurationRepository = kosmos.fakeConfigurationRepository val deviceProvisioningRepository = kosmos.fakeDeviceProvisioningRepository val disableFlagsRepository = kosmos.fakeDisableFlagsRepository val keyguardRepository = kosmos.fakeKeyguardRepository val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository val powerRepository = kosmos.fakePowerRepository val sceneInteractor = kosmos.sceneInteractor val shadeRepository = kosmos.fakeShadeRepository val userRepository = kosmos.fakeUserRepository val userSetupRepository = kosmos.fakeUserSetupRepository val dozeParameters = kosmos.dozeParameters val underTest = kosmos.shadeInteractorImpl val configurationRepository by lazy { kosmos.fakeConfigurationRepository } val deviceProvisioningRepository by lazy { kosmos.fakeDeviceProvisioningRepository } val disableFlagsRepository by lazy { kosmos.fakeDisableFlagsRepository } val keyguardRepository by lazy { kosmos.fakeKeyguardRepository } val keyguardTransitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository } val powerRepository by lazy { kosmos.fakePowerRepository } val shadeTestUtil by lazy { kosmos.shadeTestUtil } val userRepository by lazy { kosmos.fakeUserRepository } val userSetupRepository by lazy { kosmos.fakeUserSetupRepository } val dozeParameters by lazy { kosmos.dozeParameters } lateinit var underTest: ShadeInteractorImpl companion object { @JvmStatic @Parameters(name = "{0}") fun getParams(): List<FlagsParameterization> { return FlagsParameterization.allCombinationsOf().andSceneContainer() } } init { mSetFlagsRule.setFlagsParameterization(flags!!) } @Before fun setup() { underTest = kosmos.shadeInteractorImpl } @Test fun isShadeEnabled_matchesDisableFlagsRepo() = Loading Loading @@ -283,80 +301,6 @@ class ShadeInteractorImplTest : SysuiTestCase() { assertThat(actual).isTrue() } @Test fun fullShadeExpansionWhenShadeLocked() = testScope.runTest { val actual by collectLastValue(underTest.shadeExpansion) keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED) shadeRepository.setLockscreenShadeExpansion(0.5f) assertThat(actual).isEqualTo(1f) } @Test fun fullShadeExpansionWhenStatusBarStateIsNotShadeLocked() = testScope.runTest { val actual by collectLastValue(underTest.shadeExpansion) keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD) shadeRepository.setLockscreenShadeExpansion(0.5f) assertThat(actual).isEqualTo(0.5f) shadeRepository.setLockscreenShadeExpansion(0.8f) assertThat(actual).isEqualTo(0.8f) } @Test fun shadeExpansionWhenInSplitShadeAndQsExpanded() = testScope.runTest { val actual by collectLastValue(underTest.shadeExpansion) // WHEN split shade is enabled and QS is expanded keyguardRepository.setStatusBarState(StatusBarState.SHADE) overrideResource(R.bool.config_use_split_notification_shade, true) configurationRepository.onAnyConfigurationChange() shadeRepository.setQsExpansion(.5f) shadeRepository.setLegacyShadeExpansion(.7f) runCurrent() // THEN legacy shade expansion is passed through assertThat(actual).isEqualTo(.7f) } @Test fun shadeExpansionWhenNotInSplitShadeAndQsPartiallyExpanded() = testScope.runTest { val actual by collectLastValue(underTest.shadeExpansion) // WHEN split shade is not enabled and QS is expanded keyguardRepository.setStatusBarState(StatusBarState.SHADE) overrideResource(R.bool.config_use_split_notification_shade, false) shadeRepository.setQsExpansion(.5f) shadeRepository.setLegacyShadeExpansion(1f) runCurrent() // THEN shade expansion is zero assertThat(actual).isEqualTo(.5f) } @Test fun shadeExpansionWhenNotInSplitShadeAndQsFullyExpanded() = testScope.runTest { val actual by collectLastValue(underTest.shadeExpansion) // WHEN split shade is not enabled and QS is expanded keyguardRepository.setStatusBarState(StatusBarState.SHADE) overrideResource(R.bool.config_use_split_notification_shade, false) shadeRepository.setQsExpansion(1f) shadeRepository.setLegacyShadeExpansion(1f) runCurrent() // THEN shade expansion is zero assertThat(actual).isEqualTo(0f) } @Test fun shadeExpansionWhenNotInSplitShadeAndQsCollapsed() = testScope.runTest { Loading @@ -364,8 +308,7 @@ class ShadeInteractorImplTest : SysuiTestCase() { // WHEN split shade is not enabled and QS is expanded keyguardRepository.setStatusBarState(StatusBarState.SHADE) shadeRepository.setQsExpansion(0f) shadeRepository.setLegacyShadeExpansion(.6f) shadeTestUtil.setShadeAndQsExpansion(.6f, 0f) // THEN shade expansion is zero assertThat(actual).isEqualTo(.6f) Loading @@ -375,8 +318,7 @@ class ShadeInteractorImplTest : SysuiTestCase() { fun anyExpansion_shadeGreater() = testScope.runTest() { // WHEN shade is more expanded than QS shadeRepository.setLegacyShadeExpansion(.5f) shadeRepository.setQsExpansion(0f) shadeTestUtil.setShadeAndQsExpansion(.5f, 0f) runCurrent() // THEN anyExpansion is .5f Loading @@ -387,237 +329,13 @@ class ShadeInteractorImplTest : SysuiTestCase() { fun anyExpansion_qsGreater() = testScope.runTest() { // WHEN qs is more expanded than shade shadeRepository.setLegacyShadeExpansion(0f) shadeRepository.setQsExpansion(.5f) shadeTestUtil.setShadeAndQsExpansion(0f, .5f) runCurrent() // THEN anyExpansion is .5f assertThat(underTest.anyExpansion.value).isEqualTo(.5f) } @Test fun userInteractingWithShade_shadeDraggedUpAndDown() = testScope.runTest() { val actual by collectLastValue(underTest.isUserInteractingWithShade) // GIVEN shade collapsed and not tracking input shadeRepository.setLegacyShadeExpansion(0f) shadeRepository.setLegacyShadeTracking(false) runCurrent() // THEN user is not interacting assertThat(actual).isFalse() // WHEN shade tracking starts shadeRepository.setLegacyShadeTracking(true) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade dragged down halfway shadeRepository.setLegacyShadeExpansion(.5f) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade fully expanded but tracking is not stopped shadeRepository.setLegacyShadeExpansion(1f) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade fully collapsed but tracking is not stopped shadeRepository.setLegacyShadeExpansion(0f) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade dragged halfway and tracking is stopped shadeRepository.setLegacyShadeExpansion(.6f) shadeRepository.setLegacyShadeTracking(false) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade completes expansion stopped shadeRepository.setLegacyShadeExpansion(1f) runCurrent() // THEN user is not interacting assertThat(actual).isFalse() } @Test fun userInteractingWithShade_shadeExpanded() = testScope.runTest() { val actual by collectLastValue(underTest.isUserInteractingWithShade) // GIVEN shade collapsed and not tracking input shadeRepository.setLegacyShadeExpansion(0f) shadeRepository.setLegacyShadeTracking(false) runCurrent() // THEN user is not interacting assertThat(actual).isFalse() // WHEN shade tracking starts shadeRepository.setLegacyShadeTracking(true) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade dragged down halfway shadeRepository.setLegacyShadeExpansion(.5f) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade fully expanded and tracking is stopped shadeRepository.setLegacyShadeExpansion(1f) shadeRepository.setLegacyShadeTracking(false) runCurrent() // THEN user is not interacting assertThat(actual).isFalse() } @Test fun userInteractingWithShade_shadePartiallyExpanded() = testScope.runTest() { val actual by collectLastValue(underTest.isUserInteractingWithShade) // GIVEN shade collapsed and not tracking input shadeRepository.setLegacyShadeExpansion(0f) shadeRepository.setLegacyShadeTracking(false) runCurrent() // THEN user is not interacting assertThat(actual).isFalse() // WHEN shade tracking starts shadeRepository.setLegacyShadeTracking(true) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade partially expanded shadeRepository.setLegacyShadeExpansion(.4f) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN tracking is stopped shadeRepository.setLegacyShadeTracking(false) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade goes back to collapsed shadeRepository.setLegacyShadeExpansion(0f) runCurrent() // THEN user is not interacting assertThat(actual).isFalse() } @Test fun userInteractingWithShade_shadeCollapsed() = testScope.runTest() { val actual by collectLastValue(underTest.isUserInteractingWithShade) // GIVEN shade expanded and not tracking input shadeRepository.setLegacyShadeExpansion(1f) shadeRepository.setLegacyShadeTracking(false) runCurrent() // THEN user is not interacting assertThat(actual).isFalse() // WHEN shade tracking starts shadeRepository.setLegacyShadeTracking(true) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade dragged up halfway shadeRepository.setLegacyShadeExpansion(.5f) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN shade fully collapsed and tracking is stopped shadeRepository.setLegacyShadeExpansion(0f) shadeRepository.setLegacyShadeTracking(false) runCurrent() // THEN user is not interacting assertThat(actual).isFalse() } @Test fun userInteractingWithQs_qsDraggedUpAndDown() = testScope.runTest() { val actual by collectLastValue(underTest.isUserInteractingWithQs) // GIVEN qs collapsed and not tracking input shadeRepository.setQsExpansion(0f) shadeRepository.setLegacyQsTracking(false) runCurrent() // THEN user is not interacting assertThat(actual).isFalse() // WHEN qs tracking starts shadeRepository.setLegacyQsTracking(true) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN qs dragged down halfway shadeRepository.setQsExpansion(.5f) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN qs fully expanded but tracking is not stopped shadeRepository.setQsExpansion(1f) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN qs fully collapsed but tracking is not stopped shadeRepository.setQsExpansion(0f) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN qs dragged halfway and tracking is stopped shadeRepository.setQsExpansion(.6f) shadeRepository.setLegacyQsTracking(false) runCurrent() // THEN user is interacting assertThat(actual).isTrue() // WHEN qs completes expansion stopped shadeRepository.setQsExpansion(1f) runCurrent() // THEN user is not interacting assertThat(actual).isFalse() } @Test fun isShadeTouchable_isFalse_whenDeviceAsleepAndNotPulsing() = testScope.runTest { Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImplTest.kt +18 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.DisableSceneContainer import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.StatusBarState Loading @@ -40,6 +41,7 @@ import org.junit.runner.RunWith @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) @DisableSceneContainer class ShadeInteractorLegacyImplTest : SysuiTestCase() { val kosmos = testKosmos() val testScope = kosmos.testScope Loading Loading @@ -94,6 +96,22 @@ class ShadeInteractorLegacyImplTest : SysuiTestCase() { assertThat(actual).isEqualTo(.7f) } @Test fun shadeExpansionWhenNotInSplitShadeAndQsPartiallyExpanded() = testScope.runTest { val actual by collectLastValue(underTest.shadeExpansion) // WHEN split shade is not enabled and QS is expanded keyguardRepository.setStatusBarState(StatusBarState.SHADE) overrideResource(R.bool.config_use_split_notification_shade, false) shadeRepository.setQsExpansion(.5f) shadeRepository.setLegacyShadeExpansion(1f) runCurrent() // THEN shade expansion is zero assertThat(actual).isEqualTo(.5f) } @Test fun shadeExpansionWhenNotInSplitShadeAndQsFullyExpanded() = testScope.runTest { Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt +0 −4 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.coroutines.collectLastValue import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.kosmos.testScope import com.android.systemui.res.R Loading @@ -32,7 +31,6 @@ import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.data.repository.shadeRepository import com.android.systemui.shade.shared.model.ShadeMode import com.android.systemui.testKosmos import com.android.systemui.user.data.repository.userRepository import com.google.common.truth.Truth import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi Loading @@ -52,9 +50,7 @@ class ShadeInteractorSceneContainerImplTest : SysuiTestCase() { private val testScope = kosmos.testScope private val configurationRepository = kosmos.fakeConfigurationRepository private val keyguardRepository = kosmos.fakeKeyguardRepository private val keyguardTransitionRepository = kosmos.keyguardTransitionRepository private val sceneInteractor = kosmos.sceneInteractor private val userRepository = kosmos.userRepository private val shadeRepository = kosmos.shadeRepository private val underTest = kosmos.shadeInteractorSceneContainerImpl Loading
packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt 0 → 100644 +100 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.shade import com.android.compose.animation.scene.ObservableTransitionState import com.android.compose.animation.scene.SceneKey import com.android.systemui.scene.domain.interactor.SceneInteractor import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.data.repository.FakeShadeRepository import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import org.junit.Assert /** Sets up shade state for tests for either value of the scene container flag. */ class ShadeTestUtil constructor(val delegate: ShadeTestUtilDelegate) { /** Sets both shade and QS expansion. One value must be zero or values must add up to 1f. */ fun setShadeAndQsExpansion(shadeExpansion: Float, qsExpansion: Float) { Assert.assertTrue( "One expansion must be zero or both must add up to 1", shadeExpansion == 0f || qsExpansion == 0f || shadeExpansion + qsExpansion == 1f, ) delegate.assertFlagValid() delegate.setShadeAndQsExpansionInternal(shadeExpansion, qsExpansion) } } /** Sets up shade state for tests for a specific value of the scene container flag. */ interface ShadeTestUtilDelegate { /** Sets both shade and QS expansion. One value must be zero or values must add up to 1f. */ fun setShadeAndQsExpansionInternal(shadeExpansion: Float, qsExpansion: Float) /** Asserts that the scene container flag matches this implementation. */ fun assertFlagValid() } /** Sets up shade state for tests when the scene container flag is disabled. */ class ShadeTestUtilLegacyImpl(val testScope: TestScope, val shadeRepository: FakeShadeRepository) : ShadeTestUtilDelegate { override fun setShadeAndQsExpansionInternal(shadeExpansion: Float, qsExpansion: Float) { shadeRepository.setLegacyShadeExpansion(shadeExpansion) shadeRepository.setQsExpansion(qsExpansion) testScope.runCurrent() } override fun assertFlagValid() { Assert.assertFalse(SceneContainerFlag.isEnabled) } } /** Sets up shade state for tests when the scene container flag is disabled. */ class ShadeTestUtilSceneImpl(val testScope: TestScope, val sceneInteractor: SceneInteractor) : ShadeTestUtilDelegate { override fun setShadeAndQsExpansionInternal(shadeExpansion: Float, qsExpansion: Float) { if (shadeExpansion == 0f) { setTransitionProgress(Scenes.Lockscreen, Scenes.QuickSettings, qsExpansion) } else if (qsExpansion == 0f) { setTransitionProgress(Scenes.Lockscreen, Scenes.Shade, shadeExpansion) } else { setTransitionProgress(Scenes.Shade, Scenes.QuickSettings, qsExpansion) } } private fun setTransitionProgress(from: SceneKey, to: SceneKey, progress: Float) { sceneInteractor.changeScene(from, "test") val transitionState = MutableStateFlow<ObservableTransitionState>( ObservableTransitionState.Transition( fromScene = from, toScene = to, progress = MutableStateFlow(progress), isInitiatedByUserInput = false, isUserInputOngoing = flowOf(false), ) ) sceneInteractor.setTransitionState(transitionState) testScope.runCurrent() } override fun assertFlagValid() { Assert.assertTrue(SceneContainerFlag.isEnabled) } }
packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtilKosmos.kt 0 → 100644 +34 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.shade import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testScope import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.shade.data.repository.fakeShadeRepository var Kosmos.shadeTestUtil: ShadeTestUtil by Kosmos.Fixture { ShadeTestUtil( if (SceneContainerFlag.isEnabled) { ShadeTestUtilSceneImpl(testScope, sceneInteractor) } else { ShadeTestUtilLegacyImpl(testScope, fakeShadeRepository) } ) }