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 LockscreenToDreamingTransitionViewModelTest : SysuiTestCase() {
43     private lateinit var underTest: LockscreenToDreamingTransitionViewModel
44     private lateinit var repository: FakeKeyguardTransitionRepository
45 
46     @Before
47     fun setUp() {
48         repository = FakeKeyguardTransitionRepository()
49         val interactor =
50             KeyguardTransitionInteractorFactory.create(
51                     scope = TestScope().backgroundScope,
52                     repository = repository,
53                 )
54                 .keyguardTransitionInteractor
55         underTest = LockscreenToDreamingTransitionViewModel(interactor)
56     }
57 
58     @Test
59     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.2f))
70             repository.sendTransitionStep(step(0.3f))
71             // ...up to here
72             repository.sendTransitionStep(step(1f))
73 
74             // Only three values should be present, since the dream overlay runs for a small
75             // fraction 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
83     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             repository.sendTransitionStep(step(0f, TransitionState.STARTED))
92             repository.sendTransitionStep(step(0f))
93             repository.sendTransitionStep(step(0.3f))
94             repository.sendTransitionStep(step(0.5f))
95             repository.sendTransitionStep(step(1f))
96             // And a final reset event on FINISHED
97             repository.sendTransitionStep(step(1f, TransitionState.FINISHED))
98 
99             assertThat(values.size).isEqualTo(6)
100             values.forEach { assertThat(it).isIn(Range.closed(0f, 100f)) }
101             // Validate finished value
102             assertThat(values[5]).isEqualTo(0f)
103 
104             job.cancel()
105         }
106 
107     private fun step(
108         value: Float,
109         state: TransitionState = TransitionState.RUNNING
110     ): TransitionStep {
111         return TransitionStep(
112             from = KeyguardState.LOCKSCREEN,
113             to = KeyguardState.DREAMING,
114             value = value,
115             transitionState = state,
116             ownerName = "LockscreenToDreamingTransitionViewModelTest"
117         )
118     }
119 }
120