1bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes/*
2bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes * Copyright (C) 2016 The Android Open Source Project
3bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes *
4bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes * Licensed under the Apache License, Version 2.0 (the "License");
5bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes * you may not use this file except in compliance with the License.
6bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes * You may obtain a copy of the License at
7bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes *
8bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes *      http://www.apache.org/licenses/LICENSE-2.0
9bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes *
10bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes * Unless required by applicable law or agreed to in writing, software
11bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes * distributed under the License is distributed on an "AS IS" BASIS,
12bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes * See the License for the specific language governing permissions and
14bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes * limitations under the License.
15bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes */
16bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes
17bfd48d0521963754e04e407499ee9e278fe06c0fChris Banespackage android.support.design.widget;
18bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes
19754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static android.support.design.testutils.TestUtilsActions.setLayoutDirection;
20754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static android.support.test.espresso.Espresso.onView;
21754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static android.support.test.espresso.action.ViewActions.click;
22754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static android.support.test.espresso.action.ViewActions.swipeLeft;
23754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static android.support.test.espresso.action.ViewActions.swipeRight;
248c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikovimport static android.support.test.espresso.assertion.ViewAssertions.matches;
25754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom;
26754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static android.support.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
27754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static android.support.test.espresso.matcher.ViewMatchers.isDescendantOfA;
28754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static android.support.test.espresso.matcher.ViewMatchers.withId;
29754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static android.support.test.espresso.matcher.ViewMatchers.withText;
30754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikas
31754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static org.hamcrest.core.AllOf.allOf;
328c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikovimport static org.junit.Assert.assertFalse;
338c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikovimport static org.junit.Assert.assertTrue;
34754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static org.mockito.Matchers.any;
35754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static org.mockito.Mockito.mock;
368c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikovimport static org.mockito.Mockito.never;
37ca9c74379e9fb2b38965253836a2ab0e36990c45Kirill Grouchnikovimport static org.mockito.Mockito.spy;
38754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static org.mockito.Mockito.times;
39754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static org.mockito.Mockito.verify;
40754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static org.mockito.Mockito.verifyNoMoreInteractions;
41754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikas
42c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikovimport android.content.res.Resources;
43c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikovimport android.support.annotation.Nullable;
44c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikovimport android.support.annotation.StringRes;
45bfd48d0521963754e04e407499ee9e278fe06c0fChris Banesimport android.support.design.test.R;
463a8340d4a090bc8ab7ad3a774fb6d999e7384301Kirill Grouchnikovimport android.support.design.testutils.SnackbarUtils;
47bfd48d0521963754e04e407499ee9e278fe06c0fChris Banesimport android.support.test.espresso.ViewAction;
48bfd48d0521963754e04e407499ee9e278fe06c0fChris Banesimport android.support.test.espresso.ViewInteraction;
49e855c308ce795c6ac382b94670c264fc368ba882Chris Banesimport android.support.test.espresso.action.CoordinatesProvider;
50e855c308ce795c6ac382b94670c264fc368ba882Chris Banesimport android.support.test.espresso.action.GeneralSwipeAction;
51e855c308ce795c6ac382b94670c264fc368ba882Chris Banesimport android.support.test.espresso.action.Press;
52e855c308ce795c6ac382b94670c264fc368ba882Chris Banesimport android.support.test.espresso.action.Swipe;
53e6cf359406cd7baaa0659b54c1b7d8ac45db122aAurimas Liutikasimport android.support.test.filters.LargeTest;
54754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport android.support.test.filters.MediumTest;
55c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikovimport android.support.v4.view.ViewCompat;
56c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikovimport android.text.TextUtils;
57bfd48d0521963754e04e407499ee9e278fe06c0fChris Banesimport android.view.View;
58754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikas
597b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikovimport org.junit.Before;
60ee3e8053ef6b55e31fa0be004061318ec394eb64Kirill Grouchnikovimport org.junit.Test;
61bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes
624bb57b2c7c5e8fa607119bd5089535d5862cb979Aurimas Liutikas@MediumTest
637b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikovpublic class SnackbarTest extends BaseInstrumentationTestCase<SnackbarActivity> {
64bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes    private static final String MESSAGE_TEXT = "Test Message";
65c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov    private static final @StringRes int MESSAGE_ID = R.string.snackbar_text;
66bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes    private static final String ACTION_TEXT = "Action";
67c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov    private static final @StringRes int ACTION_ID = R.string.snackbar_action;
68bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes
697b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov    private CoordinatorLayout mCoordinatorLayout;
707b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov
71b6b4a30c2832e00e4d471665471748f0cb8143bcChris Banes    private interface DismissAction {
72c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        void dismiss(Snackbar snackbar);
73c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov    }
74c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov
757b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov    public SnackbarTest() {
767b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov        super(SnackbarActivity.class);
777b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov    }
787b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov
797b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov    @Before
807b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov    public void setup() {
817b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov        mCoordinatorLayout =
827b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov                (CoordinatorLayout) mActivityTestRule.getActivity().findViewById(R.id.col);
837b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov    }
847b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov
85c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov    private void verifySnackbarContent(final Snackbar snackbar, final String expectedMessage,
868c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov            final String expectedAction) throws Throwable {
873a8340d4a090bc8ab7ad3a774fb6d999e7384301Kirill Grouchnikov        // Show the snackbar
888da7b24b08afba7ec155a371117df018bcc25eefKirill Grouchnikov        SnackbarUtils.showTransientBottomBarAndWaitUntilFullyShown(snackbar);
89c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov
90c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        // Verify that we're showing the message
91c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        withText(expectedMessage).matches(allOf(
92c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                isDescendantOfA(isAssignableFrom(Snackbar.SnackbarLayout.class)),
93c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                isCompletelyDisplayed()));
94c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov
95c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        // If the action is not empty, verify that we're showing it
96c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        if (!TextUtils.isEmpty(expectedAction)) {
97c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov            withText(expectedAction).matches(allOf(
98c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                    isDescendantOfA(isAssignableFrom(Snackbar.SnackbarLayout.class)),
99c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                    isCompletelyDisplayed()));
100c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        }
101c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov
102c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        // Dismiss the snackbar
1038da7b24b08afba7ec155a371117df018bcc25eefKirill Grouchnikov        SnackbarUtils.dismissTransientBottomBarAndWaitUntilFullyDismissed(snackbar);
104c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov    }
105c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov
106e6cf359406cd7baaa0659b54c1b7d8ac45db122aAurimas Liutikas    @LargeTest
107c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov    @Test
1088c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov    public void testBasicContent() throws Throwable {
109c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        // Verify different combinations of snackbar content (message and action) and duration
110c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov
111c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        final Resources res = mActivityTestRule.getActivity().getResources();
112c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        final String resolvedMessage = res.getString(MESSAGE_ID);
113c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        final String resolvedAction = res.getString(ACTION_ID);
114c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov
115c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        // String message and no action
116c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        verifySnackbarContent(
117c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                Snackbar.make(mCoordinatorLayout, MESSAGE_TEXT, Snackbar.LENGTH_SHORT),
118c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                MESSAGE_TEXT, null);
119c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov
120c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        // Resource message and no action
121c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        verifySnackbarContent(
122c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                Snackbar.make(mCoordinatorLayout, MESSAGE_ID, Snackbar.LENGTH_LONG),
123c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                resolvedMessage, null);
124c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov
125c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        // String message and string action
126c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        verifySnackbarContent(
127c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                Snackbar.make(mCoordinatorLayout, MESSAGE_TEXT, Snackbar.LENGTH_INDEFINITE)
128c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                        .setAction(ACTION_TEXT, mock(View.OnClickListener.class)),
129c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                MESSAGE_TEXT, ACTION_TEXT);
130c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov
131c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        // String message and resource action
132c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        verifySnackbarContent(
133c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                Snackbar.make(mCoordinatorLayout, MESSAGE_TEXT, Snackbar.LENGTH_SHORT)
134c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                        .setAction(ACTION_ID, mock(View.OnClickListener.class)),
135c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                MESSAGE_TEXT, resolvedAction);
136c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov
137c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        // Resource message and resource action
138c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        verifySnackbarContent(
139c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                Snackbar.make(mCoordinatorLayout, MESSAGE_ID, Snackbar.LENGTH_LONG)
140c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                        .setAction(ACTION_ID, mock(View.OnClickListener.class)),
141c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                resolvedMessage, resolvedAction);
142c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov    }
143c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov
144c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov    private void verifyDismissCallback(final ViewInteraction interaction,
145c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov            final @Nullable ViewAction action, final @Nullable DismissAction dismissAction,
14642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas            final int length, @Snackbar.Callback.DismissEvent final int expectedEvent)
14742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas            throws Throwable {
148ca9c74379e9fb2b38965253836a2ab0e36990c45Kirill Grouchnikov        final BaseTransientBottomBar.BaseCallback mockCallback =
149ca9c74379e9fb2b38965253836a2ab0e36990c45Kirill Grouchnikov                mock(BaseTransientBottomBar.BaseCallback.class);
1507b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov        final Snackbar snackbar = Snackbar.make(mCoordinatorLayout, MESSAGE_TEXT, length)
1517b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov                .setAction(ACTION_TEXT, mock(View.OnClickListener.class))
1528c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                .addCallback(mockCallback);
1537b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov
1548c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        // Show the snackbar
1558c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        SnackbarUtils.showTransientBottomBarAndWaitUntilFullyShown(snackbar);
1568c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        // Verify that our onShown has been called
1578c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        verify(mockCallback, times(1)).onShown(snackbar);
1588c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        // and that the snackbar is either shown or queued to be shown
1598c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        assertTrue(snackbar.isShownOrQueued());
1608c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        // and also check that we have the intended message / action displayed somewhere in
1618c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        // our hierarchy
1628c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        onView(withText(MESSAGE_TEXT)).check(matches(isCompletelyDisplayed()));
1638c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        onView(withText(ACTION_TEXT)).check(matches(isCompletelyDisplayed()));
1643a8340d4a090bc8ab7ad3a774fb6d999e7384301Kirill Grouchnikov
1653a8340d4a090bc8ab7ad3a774fb6d999e7384301Kirill Grouchnikov        // Now perform the UI interaction
1668c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        SnackbarUtils.performActionAndWaitUntilFullyDismissed(snackbar,
1678c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                new SnackbarUtils.TransientBottomBarAction() {
1688c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                    @Override
1698c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                    public void perform() throws Throwable {
1708c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                        if (action != null) {
1718c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                            interaction.perform(action);
1728c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                        } else if (dismissAction != null) {
1738c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                            mActivityTestRule.runOnUiThread(new Runnable() {
1748c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                                @Override
1758c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                                public void run() {
1768c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                                    dismissAction.dismiss(snackbar);
1778c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                                }
1788c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                            });
1798c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                        }
1808c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                    }
1818c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                });
1828c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov
1838c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        // Verify that our onDismissed has been called
1847b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov        verify(mockCallback, times(1)).onDismissed(snackbar, expectedEvent);
1857b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov        verifyNoMoreInteractions(mockCallback);
1868c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        // and that the snackbar is neither shown nor queued to be shown
1878c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        assertFalse(snackbar.isShownOrQueued());
188bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes    }
189bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes
190bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes    @Test
19142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas    public void testDismissViaActionClick() throws Throwable {
1927b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov        verifyDismissCallback(
193bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes                onView(withId(R.id.snackbar_action)),
194c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                click(),
195c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                null,
196bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes                Snackbar.LENGTH_LONG,
197bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes                Snackbar.Callback.DISMISS_EVENT_ACTION);
198bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes    }
199bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes
200bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes    @Test
20142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas    public void testDismissViaSwipe() throws Throwable {
2027b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov        verifyDismissCallback(
203bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes                onView(isAssignableFrom(Snackbar.SnackbarLayout.class)),
204c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                swipeRight(),
205c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                null,
206bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes                Snackbar.LENGTH_LONG,
207bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes                Snackbar.Callback.DISMISS_EVENT_SWIPE);
208bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes    }
209bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes
210bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes    @Test
21142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas    public void testDismissViaSwipeRtl() throws Throwable {
212c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        onView(withId(R.id.col)).perform(setLayoutDirection(ViewCompat.LAYOUT_DIRECTION_RTL));
213c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        if (ViewCompat.getLayoutDirection(mCoordinatorLayout) == ViewCompat.LAYOUT_DIRECTION_RTL) {
214c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov            // On devices that support RTL layout, the start-to-end dismiss swipe is done
215c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov            // with swipeLeft() action
216c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov            verifyDismissCallback(
217c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                    onView(isAssignableFrom(Snackbar.SnackbarLayout.class)),
218c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                    swipeLeft(),
219c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                    null,
220c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                    Snackbar.LENGTH_LONG,
221c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                    Snackbar.Callback.DISMISS_EVENT_SWIPE);
222c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        }
223c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov    }
224c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov
225c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov    @Test
22642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas    public void testDismissViaApi() throws Throwable {
227c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        verifyDismissCallback(
228c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                onView(isAssignableFrom(Snackbar.SnackbarLayout.class)),
229c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                null,
230c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                new DismissAction() {
231c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                    @Override
232c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                    public void dismiss(Snackbar snackbar) {
233c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                        snackbar.dismiss();
234c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                    }
235c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                },
236c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                Snackbar.LENGTH_LONG,
237c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                Snackbar.Callback.DISMISS_EVENT_MANUAL);
238c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov    }
239c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov
240e6cf359406cd7baaa0659b54c1b7d8ac45db122aAurimas Liutikas    @LargeTest
241c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov    @Test
24242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas    public void testDismissViaTimeout() throws Throwable {
243c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        verifyDismissCallback(
244c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                onView(isAssignableFrom(Snackbar.SnackbarLayout.class)),
245c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                null,
246c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                null,
247c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                Snackbar.LENGTH_LONG,
248c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                Snackbar.Callback.DISMISS_EVENT_TIMEOUT);
249c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov    }
250c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov
251e6cf359406cd7baaa0659b54c1b7d8ac45db122aAurimas Liutikas    @LargeTest
252c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov    @Test
253e855c308ce795c6ac382b94670c264fc368ba882Chris Banes    public void testSwipeUpDismissesViaTimeout() throws Throwable {
254e855c308ce795c6ac382b94670c264fc368ba882Chris Banes        verifyDismissCallback(
255e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                onView(isAssignableFrom(Snackbar.SnackbarLayout.class)),
256e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                // This is a swipe up, from the middle center of the view, to above the view
257e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                // (outside the bounds)
258e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                new GeneralSwipeAction(
259e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                        Swipe.SLOW,
260e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                        new CoordinatesProvider() {
261e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                            @Override
262e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                            public float[] calculateCoordinates(View view) {
263e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                                final int[] loc = new int[2];
264e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                                view.getLocationOnScreen(loc);
265e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                                return new float[]{
266e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                                        loc[0] + view.getWidth() / 2,
267e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                                        loc[1] + view.getHeight() / 2};
268e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                            }
269e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                        },
270e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                        new CoordinatesProvider() {
271e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                            @Override
272e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                            public float[] calculateCoordinates(View view) {
273e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                                final int[] loc = new int[2];
274e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                                view.getLocationOnScreen(loc);
275e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                                return new float[]{
276e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                                        loc[0] + view.getWidth() / 2,
277e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                                        loc[1] - view.getHeight()};
278e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                            }
279e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                        },
280e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                        Press.FINGER
281e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                ),
282e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                null,
283e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                Snackbar.LENGTH_SHORT,
284e855c308ce795c6ac382b94670c264fc368ba882Chris Banes                Snackbar.Callback.DISMISS_EVENT_TIMEOUT);
285e855c308ce795c6ac382b94670c264fc368ba882Chris Banes    }
286e855c308ce795c6ac382b94670c264fc368ba882Chris Banes
287e855c308ce795c6ac382b94670c264fc368ba882Chris Banes    @Test
28842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas    public void testDismissViaAnotherSnackbar() throws Throwable {
289c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        final Snackbar anotherSnackbar =
290c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                Snackbar.make(mCoordinatorLayout, "A different message", Snackbar.LENGTH_SHORT);
291c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov
292c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        // Our dismiss action is to show another snackbar (and verify that the original snackbar
293c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        // is now dismissed with CONSECUTIVE event)
294c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        verifyDismissCallback(
295c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                onView(isAssignableFrom(Snackbar.SnackbarLayout.class)),
296c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                null,
297c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                new DismissAction() {
298c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                    @Override
299c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                    public void dismiss(Snackbar snackbar) {
300c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                        anotherSnackbar.show();
301c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                    }
302c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                },
303c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                Snackbar.LENGTH_LONG,
304c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov                Snackbar.Callback.DISMISS_EVENT_CONSECUTIVE);
305c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov
306c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov        // And dismiss the second snackbar to get back to clean state
3078da7b24b08afba7ec155a371117df018bcc25eefKirill Grouchnikov        SnackbarUtils.dismissTransientBottomBarAndWaitUntilFullyDismissed(anotherSnackbar);
308c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov    }
309c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov
310c554016bf7e7e057479cf005770dd5e127500329Kirill Grouchnikov    @Test
311bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes    public void testActionClickListener() {
3127b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov        final View.OnClickListener mockClickListener = mock(View.OnClickListener.class);
3137b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov        final Snackbar snackbar =
3147b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov                Snackbar.make(mCoordinatorLayout, MESSAGE_TEXT, Snackbar.LENGTH_SHORT)
3157b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov                    .setAction(ACTION_TEXT, mockClickListener);
316bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes
3173a8340d4a090bc8ab7ad3a774fb6d999e7384301Kirill Grouchnikov        // Show the snackbar
3188da7b24b08afba7ec155a371117df018bcc25eefKirill Grouchnikov        SnackbarUtils.showTransientBottomBarAndWaitUntilFullyShown(snackbar);
3193a8340d4a090bc8ab7ad3a774fb6d999e7384301Kirill Grouchnikov        // perform the action click
3203a8340d4a090bc8ab7ad3a774fb6d999e7384301Kirill Grouchnikov        onView(withId(R.id.snackbar_action)).perform(click());
3213a8340d4a090bc8ab7ad3a774fb6d999e7384301Kirill Grouchnikov        // and verify that our click listener has been called
3227b7e3bfd940aa1b41497ac4c6710a97b54c3e551Kirill Grouchnikov        verify(mockClickListener, times(1)).onClick(any(View.class));
323bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes    }
3248c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov
3258c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov    @Test
3268c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov    public void testSetCallback() throws Throwable {
3278c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        final Snackbar snackbar =
3288c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                Snackbar.make(mCoordinatorLayout, MESSAGE_TEXT, Snackbar.LENGTH_INDEFINITE)
3298c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                        .setAction(ACTION_TEXT, mock(View.OnClickListener.class));
330ca9c74379e9fb2b38965253836a2ab0e36990c45Kirill Grouchnikov        final Snackbar.Callback mockCallback = spy(new Snackbar.Callback());
3318c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        snackbar.setCallback(mockCallback);
3328c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov
3338c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        SnackbarUtils.showTransientBottomBarAndWaitUntilFullyShown(snackbar);
3348c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        verify(mockCallback, times(1)).onShown(snackbar);
3358c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov
3368c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        SnackbarUtils.dismissTransientBottomBarAndWaitUntilFullyDismissed(snackbar);
3378c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        verify(mockCallback, times(1)).onDismissed(snackbar,
3388c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                BaseTransientBottomBar.BaseCallback.DISMISS_EVENT_MANUAL);
3398c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov    }
3408c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov
3418c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov    @Test
3428c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov    public void testSingleCallback() throws Throwable {
3438c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        final Snackbar snackbar =
3448c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                Snackbar.make(mCoordinatorLayout, MESSAGE_TEXT, Snackbar.LENGTH_INDEFINITE)
3458c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                        .setAction(ACTION_TEXT, mock(View.OnClickListener.class));
3468c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        final BaseTransientBottomBar.BaseCallback mockCallback1 =
3478c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                mock(BaseTransientBottomBar.BaseCallback.class);
3488c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        final BaseTransientBottomBar.BaseCallback mockCallback2 =
3498c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                mock(BaseTransientBottomBar.BaseCallback.class);
3508c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        snackbar.addCallback(mockCallback1);
3518c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov
3528c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        SnackbarUtils.showTransientBottomBarAndWaitUntilFullyShown(snackbar);
3538c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        verify(mockCallback1, times(1)).onShown(snackbar);
3548c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        verify(mockCallback2, never()).onShown(snackbar);
3558c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov
3568c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        SnackbarUtils.dismissTransientBottomBarAndWaitUntilFullyDismissed(snackbar);
3578c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        verify(mockCallback1, times(1)).onDismissed(snackbar,
3588c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                BaseTransientBottomBar.BaseCallback.DISMISS_EVENT_MANUAL);
3598c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        verify(mockCallback2, never()).onDismissed(snackbar,
3608c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                BaseTransientBottomBar.BaseCallback.DISMISS_EVENT_MANUAL);
3618c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov    }
3628c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov
3638c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov    @Test
3648c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov    public void testMultipleCallbacks() throws Throwable {
3658c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        final Snackbar snackbar =
3668c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                Snackbar.make(mCoordinatorLayout, MESSAGE_TEXT, Snackbar.LENGTH_INDEFINITE)
3678c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                        .setAction(ACTION_TEXT, mock(View.OnClickListener.class));
3688c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        final BaseTransientBottomBar.BaseCallback mockCallback1 =
3698c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                mock(BaseTransientBottomBar.BaseCallback.class);
3708c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        final BaseTransientBottomBar.BaseCallback mockCallback2 =
3718c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                mock(BaseTransientBottomBar.BaseCallback.class);
3728c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        snackbar.addCallback(mockCallback1);
3738c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        snackbar.addCallback(mockCallback2);
3748c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov
3758c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        SnackbarUtils.showTransientBottomBarAndWaitUntilFullyShown(snackbar);
3768c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        verify(mockCallback1, times(1)).onShown(snackbar);
3778c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        verify(mockCallback2, times(1)).onShown(snackbar);
3788c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov
3798c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        SnackbarUtils.dismissTransientBottomBarAndWaitUntilFullyDismissed(snackbar);
3808c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        verify(mockCallback1, times(1)).onDismissed(snackbar,
3818c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                BaseTransientBottomBar.BaseCallback.DISMISS_EVENT_MANUAL);
3828c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        verify(mockCallback2, times(1)).onDismissed(snackbar,
3838c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                BaseTransientBottomBar.BaseCallback.DISMISS_EVENT_MANUAL);
3848c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov    }
3858c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov
3868c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov    @Test
3878c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov    public void testMultipleCallbacksWithRemoval() throws Throwable {
3888c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        final Snackbar snackbar =
3898c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                Snackbar.make(mCoordinatorLayout, MESSAGE_TEXT, Snackbar.LENGTH_INDEFINITE)
3908c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                        .setAction(ACTION_TEXT, mock(View.OnClickListener.class));
3918c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        final BaseTransientBottomBar.BaseCallback mockCallback1 =
3928c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                mock(BaseTransientBottomBar.BaseCallback.class);
3938c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        final BaseTransientBottomBar.BaseCallback mockCallback2 =
3948c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                mock(BaseTransientBottomBar.BaseCallback.class);
3958c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        snackbar.addCallback(mockCallback1);
3968c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        snackbar.addCallback(mockCallback2);
3978c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov
3988c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        SnackbarUtils.showTransientBottomBarAndWaitUntilFullyShown(snackbar);
3998c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        verify(mockCallback1, times(1)).onShown(snackbar);
4008c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        verify(mockCallback2, times(1)).onShown(snackbar);
4018c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov
4028c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        snackbar.removeCallback(mockCallback2);
4038c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov
4048c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        SnackbarUtils.dismissTransientBottomBarAndWaitUntilFullyDismissed(snackbar);
4058c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        verify(mockCallback1, times(1)).onDismissed(snackbar,
4068c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                BaseTransientBottomBar.BaseCallback.DISMISS_EVENT_MANUAL);
4078c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov        verify(mockCallback2, never()).onDismissed(snackbar,
4088c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov                BaseTransientBottomBar.BaseCallback.DISMISS_EVENT_MANUAL);
4098c153ac8980737c4292ae1c019c69471607b3859Kirill Grouchnikov    }
410bfd48d0521963754e04e407499ee9e278fe06c0fChris Banes}
411