// 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.

#import "base/i18n/message_formatter.h"
#import "base/strings/sys_string_conversions.h"
#import "base/test/ios/wait_util.h"
#import "components/policy/policy_constants.h"
#import "components/regional_capabilities/regional_capabilities_switches.h"
#import "components/signin/public/base/signin_switches.h"
#import "components/strings/grit/components_strings.h"
#import "components/sync/base/features.h"
#import "components/sync/base/user_selectable_type.h"
#import "ios/chrome/browser/authentication/account_menu/public/account_menu_constants.h"
#import "ios/chrome/browser/authentication/test/separate_profiles_util.h"
#import "ios/chrome/browser/authentication/test/signin_earl_grey.h"
#import "ios/chrome/browser/authentication/test/signin_earl_grey_app_interface.h"
#import "ios/chrome/browser/authentication/test/signin_earl_grey_ui_test_util.h"
#import "ios/chrome/browser/authentication/test/signin_matchers.h"
#import "ios/chrome/browser/authentication/ui_bundled/views/views_constants.h"
#import "ios/chrome/browser/bookmarks/model/bookmark_storage_type.h"
#import "ios/chrome/browser/bookmarks/test/bookmark_earl_grey.h"
#import "ios/chrome/browser/device_reauth/test/reauthentication_app_interface.h"
#import "ios/chrome/browser/ntp/ui_bundled/new_tab_page_feature.h"
#import "ios/chrome/browser/policy/model/policy_app_interface.h"
#import "ios/chrome/browser/policy/model/policy_earl_grey_utils.h"
#import "ios/chrome/browser/policy/model/policy_util.h"
#import "ios/chrome/browser/reading_list/ui_bundled/reading_list_egtest_utils.h"
#import "ios/chrome/browser/settings/bulk_upload/public/bulk_upload_constants.h"
#import "ios/chrome/browser/settings/google_services/public/google_services_settings_constants.h"
#import "ios/chrome/browser/settings/manage_accounts/public/manage_accounts_table_view_controller_constants.h"
#import "ios/chrome/browser/settings/manage_sync/public/manage_sync_settings_constants.h"
#import "ios/chrome/browser/settings/ui_bundled/password/password_manager_egtest_utils.h"
#import "ios/chrome/browser/settings/ui_bundled/settings_table_view_controller_constants.h"
#import "ios/chrome/browser/shared/public/features/features.h"
#import "ios/chrome/browser/signin/model/fake_system_identity.h"
#import "ios/chrome/common/ui/promo_style/constants.h"
#import "ios/chrome/grit/ios_branded_strings.h"
#import "ios/chrome/grit/ios_strings.h"
#import "ios/chrome/test/earl_grey/chrome_actions.h"
#import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
#import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
#import "ios/chrome/test/earl_grey/chrome_matchers.h"
#import "ios/chrome/test/earl_grey/chrome_test_case.h"
#import "ios/chrome/test/scoped_eg_synchronization_disabler.h"
#import "ios/testing/earl_grey/earl_grey_test.h"
#import "ui/base/l10n/l10n_util.h"

using chrome_test_util::SettingsAccountButton;
using chrome_test_util::SettingsDoneButton;
using chrome_test_util::SettingsSignInRowMatcher;

namespace {

NSString* const kPassphrase = @"hello";

void SignInWithPromoFromAccountSettings(FakeSystemIdentity* fake_identity,
                                        BOOL expect_history_sync_ui) {
  // Sign in with fake identity using the settings sign-in promo.
  [ChromeEarlGreyUI
      tapSettingsMenuButton:chrome_test_util::SettingsSignInRowMatcher()];
  [[EarlGrey
      selectElementWithMatcher:chrome_test_util::AccountChooserButtonMatcher(
                                   fake_identity)] performAction:grey_tap()];
  [[EarlGrey
      selectElementWithMatcher:chrome_test_util::IdentityCellMatcherForEmail(
                                   fake_identity.userEmail)]
      performAction:grey_tap()];
  [[EarlGrey
      selectElementWithMatcher:
          grey_allOf(
              chrome_test_util::StaticTextWithAccessibilityLabel(
                  l10n_util::GetNSStringF(
                      IDS_IOS_FIRST_RUN_SIGNIN_CONTINUE_AS,
                      base::SysNSStringToUTF16(fake_identity.userGivenName))),
              grey_sufficientlyVisible(), nil)] performAction:grey_tap()];

  [SigninEarlGreyUI dismissSigninConfirmationSnackbarForIdentity:fake_identity
                                                   assertVisible:NO];

  if (expect_history_sync_ui) {
    [[EarlGrey
        selectElementWithMatcher:chrome_test_util::ButtonStackPrimaryButton()]
        performAction:grey_tap()];
  }
  [ChromeEarlGreyUI waitForAppToIdle];
  [SigninEarlGrey verifySignedInWithFakeIdentity:fake_identity];

  // Close settings and re-open it to make sure the settings UI is updated to
  // avoid flakiness.
  [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
      performAction:grey_tap()];
  [ChromeEarlGreyUI openSettingsMenu];

  // Check that Settings is presented.
  [[EarlGrey
      selectElementWithMatcher:chrome_test_util::SettingsCollectionView()]
      assertWithMatcher:grey_notNil()];
}

// Adds a bookmark. The storage type is determined based on if the user is
// signed in or not.
void SaveBookmark(NSString* title, NSString* url) {
  BookmarkStorageType storageType = BookmarkStorageType::kAccount;
  if ([SigninEarlGrey isSignedOut]) {
    storageType = BookmarkStorageType::kLocalOrSyncable;
  }
  [BookmarkEarlGrey addBookmarkWithTitle:title URL:url inStorage:storageType];
}

// Expects a batch upload recommendation item on the current screen with
// `message_id` string formatted for `count` local items and `email` user email
// id.
void ExpectBatchUploadRecommendationItem(int message_id,
                                         int count,
                                         NSString* email) {
  NSString* text = base::SysUTF16ToNSString(
      base::i18n::MessageFormatter::FormatWithNamedArgs(
          l10n_util::GetStringUTF16(message_id), "count", count, "email",
          base::SysNSStringToUTF16(email)));
  [[EarlGrey
      selectElementWithMatcher:
          grey_allOf(grey_accessibilityID(
                         kBatchUploadRecommendationItemAccessibilityIdentifier),
                     grey_accessibilityLabel(text), grey_sufficientlyVisible(),
                     nil)] assertWithMatcher:grey_notNil()];
}

// Waits for snackbar item to show up after pressing save on the batch upload
// page.
void ExpectBatchUploadConfirmationSnackbar(int count, NSString* email) {
  NSString* text = base::SysUTF16ToNSString(
      base::i18n::MessageFormatter::FormatWithNamedArgs(
          l10n_util::GetStringUTF16(IDS_IOS_BULK_UPLOAD_SNACKBAR_MESSAGE),
          "count", count, "email", base::SysNSStringToUTF16(email)));
  [ChromeEarlGrey
      waitForSufficientlyVisibleElementWithMatcher:grey_accessibilityLabel(
                                                       text)];
}

}  // namespace

// Integration tests using the Google services settings screen.
@interface ManageSyncSettingsTestCase : ChromeTestCase
@end

@implementation ManageSyncSettingsTestCase

- (AppLaunchConfiguration)appConfigurationForTestCase {
  AppLaunchConfiguration config = [super appConfigurationForTestCase];
  if ([self isRunningTest:@selector
            (FLAKY_testPersonalizeGoogleServicesSettingsDismissedOnSignOut)]) {
    config.additional_args.push_back(
        std::string("--") + switches::kSearchEngineChoiceCountry + "=BE");
  }
  if ([self isRunningTest:@selector(testAccountSettingsWithMDMError)]) {
    config.features_enabled.push_back(
        switches::kHandleMdmErrorsForDasherAccounts);
  }

  return config;
}

// Tests that Sync settings is dismissed when the primary account is removed.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testSignoutWhileManageSyncSettingsOpened {
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity];
  [ChromeEarlGreyUI openSettingsMenu];
  [ChromeEarlGreyUI
      tapSettingsMenuButton:grey_accessibilityID(kSettingsAccountCellId)];
  id<GREYMatcher> scrollViewMatcher =
      grey_accessibilityID(kManageSyncTableViewAccessibilityIdentifier);
  [[EarlGrey selectElementWithMatcher:scrollViewMatcher]
      assertWithMatcher:grey_notNil()];
  [SigninEarlGrey forgetFakeIdentity:fakeIdentity];
  [ChromeEarlGreyUI waitForAppToIdle];

  // Verify the "manage sync" view is popped.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(
                                   kManageSyncTableViewAccessibilityIdentifier)]
      assertWithMatcher:grey_notVisible()];
}

