| Index: chrome/android/junit/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorNotificationBridgeUiTest.java
|
| diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorNotificationBridgeUiTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorNotificationBridgeUiTest.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..2947237bcfa6099043665b961709134b19fb8308
|
| --- /dev/null
|
| +++ b/chrome/android/junit/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorNotificationBridgeUiTest.java
|
| @@ -0,0 +1,334 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package org.chromium.chrome.browser.download.items;
|
| +
|
| +import static org.mockito.ArgumentMatchers.argThat;
|
| +import static org.mockito.Mockito.inOrder;
|
| +import static org.mockito.Mockito.never;
|
| +import static org.mockito.Mockito.times;
|
| +import static org.mockito.Mockito.verify;
|
| +
|
| +import android.graphics.Bitmap;
|
| +
|
| +import org.junit.Assert;
|
| +import org.junit.Rule;
|
| +import org.junit.Test;
|
| +import org.junit.runner.RunWith;
|
| +import org.mockito.ArgumentCaptor;
|
| +import org.mockito.ArgumentMatcher;
|
| +import org.mockito.ArgumentMatchers;
|
| +import org.mockito.InOrder;
|
| +import org.mockito.Mock;
|
| +import org.mockito.junit.MockitoJUnit;
|
| +import org.mockito.junit.MockitoRule;
|
| +import org.robolectric.annotation.Config;
|
| +
|
| +import org.chromium.chrome.browser.download.DownloadInfo;
|
| +import org.chromium.chrome.browser.download.DownloadNotifier;
|
| +import org.chromium.components.offline_items_collection.ContentId;
|
| +import org.chromium.components.offline_items_collection.OfflineContentProvider;
|
| +import org.chromium.components.offline_items_collection.OfflineItem;
|
| +import org.chromium.components.offline_items_collection.OfflineItemState;
|
| +import org.chromium.components.offline_items_collection.OfflineItemVisuals;
|
| +import org.chromium.testing.local.LocalRobolectricTestRunner;
|
| +
|
| +import java.util.ArrayList;
|
| +import java.util.List;
|
| +
|
| +/**
|
| + * Unit tests for {@link OfflineContentAggregatorNotifierBridgeUi}. Validate that it interacts with
|
| + * both the {@link DownloadNotifier} and the {@link OfflineContentProvider} in expected ways.
|
| + */
|
| +@RunWith(LocalRobolectricTestRunner.class)
|
| +@Config(manifest = Config.NONE)
|
| +public class OfflineContentAggregatorNotificationBridgeUiTest {
|
| + /** Helper class to validate that a DownloadInfo has the right ContentId. */
|
| + static class DownloadInfoIdMatcher implements ArgumentMatcher<DownloadInfo> {
|
| + private final ContentId mExpectedId;
|
| +
|
| + public DownloadInfoIdMatcher(ContentId expected) {
|
| + mExpectedId = expected;
|
| + }
|
| +
|
| + @Override
|
| + public boolean matches(DownloadInfo argument) {
|
| + return ((DownloadInfo) argument).getContentId().equals(mExpectedId);
|
| + }
|
| +
|
| + @Override
|
| + public String toString() {
|
| + return mExpectedId == null ? null : mExpectedId.toString();
|
| + }
|
| + }
|
| +
|
| + @Mock
|
| + private OfflineContentProvider mProvider;
|
| +
|
| + @Mock
|
| + private DownloadNotifier mNotifier;
|
| +
|
| + @Rule
|
| + public MockitoRule mMockitoRule = MockitoJUnit.rule();
|
| +
|
| + private static OfflineItem buildOfflineItem(ContentId id, @OfflineItemState int state) {
|
| + OfflineItem item = new OfflineItem();
|
| + item.id = id;
|
| + item.state = state;
|
| + return item;
|
| + }
|
| +
|
| + @Test
|
| + public void testOnlyInterestingNewItemsGetSentToTheUi() {
|
| + OfflineContentAggregatorNotificationBridgeUi bridge =
|
| + new OfflineContentAggregatorNotificationBridgeUi(mProvider, mNotifier);
|
| + verify(mProvider, times(1)).addObserver(bridge);
|
| +
|
| + ArrayList<OfflineItem> items = new ArrayList<OfflineItem>() {
|
| + {
|
| + add(buildOfflineItem(new ContentId("1", "A"), OfflineItemState.IN_PROGRESS));
|
| + add(buildOfflineItem(new ContentId("2", "B"), OfflineItemState.PENDING));
|
| + add(buildOfflineItem(new ContentId("3", "C"), OfflineItemState.COMPLETE));
|
| + add(buildOfflineItem(new ContentId("4", "D"), OfflineItemState.CANCELLED));
|
| + add(buildOfflineItem(new ContentId("5", "E"), OfflineItemState.INTERRUPTED));
|
| + add(buildOfflineItem(new ContentId("6", "F"), OfflineItemState.FAILED));
|
| + add(buildOfflineItem(new ContentId("7", "G"), OfflineItemState.PAUSED));
|
| + }
|
| + };
|
| +
|
| + bridge.onItemsAvailable();
|
| + bridge.onItemsAdded(items);
|
| +
|
| + InOrder order = inOrder(mProvider);
|
| + order.verify(mProvider, times(1))
|
| + .getVisualsForItem(items.get(0).id /* OfflineItemState.IN_PROGRESS */, bridge);
|
| + order.verify(mProvider, never())
|
| + .getVisualsForItem(ArgumentMatchers.any(), ArgumentMatchers.any());
|
| +
|
| + bridge.onVisualsAvailable(items.get(0).id, new OfflineItemVisuals());
|
| +
|
| + verify(mNotifier, times(1))
|
| + .notifyDownloadProgress(argThat(new DownloadInfoIdMatcher(items.get(0).id)),
|
| + ArgumentMatchers.anyLong(), ArgumentMatchers.anyBoolean());
|
| +
|
| + bridge.destroy();
|
| + verify(mProvider, times(1)).removeObserver(bridge);
|
| + }
|
| +
|
| + @Test
|
| + public void testItemUpdatesGetSentToTheUi() {
|
| + OfflineContentAggregatorNotificationBridgeUi bridge =
|
| + new OfflineContentAggregatorNotificationBridgeUi(mProvider, mNotifier);
|
| + verify(mProvider, times(1)).addObserver(bridge);
|
| +
|
| + ArrayList<OfflineItem> items = new ArrayList<OfflineItem>() {
|
| + {
|
| + add(buildOfflineItem(new ContentId("1", "A"), OfflineItemState.IN_PROGRESS));
|
| + add(buildOfflineItem(new ContentId("2", "B"), OfflineItemState.PENDING));
|
| + add(buildOfflineItem(new ContentId("3", "C"), OfflineItemState.COMPLETE));
|
| + add(buildOfflineItem(new ContentId("4", "D"), OfflineItemState.CANCELLED));
|
| + add(buildOfflineItem(new ContentId("5", "E"), OfflineItemState.INTERRUPTED));
|
| + add(buildOfflineItem(new ContentId("6", "F"), OfflineItemState.FAILED));
|
| + add(buildOfflineItem(new ContentId("7", "G"), OfflineItemState.PAUSED));
|
| + }
|
| + };
|
| +
|
| + bridge.onItemsAvailable();
|
| + for (int i = 0; i < items.size(); i++) bridge.onItemUpdated(items.get(i));
|
| +
|
| + verify(mProvider, times(1)).getVisualsForItem(items.get(0).id, bridge);
|
| + verify(mProvider, times(1)).getVisualsForItem(items.get(1).id, bridge);
|
| + verify(mProvider, times(1)).getVisualsForItem(items.get(2).id, bridge);
|
| + verify(mProvider, never()).getVisualsForItem(items.get(3).id, bridge);
|
| + verify(mProvider, times(1)).getVisualsForItem(items.get(4).id, bridge);
|
| + verify(mProvider, times(1)).getVisualsForItem(items.get(5).id, bridge);
|
| + verify(mProvider, times(1)).getVisualsForItem(items.get(6).id, bridge);
|
| +
|
| + for (int i = 0; i < items.size(); i++) {
|
| + bridge.onVisualsAvailable(items.get(i).id, new OfflineItemVisuals());
|
| + }
|
| +
|
| + verify(mNotifier, times(1))
|
| + .notifyDownloadProgress(argThat(new DownloadInfoIdMatcher(items.get(0).id)),
|
| + ArgumentMatchers.anyLong(), ArgumentMatchers.anyBoolean());
|
| + verify(mNotifier, times(1))
|
| + .notifyDownloadSuccessful(argThat(new DownloadInfoIdMatcher(items.get(2).id)),
|
| + ArgumentMatchers.anyLong(), ArgumentMatchers.anyBoolean(),
|
| + ArgumentMatchers.anyBoolean());
|
| + verify(mNotifier, times(1))
|
| + .notifyDownloadCanceled(items.get(3).id /* OfflineItemState.CANCELLED */);
|
| + verify(mNotifier, times(1))
|
| + .notifyDownloadInterrupted(argThat(new DownloadInfoIdMatcher(items.get(4).id)),
|
| + ArgumentMatchers.anyBoolean());
|
| + verify(mNotifier, times(1))
|
| + .notifyDownloadFailed(argThat(new DownloadInfoIdMatcher(items.get(5).id)));
|
| + verify(mNotifier, times(1))
|
| + .notifyDownloadPaused(argThat(new DownloadInfoIdMatcher(items.get(6).id)));
|
| +
|
| + bridge.destroy();
|
| + verify(mProvider, times(1)).removeObserver(bridge);
|
| + }
|
| +
|
| + @Test
|
| + public void testNullVisuals() {
|
| + OfflineContentAggregatorNotificationBridgeUi bridge =
|
| + new OfflineContentAggregatorNotificationBridgeUi(mProvider, mNotifier);
|
| + verify(mProvider, times(1)).addObserver(bridge);
|
| +
|
| + OfflineItem item1 = buildOfflineItem(new ContentId("1", "A"), OfflineItemState.IN_PROGRESS);
|
| + OfflineItem item2 = buildOfflineItem(new ContentId("2", "B"), OfflineItemState.IN_PROGRESS);
|
| +
|
| + OfflineItemVisuals visuals1 = new OfflineItemVisuals();
|
| + visuals1.icon = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8);
|
| +
|
| + bridge.onItemsAvailable();
|
| + bridge.onItemUpdated(item1);
|
| + bridge.onItemUpdated(item2);
|
| +
|
| + verify(mProvider, times(1)).getVisualsForItem(item1.id, bridge);
|
| + verify(mProvider, times(1)).getVisualsForItem(item2.id, bridge);
|
| +
|
| + ArgumentCaptor<DownloadInfo> captor = ArgumentCaptor.forClass(DownloadInfo.class);
|
| +
|
| + bridge.onVisualsAvailable(item1.id, visuals1);
|
| + bridge.onVisualsAvailable(item2.id, null);
|
| + verify(mNotifier, times(2))
|
| + .notifyDownloadProgress(captor.capture(), ArgumentMatchers.anyLong(),
|
| + ArgumentMatchers.anyBoolean());
|
| +
|
| + List<DownloadInfo> capturedInfo = captor.getAllValues();
|
| + Assert.assertEquals(item1.id, capturedInfo.get(0).getContentId());
|
| + Assert.assertEquals(visuals1.icon, capturedInfo.get(0).getIcon());
|
| + Assert.assertEquals(item2.id, capturedInfo.get(1).getContentId());
|
| + Assert.assertEquals(null, capturedInfo.get(1).getIcon());
|
| +
|
| + bridge.destroy();
|
| + verify(mProvider, times(1)).removeObserver(bridge);
|
| + }
|
| +
|
| + @Test
|
| + public void testRemovedItemsGetRemovedFromTheUi() {
|
| + OfflineContentAggregatorNotificationBridgeUi bridge =
|
| + new OfflineContentAggregatorNotificationBridgeUi(mProvider, mNotifier);
|
| + verify(mProvider, times(1)).addObserver(bridge);
|
| +
|
| + ContentId id = new ContentId("1", "A");
|
| +
|
| + bridge.onItemsAvailable();
|
| + bridge.onItemRemoved(id);
|
| + verify(mNotifier, times(1)).notifyDownloadCanceled(id);
|
| +
|
| + bridge.destroy();
|
| + verify(mProvider, times(1)).removeObserver(bridge);
|
| + }
|
| +
|
| + @Test
|
| + public void testRemovedItemsIgnoreVisualsCallback() {
|
| + OfflineContentAggregatorNotificationBridgeUi bridge =
|
| + new OfflineContentAggregatorNotificationBridgeUi(mProvider, mNotifier);
|
| + verify(mProvider, times(1)).addObserver(bridge);
|
| +
|
| + OfflineItem item = buildOfflineItem(new ContentId("1", "A"), OfflineItemState.IN_PROGRESS);
|
| +
|
| + bridge.onItemsAvailable();
|
| + bridge.onItemUpdated(item);
|
| + verify(mProvider, times(1)).getVisualsForItem(item.id, bridge);
|
| +
|
| + bridge.onItemRemoved(item.id);
|
| + bridge.onVisualsAvailable(item.id, new OfflineItemVisuals());
|
| + InOrder order = inOrder(mNotifier);
|
| + order.verify(mNotifier, times(1)).notifyDownloadCanceled(item.id);
|
| + order.verifyNoMoreInteractions();
|
| +
|
| + bridge.destroy();
|
| + verify(mProvider, times(1)).removeObserver(bridge);
|
| + }
|
| +
|
| + @Test
|
| + public void testOnlyRequestsVisualsOnceForMultipleUpdates() {
|
| + OfflineContentAggregatorNotificationBridgeUi bridge =
|
| + new OfflineContentAggregatorNotificationBridgeUi(mProvider, mNotifier);
|
| + verify(mProvider, times(1)).addObserver(bridge);
|
| +
|
| + OfflineItem item = buildOfflineItem(new ContentId("1", "A"), OfflineItemState.IN_PROGRESS);
|
| +
|
| + bridge.onItemsAvailable();
|
| + bridge.onItemUpdated(item);
|
| + bridge.onItemUpdated(item);
|
| + verify(mProvider, times(1)).getVisualsForItem(item.id, bridge);
|
| +
|
| + bridge.destroy();
|
| + verify(mProvider, times(1)).removeObserver(bridge);
|
| + }
|
| +
|
| + @Test
|
| + public void testVisualsAreCachedForInterestingItems() {
|
| + OfflineContentAggregatorNotificationBridgeUi bridge =
|
| + new OfflineContentAggregatorNotificationBridgeUi(mProvider, mNotifier);
|
| + verify(mProvider, times(1)).addObserver(bridge);
|
| +
|
| + ArrayList<OfflineItem> interestingItems = new ArrayList<OfflineItem>() {
|
| + {
|
| + add(buildOfflineItem(new ContentId("1", "A"), OfflineItemState.IN_PROGRESS));
|
| + add(buildOfflineItem(new ContentId("2", "B"), OfflineItemState.PENDING));
|
| + add(buildOfflineItem(new ContentId("5", "E"), OfflineItemState.INTERRUPTED));
|
| + add(buildOfflineItem(new ContentId("7", "G"), OfflineItemState.PAUSED));
|
| + }
|
| + };
|
| +
|
| + ArrayList<OfflineItem> uninterestingItems = new ArrayList<OfflineItem>() {
|
| + {
|
| + add(buildOfflineItem(new ContentId("3", "C"), OfflineItemState.COMPLETE));
|
| + add(buildOfflineItem(new ContentId("6", "F"), OfflineItemState.FAILED));
|
| + }
|
| + };
|
| +
|
| + bridge.onItemsAvailable();
|
| +
|
| + for (int i = 0; i < interestingItems.size(); i++) {
|
| + OfflineItem item = interestingItems.get(i);
|
| + bridge.onItemUpdated(item);
|
| + bridge.onVisualsAvailable(item.id, null);
|
| + bridge.onItemUpdated(item);
|
| + verify(mProvider, times(1)).getVisualsForItem(item.id, bridge);
|
| + verify(mNotifier, times(2))
|
| + .notifyDownloadProgress(ArgumentMatchers.any(), ArgumentMatchers.anyLong(),
|
| + ArgumentMatchers.anyBoolean());
|
| + }
|
| +
|
| + for (int i = 0; i < uninterestingItems.size(); i++) {
|
| + OfflineItem item = uninterestingItems.get(i);
|
| + bridge.onItemUpdated(item);
|
| + bridge.onVisualsAvailable(item.id, null);
|
| + bridge.onItemUpdated(item);
|
| + verify(mProvider, times(2)).getVisualsForItem(item.id, bridge);
|
| + }
|
| +
|
| + bridge.destroy();
|
| + verify(mProvider, times(1)).removeObserver(bridge);
|
| + }
|
| +
|
| + @Test
|
| + public void testVisualsGetClearedForUninterestingItems() {
|
| + OfflineContentAggregatorNotificationBridgeUi bridge =
|
| + new OfflineContentAggregatorNotificationBridgeUi(mProvider, mNotifier);
|
| + verify(mProvider, times(1)).addObserver(bridge);
|
| +
|
| + ContentId id = new ContentId("1", "A");
|
| + OfflineItem item1 = buildOfflineItem(id, OfflineItemState.IN_PROGRESS);
|
| + OfflineItem item2 = buildOfflineItem(id, OfflineItemState.FAILED);
|
| + OfflineItem item3 = buildOfflineItem(id, OfflineItemState.IN_PROGRESS);
|
| +
|
| + bridge.onItemsAvailable();
|
| + bridge.onItemUpdated(item1);
|
| + bridge.onVisualsAvailable(item1.id, new OfflineItemVisuals());
|
| + bridge.onItemUpdated(item2);
|
| + bridge.onItemUpdated(item3);
|
| + bridge.onVisualsAvailable(item1.id, new OfflineItemVisuals());
|
| + verify(mProvider, times(2)).getVisualsForItem(id, bridge);
|
| +
|
| + bridge.destroy();
|
| + verify(mProvider, times(1)).removeObserver(bridge);
|
| + }
|
| +}
|
|
|