[go: nahoru, domu]

blob: b7d46f127a5a3f0a14693368eb94b736525be48e [file] [log] [blame]
// Copyright 2021 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.pressKey;
import static androidx.test.espresso.action.ViewActions.replaceText;
import static androidx.test.espresso.action.ViewActions.swipeUp;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withParent;
import static androidx.test.espresso.matcher.ViewMatchers.withTagValue;
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.assertTrue;
import static org.chromium.chrome.features.start_surface.StartSurfaceTestUtils.INSTANT_START_TEST_BASE_PARAMS;
import static org.chromium.ui.test.util.ViewUtils.onViewWaiting;
import android.os.Build.VERSION_CODES;
import android.view.KeyEvent;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.test.filters.LargeTest;
import androidx.test.filters.MediumTest;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.test.params.ParameterAnnotations;
import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameter;
import org.chromium.base.test.params.ParameterProvider;
import org.chromium.base.test.params.ParameterSet;
import org.chromium.base.test.params.ParameterizedRunner;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.DisableIf;
import org.chromium.base.test.util.DoNotBatch;
import org.chromium.base.test.util.JniMocker;
import org.chromium.base.test.util.Restriction;
import org.chromium.chrome.browser.ChromeTabbedActivity;
import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
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.homepage.HomepageManager;
import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
import org.chromium.chrome.browser.preferences.ChromeSharedPreferences;
import org.chromium.chrome.browser.tabmodel.TabModelFilter;
import org.chromium.chrome.browser.tasks.ReturnToChromeUtil;
import org.chromium.chrome.browser.tasks.pseudotab.TabAttributeCache;
import org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper;
import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.chrome.test.R;
import org.chromium.chrome.test.util.ActivityTestUtils;
import org.chromium.chrome.test.util.ChromeRenderTestRule;
import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.ui.test.util.UiRestriction;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Integration tests of tab switcher with Instant Start which requires 2-stage initialization for
* Clank startup.
*/
@RunWith(ParameterizedRunner.class)
@ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
@CommandLineFlags.Add({
ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
"force-fieldtrials=Study/Group"
})
@EnableFeatures({
ChromeFeatureList.START_SURFACE_RETURN_TIME + "<Study,",
ChromeFeatureList.START_SURFACE_ANDROID + "<Study",
ChromeFeatureList.INSTANT_START,
})
@DisableFeatures({ChromeFeatureList.SHOW_NTP_AT_STARTUP_ANDROID})
@Restriction({
Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE,
UiRestriction.RESTRICTION_TYPE_PHONE
})
@DoNotBatch(reason = "This test suite tests startup behaviours and thus can't be batched.")
public class InstantStartTabSwitcherTest {
private static final String SHADOW_VIEW_TAG = "TabListViewShadow";
@Rule
public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
@Rule
public ChromeRenderTestRule mRenderTestRule =
ChromeRenderTestRule.Builder.withPublicCorpus()
.setRevision(4)
.setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_MOBILE_START)
.build();
@Rule public JniMocker mJniMocker = new JniMocker();
@Mock public BrowserControlsStateProvider mBrowserControlsStateProvider;
@Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
/**
* {@link ParameterProvider} used for parameterized test that provides whether last visited tab
* is a search result page.
*/
public static class LastVisitedTabIsSRPTestParams implements ParameterProvider {
private static final List<ParameterSet> sLVTIsSRPTestParams =
Arrays.asList(
new ParameterSet().value(false).name("SingleTab_NotSRP"),
new ParameterSet().value(true).name("SingleTab_SRP"));
@Override
public List<ParameterSet> getParameters() {
return sLVTIsSRPTestParams;
}
}
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ReturnToChromeUtil.setSkipInitializationCheckForTesting(true);
}
@After
public void tearDown() {
if (mActivityTestRule.getActivity() != null) {
ActivityTestUtils.clearActivityOrientation(mActivityTestRule.getActivity());
}
}
/**
* Tests that clicking the tab switcher button won't make Omnibox get focused when single tab is
* shown on the StartSurface.
*/
@Test
@MediumTest
@CommandLineFlags.Add({INSTANT_START_TEST_BASE_PARAMS})
public void startSurfaceTabSwitcherButtonTest() throws IOException {
StartSurfaceTestUtils.createTabStatesAndMetadataFile(new int[] {0});
StartSurfaceTestUtils.createThumbnailBitmapAndWriteToFile(0, mBrowserControlsStateProvider);
TabAttributeCache.setTitleForTesting(0, "Google");
StartSurfaceTestUtils.startMainActivityFromLauncher(mActivityTestRule);
ChromeTabbedActivity cta = mActivityTestRule.getActivity();
Assert.assertFalse(cta.isTablet());
Assert.assertTrue(ChromeFeatureList.sInstantStart.isEnabled());
Assert.assertTrue(ReturnToChromeUtil.shouldShowTabSwitcher(-1, false));
mActivityTestRule.waitForActivityNativeInitializationComplete();
StartSurfaceTestUtils.clickTabSwitcherButton(cta);
onViewWaiting(
allOf(
withParent(
withId(
TabUiTestHelper.getTabSwitcherParentId(
mActivityTestRule.getActivity()))),
withId(org.chromium.chrome.test.R.id.tab_list_recycler_view)));
Assert.assertFalse(cta.findViewById(org.chromium.chrome.test.R.id.url_bar).isFocused());
}
@Test
@LargeTest
@CommandLineFlags.Add({
ChromeSwitches.DISABLE_NATIVE_INITIALIZATION,
INSTANT_START_TEST_BASE_PARAMS,
FeedPlaceholderLayout.DISABLE_ANIMATION_SWITCH
})
// TODO(https://crbug.com/1500080): Fix this test with "start surface refactor" enabled.
@DisableFeatures({ChromeFeatureList.START_SURFACE_REFACTOR})
public void testScrollToSelectedTab() throws Exception {
StartSurfaceTestUtils.createTabStatesAndMetadataFile(
new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, null, 5);
StartSurfaceTestUtils.startMainActivityFromLauncher(mActivityTestRule);
ChromeTabbedActivity cta = mActivityTestRule.getActivity();
StartSurfaceTestUtils.waitForStartSurfaceVisible(cta);
StartSurfaceTestUtils.startAndWaitNativeInitialization(mActivityTestRule);
StartSurfaceTestUtils.waitForStartSurfaceVisible(cta);
StartSurfaceTestUtils.clickTabSwitcherButton(cta);
StartSurfaceTestUtils.waitForTabSwitcherVisible(cta);
int tabSwitcherParentViewId = TabUiTestHelper.getTabSwitcherParentId(cta);
// Make sure the grid tab switcher is scrolled down to show the selected tab.
onView(
allOf(
withId(org.chromium.chrome.test.R.id.tab_list_recycler_view),
withParent(withId(tabSwitcherParentViewId))))
.check(
(v, noMatchException) -> {
if (noMatchException != null) throw noMatchException;
Assert.assertTrue(v instanceof RecyclerView);
LinearLayoutManager layoutManager =
(LinearLayoutManager) ((RecyclerView) v).getLayoutManager();
assertEquals(2, layoutManager.findFirstVisibleItemPosition());
assertTrue(
layoutManager.isViewPartiallyVisible(
layoutManager.getChildAt(5), false, false));
assertEquals(7, layoutManager.findLastVisibleItemPosition());
});
// On tab switcher page, shadow is handled by TabListRecyclerView itself, so toolbar shadow
// shouldn't show.
onView(withId(org.chromium.chrome.test.R.id.toolbar_hairline))
.check(matches(not(isDisplayed())));
// Scroll the tab list a little bit and shadow should show.
onView(
allOf(
withId(org.chromium.chrome.test.R.id.tab_list_recycler_view),
withParent(withId(tabSwitcherParentViewId))))
.perform(swipeUp());
onView(
allOf(
withTagValue(is(SHADOW_VIEW_TAG)),
isDescendantOfA(withId(tabSwitcherParentViewId))))
.check(matches(isDisplayed()));
}
@Test
@MediumTest
@CommandLineFlags.Add({INSTANT_START_TEST_BASE_PARAMS})
public void testShowStartWhenHomepageDisabledWithImmediateReturn() throws IOException {
Assert.assertTrue(ChromeFeatureList.sInstantStart.isEnabled());
Assert.assertEquals(
0, StartSurfaceConfiguration.START_SURFACE_RETURN_TIME_SECONDS.getValue());
testShowStartWhenHomepageDisabledWithImmediateReturnImpl();
}
@Test
@MediumTest
@DisableFeatures(ChromeFeatureList.INSTANT_START)
@CommandLineFlags.Add({INSTANT_START_TEST_BASE_PARAMS})
public void testShowStartWhenHomepageDisabledWithImmediateReturn_NoInstant()
throws IOException {
Assert.assertFalse(ChromeFeatureList.sInstantStart.isEnabled());
Assert.assertEquals(
0, StartSurfaceConfiguration.START_SURFACE_RETURN_TIME_SECONDS.getValue());
testShowStartWhenHomepageDisabledWithImmediateReturnImpl();
}
private void testShowStartWhenHomepageDisabledWithImmediateReturnImpl() throws IOException {
StartSurfaceTestUtils.createTabStatesAndMetadataFile(new int[] {0});
StartSurfaceTestUtils.createThumbnailBitmapAndWriteToFile(0, mBrowserControlsStateProvider);
TabAttributeCache.setTitleForTesting(0, "Google");
TestThreadUtils.runOnUiThreadBlocking(
() -> HomepageManager.getInstance().setPrefHomepageEnabled(false));
Assert.assertFalse(HomepageManager.isHomepageEnabled());
// Launches Chrome and verifies that the Tab switcher is showing.
StartSurfaceTestUtils.startMainActivityFromLauncher(mActivityTestRule);
ChromeTabbedActivity cta = mActivityTestRule.getActivity();
StartSurfaceTestUtils.waitForTabModel(cta);
TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0);
StartSurfaceTestUtils.waitForStartSurfaceVisible(cta);
// After the Start surface refactoring is enabled, the StartSurfaceState.SHOWN_TABSWITCHER
// will go away.
if (!TabUiTestHelper.getIsStartSurfaceRefactorEnabledFromUIThread(cta)) {
StartSurfaceCoordinator startSurfaceCoordinator =
StartSurfaceTestUtils.getStartSurfaceFromUIThread(cta);
TestThreadUtils.runOnUiThreadBlocking(
() -> {
Assert.assertEquals(
startSurfaceCoordinator.getStartSurfaceState(),
StartSurfaceState.SHOWN_TABSWITCHER);
});
}
}
@Test
@MediumTest
@UseMethodParameter(LastVisitedTabIsSRPTestParams.class)
@CommandLineFlags.Add({
ChromeSwitches.DISABLE_NATIVE_INITIALIZATION,
INSTANT_START_TEST_BASE_PARAMS
})
public void testRecordLastVisitedTabIsSRPHistogram_Instant(boolean isSRP) throws IOException {
testRecordLastVisitedTabIsSRPHistogram(isSRP);
}
@Test
@MediumTest
@DisableFeatures(ChromeFeatureList.INSTANT_START)
@UseMethodParameter(LastVisitedTabIsSRPTestParams.class)
@CommandLineFlags.Add({
ChromeSwitches.DISABLE_NATIVE_INITIALIZATION,
INSTANT_START_TEST_BASE_PARAMS
})
public void testRecordLastVisitedTabIsSRPHistogram_NoInstant(boolean isSRP) throws IOException {
testRecordLastVisitedTabIsSRPHistogram(isSRP);
}
@Test
@MediumTest
@DisableFeatures(ChromeFeatureList.INSTANT_START)
@CommandLineFlags.Add({
ChromeSwitches.DISABLE_NATIVE_INITIALIZATION,
INSTANT_START_TEST_BASE_PARAMS
})
@DisableIf.Build(
message = "https://crbug.com/1470412",
sdk_is_greater_than = VERSION_CODES.M,
sdk_is_less_than = VERSION_CODES.Q)
public void testSaveIsLastVisitedTabSRP() throws Exception {
StartSurfaceTestUtils.startMainActivityFromLauncher(mActivityTestRule);
StartSurfaceTestUtils.startAndWaitNativeInitialization(mActivityTestRule);
ChromeTabbedActivity cta = mActivityTestRule.getActivity();
StartSurfaceTestUtils.waitForStartSurfaceVisible(cta);
StartSurfaceTestUtils.waitForDeferredStartup(mActivityTestRule);
// Create a new search result tab by perform a query search in fake box.
onViewWaiting(withId(R.id.search_box_text))
.check(matches(isCompletelyDisplayed()))
.perform(replaceText("test"));
onView(withId(R.id.url_bar)).perform(pressKey(KeyEvent.KEYCODE_ENTER));
TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0);
StartSurfaceTestUtils.pressHome();
Assert.assertTrue(
ChromeSharedPreferences.getInstance()
.readBoolean(ChromePreferenceKeys.IS_LAST_VISITED_TAB_SRP, false));
// Simulates pressing Chrome's icon and launching Chrome from warm start.
mActivityTestRule.resumeMainActivityFromLauncher();
// Create a non search result tab and check the shared preferences.
StartSurfaceTestUtils.waitForStartSurfaceVisible(cta);
StartSurfaceTestUtils.waitForTabModel(cta);
StartSurfaceTestUtils.launchFirstMVTile(cta, 1);
StartSurfaceTestUtils.pressHome();
Assert.assertFalse(
ChromeSharedPreferences.getInstance()
.readBoolean(ChromePreferenceKeys.IS_LAST_VISITED_TAB_SRP, false));
}
private void testRecordLastVisitedTabIsSRPHistogram(boolean isSRP) throws IOException {
StartSurfaceTestUtils.createTabStatesAndMetadataFile(
new int[] {0, 1},
new String[] {"https://www.google.com/search?q=test", "https://www.google.com"},
isSRP ? 0 : 1);
StartSurfaceTestUtils.createThumbnailBitmapAndWriteToFile(0, mBrowserControlsStateProvider);
StartSurfaceTestUtils.createThumbnailBitmapAndWriteToFile(1, mBrowserControlsStateProvider);
TabAttributeCache.setTitleForTesting(0, "Google SRP");
TabAttributeCache.setTitleForTesting(1, "Google Homepage");
ChromeSharedPreferences.getInstance()
.writeBoolean(ChromePreferenceKeys.IS_LAST_VISITED_TAB_SRP, isSRP);
StartSurfaceTestUtils.startMainActivityFromLauncher(mActivityTestRule);
StartSurfaceTestUtils.startAndWaitNativeInitialization(mActivityTestRule);
ChromeTabbedActivity cta = mActivityTestRule.getActivity();
StartSurfaceTestUtils.waitForStartSurfaceVisible(cta);
StartSurfaceTestUtils.waitForDeferredStartup(mActivityTestRule);
Assert.assertEquals(
1,
RecordHistogram.getHistogramValueCountForTesting(
ReturnToChromeUtil
.LAST_VISITED_TAB_IS_SRP_WHEN_OVERVIEW_IS_SHOWN_AT_LAUNCH_UMA,
isSRP ? 1 : 0));
}
private int getRelatedTabListSizeOnUiThread(TabModelFilter tabModelFilter) {
AtomicInteger res = new AtomicInteger();
TestThreadUtils.runOnUiThreadBlocking(
() -> {
res.set(tabModelFilter.getRelatedTabList(2).size());
});
return res.get();
}
}