// Tests that unified account settings row is showing.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testShowingUnifiedAccountSettings {
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [ChromeEarlGreyUI openSettingsMenu];

  // Sign in with fake identity using the settings sign-in promo.
  SignInWithPromoFromAccountSettings(fakeIdentity,
                                     /*expect_history_sync_ui=*/YES);

  // Verify the account settings row is showing.
  [[EarlGrey selectElementWithMatcher:SettingsAccountButton()]
      assertWithMatcher:grey_notNil()];
}

// Tests sign out from the unified account settings page.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testSignOutFromUnifiedAccountSettings {
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];
  [SigninEarlGreyUI openSyncSettings];

  [SigninEarlGreyUI tapSignOutFromSyncSettings];
  [SigninEarlGreyUI dismissSignoutSnackbar];
  [ChromeEarlGreyUI waitForAppToIdle];

  [SigninEarlGrey verifySignedOut];

  // Verify the "manage sync" view is popped.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(
                                   kManageSyncTableViewAccessibilityIdentifier)]
      assertWithMatcher:grey_notVisible()];

  // Verify the account settings row is not showing in the settings menu.
  [[EarlGrey selectElementWithMatcher:SettingsAccountButton()]
      assertWithMatcher:grey_notVisible()];
}

// Tests the unsynced data dialog shows when there are unsynced passwords. Also
// verifies that the user is still signed in when the dialog Cancel button is
// tapped.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testUnsyncedDataDialogShowsInCaseOfUnsyncedPasswords {
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];

  [ChromeEarlGrey disconnectFakeSyncServerNetwork];

  password_manager_test_utils::SavePasswordFormToAccountStore(
      @"password", @"user", @"https://example.com");

  [SigninEarlGreyUI openSyncSettings];

  [[EarlGrey selectElementWithMatcher:chrome_test_util::TableViewSwitchCell(
                                          kSyncPasswordsIdentifier,
                                          /*is_toggled_on=*/YES,
                                          /*enabled=*/YES)]
      assertWithMatcher:grey_sufficientlyVisible()];

  [SigninEarlGreyUI tapSignOutFromSyncSettings];
  [[EarlGrey selectElementWithMatcher:
                 chrome_test_util::AlertItemWithAccessibilityLabelId(
                     IDS_CANCEL)] performAction:grey_tap()];

  [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity];

  // Re-connect the fake sync server to the network to be able to sign-in when
  // the test gets run repeatedly.
  [ChromeEarlGrey connectFakeSyncServerNetwork];
}

// TODO(crbug.com/355133719): Remove FLAKY_ from this test.
// Tests the unsynced data dialog shows when there are unsynced readinglist
// entries. Also verifies that the user is still signed in when the dialog
// Cancel button is tapped.
- (void)FLAKY_testUnsyncedDataDialogShowsInCaseOfUnsyncedReadingListEntry {
  // TODO(crbug.com/41494658): Test fails on iPhone device and simulator.
  if (![ChromeEarlGrey isIPadIdiom]) {
    EARL_GREY_TEST_DISABLED(@"Fails on iPhone.");
  }
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];

  [ChromeEarlGrey disconnectFakeSyncServerNetwork];

  reading_list_test_utils::AddURLToReadingListWithSnackbarDismiss(
      GURL("https://example.com"), fakeIdentity.userEmail);

  [SigninEarlGreyUI openSyncSettings];

  [[EarlGrey selectElementWithMatcher:chrome_test_util::TableViewSwitchCell(
                                          kSyncReadingListIdentifier,
                                          /*is_toggled_on=*/YES,
                                          /*enabled=*/YES)]
      assertWithMatcher:grey_sufficientlyVisible()];

  [SigninEarlGreyUI tapSignOutFromSyncSettings];
  [[EarlGrey selectElementWithMatcher:
                 chrome_test_util::AlertItemWithAccessibilityLabelId(
                     IDS_CANCEL)] performAction:grey_tap()];

  [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity];

  // Re-connect the fake sync server to the network to be able to sign-in when
  // the test gets run repeatedly.
  [ChromeEarlGrey connectFakeSyncServerNetwork];
}

// Tests the unsynced data dialog shows when there are unsynced bookmarks. Also
// verifies that the user still signed in when the dialog Cancel button is
// tapped.
// TODO(crbug.com/512422445): Test is flaky.
- (void)
    FLAKY_testCancelSigningOutFromUnsyncedDataDialogInCaseOfUnsyncedBookmarks {
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];
  [SigninEarlGreyUI openSyncSettings];

  [[EarlGrey selectElementWithMatcher:chrome_test_util::TableViewSwitchCell(
                                          kSyncBookmarksIdentifier,
                                          /*is_toggled_on=*/YES,
                                          /*enabled=*/YES)]
      assertWithMatcher:grey_sufficientlyVisible()];

  [ChromeEarlGrey disconnectFakeSyncServerNetwork];

  SaveBookmark(@"foo", @"https://www.foo.com");

  [SigninEarlGreyUI tapSignOutFromSyncSettings];
  [[EarlGrey selectElementWithMatcher:
                 chrome_test_util::AlertItemWithAccessibilityLabelId(
                     IDS_CANCEL)] performAction:grey_tap()];

  [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity];

  // Re-connect the fake sync server to the network to be able to sign-in when
  // the test gets run repeatedly.
  [ChromeEarlGrey connectFakeSyncServerNetwork];
}

// Tests the unsynced data dialog shows when there are unsynced bookmarks. Also
// verifies that the user is signed out when the dialog Delete and Sign Out
// button is tapped.
// TODO(crbug.com/512422445): Test is flaky.
- (void)
    FLAKY_testDeleteAndSignOutFromUnsyncedDataDialogInCaseOfUnsyncedBookmarks {
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];
  [SigninEarlGreyUI openSyncSettings];

  [[EarlGrey selectElementWithMatcher:chrome_test_util::TableViewSwitchCell(
                                          kSyncBookmarksIdentifier,
                                          /*is_toggled_on=*/YES,
                                          /*enabled=*/YES)]
      assertWithMatcher:grey_sufficientlyVisible()];

  [ChromeEarlGrey disconnectFakeSyncServerNetwork];

  SaveBookmark(@"foo", @"https://www.foo.com");

  [SigninEarlGreyUI tapSignOutFromSyncSettings];
  [[EarlGrey selectElementWithMatcher:
                 chrome_test_util::AlertItemWithAccessibilityLabelId(
                     IDS_IOS_SIGNOUT_DIALOG_SIGN_OUT_AND_DELETE_BUTTON)]
      performAction:grey_tap()];

  [SigninEarlGrey verifySignedOut];

  // Re-connect the fake sync server to the network to be able to sign-in when
  // the test gets run repeatedly.
  [ChromeEarlGrey connectFakeSyncServerNetwork];
}

// Tests that data type settings carry over signing out.
// TODO(crbug.com/512422367): Test is flaky.
- (void)FLAKY_testDataTypeSettingsCarryOverSignOut {
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity];
  [SigninEarlGreyUI openSyncSettings];

  // Change one of the toggles; say turn off Passwords.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(kSyncPasswordsIdentifier)]
      performAction:chrome_test_util::TurnTableViewSwitchOn(/*on=*/NO)];

  [SigninEarlGreyUI tapSignOutFromSyncSettings];
  [SigninEarlGreyUI dismissSignoutSnackbar];

  [SigninEarlGrey verifySignedOut];

  // Sign back in with the same identity using the settings sign-in promo.
  // The history sync opt-in was declined in the first sign-in earlier in this
  // test.
  SignInWithPromoFromAccountSettings(fakeIdentity,
                                     /*expect_history_sync_ui=*/YES);

  // Verify the account settings row is showing in the settings menu.
  [[EarlGrey selectElementWithMatcher:SettingsAccountButton()]
      assertWithMatcher:grey_sufficientlyVisible()];
  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];

  // Verify the account settings did not change with a signout; Passwords is
  // off.
  [[EarlGrey selectElementWithMatcher:chrome_test_util::TableViewSwitchCell(
                                          kSyncPasswordsIdentifier,
                                          /*is_toggled_on=*/NO,
                                          /*enabled=*/YES)]
      assertWithMatcher:grey_sufficientlyVisible()];
}

