blob: 68aea209592c2df306cd9b8ebbc81c595044173f [file] [log] [blame]
// 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.onData;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.longClick;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.intent.Intents.assertNoUnverifiedIntents;
import static androidx.test.espresso.intent.Intents.intended;
import static androidx.test.espresso.intent.Intents.intending;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
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.anything;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.chromium.android_webview.test.devui.DeveloperUiTestUtils.getClipBoardTextOnUiThread;
import static org.chromium.android_webview.test.devui.DeveloperUiTestUtils.withCount;
import android.app.Activity;
import android.app.Instrumentation.ActivityResult;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.os.Build;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import androidx.test.espresso.intent.matcher.IntentMatchers;
import androidx.test.espresso.intent.rule.IntentsTestRule;
import androidx.test.filters.MediumTest;
import org.junit.After;
import org.junit.Assume;
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.WebViewPackageError;
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 {
public static final PackageInfo FAKE_WEBVIEW_PACKAGE = new PackageInfo();
static {
FAKE_WEBVIEW_PACKAGE.packageName = "org.chromium.fake_webview";
FAKE_WEBVIEW_PACKAGE.versionCode = 123456789;
FAKE_WEBVIEW_PACKAGE.versionName = "999.888.777.666";
}
@Rule
public IntentsTestRule mRule =
new IntentsTestRule<MainActivity>(MainActivity.class, false, false);
@After
public void tearDown() {
// Activity is launched, i.e the test is not skipped.
if (mRule.getActivity() != null) {
// Tests are responsible for verifying every Intent they trigger.
assertNoUnverifiedIntents();
}
}
private void launchHomeFragment() {
Intent intent = new Intent();
intent.putExtra(MainActivity.FRAGMENT_ID_INTENT_EXTRA, MainActivity.FRAGMENT_ID_HOME);
mRule.launchActivity(intent);
// Stub all external intents, to avoid launching other apps (ex. system browser), has to be
// done after launching the activity.
intending(not(IntentMatchers.isInternal()))
.respondWith(new ActivityResult(Activity.RESULT_OK, null));
}
@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();
// No error messages is displayed.
onView(withId(R.id.main_error_view)).check(matches(not(isDisplayed())));
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);
onData(anything())
.atPosition(0)
.onChildView(withId(android.R.id.text1))
.check(matches(withText("WebView package")));
onData(anything())
.atPosition(0)
.onChildView(withId(android.R.id.text2))
.check(matches(withText(expectedWebViewPackageInfo)));
String expectedDeviceInfo =
String.format(Locale.US, "%s - %s", Build.MODEL, Build.FINGERPRINT);
onData(anything())
.atPosition(1)
.onChildView(withId(android.R.id.text1))
.check(matches(withText("Device info")));
onData(anything())
.atPosition(1)
.onChildView(withId(android.R.id.text2))
.check(matches(withText(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.
WebViewPackageHelper.setCurrentWebViewPackageForTesting(FAKE_WEBVIEW_PACKAGE);
launchHomeFragment();
onView(withId(R.id.main_info_list)).check(matches(withCount(3)));
String expectedWebViewPackageInfo =
String.format(Locale.US, "%s (%s/%s)", FAKE_WEBVIEW_PACKAGE.packageName,
FAKE_WEBVIEW_PACKAGE.versionName, FAKE_WEBVIEW_PACKAGE.versionCode);
onData(anything())
.atPosition(0)
.onChildView(withId(android.R.id.text1))
.check(matches(withText("WebView package")));
onData(anything())
.atPosition(0)
.onChildView(withId(android.R.id.text2))
.check(matches(withText(expectedWebViewPackageInfo)));
PackageInfo devUiPackage = WebViewPackageHelper.getContextPackageInfo(context);
String expectedDevUiInfo = String.format(Locale.US, "%s (%s/%s)", devUiPackage.packageName,
devUiPackage.versionName, devUiPackage.versionCode);
onData(anything())
.atPosition(1)
.onChildView(withId(android.R.id.text1))
.check(matches(withText("DevTools package")));
onData(anything())
.atPosition(1)
.onChildView(withId(android.R.id.text2))
.check(matches(withText(expectedDevUiInfo)));
String expectedDeviceInfo =
String.format(Locale.US, "%s - %s", Build.MODEL, Build.FINGERPRINT);
onData(anything())
.atPosition(2)
.onChildView(withId(android.R.id.text1))
.check(matches(withText("Device info")));
onData(anything())
.atPosition(2)
.onChildView(withId(android.R.id.text2))
.check(matches(withText(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.
WebViewPackageHelper.setCurrentWebViewPackageForTesting(FAKE_WEBVIEW_PACKAGE);
launchHomeFragment();
onView(withText("WebView package")).perform(longClick());
String expectedWebViewInfo =
String.format(Locale.US, "%s (%s/%s)", FAKE_WEBVIEW_PACKAGE.packageName,
FAKE_WEBVIEW_PACKAGE.versionName, FAKE_WEBVIEW_PACKAGE.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)));
}
@Test
@MediumTest
@Feature({"AndroidWebView"})
public void testDifferentWebViewPackageError_bannerMessage_postNougat() throws Throwable {
Assume.assumeTrue("This test verifies behavior introduced in Nougat and above",
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N);
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.
WebViewPackageHelper.setCurrentWebViewPackageForTesting(FAKE_WEBVIEW_PACKAGE);
launchHomeFragment();
String expectedErrorMessage = String.format(Locale.US,
WebViewPackageError.DIFFERENT_WEBVIEW_PROVIDER_ERROR_MESSAGE,
WebViewPackageHelper.loadLabel(context));
onView(withId(R.id.main_error_view)).check(matches(isDisplayed()));
onView(withId(R.id.error_text)).check(matches(withText(expectedErrorMessage)));
// Since the current provider is set to a fake package not an actual installed WebView
// provider, the UI should only offer to change the system WebView provider and should not
// offer to open the current WebView provider dev UI.
onView(withId(R.id.action_button))
.check(matches(withText(WebViewPackageError.CHANGE_WEBVIEW_PROVIDER_BUTTON_TEXT)))
.perform(click());
intended(IntentMatchers.hasAction(Settings.ACTION_WEBVIEW_SETTINGS));
}
@Test
@MediumTest
@Feature({"AndroidWebView"})
// Test the dialog shown when the WebView package error message is clicked.
public void testDifferentWebViewPackageError_dialog_postNougat() throws Throwable {
Assume.assumeTrue("This test verifies behavior introduced in Nougat and above",
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N);
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.
WebViewPackageHelper.setCurrentWebViewPackageForTesting(FAKE_WEBVIEW_PACKAGE);
launchHomeFragment();
String dialogExpectedMessage = String.format(Locale.US,
WebViewPackageError.DIFFERENT_WEBVIEW_PROVIDER_DIALOG_MESSAGE,
WebViewPackageHelper.loadLabel(context));
onView(withId(R.id.main_error_view)).perform(click());
onView(withText(dialogExpectedMessage)).check(matches(isDisplayed()));
// Since the current provider is set to a fake package not an actual installed WebView
// provider, the UI should only offer to change the system WebView provider and should not
// offer to open the current WebView provider dev UI.
onView(withId(android.R.id.button1)).check(matches(not(isDisplayed()))); // positive button
onView(withId(android.R.id.button2)).check(matches(not(isDisplayed()))); // negative button
// botton3 is dialog neutral button
onView(withId(android.R.id.button3))
.check(matches(withText(WebViewPackageError.CHANGE_WEBVIEW_PROVIDER_BUTTON_TEXT)))
.perform(click());
intended(IntentMatchers.hasAction(Settings.ACTION_WEBVIEW_SETTINGS));
}
@Test
@MediumTest
@Feature({"AndroidWebView"})
// Test that error message is shown when system's WebView provider package is different from dev
// UI's on a preNougat android versions (where WebView provider can't be changed).
public void testDifferentWebViewPackageError_bannerMessage_preNougat() throws Throwable {
Assume.assumeTrue("This test verifies pre-Nougat behavior",
Build.VERSION.SDK_INT < Build.VERSION_CODES.N);
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.
WebViewPackageHelper.setCurrentWebViewPackageForTesting(FAKE_WEBVIEW_PACKAGE);
launchHomeFragment();
String expectedErrorMessage = String.format(Locale.US,
WebViewPackageError.DIFFERENT_WEBVIEW_PROVIDER_ERROR_MESSAGE,
WebViewPackageHelper.loadLabel(context));
onView(withId(R.id.main_error_view)).check(matches(isDisplayed()));
onView(withId(R.id.error_text)).check(matches(withText(expectedErrorMessage)));
// Since the current provider is set to a fake package not an actual installed WebView
// provider, the UI shouldn't offer opening current WebView provider dev UI. It should not
// offer to change system WebView provider because this is not supported on pre-Nougat
// android versions.
onView(withId(R.id.action_button)).check(matches(not(isDisplayed())));
}
@Test
@MediumTest
@Feature({"AndroidWebView"})
// Test the dialog shown when the WebView package error message is clicked (where WebView
// provider can't be changed).
public void testDifferentWebViewPackageError_dialog_preNougat() throws Throwable {
Assume.assumeTrue("This test verifies pre-Nougat behavior",
Build.VERSION.SDK_INT < Build.VERSION_CODES.N);
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.
WebViewPackageHelper.setCurrentWebViewPackageForTesting(FAKE_WEBVIEW_PACKAGE);
launchHomeFragment();
String dialogExpectedMessage = String.format(Locale.US,
WebViewPackageError.DIFFERENT_WEBVIEW_PROVIDER_DIALOG_MESSAGE,
WebViewPackageHelper.loadLabel(context));
onView(withId(R.id.main_error_view)).perform(click());
onView(withText(dialogExpectedMessage)).check(matches(isDisplayed()));
// Since the current provider is set to a fake package not an actual installed WebView
// provider, the UI shouldn't offer opening current WebView provider dev UI. It should not
// offer to change system WebView provider because this is not supported on pre-Nougat
// android versions.
//
// There should be no buttons in the Dialog.
onView(withId(android.R.id.button1)).check(matches(not(isDisplayed())));
onView(withId(android.R.id.button2)).check(matches(not(isDisplayed())));
onView(withId(android.R.id.button3)).check(matches(not(isDisplayed())));
}
}