| 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..7211d1eea9f9a5513709e3e12eb28d7e6f8d6a9a
|
| --- /dev/null
|
| +++ b/android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/ActionModeTest.java
|
| @@ -0,0 +1,215 @@
|
| +// 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.click;
|
| +import static android.support.test.espresso.action.ViewActions.longClick;
|
| +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.isEnabled;
|
| +import static android.support.test.espresso.matcher.ViewMatchers.withChild;
|
| +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.Matchers.containsString;
|
| +import static org.hamcrest.Matchers.equalTo;
|
| +import static org.hamcrest.core.AnyOf.anyOf;
|
| +
|
| +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.NoMatchingRootException;
|
| +import android.support.test.espresso.NoMatchingViewException;
|
| +import android.support.test.espresso.PerformException;
|
| +import android.support.test.espresso.Root;
|
| +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 android.webkit.WebView;
|
| +
|
| +import org.chromium.webview_ui_test.R;
|
| +
|
| +import org.hamcrest.Description;
|
| +import org.hamcrest.Matcher;
|
| +import org.hamcrest.TypeSafeMatcher;
|
| +
|
| +import java.util.ArrayList;
|
| +import java.util.List;
|
| +
|
| +
|
| +/**
|
| + * Tests for WebView ActionMode.
|
| + */
|
| +public class ActionModeTest extends WebViewTestBase {
|
| + private static final long UI_TIMEOUT = 10 * 1000;
|
| +
|
| + @Override
|
| + protected String getLayout() {
|
| + return "edittext_webview";
|
| + }
|
| +
|
| + @Override
|
| + public void setUp() throws Exception {
|
| + super.setUp();
|
| + getInstrumentation().runOnMainSync(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + WebView w = (WebView) getWebViewActivity().findViewById(R.id.webview);
|
| + w.getSettings().setJavaScriptEnabled(true);
|
| + w.loadData("<html><body><p>Hello world</p></body></html>", "text/html", "utf-8");
|
| + }
|
| + });
|
| + onWebView(withId(R.id.webview))
|
| + .withElement(findElement(Locator.TAG_NAME, "p"))
|
| + .check(webMatches(getText(), containsString("Hello world")));
|
| + }
|
| +
|
| + /** Test Copy and Paste */
|
| + @SmallTest
|
| + public void testCopyPaste() {
|
| + onView(withId(R.id.webview)).perform(longClick());
|
| + clickPopupAction("Copy");
|
| + // This is needed to get the popup to work correctly in the next step
|
| + onView(withId(R.id.edittext)).perform(click());
|
| + onView(withId(R.id.edittext)).perform(longClick());
|
| + clickPopupAction("Paste");
|
| + onView(withId(R.id.edittext)).check(matches(withText("world")));
|
| + }
|
| +
|
| + /** Test Select All */
|
| + @SmallTest
|
| + public void testSelectAll() {
|
| + onView(withId(R.id.webview)).perform(longClick());
|
| + clickPopupAction("Select all");
|
| + clickPopupAction("Copy");
|
| + // This is needed to get the popup to work correctly in the next step
|
| + onView(withId(R.id.edittext)).perform(click());
|
| + onView(withId(R.id.edittext)).perform(longClick());
|
| + clickPopupAction("Paste");
|
| + onView(withId(R.id.edittext)).check(matches(withText("Hello world")));
|
| + }
|
| +
|
| + /** Test Share */
|
| + @SmallTest
|
| + public void testShare() {
|
| + Intents.init();
|
| + intending(anyIntent())
|
| + .respondWith(new Instrumentation.ActivityResult(Activity.RESULT_OK, new Intent()));
|
| +
|
| + onView(withId(R.id.webview)).perform(longClick());
|
| + clickPopupAction("Share");
|
| +
|
| + intended(allOf(hasAction(Intent.ACTION_CHOOSER),
|
| + hasExtras(allOf(hasEntry(Intent.EXTRA_TITLE, "Share"),
|
| + hasEntry(Intent.EXTRA_INTENT,
|
| + allOf(hasAction(Intent.ACTION_SEND), hasType("text/plain"),
|
| + hasExtra(Intent.EXTRA_TEXT, "world")))))));
|
| + assertNoUnverifiedIntents();
|
| + }
|
| +
|
| + /** Test Web Search */
|
| + @SmallTest
|
| + public void testWebSearch() {
|
| + Intents.init();
|
| + intending(anyIntent())
|
| + .respondWith(new Instrumentation.ActivityResult(Activity.RESULT_OK, new Intent()));
|
| + onView(withId(R.id.webview)).perform(longClick());
|
| + clickPopupAction("Web search");
|
| + 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 */
|
| + @SmallTest
|
| + 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(longClick());
|
| + clickPopupAction("Assist");
|
| + UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
|
| + UiObject assistUi = device.findObject(
|
| + new UiSelector().packageName("com.google.android.googlequicksearchbox"));
|
| + assistUi.waitForExists(5000);
|
| + assertTrue(assistUi.exists());
|
| + device.pressBack();
|
| + }
|
| +
|
| + /** 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);
|
| + }
|
| + }
|
| +
|
| + /** Click an item on the Action Mode popup */
|
| + public void clickPopupAction(final String name) {
|
| + final List<Matcher<Root>> rootMatchers = new ArrayList<Matcher<Root>>();
|
| + rootMatchers.add(DEFAULT);
|
| + rootMatchers.add(withDecorView(isEnabled()));
|
| + rootMatchers.add(withDecorView(withChild(withText(name))));
|
| + for (Matcher<Root> rootMatcher : rootMatchers) {
|
| + try {
|
| + onView(anyOf(withText(name), withContentDescription(name)))
|
| + .inRoot(rootMatcher)
|
| + .perform(click());
|
| + break;
|
| + } catch (NoMatchingRootException | NoMatchingViewException e) {
|
| + /** Throw if we've gone through all the root matchers already */
|
| + if (rootMatchers.indexOf(rootMatcher) == rootMatchers.size() - 1) {
|
| + throw(e);
|
| + }
|
| + } catch (PerformException e2) {
|
| + /** Take care of case when the item is in the overflow menu */
|
| + onView(withContentDescription("More options"))
|
| + .inRoot(withDecorView(isEnabled()))
|
| + .perform(click());
|
| + onData(new MenuItemMatcher(equalTo(name))).inRoot(rootMatcher).perform(click());
|
| + break;
|
| + }
|
| + }
|
| + }
|
| +}
|
|
|