// Tests that data type settings do not carry over from one user to another.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testDataTypeSettingsDoNotCarryOverDifferentAccounts {
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  FakeSystemIdentity* fakeIdentity2 = [FakeSystemIdentity fakeIdentity2];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];
  [SigninEarlGrey addFakeIdentity:fakeIdentity2];

  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];
  [SigninEarlGreyUI openSyncSettings];

  // Change one of the toggles; say turn off Passwords.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(kSyncPasswordsIdentifier)]
      performAction:chrome_test_util::TurnTableViewSwitchOn(/*on=*/NO)];

  [SigninEarlGreyUI tapSignOutFromSyncSettings];
  [SigninEarlGreyUI dismissSignoutSnackbar];

  [SigninEarlGrey verifySignedOut];
  [[EarlGrey
      selectElementWithMatcher:grey_allOf(
                                   chrome_test_util::SettingsDoneButton(),
                                   grey_sufficientlyVisible(), nil)]
      performAction:grey_tap()];

  // Sign in with another identity.
  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity2];
  [SigninEarlGreyUI openSyncSettings];

  // Verify the account settings have the default value; Passwords is on.
  [[EarlGrey selectElementWithMatcher:chrome_test_util::TableViewSwitchCell(
                                          kSyncPasswordsIdentifier,
                                          /*is_toggled_on=*/YES,
                                          /*enabled=*/YES)]
      assertWithMatcher:grey_sufficientlyVisible()];
}

// Tests that removing account from device clears the data type settings.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testDataTypeSettingsAreClearedOnAccountRemoval {
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];
  [SigninEarlGreyUI openSyncSettings];

  // Change one of the toggles; say turn off Passwords.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(kSyncPasswordsIdentifier)]
      performAction:chrome_test_util::TurnTableViewSwitchOn(/*on=*/NO)];

  // Remove fakeIdentity from device.
  [ChromeEarlGreyUI waitForAppToIdle];
  [SigninEarlGrey forgetFakeIdentity:fakeIdentity];

  [[EarlGrey selectElementWithMatcher:SettingsSignInRowMatcher()]
      assertWithMatcher:grey_sufficientlyVisible()];
  [SigninEarlGrey verifySignedOut];
  [[EarlGrey
      selectElementWithMatcher:grey_allOf(
                                   chrome_test_util::SettingsDoneButton(),
                                   grey_sufficientlyVisible(), nil)]
      performAction:grey_tap()];

  // Sign in with the same identity.
  [SigninEarlGrey addFakeIdentity:fakeIdentity];
  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];
  [SigninEarlGreyUI openSyncSettings];

  // Verify the account settings are cleared and have the default value;
  // Passwords is on.
  [[EarlGrey selectElementWithMatcher:chrome_test_util::TableViewSwitchCell(
                                          kSyncPasswordsIdentifier,
                                          /*is_toggled_on=*/YES,
                                          /*enabled=*/YES)]
      assertWithMatcher:grey_sufficientlyVisible()];
}

// Tests the account settings is reflecting the SyncTypesListDisabled
// policy.
// TODO(crbug.com/512421615): Test is flaky.
- (void)FLAKY_testAccountSettingsWithSyncTypesListDisabled {
  base::ListValue list;
  list.Append("passwords");
  policy_test_utils::SetPolicy(base::Value(std::move(list)),
                               policy::key::kSyncTypesListDisabled);
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];
  [SigninEarlGreyUI openSyncSettings];

  // Verify that for Passwords an "Off" button is shown instead of a toggle.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityLabel(
                                   l10n_util::GetNSString(IDS_IOS_SETTING_OFF))]
      assertWithMatcher:grey_sufficientlyVisible()];
}

// Tests the account settings is disabling the types that were affected by the
// SyncTypesListDisabled policy when the policy is lifted.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testAccountSettingsWithSyncTypesListDisabledLifted {
  // Apply policy.
  base::ListValue list;
  list.Append("passwords");
  policy_test_utils::SetPolicy(base::Value(std::move(list)),
                               policy::key::kSyncTypesListDisabled);

  // Sign in.
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];
  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];

  // Open the account settings.
  [SigninEarlGreyUI openSyncSettings];

  // Verify that for Passwords an "Off" button is shown instead of a toggle.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityLabel(
                                   l10n_util::GetNSString(IDS_IOS_SETTING_OFF))]
      assertWithMatcher:grey_sufficientlyVisible()];
  [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
      performAction:grey_tap()];

  // Lift the policy dynamically.
  policy_test_utils::ClearPolicies();

  // Open the account settings.
  [SigninEarlGreyUI openSyncSettings];

  // Verify that for Passwords has an "Off" toggle.
  [[EarlGrey selectElementWithMatcher:chrome_test_util::TableViewSwitchCell(
                                          kSyncPasswordsIdentifier,
                                          /*is_toggled_on=*/NO,
                                          /*enabled=*/YES)]
      assertWithMatcher:grey_sufficientlyVisible()];

  // Verify that other types for example Bookmarks was not affected.
  [[EarlGrey selectElementWithMatcher:chrome_test_util::TableViewSwitchCell(
                                          kSyncBookmarksIdentifier,
                                          /*is_toggled_on=*/YES,
                                          /*enabled=*/YES)]
      assertWithMatcher:grey_sufficientlyVisible()];
}

// Tests the account settings is disabling the types that were affected by the
// SyncTypesListDisabled policy when the policy is apllied on a signed-in
// account.
// TODO(crbug.com/512422367): Test is flaky.
- (void)FLAKY_testAccountSettingsWithSyncTypesListDisabledAppliedDynamically {
  // Sign in.
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];
  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];

  // Apply policy dynamically.
  base::ListValue list;
  list.Append("passwords");
  policy_test_utils::SetPolicy(base::Value(std::move(list)),
                               policy::key::kSyncTypesListDisabled);

  // Lift the policy dynamically.
  policy_test_utils::ClearPolicies();

  // Open the account settings.
  [SigninEarlGreyUI openSyncSettings];

  // Verify that for Passwords has an "Off" toggle.
  [[EarlGrey selectElementWithMatcher:chrome_test_util::TableViewSwitchCell(
                                          kSyncPasswordsIdentifier,
                                          /*is_toggled_on=*/NO,
                                          /*enabled=*/YES)]
      assertWithMatcher:grey_sufficientlyVisible()];

  // Verify that other types for example Bookmarks was not affected.
  [[EarlGrey selectElementWithMatcher:chrome_test_util::TableViewSwitchCell(
                                          kSyncBookmarksIdentifier,
                                          /*is_toggled_on=*/YES,
                                          /*enabled=*/YES)]
      assertWithMatcher:grey_sufficientlyVisible()];
}

// Tests the account settings is reflecting the SyncDisabled policy.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testAccountSettingsWithSyncDisabled {
  policy_test_utils::SetPolicy(true, policy::key::kSyncDisabled);
  [ChromeEarlGreyUI waitForAppToIdle];

  // Dismiss the sync disabled popup.
  [[EarlGrey selectElementWithMatcher:
                 grey_allOf(grey_accessibilityLabel(l10n_util::GetNSString(
                                IDS_IOS_SYNC_SYNC_DISABLED_CONTINUE)),
                            grey_userInteractionEnabled(), nil)]
      performAction:grey_tap()];

  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [ChromeEarlGreyUI openSettingsMenu];
  SignInWithPromoFromAccountSettings(fakeIdentity,
                                     /*expect_history_sync_ui=*/NO);
  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];

  // Scroll to the bottom to view all section.
  id<GREYMatcher> scroll_view_matcher =
      grey_accessibilityID(kManageSyncTableViewAccessibilityIdentifier);
  [[EarlGrey selectElementWithMatcher:scroll_view_matcher]
      performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)];

  // Verify that the advanced settings items are not shown.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityLabel(l10n_util::GetNSString(
                                   IDS_IOS_MANAGE_SYNC_ENCRYPTION))]
      assertWithMatcher:grey_notVisible()];
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityLabel(l10n_util::GetNSString(
                                   IDS_IOS_MANAGE_DATA_IN_YOUR_ACCOUNT_TITLE))]
      assertWithMatcher:grey_notVisible()];
  [[EarlGrey selectElementWithMatcher:
                 grey_accessibilityLabel(l10n_util::GetNSString(
                     IDS_IOS_MANAGE_SYNC_GOOGLE_ACTIVITY_CONTROLS_TITLE))]
      assertWithMatcher:grey_notVisible()];
}

