Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae3ecaa2 authored by Keisuke Kuroyanagi's avatar Keisuke Kuroyanagi Committed by Android (Google) Code Review
Browse files

Merge "TextView test: floating toolbar + drag handle interaction."

parents d2441607 b0dd77c4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2270,6 +2270,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" />
+75 −15
Original line number Diff line number Diff line
@@ -28,6 +28,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;
@@ -149,19 +153,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
+109 −7
Original line number Diff line number Diff line
@@ -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);
        }
    };
}