blob: 471829bb73ba2f6d9c43395f4878aede6c2a9599 [file] [log] [blame]
// Copyright 2017 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.chrome.browser.vr;
import static org.chromium.chrome.browser.vr.XrTestFramework.NATIVE_URLS_OF_INTEREST;
import static org.chromium.chrome.browser.vr.XrTestFramework.PAGE_LOAD_TIMEOUT_S;
import static org.chromium.chrome.browser.vr.XrTestFramework.POLL_TIMEOUT_LONG_MS;
import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.SystemClock;
import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.Restriction;
import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.payments.ui.PaymentRequestUI;
import org.chromium.chrome.browser.payments.ui.PaymentRequestUI.PaymentRequestObserverForTest;
import org.chromium.chrome.browser.vr.rules.ChromeTabbedActivityVrTestRule;
import org.chromium.chrome.browser.vr.util.NativeUiUtils;
import org.chromium.chrome.browser.vr.util.RenderTestUtils;
import org.chromium.chrome.browser.vr.util.VrBrowserTransitionUtils;
import org.chromium.chrome.browser.vr.util.VrShellDelegateUtils;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.util.ChromeTabUtils;
import org.chromium.chrome.test.util.RenderTestRule;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* End-to-end tests for native UI presentation in VR Browser mode.
*/
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-webvr"})
@Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE)
public class VrBrowserNativeUiTest {
// We explicitly instantiate a rule here instead of using parameterization since this class
// only ever runs in ChromeTabbedActivity.
@Rule
public ChromeTabbedActivityVrTestRule mVrTestRule = new ChromeTabbedActivityVrTestRule();
@Rule
public RenderTestRule mRenderTestRule =
new RenderTestRule("components/test/data/vr_browser_ui/render_tests");
private VrBrowserTestFramework mVrBrowserTestFramework;
private static final String TEST_PAGE_2D_URL =
VrBrowserTestFramework.getFileUrlForHtmlTestFile("test_navigation_2d_page");
@Before
public void setUp() throws Exception {
mVrBrowserTestFramework = new VrBrowserTestFramework(mVrTestRule);
VrBrowserTransitionUtils.forceEnterVrBrowserOrFail(POLL_TIMEOUT_LONG_MS);
}
/**
* Tests that URLs are not shown for native UI.
*/
@Test
@MediumTest
public void testUrlOnNativeUi()
throws IllegalArgumentException, InterruptedException, TimeoutException {
for (String url : NATIVE_URLS_OF_INTEREST) {
mVrTestRule.loadUrl(url, PAGE_LOAD_TIMEOUT_S);
Assert.assertFalse("URL is being shown for native page " + url,
TestVrShellDelegate.isDisplayingUrlForTesting());
}
}
/**
* Tests that URLs are shown for non-native UI.
*/
@Test
@MediumTest
public void testUrlOnNonNativeUi()
throws IllegalArgumentException, InterruptedException, TimeoutException {
mVrTestRule.loadUrl(TEST_PAGE_2D_URL, PAGE_LOAD_TIMEOUT_S);
Assert.assertTrue("URL is not being show for non-native page",
TestVrShellDelegate.isDisplayingUrlForTesting());
}
/**
* Tests that the Payment Request API is supressed in the VR Browser and its native UI does not
* show. Automation of a manual test from https://crbug.com/862162.
*/
@Test
@MediumTest
public void testPaymentRequest() throws InterruptedException {
// We can't request payment on file:// URLs, so use a local server.
mVrBrowserTestFramework.loadUrlAndAwaitInitialization(
mVrBrowserTestFramework.getEmbeddedServerUrlForHtmlTestFile("test_payment_request"),
PAGE_LOAD_TIMEOUT_S);
// Set up an observer so we'll know if the payment request is shown.
AtomicBoolean requestShown = new AtomicBoolean(false);
PaymentRequestObserverForTest observer = new PaymentRequestObserverForTest() {
@Override
public void onPaymentRequestReadyForInput(PaymentRequestUI ui) {
requestShown.set(true);
}
@Override
public void onPaymentRequestReadyToPay(PaymentRequestUI ui) {}
@Override
public void onPaymentRequestSelectionChecked(PaymentRequestUI ui) {}
@Override
public void onPaymentRequestResultReady(PaymentRequestUI ui) {}
};
PaymentRequestUI.setPaymentRequestObserverForTest(observer);
// Request payment and wait for the promise to auto-reject.
mVrBrowserTestFramework.executeStepAndWait("stepRequestPayment()");
// Ensure that the native UI wasn't shown even though the request was rejected.
// Need to sleep for a bit in order to allow the UI to show if it's going to.
SystemClock.sleep(1000);
Assert.assertFalse("Native Payment Request UI was shown", requestShown.get());
// Ensure we weren't somehow kicked out of VR from this.
Assert.assertTrue("Payment request caused VR exit",
VrShellDelegateUtils.getDelegateInstance().isVrEntryComplete());
mVrBrowserTestFramework.endTest();
}
/**
* Tests that the current URL is automatically populated when opening up the omnibox text
* entry mode.
*/
@Test
@MediumTest
public void testOmniboxContainsCurrentUrl() throws InterruptedException {
// This is a really roundabout way of checking the automatically populated text in the
// omnibox without having to add yet more native plumbing to read the current text.
// The idea is that by deleting the last four characters, we should be left with just
// "chrome://", so we can then input another chrome:// URL based off that. The only way
// the second navigation will complete successfully is if the omnibox had "chrome://gpu/"
// when we opened it.
NativeUiUtils.enableMockedKeyboard();
mVrTestRule.loadUrl("chrome://gpu/");
NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
// Click near the righthand side of the text input field so the cursor is at the end instead
// of selecting the existing text.
NativeUiUtils.clickElementAndWaitForUiQuiescence(
UserFriendlyElementName.OMNIBOX_TEXT_FIELD, new PointF(0.4f, 0.0f));
// Delete "gpu/".
for (int i = 0; i < 4; ++i) {
NativeUiUtils.inputBackspace();
}
// Wait for suggestions to change so that our navigation succeeds.
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
() -> { NativeUiUtils.inputString("version/"); });
NativeUiUtils.inputEnter();
ChromeTabUtils.waitForTabPageLoaded(
mVrTestRule.getActivity().getActivityTab(), "chrome://version/");
}
/**
* Tests that the the omnibox automatically scrolls the text when it is longer than the box
* can fit.
*/
@Test
@MediumTest
public void testOmniboxTextScrolls() throws InterruptedException {
// This is a roundabout way of checking that the text scrolls. By inputting a long string,
// clicking near the beginning and deleting a character, we can check that the text scrolled
// by checking whether a character at the beginning of the string was deleted or not - if
// the text scrolled, then a character later in the string should have been deleted.
NativeUiUtils.enableMockedKeyboard();
NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
String expectedString = "chrome://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
NativeUiUtils.inputString(expectedString + "a");
// Click near the lefthand side of the input field to place the cursor near the beginning
// of the visible part of the string.
NativeUiUtils.clickElementAndWaitForUiQuiescence(
UserFriendlyElementName.OMNIBOX_TEXT_FIELD, new PointF(-0.45f, 0.0f));
// We expect this to delete an "a" instead of anything in "chrome://". Do so and wait for
// the suggestions to appear.
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
() -> { NativeUiUtils.inputBackspace(); });
NativeUiUtils.inputEnter();
// Navigating automatically appends a "/".
ChromeTabUtils.waitForTabPageLoaded(
mVrTestRule.getActivity().getActivityTab(), expectedString + "/");
}
/**
* Tests that the omnibox automatically clears any text that gets input but not committed.
*/
@Test
@MediumTest
public void testOmniboxClearsUncommittedText() throws InterruptedException {
// Similar to testOmniboxContainsCurrentUrl, we check that the uncommitted text is not
// present the second time we open the omnibox by deleting a number of characters from
// the expected text and entering additional text.
NativeUiUtils.enableMockedKeyboard();
NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
// Input text and close the omnibox without committing.
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
() -> { NativeUiUtils.inputString("chrome://version/"); });
NativeUiUtils.clickElementAndWaitForUiQuiescence(
UserFriendlyElementName.OMNIBOX_CLOSE_BUTTON, new PointF());
NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
// Click near the righthand side of the text input field so the cursor is at the end instead
// of selecting the existing text.
NativeUiUtils.clickElementAndWaitForUiQuiescence(
UserFriendlyElementName.OMNIBOX_TEXT_FIELD, new PointF(0.4f, 0.0f));
// Delete "about:blank".
for (int i = 0; i < 11; ++i) {
NativeUiUtils.inputBackspace();
}
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.SUGGESTION_BOX, true /* visibile */,
() -> { NativeUiUtils.inputString("chrome://version/"); });
NativeUiUtils.inputEnter();
// This should only succeed if the original "chrome://version/" we input is not present -
// if it is, we'll end up navigating to "chromechrome://version/".
ChromeTabUtils.waitForTabPageLoaded(
mVrTestRule.getActivity().getActivityTab(), "chrome://version/");
}
/**
* Tests that omnibox autocompletion is functional.
*/
@Test
@MediumTest
public void testOmniboxAutocompletion() throws InterruptedException {
// At least with chrome:// URLs, autocompletion only kicks in when there's one valid option
// left. So, test that:
// 1. Autocompletion works if only one option is available.
// 2. Autocompletion updates successfully if additional characters are added.
// 3. Autocompletion doesn't work if multiple options are available.
// 4. Autocompletion cancels if a non-matching character is input.
NativeUiUtils.enableMockedKeyboard();
// Test that autocompletion works with only one option left.
NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
// This should autocomplete to "chrome://version".
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
() -> { NativeUiUtils.inputString("chrome://v"); });
NativeUiUtils.inputEnter();
ChromeTabUtils.waitForTabPageLoaded(
mVrTestRule.getActivity().getActivityTab(), "chrome://version/");
// Navigate away from chrome://version/ so waitForTabPageLoaded doesn't no-op the next time.
mVrTestRule.loadUrl("about:blank");
// Test that autocompletion updates successfully when entering more text.
NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
() -> { NativeUiUtils.inputString("chrome://v"); });
NativeUiUtils.inputString("e");
// Since suggestions are already visible, we need to wait for suggestions to update via
// a glorified sleep instead of waiting for suggestions to appear.
NativeUiUtils.waitNumFrames(NativeUiUtils.NUM_FRAMES_FOR_SUGGESTION_UPDATE);
NativeUiUtils.inputEnter();
ChromeTabUtils.waitForTabPageLoaded(
mVrTestRule.getActivity().getActivityTab(), "chrome://version/");
// Test that autocompletion doesn't work with more than one option available.
NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
// This could be either "chrome://net-export" or "chrome://net-internals", so it shouldn't
// autocomplete to anything.
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
() -> { NativeUiUtils.inputString("chrome://net-"); });
NativeUiUtils.inputEnter();
ChromeTabUtils.waitForTabPageLoaded(
mVrTestRule.getActivity().getActivityTab(), "chrome://net-/");
// Test that autocompletion cancels if a non-matching character is input.
NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
// This should autocomplete to "chrome://version".
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
() -> { NativeUiUtils.inputString("chrome://v"); });
NativeUiUtils.inputString("a");
NativeUiUtils.waitNumFrames(NativeUiUtils.NUM_FRAMES_FOR_SUGGESTION_UPDATE);
NativeUiUtils.inputEnter();
ChromeTabUtils.waitForTabPageLoaded(
mVrTestRule.getActivity().getActivityTab(), "chrome://va/");
}
/**
* Tests that the keyboard appears when clicking on the URL bar.
* Also contains a regression test for https://crbug.com/874671 where inputting text into the
* URL bar would cause a browser crash.
*/
@Test
@LargeTest
@Feature({"Browser", "RenderTest"})
public void testKeyboardAppearsOnUrlBarClick()
throws InterruptedException, TimeoutException, IOException {
NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
// For whatever reason, the laser has a lot of random noise (not visible to an actual user)
// when the keyboard is present on certain OS/hardware configurations (currently known to
// happen on Pixel XL w/ N). So, allow pixels to differ by a small amount without failing.
mRenderTestRule.setPixelDiffThreshold(5);
RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
"keyboard_visible_browser_ui", mRenderTestRule);
// Regression test for https://crbug.com/874671
// We need to use the VrCore-side emulated controller because the keyboard isn't a UI
// element, meaning we can't specify it as a click target for the Chrome-side controller.
NativeUiUtils.revertToRealInput();
// Point at the keyboard and click an arbitrary key
EmulatedVrController controller = new EmulatedVrController(mVrTestRule.getActivity());
controller.recenterView();
controller.moveControllerInstant(0.0f, -0.259f, -0.996f, -0.0f);
// Spam clicks to ensure we're getting one in.
for (int i = 0; i < 5; i++) {
controller.performControllerClick();
}
}
/**
* Tests that the overflow menu appears when the overflow menu button is clicked.
*/
@Test
@LargeTest
@Feature({"Browser", "RenderTest"})
public void testOverflowMenuAppears()
throws InterruptedException, TimeoutException, IOException {
// TODO(https://crbug.com/930840): Remove this when the weird gradient behavior is fixed.
mRenderTestRule.setPixelDiffThreshold(2);
NativeUiUtils.clickElementAndWaitForUiQuiescence(
UserFriendlyElementName.OVERFLOW_MENU, new PointF());
RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
"overflow_menu_visible_browser_ui", mRenderTestRule);
}
/**
* Tests that the page info popup appears when the security token in the URL bar is clicked.
*/
@Test
@LargeTest
@Feature({"Browser", "RenderTest"})
public void testPageInfoAppearsOnSecurityTokenClick()
throws InterruptedException, TimeoutException, IOException {
NativeUiUtils.clickElementAndWaitForUiQuiescence(
UserFriendlyElementName.PAGE_INFO_BUTTON, new PointF());
// Workaround for https://crbug.com/893291, where the text doesn't actually show up until a
// bit after the element is drawn.
SystemClock.sleep(1000);
NativeUiUtils.waitForUiQuiescence();
RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
"page_info_visible_browser_ui", mRenderTestRule);
}
/**
* Tests that data URLs have the data portion of the URL emphasized like in 2D browsing.
*/
@Test
@LargeTest
@Feature({"Browser", "RenderTest"})
public void testDataUrlEmphasis() throws InterruptedException, IOException {
NativeUiUtils.enableMockedInput();
mVrTestRule.loadUrl("data:,Hello%2C%20World!", PAGE_LOAD_TIMEOUT_S);
NativeUiUtils.waitForUiQuiescence();
RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
"data_url_emphasis_browser_ui", mRenderTestRule);
}
/**
* Tests that file URLs have the entire URL emphasized like in 2D browsing.
*/
@Test
@LargeTest
@Feature({"Browser", "RenderTest"})
public void testFileUrlEmphasis() throws InterruptedException, IOException {
NativeUiUtils.enableMockedInput();
mVrTestRule.loadUrl(VrBrowserTestFramework.getFileUrlForHtmlTestFile("2d_permission_page"),
PAGE_LOAD_TIMEOUT_S);
NativeUiUtils.waitForUiQuiescence();
RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
"file_url_emphasis_browser_ui", mRenderTestRule);
}
/**
* Tests that the reposition bar does not appear if the keyboard is open.
*/
@Test
@MediumTest
@Feature({"Browser", "RenderTest"})
public void testRepositionBarDoesNotAppearWithKeyboardOpen()
throws InterruptedException, TimeoutException, IOException {
// Use the mock keyboard so it doesn't show, reducing the chance of flakes due to AA.
NativeUiUtils.enableMockedKeyboard();
mVrTestRule.loadUrl(
VrBrowserTestFramework.getFileUrlForHtmlTestFile("generic_text_entry_page"),
PAGE_LOAD_TIMEOUT_S);
NativeUiUtils.clickContentNode(
"textfield", new PointF(), 1 /* numClicks */, mVrBrowserTestFramework);
NativeUiUtils.waitForUiQuiescence();
NativeUiUtils.hoverElement(UserFriendlyElementName.CONTENT_QUAD, new PointF(0.0f, 0.55f));
NativeUiUtils.waitForUiQuiescence();
// Due to the way the repositioner works, the reposition bar is technically always visible
// in the element hierarchy, so we can't just assert that it's invisible. Instead, we have
// to resort to pixel diffing.
RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
"reposition_bar_keyboard_open", mRenderTestRule);
}
/*
* Tests that hovering over various elements in the URL bar looks as expected.
*/
@Test
@LargeTest
@Feature({"Browser", "RenderTest"})
public void testUrlBarHovering() throws InterruptedException, TimeoutException, IOException {
testUrlBarHoveringImpl(false);
}
/**
* Tests that hovering over various elements in the URL bar looks as expected while in Incognito
* mode.
*/
@Test
@LargeTest
@Feature({"Browser", "RenderTest"})
public void testUrlBarHoveringIncognito()
throws InterruptedException, TimeoutException, IOException {
mVrBrowserTestFramework.openIncognitoTab("about:blank");
testUrlBarHoveringImpl(true);
}
private void testUrlBarHoveringImpl(boolean incognito)
throws InterruptedException, TimeoutException, IOException {
// Back button hovering doesn't do anything unless the back button is actually active. so
// navigate to do that.
mVrTestRule.loadUrl("chrome://version/", PAGE_LOAD_TIMEOUT_S);
// Back button.
NativeUiUtils.hoverElement(UserFriendlyElementName.BACK_BUTTON, new PointF());
NativeUiUtils.waitForUiQuiescence();
RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
generateRenderTestIdentifier("back_button_hover", incognito), mRenderTestRule);
// Security icon.
NativeUiUtils.hoverElement(UserFriendlyElementName.PAGE_INFO_BUTTON, new PointF());
NativeUiUtils.waitForUiQuiescence();
RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
generateRenderTestIdentifier("security_icon_hover", incognito), mRenderTestRule);
// URL bar.
NativeUiUtils.hoverElement(UserFriendlyElementName.URL, new PointF());
NativeUiUtils.waitForUiQuiescence();
RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
generateRenderTestIdentifier("url_bar_hover", incognito), mRenderTestRule);
// Overflow menu.
NativeUiUtils.hoverElement(UserFriendlyElementName.OVERFLOW_MENU, new PointF());
NativeUiUtils.waitForUiQuiescence();
RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
generateRenderTestIdentifier("overflow_menu_hover", incognito), mRenderTestRule);
}
/**
* Tests that hovering over various elements in the overflow menu looks as expected.
*/
@Test
@LargeTest
@Feature({"Browser", "RenderTest"})
public void testOverflowMenuHovering()
throws InterruptedException, TimeoutException, IOException {
testOverflowMenuHoveringImpl(false);
}
/**
* Tests that hovering over various elements in the overflow menu looks as expected while in
* Incognito mode.
*/
@Test
@LargeTest
@Feature({"Browser", "RenderTest"})
public void testOverflowMenuHoveringIncognito()
throws InterruptedException, TimeoutException, IOException {
mVrBrowserTestFramework.openIncognitoTab("about:blank");
testOverflowMenuHoveringImpl(true);
}
private void testOverflowMenuHoveringImpl(boolean incognito)
throws InterruptedException, TimeoutException, IOException {
// TODO(https://crbug.com/930840): Remove this when the weird gradient behavior is fixed.
mRenderTestRule.setPixelDiffThreshold(2);
// The forward button only has a hover state if the button is actually active, so navigate
// a bit.
mVrTestRule.loadUrl("chrome://version/", PAGE_LOAD_TIMEOUT_S);
VrBrowserTransitionUtils.navigateBack();
ChromeTabUtils.waitForTabPageLoaded(
mVrTestRule.getActivity().getActivityTab(), "about:blank");
// Make the overflow menu appear.
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.RELOAD_BUTTON, true /* visible */, () -> {
NativeUiUtils.clickElement(UserFriendlyElementName.OVERFLOW_MENU, new PointF());
});
// Reload button.
NativeUiUtils.hoverElement(UserFriendlyElementName.RELOAD_BUTTON, new PointF());
NativeUiUtils.waitForUiQuiescence();
RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
generateRenderTestIdentifier("reload_button_hover", incognito), mRenderTestRule);
// Forward Button.
NativeUiUtils.hoverElement(UserFriendlyElementName.FORWARD_BUTTON, new PointF());
NativeUiUtils.waitForUiQuiescence();
RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
generateRenderTestIdentifier("forward_button_hover", incognito), mRenderTestRule);
// New Incognito tab button/close Incognito tabs button.
if (incognito) {
NativeUiUtils.hoverElement(UserFriendlyElementName.CLOSE_INCOGNITO_TABS, new PointF());
NativeUiUtils.waitForUiQuiescence();
RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
generateRenderTestIdentifier("close_incognito_tabs_hover", incognito),
mRenderTestRule);
} else {
NativeUiUtils.hoverElement(UserFriendlyElementName.NEW_INCOGNITO_TAB, new PointF());
NativeUiUtils.waitForUiQuiescence();
RenderTestUtils.dumpAndCompare(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
generateRenderTestIdentifier("new_incognito_tab_hover", incognito),
mRenderTestRule);
}
}
private String generateRenderTestIdentifier(String name, boolean incognito) {
return name + (incognito ? "_incognito" : "") + "_browser_ui";
}
/**
* Tests that highlighting suggestions looks correct and that clicking just outside of the
* suggestion doesn't trigger its onclick. Regression test for https://crbug.com/799593.
*/
@Test
@MediumTest
@Feature({"Browser", "RenderTest"})
public void testSuggestionHovering()
throws InterruptedException, TimeoutException, IOException {
// Input some text to get suggestions.
NativeUiUtils.enableMockedKeyboard();
NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF());
NativeUiUtils.performActionAndWaitForVisibilityStatus(
UserFriendlyElementName.SUGGESTION_BOX, true /* visible */,
() -> { NativeUiUtils.inputString("chrome://"); });
// We need to crop the image before comparing to avoid the blinking cursor in the omnibox.
// So, crop roughly around the suggestion box. This tends to chop off the bottom half of
// the bottom suggestion on larger devices, but that's preferable to accidentally getting
// the omnibox in the image, and should still be sufficient to catch the intended issues
// (hover states, clicks actually registering).
final RectF cropBounds = new RectF(0.1f, 0.4f, 0.6f, 0.625f);
// There should be three suggestions, so hover the top then the middle one to ensure that
// the hover effect properly moves between the two.
NativeUiUtils.hoverElement(UserFriendlyElementName.SUGGESTION_BOX, new PointF(0.0f, 0.3f));
NativeUiUtils.waitForUiQuiescence();
RenderTestUtils.dumpAndCompareWithCrop(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
"suggestion_hovering_top", cropBounds, mRenderTestRule);
NativeUiUtils.hoverElement(UserFriendlyElementName.SUGGESTION_BOX, new PointF());
NativeUiUtils.waitForUiQuiescence();
RenderTestUtils.dumpAndCompareWithCrop(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
"suggestion_hovering_middle", cropBounds, mRenderTestRule);
// Ensure that the hover effect disappears when slightly to the right of the suggestion and
// that clicking doesn't do anything.
NativeUiUtils.clickElementAndWaitForUiQuiescence(
UserFriendlyElementName.SUGGESTION_BOX, new PointF(0.51f, 0.0f));
RenderTestUtils.dumpAndCompareWithCrop(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
"suggestion_clicking_right", cropBounds, mRenderTestRule);
// Again on the left side.
NativeUiUtils.hoverElement(UserFriendlyElementName.SUGGESTION_BOX, new PointF());
NativeUiUtils.clickElementAndWaitForUiQuiescence(
UserFriendlyElementName.SUGGESTION_BOX, new PointF(-0.51f, 0.0f));
RenderTestUtils.dumpAndCompareWithCrop(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
"suggestion_clicking_left", cropBounds, mRenderTestRule);
// Again above the top suggestion.
NativeUiUtils.hoverElement(UserFriendlyElementName.SUGGESTION_BOX, new PointF(0.0f, 0.3f));
NativeUiUtils.clickElementAndWaitForUiQuiescence(
UserFriendlyElementName.SUGGESTION_BOX, new PointF(0.0f, 0.51f));
RenderTestUtils.dumpAndCompareWithCrop(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
"suggestion_clicking_top", cropBounds, mRenderTestRule);
// Again below the bottom suggestion.
NativeUiUtils.hoverElement(UserFriendlyElementName.SUGGESTION_BOX, new PointF(0.0f, -0.3f));
// For some reason, we have to aim slightly more offset than in other directions in order
// to not actually hit the suggestion (probably due to the way we calculate where to click
// not taking into account where the controller is, so hit testing can produce a slightly
// different result).
NativeUiUtils.clickElementAndWaitForUiQuiescence(
UserFriendlyElementName.SUGGESTION_BOX, new PointF(0.0f, -0.55f));
RenderTestUtils.dumpAndCompareWithCrop(NativeUiUtils.FRAME_BUFFER_SUFFIX_BROWSER_UI,
"suggestion_clicking_bottom", cropBounds, mRenderTestRule);
}
}