// Tests the account settings is disabling the types that were affected by the
// SyncDisabled policy when the policy is lifted.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testAccountSettingsWithSyncDisabledLifted {
  // Apply policy.
  policy_test_utils::SetPolicy(true, policy::key::kSyncDisabled);
  [ChromeEarlGreyUI waitForAppToIdle];
  [[EarlGrey selectElementWithMatcher:
                 grey_allOf(grey_accessibilityLabel(l10n_util::GetNSString(
                                IDS_IOS_SYNC_SYNC_DISABLED_CONTINUE)),
                            grey_userInteractionEnabled(), nil)]
      performAction:grey_tap()];

  // Sign in.
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];
  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity
              waitForSyncTransportActive:NO];

  // Disable the policy dynamically.
  policy_test_utils::ClearPolicies();

  // Open the account settings.
  [SigninEarlGreyUI openSyncSettings];

  // Verify that for any type, for example Passwords, has an "Off" toggle now.
  [[EarlGrey selectElementWithMatcher:chrome_test_util::TableViewSwitchCell(
                                          kSyncPasswordsIdentifier,
                                          /*is_toggled_on=*/NO,
                                          /*is_enabled=*/YES)]
      assertWithMatcher:grey_sufficientlyVisible()];
}

// Tests the account settings is disabling the types that were affected by the
// SyncDisabled policy when the policy is apllied on a signed-in account.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testAccountSettingsWithSyncDisabledAppliedDynamically {
  // Sign in.
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];
  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];

  // Apply policy dynamically.
  policy_test_utils::SetPolicy(true, policy::key::kSyncDisabled);
  [ChromeEarlGreyUI waitForAppToIdle];
  [[EarlGrey selectElementWithMatcher:
                 grey_allOf(grey_accessibilityLabel(l10n_util::GetNSString(
                                IDS_IOS_SYNC_SYNC_DISABLED_CONTINUE)),
                            grey_userInteractionEnabled(), nil)]
      performAction:grey_tap()];

  // Disable the policy dynamically.
  policy_test_utils::ClearPolicies();

  // Open the account settings.
  [SigninEarlGreyUI openSyncSettings];

  // Verify that for any type, for example Passwords, has an "Off" toggle now.
  [[EarlGrey selectElementWithMatcher:chrome_test_util::TableViewSwitchCell(
                                          kSyncPasswordsIdentifier,
                                          /*is_toggled_on=*/NO,
                                          /*enabled=*/YES)]
      assertWithMatcher:grey_sufficientlyVisible()];
}

// Tests the account settings is with a user actionable error; enter
// passphrase error.
// TODO(crbug.com/512422367): Test is flaky.
- (void)FLAKY_testAccountSettingsWithError {
  [ChromeEarlGrey addSyncPassphrase:kPassphrase];
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];
  [SigninEarlGreyUI openSyncSettings];

  // Verify the error section is showing.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(kSyncErrorButtonIdentifier)]
      assertWithMatcher:grey_sufficientlyVisible()];

  // Tap "Enter Passphrase" button.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(kSyncErrorButtonIdentifier)]
      performAction:grey_tap()];

  // Enter the passphrase.
  [SigninEarlGreyUI submitSyncPassphrase:kPassphrase];

  // Verify it goes back to "manage sync" UI.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(
                                   kManageSyncTableViewAccessibilityIdentifier)]
      assertWithMatcher:grey_sufficientlyVisible()];

  // Verify the error section is not showing anymore.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(kSyncErrorButtonIdentifier)]
      assertWithMatcher:grey_notVisible()];
}

// Tests the "History and Tabs" toggle manages both types. When both types
// are disabled by policy their toggle should be off.
// TODO(crbug.com/512422367): Test is flaky.
- (void)FLAKY_testAccountSettingsWithHistoryAndTabsDisabledByPolicy {
  base::ListValue list;
  list.Append("typedUrls");
  list.Append("tabs");
  policy_test_utils::SetPolicy(base::Value(std::move(list)),
                               policy::key::kSyncTypesListDisabled);
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [ChromeEarlGreyUI openSettingsMenu];
  SignInWithPromoFromAccountSettings(fakeIdentity,
                                     /*expect_history_sync_ui=*/NO);
  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];

  // Verify that for "History and Tabs" an "Off" button is shown instead of a
  // toggle.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityLabel(
                                   l10n_util::GetNSString(IDS_IOS_SETTING_OFF))]
      assertWithMatcher:grey_sufficientlyVisible()];
}

// Tests the "History and Tabs" toggle manages both types. When History
// is only disabled by policy their toggle should be active.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testAccountSettingsWithHistoryDisabledByPolicy {
  base::ListValue list;
  list.Append("typedUrls");
  policy_test_utils::SetPolicy(base::Value(std::move(list)),
                               policy::key::kSyncTypesListDisabled);
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [ChromeEarlGreyUI openSettingsMenu];
  SignInWithPromoFromAccountSettings(fakeIdentity,
                                     /*expect_history_sync_ui=*/NO);
  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];

  // Verify that for "History and Tabs" a toggle shows.
  [[EarlGrey selectElementWithMatcher:chrome_test_util::TableViewSwitchCell(
                                          kSyncHistoryAndTabsIdentifier,
                                          /*is_toggled_on=*/NO,
                                          /*enabled=*/YES)]
      assertWithMatcher:grey_sufficientlyVisible()];
}

// Tests the "History and Tabs" toggle manages both types. When Tabs
// is only disabled by policy their toggle should be active.
// TODO(crbug.com/512420798): Test is flaky.
- (void)FLAKY_testAccountSettingsWithTabsDisabledByPolicy {
  base::ListValue list;
  list.Append("tabs");
  policy_test_utils::SetPolicy(base::Value(std::move(list)),
                               policy::key::kSyncTypesListDisabled);
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [ChromeEarlGreyUI openSettingsMenu];
  SignInWithPromoFromAccountSettings(fakeIdentity,
                                     /*expect_history_sync_ui=*/NO);
  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];

  // Verify that for "History and Tabs" a toggle shows.
  [[EarlGrey selectElementWithMatcher:chrome_test_util::TableViewSwitchCell(
                                          kSyncHistoryAndTabsIdentifier,
                                          /*is_toggled_on=*/NO,
                                          /*enabled=*/YES)]
      assertWithMatcher:grey_sufficientlyVisible()];
}

// Tests closing the account settings with a remote signout.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testAccountSettingsWithRemoteSignout {
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];
  [SigninEarlGreyUI openSyncSettings];

  // Remove fakeIdentity from device.
  [SigninEarlGrey forgetFakeIdentity:fakeIdentity];
  [ChromeEarlGreyUI waitForAppToIdle];
  [SigninEarlGrey verifySignedOut];

  // Check that Settings is presented.
  [[EarlGrey
      selectElementWithMatcher:chrome_test_util::SettingsCollectionView()]
      assertWithMatcher:grey_notNil()];
}

// Tests that the batch upload button description in the account settings
// contains the correct string for passwords.
// TODO(crbug.com/512424244): Test is flaky.
- (void)FLAKY_testBulkUploadDescriptionTextForPasswords {
  // Add local data.
  password_manager_test_utils::SavePasswordFormToProfileStore(
      @"password1", @"user1", @"https://example1.com");
  password_manager_test_utils::SavePasswordFormToProfileStore(
      @"password2", @"user2", @"https://example2.com");

  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [ChromeEarlGreyUI openSettingsMenu];
  // Sign in with fake identity using the settings sign-in promo.
  SignInWithPromoFromAccountSettings(fakeIdentity,
                                     /*expect_history_sync_ui=*/YES);

  // Open the "manage sync" view.
  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];

  // Find and match the batch upload recommendation item text.
  ExpectBatchUploadRecommendationItem(
      IDS_IOS_GOOGLE_ACCOUNT_SETTINGS_BATCH_UPLOAD_PASSWORDS_ITEM, 2,
      fakeIdentity.userEmail);
}

// Tests that the batch upload button description in the account settings
// contains the correct string for bookmarks.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testBulkUploadDescriptionTextForBookmarks {
  // Add local data.
  SaveBookmark(@"foo", @"https://www.foo.com");
  SaveBookmark(@"bar", @"https://www.bar.com");

  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [ChromeEarlGreyUI openSettingsMenu];
  // Sign in with fake identity using the settings sign-in promo.
  SignInWithPromoFromAccountSettings(fakeIdentity,
                                     /*expect_history_sync_ui=*/YES);

  // Open the "manage sync" view.
  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];

  // Find and match the batch upload recommendation item text.
  ExpectBatchUploadRecommendationItem(
      IDS_IOS_GOOGLE_ACCOUNT_SETTINGS_BATCH_UPLOAD_ITEMS_ITEM, 2,
      fakeIdentity.userEmail);
}

