OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 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.suggestions; |
| 6 |
| 7 import android.support.test.filters.MediumTest; |
| 8 import android.view.View; |
| 9 import android.view.ViewGroup; |
| 10 import android.widget.TextView; |
| 11 |
| 12 import org.chromium.base.ThreadUtils; |
| 13 import org.chromium.base.test.util.CallbackHelper; |
| 14 import org.chromium.base.test.util.Feature; |
| 15 import org.chromium.base.test.util.RetryOnFailure; |
| 16 import org.chromium.chrome.R; |
| 17 import org.chromium.chrome.browser.ChromeActivity; |
| 18 import org.chromium.chrome.browser.UrlConstants; |
| 19 import org.chromium.chrome.browser.ntp.ContextMenuManager; |
| 20 import org.chromium.chrome.browser.ntp.NewTabPage; |
| 21 import org.chromium.chrome.browser.ntp.cards.NewTabPageRecyclerView; |
| 22 import org.chromium.chrome.browser.snackbar.SnackbarManager; |
| 23 import org.chromium.chrome.browser.tab.Tab; |
| 24 import org.chromium.chrome.test.ChromeTabbedActivityTestBase; |
| 25 import org.chromium.chrome.test.util.NewTabPageTestUtils; |
| 26 import org.chromium.chrome.test.util.browser.RecyclerViewTestUtils; |
| 27 import org.chromium.chrome.test.util.browser.suggestions.FakeSuggestionsSource; |
| 28 import org.chromium.content.browser.test.util.Criteria; |
| 29 import org.chromium.content.browser.test.util.CriteriaHelper; |
| 30 import org.chromium.content.browser.test.util.TestTouchUtils; |
| 31 import org.chromium.net.test.EmbeddedTestServer; |
| 32 |
| 33 import java.util.concurrent.TimeoutException; |
| 34 |
| 35 /** |
| 36 * Instrumentation tests for {@link TileGroup} on the New Tab Page. |
| 37 */ |
| 38 @RetryOnFailure |
| 39 public class TileGroupTest extends ChromeTabbedActivityTestBase { |
| 40 private static final String[] FAKE_MOST_VISITED_URLS = |
| 41 new String[] {"/chrome/test/data/android/navigate/one.html", |
| 42 "/chrome/test/data/android/navigate/two.html", |
| 43 "/chrome/test/data/android/navigate/three.html"}; |
| 44 |
| 45 private NewTabPage mNtp; |
| 46 private String[] mSiteSuggestionUrls; |
| 47 private FakeMostVisitedSites mMostVisitedSites; |
| 48 private EmbeddedTestServer mTestServer; |
| 49 |
| 50 @Override |
| 51 protected void setUp() throws Exception { |
| 52 mTestServer = EmbeddedTestServer.createAndStartServer(getInstrumentation
().getContext()); |
| 53 |
| 54 mSiteSuggestionUrls = new String[] {mTestServer.getURL(FAKE_MOST_VISITED
_URLS[0]), |
| 55 mTestServer.getURL(FAKE_MOST_VISITED_URLS[1]), |
| 56 mTestServer.getURL(FAKE_MOST_VISITED_URLS[2])}; |
| 57 |
| 58 mMostVisitedSites = new FakeMostVisitedSites(); |
| 59 mMostVisitedSites.setTileSuggestions(mSiteSuggestionUrls); |
| 60 TileGroupDelegateImpl.setMostVisitedSitesForTests(mMostVisitedSites); |
| 61 |
| 62 FakeSuggestionsSource mSource = new FakeSuggestionsSource(); |
| 63 NewTabPage.setSuggestionsSourceForTests(mSource); |
| 64 |
| 65 super.setUp(); |
| 66 } |
| 67 |
| 68 @Override |
| 69 protected void tearDown() throws Exception { |
| 70 TileGroupDelegateImpl.setMostVisitedSitesForTests(null); |
| 71 NewTabPage.setSuggestionsSourceForTests(null); |
| 72 mTestServer.stopAndDestroyServer(); |
| 73 |
| 74 super.tearDown(); |
| 75 } |
| 76 |
| 77 @Override |
| 78 public void startMainActivity() throws InterruptedException { |
| 79 startMainActivityWithURL(UrlConstants.NTP_URL); |
| 80 Tab mTab = getActivity().getActivityTab(); |
| 81 NewTabPageTestUtils.waitForNtpLoaded(mTab); |
| 82 |
| 83 assertTrue(mTab.getNativePage() instanceof NewTabPage); |
| 84 mNtp = (NewTabPage) mTab.getNativePage(); |
| 85 |
| 86 RecyclerViewTestUtils.waitForStableRecyclerView(getRecyclerView()); |
| 87 } |
| 88 |
| 89 @MediumTest |
| 90 @Feature({"NewTabPage"}) |
| 91 public void testDismissTileWithContextMenu() throws InterruptedException, Ti
meoutException { |
| 92 final View tileView = getTileViewForUrl(mSiteSuggestionUrls[0]); |
| 93 |
| 94 // Dismiss the tile using the context menu. |
| 95 invokeContextMenu(tileView, ContextMenuManager.ID_REMOVE); |
| 96 assertTrue(mMostVisitedSites.isUrlBlacklisted(mSiteSuggestionUrls[0])); |
| 97 |
| 98 // Ensure that undoing the removal is reflected in the ui. |
| 99 assertEquals(3, getTileGridLayout().getChildCount()); |
| 100 mMostVisitedSites.setTileSuggestions(mSiteSuggestionUrls[1], mSiteSugges
tionUrls[2]); |
| 101 waitForTileRemoved(mSiteSuggestionUrls[0]); |
| 102 assertEquals(2, getTileGridLayout().getChildCount()); |
| 103 } |
| 104 |
| 105 @MediumTest |
| 106 @Feature({"NewTabPage"}) |
| 107 public void testDismissTileUndo() throws InterruptedException, TimeoutExcept
ion { |
| 108 final ViewGroup tileContainer = getTileGridLayout(); |
| 109 final View tileView = getTileViewForUrl(mSiteSuggestionUrls[0]); |
| 110 assertEquals(3, tileContainer.getChildCount()); |
| 111 |
| 112 // Dismiss the tile using the context menu. |
| 113 invokeContextMenu(tileView, ContextMenuManager.ID_REMOVE); |
| 114 |
| 115 // Ensure that the removal update goes through. |
| 116 mMostVisitedSites.setTileSuggestions(mSiteSuggestionUrls[1], mSiteSugges
tionUrls[2]); |
| 117 waitForTileRemoved(mSiteSuggestionUrls[0]); |
| 118 assertEquals(2, tileContainer.getChildCount()); |
| 119 final View snackbarButton = waitForSnackbar(getActivity()); |
| 120 |
| 121 assertTrue(mMostVisitedSites.isUrlBlacklisted(mSiteSuggestionUrls[0])); |
| 122 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 123 @Override |
| 124 public void run() { |
| 125 snackbarButton.callOnClick(); |
| 126 } |
| 127 }); |
| 128 |
| 129 assertFalse(mMostVisitedSites.isUrlBlacklisted(mSiteSuggestionUrls[0])); |
| 130 |
| 131 // Ensure that the removal of the update goes through. |
| 132 mMostVisitedSites.setTileSuggestions(mSiteSuggestionUrls); |
| 133 waitForTileAdded(mSiteSuggestionUrls[0]); |
| 134 assertEquals(3, tileContainer.getChildCount()); |
| 135 } |
| 136 |
| 137 private NewTabPageRecyclerView getRecyclerView() { |
| 138 return mNtp.getNewTabPageView().getRecyclerView(); |
| 139 } |
| 140 |
| 141 private TileGridLayout getTileGridLayout() { |
| 142 ViewGroup aboveTheFoldView = getRecyclerView().getAboveTheFoldView(); |
| 143 assertNotNull("Unable to retrieve the AboveTheFold view.", aboveTheFoldV
iew); |
| 144 |
| 145 TileGridLayout tileGridLayout = |
| 146 (TileGridLayout) aboveTheFoldView.findViewById(R.id.tile_grid_la
yout); |
| 147 assertNotNull("Unable to retrieve the TileGridLayout.", tileGridLayout); |
| 148 return tileGridLayout; |
| 149 } |
| 150 |
| 151 private View getTileViewForUrl(String url) { |
| 152 View tileView = getTileGridLayout().getTileView(url); |
| 153 assertNotNull("Tile not found for url " + url, tileView); |
| 154 |
| 155 return tileView; |
| 156 } |
| 157 |
| 158 private void invokeContextMenu(View view, int contextMenuItemId) { |
| 159 TestTouchUtils.longClickView(getInstrumentation(), view); |
| 160 assertTrue( |
| 161 getInstrumentation().invokeContextMenuAction(getActivity(), cont
extMenuItemId, 0)); |
| 162 } |
| 163 |
| 164 /** Wait for the snackbar associated to a tile dismissal to be shown and ret
urns its button. */ |
| 165 private static View waitForSnackbar(final ChromeActivity activity) { |
| 166 final String expectedSnackbarMessage = |
| 167 activity.getResources().getString(R.string.most_visited_item_rem
oved); |
| 168 CriteriaHelper.pollUiThread(new Criteria("The snackbar was not shown.")
{ |
| 169 @Override |
| 170 public boolean isSatisfied() { |
| 171 SnackbarManager snackbarManager = activity.getSnackbarManager(); |
| 172 if (!snackbarManager.isShowing()) return false; |
| 173 |
| 174 TextView snackbarMessage = (TextView) activity.findViewById(R.id
.snackbar_message); |
| 175 if (snackbarMessage == null) return false; |
| 176 |
| 177 return snackbarMessage.getText().toString().equals(expectedSnack
barMessage); |
| 178 } |
| 179 }); |
| 180 |
| 181 return activity.findViewById(R.id.snackbar_button); |
| 182 } |
| 183 |
| 184 private void waitForTileRemoved(final String url) |
| 185 throws TimeoutException, InterruptedException { |
| 186 TileGridLayout tileContainer = getTileGridLayout(); |
| 187 final TileView removedTile = tileContainer.getTileView(url); |
| 188 if (removedTile == null) return; |
| 189 |
| 190 final CallbackHelper callback = new CallbackHelper(); |
| 191 tileContainer.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChan
geListener() { |
| 192 @Override |
| 193 public void onChildViewAdded(View parent, View child) {} |
| 194 |
| 195 @Override |
| 196 public void onChildViewRemoved(View parent, View child) { |
| 197 if (child == removedTile) callback.notifyCalled(); |
| 198 } |
| 199 }); |
| 200 callback.waitForCallback("The expected tile was not removed.", 0); |
| 201 tileContainer.setOnHierarchyChangeListener(null); |
| 202 } |
| 203 |
| 204 private void waitForTileAdded(final String url) throws TimeoutException, Int
erruptedException { |
| 205 TileGridLayout tileContainer = getTileGridLayout(); |
| 206 if (tileContainer.getTileView(url) != null) return; |
| 207 |
| 208 final CallbackHelper callback = new CallbackHelper(); |
| 209 tileContainer.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChan
geListener() { |
| 210 @Override |
| 211 public void onChildViewAdded(View parent, View child) { |
| 212 if (!(child instanceof TileView)) return; |
| 213 if (!((TileView) child).getUrl().equals(url)) return; |
| 214 |
| 215 callback.notifyCalled(); |
| 216 } |
| 217 |
| 218 @Override |
| 219 public void onChildViewRemoved(View parent, View child) {} |
| 220 }); |
| 221 callback.waitForCallback("The expected tile was not added.", 0); |
| 222 tileContainer.setOnHierarchyChangeListener(null); |
| 223 } |
| 224 } |
OLD | NEW |