Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(694)

Unified Diff: android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/ActionModeTest.java

Issue 2154023002: adding action mode tests (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix merge conflict Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/ActionModeTest.java
diff --git a/android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/ActionModeTest.java b/android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/ActionModeTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..f7269eb8f496743e8acef9132a2e849e0daf9f91
--- /dev/null
+++ b/android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/ActionModeTest.java
@@ -0,0 +1,288 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.webview_ui_test.test;
+
+import static android.support.test.espresso.Espresso.onData;
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.actionWithAssertions;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.intent.Intents.assertNoUnverifiedIntents;
+import static android.support.test.espresso.intent.Intents.intended;
+import static android.support.test.espresso.intent.Intents.intending;
+import static android.support.test.espresso.intent.matcher.BundleMatchers.hasEntry;
+import static android.support.test.espresso.intent.matcher.IntentMatchers.anyIntent;
+import static android.support.test.espresso.intent.matcher.IntentMatchers.hasAction;
+import static android.support.test.espresso.intent.matcher.IntentMatchers.hasExtra;
+import static android.support.test.espresso.intent.matcher.IntentMatchers.hasExtras;
+import static android.support.test.espresso.intent.matcher.IntentMatchers.hasType;
+import static android.support.test.espresso.matcher.RootMatchers.DEFAULT;
+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.isEnabled;
+import static android.support.test.espresso.matcher.ViewMatchers.withChild;
+import static android.support.test.espresso.matcher.ViewMatchers.withClassName;
+import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static android.support.test.espresso.web.assertion.WebViewAssertions.webMatches;
+import static android.support.test.espresso.web.sugar.Web.onWebView;
+import static android.support.test.espresso.web.webdriver.DriverAtoms.findElement;
+import static android.support.test.espresso.web.webdriver.DriverAtoms.getText;
+
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.endsWith;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.core.AnyOf.anyOf;
+import static org.junit.Assert.assertTrue;
+
+import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
+
+import android.animation.ValueAnimator;
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.os.Build;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.espresso.NoMatchingViewException;
+import android.support.test.espresso.PerformException;
+import android.support.test.espresso.Root;
+import android.support.test.espresso.ViewAction;
+import android.support.test.espresso.action.GeneralClickAction;
+import android.support.test.espresso.action.GeneralLocation;
+import android.support.test.espresso.action.Press;
+import android.support.test.espresso.action.Tap;
+import android.support.test.espresso.intent.Intents;
+import android.support.test.espresso.web.webdriver.Locator;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiSelector;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.MenuItem;
+
+import junit.framework.AssertionFailedError;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.Log;
+import org.chromium.base.test.BaseJUnit4ClassRunner;
+import org.chromium.webview_ui_test.R;
+import org.chromium.webview_ui_test.WebViewUiTestActivity;
+import org.chromium.webview_ui_test.test.util.UseLayout;
+import org.chromium.webview_ui_test.test.util.WebViewUiTestRule;
+
+import java.lang.reflect.Method;
+
+/**
+ * Tests for WebView ActionMode.
+ */
+@RunWith(BaseJUnit4ClassRunner.class)
+public class ActionModeTest {
+ private static final String TAG = "ActionModeTest";
+
+ // Actions available in action mode
+ private static final String ASSIST_ACTION = "Assist";
+ private static final String COPY_ACTION = "Copy";
+ private static final String MORE_OPTIONS_ACTION = "More options";
+ private static final String PASTE_ACTION = "Paste";
+ private static final String SHARE_ACTION = "Share";
+ private static final String SELECT_ALL_ACTION = "Select All";
+ private static final String WEB_SEARCH_ACTION = "Web search";
+
+ private static final String QUICK_SEARCH_BOX_PKG = "com.google.android.googlequicksearchbox";
+ private static final long ASSIST_TIMEOUT = scaleTimeout(5000);
+
+ @Rule
+ public WebViewUiTestRule mWebViewActivityRule =
+ new WebViewUiTestRule(WebViewUiTestActivity.class);
+
+ @Before
+ public void setUp() {
+ mWebViewActivityRule.launchActivity();
+ onWebView().forceJavascriptEnabled();
+ mWebViewActivityRule.loadDataSync(
+ "<html><body><p>Hello world</p></body></html>", "text/html", "utf-8", false);
+ onWebView(withId(R.id.webview))
+ .withElement(findElement(Locator.TAG_NAME, "p"))
+ .check(webMatches(getText(), containsString("Hello world")));
+ disableAnimation();
+ }
+
+ /**
+ * Only way to disable popup animations.
+ */
+ private void disableAnimation() {
+ try {
+ // This is a hidden method to disable animations. It is also being used by CTS tests.
+ Method setDurationScale = ValueAnimator.class.getMethod(
+ "setDurationScale", float.class);
+ setDurationScale.invoke(null, 0.0f);
+ } catch (Exception e) {
+ Log.e(TAG, "Couldn't disable animation", e);
+ }
+ }
+
+ /**
+ * Test Copy and Paste
+ */
+ @Test
+ @SmallTest
+ @UseLayout("edittext_webview")
+ public void testCopyPaste() {
+ onView(withId(R.id.webview)).perform(longClickOnLastWord());
+ clickPopupAction(COPY_ACTION);
+ onView(withId(R.id.edittext)).perform(longClickOnLastWord());
+ clickPopupAction(PASTE_ACTION);
+ onView(withId(R.id.edittext))
+ .check(matches(withText("world")));
+ }
+
+ /**
+ * Test Select All
+ */
+ @Test
+ @SmallTest
+ @UseLayout("edittext_webview")
+ public void testSelectAll() {
+ onView(withId(R.id.webview)).perform(longClickOnLastWord());
+ clickPopupAction("Select all");
+ clickPopupAction(COPY_ACTION);
+ onView(withId(R.id.edittext)).perform(longClickOnLastWord());
+ clickPopupAction(PASTE_ACTION);
+ onView(withId(R.id.edittext))
+ .check(matches(withText("Hello world")));
+ }
+
+ /**
+ * Test Share
+ */
+ @Test
+ @SmallTest
+ @UseLayout("edittext_webview")
+ public void testShare() {
+ Intents.init();
+ intending(anyIntent())
+ .respondWith(new Instrumentation.ActivityResult(Activity.RESULT_OK, new Intent()));
+
+ onView(withId(R.id.webview)).perform(longClickOnLastWord());
+ clickPopupAction(SHARE_ACTION);
+
+ intended(allOf(hasAction(Intent.ACTION_CHOOSER),
+ hasExtras(allOf(hasEntry(Intent.EXTRA_TITLE, SHARE_ACTION),
+ hasEntry(Intent.EXTRA_INTENT,
+ allOf(hasAction(Intent.ACTION_SEND), hasType("text/plain"),
+ hasExtra(Intent.EXTRA_TEXT, "world")))))));
+ assertNoUnverifiedIntents();
+ }
+
+ /**
+ * Test Web Search
+ */
+ @Test
+ @SmallTest
+ @UseLayout("edittext_webview")
+ public void testWebSearch() {
+ Intents.init();
+ intending(anyIntent())
+ .respondWith(new Instrumentation.ActivityResult(Activity.RESULT_OK, new Intent()));
+ onView(withId(R.id.webview)).perform(longClickOnLastWord());
+ clickPopupAction(WEB_SEARCH_ACTION);
+ intended(allOf(hasAction(Intent.ACTION_WEB_SEARCH),
+ hasExtras(allOf(hasEntry("com.android.browser.application_id",
+ "org.chromium.webview_ui_test"),
+ hasEntry("query", "world"),
+ hasEntry("new_search", true)))));
+ assertNoUnverifiedIntents();
+ }
+
+ /**
+ * Test Assist
+ */
+ @Test
+ @SmallTest
+ @UseLayout("edittext_webview")
+ public void testAssist() {
+ // TODO(aluo): Get SdkSuppress to work with the test runner
+ if (Build.VERSION.SDK_INT < 24) return;
+ onView(withId(R.id.webview)).perform(longClickOnLastWord());
+ clickPopupAction(ASSIST_ACTION);
+ UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ UiObject assistUi = device.findObject(new UiSelector().packageName(QUICK_SEARCH_BOX_PKG));
+ assertTrue(assistUi.waitForExists(ASSIST_TIMEOUT));
+ device.pressBack();
+ }
+
+ /**
+ * Click an item on the Action Mode popup
+ */
+ public void clickPopupAction(final String name) {
+ Matcher<Root> rootMatcher;
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+ try {
+ // On L and lower, use the espresso DEFAULT root matcher if ActionBar is detected
+ onView(withClassName(endsWith("widget.ActionBarContextView")))
+ .check(matches(isDisplayed()));
+ rootMatcher = DEFAULT;
+ } catch (NoMatchingViewException | AssertionFailedError e) {
+ // Else match in a popup
+ rootMatcher = withDecorView(withChild(withText(name)));
+ }
+ } else {
+ // On M and above, can use the decoreView matcher
+ rootMatcher = withDecorView(isEnabled());
+ }
+ try {
+ onView(anyOf(withText(name), withContentDescription(name)))
+ .inRoot(rootMatcher)
+ .perform(click());
+ } catch (PerformException e) {
+ // Take care of case when the item is in the overflow menu
+ onView(withContentDescription(MORE_OPTIONS_ACTION))
+ .inRoot(withDecorView(isEnabled()))
+ .perform(click());
+ onData(new MenuItemMatcher(equalTo(name))).inRoot(rootMatcher).perform(click());
+ }
+ }
+
+ /**
+ * This view action clicks on center right of a view to select the last word
+ */
+ private static final ViewAction longClickOnLastWord() {
+ // TODO(aluo): This function is not guaranteed to click on element. Change to
+ // implementation that gets bounding box for elements using Javascript.
+ return actionWithAssertions(
+ new GeneralClickAction(Tap.LONG, GeneralLocation.CENTER_RIGHT, Press.FINGER));
+ }
+
+ /**
+ * Matches an item on the Action Mode popup by the title
+ */
+ private static class MenuItemMatcher extends TypeSafeMatcher<MenuItem> {
+ private Matcher<String> mTitleMatcher;
+
+ public MenuItemMatcher(Matcher<String> titleMatcher) {
+ mTitleMatcher = titleMatcher;
+ }
+
+ @Override
+ protected boolean matchesSafely(MenuItem item) {
+ return mTitleMatcher.matches(item.getTitle());
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("has MenuItem with title: ");
+ description.appendDescriptionOf(mTitleMatcher);
+ }
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698