Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(191)

Side by Side Diff: chrome/android/junit/src/org/chromium/chrome/browser/suggestions/TileGroupTest.java

Issue 2722243002: 📰 Add tests for Tile and TileGroup (Closed)
Patch Set: moar tests Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698