chromium/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderTest.java

// Copyright 2019 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.tasks.tab_management;

import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withId;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;

import static org.chromium.ui.test.util.ViewUtils.onViewWaiting;

import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import androidx.recyclerview.widget.GridLayoutManager;
import androidx.test.filters.SmallTest;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import org.chromium.base.ThreadUtils;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.tab_ui.R;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.ui.modelutil.LayoutViewBuilder;
import org.chromium.ui.modelutil.MVCListAdapter;
import org.chromium.ui.modelutil.SimpleRecyclerViewAdapter;
import org.chromium.ui.test.util.BlankUiTestActivityTestCase;

import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/** Integration tests for MessageCardProvider component. */
@RunWith(ChromeJUnit4ClassRunner.class)
public class MessageCardProviderTest extends BlankUiTestActivityTestCase {
    private static final int SUGGESTED_TAB_COUNT = 2;

    private TabListRecyclerView mRecyclerView;

    private TabListModel mModelList;
    private SimpleRecyclerViewAdapter mAdapter;

    private MessageCardProviderCoordinator mCoordinator;
    private MessageService mTestingService;
    private MessageService mPriceService;

    private MessageCardView.DismissActionProvider mUiDismissActionProvider = (messageType) -> {};

    @Mock private PriceMessageService.PriceMessageData mPriceMessageData;

    @Mock private Profile mProfile;

    @Override
    public void setUpTest() throws Exception {
        super.setUpTest();
        MockitoAnnotations.initMocks(this);
        // TODO(meiliang): Replace with TabSwitcher instead when ready to integrate with
        // TabSwitcher.
        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    mModelList = new TabListModel();
                    ViewGroup view = new FrameLayout(getActivity());
                    mAdapter = new SimpleRecyclerViewAdapter(mModelList);

                    getActivity().setContentView(view);

                    mRecyclerView =
                            (TabListRecyclerView)
                                    getActivity()
                                            .getLayoutInflater()
                                            .inflate(
                                                    R.layout.tab_list_recycler_view_layout,
                                                    view,
                                                    false);
                    mRecyclerView.setVisibility(View.VISIBLE);

                    mAdapter.registerType(
                            TabProperties.UiType.MESSAGE,
                            new LayoutViewBuilder(R.layout.tab_grid_message_card_item),
                            MessageCardViewBinder::bind);

                    mAdapter.registerType(
                            TabProperties.UiType.LARGE_MESSAGE,
                            new LayoutViewBuilder(R.layout.large_message_card_item),
                            LargeMessageCardViewBinder::bind);

                    GridLayoutManager layoutManager =
                            new GridLayoutManager(mRecyclerView.getContext(), 2);
                    layoutManager.setSpanSizeLookup(
                            new GridLayoutManager.SpanSizeLookup() {
                                @Override
                                public int getSpanSize(int i) {
                                    int itemType = mAdapter.getItemViewType(i);

                                    if (itemType == TabProperties.UiType.MESSAGE
                                            || itemType == TabProperties.UiType.LARGE_MESSAGE) {
                                        return 2;
                                    }
                                    return 1;
                                }
                            });
                    mRecyclerView.setLayoutManager(layoutManager);
                    mRecyclerView.setAdapter(mAdapter);

                    view.addView(mRecyclerView);

                    mTestingService = new MessageService(MessageService.MessageType.FOR_TESTING);
                    mPriceService = new MessageService(MessageService.MessageType.PRICE_MESSAGE);

                    mCoordinator =
                            new MessageCardProviderCoordinator(
                                    getActivity(), () -> mProfile, mUiDismissActionProvider);
                    mCoordinator.subscribeMessageService(mTestingService);
                    mCoordinator.subscribeMessageService(mPriceService);
                });
    }

    @Test
    @SmallTest
    public void testPriceMessage() {
        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    mPriceService.sendAvailabilityNotification(mPriceMessageData);
                    addMessageCards();
                });

        onViewWaiting(withId(R.id.large_message_card_item)).check(matches(isDisplayed()));
    }

    @Test
    @SmallTest
    public void testReviewPriceMessage() {
        AtomicBoolean reviewed = new AtomicBoolean();
        when(mPriceMessageData.getReviewActionProvider()).thenReturn(() -> reviewed.set(true));

        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    mPriceService.sendAvailabilityNotification(mPriceMessageData);
                    addMessageCards();
                });

        onViewWaiting(withId(R.id.large_message_card_item)).check(matches(isDisplayed()));

        assertFalse(reviewed.get());
        onView(withId(R.id.action_button)).perform(click());
        assertTrue(reviewed.get());
    }

    @Test
    @SmallTest
    public void testDismissPriceMessage() {
        AtomicBoolean dismissed = new AtomicBoolean();
        when(mPriceMessageData.getDismissActionProvider())
                .thenReturn((type) -> dismissed.set(true));

        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    mPriceService.sendAvailabilityNotification(mPriceMessageData);
                    addMessageCards();
                });

        onViewWaiting(withId(R.id.large_message_card_item)).check(matches(isDisplayed()));

        assertFalse(dismissed.get());
        onView(withId(R.id.close_button)).perform(click());
        assertTrue(dismissed.get());
    }

    private void addMessageCards() {
        List<MessageCardProviderMediator.Message> messageList = mCoordinator.getMessageItems();
        for (int i = 0; i < messageList.size(); i++) {
            MessageCardProviderMediator.Message message = messageList.get(i);
            if (message.type == MessageService.MessageType.PRICE_MESSAGE) {
                mModelList.add(
                        new MVCListAdapter.ListItem(
                                TabProperties.UiType.LARGE_MESSAGE, message.model));
            } else {
                mModelList.add(
                        new MVCListAdapter.ListItem(TabProperties.UiType.MESSAGE, message.model));
            }
        }
    }
}