// Tests that the batch upload button description in the account settings
// contains the correct string for reading list.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testBulkUploadDescriptionTextForReadingList {
  // Add local data.
  reading_list_test_utils::AddURLToReadingListWithSnackbarDismiss(
      GURL("https://example.com"), nil);

  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [ChromeEarlGreyUI openSettingsMenu];
  // Sign in with fake identity using the settings sign-in promo.
  SignInWithPromoFromAccountSettings(fakeIdentity,
                                     /*expect_history_sync_ui=*/YES);

  // Open the "manage sync" view.
  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];

  // Find and match the batch upload recommendation item text.
  ExpectBatchUploadRecommendationItem(
      IDS_IOS_GOOGLE_ACCOUNT_SETTINGS_BATCH_UPLOAD_ITEMS_ITEM, 1,
      fakeIdentity.userEmail);
}

// Tests that the batch upload button description in the account settings
// contains the correct string for passwords and other data type.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testBulkUploadDescriptionTextForPasswordsAndOthers {
  // Add local data.
  password_manager_test_utils::SavePasswordFormToProfileStore(
      @"password", @"user", @"https://example.com");
  reading_list_test_utils::AddURLToReadingListWithSnackbarDismiss(
      GURL("https://example.com"), nil);
  SaveBookmark(@"foo", @"https://www.foo.com");

  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [ChromeEarlGreyUI openSettingsMenu];
  // Sign in with fake identity using the settings sign-in promo.
  SignInWithPromoFromAccountSettings(fakeIdentity,
                                     /*expect_history_sync_ui=*/YES);

  // Open the "manage sync" view.
  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];

  // Find and match the batch upload recommendation item text.
  ExpectBatchUploadRecommendationItem(
      IDS_IOS_GOOGLE_ACCOUNT_SETTINGS_BATCH_UPLOAD_PASSWORDS_AND_ITEMS_ITEM, 1,
      fakeIdentity.userEmail);
}

// Tests that the batch upload page contains the correct listed data types:
// - Passwords
// - Bookmarks
// - Reading list
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testBulkUploadPageForAllDataTypes {
  // Add local data.
  password_manager_test_utils::SavePasswordFormToProfileStore(
      @"password", @"user", @"https://example.com");
  reading_list_test_utils::AddURLToReadingListWithSnackbarDismiss(
      GURL("https://example.com"), nil);
  SaveBookmark(@"foo", @"https://www.foo.com");

  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [ChromeEarlGreyUI openSettingsMenu];
  // Sign in with fake identity using the settings sign-in promo.
  SignInWithPromoFromAccountSettings(fakeIdentity,
                                     /*expect_history_sync_ui=*/YES);

  // Open the "manage sync" view.
  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];

  // Tap on the batch upload button.
  [[EarlGrey
      selectElementWithMatcher:grey_allOf(
                                   grey_accessibilityID(
                                       kBatchUploadAccessibilityIdentifier),
                                   grey_sufficientlyVisible(), nil)]
      performAction:grey_tap()];
  [ChromeEarlGreyUI waitForAppToIdle];

  // Verify the bulk upload view is popped.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(
                                   kBulkUploadTableViewAccessibilityIdentifier)]
      assertWithMatcher:grey_sufficientlyVisible()];

  // Verify that only rows for the correct data types exist.
  [[EarlGrey selectElementWithMatcher:
                 grey_accessibilityID(
                     kBulkUploadTableViewPasswordsItemAccessibilityIdentifer)]
      assertWithMatcher:grey_sufficientlyVisible()];
  [[EarlGrey selectElementWithMatcher:
                 grey_accessibilityID(
                     kBulkUploadTableViewBookmarksItemAccessibilityIdentifer)]
      assertWithMatcher:grey_sufficientlyVisible()];
  [[EarlGrey selectElementWithMatcher:
                 grey_accessibilityID(
                     kBulkUploadTableViewReadingListItemAccessibilityIdentifer)]
      assertWithMatcher:grey_sufficientlyVisible()];
}

// Tests that the batch upload page contains the correct listed data types:
// - Passwords
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testBulkUploadPageForPasswordsOnly {
  // Add local data.
  password_manager_test_utils::SavePasswordFormToProfileStore(
      @"password", @"user", @"https://example.com");

  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [ChromeEarlGreyUI openSettingsMenu];
  // Sign in with fake identity using the settings sign-in promo.
  SignInWithPromoFromAccountSettings(fakeIdentity,
                                     /*expect_history_sync_ui=*/YES);

  // Open the "manage sync" view.
  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];

  // Tap on the batch upload button.
  [[EarlGrey
      selectElementWithMatcher:grey_allOf(
                                   grey_accessibilityID(
                                       kBatchUploadAccessibilityIdentifier),
                                   grey_sufficientlyVisible(), nil)]
      performAction:grey_tap()];
  [ChromeEarlGreyUI waitForAppToIdle];

  // Verify the bulk upload view is popped.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(
                                   kBulkUploadTableViewAccessibilityIdentifier)]
      assertWithMatcher:grey_sufficientlyVisible()];

  // Verify that only rows for the correct data types exist.
  [[EarlGrey selectElementWithMatcher:
                 grey_accessibilityID(
                     kBulkUploadTableViewPasswordsItemAccessibilityIdentifer)]
      assertWithMatcher:grey_sufficientlyVisible()];
  [[EarlGrey selectElementWithMatcher:
                 grey_accessibilityID(
                     kBulkUploadTableViewBookmarksItemAccessibilityIdentifer)]
      assertWithMatcher:grey_notVisible()];
  [[EarlGrey selectElementWithMatcher:
                 grey_accessibilityID(
                     kBulkUploadTableViewReadingListItemAccessibilityIdentifer)]
      assertWithMatcher:grey_notVisible()];
}

// Tests that the batch upload page contains the correct listed data types:
// - Passwords
// - Bookmarks
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testBulkUploadPageForPasswordsAndBookmarks {
  // Add local data.
  password_manager_test_utils::SavePasswordFormToProfileStore(
      @"password", @"user", @"https://example.com");
  SaveBookmark(@"foo", @"https://www.foo.com");

  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [ChromeEarlGreyUI openSettingsMenu];
  // Sign in with fake identity using the settings sign-in promo.
  SignInWithPromoFromAccountSettings(fakeIdentity,
                                     /*expect_history_sync_ui=*/YES);

  // Open the "manage sync" view.
  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];

  // Tap on the batch upload button.
  [[EarlGrey
      selectElementWithMatcher:grey_allOf(
                                   grey_accessibilityID(
                                       kBatchUploadAccessibilityIdentifier),
                                   grey_sufficientlyVisible(), nil)]
      performAction:grey_tap()];
  [ChromeEarlGreyUI waitForAppToIdle];

  // Verify the bulk upload view is popped.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(
                                   kBulkUploadTableViewAccessibilityIdentifier)]
      assertWithMatcher:grey_sufficientlyVisible()];

  // Verify that only rows for the correct data types exist.
  [[EarlGrey selectElementWithMatcher:
                 grey_accessibilityID(
                     kBulkUploadTableViewPasswordsItemAccessibilityIdentifer)]
      assertWithMatcher:grey_sufficientlyVisible()];
  [[EarlGrey selectElementWithMatcher:
                 grey_accessibilityID(
                     kBulkUploadTableViewBookmarksItemAccessibilityIdentifer)]
      assertWithMatcher:grey_sufficientlyVisible()];
  [[EarlGrey selectElementWithMatcher:
                 grey_accessibilityID(
                     kBulkUploadTableViewReadingListItemAccessibilityIdentifer)]
      assertWithMatcher:grey_notVisible()];
}

