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
17package com.android.settings.testutils;
18
19import static android.app.slice.Slice.HINT_TITLE;
20import static android.app.slice.Slice.SUBTYPE_COLOR;
21import static android.app.slice.SliceItem.FORMAT_INT;
22import static android.app.slice.SliceItem.FORMAT_TEXT;
23
24import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
25import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
26import static com.android.settings.core.BasePreferenceController.DISABLED_FOR_USER;
27import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
28
29import static com.google.common.truth.Truth.assertThat;
30
31import android.app.PendingIntent;
32import android.content.Context;
33
34import java.util.Arrays;
35import java.util.HashSet;
36import java.util.List;
37import java.util.Set;
38import java.util.stream.Collectors;
39
40import androidx.slice.Slice;
41import androidx.slice.SliceItem;
42import androidx.slice.SliceMetadata;
43import androidx.slice.builders.ListBuilder;
44import androidx.slice.core.SliceAction;
45import androidx.slice.core.SliceQuery;
46import androidx.slice.widget.EventInfo;
47
48import android.support.v4.graphics.drawable.IconCompat;
49
50import com.android.settings.Utils;
51import com.android.settings.slices.SettingsSliceProvider;
52import com.android.settings.slices.SliceBuilderUtils;
53import com.android.settings.slices.SliceData;
54
55/**
56 * Testing utility class to verify the contents of the different Settings Slices.
57 *
58 * TODO (77712944) check Summary, range (metadata.getRange()), toggle icons.
59 */
60public class SliceTester {
61
62    /**
63     * Test the contents of an intent based slice, including:
64     * - No toggles
65     * - Correct intent
66     * - Correct title
67     * - Correct keywords
68     * - TTL
69     * - Color
70     */
71    public static void testSettingsIntentSlice(Context context, Slice slice, SliceData sliceData) {
72        final SliceMetadata metadata = SliceMetadata.from(context, slice);
73
74        final long sliceTTL = metadata.getExpiry();
75        assertThat(sliceTTL).isEqualTo(ListBuilder.INFINITY);
76
77        final SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR);
78        final int color = colorItem.getInt();
79        assertThat(color).isEqualTo(Utils.getColorAccent(context));
80
81        final List<SliceAction> toggles = metadata.getToggles();
82        assertThat(toggles).isEmpty();
83
84        final PendingIntent primaryPendingIntent = metadata.getPrimaryAction().getAction();
85        assertThat(primaryPendingIntent).isEqualTo(
86                SliceBuilderUtils.getContentPendingIntent(context, sliceData));
87
88        final List<SliceItem> sliceItems = slice.getItems();
89        assertTitle(sliceItems, sliceData.getTitle());
90
91        assertKeywords(metadata, sliceData);
92    }
93
94    /**
95     * Test the contents of an toggle based slice, including:
96     * - Contains one toggle
97     * - Correct toggle intent
98     * - Correct content intent
99     * - Correct title
100     * - Correct keywords
101     * - TTL
102     * - Color
103     */
104    public static void testSettingsToggleSlice(Context context, Slice slice, SliceData sliceData) {
105        final SliceMetadata metadata = SliceMetadata.from(context, slice);
106
107        final SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR);
108        final int color = colorItem.getInt();
109        assertThat(color).isEqualTo(Utils.getColorAccent(context));
110
111        final List<SliceAction> toggles = metadata.getToggles();
112        assertThat(toggles).hasSize(1);
113
114        final long sliceTTL = metadata.getExpiry();
115        assertThat(sliceTTL).isEqualTo(ListBuilder.INFINITY);
116
117        final SliceAction mainToggleAction = toggles.get(0);
118
119        final IconCompat expectedToggleIcon = IconCompat.createWithResource(context,
120                sliceData.getIconResource());
121        assertThat(mainToggleAction.getIcon()).isNull();
122
123        // Check intent in Toggle Action
124        final PendingIntent togglePendingIntent = mainToggleAction.getAction();
125        assertThat(togglePendingIntent).isEqualTo(SliceBuilderUtils.getActionIntent(context,
126                SettingsSliceProvider.ACTION_TOGGLE_CHANGED, sliceData));
127
128        // Check primary intent
129        final PendingIntent primaryPendingIntent = metadata.getPrimaryAction().getAction();
130        assertThat(primaryPendingIntent).isEqualTo(
131                SliceBuilderUtils.getContentPendingIntent(context, sliceData));
132
133        final List<SliceItem> sliceItems = slice.getItems();
134        assertTitle(sliceItems, sliceData.getTitle());
135
136        assertKeywords(metadata, sliceData);
137    }
138
139    /**
140     * Test the contents of an slider based slice, including:
141     * - No intent
142     * - Correct title
143     * - Correct keywords
144     * - TTL
145     * - Color
146     */
147    public static void testSettingsSliderSlice(Context context, Slice slice, SliceData sliceData) {
148        final SliceMetadata metadata = SliceMetadata.from(context, slice);
149
150        final SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR);
151        final int color = colorItem.getInt();
152        assertThat(color).isEqualTo(Utils.getColorAccent(context));
153
154        final SliceAction primaryAction = metadata.getPrimaryAction();
155
156        final IconCompat expectedIcon = IconCompat.createWithResource(context,
157                sliceData.getIconResource());
158        assertThat(expectedIcon.toString()).isEqualTo(primaryAction.getIcon().toString());
159
160        final long sliceTTL = metadata.getExpiry();
161        assertThat(sliceTTL).isEqualTo(ListBuilder.INFINITY);
162
163        final int headerType = metadata.getHeaderType();
164        assertThat(headerType).isEqualTo(EventInfo.ROW_TYPE_SLIDER);
165
166        // Check primary intent
167        final PendingIntent primaryPendingIntent = primaryAction.getAction();
168        assertThat(primaryPendingIntent).isEqualTo(
169                SliceBuilderUtils.getContentPendingIntent(context, sliceData));
170
171        final List<SliceItem> sliceItems = slice.getItems();
172        assertTitle(sliceItems, sliceData.getTitle());
173
174        assertKeywords(metadata, sliceData);
175    }
176
177    /**
178     * Test the contents of an unavailable slice, including:
179     * - No toggles
180     * - Correct title
181     * - Correct intent
182     * - Correct keywords
183     * - Color
184     * - TTL
185     */
186    public static void testSettingsUnavailableSlice(Context context, Slice slice,
187            SliceData sliceData) {
188        final SliceMetadata metadata = SliceMetadata.from(context, slice);
189
190        final long sliceTTL = metadata.getExpiry();
191        assertThat(sliceTTL).isEqualTo(ListBuilder.INFINITY);
192
193        final SliceItem colorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR);
194        final int color = colorItem.getInt();
195        assertThat(color).isEqualTo(Utils.getColorAccent(context));
196
197        final List<SliceAction> toggles = metadata.getToggles();
198        assertThat(toggles).isEmpty();
199
200        final PendingIntent primaryPendingIntent = metadata.getPrimaryAction().getAction();
201        assertThat(primaryPendingIntent).isEqualTo(SliceBuilderUtils.getContentPendingIntent(
202                context, sliceData));
203
204        final List<SliceItem> sliceItems = slice.getItems();
205        assertTitle(sliceItems, sliceData.getTitle());
206
207        assertKeywords(metadata, sliceData);
208    }
209
210    public static void assertTitle(List<SliceItem> sliceItems, String title) {
211        boolean hasTitle = false;
212        for (SliceItem item : sliceItems) {
213            List<SliceItem> titleItems = SliceQuery.findAll(item, FORMAT_TEXT, HINT_TITLE,
214                    null /* non-hints */);
215            if (titleItems == null) {
216                continue;
217            }
218
219            hasTitle = true;
220            for (SliceItem subTitleItem : titleItems) {
221                assertThat(subTitleItem.getText()).isEqualTo(title);
222            }
223        }
224        assertThat(hasTitle).isTrue();
225    }
226
227    private static void assertKeywords(SliceMetadata metadata, SliceData data) {
228        final List<String> keywords = metadata.getSliceKeywords();
229        final Set<String> expectedKeywords = Arrays.stream(data.getKeywords().split(","))
230                .map(s -> s = s.trim())
231                .collect(Collectors.toSet());
232        expectedKeywords.add(data.getTitle());
233        expectedKeywords.add(data.getScreenTitle().toString());
234        assertThat(keywords).containsExactlyElementsIn(expectedKeywords);
235    }
236}