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

// Copyright 2020 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 android.view.View.GONE;
import static android.view.View.VISIBLE;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import static org.chromium.base.test.util.Batch.UNIT_TESTS;

import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;

import androidx.appcompat.content.res.AppCompatResources;
import androidx.test.annotation.UiThreadTest;
import androidx.test.filters.SmallTest;

import org.junit.Test;
import org.junit.runner.RunWith;

import org.chromium.base.ThreadUtils;
import org.chromium.base.test.util.Batch;
import org.chromium.chrome.browser.tab.state.ShoppingPersistedTabData;
import org.chromium.chrome.tab_ui.R;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
import org.chromium.ui.test.util.BlankUiTestActivityTestCase;
import org.chromium.ui.widget.ButtonCompat;
import org.chromium.ui.widget.ChromeImageView;

import java.util.concurrent.atomic.AtomicBoolean;

/** Tests for {@link LargeMessageCardViewBinder}. */
@RunWith(ChromeJUnit4ClassRunner.class)
@Batch(UNIT_TESTS)
public class LargeMessageCardViewBinderTest extends BlankUiTestActivityTestCase {
    private static final String TITLE_TEXT = "titleText";
    private static final String ACTION_TEXT = "actionText";
    private static final String DESCRIPTION_TEXT = "descriptionText";
    private static final String SECONDARY_ACTION_TEXT = "secondaryActionText";
    private static final String DISMISS_BUTTON_CONTENT_DESCRIPTION = "dismiss";
    private static final String PRICE = "$300";
    private static final String PREVIOUS_PRICE = "$400";

    private final AtomicBoolean mReviewButtonClicked = new AtomicBoolean();
    private final AtomicBoolean mSecondaryActionButtonClicked = new AtomicBoolean();
    private final AtomicBoolean mDismissButtonClicked = new AtomicBoolean();
    private final AtomicBoolean mMessageServiceReviewCallbackRan = new AtomicBoolean();
    private final AtomicBoolean mMessageServiceDismissCallbackRan = new AtomicBoolean();

    private final MessageCardView.ReviewActionProvider mUiReviewHandler =
            () -> mReviewButtonClicked.set(true);
    private final MessageCardView.DismissActionProvider mUiDismissHandler =
            (int messageType) -> mDismissButtonClicked.set(true);
    private final MessageCardView.ReviewActionProvider mMessageServiceActionHandler =
            () -> mMessageServiceReviewCallbackRan.set(true);
    private final MessageCardView.DismissActionProvider mMessageServiceDismissHandler =
            (int messageType) -> mMessageServiceDismissCallbackRan.set(true);
    private final OnClickListener mSecondaryActionButtonClickListener =
            view -> mSecondaryActionButtonClicked.set(true);

    private ChromeImageView mIcon;
    private TextView mTitle;
    private TextView mDescription;
    private ButtonCompat mActionButton;
    private ButtonCompat mSecondaryActionButton;
    private ChromeImageView mCloseButton;
    private PriceCardView mPriceInfoBox;
    private LargeMessageCardView mItemView;
    private PropertyModel mItemViewModel;
    private PropertyModelChangeProcessor mItemMCP;

