OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.appmenu; | 5 package org.chromium.chrome.browser.appmenu; |
6 | 6 |
7 import android.app.Activity; | 7 import android.app.Activity; |
8 import android.content.pm.ActivityInfo; | 8 import android.content.pm.ActivityInfo; |
| 9 import android.support.test.InstrumentationRegistry; |
9 import android.support.test.filters.SmallTest; | 10 import android.support.test.filters.SmallTest; |
10 import android.view.KeyEvent; | 11 import android.view.KeyEvent; |
11 import android.view.MenuItem; | 12 import android.view.MenuItem; |
12 import android.view.View; | 13 import android.view.View; |
13 import android.widget.ListPopupWindow; | 14 import android.widget.ListPopupWindow; |
14 import android.widget.ListView; | 15 import android.widget.ListView; |
15 | 16 |
| 17 import org.junit.Assert; |
| 18 import org.junit.Before; |
| 19 import org.junit.Rule; |
| 20 import org.junit.Test; |
| 21 import org.junit.runner.RunWith; |
| 22 |
16 import org.chromium.base.ThreadUtils; | 23 import org.chromium.base.ThreadUtils; |
17 import org.chromium.base.annotations.SuppressFBWarnings; | 24 import org.chromium.base.annotations.SuppressFBWarnings; |
| 25 import org.chromium.base.test.util.CommandLineFlags; |
18 import org.chromium.base.test.util.DisabledTest; | 26 import org.chromium.base.test.util.DisabledTest; |
19 import org.chromium.base.test.util.Feature; | 27 import org.chromium.base.test.util.Feature; |
20 import org.chromium.base.test.util.RetryOnFailure; | 28 import org.chromium.base.test.util.RetryOnFailure; |
21 import org.chromium.base.test.util.UrlUtils; | 29 import org.chromium.base.test.util.UrlUtils; |
22 import org.chromium.chrome.browser.ChromeActivity; | 30 import org.chromium.chrome.browser.ChromeActivity; |
| 31 import org.chromium.chrome.browser.ChromeSwitches; |
23 import org.chromium.chrome.browser.ChromeTabbedActivity; | 32 import org.chromium.chrome.browser.ChromeTabbedActivity; |
24 import org.chromium.chrome.test.ChromeActivityTestCaseBase; | 33 import org.chromium.chrome.test.ChromeActivityTestRule; |
| 34 import org.chromium.chrome.test.ChromeJUnit4ClassRunner; |
25 import org.chromium.chrome.test.util.ChromeTabUtils; | 35 import org.chromium.chrome.test.util.ChromeTabUtils; |
26 import org.chromium.content.browser.test.util.Criteria; | 36 import org.chromium.content.browser.test.util.Criteria; |
27 import org.chromium.content.browser.test.util.CriteriaHelper; | 37 import org.chromium.content.browser.test.util.CriteriaHelper; |
28 | 38 |
29 import java.util.concurrent.Callable; | 39 import java.util.concurrent.Callable; |
30 | 40 |
31 /** | 41 /** |
32 * Tests AppMenu popup | 42 * Tests AppMenu popup |
33 */ | 43 */ |
| 44 @RunWith(ChromeJUnit4ClassRunner.class) |
34 @RetryOnFailure | 45 @RetryOnFailure |
35 public class AppMenuTest extends ChromeActivityTestCaseBase<ChromeActivity> { | 46 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, |
| 47 ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG}) |
| 48 public class AppMenuTest { |
| 49 @Rule |
| 50 public ChromeActivityTestRule<ChromeActivity> mActivityTestRule = |
| 51 new ChromeActivityTestRule<>(ChromeActivity.class); |
| 52 |
36 private static final String TEST_URL = UrlUtils.encodeHtmlDataUri("<html>foo
</html>"); | 53 private static final String TEST_URL = UrlUtils.encodeHtmlDataUri("<html>foo
</html>"); |
37 | 54 |
38 private AppMenu mAppMenu; | 55 private AppMenu mAppMenu; |
39 private AppMenuHandler mAppMenuHandler; | 56 private AppMenuHandler mAppMenuHandler; |
40 | 57 |
41 /** | 58 /** |
42 * AppMenuHandler that will be used to intercept item selections for testing
. | 59 * AppMenuHandler that will be used to intercept item selections for testing
. |
43 */ | 60 */ |
44 @SuppressFBWarnings("URF_UNREAD_FIELD") | 61 @SuppressFBWarnings("URF_UNREAD_FIELD") |
45 public static class AppMenuHandlerForTest extends AppMenuHandler { | 62 public static class AppMenuHandlerForTest extends AppMenuHandler { |
46 int mLastSelectedItemId = -1; | 63 int mLastSelectedItemId = -1; |
47 | 64 |
48 /** | 65 /** |
49 * AppMenuHandler for intercepting options item selections. | 66 * AppMenuHandler for intercepting options item selections. |
50 */ | 67 */ |
51 public AppMenuHandlerForTest(Activity activity, AppMenuPropertiesDelegat
e delegate, | 68 public AppMenuHandlerForTest(Activity activity, AppMenuPropertiesDelegat
e delegate, |
52 int menuResourceId) { | 69 int menuResourceId) { |
53 super(activity, delegate, menuResourceId); | 70 super(activity, delegate, menuResourceId); |
54 } | 71 } |
55 | 72 |
56 @Override | 73 @Override |
57 void onOptionsItemSelected(MenuItem item) { | 74 void onOptionsItemSelected(MenuItem item) { |
58 mLastSelectedItemId = item.getItemId(); | 75 mLastSelectedItemId = item.getItemId(); |
59 } | 76 } |
60 } | 77 } |
61 | 78 |
62 public AppMenuTest() { | 79 @Before |
63 super(ChromeActivity.class); | 80 public void setUp() throws Exception { |
64 } | |
65 | |
66 @Override | |
67 public void startMainActivity() throws InterruptedException { | |
68 startMainActivityWithURL(TEST_URL); | |
69 } | |
70 | |
71 @Override | |
72 protected void setUp() throws Exception { | |
73 // We need list selection; ensure we are not in touch mode. | 81 // We need list selection; ensure we are not in touch mode. |
74 getInstrumentation().setInTouchMode(false); | 82 InstrumentationRegistry.getInstrumentation().setInTouchMode(false); |
75 | 83 |
76 ChromeActivity.setAppMenuHandlerFactoryForTesting( | 84 ChromeActivity.setAppMenuHandlerFactoryForTesting( |
77 new ChromeActivity.AppMenuHandlerFactory() { | 85 new ChromeActivity.AppMenuHandlerFactory() { |
78 @Override | 86 @Override |
79 public AppMenuHandler get(Activity activity, AppMenuProperti
esDelegate delegate, | 87 public AppMenuHandler get(Activity activity, AppMenuProperti
esDelegate delegate, |
80 int menuResourceId) { | 88 int menuResourceId) { |
81 mAppMenuHandler = | 89 mAppMenuHandler = |
82 new AppMenuHandlerForTest(activity, delegate, me
nuResourceId); | 90 new AppMenuHandlerForTest(activity, delegate, me
nuResourceId); |
83 return mAppMenuHandler; | 91 return mAppMenuHandler; |
84 } | 92 } |
85 }); | 93 }); |
86 | 94 |
87 super.setUp(); | 95 mActivityTestRule.startMainActivityWithURL(TEST_URL); |
88 | 96 |
89 showAppMenuAndAssertMenuShown(); | 97 showAppMenuAndAssertMenuShown(); |
90 mAppMenu = getActivity().getAppMenuHandler().getAppMenu(); | 98 mAppMenu = mActivityTestRule.getActivity().getAppMenuHandler().getAppMen
u(); |
91 ThreadUtils.runOnUiThread(new Runnable() { | 99 ThreadUtils.runOnUiThread(new Runnable() { |
92 @Override | 100 @Override |
93 public void run() { | 101 public void run() { |
94 mAppMenu.getPopup().getListView().setSelection(0); | 102 mAppMenu.getPopup().getListView().setSelection(0); |
95 } | 103 } |
96 }); | 104 }); |
97 CriteriaHelper.pollInstrumentationThread(Criteria.equals(0, new Callable
<Integer>() { | 105 CriteriaHelper.pollInstrumentationThread(Criteria.equals(0, new Callable
<Integer>() { |
98 @Override | 106 @Override |
99 public Integer call() { | 107 public Integer call() { |
100 return getCurrentFocusedRow(); | 108 return getCurrentFocusedRow(); |
101 } | 109 } |
102 })); | 110 })); |
103 getInstrumentation().waitForIdleSync(); | 111 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); |
104 } | 112 } |
105 | 113 |
106 /** | 114 /** |
107 * Verify opening a new tab from the menu. | 115 * Verify opening a new tab from the menu. |
108 */ | 116 */ |
| 117 @Test |
109 @SmallTest | 118 @SmallTest |
110 @Feature({"Browser", "Main"}) | 119 @Feature({"Browser", "Main"}) |
111 public void testMenuNewTab() throws InterruptedException { | 120 public void testMenuNewTab() throws InterruptedException { |
112 final int tabCountBefore = getActivity().getCurrentTabModel().getCount()
; | 121 final int tabCountBefore = mActivityTestRule.getActivity().getCurrentTab
Model().getCount(); |
113 ChromeTabUtils.newTabFromMenu(getInstrumentation(), (ChromeTabbedActivit
y) getActivity()); | 122 ChromeTabUtils.newTabFromMenu(InstrumentationRegistry.getInstrumentation
(), |
114 final int tabCountAfter = getActivity().getCurrentTabModel().getCount(); | 123 (ChromeTabbedActivity) mActivityTestRule.getActivity()); |
115 assertTrue("Expected: " + (tabCountBefore + 1) + " Got: " + tabCountAfte
r, | 124 final int tabCountAfter = mActivityTestRule.getActivity().getCurrentTabM
odel().getCount(); |
| 125 Assert.assertTrue("Expected: " + (tabCountBefore + 1) + " Got: " + tabCo
untAfter, |
116 tabCountBefore + 1 == tabCountAfter); | 126 tabCountBefore + 1 == tabCountAfter); |
117 } | 127 } |
118 | 128 |
119 /** | 129 /** |
120 * Test bounds when accessing the menu through the keyboard. | 130 * Test bounds when accessing the menu through the keyboard. |
121 * Make sure that the menu stays open when trying to move past the first and
last items. | 131 * Make sure that the menu stays open when trying to move past the first and
last items. |
122 */ | 132 */ |
| 133 @Test |
123 @SmallTest | 134 @SmallTest |
124 @Feature({"Browser", "Main"}) | 135 @Feature({"Browser", "Main"}) |
125 public void testKeyboardMenuBoundaries() { | 136 public void testKeyboardMenuBoundaries() { |
126 moveToBoundary(false, true); | 137 moveToBoundary(false, true); |
127 assertEquals(getCount() - 1, getCurrentFocusedRow()); | 138 Assert.assertEquals(getCount() - 1, getCurrentFocusedRow()); |
128 moveToBoundary(true, true); | 139 moveToBoundary(true, true); |
129 assertEquals(0, getCurrentFocusedRow()); | 140 Assert.assertEquals(0, getCurrentFocusedRow()); |
130 moveToBoundary(false, true); | 141 moveToBoundary(false, true); |
131 assertEquals(getCount() - 1, getCurrentFocusedRow()); | 142 Assert.assertEquals(getCount() - 1, getCurrentFocusedRow()); |
132 } | 143 } |
133 | 144 |
134 /** | 145 /** |
135 * Test that typing ENTER immediately opening the menu works. | 146 * Test that typing ENTER immediately opening the menu works. |
136 */ | 147 */ |
| 148 @Test |
137 @SmallTest | 149 @SmallTest |
138 @Feature({"Browser", "Main"}) | 150 @Feature({"Browser", "Main"}) |
139 public void testKeyboardMenuEnterOnOpen() { | 151 public void testKeyboardMenuEnterOnOpen() { |
140 hitEnterAndAssertAppMenuDismissed(); | 152 hitEnterAndAssertAppMenuDismissed(); |
141 } | 153 } |
142 | 154 |
143 /** | 155 /** |
144 * Test that hitting ENTER past the top item doesn't crash Chrome. | 156 * Test that hitting ENTER past the top item doesn't crash Chrome. |
145 */ | 157 */ |
| 158 @Test |
146 @SmallTest | 159 @SmallTest |
147 @Feature({"Browser", "Main"}) | 160 @Feature({"Browser", "Main"}) |
148 public void testKeyboardEnterAfterMovePastTopItem() { | 161 public void testKeyboardEnterAfterMovePastTopItem() { |
149 moveToBoundary(true, true); | 162 moveToBoundary(true, true); |
150 assertEquals(0, getCurrentFocusedRow()); | 163 Assert.assertEquals(0, getCurrentFocusedRow()); |
151 hitEnterAndAssertAppMenuDismissed(); | 164 hitEnterAndAssertAppMenuDismissed(); |
152 } | 165 } |
153 | 166 |
154 /** | 167 /** |
155 * Test that hitting ENTER past the bottom item doesn't crash Chrome. | 168 * Test that hitting ENTER past the bottom item doesn't crash Chrome. |
156 * Catches regressions for http://crbug.com/181067 | 169 * Catches regressions for http://crbug.com/181067 |
157 */ | 170 */ |
| 171 @Test |
158 @SmallTest | 172 @SmallTest |
159 @Feature({"Browser", "Main"}) | 173 @Feature({"Browser", "Main"}) |
160 public void testKeyboardEnterAfterMovePastBottomItem() { | 174 public void testKeyboardEnterAfterMovePastBottomItem() { |
161 moveToBoundary(false, true); | 175 moveToBoundary(false, true); |
162 assertEquals(getCount() - 1, getCurrentFocusedRow()); | 176 Assert.assertEquals(getCount() - 1, getCurrentFocusedRow()); |
163 hitEnterAndAssertAppMenuDismissed(); | 177 hitEnterAndAssertAppMenuDismissed(); |
164 } | 178 } |
165 | 179 |
166 /** | 180 /** |
167 * Test that hitting ENTER on the top item actually triggers the top item. | 181 * Test that hitting ENTER on the top item actually triggers the top item. |
168 * Catches regressions for https://crbug.com/191239 for shrunken menus. | 182 * Catches regressions for https://crbug.com/191239 for shrunken menus. |
169 */ | 183 */ |
| 184 @Test |
170 @SmallTest | 185 @SmallTest |
171 @Feature({"Browser", "Main"}) | 186 @Feature({"Browser", "Main"}) |
172 public void testKeyboardMenuEnterOnTopItemLandscape() { | 187 public void testKeyboardMenuEnterOnTopItemLandscape() { |
173 getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LA
NDSCAPE); | 188 mActivityTestRule.getActivity().setRequestedOrientation( |
| 189 ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); |
174 showAppMenuAndAssertMenuShown(); | 190 showAppMenuAndAssertMenuShown(); |
175 moveToBoundary(true, false); | 191 moveToBoundary(true, false); |
176 assertEquals(0, getCurrentFocusedRow()); | 192 Assert.assertEquals(0, getCurrentFocusedRow()); |
177 hitEnterAndAssertAppMenuDismissed(); | 193 hitEnterAndAssertAppMenuDismissed(); |
178 } | 194 } |
179 | 195 |
180 /** | 196 /** |
181 * Test that hitting ENTER on the top item doesn't crash Chrome. | 197 * Test that hitting ENTER on the top item doesn't crash Chrome. |
182 */ | 198 */ |
| 199 @Test |
183 @SmallTest | 200 @SmallTest |
184 @Feature({"Browser", "Main"}) | 201 @Feature({"Browser", "Main"}) |
185 public void testKeyboardMenuEnterOnTopItemPortrait() { | 202 public void testKeyboardMenuEnterOnTopItemPortrait() { |
186 getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PO
RTRAIT); | 203 mActivityTestRule.getActivity().setRequestedOrientation( |
| 204 ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); |
187 showAppMenuAndAssertMenuShown(); | 205 showAppMenuAndAssertMenuShown(); |
188 moveToBoundary(true, false); | 206 moveToBoundary(true, false); |
189 assertEquals(0, getCurrentFocusedRow()); | 207 Assert.assertEquals(0, getCurrentFocusedRow()); |
190 hitEnterAndAssertAppMenuDismissed(); | 208 hitEnterAndAssertAppMenuDismissed(); |
191 } | 209 } |
192 | 210 |
193 /** | 211 /** |
194 * Test that changing orientation hides the menu. | 212 * Test that changing orientation hides the menu. |
195 */ | 213 */ |
196 /* | 214 /* |
197 @SmallTest | 215 @SmallTest |
198 @Feature({"Browser", "Main"}) | 216 @Feature({"Browser", "Main"}) |
199 */ | 217 */ |
| 218 @Test |
200 @DisabledTest(message = "crbug.com/458193") | 219 @DisabledTest(message = "crbug.com/458193") |
201 public void testChangingOrientationHidesMenu() { | 220 public void testChangingOrientationHidesMenu() { |
202 getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LA
NDSCAPE); | 221 mActivityTestRule.getActivity().setRequestedOrientation( |
| 222 ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); |
203 showAppMenuAndAssertMenuShown(); | 223 showAppMenuAndAssertMenuShown(); |
204 getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PO
RTRAIT); | 224 mActivityTestRule.getActivity().setRequestedOrientation( |
| 225 ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); |
205 CriteriaHelper.pollInstrumentationThread(new Criteria("AppMenu did not d
ismiss") { | 226 CriteriaHelper.pollInstrumentationThread(new Criteria("AppMenu did not d
ismiss") { |
206 @Override | 227 @Override |
207 public boolean isSatisfied() { | 228 public boolean isSatisfied() { |
208 return !mAppMenuHandler.isAppMenuShowing(); | 229 return !mAppMenuHandler.isAppMenuShowing(); |
209 } | 230 } |
210 }); | 231 }); |
211 } | 232 } |
212 | 233 |
213 private void showAppMenuAndAssertMenuShown() { | 234 private void showAppMenuAndAssertMenuShown() { |
214 ThreadUtils.runOnUiThread(new Runnable() { | 235 ThreadUtils.runOnUiThread(new Runnable() { |
215 @Override | 236 @Override |
216 public void run() { | 237 public void run() { |
217 mAppMenuHandler.showAppMenu(null, false); | 238 mAppMenuHandler.showAppMenu(null, false); |
218 } | 239 } |
219 }); | 240 }); |
220 CriteriaHelper.pollInstrumentationThread(new Criteria("AppMenu did not s
how") { | 241 CriteriaHelper.pollInstrumentationThread(new Criteria("AppMenu did not s
how") { |
221 @Override | 242 @Override |
222 public boolean isSatisfied() { | 243 public boolean isSatisfied() { |
223 return mAppMenuHandler.isAppMenuShowing(); | 244 return mAppMenuHandler.isAppMenuShowing(); |
224 } | 245 } |
225 }); | 246 }); |
226 } | 247 } |
227 | 248 |
228 private void hitEnterAndAssertAppMenuDismissed() { | 249 private void hitEnterAndAssertAppMenuDismissed() { |
229 getInstrumentation().waitForIdleSync(); | 250 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); |
230 pressKey(KeyEvent.KEYCODE_ENTER); | 251 pressKey(KeyEvent.KEYCODE_ENTER); |
231 CriteriaHelper.pollInstrumentationThread(new Criteria("AppMenu did not d
ismiss") { | 252 CriteriaHelper.pollInstrumentationThread(new Criteria("AppMenu did not d
ismiss") { |
232 @Override | 253 @Override |
233 public boolean isSatisfied() { | 254 public boolean isSatisfied() { |
234 return !mAppMenuHandler.isAppMenuShowing(); | 255 return !mAppMenuHandler.isAppMenuShowing(); |
235 } | 256 } |
236 }); | 257 }); |
237 } | 258 } |
238 | 259 |
239 private void moveToBoundary(boolean towardsTop, boolean movePast) { | 260 private void moveToBoundary(boolean towardsTop, boolean movePast) { |
(...skipping 17 matching lines...) Expand all Loading... |
257 pressKey(towardsTop ? KeyEvent.KEYCODE_DPAD_UP : KeyEvent.KEYCODE_DP
AD_DOWN); | 278 pressKey(towardsTop ? KeyEvent.KEYCODE_DPAD_UP : KeyEvent.KEYCODE_DP
AD_DOWN); |
258 CriteriaHelper.pollInstrumentationThread(Criteria.equals(end, new Ca
llable<Integer>() { | 279 CriteriaHelper.pollInstrumentationThread(Criteria.equals(end, new Ca
llable<Integer>() { |
259 @Override | 280 @Override |
260 public Integer call() { | 281 public Integer call() { |
261 return getCurrentFocusedRow(); | 282 return getCurrentFocusedRow(); |
262 } | 283 } |
263 })); | 284 })); |
264 } | 285 } |
265 | 286 |
266 // The menu should stay open. | 287 // The menu should stay open. |
267 assertTrue(mAppMenu.isShowing()); | 288 Assert.assertTrue(mAppMenu.isShowing()); |
268 } | 289 } |
269 | 290 |
270 private void pressKey(final int keycode) { | 291 private void pressKey(final int keycode) { |
271 final View view = mAppMenu.getPopup().getListView(); | 292 final View view = mAppMenu.getPopup().getListView(); |
272 ThreadUtils.runOnUiThread(new Runnable() { | 293 ThreadUtils.runOnUiThread(new Runnable() { |
273 @Override | 294 @Override |
274 public void run() { | 295 public void run() { |
275 view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keycode
)); | 296 view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keycode
)); |
276 view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keycode))
; | 297 view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keycode))
; |
277 } | 298 } |
278 }); | 299 }); |
279 getInstrumentation().waitForIdleSync(); | 300 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); |
280 } | 301 } |
281 | 302 |
282 private int getCurrentFocusedRow() { | 303 private int getCurrentFocusedRow() { |
283 ListPopupWindow popup = mAppMenu.getPopup(); | 304 ListPopupWindow popup = mAppMenu.getPopup(); |
284 if (popup == null || popup.getListView() == null) return ListView.INVALI
D_POSITION; | 305 if (popup == null || popup.getListView() == null) return ListView.INVALI
D_POSITION; |
285 ListView listView = popup.getListView(); | 306 ListView listView = popup.getListView(); |
286 return listView.getSelectedItemPosition(); | 307 return listView.getSelectedItemPosition(); |
287 } | 308 } |
288 | 309 |
289 private int getCount() { | 310 private int getCount() { |
290 ListPopupWindow popup = mAppMenu.getPopup(); | 311 ListPopupWindow popup = mAppMenu.getPopup(); |
291 if (popup == null || popup.getListView() == null) return 0; | 312 if (popup == null || popup.getListView() == null) return 0; |
292 return popup.getListView().getCount(); | 313 return popup.getListView().getCount(); |
293 } | 314 } |
294 } | 315 } |
OLD | NEW |