Commit 3006c15b authored by Colin Blundell's avatar Colin Blundell Committed by Commit Bot

[WebLayer] Add test of infobar scrolling

This CL adds a basic test that the infobar container responds to
scrolling as expected in WebLayer. To enable this test we also made the
following changes:

- Factored out some support for setting up scrolling in tests from
  BrowserControlsTest.java for reuse
- Extended EventUtils.java's simulation of dragging to post the
  finger down/move/up events sequentially. This change is necessary to
  get the scroll events to be fully processed within //content and
  ripple out to the infobar container.

Bug: 1093846
Change-Id: Ifb94f33c498a13d711336165029370e259e330c0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2247894
Commit-Queue: Colin Blundell <blundell@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#780235}
parent 02385f95
...@@ -72,6 +72,7 @@ android_library("weblayer_private_java_tests") { ...@@ -72,6 +72,7 @@ android_library("weblayer_private_java_tests") {
"src/org/chromium/weblayer/test/ResourceLoadingTest.java", "src/org/chromium/weblayer/test/ResourceLoadingTest.java",
] ]
deps = [ deps = [
":weblayer_java_private_test_support",
":weblayer_java_test_support", ":weblayer_java_test_support",
"//base:base_java", "//base:base_java",
"//base:base_java_test_support", "//base:base_java_test_support",
...@@ -118,6 +119,21 @@ android_library("weblayer_java_test_support") { ...@@ -118,6 +119,21 @@ android_library("weblayer_java_test_support") {
] ]
} }
android_library("weblayer_java_private_test_support") {
testonly = true
sources = [ "src/org/chromium/weblayer/test/BrowserControlsHelper.java" ]
deps = [
":weblayer_java_test_support",
"//base:base_java",
"//base:base_java_test_support",
"//content/public/test/android:content_java_test_support",
"//third_party/junit:junit",
"//weblayer/public/java",
"//weblayer/public/javatestutil:test_java",
"//weblayer/shell/android:weblayer_shell_java",
]
}
template("weblayer_instrumentation") { template("weblayer_instrumentation") {
instrumentation_test_apk(target_name) { instrumentation_test_apk(target_name) {
forward_variables_from(invoker, "*") forward_variables_from(invoker, "*")
......
// 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.weblayer.test;
import android.os.RemoteException;
import android.view.View;
import org.junit.Assert;
import org.chromium.base.CommandLine;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.weblayer.Tab;
import org.chromium.weblayer.TestWebLayer;
import org.chromium.weblayer.shell.InstrumentationActivity;
/**
* Helper class for tests that interact with browser controls. Such tests should add the following
* above "public class FooTest":
* @CommandLineFlags.Add("enable-features=ImmediatelyHideBrowserControlsForTest")
*/
public final class BrowserControlsHelper {
private InstrumentationActivity mActivity;
// Height of the top-view. Set in waitForBrowserControlsInitialization().
private int mTopViewHeight;
// Blocks until browser controls are fully initialized. Should only be created in a test's
// setUp() method; see BrowserControlsHelper#createInSetUp().
private BrowserControlsHelper(InstrumentationActivity activity) throws Throwable {
Assert.assertTrue(CommandLine.isInitialized());
Assert.assertTrue(CommandLine.getInstance().hasSwitch("enable-features"));
String enabledFeatures = CommandLine.getInstance().getSwitchValue("enable-features");
Assert.assertTrue(enabledFeatures.contains("ImmediatelyHideBrowserControlsForTest"));
mActivity = activity;
waitForBrowserControlsInitialization();
}
private Tab getActiveTab() {
return mActivity.getBrowser().getActiveTab();
}
private TestWebLayer getTestWebLayer() {
return TestWebLayer.getTestWebLayer(mActivity.getApplicationContext());
}
void waitForBrowserControlsViewToBeVisible(View v) {
CriteriaHelper.pollUiThread(() -> {
Assert.assertTrue(v.getHeight() > 0);
Assert.assertEquals(View.VISIBLE, v.getVisibility());
});
}
// See TestWebLayer.waitForBrowserControlsMetadataState() for details on this.
void waitForBrowserControlsMetadataState(int top, int bottom) throws Exception {
CallbackHelper helper = new CallbackHelper();
TestThreadUtils.runOnUiThreadBlocking(() -> {
try {
getTestWebLayer().waitForBrowserControlsMetadataState(
getActiveTab(), top, bottom, () -> { helper.notifyCalled(); });
} catch (RemoteException e) {
throw new RuntimeException(e);
}
});
helper.waitForFirst();
}
// Ensures that browser controls are fully initialized and ready for scrolls to be processed.
private void waitForBrowserControlsInitialization() throws Throwable {
// Poll until the top view becomes visible.
waitForBrowserControlsViewToBeVisible(mActivity.getTopContentsContainer());
TestThreadUtils.runOnUiThreadBlocking(() -> {
mTopViewHeight = mActivity.getTopContentsContainer().getHeight();
Assert.assertTrue(mTopViewHeight > 0);
});
// Wait for cc to see the top-controls height.
waitForBrowserControlsMetadataState(mTopViewHeight, 0);
}
// Creates a BrowserControlsHelper instance and blocks until browser controls are fully
// initialized. Should be called from a test's setUp() method.
static BrowserControlsHelper createAndBlockUntilBrowserControlsInitializedInSetUp(
InstrumentationActivity activity) throws Throwable {
return new BrowserControlsHelper(activity);
}
// Returns the height of the top view.
int getTopViewHeight() {
return mTopViewHeight;
}
}
...@@ -19,7 +19,6 @@ import org.junit.Rule; ...@@ -19,7 +19,6 @@ import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.base.test.util.MinAndroidSdkLevel;
import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.Criteria;
...@@ -39,6 +38,8 @@ public class BrowserControlsTest { ...@@ -39,6 +38,8 @@ public class BrowserControlsTest {
public InstrumentationActivityTestRule mActivityTestRule = public InstrumentationActivityTestRule mActivityTestRule =
new InstrumentationActivityTestRule(); new InstrumentationActivityTestRule();
private BrowserControlsHelper mBrowserControlsHelper;
// Height of the top-view. Set in setUp(). // Height of the top-view. Set in setUp().
private int mTopViewHeight; private int mTopViewHeight;
// Height from the page (obtained using getVisiblePageHeight()) with the top-controls. // Height from the page (obtained using getVisiblePageHeight()) with the top-controls.
...@@ -56,13 +57,6 @@ public class BrowserControlsTest { ...@@ -56,13 +57,6 @@ public class BrowserControlsTest {
return mActivityTestRule.getActivity().getBrowser().getActiveTab(); return mActivityTestRule.getActivity().getBrowser().getActiveTab();
} }
private void waitForBrowserControlsViewToBeVisible(View v) {
CriteriaHelper.pollUiThread(() -> {
Assert.assertTrue(v.getHeight() > 0);
Assert.assertEquals(View.VISIBLE, v.getVisibility());
});
}
private TestWebLayer getTestWebLayer() { private TestWebLayer getTestWebLayer() {
return TestWebLayer.getTestWebLayer( return TestWebLayer.getTestWebLayer(
mActivityTestRule.getActivity().getApplicationContext()); mActivityTestRule.getActivity().getApplicationContext());
...@@ -88,35 +82,16 @@ public class BrowserControlsTest { ...@@ -88,35 +82,16 @@ public class BrowserControlsTest {
}); });
} }
// See TestWebLayer.waitForBrowserControlsMetadataState() for details on this.
private void waitForBrowserControlsMetadataState(int top, int bottom) throws Exception {
CallbackHelper helper = new CallbackHelper();
TestThreadUtils.runOnUiThreadBlocking(() -> {
try {
getTestWebLayer().waitForBrowserControlsMetadataState(
getActiveTab(), top, bottom, () -> { helper.notifyCalled(); });
} catch (RemoteException e) {
throw new RuntimeException(e);
}
});
helper.waitForCallback(0);
}
@Before @Before
public void setUp() throws Throwable { public void setUp() throws Throwable {
final String url = mActivityTestRule.getTestDataURL("tall_page.html"); final String url = mActivityTestRule.getTestDataURL("tall_page.html");
InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(url); InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(url);
// Poll until the top view becomes visible. mBrowserControlsHelper =
waitForBrowserControlsViewToBeVisible(activity.getTopContentsContainer()); BrowserControlsHelper.createAndBlockUntilBrowserControlsInitializedInSetUp(
TestThreadUtils.runOnUiThreadBlocking(() -> { activity);
mTopViewHeight = activity.getTopContentsContainer().getHeight();
Assert.assertTrue(mTopViewHeight > 0);
});
// Wait for cc to see the top-controls height.
waitForBrowserControlsMetadataState(mTopViewHeight, 0);
mTopViewHeight = mBrowserControlsHelper.getTopViewHeight();
mPageHeightWithTopView = getVisiblePageHeight(); mPageHeightWithTopView = getVisiblePageHeight();
} }
...@@ -133,7 +108,7 @@ public class BrowserControlsTest { ...@@ -133,7 +108,7 @@ public class BrowserControlsTest {
return view; return view;
}); });
waitForBrowserControlsViewToBeVisible(bottomView); mBrowserControlsHelper.waitForBrowserControlsViewToBeVisible(bottomView);
int bottomViewHeight = int bottomViewHeight =
TestThreadUtils.runOnUiThreadBlocking(() -> { return bottomView.getHeight(); }); TestThreadUtils.runOnUiThreadBlocking(() -> { return bottomView.getHeight(); });
...@@ -144,7 +119,8 @@ public class BrowserControlsTest { ...@@ -144,7 +119,8 @@ public class BrowserControlsTest {
// Wait for cc to see the bottom height. This is very important, as scrolling is gated by // Wait for cc to see the bottom height. This is very important, as scrolling is gated by
// cc getting the bottom height. // cc getting the bottom height.
waitForBrowserControlsMetadataState(mTopViewHeight, bottomViewHeight); mBrowserControlsHelper.waitForBrowserControlsMetadataState(
mTopViewHeight, bottomViewHeight);
// Adding a bottom view should change the page height. // Adding a bottom view should change the page height.
CriteriaHelper.pollInstrumentationThread( CriteriaHelper.pollInstrumentationThread(
...@@ -166,7 +142,7 @@ public class BrowserControlsTest { ...@@ -166,7 +142,7 @@ public class BrowserControlsTest {
EventUtils.simulateDragFromCenterOfView( EventUtils.simulateDragFromCenterOfView(
activity.getWindow().getDecorView(), 0, maxViewsHeight); activity.getWindow().getDecorView(), 0, maxViewsHeight);
waitForBrowserControlsViewToBeVisible(bottomView); mBrowserControlsHelper.waitForBrowserControlsViewToBeVisible(bottomView);
CriteriaHelper.pollInstrumentationThread( CriteriaHelper.pollInstrumentationThread(
() -> Assert.assertEquals(getVisiblePageHeight(), pageHeightWithTopAndBottomViews)); () -> Assert.assertEquals(getVisiblePageHeight(), pageHeightWithTopAndBottomViews));
} }
...@@ -181,7 +157,7 @@ public class BrowserControlsTest { ...@@ -181,7 +157,7 @@ public class BrowserControlsTest {
TestThreadUtils.runOnUiThreadBlocking(() -> { activity.getBrowser().setTopView(null); }); TestThreadUtils.runOnUiThreadBlocking(() -> { activity.getBrowser().setTopView(null); });
// Wait for cc to see the top-controls height change. // Wait for cc to see the top-controls height change.
waitForBrowserControlsMetadataState(0, 0); mBrowserControlsHelper.waitForBrowserControlsMetadataState(0, 0);
int pageHeightWithNoTopView = getVisiblePageHeight(); int pageHeightWithNoTopView = getVisiblePageHeight();
Assert.assertNotEquals(pageHeightWithNoTopView, mPageHeightWithTopView); Assert.assertNotEquals(pageHeightWithNoTopView, mPageHeightWithTopView);
...@@ -194,12 +170,12 @@ public class BrowserControlsTest { ...@@ -194,12 +170,12 @@ public class BrowserControlsTest {
return view; return view;
}); });
waitForBrowserControlsViewToBeVisible(bottomView); mBrowserControlsHelper.waitForBrowserControlsViewToBeVisible(bottomView);
int bottomViewHeight = int bottomViewHeight =
TestThreadUtils.runOnUiThreadBlocking(() -> { return bottomView.getHeight(); }); TestThreadUtils.runOnUiThreadBlocking(() -> { return bottomView.getHeight(); });
Assert.assertTrue(bottomViewHeight > 0); Assert.assertTrue(bottomViewHeight > 0);
// Wait for cc to see the bottom-controls height change. // Wait for cc to see the bottom-controls height change.
waitForBrowserControlsMetadataState(0, bottomViewHeight); mBrowserControlsHelper.waitForBrowserControlsMetadataState(0, bottomViewHeight);
int pageHeightWithBottomView = getVisiblePageHeight(); int pageHeightWithBottomView = getVisiblePageHeight();
Assert.assertNotEquals(pageHeightWithNoTopView, pageHeightWithBottomView); Assert.assertNotEquals(pageHeightWithNoTopView, pageHeightWithBottomView);
...@@ -218,7 +194,7 @@ public class BrowserControlsTest { ...@@ -218,7 +194,7 @@ public class BrowserControlsTest {
EventUtils.simulateDragFromCenterOfView( EventUtils.simulateDragFromCenterOfView(
activity.getWindow().getDecorView(), 0, bottomViewHeight); activity.getWindow().getDecorView(), 0, bottomViewHeight);
waitForBrowserControlsViewToBeVisible(bottomView); mBrowserControlsHelper.waitForBrowserControlsViewToBeVisible(bottomView);
CriteriaHelper.pollInstrumentationThread( CriteriaHelper.pollInstrumentationThread(
() -> Assert.assertEquals(getVisiblePageHeight(), pageHeightWithBottomView)); () -> Assert.assertEquals(getVisiblePageHeight(), pageHeightWithBottomView));
} }
...@@ -245,7 +221,7 @@ public class BrowserControlsTest { ...@@ -245,7 +221,7 @@ public class BrowserControlsTest {
activity.getWindow().getDecorView(), 0, mTopViewHeight); activity.getWindow().getDecorView(), 0, mTopViewHeight);
// Wait for the page height to match initial height. // Wait for the page height to match initial height.
waitForBrowserControlsViewToBeVisible(topView); mBrowserControlsHelper.waitForBrowserControlsViewToBeVisible(topView);
CriteriaHelper.pollInstrumentationThread( CriteriaHelper.pollInstrumentationThread(
() -> Assert.assertEquals(getVisiblePageHeight(), mPageHeightWithTopView)); () -> Assert.assertEquals(getVisiblePageHeight(), mPageHeightWithTopView));
} }
...@@ -298,7 +274,8 @@ public class BrowserControlsTest { ...@@ -298,7 +274,8 @@ public class BrowserControlsTest {
// Turn on accessibility, which should force the controls to show. // Turn on accessibility, which should force the controls to show.
setAccessibilityEnabled(true); setAccessibilityEnabled(true);
waitForBrowserControlsViewToBeVisible(activity.getTopContentsContainer()); mBrowserControlsHelper.waitForBrowserControlsViewToBeVisible(
activity.getTopContentsContainer());
CriteriaHelper.pollInstrumentationThread( CriteriaHelper.pollInstrumentationThread(
() -> Assert.assertEquals(getVisiblePageHeight(), mPageHeightWithTopView)); () -> Assert.assertEquals(getVisiblePageHeight(), mPageHeightWithTopView));
...@@ -338,11 +315,11 @@ public class BrowserControlsTest { ...@@ -338,11 +315,11 @@ public class BrowserControlsTest {
TestThreadUtils.runOnUiThreadBlocking(() -> { return newTopView.getHeight(); }); TestThreadUtils.runOnUiThreadBlocking(() -> { return newTopView.getHeight(); });
Assert.assertNotEquals(newTopViewHeight, mTopViewHeight); Assert.assertNotEquals(newTopViewHeight, mTopViewHeight);
Assert.assertTrue(newTopViewHeight > 0); Assert.assertTrue(newTopViewHeight > 0);
waitForBrowserControlsMetadataState(newTopViewHeight, 0); mBrowserControlsHelper.waitForBrowserControlsMetadataState(newTopViewHeight, 0);
// Remove all, and ensure metadata and page-height change. // Remove all, and ensure metadata and page-height change.
TestThreadUtils.runOnUiThreadBlocking(() -> { newTopView.removeAllViews(); }); TestThreadUtils.runOnUiThreadBlocking(() -> { newTopView.removeAllViews(); });
waitForBrowserControlsMetadataState(0, 0); mBrowserControlsHelper.waitForBrowserControlsMetadataState(0, 0);
CriteriaHelper.pollInstrumentationThread( CriteriaHelper.pollInstrumentationThread(
() -> Assert.assertNotEquals(getVisiblePageHeight(), mPageHeightWithTopView)); () -> Assert.assertNotEquals(getVisiblePageHeight(), mPageHeightWithTopView));
} }
......
...@@ -23,7 +23,9 @@ public final class EventUtils { ...@@ -23,7 +23,9 @@ public final class EventUtils {
/** /**
* Asynchronously posts a touch-down and touch-up event at the center of the supplied View. If * Asynchronously posts a touch-down and touch-up event at the center of the supplied View. If
* deltaX or deltaY is non-zero a touch-move is generated between the down/up. * deltaX or deltaY is non-zero a touch-move is generated between the down/up. Each individual
* event is posted asynchronously wrt the other events, which is necessary for scrolling events
* to be fully processed by //content and ripple out to observers (e.g., the infobar container).
*/ */
public static void simulateDragFromCenterOfView( public static void simulateDragFromCenterOfView(
final View view, final float deltaX, final float deltaY) { final View view, final float deltaX, final float deltaY) {
...@@ -33,12 +35,18 @@ public final class EventUtils { ...@@ -33,12 +35,18 @@ public final class EventUtils {
float y = (float) (view.getBottom() - view.getTop()) / 2; float y = (float) (view.getBottom() - view.getTop()) / 2;
view.dispatchTouchEvent( view.dispatchTouchEvent(
MotionEvent.obtain(eventTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0)); MotionEvent.obtain(eventTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0));
if (deltaX != 0 || deltaY != 0) { view.post(() -> {
view.dispatchTouchEvent(MotionEvent.obtain( long newEventTime = SystemClock.uptimeMillis();
eventTime, eventTime, MotionEvent.ACTION_MOVE, x + deltaX, y + deltaY, 0)); if (deltaX != 0 || deltaY != 0) {
} view.dispatchTouchEvent(MotionEvent.obtain(newEventTime, newEventTime,
view.dispatchTouchEvent(MotionEvent.obtain( MotionEvent.ACTION_MOVE, x + deltaX, y + deltaY, 0));
eventTime, eventTime, MotionEvent.ACTION_UP, x + deltaX, y + deltaY, 0)); }
view.post(() -> {
long newestEventTime = SystemClock.uptimeMillis();
view.dispatchTouchEvent(MotionEvent.obtain(newestEventTime, newestEventTime,
MotionEvent.ACTION_UP, x + deltaX, y + deltaY, 0));
});
});
}); });
} }
} }
...@@ -16,6 +16,8 @@ import org.junit.Test; ...@@ -16,6 +16,8 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.weblayer.Tab; import org.chromium.weblayer.Tab;
import org.chromium.weblayer.TestWebLayer; import org.chromium.weblayer.TestWebLayer;
...@@ -25,11 +27,16 @@ import org.chromium.weblayer.shell.InstrumentationActivity; ...@@ -25,11 +27,16 @@ import org.chromium.weblayer.shell.InstrumentationActivity;
* Test for infobars. * Test for infobars.
*/ */
@RunWith(WebLayerJUnit4ClassRunner.class) @RunWith(WebLayerJUnit4ClassRunner.class)
@CommandLineFlags.Add("enable-features=ImmediatelyHideBrowserControlsForTest")
public class InfoBarTest { public class InfoBarTest {
@Rule @Rule
public InstrumentationActivityTestRule mActivityTestRule = public InstrumentationActivityTestRule mActivityTestRule =
new InstrumentationActivityTestRule(); new InstrumentationActivityTestRule();
// When comparing two floats for equality via Assert.assertEquals() it is necessary to provide a
// delta. Use a sufficiently small value to have confidence in the equality check.
private static final double FLOAT_EQUALITY_DELTA = 0.0001;
private Tab getActiveTab() { private Tab getActiveTab() {
return mActivityTestRule.getActivity().getBrowser().getActiveTab(); return mActivityTestRule.getActivity().getBrowser().getActiveTab();
} }
...@@ -65,6 +72,8 @@ public class InfoBarTest { ...@@ -65,6 +72,8 @@ public class InfoBarTest {
public void setUp() throws Throwable { public void setUp() throws Throwable {
final String url = mActivityTestRule.getTestDataURL("tall_page.html"); final String url = mActivityTestRule.getTestDataURL("tall_page.html");
InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(url); InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(url);
BrowserControlsHelper.createAndBlockUntilBrowserControlsInitializedInSetUp(activity);
} }
@Test @Test
...@@ -83,4 +92,37 @@ public class InfoBarTest { ...@@ -83,4 +92,37 @@ public class InfoBarTest {
Assert.assertTrue(infoBarContainerView.getHeight() > 0); Assert.assertTrue(infoBarContainerView.getHeight() > 0);
Assert.assertEquals(View.VISIBLE, infoBarContainerView.getVisibility()); Assert.assertEquals(View.VISIBLE, infoBarContainerView.getVisibility());
} }
@Test
@SmallTest
/**
* Tests that infobars respond to scrolling.
*
*/
public void testScrolling() throws Exception {
addInfoBarToActiveTab();
View infoBarContainerView = getInfoBarContainerView();
Assert.assertEquals(infoBarContainerView.getTranslationY(), 0.0, /*delta=*/0.001);
InstrumentationActivity activity = mActivityTestRule.getActivity();
int infoBarContainerViewHeight = infoBarContainerView.getHeight();
Assert.assertTrue(infoBarContainerViewHeight > 0);
// Scroll down and check that infobar container view is translated in response.
EventUtils.simulateDragFromCenterOfView(
activity.getWindow().getDecorView(), 0, -infoBarContainerViewHeight);
CriteriaHelper.pollUiThread(
()
-> Assert.assertEquals(infoBarContainerView.getTranslationY(),
infoBarContainerViewHeight, FLOAT_EQUALITY_DELTA));
// Scroll back up and check that infobar container view is translated in response.
EventUtils.simulateDragFromCenterOfView(
activity.getWindow().getDecorView(), 0, infoBarContainerViewHeight);
CriteriaHelper.pollUiThread(
()
-> Assert.assertEquals(
infoBarContainerView.getTranslationY(), 0.0, FLOAT_EQUALITY_DELTA));
}
} }
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