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