diff options
| author | 2015-09-29 18:44:41 +0000 | |
|---|---|---|
| committer | 2015-09-29 18:44:41 +0000 | |
| commit | 66e47b6aa142edd6e613b081f6672dde891277b1 (patch) | |
| tree | 4034718e5f4999b8a899e916f4914f016b814c18 | |
| parent | e5ec210bb14619ff59b9adae31e3278f815a0ba6 (diff) | |
| parent | 8a5e1ae2f4e1aaf2db2a217e841371e18851df3f (diff) | |
Merge "FloatingToolbarEspressoUtils + more TextView selection by touch tests"
5 files changed, 212 insertions, 2 deletions
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java index 2a25db6b64c4..7bab446d4705 100644 --- a/core/java/com/android/internal/widget/FloatingToolbar.java +++ b/core/java/com/android/internal/widget/FloatingToolbar.java @@ -73,6 +73,8 @@ public final class FloatingToolbar { // This class is responsible for the public API of the floating toolbar. // It delegates rendering operations to the FloatingToolbarPopup. + public static final String FLOATING_TOOLBAR_TAG = "floating_toolbar"; + private static final MenuItem.OnMenuItemClickListener NO_OP_MENUITEM_CLICK_LISTENER = new MenuItem.OnMenuItemClickListener() { @Override @@ -1460,8 +1462,10 @@ public final class FloatingToolbar { } private static ViewGroup createContentContainer(Context context) { - return (ViewGroup) LayoutInflater.from(context) + ViewGroup contentContainer = (ViewGroup) LayoutInflater.from(context) .inflate(R.layout.floating_popup_container, null); + contentContainer.setTag(FLOATING_TOOLBAR_TAG); + return contentContainer; } private static PopupWindow createPopupWindow(View content) { diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java index ce9ae02c9cec..4db1d9a56c47 100644 --- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java +++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java @@ -18,8 +18,12 @@ package android.widget; import static android.widget.espresso.TextViewActions.clickOnTextAtIndex; import static android.widget.espresso.TextViewActions.doubleTapAndDragOnText; +import static android.widget.espresso.TextViewActions.doubleClickOnTextAtIndex; import static android.widget.espresso.TextViewActions.longPressAndDragOnText; +import static android.widget.espresso.TextViewActions.longPressOnTextAtIndex; +import static android.widget.espresso.TextViewAssertions.hasInsertionPointerAtIndex; import static android.widget.espresso.TextViewAssertions.hasSelection; +import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsDisplayed; 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.pressKey; @@ -59,6 +63,7 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV getActivity(); final String helloWorld = "Hello world!"; + onView(withId(R.id.textview)).perform(click()); onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(helloWorld)); onView(withId(R.id.textview)).perform(clickOnTextAtIndex(helloWorld.indexOf("world"))); @@ -68,10 +73,39 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV } @SmallTest + public void testLongPressToSelect() throws Exception { + getActivity(); + + final String helloWorld = "Hello Kirk!"; + onView(withId(R.id.textview)).perform(click()); + onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(helloWorld)); + onView(withId(R.id.textview)).perform( + longPressOnTextAtIndex(helloWorld.indexOf("Kirk"))); + + onView(withId(R.id.textview)).check(hasSelection("Kirk")); + } + + @SmallTest + public void testLongPressEmptySpace() throws Exception { + getActivity(); + + final String helloWorld = "Hello big round sun!"; + onView(withId(R.id.textview)).perform(click()); + onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(helloWorld)); + // Move cursor somewhere else + onView(withId(R.id.textview)).perform(clickOnTextAtIndex(helloWorld.indexOf("big"))); + // Long-press at end of line. + onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(helloWorld.length())); + + onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(helloWorld.length())); + } + + @SmallTest public void testLongPressAndDragToSelect() throws Exception { getActivity(); final String helloWorld = "Hello little handsome boy!"; + onView(withId(R.id.textview)).perform(click()); onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(helloWorld)); onView(withId(R.id.textview)).perform( longPressAndDragOnText(helloWorld.indexOf("little"), helloWorld.indexOf(" boy!"))); @@ -80,14 +114,60 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV } @SmallTest + public void testDoubleTapToSelect() throws Exception { + getActivity(); + + final String helloWorld = "Hello SuetYi!"; + onView(withId(R.id.textview)).perform(click()); + onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(helloWorld)); + onView(withId(R.id.textview)).perform( + doubleClickOnTextAtIndex(helloWorld.indexOf("SuetYi"))); + + onView(withId(R.id.textview)).check(hasSelection("SuetYi")); + } + + @SmallTest public void testDoubleTapAndDragToSelect() throws Exception { getActivity(); final String helloWorld = "Hello young beautiful girl!"; + onView(withId(R.id.textview)).perform(click()); onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(helloWorld)); onView(withId(R.id.textview)).perform( doubleTapAndDragOnText(helloWorld.indexOf("young"), helloWorld.indexOf(" girl!"))); onView(withId(R.id.textview)).check(hasSelection("young beautiful")); } + + @SmallTest + public void testSelectBackwordsByTouch() throws Exception { + getActivity(); + + final String helloWorld = "Hello king of the Jungle!"; + onView(withId(R.id.textview)).perform(click()); + onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(helloWorld)); + onView(withId(R.id.textview)).perform( + doubleTapAndDragOnText(helloWorld.indexOf(" Jungle!"), helloWorld.indexOf("king"))); + + onView(withId(R.id.textview)).check(hasSelection("king of the")); + } + + @SmallTest + public void testToolbarAppearsAfterSelection() throws Exception { + getActivity(); + + // It'll be nice to check that the toolbar is not visible (or does not exist) here + // I can't currently find a way to do this. I'll get to it later. + + final String text = "Toolbar appears after selection."; + onView(withId(R.id.textview)).perform(click()); + onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); + onView(withId(R.id.textview)).perform( + longPressOnTextAtIndex(text.indexOf("appears"))); + + // It takes the toolbar less than 100ms to start to animate into screen. + // Ideally, we'll wait using the UiController, but I guess this works for now. + Thread.sleep(100); + assertFloatingToolbarIsDisplayed(getActivity()); + } } diff --git a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java new file mode 100644 index 000000000000..fc01d8416df3 --- /dev/null +++ b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015 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 android.widget.espresso; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.RootMatchers.withDecorView; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withTagValue; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; + +import android.app.Activity; +import com.android.internal.widget.FloatingToolbar; + +/** + * Espresso utility methods for the floating toolbar. + */ +public class FloatingToolbarEspressoUtils { + + + private FloatingToolbarEspressoUtils() {} + + /** + * Asserts that the floating toolbar is displayed on screen. + * + * @throws AssertionError if the assertion fails + */ + public static void assertFloatingToolbarIsDisplayed(Activity activity) { + onView(withTagValue(is((Object) FloatingToolbar.FLOATING_TOOLBAR_TAG))) + .inRoot(withDecorView(not(is(activity.getWindow().getDecorView())))) + .check(matches(isDisplayed())); + } + +} diff --git a/core/tests/coretests/src/android/widget/espresso/TextViewActions.java b/core/tests/coretests/src/android/widget/espresso/TextViewActions.java index 7e4735b298fe..835b1b958860 100644 --- a/core/tests/coretests/src/android/widget/espresso/TextViewActions.java +++ b/core/tests/coretests/src/android/widget/espresso/TextViewActions.java @@ -52,6 +52,36 @@ public final class TextViewActions { } /** + * Returns an action that double-clicks 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 double-click on. + */ + public static ViewAction doubleClickOnTextAtIndex(int index) { + return actionWithAssertions( + new GeneralClickAction(Tap.DOUBLE, new TextCoordinates(index), Press.FINGER)); + } + + /** + * Returns an action that long presses 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 long press on. + */ + public static ViewAction longPressOnTextAtIndex(int index) { + return actionWithAssertions( + new GeneralClickAction(Tap.LONG, new TextCoordinates(index), Press.FINGER)); + } + + /** * Returns an action that long presses then drags on text from startIndex to endIndex on the * TextView.<br> * <br> diff --git a/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java b/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java index dce3182693a6..37c7425ce478 100644 --- a/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java +++ b/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java @@ -47,7 +47,7 @@ public final class TextViewAssertions { * @param selection The expected selection. */ public static ViewAssertion hasSelection(String selection) { - return new TextSelectionAssertion(is(selection)); + return hasSelection(is(selection)); } /** @@ -66,6 +66,53 @@ public final class TextViewAssertions { } /** + * Returns a {@link ViewAssertion} that asserts that the text view insertion pointer is at + * a specified index.<br> + * <br> + * View constraints: + * <ul> + * <li>must be a text view displayed on screen + * <ul> + * + * @param index The expected index. + */ + public static ViewAssertion hasInsertionPointerAtIndex(int index) { + return hasInsertionPointerAtIndex(is(index)); + } + + /** + * Returns a {@link ViewAssertion} that asserts that the text view insertion pointer is at + * a specified index.<br> + * <br> + * View constraints: + * <ul> + * <li>must be a text view displayed on screen + * <ul> + * + * @param index A matcher representing the expected index. + */ + public static ViewAssertion hasInsertionPointerAtIndex(final Matcher<Integer> index) { + return new ViewAssertion() { + @Override + public void check(View view, NoMatchingViewException exception) { + if (view instanceof TextView) { + TextView textView = (TextView) view; + int selectionStart = textView.getSelectionStart(); + int selectionEnd = textView.getSelectionEnd(); + try { + assertThat(selectionStart, index); + assertThat(selectionEnd, index); + } catch (IndexOutOfBoundsException e) { + throw new AssertionFailedError(e.getMessage()); + } + } else { + throw new AssertionFailedError("TextView not found"); + } + } + }; + } + + /** * A {@link ViewAssertion} to check the selected text in a {@link TextView}. */ private static final class TextSelectionAssertion implements ViewAssertion { |