chromium/components/webapps/browser/android/java/src/org/chromium/components/webapps/pwa_restore_ui/PwaRestoreBottomSheetCoordinatorTest.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.components.webapps.pwa_restore_ui;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.view.View;
import android.widget.TextView;

import androidx.test.filters.MediumTest;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.LooperMode;

import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.JniMocker;
import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
import org.chromium.components.webapps.R;
import org.chromium.components.webapps.pwa_restore_ui.PwaRestoreProperties.ViewState;
import org.chromium.ui.shadows.ShadowColorUtils;

import java.util.ArrayList;
import java.util.List;

/** Instrumentation tests for PWA Restore bottom sheet. */
@RunWith(BaseRobolectricTestRunner.class)
@Config(
        manifest = Config.NONE,
        shadows = {ShadowColorUtils.class})
@LooperMode(LooperMode.Mode.PAUSED)
public class PwaRestoreBottomSheetCoordinatorTest {
    Activity mActivity;

    @Rule public JniMocker mocker = new JniMocker();

    // Each entry in this list should have a corresponding entry in
    // mLastUsedList below.
    private final String[] mDefaultAppIds = new String[] {"appId1", "appId2", "appId3"};
    private final String[] mDefaultAppNames = new String[] {"App 1", "App 2", "App 3"};
    private final ArrayList<Bitmap> mDefaultAppIcons =
            new ArrayList<Bitmap>(
                    List.of(
                            createBitmap(Color.RED),
                            createBitmap(Color.GREEN),
                            createBitmap(Color.BLUE)));
    private final int[] mLastUsedList = new int[] {1, 1, 35};

    @Mock private BottomSheetController mBottomSheetControllerMock;
    @Mock private PwaRestoreBottomSheetMediator.Natives mNativeMediatorMock;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mActivity = Robolectric.buildActivity(Activity.class).create().get();
        mocker.mock(PwaRestoreBottomSheetMediatorJni.TEST_HOOKS, mNativeMediatorMock);
        when(mNativeMediatorMock.initialize(Mockito.any())).thenReturn(0L);
    }

    @After
    public void tearDown() {
        ShadowColorUtils.sInNightMode = false;
    }

    private static Bitmap createBitmap(int color) {
        int[] colors = {color};
        return Bitmap.createBitmap(colors, 1, 1, Bitmap.Config.ALPHA_8);
    }

    @Test
    @MediumTest
    public void testViewInitialization() {
        PwaRestoreBottomSheetCoordinator coordinator =
                new PwaRestoreBottomSheetCoordinator(
                        mDefaultAppIds,
                        mDefaultAppNames,
                        mDefaultAppIcons,
                        mLastUsedList,
                        mActivity,
                        mBottomSheetControllerMock,
                        /* backArrowId= */ 0);

        View bottomSheetView = coordinator.getBottomSheetViewForTesting();
        {
            TextView title = bottomSheetView.findViewById(R.id.title_preview);
            String expected = "Restore your web apps";
            Assert.assertEquals(expected, title.getText());

            TextView description = bottomSheetView.findViewById(R.id.description_preview);
            expected =
                    "Restore web apps you have recently used on devices connected to this account";
            Assert.assertEquals(expected, description.getText());

            View button = bottomSheetView.findViewById(R.id.review_button);
            Assert.assertTrue(button.isEnabled());
        }

        {
            TextView title = bottomSheetView.findViewById(R.id.title_content);
            String expected = "Review web apps";
            Assert.assertEquals(expected, title.getText());

            TextView description = bottomSheetView.findViewById(R.id.description_content);
            expected =
                    "Choose web apps to restore on this device. Apps shown here are based on "
                            + "your Chrome history.";
            Assert.assertEquals(expected, description.getText());

            View pwaList = bottomSheetView.findViewById(R.id.pwa_list);
            Assert.assertTrue(pwaList.getVisibility() == View.VISIBLE);

            View deselectButton = bottomSheetView.findViewById(R.id.deselect_button);
            Assert.assertTrue(deselectButton.isEnabled());

            View restoreButton = bottomSheetView.findViewById(R.id.restore_button);
            Assert.assertTrue(restoreButton.isEnabled());
        }
    }

    @Test
    @MediumTest
    public void testShowAndExpand() {
        PwaRestoreBottomSheetCoordinator coordinator =
                new PwaRestoreBottomSheetCoordinator(
                        mDefaultAppIds,
                        mDefaultAppNames,
                        mDefaultAppIcons,
                        mLastUsedList,
                        mActivity,
                        mBottomSheetControllerMock,
                        /* backArrowId= */ 0);

        coordinator.show();

        // Calling show() results in the bottom sheet showing (peeking).
        Assert.assertEquals(
                ViewState.PREVIEW,
                coordinator.getModelForTesting().get(PwaRestoreProperties.VIEW_STATE));
        verify(mBottomSheetControllerMock, times(1)).requestShowContent(any(), eq(true));

        coordinator.onReviewButtonClicked();

        // Clicking the Review button results in the sheet expanding.
        Assert.assertEquals(
                ViewState.VIEW_PWA_LIST,
                coordinator.getModelForTesting().get(PwaRestoreProperties.VIEW_STATE));

        coordinator.onDialogBackButtonClicked();

        // Clicking the Dialog Back button results in the sheet going back to peeking state.
        Assert.assertEquals(
                ViewState.PREVIEW,
                coordinator.getModelForTesting().get(PwaRestoreProperties.VIEW_STATE));

        coordinator.onReviewButtonClicked();

        // Clicking the Review button (again) results in the sheet expanding.
        Assert.assertEquals(
                ViewState.VIEW_PWA_LIST,
                coordinator.getModelForTesting().get(PwaRestoreProperties.VIEW_STATE));

        coordinator.onOsBackButtonClicked();

        // Clicking the OS Back button results in the sheet going back to peeking state.
        Assert.assertEquals(
                ViewState.PREVIEW,
                coordinator.getModelForTesting().get(PwaRestoreProperties.VIEW_STATE));
    }
}