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

Side by Side Diff: chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java

Issue 2860463002: [Suggestions] Remove TreeNode.getSuggestionAt() in favor of a visitor. (Closed)
Patch Set: rebase Created 3 years, 7 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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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.ntp.cards; 5 package org.chromium.chrome.browser.ntp.cards;
6 6
7 import static org.junit.Assert.assertEquals; 7 import static org.junit.Assert.assertEquals;
8 import static org.junit.Assert.assertFalse; 8 import static org.junit.Assert.assertFalse;
9 import static org.junit.Assert.assertNotEquals; 9 import static org.junit.Assert.assertNotEquals;
10 import static org.junit.Assert.assertThat;
11 import static org.junit.Assert.assertTrue; 10 import static org.junit.Assert.assertTrue;
12 import static org.junit.Assert.fail;
13 import static org.mockito.ArgumentMatchers.anyString; 11 import static org.mockito.ArgumentMatchers.anyString;
12 import static org.mockito.ArgumentMatchers.eq;
14 import static org.mockito.Mockito.atLeastOnce; 13 import static org.mockito.Mockito.atLeastOnce;
15 import static org.mockito.Mockito.doNothing; 14 import static org.mockito.Mockito.doNothing;
15 import static org.mockito.Mockito.inOrder;
16 import static org.mockito.Mockito.mock; 16 import static org.mockito.Mockito.mock;
17 import static org.mockito.Mockito.reset; 17 import static org.mockito.Mockito.reset;
18 import static org.mockito.Mockito.spy; 18 import static org.mockito.Mockito.spy;
19 import static org.mockito.Mockito.times; 19 import static org.mockito.Mockito.times;
20 import static org.mockito.Mockito.verify; 20 import static org.mockito.Mockito.verify;
21 import static org.mockito.Mockito.verifyNoMoreInteractions;
21 import static org.mockito.Mockito.when; 22 import static org.mockito.Mockito.when;
22 23
23 import static org.chromium.base.test.util.Matchers.greaterThanOrEqualTo;
24 import static org.chromium.chrome.browser.ntp.cards.ContentSuggestionsUnitTestUt ils.bindViewHolders; 24 import static org.chromium.chrome.browser.ntp.cards.ContentSuggestionsUnitTestUt ils.bindViewHolders;
25 import static org.chromium.chrome.browser.ntp.cards.ContentSuggestionsUnitTestUt ils.makeUiConfig; 25 import static org.chromium.chrome.browser.ntp.cards.ContentSuggestionsUnitTestUt ils.makeUiConfig;
26 import static org.chromium.chrome.test.util.browser.suggestions.ContentSuggestio nsTestUtils.createDummySuggestions; 26 import static org.chromium.chrome.test.util.browser.suggestions.ContentSuggestio nsTestUtils.createDummySuggestions;
27 import static org.chromium.chrome.test.util.browser.suggestions.ContentSuggestio nsTestUtils.explainFailedExpectation;
28 import static org.chromium.chrome.test.util.browser.suggestions.ContentSuggestio nsTestUtils.registerCategory; 27 import static org.chromium.chrome.test.util.browser.suggestions.ContentSuggestio nsTestUtils.registerCategory;
29 import static org.chromium.chrome.test.util.browser.suggestions.ContentSuggestio nsTestUtils.viewTypeToString; 28 import static org.chromium.chrome.test.util.browser.suggestions.ContentSuggestio nsTestUtils.stringify;
30 29
31 import android.content.res.Resources; 30 import android.content.res.Resources;
32 import android.support.v7.widget.RecyclerView; 31 import android.support.v7.widget.RecyclerView;
33 import android.support.v7.widget.RecyclerView.AdapterDataObserver; 32 import android.support.v7.widget.RecyclerView.AdapterDataObserver;
34 import android.view.View; 33 import android.view.View;
35 34
36 import org.junit.After; 35 import org.junit.After;
37 import org.junit.Before; 36 import org.junit.Before;
38 import org.junit.Rule; 37 import org.junit.Rule;
39 import org.junit.Test; 38 import org.junit.Test;
40 import org.junit.runner.RunWith; 39 import org.junit.runner.RunWith;
41 import org.mockito.ArgumentCaptor; 40 import org.mockito.ArgumentCaptor;
41 import org.mockito.InOrder;
42 import org.mockito.Mock; 42 import org.mockito.Mock;
43 import org.mockito.MockitoAnnotations; 43 import org.mockito.MockitoAnnotations;
44 import org.mockito.exceptions.base.MockitoAssertionError;
45 import org.mockito.internal.verification.Times;
46 import org.mockito.internal.verification.api.VerificationDataInOrder;
47 import org.mockito.verification.VerificationMode;
44 import org.robolectric.RuntimeEnvironment; 48 import org.robolectric.RuntimeEnvironment;
45 import org.robolectric.annotation.Config; 49 import org.robolectric.annotation.Config;
46 import org.robolectric.annotation.Implementation; 50 import org.robolectric.annotation.Implementation;
47 import org.robolectric.annotation.Implements; 51 import org.robolectric.annotation.Implements;
48 import org.robolectric.shadows.ShadowResources; 52 import org.robolectric.shadows.ShadowResources;
49 53
50 import org.chromium.base.Callback; 54 import org.chromium.base.Callback;
51 import org.chromium.base.ContextUtils; 55 import org.chromium.base.ContextUtils;
52 import org.chromium.base.test.util.Feature; 56 import org.chromium.base.test.util.Feature;
53 import org.chromium.chrome.R; 57 import org.chromium.chrome.R;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 @Mock 103 @Mock
100 private SigninManager mMockSigninManager; 104 private SigninManager mMockSigninManager;
101 @Mock 105 @Mock
102 private OfflinePageBridge mOfflinePageBridge; 106 private OfflinePageBridge mOfflinePageBridge;
103 @Mock 107 @Mock
104 private SuggestionsUiDelegate mUiDelegate; 108 private SuggestionsUiDelegate mUiDelegate;
105 109
106 /** 110 /**
107 * Stores information about a section that should be present in the adapter. 111 * Stores information about a section that should be present in the adapter.
108 */ 112 */
109 private static class SectionDescriptor { 113 private static class SectionDescriptor {
dgn 2017/05/22 13:47:03 I think it would be nice to extract all of that fr
Bernhard Bauer 2017/05/23 16:40:27 I think it's a good idea, but can we do that in a
110 public final int mNumSuggestions; 114 public final List<SnippetArticle> mSuggestions;
111 public final boolean mStatusCard; 115 public final boolean mStatusCard;
112 public boolean mActionButton; 116 public boolean mViewAllButton;
117 public boolean mFetchButton;
113 public boolean mProgressItem; 118 public boolean mProgressItem;
114 public SnippetArticle mFirstItem;
115 119
116 public SectionDescriptor(int numSuggestions) { 120 public SectionDescriptor(List<SnippetArticle> suggestions) {
117 mNumSuggestions = numSuggestions; 121 mSuggestions = suggestions;
118 mStatusCard = numSuggestions == 0; 122 mStatusCard = suggestions.isEmpty();
119 } 123 }
120 124
121 public SectionDescriptor withActionButton() { 125 public SectionDescriptor withViewAllButton() {
122 mActionButton = true; 126 mViewAllButton = true;
127 return this;
128 }
129
130 public SectionDescriptor withFetchButton() {
131 mFetchButton = true;
123 return this; 132 return this;
124 } 133 }
125 134
126 public SectionDescriptor withProgress() { 135 public SectionDescriptor withProgress() {
127 mProgressItem = true; 136 mProgressItem = true;
128 return this; 137 return this;
129 } 138 }
130
131 public SectionDescriptor withFirstItem(SnippetArticle firstItem) {
132 mFirstItem = firstItem;
133 return this;
134 }
135 } 139 }
136 140
137 /** 141 /**
138 * Checks the list of items from the adapter against a sequence of expectati on, which is 142 * Checks the list of items from the adapter against a sequence of expectati on, which is
139 * expressed as a sequence of calls to the {@link #expect} methods. 143 * expressed as a sequence of calls to the {@code expect...()} methods.
140 */ 144 */
141 private static class ItemsMatcher { // TODO(pke): Find better name. 145 private static class ItemsMatcher { // TODO(pke): Find better name.
142 private final TreeNode mTreeNode; 146 private final TreeNode mRoot;
143 private int mCurrentIndex; 147 private final NodeVisitor mVisitor = mock(NodeVisitor.class);
148 private final InOrder mInOrder = inOrder(mVisitor);
149
150 /**
151 * The {@link org.mockito.internal.verification.Description} verificatio n mode doesn't
152 * support in-order verification, so we use a custom verification mode t hat derives from the
153 * default one.
154 */
155 private final VerificationMode mVerification = new Times(1) {
156 @Override
157 public void verifyInOrder(VerificationDataInOrder data) {
158 try {
159 super.verifyInOrder(data);
160 } catch (MockitoAssertionError e) {
161 throw new MockitoAssertionError(e, stringify(mRoot));
162 }
163 }
164 };
144 165
145 public ItemsMatcher(TreeNode root) { 166 public ItemsMatcher(TreeNode root) {
146 mTreeNode = root; 167 mRoot = root;
168 root.visitItems(mVisitor);
147 } 169 }
148 170
149 public void expect(@ItemViewType int expectedItemType) { 171 public void expectSection(SectionDescriptor descriptor) {
150 if (mCurrentIndex >= mTreeNode.getItemCount()) { 172 mInOrder.verify(mVisitor, mVerification).visitHeader();
dgn 2017/05/22 13:47:03 we can have sections without headers, if the secti
Bernhard Bauer 2017/05/23 16:40:27 That is true, good catch! It only applies to Artic
151 fail("Expected item of type " + viewTypeToString(expectedItemTyp e) 173 for (SnippetArticle suggestion : descriptor.mSuggestions) {
152 + " but encountered end of list\n" 174 mInOrder.verify(mVisitor, mVerification).visitSuggestion(eq(sugg estion));
153 + explainFailedExpectation(mTreeNode, mCurrentIndex, exp ectedItemType));
154 }
155 if (mTreeNode.getItemViewType(mCurrentIndex) != expectedItemType) {
156 fail("Type mismatch at position " + mCurrentIndex + "\n"
157 + explainFailedExpectation(mTreeNode, mCurrentIndex, exp ectedItemType));
158 }
159 mCurrentIndex++;
160 }
161
162 public void expect(SectionDescriptor descriptor) {
163 expect(ItemViewType.HEADER);
164
165 if (descriptor.mFirstItem != null) {
166 if (mTreeNode.getSuggestionAt(mCurrentIndex) != descriptor.mFirs tItem) {
167 fail("Wrong item at position " + mCurrentIndex + "\n"
168 + explainFailedExpectation(
169 mTreeNode, mCurrentIndex, ItemViewType.SNI PPET));
170 }
171 }
172
173 for (int i = 1; i <= descriptor.mNumSuggestions; i++) {
174 expect(ItemViewType.SNIPPET);
175 } 175 }
176 176
177 if (descriptor.mStatusCard) { 177 if (descriptor.mStatusCard) {
178 expect(ItemViewType.STATUS); 178 mInOrder.verify(mVisitor, mVerification).visitNoSuggestionsItem( );
179 } 179 }
180 180
181 if (descriptor.mActionButton) { 181 if (descriptor.mViewAllButton) {
182 // TODO(bauerb): Verify the action. 182 mInOrder.verify(mVisitor, mVerification)
183 expect(ItemViewType.ACTION); 183 .visitActionItem(ContentSuggestionsAdditionalAction.VIEW _ALL);
184 }
185
186 if (descriptor.mFetchButton) {
187 mInOrder.verify(mVisitor, mVerification)
188 .visitActionItem(ContentSuggestionsAdditionalAction.FETC H);
184 } 189 }
185 190
186 if (descriptor.mProgressItem) { 191 if (descriptor.mProgressItem) {
187 expect(ItemViewType.PROGRESS); 192 mInOrder.verify(mVisitor, mVerification).visitProgressItem();
188 } 193 }
189 } 194 }
190 195
196 public void expectAboveTheFoldItem() {
197 mInOrder.verify(mVisitor, mVerification).visitAboveTheFoldItem();
198 }
199
200 public void expectAllDismissedItem() {
201 mInOrder.verify(mVisitor, mVerification).visitAllDismissedItem();
202 }
203
204 public void expectFooter() {
205 mInOrder.verify(mVisitor, mVerification).visitFooter();
206 }
207
208 public void expectSpacingItem() {
209 mInOrder.verify(mVisitor, mVerification).visitSpacingItem();
210 }
211
191 public void expectEnd() { 212 public void expectEnd() {
192 assertEquals(mTreeNode.getItemCount(), mCurrentIndex); 213 try {
214 verifyNoMoreInteractions(mVisitor);
215 } catch (MockitoAssertionError e) {
216 throw new MockitoAssertionError(e, stringify(mRoot));
217 }
193 } 218 }
194 } 219 }
195 220
196 @Before 221 @Before
197 public void setUp() { 222 public void setUp() {
198 MockitoAnnotations.initMocks(this); 223 MockitoAnnotations.initMocks(this);
199 224
200 ContextUtils.initApplicationContextForTests(RuntimeEnvironment.applicati on); 225 ContextUtils.initApplicationContextForTests(RuntimeEnvironment.applicati on);
201 226
202 // Set empty variation params for the test. 227 // Set empty variation params for the test.
(...skipping 30 matching lines...) Expand all
233 @Test 258 @Test
234 @Feature({"Ntp"}) 259 @Feature({"Ntp"})
235 public void testSuggestionLoading() { 260 public void testSuggestionLoading() {
236 assertItemsFor(sectionWithStatusCard().withProgress()); 261 assertItemsFor(sectionWithStatusCard().withProgress());
237 262
238 final int numSuggestions = 3; 263 final int numSuggestions = 3;
239 List<SnippetArticle> suggestions = createDummySuggestions(numSuggestions , TEST_CATEGORY); 264 List<SnippetArticle> suggestions = createDummySuggestions(numSuggestions , TEST_CATEGORY);
240 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE); 265 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE);
241 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions); 266 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions);
242 267
243 assertItemsFor(section(numSuggestions)); 268 assertItemsFor(section(suggestions));
244 } 269 }
245 270
246 /** 271 /**
247 * Tests that the adapter keeps listening for suggestion updates. 272 * Tests that the adapter keeps listening for suggestion updates.
248 */ 273 */
249 @Test 274 @Test
250 @Feature({"Ntp"}) 275 @Feature({"Ntp"})
251 public void testSuggestionLoadingInitiallyEmpty() { 276 public void testSuggestionLoadingInitiallyEmpty() {
252 // If we don't get anything, we should be in the same situation as the i nitial one. 277 // If we don't get anything, we should be in the same situation as the i nitial one.
253 mSource.setSuggestionsForCategory(TEST_CATEGORY, new ArrayList<SnippetAr ticle>()); 278 mSource.setSuggestionsForCategory(TEST_CATEGORY, new ArrayList<SnippetAr ticle>());
254 assertItemsFor(sectionWithStatusCard().withProgress()); 279 assertItemsFor(sectionWithStatusCard().withProgress());
255 280
256 // We should load new suggestions when we get notified about them. 281 // We should load new suggestions when we get notified about them.
257 final int numSuggestions = 5; 282 final int numSuggestions = 5;
258 283
259 List<SnippetArticle> suggestions = createDummySuggestions(numSuggestions , TEST_CATEGORY); 284 List<SnippetArticle> suggestions = createDummySuggestions(numSuggestions , TEST_CATEGORY);
260 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE); 285 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE);
261 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions); 286 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions);
262 287
263 assertItemsFor(section(numSuggestions)); 288 assertItemsFor(section(suggestions));
264 } 289 }
265 290
266 /** 291 /**
267 * Tests that the adapter clears the suggestions when asked to. 292 * Tests that the adapter clears the suggestions when asked to.
268 */ 293 */
269 @Test 294 @Test
270 @Feature({"Ntp"}) 295 @Feature({"Ntp"})
271 public void testSuggestionClearing() { 296 public void testSuggestionClearing() {
272 List<SnippetArticle> suggestions = createDummySuggestions(4, TEST_CATEGO RY); 297 List<SnippetArticle> suggestions = createDummySuggestions(4, TEST_CATEGO RY);
273 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE); 298 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE);
274 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions); 299 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions);
275 assertItemsFor(section(4)); 300 assertItemsFor(section(suggestions));
276 301
277 // If we get told that the category is enabled, we just leave the curren t suggestions do not 302 // If we get told that the category is enabled, we just leave the curren t suggestions do not
278 // clear them. 303 // clear them.
279 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE); 304 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE);
280 assertItemsFor(section(4)); 305 assertItemsFor(section(suggestions));
281 306
282 // When the category is disabled, the section should go away completely. 307 // When the category is disabled, the section should go away completely.
283 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.CATEGORY_EXPL ICITLY_DISABLED); 308 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.CATEGORY_EXPL ICITLY_DISABLED);
284 assertItemsFor(); 309 assertItemsFor();
285 310
286 // Now we're in the "all dismissed" state. No suggestions should be acce pted. 311 // Now we're in the "all dismissed" state. No suggestions should be acce pted.
287 suggestions = createDummySuggestions(6, TEST_CATEGORY); 312 suggestions = createDummySuggestions(6, TEST_CATEGORY);
288 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE); 313 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE);
289 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions); 314 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions);
290 assertItemsFor(); 315 assertItemsFor();
291 316
292 // After a full refresh, the adapter should accept suggestions again. 317 // After a full refresh, the adapter should accept suggestions again.
293 mSource.fireFullRefreshRequired(); 318 mSource.fireFullRefreshRequired();
294 assertItemsFor(section(6)); 319 assertItemsFor(section(suggestions));
295 } 320 }
296 321
297 /** 322 /**
298 * Tests that the adapter loads suggestions only when the status is favorabl e. 323 * Tests that the adapter loads suggestions only when the status is favorabl e.
299 */ 324 */
300 @Test 325 @Test
301 @Feature({"Ntp"}) 326 @Feature({"Ntp"})
302 public void testSuggestionLoadingBlock() { 327 public void testSuggestionLoadingBlock() {
303 List<SnippetArticle> suggestions = createDummySuggestions(3, TEST_CATEGO RY); 328 List<SnippetArticle> suggestions = createDummySuggestions(3, TEST_CATEGO RY);
304 329
305 // By default, status is INITIALIZING, so we can load suggestions. 330 // By default, status is INITIALIZING, so we can load suggestions.
306 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE); 331 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE);
307 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions); 332 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions);
308 assertItemsFor(section(3)); 333 assertItemsFor(section(suggestions));
309 334
310 // Add another suggestion. 335 // Add another suggestion.
311 suggestions.add(new SnippetArticle(TEST_CATEGORY, "https://site.com/url1 ", "title1", "pub1", 336 suggestions.add(new SnippetArticle(TEST_CATEGORY, "https://site.com/url3 ", "title3", "pub3",
312 "txt1", "https://site.com/url1", 0, 0, 0)); 337 "txt3", "https://site.com/url3", 0, 0, 0));
313 338
314 // When the provider is removed, we should not be able to load suggestio ns. The UI should 339 // When the provider is removed, we should not be able to load suggestio ns. The UI should
315 // stay the same though. 340 // stay the same though.
316 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.NOT_PROVIDED) ; 341 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.NOT_PROVIDED) ;
317 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions); 342 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions);
318 assertItemsFor(section(3)); 343 assertItemsFor(section(suggestions.subList(0, 3)));
319 344
320 // INITIALIZING lets us load suggestions still. 345 // INITIALIZING lets us load suggestions still.
321 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.INITIALIZING) ; 346 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.INITIALIZING) ;
322 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions); 347 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions);
323 assertItemsFor(sectionWithStatusCard().withProgress()); 348 assertItemsFor(sectionWithStatusCard().withProgress());
324 349
325 // The adapter should now be waiting for new suggestions and the fourth one should appear. 350 // The adapter should now be waiting for new suggestions and the fourth one should appear.
326 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE); 351 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE);
327 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions); 352 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions);
328 assertItemsFor(section(4)); 353 assertItemsFor(section(suggestions));
329 354
330 // When the category gets disabled, the section should go away and not l oad any suggestions. 355 // When the category gets disabled, the section should go away and not l oad any suggestions.
331 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.CATEGORY_EXPL ICITLY_DISABLED); 356 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.CATEGORY_EXPL ICITLY_DISABLED);
332 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions); 357 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions);
333 assertItemsFor(); 358 assertItemsFor();
334 } 359 }
335 360
336 /** 361 /**
337 * Tests how the loading indicator reacts to status changes. 362 * Tests how the loading indicator reacts to status changes.
338 */ 363 */
(...skipping 22 matching lines...) Expand all
361 /** 386 /**
362 * Tests that the entire section disappears if its status switches to LOADIN G_ERROR or 387 * Tests that the entire section disappears if its status switches to LOADIN G_ERROR or
363 * CATEGORY_EXPLICITLY_DISABLED. Also tests that they are not shown when the NTP reloads. 388 * CATEGORY_EXPLICITLY_DISABLED. Also tests that they are not shown when the NTP reloads.
364 */ 389 */
365 @Test 390 @Test
366 @Feature({"Ntp"}) 391 @Feature({"Ntp"})
367 public void testSectionClearingWhenUnavailable() { 392 public void testSectionClearingWhenUnavailable() {
368 List<SnippetArticle> suggestions = createDummySuggestions(5, TEST_CATEGO RY); 393 List<SnippetArticle> suggestions = createDummySuggestions(5, TEST_CATEGO RY);
369 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE); 394 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE);
370 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions); 395 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions);
371 assertItemsFor(section(5)); 396 assertItemsFor(section(suggestions));
372 397
373 // When the category goes away with a hard error, the section is cleared from the UI. 398 // When the category goes away with a hard error, the section is cleared from the UI.
374 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.LOADING_ERROR ); 399 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.LOADING_ERROR );
375 assertItemsFor(); 400 assertItemsFor();
376 401
377 // Same when loading a new NTP. 402 // Same when loading a new NTP.
378 reloadNtp(); 403 reloadNtp();
379 assertItemsFor(); 404 assertItemsFor();
380 405
381 // Same for CATEGORY_EXPLICITLY_DISABLED. 406 // Same for CATEGORY_EXPLICITLY_DISABLED.
382 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE); 407 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE);
383 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions); 408 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions);
384 reloadNtp(); 409 reloadNtp();
385 assertItemsFor(section(5)); 410 assertItemsFor(section(suggestions));
386 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.CATEGORY_EXPL ICITLY_DISABLED); 411 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.CATEGORY_EXPL ICITLY_DISABLED);
387 assertItemsFor(); 412 assertItemsFor();
388 413
389 reloadNtp(); 414 reloadNtp();
390 assertItemsFor(); 415 assertItemsFor();
391 } 416 }
392 417
393 /** 418 /**
394 * Tests that the UI remains untouched if a category switches to NOT_PROVIDE D. 419 * Tests that the UI remains untouched if a category switches to NOT_PROVIDE D.
395 */ 420 */
396 @Test 421 @Test
397 @Feature({"Ntp"}) 422 @Feature({"Ntp"})
398 public void testUIUntouchedWhenNotProvided() { 423 public void testUIUntouchedWhenNotProvided() {
399 List<SnippetArticle> suggestions = createDummySuggestions(4, TEST_CATEGO RY); 424 List<SnippetArticle> suggestions = createDummySuggestions(4, TEST_CATEGO RY);
400 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE); 425 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE);
401 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions); 426 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions);
402 assertItemsFor(section(4)); 427 assertItemsFor(section(suggestions));
403 428
404 // When the category switches to NOT_PROVIDED, UI stays the same. 429 // When the category switches to NOT_PROVIDED, UI stays the same.
405 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.NOT_PROVIDED) ; 430 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.NOT_PROVIDED) ;
406 mSource.silentlyRemoveCategory(TEST_CATEGORY); 431 mSource.silentlyRemoveCategory(TEST_CATEGORY);
407 assertItemsFor(section(4)); 432 assertItemsFor(section(suggestions));
408 433
409 reloadNtp(); 434 reloadNtp();
410 assertItemsFor(); 435 assertItemsFor();
411 } 436 }
412 437
413 /** 438 /**
414 * Tests that the UI updates on updated suggestions. 439 * Tests that the UI updates on updated suggestions.
415 */ 440 */
416 @Test 441 @Test
417 @Feature({"Ntp"}) 442 @Feature({"Ntp"})
418 public void testUIUpdatesOnNewSuggestionsWhenOtherSectionSeen() { 443 public void testUIUpdatesOnNewSuggestionsWhenOtherSectionSeen() {
419 List<SnippetArticle> suggestions = createDummySuggestions(4, TEST_CATEGO RY); 444 List<SnippetArticle> suggestions = createDummySuggestions(4, TEST_CATEGO RY);
420 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE); 445 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE);
421 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions); 446 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions);
422 447
423 @CategoryInt 448 @CategoryInt
424 final int otherCategory = TEST_CATEGORY + 1; 449 final int otherCategory = TEST_CATEGORY + 1;
425 List<SnippetArticle> otherSuggestions = createDummySuggestions(2, otherC ategory); 450 List<SnippetArticle> otherSuggestions = createDummySuggestions(2, otherC ategory);
426 mSource.setStatusForCategory(otherCategory, CategoryStatus.AVAILABLE); 451 mSource.setStatusForCategory(otherCategory, CategoryStatus.AVAILABLE);
427 mSource.setInfoForCategory( 452 mSource.setInfoForCategory(
428 otherCategory, new CategoryInfoBuilder(otherCategory).showIfEmpt y().build()); 453 otherCategory, new CategoryInfoBuilder(otherCategory).showIfEmpt y().build());
429 mSource.setSuggestionsForCategory(otherCategory, otherSuggestions); 454 mSource.setSuggestionsForCategory(otherCategory, otherSuggestions);
430 455
431 reloadNtp(); 456 reloadNtp();
432 assertItemsFor(section(4), section(2)); 457 assertItemsFor(section(suggestions), section(otherSuggestions));
433 458
434 // Bind the whole section - indicate that it is being viewed. 459 // Bind the whole section - indicate that it is being viewed.
435 bindViewHolders(mAdapter.getSectionListForTesting().getSectionForTesting (otherCategory)); 460 bindViewHolders(mAdapter.getSectionListForTesting().getSectionForTesting (otherCategory));
436 461
437 List<SnippetArticle> newSuggestions = createDummySuggestions(3, TEST_CAT EGORY, "new"); 462 List<SnippetArticle> newSuggestions = createDummySuggestions(3, TEST_CAT EGORY, "new");
438 mSource.setSuggestionsForCategory(TEST_CATEGORY, newSuggestions); 463 mSource.setSuggestionsForCategory(TEST_CATEGORY, newSuggestions);
439 assertItemsFor(section(3), section(2)); 464 assertItemsFor(section(newSuggestions), section(otherSuggestions));
440 465
441 reloadNtp(); 466 reloadNtp();
442 assertItemsFor(section(3), section(2)); 467 assertItemsFor(section(newSuggestions), section(otherSuggestions));
443 } 468 }
444 469
445 /** Tests whether a section stays visible if empty, if required. */ 470 /** Tests whether a section stays visible if empty, if required. */
446 @Test 471 @Test
447 @Feature({"Ntp"}) 472 @Feature({"Ntp"})
448 public void testSectionVisibleIfEmpty() { 473 public void testSectionVisibleIfEmpty() {
449 // Part 1: VisibleIfEmpty = true 474 // Part 1: VisibleIfEmpty = true
450 FakeSuggestionsSource suggestionsSource = new FakeSuggestionsSource(); 475 FakeSuggestionsSource suggestionsSource = new FakeSuggestionsSource();
451 suggestionsSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.INI TIALIZING); 476 suggestionsSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.INI TIALIZING);
452 suggestionsSource.setInfoForCategory( 477 suggestionsSource.setInfoForCategory(
453 TEST_CATEGORY, new CategoryInfoBuilder(TEST_CATEGORY).showIfEmpt y().build()); 478 TEST_CATEGORY, new CategoryInfoBuilder(TEST_CATEGORY).showIfEmpt y().build());
454 479
455 // 1.1 - Initial state 480 // 1.1 - Initial state
456 when(mUiDelegate.getSuggestionsSource()).thenReturn(suggestionsSource); 481 when(mUiDelegate.getSuggestionsSource()).thenReturn(suggestionsSource);
457 reloadNtp(); 482 reloadNtp();
458 assertItemsFor(sectionWithStatusCard().withProgress()); 483 assertItemsFor(sectionWithStatusCard().withProgress());
459 484
460 // 1.2 - With suggestions 485 // 1.2 - With suggestions
461 List<SnippetArticle> suggestions = 486 List<SnippetArticle> suggestions =
462 Collections.unmodifiableList(createDummySuggestions(3, TEST_CATE GORY)); 487 Collections.unmodifiableList(createDummySuggestions(3, TEST_CATE GORY));
463 suggestionsSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVA ILABLE); 488 suggestionsSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVA ILABLE);
464 suggestionsSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions); 489 suggestionsSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions);
465 assertItemsFor(section(3)); 490 assertItemsFor(section(suggestions));
466 491
467 // 1.3 - When all suggestions are dismissed 492 // 1.3 - When all suggestions are dismissed
468 SuggestionsSection section = 493 SuggestionsSection section =
469 mAdapter.getSectionListForTesting().getSectionForTesting(TEST_CA TEGORY); 494 mAdapter.getSectionListForTesting().getSectionForTesting(TEST_CA TEGORY);
470 assertSectionMatches(section(3), section); 495 assertSectionMatches(section(suggestions), section);
471 section.removeSuggestionById(suggestions.get(0).mIdWithinCategory); 496 section.removeSuggestionById(suggestions.get(0).mIdWithinCategory);
472 section.removeSuggestionById(suggestions.get(1).mIdWithinCategory); 497 section.removeSuggestionById(suggestions.get(1).mIdWithinCategory);
473 section.removeSuggestionById(suggestions.get(2).mIdWithinCategory); 498 section.removeSuggestionById(suggestions.get(2).mIdWithinCategory);
474 assertItemsFor(sectionWithStatusCard()); 499 assertItemsFor(sectionWithStatusCard());
475 500
476 // Part 2: VisibleIfEmpty = false 501 // Part 2: VisibleIfEmpty = false
477 suggestionsSource = new FakeSuggestionsSource(); 502 suggestionsSource = new FakeSuggestionsSource();
478 suggestionsSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.INI TIALIZING); 503 suggestionsSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.INI TIALIZING);
479 suggestionsSource.setInfoForCategory( 504 suggestionsSource.setInfoForCategory(
480 TEST_CATEGORY, new CategoryInfoBuilder(TEST_CATEGORY).build()); 505 TEST_CATEGORY, new CategoryInfoBuilder(TEST_CATEGORY).build());
481 506
482 // 2.1 - Initial state 507 // 2.1 - Initial state
483 when(mUiDelegate.getSuggestionsSource()).thenReturn(suggestionsSource); 508 when(mUiDelegate.getSuggestionsSource()).thenReturn(suggestionsSource);
484 reloadNtp(); 509 reloadNtp();
485 assertItemsFor(); 510 assertItemsFor();
486 511
487 // 2.2 - With suggestions 512 // 2.2 - With suggestions
488 suggestionsSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVA ILABLE); 513 suggestionsSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVA ILABLE);
489 suggestionsSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions); 514 suggestionsSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions);
490 assertItemsFor(); 515 assertItemsFor();
491 516
492 // 2.3 - When all suggestions are dismissed - N/A, suggestions don't get added. 517 // 2.3 - When all suggestions are dismissed - N/A, suggestions don't get added.
493 } 518 }
494 519
495 /** 520 /**
496 * Tests that the more button is shown for sections that declare it. 521 * Tests that the more button is shown for sections that declare it.
497 */ 522 */
498 @Test 523 @Test
499 @Feature({"Ntp"}) 524 @Feature({"Ntp"})
500 public void testMoreButton() { 525 public void testViewAllButton() {
501 // Part 1: With "View All" action 526 // Part 1: With "View All" action
502 FakeSuggestionsSource suggestionsSource = new FakeSuggestionsSource(); 527 FakeSuggestionsSource suggestionsSource = new FakeSuggestionsSource();
503 suggestionsSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.INI TIALIZING); 528 suggestionsSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.INI TIALIZING);
504 suggestionsSource.setInfoForCategory(TEST_CATEGORY, 529 suggestionsSource.setInfoForCategory(TEST_CATEGORY,
505 new CategoryInfoBuilder(TEST_CATEGORY) 530 new CategoryInfoBuilder(TEST_CATEGORY)
506 .withAction(ContentSuggestionsAdditionalAction.VIEW_ALL) 531 .withAction(ContentSuggestionsAdditionalAction.VIEW_ALL)
507 .showIfEmpty() 532 .showIfEmpty()
508 .build()); 533 .build());
509 534
510 // 1.1 - Initial state. 535 // 1.1 - Initial state.
511 when(mUiDelegate.getSuggestionsSource()).thenReturn(suggestionsSource); 536 when(mUiDelegate.getSuggestionsSource()).thenReturn(suggestionsSource);
512 reloadNtp(); 537 reloadNtp();
513 assertItemsFor(sectionWithStatusCard().withActionButton().withProgress() ); 538 assertItemsFor(sectionWithStatusCard().withViewAllButton().withProgress( ));
514 539
515 // 1.2 - With suggestions. 540 // 1.2 - With suggestions.
516 List<SnippetArticle> suggestions = 541 List<SnippetArticle> suggestions =
517 Collections.unmodifiableList(createDummySuggestions(3, TEST_CATE GORY)); 542 Collections.unmodifiableList(createDummySuggestions(3, TEST_CATE GORY));
518 suggestionsSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVA ILABLE); 543 suggestionsSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVA ILABLE);
519 suggestionsSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions); 544 suggestionsSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions);
520 assertItemsFor(section(3).withActionButton()); 545 assertItemsFor(section(suggestions).withViewAllButton());
521 546
522 // 1.3 - When all suggestions are dismissed. 547 // 1.3 - When all suggestions are dismissed.
523 SuggestionsSection section = 548 SuggestionsSection section =
524 mAdapter.getSectionListForTesting().getSectionForTesting(TEST_CA TEGORY); 549 mAdapter.getSectionListForTesting().getSectionForTesting(TEST_CA TEGORY);
525 assertSectionMatches(section(3).withActionButton(), section); 550 assertSectionMatches(section(suggestions).withViewAllButton(), section);
526 section.removeSuggestionById(suggestions.get(0).mIdWithinCategory); 551 section.removeSuggestionById(suggestions.get(0).mIdWithinCategory);
527 section.removeSuggestionById(suggestions.get(1).mIdWithinCategory); 552 section.removeSuggestionById(suggestions.get(1).mIdWithinCategory);
528 section.removeSuggestionById(suggestions.get(2).mIdWithinCategory); 553 section.removeSuggestionById(suggestions.get(2).mIdWithinCategory);
529 assertItemsFor(sectionWithStatusCard().withActionButton()); 554 assertItemsFor(sectionWithStatusCard().withViewAllButton());
530 555
531 // Part 1: Without "View All" action 556 // Part 1: Without "View All" action
532 suggestionsSource = new FakeSuggestionsSource(); 557 suggestionsSource = new FakeSuggestionsSource();
533 suggestionsSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.INI TIALIZING); 558 suggestionsSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.INI TIALIZING);
534 suggestionsSource.setInfoForCategory( 559 suggestionsSource.setInfoForCategory(
535 TEST_CATEGORY, new CategoryInfoBuilder(TEST_CATEGORY).showIfEmpt y().build()); 560 TEST_CATEGORY, new CategoryInfoBuilder(TEST_CATEGORY).showIfEmpt y().build());
536 561
537 // 2.1 - Initial state. 562 // 2.1 - Initial state.
538 when(mUiDelegate.getSuggestionsSource()).thenReturn(suggestionsSource); 563 when(mUiDelegate.getSuggestionsSource()).thenReturn(suggestionsSource);
539 reloadNtp(); 564 reloadNtp();
540 assertItemsFor(sectionWithStatusCard().withProgress()); 565 assertItemsFor(sectionWithStatusCard().withProgress());
541 566
542 // 2.2 - With suggestions. 567 // 2.2 - With suggestions.
543 suggestionsSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVA ILABLE); 568 suggestionsSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVA ILABLE);
544 suggestionsSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions); 569 suggestionsSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions);
545 assertItemsFor(section(3)); 570 assertItemsFor(section(suggestions));
546 571
547 // 2.3 - When all suggestions are dismissed. 572 // 2.3 - When all suggestions are dismissed.
548 section = mAdapter.getSectionListForTesting().getSectionForTesting(TEST_ CATEGORY); 573 section = mAdapter.getSectionListForTesting().getSectionForTesting(TEST_ CATEGORY);
549 assertSectionMatches(section(3), section); 574 assertSectionMatches(section(suggestions), section);
550 section.removeSuggestionById(suggestions.get(0).mIdWithinCategory); 575 section.removeSuggestionById(suggestions.get(0).mIdWithinCategory);
551 section.removeSuggestionById(suggestions.get(1).mIdWithinCategory); 576 section.removeSuggestionById(suggestions.get(1).mIdWithinCategory);
552 section.removeSuggestionById(suggestions.get(2).mIdWithinCategory); 577 section.removeSuggestionById(suggestions.get(2).mIdWithinCategory);
553 assertItemsFor(sectionWithStatusCard()); 578 assertItemsFor(sectionWithStatusCard());
554 } 579 }
555 580
556 /** 581 /**
582 * Tests that the more button is shown for sections that declare it.
583 */
584 @Test
585 @Feature({"Ntp"})
586 public void testFetchButton() {
587 @CategoryInt
588 final int category = 42;
dgn 2017/05/22 13:47:03 nit: use TEST_CATEGORY
Bernhard Bauer 2017/05/23 16:40:26 Done.
589
590 // Part 1: With "Fetch more" action
591 FakeSuggestionsSource suggestionsSource = new FakeSuggestionsSource();
592 suggestionsSource.setStatusForCategory(category, CategoryStatus.INITIALI ZING);
593 suggestionsSource.setInfoForCategory(category,
594 new CategoryInfoBuilder(category)
595 .withAction(ContentSuggestionsAdditionalAction.FETCH)
596 .showIfEmpty()
597 .build());
598
599 // 1.1 - Initial state.
600 when(mUiDelegate.getSuggestionsSource()).thenReturn(suggestionsSource);
601 reloadNtp();
602 assertItemsFor(sectionWithStatusCard().withFetchButton().withProgress()) ;
603
604 // 1.2 - With suggestions.
605 List<SnippetArticle> articles =
606 Collections.unmodifiableList(createDummySuggestions(3, category) );
607 suggestionsSource.setStatusForCategory(category, CategoryStatus.AVAILABL E);
608 suggestionsSource.setSuggestionsForCategory(category, articles);
609 assertItemsFor(section(articles).withFetchButton());
610
611 // 1.3 - When all suggestions are dismissed.
612 SuggestionsSection section42 =
613 mAdapter.getSectionListForTesting().getSectionForTesting(categor y);
614 assertSectionMatches(section(articles).withFetchButton(), section42);
615 section42.removeSuggestionById(articles.get(0).mIdWithinCategory);
616 section42.removeSuggestionById(articles.get(1).mIdWithinCategory);
617 section42.removeSuggestionById(articles.get(2).mIdWithinCategory);
618 assertItemsFor(sectionWithStatusCard().withFetchButton());
619
620 // Part 1: Without "Fetch more" action
621 suggestionsSource = new FakeSuggestionsSource();
622 suggestionsSource.setStatusForCategory(category, CategoryStatus.INITIALI ZING);
623 suggestionsSource.setInfoForCategory(
624 category, new CategoryInfoBuilder(category).showIfEmpty().build( ));
625
626 // 2.1 - Initial state.
627 when(mUiDelegate.getSuggestionsSource()).thenReturn(suggestionsSource);
628 reloadNtp();
629 assertItemsFor(sectionWithStatusCard().withProgress());
630
631 // 2.2 - With suggestions.
632 suggestionsSource.setStatusForCategory(category, CategoryStatus.AVAILABL E);
633 suggestionsSource.setSuggestionsForCategory(category, articles);
634 assertItemsFor(section(articles));
635
636 // 2.3 - When all suggestions are dismissed.
637 section42 = mAdapter.getSectionListForTesting().getSectionForTesting(cat egory);
638 assertSectionMatches(section(articles), section42);
639 section42.removeSuggestionById(articles.get(0).mIdWithinCategory);
640 section42.removeSuggestionById(articles.get(1).mIdWithinCategory);
641 section42.removeSuggestionById(articles.get(2).mIdWithinCategory);
642 assertItemsFor(sectionWithStatusCard());
643 }
644
645 /**
557 * Tests that invalidated suggestions are immediately removed. 646 * Tests that invalidated suggestions are immediately removed.
558 */ 647 */
559 @Test 648 @Test
560 @Feature({"Ntp"}) 649 @Feature({"Ntp"})
561 public void testSuggestionInvalidated() { 650 public void testSuggestionInvalidated() {
562 List<SnippetArticle> suggestions = createDummySuggestions(3, TEST_CATEGO RY); 651 List<SnippetArticle> suggestions = createDummySuggestions(3, TEST_CATEGO RY);
563 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE); 652 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE);
564 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions); 653 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions);
565 assertItemsFor(section(3)); 654 assertItemsFor(section(suggestions));
566 assertArticlesEqual(suggestions, 2, 5);
567 655
568 SnippetArticle removed = suggestions.remove(1); 656 SnippetArticle removed = suggestions.remove(1);
569 mSource.fireSuggestionInvalidated(TEST_CATEGORY, removed.mIdWithinCatego ry); 657 mSource.fireSuggestionInvalidated(TEST_CATEGORY, removed.mIdWithinCatego ry);
570 assertArticlesEqual(suggestions, 2, 4); 658 assertItemsFor(section(suggestions));
571 } 659 }
572 660
573 /** 661 /**
574 * Tests that the UI handles dynamically added (server-side) categories corr ectly. 662 * Tests that the UI handles dynamically added (server-side) categories corr ectly.
575 */ 663 */
576 @Test 664 @Test
577 @Feature({"Ntp"}) 665 @Feature({"Ntp"})
578 public void testDynamicCategories() { 666 public void testDynamicCategories() {
579 List<SnippetArticle> suggestions = createDummySuggestions(3, TEST_CATEGO RY); 667 List<SnippetArticle> suggestions = createDummySuggestions(3, TEST_CATEGO RY);
580 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE); 668 mSource.setStatusForCategory(TEST_CATEGORY, CategoryStatus.AVAILABLE);
581 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions); 669 mSource.setSuggestionsForCategory(TEST_CATEGORY, suggestions);
582 assertItemsFor(section(3)); 670 assertItemsFor(section(suggestions));
583 671
584 int dynamicCategory1 = 1010; 672 int dynamicCategory1 = 1010;
585 List<SnippetArticle> dynamics1 = createDummySuggestions(5, dynamicCatego ry1); 673 List<SnippetArticle> dynamics1 = createDummySuggestions(5, dynamicCatego ry1);
586 mSource.setInfoForCategory(dynamicCategory1, 674 mSource.setInfoForCategory(dynamicCategory1,
587 new CategoryInfoBuilder(dynamicCategory1) 675 new CategoryInfoBuilder(dynamicCategory1)
588 .withAction(ContentSuggestionsAdditionalAction.VIEW_ALL) 676 .withAction(ContentSuggestionsAdditionalAction.VIEW_ALL)
589 .build()); 677 .build());
590 mSource.setStatusForCategory(dynamicCategory1, CategoryStatus.AVAILABLE) ; 678 mSource.setStatusForCategory(dynamicCategory1, CategoryStatus.AVAILABLE) ;
591 mSource.setSuggestionsForCategory(dynamicCategory1, dynamics1); 679 mSource.setSuggestionsForCategory(dynamicCategory1, dynamics1);
592 reloadNtp(); 680 reloadNtp();
593 681
594 assertItemsFor(section(3), section(5).withActionButton()); 682 assertItemsFor(section(suggestions), section(dynamics1).withViewAllButto n());
595 683
596 int dynamicCategory2 = 1011; 684 int dynamicCategory2 = 1011;
597 List<SnippetArticle> dynamics2 = createDummySuggestions(11, dynamicCateg ory2); 685 List<SnippetArticle> dynamics2 = createDummySuggestions(11, dynamicCateg ory2);
598 mSource.setInfoForCategory(dynamicCategory2, 686 mSource.setInfoForCategory(dynamicCategory2,
599 new CategoryInfoBuilder(dynamicCategory1).build()); 687 new CategoryInfoBuilder(dynamicCategory1).build());
600 mSource.setStatusForCategory(dynamicCategory2, CategoryStatus.AVAILABLE) ; 688 mSource.setStatusForCategory(dynamicCategory2, CategoryStatus.AVAILABLE) ;
601 mSource.setSuggestionsForCategory(dynamicCategory2, dynamics2); 689 mSource.setSuggestionsForCategory(dynamicCategory2, dynamics2);
602 reloadNtp(); 690 reloadNtp();
603 assertItemsFor(section(3), section(5).withActionButton(), section(11)); 691 assertItemsFor(
692 section(suggestions), section(dynamics1).withViewAllButton(), se ction(dynamics2));
604 } 693 }
605 694
606 /** 695 /**
607 * Tests that the order of the categories is kept. 696 * Tests that the order of the categories is kept.
608 */ 697 */
609 @Test 698 @Test
610 @Feature({"Ntp"}) 699 @Feature({"Ntp"})
611 public void testCategoryOrder() { 700 public void testCategoryOrder() {
612 int[] categories = {TEST_CATEGORY, TEST_CATEGORY + 2, TEST_CATEGORY + 3, TEST_CATEGORY + 4}; 701 int[] categories = {TEST_CATEGORY, TEST_CATEGORY + 2, TEST_CATEGORY + 3, TEST_CATEGORY + 4};
613 FakeSuggestionsSource suggestionsSource = new FakeSuggestionsSource(); 702 FakeSuggestionsSource suggestionsSource = new FakeSuggestionsSource();
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after
953 } 1042 }
954 1043
955 /** 1044 /**
956 * Asserts that the given {@link TreeNode} is a {@link SuggestionsSection} t hat matches the 1045 * Asserts that the given {@link TreeNode} is a {@link SuggestionsSection} t hat matches the
957 * given {@link SectionDescriptor}. 1046 * given {@link SectionDescriptor}.
958 * @param descriptor The section descriptor to match against. 1047 * @param descriptor The section descriptor to match against.
959 * @param section The section from the adapter. 1048 * @param section The section from the adapter.
960 */ 1049 */
961 private void assertSectionMatches(SectionDescriptor descriptor, SuggestionsS ection section) { 1050 private void assertSectionMatches(SectionDescriptor descriptor, SuggestionsS ection section) {
962 ItemsMatcher matcher = new ItemsMatcher(section); 1051 ItemsMatcher matcher = new ItemsMatcher(section);
963 matcher.expect(descriptor); 1052 matcher.expectSection(descriptor);
964 matcher.expectEnd(); 1053 matcher.expectEnd();
965 } 1054 }
966 1055
967 /** 1056 /**
968 * Asserts that {@link #mAdapter}.{@link NewTabPageAdapter#getItemCount()} c orresponds to an NTP 1057 * Asserts that {@link #mAdapter}.{@link NewTabPageAdapter#getItemCount()} c orresponds to an NTP
969 * with the given sections in it. 1058 * with the given sections in it.
970 * 1059 *
971 * @param descriptors A list of descriptors, each describing a section that should be present on 1060 * @param descriptors A list of descriptors, each describing a section that should be present on
972 * the UI. 1061 * the UI.
973 */ 1062 */
974 private void assertItemsFor(SectionDescriptor... descriptors) { 1063 private void assertItemsFor(SectionDescriptor... descriptors) {
975 ItemsMatcher matcher = new ItemsMatcher(mAdapter.getRootForTesting()); 1064 ItemsMatcher matcher = new ItemsMatcher(mAdapter.getRootForTesting());
976 matcher.expect(ItemViewType.ABOVE_THE_FOLD); 1065 matcher.expectAboveTheFoldItem();
977 for (SectionDescriptor descriptor : descriptors) matcher.expect(descript or); 1066 for (SectionDescriptor descriptor : descriptors) matcher.expectSection(d escriptor);
978 if (descriptors.length == 0) { 1067 if (descriptors.length == 0) {
979 matcher.expect(ItemViewType.ALL_DISMISSED); 1068 matcher.expectAllDismissedItem();
980 } else { 1069 } else {
981 matcher.expect(ItemViewType.FOOTER); 1070 matcher.expectFooter();
982 } 1071 }
983 matcher.expect(ItemViewType.SPACING); 1072 matcher.expectSpacingItem();
984 matcher.expectEnd(); 1073 matcher.expectEnd();
985 } 1074 }
986 1075
987 /** 1076 /**
988 * To be used with {@link #assertItemsFor(SectionDescriptor...)}, for a sect ion with 1077 * To be used with {@link #assertItemsFor(SectionDescriptor...)}, for a sect ion with
989 * {@code numSuggestions} cards in it. 1078 * {@code numSuggestions} cards in it.
990 * @param numSuggestions The number of suggestions in the section. If there are zero, use either 1079 * @param suggestions The list of suggestions in the section. If the list is empty, use either
991 * no section at all (if it is not displayed) or 1080 * no section at all (if it is not displayed) or
992 * {@link #sectionWithStatusCard()}. 1081 * {@link #sectionWithStatusCard()}.
993 * @return A descriptor for the section. 1082 * @return A descriptor for the section.
994 */ 1083 */
995 private SectionDescriptor section(int numSuggestions) { 1084 private SectionDescriptor section(List<SnippetArticle> suggestions) {
996 assert numSuggestions > 0; 1085 assert !suggestions.isEmpty();
997 return new SectionDescriptor(numSuggestions); 1086 return new SectionDescriptor(suggestions);
998 } 1087 }
999 1088
1000 /** 1089 /**
1001 * To be used with {@link #assertItemsFor(SectionDescriptor...)}, for a sect ion that has no 1090 * To be used with {@link #assertItemsFor(SectionDescriptor...)}, for a sect ion that has no
1002 * suggestions, but a status card to be displayed. 1091 * suggestions, but a status card to be displayed.
1003 * @return A descriptor for the section. 1092 * @return A descriptor for the section.
1004 */ 1093 */
1005 private SectionDescriptor sectionWithStatusCard() { 1094 private SectionDescriptor sectionWithStatusCard() {
1006 return new SectionDescriptor(0); 1095 return new SectionDescriptor(Collections.<SnippetArticle>emptyList());
1007 } 1096 }
1008 1097
1009 private void reloadNtp() { 1098 private void reloadNtp() {
1010 mAdapter = new NewTabPageAdapter(mUiDelegate, mock(View.class), makeUiCo nfig(), 1099 mAdapter = new NewTabPageAdapter(mUiDelegate, mock(View.class), makeUiCo nfig(),
1011 mOfflinePageBridge, mock(ContextMenuManager.class), /* tileGroup Delegate = 1100 mOfflinePageBridge, mock(ContextMenuManager.class), /* tileGroup Delegate =
1012 */ null); 1101 */ null);
1013 mAdapter.refreshSuggestions(); 1102 mAdapter.refreshSuggestions();
1014 } 1103 }
1015 1104
1016 private void assertArticlesEqual(List<SnippetArticle> articles, int start, i nt end) {
1017 assertThat(mAdapter.getItemCount(), greaterThanOrEqualTo(end));
1018 for (int i = start; i < end; i++) {
1019 assertEquals(articles.get(i - start), mAdapter.getSuggestionAt(i));
1020 }
1021 }
1022
1023 private boolean isSignInPromoVisible() { 1105 private boolean isSignInPromoVisible() {
1024 return mAdapter.getFirstPositionForType(ItemViewType.PROMO) != RecyclerV iew.NO_POSITION; 1106 return mAdapter.getFirstPositionForType(ItemViewType.PROMO) != RecyclerV iew.NO_POSITION;
1025 } 1107 }
1026 1108
1027 private int getCategory(TreeNode item) { 1109 private int getCategory(TreeNode item) {
1028 return ((SuggestionsSection) item).getCategory(); 1110 return ((SuggestionsSection) item).getCategory();
1029 } 1111 }
1030 } 1112 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698