    @Override
    public void setUpTest() throws Exception {
        super.setUpTest();

        ViewGroup view = new FrameLayout(getActivity());

        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    getActivity().setContentView(view);

                    mItemView =
                            (LargeMessageCardView)
                                    getActivity()
                                            .getLayoutInflater()
                                            .inflate(R.layout.large_message_card_item, null);
                    view.addView(mItemView);

                    mPriceInfoBox = mItemView.findViewById(R.id.price_info_box);
                    mIcon = mItemView.findViewById(R.id.icon);
                    mTitle = mItemView.findViewById(R.id.title);
                    mDescription = mItemView.findViewById(R.id.description);
                    mActionButton = mItemView.findViewById(R.id.action_button);
                    mSecondaryActionButton = mItemView.findViewById(R.id.secondary_action_button);
                    mCloseButton = mItemView.findViewById(R.id.close_button);

                    mItemViewModel =
                            new PropertyModel.Builder(MessageCardViewProperties.ALL_KEYS)
                                    .with(MessageCardViewProperties.TITLE_TEXT, TITLE_TEXT)
                                    .with(MessageCardViewProperties.ACTION_TEXT, ACTION_TEXT)
                                    .with(
                                            MessageCardViewProperties.DESCRIPTION_TEXT,
                                            DESCRIPTION_TEXT)
                                    .with(
                                            MessageCardViewProperties
                                                    .DISMISS_BUTTON_CONTENT_DESCRIPTION,
                                            DISMISS_BUTTON_CONTENT_DESCRIPTION)
                                    .with(MessageCardViewProperties.SHOULD_KEEP_AFTER_REVIEW, false)
                                    .build();

                    mItemMCP =
                            PropertyModelChangeProcessor.create(
                                    mItemViewModel, mItemView, LargeMessageCardViewBinder::bind);
                });
    }

    @Test
    @UiThreadTest
    @SmallTest
    public void testInitialBinding() {
        assertEquals(TITLE_TEXT, mTitle.getText().toString());
        assertEquals(ACTION_TEXT, mActionButton.getText().toString());
        assertEquals(DESCRIPTION_TEXT, mDescription.getText().toString());
        assertEquals(DISMISS_BUTTON_CONTENT_DESCRIPTION, mCloseButton.getContentDescription());
        assertEquals(
                "Secondary action button should be gone by default.",
                GONE,
                mSecondaryActionButton.getVisibility());
        assertEquals(
                "Close button should be visible by default.",
                VISIBLE,
                mCloseButton.getVisibility());
    }

    @Test
    @UiThreadTest
    @SmallTest
    public void testSetIconDrawable() {
        assertNull(mIcon.getDrawable());

        Drawable iconDrawable =
                AppCompatResources.getDrawable(getActivity(), R.drawable.ic_globe_24dp);
        mItemViewModel.set(
                MessageCardViewProperties.ICON_PROVIDER,
                (callback) -> {
                    callback.onResult(iconDrawable);
                });
        assertEquals(iconDrawable, mIcon.getDrawable());
    }

    @Test
    @UiThreadTest
    @SmallTest
    public void testSetIconVisibility() {
        assertEquals(GONE, mIcon.getVisibility());

        mItemViewModel.set(MessageCardViewProperties.IS_ICON_VISIBLE, true);
        assertEquals(VISIBLE, mIcon.getVisibility());
        mItemViewModel.set(MessageCardViewProperties.IS_ICON_VISIBLE, false);
        assertEquals(GONE, mIcon.getVisibility());
    }

    @Test
    @UiThreadTest
    @SmallTest
    public void testSetCloseIconVisibility() {
        mItemViewModel.set(MessageCardViewProperties.IS_CLOSE_BUTTON_VISIBLE, false);
        assertEquals("Close button should not be visible.", GONE, mCloseButton.getVisibility());
    }

    @Test
    @UiThreadTest
    @SmallTest
    public void testSecondaryActionText() {
        mItemViewModel.set(MessageCardViewProperties.SECONDARY_ACTION_TEXT, SECONDARY_ACTION_TEXT);
        assertEquals(
                "Fail to set secondary action text.",
                SECONDARY_ACTION_TEXT,
                mSecondaryActionButton.getText());
        assertEquals(
                "Secondary action text should be visible.",
                View.VISIBLE,
                mSecondaryActionButton.getVisibility());
    }

    @Test
    @UiThreadTest
    @SmallTest
    public void testSecondaryActionOnClickListenerTest() {
        mSecondaryActionButtonClicked.set(false);
        mItemViewModel.set(MessageCardViewProperties.SECONDARY_ACTION_TEXT, SECONDARY_ACTION_TEXT);
        mItemViewModel.set(
                MessageCardViewProperties.SECONDARY_ACTION_BUTTON_CLICK_HANDLER,
                mSecondaryActionButtonClickListener);
        mSecondaryActionButton.performClick();
        assertTrue("Secondary button didn't fire properly.", mSecondaryActionButtonClicked.get());
    }

    @Test
    @UiThreadTest
    @SmallTest
    public void testSetupPriceInfoBox() {
        assertEquals(GONE, mPriceInfoBox.getVisibility());

        mItemViewModel.set(
                MessageCardViewProperties.PRICE_DROP,
                new ShoppingPersistedTabData.PriceDrop(PRICE, PREVIOUS_PRICE));
        assertEquals(VISIBLE, mPriceInfoBox.getVisibility());
        assertEquals(
                PRICE,
                ((TextView) mItemView.findViewById(R.id.current_price)).getText().toString());
        assertEquals(
                PREVIOUS_PRICE,
                ((TextView) mItemView.findViewById(R.id.previous_price)).getText().toString());

        mItemViewModel.set(MessageCardViewProperties.PRICE_DROP, null);
        assertEquals(GONE, mPriceInfoBox.getVisibility());
    }

    @Test
    @UiThreadTest
    @SmallTest
    public void testBindingAndClickingReviewHandler() {
        mReviewButtonClicked.set(false);
        mMessageServiceReviewCallbackRan.set(false);
        mDismissButtonClicked.set(false);
        mItemViewModel.set(MessageCardViewProperties.UI_ACTION_PROVIDER, mUiReviewHandler);
        mItemViewModel.set(
                MessageCardViewProperties.MESSAGE_SERVICE_ACTION_PROVIDER,
                mMessageServiceActionHandler);
        mItemViewModel.set(MessageCardViewProperties.UI_DISMISS_ACTION_PROVIDER, mUiDismissHandler);
        mItemViewModel.set(MessageCardViewProperties.ACTION_TEXT, ACTION_TEXT);

        mActionButton.performClick();
        assertTrue(mReviewButtonClicked.get());
        assertTrue(mMessageServiceReviewCallbackRan.get());
        assertTrue(mDismissButtonClicked.get());
    }

    @Test
    @UiThreadTest
    @SmallTest
    public void testBindingAndClickingDismissHandler() {
        mDismissButtonClicked.set(false);
        mMessageServiceDismissCallbackRan.set(false);
        mItemViewModel.set(MessageCardViewProperties.UI_DISMISS_ACTION_PROVIDER, mUiDismissHandler);
        mItemViewModel.set(
                MessageCardViewProperties.MESSAGE_SERVICE_DISMISS_ACTION_PROVIDER,
                mMessageServiceDismissHandler);
        mItemViewModel.set(
                MessageCardViewProperties.DISMISS_BUTTON_CONTENT_DESCRIPTION,
                DISMISS_BUTTON_CONTENT_DESCRIPTION);

        mCloseButton.performClick();
        assertTrue(mDismissButtonClicked.get());
        assertTrue(mMessageServiceDismissCallbackRan.get());
    }

    @Test
    @UiThreadTest
    @SmallTest
    public void testUpdateWidthWithOrientation() {
        mItemView.setPadding(0, 0, 0, 0);
        mItemView.updateWidthWithOrientation(Configuration.ORIENTATION_PORTRAIT);
        assertEquals(0, mItemView.getPaddingLeft());
        assertEquals(0, mItemView.getPaddingTop());
        assertEquals(0, mItemView.getPaddingRight());
        assertEquals(0, mItemView.getPaddingBottom());

        int landscapeSidePadding =
                (int)
                        getActivity()
                                .getResources()
                                .getDimension(
                                        R.dimen.tab_grid_large_message_side_padding_landscape);
        mItemView.setPadding(0, 0, 0, 0);
        mItemView.updateWidthWithOrientation(Configuration.ORIENTATION_LANDSCAPE);
        assertEquals(landscapeSidePadding, mItemView.getPaddingLeft());
        assertEquals(0, mItemView.getPaddingTop());
        assertEquals(landscapeSidePadding, mItemView.getPaddingRight());
        assertEquals(0, mItemView.getPaddingBottom());
    }

    @Override
    public void tearDownTest() throws Exception {
        ThreadUtils.runOnUiThreadBlocking(mItemMCP::destroy);
        super.tearDownTest();
    }
}