MultiSelectManagerTest.java revision 743c7c2f0f57b4cef7cc11154b2e804a7eb33177
1/*
2 * Copyright (C) 2015 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.documentsui.dirlist;
18
19import android.support.v7.widget.RecyclerView;
20import android.test.AndroidTestCase;
21import android.test.suitebuilder.annotation.SmallTest;
22import android.util.SparseBooleanArray;
23
24import com.android.documentsui.TestInputEvent;
25import com.android.documentsui.dirlist.MultiSelectManager.Selection;
26import com.google.common.collect.Lists;
27
28import java.util.ArrayList;
29import java.util.HashSet;
30import java.util.List;
31import java.util.Set;
32
33@SmallTest
34public class MultiSelectManagerTest extends AndroidTestCase {
35
36    private static final List<String> items;
37    static {
38        items = new ArrayList<String>();
39        for (int i = 0; i < 100; ++i) {
40            items.add(Integer.toString(i));
41        }
42    }
43
44    private MultiSelectManager mManager;
45    private TestCallback mCallback;
46    private TestSelectionEnvironment mEnv;
47
48    public void setUp() throws Exception {
49        mCallback = new TestCallback();
50        mEnv = new TestSelectionEnvironment(items);
51        mManager = new MultiSelectManager(mEnv, MultiSelectManager.MODE_MULTIPLE);
52        mManager.addCallback(mCallback);
53    }
54
55    public void testMouseClick_StartsSelectionMode() {
56        click(7);
57        assertSelection(items.get(7));
58    }
59
60    public void testMouseClick_NotifiesSelectionChanged() {
61        click(7);
62        mCallback.assertSelectionChanged();
63    }
64
65    public void testMouseClick_ShiftClickExtendsSelection() {
66        longPress(7);
67        shiftClick(11);
68        assertRangeSelection(7, 11);
69    }
70
71    public void testMouseClick_NoPosition_ClearsSelection() {
72        longPress(7);
73        click(11);
74        click(RecyclerView.NO_POSITION);
75        assertSelection();
76    }
77
78    public void testSetSelectionFocusBegin() {
79        mManager.setItemsSelected(Lists.newArrayList(items.get(7)), true);
80        mManager.setSelectionRangeBegin(7);
81        shiftClick(11);
82        assertRangeSelection(7, 11);
83    }
84
85    public void testLongPress_StartsSelectionMode() {
86        longPress(7);
87        assertSelection(items.get(7));
88    }
89
90    public void testLongPress_SecondPressExtendsSelection() {
91        longPress(7);
92        longPress(99);
93        assertSelection(items.get(7), items.get(99));
94    }
95
96    public void testSingleTapUp_UnselectsSelectedItem() {
97        longPress(7);
98        tap(7);
99        assertSelection();
100    }
101
102    public void testSingleTapUp_NoPosition_ClearsSelection() {
103        longPress(7);
104        tap(11);
105        tap(RecyclerView.NO_POSITION);
106        assertSelection();
107    }
108
109    public void testSingleTapUp_ExtendsSelection() {
110        longPress(99);
111        tap(7);
112        tap(13);
113        assertSelection(items.get(7), items.get(99), items.get(13));
114    }
115
116    public void testSingleTapUp_ShiftCreatesRangeSelection() {
117        longPress(7);
118        shiftTap(17);
119        assertRangeSelection(7, 17);
120    }
121
122    public void testSingleTapUp_ShiftCreatesRangeSeletion_Backwards() {
123        longPress(17);
124        shiftTap(7);
125        assertRangeSelection(7, 17);
126    }
127
128    public void testSingleTapUp_SecondShiftClickExtendsSelection() {
129        longPress(7);
130        shiftTap(11);
131        shiftTap(17);
132        assertRangeSelection(7, 17);
133    }
134
135    public void testSingleTapUp_MultipleContiguousRangesSelected() {
136        longPress(7);
137        shiftTap(11);
138        tap(20);
139        shiftTap(25);
140        assertRangeSelected(7, 11);
141        assertRangeSelected(20, 25);
142        assertSelectionSize(11);
143    }
144
145    public void testSingleTapUp_ShiftReducesSelectionRange_FromPreviousShiftClick() {
146        longPress(7);
147        shiftTap(17);
148        shiftTap(10);
149        assertRangeSelection(7, 10);
150    }
151
152    public void testSingleTapUp_ShiftReducesSelectionRange_FromPreviousShiftClick_Backwards() {
153        mManager.onLongPress(TestInputEvent.tap(17));
154        shiftTap(7);
155        shiftTap(14);
156        assertRangeSelection(14, 17);
157    }
158
159    public void testSingleTapUp_ShiftReversesSelectionDirection() {
160        longPress(7);
161        shiftTap(17);
162        shiftTap(0);
163        assertRangeSelection(0, 7);
164    }
165
166    public void testSingleSelectMode() {
167        mManager = new MultiSelectManager(mEnv, MultiSelectManager.MODE_SINGLE);
168        mManager.addCallback(mCallback);
169        longPress(20);
170        tap(13);
171        assertSelection(items.get(13));
172    }
173
174    public void testSingleSelectMode_ShiftTap() {
175        mManager = new MultiSelectManager(mEnv, MultiSelectManager.MODE_SINGLE);
176        mManager.addCallback(mCallback);
177        longPress(13);
178        shiftTap(20);
179        assertSelection(items.get(20));
180    }
181
182    public void testSingleSelectMode_ShiftDoesNotExtendSelection() {
183        mManager = new MultiSelectManager(mEnv, MultiSelectManager.MODE_SINGLE);
184        mManager.addCallback(mCallback);
185        longPress(20);
186        keyToPosition(22, true);
187        assertSelection(items.get(22));
188    }
189
190    public void testProvisionalSelection() {
191        Selection s = mManager.getSelection();
192        assertSelection();
193
194        SparseBooleanArray provisional = new SparseBooleanArray();
195        provisional.append(1, true);
196        provisional.append(2, true);
197        s.setProvisionalSelection(getItemIds(provisional));
198        assertSelection(items.get(1), items.get(2));
199
200        provisional.delete(1);
201        provisional.append(3, true);
202        s.setProvisionalSelection(getItemIds(provisional));
203        assertSelection(items.get(2), items.get(3));
204
205        s.applyProvisionalSelection();
206        assertSelection(items.get(2), items.get(3));
207
208        provisional.clear();
209        provisional.append(3, true);
210        provisional.append(4, true);
211        s.setProvisionalSelection(getItemIds(provisional));
212        assertSelection(items.get(2), items.get(3), items.get(4));
213
214        provisional.delete(3);
215        s.setProvisionalSelection(getItemIds(provisional));
216        assertSelection(items.get(2), items.get(3), items.get(4));
217    }
218
219    private static Set<String> getItemIds(SparseBooleanArray selection) {
220        Set<String> ids = new HashSet<>();
221
222        int count = selection.size();
223        for (int i = 0; i < count; ++i) {
224            ids.add(items.get(selection.keyAt(i)));
225        }
226
227        return ids;
228    }
229
230    private void longPress(int position) {
231        mManager.onLongPress(TestInputEvent.tap(position));
232    }
233
234    private void tap(int position) {
235        mManager.onSingleTapUp(TestInputEvent.tap(position));
236    }
237
238    private void shiftTap(int position) {
239        mManager.onSingleTapUp(TestInputEvent.shiftTap(position));
240    }
241
242    private void click(int position) {
243        mManager.onSingleTapUp(TestInputEvent.click(position));
244    }
245
246    private void shiftClick(int position) {
247        mManager.onSingleTapUp(TestInputEvent.shiftClick(position));
248    }
249
250    private void keyToPosition(int position, boolean shift) {
251        mManager.attemptChangeFocus(position, shift);
252    }
253
254    private void assertSelected(String... expected) {
255        for (int i = 0; i < expected.length; i++) {
256            Selection selection = mManager.getSelection();
257            String err = String.format(
258                    "Selection %s does not contain %s", selection, expected[i]);
259            assertTrue(err, selection.contains(expected[i]));
260        }
261    }
262
263    private void assertSelection(String... expected) {
264        assertSelectionSize(expected.length);
265        assertSelected(expected);
266    }
267
268    private void assertRangeSelected(int begin, int end) {
269        for (int i = begin; i <= end; i++) {
270            assertSelected(items.get(i));
271        }
272    }
273
274    private void assertRangeSelection(int begin, int end) {
275        assertSelectionSize(end - begin + 1);
276        assertRangeSelected(begin, end);
277    }
278
279    private void assertSelectionSize(int expected) {
280        Selection selection = mManager.getSelection();
281        assertEquals(selection.toString(), expected, selection.size());
282    }
283
284    private static final class TestCallback implements MultiSelectManager.Callback {
285
286        Set<String> ignored = new HashSet<>();
287        private boolean mSelectionChanged = false;
288
289        @Override
290        public void onItemStateChanged(String modelId, boolean selected) {}
291
292        @Override
293        public boolean onBeforeItemStateChange(String modelId, boolean selected) {
294            return !ignored.contains(modelId);
295        }
296
297        @Override
298        public void onSelectionChanged() {
299            mSelectionChanged = true;
300        }
301
302        void assertSelectionChanged() {
303            assertTrue(mSelectionChanged);
304        }
305    }
306}
307