diff options
| author | 2025-01-22 10:50:00 -0800 | |
|---|---|---|
| committer | 2025-01-22 10:50:00 -0800 | |
| commit | d5258154fdf075e09808142d1e18cf18c063f392 (patch) | |
| tree | 628dbcba34ba00a7a8ee9831278a33982fd928bf | |
| parent | 33ad61da50e6898f8551c9092184e60ffe26541f (diff) | |
| parent | c93e5ebb7685768b5ad487aab42cb66b83b851b4 (diff) | |
Merge "[Quickswitch] tests" into main
4 files changed, 220 insertions, 14 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/gesture/SwitchAppsGestureRecognizerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/gesture/SwitchAppsGestureRecognizerTest.kt new file mode 100644 index 000000000000..756b79c6a868 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/gesture/SwitchAppsGestureRecognizerTest.kt @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2025 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.touchpad.tutorial.ui.gesture + +import android.view.MotionEvent +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.InProgress +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NotStarted +import com.android.systemui.touchpad.tutorial.ui.gesture.MultiFingerGesture.Companion.SWIPE_DISTANCE +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +class SwitchAppsGestureRecognizerTest : SysuiTestCase() { + + private var gestureState: GestureState = NotStarted + private val gestureRecognizer = + SwitchAppsGestureRecognizer(gestureDistanceThresholdPx = SWIPE_DISTANCE.toInt()) + + @Before + fun before() { + gestureRecognizer.addGestureStateCallback { gestureState = it } + } + + @Test + fun triggersProgressRelativeToDistanceWhenSwipingRight() { + assertProgressWhileMovingFingers( + deltaX = SWIPE_DISTANCE / 2, + expected = InProgress(progress = 0.5f), + ) + assertProgressWhileMovingFingers( + deltaX = SWIPE_DISTANCE, + expected = InProgress(progress = 1f), + ) + } + + @Test + fun triggersProgressDoesNotGoBelowZero() { + // going in the wrong direction + assertProgressWhileMovingFingers( + deltaX = -SWIPE_DISTANCE, + expected = InProgress(progress = 0f), + ) + } + + @Test + fun triggersProgressDoesNotExceedOne() { + // going further than required distance + assertProgressWhileMovingFingers( + deltaX = SWIPE_DISTANCE * 2, + expected = InProgress(progress = 1f), + ) + } + + private fun assertProgressWhileMovingFingers(deltaX: Float, expected: InProgress) { + assertStateAfterEvents( + events = FourFingerGesture.eventsForGestureInProgress { move(deltaX = deltaX) }, + expectedState = expected, + ) + } + + private fun assertStateAfterEvents(events: List<MotionEvent>, expectedState: GestureState) { + events.forEach { gestureRecognizer.accept(it) } + assertThat(gestureState).isEqualTo(expectedState) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/SwitchAppsGestureScreenViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/SwitchAppsGestureScreenViewModelTest.kt new file mode 100644 index 000000000000..ee339b0b7446 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/SwitchAppsGestureScreenViewModelTest.kt @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2025 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.touchpad.tutorial.ui.viewmodel + +import android.content.res.mockResources +import android.view.MotionEvent +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository +import com.android.systemui.inputdevice.tutorial.inputDeviceTutorialLogger +import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState +import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.Error +import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.Finished +import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState.InProgress +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.collectLastValue +import com.android.systemui.kosmos.runTest +import com.android.systemui.kosmos.useUnconfinedTestDispatcher +import com.android.systemui.res.R +import com.android.systemui.testKosmos +import com.android.systemui.touchpad.tutorial.ui.gesture.FourFingerGesture +import com.android.systemui.touchpad.tutorial.ui.gesture.MultiFingerGesture.Companion.SWIPE_DISTANCE +import com.android.systemui.touchpad.ui.gesture.touchpadGestureResources +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.whenever + +@SmallTest +@RunWith(AndroidJUnit4::class) +class SwitchAppsGestureScreenViewModelTest : SysuiTestCase() { + + private val kosmos = testKosmos() + private val resources = kosmos.mockResources + private val fakeConfigRepository = kosmos.fakeConfigurationRepository + private val viewModel = + SwitchAppsGestureScreenViewModel( + GestureRecognizerAdapter( + SwitchAppsGestureRecognizerProvider(kosmos.touchpadGestureResources), + kosmos.inputDeviceTutorialLogger, + ) + ) + + @Before + fun before() { + setDistanceThreshold(threshold = SWIPE_DISTANCE - 1) + kosmos.useUnconfinedTestDispatcher() + } + + @Test + fun emitsProgressStateWithProgressAnimation() = + kosmos.runTest { + assertProgressWhileMovingFingers( + deltaX = SWIPE_DISTANCE, + expected = + InProgress( + progress = 1f, + startMarker = "gesture to R", + endMarker = "end of gesture", + ), + ) + } + + @Test + fun emitsFinishedStateWithSuccessAnimation() = + kosmos.runTest { + assertStateAfterEvents( + events = FourFingerGesture.swipeRight(), + expected = Finished(successAnimation = R.raw.trackpad_switch_apps_success), + ) + } + + @Test + fun emitErrorStateWhenLatestDistanceThresholdNotReached() = + kosmos.runTest { + fun performGesture() = + FourFingerGesture.swipeRight().forEach { viewModel.handleEvent(it) } + val state by collectLastValue(viewModel.tutorialState) + performGesture() + assertThat(state).isInstanceOf(Finished::class.java) + + setDistanceThreshold(SWIPE_DISTANCE + 1) + performGesture() // now swipe distance is not enough to trigger success + + assertThat(state).isInstanceOf(Error::class.java) + } + + private fun setDistanceThreshold(threshold: Float) { + whenever( + resources.getDimensionPixelSize( + R.dimen.touchpad_tutorial_gestures_distance_threshold + ) + ) + .thenReturn(threshold.toInt()) + fakeConfigRepository.onAnyConfigurationChange() + } + + private fun Kosmos.assertProgressWhileMovingFingers( + deltaX: Float, + expected: TutorialActionState, + ) { + assertStateAfterEvents( + events = FourFingerGesture.eventsForGestureInProgress { move(deltaX = deltaX) }, + expected = expected, + ) + } + + private fun Kosmos.assertStateAfterEvents( + events: List<MotionEvent>, + expected: TutorialActionState, + ) { + val state by collectLastValue(viewModel.tutorialState) + events.forEach { viewModel.handleEvent(it) } + assertThat(state).isEqualTo(expected) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/SwitchAppsGestureRecognizer.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/SwitchAppsGestureRecognizer.kt index cc382d0a6148..6732287fe256 100644 --- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/SwitchAppsGestureRecognizer.kt +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/SwitchAppsGestureRecognizer.kt @@ -18,12 +18,9 @@ package com.android.systemui.touchpad.tutorial.ui.gesture import android.util.MathUtils import android.view.MotionEvent -import com.android.systemui.touchpad.tutorial.ui.gesture.GestureDirection.LEFT -import com.android.systemui.touchpad.tutorial.ui.gesture.GestureDirection.RIGHT import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.InProgress -import kotlin.math.abs -/** Recognizes Quickswitch gesture i.e. using four fingers on touchpad, swiping right. */ +/** Recognizes Quickswitch gesture i.e. using four fingers on touchpad, swiping to right. */ class SwitchAppsGestureRecognizer(private val gestureDistanceThresholdPx: Int) : GestureRecognizer { private val distanceTracker = DistanceTracker() @@ -50,13 +47,7 @@ class SwitchAppsGestureRecognizer(private val gestureDistanceThresholdPx: Int) : gestureStateChangedCallback, gestureState, isFinished = { it.deltaX >= gestureDistanceThresholdPx }, - progress = ::getProgress, + progress = { InProgress(MathUtils.saturate(it.deltaX / gestureDistanceThresholdPx)) }, ) } - - private fun getProgress(it: Moving): InProgress { - val direction = if (it.deltaX > 0) RIGHT else LEFT - val value = MathUtils.saturate(abs(it.deltaX / gestureDistanceThresholdPx)) - return InProgress(value, direction) - } } diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/SwitchAppsGestureRecognizerProvider.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/SwitchAppsGestureRecognizerProvider.kt index b1e163b55377..8b8606a119d4 100644 --- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/SwitchAppsGestureRecognizerProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/SwitchAppsGestureRecognizerProvider.kt @@ -18,15 +18,13 @@ package com.android.systemui.touchpad.tutorial.ui.viewmodel import com.android.systemui.touchpad.tutorial.ui.gesture.GestureRecognizer import com.android.systemui.touchpad.tutorial.ui.gesture.SwitchAppsGestureRecognizer -import com.android.systemui.touchpad.tutorial.ui.gesture.VelocityTracker import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map class SwitchAppsGestureRecognizerProvider @Inject -constructor(val resources: TouchpadGestureResources, val velocityTracker: VelocityTracker) : - GestureRecognizerProvider { +constructor(val resources: TouchpadGestureResources) : GestureRecognizerProvider { override val recognizer: Flow<GestureRecognizer> = resources.distanceThreshold().map { |