// Tests that bulk upload moves the following data types to account:
// - Passwords
// TODO(crbug.com/407020882): Remove FLAKY_ from this test.
- (void)FLAKY_testBulkUploadForPasswords {
  // Add local data.
  password_manager_test_utils::SavePasswordFormToProfileStore(
      @"password", @"user", @"https://example.com");
  reading_list_test_utils::AddURLToReadingListWithSnackbarDismiss(
      GURL("https://example.com"), nil);
  SaveBookmark(@"foo", @"https://www.foo.com");

  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [ChromeEarlGreyUI openSettingsMenu];
  // Sign in with fake identity using the settings sign-in promo.
  SignInWithPromoFromAccountSettings(fakeIdentity,
                                     /*expect_history_sync_ui=*/YES);

  // Open the "manage sync" view.
  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];

  // Tap on the batch upload button.
  [[EarlGrey
      selectElementWithMatcher:grey_allOf(
                                   grey_accessibilityID(
                                       kBatchUploadAccessibilityIdentifier),
                                   grey_sufficientlyVisible(), nil)]
      performAction:grey_tap()];
  [ChromeEarlGreyUI waitForAppToIdle];

  // Verify the bulk upload view is shown.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(
                                   kBulkUploadTableViewAccessibilityIdentifier)]
      assertWithMatcher:grey_sufficientlyVisible()];

  // Verify that switches for Passwords is ON.
  [[EarlGrey selectElementWithMatcher:
                 chrome_test_util::TableViewSwitchCell(
                     kBulkUploadTableViewPasswordsItemAccessibilityIdentifer,
                     YES)] assertWithMatcher:grey_sufficientlyVisible()];
  // Turn switches for Bookmarks and Reading List to OFF.
  [[EarlGrey selectElementWithMatcher:
                 grey_accessibilityID(
                     kBulkUploadTableViewBookmarksItemAccessibilityIdentifer)]
      performAction:chrome_test_util::TurnTableViewSwitchOn(NO)];
  [[EarlGrey selectElementWithMatcher:
                 grey_accessibilityID(
                     kBulkUploadTableViewReadingListItemAccessibilityIdentifer)]
      performAction:chrome_test_util::TurnTableViewSwitchOn(NO)];

  // Mock reauth since passwords needs upload.
  [ReauthenticationAppInterface mockReauthenticationModuleExpectedResult:
                                    ReauthenticationResult::kSuccess];
  // Delay the auth result to be able to validate that the passwords are not
  // visible until the result is emitted.
  [ReauthenticationAppInterface mockReauthenticationModuleShouldSkipReAuth:NO];

  // Tap on the save button.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(
                                   kBulkUploadSaveButtonAccessibilityIdentifer)]
      performAction:grey_tap()];

  // Successful auth should remove blocking view and "manage sync" view should
  // be fully visible.
  [ReauthenticationAppInterface mockReauthenticationModuleReturnMockedResult];
  [ChromeEarlGrey
      waitForSufficientlyVisibleElementWithMatcher:
          grey_accessibilityID(kManageSyncTableViewAccessibilityIdentifier)];

  // Ensure the correct snackbar appears.
  ExpectBatchUploadConfirmationSnackbar(1, fakeIdentity.userEmail);

  [ChromeEarlGreyUI waitForAppToIdle];

  // Ensure that the batch upload dialog section has been modified on the
  // account settings page.
  ExpectBatchUploadRecommendationItem(
      IDS_IOS_GOOGLE_ACCOUNT_SETTINGS_BATCH_UPLOAD_ITEMS_ITEM, 2,
      fakeIdentity.userEmail);
}

// Tests that bulk upload moves the following data types to account:
// - Bookmarks
// - Reading List
//
// TODO(crbug.com/468296957): This test is flaky.
- (void)FLAKY_testBulkUploadForBookmarksAndReadingList {
  // Add local data.
  password_manager_test_utils::SavePasswordFormToProfileStore(
      @"password", @"user", @"https://example.com");
  reading_list_test_utils::AddURLToReadingListWithSnackbarDismiss(
      GURL("https://example.com"), nil);
  SaveBookmark(@"foo", @"https://www.foo.com");

  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [ChromeEarlGreyUI openSettingsMenu];
  // Sign in with fake identity using the settings sign-in promo.
  SignInWithPromoFromAccountSettings(fakeIdentity,
                                     /*expect_history_sync_ui=*/YES);

  // Open the "manage sync" view.
  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];

  // Tap on the batch upload button.
  [[EarlGrey
      selectElementWithMatcher:grey_allOf(
                                   grey_accessibilityID(
                                       kBatchUploadAccessibilityIdentifier),
                                   grey_sufficientlyVisible(), nil)]
      performAction:grey_tap()];
  [ChromeEarlGreyUI waitForAppToIdle];

  // Verify the bulk upload view is popped.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(
                                   kBulkUploadTableViewAccessibilityIdentifier)]
      assertWithMatcher:grey_sufficientlyVisible()];

  // Verify that switches for Bookmarks and Reading List are ON.
  [[EarlGrey selectElementWithMatcher:
                 chrome_test_util::TableViewSwitchCell(
                     kBulkUploadTableViewBookmarksItemAccessibilityIdentifer,
                     YES)] assertWithMatcher:grey_sufficientlyVisible()];
  [[EarlGrey selectElementWithMatcher:
                 chrome_test_util::TableViewSwitchCell(
                     kBulkUploadTableViewReadingListItemAccessibilityIdentifer,
                     YES)] assertWithMatcher:grey_sufficientlyVisible()];
  // Turn switch for Passwords to OFF.
  [[EarlGrey selectElementWithMatcher:
                 grey_accessibilityID(
                     kBulkUploadTableViewPasswordsItemAccessibilityIdentifer)]
      performAction:chrome_test_util::TurnTableViewSwitchOn(NO)];

  {
    // Workaround for Earl Grey synchronization bug on iOS 26 that prevents
    // snackbar detection. Temporarily disabling synchronization allows the
    // view to be found.
    ScopedSynchronizationDisabler disabler;

    // Tap on the save button.
    [[EarlGrey
        selectElementWithMatcher:
            grey_accessibilityID(kBulkUploadSaveButtonAccessibilityIdentifer)]
        performAction:grey_tap()];

    // Ensure the correct snackbar appears.
    ExpectBatchUploadConfirmationSnackbar(2, fakeIdentity.userEmail);
  }

  [ChromeEarlGrey
      waitForSufficientlyVisibleElementWithMatcher:
          grey_accessibilityID(kManageSyncTableViewAccessibilityIdentifier)];

  [ChromeEarlGreyUI waitForAppToIdle];

  // Ensure that the batch upload dialog section has been modified on the
  // account settings page.
  ExpectBatchUploadRecommendationItem(
      IDS_IOS_GOOGLE_ACCOUNT_SETTINGS_BATCH_UPLOAD_PASSWORDS_ITEM, 1,
      fakeIdentity.userEmail);
}

// Tests that bulk upload moves the following data types to account:
// - Passwords
// - Bookmarks
// - Reading List
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testBulkUploadForAllDataTypes {
  // Add local data.
  password_manager_test_utils::SavePasswordFormToProfileStore(
      @"password", @"user", @"https://example.com");
  reading_list_test_utils::AddURLToReadingListWithSnackbarDismiss(
      GURL("https://example.com"), nil);
  SaveBookmark(@"foo", @"https://www.foo.com");

  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [ChromeEarlGreyUI openSettingsMenu];
  // Sign in with fake identity using the settings sign-in promo.
  SignInWithPromoFromAccountSettings(fakeIdentity,
                                     /*expect_history_sync_ui=*/YES);

  // Open the "manage sync" view.
  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];

  // Tap on the batch upload button.
  [[EarlGrey
      selectElementWithMatcher:grey_allOf(
                                   grey_accessibilityID(
                                       kBatchUploadAccessibilityIdentifier),
                                   grey_sufficientlyVisible(), nil)]
      performAction:grey_tap()];
  [ChromeEarlGreyUI waitForAppToIdle];

  // Verify the bulk upload view is popped.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(
                                   kBulkUploadTableViewAccessibilityIdentifier)]
      assertWithMatcher:grey_sufficientlyVisible()];

  // Verify that switches for all data types are ON.
  [[EarlGrey selectElementWithMatcher:
                 chrome_test_util::TableViewSwitchCell(
                     kBulkUploadTableViewPasswordsItemAccessibilityIdentifer,
                     YES)] assertWithMatcher:grey_sufficientlyVisible()];
  [[EarlGrey selectElementWithMatcher:
                 chrome_test_util::TableViewSwitchCell(
                     kBulkUploadTableViewBookmarksItemAccessibilityIdentifer,
                     YES)] assertWithMatcher:grey_sufficientlyVisible()];
  [[EarlGrey selectElementWithMatcher:
                 chrome_test_util::TableViewSwitchCell(
                     kBulkUploadTableViewReadingListItemAccessibilityIdentifer,
                     YES)] assertWithMatcher:grey_sufficientlyVisible()];

  // Mock reauth since passwords needs upload.
  [ReauthenticationAppInterface mockReauthenticationModuleExpectedResult:
                                    ReauthenticationResult::kSuccess];
  // Delay the auth result to be able to validate that the passwords are not
  // visible until the result is emitted.
  [ReauthenticationAppInterface mockReauthenticationModuleShouldSkipReAuth:NO];

  // Tap on the save button.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(
                                   kBulkUploadSaveButtonAccessibilityIdentifer)]
      performAction:grey_tap()];

  // Verify the "manage sync" view is not visible yet (it is present behind the
  // screen, so we can't use notVisible directly).
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(
                                   kManageSyncTableViewAccessibilityIdentifier)]
      assertWithMatcher:grey_not(grey_minimumVisiblePercent(0.05))];

  // Successful auth should remove blocking view and "manage sync" view should
  // be visible.
  [ReauthenticationAppInterface mockReauthenticationModuleReturnMockedResult];
  [ChromeEarlGrey
      waitForSufficientlyVisibleElementWithMatcher:
          grey_accessibilityID(kManageSyncTableViewAccessibilityIdentifier)];

  // Ensure the correct snackbar appears.
  ExpectBatchUploadConfirmationSnackbar(3, fakeIdentity.userEmail);

  [ChromeEarlGreyUI waitForAppToIdle];

  // Ensure that the batch upload dialog section does not exist anymore.
  [[EarlGrey
      selectElementWithMatcher:
          grey_allOf(grey_accessibilityID(
                         kBatchUploadRecommendationItemAccessibilityIdentifier),
                     grey_sufficientlyVisible(), nil)]
      assertWithMatcher:grey_notVisible()];
  [[EarlGrey
      selectElementWithMatcher:grey_allOf(
                                   grey_accessibilityID(
                                       kBatchUploadAccessibilityIdentifier),
                                   grey_minimumVisiblePercent(0.05), nil)]
      assertWithMatcher:grey_nil()];
}

