DragScrollListener test, from ag/1247908.
Change-Id: Ifd550281094fd12395333ae2071742d5893cd9f7
diff --git a/src/com/android/documentsui/dirlist/DirectoryFragment.java b/src/com/android/documentsui/dirlist/DirectoryFragment.java
index db19881..e6e1048 100644
--- a/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -215,8 +215,9 @@
mRecView.setItemAnimator(new DirectoryItemAnimator(getActivity()));
+ final int edgeHeight = (int) getResources().getDimension(R.dimen.autoscroll_edge_height);
mOnDragListener = DragScrollListener.create(
- getActivity(), new DirectoryDragListener(this), mRecView);
+ edgeHeight, new DirectoryDragListener(this), mRecView);
// Make the recycler and the empty views responsive to drop events.
mRecView.setOnDragListener(mOnDragListener);
diff --git a/src/com/android/documentsui/dirlist/DragScrollListener.java b/src/com/android/documentsui/dirlist/DragScrollListener.java
index 898a4a2..4518033 100644
--- a/src/com/android/documentsui/dirlist/DragScrollListener.java
+++ b/src/com/android/documentsui/dirlist/DragScrollListener.java
@@ -16,8 +16,8 @@
package com.android.documentsui.dirlist;
-import android.content.Context;
import android.graphics.Point;
+import android.support.annotation.VisibleForTesting;
import android.view.DragEvent;
import android.view.View;
import android.view.View.OnDragListener;
@@ -26,7 +26,6 @@
import com.android.documentsui.ItemDragListener.DragHost;
import com.android.documentsui.dirlist.ViewAutoScroller.ScrollActionDelegate;
import com.android.documentsui.dirlist.ViewAutoScroller.ScrollDistanceDelegate;
-import com.android.documentsui.R;
import java.util.function.BooleanSupplier;
import java.util.function.IntSupplier;
@@ -49,16 +48,16 @@
private boolean mDragHappening;
private @Nullable Point mCurrentPosition;
- private DragScrollListener(
- Context context,
+ @VisibleForTesting
+ DragScrollListener(
+ int autoScrollEdgeHeight,
ItemDragListener<? extends DragHost> dragHandler,
IntSupplier heightSupplier,
BooleanSupplier scrollUpSupplier,
BooleanSupplier scrollDownSupplier,
ViewAutoScroller.ScrollActionDelegate actionDelegate) {
mDragHandler = dragHandler;
- mAutoScrollEdgeHeight = (int) context.getResources()
- .getDimension(R.dimen.autoscroll_edge_height);
+ mAutoScrollEdgeHeight = autoScrollEdgeHeight;
mHeight = heightSupplier;
mCanScrollUp = scrollUpSupplier;
mCanScrollDown = scrollDownSupplier;
@@ -85,7 +84,9 @@
}
static DragScrollListener create(
- Context context, ItemDragListener<? extends DragHost> dragHandler, View scrollView) {
+ int autoScrollEdgeHeight,
+ ItemDragListener<? extends DragHost> dragHandler,
+ View scrollView) {
ScrollActionDelegate actionDelegate = new ScrollActionDelegate() {
@Override
public void scrollBy(int dy) {
@@ -104,7 +105,7 @@
}
};
DragScrollListener listener = new DragScrollListener(
- context,
+ autoScrollEdgeHeight,
dragHandler,
scrollView::getHeight,
() -> {
diff --git a/tests/src/com/android/documentsui/dirlist/DragScrollListenerTest.java b/tests/src/com/android/documentsui/dirlist/DragScrollListenerTest.java
new file mode 100644
index 0000000..edc5537
--- /dev/null
+++ b/tests/src/com/android/documentsui/dirlist/DragScrollListenerTest.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.dirlist;
+
+import static org.junit.Assert.assertTrue;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.DragEvent;
+import android.view.View;
+
+import com.android.documentsui.ItemDragListener;
+import com.android.documentsui.dirlist.ViewAutoScroller.ScrollActionDelegate;
+import com.android.documentsui.testing.DragEvents;
+import com.android.documentsui.testing.TestTimer;
+import com.android.documentsui.testing.Views;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Timer;
+import java.util.function.IntConsumer;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DragScrollListenerTest {
+
+ private static final int VIEW_HEIGHT = 100;
+ private static final int EDGE_HEIGHT = 10;
+
+ private View mTestView;
+ private TestDragHost mTestDragHost;
+ private TestTimer mTestTimer;
+ private TestDragHandler mDragHandler;
+ private TestScrollActionDelegate mActionDelegate = new TestScrollActionDelegate();
+ private DragScrollListener mListener;
+ private boolean mCanScrollUp;
+ private boolean mCanScrollDown;
+
+ @Before
+ public void setUp() {
+ mTestView = Views.createTestView(0, 0);
+ mTestTimer = new TestTimer();
+ mTestDragHost = new TestDragHost();
+ mDragHandler = new TestDragHandler(mTestDragHost, mTestTimer);
+ mListener = new DragScrollListener(
+ EDGE_HEIGHT,
+ mDragHandler,
+ () -> {
+ return VIEW_HEIGHT;
+ },
+ () -> {
+ return mCanScrollUp;
+ },
+ () -> {
+ return mCanScrollDown;
+ },
+ mActionDelegate);
+ mCanScrollUp = true;
+ mCanScrollDown = true;
+ }
+
+ @Test
+ public void testDragEvent_DelegateToHandler() {
+ triggerDragEvent(DragEvent.ACTION_DRAG_STARTED);
+ assertTrue(mDragHandler.mLastDropEvent.getAction() == DragEvent.ACTION_DRAG_STARTED);
+
+ triggerDragEvent(DragEvent.ACTION_DROP);
+ assertTrue(mDragHandler.mLastDropEvent.getAction() == DragEvent.ACTION_DROP);
+
+ triggerDragEvent(DragEvent.ACTION_DRAG_ENDED);
+ assertTrue(mDragHandler.mLastDropEvent.getAction() == DragEvent.ACTION_DRAG_ENDED);
+
+ triggerDragEvent(DragEvent.ACTION_DRAG_EXITED);
+ assertTrue(mDragHandler.mLastDropEvent.getAction() == DragEvent.ACTION_DRAG_EXITED);
+ }
+
+ @Test
+ public void testDragLocationEvent_DelegateToHandler() {
+ triggerDragEvent(DragEvent.ACTION_DRAG_STARTED);
+
+ // Not in hotspot
+ triggerDragLocationEvent(0, 50);
+ assertTrue(mDragHandler.mLastDropEvent.getAction() == DragEvent.ACTION_DRAG_LOCATION);
+
+ // Can't scroll up
+ mCanScrollUp = false;
+ mCanScrollDown = true;
+ triggerDragLocationEvent(0, 5);
+ assertTrue(mDragHandler.mLastDropEvent.getAction() == DragEvent.ACTION_DRAG_LOCATION);
+
+ // Can't scroll Down
+ mCanScrollDown = false;
+ mCanScrollUp = true;
+ triggerDragLocationEvent(0, 95);
+ assertTrue(mDragHandler.mLastDropEvent.getAction() == DragEvent.ACTION_DRAG_LOCATION);
+
+ triggerDragEvent(DragEvent.ACTION_DRAG_ENDED);
+ }
+
+ @Test
+ public void testDragEnterEvent_DelegateToHandler() {
+ triggerDragEvent(DragEvent.ACTION_DRAG_STARTED);
+
+ // Location Event always precedes Entered event
+ triggerDragLocationEvent(0, 50);
+ // If not in the hotspot, we don't want to trap the event
+ triggerDragEvent(DragEvent.ACTION_DRAG_ENTERED);
+ assertTrue(mDragHandler.mLastDropEvent.getAction() == DragEvent.ACTION_DRAG_ENTERED);
+
+ // Can't scroll up
+ mCanScrollUp = false;
+ mCanScrollDown = true;
+ triggerDragLocationEvent(0, 5);
+ triggerDragEvent(DragEvent.ACTION_DRAG_ENTERED);
+ assertTrue(mDragHandler.mLastDropEvent.getAction() == DragEvent.ACTION_DRAG_ENTERED);
+
+ // Can't scroll Down
+ mCanScrollDown = false;
+ mCanScrollUp = true;
+ triggerDragLocationEvent(0, 95);
+ triggerDragEvent(DragEvent.ACTION_DRAG_ENTERED);
+ assertTrue(mDragHandler.mLastDropEvent.getAction() == DragEvent.ACTION_DRAG_ENTERED);
+
+ triggerDragEvent(DragEvent.ACTION_DRAG_ENDED);
+ }
+
+ // Make sure given correct location/enter events, DragScrollListener handle them itself
+ @Test
+ public void testDragScrollEvent_Handled() {
+ triggerDragLocationEvent(0, 5);
+ triggerDragEvent(DragEvent.ACTION_DRAG_ENTERED);
+ assertTrue(mDragHandler.mLastDropEvent == null);
+
+ triggerDragLocationEvent(0, 95);
+ triggerDragEvent(DragEvent.ACTION_DRAG_ENTERED);
+ assertTrue(mDragHandler.mLastDropEvent == null);
+ }
+
+ // A correct Auto-scroll happens in the sequence of:
+ // Started -> LocationChanged -> Scroll -> Enter -> Exit
+ // This test to make sure scroll actually happens in the right direction given correct sequence
+ @Test
+ public void testActualDragScrolldEvents() {
+ triggerDragEvent(DragEvent.ACTION_DRAG_STARTED);
+
+ triggerDragLocationEvent(0, 5);
+ triggerDragEvent(DragEvent.ACTION_DRAG_ENTERED);
+ assertTrue(mDragHandler.mLastDropEvent.getAction() == DragEvent.ACTION_DRAG_STARTED);
+ mActionDelegate.assertScrollNegative();
+
+ triggerDragLocationEvent(0, 95);
+ triggerDragEvent(DragEvent.ACTION_DRAG_ENTERED);
+
+ triggerDragEvent(DragEvent.ACTION_DRAG_ENDED);
+ assertTrue(mDragHandler.mLastDropEvent.getAction() == DragEvent.ACTION_DRAG_ENDED);
+ mActionDelegate.assertScrollPositive();
+ }
+
+ protected boolean triggerDragEvent(int actionId) {
+ final DragEvent testEvent = DragEvents.createTestDragEvent(actionId);
+
+ return mListener.onDrag(mTestView, testEvent);
+ }
+
+ protected boolean triggerDragLocationEvent(float x, float y) {
+ final DragEvent testEvent = DragEvents.createTestLocationEvent(x, y);
+
+ return mListener.onDrag(mTestView, testEvent);
+ }
+
+ private static class TestDragHandler extends ItemDragListener<TestDragHost> {
+
+ private DragEvent mLastDropEvent;
+
+ protected TestDragHandler(TestDragHost dragHost, Timer timer) {
+ super(dragHost, timer);
+ }
+
+ @Override
+ public boolean onDrag(View v, DragEvent event) {
+ mLastDropEvent = event;
+ return true;
+ }
+ }
+
+ private static class TestDragHost implements ItemDragListener.DragHost {
+
+ @Override
+ public void setDropTargetHighlight(View v, boolean highlight) {
+ }
+
+ @Override
+ public void runOnUiThread(Runnable runnable) {
+ }
+
+ @Override
+ public void onViewHovered(View v) {
+ }
+ }
+
+ private class TestScrollActionDelegate implements ScrollActionDelegate {
+
+ private int mDy;
+
+ @Override
+ public void scrollBy(int dy) {
+ mDy = dy;
+ }
+
+ @Override
+ public void runAtNextFrame(Runnable r) {
+ }
+
+ @Override
+ public void removeCallback(Runnable r) {
+ }
+
+ public void assertScrollPositive() {
+ assertTrue(mDy > 0);
+ }
+
+ public void assertScrollNegative() {
+ assertTrue(mDy < 0);
+ }
+ };
+}
diff --git a/tests/src/com/android/documentsui/testing/Views.java b/tests/src/com/android/documentsui/testing/Views.java
index 52a9cbc..d2b920d 100644
--- a/tests/src/com/android/documentsui/testing/Views.java
+++ b/tests/src/com/android/documentsui/testing/Views.java
@@ -33,6 +33,17 @@
return view;
}
+ /*
+ * Dummy View object with (x, y) coordinates
+ */
+ public static View createTestView(float x, float y) {
+ View view = createTestView();
+ Mockito.when(view.getX()).thenReturn(x);
+ Mockito.when(view.getY()).thenReturn(y);
+
+ return view;
+ }
+
public static void setBackground(View testView, Drawable background) {
Mockito.when(testView.getBackground()).thenReturn(background);
}