1 /* 2 * Copyright (C) 2019 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.controls.management 18 19 import android.app.PendingIntent 20 import android.content.ComponentName 21 import android.service.controls.Control 22 import android.testing.AndroidTestingRunner 23 import androidx.test.filters.SmallTest 24 import com.android.systemui.SysuiTestCase 25 import com.android.systemui.controls.ControlStatus 26 import com.android.systemui.controls.controller.ControlInfo 27 import org.junit.Assert.assertEquals 28 import org.junit.Assert.assertFalse 29 import org.junit.Assert.assertTrue 30 import org.junit.Before 31 import org.junit.Test 32 import org.junit.runner.RunWith 33 import org.mockito.Mock 34 import org.mockito.Mockito.never 35 import org.mockito.Mockito.verify 36 import org.mockito.MockitoAnnotations 37 38 @SmallTest 39 @RunWith(AndroidTestingRunner::class) 40 class AllModelTest : SysuiTestCase() { 41 42 companion object { 43 private const val EMPTY_STRING = "Other" 44 } 45 46 @Mock 47 lateinit var pendingIntent: PendingIntent 48 @Mock 49 lateinit var controlsModelCallback: ControlsModel.ControlsModelCallback 50 51 val idPrefix = "controlId" 52 val favoritesIndices = listOf(7, 3, 1, 9) 53 val favoritesList = favoritesIndices.map { "controlId$it" } 54 lateinit var controls: List<ControlStatus> 55 56 lateinit var model: AllModel 57 58 private fun zoneMap(id: Int): String? { 59 return when (id) { 60 10 -> "" 61 11 -> null 62 else -> ((id + 1) % 3).toString() 63 } 64 } 65 66 @Before 67 fun setUp() { 68 MockitoAnnotations.initMocks(this) 69 70 // controlId0 --> zone = 1 71 // controlId1 --> zone = 2, favorite 72 // controlId2 --> zone = 0 73 // controlId3 --> zone = 1, favorite 74 // controlId4 --> zone = 2 75 // controlId5 --> zone = 0 76 // controlId6 --> zone = 1 77 // controlId7 --> zone = 2, favorite 78 // controlId8 --> zone = 0 79 // controlId9 --> zone = 1, favorite 80 // controlId10 --> zone = "" 81 // controlId11 --> zone = null 82 controls = (0..11).map { 83 ControlStatus( 84 Control.StatelessBuilder("$idPrefix$it", pendingIntent) 85 .setZone(zoneMap(it)) 86 .build(), 87 ComponentName("", ""), 88 it in favoritesIndices 89 ) 90 } 91 model = AllModel(controls, favoritesList, EMPTY_STRING, controlsModelCallback) 92 } 93 94 @Test 95 fun testElements() { 96 97 // Zones are sorted by order of appearance, with empty at the end with special header. 98 val expected = listOf( 99 ZoneNameWrapper("1"), 100 ControlStatusWrapper(controls[0]), 101 ControlStatusWrapper(controls[3]), 102 ControlStatusWrapper(controls[6]), 103 ControlStatusWrapper(controls[9]), 104 ZoneNameWrapper("2"), 105 ControlStatusWrapper(controls[1]), 106 ControlStatusWrapper(controls[4]), 107 ControlStatusWrapper(controls[7]), 108 ZoneNameWrapper("0"), 109 ControlStatusWrapper(controls[2]), 110 ControlStatusWrapper(controls[5]), 111 ControlStatusWrapper(controls[8]), 112 ZoneNameWrapper(EMPTY_STRING), 113 ControlStatusWrapper(controls[10]), 114 ControlStatusWrapper(controls[11]) 115 ) 116 expected.zip(model.elements).forEachIndexed { index, it -> 117 assertEquals("Error in item at index $index", it.first, it.second) 118 } 119 } 120 121 private fun sameControl(controlInfo: ControlInfo, control: Control): Boolean { 122 return controlInfo.controlId == control.controlId && 123 controlInfo.controlTitle == control.title && 124 controlInfo.controlSubtitle == control.subtitle && 125 controlInfo.deviceType == control.deviceType 126 } 127 128 @Test 129 fun testAllEmpty_noHeader() { 130 val selected_controls = listOf(controls[10], controls[11]) 131 val new_model = AllModel(selected_controls, emptyList(), EMPTY_STRING, 132 controlsModelCallback) 133 val expected = listOf( 134 ControlStatusWrapper(controls[10]), 135 ControlStatusWrapper(controls[11]) 136 ) 137 138 expected.zip(new_model.elements).forEachIndexed { index, it -> 139 assertEquals("Error in item at index $index", it.first, it.second) 140 } 141 } 142 143 @Test 144 fun testFavorites() { 145 val expectedFavorites = favoritesIndices.map(controls::get).map(ControlStatus::control) 146 model.favorites.zip(expectedFavorites).forEach { 147 assertTrue(sameControl(it.first, it.second)) 148 } 149 } 150 151 @Test 152 fun testAddFavorite() { 153 val indexToAdd = 6 154 model.changeFavoriteStatus("$idPrefix$indexToAdd", true) 155 156 val expectedFavorites = favoritesIndices.map(controls::get).map(ControlStatus::control) + 157 controls[indexToAdd].control 158 159 model.favorites.zip(expectedFavorites).forEach { 160 assertTrue(sameControl(it.first, it.second)) 161 } 162 163 verify(controlsModelCallback).onFirstChange() 164 } 165 166 @Test 167 fun testAddFavorite_changesModelFlag() { 168 val indexToAdd = 6 169 val id = "$idPrefix$indexToAdd" 170 model.changeFavoriteStatus(id, true) 171 assertTrue( 172 (model.elements.first { 173 it is ControlStatusWrapper && it.controlStatus.control.controlId == id 174 } as ControlStatusWrapper) 175 .controlStatus.favorite 176 ) 177 178 verify(controlsModelCallback).onFirstChange() 179 } 180 181 @Test 182 fun testAddFavorite_alreadyThere() { 183 val indexToAdd = 7 184 model.changeFavoriteStatus("$idPrefix$indexToAdd", true) 185 186 val expectedFavorites = favoritesIndices.map(controls::get).map(ControlStatus::control) 187 188 assertEquals(expectedFavorites.size, model.favorites.size) 189 model.favorites.zip(expectedFavorites).forEach { 190 assertTrue(sameControl(it.first, it.second)) 191 } 192 193 verify(controlsModelCallback, never()).onFirstChange() 194 } 195 196 @Test 197 fun testRemoveFavorite() { 198 val indexToRemove = 3 199 model.changeFavoriteStatus("$idPrefix$indexToRemove", false) 200 201 val expectedFavorites = (favoritesIndices.filterNot { it == indexToRemove }) 202 .map(controls::get) 203 .map(ControlStatus::control) 204 205 model.favorites.zip(expectedFavorites).forEach { 206 assertTrue(sameControl(it.first, it.second)) 207 } 208 209 verify(controlsModelCallback).onFirstChange() 210 } 211 212 @Test 213 fun testRemoveFavorite_changesModelFlag() { 214 val indexToRemove = 3 215 val id = "$idPrefix$indexToRemove" 216 model.changeFavoriteStatus(id, false) 217 assertFalse( 218 (model.elements.first { 219 it is ControlStatusWrapper && it.controlStatus.control.controlId == id 220 } as ControlStatusWrapper) 221 .controlStatus.favorite 222 ) 223 224 verify(controlsModelCallback).onFirstChange() 225 } 226 227 @Test 228 fun testRemoveFavorite_notThere() { 229 val indexToRemove = 4 230 model.changeFavoriteStatus("$idPrefix$indexToRemove", false) 231 232 val expectedFavorites = favoritesIndices.map(controls::get).map(ControlStatus::control) 233 234 model.favorites.zip(expectedFavorites).forEach { 235 assertTrue(sameControl(it.first, it.second)) 236 } 237 238 verify(controlsModelCallback, never()).onFirstChange() 239 } 240 } 241