// Tests that the batch upload card in account settings can be displayed without
// crashing when the passwords data type is disabled. Regression test for
// crbug.com/360304897.
// TODO(crbug.com/512423981): This test is flaky.
- (void)FLAKY_testBulkUploadCardWhenPasswordsDisabled {
  SaveBookmark(@"foo", @"https://www.foo.com");
  SaveBookmark(@"bar", @"https://www.bar.com");
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey signinWithFakeIdentity:[FakeSystemIdentity fakeIdentity1]];
  [SigninEarlGreyAppInterface
      setSelectedType:syncer::UserSelectableType::kPasswords
              enabled:NO];

  [SigninEarlGreyUI openSyncSettings];

  ExpectBatchUploadRecommendationItem(
      IDS_IOS_GOOGLE_ACCOUNT_SETTINGS_BATCH_UPLOAD_ITEMS_ITEM, 2,
      fakeIdentity.userEmail);
}

// Before crbug.com/40265120, the autofill and payments toggles used to be
// coupled. This test verifies they no longer are.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testDeCouplingOfAddressAndPaymentToggles {
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];
  [SigninEarlGreyUI openSyncSettings];

  // Toggle off the address.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(kSyncAutofillIdentifier)]
      performAction:chrome_test_util::TurnTableViewSwitchOn(/*on=*/NO)];

  // Verify that the Payments is still enabled.
  [[EarlGrey selectElementWithMatcher:chrome_test_util::TableViewSwitchCell(
                                          kSyncPaymentsIdentifier,
                                          /*is_toggled_on=*/YES,
                                          /*enabled=*/YES)]
      assertWithMatcher:grey_sufficientlyVisible()];
}

// Tests the account settings and the user actionable error view are dismissed
// on account removal.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testAccountSettingsWithErrorDismissed {
  [ChromeEarlGrey addSyncPassphrase:kPassphrase];
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];
  [SigninEarlGreyUI openSyncSettings];

  // Verify the error section is showing.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(kSyncErrorButtonIdentifier)]
      assertWithMatcher:grey_sufficientlyVisible()];

  // Tap "Enter Passphrase" button.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(kSyncErrorButtonIdentifier)]
      performAction:grey_tap()];

  // Remove fakeIdentity from device.
  [ChromeEarlGreyUI waitForAppToIdle];
  [SigninEarlGrey forgetFakeIdentity:fakeIdentity];

  // Check that user is signed out and back to Settings main view.
  [SigninEarlGrey verifySignedOut];
  [[EarlGrey
      selectElementWithMatcher:chrome_test_util::SettingsCollectionView()]
      assertWithMatcher:grey_notNil()];
}

// Tests the passphrase error view is dismissed when "Cancel" button is pressed.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testErrorViewFromAccountSettingsDismissed {
  [ChromeEarlGrey addSyncPassphrase:kPassphrase];
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];
  [SigninEarlGreyUI openSyncSettings];

  // Verify the error section is showing.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(kSyncErrorButtonIdentifier)]
      assertWithMatcher:grey_sufficientlyVisible()];

  // Tap "Enter Passphrase" button.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(kSyncErrorButtonIdentifier)]
      performAction:grey_tap()];

  // Tap "Cancel".
  [[EarlGrey
      selectElementWithMatcher:chrome_test_util::NavigationBarCancelButton()]
      performAction:grey_tap()];

  // Verify it goes back to account settings UI.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(
                                   kManageSyncTableViewAccessibilityIdentifier)]
      assertWithMatcher:grey_sufficientlyVisible()];
}

// Tests the account settings and the encryption view are dismissed
// on account removal.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testAccountSettingsAndEncryptionDismissed {
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];
  [SigninEarlGreyUI openSyncSettings];

  // Scroll to the bottom to view all section.
  id<GREYMatcher> scroll_view_matcher =
      grey_accessibilityID(kManageSyncTableViewAccessibilityIdentifier);
  [[EarlGrey selectElementWithMatcher:scroll_view_matcher]
      performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)];

  // Verify the encryption item is shown.
  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
                                          kEncryptionAccessibilityIdentifier)]
      assertWithMatcher:grey_sufficientlyVisible()];

  // Tap on the encryption item.
  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
                                          kEncryptionAccessibilityIdentifier)]
      performAction:grey_tap()];

  // Remove fakeIdentity from device.
  [ChromeEarlGreyUI waitForAppToIdle];
  [SigninEarlGrey forgetFakeIdentity:fakeIdentity];

  // Check that user is signed out and back to Settings main view.
  [ChromeEarlGreyUI waitForAppToIdle];
  [SigninEarlGrey verifySignedOut];
  [[EarlGrey
      selectElementWithMatcher:chrome_test_util::SettingsCollectionView()]
      assertWithMatcher:grey_notNil()];
}

// Tests the custom passphrase is remembered per account, kept across signout,
// and cleared when account is removed from device.
// TODO(crbug.com/384646508): Re-enable after the fix on iOS 17.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testRememberCustomPassphraseAfterSignout {
  if (!@available(iOS 18.0, *)) {
    EARL_GREY_TEST_SKIPPED(@"Failed on iOS 17");
  }
  // Enable custom passphrase.
  [ChromeEarlGrey addSyncPassphrase:kPassphrase];
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity];
  [SigninEarlGreyUI openSyncSettings];

  // Verify the error section is showing.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(kSyncErrorButtonIdentifier)]
      assertWithMatcher:grey_sufficientlyVisible()];

  // Tap "Enter Passphrase" button.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(kSyncErrorButtonIdentifier)]
      performAction:grey_tap()];

  // Enter the passphrase.
  [SigninEarlGreyUI submitSyncPassphrase:kPassphrase];

  // Verify it goes back to "manage sync" UI.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(
                                   kManageSyncTableViewAccessibilityIdentifier)]
      assertWithMatcher:grey_sufficientlyVisible()];

  // Verify the error section is not showing anymore.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(kSyncErrorButtonIdentifier)]
      assertWithMatcher:grey_notVisible()];

  // Sign out.
  [SigninEarlGreyUI tapSignOutFromSyncSettings];
  [SigninEarlGreyUI dismissSignoutSnackbar];
  [ChromeEarlGreyUI waitForAppToIdle];
  [SigninEarlGrey verifySignedOut];

  // Sign back in with the same identity using the settings sign-in promo.
  // The history sync opt-in was declined in the first sign-in earlier in this
  // test.
  SignInWithPromoFromAccountSettings(fakeIdentity,
                                     /*expect_history_sync_ui=*/YES);

  // Verify the account settings row is showing in the settings menu.
  [[EarlGrey selectElementWithMatcher:SettingsAccountButton()]
      assertWithMatcher:grey_sufficientlyVisible()];
  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];

  // Verify the "enter passphrase" error section is not showing.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(kSyncErrorButtonIdentifier)]
      assertWithMatcher:grey_notVisible()];

  // Remove fakeIdentity from device.
  [SigninEarlGrey forgetFakeIdentity:fakeIdentity];
  [ChromeEarlGreyUI waitForAppToIdle];
  [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
      performAction:grey_tap()];

  // Sign back in.
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];
  [SigninEarlGreyUI openSyncSettings];

  // Verify the error section is showing because the passphrase was cleared.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(kSyncErrorButtonIdentifier)]
      assertWithMatcher:grey_sufficientlyVisible()];
}

