1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.keyguard.ui.viewmodel 18 19 import androidx.test.ext.junit.runners.AndroidJUnit4 20 import androidx.test.filters.SmallTest 21 import com.android.systemui.RoboPilotTest 22 import com.android.systemui.SysuiTestCase 23 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository 24 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory 25 import com.android.systemui.keyguard.shared.model.KeyguardState 26 import com.android.systemui.keyguard.shared.model.TransitionState 27 import com.android.systemui.keyguard.shared.model.TransitionStep 28 import com.google.common.collect.Range 29 import com.google.common.truth.Truth.assertThat 30 import kotlinx.coroutines.flow.launchIn 31 import kotlinx.coroutines.flow.onEach 32 import kotlinx.coroutines.test.TestScope 33 import kotlinx.coroutines.test.UnconfinedTestDispatcher 34 import kotlinx.coroutines.test.runTest 35 import org.junit.Before 36 import org.junit.Test 37 import org.junit.runner.RunWith 38 39 @SmallTest 40 @RoboPilotTest 41 @RunWith(AndroidJUnit4::class) 42 class LockscreenToOccludedTransitionViewModelTest : SysuiTestCase() { 43 private lateinit var underTest: LockscreenToOccludedTransitionViewModel 44 private lateinit var repository: FakeKeyguardTransitionRepository 45 46 @Before setUpnull47 fun setUp() { 48 repository = FakeKeyguardTransitionRepository() 49 val interactor = 50 KeyguardTransitionInteractorFactory.create( 51 scope = TestScope().backgroundScope, 52 repository = repository, 53 ) 54 .keyguardTransitionInteractor 55 underTest = LockscreenToOccludedTransitionViewModel(interactor) 56 } 57 58 @Test lockscreenFadeOutnull59 fun lockscreenFadeOut() = 60 runTest(UnconfinedTestDispatcher()) { 61 val values = mutableListOf<Float>() 62 63 val job = underTest.lockscreenAlpha.onEach { values.add(it) }.launchIn(this) 64 65 // Should start running here... 66 repository.sendTransitionStep(step(0f, TransitionState.STARTED)) 67 repository.sendTransitionStep(step(0f)) 68 repository.sendTransitionStep(step(0.1f)) 69 repository.sendTransitionStep(step(0.4f)) 70 repository.sendTransitionStep(step(0.7f)) 71 // ...up to here 72 repository.sendTransitionStep(step(1f)) 73 74 // Only 3 values should be present, since the dream overlay runs for a small fraction 75 // of the overall animation time 76 assertThat(values.size).isEqualTo(5) 77 values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) } 78 79 job.cancel() 80 } 81 82 @Test lockscreenTranslationYnull83 fun lockscreenTranslationY() = 84 runTest(UnconfinedTestDispatcher()) { 85 val values = mutableListOf<Float>() 86 87 val pixels = 100 88 val job = 89 underTest.lockscreenTranslationY(pixels).onEach { values.add(it) }.launchIn(this) 90 91 // Should start running here... 92 repository.sendTransitionStep(step(0f, TransitionState.STARTED)) 93 repository.sendTransitionStep(step(0f)) 94 repository.sendTransitionStep(step(0.3f)) 95 repository.sendTransitionStep(step(0.5f)) 96 repository.sendTransitionStep(step(1f)) 97 // ...up to here 98 99 assertThat(values.size).isEqualTo(5) 100 values.forEach { assertThat(it).isIn(Range.closed(0f, 100f)) } 101 102 job.cancel() 103 } 104 105 @Test lockscreenTranslationYIsCancelednull106 fun lockscreenTranslationYIsCanceled() = 107 runTest(UnconfinedTestDispatcher()) { 108 val values = mutableListOf<Float>() 109 110 val pixels = 100 111 val job = 112 underTest.lockscreenTranslationY(pixels).onEach { values.add(it) }.launchIn(this) 113 114 repository.sendTransitionStep(step(0f, TransitionState.STARTED)) 115 repository.sendTransitionStep(step(0f)) 116 repository.sendTransitionStep(step(0.3f)) 117 repository.sendTransitionStep(step(0.3f, TransitionState.CANCELED)) 118 119 assertThat(values.size).isEqualTo(4) 120 values.forEach { assertThat(it).isIn(Range.closed(0f, 100f)) } 121 122 // Cancel will reset the translation 123 assertThat(values[3]).isEqualTo(0) 124 125 job.cancel() 126 } 127 stepnull128 private fun step( 129 value: Float, 130 state: TransitionState = TransitionState.RUNNING, 131 ): TransitionStep { 132 return TransitionStep( 133 from = KeyguardState.LOCKSCREEN, 134 to = KeyguardState.OCCLUDED, 135 value = value, 136 transitionState = state, 137 ownerName = "LockscreenToOccludedTransitionViewModelTest" 138 ) 139 } 140 } 141