blob: c246a90665433a2023958d091097d0fc38568f73 [file] [log] [blame]
// Copyright 2019 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.features.start_surface;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.pressKey;
import static androidx.test.espresso.action.ViewActions.replaceText;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.Visibility.GONE;
import static androidx.test.espresso.matcher.ViewMatchers.Visibility.VISIBLE;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withParent;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import static org.chromium.chrome.features.start_surface.StartSurfaceConfiguration.START_SURFACE_RETURN_TIME_SECONDS;
import static org.chromium.chrome.features.start_surface.StartSurfaceMediator.FEED_VISIBILITY_CONSISTENCY;
import static org.chromium.chrome.features.start_surface.StartSurfaceTestUtils.START_SURFACE_TEST_BASE_PARAMS;
import static org.chromium.chrome.features.start_surface.StartSurfaceTestUtils.START_SURFACE_TEST_SINGLE_ENABLED_PARAMS;
import static org.chromium.chrome.features.start_surface.StartSurfaceTestUtils.getStartSurfaceLayoutType;
import static org.chromium.chrome.features.start_surface.StartSurfaceTestUtils.sClassParamsForStartSurfaceTest;
import static org.chromium.ui.test.util.ViewUtils.onViewWaiting;
import static org.chromium.ui.test.util.ViewUtils.waitForStableView;
import static org.chromium.ui.test.util.ViewUtils.waitForView;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.support.test.InstrumentationRegistry;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.widget.TextView;
import androidx.test.filters.LargeTest;
import androidx.test.filters.MediumTest;
import com.google.android.material.appbar.AppBarLayout;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.TimeUtils;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.test.params.ParameterAnnotations;
import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate;
import org.chromium.base.test.params.ParameterSet;
import org.chromium.base.test.params.ParameterizedRunner;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.CriteriaHelper;
import org.chromium.base.test.util.DisableIf;
import org.chromium.base.test.util.DisabledTest;
import org.chromium.base.test.util.DoNotBatch;
import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.Restriction;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeTabbedActivity;
import org.chromium.chrome.browser.feed.FeedPlaceholderLayout;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.init.AsyncInitializationActivity;
import org.chromium.chrome.browser.layouts.LayoutStateProvider;
import org.chromium.chrome.browser.layouts.LayoutTestUtils;
import org.chromium.chrome.browser.layouts.LayoutType;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabLaunchType;
import org.chromium.chrome.browser.tasks.ReturnToChromeUtil;
import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities;
import org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper;
import org.chromium.chrome.features.tasks.SingleTabSwitcherMediator;
import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.chrome.test.util.ChromeTabUtils;
import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
import org.chromium.chrome.test.util.browser.suggestions.SuggestionsDependenciesRule;
import org.chromium.components.browser_ui.bottomsheet.BottomSheetTestSupport;
import org.chromium.components.embedder_support.util.UrlUtilities;
import org.chromium.content_public.browser.test.util.RenderProcessHostUtils;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.ui.test.util.UiRestriction;
import java.io.IOException;
import java.util.List;
/**
* Integration tests of the {@link StartSurface} for cases with tabs. See {@link
* StartSurfaceNoTabsTest} for test that have no tabs. See {@link StartSurfaceTabSwitcherTest},
* {@link StartSurfaceMVTilesTest}, {@link StartSurfaceBackButtonTest} for more tests.
*/
@RunWith(ParameterizedRunner.class)
@UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
@Restriction(
{UiRestriction.RESTRICTION_TYPE_PHONE, Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE})
@EnableFeatures({ChromeFeatureList.START_SURFACE_ANDROID + "<Study"})
@CommandLineFlags.
Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "force-fieldtrials=Study/Group"})
@DoNotBatch(reason = "This test suite tests startup behaviors.")
public class StartSurfaceTest {
@ParameterAnnotations.ClassParameter
private static List<ParameterSet> sClassParams = sClassParamsForStartSurfaceTest;
private static final long MAX_TIMEOUT_MS = 40000L;
private static final long MILLISECONDS_PER_MINUTE = TimeUtils.SECONDS_PER_MINUTE * 1000;
@Rule
public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
@Rule
public SuggestionsDependenciesRule mSuggestionsDeps = new SuggestionsDependenciesRule();
/**
* Whether feature {@link ChromeFeatureList#INSTANT_START} is enabled.
*/
private final boolean mUseInstantStart;
/**
* Whether feature {@link ChromeFeatureList#START_SURFACE_RETURN_TIME} is enabled as
* "immediately". When immediate return is enabled, the Start surface is showing when Chrome is
* launched.
*/
private final boolean mImmediateReturn;
private CallbackHelper mLayoutChangedCallbackHelper;
private LayoutStateProvider.LayoutStateObserver mLayoutObserver;
@LayoutType
private int mCurrentlyActiveLayout;
public StartSurfaceTest(boolean useInstantStart, boolean immediateReturn) {
ChromeFeatureList.sInstantStart.setForTesting(useInstantStart);
mUseInstantStart = useInstantStart;
mImmediateReturn = immediateReturn;
}
@Before
public void setUp() throws IOException {
StartSurfaceTestUtils.setUpStartSurfaceTests(mImmediateReturn, mActivityTestRule);
mLayoutChangedCallbackHelper = new CallbackHelper();
if (isInstantReturn()) {
// Assume start surface is shown immediately, and the LayoutStateObserver may miss the
// first onFinishedShowing event.
mCurrentlyActiveLayout = StartSurfaceTestUtils.getStartSurfaceLayoutType();
}
mLayoutObserver = new LayoutStateProvider.LayoutStateObserver() {
@Override
public void onFinishedShowing(@LayoutType int layoutType) {
mCurrentlyActiveLayout = layoutType;
mLayoutChangedCallbackHelper.notifyCalled();
}
};
TestThreadUtils.runOnUiThreadBlocking(() -> {
mActivityTestRule.getActivity().getLayoutManagerSupplier().addObserver((manager) -> {
if (manager.getActiveLayout() != null) {
mCurrentlyActiveLayout = manager.getActiveLayout().getLayoutType();
mLayoutChangedCallbackHelper.notifyCalled();
}
manager.addObserver(mLayoutObserver);
});
});
}
@Test
@MediumTest
@Feature({"StartSurface"})
@CommandLineFlags.Add({START_SURFACE_TEST_SINGLE_ENABLED_PARAMS})
public void testShow_SingleAsHomepage() {
if (!mImmediateReturn) {
StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity());
}
ChromeTabbedActivity cta = mActivityTestRule.getActivity();
StartSurfaceTestUtils.waitForStartSurfaceVisible(
mLayoutChangedCallbackHelper, mCurrentlyActiveLayout, cta);
onViewWaiting(withId(R.id.primary_tasks_surface_view));
onViewWaiting(withId(R.id.search_box_text)).check(matches(isDisplayed()));
onViewWaiting(withId(R.id.mv_tiles_container)).check(matches(isDisplayed()));
onViewWaiting(withId(R.id.tab_switcher_title)).check(matches(isDisplayed()));
onViewWaiting(withId(R.id.carousel_tab_switcher_container)).check(matches(isDisplayed()));
onView(withId(R.id.tasks_surface_body)).check(matches(isDisplayed()));
StartSurfaceTestUtils.clickMoreTabs(cta);
StartSurfaceTestUtils.waitForTabSwitcherVisible(cta);
waitForView(allOf(withParent(withId(TabUiTestHelper.getTabSwitcherParentId(cta))),
withId(R.id.tab_list_view)));
// When the start surface refactoring is enabled, tapping the back button on Tab switcher
// will show the last tab.
if (TabUiTestHelper.getIsStartSurfaceRefactorEnabledFromUIThread(
mActivityTestRule.getActivity())) {
StartSurfaceTestUtils.pressBack(mActivityTestRule);
// Verifies that the last tab is opening.
LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.BROWSING);
} else {
StartSurfaceTestUtils.pressBack(mActivityTestRule);
onViewWaiting(allOf(withId(R.id.primary_tasks_surface_view), isDisplayed()));
StartSurfaceTestUtils.clickFirstTabInCarousel();
LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.BROWSING);
}
}
@Test
@MediumTest
@Feature({"StartSurface"})
@CommandLineFlags.
Add({START_SURFACE_TEST_SINGLE_ENABLED_PARAMS + "/hide_switch_when_no_incognito_tabs/false"})
@DisableFeatures(ChromeFeatureList.START_SURFACE_REFACTOR)
public void testShow_SingleAsHomepage_NoIncognitoSwitch() {
if (!mImmediateReturn) {
StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity());
}
ChromeTabbedActivity cta = mActivityTestRule.getActivity();
StartSurfaceTestUtils.waitForStartSurfaceVisible(
mLayoutChangedCallbackHelper, mCurrentlyActiveLayout, cta);
onViewWaiting(withId(R.id.primary_tasks_surface_view));
onViewWaiting(withId(R.id.search_box_text));
onViewWaiting(withId(R.id.mv_tiles_container)).check(matches(isDisplayed()));
onViewWaiting(withId(R.id.tab_switcher_title)).check(matches(isDisplayed()));
onViewWaiting(withId(R.id.carousel_tab_switcher_container)).check(matches(isDisplayed()));
onView(withId(R.id.tasks_surface_body)).check(matches(isDisplayed()));
// TODO(crbug.com/1076274): fix toolbar to make incognito switch part of the view.
onView(withId(R.id.incognito_toggle_tabs)).check(matches(withEffectiveVisibility(GONE)));
StartSurfaceTestUtils.clickMoreTabs(cta);
StartSurfaceTestUtils.waitForTabSwitcherVisible(cta);
onView(withId(R.id.incognito_toggle_tabs)).check(matches(withEffectiveVisibility(VISIBLE)));
StartSurfaceTestUtils.pressBack(mActivityTestRule);
onViewWaiting(withId(R.id.primary_tasks_surface_view));
if (isInstantReturn() && Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
// TODO(crbug.com/1139515): Fix incognito_toggle_tabs visibility AssertionFailedError
// issue.
// TODO(crbug.com/1092642): Fix androidx.test.espresso.PerformException issue when
// performing a single click on position: 0. See code below.
return;
}
onView(withId(R.id.incognito_toggle_tabs)).check(matches(withEffectiveVisibility(GONE)));
StartSurfaceTestUtils.clickFirstTabInCarousel();
LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.BROWSING);
}
@Test
@MediumTest
@Feature({"StartSurface"})
@CommandLineFlags.
Add({START_SURFACE_TEST_SINGLE_ENABLED_PARAMS + "/hide_switch_when_no_incognito_tabs/false"})
@EnableFeatures(ChromeFeatureList.START_SURFACE_REFACTOR)
public void testShow_SingleAsHomepage_NoIncognitoSwitch_RefactorEnabled() {
if (!mImmediateReturn) {
StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity());
}
ChromeTabbedActivity cta = mActivityTestRule.getActivity();
StartSurfaceTestUtils.waitForStartSurfaceVisible(
mLayoutChangedCallbackHelper, mCurrentlyActiveLayout, cta);
onViewWaiting(withId(R.id.primary_tasks_surface_view));
onViewWaiting(withId(R.id.search_box_text));
onViewWaiting(withId(R.id.mv_tiles_container)).check(matches(isDisplayed()));
onViewWaiting(withId(R.id.tab_switcher_title)).check(matches(isDisplayed()));
onViewWaiting(withId(R.id.carousel_tab_switcher_container)).check(matches(isDisplayed()));
onView(withId(R.id.tasks_surface_body)).check(matches(isDisplayed()));
// TODO(crbug.com/1076274): fix toolbar to make incognito switch part of the view.
onView(withId(R.id.incognito_toggle_tabs)).check(matches(withEffectiveVisibility(GONE)));
StartSurfaceTestUtils.clickMoreTabs(cta);
StartSurfaceTestUtils.waitForTabSwitcherVisible(cta);
onView(withId(R.id.incognito_toggle_tabs)).check(matches(withEffectiveVisibility(VISIBLE)));
// Verifies that the tab switcher is hidden.
StartSurfaceTestUtils.pressBack(mActivityTestRule);
LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.BROWSING);
}
@Test
@LargeTest
@Feature({"StartSurface"})
@CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS
+ "open_ntp_instead_of_start/false/open_start_as_homepage/true"})
// clang-format off
public void testShow_SingleAsHomepage_SingleTab() {
// clang-format on
if (!mImmediateReturn) {
StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity());
}
ChromeTabbedActivity cta = mActivityTestRule.getActivity();
StartSurfaceTestUtils.waitForStartSurfaceVisible(
mLayoutChangedCallbackHelper, mCurrentlyActiveLayout, cta);
onViewWaiting(withId(R.id.primary_tasks_surface_view));
onViewWaiting(withId(R.id.search_box_text));
onView(withId(R.id.mv_tiles_container)).check(matches(isDisplayed()));
onView(withId(R.id.tab_switcher_title)).check(matches(withEffectiveVisibility(GONE)));
onView(withId(R.id.carousel_tab_switcher_container)).check(matches(isDisplayed()));
onView(withId(R.id.single_tab_view)).check(matches(isDisplayed()));
onView(withId(R.id.tasks_surface_body)).check(matches(isDisplayed()));
if (!isInstantReturn()) {
// TODO(crbug.com/1076274): fix toolbar to make incognito switch part of the view.
onView(withId(R.id.incognito_toggle_tabs))
.check(matches(withEffectiveVisibility(GONE)));
}
onViewWaiting(allOf(withId(R.id.tab_title_view), withText(not(is("")))));
StartSurfaceTestUtils.clickTabSwitcherButton(cta);
StartSurfaceTestUtils.waitForTabSwitcherVisible(cta);
if (isInstantReturn()) {
// TODO(crbug.com/1076274): fix toolbar to avoid wrongly focusing on the toolbar
// omnibox.
return;
}
// When the start surface refactoring is enabled, tapping the back button on Tab switcher
// will show the last tab.
if (TabUiTestHelper.getIsStartSurfaceRefactorEnabledFromUIThread(
mActivityTestRule.getActivity())) {
StartSurfaceTestUtils.pressBack(mActivityTestRule);
// Verifies that the last tab is opening.
LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.BROWSING);
} else {
StartSurfaceTestUtils.pressBack(mActivityTestRule);
onViewWaiting(withId(R.id.primary_tasks_surface_view));
onViewWaiting(withId(R.id.single_tab_view)).perform(click());
LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.BROWSING);
}
}
@Test
@MediumTest
@Feature({"StartSurface"})
// clang-format off
@CommandLineFlags.Add({START_SURFACE_TEST_SINGLE_ENABLED_PARAMS})
public void testShow_SingleAsHomepage_FromResumeShowStart() throws Exception {
// clang-format on
if (!mImmediateReturn) {
StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity());
}
ChromeTabbedActivity cta = mActivityTestRule.getActivity();
CriteriaHelper.pollUiThread(()
-> cta.getLayoutManager() != null
&& cta.getLayoutManager().isLayoutVisible(
StartSurfaceTestUtils.getStartSurfaceLayoutType()));
StartSurfaceTestUtils.waitForTabModel(cta);
TestThreadUtils.runOnUiThreadBlocking(
() -> { cta.getTabModelSelector().getModel(false).closeAllTabs(); });
TabUiTestHelper.verifyTabModelTabCount(cta, 0, 0);
assertTrue(cta.getLayoutManager().isLayoutVisible(getStartSurfaceLayoutType()));
TestThreadUtils.runOnUiThreadBlocking(
() -> cta.getTabCreator(true /*incognito*/).launchNTP());
TabUiTestHelper.verifyTabModelTabCount(cta, 0, 1);
// Simulates pressing the Android's home button and bringing Chrome to the background.
StartSurfaceTestUtils.pressHome();
// Simulates pressing Chrome's icon and launching Chrome from warm start.
mActivityTestRule.resumeMainActivityFromLauncher();
StartSurfaceTestUtils.waitForTabModel(cta);
assertTrue(cta.getTabModelSelector().getCurrentModel().isIncognito());
if (mImmediateReturn) {
StartSurfaceTestUtils.waitForTabSwitcherVisible(
mLayoutChangedCallbackHelper, mCurrentlyActiveLayout, cta);
} else {
int container_id = ChromeFeatureList.isEnabled(ChromeFeatureList.INCOGNITO_NTP_REVAMP)
? R.id.revamped_incognito_ntp_container
: R.id.new_tab_incognito_container;
onViewWaiting(withId(container_id)).check(matches(isDisplayed()));
}
}
@Test
@MediumTest
@Feature({"StartSurface"})
@CommandLineFlags.Add({START_SURFACE_TEST_SINGLE_ENABLED_PARAMS})
@DisabledTest(message = "crbug.com/1170673 - NoInstant_NoReturn version is flaky")
public void testSearchInSingleSurface() {
if (!mImmediateReturn) {
StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity());
}
ChromeTabbedActivity cta = mActivityTestRule.getActivity();
StartSurfaceTestUtils.waitForStartSurfaceVisible(
mLayoutChangedCallbackHelper, mCurrentlyActiveLayout, cta);
TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0);
onViewWaiting(withId(R.id.search_box_text)).perform(replaceText("about:blank"));
CriteriaHelper.pollInstrumentationThread(
() -> StartSurfaceTestUtils.isKeyboardShown(mActivityTestRule));
onViewWaiting(withId(R.id.url_bar)).perform(pressKey(KeyEvent.KEYCODE_ENTER));
LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.BROWSING);
TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0);
ChromeTabUtils.waitForTabPageLoaded(cta.getActivityTab(), (String) null);
TestThreadUtils.runOnUiThreadBlocking(() -> cta.getTabCreator(false).launchNTP());
StartSurfaceTestUtils.waitForStartSurfaceVisible(
mLayoutChangedCallbackHelper, mCurrentlyActiveLayout, cta);
onViewWaiting(withId(R.id.primary_tasks_surface_view));
TextView urlBar = cta.findViewById(R.id.url_bar);
Assert.assertFalse(urlBar.isFocused());
waitForStableView(cta.findViewById(R.id.search_box_text));
onView(withId(R.id.search_box_text)).perform(click());
Assert.assertTrue(TextUtils.isEmpty(urlBar.getText()));
}
@Test
@MediumTest
@Feature({"StartSurface"})
@CommandLineFlags.
Add({START_SURFACE_TEST_BASE_PARAMS + "hide_switch_when_no_incognito_tabs/false"})
public void testCreateNewTab_OpenNTPInsteadOfStart() {
ChromeTabbedActivity cta = mActivityTestRule.getActivity();
StartSurfaceTestUtils.waitForTabModel(cta);
TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0);
// Create a new tab from menu should create NTP instead of showing start.
ChromeTabUtils.newTabFromMenu(
InstrumentationRegistry.getInstrumentation(), cta, false, false);
TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0);
if (isInstantReturn()) {
// TODO(crbug.com/1076274): fix toolbar to avoid wrongly focusing on the toolbar
// omnibox.
return;
}
LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.BROWSING);
TabUiTestHelper.enterTabSwitcher(cta);
TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0);
LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.TAB_SWITCHER);
// Click plus button from top toolbar should create NTP instead of showing start surface.
onViewWaiting(withId(R.id.new_tab_button)).perform(click());
TabUiTestHelper.verifyTabModelTabCount(cta, 3, 0);
assertTrue(cta.getLayoutManager().isLayoutVisible(LayoutType.BROWSING));
}
@Test
@MediumTest
@Feature({"StartSurface"})
public void testHomeButton_OpenNTPInsteadOfStart() {
ChromeTabbedActivity cta = mActivityTestRule.getActivity();
StartSurfaceTestUtils.waitForTabModel(cta);
TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0);
ChromeTabUtils.newTabFromMenu(
InstrumentationRegistry.getInstrumentation(), cta, false, false);
TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0);
if (isInstantReturn()) {
// TODO(crbug.com/1076274): fix toolbar to avoid wrongly focusing on the toolbar
// omnibox.
return;
}
mActivityTestRule.loadUrl("about:blank");
CriteriaHelper.pollUiThread(()
-> cta.getTabModelSelector()
.getCurrentTab()
.getOriginalUrl()
.getSpec()
.equals("about:blank"));
// Click the home button should navigate to NTP instead of showing start surface.
StartSurfaceTestUtils.pressHomePageButton(cta);
CriteriaHelper.pollUiThread(
() -> UrlUtilities.isNTPUrl(cta.getTabModelSelector().getCurrentTab().getUrl()));
assertFalse(cta.getLayoutManager().isLayoutVisible(
StartSurfaceTestUtils.getStartSurfaceLayoutType()));
}
/**
* Tests that histograms are recorded only if the StartSurface is shown when Chrome is launched
* from cold start.
*/
@Test
@MediumTest
@Restriction({UiRestriction.RESTRICTION_TYPE_PHONE})
@EnableFeatures({ChromeFeatureList.START_SURFACE_RETURN_TIME + "<Study",
ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID,
ChromeFeatureList.START_SURFACE_ANDROID + "<Study"})
@CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS
+ "open_ntp_instead_of_start/false/open_start_as_homepage/true",
// Disable feed placeholder animation because it causes waitForDeferredStartup() to time
// out.
FeedPlaceholderLayout.DISABLE_ANIMATION_SWITCH})
// clang-format off
public void startSurfaceRecordHistogramsTest_SingleTab() {
// clang-format on
startSurfaceRecordHistogramsTest(true);
}
@Test
@MediumTest
@Restriction({UiRestriction.RESTRICTION_TYPE_PHONE})
// clang-format off
@EnableFeatures({ChromeFeatureList.START_SURFACE_RETURN_TIME + "<Study",
ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID,
ChromeFeatureList.START_SURFACE_ANDROID + "<Study"})
@CommandLineFlags.Add({START_SURFACE_TEST_SINGLE_ENABLED_PARAMS,
// Disable feed placeholder animation because it causes waitForDeferredStartup() to time
// out.
FeedPlaceholderLayout.DISABLE_ANIMATION_SWITCH})
public void startSurfaceRecordHistogramsTest_CarouselTab() {
// clang-format on
startSurfaceRecordHistogramsTest(false);
}
private void startSurfaceRecordHistogramsTest(boolean isSingleTabSwitcher) {
if (!mImmediateReturn) {
assertNotEquals(0, START_SURFACE_RETURN_TIME_SECONDS.getValue());
StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity());
} else {
assertEquals(0, START_SURFACE_RETURN_TIME_SECONDS.getValue());
}
Assert.assertEquals("single", StartSurfaceConfiguration.START_SURFACE_VARIATION.getValue());
Assert.assertEquals(isSingleTabSwitcher,
StartSurfaceConfiguration.START_SURFACE_LAST_ACTIVE_TAB_ONLY.getValue());
StartSurfaceTestUtils.waitForStartSurfaceVisible(mLayoutChangedCallbackHelper,
mCurrentlyActiveLayout, mActivityTestRule.getActivity());
mActivityTestRule.waitForActivityNativeInitializationComplete();
StartSurfaceTestUtils.waitForDeferredStartup(mActivityTestRule);
boolean isInstantStart =
TabUiFeatureUtilities.supportInstantStart(false, mActivityTestRule.getActivity());
Assert.assertEquals(1,
RecordHistogram.getHistogramTotalCountForTesting(
StartSurfaceConfiguration.getHistogramName(
AsyncInitializationActivity.FIRST_DRAW_COMPLETED_TIME_MS_UMA,
isInstantStart)));
int expectedRecordCount = mImmediateReturn ? 1 : 0;
// Histograms should be only recorded when StartSurface is shown immediately after
// launch.
if (isSingleTabSwitcher) {
Assert.assertEquals(expectedRecordCount,
RecordHistogram.getHistogramTotalCountForTesting(
StartSurfaceConfiguration.getHistogramName(
SingleTabSwitcherMediator.SINGLE_TAB_TITLE_AVAILABLE_TIME_UMA,
isInstantStart)));
}
Assert.assertEquals(expectedRecordCount,
RecordHistogram.getHistogramTotalCountForTesting(
ReturnToChromeUtil
.LAST_VISITED_TAB_IS_SRP_WHEN_OVERVIEW_IS_SHOWN_AT_LAUNCH_UMA));
Assert.assertEquals(expectedRecordCount,
RecordHistogram.getHistogramTotalCountForTesting(
StartSurfaceConfiguration.getHistogramName(
ExploreSurfaceCoordinator.FEED_CONTENT_FIRST_LOADED_TIME_MS_UMA,
isInstantStart)));
Assert.assertEquals(expectedRecordCount,
RecordHistogram.getHistogramTotalCountForTesting(
StartSurfaceConfiguration.getHistogramName(
ExploreSurfaceCoordinator.FEED_STREAM_CREATED_TIME_MS_UMA,
isInstantStart)));
Assert.assertEquals(isInstantReturn() ? 1 : 0,
RecordHistogram.getHistogramTotalCountForTesting(
StartSurfaceConfiguration.getHistogramName(
FeedPlaceholderCoordinator.FEEDS_PLACEHOLDER_SHOWN_TIME_UMA,
true)));
Assert.assertEquals(expectedRecordCount,
RecordHistogram.getHistogramTotalCountForTesting(FEED_VISIBILITY_CONSISTENCY));
Assert.assertEquals(expectedRecordCount,
RecordHistogram.getHistogramValueCountForTesting(FEED_VISIBILITY_CONSISTENCY, 1));
int showAtStartup = mImmediateReturn ? 1 : 0;
Assert.assertEquals(1,
RecordHistogram.getHistogramValueCountForTesting(
StartSurfaceCoordinator.START_SHOWN_AT_STARTUP_UMA, showAtStartup));
}
@Test
@MediumTest
@Feature({"StartSurface"})
@CommandLineFlags.Add({START_SURFACE_TEST_SINGLE_ENABLED_PARAMS})
public void testShow_SingleAsHomepage_VoiceSearchButtonShown() {
if (!mImmediateReturn) {
StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity());
}
StartSurfaceTestUtils.waitForStartSurfaceVisible(mLayoutChangedCallbackHelper,
mCurrentlyActiveLayout, mActivityTestRule.getActivity());
onViewWaiting(withId(R.id.primary_tasks_surface_view));
onView(withId(R.id.search_box_text)).check(matches(isDisplayed()));
onView(withId(R.id.voice_search_button)).check(matches(isDisplayed()));
}
@Test
@MediumTest
@Feature({"StartSurface"})
@CommandLineFlags.Add({START_SURFACE_TEST_SINGLE_ENABLED_PARAMS})
public void testShow_SingleAsHomepage_BottomSheet() {
if (!mImmediateReturn) {
StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity());
}
ChromeTabbedActivity cta = mActivityTestRule.getActivity();
BottomSheetTestSupport bottomSheetTestSupport = new BottomSheetTestSupport(
cta.getRootUiCoordinatorForTesting().getBottomSheetController());
StartSurfaceTestUtils.waitForStartSurfaceVisible(
mLayoutChangedCallbackHelper, mCurrentlyActiveLayout, cta);
TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0);
assertFalse(bottomSheetTestSupport.hasSuppressionTokens());
if (isInstantReturn()) {
// TODO(crbug.com/1076274): fix toolbar to avoid wrongly focusing on the toolbar
// omnibox.
return;
}
/** Verifies the case of start surface -> a tab -> tab switcher -> start surface. */
StartSurfaceTestUtils.clickFirstTabInCarousel();
assertFalse(bottomSheetTestSupport.hasSuppressionTokens());
TabUiTestHelper.enterTabSwitcher(cta);
StartSurfaceTestUtils.waitForTabSwitcherVisible(cta);
assertTrue(bottomSheetTestSupport.hasSuppressionTokens());
TestThreadUtils.runOnUiThreadBlocking(() -> cta.getTabCreator(false).launchNTP());
onViewWaiting(withId(R.id.primary_tasks_surface_view));
assertFalse(bottomSheetTestSupport.hasSuppressionTokens());
/** Verifies the case of navigating to a tab -> start surface -> tab switcher. */
StartSurfaceTestUtils.clickFirstTabInCarousel();
assertFalse(bottomSheetTestSupport.hasSuppressionTokens());
StartSurfaceTestUtils.pressHomePageButton(cta);
StartSurfaceTestUtils.waitForStartSurfaceVisible(cta);
assertFalse(bottomSheetTestSupport.hasSuppressionTokens());
StartSurfaceTestUtils.clickTabSwitcherButton(cta);
StartSurfaceTestUtils.waitForTabSwitcherVisible(cta);
assertTrue(bottomSheetTestSupport.hasSuppressionTokens());
}
@Test
@MediumTest
@Feature({"StartSurface"})
@CommandLineFlags.Add({START_SURFACE_TEST_SINGLE_ENABLED_PARAMS})
public void testShow_SingleAsHomepage_ResetScrollPosition() {
if (!mImmediateReturn) {
StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity());
}
ChromeTabbedActivity cta = mActivityTestRule.getActivity();
StartSurfaceTestUtils.waitForStartSurfaceVisible(
mLayoutChangedCallbackHelper, mCurrentlyActiveLayout, cta);
TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0);
// Scroll the toolbar.
StartSurfaceTestUtils.scrollToolbar(cta);
AppBarLayout taskSurfaceHeader = cta.findViewById(R.id.task_surface_header);
assertNotEquals(taskSurfaceHeader.getBottom(), taskSurfaceHeader.getHeight());
// Verifies the case of scrolling Start surface -> tab switcher -> tap "+1" button ->
// Start surface. The Start surface should reset its scroll position.
StartSurfaceTestUtils.clickTabSwitcherButton(cta);
StartSurfaceTestUtils.waitForTabSwitcherVisible(cta);
TestThreadUtils.runOnUiThreadBlocking(() -> cta.getTabCreator(false).launchNTP());
onViewWaiting(withId(R.id.primary_tasks_surface_view));
// The Start surface should reset its scroll position.
CriteriaHelper.pollInstrumentationThread(
() -> taskSurfaceHeader.getBottom() == taskSurfaceHeader.getHeight());
}
@Test
@MediumTest
@Feature({"StartSurface"})
@EnableFeatures(ChromeFeatureList.START_SURFACE_REFACTOR)
@CommandLineFlags.Add({START_SURFACE_TEST_SINGLE_ENABLED_PARAMS})
@DisabledTest(message = "Flaky, crbug.com/1407193")
public void testShow_SingleAsHomepage_DoNotResetScrollPositionFromBack() {
assumeTrue(mImmediateReturn);
ChromeTabbedActivity cta = mActivityTestRule.getActivity();
StartSurfaceTestUtils.waitForStartSurfaceVisible(
mLayoutChangedCallbackHelper, mCurrentlyActiveLayout, cta);
TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0);
// Scroll the toolbar.
StartSurfaceTestUtils.scrollToolbar(cta);
AppBarLayout taskSurfaceHeader = cta.findViewById(R.id.task_surface_header);
assertNotEquals(taskSurfaceHeader.getBottom(), taskSurfaceHeader.getHeight());
// Verifies the case of scrolling Start surface -> MV tile -> tapping back ->
// Start surface. The Start surface should not reset its scroll position.
StartSurfaceTestUtils.launchFirstMVTile(cta, 1);
Assert.assertEquals("The launched tab should have the launch type FROM_START_SURFACE",
TabLaunchType.FROM_START_SURFACE,
cta.getActivityTabProvider().get().getLaunchType());
StartSurfaceTestUtils.pressBack(mActivityTestRule);
// Back gesture on the tab should take us back to the start surface homepage.
StartSurfaceTestUtils.waitForStartSurfaceVisible(
mLayoutChangedCallbackHelper, mCurrentlyActiveLayout, cta);
// The Start surface should not reset its scroll position.
CriteriaHelper.pollInstrumentationThread(
() -> taskSurfaceHeader.getBottom() != taskSurfaceHeader.getHeight());
}
@Test
@MediumTest
@Feature({"StartSurface"})
@CommandLineFlags.Add({START_SURFACE_TEST_SINGLE_ENABLED_PARAMS})
public void singleAsHomepage_PressHomeButtonWillKeepTab() {
if (!mImmediateReturn) {
StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity());
}
ChromeTabbedActivity cta = mActivityTestRule.getActivity();
StartSurfaceTestUtils.waitForStartSurfaceVisible(
mLayoutChangedCallbackHelper, mCurrentlyActiveLayout, cta);
onViewWaiting(allOf(withId(R.id.mv_tiles_container), isDisplayed()));
// Launches the first site in mv tiles.
StartSurfaceTestUtils.launchFirstMVTile(cta, /* currentTabCount = */ 1);
if (isInstantReturn() && Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
// Fix the issue that failed to perform a single click on the tab switcher button.
// See code below.
return;
}
Tab tab = cta.getActivityTab();
StartSurfaceTestUtils.pressHomePageButton(cta);
waitForView(withId(R.id.primary_tasks_surface_view));
StartSurfaceTestUtils.waitForStartSurfaceVisible(cta);
Assert.assertEquals(TabLaunchType.FROM_START_SURFACE, tab.getLaunchType());
TestThreadUtils.runOnUiThreadBlocking(
() -> { Assert.assertTrue(StartSurfaceUserData.getKeepTab(tab)); });
}
@Test
@MediumTest
@Feature({"StartSurface"})
// clang-format off
@CommandLineFlags.Add({START_SURFACE_TEST_SINGLE_ENABLED_PARAMS})
@DisableIf.Build(sdk_is_greater_than = VERSION_CODES.O_MR1, supported_abis_includes = "x86",
message = "Flaky, see crbug.com/1258154")
public void testNotShowIncognitoHomepage() {
// clang-format on
if (!mImmediateReturn) {
StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity());
}
ChromeTabbedActivity cta = mActivityTestRule.getActivity();
StartSurfaceTestUtils.waitForStartSurfaceVisible(
mLayoutChangedCallbackHelper, mCurrentlyActiveLayout, cta);
TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0);
TestThreadUtils.runOnUiThreadBlocking(
() -> { cta.getTabModelSelector().getModel(false).closeAllTabs(); });
TabUiTestHelper.verifyTabModelTabCount(cta, 0, 0);
assertTrue(cta.getLayoutManager().isLayoutVisible(
StartSurfaceTestUtils.getStartSurfaceLayoutType()));
TestThreadUtils.runOnUiThreadBlocking(
() -> cta.getTabCreator(true /*incognito*/).launchNTP());
TabUiTestHelper.verifyTabModelTabCount(cta, 0, 1);
// Simulates pressing the home button. Incognito tab should stay and homepage shouldn't
// show.
onView(withId(R.id.home_button)).perform(click());
int container_id = ChromeFeatureList.isEnabled(ChromeFeatureList.INCOGNITO_NTP_REVAMP)
? R.id.revamped_incognito_ntp_container
: R.id.new_tab_incognito_container;
onViewWaiting(withId(container_id)).check(matches(isDisplayed()));
assertFalse(cta.getLayoutManager().isLayoutVisible(
StartSurfaceTestUtils.getStartSurfaceLayoutType()));
}
@Test
@MediumTest
@Feature({"StartSurface"})
// clang-format off
@CommandLineFlags.Add({START_SURFACE_TEST_SINGLE_ENABLED_PARAMS})
public void test_DoNotLoadLastSelectedTabOnStartup() {
// clang-format on
doTestNotLoadLastSelectedTabOnStartupImpl();
}
@Test
@MediumTest
@Feature({"StartSurface"})
// clang-format off
public void test_DoNotLoadLastSelectedTabOnStartupV2() {
// clang-format on
doTestNotLoadLastSelectedTabOnStartupImpl();
}
private void doTestNotLoadLastSelectedTabOnStartupImpl() {
assumeTrue(mImmediateReturn);
ChromeTabbedActivity cta = mActivityTestRule.getActivity();
StartSurfaceTestUtils.waitForStartSurfaceVisible(
mLayoutChangedCallbackHelper, mCurrentlyActiveLayout, cta);
TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0);
Assert.assertEquals(0, RenderProcessHostUtils.getCurrentRenderProcessCount());
StartSurfaceTestUtils.launchFirstMVTile(cta, /* currentTabCount = */ 1);
TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0);
StartSurfaceTestUtils.waitForCurrentTabLoaded(mActivityTestRule);
Assert.assertEquals(1, RenderProcessHostUtils.getCurrentRenderProcessCount());
}
/**
* @return Whether both features {@link ChromeFeatureList#INSTANT_START} and
* {@link ChromeFeatureList#START_SURFACE_RETURN_TIME} are enabled.
*/
private boolean isInstantReturn() {
return mUseInstantStart && mImmediateReturn;
}
}