// Test that the Personalize Google Services page is dismissed when the user
// signs out.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testPersonalizeGoogleServicesSettingsDismissedOnSignOut {
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];

  // Go to the Sync settings page.
  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];
  [SigninEarlGreyUI openSyncSettings];

  // Scroll to the bottom to view all section.
  id<GREYMatcher> scroll_view_matcher =
      grey_accessibilityID(kManageSyncTableViewAccessibilityIdentifier);
  [[EarlGrey selectElementWithMatcher:scroll_view_matcher]
      performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)];

  // Tap on the Personalize Google Services item.
  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
                                          kPersonalizeGoogleServicesIdentifier)]
      performAction:grey_tap()];

  // Check that the Personalize Google Services view is displayed.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(
                                   kPersonalizeGoogleServicesViewIdentifier)]
      assertWithMatcher:grey_notNil()];

  // Remove fakeIdentity from device.
  [ChromeEarlGreyUI waitForAppToIdle];
  [SigninEarlGrey forgetFakeIdentity:fakeIdentity];

  // Check that user is signed out and back to Settings main view.
  [SigninEarlGrey verifySignedOut];
  [[EarlGrey
      selectElementWithMatcher:chrome_test_util::SettingsCollectionView()]
      assertWithMatcher:grey_notNil()];
}

// Test switching account from the account menu.
// TODO(crbug.com/512422367): Test is flaky.
- (void)FLAKY_testSwitchAccountFromAccountMenu {
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  FakeSystemIdentity* fakeIdentity2 = [FakeSystemIdentity fakeIdentity2];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];
  [SigninEarlGrey addFakeIdentity:fakeIdentity2];

  // Go to the Sync settings page.
  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];
  [SigninEarlGreyUI openAccountMenuFromSettings];

  // Switch account.
  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
                                          kAccountMenuSecondaryAccountButtonId)]
      performAction:grey_tap()];

  // Verify the account settings view remains on top of screen.
  id<GREYMatcher> scrollViewMatcher =
      grey_accessibilityID(kManageSyncTableViewAccessibilityIdentifier);
  [[EarlGrey selectElementWithMatcher:scrollViewMatcher]
      performAction:grey_scrollToContentEdgeWithStartPoint(kGREYContentEdgeTop,
                                                           0.5, 0.2)];
  // And it displays the new account.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(
                                   CentralAccountViewAccessibilityIdentifier(
                                       fakeIdentity2.userEmail))]
      assertWithMatcher:grey_sufficientlyVisible()];

  // Verify account is switched.
  [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity2];
}

// Test signing out from the account menu.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testSignOutFromAccountFromAccountMenu {
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  FakeSystemIdentity* fakeIdentity2 = [FakeSystemIdentity fakeIdentity2];
  [SigninEarlGrey addFakeIdentity:fakeIdentity];
  [SigninEarlGrey addFakeIdentity:fakeIdentity2];

  // Go to the Sync settings page.
  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];
  [SigninEarlGreyUI openAccountMenuFromSettings];

  // Scroll to the bottom to view the sign-out button.
  id<GREYMatcher> account_menu_view_matcher =
      grey_accessibilityID(kAccountMenuTableViewId);
  [[EarlGrey selectElementWithMatcher:account_menu_view_matcher]
      performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)];
  // Sign out.
  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
                                          kAccountMenuSignoutButtonId)]
      performAction:grey_tap()];

  [SigninEarlGrey verifySignedOut];

  // Verify the account menu is closed.
  ConditionBlock wait_for_disappearance = ^{
    NSError* error;
    // Checking if collection view does not exist in the UI hierarchy.
    [[EarlGrey
        selectElementWithMatcher:grey_accessibilityID(kAccountMenuTableViewId)]
        assertWithMatcher:grey_nil()
                    error:&error];

    return error == nil;
  };
  // The account menu fades with animation; wait for 5 seconds to ensure the
  // animation is completed.
  GREYAssert(base::test::ios::WaitUntilConditionOrTimeout(
                 base::Seconds(5), wait_for_disappearance),
             @"Account menu did not disappear.");

  // Verify the account settings view is popped.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(
                                   kManageSyncTableViewAccessibilityIdentifier)]
      assertWithMatcher:grey_notVisible()];
}

// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testManageAccountsRemoveManagedAccount {
  FakeSystemIdentity* managedIdentity =
      [FakeSystemIdentity fakeManagedIdentity];
  [SigninEarlGrey
      signinWithFakeManagedIdentityInPersonalProfile:managedIdentity];
  [SigninEarlGreyUI openManageAccountsFromSettings];

  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
                                          kSettingsEditAccountListTableViewId)]
      assertWithMatcher:grey_sufficientlyVisible()];

  // Tap remove button for the managed account.
  [[EarlGrey
      selectElementWithMatcher:
          grey_accessibilityID(
              [kSettingsAccountsRemoveAccountButtonAccessibilityIdentifier
                  stringByAppendingString:managedIdentity.userEmail])]
      performAction:grey_tap()];

  // Confirm account removal.
  [[EarlGrey selectElementWithMatcher:
                 chrome_test_util::ActionSheetItemWithAccessibilityLabelId(
                     IDS_IOS_REMOVE_ACCOUNT_LABEL)] performAction:grey_tap()];

  [SigninEarlGrey verifySignedOut];
}

// Tests switching to a managed account from sync settings.
// TODO(crbug.com/512422445): Test is flaky.
- (void)FLAKY_testSwitchToManagedAccountFromAccountMenu {
  FakeSystemIdentity* managedIdentity =
      [FakeSystemIdentity fakeManagedIdentity];
  FakeSystemIdentity* personalIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey addFakeIdentity:managedIdentity];
  [SigninEarlGrey addFakeIdentity:personalIdentity];

  [SigninEarlGrey signinWithFakeIdentity:personalIdentity];
  [SigninEarlGreyUI openAccountMenuFromSettings];

  // Tap on the managed account.
  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
                                          kAccountMenuSecondaryAccountButtonId)]
      performAction:grey_tap()];

  WaitForEnterpriseOnboardingScreen();

  // Tap on Continue button to acknowledge signing in with a managed account.
  [[EarlGrey selectElementWithMatcher:
                 grey_allOf(grey_text(l10n_util::GetNSString(
                                IDS_IOS_ENTERPRISE_PROFILE_CREATION_CONTINUE)),
                            grey_interactable(), nil)]
      performAction:grey_tap()];

  // Dismiss history sync screen.
  [ChromeEarlGrey waitForMatcher:HistoryScreenMatcher()];
  [[EarlGrey
      selectElementWithMatcher:chrome_test_util::ButtonStackSecondaryButton()]
      performAction:grey_tap()];

  [SigninEarlGrey verifySignedInWithFakeIdentity:managedIdentity];
}

// Tests that an MDM error in Manage Sync Settings shows the error section
// and tapping the Fix Now button requests the MDM dialog.
- (void)testAccountSettingsWithMDMError {
  FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
  [SigninEarlGrey signinWithFakeIdentity:fakeIdentity];

  // Set the MDM error.
  [SigninEarlGrey setMDMErrorForIdentity:fakeIdentity userActionable:YES];

  [SigninEarlGreyUI openSyncSettings];

  // Verify the error section is showing.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(kSyncErrorButtonIdentifier)]
      assertWithMatcher:grey_sufficientlyVisible()];

  // Reset the MDM notification status.
  [SigninEarlGrey resetMDMNotificationDisplayed];

  // Tap "Fix Now" (which is the error button in sync settings).
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(kSyncErrorButtonIdentifier)]
      performAction:grey_tap()];

  // Verify that the MDM dialog was requested.
  [SigninEarlGrey waitForMDMNotificationDisplayed];

  // Resolve the error and verify the error UI is dismissed.
  [SigninEarlGrey resetMDMNotificationDisplayed];
  [SigninEarlGrey clearMDMErrorForIdentity:fakeIdentity];
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(kSyncErrorButtonIdentifier)]
      assertWithMatcher:grey_notVisible()];
  GREYAssertFalse([SigninEarlGrey wasMDMNotificationDisplayed],
                  @"MDM dialog should not be shown.");
}

@end
