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 17 package androidx.recyclerview.selection; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertNotNull; 21 import static org.junit.Assert.assertNull; 22 23 import android.graphics.Point; 24 25 import androidx.recyclerview.selection.ViewAutoScroller.ScrollHost; 26 import androidx.test.ext.junit.runners.AndroidJUnit4; 27 import androidx.test.filters.SmallTest; 28 29 import org.jspecify.annotations.Nullable; 30 import org.junit.Before; 31 import org.junit.Test; 32 import org.junit.runner.RunWith; 33 34 @RunWith(AndroidJUnit4.class) 35 @SmallTest 36 public final class ViewAutoScrollerTest { 37 38 private static final float SCROLL_THRESHOLD_RATIO = 0.125f; 39 private static final int VIEW_HEIGHT = 100; 40 private static final int TOP_Y_POINT = (int) (VIEW_HEIGHT * SCROLL_THRESHOLD_RATIO) - 1; 41 private static final int BOTTOM_Y_POINT = 42 VIEW_HEIGHT - (int) (VIEW_HEIGHT * SCROLL_THRESHOLD_RATIO) + 1; 43 44 private ViewAutoScroller mScroller; 45 private TestHost mHost; 46 47 @Before setUp()48 public void setUp() { 49 mHost = new TestHost(); 50 mScroller = new ViewAutoScroller(mHost, SCROLL_THRESHOLD_RATIO); 51 } 52 53 @Test testNoScrollWhenOutOfScrollZone()54 public void testNoScrollWhenOutOfScrollZone() { 55 mScroller.scroll(new Point(0, VIEW_HEIGHT / 2)); 56 mHost.run(); 57 mHost.assertNotScrolled(); 58 } 59 60 // @Test 61 // public void testNoScrollWhenDisabled() { 62 // mScroller.reset(); 63 // mScroller.scroll(mEvent.location(0, TOP_Y_POINT).build()); 64 // mHost.assertNotScrolled(); 65 // } 66 67 @Test testMotionThreshold()68 public void testMotionThreshold() { 69 mScroller.scroll(new Point(0, TOP_Y_POINT)); 70 mHost.run(); 71 72 mScroller.scroll(new Point(0, TOP_Y_POINT - 1)); 73 mHost.run(); 74 75 mHost.assertNotScrolled(); 76 } 77 78 @Test testMotionThreshold_Resets()79 public void testMotionThreshold_Resets() { 80 int expectedScrollDistance = mScroller.computeScrollDistance(-21); 81 mScroller.scroll(new Point(0, TOP_Y_POINT)); 82 mHost.run(); 83 // We need enough y motion to overcome motion threshold 84 mScroller.scroll(new Point(0, TOP_Y_POINT - 20)); 85 mHost.run(); 86 87 mHost.reset(); 88 // After resetting events should be required to cross the motion threshold 89 // before auto-scrolling again. 90 mScroller.reset(); 91 92 mScroller.scroll(new Point(0, TOP_Y_POINT)); 93 mHost.run(); 94 95 mHost.assertNotScrolled(); 96 } 97 98 @Test testAutoScrolls_Top()99 public void testAutoScrolls_Top() { 100 int expectedScrollDistance = mScroller.computeScrollDistance(-21); 101 mScroller.scroll(new Point(0, TOP_Y_POINT)); 102 mHost.run(); 103 // We need enough y motion to overcome motion threshold 104 mScroller.scroll(new Point(0, TOP_Y_POINT - 20)); 105 mHost.run(); 106 107 mHost.assertScrolledBy(expectedScrollDistance); 108 } 109 110 @Test testAutoScrolls_Bottom()111 public void testAutoScrolls_Bottom() { 112 int expectedScrollDistance = mScroller.computeScrollDistance(21); 113 mScroller.scroll(new Point(0, BOTTOM_Y_POINT)); 114 mHost.run(); 115 // We need enough y motion to overcome motion threshold 116 mScroller.scroll(new Point(0, BOTTOM_Y_POINT + 20)); 117 mHost.run(); 118 119 mHost.assertScrolledBy(expectedScrollDistance); 120 } 121 122 private final class TestHost extends ScrollHost { 123 124 private @Nullable Integer mScrollDistance; 125 private @Nullable Runnable mRunnable; 126 127 @Override getViewHeight()128 int getViewHeight() { 129 return VIEW_HEIGHT; 130 } 131 132 @Override scrollBy(int distance)133 void scrollBy(int distance) { 134 mScrollDistance = distance; 135 } 136 137 @Override runAtNextFrame(Runnable r)138 void runAtNextFrame(Runnable r) { 139 mRunnable = r; 140 } 141 142 @Override removeCallback(Runnable r)143 void removeCallback(Runnable r) { 144 } 145 reset()146 private void reset() { 147 mScrollDistance = null; 148 mRunnable = null; 149 } 150 run()151 private void run() { 152 mRunnable.run(); 153 } 154 assertNotScrolled()155 private void assertNotScrolled() { 156 assertNull(mScrollDistance); 157 } 158 assertScrolledBy(int expectedDistance)159 private void assertScrolledBy(int expectedDistance) { 160 assertNotNull(mScrollDistance); 161 assertEquals(expectedDistance, mScrollDistance.intValue()); 162 } 163 } 164 } 165