1 /* 2 * Copyright 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.example.androidx.webkit; 18 19 import static androidx.test.espresso.Espresso.onData; 20 import static androidx.test.espresso.Espresso.onView; 21 import static androidx.test.espresso.action.ViewActions.click; 22 import static androidx.test.espresso.assertion.ViewAssertions.matches; 23 import static androidx.test.espresso.matcher.ViewMatchers.withId; 24 import static androidx.test.espresso.matcher.ViewMatchers.withText; 25 import static androidx.test.espresso.web.assertion.WebViewAssertions.webMatches; 26 import static androidx.test.espresso.web.sugar.Web.onWebView; 27 import static androidx.test.espresso.web.webdriver.DriverAtoms.findElement; 28 import static androidx.test.espresso.web.webdriver.DriverAtoms.getText; 29 30 import static org.hamcrest.Matchers.containsString; 31 import static org.hamcrest.Matchers.equalTo; 32 import static org.hamcrest.Matchers.hasToString; 33 34 import android.content.Context; 35 36 import androidx.annotation.IdRes; 37 import androidx.annotation.StringRes; 38 import androidx.test.espresso.web.webdriver.Locator; 39 import androidx.test.platform.app.InstrumentationRegistry; 40 import androidx.webkit.WebViewFeature; 41 42 import org.jspecify.annotations.NonNull; 43 import org.junit.Assume; 44 45 /** 46 * Helper methods for testing. 47 */ 48 public final class WebkitTestHelpers { 49 50 /** 51 * Click on a MenuListView entry. 52 * 53 * @param resourceId string id of menu item 54 */ clickMenuListItemWithString(@tringRes int resourceId)55 public static void clickMenuListItemWithString(@StringRes int resourceId) { 56 Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); 57 onData(hasToString(equalTo(context.getString(resourceId)))).perform(click()); 58 } 59 60 /** 61 * Click on a view by id. 62 * 63 * @param viewId view to be clicked on 64 */ clickViewWithId(@dRes int viewId)65 public static void clickViewWithId(@IdRes int viewId) { 66 onView(withId(viewId)).perform(click()); 67 } 68 69 /** 70 * Asserts that a view displays the expected text. 71 * 72 * @param viewId the view to be checked 73 * @param stringResourceId the text's resource id 74 * @param formatArgs optional format args used by the text string 75 */ assertViewHasText(@dRes int viewId, @StringRes int stringResourceId, Object... formatArgs)76 public static void assertViewHasText(@IdRes int viewId, @StringRes int stringResourceId, 77 Object... formatArgs) { 78 Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); 79 onView(withId(viewId)) 80 .check(matches(withText(context.getString(stringResourceId, formatArgs)))); 81 } 82 83 /** 84 * Assert that an HTML element in the given WebView object contains the given text. 85 * 86 * @param webViewId ID of the WebView object that contains the HTML object. 87 * @param tagId the ID attribute of the HTML tag. 88 * @param text the expected text inside the HTML element. 89 */ assertHtmlElementContainsText(@dRes int webViewId, @NonNull String tagId, @NonNull String text)90 public static void assertHtmlElementContainsText(@IdRes int webViewId, 91 @NonNull String tagId, @NonNull String text) { 92 onWebView(withId(webViewId)) 93 .withElement(findElement(Locator.ID, tagId)) 94 .check(webMatches(getText(), 95 containsString(text))); 96 } 97 98 /** 99 * Throws {@link org.junit.AssumptionViolatedException} if the device does not support the 100 * particular feature, otherwise returns. 101 * 102 * <p> 103 * This provides a more descriptive message than a bare {@code assumeTrue} call. 104 * 105 * @param featureName the feature to be checked 106 */ assumeFeature(@ebViewFeature.WebViewSupportFeature String featureName)107 public static void assumeFeature(@WebViewFeature.WebViewSupportFeature String featureName) { 108 final String msg = "This device does not have the feature '" + featureName + "'"; 109 final boolean hasFeature = WebViewFeature.isFeatureSupported(featureName); 110 Assume.assumeTrue(msg, hasFeature); 111 } 112 113 /** 114 * Throws {@link org.junit.AssumptionViolatedException} if the device supports the 115 * particular feature, otherwise returns. 116 * 117 * <p> 118 * This provides a more descriptive message than a bare {@code assumeFalse} call. 119 * 120 * @param featureName the feature to be checked 121 */ assumeFeatureNotAvailable( @ebViewFeature.WebViewSupportFeature String featureName)122 public static void assumeFeatureNotAvailable( 123 @WebViewFeature.WebViewSupportFeature String featureName) { 124 final String msg = "This device has the feature '" + featureName + "'"; 125 final boolean hasFeature = WebViewFeature.isFeatureSupported(featureName); 126 Assume.assumeFalse(msg, hasFeature); 127 } 128 129 /** 130 * Throws {@link org.junit.AssumptionViolatedException} if the device does not support the 131 * particular startup feature, otherwise returns. 132 * 133 * <p> 134 * This provides a more descriptive message than a bare {@code assumeTrue} call. 135 * 136 * @param featureName the feature to be checked 137 */ assumeStartupFeature( @ebViewFeature.WebViewStartupFeature String featureName, Context context)138 public static void assumeStartupFeature( 139 @WebViewFeature.WebViewStartupFeature String featureName, 140 Context context) { 141 final String msg = "This device does not have the feature '" + featureName + "'"; 142 final boolean hasFeature = WebViewFeature.isStartupFeatureSupported(context, featureName); 143 Assume.assumeTrue(msg, hasFeature); 144 } 145 146 /** 147 * Throws {@link org.junit.AssumptionViolatedException} if the device supports the 148 * particular startup feature, otherwise returns. 149 * 150 * <p> 151 * This provides a more descriptive message than a bare {@code assumeFalse} call. 152 * 153 * @param featureName the feature to be checked 154 */ assumeStartupFeatureNotAvailable( @ebViewFeature.WebViewStartupFeature String featureName, Context context)155 public static void assumeStartupFeatureNotAvailable( 156 @WebViewFeature.WebViewStartupFeature String featureName, Context context) { 157 final String msg = "This device has the feature '" + featureName + "'"; 158 final boolean hasFeature = WebViewFeature.isStartupFeatureSupported(context, featureName); 159 Assume.assumeFalse(msg, hasFeature); 160 } 161 162 /** 163 * Javascript has to be enabled for espresso tests to work. 164 * 165 * @param webViewIds WebView IDs for which to enable JavaScript 166 */ enableJavaScript(@dRes int... webViewIds)167 public static void enableJavaScript(@IdRes int... webViewIds) { 168 for (int webViewId : webViewIds) { 169 onWebView(withId(webViewId)).forceJavascriptEnabled(); 170 } 171 } 172 173 // Do not instantiate this class. WebkitTestHelpers()174 private WebkitTestHelpers() {} 175 } 176