• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.documentsui.selection;
18 import static org.junit.Assert.assertFalse;
19 
20 import android.support.test.filters.SmallTest;
21 import android.support.test.runner.AndroidJUnit4;
22 import android.util.SparseBooleanArray;
23 
24 import com.android.documentsui.selection.SelectionHelper.SelectionPredicate;
25 import com.android.documentsui.selection.testing.SelectionProbe;
26 import com.android.documentsui.selection.testing.TestAdapter;
27 import com.android.documentsui.selection.testing.TestSelectionObserver;
28 import com.android.documentsui.selection.testing.TestStableIdProvider;
29 
30 import org.junit.Before;
31 import org.junit.Test;
32 import org.junit.runner.RunWith;
33 
34 import java.util.ArrayList;
35 import java.util.HashSet;
36 import java.util.List;
37 import java.util.Set;
38 
39 @RunWith(AndroidJUnit4.class)
40 @SmallTest
41 public class DefaultSelectionHelperTest {
42 
43     private List<String> mItems;
44     private Set<String> mIgnored;
45     private TestAdapter mAdapter;
46     private DefaultSelectionHelper mHelper;
47     private TestSelectionObserver mListener;
48     private SelectionProbe mSelection;
49 
50     @Before
setUp()51     public void setUp() throws Exception {
52         mIgnored = new HashSet<>();
53         mItems = TestAdapter.createItemList(100);
54         mListener = new TestSelectionObserver();
55         mAdapter = new TestAdapter();
56         mAdapter.updateTestModelIds(mItems);
57 
58         SelectionPredicate canSelect = new SelectionPredicate() {
59 
60             @Override
61             public boolean canSetStateForId(String id, boolean nextState) {
62                 return !nextState || !mIgnored.contains(id);
63             }
64 
65             @Override
66             public boolean canSetStateAtPosition(int position, boolean nextState) {
67                 throw new UnsupportedOperationException("Not implemented.");
68             }
69         };
70         mHelper = new DefaultSelectionHelper(
71                 DefaultSelectionHelper.MODE_MULTIPLE,
72                 mAdapter,
73                 new TestStableIdProvider(mAdapter),
74                 canSelect);
75 
76         mHelper.addObserver(mListener);
77 
78         mSelection = new SelectionProbe(mHelper, mListener);
79 
80         mIgnored.clear();
81     }
82 
83     @Test
testSelect()84     public void testSelect() {
85         mHelper.select(mItems.get(7));
86 
87         mSelection.assertSelection(7);
88     }
89 
90     @Test
testDeselect()91     public void testDeselect() {
92         mHelper.select(mItems.get(7));
93         mHelper.deselect(mItems.get(7));
94 
95         mSelection.assertNoSelection();
96     }
97 
98     @Test
testSelection_DoNothingOnUnselectableItem()99     public void testSelection_DoNothingOnUnselectableItem() {
100         mIgnored.add(mItems.get(7));
101         boolean selected = mHelper.select(mItems.get(7));
102 
103         assertFalse(selected);
104         mSelection.assertNoSelection();
105     }
106 
107     @Test
testSelect_NotifiesListenersOfChange()108     public void testSelect_NotifiesListenersOfChange() {
109         mHelper.select(mItems.get(7));
110 
111         mListener.assertSelectionChanged();
112     }
113 
114     @Test
testSelect_NotifiesAdapterOfSelect()115     public void testSelect_NotifiesAdapterOfSelect() {
116         mHelper.select(mItems.get(7));
117 
118         mAdapter.assertNotifiedOfSelectionChange(7);
119     }
120 
121     @Test
testSelect_NotifiesAdapterOfDeselect()122     public void testSelect_NotifiesAdapterOfDeselect() {
123         mHelper.select(mItems.get(7));
124         mAdapter.resetSelectionNotifications();
125         mHelper.deselect(mItems.get(7));
126         mAdapter.assertNotifiedOfSelectionChange(7);
127     }
128 
129     @Test
testDeselect_NotifiesSelectionChanged()130     public void testDeselect_NotifiesSelectionChanged() {
131         mHelper.select(mItems.get(7));
132         mHelper.deselect(mItems.get(7));
133 
134         mListener.assertSelectionChanged();
135     }
136 
137     @Test
testSelection_PersistsOnUpdate()138     public void testSelection_PersistsOnUpdate() {
139         mHelper.select(mItems.get(7));
140         mAdapter.updateTestModelIds(mItems);
141 
142         mSelection.assertSelection(7);
143     }
144 
145     @Test
testSelection_IntersectsWithNewDataSet()146     public void testSelection_IntersectsWithNewDataSet() {
147         mHelper.select(mItems.get(99));
148         mHelper.select(mItems.get(7));
149 
150         mAdapter.updateTestModelIds(TestAdapter.createItemList(50));
151 
152         mSelection.assertSelection(7);
153     }
154 
155     @Test
testSetItemsSelected()156     public void testSetItemsSelected() {
157         mHelper.setItemsSelected(getStringIds(6, 7, 8), true);
158 
159         mSelection.assertRangeSelected(6, 8);
160     }
161 
162     @Test
testSetItemsSelected_SkipUnselectableItem()163     public void testSetItemsSelected_SkipUnselectableItem() {
164         mIgnored.add(mItems.get(7));
165 
166         mHelper.setItemsSelected(getStringIds(6, 7, 8), true);
167 
168         mSelection.assertSelected(6);
169         mSelection.assertNotSelected(7);
170         mSelection.assertSelected(8);
171     }
172 
173     @Test
testRangeSelection()174     public void testRangeSelection() {
175         mHelper.startRange(15);
176         mHelper.extendRange(19);
177         mSelection.assertRangeSelection(15, 19);
178     }
179 
180     @Test
testRangeSelection_SkipUnselectableItem()181     public void testRangeSelection_SkipUnselectableItem() {
182         mIgnored.add(mItems.get(17));
183 
184         mHelper.startRange(15);
185         mHelper.extendRange(19);
186 
187         mSelection.assertRangeSelected(15, 16);
188         mSelection.assertNotSelected(17);
189         mSelection.assertRangeSelected(18, 19);
190     }
191 
192     @Test
testRangeSelection_snapExpand()193     public void testRangeSelection_snapExpand() {
194         mHelper.startRange(15);
195         mHelper.extendRange(19);
196         mHelper.extendRange(27);
197         mSelection.assertRangeSelection(15, 27);
198     }
199 
200     @Test
testRangeSelection_snapContract()201     public void testRangeSelection_snapContract() {
202         mHelper.startRange(15);
203         mHelper.extendRange(27);
204         mHelper.extendRange(19);
205         mSelection.assertRangeSelection(15, 19);
206     }
207 
208     @Test
testRangeSelection_snapInvert()209     public void testRangeSelection_snapInvert() {
210         mHelper.startRange(15);
211         mHelper.extendRange(27);
212         mHelper.extendRange(3);
213         mSelection.assertRangeSelection(3, 15);
214     }
215 
216     @Test
testRangeSelection_multiple()217     public void testRangeSelection_multiple() {
218         mHelper.startRange(15);
219         mHelper.extendRange(27);
220         mHelper.endRange();
221         mHelper.startRange(42);
222         mHelper.extendRange(57);
223         mSelection.assertSelectionSize(29);
224         mSelection.assertRangeSelected(15, 27);
225         mSelection.assertRangeSelected(42, 57);
226     }
227 
228     @Test
testProvisionalRangeSelection()229     public void testProvisionalRangeSelection() {
230         mHelper.startRange(13);
231         mHelper.extendProvisionalRange(15);
232         mSelection.assertRangeSelection(13, 15);
233         mHelper.getSelection().mergeProvisionalSelection();
234         mHelper.endRange();
235         mSelection.assertSelectionSize(3);
236     }
237 
238     @Test
testProvisionalRangeSelection_endEarly()239     public void testProvisionalRangeSelection_endEarly() {
240         mHelper.startRange(13);
241         mHelper.extendProvisionalRange(15);
242         mSelection.assertRangeSelection(13, 15);
243 
244         mHelper.endRange();
245         // If we end range selection prematurely for provision selection, nothing should be selected
246         // except the first item
247         mSelection.assertSelectionSize(1);
248     }
249 
250     @Test
testProvisionalRangeSelection_snapExpand()251     public void testProvisionalRangeSelection_snapExpand() {
252         mHelper.startRange(13);
253         mHelper.extendProvisionalRange(15);
254         mSelection.assertRangeSelection(13, 15);
255         mHelper.getSelection().mergeProvisionalSelection();
256         mHelper.extendRange(18);
257         mSelection.assertRangeSelection(13, 18);
258     }
259 
260     @Test
testCombinationRangeSelection_IntersectsOldSelection()261     public void testCombinationRangeSelection_IntersectsOldSelection() {
262         mHelper.startRange(13);
263         mHelper.extendRange(15);
264         mSelection.assertRangeSelection(13, 15);
265 
266         mHelper.startRange(11);
267         mHelper.extendProvisionalRange(18);
268         mSelection.assertRangeSelected(11, 18);
269         mHelper.endRange();
270         mSelection.assertRangeSelected(13, 15);
271         mSelection.assertRangeSelected(11, 11);
272         mSelection.assertSelectionSize(4);
273     }
274 
275     @Test
testProvisionalSelection()276     public void testProvisionalSelection() {
277         Selection s = mHelper.getSelection();
278         mSelection.assertNoSelection();
279 
280         // Mimicking band selection case -- BandController notifies item callback by itself.
281         mListener.onItemStateChanged(mItems.get(1), true);
282         mListener.onItemStateChanged(mItems.get(2), true);
283 
284         SparseBooleanArray provisional = new SparseBooleanArray();
285         provisional.append(1, true);
286         provisional.append(2, true);
287         s.setProvisionalSelection(getItemIds(provisional));
288         mSelection.assertSelection(1, 2);
289     }
290 
291     @Test
testProvisionalSelection_Replace()292     public void testProvisionalSelection_Replace() {
293         Selection s = mHelper.getSelection();
294 
295         // Mimicking band selection case -- BandController notifies item callback by itself.
296         mListener.onItemStateChanged(mItems.get(1), true);
297         mListener.onItemStateChanged(mItems.get(2), true);
298         SparseBooleanArray provisional = new SparseBooleanArray();
299         provisional.append(1, true);
300         provisional.append(2, true);
301         s.setProvisionalSelection(getItemIds(provisional));
302 
303         mListener.onItemStateChanged(mItems.get(1), false);
304         mListener.onItemStateChanged(mItems.get(2), false);
305         provisional.clear();
306 
307         mListener.onItemStateChanged(mItems.get(3), true);
308         mListener.onItemStateChanged(mItems.get(4), true);
309         provisional.append(3, true);
310         provisional.append(4, true);
311         s.setProvisionalSelection(getItemIds(provisional));
312         mSelection.assertSelection(3, 4);
313     }
314 
315     @Test
testProvisionalSelection_IntersectsExistingProvisionalSelection()316     public void testProvisionalSelection_IntersectsExistingProvisionalSelection() {
317         Selection s = mHelper.getSelection();
318 
319         // Mimicking band selection case -- BandController notifies item callback by itself.
320         mListener.onItemStateChanged(mItems.get(1), true);
321         mListener.onItemStateChanged(mItems.get(2), true);
322         SparseBooleanArray provisional = new SparseBooleanArray();
323         provisional.append(1, true);
324         provisional.append(2, true);
325         s.setProvisionalSelection(getItemIds(provisional));
326 
327         mListener.onItemStateChanged(mItems.get(1), false);
328         mListener.onItemStateChanged(mItems.get(2), false);
329         provisional.clear();
330 
331         mListener.onItemStateChanged(mItems.get(1), true);
332         provisional.append(1, true);
333         s.setProvisionalSelection(getItemIds(provisional));
334         mSelection.assertSelection(1);
335     }
336 
337     @Test
testProvisionalSelection_Apply()338     public void testProvisionalSelection_Apply() {
339         Selection s = mHelper.getSelection();
340 
341         // Mimicking band selection case -- BandController notifies item callback by itself.
342         mListener.onItemStateChanged(mItems.get(1), true);
343         mListener.onItemStateChanged(mItems.get(2), true);
344         SparseBooleanArray provisional = new SparseBooleanArray();
345         provisional.append(1, true);
346         provisional.append(2, true);
347         s.setProvisionalSelection(getItemIds(provisional));
348         s.mergeProvisionalSelection();
349 
350         mSelection.assertSelection(1, 2);
351     }
352 
353     @Test
testProvisionalSelection_Cancel()354     public void testProvisionalSelection_Cancel() {
355         mHelper.select(mItems.get(1));
356         mHelper.select(mItems.get(2));
357         Selection s = mHelper.getSelection();
358 
359         SparseBooleanArray provisional = new SparseBooleanArray();
360         provisional.append(3, true);
361         provisional.append(4, true);
362         s.setProvisionalSelection(getItemIds(provisional));
363         s.clearProvisionalSelection();
364 
365         // Original selection should remain.
366         mSelection.assertSelection(1, 2);
367     }
368 
369     @Test
testProvisionalSelection_IntersectsAppliedSelection()370     public void testProvisionalSelection_IntersectsAppliedSelection() {
371         mHelper.select(mItems.get(1));
372         mHelper.select(mItems.get(2));
373         Selection s = mHelper.getSelection();
374 
375         // Mimicking band selection case -- BandController notifies item callback by itself.
376         mListener.onItemStateChanged(mItems.get(3), true);
377         SparseBooleanArray provisional = new SparseBooleanArray();
378         provisional.append(2, true);
379         provisional.append(3, true);
380         s.setProvisionalSelection(getItemIds(provisional));
381         mSelection.assertSelection(1, 2, 3);
382     }
383 
384     @Test
testObserverOnChanged_NotifiesListenersOfChange()385     public void testObserverOnChanged_NotifiesListenersOfChange() {
386         mAdapter.notifyDataSetChanged();
387 
388         mListener.assertSelectionChanged();
389     }
390 
getItemIds(SparseBooleanArray selection)391     private Set<String> getItemIds(SparseBooleanArray selection) {
392         Set<String> ids = new HashSet<>();
393 
394         int count = selection.size();
395         for (int i = 0; i < count; ++i) {
396             ids.add(mItems.get(selection.keyAt(i)));
397         }
398 
399         return ids;
400     }
401 
getStringIds(int... ids)402     private Iterable<String> getStringIds(int... ids) {
403         List<String> stringIds = new ArrayList<>(ids.length);
404         for (int id : ids) {
405             stringIds.add(mItems.get(id));
406         }
407         return stringIds;
408     }
409 }
410