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.panels.domain.interactor
18 
19 import android.content.ComponentName
20 import android.graphics.drawable.TestStubDrawable
21 import androidx.test.ext.junit.runners.AndroidJUnit4
22 import androidx.test.filters.SmallTest
23 import com.android.systemui.SysuiTestCase
24 import com.android.systemui.common.shared.model.ContentDescription
25 import com.android.systemui.common.shared.model.Icon
26 import com.android.systemui.common.shared.model.Text
27 import com.android.systemui.kosmos.testScope
28 import com.android.systemui.qs.panels.data.repository.iconAndNameCustomRepository
29 import com.android.systemui.qs.panels.data.repository.stockTilesRepository
30 import com.android.systemui.qs.panels.shared.model.EditTileData
31 import com.android.systemui.qs.pipeline.data.repository.FakeInstalledTilesComponentRepository
32 import com.android.systemui.qs.pipeline.data.repository.fakeInstalledTilesRepository
33 import com.android.systemui.qs.pipeline.shared.TileSpec
34 import com.android.systemui.qs.tiles.impl.battery.qsBatterySaverTileConfig
35 import com.android.systemui.qs.tiles.impl.flashlight.qsFlashlightTileConfig
36 import com.android.systemui.qs.tiles.impl.internet.qsInternetTileConfig
37 import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
38 import com.android.systemui.qs.tiles.viewmodel.fakeQSTileConfigProvider
39 import com.android.systemui.qs.tiles.viewmodel.qSTileConfigProvider
40 import com.android.systemui.settings.userTracker
41 import com.android.systemui.testKosmos
42 import com.google.common.truth.Truth.assertThat
43 import kotlinx.coroutines.test.runTest
44 import org.junit.Before
45 import org.junit.Test
46 import org.junit.runner.RunWith
47 
48 @RunWith(AndroidJUnit4::class)
49 @SmallTest
50 class EditTilesListInteractorTest : SysuiTestCase() {
51     private val kosmos = testKosmos()
52 
53     // Only have some configurations so we can test the effect of missing configurations.
54     // As the configurations are injected by dagger, we'll have all the existing configurations
55     private val internetTileConfig = kosmos.qsInternetTileConfig
56     private val flashlightTileConfig = kosmos.qsFlashlightTileConfig
57     private val batteryTileConfig = kosmos.qsBatterySaverTileConfig
58 
59     private val serviceInfo =
60         FakeInstalledTilesComponentRepository.ServiceInfo(
61             component,
62             tileName,
63             icon,
64             appName,
65         )
66 
67     private val underTest =
<lambda>null68         with(kosmos) {
69             EditTilesListInteractor(
70                 stockTilesRepository,
71                 qSTileConfigProvider,
72                 iconAndNameCustomRepository,
73             )
74         }
75 
76     @Before
setUpnull77     fun setUp() {
78         with(kosmos) {
79             fakeInstalledTilesRepository.setInstalledServicesForUser(
80                 userTracker.userId,
81                 listOf(serviceInfo)
82             )
83 
84             with(fakeQSTileConfigProvider) {
85                 putConfig(internetTileConfig.tileSpec, internetTileConfig)
86                 putConfig(flashlightTileConfig.tileSpec, flashlightTileConfig)
87                 putConfig(batteryTileConfig.tileSpec, batteryTileConfig)
88             }
89         }
90     }
91 
92     @Test
getTilesToEdit_stockTilesHaveNoAppNamenull93     fun getTilesToEdit_stockTilesHaveNoAppName() =
94         with(kosmos) {
95             testScope.runTest {
96                 val editTiles = underTest.getTilesToEdit()
97 
98                 assertThat(editTiles.stockTiles.all { it.appName == null }).isTrue()
99             }
100         }
101 
102     @Test
getTilesToEdit_stockTilesAreAllPlatformSpecsnull103     fun getTilesToEdit_stockTilesAreAllPlatformSpecs() =
104         with(kosmos) {
105             testScope.runTest {
106                 val editTiles = underTest.getTilesToEdit()
107 
108                 assertThat(editTiles.stockTiles.all { it.tileSpec is TileSpec.PlatformTileSpec })
109                     .isTrue()
110             }
111         }
112 
113     @Test
getTilesToEdit_stockTiles_sameOrderAsRepositorynull114     fun getTilesToEdit_stockTiles_sameOrderAsRepository() =
115         with(kosmos) {
116             testScope.runTest {
117                 val editTiles = underTest.getTilesToEdit()
118 
119                 assertThat(editTiles.stockTiles.map { it.tileSpec })
120                     .isEqualTo(stockTilesRepository.stockTiles)
121             }
122         }
123 
124     @Test
getTilesToEdit_customTileData_matchesServicenull125     fun getTilesToEdit_customTileData_matchesService() =
126         with(kosmos) {
127             testScope.runTest {
128                 val editTiles = underTest.getTilesToEdit()
129                 val expected =
130                     EditTileData(
131                         tileSpec = TileSpec.create(component),
132                         icon = Icon.Loaded(icon, ContentDescription.Loaded(tileName)),
133                         label = Text.Loaded(tileName),
134                         appName = Text.Loaded(appName),
135                     )
136 
137                 assertThat(editTiles.customTiles).hasSize(1)
138                 assertThat(editTiles.customTiles[0]).isEqualTo(expected)
139             }
140         }
141 
142     @Test
getTilesToEdit_tilesInConfigProvider_correctDatanull143     fun getTilesToEdit_tilesInConfigProvider_correctData() =
144         with(kosmos) {
145             testScope.runTest {
146                 val editTiles = underTest.getTilesToEdit()
147 
148                 assertThat(
149                         editTiles.stockTiles.first { it.tileSpec == internetTileConfig.tileSpec }
150                     )
151                     .isEqualTo(internetTileConfig.toEditTileData())
152                 assertThat(
153                         editTiles.stockTiles.first { it.tileSpec == flashlightTileConfig.tileSpec }
154                     )
155                     .isEqualTo(flashlightTileConfig.toEditTileData())
156                 assertThat(editTiles.stockTiles.first { it.tileSpec == batteryTileConfig.tileSpec })
157                     .isEqualTo(batteryTileConfig.toEditTileData())
158             }
159         }
160 
161     @Test
getTilesToEdit_tilesNotInConfigProvider_useDefaultDatanull162     fun getTilesToEdit_tilesNotInConfigProvider_useDefaultData() =
163         with(kosmos) {
164             testScope.runTest {
165                 underTest
166                     .getTilesToEdit()
167                     .stockTiles
168                     .filterNot { qSTileConfigProvider.hasConfig(it.tileSpec.spec) }
169                     .forEach { assertThat(it).isEqualTo(it.tileSpec.missingConfigEditTileData()) }
170             }
171         }
172 
173     private companion object {
174         val component = ComponentName("pkg", "srv")
175         const val tileName = "Tile Service"
176         const val appName = "App"
177         val icon = TestStubDrawable("icon")
178 
TileSpecnull179         fun TileSpec.missingConfigEditTileData(): EditTileData {
180             return EditTileData(
181                 tileSpec = this,
182                 icon = Icon.Resource(android.R.drawable.star_on, ContentDescription.Loaded(spec)),
183                 label = Text.Loaded(spec),
184                 appName = null
185             )
186         }
187 
toEditTileDatanull188         fun QSTileConfig.toEditTileData(): EditTileData {
189             return EditTileData(
190                 tileSpec = tileSpec,
191                 icon =
192                     Icon.Resource(uiConfig.iconRes, ContentDescription.Resource(uiConfig.labelRes)),
193                 label = Text.Resource(uiConfig.labelRes),
194                 appName = null,
195             )
196         }
197     }
198 }
199