Commit cb292df6 authored by Hazem Ashmawy's avatar Hazem Ashmawy Committed by Commit Bot

[AW][Devui] add espresso tests for HomeFragment

Add espresso tests for HomeFragment to test:
- Correct info is shown when the app is launched from the current
  WebView provider and when it's not.
- Long press on the items copy the correct info to clipboard.

Bug: 1106300
Test: out/Debug86/bin/run_webview_instrumentation_test_apk -f "*android_webview.devui*"
Change-Id: I63bab2647e65b758e4b14838d1ba34edd54a064a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2352738
Commit-Queue: Hazem Ashmawy <hazems@chromium.org>
Reviewed-by: default avatarNate Fischer <ntfschr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#800128}
parent df423457
// Copyright 2020 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.android_webview.test.devui;
import static org.hamcrest.Matchers.is;
import android.content.ClipboardManager;
import android.content.Context;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import java.util.concurrent.ExecutionException;
/**
* Util methods for developer UI tests.
*/
public class DeveloperUiTestUtils {
/**
* Matches that a {@link ListView} has a specific number of items.
*
* @param intMatcher {@line Matcher} class that matches a given integer.
*/
public static Matcher<View> withCount(final Matcher<Integer> intMatcher) {
return new TypeSafeMatcher<View>() {
@Override
public boolean matchesSafely(View view) {
if (!(view instanceof ListView)) {
return false;
}
int count = ((ListView) view).getCount();
return intMatcher.matches(count);
}
@Override
public void describeTo(Description description) {
description.appendText("with child-count: ");
intMatcher.describeTo(description);
}
};
}
/**
* Matches that a {@link ListView} has a specific number of items
*/
public static Matcher<View> withCount(final int itemCount) {
return withCount(is(itemCount));
}
/**
* Matches a view that has this layout
* android_webview/nonembedded/java/res_devui/layout/two_line_list_item.xml and has the given
* title.
*/
public static Matcher<View> withTitle(final Matcher<String> stringMatcher) {
return new TypeSafeMatcher<View>() {
@Override
public boolean matchesSafely(View view) {
if (!(view instanceof LinearLayout)) {
return false;
}
TextView textView = (TextView) view.findViewById(android.R.id.text1);
// Make sure only the immediate parent View is matched.
return textView != null && textView.getParent() == view
&& stringMatcher.matches(textView.getText());
}
@Override
public void describeTo(Description description) {
description.appendText("with title: ");
stringMatcher.describeTo(description);
}
};
}
/**
* Matches a view that has this layout
* android_webview/nonembedded/java/res_devui/layout/two_line_list_item.xml and has the given
* title.
*/
public static Matcher<View> withTitle(String title) {
return withTitle(is(title));
}
/**
* Matches a view that has this layout
* android_webview/nonembedded/java/res_devui/layout/two_line_list_item.xml and has the given
* subtitle.
*/
public static Matcher<View> withSubtitle(final Matcher<String> stringMatcher) {
return new TypeSafeMatcher<View>() {
@Override
public boolean matchesSafely(View view) {
if (!(view instanceof LinearLayout)) {
return false;
}
TextView textView = (TextView) view.findViewById(android.R.id.text2);
// Make sure only the immediate parent View is matched.
return textView != null && textView.getParent() == view
&& stringMatcher.matches(textView.getText());
}
@Override
public void describeTo(Description description) {
description.appendText("with subtitle: ");
stringMatcher.describeTo(description);
}
};
}
/**
* Matches a view that has this layout
* android_webview/nonembedded/java/res_devui/layout/two_line_list_item.xml and has the given
* subtitle.
*/
public static Matcher<View> withSubtitle(String subtitle) {
return withSubtitle(is(subtitle));
}
public static String getClipBoardTextOnUiThread(Context context) throws ExecutionException {
// ClipManager service has to be called on the UI main thread.
return TestThreadUtils.runOnUiThreadBlocking(() -> {
ClipboardManager clipboardManager =
(ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
return clipboardManager.getPrimaryClip().getItemAt(0).getText().toString();
});
}
// Don't instantiate this class.
private DeveloperUiTestUtils() {}
}
......@@ -17,6 +17,8 @@ import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.Matchers.not;
import static org.chromium.android_webview.test.devui.DeveloperUiTestUtils.withCount;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.SystemClock;
......@@ -92,29 +94,6 @@ public class FlagsFragmentTest {
return withHintText(is(expectedHint));
}
private static Matcher<View> withCount(final Matcher<Integer> intMatcher) {
return new TypeSafeMatcher<View>() {
@Override
public boolean matchesSafely(View view) {
if (!(view instanceof ListView)) {
return false;
}
int count = ((ListView) view).getCount();
return intMatcher.matches(count);
}
@Override
public void describeTo(Description description) {
description.appendText("with child-count: ");
intMatcher.describeTo(description);
}
};
}
private static Matcher<View> withCount(final int totalNumFlags) {
return withCount(is(totalNumFlags));
}
@IntDef({CompoundDrawable.START, CompoundDrawable.TOP, CompoundDrawable.END,
CompoundDrawable.BOTTOM})
private @interface CompoundDrawable {
......
// Copyright 2020 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.android_webview.test.devui;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.longClick;
import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.chromium.android_webview.test.devui.DeveloperUiTestUtils.getClipBoardTextOnUiThread;
import static org.chromium.android_webview.test.devui.DeveloperUiTestUtils.withCount;
import static org.chromium.android_webview.test.devui.DeveloperUiTestUtils.withSubtitle;
import static org.chromium.android_webview.test.devui.DeveloperUiTestUtils.withTitle;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.os.Build;
import android.support.test.InstrumentationRegistry;
import androidx.test.espresso.intent.rule.IntentsTestRule;
import androidx.test.filters.MediumTest;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.android_webview.devui.MainActivity;
import org.chromium.android_webview.devui.R;
import org.chromium.android_webview.devui.util.WebViewPackageHelper;
import org.chromium.android_webview.test.AwJUnit4ClassRunner;
import org.chromium.base.test.util.Feature;
import java.util.Locale;
/**
* UI tests for the developer UI's HomeFragment.
*/
@RunWith(AwJUnit4ClassRunner.class)
public class HomeFragmentTest {
@Rule
public IntentsTestRule mRule =
new IntentsTestRule<MainActivity>(MainActivity.class, false, false);
private void launchHomeFragment() {
Intent intent = new Intent();
intent.putExtra(MainActivity.FRAGMENT_ID_INTENT_EXTRA, MainActivity.FRAGMENT_ID_HOME);
mRule.launchActivity(intent);
}
@Test
@MediumTest
@Feature({"AndroidWebView"})
// Test when the system WebView provider is the same package from which the developer UI is
// launched.
public void testSameWebViewPackage() throws Throwable {
Context context = InstrumentationRegistry.getTargetContext();
// Inject test app package as the current WebView package.
WebViewPackageHelper.setCurrentWebViewPackageForTesting(
WebViewPackageHelper.getContextPackageInfo(context));
launchHomeFragment();
onView(withId(R.id.main_info_list)).check(matches(withCount(2)));
PackageInfo currentWebViewPackage = WebViewPackageHelper.getCurrentWebViewPackage(context);
String expectedWebViewPackageInfo =
String.format(Locale.US, "%s (%s/%s)", currentWebViewPackage.packageName,
currentWebViewPackage.versionName, currentWebViewPackage.versionCode);
onView(withTitle("WebView package"))
.check(matches(withSubtitle(expectedWebViewPackageInfo)));
onView(withTitle("DevTools package")).check(doesNotExist());
String expectedDeviceInfo =
String.format(Locale.US, "%s - %s", Build.MODEL, Build.FINGERPRINT);
onView(withTitle("Device info")).check(matches(withSubtitle(expectedDeviceInfo)));
}
@Test
@MediumTest
@Feature({"AndroidWebView"})
// Test when the system WebView provider is different from the package from which the developer
// UI is launched.
public void testDifferentWebViewPackage() throws Throwable {
Context context = InstrumentationRegistry.getTargetContext();
// Inject a dummy PackageInfo as the current WebView package to make sure it will always be
// different from the test's app package.
PackageInfo dummyTestPackage = new PackageInfo();
dummyTestPackage.packageName = "org.chromium.dummy_webview";
dummyTestPackage.versionCode = 123456789;
dummyTestPackage.versionName = "999.888.777.666";
WebViewPackageHelper.setCurrentWebViewPackageForTesting(dummyTestPackage);
launchHomeFragment();
onView(withId(R.id.main_info_list)).check(matches(withCount(3)));
String expectedWebViewPackageInfo =
String.format(Locale.US, "%s (%s/%s)", dummyTestPackage.packageName,
dummyTestPackage.versionName, dummyTestPackage.versionCode);
onView(withTitle("WebView package"))
.check(matches(withSubtitle(expectedWebViewPackageInfo)));
PackageInfo devUiPackage = WebViewPackageHelper.getContextPackageInfo(context);
String expectedDevUiInfo = String.format(Locale.US, "%s (%s/%s)", devUiPackage.packageName,
devUiPackage.versionName, devUiPackage.versionCode);
onView(withTitle("DevTools package")).check(matches(withSubtitle(expectedDevUiInfo)));
String expectedDeviceInfo =
String.format(Locale.US, "%s - %s", Build.MODEL, Build.FINGERPRINT);
onView(withTitle("Device info")).check(matches(withSubtitle(expectedDeviceInfo)));
}
@Test
@MediumTest
@Feature({"AndroidWebView"})
public void testLongPressCopy() throws Throwable {
Context context = InstrumentationRegistry.getTargetContext();
// Inject a dummy PackageInfo as the current WebView package to make sure it will always be
// different from the test's app package.
PackageInfo dummyTestPackage = new PackageInfo();
dummyTestPackage.packageName = "org.chromium.dummy_webview";
dummyTestPackage.versionCode = 123456789;
dummyTestPackage.versionName = "999.888.777.666";
WebViewPackageHelper.setCurrentWebViewPackageForTesting(dummyTestPackage);
launchHomeFragment();
onView(withText("WebView package")).perform(longClick());
String expectedWebViewInfo =
String.format(Locale.US, "%s (%s/%s)", dummyTestPackage.packageName,
dummyTestPackage.versionName, dummyTestPackage.versionCode);
assertThat(getClipBoardTextOnUiThread(context), is(equalTo(expectedWebViewInfo)));
onView(withText("DevTools package")).perform(longClick());
PackageInfo devUiPackage = WebViewPackageHelper.getContextPackageInfo(context);
String expectedDevUiInfo = String.format(Locale.US, "%s (%s/%s)", devUiPackage.packageName,
devUiPackage.versionName, devUiPackage.versionCode);
assertThat(getClipBoardTextOnUiThread(context), is(equalTo(expectedDevUiInfo)));
onView(withText("Device info")).perform(longClick());
String expectedDeviceInfo =
String.format(Locale.US, "%s - %s", Build.MODEL, Build.FINGERPRINT);
assertThat(getClipBoardTextOnUiThread(context), is(equalTo(expectedDeviceInfo)));
}
}
......@@ -12,6 +12,8 @@ import android.content.pm.PackageManager;
import android.os.Build;
import android.webkit.WebView;
import androidx.annotation.VisibleForTesting;
import java.lang.reflect.InvocationTargetException;
import java.util.Locale;
......@@ -19,6 +21,8 @@ import java.util.Locale;
* A helper class to get info about WebView package.
*/
public final class WebViewPackageHelper {
private static PackageInfo sWebViewCurrentPackage;
/**
* If WebView has already been loaded into the current process this method will return the
* package that was used to load it. Otherwise, the package that would be used if the WebView
......@@ -33,6 +37,9 @@ public final class WebViewPackageHelper {
// This method is copied from androidx.webkit.WebViewCompat.
// TODO(crbug.com/1020024) use androidx.webkit.WebViewCompat#getCurrentWebViewPackage instead.
public static PackageInfo getCurrentWebViewPackage(Context context) {
if (sWebViewCurrentPackage != null) {
return sWebViewCurrentPackage;
}
// There was no WebView Package before Lollipop, the WebView code was part of the framework
// back then.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
......@@ -159,6 +166,15 @@ public final class WebViewPackageHelper {
}
}
/**
* Inject a {@link PackageInfo} as the current webview package for testing. This PackageInfo
* will be returned by {@link #getCurrentWebViewPackage}.
*/
@VisibleForTesting
public static void setCurrentWebViewPackageForTesting(PackageInfo currentWebView) {
sWebViewCurrentPackage = currentWebView;
}
// Do not instantiate this class.
private WebViewPackageHelper() {}
}
......@@ -319,7 +319,9 @@ instrumentation_test_apk("webview_instrumentation_test_apk") {
"../javatests/src/org/chromium/android_webview/test/common/variations/VariationsUtilsTest.java",
"../javatests/src/org/chromium/android_webview/test/devui/AwNonembeddedUmaRecorderTest.java",
"../javatests/src/org/chromium/android_webview/test/devui/DeveloperUiTest.java",
"../javatests/src/org/chromium/android_webview/test/devui/DeveloperUiTestUtils.java",
"../javatests/src/org/chromium/android_webview/test/devui/FlagsFragmentTest.java",
"../javatests/src/org/chromium/android_webview/test/devui/HomeFragmentTest.java",
"../javatests/src/org/chromium/android_webview/test/devui/util/CrashBugUrlFactoryTest.java",
"../javatests/src/org/chromium/android_webview/test/devui/util/UnuploadedFilesStateLoaderTest.java",
"../javatests/src/org/chromium/android_webview/test/devui/util/UploadedCrashesInfoLoaderTest.java",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment