1 /* 2 * Copyright (C) 2018 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.settings.testutils; 18 19 import static android.app.slice.Slice.HINT_TITLE; 20 import static android.app.slice.Slice.SUBTYPE_COLOR; 21 import static android.app.slice.SliceItem.FORMAT_IMAGE; 22 import static android.app.slice.SliceItem.FORMAT_INT; 23 import static android.app.slice.SliceItem.FORMAT_TEXT; 24 25 import static com.google.common.truth.Truth.assertThat; 26 27 import android.app.PendingIntent; 28 import android.content.Context; 29 import android.text.TextUtils; 30 31 import androidx.core.graphics.drawable.IconCompat; 32 import androidx.slice.Slice; 33 import androidx.slice.SliceItem; 34 import androidx.slice.SliceMetadata; 35 import androidx.slice.builders.ListBuilder; 36 import androidx.slice.core.SliceAction; 37 import androidx.slice.core.SliceQuery; 38 import androidx.slice.widget.EventInfo; 39 40 import com.android.settings.Utils; 41 import com.android.settings.slices.SettingsSliceProvider; 42 import com.android.settings.slices.SliceBuilderUtils; 43 import com.android.settings.slices.SliceData; 44 45 import java.util.Arrays; 46 import java.util.List; 47 import java.util.Set; 48 import java.util.stream.Collectors; 49 50 /** 51 * Testing utility class to verify the contents of the different Settings Slices. 52 * 53 * TODO (77712944) check Summary, range (metadata.getRange()), toggle icons. 54 */ 55 public class SliceTester { 56 57 /** 58 * Test the contents of an intent based slice, including: 59 * - No toggles 60 * - Correct intent 61 * - Correct title 62 * - Correct keywords 63 * - TTL 64 * - Color 65 */ testSettingsIntentSlice(Context context, Slice slice, SliceData sliceData)66 public static void testSettingsIntentSlice(Context context, Slice slice, SliceData sliceData) { 67 final SliceMetadata metadata = SliceMetadata.from(context, slice); 68 69 final long sliceTTL = metadata.getExpiry(); 70 assertThat(sliceTTL).isEqualTo(ListBuilder.INFINITY); 71 72 final SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR); 73 final int color = colorItem.getInt(); 74 assertThat(color).isEqualTo(Utils.getColorAccentDefaultColor(context)); 75 76 final List<SliceAction> toggles = metadata.getToggles(); 77 assertThat(toggles).isEmpty(); 78 79 final PendingIntent primaryPendingIntent = metadata.getPrimaryAction().getAction(); 80 assertThat(primaryPendingIntent).isEqualTo( 81 SliceBuilderUtils.getContentPendingIntent(context, sliceData)); 82 83 assertThat(metadata.getTitle()).isEqualTo(sliceData.getTitle()); 84 85 assertKeywords(metadata, sliceData); 86 } 87 88 /** 89 * Test the contents of an toggle based slice, including: 90 * - Contains one toggle 91 * - Correct toggle intent 92 * - Correct content intent 93 * - Correct title 94 * - Correct keywords 95 * - TTL 96 * - Color 97 */ testSettingsToggleSlice(Context context, Slice slice, SliceData sliceData)98 public static void testSettingsToggleSlice(Context context, Slice slice, SliceData sliceData) { 99 final SliceMetadata metadata = SliceMetadata.from(context, slice); 100 101 final SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR); 102 final int color = colorItem.getInt(); 103 assertThat(color).isEqualTo(Utils.getColorAccentDefaultColor(context)); 104 105 final List<SliceAction> toggles = metadata.getToggles(); 106 assertThat(toggles).hasSize(1); 107 108 final long sliceTTL = metadata.getExpiry(); 109 assertThat(sliceTTL).isEqualTo(ListBuilder.INFINITY); 110 111 final SliceAction mainToggleAction = toggles.get(0); 112 113 assertThat(mainToggleAction.getIcon()).isNull(); 114 115 // Check intent in Toggle Action 116 final PendingIntent togglePendingIntent = mainToggleAction.getAction(); 117 assertThat(togglePendingIntent).isEqualTo(SliceBuilderUtils.getActionIntent(context, 118 SettingsSliceProvider.ACTION_TOGGLE_CHANGED, sliceData)); 119 120 // Check primary intent 121 final PendingIntent primaryPendingIntent = metadata.getPrimaryAction().getAction(); 122 assertThat(primaryPendingIntent).isEqualTo( 123 SliceBuilderUtils.getContentPendingIntent(context, sliceData)); 124 125 assertThat(metadata.getTitle()).isEqualTo(sliceData.getTitle()); 126 127 assertKeywords(metadata, sliceData); 128 } 129 130 /** 131 * Test the contents of an slider based slice, including: 132 * - No intent 133 * - Correct title 134 * - Correct keywords 135 * - TTL 136 * - Color 137 */ testSettingsSliderSlice(Context context, Slice slice, SliceData sliceData)138 public static void testSettingsSliderSlice(Context context, Slice slice, SliceData sliceData) { 139 final SliceMetadata metadata = SliceMetadata.from(context, slice); 140 141 final SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR); 142 final int color = colorItem.getInt(); 143 assertThat(color).isEqualTo(Utils.getColorAccentDefaultColor(context)); 144 145 final SliceAction primaryAction = metadata.getPrimaryAction(); 146 147 final IconCompat expectedIcon = IconCompat.createWithResource(context, 148 sliceData.getIconResource()); 149 assertThat(expectedIcon.toString()).isEqualTo(primaryAction.getIcon().toString()); 150 151 final long sliceTTL = metadata.getExpiry(); 152 assertThat(sliceTTL).isEqualTo(ListBuilder.INFINITY); 153 154 final int headerType = metadata.getHeaderType(); 155 assertThat(headerType).isEqualTo(EventInfo.ROW_TYPE_SLIDER); 156 157 // Check primary intent 158 final PendingIntent primaryPendingIntent = primaryAction.getAction(); 159 assertThat(primaryPendingIntent).isEqualTo( 160 SliceBuilderUtils.getContentPendingIntent(context, sliceData)); 161 162 assertThat(metadata.getTitle()).isEqualTo(sliceData.getTitle()); 163 164 assertKeywords(metadata, sliceData); 165 } 166 167 /** 168 * Test the copyable slice, including: 169 * - No intent 170 * - Correct title 171 * - Correct intent 172 * - Correct keywords 173 * - TTL 174 * - Color 175 */ testSettingsCopyableSlice(Context context, Slice slice, SliceData sliceData)176 public static void testSettingsCopyableSlice(Context context, Slice slice, 177 SliceData sliceData) { 178 final SliceMetadata metadata = SliceMetadata.from(context, slice); 179 180 final SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR); 181 final int color = colorItem.getInt(); 182 assertThat(color).isEqualTo(Utils.getColorAccentDefaultColor(context)); 183 184 final SliceAction primaryAction = metadata.getPrimaryAction(); 185 186 final IconCompat expectedIcon = IconCompat.createWithResource(context, 187 sliceData.getIconResource()); 188 assertThat(expectedIcon.toString()).isEqualTo(primaryAction.getIcon().toString()); 189 190 final long sliceTTL = metadata.getExpiry(); 191 assertThat(sliceTTL).isEqualTo(ListBuilder.INFINITY); 192 193 // Check primary intent 194 final PendingIntent primaryPendingIntent = primaryAction.getAction(); 195 assertThat(primaryPendingIntent).isEqualTo( 196 SliceBuilderUtils.getContentPendingIntent(context, sliceData)); 197 198 assertThat(metadata.getTitle()).isEqualTo(sliceData.getTitle()); 199 200 assertKeywords(metadata, sliceData); 201 } 202 203 /** 204 * Test the contents of an unavailable slice, including: 205 * - No toggles 206 * - Correct title 207 * - Correct intent 208 * - Correct keywords 209 * - Color 210 * - TTL 211 */ testSettingsUnavailableSlice(Context context, Slice slice, SliceData sliceData)212 public static void testSettingsUnavailableSlice(Context context, Slice slice, 213 SliceData sliceData) { 214 final SliceMetadata metadata = SliceMetadata.from(context, slice); 215 216 final long sliceTTL = metadata.getExpiry(); 217 assertThat(sliceTTL).isEqualTo(ListBuilder.INFINITY); 218 219 final SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR); 220 final int color = colorItem.getInt(); 221 assertThat(color).isEqualTo(Utils.getColorAccentDefaultColor(context)); 222 223 final List<SliceAction> toggles = metadata.getToggles(); 224 assertThat(toggles).isEmpty(); 225 226 final PendingIntent primaryPendingIntent = metadata.getPrimaryAction().getAction(); 227 assertThat(primaryPendingIntent).isEqualTo(SliceBuilderUtils.getContentPendingIntent( 228 context, sliceData)); 229 230 assertThat(metadata.getTitle()).isEqualTo(sliceData.getTitle()); 231 232 assertKeywords(metadata, sliceData); 233 } 234 235 /** 236 * Assert any slice item contains title. 237 * 238 * @param sliceItems All slice items of a Slice. 239 * @param title Title for asserting. 240 */ assertAnySliceItemContainsTitle(List<SliceItem> sliceItems, String title)241 public static void assertAnySliceItemContainsTitle(List<SliceItem> sliceItems, String title) { 242 assertThat(hasText(sliceItems, title, HINT_TITLE)).isTrue(); 243 } 244 245 /** 246 * Assert any slice item contains subtitle. 247 * 248 * @param sliceItems All slice items of a Slice. 249 * @param subtitle Subtitle for asserting. 250 */ assertAnySliceItemContainsSubtitle(List<SliceItem> sliceItems, String subtitle)251 public static void assertAnySliceItemContainsSubtitle(List<SliceItem> sliceItems, 252 String subtitle) { 253 // Subtitle has no hints 254 assertThat(hasText(sliceItems, subtitle, null /* hints */)).isTrue(); 255 } 256 257 /** 258 * Assert no slice item contains subtitle. 259 * 260 * @param sliceItems All slice items of a Slice. 261 * @param subtitle Subtitle for asserting. 262 */ assertNoSliceItemContainsSubtitle(List<SliceItem> sliceItems, String subtitle)263 public static void assertNoSliceItemContainsSubtitle(List<SliceItem> sliceItems, 264 String subtitle) { 265 // Subtitle has no hints 266 assertThat(hasText(sliceItems, subtitle, null /* hints */)).isFalse(); 267 } 268 hasText(List<SliceItem> sliceItems, String text, String hints)269 private static boolean hasText(List<SliceItem> sliceItems, String text, String hints) { 270 boolean hasText = false; 271 for (SliceItem item : sliceItems) { 272 List<SliceItem> textItems = SliceQuery.findAll(item, FORMAT_TEXT, hints, 273 null /* non-hints */); 274 if (textItems == null) { 275 continue; 276 } 277 278 for (SliceItem textItem : textItems) { 279 if (TextUtils.equals(textItem.getText(), text)) { 280 hasText = true; 281 break; 282 } 283 } 284 } 285 return hasText; 286 } 287 288 /** 289 * Assert any slice item contains icon. 290 * 291 * @param sliceItems All slice items of a Slice. 292 * @param icon Icon for asserting. 293 */ assertAnySliceItemContainsIcon(List<SliceItem> sliceItems, IconCompat icon)294 public static void assertAnySliceItemContainsIcon(List<SliceItem> sliceItems, IconCompat icon) { 295 boolean hasIcon = false; 296 for (SliceItem item : sliceItems) { 297 List<SliceItem> iconItems = SliceQuery.findAll(item, FORMAT_IMAGE, 298 (String) null /* hints */, null /* non-hints */); 299 if (iconItems == null) { 300 continue; 301 } 302 303 for (SliceItem iconItem : iconItems) { 304 if (icon.toString().equals(iconItem.getIcon().toString())) { 305 hasIcon = true; 306 break; 307 } 308 } 309 } 310 assertThat(hasIcon).isTrue(); 311 } 312 assertKeywords(SliceMetadata metadata, SliceData data)313 private static void assertKeywords(SliceMetadata metadata, SliceData data) { 314 final List<String> keywords = metadata.getSliceKeywords(); 315 final Set<String> expectedKeywords = Arrays.stream(data.getKeywords().split(",")) 316 .map(s -> s = s.trim()) 317 .collect(Collectors.toSet()); 318 expectedKeywords.add(data.getTitle()); 319 expectedKeywords.add(data.getScreenTitle().toString()); 320 assertThat(keywords).containsExactlyElementsIn(expectedKeywords); 321 } 322 }