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 final SliceAction primaryAction = metadata.getPrimaryAction(); 141 142 final IconCompat icon = primaryAction.getIcon(); 143 if (icon == null) { 144 final SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR); 145 final int color = colorItem.getInt(); 146 assertThat(color).isEqualTo(Utils.getColorAccentDefaultColor(context)); 147 148 } else { 149 final IconCompat expectedIcon = IconCompat.createWithResource(context, 150 sliceData.getIconResource()); 151 assertThat(expectedIcon.toString()).isEqualTo(icon.toString()); 152 } 153 154 final long sliceTTL = metadata.getExpiry(); 155 assertThat(sliceTTL).isEqualTo(ListBuilder.INFINITY); 156 157 final int headerType = metadata.getHeaderType(); 158 assertThat(headerType).isEqualTo(EventInfo.ROW_TYPE_SLIDER); 159 160 // Check primary intent 161 final PendingIntent primaryPendingIntent = primaryAction.getAction(); 162 assertThat(primaryPendingIntent).isEqualTo( 163 SliceBuilderUtils.getContentPendingIntent(context, sliceData)); 164 165 assertThat(metadata.getTitle()).isEqualTo(sliceData.getTitle()); 166 167 assertKeywords(metadata, sliceData); 168 } 169 170 /** 171 * Test the copyable slice, including: 172 * - No intent 173 * - Correct title 174 * - Correct intent 175 * - Correct keywords 176 * - TTL 177 * - Color 178 */ testSettingsCopyableSlice(Context context, Slice slice, SliceData sliceData)179 public static void testSettingsCopyableSlice(Context context, Slice slice, 180 SliceData sliceData) { 181 final SliceMetadata metadata = SliceMetadata.from(context, slice); 182 183 final SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR); 184 final int color = colorItem.getInt(); 185 assertThat(color).isEqualTo(Utils.getColorAccentDefaultColor(context)); 186 187 final SliceAction primaryAction = metadata.getPrimaryAction(); 188 189 final IconCompat expectedIcon = IconCompat.createWithResource(context, 190 sliceData.getIconResource()); 191 assertThat(expectedIcon.toString()).isEqualTo(primaryAction.getIcon().toString()); 192 193 final long sliceTTL = metadata.getExpiry(); 194 assertThat(sliceTTL).isEqualTo(ListBuilder.INFINITY); 195 196 // Check primary intent 197 final PendingIntent primaryPendingIntent = primaryAction.getAction(); 198 assertThat(primaryPendingIntent).isEqualTo( 199 SliceBuilderUtils.getContentPendingIntent(context, sliceData)); 200 201 assertThat(metadata.getTitle()).isEqualTo(sliceData.getTitle()); 202 203 assertKeywords(metadata, sliceData); 204 } 205 206 /** 207 * Test the contents of an unavailable slice, including: 208 * - No toggles 209 * - Correct title 210 * - Correct intent 211 * - Correct keywords 212 * - Color 213 * - TTL 214 */ testSettingsUnavailableSlice(Context context, Slice slice, SliceData sliceData)215 public static void testSettingsUnavailableSlice(Context context, Slice slice, 216 SliceData sliceData) { 217 final SliceMetadata metadata = SliceMetadata.from(context, slice); 218 219 final long sliceTTL = metadata.getExpiry(); 220 assertThat(sliceTTL).isEqualTo(ListBuilder.INFINITY); 221 222 final SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR); 223 final int color = colorItem.getInt(); 224 assertThat(color).isEqualTo(Utils.getColorAccentDefaultColor(context)); 225 226 final List<SliceAction> toggles = metadata.getToggles(); 227 assertThat(toggles).isEmpty(); 228 229 final PendingIntent primaryPendingIntent = metadata.getPrimaryAction().getAction(); 230 assertThat(primaryPendingIntent).isEqualTo(SliceBuilderUtils.getContentPendingIntent( 231 context, sliceData)); 232 233 assertThat(metadata.getTitle()).isEqualTo(sliceData.getTitle()); 234 235 assertKeywords(metadata, sliceData); 236 } 237 238 /** 239 * Assert any slice item contains title. 240 * 241 * @param sliceItems All slice items of a Slice. 242 * @param title Title for asserting. 243 */ assertAnySliceItemContainsTitle(List<SliceItem> sliceItems, String title)244 public static void assertAnySliceItemContainsTitle(List<SliceItem> sliceItems, String title) { 245 assertThat(hasText(sliceItems, title, HINT_TITLE)).isTrue(); 246 } 247 248 /** 249 * Assert any slice item contains subtitle. 250 * 251 * @param sliceItems All slice items of a Slice. 252 * @param subtitle Subtitle for asserting. 253 */ assertAnySliceItemContainsSubtitle(List<SliceItem> sliceItems, String subtitle)254 public static void assertAnySliceItemContainsSubtitle(List<SliceItem> sliceItems, 255 String subtitle) { 256 // Subtitle has no hints 257 assertThat(hasText(sliceItems, subtitle, null /* hints */)).isTrue(); 258 } 259 260 /** 261 * Assert no slice item contains subtitle. 262 * 263 * @param sliceItems All slice items of a Slice. 264 * @param subtitle Subtitle for asserting. 265 */ assertNoSliceItemContainsSubtitle(List<SliceItem> sliceItems, String subtitle)266 public static void assertNoSliceItemContainsSubtitle(List<SliceItem> sliceItems, 267 String subtitle) { 268 // Subtitle has no hints 269 assertThat(hasText(sliceItems, subtitle, null /* hints */)).isFalse(); 270 } 271 hasText(List<SliceItem> sliceItems, String text, String hints)272 private static boolean hasText(List<SliceItem> sliceItems, String text, String hints) { 273 boolean hasText = false; 274 for (SliceItem item : sliceItems) { 275 List<SliceItem> textItems = SliceQuery.findAll(item, FORMAT_TEXT, hints, 276 null /* non-hints */); 277 if (textItems == null) { 278 continue; 279 } 280 281 for (SliceItem textItem : textItems) { 282 if (TextUtils.equals(textItem.getText(), text)) { 283 hasText = true; 284 break; 285 } 286 } 287 } 288 return hasText; 289 } 290 291 /** 292 * Assert any slice item contains icon. 293 * 294 * @param sliceItems All slice items of a Slice. 295 * @param icon Icon for asserting. 296 */ assertAnySliceItemContainsIcon(List<SliceItem> sliceItems, IconCompat icon)297 public static void assertAnySliceItemContainsIcon(List<SliceItem> sliceItems, IconCompat icon) { 298 boolean hasIcon = false; 299 for (SliceItem item : sliceItems) { 300 List<SliceItem> iconItems = SliceQuery.findAll(item, FORMAT_IMAGE, 301 (String) null /* hints */, null /* non-hints */); 302 if (iconItems == null) { 303 continue; 304 } 305 306 for (SliceItem iconItem : iconItems) { 307 if (icon.toString().equals(iconItem.getIcon().toString())) { 308 hasIcon = true; 309 break; 310 } 311 } 312 } 313 assertThat(hasIcon).isTrue(); 314 } 315 assertKeywords(SliceMetadata metadata, SliceData data)316 private static void assertKeywords(SliceMetadata metadata, SliceData data) { 317 final List<String> keywords = metadata.getSliceKeywords(); 318 final Set<String> expectedKeywords = Arrays.stream(data.getKeywords().split(",")) 319 .map(s -> s = s.trim()) 320 .collect(Collectors.toSet()); 321 expectedKeywords.add(data.getTitle()); 322 expectedKeywords.add(data.getScreenTitle().toString()); 323 assertThat(keywords).containsExactlyElementsIn(expectedKeywords); 324 } 325 } 326