chromium/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelUtilsUnitTest.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.tabmodel;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import androidx.test.filters.SmallTest;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;

import org.chromium.base.Callback;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabCreationState;
import org.chromium.chrome.browser.tab.TabLaunchType;
import org.chromium.chrome.browser.tab.TabSelectionType;
import org.chromium.chrome.test.util.browser.tabmodel.MockTabModel;
import org.chromium.chrome.test.util.browser.tabmodel.MockTabModelSelector;
import org.chromium.ui.base.WindowAndroid;

/** Tests for {@link TabModelUtils}. */
@RunWith(BaseRobolectricTestRunner.class)
public class TabModelUtilsUnitTest {
    private static final int TAB_ID = 5;
    private static final int INCOGNITO_TAB_ID = 7;
    private static final int UNUSED_TAB_ID = 9;

    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();

    @Mock private Profile mProfile;
    @Mock private Profile mIncognitoProfile;
    @Mock private Tab mTab;
    @Mock private Tab mIncognitoTab;
    @Mock private Callback<TabModelSelector> mTabModelSelectorCallback;
    @Mock private WindowAndroid mWindowAndroid;

    @Captor private ArgumentCaptor<TabModelSelectorObserver> mTabModelSelectorObserverCaptor;

    private MockTabModelSelector mTabModelSelector;
    private MockTabModel mTabModel;
    private MockTabModel mIncognitoTabModel;

    @Before
    public void setUp() {
        when(mIncognitoProfile.isOffTheRecord()).thenReturn(true);
        when(mTab.getId()).thenReturn(TAB_ID);
        when(mTab.getWindowAndroid()).thenReturn(mWindowAndroid);
        when(mIncognitoTab.getId()).thenReturn(INCOGNITO_TAB_ID);
        when(mIncognitoTab.isIncognito()).thenReturn(true);
        mTabModelSelector = spy(new MockTabModelSelector(mProfile, mIncognitoProfile, 0, 0, null));
        TabModelSelectorSupplier.setInstanceForTesting(mTabModelSelector);

        mTabModel = (MockTabModel) mTabModelSelector.getModel(false);
        mTabModel.addTab(
                mTab,
                TabList.INVALID_TAB_INDEX,
                TabLaunchType.FROM_LINK,
                TabCreationState.LIVE_IN_BACKGROUND);
        mIncognitoTabModel = (MockTabModel) mTabModelSelector.getModel(true);
        mIncognitoTabModel.addTab(
                mIncognitoTab,
                TabList.INVALID_TAB_INDEX,
                TabLaunchType.FROM_LINK,
                TabCreationState.LIVE_IN_BACKGROUND);
    }

    @Test
    @SmallTest
    public void testSelectTabById() {
        assertEquals(TabList.INVALID_TAB_INDEX, mTabModel.index());
        TabModelUtils.selectTabById(mTabModelSelector, TAB_ID, TabSelectionType.FROM_USER);
        assertEquals(TAB_ID, mTabModel.getTabAt(mTabModel.index()).getId());
    }

    @Test
    @SmallTest
    public void testSelectTabByIdIncognito() {
        assertEquals(TabList.INVALID_TAB_INDEX, mIncognitoTabModel.index());
        TabModelUtils.selectTabById(
                mTabModelSelector, INCOGNITO_TAB_ID, TabSelectionType.FROM_USER);
        assertEquals(
                INCOGNITO_TAB_ID, mIncognitoTabModel.getTabAt(mIncognitoTabModel.index()).getId());
    }

    @Test
    @SmallTest
    public void testSelectTabByIdNoOpInvalidTabId() {
        assertEquals(TabList.INVALID_TAB_INDEX, mTabModel.index());
        TabModelUtils.selectTabById(
                mTabModelSelector, Tab.INVALID_TAB_ID, TabSelectionType.FROM_USER);
        assertEquals(TabList.INVALID_TAB_INDEX, mTabModel.index());
    }

    @Test
    @SmallTest
    public void testSelectTabByIdNoOpNotFound() {
        assertEquals(TabList.INVALID_TAB_INDEX, mTabModel.index());
        TabModelUtils.selectTabById(mTabModelSelector, UNUSED_TAB_ID, TabSelectionType.FROM_USER);
        assertEquals(TabList.INVALID_TAB_INDEX, mTabModel.index());
    }

    @Test
    @SmallTest
    public void testRunOnTabStateInitializedCallback() {
        mTabModelSelector.markTabStateInitialized();
        TabModelUtils.runOnTabStateInitialized(mTabModelSelector, mTabModelSelectorCallback);
        verify(mTabModelSelectorCallback).onResult(mTabModelSelector);
    }

    @Test
    @SmallTest
    public void testRunOnTabStateInitializedObserver() {
        TabModelUtils.runOnTabStateInitialized(mTabModelSelector, mTabModelSelectorCallback);
        verify(mTabModelSelector).addObserver(mTabModelSelectorObserverCaptor.capture());
        verify(mTabModelSelectorCallback, never()).onResult(mTabModelSelector);
        mTabModelSelector.markTabStateInitialized();
        verify(mTabModelSelectorCallback).onResult(mTabModelSelector);
        verify(mTabModelSelector).removeObserver(eq(mTabModelSelectorObserverCaptor.getValue()));
    }

    @Test
    @SmallTest
    public void testRunOnTabStateInitializedRemoveObserverWhenDestroyed() {
        TabModelUtils.runOnTabStateInitialized(mTabModelSelector, mTabModelSelectorCallback);
        verify(mTabModelSelector).addObserver(mTabModelSelectorObserverCaptor.capture());
        verify(mTabModelSelector, never())
                .removeObserver(eq(mTabModelSelectorObserverCaptor.getValue()));
        mTabModelSelector.destroy();
        verify(mTabModelSelector).removeObserver(eq(mTabModelSelectorObserverCaptor.getValue()));
    }

    @Test
    @SmallTest
    public void testGetTabModelFilterByTab() {
        assertEquals(TabList.INVALID_TAB_INDEX, mTabModel.index());
        TabModelFilter filter = TabModelUtils.getTabModelFilterByTab(mTab);
        assertEquals(
                mTabModelSelector.getTabModelFilterProvider().getCurrentTabModelFilter(), filter);
    }
}