1 /*
2  * Copyright (C) 2024 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.qs.external.ui.viewmodel
18 
19 import android.content.applicationContext
20 import android.content.res.mainResources
21 import android.graphics.drawable.Icon
22 import android.graphics.drawable.TestStubDrawable
23 import android.service.quicksettings.Tile
24 import androidx.test.ext.junit.runners.AndroidJUnit4
25 import androidx.test.filters.SmallTest
26 import com.android.app.iUriGrantsManager
27 import com.android.systemui.SysuiTestCase
28 import com.android.systemui.kosmos.Kosmos
29 import com.android.systemui.kosmos.runCurrent
30 import com.android.systemui.kosmos.runTest
31 import com.android.systemui.kosmos.testScope
32 import com.android.systemui.lifecycle.activateIn
33 import com.android.systemui.plugins.qs.QSTile
34 import com.android.systemui.qs.external.TileData
35 import com.android.systemui.qs.panels.ui.viewmodel.toUiState
36 import com.android.systemui.qs.tileimpl.QSTileImpl
37 import com.android.systemui.qs.tileimpl.QSTileImpl.ResourceIcon
38 import com.android.systemui.res.R
39 import com.android.systemui.testKosmos
40 import com.google.common.truth.Expect
41 import com.google.common.truth.Truth.assertThat
42 import org.junit.Rule
43 import org.junit.Test
44 import org.junit.runner.RunWith
45 import org.mockito.kotlin.doReturn
46 import org.mockito.kotlin.mock
47 import org.mockito.kotlin.stub
48 
49 @SmallTest
50 @RunWith(AndroidJUnit4::class)
51 class TileRequestDialogViewModelTest : SysuiTestCase() {
52 
53     @get:Rule val expect: Expect = Expect.create()
54 
55     private val kosmos = testKosmos()
56 
<lambda>null57     private val icon: Icon = mock {
58         on {
59             loadDrawableCheckingUriGrant(
60                 kosmos.applicationContext,
61                 kosmos.iUriGrantsManager,
62                 TEST_UID,
63                 TEST_PACKAGE,
64             )
65         } doReturn (loadedDrawable)
66     }
67 
68     private val tileData = TileData(TEST_UID, TEST_APP_NAME, TEST_LABEL, icon, TEST_PACKAGE)
69 
70     private val Kosmos.underTest by
<lambda>null71         Kosmos.Fixture { tileRequestDialogViewModelFactory.create(applicationContext, tileData) }
72 
73     private val baseResultLegacyState =
<lambda>null74         QSTile.State().apply {
75             label = TEST_LABEL
76             state = Tile.STATE_ACTIVE
77             handlesLongClick = false
78         }
79 
80     @Test
uiState_beforeActivation_hasDefaultIcon_andCorrectDatanull81     fun uiState_beforeActivation_hasDefaultIcon_andCorrectData() =
82         kosmos.runTest {
83             val expectedState =
84                 baseResultLegacyState.apply { icon = defaultIcon }.toUiState(mainResources)
85 
86             with(underTest.uiState) {
87                 expect.that(label).isEqualTo(TEST_LABEL)
88                 expect.that(secondaryLabel).isEmpty()
89                 expect.that(state).isEqualTo(expectedState.state)
90                 expect.that(handlesLongClick).isFalse()
91                 expect.that(handlesSecondaryClick).isFalse()
92                 expect.that(icon.get()).isEqualTo(defaultIcon)
93                 expect.that(sideDrawable).isNull()
94                 expect.that(accessibilityUiState).isEqualTo(expectedState.accessibilityUiState)
95             }
96         }
97 
98     @Test
uiState_afterActivation_hasCorrectIcon_andCorrectDatanull99     fun uiState_afterActivation_hasCorrectIcon_andCorrectData() =
100         kosmos.runTest {
101             val expectedState =
102                 baseResultLegacyState
103                     .apply { icon = QSTileImpl.DrawableIcon(loadedDrawable) }
104                     .toUiState(mainResources)
105 
106             underTest.activateIn(testScope)
107             runCurrent()
108 
109             with(underTest.uiState) {
110                 expect.that(label).isEqualTo(TEST_LABEL)
111                 expect.that(secondaryLabel).isEmpty()
112                 expect.that(state).isEqualTo(expectedState.state)
113                 expect.that(handlesLongClick).isFalse()
114                 expect.that(handlesSecondaryClick).isFalse()
115                 expect.that(icon.get()).isEqualTo(QSTileImpl.DrawableIcon(loadedDrawable))
116                 expect.that(sideDrawable).isNull()
117                 expect.that(accessibilityUiState).isEqualTo(expectedState.accessibilityUiState)
118             }
119         }
120 
121     @Test
uiState_afterActivation_iconNotLoaded_usesDefaultnull122     fun uiState_afterActivation_iconNotLoaded_usesDefault() =
123         kosmos.runTest {
124             icon.stub {
125                 on {
126                     loadDrawableCheckingUriGrant(
127                         kosmos.applicationContext,
128                         kosmos.iUriGrantsManager,
129                         TEST_UID,
130                         TEST_PACKAGE,
131                     )
132                 } doReturn (null)
133             }
134 
135             underTest.activateIn(testScope)
136             runCurrent()
137 
138             assertThat(underTest.uiState.icon.get()).isEqualTo(defaultIcon)
139         }
140 
141     companion object {
142         private val defaultIcon: QSTile.Icon = ResourceIcon.get(R.drawable.android)
143         private val loadedDrawable = TestStubDrawable("loaded")
144 
145         private const val TEST_PACKAGE = "test_pkg"
146         private const val TEST_APP_NAME = "App"
147         private const val TEST_LABEL = "Label"
148         private const val TEST_UID = 12345
149     }
150 }
151