Commit 8e9cf5a1 authored by Theresa Wellington's avatar Theresa Wellington Committed by Commit Bot

Fix flakiness in AppMenuTest#testDragHelper_ClickItem

This test was flakily failing due to improper calculation of motion
event x/y coordinates. An animatioin runs when the app menu is opened
and ending it doesn't immediately result in the views reaching their
resting position.

This CL adds a wait for AppMenuDragHelper to be ready for menu item
actions and retrieves the View rect on the UI thread. 0 flakes in 120
runs locally.

BUG=1062236

Change-Id: Ie7264fb23ceaf9e0b6653c7ca78c1b5d2bf555b2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2121451Reviewed-by: default avatarMatthew Jones <mdjones@chromium.org>
Commit-Queue: Theresa  <twellington@chromium.org>
Cr-Commit-Position: refs/heads/master@{#753694}
parent 2ddb8ad7
......@@ -238,18 +238,9 @@ class AppMenuDragHelper {
* @return true whether or not a menu item is performed (executed).
*/
private boolean menuItemAction(int screenX, int screenY, @ItemAction int action) {
ListView listView = mAppMenu.getListView();
if (!isReadyForMenuItemAction()) return false;
// Starting M, we have a popup menu animation that slides down. If we process dragging
// events while it's sliding, it will touch many views that are passing by user's finger,
// which is not desirable. So we only process when the first item is below the menu button.
// Unfortunately, there is no available listener for sliding animation finished. Thus the
// following nasty heuristics.
final View firstRow = listView.getChildAt(0);
if (listView.getFirstVisiblePosition() == 0 && firstRow != null && firstRow.getTop() == 0
&& getScreenVisibleRect(firstRow).bottom <= mMenuButtonScreenCenterY) {
return false;
}
ListView listView = mAppMenu.getListView();
ArrayList<View> itemViews = new ArrayList<View>();
for (int i = 0; i < listView.getChildCount(); ++i) {
......@@ -303,4 +294,22 @@ class AppMenuDragHelper {
mScreenVisibleRect.offset(mScreenVisiblePoint[0], mScreenVisiblePoint[1]);
return mScreenVisibleRect;
}
@VisibleForTesting
boolean isReadyForMenuItemAction() {
ListView listView = mAppMenu.getListView();
// Starting M, we have a popup menu animation that slides down. If we process dragging
// events while it's sliding, it will touch many views that are passing by user's finger,
// which is not desirable. So we only process when the first item is below the menu button.
// Unfortunately, there is no available listener for sliding animation finished. Thus the
// following nasty heuristics.
final View firstRow = listView.getChildAt(0);
if (listView.getFirstVisiblePosition() == 0 && firstRow != null && firstRow.getTop() == 0
&& getScreenVisibleRect(firstRow).bottom <= mMenuButtonScreenCenterY) {
return false;
}
return true;
}
}
......@@ -629,13 +629,13 @@ public class AppMenuTest extends DummyUiActivityTestCase {
buttonHelper, mTestMenuButtonDelegate.getMenuButtonView(), downMotionEvent);
waitForMenuToShow(0);
Assert.assertTrue("Menu should be showing", mAppMenuHandler.isAppMenuShowing());
CriteriaHelper.pollUiThread(
() -> mAppMenuHandler.getAppMenuDragHelper().isReadyForMenuItemAction());
Rect firstItemScreenRect = getVisibleScreenRectAtPosition(0);
int eventX = firstItemScreenRect.left + (firstItemScreenRect.width() / 2);
int eventY = firstItemScreenRect.top + (firstItemScreenRect.height() / 2);
View firstItem = mAppMenuHandler.getAppMenu().getListView().getChildAt(0);
Rect firstItemScreenRect =
mAppMenuHandler.getAppMenuDragHelper().getScreenVisibleRect(firstItem);
int eventX = firstItemScreenRect.left + (firstItemScreenRect.right / 2);
int eventY = firstItemScreenRect.top + (firstItemScreenRect.bottom / 2);
MotionEvent dragMotionEvent =
MotionEvent.obtain(0, 100, MotionEvent.ACTION_MOVE, eventX, eventY, 0);
sendMotionEventToButtonHelper(
......@@ -645,8 +645,9 @@ public class AppMenuTest extends DummyUiActivityTestCase {
MotionEvent.obtain(0, 150, MotionEvent.ACTION_UP, eventX, eventY, 0);
sendMotionEventToButtonHelper(
buttonHelper, mTestMenuButtonDelegate.getMenuButtonView(), upMotionEvent);
mDelegate.itemSelectedCallbackHelper.waitForCallback(0);
mDelegate.itemSelectedCallbackHelper.waitForCallback(
"itemRect: " + firstItemScreenRect + " eventX: " + eventX + " eventY: " + eventY,
0);
Assert.assertEquals("Incorrect id for last selected item.", R.id.menu_item_one,
mDelegate.lastSelectedItemId);
}
......@@ -739,6 +740,12 @@ public class AppMenuTest extends DummyUiActivityTestCase {
return viewRect;
}
private Rect getVisibleScreenRectAtPosition(int position) throws ExecutionException {
View view = getViewAtPosition(position);
return TestThreadUtils.runOnUiThreadBlocking(
() -> mAppMenuHandler.getAppMenuDragHelper().getScreenVisibleRect(view));
}
private void sendMotionEventToButtonHelper(AppMenuButtonHelperImpl helper, View view,
MotionEvent event) throws ExecutionException {
TestThreadUtils.runOnUiThreadBlocking(() -> helper.onTouch(view, event));
......
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