1/*
2 * Copyright (C) 2016 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.selection;
18
19import static org.junit.Assert.assertFalse;
20import static org.junit.Assert.assertTrue;
21import static org.junit.Assert.fail;
22
23import android.support.test.filters.SmallTest;
24import android.support.test.runner.AndroidJUnit4;
25import android.support.v7.widget.RecyclerView;
26import android.view.MotionEvent;
27
28import com.android.documentsui.selection.testing.SelectionProbe;
29import com.android.documentsui.selection.testing.TestData;
30import com.android.documentsui.testing.SelectionHelpers;
31import com.android.documentsui.testing.TestEvents;
32
33import org.junit.Before;
34import org.junit.Test;
35import org.junit.runner.RunWith;
36
37import java.util.List;
38
39@RunWith(AndroidJUnit4.class)
40@SmallTest
41public class GestureSelectionHelperTest {
42
43    private static final List<String> ITEMS = TestData.create(100);
44    private static final MotionEvent DOWN = TestEvents.builder()
45            .action(MotionEvent.ACTION_DOWN)
46            .location(1, 1)
47            .build();
48
49    private static final MotionEvent MOVE = TestEvents.builder()
50            .action(MotionEvent.ACTION_MOVE)
51            .location(1, 1)
52            .build();
53
54    private static final MotionEvent UP = TestEvents.builder()
55            .action(MotionEvent.ACTION_UP)
56            .location(1, 1)
57            .build();
58
59    private GestureSelectionHelper mHelper;
60    private SelectionHelper mSelectionHelper;
61    private SelectionProbe mSelection;
62    private ContentLock mLock;
63    private TestItemDetailsLookup mItemLookup;
64    private TestViewDelegate mView;
65
66    @Before
67    public void setUp() {
68        mSelectionHelper = SelectionHelpers.createTestInstance(ITEMS);
69        mSelection = new SelectionProbe(mSelectionHelper);
70        mLock = new ContentLock();
71        mItemLookup = new TestItemDetailsLookup();
72        mItemLookup.initAt(3);
73        mView = new TestViewDelegate();
74        mHelper = new GestureSelectionHelper(mSelectionHelper, mView, mLock, mItemLookup);
75    }
76
77    @Test
78    public void testIgnoresDown_NoPosition() {
79        mView.mNextPosition = RecyclerView.NO_POSITION;
80        assertFalse(mHelper.onInterceptTouchEvent(null, DOWN));
81    }
82
83    @Test
84    public void testIgnoresDown_NoItemDetails() {
85        mItemLookup.reset();
86        assertFalse(mHelper.onInterceptTouchEvent(null, DOWN));
87    }
88
89    @Test
90    public void testNoStartOnIllegalPosition() {
91        mView.mNextPosition = -1;
92        mHelper.onInterceptTouchEvent(null, DOWN);
93        mHelper.start();
94        assertFalse(mLock.isLocked());
95    }
96
97    @Test
98    public void testClaimsDownOnItem() {
99        mView.mNextPosition = 0;
100        assertTrue(mHelper.onInterceptTouchEvent(null, DOWN));
101    }
102
103    @Test
104    public void testClaimsMoveIfStarted() {
105        mView.mNextPosition = 0;
106        assertTrue(mHelper.onInterceptTouchEvent(null, DOWN));
107
108        // Normally, this is controller by the TouchSelectionHelper via a a long press gesture.
109        mSelectionHelper.select("1");
110        mSelectionHelper.anchorRange(1);
111        mHelper.start();
112        assertTrue(mHelper.onInterceptTouchEvent(null, MOVE));
113    }
114
115    @Test
116    public void testCreatesRangeSelection() {
117        mView.mNextPosition = 1;
118        mHelper.onInterceptTouchEvent(null, DOWN);
119        // Another way we are implicitly coupled to TouchInputHandler, is that we depend on
120        // long press to establish the initial anchor point. Without that we'll get an
121        // error when we try to extend the range.
122
123        mSelectionHelper.select("1");
124        mSelectionHelper.anchorRange(1);
125        mHelper.start();
126
127        mHelper.onTouchEvent(null, MOVE);
128
129        mView.mNextPosition = 9;
130        mHelper.onTouchEvent(null, MOVE);
131        mHelper.onTouchEvent(null, UP);
132
133        mSelection.assertRangeSelected(1,  9);
134    }
135
136    private static final class TestViewDelegate extends GestureSelectionHelper.ViewDelegate {
137
138        private int mNextPosition = RecyclerView.NO_POSITION;
139
140        @Override
141        int getHeight() {
142            return 1000;
143        }
144
145        @Override
146        int getItemUnder(MotionEvent e) {
147            return mNextPosition;
148        }
149
150        @Override
151        int getLastGlidedItemPosition(MotionEvent e) {
152            return mNextPosition;
153        }
154    }
155}
156