diff options
3 files changed, 185 insertions, 22 deletions
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 3860f68f1292..dd122583ff23 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2261,6 +2261,7 @@ <!-- Floating toolbar --> <java-symbol type="id" name="floating_toolbar_menu_item_image_button" /> + <java-symbol type="id" name="overflow" /> <java-symbol type="layout" name="floating_popup_container" /> <java-symbol type="layout" name="floating_popup_menu_button" /> <java-symbol type="layout" name="floating_popup_open_overflow_button" /> diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java index 2640a66c989b..793aaadb2d80 100644 --- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java +++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java @@ -26,6 +26,10 @@ 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.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsNotDisplayed; +import static android.widget.espresso.FloatingToolbarEspressoUtils.sleepForFloatingToolbarPopup; +import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarContainsItem; +import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarDoesNotContainItem; 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; @@ -154,19 +158,75 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV @SmallTest public void testToolbarAppearsAfterSelection() throws Exception { - // 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()); + assertFloatingToolbarIsNotDisplayed(); 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()); + sleepForFloatingToolbarPopup(); + assertFloatingToolbarIsDisplayed(); + + final String text2 = "Toolbar disappears after typing text."; + onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text2)); + assertFloatingToolbarIsNotDisplayed(); + } + + @SmallTest + public void testToolbarAndInsertionHandle() throws Exception { + final String text = "text"; + onView(withId(R.id.textview)).perform(click()); + onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); + onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length())); + assertFloatingToolbarIsNotDisplayed(); + + onHandleView(com.android.internal.R.id.insertion_handle).perform(click()); + sleepForFloatingToolbarPopup(); + assertFloatingToolbarIsDisplayed(); + + assertFloatingToolbarContainsItem( + getActivity().getString(com.android.internal.R.string.selectAll)); + assertFloatingToolbarDoesNotContainItem( + getActivity().getString(com.android.internal.R.string.copy)); + assertFloatingToolbarDoesNotContainItem( + getActivity().getString(com.android.internal.R.string.cut)); + } + + @SmallTest + public void testToolbarAndSelectionHandle() throws Exception { + final String text = "abcd efg hijk"; + onView(withId(R.id.textview)).perform(click()); + onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); + + onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf("f"))); + sleepForFloatingToolbarPopup(); + assertFloatingToolbarIsDisplayed(); + + assertFloatingToolbarContainsItem( + getActivity().getString(com.android.internal.R.string.selectAll)); + assertFloatingToolbarContainsItem( + getActivity().getString(com.android.internal.R.string.copy)); + assertFloatingToolbarContainsItem( + getActivity().getString(com.android.internal.R.string.cut)); + + final TextView textView = (TextView) getActivity().findViewById(R.id.textview); + onHandleView(com.android.internal.R.id.selection_start_handle) + .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('a'))); + sleepForFloatingToolbarPopup(); + assertFloatingToolbarIsDisplayed(); + + onHandleView(com.android.internal.R.id.selection_end_handle) + .perform(dragHandle(textView, Handle.SELECTION_END, text.length())); + sleepForFloatingToolbarPopup(); + assertFloatingToolbarIsDisplayed(); + + assertFloatingToolbarDoesNotContainItem( + getActivity().getString(com.android.internal.R.string.selectAll)); + assertFloatingToolbarContainsItem( + getActivity().getString(com.android.internal.R.string.copy)); + assertFloatingToolbarContainsItem( + getActivity().getString(com.android.internal.R.string.cut)); } @SmallTest @@ -178,7 +238,7 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length())); onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.length())); - final TextView textView = (TextView)getActivity().findViewById(R.id.textview); + final TextView textView = (TextView) getActivity().findViewById(R.id.textview); onHandleView(com.android.internal.R.id.insertion_handle) .perform(dragHandle(textView, Handle.INSERTION, text.indexOf('a'))); @@ -198,7 +258,7 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length())); onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.length())); - final TextView textView = (TextView)getActivity().findViewById(R.id.textview); + final TextView textView = (TextView) getActivity().findViewById(R.id.textview); onHandleView(com.android.internal.R.id.insertion_handle) .perform(dragHandle(textView, Handle.INSERTION, text.indexOf('a'))); @@ -224,7 +284,7 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV onHandleView(com.android.internal.R.id.selection_end_handle) .check(matches(isDisplayed())); - final TextView textView = (TextView)getActivity().findViewById(R.id.textview); + final TextView textView = (TextView) getActivity().findViewById(R.id.textview); onHandleView(com.android.internal.R.id.selection_start_handle) .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('a'))); onView(withId(R.id.textview)).check(hasSelection("abcd efg")); @@ -241,7 +301,7 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('i'))); - final TextView textView = (TextView)getActivity().findViewById(R.id.textview); + final TextView textView = (TextView) getActivity().findViewById(R.id.textview); onHandleView(com.android.internal.R.id.selection_start_handle) .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('e'))); onView(withId(R.id.textview)).check(hasSelection("efg\nhijk")); @@ -299,7 +359,7 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('f'))); - final TextView textView = (TextView)getActivity().findViewById(R.id.textview); + final TextView textView = (TextView) getActivity().findViewById(R.id.textview); onHandleView(com.android.internal.R.id.selection_start_handle) .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('l'))); onView(withId(R.id.textview)).check(hasSelection("g")); @@ -317,7 +377,7 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('i'))); - final TextView textView = (TextView)getActivity().findViewById(R.id.textview); + final TextView textView = (TextView) getActivity().findViewById(R.id.textview); onHandleView(com.android.internal.R.id.selection_start_handle) .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('r') + 1)); onView(withId(R.id.textview)).check(hasSelection("k")); @@ -335,7 +395,7 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('i'))); - final TextView textView = (TextView)getActivity().findViewById(R.id.textview); + final TextView textView = (TextView) getActivity().findViewById(R.id.textview); onHandleView(com.android.internal.R.id.selection_start_handle) .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('f'))); @@ -388,7 +448,7 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('m'))); - final TextView textView = (TextView)getActivity().findViewById(R.id.textview); + final TextView textView = (TextView) getActivity().findViewById(R.id.textview); onHandleView(com.android.internal.R.id.selection_start_handle) .perform(dragHandle(textView, Handle.SELECTION_START, text.indexOf('c'))); diff --git a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java index fc01d8416df3..f02fe004e5b8 100644 --- a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java +++ b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java @@ -19,31 +19,133 @@ 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.hasDescendant; import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.isRoot; import static android.support.test.espresso.matcher.ViewMatchers.withTagValue; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; -import android.app.Activity; +import org.hamcrest.Matcher; + +import android.support.test.espresso.NoMatchingRootException; +import android.support.test.espresso.NoMatchingViewException; +import android.support.test.espresso.UiController; +import android.support.test.espresso.ViewAction; +import android.support.test.espresso.ViewInteraction; +import android.support.test.espresso.action.ViewActions; +import android.support.test.espresso.matcher.ViewMatchers; +import android.view.View; + import com.android.internal.widget.FloatingToolbar; /** * Espresso utility methods for the floating toolbar. */ public class FloatingToolbarEspressoUtils { - + private final static Object TAG = FloatingToolbar.FLOATING_TOOLBAR_TAG; private FloatingToolbarEspressoUtils() {} + private static ViewInteraction onFloatingToolBar() { + return onView(withTagValue(is(TAG))) + .inRoot(withDecorView(hasDescendant(withTagValue(is(TAG))))); + } + /** * 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())); + public static void assertFloatingToolbarIsDisplayed() { + onFloatingToolBar().check(matches(isDisplayed())); + } + + /** + * Asserts that the floating toolbar is not displayed on screen. + * + * @throws AssertionError if the assertion fails + */ + public static void assertFloatingToolbarIsNotDisplayed() { + try { + onFloatingToolBar().check(matches(isDisplayed())); + } catch (NoMatchingRootException | NoMatchingViewException | AssertionError e) { + return; + } + throw new AssertionError("Floating toolbar is displayed"); + } + + private static void toggleOverflow() { + final int id = com.android.internal.R.id.overflow; + onView(allOf(withId(id), isDisplayed())) + .inRoot(withDecorView(hasDescendant(withId(id)))) + .perform(ViewActions.click()); + onView(isRoot()).perform(SLEEP); + } + + public static void sleepForFloatingToolbarPopup() { + onView(isRoot()).perform(SLEEP); + } + + /** + * Asserts that the floating toolbar contains the specified item. + * + * @param itemLabel label of the item. + * @throws AssertionError if the assertion fails + */ + public static void assertFloatingToolbarContainsItem(String itemLabel) { + try{ + onFloatingToolBar().check(matches(hasDescendant(ViewMatchers.withText(itemLabel)))); + } catch (AssertionError e) { + try{ + toggleOverflow(); + } catch (NoMatchingViewException | NoMatchingRootException e2) { + // No overflow items. + throw e; + } + try{ + onFloatingToolBar().check(matches(hasDescendant(ViewMatchers.withText(itemLabel)))); + } finally { + toggleOverflow(); + } + } + } + + /** + * Asserts that the floating toolbar doesn't contain the specified item. + * + * @param itemLabel label of the item. + * @throws AssertionError if the assertion fails + */ + public static void assertFloatingToolbarDoesNotContainItem(String itemLabel) { + try{ + assertFloatingToolbarContainsItem(itemLabel); + } catch (AssertionError e) { + return; + } + throw new AssertionError("Floating toolbar contains " + itemLabel); } + /** + * ViewAction to sleep to wait floating toolbar's animation. + */ + private static final ViewAction SLEEP = new ViewAction() { + private static final long SLEEP_DURATION = 400; + + @Override + public Matcher<View> getConstraints() { + return isDisplayed(); + } + + @Override + public String getDescription() { + return "Sleep " + SLEEP_DURATION + " ms."; + } + + @Override + public void perform(UiController uiController, View view) { + uiController.loopMainThreadForAtLeast(SLEEP_DURATION); + } + }; } |