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