chromium/chrome/android/junit/src/org/chromium/chrome/browser/autofill/vcn/AutofillVcnEnrollBottomSheetMediatorTest.java

// Copyright 2023 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.autofill.vcn;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;

import android.app.Activity;

import androidx.test.filters.SmallTest;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.Robolectric;

import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.Features.DisableFeatures;
import org.chromium.base.test.util.Features.EnableFeatures;
import org.chromium.base.test.util.HistogramWatcher;
import org.chromium.chrome.browser.autofill.vcn.AutofillVcnEnrollBottomSheetMediator.VirtualCardEnrollmentBubbleResult;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerFactory;
import org.chromium.components.browser_ui.bottomsheet.ManagedBottomSheetController;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.modelutil.PropertyModel;

/** Unit test for {@link AutofillVcnEnrollBottomSheetMediator}. */
@RunWith(BaseRobolectricTestRunner.class)
@SmallTest
public final class AutofillVcnEnrollBottomSheetMediatorTest {
    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();

    @Mock private AutofillVcnEnrollBottomSheetContent mContent;
    @Mock private AutofillVcnEnrollBottomSheetLifecycle mLifecycle;
    @Mock private ManagedBottomSheetController mBottomSheetController;
    private PropertyModel mModel;
    private WindowAndroid mWindow;
    private AutofillVcnEnrollBottomSheetMediator mMediator;

    @Before
    public void setUp() {
        Activity activity = Robolectric.buildActivity(Activity.class).create().get();
        mModel = new PropertyModel.Builder(AutofillVcnEnrollBottomSheetProperties.ALL_KEYS).build();
        mWindow = new WindowAndroid(activity);
        BottomSheetControllerFactory.attach(mWindow, mBottomSheetController);
        when(mLifecycle.canBegin()).thenReturn(true);
        mMediator = new AutofillVcnEnrollBottomSheetMediator(mContent, mLifecycle, mModel);
    }

    @After
    public void tearDown() {
        BottomSheetControllerFactory.detach(mBottomSheetController);
        mWindow.destroy();
    }

    @Test
    public void testShowBottomSheet() {
        mMediator.requestShowContent(mWindow);

        verify(mBottomSheetController)
                .requestShowContent(/* content= */ eq(mContent), /* animate= */ eq(true));
    }

    @Test
    public void testCannotShowBottomSheet() {
        when(mLifecycle.canBegin()).thenReturn(false); // E.g., when in tab overview.

        mMediator.requestShowContent(mWindow);

        verifyNoInteractions(mBottomSheetController);
    }

    @Test
    @EnableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_VCN_ENROLL_LOADING_AND_CONFIRMATION})
    public void testOnAccept_showsLoadingState() {
        mMediator.requestShowContent(mWindow);
        mMediator.onAccept();

        assertTrue(mModel.get(AutofillVcnEnrollBottomSheetProperties.SHOW_LOADING_STATE));
        verify(mBottomSheetController, times(0)).hideContent(any(), anyBoolean(), anyInt());
    }

    @Test
    @DisableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_VCN_ENROLL_LOADING_AND_CONFIRMATION})
    public void testOnAccept_hidesBottomSheet() {
        mMediator.requestShowContent(mWindow);
        mMediator.onAccept();

        assertFalse(mModel.get(AutofillVcnEnrollBottomSheetProperties.SHOW_LOADING_STATE));
        verify(mBottomSheetController)
                .hideContent(
                        eq(mContent),
                        /* animate= */ eq(true),
                        eq(BottomSheetController.StateChangeReason.INTERACTION_COMPLETE));
    }

    @Test
    public void testOnCancel() {
        mMediator.requestShowContent(mWindow);
        mMediator.onCancel();

        verify(mBottomSheetController)
                .hideContent(
                        eq(mContent),
                        /* animate= */ eq(true),
                        eq(BottomSheetController.StateChangeReason.INTERACTION_COMPLETE));
    }

    @Test
    public void testHideBottomSheetAfterShowing() {
        mMediator.requestShowContent(mWindow);
        mMediator.hide();

        verify(mBottomSheetController)
                .hideContent(
                        /* content= */ eq(mContent),
                        /* animate= */ eq(true),
                        eq(BottomSheetController.StateChangeReason.INTERACTION_COMPLETE));
    }

    @Test
    public void testHideBottomSheetWithoutShowing() {
        mMediator.hide();

        verifyNoInteractions(mBottomSheetController);
    }

    @Test
    @EnableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_VCN_ENROLL_LOADING_AND_CONFIRMATION})
    public void testMetrics_hideAfterOnAccept_RecordsMetric() {
        HistogramWatcher loadingShownHistogram =
                HistogramWatcher.newSingleRecordWatcher(
                        AutofillVcnEnrollBottomSheetMediator.LOADING_SHOWN_HISTOGRAM, true);
        HistogramWatcher loadingResultHistogram =
                HistogramWatcher.newSingleRecordWatcher(
                        AutofillVcnEnrollBottomSheetMediator.LOADING_RESULT_HISTOGRAM,
                        VirtualCardEnrollmentBubbleResult.ACCEPTED);

        mMediator.requestShowContent(mWindow);
        mMediator.onAccept();
        mMediator.hide();

        loadingShownHistogram.assertExpected();
        loadingResultHistogram.assertExpected();
    }

    @Test
    @DisableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_VCN_ENROLL_LOADING_AND_CONFIRMATION})
    public void testMetrics_hideAfterOnAccept_NoRecords() {
        HistogramWatcher loadingShownHistogram =
                HistogramWatcher.newBuilder()
                        .expectNoRecords(
                                AutofillVcnEnrollBottomSheetMediator.LOADING_SHOWN_HISTOGRAM)
                        .build();
        HistogramWatcher loadingResultHistogram =
                HistogramWatcher.newBuilder()
                        .expectNoRecords(
                                AutofillVcnEnrollBottomSheetMediator.LOADING_RESULT_HISTOGRAM)
                        .build();

        mMediator.requestShowContent(mWindow);
        mMediator.onAccept();
        mMediator.hide();

        loadingShownHistogram.assertExpected();
        loadingResultHistogram.assertExpected();
    }

    @Test
    @EnableFeatures({ChromeFeatureList.AUTOFILL_ENABLE_VCN_ENROLL_LOADING_AND_CONFIRMATION})
    public void testMetrics_onCanceledAfterOnAccept_RecordsClosedLoadingResult() {
        HistogramWatcher loadingResultHistogram =
                HistogramWatcher.newSingleRecordWatcher(
                        AutofillVcnEnrollBottomSheetMediator.LOADING_RESULT_HISTOGRAM,
                        VirtualCardEnrollmentBubbleResult.CLOSED);

        mMediator.requestShowContent(mWindow);
        mMediator.onAccept();
        mMediator.onCancel();

        loadingResultHistogram.assertExpected();
    }

    @Test
    public void testMetrics_hideWithoutCallbacks_NoRecords() {
        HistogramWatcher loadingResultHistogram =
                HistogramWatcher.newBuilder()
                        .expectNoRecords(
                                AutofillVcnEnrollBottomSheetMediator.LOADING_RESULT_HISTOGRAM)
                        .build();

        mMediator.requestShowContent(mWindow);
        mMediator.hide();

        loadingResultHistogram.assertExpected();
    }
}