blob: 5634eb0ba523bd6244b4a9edb37cd7aceb466aeb [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// 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 org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.chromium.chrome.browser.multiwindow.MultiWindowTestHelper.moveActivityToFront;
import static org.chromium.chrome.browser.multiwindow.MultiWindowTestHelper.waitForSecondChromeTabbedActivity;
import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.clickFirstCardFromTabSwitcher;
import android.annotation.TargetApi;
import android.os.Build;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.view.ViewGroup;
import androidx.recyclerview.widget.RecyclerView;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.DisableIf;
import org.chromium.base.test.util.MinAndroidSdkLevel;
import org.chromium.base.test.util.Restriction;
import org.chromium.chrome.browser.ChromeTabbedActivity;
import org.chromium.chrome.browser.compositor.layouts.Layout;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.toolbar.IncognitoToggleTabLayout;
import org.chromium.chrome.features.start_surface.StartSurfaceLayout;
import org.chromium.chrome.tab_ui.R;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.chrome.test.util.ChromeTabUtils;
import org.chromium.chrome.test.util.MenuUtils;
import org.chromium.chrome.test.util.browser.Features;
import org.chromium.content_public.browser.test.util.Criteria;
import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.ui.test.util.UiRestriction;
/** Tests for Multi-window related behavior in grid tab switcher. */
@RunWith(ChromeJUnit4ClassRunner.class)
// clang-format off
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
ChromeSwitches.DISABLE_TAB_MERGING_FOR_TESTING})
@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
@MinAndroidSdkLevel(Build.VERSION_CODES.N)
@Features.EnableFeatures({ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID})
public class TabSwitcherMultiWindowTest {
// clang-format on
@Rule
public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
@Rule
public TestRule mProcessor = new Features.InstrumentationProcessor();
@Before
public void setUp() {
mActivityTestRule.startMainActivityFromLauncher();
Layout layout = mActivityTestRule.getActivity().getLayoutManager().getOverviewLayout();
assertTrue(layout instanceof StartSurfaceLayout);
CriteriaHelper.pollUiThread(Criteria.equals(true,
mActivityTestRule.getActivity()
.getTabModelSelector()
.getTabModelFilterProvider()
.getCurrentTabModelFilter()::isTabModelRestored));
}
@Test
@MediumTest
@TargetApi(Build.VERSION_CODES.N)
@DisableIf.Build(message = "crbug.com/1017141", sdk_is_less_than = Build.VERSION_CODES.P)
public void testMoveTabsAcrossWindow_GTS_WithoutGroup() throws InterruptedException {
final ChromeTabbedActivity cta1 = mActivityTestRule.getActivity();
// Initially, we have 4 normal tabs and 3 incognito tabs in cta1.
initializeTabModel(cta1, false, 4);
initializeTabModel(cta1, true, 3);
verifyTabModelTabCount(cta1, 4, 3);
// Enter tab switcher in cta1 in incognito mode.
enterTabSwitcher(cta1);
assertTrue(cta1.getTabModelSelector().getCurrentModel().isIncognito());
// Before move, there are 3 incognito tabs in cta1.
RecyclerView recyclerView1 = cta1.findViewById(R.id.tab_list_view);
CriteriaHelper.pollUiThread(Criteria.equals(3, recyclerView1::getChildCount));
// Move 2 incognito tabs to cta2.
clickFirstCardFromTabSwitcher(cta1);
moveTabsToOtherWindow(cta1, 2);
// After move, there are 1 incognito tab in cta1 and 2 incognito tabs in cta2.
final ChromeTabbedActivity cta2 = waitForSecondChromeTabbedActivity();
verifyTabModelTabCount(cta1, 4, 1);
verifyTabModelTabCount(cta2, 0, 2);
enterTabSwitcher(cta1);
CriteriaHelper.pollUiThread(Criteria.equals(1, recyclerView1::getChildCount));
// Enter tab switcher in cta2.
moveActivityToFront(cta2);
enterTabSwitcher(cta2);
// There should be two incognito tabs in tab switcher in cta2.
RecyclerView recyclerView2 = cta2.findViewById(R.id.tab_list_view);
CriteriaHelper.pollUiThread(Criteria.equals(2, recyclerView2::getChildCount));
// Move 1 incognito tab back to cta1.
clickFirstCardFromTabSwitcher(cta2);
moveTabsToOtherWindow(cta2, 1);
// After move, there are 2 incognito tabs in cta1 and 1 incognito tab in cta2.
verifyTabModelTabCount(cta1, 4, 2);
verifyTabModelTabCount(cta2, 0, 1);
enterTabSwitcher(cta2);
CriteriaHelper.pollUiThread(Criteria.equals(1, recyclerView2::getChildCount));
// Enter tab switcher in cta1.
moveActivityToFront(cta1);
// There should be two incognito tabs in tab switcher in cta1.
CriteriaHelper.pollUiThread(Criteria.equals(2, recyclerView1::getChildCount));
// Switch to normal tab list in cta1.
TestThreadUtils.runOnUiThreadBlocking(() -> {
IncognitoToggleTabLayout toggleTabLayout =
cta1.findViewById(R.id.incognito_toggle_tabs);
ViewGroup toggleButtons = (ViewGroup) toggleTabLayout.getChildAt(0);
toggleButtons.getChildAt(0).performClick();
});
assertEquals(false, cta1.getTabModelSelector().getCurrentModel().isIncognito());
// Move 3 normal tabs to cta2.
clickFirstCardFromTabSwitcher(cta1);
moveTabsToOtherWindow(cta1, 3);
// After move, there are 1 normal tab in cta1 and 3 normal tabs in cta2.
verifyTabModelTabCount(cta1, 1, 2);
verifyTabModelTabCount(cta2, 3, 1);
enterTabSwitcher(cta1);
CriteriaHelper.pollUiThread(Criteria.equals(1, recyclerView1::getChildCount));
// Enter tab switcher in cta2.
moveActivityToFront(cta2);
enterTabSwitcher(cta2);
// There should be 3 normal tabs in tab switcher in cta2.
CriteriaHelper.pollUiThread(Criteria.equals(3, recyclerView2::getChildCount));
// Move 2 normal tabs back to cta1.
clickFirstCardFromTabSwitcher(cta2);
moveTabsToOtherWindow(cta2, 2);
// After move, there are 3 normal tabs in cta1 and 1 normal tab in cta2.
verifyTabModelTabCount(cta1, 3, 2);
verifyTabModelTabCount(cta2, 1, 1);
enterTabSwitcher(cta2);
CriteriaHelper.pollUiThread(Criteria.equals(1, recyclerView2::getChildCount));
}
private void initializeTabModel(ChromeTabbedActivity cta, boolean isIncognito, int tabsCount) {
for (int i = 0; i < (isIncognito ? tabsCount : tabsCount - 1); i++) {
ChromeTabUtils.newTabFromMenu(
InstrumentationRegistry.getInstrumentation(), cta, isIncognito, true);
}
}
private void moveTabsToOtherWindow(ChromeTabbedActivity cta, int number) {
for (int i = 0; i < number; i++) {
MenuUtils.invokeCustomMenuActionSync(InstrumentationRegistry.getInstrumentation(), cta,
org.chromium.chrome.R.id.move_to_other_window_menu_id);
}
}
private void enterTabSwitcher(ChromeTabbedActivity cta) {
assertFalse(cta.getLayoutManager().overviewVisible());
TestThreadUtils.runOnUiThreadBlocking(
() -> { cta.findViewById(R.id.tab_switcher_button).performClick(); });
CriteriaHelper.pollUiThread(
Criteria.equals(true, () -> cta.getLayoutManager().overviewVisible()));
}
private void verifyTabModelTabCount(
ChromeTabbedActivity cta, int normalTabs, int incognitoTabs) {
CriteriaHelper.pollUiThread(Criteria.equals(
normalTabs, () -> cta.getTabModelSelector().getModel(false).getCount()));
CriteriaHelper.pollUiThread(Criteria.equals(
incognitoTabs, () -> cta.getTabModelSelector().getModel(true).getCount()));
}
}