Commit a311f5a3 authored by Theresa Wellington's avatar Theresa Wellington Committed by Commit Bot

[Android] Introduce AppMenuTest and AppMenuAdapterRenderTest

Adds an AppMenuTest for app menu integration tests
 - #testShowHideAppMenu
 - #testShowDestroyAppMenu
 - #testClickMenuItem
 - #testAppMenuBlockers
 - #testSetMenuHighlight_StandardItem
 - #testSetMenuHighlight_Icon
 - #testMenuItemContentChnaged
 - #testHeaderFooter
 - #testAppMenuHiddenOnStopWithNative
 - #testAppMenuHiddenOnConfigurationChange

Also adds a few more tests to AppMenuAdapterTest to shore up test
coverage and adds an AppMenuAdapterRenderTest that runs a suite of
render tests for the various types of menu items supported natively
by the app menu.

This patch includes an update to AnimationFrameTimeHistogram to allow
histogram recording to be disabled for tests.

BUG=966644

Change-Id: I035b10557a9e35ef0e86b315ccd926230bb18bf0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1893984
Commit-Queue: Theresa  <twellington@chromium.org>
Reviewed-by: default avatarTommy Nyquist <nyquist@chromium.org>
Reviewed-by: default avatarMatthew Jones <mdjones@chromium.org>
Cr-Commit-Position: refs/heads/master@{#712702}
parent 41c87dbd
...@@ -12,6 +12,7 @@ import android.animation.TimeAnimator.TimeListener; ...@@ -12,6 +12,7 @@ import android.animation.TimeAnimator.TimeListener;
import android.util.Log; import android.util.Log;
import org.chromium.base.annotations.NativeMethods; import org.chromium.base.annotations.NativeMethods;
import org.chromium.base.metrics.RecordHistogram;
/** /**
* Record Android animation frame rate and save it to UMA histogram. This is mainly for monitoring * Record Android animation frame rate and save it to UMA histogram. This is mainly for monitoring
...@@ -72,7 +73,7 @@ public class AnimationFrameTimeHistogram { ...@@ -72,7 +73,7 @@ public class AnimationFrameTimeHistogram {
* successful. * successful.
*/ */
public void endRecording() { public void endRecording() {
if (mRecorder.endRecording()) { if (mRecorder.endRecording() && RecordHistogram.sDisabledBy == null) {
AnimationFrameTimeHistogramJni.get().saveHistogram( AnimationFrameTimeHistogramJni.get().saveHistogram(
mHistogramName, mRecorder.getFrameTimesMs(), mRecorder.getFrameTimesCount()); mHistogramName, mRecorder.getFrameTimesMs(), mRecorder.getFrameTimesCount());
} }
......
...@@ -29,7 +29,13 @@ import java.util.Map; ...@@ -29,7 +29,13 @@ import java.util.Map;
@JNINamespace("base::android") @JNINamespace("base::android")
@MainDex @MainDex
public class RecordHistogram { public class RecordHistogram {
private static Throwable sDisabledBy; /**
* Whether recording histograms is currently disabled for testing. Exposed for use in peer
* classes {e.g. AnimationFrameTimeHistogram}.
* Use {@link #setDisabledForTests(boolean)} to set this value.
*/
@VisibleForTesting
public static Throwable sDisabledBy;
private static Map<String, Long> sCache = private static Map<String, Long> sCache =
Collections.synchronizedMap(new HashMap<String, Long>()); Collections.synchronizedMap(new HashMap<String, Long>());
......
...@@ -823,6 +823,7 @@ android_library("chrome_test_java") { ...@@ -823,6 +823,7 @@ android_library("chrome_test_java") {
"//chrome/browser/ui/android/widget:java", "//chrome/browser/ui/android/widget:java",
"//chrome/browser/ui/android/widget:test_support_java", "//chrome/browser/ui/android/widget:test_support_java",
"//chrome/browser/util:java", "//chrome/browser/util:java",
"//chrome/lib/lifecycle/public/android:java",
"//chrome/test/android:chrome_java_test_support", "//chrome/test/android:chrome_java_test_support",
"//chrome/test/android/test_trusted_web_activity:test_trusted_web_activity_java", "//chrome/test/android/test_trusted_web_activity:test_trusted_web_activity_java",
"//components/autofill/android:autofill_java", "//components/autofill/android:autofill_java",
......
...@@ -47,7 +47,12 @@ chrome_test_java_sources = [ ...@@ -47,7 +47,12 @@ chrome_test_java_sources = [
"javatests/src/org/chromium/chrome/browser/accessibility/FontSizePrefsTest.java", "javatests/src/org/chromium/chrome/browser/accessibility/FontSizePrefsTest.java",
"javatests/src/org/chromium/chrome/browser/accessibility_tab_switcher/OverviewListLayoutTest.java", "javatests/src/org/chromium/chrome/browser/accessibility_tab_switcher/OverviewListLayoutTest.java",
"javatests/src/org/chromium/chrome/browser/appmenu/AppMenuAdapterTest.java", "javatests/src/org/chromium/chrome/browser/appmenu/AppMenuAdapterTest.java",
"javatests/src/org/chromium/chrome/browser/appmenu/AppMenuAdapterRenderTest.java",
"javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java",
"javatests/src/org/chromium/chrome/browser/appmenu/TabbedAppMenuTest.java", "javatests/src/org/chromium/chrome/browser/appmenu/TabbedAppMenuTest.java",
"javatests/src/org/chromium/chrome/browser/appmenu/TestAppMenuDelegate.java",
"javatests/src/org/chromium/chrome/browser/appmenu/TestAppMenuPropertiesDelegate.java",
"javatests/src/org/chromium/chrome/browser/appmenu/TestAppMenuObserver.java",
"javatests/src/org/chromium/chrome/browser/appmenu/DataSaverAppMenuTest.java", "javatests/src/org/chromium/chrome/browser/appmenu/DataSaverAppMenuTest.java",
"javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupTest.java", "javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupTest.java",
"javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupWithKeyboardTest.java", "javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupWithKeyboardTest.java",
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
Use of this source code is governed by a BSD-style license that can be Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. found in the LICENSE file.
--> -->
<!-- TODO(twellington): Add an item for disabled state. -->
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:color="@color/light_active_color" /> <item android:state_checked="true" android:color="@color/light_active_color" />
<item android:color="@color/control_normal_color"/> <item android:color="@color/control_normal_color"/>
......
...@@ -40,6 +40,9 @@ ...@@ -40,6 +40,9 @@
android:src="?android:attr/listChoiceIndicatorMultiple" /> android:src="?android:attr/listChoiceIndicatorMultiple" />
<!-- Displays an icon. --> <!-- Displays an icon. -->
<!-- TODO(twellington): Consider setting a default tint that adjusts when the item is disabled.
currently there are no menu items with icons that are visible but disabled so this behavior
is currently unused. -->
<org.chromium.ui.widget.ChromeImageButton <org.chromium.ui.widget.ChromeImageButton
android:id="@+id/button" android:id="@+id/button"
android:layout_width="56dp" android:layout_width="56dp"
......
...@@ -37,6 +37,7 @@ import org.chromium.base.AnimationFrameTimeHistogram; ...@@ -37,6 +37,7 @@ import org.chromium.base.AnimationFrameTimeHistogram;
import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.ContextUtils; import org.chromium.base.ContextUtils;
import org.chromium.base.SysUtils; import org.chromium.base.SysUtils;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.metrics.RecordUserAction; import org.chromium.base.metrics.RecordUserAction;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.ui.widget.highlight.ViewHighlighter; import org.chromium.chrome.browser.ui.widget.highlight.ViewHighlighter;
...@@ -297,14 +298,6 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuAdapter.OnCl ...@@ -297,14 +298,6 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuAdapter.OnCl
} }
} }
/**
* @return The footer view for the menu or null if one has not been set.
*/
@Nullable
public View getFooterView() {
return mFooterView;
}
private int[] getPopupPosition(int screenRotation, Rect appRect, Rect padding, View anchorView, private int[] getPopupPosition(int screenRotation, Rect appRect, Rect padding, View anchorView,
int popupWidth, int popupHeight, boolean isAnchorAtBottom) { int popupWidth, int popupHeight, boolean isAnchorAtBottom) {
anchorView.getLocationInWindow(mTempLocation); anchorView.getLocationInWindow(mTempLocation);
...@@ -568,4 +561,9 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuAdapter.OnCl ...@@ -568,4 +561,9 @@ class AppMenu implements OnItemClickListener, OnKeyListener, AppMenuAdapter.OnCl
return headerView.getMeasuredHeight(); return headerView.getMeasuredHeight();
} }
@VisibleForTesting
void finishAnimationsForTests() {
if (mMenuItemEnterAnimator != null) mMenuItemEnterAnimator.end();
}
} }
...@@ -245,6 +245,7 @@ class AppMenuAdapter extends BaseAdapter { ...@@ -245,6 +245,7 @@ class AppMenuAdapter extends BaseAdapter {
holder.title.setEnabled(titleItem.isEnabled()); holder.title.setEnabled(titleItem.isEnabled());
holder.title.setFocusable(titleItem.isEnabled()); holder.title.setFocusable(titleItem.isEnabled());
holder.title.setOnClickListener(v -> mOnClickHandler.onItemClick(titleItem)); holder.title.setOnClickListener(v -> mOnClickHandler.onItemClick(titleItem));
if (TextUtils.isEmpty(titleItem.getTitleCondensed())) { if (TextUtils.isEmpty(titleItem.getTitleCondensed())) {
holder.title.setContentDescription(null); holder.title.setContentDescription(null);
} else { } else {
......
...@@ -25,11 +25,14 @@ public class AppMenuCoordinatorFactory { ...@@ -25,11 +25,14 @@ public class AppMenuCoordinatorFactory {
* @param appMenuDelegate The {@link AppMenuDelegate} for the containing activity. * @param appMenuDelegate The {@link AppMenuDelegate} for the containing activity.
* @param decorView The decor {@link View}, e.g. from Window#getDecorView(), for the containing * @param decorView The decor {@link View}, e.g. from Window#getDecorView(), for the containing
* activity. * activity.
* @param hardwareButtonAnchorView The {@link View} used as an anchor for the menu when it is
* displayed using a hardware butt
*/ */
public static AppMenuCoordinator createAppMenuCoordinator(Context context, public static AppMenuCoordinator createAppMenuCoordinator(Context context,
ActivityLifecycleDispatcher activityLifecycleDispatcher, ActivityLifecycleDispatcher activityLifecycleDispatcher,
MenuButtonDelegate buttonDelegate, AppMenuDelegate appMenuDelegate, View decorView) { MenuButtonDelegate buttonDelegate, AppMenuDelegate appMenuDelegate, View decorView,
return new AppMenuCoordinatorImpl( View hardwareButtonAnchorView) {
context, activityLifecycleDispatcher, buttonDelegate, appMenuDelegate, decorView); return new AppMenuCoordinatorImpl(context, activityLifecycleDispatcher, buttonDelegate,
appMenuDelegate, decorView, hardwareButtonAnchorView);
} }
} }
...@@ -8,7 +8,6 @@ import android.content.Context; ...@@ -8,7 +8,6 @@ import android.content.Context;
import android.view.View; import android.view.View;
import android.view.ViewConfiguration; import android.view.ViewConfiguration;
import org.chromium.base.VisibleForTesting; import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
...@@ -51,10 +50,13 @@ class AppMenuCoordinatorImpl implements AppMenuCoordinator { ...@@ -51,10 +50,13 @@ class AppMenuCoordinatorImpl implements AppMenuCoordinator {
* @param appMenuDelegate The {@link AppMenuDelegate} for the containing activity. * @param appMenuDelegate The {@link AppMenuDelegate} for the containing activity.
* @param decorView The decor {@link View}, e.g. from Window#getDecorView(), for the containing * @param decorView The decor {@link View}, e.g. from Window#getDecorView(), for the containing
* activity. * activity.
* @param hardwareButtonAnchorView The {@link View} used as an anchor for the menu when it is
* displayed using a hardware button.
*/ */
public AppMenuCoordinatorImpl(Context context, public AppMenuCoordinatorImpl(Context context,
ActivityLifecycleDispatcher activityLifecycleDispatcher, ActivityLifecycleDispatcher activityLifecycleDispatcher,
MenuButtonDelegate buttonDelegate, AppMenuDelegate appMenuDelegate, View decorView) { MenuButtonDelegate buttonDelegate, AppMenuDelegate appMenuDelegate, View decorView,
View hardwareButtonAnchorView) {
mContext = context; mContext = context;
mButtonDelegate = buttonDelegate; mButtonDelegate = buttonDelegate;
mAppMenuDelegate = appMenuDelegate; mAppMenuDelegate = appMenuDelegate;
...@@ -62,7 +64,7 @@ class AppMenuCoordinatorImpl implements AppMenuCoordinator { ...@@ -62,7 +64,7 @@ class AppMenuCoordinatorImpl implements AppMenuCoordinator {
mAppMenuHandler = new AppMenuHandlerImpl(mAppMenuPropertiesDelegate, mAppMenuDelegate, mAppMenuHandler = new AppMenuHandlerImpl(mAppMenuPropertiesDelegate, mAppMenuDelegate,
mAppMenuPropertiesDelegate.getAppMenuLayoutId(), decorView, mAppMenuPropertiesDelegate.getAppMenuLayoutId(), decorView,
activityLifecycleDispatcher); activityLifecycleDispatcher, hardwareButtonAnchorView);
} }
@Override @Override
...@@ -106,7 +108,7 @@ class AppMenuCoordinatorImpl implements AppMenuCoordinator { ...@@ -106,7 +108,7 @@ class AppMenuCoordinatorImpl implements AppMenuCoordinator {
// Testing methods // Testing methods
@VisibleForTesting @VisibleForTesting
public AppMenuHandlerImpl getAppMenuHandlerImplForTesting() { AppMenuHandlerImpl getAppMenuHandlerImplForTesting() {
return mAppMenuHandler; return mAppMenuHandler;
} }
} }
...@@ -73,17 +73,20 @@ class AppMenuHandlerImpl ...@@ -73,17 +73,20 @@ class AppMenuHandlerImpl
* activity. * activity.
* @param activityLifecycleDispatcher The {@link ActivityLifecycleDispatcher} for the containing * @param activityLifecycleDispatcher The {@link ActivityLifecycleDispatcher} for the containing
* activity. * activity.
* @param hardwareButtonAnchorView The {@link View} used as an anchor for the menu when it is
* displayed using a hardware button.
*/ */
public AppMenuHandlerImpl(AppMenuPropertiesDelegate delegate, AppMenuDelegate appMenuDelegate, public AppMenuHandlerImpl(AppMenuPropertiesDelegate delegate, AppMenuDelegate appMenuDelegate,
int menuResourceId, View decorView, int menuResourceId, View decorView,
ActivityLifecycleDispatcher activityLifecycleDispatcher) { ActivityLifecycleDispatcher activityLifecycleDispatcher,
View hardwareButtonAnchorView) {
mAppMenuDelegate = appMenuDelegate; mAppMenuDelegate = appMenuDelegate;
mDelegate = delegate; mDelegate = delegate;
mDecorView = decorView; mDecorView = decorView;
mBlockers = new ArrayList<>(); mBlockers = new ArrayList<>();
mObservers = new ArrayList<>(); mObservers = new ArrayList<>();
mMenuResourceId = menuResourceId; mMenuResourceId = menuResourceId;
mHardwareButtonMenuAnchor = mDecorView.findViewById(R.id.menu_anchor_stub); mHardwareButtonMenuAnchor = hardwareButtonAnchorView;
mActivityLifecycleDispatcher = activityLifecycleDispatcher; mActivityLifecycleDispatcher = activityLifecycleDispatcher;
mActivityLifecycleDispatcher.register(this); mActivityLifecycleDispatcher.register(this);
......
...@@ -279,7 +279,8 @@ public class RootUiCoordinator ...@@ -279,7 +279,8 @@ public class RootUiCoordinator
if (mActivity.supportsAppMenu()) { if (mActivity.supportsAppMenu()) {
mAppMenuCoordinator = AppMenuCoordinatorFactory.createAppMenuCoordinator(mActivity, mAppMenuCoordinator = AppMenuCoordinatorFactory.createAppMenuCoordinator(mActivity,
mActivity.getLifecycleDispatcher(), mActivity.getToolbarManager(), mActivity, mActivity.getLifecycleDispatcher(), mActivity.getToolbarManager(), mActivity,
mActivity.getWindow().getDecorView()); mActivity.getWindow().getDecorView(),
mActivity.getWindow().getDecorView().findViewById(R.id.menu_anchor_stub));
mActivity.getToolbarManager().onAppMenuInitialized( mActivity.getToolbarManager().onAppMenuInitialized(
mAppMenuCoordinator.getAppMenuHandler(), mAppMenuCoordinator.getAppMenuHandler(),
mAppMenuCoordinator.getAppMenuPropertiesDelegate()); mAppMenuCoordinator.getAppMenuPropertiesDelegate());
......
...@@ -3,6 +3,7 @@ include_rules = [ ...@@ -3,6 +3,7 @@ include_rules = [
"+chrome/browser/ui/android/styles", "+chrome/browser/ui/android/styles",
"+chrome/browser/ui/android/widget", "+chrome/browser/ui/android/widget",
"+chrome/browser/util/android", "+chrome/browser/util/android",
"+chrome/lib/lifecycle/public",
"+components/autofill/android/java/src/org/chromium/components/autofill", "+components/autofill/android/java/src/org/chromium/components/autofill",
"+components/background_task_scheduler/android/java", "+components/background_task_scheduler/android/java",
"+components/bookmarks/common/android/java/src/org/chromium/components/bookmarks", "+components/bookmarks/common/android/java/src/org/chromium/components/bookmarks",
......
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2019 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. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:targetApi="21"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:pathData="M20,12l-1.41,-1.41L13,16.17V4h-2v12.17l-5.58,-5.59L4,12l8,8 8,-8z"
android:fillColor="#010101"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2019 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. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:targetApi="21"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2019 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. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:targetApi="21"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2019 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. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:targetApi="21"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2019 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. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:targetApi="21"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M22,9.24l-7.19,-0.62L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21 12,17.27 18.18,21l-1.63,-7.03L22,9.24zM12,15.4l-3.76,2.27 1,-4.28 -3.32,-2.88 4.38,-0.38L12,6.1l1.71,4.04 4.38,0.38 -3.32,2.88 1,4.28L12,15.4z"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2019 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. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:targetApi="21"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M18.7,12.4c-0.28,-0.16 -0.57,-0.29 -0.86,-0.4 0.29,-0.11 0.58,-0.24 0.86,-0.4 1.92,-1.11 2.99,-3.12 3,-5.19 -1.79,-1.03 -4.07,-1.11 -6,0 -0.28,0.16 -0.54,0.35 -0.78,0.54 0.05,-0.31 0.08,-0.63 0.08,-0.95 0,-2.22 -1.21,-4.15 -3,-5.19C10.21,1.85 9,3.78 9,6c0,0.32 0.03,0.64 0.08,0.95 -0.24,-0.2 -0.5,-0.39 -0.78,-0.55 -1.92,-1.11 -4.2,-1.03 -6,0 0,2.07 1.07,4.08 3,5.19 0.28,0.16 0.57,0.29 0.86,0.4 -0.29,0.11 -0.58,0.24 -0.86,0.4 -1.92,1.11 -2.99,3.12 -3,5.19 1.79,1.03 4.07,1.11 6,0 0.28,-0.16 0.54,-0.35 0.78,-0.54 -0.05,0.32 -0.08,0.64 -0.08,0.96 0,2.22 1.21,4.15 3,5.19 1.79,-1.04 3,-2.97 3,-5.19 0,-0.32 -0.03,-0.64 -0.08,-0.95 0.24,0.2 0.5,0.38 0.78,0.54 1.92,1.11 4.2,1.03 6,0 -0.01,-2.07 -1.08,-4.08 -3,-5.19zM12,16c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4 4,1.79 4,4 -1.79,4 -4,4z"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2019 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. -->
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="HardcodedText"
android:text="Menu Footer"/>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2019 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. -->
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="HardcodedText"
android:text="Menu Header"/>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2019 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. -->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="HardcodedText">
<item android:id="@+id/menu_item_one"
android:title="Menu Item One" />
<item android:id="@+id/menu_item_two"
android:title="Menu Item Two" />
<item android:id="@+id/menu_item_three"
android:title="Menu Item Three" />
<item android:id="@+id/icon_row_menu_id"
android:title="@null">
<menu>
<item android:id="@+id/icon_one"
android:title="Icon One" />
<item android:id="@+id/icon_two"
android:title="Icon Two" />
<item android:id="@+id/icon_three"
android:title="Icon Three" />
</menu>
</item>
</menu>
\ No newline at end of file
// Copyright 2019 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.appmenu;
import static org.chromium.chrome.browser.appmenu.AppMenuAdapterTest.TITLE_1;
import static org.chromium.chrome.browser.appmenu.AppMenuAdapterTest.TITLE_2;
import static org.chromium.chrome.browser.appmenu.AppMenuAdapterTest.TITLE_3;
import static org.chromium.chrome.browser.appmenu.AppMenuAdapterTest.TITLE_4;
import static org.chromium.chrome.browser.appmenu.AppMenuAdapterTest.TITLE_5;
import static org.chromium.chrome.browser.appmenu.AppMenuAdapterTest.buildIconRow;
import static org.chromium.chrome.browser.appmenu.AppMenuAdapterTest.buildMenuItem;
import static org.chromium.chrome.browser.appmenu.AppMenuAdapterTest.buildTitleMenuItem;
import android.graphics.drawable.Drawable;
import android.support.test.filters.MediumTest;
import android.support.v7.content.res.AppCompatResources;
import android.view.MenuItem;
import android.view.View;
import android.widget.FrameLayout;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.chromium.base.test.params.ParameterAnnotations;
import org.chromium.base.test.params.ParameterProvider;
import org.chromium.base.test.params.ParameterSet;
import org.chromium.base.test.params.ParameterizedRunner;
import org.chromium.base.test.util.Feature;
import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
import org.chromium.chrome.test.R;
import org.chromium.chrome.test.ui.DummyUiActivityTestCase;
import org.chromium.chrome.test.util.RenderTestRule;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Render tests for {@link AppMenuAdapter}.
*/
@RunWith(ParameterizedRunner.class)
@ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
public class AppMenuAdapterRenderTest extends DummyUiActivityTestCase {
// TODO(twellington): Add night mode variant after NightModeTestUtils methods are modularized
// in https://crbug.com/1002287.
/**
* Parameter set controlling whether the menu item being rendered is enabled.
*/
public static class EnabledParams implements ParameterProvider {
private static List<ParameterSet> sEnabledDisabledParams =
Arrays.asList(new ParameterSet().value(false).name("Enabled"),
new ParameterSet().value(true).name("Disabled"));
@Override
public List<ParameterSet> getParameters() {
return sEnabledDisabledParams;
}
}
@Rule
public RenderTestRule mRenderTestRule =
new RenderTestRule("chrome/test/data/android/render_tests");
@Override
public void setUpTest() throws Exception {
super.setUpTest();
MockitoAnnotations.initMocks(this);
}
@Test
@MediumTest
@Feature("RenderTest")
@ParameterAnnotations.UseMethodParameter(EnabledParams.class)
public void testStandardMenuItem(boolean enabled) throws IOException {
setRenderTestPrefix(enabled);
MenuItem item = buildMenuItem(1, TITLE_1, enabled);
mRenderTestRule.render(createView(item), "standard");
}
@Test
@MediumTest
@Feature("RenderTest")
@ParameterAnnotations.UseMethodParameter(EnabledParams.class)
public void testStandardMenuItem_Icon(boolean enabled) throws IOException {
setRenderTestPrefix(enabled);
Drawable icon =
AppCompatResources.getDrawable(getActivity(), R.drawable.test_ic_vintage_filter);
MenuItem item = buildMenuItem(1, TITLE_1, enabled, icon);
mRenderTestRule.render(createView(item), "standard_with_icon");
}
@Test
@MediumTest
@Feature("RenderTest")
@ParameterAnnotations.UseMethodParameter(EnabledParams.class)
public void testTitleButtonMenuItem_Icon(boolean enabled) throws IOException {
setRenderTestPrefix(enabled);
Drawable icon =
AppCompatResources.getDrawable(getActivity(), R.drawable.test_ic_vintage_filter);
MenuItem item = buildTitleMenuItem(1, 2, TITLE_2, 3, TITLE_3, icon, false, false, enabled);
mRenderTestRule.render(createView(item), "title_button_icon");
}
@Test
@MediumTest
@Feature("RenderTest")
@ParameterAnnotations.UseMethodParameter(EnabledParams.class)
public void testTitleButtonMenuItem_Checkbox_Checked(boolean enabled) throws IOException {
setRenderTestPrefix(enabled);
MenuItem item = buildTitleMenuItem(1, 2, TITLE_2, 3, TITLE_3, null, true, true, enabled);
mRenderTestRule.render(createView(item), "title_button_checkbox_checked");
}
@Test
@MediumTest
@Feature("RenderTest")
@ParameterAnnotations.UseMethodParameter(EnabledParams.class)
public void testTitleButtonMenuItem_Checkbox_Unchecked(boolean enabled) throws IOException {
setRenderTestPrefix(enabled);
MenuItem item = buildTitleMenuItem(1, 2, TITLE_2, 3, TITLE_3, null, true, false, enabled);
mRenderTestRule.render(createView(item), "title_button_checkbox_unchecked");
}
@Test
@MediumTest
@Feature("RenderTest")
@ParameterAnnotations.UseMethodParameter(EnabledParams.class)
public void testIconRow_ThreeIcons(boolean enabled) throws IOException {
setRenderTestPrefix(enabled);
Drawable icon1 = AppCompatResources.getDrawable(
getActivity(), R.drawable.test_ic_arrow_forward_black_24dp);
Drawable icon2 = AppCompatResources.getDrawable(
getActivity(), R.drawable.test_ic_star_border_black_24dp);
Drawable icon3 = AppCompatResources.getDrawable(
getActivity(), R.drawable.test_ic_arrow_downward_black_24dp);
MenuItem item = buildIconRow(1, 2, TITLE_1, icon1, 3, TITLE_2, icon2, 4, TITLE_3, icon3, 0,
"", null, 0, "", null, enabled);
mRenderTestRule.render(createView(item), "iconrow_three_icons");
}
@Test
@MediumTest
@Feature("RenderTest")
public void testIconRow_FourIcons() throws IOException {
setRenderTestPrefix(true);
Drawable icon1 = AppCompatResources.getDrawable(
getActivity(), R.drawable.test_ic_arrow_forward_black_24dp);
Drawable icon2 = AppCompatResources.getDrawable(
getActivity(), R.drawable.test_ic_star_border_black_24dp);
Drawable icon3 = AppCompatResources.getDrawable(
getActivity(), R.drawable.test_ic_arrow_downward_black_24dp);
Drawable icon4 = AppCompatResources.getDrawable(
getActivity(), R.drawable.test_ic_info_outline_black_24dp);
MenuItem item = buildIconRow(1, 2, TITLE_1, icon1, 3, TITLE_2, icon2, 4, TITLE_3, icon3, 5,
TITLE_4, icon4, 0, "", null, true);
mRenderTestRule.render(createView(item), "iconrow_four_icons");
}
@Test
@MediumTest
@Feature("RenderTest")
public void testIconRow_FiveIcons() throws IOException {
setRenderTestPrefix(true);
Drawable icon1 = AppCompatResources.getDrawable(
getActivity(), R.drawable.test_ic_arrow_forward_black_24dp);
Drawable icon2 = AppCompatResources.getDrawable(
getActivity(), R.drawable.test_ic_star_border_black_24dp);
Drawable icon3 = AppCompatResources.getDrawable(
getActivity(), R.drawable.test_ic_arrow_downward_black_24dp);
Drawable icon4 = AppCompatResources.getDrawable(
getActivity(), R.drawable.test_ic_info_outline_black_24dp);
Drawable icon5 = AppCompatResources.getDrawable(
getActivity(), R.drawable.test_ic_refresh_black_24dp);
MenuItem item = buildIconRow(1, 2, TITLE_1, icon1, 3, TITLE_2, icon2, 4, TITLE_3, icon3, 5,
TITLE_4, icon4, 6, TITLE_5, icon5, true);
mRenderTestRule.render(createView(item), "iconrow_five_icons");
}
private void setRenderTestPrefix(boolean enabled) {
mRenderTestRule.setVariantPrefix(enabled ? "Enabled" : "Disabled");
}
private View createView(MenuItem item) {
List<MenuItem> items = new ArrayList<>();
items.add(item);
AppMenuAdapter adapter = new AppMenuAdapter(new AppMenuAdapterTest.TestClickHandler(),
items, getActivity().getLayoutInflater(), 0, null);
// Create a new FrameLayout to set as the main content view.
FrameLayout parentView = new FrameLayout(getActivity());
parentView.setLayoutParams(new FrameLayout.LayoutParams(
getActivity().getResources().getDimensionPixelSize(R.dimen.menu_width),
FrameLayout.LayoutParams.WRAP_CONTENT));
// Create a view for the provided menu item and attach it to the content view.
TestThreadUtils.runOnUiThreadBlocking(() -> {
View view = adapter.getView(0, null, parentView);
parentView.addView(view);
getActivity().setContentView(parentView);
});
return parentView.getChildAt(0);
}
}
...@@ -4,8 +4,9 @@ ...@@ -4,8 +4,9 @@
package org.chromium.chrome.browser.appmenu; package org.chromium.chrome.browser.appmenu;
import android.graphics.drawable.Drawable;
import android.support.test.filters.MediumTest; import android.support.test.filters.MediumTest;
import android.support.test.rule.UiThreadTestRule; import android.support.v7.content.res.AppCompatResources;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.SubMenu; import android.view.SubMenu;
...@@ -16,7 +17,6 @@ import android.widget.TextView; ...@@ -16,7 +17,6 @@ import android.widget.TextView;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mockito; import org.mockito.Mockito;
...@@ -26,17 +26,20 @@ import org.chromium.base.test.util.CallbackHelper; ...@@ -26,17 +26,20 @@ import org.chromium.base.test.util.CallbackHelper;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ui.DummyUiActivityTestCase; import org.chromium.chrome.test.ui.DummyUiActivityTestCase;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
/** /**
* Tests for {@link AppMenuAdapter}. * Tests for {@link AppMenuAdapter}.
*/ */
@RunWith(ChromeJUnit4ClassRunner.class) @RunWith(ChromeJUnit4ClassRunner.class)
public class AppMenuAdapterTest extends DummyUiActivityTestCase { public class AppMenuAdapterTest extends DummyUiActivityTestCase {
private static class TestClickHandler implements AppMenuAdapter.OnClickHandler { static class TestClickHandler implements AppMenuAdapter.OnClickHandler {
public CallbackHelper onClickCallback = new CallbackHelper(); public CallbackHelper onClickCallback = new CallbackHelper();
public MenuItem lastClickedItem; public MenuItem lastClickedItem;
...@@ -57,14 +60,11 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase { ...@@ -57,14 +60,11 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase {
} }
} }
@Rule static final String TITLE_1 = "Menu Item One";
public UiThreadTestRule mRule = new UiThreadTestRule(); static final String TITLE_2 = "Menu Item Two";
static final String TITLE_3 = "Menu Item Three";
private static final String TITLE_1 = "Menu Item One"; static final String TITLE_4 = "Menu Item Four";
private static final String TITLE_2 = "Menu Item Two"; static final String TITLE_5 = "Menu Item Five";
private static final String TITLE_3 = "Menu Item Three";
private static final String TITLE_4 = "Menu Item Four";
private static final String TITLE_5 = "Menu Item Five";
private TestClickHandler mClickHandler; private TestClickHandler mClickHandler;
...@@ -78,9 +78,10 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase { ...@@ -78,9 +78,10 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase {
@Test @Test
@MediumTest @MediumTest
public void testStandardMenuItem() { public void testStandardMenuItem() throws ExecutionException, TimeoutException {
int itemId = 1234;
List<MenuItem> items = new ArrayList<>(); List<MenuItem> items = new ArrayList<>();
items.add(buildMenuItem(0, TITLE_1)); items.add(buildMenuItem(itemId, TITLE_1));
AppMenuAdapter adapter = new AppMenuAdapter( AppMenuAdapter adapter = new AppMenuAdapter(
mClickHandler, items, getActivity().getLayoutInflater(), 0, null); mClickHandler, items, getActivity().getLayoutInflater(), 0, null);
...@@ -92,14 +93,19 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase { ...@@ -92,14 +93,19 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase {
TextView titleView1 = view1.findViewById(R.id.menu_item_text); TextView titleView1 = view1.findViewById(R.id.menu_item_text);
Assert.assertEquals("Incorrect title text for item 1", TITLE_1, titleView1.getText()); Assert.assertEquals("Incorrect title text for item 1", TITLE_1, titleView1.getText());
TestThreadUtils.runOnUiThreadBlocking(() -> view1.performClick());
mClickHandler.onClickCallback.waitForCallback(0);
Assert.assertEquals(
"Incorrect clicked item id", itemId, mClickHandler.lastClickedItem.getItemId());
} }
@Test @Test
@MediumTest @MediumTest
public void testConvertView_Reused_StandardMenuItem() { public void testConvertView_Reused_StandardMenuItem() {
List<MenuItem> items = new ArrayList<>(); List<MenuItem> items = new ArrayList<>();
items.add(buildMenuItem(0, TITLE_1)); items.add(buildMenuItem(1, TITLE_1));
items.add(buildMenuItem(1, TITLE_2)); items.add(buildMenuItem(2, TITLE_2));
AppMenuAdapter adapter = new AppMenuAdapter( AppMenuAdapter adapter = new AppMenuAdapter(
mClickHandler, items, getActivity().getLayoutInflater(), 0, null); mClickHandler, items, getActivity().getLayoutInflater(), 0, null);
...@@ -111,16 +117,67 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase { ...@@ -111,16 +117,67 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase {
Assert.assertEquals("Incorrect title text for item 1", TITLE_1, titleView.getText()); Assert.assertEquals("Incorrect title text for item 1", TITLE_1, titleView.getText());
View view2 = adapter.getView(1, view1, parentView); View view2 = adapter.getView(1, view1, parentView);
Assert.assertEquals("Convert view should have been re-used.", view1, view2); Assert.assertEquals("Convert view should have been re-used", view1, view2);
Assert.assertEquals("Title should have been updated", TITLE_2, titleView.getText()); Assert.assertEquals("Title should have been updated", TITLE_2, titleView.getText());
} }
@Test
@MediumTest
public void testConvertView_Reused_TitleMenuItem() {
List<MenuItem> items = new ArrayList<>();
items.add(buildTitleMenuItem(1, 2, TITLE_1, 3, TITLE_2));
items.add(buildTitleMenuItem(4, 5, TITLE_3, 6, TITLE_4));
AppMenuAdapter adapter = new AppMenuAdapter(
mClickHandler, items, getActivity().getLayoutInflater(), 0, null);
Assert.assertEquals("Wrong item view type", AppMenuAdapter.MenuItemType.TITLE_BUTTON,
adapter.getItemViewType(0));
ViewGroup parentView = getActivity().findViewById(android.R.id.content);
View view1 = adapter.getView(0, null, parentView);
TextView titleView = view1.findViewById(R.id.title);
Assert.assertEquals("Incorrect title text for item 1", TITLE_1, titleView.getText());
View view2 = adapter.getView(1, view1, parentView);
Assert.assertEquals("Convert view should have been re-used", view1, view2);
Assert.assertEquals("Title should have been updated", TITLE_3, titleView.getText());
}
@Test
@MediumTest
public void testConvertView_Reused_IconRow() {
Drawable icon = AppCompatResources.getDrawable(
getActivity(), org.chromium.chrome.test.R.drawable.test_ic_vintage_filter);
List<MenuItem> items = new ArrayList<>();
items.add(buildIconRow(1, 2, TITLE_1, icon, 3, TITLE_2, icon, 4, "", icon, 0, null, null, 0,
null, null, true));
items.add(buildIconRow(5, 6, TITLE_3, icon, 7, TITLE_4, icon, 8, "", icon, 0, null, null, 0,
null, null, true));
AppMenuAdapter adapter = new AppMenuAdapter(
mClickHandler, items, getActivity().getLayoutInflater(), 0, null);
ViewGroup parentView = getActivity().findViewById(android.R.id.content);
View view1 = adapter.getView(0, null, parentView);
View buttonOne = view1.findViewById(R.id.button_one);
Assert.assertEquals("Incorrect content description for item 1", TITLE_1,
buttonOne.getContentDescription());
View view2 = adapter.getView(1, view1, parentView);
Assert.assertEquals("Convert view should have been re-used", view1, view2);
Assert.assertEquals("Content description should have been updated", TITLE_3,
buttonOne.getContentDescription());
}
@Test @Test
@MediumTest @MediumTest
public void testConvertView_NotReused() { public void testConvertView_NotReused() {
List<MenuItem> items = new ArrayList<>(); List<MenuItem> items = new ArrayList<>();
items.add(buildMenuItem(0, TITLE_1)); items.add(buildMenuItem(1, TITLE_1));
items.add(buildTitleMenuItem(1, 2, TITLE_2, 3, TITLE_3)); items.add(buildTitleMenuItem(2, 3, TITLE_2, 4, TITLE_3));
AppMenuAdapter adapter = new AppMenuAdapter( AppMenuAdapter adapter = new AppMenuAdapter(
mClickHandler, items, getActivity().getLayoutInflater(), 0, null); mClickHandler, items, getActivity().getLayoutInflater(), 0, null);
...@@ -137,9 +194,32 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase { ...@@ -137,9 +194,32 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase {
Assert.assertEquals("Incorrect title text for item 1", TITLE_1, titleView.getText()); Assert.assertEquals("Incorrect title text for item 1", TITLE_1, titleView.getText());
View view2 = adapter.getView(1, view1, parentView); View view2 = adapter.getView(1, view1, parentView);
Assert.assertNotEquals("Convert view should not have been re-used.", view1, view2); Assert.assertNotEquals("Standard view should not have been re-used", view1, view2);
Assert.assertEquals( Assert.assertEquals(
"Title for view 1 should have not have been updated", TITLE_1, titleView.getText()); "Title for view 1 should have not have been updated", TITLE_1, titleView.getText());
View view3 = adapter.getView(0, view2, parentView);
Assert.assertNotEquals("Title button view should not have been re-used", view2, view3);
}
@Test
@MediumTest
public void testConvertView_NotReused_IconRow() {
Drawable icon = AppCompatResources.getDrawable(
getActivity(), org.chromium.chrome.test.R.drawable.test_ic_vintage_filter);
List<MenuItem> items = new ArrayList<>();
items.add(buildIconRow(1, 2, TITLE_1, icon, 3, TITLE_2, icon, 4, "", icon, 0, null, null, 0,
null, null, true));
items.add(buildIconRow(5, 6, TITLE_3, icon, 7, TITLE_4, icon, 8, "", icon, 9, TITLE_5, icon,
0, null, null, true));
AppMenuAdapter adapter = new AppMenuAdapter(
mClickHandler, items, getActivity().getLayoutInflater(), 0, null);
ViewGroup parentView = getActivity().findViewById(android.R.id.content);
View view1 = adapter.getView(0, null, parentView);
View view2 = adapter.getView(1, view1, parentView);
Assert.assertNotEquals("Convert view should not have been re-used", view1, view2);
} }
@Test @Test
...@@ -203,6 +283,8 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase { ...@@ -203,6 +283,8 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase {
Assert.assertEquals("Binder2 incorrectly called", 0, Assert.assertEquals("Binder2 incorrectly called", 0,
customBinder2.getViewItemCallbackHelper.getCallCount()); customBinder2.getViewItemCallbackHelper.getCallCount());
Assert.assertNotEquals("Convert view should not have been re-used", view1, view2); Assert.assertNotEquals("Convert view should not have been re-used", view1, view2);
Assert.assertNotNull("Views created with binder1 should have an enter animation.",
view2.getTag(R.id.menu_item_enter_anim_id));
View view3 = adapter.getView(2, view2, parentView); View view3 = adapter.getView(2, view2, parentView);
Assert.assertEquals( Assert.assertEquals(
...@@ -224,17 +306,36 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase { ...@@ -224,17 +306,36 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase {
Assert.assertEquals( Assert.assertEquals(
"Binder2 not called", 1, customBinder2.getViewItemCallbackHelper.getCallCount()); "Binder2 not called", 1, customBinder2.getViewItemCallbackHelper.getCallCount());
Assert.assertNotEquals("Convert view should not have been re-used", view2, view5); Assert.assertNotEquals("Convert view should not have been re-used", view2, view5);
Assert.assertNull("Views created with binder2 should not have an enter animation",
view5.getTag(R.id.menu_item_enter_anim_id));
} }
private static MenuItem buildMenuItem(int id, CharSequence title) { static MenuItem buildMenuItem(int id, CharSequence title) {
return buildMenuItem(id, title, true);
}
static MenuItem buildMenuItem(int id, CharSequence title, boolean enabled) {
MenuItem item = Mockito.mock(MenuItem.class); MenuItem item = Mockito.mock(MenuItem.class);
Mockito.when(item.getItemId()).thenReturn(id); Mockito.when(item.getItemId()).thenReturn(id);
Mockito.when(item.getTitle()).thenReturn(title); Mockito.when(item.getTitle()).thenReturn(title);
Mockito.when(item.isEnabled()).thenReturn(enabled);
return item; return item;
} }
private static MenuItem buildTitleMenuItem( static MenuItem buildMenuItem(int id, CharSequence title, boolean enabled, Drawable icon) {
MenuItem item = buildMenuItem(id, title, enabled);
Mockito.when(item.getIcon()).thenReturn(icon);
return item;
}
static MenuItem buildTitleMenuItem(
int id, int subId1, CharSequence title1, int subId2, CharSequence title2) { int id, int subId1, CharSequence title1, int subId2, CharSequence title2) {
return buildTitleMenuItem(id, subId1, title1, subId2, title2, null, false, false, true);
}
static MenuItem buildTitleMenuItem(int id, int subId1, CharSequence title1, int subId2,
CharSequence title2, @Nullable Drawable icon, boolean checkable, boolean checked,
boolean enabled) {
MenuItem item = Mockito.mock(MenuItem.class); MenuItem item = Mockito.mock(MenuItem.class);
SubMenu subMenu = Mockito.mock(SubMenu.class); SubMenu subMenu = Mockito.mock(SubMenu.class);
Mockito.when(item.getItemId()).thenReturn(id); Mockito.when(item.getItemId()).thenReturn(id);
...@@ -242,12 +343,84 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase { ...@@ -242,12 +343,84 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase {
Mockito.when(item.getSubMenu()).thenReturn(subMenu); Mockito.when(item.getSubMenu()).thenReturn(subMenu);
Mockito.when(subMenu.size()).thenReturn(2); Mockito.when(subMenu.size()).thenReturn(2);
MenuItem subMenuItem1 = buildMenuItem(subId1, title1); MenuItem title = buildMenuItem(subId1, title1, enabled);
MenuItem subMenuItem2 = buildMenuItem(subId2, title2); MenuItem subItem = buildMenuItem(subId2, title2, enabled);
Mockito.when(subMenu.getItem(0)).thenReturn(title);
Mockito.when(subMenu.getItem(1)).thenReturn(subItem);
if (icon != null) {
assert !checkable : "Title button only supports icon or checkbox";
Mockito.when(subItem.isCheckable()).thenReturn(false);
Mockito.when(subItem.getIcon()).thenReturn(icon);
Mockito.when(subItem.isChecked()).thenReturn(checked);
Mockito.when(subItem.isVisible()).thenReturn(true);
}
if (checkable) {
assert icon == null : "Title button only supports icon or checkbox";
Mockito.when(subItem.isCheckable()).thenReturn(true);
Mockito.when(subItem.isChecked()).thenReturn(checked);
Mockito.when(subItem.isVisible()).thenReturn(true);
}
return item;
}
static MenuItem buildIconMenuItem(int id, CharSequence titleCondensed, boolean enabled) {
MenuItem item = Mockito.mock(MenuItem.class);
Mockito.when(item.getItemId()).thenReturn(id);
Mockito.when(item.getTitleCondensed()).thenReturn(titleCondensed);
Mockito.when(item.isEnabled()).thenReturn(enabled);
return item;
}
static MenuItem buildIconRow(int id, int subId1, CharSequence title1, Drawable icon1,
int subId2, CharSequence title2, Drawable icon2, int subId3, CharSequence title3,
Drawable icon3, int subId4, CharSequence title4, @Nullable Drawable icon4, int subId5,
CharSequence title5, @Nullable Drawable icon5, boolean enabled) {
MenuItem item = Mockito.mock(MenuItem.class);
SubMenu subMenu = Mockito.mock(SubMenu.class);
Mockito.when(item.getItemId()).thenReturn(id);
Mockito.when(item.hasSubMenu()).thenReturn(true);
Mockito.when(item.getSubMenu()).thenReturn(subMenu);
int numSubMenus = 3;
if (subId4 != 0) {
numSubMenus++;
if (subId5 != 0) numSubMenus++;
}
Mockito.when(subMenu.size()).thenReturn(numSubMenus);
MenuItem subMenuItem1 = buildIconMenuItem(subId1, title1, enabled);
Mockito.when(subMenuItem1.getIcon()).thenReturn(icon1);
Mockito.when(subMenuItem1.isVisible()).thenReturn(true);
Mockito.when(subMenu.getItem(0)).thenReturn(subMenuItem1); Mockito.when(subMenu.getItem(0)).thenReturn(subMenuItem1);
MenuItem subMenuItem2 = buildIconMenuItem(subId2, title2, enabled);
Mockito.when(subMenuItem2.getIcon()).thenReturn(icon2);
Mockito.when(subMenuItem2.isVisible()).thenReturn(true);
Mockito.when(subMenu.getItem(1)).thenReturn(subMenuItem2); Mockito.when(subMenu.getItem(1)).thenReturn(subMenuItem2);
MenuItem subMenuItem3 = buildIconMenuItem(subId3, title3, enabled);
Mockito.when(subMenuItem3.getIcon()).thenReturn(icon3);
Mockito.when(subMenuItem3.isVisible()).thenReturn(true);
Mockito.when(subMenu.getItem(2)).thenReturn(subMenuItem3);
if (subId4 != 0) {
MenuItem subMenuItem4 = buildIconMenuItem(subId4, title4, enabled);
Mockito.when(subMenuItem4.getIcon()).thenReturn(icon4);
Mockito.when(subMenuItem4.isVisible()).thenReturn(true);
Mockito.when(subMenu.getItem(3)).thenReturn(subMenuItem4);
if (subId5 != 0) {
MenuItem subMenuItem5 = buildIconMenuItem(subId5, title5, enabled);
Mockito.when(subMenuItem5.getIcon()).thenReturn(icon5);
Mockito.when(subMenuItem5.isVisible()).thenReturn(true);
Mockito.when(subMenu.getItem(4)).thenReturn(subMenuItem5);
}
}
return item; return item;
} }
...@@ -336,7 +509,7 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase { ...@@ -336,7 +509,7 @@ public class AppMenuAdapterTest extends DummyUiActivityTestCase {
@Override @Override
public boolean supportsEnterAnimation(int id) { public boolean supportsEnterAnimation(int id) {
return true; return false;
} }
} }
} }
// Copyright 2019 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.appmenu;
import android.support.test.filters.MediumTest;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
import org.chromium.chrome.browser.lifecycle.LifecycleObserver;
import org.chromium.chrome.browser.ui.widget.highlight.ViewHighlighterTestUtils;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.R;
import org.chromium.chrome.test.ui.DummyUiActivityTestCase;
import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import java.util.concurrent.TimeoutException;
/**
* Integration tests the app menu popup. Covers AppMenuCoordinatorImpl and public interface for
* AppMenuHandlerImpl.
*/
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
public class AppMenuTest extends DummyUiActivityTestCase {
private AppMenuCoordinatorImpl mAppMenuCoordinator;
private AppMenuHandlerImpl mAppMenuHandler;
private TestAppMenuPropertiesDelegate mPropertiesDelegate;
private TestAppMenuDelegate mDelegate;
private TestAppMenuObserver mMenuObserver;
private TestActivityLifecycleDispatcher mLifecycleDispatcher;
@Override
public void setUpTest() throws Exception {
super.setUpTest();
TestThreadUtils.runOnUiThreadBlocking(this::setUpTestOnUiThread);
mLifecycleDispatcher.observerRegisteredCallbackHelper.waitForCallback(0);
}
private void setUpTestOnUiThread() {
mLifecycleDispatcher = new TestActivityLifecycleDispatcher();
mDelegate = new TestAppMenuDelegate();
mAppMenuCoordinator = new AppMenuCoordinatorImpl(getActivity(), mLifecycleDispatcher,
new TestMenuButtonDelegate(), mDelegate, getActivity().getWindow().getDecorView(),
new View(getActivity()));
mAppMenuHandler = mAppMenuCoordinator.getAppMenuHandlerImplForTesting();
mMenuObserver = new TestAppMenuObserver();
mAppMenuCoordinator.getAppMenuHandler().addObserver(mMenuObserver);
mPropertiesDelegate =
(TestAppMenuPropertiesDelegate) mAppMenuCoordinator.getAppMenuPropertiesDelegate();
}
@Test
@MediumTest
public void testShowHideAppMenu() throws TimeoutException {
showSimpleMenuAndAssert();
TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuHandler.hideAppMenu());
mMenuObserver.menuHiddenCallback.waitForCallback(0);
Assert.assertEquals("Incorrect number of calls to #onMenuDismissed after hide", 1,
mPropertiesDelegate.menuDismissedCallback.getCallCount());
TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuCoordinator.destroy());
Assert.assertEquals("Incorrect number of calls to #onMenuDismissed after destroy", 1,
mPropertiesDelegate.menuDismissedCallback.getCallCount());
}
@Test
@MediumTest
public void testShowDestroyAppMenu() throws TimeoutException {
showSimpleMenuAndAssert();
TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuCoordinator.destroy());
Assert.assertEquals("Incorrect number of calls to #onMenuDismissed after destroy", 1,
mPropertiesDelegate.menuDismissedCallback.getCallCount());
}
@Test
@MediumTest
public void testClickMenuItem() throws TimeoutException {
showSimpleMenuAndAssert();
TestThreadUtils.runOnUiThreadBlocking(
()
-> AppMenuTestSupport.callOnItemClick(
mAppMenuCoordinator, R.id.menu_item_three));
mDelegate.itemSelectedCallbackHelper.waitForCallback(0);
Assert.assertEquals("Incorrect id for last selected item.", R.id.menu_item_three,
mDelegate.lastSelectedItemId);
}
@Test
@MediumTest
public void testAppMenuBlockers() throws TimeoutException {
Assert.assertTrue("App menu should be allowed to show, no blockers registered",
AppMenuTestSupport.shouldShowAppMenu(mAppMenuCoordinator));
AppMenuBlocker blocker1 = () -> false;
AppMenuBlocker blocker2 = () -> true;
mAppMenuCoordinator.registerAppMenuBlocker(blocker1);
mAppMenuCoordinator.registerAppMenuBlocker(blocker2);
Assert.assertFalse("App menu should not be allowed to show, both blockers registered",
AppMenuTestSupport.shouldShowAppMenu(mAppMenuCoordinator));
TestThreadUtils.runOnUiThreadBlocking(
() -> mAppMenuCoordinator.showAppMenuForKeyboardEvent());
Assert.assertFalse(
"App menu should not have been shown.", mAppMenuHandler.isAppMenuShowing());
mAppMenuCoordinator.unregisterAppMenuBlocker(blocker1);
Assert.assertTrue("App menu should be allowed to show, only blocker2 registered",
AppMenuTestSupport.shouldShowAppMenu(mAppMenuCoordinator));
showSimpleMenuAndAssert();
}
@Test
@MediumTest
public void testSetMenuHighlight_StandardItem() throws TimeoutException {
Assert.assertFalse(mMenuObserver.menuHighlighting);
TestThreadUtils.runOnUiThreadBlocking(
() -> mAppMenuHandler.setMenuHighlight(R.id.menu_item_one, false));
mMenuObserver.menuHighlightChangedCallback.waitForCallback(0);
Assert.assertTrue(mMenuObserver.menuHighlighting);
showSimpleMenuAndAssert();
View itemView = getViewAtPosition(0);
ViewHighlighterTestUtils.checkHighlightOn(itemView);
TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuHandler.clearMenuHighlight());
mMenuObserver.menuHighlightChangedCallback.waitForCallback(1);
Assert.assertFalse(mMenuObserver.menuHighlighting);
ViewHighlighterTestUtils.checkHighlightOff(itemView);
}
@Test
@MediumTest
public void testSetMenuHighlight_Icon() throws TimeoutException {
mPropertiesDelegate.enableAppIconRow = true;
Assert.assertFalse(mMenuObserver.menuHighlighting);
TestThreadUtils.runOnUiThreadBlocking(
() -> mAppMenuHandler.setMenuHighlight(R.id.icon_one, false));
mMenuObserver.menuHighlightChangedCallback.waitForCallback(0);
Assert.assertTrue(mMenuObserver.menuHighlighting);
showSimpleMenuAndAssert();
View itemView = ((LinearLayout) getViewAtPosition(3)).getChildAt(0);
ViewHighlighterTestUtils.checkHighlightOn(itemView);
TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuHandler.clearMenuHighlight());
mMenuObserver.menuHighlightChangedCallback.waitForCallback(1);
Assert.assertFalse(mMenuObserver.menuHighlighting);
ViewHighlighterTestUtils.checkHighlightOff(itemView);
}
@Test
@MediumTest
public void testMenuItemContentChanged() throws TimeoutException {
showSimpleMenuAndAssert();
View itemView = getViewAtPosition(1);
Assert.assertEquals("Menu item text incorrect", "Menu Item Two",
((TextView) itemView.findViewById(R.id.menu_item_text)).getText());
String newText = "Test!";
TestThreadUtils.runOnUiThreadBlocking(() -> {
mAppMenuHandler.getAppMenu().getMenu().findItem(R.id.menu_item_two).setTitle(newText);
mAppMenuHandler.menuItemContentChanged(R.id.menu_item_two);
});
itemView = getViewAtPosition(1);
Assert.assertEquals("Menu item text incorrect", newText,
((TextView) itemView.findViewById(R.id.menu_item_text)).getText());
}
@Test
@MediumTest
public void testHeaderFooter() throws TimeoutException {
mPropertiesDelegate.headerResourceId = R.layout.test_menu_header;
mPropertiesDelegate.footerResourceId = R.layout.test_menu_footer;
showSimpleMenuAndAssert();
mPropertiesDelegate.headerInflatedCallback.waitForCallback(0);
mPropertiesDelegate.footerInflatedCallback.waitForCallback(0);
Assert.assertEquals("Incorrect number of header views", 1,
mAppMenuHandler.getAppMenu().getListView().getHeaderViewsCount());
Assert.assertNotNull("Footer stub not inflated.",
mAppMenuHandler.getAppMenu().getPopup().getContentView().findViewById(
R.id.app_menu_footer));
}
@Test
@MediumTest
public void testAppMenuHiddenOnStopWithNative() throws TimeoutException {
showSimpleMenuAndAssert();
TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuHandler.onStopWithNative());
Assert.assertFalse(mAppMenuHandler.isAppMenuShowing());
}
@Test
@MediumTest
public void testAppMenuHiddenOnConfigurationChange() throws TimeoutException {
showSimpleMenuAndAssert();
TestThreadUtils.runOnUiThreadBlocking(() -> mAppMenuHandler.onConfigurationChanged(null));
Assert.assertFalse(mAppMenuHandler.isAppMenuShowing());
}
private void showSimpleMenuAndAssert() throws TimeoutException {
int currentCallCount = mMenuObserver.menuShownCallback.getCallCount();
TestThreadUtils.runOnUiThreadBlocking(
() -> mAppMenuCoordinator.showAppMenuForKeyboardEvent());
mMenuObserver.menuShownCallback.waitForCallback(currentCallCount);
Assert.assertTrue("Menu should be showing", mAppMenuHandler.isAppMenuShowing());
TestThreadUtils.runOnUiThreadBlocking(
() -> mAppMenuHandler.getAppMenu().finishAnimationsForTests());
}
private class TestActivityLifecycleDispatcher implements ActivityLifecycleDispatcher {
public CallbackHelper observerRegisteredCallbackHelper = new CallbackHelper();
@Override
public void register(LifecycleObserver observer) {
observerRegisteredCallbackHelper.notifyCalled();
}
@Override
public void unregister(LifecycleObserver observer) {}
@Override
public int getCurrentActivityState() {
return 0;
}
}
private class TestMenuButtonDelegate implements MenuButtonDelegate {
@Nullable
@Override
public View getMenuButtonView() {
return null;
}
@Override
public boolean isMenuFromBottom() {
return false;
}
}
private View getViewAtPosition(int index) {
// Wait for the view to be available. This is necessary when the menu is first shown.
CriteriaHelper.pollUiThread(
()
-> AppMenuTestSupport.getListView(mAppMenuCoordinator).getChildAt(index)
!= null);
return AppMenuTestSupport.getListView(mAppMenuCoordinator).getChildAt(index);
}
}
...@@ -43,7 +43,7 @@ import org.chromium.ui.test.util.UiRestriction; ...@@ -43,7 +43,7 @@ import org.chromium.ui.test.util.UiRestriction;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
/** /**
* Tests AppMenu popup * Tests tabbed mode app menu popup.
*/ */
@RunWith(ChromeJUnit4ClassRunner.class) @RunWith(ChromeJUnit4ClassRunner.class)
@RetryOnFailure @RetryOnFailure
...@@ -178,29 +178,6 @@ public class TabbedAppMenuTest { ...@@ -178,29 +178,6 @@ public class TabbedAppMenuTest {
hitEnterAndAssertAppMenuDismissed(); hitEnterAndAssertAppMenuDismissed();
} }
/**
* Test that changing orientation hides the menu.
*/
/*
@SmallTest
@Feature({"Browser", "Main"})
*/
@Test
@DisabledTest(message = "crbug.com/458193")
public void testChangingOrientationHidesMenu() {
mActivityTestRule.getActivity().setRequestedOrientation(
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
showAppMenuAndAssertMenuShown();
mActivityTestRule.getActivity().setRequestedOrientation(
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
CriteriaHelper.pollInstrumentationThread(new Criteria("AppMenu did not dismiss") {
@Override
public boolean isSatisfied() {
return !mAppMenuHandler.isAppMenuShowing();
}
});
}
@Test @Test
@SmallTest @SmallTest
@Feature({"Browser", "Main"}) @Feature({"Browser", "Main"})
......
// Copyright 2019 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.appmenu;
import android.os.Bundle;
import androidx.annotation.Nullable;
import org.chromium.base.test.util.CallbackHelper;
class TestAppMenuDelegate implements AppMenuDelegate {
public final CallbackHelper itemSelectedCallbackHelper = new CallbackHelper();
public int lastSelectedItemId;
@Override
public boolean onOptionsItemSelected(int itemId, @Nullable Bundle menuItemData) {
lastSelectedItemId = itemId;
itemSelectedCallbackHelper.notifyCalled();
return true;
}
@Override
public AppMenuPropertiesDelegate createAppMenuPropertiesDelegate() {
return new TestAppMenuPropertiesDelegate();
}
}
// Copyright 2019 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.appmenu;
import org.chromium.base.test.util.CallbackHelper;
/**
* AppMenuObserver that notifies callbacks when app menu events occur.
*/
public class TestAppMenuObserver implements AppMenuObserver {
public CallbackHelper menuShownCallback = new CallbackHelper();
public CallbackHelper menuHiddenCallback = new CallbackHelper();
public CallbackHelper menuHighlightChangedCallback = new CallbackHelper();
public boolean menuHighlighting;
@Override
public void onMenuVisibilityChanged(boolean isVisible) {
if (isVisible) {
menuShownCallback.notifyCalled();
} else {
menuHiddenCallback.notifyCalled();
}
}
@Override
public void onMenuHighlightChanged(boolean highlighting) {
menuHighlighting = highlighting;
menuHighlightChangedCallback.notifyCalled();
}
}
// Copyright 2019 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.appmenu;
import android.os.Bundle;
import android.support.v7.content.res.AppCompatResources;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import androidx.annotation.Nullable;
import org.chromium.base.ContextUtils;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.chrome.test.R;
import java.util.List;
class TestAppMenuPropertiesDelegate implements AppMenuPropertiesDelegate {
public final CallbackHelper menuDismissedCallback = new CallbackHelper();
public final CallbackHelper footerInflatedCallback = new CallbackHelper();
public final CallbackHelper headerInflatedCallback = new CallbackHelper();
public int footerResourceId;
public int headerResourceId;
public boolean enableAppIconRow;
@Override
public void destroy() {}
@Override
public int getAppMenuLayoutId() {
return R.menu.test_menu;
}
@Nullable
@Override
public List<CustomViewBinder> getCustomViewBinders() {
return null;
}
@Override
public void prepareMenu(Menu menu, AppMenuHandler handler) {
menu.findItem(R.id.icon_row_menu_id).setVisible(enableAppIconRow);
if (enableAppIconRow) {
menu.findItem(R.id.icon_one)
.setIcon(AppCompatResources.getDrawable(ContextUtils.getApplicationContext(),
R.drawable.test_ic_arrow_forward_black_24dp));
menu.findItem(R.id.icon_two)
.setIcon(AppCompatResources.getDrawable(ContextUtils.getApplicationContext(),
R.drawable.test_ic_arrow_forward_black_24dp));
menu.findItem(R.id.icon_three)
.setIcon(AppCompatResources.getDrawable(ContextUtils.getApplicationContext(),
R.drawable.test_ic_arrow_forward_black_24dp));
}
}
@Nullable
@Override
public Bundle getBundleForMenuItem(MenuItem item) {
return null;
}
@Override
public void loadingStateChanged(boolean isLoading) {}
@Override
public void onMenuDismissed() {
menuDismissedCallback.notifyCalled();
}
@Override
public int getFooterResourceId() {
return footerResourceId;
}
@Override
public int getHeaderResourceId() {
return headerResourceId;
}
@Override
public boolean shouldShowFooter(int maxMenuHeight) {
return footerResourceId != 0;
}
@Override
public boolean shouldShowHeader(int maxMenuHeight) {
return headerResourceId != 0;
}
@Override
public void onFooterViewInflated(AppMenuHandler appMenuHandler, View view) {
footerInflatedCallback.notifyCalled();
}
@Override
public void onHeaderViewInflated(AppMenuHandler appMenuHandler, View view) {
headerInflatedCallback.notifyCalled();
}
}
...@@ -19,15 +19,14 @@ import org.junit.Test; ...@@ -19,15 +19,14 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordHistogram;
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.Feature; import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.Restriction; import org.chromium.base.test.util.Restriction;
import org.chromium.base.test.util.RetryOnFailure; import org.chromium.base.test.util.RetryOnFailure;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.appmenu.AppMenuObserver;
import org.chromium.chrome.browser.appmenu.AppMenuTestSupport; import org.chromium.chrome.browser.appmenu.AppMenuTestSupport;
import org.chromium.chrome.browser.appmenu.TestAppMenuObserver;
import org.chromium.chrome.browser.util.UrlConstants; import org.chromium.chrome.browser.util.UrlConstants;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
...@@ -106,22 +105,6 @@ public class UpdateMenuItemHelperTest { ...@@ -106,22 +105,6 @@ public class UpdateMenuItemHelperTest {
} }
} }
private static class TestAppMenuObserver implements AppMenuObserver {
CallbackHelper mMenuShownCallback = new CallbackHelper();
CallbackHelper mMenuHiddenCallback = new CallbackHelper();
@Override
public void onMenuVisibilityChanged(boolean isVisible) {
if (isVisible) {
mMenuShownCallback.notifyCalled();
} else {
mMenuHiddenCallback.notifyCalled();
}
}
@Override
public void onMenuHighlightChanged(boolean highlighting) {}
}
private MockVersionNumberGetter mMockVersionNumberGetter; private MockVersionNumberGetter mMockVersionNumberGetter;
private MockMarketURLGetter mMockMarketURLGetter; private MockMarketURLGetter mMockMarketURLGetter;
...@@ -278,7 +261,7 @@ public class UpdateMenuItemHelperTest { ...@@ -278,7 +261,7 @@ public class UpdateMenuItemHelperTest {
Assert.assertEquals("Incorrect item not clicked histogram count after item clicked", 0, Assert.assertEquals("Incorrect item not clicked histogram count after item clicked", 0,
getTotalItemNotClickedCount()); getTotalItemNotClickedCount());
mMenuObserver.mMenuHiddenCallback.waitForCallback(0); mMenuObserver.menuHiddenCallback.waitForCallback(0);
waitForAppMenuDimissedRunnable(); waitForAppMenuDimissedRunnable();
Assert.assertEquals("Incorrect item clicked histogram count after menu dismissed", 1, Assert.assertEquals("Incorrect item clicked histogram count after menu dismissed", 1,
...@@ -311,21 +294,21 @@ public class UpdateMenuItemHelperTest { ...@@ -311,21 +294,21 @@ public class UpdateMenuItemHelperTest {
} }
private void showAppMenuAndAssertMenuShown() throws TimeoutException { private void showAppMenuAndAssertMenuShown() throws TimeoutException {
int currentCallCount = mMenuObserver.mMenuShownCallback.getCallCount(); int currentCallCount = mMenuObserver.menuShownCallback.getCallCount();
TestThreadUtils.runOnUiThreadBlocking(() -> { TestThreadUtils.runOnUiThreadBlocking(() -> {
AppMenuTestSupport.showAppMenu( AppMenuTestSupport.showAppMenu(
mActivityTestRule.getAppMenuCoordinator(), null, false, false); mActivityTestRule.getAppMenuCoordinator(), null, false, false);
}); });
mMenuObserver.mMenuShownCallback.waitForCallback(currentCallCount); mMenuObserver.menuShownCallback.waitForCallback(currentCallCount);
} }
private void hideAppMenuAndAssertMenuShown() throws TimeoutException { private void hideAppMenuAndAssertMenuShown() throws TimeoutException {
int currentCallCount = mMenuObserver.mMenuHiddenCallback.getCallCount(); int currentCallCount = mMenuObserver.menuHiddenCallback.getCallCount();
TestThreadUtils.runOnUiThreadBlocking( TestThreadUtils.runOnUiThreadBlocking(
() -> mActivityTestRule.getAppMenuCoordinator().getAppMenuHandler().hideAppMenu()); () -> mActivityTestRule.getAppMenuCoordinator().getAppMenuHandler().hideAppMenu());
mMenuObserver.mMenuHiddenCallback.waitForCallback(currentCallCount); mMenuObserver.menuHiddenCallback.waitForCallback(currentCallCount);
} }
private int getTotalItemClickedCount() { private int getTotalItemClickedCount() {
......
a4201a720f7bd86bd2d2ee430c5d474a46045c49
\ No newline at end of file
aee3b1f0f4ebedc3f638a67a1ac10e8a1f3ad26f
\ No newline at end of file
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