OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 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 | 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.suggestions; | 5 package org.chromium.chrome.browser.suggestions; |
6 | 6 |
7 import static junit.framework.TestCase.assertNotNull; | 7 import static org.hamcrest.CoreMatchers.is; |
| 8 import static org.junit.Assert.assertNotNull; |
| 9 import static org.junit.Assert.assertThat; |
| 10 import static org.junit.Assert.fail; |
| 11 import static org.mockito.ArgumentMatchers.any; |
| 12 import static org.mockito.ArgumentMatchers.anyBoolean; |
| 13 import static org.mockito.ArgumentMatchers.anyInt; |
| 14 import static org.mockito.Mockito.doAnswer; |
| 15 import static org.mockito.Mockito.mock; |
| 16 import static org.mockito.Mockito.never; |
| 17 import static org.mockito.Mockito.reset; |
| 18 import static org.mockito.Mockito.verify; |
| 19 import static org.mockito.Mockito.verifyNoMoreInteractions; |
| 20 import static org.mockito.Mockito.when; |
8 | 21 |
9 import static org.mockito.Mockito.inOrder; | 22 import android.content.Context; |
10 import static org.mockito.Mockito.mock; | |
11 import static org.mockito.Mockito.verify; | |
12 | |
13 import android.content.res.Resources; | 23 import android.content.res.Resources; |
| 24 import android.graphics.Bitmap; |
| 25 import android.graphics.Color; |
14 import android.support.annotation.ColorRes; | 26 import android.support.annotation.ColorRes; |
15 import android.support.annotation.DimenRes; | 27 import android.support.annotation.DimenRes; |
| 28 import android.support.annotation.LayoutRes; |
| 29 import android.view.LayoutInflater; |
| 30 import android.view.View; |
| 31 import android.view.ViewGroup; |
| 32 import android.widget.FrameLayout; |
16 | 33 |
| 34 import org.hamcrest.CoreMatchers; |
17 import org.junit.Before; | 35 import org.junit.Before; |
18 import org.junit.Rule; | 36 import org.junit.Rule; |
19 import org.junit.Test; | 37 import org.junit.Test; |
20 import org.junit.runner.RunWith; | 38 import org.junit.runner.RunWith; |
21 import org.mockito.InOrder; | 39 import org.mockito.ArgumentCaptor; |
22 import org.mockito.Mock; | 40 import org.mockito.Mock; |
23 import org.mockito.MockitoAnnotations; | 41 import org.mockito.MockitoAnnotations; |
| 42 import org.mockito.invocation.InvocationOnMock; |
| 43 import org.mockito.stubbing.Answer; |
24 import org.robolectric.RuntimeEnvironment; | 44 import org.robolectric.RuntimeEnvironment; |
25 import org.robolectric.annotation.Config; | 45 import org.robolectric.annotation.Config; |
| 46 import org.robolectric.annotation.Implementation; |
26 import org.robolectric.annotation.Implements; | 47 import org.robolectric.annotation.Implements; |
27 import org.robolectric.annotation.RealObject; | |
28 import org.robolectric.shadows.ShadowResources; | 48 import org.robolectric.shadows.ShadowResources; |
29 | 49 |
30 import org.chromium.chrome.R; | 50 import org.chromium.chrome.R; |
31 import org.chromium.chrome.browser.ChromeFeatureList; | |
32 import org.chromium.chrome.browser.EnableFeatures; | 51 import org.chromium.chrome.browser.EnableFeatures; |
| 52 import org.chromium.chrome.browser.favicon.LargeIconBridge.LargeIconCallback; |
33 import org.chromium.chrome.browser.ntp.ContextMenuManager; | 53 import org.chromium.chrome.browser.ntp.ContextMenuManager; |
34 import org.chromium.chrome.browser.ntp.cards.NodeParent; | 54 import org.chromium.chrome.browser.ntp.NTPTileSource; |
35 import org.chromium.chrome.browser.ntp.cards.SuggestionsSection; | |
36 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; | 55 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; |
37 import org.chromium.testing.local.LocalRobolectricTestRunner; | 56 import org.chromium.testing.local.LocalRobolectricTestRunner; |
38 | 57 |
39 /** | 58 /** |
40 * Unit tests for {@link TileGroup}. | 59 * Unit tests for {@link TileGroup}. |
41 */ | 60 */ |
42 @RunWith(LocalRobolectricTestRunner.class) | 61 @RunWith(LocalRobolectricTestRunner.class) |
43 @Config(manifest = Config.NONE, shadows = {TileGroupTest.TileShadowResources.cla
ss}) | 62 @Config(manifest = Config.NONE, |
| 63 shadows = {TileGroupTest.TileShadowResources.class, |
| 64 TileGroupTest.ShadowLayoutInflater.class}) |
| 65 @EnableFeatures({}) |
44 public class TileGroupTest { | 66 public class TileGroupTest { |
45 private static final int MAX_TILES_TO_FETCH = 4; | 67 private static final int MAX_TILES_TO_FETCH = 4; |
46 private static final int TILE_TITLE_LINES = 1; | 68 private static final int TILE_TITLE_LINES = 1; |
47 private static final String[] URLS = {"https://www.google.com", "https://tel
lmedadjokes.com"}; | 69 private static final String[] URLS = {"https://www.google.com", "https://tel
lmedadjokes.com"}; |
48 | 70 |
49 @Rule | 71 @Rule |
50 public EnableFeatures.Processor mEnableFeatureProcessor = new EnableFeatures
.Processor(); | 72 public EnableFeatures.Processor mEnableFeatureProcessor = new EnableFeatures
.Processor(); |
51 | 73 |
52 @Mock | 74 @Mock |
53 private SuggestionsSection.Delegate mDelegate; | |
54 @Mock | |
55 private NodeParent mParent; | |
56 @Mock | |
57 private SuggestionsUiDelegate mUiDelegate; | |
58 @Mock | |
59 private TileGroup.Observer mTileGroupObserver; | 75 private TileGroup.Observer mTileGroupObserver; |
60 @Mock | |
61 private OfflinePageBridge mOfflinePageBridge; | |
62 | 76 |
63 private FakeTileGroupDelegate mTileGroupDelegate; | 77 private FakeTileGroupDelegate mTileGroupDelegate; |
64 | 78 |
65 @Before | 79 @Before |
66 public void setUp() { | 80 public void setUp() { |
67 MockitoAnnotations.initMocks(this); | 81 MockitoAnnotations.initMocks(this); |
68 | 82 |
69 mTileGroupDelegate = new FakeTileGroupDelegate(); | 83 mTileGroupDelegate = new FakeTileGroupDelegate(); |
70 } | 84 } |
71 | 85 |
72 @Test | 86 @Test |
73 @EnableFeatures({ChromeFeatureList.NTP_OFFLINE_PAGES_FEATURE_NAME}) | |
74 public void testInitialiseWithEmptyTileList() { | 87 public void testInitialiseWithEmptyTileList() { |
75 TileGroup tileGroup = new TileGroup(RuntimeEnvironment.application, mUiD
elegate, | 88 TileGroup tileGroup = |
| 89 new TileGroup(RuntimeEnvironment.application, mock(SuggestionsUi
Delegate.class), |
| 90 mock(ContextMenuManager.class), mTileGroupDelegate, mTil
eGroupObserver, |
| 91 mock(OfflinePageBridge.class), TILE_TITLE_LINES); |
| 92 tileGroup.startObserving(MAX_TILES_TO_FETCH); |
| 93 notifyTileUrlsAvailable(); |
| 94 |
| 95 // The TileGroup.Observer methods should be called even though no tiles
are added, which is |
| 96 // an initialisation but not real state change. |
| 97 verify(mTileGroupObserver).onTileCountChanged(); |
| 98 verify(mTileGroupObserver).onLoadTaskCompleted(); |
| 99 verify(mTileGroupObserver).onTileDataChanged(); |
| 100 } |
| 101 |
| 102 @Test |
| 103 public void testInitialiseWithTileList() { |
| 104 TileGroup tileGroup = |
| 105 new TileGroup(RuntimeEnvironment.application, mock(SuggestionsUi
Delegate.class), |
| 106 mock(ContextMenuManager.class), mTileGroupDelegate, mTil
eGroupObserver, |
| 107 mock(OfflinePageBridge.class), TILE_TITLE_LINES); |
| 108 tileGroup.startObserving(MAX_TILES_TO_FETCH); |
| 109 |
| 110 notifyTileUrlsAvailable(URLS); |
| 111 |
| 112 verify(mTileGroupObserver).onTileCountChanged(); |
| 113 verify(mTileGroupObserver).onLoadTaskCompleted(); |
| 114 verify(mTileGroupObserver).onTileDataChanged(); |
| 115 } |
| 116 |
| 117 @Test |
| 118 public void testReceiveNewTilesWithoutChanges() { |
| 119 TileGroup tileGroup = |
| 120 new TileGroup(RuntimeEnvironment.application, mock(SuggestionsUi
Delegate.class), |
| 121 mock(ContextMenuManager.class), mTileGroupDelegate, mTil
eGroupObserver, |
| 122 mock(OfflinePageBridge.class), TILE_TITLE_LINES); |
| 123 tileGroup.startObserving(MAX_TILES_TO_FETCH); |
| 124 |
| 125 // First initialisation |
| 126 notifyTileUrlsAvailable(URLS); |
| 127 reset(mTileGroupObserver); |
| 128 |
| 129 // Notify the same thing. No changes so|mTileGroupObserver| should not b
e notified. |
| 130 notifyTileUrlsAvailable(URLS); |
| 131 verifyNoMoreInteractions(mTileGroupObserver); |
| 132 } |
| 133 |
| 134 @Test |
| 135 public void testReceiveNewTilesWithDataChanges() { |
| 136 TileGroup tileGroup = |
| 137 new TileGroup(RuntimeEnvironment.application, mock(SuggestionsUi
Delegate.class), |
| 138 mock(ContextMenuManager.class), mTileGroupDelegate, mTil
eGroupObserver, |
| 139 mock(OfflinePageBridge.class), TILE_TITLE_LINES); |
| 140 tileGroup.startObserving(MAX_TILES_TO_FETCH); |
| 141 |
| 142 // First initialisation |
| 143 notifyTileUrlsAvailable(URLS); |
| 144 reset(mTileGroupObserver); |
| 145 |
| 146 // Notify the about different URLs, but the same number. #onTileCountCha
nged() should not be |
| 147 // called. |
| 148 notifyTileUrlsAvailable("foo", "bar"); |
| 149 verify(mTileGroupObserver, never()).onTileCountChanged(); // Tile count
is still 2 |
| 150 verify(mTileGroupObserver, never()).onLoadTaskCompleted(); // No load ta
sk the second time. |
| 151 verify(mTileGroupObserver).onTileDataChanged(); // Data DID change. |
| 152 } |
| 153 |
| 154 @Test |
| 155 public void testReceiveNewTilesWithCountChanges() { |
| 156 TileGroup tileGroup = |
| 157 new TileGroup(RuntimeEnvironment.application, mock(SuggestionsUi
Delegate.class), |
| 158 mock(ContextMenuManager.class), mTileGroupDelegate, mTil
eGroupObserver, |
| 159 mock(OfflinePageBridge.class), TILE_TITLE_LINES); |
| 160 tileGroup.startObserving(MAX_TILES_TO_FETCH); |
| 161 |
| 162 // First initialisation |
| 163 notifyTileUrlsAvailable(URLS); |
| 164 reset(mTileGroupObserver); |
| 165 |
| 166 notifyTileUrlsAvailable(URLS[0]); |
| 167 verify(mTileGroupObserver).onTileCountChanged(); // Tile count DID chang
e. |
| 168 verify(mTileGroupObserver, never()).onLoadTaskCompleted(); // No load ta
sk the second time. |
| 169 verify(mTileGroupObserver).onTileDataChanged(); // Data DID change. |
| 170 } |
| 171 |
| 172 @Test |
| 173 public void testRenderTileView() { |
| 174 TileGroup tileGroup = |
| 175 new TileGroup(RuntimeEnvironment.application, mock(SuggestionsUi
Delegate.class), |
| 176 mock(ContextMenuManager.class), mTileGroupDelegate, mTil
eGroupObserver, |
| 177 mock(OfflinePageBridge.class), TILE_TITLE_LINES); |
| 178 tileGroup.startObserving(MAX_TILES_TO_FETCH); |
| 179 ViewGroup layout = new FrameLayout(RuntimeEnvironment.application, null)
; |
| 180 |
| 181 // Initialise the internal list of tiles |
| 182 notifyTileUrlsAvailable(URLS); |
| 183 |
| 184 // Render them to the layout. |
| 185 tileGroup.renderTileViews(layout, false, false); |
| 186 assertThat(layout.getChildCount(), is(2)); |
| 187 assertThat(((TileView) layout.getChildAt(0)).getUrl(), is(URLS[0])); |
| 188 assertThat(((TileView) layout.getChildAt(1)).getUrl(), is(URLS[1])); |
| 189 } |
| 190 |
| 191 @Test |
| 192 public void testRenderTileViewReplacing() { |
| 193 TileGroup tileGroup = |
| 194 new TileGroup(RuntimeEnvironment.application, mock(SuggestionsUi
Delegate.class), |
| 195 mock(ContextMenuManager.class), mTileGroupDelegate, mTil
eGroupObserver, |
| 196 mock(OfflinePageBridge.class), TILE_TITLE_LINES); |
| 197 tileGroup.startObserving(MAX_TILES_TO_FETCH); |
| 198 notifyTileUrlsAvailable(URLS); |
| 199 |
| 200 // Initialise the layout with views whose URLs don't match the ones of t
he new tiles. |
| 201 ViewGroup layout = new FrameLayout(RuntimeEnvironment.application, null)
; |
| 202 TileView view1 = mock(TileView.class); |
| 203 layout.addView(view1); |
| 204 |
| 205 TileView view2 = mock(TileView.class); |
| 206 layout.addView(view2); |
| 207 |
| 208 // The tiles should be updated, the old ones removed. |
| 209 tileGroup.renderTileViews(layout, false, false); |
| 210 assertThat(layout.getChildCount(), is(2)); |
| 211 assertThat(layout.indexOfChild(view1), is(-1)); |
| 212 assertThat(layout.indexOfChild(view2), is(-1)); |
| 213 verify(view1, never()).updateIfDataChanged(tileGroup.getTiles()[0]); |
| 214 verify(view2, never()).updateIfDataChanged(tileGroup.getTiles()[1]); |
| 215 } |
| 216 |
| 217 @Test |
| 218 public void testRenderTileViewRecycling() { |
| 219 TileGroup tileGroup = |
| 220 new TileGroup(RuntimeEnvironment.application, mock(SuggestionsUi
Delegate.class), |
| 221 mock(ContextMenuManager.class), mTileGroupDelegate, mTil
eGroupObserver, |
| 222 mock(OfflinePageBridge.class), TILE_TITLE_LINES); |
| 223 tileGroup.startObserving(MAX_TILES_TO_FETCH); |
| 224 notifyTileUrlsAvailable(URLS); |
| 225 |
| 226 // Initialise the layout with views whose URLs match the ones of the new
tiles. |
| 227 ViewGroup layout = new FrameLayout(RuntimeEnvironment.application, null)
; |
| 228 TileView view1 = mock(TileView.class); |
| 229 when(view1.getUrl()).thenReturn(URLS[0]); |
| 230 layout.addView(view1); |
| 231 |
| 232 TileView view2 = mock(TileView.class); |
| 233 when(view2.getUrl()).thenReturn(URLS[1]); |
| 234 layout.addView(view2); |
| 235 |
| 236 // The tiles should be updated, the old ones reused. |
| 237 tileGroup.renderTileViews(layout, false, false); |
| 238 assertThat(layout.getChildCount(), is(2)); |
| 239 assertThat(layout.getChildAt(0), CoreMatchers.<View>is(view1)); |
| 240 assertThat(layout.getChildAt(1), CoreMatchers.<View>is(view2)); |
| 241 verify(view1).updateIfDataChanged(tileGroup.getTiles()[0]); |
| 242 verify(view2).updateIfDataChanged(tileGroup.getTiles()[1]); |
| 243 } |
| 244 |
| 245 @Test |
| 246 public void testIconLoading() { |
| 247 SuggestionsUiDelegate uiDelegate = mock(SuggestionsUiDelegate.class); |
| 248 TileGroup tileGroup = new TileGroup(RuntimeEnvironment.application, uiDe
legate, |
76 mock(ContextMenuManager.class), mTileGroupDelegate, mTileGroupOb
server, | 249 mock(ContextMenuManager.class), mTileGroupDelegate, mTileGroupOb
server, |
77 mOfflinePageBridge, TILE_TITLE_LINES); | 250 mock(OfflinePageBridge.class), TILE_TITLE_LINES); |
78 tileGroup.startObserving(MAX_TILES_TO_FETCH); | 251 tileGroup.startObserving(MAX_TILES_TO_FETCH); |
79 notifyTileUrlsAvailable(); | 252 notifyTileUrlsAvailable(URLS); // Initialise the internal state to inclu
de the test tile. |
80 | 253 reset(mTileGroupObserver); |
81 verify(mTileGroupObserver).onTileCountChanged(); | 254 Tile tile = tileGroup.getTiles()[0]; |
82 verify(mTileGroupObserver).onLoadTaskCompleted(); | 255 |
83 verify(mTileGroupObserver).onTileDataChanged(); | 256 ViewGroup layout = new FrameLayout(RuntimeEnvironment.application, null)
; |
84 } | 257 tileGroup.buildTileView(tile, layout, /* trackLoadTask = */ true, /* con
densed = */ false); |
85 | 258 |
86 @Test | 259 verify(mTileGroupObserver).onLoadTaskAdded(); |
87 @EnableFeatures({ChromeFeatureList.NTP_OFFLINE_PAGES_FEATURE_NAME}) | 260 |
88 public void testInitialiseWithTileList() { | 261 ArgumentCaptor<LargeIconCallback> captor = ArgumentCaptor.forClass(Large
IconCallback.class); |
89 TileGroup tileGroup = new TileGroup(RuntimeEnvironment.application, mUiD
elegate, | 262 verify(uiDelegate).getLargeIconForUrl(any(String.class), anyInt(), capto
r.capture()); |
| 263 for (LargeIconCallback cb : captor.getAllValues()) { |
| 264 cb.onLargeIconAvailable(mock(Bitmap.class), Color.BLACK, /* isColorD
efault = */ false); |
| 265 } |
| 266 |
| 267 verify(mTileGroupObserver).onLoadTaskCompleted(); |
| 268 verify(mTileGroupObserver).onTileIconChanged(tile); |
| 269 } |
| 270 |
| 271 @Test |
| 272 public void testIconLoadingNoTask() { |
| 273 SuggestionsUiDelegate uiDelegate = mock(SuggestionsUiDelegate.class); |
| 274 TileGroup tileGroup = new TileGroup(RuntimeEnvironment.application, uiDe
legate, |
90 mock(ContextMenuManager.class), mTileGroupDelegate, mTileGroupOb
server, | 275 mock(ContextMenuManager.class), mTileGroupDelegate, mTileGroupOb
server, |
91 mOfflinePageBridge, TILE_TITLE_LINES); | 276 mock(OfflinePageBridge.class), TILE_TITLE_LINES); |
92 tileGroup.startObserving(MAX_TILES_TO_FETCH); | 277 tileGroup.startObserving(MAX_TILES_TO_FETCH); |
93 | 278 notifyTileUrlsAvailable(URLS); // Initialise the internal state to inclu
de the test tile. |
94 notifyTileUrlsAvailable(URLS); | 279 reset(mTileGroupObserver); |
95 | 280 Tile tile = tileGroup.getTiles()[0]; |
96 InOrder inOrder = inOrder(mTileGroupObserver); | 281 |
97 inOrder.verify(mTileGroupObserver).onTileCountChanged(); | 282 ViewGroup layout = new FrameLayout(RuntimeEnvironment.application, null)
; |
98 inOrder.verify(mTileGroupObserver).onLoadTaskCompleted(); | 283 tileGroup.buildTileView(tile, layout, /* trackLoadTask = */ false, /* co
ndensed = */ false); |
99 inOrder.verify(mTileGroupObserver).onTileDataChanged(); | 284 |
100 inOrder.verifyNoMoreInteractions(); | 285 verify(mTileGroupObserver, never()).onLoadTaskAdded(); |
101 } | 286 |
102 | 287 ArgumentCaptor<LargeIconCallback> captor = ArgumentCaptor.forClass(Large
IconCallback.class); |
| 288 verify(uiDelegate).getLargeIconForUrl(any(String.class), anyInt(), capto
r.capture()); |
| 289 for (LargeIconCallback cb : captor.getAllValues()) { |
| 290 cb.onLargeIconAvailable(mock(Bitmap.class), Color.BLACK, /* isColorD
efault = */ false); |
| 291 } |
| 292 |
| 293 verify(mTileGroupObserver, never()).onLoadTaskCompleted(); |
| 294 verify(mTileGroupObserver).onTileIconChanged(tile); |
| 295 } |
| 296 |
| 297 @Test |
| 298 public void testIconLoadingWhenTileNotRegistered() { |
| 299 SuggestionsUiDelegate uiDelegate = mock(SuggestionsUiDelegate.class); |
| 300 TileGroup tileGroup = new TileGroup(RuntimeEnvironment.application, uiDe
legate, |
| 301 mock(ContextMenuManager.class), mTileGroupDelegate, mTileGroupOb
server, |
| 302 mock(OfflinePageBridge.class), TILE_TITLE_LINES); |
| 303 tileGroup.startObserving(MAX_TILES_TO_FETCH); |
| 304 reset(mTileGroupObserver); |
| 305 Tile tile = new Tile("title", URLS[0], "", 0, NTPTileSource.POPULAR); |
| 306 |
| 307 ViewGroup layout = new FrameLayout(RuntimeEnvironment.application, null)
; |
| 308 tileGroup.buildTileView(tile, layout, /* trackLoadTask = */ true, /* con
densed = */ false); |
| 309 verify(mTileGroupObserver).onLoadTaskAdded(); |
| 310 |
| 311 ArgumentCaptor<LargeIconCallback> captor = ArgumentCaptor.forClass(Large
IconCallback.class); |
| 312 verify(uiDelegate).getLargeIconForUrl(any(String.class), anyInt(), capto
r.capture()); |
| 313 captor.getValue().onLargeIconAvailable(mock(Bitmap.class), Color.BLACK,
false); |
| 314 |
| 315 verify(mTileGroupObserver).onLoadTaskCompleted(); |
| 316 verify(mTileGroupObserver, never()).onTileIconChanged(tile); |
| 317 } |
| 318 |
| 319 /** |
| 320 * Notifies the tile group of new tiles created from the provided URLs. Requ
ires |
| 321 * {@link TileGroup#startObserving(int)} to have been called on the tile gro
up under test. |
| 322 * @see TileGroup#onMostVisitedURLsAvailable(String[], String[], String[], i
nt[]) |
| 323 */ |
103 private void notifyTileUrlsAvailable(String... urls) { | 324 private void notifyTileUrlsAvailable(String... urls) { |
104 assertNotNull("MostVisitedObserver has not been registered.", mTileGroup
Delegate.mObserver); | 325 assertNotNull("MostVisitedObserver has not been registered.", mTileGroup
Delegate.mObserver); |
105 | 326 |
106 String[] titles = urls.clone(); | 327 String[] titles = urls.clone(); |
107 String[] whitelistIconPaths = new String[urls.length]; | 328 String[] whitelistIconPaths = new String[urls.length]; |
108 int[] sources = new int[urls.length]; | 329 int[] sources = new int[urls.length]; |
109 for (int i = 0; i < urls.length; ++i) whitelistIconPaths[i] = ""; | 330 for (int i = 0; i < urls.length; ++i) whitelistIconPaths[i] = ""; |
110 mTileGroupDelegate.mObserver.onMostVisitedURLsAvailable( | 331 mTileGroupDelegate.mObserver.onMostVisitedURLsAvailable( |
111 titles, urls, whitelistIconPaths, sources); | 332 titles, urls, whitelistIconPaths, sources); |
112 } | 333 } |
113 | 334 |
| 335 /** |
| 336 * Creates a mocked {@link TileView} that will return the URL of the tile it
has been |
| 337 * initialised with. |
| 338 */ |
| 339 private static TileView createMockTileView() { |
| 340 final TileView tileView = mock(TileView.class); |
| 341 doAnswer(new Answer<Void>() { |
| 342 @Override |
| 343 public Void answer(InvocationOnMock invocation) throws Throwable { |
| 344 Tile tile = invocation.getArgument(0); |
| 345 when(tileView.getUrl()).thenReturn(tile.getUrl()); |
| 346 return null; |
| 347 } |
| 348 }) |
| 349 .when(tileView) |
| 350 .initialize(any(Tile.class), anyInt(), anyBoolean()); |
| 351 return tileView; |
| 352 } |
| 353 |
114 private class FakeTileGroupDelegate implements TileGroup.Delegate { | 354 private class FakeTileGroupDelegate implements TileGroup.Delegate { |
115 public MostVisitedSites.Observer mObserver; | 355 public MostVisitedSites.Observer mObserver; |
116 | 356 |
117 @Override | 357 @Override |
118 public void removeMostVisitedItem(Tile tile) {} | 358 public void removeMostVisitedItem(Tile tile) {} |
119 | 359 |
120 @Override | 360 @Override |
121 public void openMostVisitedItem(int windowDisposition, Tile tile) {} | 361 public void openMostVisitedItem(int windowDisposition, Tile tile) {} |
122 | 362 |
123 @Override | 363 @Override |
124 public void setMostVisitedSitesObserver( | 364 public void setMostVisitedSitesObserver( |
125 MostVisitedSites.Observer observer, int maxResults) { | 365 MostVisitedSites.Observer observer, int maxResults) { |
126 mObserver = observer; | 366 mObserver = observer; |
127 } | 367 } |
128 | 368 |
129 @Override | 369 @Override |
130 public void onLoadingComplete(Tile[] tiles) {} | 370 public void onLoadingComplete(Tile[] tiles) {} |
131 | 371 |
132 @Override | 372 @Override |
133 public void destroy() {} | 373 public void destroy() {} |
134 } | 374 } |
135 | 375 |
136 /** | 376 /** |
137 * Replacement for the {@link Resources} to allow loading resources used by
{@link TileGroup} in | 377 * Replacement for the {@link Resources} to allow loading resources used by
{@link TileGroup} in |
138 * unit tests. | 378 * unit tests. |
139 * TODO(https://crbug.com/693573): Needed until unit tests can pick up resou
rces themselves. | 379 * TODO(https://crbug.com/693573): Needed until unit tests can pick up resou
rces themselves. |
140 */ | 380 */ |
141 @Implements(Resources.class) | 381 @Implements(Resources.class) |
142 public static class TileShadowResources extends ShadowResources { | 382 public static class TileShadowResources extends ShadowResources { |
143 @RealObject | 383 @Implementation |
144 private Resources mRealResources; | |
145 public int getDimensionPixelSize(@DimenRes int id) { | 384 public int getDimensionPixelSize(@DimenRes int id) { |
146 if (id == R.dimen.tile_view_icon_size) return 2; | 385 if (id == R.dimen.tile_view_icon_size) return 48; |
147 return mRealResources.getDimensionPixelSize(id); | 386 |
| 387 throw new IllegalArgumentException(); |
148 } | 388 } |
149 | 389 |
150 @SuppressWarnings("deprecation") | 390 @Implementation |
151 public int getColor(@ColorRes int id) { | 391 public int getColor(@ColorRes int id) { |
152 if (id == R.color.default_favicon_background_color) return 2; | 392 if (id == R.color.default_favicon_background_color) return Color.BLA
CK; |
153 return mRealResources.getColor(id); | 393 |
| 394 throw new IllegalArgumentException(); |
| 395 } |
| 396 } |
| 397 |
| 398 /** Intercepts calls to inflate views to replace them with mocks. */ |
| 399 @Implements(LayoutInflater.class) |
| 400 public static class ShadowLayoutInflater { |
| 401 @Implementation |
| 402 public static LayoutInflater from(Context context) { |
| 403 LayoutInflater layoutInflater = mock(LayoutInflater.class); |
| 404 when(layoutInflater.inflate(anyInt(), any(ViewGroup.class), anyBoole
an())) |
| 405 .thenAnswer(new Answer<View>() { |
| 406 @Override |
| 407 public View answer(InvocationOnMock invocation) throws T
hrowable { |
| 408 @LayoutRes |
| 409 int layoutId = invocation.getArgument(0); |
| 410 if (layoutId != R.layout.tile_view) fail("Unexpected
resource id."); |
| 411 return createMockTileView(); |
| 412 } |
| 413 }); |
| 414 return layoutInflater; |
154 } | 415 } |
155 } | 416 } |
156 } | 417 } |
OLD | NEW |