// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.settings;
import static androidx.test.espresso.Espresso.onData;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.contrib.RecyclerViewActions.scrollTo;
import static androidx.test.espresso.intent.Intents.intended;
import static androidx.test.espresso.matcher.PreferenceMatchers.withKey;
import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.chromium.ui.test.util.ViewUtils.onViewWaiting;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Looper;
import android.provider.Settings;
import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.test.espresso.contrib.RecyclerViewActions;
import androidx.test.espresso.intent.Intents;
import androidx.test.espresso.intent.matcher.IntentMatchers;
import androidx.test.filters.LargeTest;
import androidx.test.filters.MediumTest;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.chromium.base.BuildInfo;
import org.chromium.base.PackageManagerUtils;
import org.chromium.base.ThreadUtils;
import org.chromium.base.test.util.ApplicationTestUtils;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.Criteria;
import org.chromium.base.test.util.CriteriaHelper;
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.Features.DisableFeatures;
import org.chromium.base.test.util.Features.EnableFeatures;
import org.chromium.base.test.util.HistogramWatcher;
import org.chromium.base.test.util.JniMocker;
import org.chromium.chrome.browser.about_settings.AboutChromeSettings;
import org.chromium.chrome.browser.accessibility.settings.AccessibilitySettings;
import org.chromium.chrome.browser.autofill.settings.AutofillPaymentMethodsFragment;
import org.chromium.chrome.browser.autofill.settings.AutofillProfilesFragment;
import org.chromium.chrome.browser.download.settings.DownloadSettings;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.homepage.HomepageTestRule;
import org.chromium.chrome.browser.homepage.settings.HomepageSettings;
import org.chromium.chrome.browser.language.settings.LanguageSettings;
import org.chromium.chrome.browser.magic_stack.HomeModulesConfigManager;
import org.chromium.chrome.browser.magic_stack.HomeModulesConfigSettings;
import org.chromium.chrome.browser.night_mode.NightModeMetrics.ThemeSettingsEntry;
import org.chromium.chrome.browser.night_mode.NightModeUtils;
import org.chromium.chrome.browser.night_mode.settings.ThemeSettingsFragment;
import org.chromium.chrome.browser.password_check.PasswordCheck;
import org.chromium.chrome.browser.password_check.PasswordCheckFactory;
import org.chromium.chrome.browser.password_manager.PasswordManagerUtilBridge;
import org.chromium.chrome.browser.password_manager.PasswordManagerUtilBridgeJni;
import org.chromium.chrome.browser.password_manager.settings.PasswordSettings;
import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
import org.chromium.chrome.browser.preferences.ChromeSharedPreferences;
import org.chromium.chrome.browser.privacy.settings.PrivacySettings;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.safety_check.SafetyCheckSettingsFragment;
import org.chromium.chrome.browser.safety_hub.SafetyHubFragment;
import org.chromium.chrome.browser.safety_hub.SafetyHubMetricUtils;
import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory;
import org.chromium.chrome.browser.search_engines.settings.SearchEngineSettings;
import org.chromium.chrome.browser.signin.SigninAndHistorySyncActivityLauncherImpl;
import org.chromium.chrome.browser.signin.SyncConsentActivityLauncherImpl;
import org.chromium.chrome.browser.sync.FakeSyncServiceImpl;
import org.chromium.chrome.browser.sync.SyncServiceFactory;
import org.chromium.chrome.browser.sync.SyncTestRule;
import org.chromium.chrome.browser.sync.settings.AccountManagementFragment;
import org.chromium.chrome.browser.sync.settings.ManageSyncSettings;
import org.chromium.chrome.browser.sync.settings.SignInPreference;
import org.chromium.chrome.browser.sync.settings.SyncPromoPreference;
import org.chromium.chrome.browser.sync.settings.SyncPromoPreference.State;
import org.chromium.chrome.browser.tasks.tab_management.TabsSettings;
import org.chromium.chrome.browser.tracing.settings.DeveloperSettings;
import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
import org.chromium.chrome.browser.ui.signin.SigninAndHistorySyncActivityLauncher;
import org.chromium.chrome.browser.ui.signin.SigninAndHistorySyncCoordinator;
import org.chromium.chrome.browser.ui.signin.SyncConsentActivityLauncher;
import org.chromium.chrome.browser.ui.signin.SyncPromoController;
import org.chromium.chrome.browser.ui.signin.account_picker.AccountPickerBottomSheetStrings;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.R;
import org.chromium.chrome.test.util.ChromeRenderTestRule;
import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule;
import org.chromium.chrome.test.util.browser.signin.SigninTestRule;
import org.chromium.chrome.test.util.browser.signin.SigninTestUtil;
import org.chromium.chrome.test.util.browser.sync.SyncTestUtil;
import org.chromium.components.autofill.AutofillFeatures;
import org.chromium.components.browser_ui.site_settings.SiteSettings;
import org.chromium.components.policy.test.annotations.Policies;
import org.chromium.components.search_engines.TemplateUrl;
import org.chromium.components.search_engines.TemplateUrlService;
import org.chromium.components.signin.SigninFeatures;
import org.chromium.components.signin.base.AccountInfo;
import org.chromium.components.signin.base.CoreAccountInfo;
import org.chromium.components.signin.identitymanager.ConsentLevel;
import org.chromium.components.signin.metrics.SigninAccessPoint;
import org.chromium.components.signin.test.util.AccountCapabilitiesBuilder;
import org.chromium.components.sync.SyncService;
import org.chromium.ui.test.util.RenderTestRule;
import java.io.IOException;
import java.util.HashSet;
/** Test for {@link MainSettings}. Main purpose is to have a quick confidence check on the xml. */
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "show-autofill-signatures"})
@DoNotBatch(reason = "Tests cannot run batched because they launch a Settings activity.")
@EnableFeatures(SigninFeatures.HIDE_SETTINGS_SIGN_IN_PROMO)
public class MainSettingsFragmentTest {
private static final String SEARCH_ENGINE_SHORT_NAME = "Google";
private static final int RENDER_TEST_REVISION = 13;
private static final String RENDER_TEST_DESCRIPTION =
"Alert icon on identity error for signed in users";
private final HomepageTestRule mHomepageTestRule = new HomepageTestRule();
private final SyncTestRule mSyncTestRule = new SyncTestRule();
private final SettingsActivityTestRule<MainSettings> mSettingsActivityTestRule =
new SettingsActivityTestRule<>(MainSettings.class);
// SettingsActivity needs to be initialized and destroyed with the mock
// signin environment setup in SyncTestRule
@Rule
public final RuleChain mRuleChain =
RuleChain.outerRule(mSyncTestRule)
.around(mHomepageTestRule)
.around(mSettingsActivityTestRule);
@Rule
public ChromeRenderTestRule mRenderTestRule =
ChromeRenderTestRule.Builder.withPublicCorpus()
.setRevision(RENDER_TEST_REVISION)
.setDescription(RENDER_TEST_DESCRIPTION)
.setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_MOBILE_SETTINGS)
.build();
@Rule public JniMocker mJniMocker = new JniMocker();
@Mock public TemplateUrlService mMockTemplateUrlService;
@Mock public TemplateUrl mMockSearchEngine;
@Mock private PasswordCheck mPasswordCheck;
@Mock private PasswordManagerUtilBridge.Natives mPasswordManagerUtilBridgeJniMock;
@Mock private SyncConsentActivityLauncher mSyncConsentActivityLauncher;
@Mock private SigninAndHistorySyncActivityLauncher mSigninAndHistorySyncActivityLauncher;
@Mock private HomeModulesConfigManager mHomeModulesConfigManager;
private MainSettings mMainSettings;
@Before
public void setup() {
// ObservableSupplierImpl needs a Looper.
Looper.prepare();
MockitoAnnotations.initMocks(this);
InstrumentationRegistry.getInstrumentation().setInTouchMode(true);
PasswordCheckFactory.setPasswordCheckForTesting(mPasswordCheck);
mJniMocker.mock(PasswordManagerUtilBridgeJni.TEST_HOOKS, mPasswordManagerUtilBridgeJniMock);
SyncConsentActivityLauncherImpl.setLauncherForTest(mSyncConsentActivityLauncher);
SigninAndHistorySyncActivityLauncherImpl.setLauncherForTest(
mSigninAndHistorySyncActivityLauncher);
DeveloperSettings.setIsEnabledForTests(true);
NightModeUtils.setNightModeSupportedForTesting(true);
Intents.init();
}
@After
public void tearDown() {
ChromeSharedPreferences.getInstance()
.removeKey(
SyncPromoController.getPromoShowCountPreferenceName(
SigninAccessPoint.SETTINGS));
ChromeSharedPreferences.getInstance()
.removeKey(ChromePreferenceKeys.SYNC_PROMO_TOTAL_SHOW_COUNT);
Intents.release();
}
@Test
@LargeTest
@Feature({"RenderTest"})
@DisabledTest(message = "http://b/issues/41491395")
public void testRenderDifferentSignedInStates() throws IOException {
launchSettingsActivity();
waitForOptionsMenu();
View view =
mSettingsActivityTestRule
.getActivity()
.findViewById(android.R.id.content)
.getRootView();
mRenderTestRule.render(view, "main_settings_signed_out");
// Sign in and render changes.
mSyncTestRule.setUpAccountAndEnableSyncForTesting();
SyncTestUtil.waitForSyncFeatureActive();
waitForOptionsMenu();
// Waiting for sync to become active might take some time, so the scrollbar on the settings
// view starts to fade, making the test flaky due to differences in the rendered image.
// Sanitize the view to hide scrollbars (see https://crbug.com/1204117 for details).
ThreadUtils.runOnUiThreadBlocking(() -> RenderTestRule.sanitize(view));
mRenderTestRule.render(view, "main_settings_signed_in");
}
@Test
@LargeTest
@Feature({"RenderTest"})
@EnableFeatures(ChromeFeatureList.REPLACE_SYNC_PROMOS_WITH_SIGN_IN_PROMOS)
public void testRenderSignedOutAccountManagementRows_replaceSyncBySigninEnabled()
throws IOException {
launchSettingsActivity();
waitForOptionsMenu();
View accountRow =
mSettingsActivityTestRule
.getActivity()
.findViewById(R.id.account_management_account_row);
mRenderTestRule.render(
accountRow, "main_settings_signed_out_account_replace_sync_by_signin_enabled");
View googleServicesRow =
mSettingsActivityTestRule
.getActivity()
.findViewById(R.id.account_management_google_services_row);
mRenderTestRule.render(
googleServicesRow,
"main_settings_signed_out_google_services_replace_sync_by_signin_enabled");
}
@Test
@LargeTest
@Feature({"RenderTest"})
@Policies.Add({@Policies.Item(key = "BrowserSignin", string = "0")})
@EnableFeatures(ChromeFeatureList.REPLACE_SYNC_PROMOS_WITH_SIGN_IN_PROMOS)
public void testRenderSigninDisabledByPolicyAccountRow_replaceSyncBySigninEnabled()
throws IOException {
launchSettingsActivity();
waitForOptionsMenu();
View accountRow =
mSettingsActivityTestRule
.getActivity()
.findViewById(R.id.account_management_account_row);
mRenderTestRule.render(
accountRow,
"main_settings_signin_disabled_by_policy_account_replace_sync_by_signin_enabled");
}
/**
* Test for the "Account" section.
*
* <p>TODO(b/324562205): update to check for Safety Hub instead of Safety Check once it's fully
* launched.
*/
@Test
@SmallTest
@EnableFeatures(AutofillFeatures.AUTOFILL_VIRTUAL_VIEW_STRUCTURE_ANDROID)
@DisableFeatures(ChromeFeatureList.SAFETY_HUB)
public void testStartup() {
launchSettingsActivity();
// For non-signed-in users, the section contains the generic header.
assertSettingsExists(MainSettings.PREF_SIGN_IN, null);
Assert.assertTrue(
"Google services preference should be shown",
mMainSettings.findPreference(MainSettings.PREF_GOOGLE_SERVICES).isVisible());
// SignInPreference status check.
// As the user is not signed in, sign in promo and section header will show. Sync preference
// will be hidden.
Assert.assertTrue(
"Account section header should be visible.",
mMainSettings
.findPreference(MainSettings.PREF_ACCOUNT_AND_GOOGLE_SERVICES_SECTION)
.isVisible());
Assert.assertFalse(
"Sync preference should be hidden",
mMainSettings.findPreference(MainSettings.PREF_MANAGE_SYNC).isVisible());
// Assert for "Basics" section
assertSettingsExists(MainSettings.PREF_SEARCH_ENGINE, SearchEngineSettings.class);
if (supportThirdPartyFillingSetting()) {
assertSettingsExists(MainSettings.PREF_AUTOFILL_OPTIONS, null);
assertSettingsExists(MainSettings.PREF_AUTOFILL_SECTION, null);
assertSettingsExists(MainSettings.PREF_PRIVACY_SECTION, null);
} else {
Assert.assertNull(
"Third party filling setting should be hidden",
mMainSettings.findPreference(MainSettings.PREF_AUTOFILL_OPTIONS));
Assert.assertNull(
"Autofill section header should be hidden",
mMainSettings.findPreference(MainSettings.PREF_AUTOFILL_SECTION));
Assert.assertNull(
"Privacy section header should be hidden",
mMainSettings.findPreference(MainSettings.PREF_PRIVACY_SECTION));
}
assertSettingsExists(MainSettings.PREF_PASSWORDS, PasswordSettings.class);
assertSettingsExists("autofill_payment_methods", AutofillPaymentMethodsFragment.class);
assertSettingsExists("autofill_addresses", AutofillProfilesFragment.class);
if (supportNotificationSettings()) {
assertSettingsExists(MainSettings.PREF_NOTIFICATIONS, null);
} else {
Assert.assertNull(
"Notification setting should be hidden",
mMainSettings.findPreference(MainSettings.PREF_NOTIFICATIONS));
}
assertSettingsExists(MainSettings.PREF_HOMEPAGE, HomepageSettings.class);
Preference themePref =
assertSettingsExists(MainSettings.PREF_UI_THEME, ThemeSettingsFragment.class);
Assert.assertEquals(
"ThemeSettingsEntry is missing.",
ThemeSettingsEntry.SETTINGS,
themePref.getExtras().getInt(ThemeSettingsFragment.KEY_THEME_SETTINGS_ENTRY));
// Verification for summary for the search engine and the homepage
Assert.assertEquals(
"Homepage summary is different than homepage state",
mMainSettings.getString(R.string.text_on),
mMainSettings.findPreference(MainSettings.PREF_HOMEPAGE).getSummary().toString());
// Assert for advanced section
assertSettingsExists("privacy", PrivacySettings.class);
if (BuildInfo.getInstance().isAutomotive) {
Assert.assertNull(
"Safety check should not be shown on automotive",
mMainSettings.findPreference(MainSettings.PREF_SAFETY_CHECK));
} else {
assertSettingsExists(MainSettings.PREF_SAFETY_CHECK, SafetyCheckSettingsFragment.class);
}
assertSettingsExists("accessibility", AccessibilitySettings.class);
assertSettingsExists("content_settings", SiteSettings.class);
assertSettingsExists("languages", LanguageSettings.class);
assertSettingsExists(MainSettings.PREF_DOWNLOADS, DownloadSettings.class);
assertSettingsExists(MainSettings.PREF_DEVELOPER, DeveloperSettings.class);
assertSettingsExists("about_chrome", AboutChromeSettings.class);
}
@Test
@SmallTest
@DisableFeatures({
ChromeFeatureList.SAFETY_HUB,
AutofillFeatures.AUTOFILL_VIRTUAL_VIEW_STRUCTURE_ANDROID
})
public void testLegacyOrderRemainsConsistent() {
launchSettingsActivity();
@Nullable Preference prevPref = null;
for (int i = 0; i < mMainSettings.getPreferenceScreen().getPreferenceCount(); ++i) {
Preference pref = mMainSettings.getPreferenceScreen().getPreference(i);
if (!pref.isShown()) { // Skip invisible prefs.
continue;
}
if (prevPref == null) { // Skip first pref.
prevPref = pref;
continue;
}
assertTrue(
prevPref.getTitle() + " should precede " + pref.getTitle(),
pref.getOrder() > prevPref.getOrder());
}
}
@Test
@SmallTest
@EnableFeatures(AutofillFeatures.AUTOFILL_VIRTUAL_VIEW_STRUCTURE_ANDROID)
@DisableFeatures(ChromeFeatureList.SAFETY_HUB)
public void testConsistentOrder() {
launchSettingsActivity();
@Nullable Preference prevPref = null;
for (int i = 0; i < mMainSettings.getPreferenceScreen().getPreferenceCount(); ++i) {
Preference pref = mMainSettings.getPreferenceScreen().getPreference(i);
if (!pref.isShown()) { // Skip invisible prefs.
continue;
}
if (prevPref == null) { // Skip first pref.
prevPref = pref;
continue;
}
assertTrue(
prevPref.getTitle() + " should precede " + pref.getTitle(),
pref.getOrder() > prevPref.getOrder());
}
}
@Test
@MediumTest
@DisableFeatures(ChromeFeatureList.REPLACE_SYNC_PROMOS_WITH_SIGN_IN_PROMOS)
public void testSignInRowLaunchesSyncFlowForSignedOutAccounts() {
// When there are no accounts, sync promo and the signin preference shows the same text.
mSyncTestRule.addTestAccount();
launchSettingsActivity();
onViewWaiting(allOf(withId(R.id.recycler_view), isDisplayed()));
onView(withId(R.id.recycler_view))
.perform(scrollTo(hasDescendant(withText(R.string.sync_promo_turn_on_sync))));
onView(withText(R.string.sync_promo_turn_on_sync)).perform(click());
verify(mSyncConsentActivityLauncher)
.launchActivityIfAllowed(
any(Activity.class), eq(SigninAccessPoint.SETTINGS_SYNC_OFF_ROW));
}
@Test
@LargeTest
@Feature({"Sync"})
@EnableFeatures({ChromeFeatureList.REPLACE_SYNC_PROMOS_WITH_SIGN_IN_PROMOS})
public void testPressingSignOut() {
CoreAccountInfo accountInfo = mSyncTestRule.setUpAccountAndSignInForTesting();
launchSettingsActivity();
onView(withText(accountInfo.getEmail())).perform(click());
onView(withId(R.id.recycler_view)).perform(RecyclerViewActions.scrollToLastPosition());
onView(withText(R.string.sign_out)).perform(click());
Assert.assertNull(mSyncTestRule.getSigninTestRule().getPrimaryAccount(ConsentLevel.SIGNIN));
Activity activity = mSettingsActivityTestRule.getActivity();
final String expectedSnackbarMessage =
activity.getString(R.string.sign_out_snackbar_message);
CriteriaHelper.pollUiThread(
() -> {
SnackbarManager snackbarManager =
((SnackbarManager.SnackbarManageable) activity).getSnackbarManager();
Criteria.checkThat(snackbarManager.isShowing(), Matchers.is(true));
TextView snackbarMessage = activity.findViewById(R.id.snackbar_message);
Criteria.checkThat(snackbarMessage, Matchers.notNullValue());
Criteria.checkThat(
snackbarMessage.getText().toString(),
Matchers.is(expectedSnackbarMessage));
});
}
@Test
@LargeTest
@Feature({"Sync"})
@EnableFeatures({ChromeFeatureList.REPLACE_SYNC_PROMOS_WITH_SIGN_IN_PROMOS})
public void testPressingTurnOffSyncWhileTheUNOFlagIsEnabled() {
mSyncTestRule.setUpChildAccountAndEnableSyncForTesting();
launchSettingsActivity();
onView(withText(R.string.sync_category_title)).perform(click());
onView(withId(R.id.recycler_view)).perform(RecyclerViewActions.scrollToLastPosition());
onView(withText(R.string.turn_off_sync)).perform(click());
onView(withText(R.string.continue_button)).perform(click());
Assert.assertNull(mSyncTestRule.getSigninTestRule().getPrimaryAccount(ConsentLevel.SYNC));
Assert.assertNotNull(
mSyncTestRule.getSigninTestRule().getPrimaryAccount(ConsentLevel.SIGNIN));
Activity activity = mSettingsActivityTestRule.getActivity();
CriteriaHelper.pollUiThread(
() -> {
SnackbarManager snackbarManager =
((SnackbarManager.SnackbarManageable) activity).getSnackbarManager();
Criteria.checkThat(snackbarManager.isShowing(), Matchers.is(false));
TextView snackbarMessage = activity.findViewById(R.id.snackbar_message);
Criteria.checkThat(snackbarMessage, Matchers.nullValue());
});
}
@Test
@MediumTest
@EnableFeatures(ChromeFeatureList.REPLACE_SYNC_PROMOS_WITH_SIGN_IN_PROMOS)
public void testSignInRowLaunchesSignInFlowForSignedOutAccounts() {
mSyncTestRule.addTestAccount();
launchSettingsActivity();
onView(withId(R.id.recycler_view))
.perform(scrollTo(hasDescendant(withText(R.string.signin_settings_title))));
onView(withText(R.string.signin_settings_subtitle)).check(matches(isDisplayed()));
onView(withText(R.string.signin_settings_title)).perform(click());
verify(mSigninAndHistorySyncActivityLauncher)
.launchActivityIfAllowed(
any(Activity.class),
any(Profile.class),
any(AccountPickerBottomSheetStrings.class),
eq(SigninAndHistorySyncCoordinator.NoAccountSigninMode.BOTTOM_SHEET),
eq(
SigninAndHistorySyncCoordinator.WithAccountSigninMode
.DEFAULT_ACCOUNT_BOTTOM_SHEET),
eq(SigninAndHistorySyncCoordinator.HistoryOptInMode.OPTIONAL),
eq(SigninAccessPoint.SETTINGS));
}
@Test
@SmallTest
@DisableFeatures(ChromeFeatureList.REPLACE_SYNC_PROMOS_WITH_SIGN_IN_PROMOS)
public void testSyncRowLaunchesSignInFlowForSignedInAccounts() {
CoreAccountInfo accountInfo = mSyncTestRule.setUpAccountAndSignInForTesting();
launchSettingsActivity();
onViewWaiting(allOf(withId(R.id.recycler_view), isDisplayed()));
onView(withId(R.id.recycler_view))
.perform(scrollTo(hasDescendant(withText(R.string.sync_category_title))));
onView(withText(R.string.sync_category_title)).perform(click());
verify(mSyncConsentActivityLauncher)
.launchActivityForPromoDefaultFlow(
any(Activity.class),
eq(SigninAccessPoint.SETTINGS_SYNC_OFF_ROW),
eq(accountInfo.getEmail()));
}
// Tests that no alert icon is visible if there are no identity errors.
@Test
@SmallTest
public void testSigninRowShowsNoAlertWhenNoIdentityErrors() {
// Sign-in and open settings.
mSyncTestRule.setUpAccountAndSignInForTesting();
launchSettingsActivity();
assertSettingsExists(
MainSettings.PREF_SIGN_IN,
ChromeFeatureList.isEnabled(
ChromeFeatureList.REPLACE_SYNC_PROMOS_WITH_SIGN_IN_PROMOS)
? ManageSyncSettings.class
: AccountManagementFragment.class);
onView(allOf(withId(R.id.alert_icon), isDisplayed())).check(doesNotExist());
}
// Tests that no alert icon is shown on the account row for syncing users, even if there exists
// an identity error.
@Test
@SmallTest
public void testSigninRowShowsNoAlertForIdentityErrorsForSyncingUsers() {
FakeSyncServiceImpl fakeSyncService =
ThreadUtils.runOnUiThreadBlocking(
() -> {
FakeSyncServiceImpl fakeSyncServiceImpl = new FakeSyncServiceImpl();
SyncServiceFactory.setInstanceForTesting(fakeSyncServiceImpl);
return fakeSyncServiceImpl;
});
// Fake an identity error.
fakeSyncService.setRequiresClientUpgrade(true);
// Sign-in and enable sync. Open settings.
mSyncTestRule.setUpAccountAndEnableSyncForTesting();
launchSettingsActivity();
assertSettingsExists(MainSettings.PREF_SIGN_IN, AccountManagementFragment.class);
onView(allOf(withId(R.id.alert_icon), isDisplayed())).check(doesNotExist());
}
// Tests that an alert icon is shown on the account row in case of an identity error for a
// signed-in non-syncing user.
@Test
@SmallTest
public void testSigninRowShowsAlertForIdentityErrors() {
FakeSyncServiceImpl fakeSyncService =
ThreadUtils.runOnUiThreadBlocking(
() -> {
FakeSyncServiceImpl fakeSyncServiceImpl = new FakeSyncServiceImpl();
SyncServiceFactory.setInstanceForTesting(fakeSyncServiceImpl);
return fakeSyncServiceImpl;
});
// Fake an identity error.
fakeSyncService.setRequiresClientUpgrade(true);
// Sign in and open settings.
mSyncTestRule.setUpAccountAndSignInForTesting();
launchSettingsActivity();
assertSettingsExists(
MainSettings.PREF_SIGN_IN,
ChromeFeatureList.isEnabled(
ChromeFeatureList.REPLACE_SYNC_PROMOS_WITH_SIGN_IN_PROMOS)
? ManageSyncSettings.class
: AccountManagementFragment.class);
onView(allOf(withId(R.id.alert_icon), isDisplayed())).check(matches(isDisplayed()));
}
@Test
@LargeTest
@Feature({"RenderTest"})
@DisableFeatures(ChromeFeatureList.REPLACE_SYNC_PROMOS_WITH_SIGN_IN_PROMOS)
public void testRenderOnIdentityErrorForSignedInUsers_withoutReplaceSyncPromos()
throws IOException {
FakeSyncServiceImpl fakeSyncService =
ThreadUtils.runOnUiThreadBlocking(
() -> {
FakeSyncServiceImpl fakeSyncServiceImpl = new FakeSyncServiceImpl();
SyncServiceFactory.setInstanceForTesting(fakeSyncServiceImpl);
return fakeSyncServiceImpl;
});
// Fake an identity error.
fakeSyncService.setRequiresClientUpgrade(true);
// Sign in and wait for sync machinery to be active.
mSyncTestRule.setUpAccountAndSignInForTesting();
SyncTestUtil.waitForSyncTransportActive();
launchSettingsActivity();
View view =
mSettingsActivityTestRule
.getActivity()
.findViewById(android.R.id.content)
.getRootView();
mRenderTestRule.render(view, "main_settings_signed_in_identity_error");
}
@Test
@LargeTest
@Feature({"RenderTest"})
@EnableFeatures(ChromeFeatureList.REPLACE_SYNC_PROMOS_WITH_SIGN_IN_PROMOS)
public void testRenderOnIdentityErrorForSignedInUsers_withReplaceSyncPromos()
throws IOException {
FakeSyncServiceImpl fakeSyncService =
ThreadUtils.runOnUiThreadBlocking(
() -> {
FakeSyncServiceImpl fakeSyncServiceImpl = new FakeSyncServiceImpl();
SyncServiceFactory.setInstanceForTesting(fakeSyncServiceImpl);
return fakeSyncServiceImpl;
});
// Fake an identity error.
fakeSyncService.setRequiresClientUpgrade(true);
// Sign in and wait for sync machinery to be active.
CoreAccountInfo accountInfo = mSyncTestRule.setUpAccountAndSignInForTesting();
SyncTestUtil.waitForSyncTransportActive();
launchSettingsActivity();
// Population of profile data is flaky. Thus, wait till it's populated.
// TODO(crbug.com/40944114): Check if there exists an alternate way out.
SignInPreference signInPreference = mMainSettings.findPreference(MainSettings.PREF_SIGN_IN);
CriteriaHelper.pollUiThread(
() -> {
return signInPreference
.getProfileDataCache()
.hasProfileDataForTesting(accountInfo.getEmail());
});
View view =
mSettingsActivityTestRule
.getActivity()
.findViewById(android.R.id.content)
.getRootView();
mRenderTestRule.render(
view, "main_settings_signed_in_identity_error_with_replace_sync_promos");
}
@Test
@SmallTest
public void testSyncRowSummaryWhenNoDataTypeSynced() {
CoreAccountInfo account = mSyncTestRule.addTestAccount();
final SyncService syncService = SyncTestUtil.getSyncServiceForLastUsedProfile();
SigninTestUtil.signinAndEnableSync(account, syncService);
ThreadUtils.runOnUiThreadBlocking(
() -> {
syncService.setSelectedTypes(false, new HashSet<>());
});
launchSettingsActivity();
onView(withText(R.string.sync_data_types_off)).check(matches(isDisplayed()));
}
@Test
@SmallTest
public void testSyncRowSummaryWhenUpmBackendOutdated() {
when(mPasswordManagerUtilBridgeJniMock.isGmsCoreUpdateRequired(any(), any()))
.thenReturn(true);
mSyncTestRule.setUpAccountAndEnableSyncForTesting();
SyncTestUtil.waitForSyncFeatureActive();
launchSettingsActivity();
onViewWaiting(withText(R.string.sync_error_outdated_gms)).check(matches(isDisplayed()));
}
@Test
@SmallTest
public void testSafeBrowsingSecuritySectionUiFlagOn() {
launchSettingsActivity();
assertSettingsExists(MainSettings.PREF_PRIVACY, PrivacySettings.class);
Assert.assertEquals(
mMainSettings.getString(R.string.prefs_privacy_security),
mMainSettings.findPreference(MainSettings.PREF_PRIVACY).getTitle().toString());
}
@Test
@SmallTest
public void testHomepageOff() {
mHomepageTestRule.disableHomepageForTest();
launchSettingsActivity();
// Verification for summary for the search engine and the homepage
Assert.assertEquals(
"Homepage summary is different than homepage state",
mMainSettings.getString(R.string.text_off),
mMainSettings.findPreference(MainSettings.PREF_HOMEPAGE).getSummary().toString());
}
@Test
@SmallTest
public void testSearchEngineDisabled() {
Mockito.doReturn(false).when(mMockTemplateUrlService).isLoaded();
configureMockSearchEngine();
launchSettingsActivity();
Preference searchEngineSettings =
assertSettingsExists(MainSettings.PREF_SEARCH_ENGINE, SearchEngineSettings.class);
// Verification for summary for the search engine and the homepage
Assert.assertFalse(
"Search Engine preference should be disabled when service is not ready.",
searchEngineSettings.isEnabled());
Assert.assertTrue(
"Search Engine preference should be disabled when service is not ready.",
TextUtils.isEmpty(searchEngineSettings.getSummary()));
}
@Test
@SmallTest
@DisabledTest(message = "http://b/issues/41491395")
public void testAccountSignIn() throws InterruptedException {
launchSettingsActivity();
SyncPromoPreference syncPromoPreference =
(SyncPromoPreference) mMainSettings.findPreference(MainSettings.PREF_SYNC_PROMO);
Assert.assertEquals(
"SyncPromoPreference should be at the personalized signin promo state. ",
syncPromoPreference.getState(),
State.PERSONALIZED_SIGNIN_PROMO);
Assert.assertTrue(
"Account section header should be shown together with the promo.",
mMainSettings
.findPreference(MainSettings.PREF_ACCOUNT_AND_GOOGLE_SERVICES_SECTION)
.isVisible());
Assert.assertFalse(
"Sync preference should be hidden when promo is shown.",
mMainSettings.findPreference(MainSettings.PREF_MANAGE_SYNC).isVisible());
CoreAccountInfo account = mSyncTestRule.setUpAccountAndEnableSyncForTesting();
SyncTestUtil.waitForSyncFeatureActive();
Assert.assertEquals(
"SignInPreference should be at the signed in state.",
account.getEmail(),
mMainSettings.findPreference(MainSettings.PREF_SIGN_IN).getSummary().toString());
assertSettingsExists(MainSettings.PREF_SIGN_IN, AccountManagementFragment.class);
Assert.assertTrue(
"Account section header should be shown when user signed in.",
mMainSettings
.findPreference(MainSettings.PREF_ACCOUNT_AND_GOOGLE_SERVICES_SECTION)
.isVisible());
Assert.assertTrue(
"Sync preference should be shown when the user is signed in.",
mMainSettings.findPreference(MainSettings.PREF_MANAGE_SYNC).isVisible());
}
@Test
@MediumTest
@EnableFeatures(SigninFeatures.HIDE_SETTINGS_SIGN_IN_PROMO)
public void testSignInPromoHidden_HideSignInPromoEnabled() {
launchSettingsActivity();
onView(withText(R.string.sync_promo_title_settings)).check(doesNotExist());
}
@Test
@SmallTest
@EnableFeatures(ChromeFeatureList.REPLACE_SYNC_PROMOS_WITH_SIGN_IN_PROMOS)
public void
testManageSyncRowIsNotShownWhenReplaceSyncPromosWithSignInPromosEnabledWithoutSyncConsent()
throws InterruptedException {
launchSettingsActivity();
Assert.assertFalse(
"Sync preference should be hidden when the user is signed out.",
mMainSettings.findPreference(MainSettings.PREF_MANAGE_SYNC).isVisible());
mSyncTestRule.setUpAccountAndSignInForTesting();
Assert.assertFalse(
"Sync preference should not be shown when the user is signed in.",
mMainSettings.findPreference(MainSettings.PREF_MANAGE_SYNC).isVisible());
}
@Test
@SmallTest
@EnableFeatures(ChromeFeatureList.REPLACE_SYNC_PROMOS_WITH_SIGN_IN_PROMOS)
@DisabledTest(message = "http://b/issues/41491395")
public void
testManageSyncRowIsShownWhenReplaceSyncPromosWithSignInPromosEnabledWithSyncConsent()
throws InterruptedException {
launchSettingsActivity();
Assert.assertFalse(
"Sync preference should be hidden when the user is signed out.",
mMainSettings.findPreference(MainSettings.PREF_MANAGE_SYNC).isVisible());
mSyncTestRule.setUpAccountAndEnableSyncForTesting();
SyncTestUtil.waitForSyncFeatureActive();
Assert.assertTrue(
"Sync preference should be shown when the user is syncing.",
mMainSettings.findPreference(MainSettings.PREF_MANAGE_SYNC).isVisible());
}
@Test
@SmallTest
public void testAccountManagementRowForChildAccountWithNonDisplayableAccountEmail()
throws InterruptedException {
launchSettingsActivity();
// Account set up.
final SigninTestRule signinTestRule = mSyncTestRule.getSigninTestRule();
AccountInfo accountInfo =
signinTestRule.addChildTestAccountThenWaitForSignin(
new AccountCapabilitiesBuilder().setCanHaveEmailAddressDisplayed(false));
// Force update the preference so that NON_DISPLAYABLE_EMAIL_ACCOUNT_CAPABILITIES is
// actually utilized. This is to replicate downstream implementation behavior, where
// checkIfDisplayableEmailAddress() differs.
SignInPreference signInPreference = mMainSettings.findPreference(MainSettings.PREF_SIGN_IN);
CriteriaHelper.pollUiThread(
() -> {
return !signInPreference
.getProfileDataCache()
.getProfileDataOrDefault(accountInfo.getEmail())
.hasDisplayableEmailAddress();
});
ThreadUtils.runOnUiThreadBlocking(signInPreference::syncStateChanged);
mSettingsActivityTestRule.startSettingsActivity();
onView(allOf(withText(accountInfo.getFullName()), isDisplayed()))
.check(matches(isDisplayed()));
onView(withText(accountInfo.getEmail())).check(doesNotExist());
}
@Test
@SmallTest
@DisabledTest(message = "crbug.com/362211398")
public void
testAccountManagementRowForChildAccountWithNonDisplayableAccountEmailWithEmptyDisplayName()
throws InterruptedException {
launchSettingsActivity();
// Account set up.
// If both fullName and givenName are empty, accountCapabilities is ignored.
final SigninTestRule signinTestRule = mSyncTestRule.getSigninTestRule();
signinTestRule.addAccountThenSignin(
AccountManagerTestRule.TEST_ACCOUNT_NON_DISPLAYABLE_EMAIL_AND_NO_NAME);
SignInPreference signInPreference = mMainSettings.findPreference(MainSettings.PREF_SIGN_IN);
CriteriaHelper.pollUiThread(
() -> {
return !signInPreference
.getProfileDataCache()
.getProfileDataOrDefault(
AccountManagerTestRule
.TEST_ACCOUNT_NON_DISPLAYABLE_EMAIL_AND_NO_NAME
.getEmail())
.hasDisplayableEmailAddress();
});
ThreadUtils.runOnUiThreadBlocking(signInPreference::syncStateChanged);
mSettingsActivityTestRule.startSettingsActivity();
onView(
withText(
AccountManagerTestRule
.TEST_ACCOUNT_NON_DISPLAYABLE_EMAIL_AND_NO_NAME
.getEmail()))
.check(doesNotExist());
onView(allOf(withText(R.string.default_google_account_username), isDisplayed()))
.check(matches(isDisplayed()));
}
@Test
@SmallTest
public void testRemoveSettings() {
// Disable night mode
NightModeUtils.setNightModeSupportedForTesting(false);
// Disable developer option
DeveloperSettings.setIsEnabledForTests(false);
launchSettingsActivity();
Assert.assertNull(
"Preference should be disabled: " + MainSettings.PREF_UI_THEME,
mMainSettings.findPreference(MainSettings.PREF_UI_THEME));
Assert.assertNull(
"Preference should be disabled: " + MainSettings.PREF_DEVELOPER,
mMainSettings.findPreference(MainSettings.PREF_DEVELOPER));
}
@Test
@SmallTest
public void testDestroysPasswordCheck() {
launchSettingsActivity();
Activity activity = mMainSettings.getActivity();
activity.finish();
CriteriaHelper.pollUiThread(() -> activity.isDestroyed());
Assert.assertNull(PasswordCheckFactory.getPasswordCheckInstance());
}
@Test
@MediumTest
@DisableFeatures({
SigninFeatures.HIDE_SETTINGS_SIGN_IN_PROMO,
ChromeFeatureList.REPLACE_SYNC_PROMOS_WITH_SIGN_IN_PROMOS
})
public void testSyncPromoNotShownAfterBeingDismissed() throws Exception {
var dismissedCountHistogram =
HistogramWatcher.newSingleRecordWatcher(
"Signin.SyncPromo.Dismissed.Count.Settings", 1);
launchSettingsActivity();
onViewWaiting(allOf(withId(R.id.signin_promo_view_container), isDisplayed()));
onView(withId(R.id.sync_promo_close_button)).perform(click());
onView(withId(R.id.signin_promo_view_container)).check(doesNotExist());
// Close settings activity.
Activity activity = mMainSettings.getActivity();
ApplicationTestUtils.finishActivity(activity);
// Launch settings activity again.
mSettingsActivityTestRule.startSettingsActivity();
onView(withId(R.id.signin_promo_view_container)).check(doesNotExist());
dismissedCountHistogram.assertExpected();
}
@Test
@MediumTest
@DisableFeatures({
SigninFeatures.HIDE_SETTINGS_SIGN_IN_PROMO,
ChromeFeatureList.REPLACE_SYNC_PROMOS_WITH_SIGN_IN_PROMOS
})
public void testSyncPromoShownIsNotOverCounted() {
var showCountHistogram =
HistogramWatcher.newSingleRecordWatcher("Signin.SyncPromo.Shown.Count.Settings", 1);
int promoShowCount =
ChromeSharedPreferences.getInstance()
.readInt(
SyncPromoController.getPromoShowCountPreferenceName(
SigninAccessPoint.SETTINGS));
Assert.assertEquals(0, promoShowCount);
Assert.assertEquals(
0,
ChromeSharedPreferences.getInstance()
.readInt(ChromePreferenceKeys.SYNC_PROMO_TOTAL_SHOW_COUNT));
launchSettingsActivity();
onViewWaiting(allOf(withId(R.id.signin_promo_view_container), isDisplayed()));
promoShowCount =
ChromeSharedPreferences.getInstance()
.readInt(
SyncPromoController.getPromoShowCountPreferenceName(
SigninAccessPoint.SETTINGS));
Assert.assertEquals(1, promoShowCount);
Assert.assertEquals(
1,
ChromeSharedPreferences.getInstance()
.readInt(ChromePreferenceKeys.SYNC_PROMO_TOTAL_SHOW_COUNT));
showCountHistogram.assertExpected();
}
@Test
@SmallTest
// Setting BrowserSignin suppresses the sync promo so the password settings preference
// is visible without scrolling.
@Policies.Add({
@Policies.Item(key = "PasswordManagerEnabled", string = "false"),
@Policies.Item(key = "BrowserSignin", string = "0")
})
public void testPasswordsItemClickableWhenManaged() {
launchSettingsActivity();
onData(withKey(MainSettings.PREF_PASSWORDS))
.inAdapterView(
allOf(
isDisplayed(),
hasDescendant(withText(R.string.password_manager_settings_title)),
hasDescendant(
allOf(
withText(R.string.managed_by_your_organization),
isDisplayed()))));
Assert.assertTrue(mMainSettings.findPreference(MainSettings.PREF_PASSWORDS).isEnabled());
Assert.assertNotNull(
mMainSettings
.findPreference(MainSettings.PREF_PASSWORDS)
.getOnPreferenceClickListener());
}
@Test
@SmallTest
@Policies.Remove({@Policies.Item(key = "PasswordManagerEnabled", string = "false")})
// Setting BrowserSignin suppresses the sync promo so the password settings preference
// is visible without scrolling.
@Policies.Add(@Policies.Item(key = "BrowserSignin", string = "0"))
public void testPasswordsItemEnabledWhenNotManaged() throws InterruptedException {
launchSettingsActivity();
onData(withKey(MainSettings.PREF_PASSWORDS))
.inAdapterView(
allOf(
isDisplayed(),
hasDescendant(withText(R.string.password_manager_settings_title)),
hasDescendant(
allOf(
withText(R.string.managed_by_your_organization),
not(isDisplayed())))));
Assert.assertTrue(mMainSettings.findPreference(MainSettings.PREF_PASSWORDS).isEnabled());
Assert.assertNotNull(
mMainSettings
.findPreference(MainSettings.PREF_PASSWORDS)
.getOnPreferenceClickListener());
}
@Test
@SmallTest
@DisableFeatures(ChromeFeatureList.PLUS_ADDRESSES_ENABLED)
public void testPlusAddressesHiddenWhenNotEnabled() {
Assert.assertFalse(ChromeFeatureList.isEnabled(ChromeFeatureList.PLUS_ADDRESSES_ENABLED));
launchSettingsActivity();
Assert.assertNull(mMainSettings.findPreference(MainSettings.PREF_PLUS_ADDRESSES));
}
@Test
@SmallTest
public void testPlusAddressesHiddenWhenLabelIsEmpty() {
Assert.assertTrue(
ChromeFeatureList.getFieldTrialParamByFeature(
ChromeFeatureList.PLUS_ADDRESSES_ENABLED, "settings-label")
.isEmpty());
launchSettingsActivity();
Assert.assertNull(mMainSettings.findPreference(MainSettings.PREF_PLUS_ADDRESSES));
}
@Test
@SmallTest
@CommandLineFlags.Add({
"enable-features=PlusAddressesEnabled:"
+ "settings-label/PlusAddressesTestTitle/"
+ "manage-url/https%3A%2F%2Ftest.plusaddresses.google.com"
})
public void testPlusAddressesEnabled() {
launchSettingsActivity();
Preference preference = mMainSettings.findPreference(MainSettings.PREF_PLUS_ADDRESSES);
Assert.assertNotNull(preference);
Assert.assertTrue(preference.isVisible());
Assert.assertEquals(preference.getTitle(), "PlusAddressesTestTitle");
onView(withId(R.id.recycler_view))
.perform(scrollTo(hasDescendant(withText("PlusAddressesTestTitle"))));
onView(withText("PlusAddressesTestTitle")).perform(click());
intended(IntentMatchers.hasData("https://test.plusaddresses.google.com"));
}
@Test
@SmallTest
public void testHomeModulesConfigSettingsWithCustomizableModule() {
when(mHomeModulesConfigManager.hasModuleShownInSettings()).thenReturn(true);
HomeModulesConfigManager.setInstanceForTesting(mHomeModulesConfigManager);
launchSettingsActivity();
assertSettingsExists(
MainSettings.PREF_HOME_MODULES_CONFIG, HomeModulesConfigSettings.class);
}
@Test
@SmallTest
public void testHomeModulesConfigSettingsWithoutCustomizableModule() {
when(mHomeModulesConfigManager.hasModuleShownInSettings()).thenReturn(false);
HomeModulesConfigManager.setInstanceForTesting(mHomeModulesConfigManager);
launchSettingsActivity();
Assert.assertNull(
"Home modules config setting should not be shown on automotive",
mMainSettings.findPreference(MainSettings.PREF_HOME_MODULES_CONFIG));
}
@Test
@SmallTest
@EnableFeatures({
ChromeFeatureList.TAB_GROUP_SYNC_ANDROID,
ChromeFeatureList.TAB_GROUP_SYNC_AUTO_OPEN_KILL_SWITCH
})
@DisableFeatures(ChromeFeatureList.ANDROID_TAB_DECLUTTER)
public void testTabsSettingsOn_GroupSync_KillSwitchInactive() {
launchSettingsActivity();
assertSettingsExists(MainSettings.PREF_TABS, TabsSettings.class);
}
@Test
@SmallTest
@EnableFeatures(ChromeFeatureList.TAB_GROUP_SYNC_ANDROID)
@DisableFeatures({
ChromeFeatureList.ANDROID_TAB_DECLUTTER,
ChromeFeatureList.TAB_GROUP_CREATION_DIALOG_ANDROID,
ChromeFeatureList.TAB_GROUP_PARITY_ANDROID,
ChromeFeatureList.TAB_GROUP_SYNC_AUTO_OPEN_KILL_SWITCH
})
public void testTabsSettingsOn_GroupSync_KillSwitchActive() {
launchSettingsActivity();
Assert.assertNull(
"Tabs settings should not be shown",
mMainSettings.findPreference(MainSettings.PREF_TABS));
}
@Test
@SmallTest
@DisableFeatures({
ChromeFeatureList.TAB_GROUP_SYNC_ANDROID,
ChromeFeatureList.TAB_GROUP_SYNC_AUTO_OPEN_KILL_SWITCH
})
@EnableFeatures(ChromeFeatureList.ANDROID_TAB_DECLUTTER)
public void testTabsSettingsOn_Declutter() {
launchSettingsActivity();
assertSettingsExists(MainSettings.PREF_TABS, TabsSettings.class);
}
@Test
@SmallTest
@DisableFeatures({
ChromeFeatureList.ANDROID_TAB_DECLUTTER,
ChromeFeatureList.TAB_GROUP_CREATION_DIALOG_ANDROID,
ChromeFeatureList.TAB_GROUP_PARITY_ANDROID,
ChromeFeatureList.TAB_GROUP_SYNC_ANDROID
})
@EnableFeatures(ChromeFeatureList.TAB_GROUP_SYNC_AUTO_OPEN_KILL_SWITCH)
public void testTabsSettingsOff() {
launchSettingsActivity();
Assert.assertNull(
"Tabs settings should not be shown",
mMainSettings.findPreference(MainSettings.PREF_TABS));
}
@Test
@SmallTest
@EnableFeatures(ChromeFeatureList.SAFETY_HUB)
public void testSafetyHubFlagOn() {
launchSettingsActivity();
if (BuildInfo.getInstance().isAutomotive) {
Assert.assertNull(
"Safety hub should not be shown on automotive",
mMainSettings.findPreference(MainSettings.PREF_SAFETY_HUB));
Assert.assertNull(
"Safety check should not be shown on automotive",
mMainSettings.findPreference(MainSettings.PREF_SAFETY_CHECK));
return;
}
assertSettingsExists(MainSettings.PREF_SAFETY_HUB, SafetyHubFragment.class);
// Safety check should be hidden when safety hub is enabled.
Assert.assertNull(
"Safety check setting should be hidden",
mMainSettings.findPreference(MainSettings.PREF_SAFETY_CHECK));
// Verify that the correct metrics are logged.
HistogramWatcher histogramExpectation =
HistogramWatcher.newSingleRecordWatcher(
SafetyHubMetricUtils.EXTERNAL_INTERACTIONS_HISTOGRAM_NAME,
SafetyHubMetricUtils.ExternalInteractions.OPEN_FROM_SETTINGS_PAGE);
onView(withId(R.id.recycler_view))
.perform(scrollTo(hasDescendant(withText(R.string.prefs_safety_check))));
onView(withText(R.string.prefs_safety_check)).perform(click());
histogramExpectation.assertExpected();
}
@Test
@SmallTest
@DisableFeatures(ChromeFeatureList.SAFETY_HUB)
public void testSafetyHubFlagOff() {
launchSettingsActivity();
if (BuildInfo.getInstance().isAutomotive) {
Assert.assertNull(
"Safety hub should not be shown on automotive",
mMainSettings.findPreference(MainSettings.PREF_SAFETY_HUB));
Assert.assertNull(
"Safety check should not be shown on automotive",
mMainSettings.findPreference(MainSettings.PREF_SAFETY_CHECK));
} else {
assertSettingsExists(MainSettings.PREF_SAFETY_CHECK, SafetyCheckSettingsFragment.class);
// Safety hub should be hidden when the flag is disabled.
Assert.assertNull(
"Safety hub setting should be hidden",
mMainSettings.findPreference(MainSettings.PREF_SAFETY_HUB));
}
}
private void launchSettingsActivity() {
mSettingsActivityTestRule.startSettingsActivity();
mMainSettings = mSettingsActivityTestRule.getFragment();
Assert.assertNotNull("SettingsActivity failed to launch.", mMainSettings);
}
private void configureMockSearchEngine() {
TemplateUrlServiceFactory.setInstanceForTesting(mMockTemplateUrlService);
Mockito.doReturn(mMockSearchEngine)
.when(mMockTemplateUrlService)
.getDefaultSearchEngineTemplateUrl();
Mockito.doReturn(SEARCH_ENGINE_SHORT_NAME).when(mMockSearchEngine).getShortName();
}
private void waitForOptionsMenu() {
CriteriaHelper.pollUiThread(
() -> {
return mSettingsActivityTestRule
.getActivity()
.findViewById(R.id.menu_id_general_help)
!= null;
});
}
/**
* Assert the target preference exists in the main settings and creates the expected fragment,
* then return that preference.
*
* @param prefKey preference key for {@link
* androidx.preference.PreferenceFragmentCompat#findPreference(CharSequence)}
* @param settingsFragmentClass class name that the target preference is holding
* @return the target preference if exists, raise {@link AssertionError} otherwise.
*/
private Preference assertSettingsExists(String prefKey, @Nullable Class settingsFragmentClass) {
Preference pref = mMainSettings.findPreference(prefKey);
Assert.assertNotNull("Preference is missing: " + prefKey, pref);
if (settingsFragmentClass == null) return pref;
try {
Assert.assertNotNull(
"Fragment attached to the preference is null.", pref.getFragment());
Assert.assertEquals(
"Preference class is different.",
settingsFragmentClass,
Class.forName(pref.getFragment()));
} catch (ClassNotFoundException e) {
throw new AssertionError("Pref fragment <" + pref.getFragment() + "> is not found.");
}
return pref;
}
private boolean supportNotificationSettings() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return false;
return PackageManagerUtils.canResolveActivity(
new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS));
}
private boolean supportThirdPartyFillingSetting() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
}
}