diff options
| author | 2015-12-06 10:03:23 -0800 | |
|---|---|---|
| committer | 2015-12-06 10:03:23 -0800 | |
| commit | 46faad60230ade76b6a4944a2b9fae274698ab91 (patch) | |
| tree | 447edbf47fcdbc9d94c78343f5cd7bc0f4596c8b | |
| parent | d42cb8ffa77266abe3bcffe98212d313d223a86c (diff) | |
TextView tests: Add mouse triple click tests.
Bug: 19544351
Change-Id: I20f1b169915a8013f7786684f97172767c162420
4 files changed, 257 insertions, 6 deletions
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java index 7e84fb8d89af..83a9e01761d9 100644 --- a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java +++ b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java @@ -24,9 +24,12 @@ import static android.widget.espresso.TextViewActions.mouseLongClickOnTextAtInde import static android.widget.espresso.TextViewActions.mouseDoubleClickAndDragOnText; import static android.widget.espresso.TextViewActions.mouseDragOnText; import static android.widget.espresso.TextViewActions.mouseLongClickAndDragOnText; +import static android.widget.espresso.TextViewActions.mouseTripleClickAndDragOnText; +import static android.widget.espresso.TextViewActions.mouseTripleClickOnTextAtIndex; import static android.widget.espresso.TextViewAssertions.hasSelection; import static android.support.test.espresso.Espresso.onView; import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.action.ViewActions.replaceText; import static android.support.test.espresso.action.ViewActions.typeTextIntoFocusedView; import static android.support.test.espresso.assertion.ViewAssertions.matches; import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; @@ -190,4 +193,102 @@ public class TextViewActivityMouseTest extends ActivityInstrumentationTestCase2< mouseLongClickAndDragOnText(text.indexOf("j"), text.indexOf("f"))); onView(withId(R.id.textview)).check(hasSelection("efg hijk")); } + + @SmallTest + public void testSelectTextByTripleClick() throws Exception { + getActivity(); + + final StringBuilder builder = new StringBuilder(); + builder.append("First paragraph.\n"); + builder.append("Second paragraph."); + for (int i = 0; i < 10; i++) { + builder.append(" This paragraph is very long."); + } + builder.append('\n'); + builder.append("Third paragraph."); + final String text = builder.toString(); + + onView(withId(R.id.textview)).perform(click()); + onView(withId(R.id.textview)).perform(replaceText(text)); + + onView(withId(R.id.textview)).perform( + mouseTripleClickOnTextAtIndex(text.indexOf("rst"))); + onView(withId(R.id.textview)).check(hasSelection("First paragraph.\n")); + + onView(withId(R.id.textview)).perform( + mouseTripleClickOnTextAtIndex(text.indexOf("cond"))); + onView(withId(R.id.textview)).check(hasSelection( + text.substring(text.indexOf("Second"), text.indexOf("Third")))); + + onView(withId(R.id.textview)).perform( + mouseTripleClickOnTextAtIndex(text.indexOf("ird"))); + onView(withId(R.id.textview)).check(hasSelection("Third paragraph.")); + + onView(withId(R.id.textview)).perform( + mouseTripleClickOnTextAtIndex(text.indexOf("very long"))); + onView(withId(R.id.textview)).check(hasSelection( + text.substring(text.indexOf("Second"), text.indexOf("Third")))); + } + + @SmallTest + public void testSelectTextByTripleClickAndDrag() throws Exception { + getActivity(); + + final StringBuilder builder = new StringBuilder(); + builder.append("First paragraph.\n"); + builder.append("Second paragraph."); + for (int i = 0; i < 10; i++) { + builder.append(" This paragraph is very long."); + } + builder.append('\n'); + builder.append("Third paragraph."); + final String text = builder.toString(); + + onView(withId(R.id.textview)).perform(click()); + onView(withId(R.id.textview)).perform(replaceText(text)); + + onView(withId(R.id.textview)).perform( + mouseTripleClickAndDragOnText(text.indexOf("irst"), text.indexOf("st"))); + onView(withId(R.id.textview)).check(hasSelection("First paragraph.\n")); + + onView(withId(R.id.textview)).perform( + mouseTripleClickAndDragOnText(text.indexOf("cond"), text.indexOf("Third") - 2)); + onView(withId(R.id.textview)).check(hasSelection( + text.substring(text.indexOf("Second"), text.indexOf("Third")))); + + onView(withId(R.id.textview)).perform( + mouseTripleClickAndDragOnText(text.indexOf("First"), text.indexOf("ird"))); + onView(withId(R.id.textview)).check(hasSelection(text)); + } + + @SmallTest + public void testSelectTextByTripleClickAndDrag_reverse() throws Exception { + getActivity(); + + final StringBuilder builder = new StringBuilder(); + builder.append("First paragraph.\n"); + builder.append("Second paragraph."); + for (int i = 0; i < 10; i++) { + builder.append(" This paragraph is very long."); + } + builder.append('\n'); + builder.append("Third paragraph."); + final String text = builder.toString(); + + onView(withId(R.id.textview)).perform(click()); + onView(withId(R.id.textview)).perform(replaceText(text)); + + onView(withId(R.id.textview)).perform( + mouseTripleClickAndDragOnText(text.indexOf("st"), text.indexOf("irst"))); + onView(withId(R.id.textview)).check(hasSelection("First paragraph.\n")); + + onView(withId(R.id.textview)).perform( + mouseTripleClickAndDragOnText(text.indexOf("Third") - 2, text.indexOf("cond"))); + onView(withId(R.id.textview)).check(hasSelection( + text.substring(text.indexOf("Second"), text.indexOf("Third")))); + + onView(withId(R.id.textview)).perform( + mouseTripleClickAndDragOnText(text.indexOf("ird"), text.indexOf("First"))); + onView(withId(R.id.textview)).check(hasSelection(text)); + } } diff --git a/core/tests/coretests/src/android/widget/espresso/DragAction.java b/core/tests/coretests/src/android/widget/espresso/DragAction.java index ce975688a894..b2c8e38141b8 100644 --- a/core/tests/coretests/src/android/widget/espresso/DragAction.java +++ b/core/tests/coretests/src/android/widget/espresso/DragAction.java @@ -157,6 +157,59 @@ public final class DragAction implements ViewAction { }, /** + * Starts a drag with a mouse triple click. + */ + MOUSE_TRIPLE_CLICK { + private DownMotionPerformer downMotion = new DownMotionPerformer() { + @Override + @Nullable + public MotionEvent perform( + UiController uiController, float[] coordinates, float[] precision) { + MotionEvent downEvent = MotionEvents.sendDown( + uiController, coordinates, precision) + .down; + for (int i = 0; i < 2; ++i) { + try { + if (!MotionEvents.sendUp(uiController, downEvent)) { + String logMessage = "Injection of up event as part of the triple " + + "click failed. Sending cancel event."; + Log.d(TAG, logMessage); + MotionEvents.sendCancel(uiController, downEvent); + return null; + } + + long doubleTapMinimumTimeout = ViewConfiguration.getDoubleTapMinTime(); + uiController.loopMainThreadForAtLeast(doubleTapMinimumTimeout); + } finally { + downEvent.recycle(); + } + downEvent = MotionEvents.sendDown( + uiController, coordinates, precision).down; + } + return downEvent; + } + }; + + @Override + public Status sendSwipe( + UiController uiController, + float[] startCoordinates, float[] endCoordinates, float[] precision) { + return sendLinearDrag( + uiController, downMotion, startCoordinates, endCoordinates, precision); + } + + @Override + public String toString() { + return "mouse triple click and drag to select"; + } + + @Override + public UiController wrapUiController(UiController uiController) { + return new MouseUiController(uiController); + } + }, + + /** * Starts a drag with a tap. */ TAP { diff --git a/core/tests/coretests/src/android/widget/espresso/MouseClickAction.java b/core/tests/coretests/src/android/widget/espresso/MouseClickAction.java index de640ca1053d..e51f27857a4b 100644 --- a/core/tests/coretests/src/android/widget/espresso/MouseClickAction.java +++ b/core/tests/coretests/src/android/widget/espresso/MouseClickAction.java @@ -22,9 +22,13 @@ import android.support.test.espresso.UiController; import android.support.test.espresso.ViewAction; import android.support.test.espresso.action.CoordinatesProvider; import android.support.test.espresso.action.GeneralClickAction; +import android.support.test.espresso.action.MotionEvents; +import android.support.test.espresso.action.MotionEvents.DownResultHolder; import android.support.test.espresso.action.PrecisionDescriber; +import android.support.test.espresso.action.Press; import android.support.test.espresso.action.Tapper; import android.view.View; +import android.view.ViewConfiguration; /** * ViewAction for performing an click on View by a mouse. @@ -32,10 +36,58 @@ import android.view.View; public final class MouseClickAction implements ViewAction { private final GeneralClickAction mGeneralClickAction; - public MouseClickAction(Tapper tapper, CoordinatesProvider coordinatesProvider, - PrecisionDescriber precisionDescriber) { + public enum CLICK implements Tapper { + TRIPLE { + @Override + public Tapper.Status sendTap(UiController uiController, float[] coordinates, + float[] precision) { + Tapper.Status stat = sendSingleTap(uiController, coordinates, precision); + boolean warning = false; + if (stat == Tapper.Status.FAILURE) { + return Tapper.Status.FAILURE; + } else if (stat == Tapper.Status.WARNING) { + warning = true; + } + + long doubleTapMinimumTimeout = ViewConfiguration.getDoubleTapMinTime(); + for (int i = 0; i < 2; i++) { + if (0 < doubleTapMinimumTimeout) { + uiController.loopMainThreadForAtLeast(doubleTapMinimumTimeout); + } + stat = sendSingleTap(uiController, coordinates, precision); + if (stat == Tapper.Status.FAILURE) { + return Tapper.Status.FAILURE; + } else if (stat == Tapper.Status.WARNING) { + warning = true; + } + } + + if (warning) { + return Tapper.Status.WARNING; + } else { + return Tapper.Status.SUCCESS; + } + } + }; + + private static Tapper.Status sendSingleTap(UiController uiController, + float[] coordinates, float[] precision) { + DownResultHolder res = MotionEvents.sendDown(uiController, coordinates, precision); + try { + if (!MotionEvents.sendUp(uiController, res.down)) { + MotionEvents.sendCancel(uiController, res.down); + return Tapper.Status.FAILURE; + } + } finally { + res.down.recycle(); + } + return res.longPress ? Tapper.Status.WARNING : Tapper.Status.SUCCESS; + } + }; + + public MouseClickAction(Tapper tapper, CoordinatesProvider coordinatesProvider) { mGeneralClickAction = new GeneralClickAction(tapper, coordinatesProvider, - precisionDescriber); + Press.PINPOINT); } @Override @@ -51,5 +103,13 @@ public final class MouseClickAction implements ViewAction { @Override public void perform(UiController uiController, View view) { mGeneralClickAction.perform(new MouseUiController(uiController), view); + long doubleTapTimeout = ViewConfiguration.getDoubleTapTimeout(); + if (0 < doubleTapTimeout) { + // Wait to avoid false gesture detection. Without this wait, consecutive clicks can be + // detected as a triple click. e.g. 2 double clicks are detected as a triple click and + // a single click because espresso isn't aware of triple click detection logic, which + // is TextView specific gesture. + uiController.loopMainThreadForAtLeast(doubleTapTimeout); + } } } diff --git a/core/tests/coretests/src/android/widget/espresso/TextViewActions.java b/core/tests/coretests/src/android/widget/espresso/TextViewActions.java index 32cc6d648556..54d5823c7aca 100644 --- a/core/tests/coretests/src/android/widget/espresso/TextViewActions.java +++ b/core/tests/coretests/src/android/widget/espresso/TextViewActions.java @@ -64,7 +64,7 @@ public final class TextViewActions { */ public static ViewAction mouseClickOnTextAtIndex(int index) { return actionWithAssertions( - new MouseClickAction(Tap.SINGLE, new TextCoordinates(index), Press.PINPOINT)); + new MouseClickAction(Tap.SINGLE, new TextCoordinates(index))); } /** @@ -94,7 +94,7 @@ public final class TextViewActions { */ public static ViewAction mouseDoubleClickOnTextAtIndex(int index) { return actionWithAssertions( - new MouseClickAction(Tap.DOUBLE, new TextCoordinates(index), Press.PINPOINT)); + new MouseClickAction(Tap.DOUBLE, new TextCoordinates(index))); } /** @@ -124,7 +124,22 @@ public final class TextViewActions { */ public static ViewAction mouseLongClickOnTextAtIndex(int index) { return actionWithAssertions( - new MouseClickAction(Tap.LONG, new TextCoordinates(index), Press.PINPOINT)); + new MouseClickAction(Tap.LONG, new TextCoordinates(index))); + } + + /** + * Returns an action that triple-clicks by mouse on text at an index on the TextView.<br> + * <br> + * View constraints: + * <ul> + * <li>must be a TextView displayed on screen + * <ul> + * + * @param index The index of the TextView's text to triple-click on. + */ + public static ViewAction mouseTripleClickOnTextAtIndex(int index) { + return actionWithAssertions( + new MouseClickAction(MouseClickAction.CLICK.TRIPLE, new TextCoordinates(index))); } /** @@ -237,6 +252,28 @@ public final class TextViewActions { TextView.class)); } + /** + * Returns an action that triple click then drags by mouse on text from startIndex to endIndex + * on the TextView.<br> + * <br> + * View constraints: + * <ul> + * <li>must be a TextView displayed on screen + * <ul> + * + * @param startIndex The index of the TextView's text to start a drag from + * @param endIndex The index of the TextView's text to end the drag at + */ + public static ViewAction mouseTripleClickAndDragOnText(int startIndex, int endIndex) { + return actionWithAssertions( + new DragAction( + DragAction.Drag.MOUSE_TRIPLE_CLICK, + new TextCoordinates(startIndex), + new TextCoordinates(endIndex), + Press.PINPOINT, + TextView.class)); + } + public enum Handle { SELECTION_START, SELECTION_END, |