OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.chrome.browser.ntp; |
| 6 |
| 7 import android.test.suitebuilder.annotation.LargeTest; |
| 8 import android.test.suitebuilder.annotation.MediumTest; |
| 9 import android.test.suitebuilder.annotation.SmallTest; |
| 10 import android.view.KeyEvent; |
| 11 import android.view.View; |
| 12 import android.view.ViewGroup; |
| 13 |
| 14 import com.google.android.apps.chrome.R; |
| 15 |
| 16 import org.chromium.base.ThreadUtils; |
| 17 import org.chromium.base.test.util.Feature; |
| 18 import org.chromium.chrome.browser.EmptyTabObserver; |
| 19 import org.chromium.chrome.browser.Tab; |
| 20 import org.chromium.chrome.browser.UrlConstants; |
| 21 import org.chromium.chrome.browser.omnibox.LocationBarLayout; |
| 22 import org.chromium.chrome.browser.omnibox.UrlBar; |
| 23 import org.chromium.chrome.test.ChromeTabbedActivityTestBase; |
| 24 import org.chromium.chrome.test.util.ChromeTabUtils; |
| 25 import org.chromium.chrome.test.util.NewTabPageTestUtils; |
| 26 import org.chromium.chrome.test.util.OmniboxTestUtils; |
| 27 import org.chromium.chrome.test.util.TestHttpServerClient; |
| 28 import org.chromium.content.browser.test.util.CallbackHelper; |
| 29 import org.chromium.content.browser.test.util.Criteria; |
| 30 import org.chromium.content.browser.test.util.CriteriaHelper; |
| 31 import org.chromium.content.browser.test.util.KeyUtils; |
| 32 import org.chromium.content.browser.test.util.TestTouchUtils; |
| 33 import org.chromium.content_public.browser.LoadUrlParams; |
| 34 import org.chromium.net.test.util.TestWebServer; |
| 35 import org.chromium.ui.base.PageTransition; |
| 36 |
| 37 import java.util.ArrayList; |
| 38 import java.util.concurrent.Callable; |
| 39 import java.util.concurrent.Semaphore; |
| 40 import java.util.concurrent.TimeUnit; |
| 41 |
| 42 /** |
| 43 * Tests for the native android New Tab Page. |
| 44 */ |
| 45 public class NewTabPageTest extends ChromeTabbedActivityTestBase { |
| 46 |
| 47 private static final String TEST_PAGE = |
| 48 TestHttpServerClient.getUrl("chrome/test/data/android/navigate/simpl
e.html"); |
| 49 |
| 50 private static final String[] FAKE_MOST_VISITED_TITLES = new String[] { "Sim
ple" }; |
| 51 private static final String[] FAKE_MOST_VISITED_URLS = new String[] { TEST_P
AGE }; |
| 52 |
| 53 private Tab mTab; |
| 54 private NewTabPage mNtp; |
| 55 private View mFakebox; |
| 56 private ViewGroup mMostVisitedLayout; |
| 57 private FakeMostVisitedSites mFakeMostVisitedSites; |
| 58 |
| 59 @Override |
| 60 public void startMainActivity() throws InterruptedException { |
| 61 startMainActivityOnBlankPage(); |
| 62 mTab = getActivity().getActivityTab(); |
| 63 |
| 64 try { |
| 65 runTestOnUiThread(new Runnable() { |
| 66 @Override |
| 67 public void run() { |
| 68 // Create FakeMostVisitedSites after starting the activity,
since it depends on |
| 69 // native code. |
| 70 mFakeMostVisitedSites = new FakeMostVisitedSites(mTab.getPro
file(), |
| 71 FAKE_MOST_VISITED_TITLES, FAKE_MOST_VISITED_URLS); |
| 72 } |
| 73 }); |
| 74 } catch (Throwable t) { |
| 75 fail(t.getMessage()); |
| 76 } |
| 77 NewTabPage.setMostVisitedSitesForTests(mFakeMostVisitedSites); |
| 78 |
| 79 loadUrl(UrlConstants.NTP_URL); |
| 80 NewTabPageTestUtils.waitForNtpLoaded(mTab); |
| 81 |
| 82 assertTrue(mTab.getNativePage() instanceof NewTabPage); |
| 83 mNtp = (NewTabPage) mTab.getNativePage(); |
| 84 mFakebox = mNtp.getView().findViewById(R.id.search_box); |
| 85 mMostVisitedLayout = (ViewGroup) mNtp.getView().findViewById(R.id.most_v
isited_layout); |
| 86 assertEquals(FAKE_MOST_VISITED_URLS.length, mMostVisitedLayout.getChildC
ount()); |
| 87 } |
| 88 |
| 89 /** |
| 90 * Tests that clicking on the fakebox causes it to animate upwards and focus
the omnibox, and |
| 91 * defocusing the omnibox causes the fakebox to animate back down. |
| 92 */ |
| 93 @SmallTest |
| 94 @Feature({"NewTabPage"}) |
| 95 public void testFocusFakebox() throws InterruptedException { |
| 96 int initialFakeboxTop = getFakeboxTop(mNtp); |
| 97 |
| 98 singleClickView(mFakebox); |
| 99 waitForFakeboxFocusAnimationComplete(mNtp); |
| 100 UrlBar urlBar = (UrlBar) getActivity().findViewById(R.id.url_bar); |
| 101 assertTrue(OmniboxTestUtils.waitForFocusAndKeyboardActive(urlBar, true))
; |
| 102 int afterFocusFakeboxTop = getFakeboxTop(mNtp); |
| 103 assertTrue(afterFocusFakeboxTop < initialFakeboxTop); |
| 104 |
| 105 OmniboxTestUtils.toggleUrlBarFocus(urlBar, false); |
| 106 waitForFakeboxTopPosition(mNtp, initialFakeboxTop); |
| 107 assertTrue(OmniboxTestUtils.waitForFocusAndKeyboardActive(urlBar, false)
); |
| 108 } |
| 109 |
| 110 /** |
| 111 * Tests that clicking on the fakebox causes it to focus the omnibox and all
ows typing and |
| 112 * navigating to a URL. |
| 113 */ |
| 114 @SmallTest |
| 115 @Feature({"NewTabPage"}) |
| 116 public void testSearchFromFakebox() throws InterruptedException { |
| 117 singleClickView(mFakebox); |
| 118 waitForFakeboxFocusAnimationComplete(mNtp); |
| 119 final UrlBar urlBar = (UrlBar) getActivity().findViewById(R.id.url_bar); |
| 120 assertTrue(OmniboxTestUtils.waitForFocusAndKeyboardActive(urlBar, true))
; |
| 121 |
| 122 getInstrumentation().sendStringSync(TEST_PAGE); |
| 123 LocationBarLayout locationBar = |
| 124 (LocationBarLayout) getActivity().findViewById(R.id.location_bar
); |
| 125 OmniboxTestUtils.waitForOmniboxSuggestions(locationBar); |
| 126 |
| 127 ChromeTabUtils.waitForTabPageLoaded(mTab, new Runnable() { |
| 128 @Override |
| 129 public void run() { |
| 130 KeyUtils.singleKeyEventView(getInstrumentation(), urlBar, KeyEve
nt.KEYCODE_ENTER); |
| 131 } |
| 132 }); |
| 133 } |
| 134 |
| 135 /** |
| 136 * Tests clicking on a most visited item. |
| 137 */ |
| 138 @SmallTest |
| 139 @Feature({"NewTabPage"}) |
| 140 public void testClickMostVisitedItem() throws InterruptedException { |
| 141 ChromeTabUtils.waitForTabPageLoaded(mTab, new Runnable() { |
| 142 @Override |
| 143 public void run() { |
| 144 View mostVisitedItem = mMostVisitedLayout.getChildAt(0); |
| 145 singleClickView(mostVisitedItem); |
| 146 } |
| 147 }); |
| 148 assertEquals(FAKE_MOST_VISITED_URLS[0], mTab.getUrl()); |
| 149 } |
| 150 |
| 151 /** |
| 152 * Tests opening a most visited item in a new tab. |
| 153 */ |
| 154 @SmallTest |
| 155 @Feature({"NewTabPage"}) |
| 156 public void testOpenMostVisitedItemInNewTab() throws InterruptedException { |
| 157 invokeContextMenuAndOpenInANewTab(mMostVisitedLayout.getChildAt(0), |
| 158 NewTabPage.ID_OPEN_IN_NEW_TAB, false, FAKE_MOST_VISITED_URLS[0])
; |
| 159 } |
| 160 |
| 161 /** |
| 162 * Tests opening a most visited item in a new incognito tab. |
| 163 */ |
| 164 @SmallTest |
| 165 @Feature({"NewTabPage"}) |
| 166 public void testOpenMostVisitedItemInIncognitoTab() throws InterruptedExcept
ion { |
| 167 invokeContextMenuAndOpenInANewTab(mMostVisitedLayout.getChildAt(0), |
| 168 NewTabPage.ID_OPEN_IN_INCOGNITO_TAB, true, FAKE_MOST_VISITED_URL
S[0]); |
| 169 } |
| 170 |
| 171 /** |
| 172 * Tests deleting a most visited item. |
| 173 */ |
| 174 @SmallTest |
| 175 @Feature({"NewTabPage"}) |
| 176 public void testRemoveMostVisitedItem() { |
| 177 View mostVisitedItem = mMostVisitedLayout.getChildAt(0); |
| 178 ArrayList<View> views = new ArrayList<View>(); |
| 179 mMostVisitedLayout.findViewsWithText(views, FAKE_MOST_VISITED_TITLES[0], |
| 180 View.FIND_VIEWS_WITH_TEXT); |
| 181 assertEquals(1, views.size()); |
| 182 |
| 183 TestTouchUtils.longClickView(getInstrumentation(), mostVisitedItem); |
| 184 assertTrue(getInstrumentation().invokeContextMenuAction(getActivity(), |
| 185 NewTabPage.ID_REMOVE, 0)); |
| 186 |
| 187 assertTrue(mFakeMostVisitedSites.isUrlBlacklisted(FAKE_MOST_VISITED_URLS
[0])); |
| 188 } |
| 189 |
| 190 @MediumTest |
| 191 @Feature({"NewTabPage"}) |
| 192 public void testUrlFocusAnimationsDisabledOnLoad() throws InterruptedExcepti
on { |
| 193 assertFalse(getUrlFocusAnimatonsDisabled()); |
| 194 ChromeTabUtils.waitForTabPageLoaded(mTab, new Runnable() { |
| 195 @Override |
| 196 public void run() { |
| 197 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 198 @Override |
| 199 public void run() { |
| 200 int pageTransition = |
| 201 PageTransition.TYPED | PageTransition.FROM_ADDRE
SS_BAR; |
| 202 mTab.loadUrl(new LoadUrlParams(TEST_PAGE, pageTransition
)); |
| 203 // It should be disabled as soon as a load URL is trigge
red. |
| 204 assertTrue(getUrlFocusAnimatonsDisabled()); |
| 205 } |
| 206 }); |
| 207 } |
| 208 }); |
| 209 // Ensure it is still marked as disabled once the new page is fully load
ed. |
| 210 assertTrue(getUrlFocusAnimatonsDisabled()); |
| 211 } |
| 212 |
| 213 @LargeTest |
| 214 @Feature({"NewTagPage"}) |
| 215 public void testUrlFocusAnimationsEnabledOnFailedLoad() throws Exception { |
| 216 TestWebServer webServer = TestWebServer.start(); |
| 217 try { |
| 218 final Semaphore delaySemaphore = new Semaphore(0); |
| 219 Runnable delayAction = new Runnable() { |
| 220 @Override |
| 221 public void run() { |
| 222 try { |
| 223 assertTrue(delaySemaphore.tryAcquire(10, TimeUnit.SECOND
S)); |
| 224 } catch (InterruptedException e) { |
| 225 e.printStackTrace(); |
| 226 } |
| 227 } |
| 228 }; |
| 229 final String testPageUrl = webServer.setResponseWithRunnableAction( |
| 230 "/ntp_test.html", |
| 231 "<html><body></body></html>", null, delayAction); |
| 232 |
| 233 assertFalse(getUrlFocusAnimatonsDisabled()); |
| 234 |
| 235 clickFakebox(); |
| 236 UrlBar urlBar = (UrlBar) getActivity().findViewById(R.id.url_bar); |
| 237 OmniboxTestUtils.waitForFocusAndKeyboardActive(urlBar, true); |
| 238 typeInOmnibox(testPageUrl, false); |
| 239 LocationBarLayout locationBar = |
| 240 (LocationBarLayout) getActivity().findViewById(R.id.location
_bar); |
| 241 OmniboxTestUtils.waitForOmniboxSuggestions(locationBar); |
| 242 |
| 243 final CallbackHelper loadedCallback = new CallbackHelper(); |
| 244 mTab.addObserver(new EmptyTabObserver() { |
| 245 @Override |
| 246 public void onPageLoadFinished(Tab tab) { |
| 247 loadedCallback.notifyCalled(); |
| 248 tab.removeObserver(this); |
| 249 } |
| 250 }); |
| 251 |
| 252 final View v = urlBar; |
| 253 KeyUtils.singleKeyEventView(getInstrumentation(), v, KeyEvent.KEYCOD
E_ENTER); |
| 254 |
| 255 assertTrue(waitForUrlFocusAnimationsDisabledState(true)); |
| 256 assertTrue(waitForTabLoading()); |
| 257 |
| 258 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 259 @Override |
| 260 public void run() { |
| 261 mTab.stopLoading(); |
| 262 } |
| 263 }); |
| 264 assertTrue(waitForUrlFocusAnimationsDisabledState(false)); |
| 265 delaySemaphore.release(); |
| 266 loadedCallback.waitForCallback(0); |
| 267 assertFalse(getUrlFocusAnimatonsDisabled()); |
| 268 } finally { |
| 269 webServer.shutdown(); |
| 270 } |
| 271 } |
| 272 |
| 273 private boolean getUrlFocusAnimatonsDisabled() { |
| 274 return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Boolean
>() { |
| 275 @Override |
| 276 public Boolean call() throws Exception { |
| 277 return mNtp.getNewTabPageView().urlFocusAnimationsDisabled(); |
| 278 } |
| 279 }); |
| 280 } |
| 281 |
| 282 private boolean waitForUrlFocusAnimationsDisabledState(final boolean disable
d) |
| 283 throws InterruptedException { |
| 284 return CriteriaHelper.pollForCriteria(new Criteria() { |
| 285 @Override |
| 286 public boolean isSatisfied() { |
| 287 return getUrlFocusAnimatonsDisabled() == disabled; |
| 288 } |
| 289 }); |
| 290 } |
| 291 |
| 292 private boolean waitForTabLoading() throws InterruptedException { |
| 293 return CriteriaHelper.pollForCriteria(new Criteria() { |
| 294 @Override |
| 295 public boolean isSatisfied() { |
| 296 return ThreadUtils.runOnUiThreadBlockingNoException(new Callable
<Boolean>() { |
| 297 @Override |
| 298 public Boolean call() throws Exception { |
| 299 return mTab.isLoading(); |
| 300 } |
| 301 }); |
| 302 } |
| 303 }); |
| 304 } |
| 305 |
| 306 private void waitForFakeboxFocusAnimationComplete(NewTabPage ntp) throws Int
erruptedException { |
| 307 waitForUrlFocusPercent(ntp, 1f); |
| 308 } |
| 309 |
| 310 private void waitForFakeboxUnfocusAnimationComplete(NewTabPage ntp) |
| 311 throws InterruptedException { |
| 312 waitForUrlFocusPercent(ntp, 0f); |
| 313 } |
| 314 |
| 315 private void waitForUrlFocusPercent(final NewTabPage ntp, final float percen
t) |
| 316 throws InterruptedException { |
| 317 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { |
| 318 @Override |
| 319 public boolean isSatisfied() { |
| 320 return ThreadUtils.runOnUiThreadBlockingNoException(new Callable
<Boolean>() { |
| 321 @Override |
| 322 public Boolean call() throws Exception { |
| 323 return ntp.getNewTabPageView().getUrlFocusChangeAnimatio
nPercent() |
| 324 == percent; |
| 325 } |
| 326 }); |
| 327 } |
| 328 })); |
| 329 } |
| 330 |
| 331 private void clickFakebox() { |
| 332 View fakebox = mNtp.getView().findViewById(R.id.search_box); |
| 333 singleClickView(fakebox); |
| 334 } |
| 335 |
| 336 /** |
| 337 * @return The position of the top of the fakebox relative to the window. |
| 338 */ |
| 339 private int getFakeboxTop(final NewTabPage ntp) { |
| 340 return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Integer
>() { |
| 341 @Override |
| 342 public Integer call() { |
| 343 final View fakebox = ntp.getView().findViewById(R.id.search_box)
; |
| 344 int[] location = new int[2]; |
| 345 fakebox.getLocationInWindow(location); |
| 346 return location[1]; |
| 347 } |
| 348 }); |
| 349 } |
| 350 |
| 351 /** |
| 352 * Waits until the top of the fakebox reaches the given position. |
| 353 */ |
| 354 private void waitForFakeboxTopPosition(final NewTabPage ntp, final int posit
ion) |
| 355 throws InterruptedException { |
| 356 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { |
| 357 @Override |
| 358 public boolean isSatisfied() { |
| 359 return ThreadUtils.runOnUiThreadBlockingNoException(new Callable
<Boolean>() { |
| 360 @Override |
| 361 public Boolean call() throws Exception { |
| 362 return getFakeboxTop(ntp) == position; |
| 363 } |
| 364 }); |
| 365 } |
| 366 })); |
| 367 } |
| 368 } |
OLD | NEW |