chromium/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarCollectionUnitTest.java

// Copyright 2016 The Chromium Authors
// 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.ui.messages.snackbar;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;

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.ui.messages.snackbar.SnackbarManager.SnackbarController;

/** Tests for {@link SnackbarCollection}. */
@RunWith(BlockJUnit4ClassRunner.class)
public class SnackbarCollectionUnitTest {
    private static final String ACTION_TITLE = "stack";
    private static final String NOTIFICATION_TITLE = "queue";

    @Mock private SnackbarController mMockController;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    @Feature({"Browser", "Snackbar"})
    public void testActionCoversNotification() {
        SnackbarCollection collection = new SnackbarCollection();
        assertTrue(collection.isEmpty());

        Snackbar notiBar = makeNotificationSnackbar();
        collection.add(notiBar);
        assertFalse(collection.isEmpty());
        assertEquals(notiBar, collection.getCurrent());

        Snackbar actionBar = makeActionSnackbar();
        collection.add(actionBar);
        verify(mMockController, times(1)).onDismissNoAction(null);
        assertFalse(collection.isEmpty());
        assertEquals(
                "Notification snackbar should not cover action snackbar!",
                actionBar,
                collection.getCurrent());

        collection.removeCurrentDueToAction();
        verify(mMockController, times(1)).onAction(null);
        assertTrue(collection.isEmpty());
    }

    @Test
    @Feature({"Browser", "Snackbar"})
    public void testNotificationGoesUnderAction() {
        SnackbarCollection collection = new SnackbarCollection();
        assertTrue(collection.isEmpty());

        Snackbar actionBar = makeActionSnackbar();
        collection.add(actionBar);
        assertFalse(collection.isEmpty());
        assertEquals(actionBar, collection.getCurrent());

        Snackbar notiBar = makeNotificationSnackbar();
        collection.add(notiBar);
        verify(mMockController, times(0)).onDismissNoAction(null);
        assertFalse(collection.isEmpty());
        assertEquals(
                "Action snackbar should not be covered by notification snackbars!",
                actionBar,
                collection.getCurrent());

        collection.removeCurrentDueToAction();
        verify(mMockController, times(1)).onAction(null);
        assertFalse(collection.isEmpty());
        assertEquals(notiBar, collection.getCurrent());

        collection.removeCurrentDueToAction();
        verify(mMockController, times(2)).onAction(null);
        assertTrue(collection.isEmpty());
    }

    @Test
    @Feature({"Browser", "Snackbar"})
    public void testClear() {
        SnackbarCollection collection = new SnackbarCollection();
        for (int i = 0; i < 3; i++) {
            collection.add(makeActionSnackbar());
            collection.add(makeNotificationSnackbar());
        }
        assertFalse(collection.isEmpty());

        collection.clear();
        assertTrue(collection.isEmpty());
    }

    @Test
    @Feature({"Browser", "Snackbar"})
    public void testRemoveMatchingSnackbars() {
        SnackbarCollection collection = new SnackbarCollection();
        for (int i = 0; i < 3; i++) {
            collection.add(makeActionSnackbar());
            collection.add(makeNotificationSnackbar());
        }
        SnackbarController anotherController = mock(SnackbarController.class);
        for (int i = 0; i < 3; i++) {
            collection.add(makeActionSnackbar(anotherController));
            collection.add(makeNotificationSnackbar(anotherController));
        }

        collection.removeMatchingSnackbars(mMockController);
        while (!collection.isEmpty()) {
            Snackbar removed = collection.removeCurrentDueToAction();
            assertEquals(anotherController, removed.getController());
        }
    }

    @Test
    @Feature({"Browser", "Snackbar"})
    public void testRemoveMatchingSnackbarsWithData() {
        SnackbarCollection collection = new SnackbarCollection();
        for (int i = 0; i < 3; i++) {
            collection.add(makeActionSnackbar().setAction(ACTION_TITLE, i));
            collection.add(makeNotificationSnackbar().setAction(NOTIFICATION_TITLE, i));
        }
        SnackbarController anotherController = mock(SnackbarController.class);
        for (int i = 0; i < 3; i++) {
            collection.add(makeActionSnackbar(anotherController).setAction(ACTION_TITLE, i));
            collection.add(
                    makeNotificationSnackbar(anotherController).setAction(NOTIFICATION_TITLE, i));
        }

        final Integer dataToRemove = 0;
        collection.removeMatchingSnackbars(mMockController, dataToRemove);
        while (!collection.isEmpty()) {
            Snackbar removed = collection.removeCurrentDueToAction();
            assertFalse(
                    mMockController == removed.getController()
                            && dataToRemove.equals(removed.getActionData()));
        }
    }

    // This test is added as a result of crbug.com/1258303.
    // Test that the action/dismiss callbacks are not invoked when the controller is null.
    @Test
    @Feature({"Browser", "Snackbar"})
    public void testRemoveCurrent_ControllerNotSpecified() {
        SnackbarCollection collection = new SnackbarCollection();
        assertTrue(collection.isEmpty());

        Snackbar snackbar =
                Snackbar.make(
                        NOTIFICATION_TITLE,
                        null,
                        Snackbar.TYPE_NOTIFICATION,
                        Snackbar.UMA_TEST_SNACKBAR);
        collection.add(snackbar);
        assertFalse("Snackbar collection should contain a snackbar.", collection.isEmpty());
        assertEquals(
                "The currently displayed snackbar is incorrect.",
                snackbar,
                collection.getCurrent());
        collection.removeCurrentDueToTimeout();
        verifyNoMoreInteractions(mMockController);
    }

    private Snackbar makeActionSnackbar(SnackbarController controller) {
        return Snackbar.make(
                ACTION_TITLE, controller, Snackbar.TYPE_ACTION, Snackbar.UMA_TEST_SNACKBAR);
    }

    private Snackbar makeNotificationSnackbar(SnackbarController controller) {
        return Snackbar.make(
                NOTIFICATION_TITLE,
                controller,
                Snackbar.TYPE_NOTIFICATION,
                Snackbar.UMA_TEST_SNACKBAR);
    }

    private Snackbar makeActionSnackbar() {
        return makeActionSnackbar(mMockController);
    }

    private Snackbar makeNotificationSnackbar() {
        return makeNotificationSnackbar(mMockController);
    }
}