| // 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.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.equalTo; |
| import static org.hamcrest.CoreMatchers.is; |
| import static org.hamcrest.CoreMatchers.not; |
| import static org.hamcrest.MatcherAssert.assertThat; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assume.assumeTrue; |
| |
| 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.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; |
| import android.os.Build.VERSION_CODES; |
| import android.support.test.InstrumentationRegistry; |
| import android.support.test.uiautomator.UiDevice; |
| import android.text.TextUtils; |
| import android.view.KeyEvent; |
| import android.view.View; |
| import android.widget.TextView; |
| |
| import androidx.test.filters.LargeTest; |
| import androidx.test.filters.MediumTest; |
| |
| import com.google.android.material.appbar.AppBarLayout; |
| |
| import org.hamcrest.Matchers; |
| import org.junit.Assert; |
| import org.junit.Assume; |
| 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.Feature; |
| import org.chromium.base.test.util.FlakyTest; |
| import org.chromium.base.test.util.Restriction; |
| import org.chromium.chrome.browser.ChromeTabbedActivity; |
| import org.chromium.chrome.browser.feed.FeedPlaceholderLayout; |
| import org.chromium.chrome.browser.flags.CachedFeatureFlags; |
| 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.LayoutType; |
| import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; |
| import org.chromium.chrome.browser.preferences.SharedPreferencesManager; |
| import org.chromium.chrome.browser.tab.Tab; |
| import org.chromium.chrome.browser.tab.TabLaunchType; |
| import org.chromium.chrome.browser.tasks.ReturnToChromeExperimentsUtil; |
| import org.chromium.chrome.browser.tasks.SingleTabSwitcherMediator; |
| import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities; |
| import org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper; |
| import org.chromium.chrome.browser.ui.appmenu.AppMenuTestSupport; |
| import org.chromium.chrome.start_surface.R; |
| import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; |
| import org.chromium.chrome.test.ChromeTabbedActivityTestRule; |
| import org.chromium.chrome.test.util.ChromeApplicationTestUtils; |
| import org.chromium.chrome.test.util.ChromeTabUtils; |
| import org.chromium.chrome.test.util.OverviewModeBehaviorWatcher; |
| 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.modelutil.MVCListAdapter.ModelList; |
| import org.chromium.ui.test.util.UiRestriction; |
| |
| import java.io.IOException; |
| import java.util.List; |
| import java.util.concurrent.ExecutionException; |
| |
| /** |
| * 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}, {@link |
| * StartSurfaceFinaleTest} 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"}) |
| 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#TAB_SWITCHER_ON_RETURN} 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) { |
| CachedFeatureFlags.setForTesting(ChromeFeatureList.INSTANT_START, 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 = LayoutType.TAB_SWITCHER; |
| } |
| |
| 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"}) |
| // clang-format off |
| @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS + |
| "/home_button_on_grid_tab_switcher/false"}) |
| public void testShow_SingleAsHomepage() { |
| // clang-format on |
| if (!mImmediateReturn) { |
| StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity()); |
| } |
| StartSurfaceTestUtils.waitForOverviewVisible( |
| mLayoutChangedCallbackHelper, mCurrentlyActiveLayout); |
| ChromeTabbedActivity cta = mActivityTestRule.getActivity(); |
| |
| onViewWaiting(withId(R.id.primary_tasks_surface_view)); |
| onViewWaiting(withId(R.id.search_box_text)).check(matches(isDisplayed())); |
| onView(withId(org.chromium.chrome.tab_ui.R.id.mv_tiles_container)) |
| .check(matches(isDisplayed())); |
| onView(withId(org.chromium.chrome.tab_ui.R.id.tab_switcher_title)) |
| .check(matches(isDisplayed())); |
| onView(withId(org.chromium.chrome.tab_ui.R.id.carousel_tab_switcher_container)) |
| .check(matches(isDisplayed())); |
| onView(withId(org.chromium.chrome.tab_ui.R.id.tasks_surface_body)) |
| .check(matches(isDisplayed())); |
| |
| StartSurfaceTestUtils.clickMoreTabs(cta); |
| onViewWaiting(withId(R.id.secondary_tasks_surface_view)); |
| waitForView(allOf(withParent(withId(R.id.secondary_tasks_surface_view)), |
| withId(org.chromium.chrome.tab_ui.R.id.tab_list_view))); |
| assertEquals(cta.findViewById(R.id.home_button_on_tab_switcher).getVisibility(), View.GONE); |
| |
| StartSurfaceTestUtils.pressBack(mActivityTestRule); |
| onViewWaiting(allOf(withId(R.id.primary_tasks_surface_view), isDisplayed())); |
| |
| OverviewModeBehaviorWatcher hideWatcher = TabUiTestHelper.createOverviewHideWatcher(cta); |
| StartSurfaceTestUtils.clickFirstTabInCarousel(); |
| hideWatcher.waitForBehavior(); |
| } |
| |
| @Test |
| @MediumTest |
| @Feature({"StartSurface"}) |
| @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS}) |
| public void testShow_SingleAsHomepage_NoIncognitoSwitch() { |
| if (!mImmediateReturn) { |
| StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity()); |
| } |
| |
| StartSurfaceTestUtils.waitForOverviewVisible( |
| mLayoutChangedCallbackHelper, mCurrentlyActiveLayout); |
| ChromeTabbedActivity cta = mActivityTestRule.getActivity(); |
| |
| onViewWaiting(withId(R.id.primary_tasks_surface_view)); |
| onViewWaiting(withId(R.id.search_box_text)); |
| onView(withId(org.chromium.chrome.tab_ui.R.id.mv_tiles_container)) |
| .check(matches(isDisplayed())); |
| onView(withId(org.chromium.chrome.tab_ui.R.id.tab_switcher_title)) |
| .check(matches(isDisplayed())); |
| onView(withId(org.chromium.chrome.tab_ui.R.id.carousel_tab_switcher_container)) |
| .check(matches(isDisplayed())); |
| onView(withId(org.chromium.chrome.tab_ui.R.id.tasks_surface_body)) |
| .check(matches(isDisplayed())); |
| |
| // TODO(crbug.com/1076274): fix toolbar to make incognito switch part of the view. |
| onView(withId(org.chromium.chrome.tab_ui.R.id.incognito_toggle_tabs)) |
| .check(matches(withEffectiveVisibility(GONE))); |
| |
| StartSurfaceTestUtils.clickMoreTabs(cta); |
| onViewWaiting(withId(R.id.secondary_tasks_surface_view)); |
| onView(withId(org.chromium.chrome.tab_ui.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.LOLLIPOP |
| && 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(org.chromium.chrome.tab_ui.R.id.incognito_toggle_tabs)) |
| .check(matches(withEffectiveVisibility(GONE))); |
| |
| OverviewModeBehaviorWatcher hideWatcher = TabUiTestHelper.createOverviewHideWatcher(cta); |
| StartSurfaceTestUtils.clickFirstTabInCarousel(); |
| hideWatcher.waitForBehavior(); |
| } |
| |
| @Test |
| @LargeTest |
| @Feature({"StartSurface"}) |
| // clang-format off |
| @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS + |
| "/exclude_mv_tiles/true/hide_switch_when_no_incognito_tabs/true"}) |
| public void testShow_SingleAsHomepage_NoMVTiles() { |
| // clang-format on |
| if (!mImmediateReturn) { |
| StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity()); |
| } |
| StartSurfaceTestUtils.waitForOverviewVisible( |
| mLayoutChangedCallbackHelper, mCurrentlyActiveLayout); |
| ChromeTabbedActivity cta = mActivityTestRule.getActivity(); |
| |
| onViewWaiting(withId(R.id.primary_tasks_surface_view)); |
| onViewWaiting(withId(R.id.search_box_text)); |
| onView(withId(org.chromium.chrome.tab_ui.R.id.mv_tiles_container)) |
| .check(matches(withEffectiveVisibility(GONE))); |
| onView(withId(org.chromium.chrome.tab_ui.R.id.tab_switcher_title)) |
| .check(matches(isDisplayed())); |
| onView(withId(org.chromium.chrome.tab_ui.R.id.carousel_tab_switcher_container)) |
| .check(matches(isDisplayed())); |
| onView(withId(org.chromium.chrome.tab_ui.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(org.chromium.chrome.tab_ui.R.id.incognito_toggle_tabs)) |
| .check(matches(withEffectiveVisibility(GONE))); |
| } |
| |
| StartSurfaceTestUtils.clickMoreTabs(cta); |
| onViewWaiting(withId(R.id.secondary_tasks_surface_view)); |
| |
| StartSurfaceTestUtils.pressBack(mActivityTestRule); |
| onViewWaiting(withId(R.id.primary_tasks_surface_view)); |
| |
| if (isInstantReturn() |
| && (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP |
| && Build.VERSION.SDK_INT < Build.VERSION_CODES.O)) { |
| // TODO(crbug.com/1092642): Fix androidx.test.espresso.PerformException issue when |
| // performing a single click on position: 0. See code below. |
| return; |
| } |
| |
| OverviewModeBehaviorWatcher hideWatcher = TabUiTestHelper.createOverviewHideWatcher(cta); |
| StartSurfaceTestUtils.clickFirstTabInCarousel(); |
| hideWatcher.waitForBehavior(); |
| } |
| |
| @Test |
| @LargeTest |
| @Feature({"StartSurface"}) |
| // clang-format off |
| @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS + "/exclude_mv_tiles/true" + |
| "/hide_switch_when_no_incognito_tabs/true/show_last_active_tab_only/true"}) |
| public void testShow_SingleAsHomepage_SingleTabNoMVTiles() { |
| // clang-format on |
| Assume.assumeFalse("https://crbug.com/1205642, https://crbug.com/1214303", |
| !mUseInstantStart && mImmediateReturn && VERSION.SDK_INT == VERSION_CODES.M); |
| if (!mImmediateReturn) { |
| StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity()); |
| } |
| StartSurfaceTestUtils.waitForOverviewVisible( |
| mLayoutChangedCallbackHelper, mCurrentlyActiveLayout); |
| ChromeTabbedActivity cta = mActivityTestRule.getActivity(); |
| |
| onViewWaiting(withId(R.id.primary_tasks_surface_view)); |
| onViewWaiting(withId(R.id.search_box_text)); |
| onView(withId(org.chromium.chrome.tab_ui.R.id.mv_tiles_container)) |
| .check(matches(withEffectiveVisibility(GONE))); |
| onView(withId(org.chromium.chrome.tab_ui.R.id.tab_switcher_title)) |
| .check(matches(isDisplayed())); |
| onView(withId(org.chromium.chrome.tab_ui.R.id.carousel_tab_switcher_container)) |
| .check(matches(isDisplayed())); |
| onView(withId(org.chromium.chrome.tab_ui.R.id.single_tab_view)) |
| .check(matches(isDisplayed())); |
| onView(withId(org.chromium.chrome.tab_ui.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(org.chromium.chrome.tab_ui.R.id.incognito_toggle_tabs)) |
| .check(matches(withEffectiveVisibility(GONE))); |
| } |
| onViewWaiting(allOf( |
| withId(org.chromium.chrome.tab_ui.R.id.tab_title_view), withText(not(is(""))))); |
| |
| StartSurfaceTestUtils.clickMoreTabs(cta); |
| onViewWaiting(withId(R.id.secondary_tasks_surface_view)); |
| |
| if (isInstantReturn()) { |
| // TODO(crbug.com/1076274): fix toolbar to avoid wrongly focusing on the toolbar |
| // omnibox. |
| return; |
| } |
| StartSurfaceTestUtils.pressBack(mActivityTestRule); |
| onViewWaiting(withId(R.id.primary_tasks_surface_view)); |
| |
| OverviewModeBehaviorWatcher hideWatcher = TabUiTestHelper.createOverviewHideWatcher(cta); |
| onViewWaiting(withId(org.chromium.chrome.tab_ui.R.id.single_tab_view)).perform(click()); |
| hideWatcher.waitForBehavior(); |
| } |
| |
| @Test |
| @MediumTest |
| @Feature({"StartSurface"}) |
| // clang-format off |
| @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS}) |
| @DisableIf. |
| Build(sdk_is_less_than = Build.VERSION_CODES.N, message = "Flaky, see crbug.com/1246457") |
| 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().overviewVisible()); |
| StartSurfaceTestUtils.waitForTabModel(cta); |
| TestThreadUtils.runOnUiThreadBlocking( |
| () -> { cta.getTabModelSelector().getModel(false).closeAllTabs(); }); |
| TabUiTestHelper.verifyTabModelTabCount(cta, 0, 0); |
| assertTrue(cta.getLayoutManager().overviewVisible()); |
| 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. |
| 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.waitForOverviewVisible( |
| mLayoutChangedCallbackHelper, mCurrentlyActiveLayout); |
| onViewWaiting(withId(R.id.secondary_tasks_surface_view)); |
| } else { |
| onViewWaiting(withId(R.id.new_tab_incognito_container)); |
| } |
| } |
| |
| @Test |
| @MediumTest |
| @Feature({"StartSurface"}) |
| @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS + "/omnibox_focused_on_new_tab/false"}) |
| @DisableIf. |
| Build(sdk_is_less_than = Build.VERSION_CODES.O, message = "Flaky, see crbug.com/1170673") |
| public void testSearchInSingleSurface() { |
| if (!mImmediateReturn) { |
| StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity()); |
| } |
| StartSurfaceTestUtils.waitForOverviewVisible( |
| mLayoutChangedCallbackHelper, mCurrentlyActiveLayout); |
| ChromeTabbedActivity cta = mActivityTestRule.getActivity(); |
| StartSurfaceTestUtils.waitForTabModel(cta); |
| assertThat(cta.getTabModelSelector().getCurrentModel().getCount(), equalTo(1)); |
| |
| OverviewModeBehaviorWatcher hideWatcher = TabUiTestHelper.createOverviewHideWatcher(cta); |
| onViewWaiting(withId(R.id.search_box_text)).perform(replaceText("about:blank")); |
| onViewWaiting(withId(R.id.url_bar)).perform(pressKey(KeyEvent.KEYCODE_ENTER)); |
| hideWatcher.waitForBehavior(); |
| assertThat(cta.getTabModelSelector().getCurrentModel().getCount(), equalTo(2)); |
| |
| TestThreadUtils.runOnUiThreadBlocking(() -> cta.getTabCreator(false).launchNTP()); |
| StartSurfaceTestUtils.waitForOverviewVisible(cta); |
| onViewWaiting(withId(R.id.search_box_text)); |
| 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}) |
| @DisabledTest(message = "http://crbug/1120698 - NoInstant_Return version is flaky on bots.") |
| public void testSearchInIncognitoSingleSurface() { |
| if (!mImmediateReturn) { |
| StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity()); |
| } |
| StartSurfaceTestUtils.waitForOverviewVisible( |
| mLayoutChangedCallbackHelper, mCurrentlyActiveLayout); |
| ChromeTabbedActivity cta = mActivityTestRule.getActivity(); |
| StartSurfaceTestUtils.waitForTabModel(cta); |
| if (isInstantReturn()) { |
| // TODO(crbug.com/1076274): hide toolbar to make incognito switch visible. |
| TestThreadUtils.runOnUiThreadBlocking( |
| () -> { cta.getTabModelSelector().selectModel(true); }); |
| |
| // TODO(crbug.com/1097001): remove after fixing the default focus issue, which might |
| // relate to crbug.com/1076274 above since it doesn't exist for the other combinations. |
| assumeTrue(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P); |
| } else { |
| onViewWaiting(withId(R.id.incognito_toggle_tabs)).perform(click()); |
| } |
| assertTrue(cta.getTabModelSelector().isIncognitoSelected()); |
| |
| OverviewModeBehaviorWatcher hideWatcher = TabUiTestHelper.createOverviewHideWatcher(cta); |
| onViewWaiting(withId(R.id.search_box_text)).perform(replaceText("about:blank")); |
| onView(withId(R.id.url_bar)).perform(pressKey(KeyEvent.KEYCODE_ENTER)); |
| hideWatcher.waitForBehavior(); |
| assertThat(cta.getTabModelSelector().getCurrentModel().getCount(), equalTo(1)); |
| } |
| |
| @Test |
| @MediumTest |
| @Feature({"StartSurface"}) |
| @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS + "/open_ntp_instead_of_start/true"}) |
| @FlakyTest(message = "https://crbug.com/1201548") |
| 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; |
| } |
| CriteriaHelper.pollUiThread(() -> !cta.getOverviewModeBehavior().overviewVisible()); |
| TabUiTestHelper.enterTabSwitcher(cta); |
| TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0); |
| |
| // 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); |
| assertFalse(cta.getOverviewModeBehavior().overviewVisible()); |
| } |
| |
| @Test |
| @MediumTest |
| @Feature({"StartSurface"}) |
| @DisabledTest(message = "https://crbug.com/1119322") |
| @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS + "/open_ntp_instead_of_start/true"}) |
| 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.getOverviewModeBehavior().overviewVisible()); |
| } |
| |
| /** |
| * 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}) |
| // clang-format off |
| @EnableFeatures({ChromeFeatureList.TAB_SWITCHER_ON_RETURN + "<Study", |
| ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID, |
| ChromeFeatureList.START_SURFACE_ANDROID + "<Study"}) |
| @CommandLineFlags.Add({ |
| START_SURFACE_TEST_BASE_PARAMS + "/show_last_active_tab_only/true", |
| // Disable feed placeholder animation because it causes waitForDeferredStartup() to time |
| // out. |
| FeedPlaceholderLayout.DISABLE_ANIMATION_SWITCH}) |
| public void startSurfaceRecordHistogramsTest_SingleTab() { |
| // clang-format on |
| startSurfaceRecordHistogramsTest(true); |
| } |
| |
| @Test |
| @MediumTest |
| @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE}) |
| // clang-format off |
| @EnableFeatures({ChromeFeatureList.TAB_SWITCHER_ON_RETURN + "<Study", |
| ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID, |
| ChromeFeatureList.START_SURFACE_ANDROID + "<Study"}) |
| @CommandLineFlags.Add({START_SURFACE_TEST_BASE_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, ReturnToChromeExperimentsUtil.TAB_SWITCHER_ON_RETURN_MS.getValue()); |
| StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity()); |
| } else { |
| assertEquals(0, ReturnToChromeExperimentsUtil.TAB_SWITCHER_ON_RETURN_MS.getValue()); |
| } |
| |
| Assert.assertEquals("single", StartSurfaceConfiguration.START_SURFACE_VARIATION.getValue()); |
| Assert.assertEquals(isSingleTabSwitcher, |
| StartSurfaceConfiguration.START_SURFACE_LAST_ACTIVE_TAB_ONLY.getValue()); |
| StartSurfaceTestUtils.waitForOverviewVisible( |
| mLayoutChangedCallbackHelper, mCurrentlyActiveLayout); |
| 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( |
| ReturnToChromeExperimentsUtil |
| .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_BASE_PARAMS}) |
| public void testShow_SingleAsHomepage_VoiceSearchButtonShown() { |
| if (!mImmediateReturn) { |
| StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity()); |
| } |
| |
| StartSurfaceTestUtils.waitForOverviewVisible( |
| mLayoutChangedCallbackHelper, mCurrentlyActiveLayout); |
| StartSurfaceTestUtils.waitForTabModel(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_BASE_PARAMS}) |
| public void testShow_SingleAsHomepage_BottomSheet() { |
| if (!mImmediateReturn) { |
| StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity()); |
| } |
| |
| ChromeTabbedActivity cta = mActivityTestRule.getActivity(); |
| BottomSheetTestSupport bottomSheetTestSupport = new BottomSheetTestSupport( |
| cta.getRootUiCoordinatorForTesting().getBottomSheetController()); |
| StartSurfaceTestUtils.waitForOverviewVisible( |
| mLayoutChangedCallbackHelper, mCurrentlyActiveLayout); |
| StartSurfaceTestUtils.waitForTabModel(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); |
| onViewWaiting(withId(R.id.secondary_tasks_surface_view)); |
| 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); |
| assertFalse(bottomSheetTestSupport.hasSuppressionTokens()); |
| |
| StartSurfaceTestUtils.clickMoreTabs(cta); |
| onViewWaiting(withId(R.id.secondary_tasks_surface_view)); |
| assertTrue(bottomSheetTestSupport.hasSuppressionTokens()); |
| } |
| |
| @Test |
| @MediumTest |
| @Feature({"StartSurface"}) |
| @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS}) |
| public void testShow_SingleAsHomepage_ResetScrollPosition() { |
| if (!mImmediateReturn) { |
| StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity()); |
| } |
| |
| ChromeTabbedActivity cta = mActivityTestRule.getActivity(); |
| StartSurfaceTestUtils.waitForOverviewVisible( |
| mLayoutChangedCallbackHelper, mCurrentlyActiveLayout); |
| StartSurfaceTestUtils.waitForTabModel(cta); |
| TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0); |
| |
| // Scroll the toolbar. |
| StartSurfaceTestUtils.scrollToolbar(cta); |
| AppBarLayout taskSurfaceHeader = |
| cta.findViewById(org.chromium.chrome.tab_ui.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.clickMoreTabs(cta); |
| |
| onViewWaiting(withId(R.id.secondary_tasks_surface_view)); |
| 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"}) |
| @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS}) |
| public void singleAsHomepage_PressHomeButtonWillKeepTab() { |
| if (!mImmediateReturn) { |
| StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity()); |
| } |
| |
| ChromeTabbedActivity cta = mActivityTestRule.getActivity(); |
| StartSurfaceTestUtils.waitForOverviewVisible( |
| mLayoutChangedCallbackHelper, mCurrentlyActiveLayout); |
| onViewWaiting( |
| allOf(withId(org.chromium.chrome.tab_ui.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.LOLLIPOP |
| && 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)); |
| CriteriaHelper.pollUiThread(() -> cta.getLayoutManager().overviewVisible()); |
| 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_BASE_PARAMS + |
| "/check_sync_before_show_start_at_startup/true"}) |
| public void testShowStartWithSyncCheck() throws Exception { |
| // clang-format on |
| ChromeTabbedActivity cta = mActivityTestRule.getActivity(); |
| StartSurfaceTestUtils.waitForTabModel(cta); |
| assertEquals(1, cta.getTabModelSelector().getTotalTabCount()); |
| mActivityTestRule.waitForActivityNativeInitializationComplete(); |
| Assert.assertFalse(cta.getLayoutManager().overviewVisible()); |
| |
| Assert.assertFalse(ReturnToChromeExperimentsUtil.isPrimaryAccountSync()); |
| Assert.assertFalse(ReturnToChromeExperimentsUtil.shouldShowOverviewPageOnStart(cta, |
| cta.getIntent(), cta.getTabModelSelector(), cta.getInactivityTrackerForTesting())); |
| ReturnToChromeExperimentsUtil.setSyncForTesting(true); |
| Assert.assertTrue(ReturnToChromeExperimentsUtil.isPrimaryAccountSync()); |
| Assert.assertEquals(mImmediateReturn, |
| ReturnToChromeExperimentsUtil.shouldShowOverviewPageOnStart(cta, cta.getIntent(), |
| cta.getTabModelSelector(), cta.getInactivityTrackerForTesting())); |
| ReturnToChromeExperimentsUtil.setSyncForTesting(false); |
| } |
| |
| @Test |
| @MediumTest |
| @Feature({"StartSurface"}) |
| // clang-format off |
| @CommandLineFlags.Add({START_SURFACE_TEST_BASE_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(); |
| CriteriaHelper.pollUiThread( |
| () -> cta.getLayoutManager() != null && cta.getLayoutManager().overviewVisible()); |
| StartSurfaceTestUtils.waitForTabModel(cta); |
| TestThreadUtils.runOnUiThreadBlocking( |
| () -> { cta.getTabModelSelector().getModel(false).closeAllTabs(); }); |
| TabUiTestHelper.verifyTabModelTabCount(cta, 0, 0); |
| assertTrue(cta.getLayoutManager().overviewVisible()); |
| 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()); |
| assertFalse(cta.getLayoutManager().overviewVisible()); |
| onViewWaiting(withId(R.id.new_tab_incognito_container)).check(matches(isDisplayed())); |
| } |
| |
| @Test |
| @MediumTest |
| @Feature({"StartSurface"}) |
| // clang-format off |
| @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS + "/behavioural_targeting/model_mv_tiles" |
| + "/user_clicks_threshold/1/num_days_user_click_below_threshold/2"}) |
| public void testStartWithBehaviouralTargeting() throws Exception { |
| // clang-format on |
| Assume.assumeTrue(mImmediateReturn); |
| ChromeTabbedActivity cta = mActivityTestRule.getActivity(); |
| StartSurfaceTestUtils.waitForTabModel(cta); |
| TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0); |
| Assert.assertFalse(cta.getLayoutManager().overviewVisible()); |
| |
| SharedPreferencesManager manager = SharedPreferencesManager.getInstance(); |
| // Verifies that the START_NEXT_SHOW_ON_STARTUP_DECISION_MS has been set. |
| long nextDecisionTime = |
| manager.readLong(ChromePreferenceKeys.START_NEXT_SHOW_ON_STARTUP_DECISION_MS, |
| ReturnToChromeExperimentsUtil.INVALID_DECISION_TIMESTAMP); |
| verifyNextDecisionTimeStampInDays( |
| manager, StartSurfaceConfiguration.NUM_DAYS_USER_CLICK_BELOW_THRESHOLD.getValue()); |
| Assert.assertFalse(manager.readBoolean(ChromePreferenceKeys.START_SHOW_ON_STARTUP, false)); |
| Assert.assertEquals(0, manager.readInt(ChromePreferenceKeys.TAP_MV_TILES_COUNT, 0)); |
| |
| manager.writeInt(ChromePreferenceKeys.SHOW_START_SEGMENTATION_RESULT, |
| ReturnToChromeExperimentsUtil.ShowChromeStartSegmentationResult.DONT_SHOW); |
| |
| StartSurfaceConfiguration.USER_CLICK_THRESHOLD.setForTesting(1); |
| int clicksHigherThreshold = StartSurfaceConfiguration.USER_CLICK_THRESHOLD.getValue(); |
| Assert.assertEquals(1, clicksHigherThreshold); |
| ReturnToChromeExperimentsUtil.onMVTileOpened(); |
| // Verifies that userBehaviourSupported() returns the same result before the next decision |
| // time arrives. |
| Assert.assertFalse(ReturnToChromeExperimentsUtil.userBehaviourSupported()); |
| Assert.assertEquals(nextDecisionTime, |
| manager.readLong(ChromePreferenceKeys.START_NEXT_SHOW_ON_STARTUP_DECISION_MS, |
| ReturnToChromeExperimentsUtil.INVALID_DECISION_TIMESTAMP)); |
| Assert.assertFalse(manager.readBoolean(ChromePreferenceKeys.START_SHOW_ON_STARTUP, false)); |
| Assert.assertEquals(1, manager.readInt(ChromePreferenceKeys.TAP_MV_TILES_COUNT, 0)); |
| |
| Assert.assertEquals(0, |
| RecordHistogram.getHistogramTotalCountForTesting( |
| "Startup.Android.ShowChromeStartSegmentationResultComparison")); |
| |
| // Verifies if the next decision time past and the clicks of MV tiles is higher than the |
| // threshold, userBehaviourSupported() returns true. Besides, the next decision time is set |
| // to NUM_DAYS_KEEP_SHOW_START_AT_STARTUP day's later, and MV tiles count is reset. |
| manager.writeLong(ChromePreferenceKeys.START_NEXT_SHOW_ON_STARTUP_DECISION_MS, |
| System.currentTimeMillis() - 1); |
| Assert.assertTrue(ReturnToChromeExperimentsUtil.userBehaviourSupported()); |
| Assert.assertTrue(manager.readBoolean(ChromePreferenceKeys.START_SHOW_ON_STARTUP, false)); |
| verifyNextDecisionTimeStampInDays( |
| manager, StartSurfaceConfiguration.NUM_DAYS_KEEP_SHOW_START_AT_STARTUP.getValue()); |
| Assert.assertEquals(0, manager.readInt(ChromePreferenceKeys.TAP_MV_TILES_COUNT, 0)); |
| Assert.assertEquals(1, |
| RecordHistogram.getHistogramValueCountForTesting( |
| "Startup.Android.ShowChromeStartSegmentationResultComparison", |
| ReturnToChromeExperimentsUtil.ShowChromeStartSegmentationResultComparison |
| .SEGMENTATION_DISABLED_LOGIC_ENABLED)); |
| |
| // Verifies if the next decision time past and the clicks of MV tiles is lower than the |
| // threshold, userBehaviourSupported() returns false. Besides, the next decision time is |
| // set to NUM_DAYS_USER_CLICK_BELOW_THRESHOLD day's later. |
| manager.writeLong(ChromePreferenceKeys.START_NEXT_SHOW_ON_STARTUP_DECISION_MS, |
| System.currentTimeMillis() - 1); |
| manager.writeInt(ChromePreferenceKeys.SHOW_START_SEGMENTATION_RESULT, |
| ReturnToChromeExperimentsUtil.ShowChromeStartSegmentationResult.SHOW); |
| Assert.assertEquals(0, manager.readInt(ChromePreferenceKeys.TAP_MV_TILES_COUNT, 0)); |
| Assert.assertFalse(ReturnToChromeExperimentsUtil.userBehaviourSupported()); |
| Assert.assertFalse(manager.readBoolean(ChromePreferenceKeys.START_SHOW_ON_STARTUP, false)); |
| verifyNextDecisionTimeStampInDays( |
| manager, StartSurfaceConfiguration.NUM_DAYS_USER_CLICK_BELOW_THRESHOLD.getValue()); |
| Assert.assertEquals(1, |
| RecordHistogram.getHistogramValueCountForTesting( |
| "Startup.Android.ShowChromeStartSegmentationResultComparison", |
| ReturnToChromeExperimentsUtil.ShowChromeStartSegmentationResultComparison |
| .SEGMENTATION_ENABLED_LOGIC_DISABLED)); |
| |
| StartSurfaceConfiguration.BEHAVIOURAL_TARGETING.setForTesting("feeds"); |
| verifyBehaviourTypeRecordedAndChecked(manager); |
| |
| StartSurfaceConfiguration.BEHAVIOURAL_TARGETING.setForTesting("open_new_tab"); |
| verifyBehaviourTypeRecordedAndChecked(manager); |
| |
| StartSurfaceConfiguration.BEHAVIOURAL_TARGETING.setForTesting("open_history"); |
| verifyBehaviourTypeRecordedAndChecked(manager); |
| |
| StartSurfaceConfiguration.BEHAVIOURAL_TARGETING.setForTesting("open_recent_tabs"); |
| verifyBehaviourTypeRecordedAndChecked(manager); |
| |
| // Verifies if the key doesn't match the value of |
| // StartSurfaceConfiguration.BEHAVIOURAL_TARGETING, e.g., the value isn't set, onUIClicked() |
| // doesn't record or increase the count. |
| StartSurfaceConfiguration.BEHAVIOURAL_TARGETING.setForTesting(""); |
| String type = "feeds"; |
| String key = ReturnToChromeExperimentsUtil.getBehaviourTypeKeyForTesting(type); |
| ReturnToChromeExperimentsUtil.onUIClicked(key); |
| Assert.assertEquals(0, manager.readInt(key, 0)); |
| |
| // Verifies the combination case that BEHAVIOURAL_TARGETING is set to "all". |
| StartSurfaceConfiguration.BEHAVIOURAL_TARGETING.setForTesting("all"); |
| String type1 = "open_history"; |
| String type2 = "open_recent_tabs"; |
| String key1 = ReturnToChromeExperimentsUtil.getBehaviourTypeKeyForTesting(type1); |
| String key2 = ReturnToChromeExperimentsUtil.getBehaviourTypeKeyForTesting(type2); |
| Assert.assertEquals(0, manager.readInt(key1, 0)); |
| Assert.assertEquals(0, manager.readInt(key2, 0)); |
| Assert.assertFalse(manager.readBoolean(ChromePreferenceKeys.START_SHOW_ON_STARTUP, false)); |
| |
| // Increase the count of one key. |
| ReturnToChromeExperimentsUtil.onHistoryOpened(); |
| Assert.assertEquals(1, manager.readInt(key1, 0)); |
| |
| // Verifies that userBehaviourSupported() return true due to the count of this key is higher |
| // or equal to the threshold. |
| manager.writeLong(ChromePreferenceKeys.START_NEXT_SHOW_ON_STARTUP_DECISION_MS, |
| System.currentTimeMillis() - 1); |
| Assert.assertTrue(ReturnToChromeExperimentsUtil.userBehaviourSupported()); |
| Assert.assertEquals(0, manager.readInt(key1, 0)); |
| Assert.assertEquals(0, manager.readInt(key2, 0)); |
| Assert.assertTrue(manager.readBoolean(ChromePreferenceKeys.START_SHOW_ON_STARTUP, false)); |
| |
| // Resets the decision. |
| manager.writeBoolean(ChromePreferenceKeys.START_SHOW_ON_STARTUP, false); |
| } |
| |
| @Test |
| @MediumTest |
| @Feature({"StartSurface"}) |
| @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS + "/behavioural_targeting/model"}) |
| public void testStartSegmentationUsage() throws Exception { |
| Assume.assumeTrue(mImmediateReturn); |
| ChromeTabbedActivity cta = mActivityTestRule.getActivity(); |
| StartSurfaceTestUtils.waitForTabModel(cta); |
| TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0); |
| Assert.assertFalse(cta.getLayoutManager().overviewVisible()); |
| |
| SharedPreferencesManager manager = SharedPreferencesManager.getInstance(); |
| // Verifies that the START_NEXT_SHOW_ON_STARTUP_DECISION_MS has been set. |
| long nextDecisionTime = |
| manager.readLong(ChromePreferenceKeys.START_NEXT_SHOW_ON_STARTUP_DECISION_MS, |
| ReturnToChromeExperimentsUtil.INVALID_DECISION_TIMESTAMP); |
| verifyNextDecisionTimeStampInDays( |
| manager, StartSurfaceConfiguration.NUM_DAYS_USER_CLICK_BELOW_THRESHOLD.getValue()); |
| Assert.assertFalse(manager.readBoolean(ChromePreferenceKeys.START_SHOW_ON_STARTUP, false)); |
| Assert.assertEquals(0, manager.readInt(ChromePreferenceKeys.TAP_MV_TILES_COUNT, 0)); |
| |
| manager.writeInt(ChromePreferenceKeys.SHOW_START_SEGMENTATION_RESULT, |
| ReturnToChromeExperimentsUtil.ShowChromeStartSegmentationResult.SHOW); |
| |
| // Verifies that userBehaviourSupported() returns the same result before the next decision |
| // time arrives. |
| Assert.assertFalse(ReturnToChromeExperimentsUtil.userBehaviourSupported()); |
| Assert.assertEquals(nextDecisionTime, |
| manager.readLong(ChromePreferenceKeys.START_NEXT_SHOW_ON_STARTUP_DECISION_MS, |
| ReturnToChromeExperimentsUtil.INVALID_DECISION_TIMESTAMP)); |
| Assert.assertFalse(manager.readBoolean(ChromePreferenceKeys.START_SHOW_ON_STARTUP, false)); |
| |
| // Verifies if the next decision time past, userBehaviourSupported() returns true. Besides, |
| // the next decision time is set to NUM_DAYS_KEEP_SHOW_START_AT_STARTUP day's later. |
| manager.writeLong(ChromePreferenceKeys.START_NEXT_SHOW_ON_STARTUP_DECISION_MS, |
| System.currentTimeMillis() - 1); |
| Assert.assertTrue(ReturnToChromeExperimentsUtil.userBehaviourSupported()); |
| Assert.assertTrue(manager.readBoolean(ChromePreferenceKeys.START_SHOW_ON_STARTUP, false)); |
| verifyNextDecisionTimeStampInDays( |
| manager, StartSurfaceConfiguration.NUM_DAYS_KEEP_SHOW_START_AT_STARTUP.getValue()); |
| |
| // Verifies if the next decision time past and segmentation says dont show, |
| // userBehaviourSupported() returns false. Besides, the next decision time is set to |
| // NUM_DAYS_USER_CLICK_BELOW_THRESHOLD day's later. |
| manager.writeInt(ChromePreferenceKeys.SHOW_START_SEGMENTATION_RESULT, |
| ReturnToChromeExperimentsUtil.ShowChromeStartSegmentationResult.DONT_SHOW); |
| manager.writeLong(ChromePreferenceKeys.START_NEXT_SHOW_ON_STARTUP_DECISION_MS, |
| System.currentTimeMillis() - 1); |
| Assert.assertFalse(ReturnToChromeExperimentsUtil.userBehaviourSupported()); |
| Assert.assertFalse(manager.readBoolean(ChromePreferenceKeys.START_SHOW_ON_STARTUP, false)); |
| verifyNextDecisionTimeStampInDays( |
| manager, StartSurfaceConfiguration.NUM_DAYS_USER_CLICK_BELOW_THRESHOLD.getValue()); |
| |
| // Verifies that if segmentation stops returning results, then we continue to use the |
| // previous result. |
| manager.writeInt(ChromePreferenceKeys.SHOW_START_SEGMENTATION_RESULT, |
| ReturnToChromeExperimentsUtil.ShowChromeStartSegmentationResult.UNINITIALIZED); |
| manager.writeLong(ChromePreferenceKeys.START_NEXT_SHOW_ON_STARTUP_DECISION_MS, |
| System.currentTimeMillis() - 1); |
| Assert.assertFalse(ReturnToChromeExperimentsUtil.userBehaviourSupported()); |
| Assert.assertFalse(manager.readBoolean(ChromePreferenceKeys.START_SHOW_ON_STARTUP, false)); |
| verifyNextDecisionTimeStampInDays( |
| manager, StartSurfaceConfiguration.NUM_DAYS_USER_CLICK_BELOW_THRESHOLD.getValue()); |
| } |
| |
| @Test |
| @MediumTest |
| @Feature({"StartSurface"}) |
| @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS}) |
| public void testStartSurfaceMenu() throws ExecutionException { |
| ChromeTabbedActivity cta = mActivityTestRule.getActivity(); |
| if (!mImmediateReturn) StartSurfaceTestUtils.pressHomePageButton(cta); |
| StartSurfaceTestUtils.waitForOverviewVisible( |
| mLayoutChangedCallbackHelper, mCurrentlyActiveLayout); |
| StartSurfaceTestUtils.waitForTabModel(cta); |
| TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0); |
| |
| TestThreadUtils.runOnUiThreadBlocking(() -> { |
| AppMenuTestSupport.showAppMenu(mActivityTestRule.getAppMenuCoordinator(), null, false); |
| }); |
| |
| assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel( |
| mActivityTestRule.getAppMenuCoordinator(), R.id.icon_row_menu_id)); |
| assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel( |
| mActivityTestRule.getAppMenuCoordinator(), R.id.new_tab_menu_id)); |
| assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel( |
| mActivityTestRule.getAppMenuCoordinator(), R.id.new_incognito_tab_menu_id)); |
| assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel( |
| mActivityTestRule.getAppMenuCoordinator(), R.id.divider_line_id)); |
| assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel( |
| mActivityTestRule.getAppMenuCoordinator(), R.id.open_history_menu_id)); |
| assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel( |
| mActivityTestRule.getAppMenuCoordinator(), R.id.downloads_menu_id)); |
| assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel( |
| mActivityTestRule.getAppMenuCoordinator(), R.id.all_bookmarks_menu_id)); |
| assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel( |
| mActivityTestRule.getAppMenuCoordinator(), R.id.recent_tabs_menu_id)); |
| assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel( |
| mActivityTestRule.getAppMenuCoordinator(), R.id.divider_line_id)); |
| assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel( |
| mActivityTestRule.getAppMenuCoordinator(), R.id.preferences_id)); |
| assertNotNull(AppMenuTestSupport.getMenuItemPropertyModel( |
| mActivityTestRule.getAppMenuCoordinator(), R.id.help_id)); |
| |
| assertNull(AppMenuTestSupport.getMenuItemPropertyModel( |
| mActivityTestRule.getAppMenuCoordinator(), R.id.menu_group_tabs)); |
| assertNull(AppMenuTestSupport.getMenuItemPropertyModel( |
| mActivityTestRule.getAppMenuCoordinator(), R.id.close_all_tabs_menu_id)); |
| |
| boolean hasUpdateMenuItem = |
| AppMenuTestSupport.getMenuItemPropertyModel( |
| mActivityTestRule.getAppMenuCoordinator(), R.id.update_menu_id) |
| != null; |
| ModelList menuItemsModelList = |
| AppMenuTestSupport.getMenuModelList(mActivityTestRule.getAppMenuCoordinator()); |
| assertEquals(hasUpdateMenuItem ? 12 : 11, menuItemsModelList.size()); |
| } |
| |
| @Test |
| @MediumTest |
| @Feature({"StartSurface"}) |
| // clang-format off |
| @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS}) |
| public void test_DoNotLoadLastSelectedTabOnStartup() { |
| // clang-format on |
| doTestNotLoadLastSelectedTabOnStartupImpl(); |
| } |
| |
| @Test |
| @MediumTest |
| @Feature({"StartSurface"}) |
| // clang-format off |
| @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS + "/show_last_active_tab_only/true"}) |
| public void test_DoNotLoadLastSelectedTabOnStartupV2() { |
| // clang-format on |
| doTestNotLoadLastSelectedTabOnStartupImpl(); |
| } |
| |
| private void doTestNotLoadLastSelectedTabOnStartupImpl() { |
| assumeTrue(mImmediateReturn); |
| |
| ChromeTabbedActivity cta = mActivityTestRule.getActivity(); |
| StartSurfaceTestUtils.waitForOverviewVisible( |
| mLayoutChangedCallbackHelper, mCurrentlyActiveLayout); |
| StartSurfaceTestUtils.waitForTabModel(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()); |
| } |
| |
| /** |
| * Check that the next decision time is within |numOfDays| from now. |
| * @param numOfDays Number of days to check. |
| */ |
| private void verifyNextDecisionTimeStampInDays( |
| SharedPreferencesManager manager, int numOfDays) { |
| long approximateTime = System.currentTimeMillis() |
| + numOfDays * ReturnToChromeExperimentsUtil.MILLISECONDS_PER_DAY; |
| long nextDecisionTime = |
| manager.readLong(ChromePreferenceKeys.START_NEXT_SHOW_ON_STARTUP_DECISION_MS, |
| ReturnToChromeExperimentsUtil.INVALID_DECISION_TIMESTAMP); |
| |
| Assert.assertThat("new decision time lower bound", |
| approximateTime - MILLISECONDS_PER_MINUTE, |
| Matchers.lessThanOrEqualTo(nextDecisionTime)); |
| |
| Assert.assertThat("new decision time upper bound", |
| approximateTime + MILLISECONDS_PER_MINUTE, |
| Matchers.greaterThanOrEqualTo(nextDecisionTime)); |
| } |
| |
| private void verifyBehaviourTypeRecordedAndChecked(SharedPreferencesManager manager) { |
| String key = ReturnToChromeExperimentsUtil.getBehaviourTypeKeyForTesting( |
| StartSurfaceConfiguration.BEHAVIOURAL_TARGETING.getValue()); |
| Assert.assertEquals(0, manager.readInt(key, 0)); |
| |
| // Increase the count of the key. |
| ReturnToChromeExperimentsUtil.onUIClicked(key); |
| Assert.assertEquals(1, manager.readInt(key, 0)); |
| Assert.assertFalse(manager.readBoolean(ChromePreferenceKeys.START_SHOW_ON_STARTUP, false)); |
| |
| // Verifies that userBehaviourSupported() return true due to the count of this key is higher |
| // or equal to the threshold. |
| manager.writeLong(ChromePreferenceKeys.START_NEXT_SHOW_ON_STARTUP_DECISION_MS, |
| System.currentTimeMillis() - 1); |
| Assert.assertTrue(ReturnToChromeExperimentsUtil.userBehaviourSupported()); |
| Assert.assertEquals(0, manager.readInt(key, 0)); |
| Assert.assertTrue(manager.readBoolean(ChromePreferenceKeys.START_SHOW_ON_STARTUP, false)); |
| |
| // Resets the decision. |
| manager.writeBoolean(ChromePreferenceKeys.START_SHOW_ON_STARTUP, false); |
| } |
| |
| /** |
| * @return Whether both features {@link ChromeFeatureList#INSTANT_START} and |
| * {@link ChromeFeatureList#TAB_SWITCHER_ON_RETURN} are enabled. |
| */ |
| private boolean isInstantReturn() { |
| return mUseInstantStart && mImmediateReturn; |
| } |
| |
| private void pressHome() { |
| UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); |
| device.pressHome(); |
| ChromeApplicationTestUtils.waitUntilChromeInBackground(); |
| } |
| } |