blob: 37b99934992dab04fad94546fc81292f87e9397d [file] [log] [blame]
// Copyright 2022 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.interstitial;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.doAnswer;
import static org.chromium.chrome.browser.download.interstitial.DownloadInterstitialProperties.DOWNLOAD_ITEM;
import static org.chromium.chrome.browser.download.interstitial.DownloadInterstitialProperties.STATE;
import android.support.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.chromium.base.test.util.Feature;
import org.chromium.chrome.browser.download.home.StubbedOfflineContentProvider;
import org.chromium.chrome.browser.download.home.list.ListProperties;
import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
import org.chromium.components.offline_items_collection.ContentId;
import org.chromium.components.offline_items_collection.OfflineItem;
import org.chromium.components.offline_items_collection.OfflineItemProgressUnit;
import org.chromium.components.offline_items_collection.OfflineItemState;
import org.chromium.components.offline_items_collection.OpenParams;
import org.chromium.ui.modelutil.PropertyModel;
/**
* Unit tests for the {@link DownloadInterstitialMediator}. Modifies the page state through the
* {@link PropertyModel} and observes changes to the mediator/model.
*/
@RunWith(BlockJUnit4ClassRunner.class)
public class DownloadInterstitialMediatorTest {
private static final String DOWNLOAD_BUTTON_TEXT = "Download";
private static final String CANCEL_BUTTON_TEXT = "Cancel";
private static final String RESUME_BUTTON_TEXT = "Resume";
private static final String OPEN_BUTTON_TEXT = "Open";
private static final String DELETE_BUTTON_TEXT = "Delete";
@Mock
private SnackbarManager mSnackbarManager;
private final TestOfflineContentProvider mProvider = new TestOfflineContentProvider();
private DownloadInterstitialMediator mMediator;
private PropertyModel mModel;
private OfflineItem mItem0;
private boolean mSnackbarShown;
@Before
public void before() {
MockitoAnnotations.initMocks(this);
mSnackbarShown = false;
doAnswer((invocation) -> mSnackbarShown = true)
.when(mSnackbarManager)
.showSnackbar(isA(Snackbar.class));
SharedPreferencesManager sharedPrefsManager = SharedPreferencesManager.getInstance();
sharedPrefsManager.disableKeyCheckerForTesting();
mItem0 = createOfflineItem("item0");
mModel = new PropertyModel.Builder(DownloadInterstitialProperties.ALL_KEYS).build();
// Set the initial button texts. This is usually done in DownloadInterstitialView.
mModel.set(DownloadInterstitialProperties.PRIMARY_BUTTON_TEXT, "");
mModel.set(DownloadInterstitialProperties.SECONDARY_BUTTON_TEXT, CANCEL_BUTTON_TEXT);
mProvider.addItem(mItem0);
mMediator = new DownloadInterstitialMediator(InstrumentationRegistry::getContext, mModel,
mItem0.originalUrl, mProvider, mSnackbarManager, sharedPrefsManager);
// Increment progress to trigger onItemUpdated method for OfflineContentProvider observers.
// This attaches the OfflineItem to the mediator.
mProvider.incrementProgress(mItem0.id);
}
@Test
@SmallTest
@Feature({"NewDownloadTab"})
public void testItemIsAttached() {
assertEquals(mItem0, mModel.get(DOWNLOAD_ITEM));
}
@Test
@SmallTest
@Feature({"NewDownloadTab"})
public void testSecondDownloadNotAttached() {
OfflineItem item1 = createOfflineItem("item1");
item1.originalUrl = "www.bar.com";
mProvider.addItem(item1);
mProvider.incrementProgress(item1.id);
assertEquals(mItem0, mModel.get(DOWNLOAD_ITEM));
}
@Test
@SmallTest
@Feature({"NewDownloadTab"})
public void testInProgressDownloadNotAttached() {
OfflineItem item1 = createOfflineItem("item1");
item1.originalUrl = "www.bar.com";
// Remove observer so that the mediator can attach its own observer.
mProvider.setObserver(null);
mModel.set(DOWNLOAD_ITEM, null);
mMediator = new DownloadInterstitialMediator(InstrumentationRegistry::getContext, mModel,
item1.originalUrl, mProvider, mSnackbarManager,
SharedPreferencesManager.getInstance());
mProvider.incrementProgress(mItem0.id);
mProvider.addItem(item1);
mProvider.incrementProgress(item1.id);
assertEquals(item1.id.id, mModel.get(DOWNLOAD_ITEM).id.id);
}
@Test
@SmallTest
@Feature({"NewDownloadTab"})
public void testInProgressItemIsCancelled() {
assertEquals(OfflineItemState.IN_PROGRESS, mModel.get(DOWNLOAD_ITEM).state);
clickButtonWithText(CANCEL_BUTTON_TEXT);
assertEquals(DownloadInterstitialProperties.State.CANCELLED, mModel.get(STATE));
assertNotEquals(OfflineItemState.IN_PROGRESS, mModel.get(DOWNLOAD_ITEM).state);
}
@Test
@SmallTest
@Feature({"NewDownloadTab"})
public void testInProgressReDownload() {
assertEquals(OfflineItemState.IN_PROGRESS, mModel.get(DOWNLOAD_ITEM).state);
clickButtonWithText(CANCEL_BUTTON_TEXT);
clickButtonWithText(DOWNLOAD_BUTTON_TEXT);
assertEquals(DownloadInterstitialProperties.State.IN_PROGRESS, mModel.get(STATE));
assertEquals(OfflineItemState.IN_PROGRESS, mModel.get(DOWNLOAD_ITEM).state);
}
@Test
@SmallTest
@Feature({"NewDownloadTab"})
public void testInProgressPauseDownload() {
assertEquals(OfflineItemState.IN_PROGRESS, mModel.get(DOWNLOAD_ITEM).state);
mModel.get(ListProperties.CALLBACK_PAUSE).onResult(mModel.get(DOWNLOAD_ITEM));
assertEquals(DownloadInterstitialProperties.State.PAUSED, mModel.get(STATE));
assertEquals(OfflineItemState.PAUSED, mModel.get(DOWNLOAD_ITEM).state);
}
@Test
@SmallTest
@Feature({"NewDownloadTab"})
public void testInProgressResumeDownload() {
assertEquals(OfflineItemState.IN_PROGRESS, mModel.get(DOWNLOAD_ITEM).state);
mModel.get(ListProperties.CALLBACK_PAUSE).bind(mModel.get(DOWNLOAD_ITEM));
clickButtonWithText(RESUME_BUTTON_TEXT);
assertEquals(DownloadInterstitialProperties.State.IN_PROGRESS, mModel.get(STATE));
assertEquals(OfflineItemState.IN_PROGRESS, mModel.get(DOWNLOAD_ITEM).state);
}
@Test
@SmallTest
@Feature({"NewDownloadTab"})
public void testCancelledDownloadIsDeletedAfterClose() {
assertEquals(OfflineItemState.IN_PROGRESS, mModel.get(DOWNLOAD_ITEM).state);
clickButtonWithText(CANCEL_BUTTON_TEXT);
mMediator.destroy();
assertFalse(mProvider.getItems().contains(mModel.get(DOWNLOAD_ITEM)));
}
@Test
@SmallTest
@Feature({"NewDownloadTab"})
public void testOpenDownload() {
mProvider.completeDownload(mModel.get(DOWNLOAD_ITEM).id);
assertEquals(OfflineItemState.COMPLETE, mModel.get(DOWNLOAD_ITEM).state);
clickButtonWithText(OPEN_BUTTON_TEXT);
assertEquals(mModel.get(DOWNLOAD_ITEM).id, mProvider.mLastOpenedDownload);
}
@Test
@SmallTest
@Feature({"NewDownloadTab"})
public void testDeleteDownload() {
mProvider.completeDownload(mModel.get(DOWNLOAD_ITEM).id);
assertEquals(OfflineItemState.COMPLETE, mModel.get(DOWNLOAD_ITEM).state);
clickButtonWithText(DELETE_BUTTON_TEXT);
assertTrue(mSnackbarShown);
assertEquals(DownloadInterstitialProperties.State.CANCELLED, mModel.get(STATE));
}
@Test
@SmallTest
@Feature({"NewDownloadTab"})
public void testReDownloadDeletedDownload() {
mProvider.completeDownload(mModel.get(DOWNLOAD_ITEM).id);
assertEquals(OfflineItemState.COMPLETE, mModel.get(DOWNLOAD_ITEM).state);
clickButtonWithText(DELETE_BUTTON_TEXT);
clickButtonWithText(DOWNLOAD_BUTTON_TEXT);
assertEquals(DownloadInterstitialProperties.State.SUCCESSFUL, mModel.get(STATE));
assertTrue(mProvider.getItems().contains(mModel.get(DOWNLOAD_ITEM)));
}
@Test
@SmallTest
@Feature({"NewDownloadTab"})
public void testDeletedDownloadIsRemovedAfterClose() {
mProvider.completeDownload(mModel.get(DOWNLOAD_ITEM).id);
assertEquals(OfflineItemState.COMPLETE, mModel.get(DOWNLOAD_ITEM).state);
clickButtonWithText(DELETE_BUTTON_TEXT);
mMediator.destroy();
assertFalse(mProvider.getItems().contains(mModel.get(DOWNLOAD_ITEM)));
}
private void clickButtonWithText(String text) {
if (mModel.get(DownloadInterstitialProperties.PRIMARY_BUTTON_TEXT).equals(text)) {
mModel.get(DownloadInterstitialProperties.PRIMARY_BUTTON_CALLBACK)
.onResult(mModel.get(DOWNLOAD_ITEM));
} else if (mModel.get(DownloadInterstitialProperties.SECONDARY_BUTTON_TEXT).equals(text)) {
mModel.get(DownloadInterstitialProperties.SECONDARY_BUTTON_CALLBACK)
.onResult(mModel.get(DOWNLOAD_ITEM));
}
}
private static OfflineItem createOfflineItem(String id) {
OfflineItem item = new OfflineItem();
item.id = new ContentId("test", id);
item.progress = new OfflineItem.Progress(0L, 10L, OfflineItemProgressUnit.BYTES);
item.state = OfflineItemState.IN_PROGRESS;
item.title = "Test Item";
item.description = "Test Description";
item.originalUrl = "www.foo.com";
return item;
}
/**
* Extends {@link StubbedOfflineContentProvider} to add some logic to some of the no-op methods
* for testing.
*/
private static class TestOfflineContentProvider extends StubbedOfflineContentProvider {
private ContentId mLastOpenedDownload;
/** Called to increment the progress of an offline item and notify observers. */
public void incrementProgress(ContentId id) {
OfflineItem item = findItem(id);
item.progress = new OfflineItem.Progress(
item.progress.value + 1, item.progress.max, item.progress.unit);
if (item.progress.value == item.progress.max) {
item.state = OfflineItemState.COMPLETE;
}
notifyObservers(id);
}
/**
* Called to complete the progress of an offline item, update its state and notify
* observers.
*/
public void completeDownload(ContentId id) {
OfflineItem item = findItem(id);
item.progress = new OfflineItem.Progress(
item.progress.max, item.progress.max, item.progress.unit);
item.state = OfflineItemState.COMPLETE;
notifyObservers(id);
}
@Override
public void openItem(OpenParams openParams, ContentId id) {
mLastOpenedDownload = id;
}
@Override
public void pauseDownload(ContentId id) {
findItem(id).state = OfflineItemState.PAUSED;
notifyObservers(id);
}
@Override
public void resumeDownload(ContentId id, boolean hasUserGesture) {
if (findItem(id).state != OfflineItemState.COMPLETE) {
findItem(id).state = OfflineItemState.IN_PROGRESS;
}
notifyObservers(id);
}
@Override
public void cancelDownload(ContentId id) {
findItem(id).state = OfflineItemState.CANCELLED;
removeItem(id);
notifyObservers(id);
}
}
}