// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <XCTest/XCTest.h>
#import "base/ios/ios_util.h"
#import "base/test/ios/wait_util.h"
#import "components/autofill/core/common/autofill_features.h"
#import "components/strings/grit/components_strings.h"
#import "ios/chrome/browser/autofill/ui_bundled/autofill_app_interface.h"
#import "ios/chrome/browser/autofill/ui_bundled/autofill_constants.h"
#import "ios/chrome/browser/shared/ui/elements/activity_overlay_egtest_util.h"
#import "ios/chrome/browser/signin/model/fake_system_identity.h"
#import "ios/chrome/browser/ui/authentication/signin_earl_grey.h"
#import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui_test_util.h"
#import "ios/chrome/browser/ui/settings/autofill/autofill_settings_constants.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/testing/earl_grey/earl_grey_test.h"
#import "ui/base/l10n/l10n_util.h"
#import "ui/strings/grit/ui_strings.h"
using chrome_test_util::ButtonWithAccessibilityLabel;
using chrome_test_util::ButtonWithAccessibilityLabelId;
using chrome_test_util::NavigationBarDoneButton;
using chrome_test_util::SettingsDoneButton;
using chrome_test_util::SettingsMenuBackButton;
using chrome_test_util::TabGridEditButton;
namespace {
// Expectation of how the saved Autofill profile looks like, a map from cell
// name IDs to expected contents.
struct DisplayStringIDToExpectedResult {
int display_string_id;
NSString* expected_result;
};
// Will be used to test the country selection logic.
NSString* const kCountryForSelection = @"Germany";
constexpr base::TimeDelta kSnackbarAppearanceTimeout = base::Seconds(5);
// kSnackbarDisappearanceTimeout = MDCSnackbarMessageDurationMax + 1
constexpr base::TimeDelta kSnackbarDisappearanceTimeout = base::Seconds(10 + 1);
const DisplayStringIDToExpectedResult kExpectedFields[] = {
{IDS_IOS_AUTOFILL_FULLNAME, @"John H. Doe"},
{IDS_IOS_AUTOFILL_COMPANY_NAME, @"Underworld"},
{IDS_IOS_AUTOFILL_ADDRESS1, @"666 Erebus St."},
{IDS_IOS_AUTOFILL_ADDRESS2, @"Apt 8"},
{IDS_IOS_AUTOFILL_CITY, @"Elysium"},
{IDS_IOS_AUTOFILL_STATE, @"CA"},
{IDS_IOS_AUTOFILL_ZIP, @"91111"},
{IDS_IOS_AUTOFILL_COUNTRY, @"United States"},
{IDS_IOS_AUTOFILL_PHONE, @"16502111111"},
{IDS_IOS_AUTOFILL_EMAIL, @"[email protected]"}};
NSString* const kProfileLabel = @"John H. Doe, 666 Erebus St.";
// Expectation of how user-typed country names should be canonicalized.
struct UserTypedCountryExpectedResultPair {
NSString* user_typed_country;
NSString* expected_result;
};
const UserTypedCountryExpectedResultPair kCountryTests[] = {
{@"Brasil", @"Brazil"},
{@"China", @"China mainland"},
{@"DEUTSCHLAND", @"Germany"},
{@"GREAT BRITAIN", @"United Kingdom"},
{@"IN", @"India"},
{@"JaPaN", @"Japan"},
{@"JP", @"Japan"},
{@"Nigeria", @"Nigeria"},
{@"TW", @"Taiwan"},
{@"U.S.A.", @"United States"},
{@"UK", @"United Kingdom"},
{@"USA", @"United States"},
{@"Nonexistia", @""},
};
// Return the edit button from the navigation bar.
id<GREYMatcher> NavigationBarEditButton() {
return grey_allOf(
ButtonWithAccessibilityLabelId(IDS_IOS_NAVIGATION_BAR_EDIT_BUTTON),
grey_not(TabGridEditButton()),
grey_not(grey_accessibilityTrait(UIAccessibilityTraitNotEnabled)), nil);
}
// Matcher for a country entry with the given accessibility label.
id<GREYMatcher> CountryEntry(NSString* label) {
return grey_allOf(chrome_test_util::ButtonWithAccessibilityLabel(label),
grey_sufficientlyVisible(), nil);
}
// Matcher for the search bar.
id<GREYMatcher> SearchBar() {
return grey_allOf(grey_accessibilityID(kAutofillCountrySelectionTableViewId),
grey_sufficientlyVisible(), nil);
}
// Matcher for the search bar's cancel button.
id<GREYMatcher> SearchBarCancelButton() {
return grey_allOf(ButtonWithAccessibilityLabelId(IDS_APP_CANCEL),
grey_kindOfClass([UIButton class]),
grey_ancestor(grey_kindOfClass([UISearchBar class])),
grey_sufficientlyVisible(), nil);
}
// Matcher for the search bar's scrim.
id<GREYMatcher> SearchBarScrim() {
return grey_accessibilityID(kAutofillCountrySelectionSearchScrimId);
}
// Matcher for migrate to account button.
id<GREYMatcher> MigrateToAccountButton() {
return grey_accessibilityID(kAutofillAddressMigrateToAccountButtonId);
}
} // namespace
// Various tests for the Autofill profiles section of the settings.
@interface AutofillProfileSettingsTestCase : ChromeTestCase
@end
@implementation AutofillProfileSettingsTestCase
- (void)setUp {
[super setUp];
[AutofillAppInterface clearProfilesStore];
}
- (void)tearDown {
[AutofillAppInterface clearProfilesStore];
[super tearDown];
}
// Helper to open the settings page for Autofill profiles.
- (void)openAutofillProfilesSettings {
[ChromeEarlGreyUI openSettingsMenu];
[ChromeEarlGreyUI
tapSettingsMenuButton:chrome_test_util::AddressesAndMoreButton()];
}
// Helper to open the settings page for the Autofill profile with `label`.
- (void)openEditProfile:(NSString*)label {
[self openAutofillProfilesSettings];
[[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(label)]
performAction:grey_tap()];
}
// Close the settings.
- (void)exitSettingsMenu {
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(0)]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
performAction:grey_tap()];
// Wait for UI components to finish loading.
[ChromeEarlGreyUI waitForAppToIdle];
}
// Scroll to the bottom.
- (void)scrollDownWithMatcher:(id<GREYMatcher>)scrollViewMatcher {
[[EarlGrey selectElementWithMatcher:scrollViewMatcher]
performAction:grey_scrollToContentEdgeWithStartPoint(
kGREYContentEdgeBottom, 0.1f, 0.1f)];
}
// Helper to open the settings page for the Autofill profile card list in edit
// mode.
- (void)openProfileListInEditMode {
[self openAutofillProfilesSettings];
[[EarlGrey selectElementWithMatcher:NavigationBarEditButton()]
performAction:grey_tap()];
}
// Returns the delete button on the deletion confirmation action sheet.
- (id<GREYMatcher>)confirmButtonForNumberOfAddressesBeingDeleted:
(int)numberOfAddresses {
return grey_allOf(
grey_accessibilityLabel(l10n_util::GetPluralNSStringF(
IDS_IOS_SETTINGS_AUTOFILL_DELETE_ADDRESS_CONFIRMATION_BUTTON,
numberOfAddresses)),
grey_accessibilityTrait(UIAccessibilityTraitButton),
grey_userInteractionEnabled(), nil);
}
// Returns the footer based on the count of errors due to the empty required
// fields.
- (id<GREYMatcher>)footerWithCountOfEmptyRequiredFields:(int)countOfrrors {
return grey_allOf(
grey_accessibilityLabel(l10n_util::GetPluralNSStringF(
IDS_IOS_SETTINGS_EDIT_AUTOFILL_ADDRESS_REQUIREMENT_ERROR,
countOfrrors)),
grey_sufficientlyVisible(), nil);
}
// Test that the page for viewing Autofill profile details is as expected.
- (void)testAutofillProfileViewPage {
if ([AutofillAppInterface isDynamicallyLoadFieldsOnInputEnabled]) {
EARL_GREY_TEST_SKIPPED(@"This test is not relevant when the fields "
@"are loaded dynamically on input.");
}
[AutofillAppInterface saveExampleProfile];
[self openEditProfile:kProfileLabel];
// Check that all fields and values match the expectations.
for (const DisplayStringIDToExpectedResult& expectation : kExpectedFields) {
id<GREYMatcher> elementMatcher = nil;
if (expectation.display_string_id == IDS_IOS_AUTOFILL_COUNTRY) {
elementMatcher = grey_accessibilityLabel(
l10n_util::GetNSString(IDS_IOS_AUTOFILL_COUNTRY));
} else {
elementMatcher = grey_accessibilityLabel(
[NSString stringWithFormat:@"%@, %@",
l10n_util::GetNSString(
expectation.display_string_id),
expectation.expected_result]);
}
[[[EarlGrey
selectElementWithMatcher:grey_allOf(elementMatcher,
grey_sufficientlyVisible(), nil)]
usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 150)
onElementWithMatcher:grey_accessibilityID(
kAutofillProfileEditTableViewId)]
assertWithMatcher:grey_notNil()];
}
// Go back to the list view page.
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(0)]
performAction:grey_tap()];
[self exitSettingsMenu];
}
// Test that the page for viewing Autofill profile details is accessible.
- (void)testAccessibilityOnAutofillProfileViewPage {
[AutofillAppInterface saveExampleProfile];
[self openEditProfile:kProfileLabel];
[ChromeEarlGrey verifyAccessibilityForCurrentScreen];
// Go back to the list view page.
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(0)]
performAction:grey_tap()];
[self exitSettingsMenu];
}
// Test that the page for editing Autofill profile details is accessible.
- (void)testAccessibilityOnAutofillProfileEditPage {
[AutofillAppInterface saveExampleProfile];
[self openEditProfile:kProfileLabel];
// Switch on edit mode.
[[EarlGrey selectElementWithMatcher:NavigationBarEditButton()]
performAction:grey_tap()];
[ChromeEarlGrey verifyAccessibilityForCurrentScreen];
// Go back to the list view page.
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(0)]
performAction:grey_tap()];
[self exitSettingsMenu];
}
// Checks that the Autofill profiles list view is in edit mode and the Autofill
// profiles switch is disabled.
- (void)testListViewEditMode {
[AutofillAppInterface saveExampleProfile];
[self openProfileListInEditMode];
// Check the Autofill profile switch is disabled.
[[EarlGrey
selectElementWithMatcher:chrome_test_util::TableViewSwitchCell(
kAutofillAddressSwitchViewId,
/*is_toggled_on=*/YES, /*is_enabled=*/NO)]
assertWithMatcher:grey_notNil()];
[self exitSettingsMenu];
}
// Checks that the Autofill profile switch can be toggled on/off and the list of
// Autofill profiles is not affected by it.
- (void)testToggleAutofillProfileSwitch {
[AutofillAppInterface saveExampleProfile];
[self openAutofillProfilesSettings];
// Toggle the Autofill profiles switch off.
[[EarlGrey
selectElementWithMatcher:chrome_test_util::TableViewSwitchCell(
kAutofillAddressSwitchViewId,
/*is_toggled_on=*/YES, /*is_enabled=*/YES)]
performAction:chrome_test_util::TurnTableViewSwitchOn(NO)];
// Expect Autofill profiles to remain visible.
[[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(kProfileLabel)]
assertWithMatcher:grey_notNil()];
// Toggle the Autofill profiles switch back on.
[[EarlGrey
selectElementWithMatcher:chrome_test_util::TableViewSwitchCell(
kAutofillAddressSwitchViewId,
/*is_toggled_on=*/NO, /*is_enabled=*/YES)]
performAction:chrome_test_util::TurnTableViewSwitchOn(YES)];
// Expect Autofill profiles to remain visible.
[[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(kProfileLabel)]
assertWithMatcher:grey_notNil()];
[self exitSettingsMenu];
}
// Checks that the confirmation action sheet is shown when an autofill profile
// is deleted and the profile is deleted when the confirmation is accepted.
- (void)testConfirmationShownOnDeletion {
[AutofillAppInterface saveExampleProfile];
[self openProfileListInEditMode];
[[EarlGrey
selectElementWithMatcher:grey_accessibilityLabel(
[AutofillAppInterface exampleProfileName])]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:chrome_test_util::
SettingsBottomToolbarDeleteButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:
[self confirmButtonForNumberOfAddressesBeingDeleted:1]]
performAction:grey_tap()];
WaitForActivityOverlayToDisappear();
[[EarlGrey selectElementWithMatcher:chrome_test_util::
SettingsBottomToolbarDeleteButton()]
assertWithMatcher:grey_nil()];
// If the done button in the nav bar is enabled it is no longer in edit
// mode.
[[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
assertWithMatcher:grey_sufficientlyVisible()];
}
// Checks that the confirmation action sheet is shown when an autofill profile
// is swiped to be deleted.
- (void)testConfirmationShownOnSwipeToDelete {
[AutofillAppInterface saveExampleProfile];
[self openAutofillProfilesSettings];
[[EarlGrey
selectElementWithMatcher:grey_accessibilityLabel(
[AutofillAppInterface exampleProfileName])]
performAction:chrome_test_util::SwipeToShowDeleteButton()];
// There are multiple delete buttons but only one enabled.
[[EarlGrey
selectElementWithMatcher:grey_allOf(
ButtonWithAccessibilityLabel(@"Delete"),
grey_not(grey_accessibilityTrait(
UIAccessibilityTraitNotEnabled)),
nil)] performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:
[self confirmButtonForNumberOfAddressesBeingDeleted:1]]
performAction:grey_tap()];
WaitForActivityOverlayToDisappear();
// Check the profile has been deleted.
[[EarlGrey
selectElementWithMatcher:grey_accessibilityLabel(
[AutofillAppInterface exampleProfileName])]
assertWithMatcher:grey_notVisible()];
}
// Checks that the country field is a selection field in the edit mode and the
// newly selected country gets saved in the profile.
- (void)testCountrySelection {
[AutofillAppInterface saveExampleProfile];
[self openEditProfile:kProfileLabel];
// Switch on edit mode.
[[EarlGrey selectElementWithMatcher:NavigationBarEditButton()]
performAction:grey_tap()];
[[EarlGrey
selectElementWithMatcher:grey_accessibilityLabel(l10n_util::GetNSString(
IDS_IOS_AUTOFILL_COUNTRY))]
performAction:grey_tap()];
// Focus the search bar.
[[EarlGrey selectElementWithMatcher:SearchBar()] performAction:grey_tap()];
// Verify the scrim is visible when search bar is focused but not typed in.
[[EarlGrey selectElementWithMatcher:SearchBarScrim()]
assertWithMatcher:grey_notNil()];
// Verify the cancel button is visible and unfocuses search bar when tapped.
[[EarlGrey selectElementWithMatcher:SearchBarCancelButton()]
performAction:grey_tap()];
// Verify countries are searchable using their name in the current locale.
[[EarlGrey selectElementWithMatcher:SearchBar()] performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SearchBar()]
performAction:grey_replaceText(kCountryForSelection)];
// Verify that scrim is not visible anymore.
[[EarlGrey selectElementWithMatcher:SearchBarScrim()]
assertWithMatcher:grey_nil()];
// Verify the `kCountryForSelection` country is visible.
[[EarlGrey selectElementWithMatcher:CountryEntry(kCountryForSelection)]
assertWithMatcher:grey_notNil()];
// Tap on `kCountryForSelection`.
[[EarlGrey selectElementWithMatcher:CountryEntry(kCountryForSelection)]
performAction:grey_tap()];
// Save the profile.
[[EarlGrey selectElementWithMatcher:NavigationBarDoneButton()]
performAction:grey_tap()];
// Go back to the list view page.
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(0)]
performAction:grey_tap()];
// Open the profile again.
[[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(kProfileLabel)]
performAction:grey_tap()];
// Check `kCountryForSelection` is saved.
[[EarlGrey selectElementWithMatcher:grey_text(kCountryForSelection)]
assertWithMatcher:grey_sufficientlyVisible()];
// Go back to the list view page.
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(0)]
performAction:grey_tap()];
[self exitSettingsMenu];
}
// Checks when the country field is changed to Germany in the edit mode, the
// city is added to the required fields. When it is emptied, the save button in
// displayed. The profile is an account profile.
- (void)testRequiredFields {
if ([AutofillAppInterface isDynamicallyLoadFieldsOnInputEnabled]) {
EARL_GREY_TEST_SKIPPED(@"This test is not relevant when the fields "
@"are loaded dynamically on input.");
}
[SigninEarlGrey signinWithFakeIdentity:[FakeSystemIdentity fakeIdentity1]];
[AutofillAppInterface saveExampleAccountProfile];
[self openEditProfile:kProfileLabel];
// Switch on edit mode.
[[EarlGrey selectElementWithMatcher:NavigationBarEditButton()]
performAction:grey_tap()];
[[EarlGrey
selectElementWithMatcher:grey_accessibilityLabel(l10n_util::GetNSString(
IDS_IOS_AUTOFILL_COUNTRY))]
performAction:grey_tap()];
// Focus the search bar.
[[EarlGrey selectElementWithMatcher:SearchBar()] performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SearchBar()]
performAction:grey_replaceText(kCountryForSelection)];
// Verify that scrim is not visible anymore.
[[EarlGrey selectElementWithMatcher:SearchBarScrim()]
assertWithMatcher:grey_nil()];
// Verify the `kCountryForSelection` country is visible.
[[EarlGrey selectElementWithMatcher:CountryEntry(kCountryForSelection)]
assertWithMatcher:grey_notNil()];
// Tap on `kCountryForSelection`.
[[EarlGrey selectElementWithMatcher:CountryEntry(kCountryForSelection)]
performAction:grey_tap()];
// Remove the text from the state field.
[[EarlGrey
selectElementWithMatcher:chrome_test_util::TextFieldForCellWithLabelId(
IDS_IOS_AUTOFILL_STATE)]
performAction:grey_replaceText(@"")];
// The "Done" button is still visible as the state field is not a required
// field.
[[EarlGrey selectElementWithMatcher:NavigationBarDoneButton()]
assertWithMatcher:grey_sufficientlyVisible()];
// Remove the text from the city field.
[[EarlGrey
selectElementWithMatcher:chrome_test_util::TextFieldForCellWithLabelId(
IDS_IOS_AUTOFILL_CITY)]
performAction:grey_replaceText(@"")];
// The "Done" button is not enabled now.
[[EarlGrey selectElementWithMatcher:NavigationBarDoneButton()]
assertWithMatcher:grey_not(grey_enabled())];
// Go back to the list view page.
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(0)]
performAction:grey_tap()];
[self exitSettingsMenu];
[SigninEarlGrey signOut];
}
// Tests that when country selection view opens, the currently selected country
// is in view.
- (void)testAutoScrollInCountrySelector {
[AutofillAppInterface saveExampleProfile];
[self openEditProfile:kProfileLabel];
// Switch on edit mode.
[[EarlGrey selectElementWithMatcher:NavigationBarEditButton()]
performAction:grey_tap()];
[[EarlGrey
selectElementWithMatcher:grey_accessibilityLabel(l10n_util::GetNSString(
IDS_IOS_AUTOFILL_COUNTRY))]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:CountryEntry(@"United States")]
assertWithMatcher:grey_sufficientlyVisible()];
}
// Tests that when the state data is removed, the "Done" button is enabled for
// "Germany" but not for "India". Similarly, the "Done" is disabled for "US".
- (void)testDoneButtonByRequirementsOfCountries {
if ([AutofillAppInterface isDynamicallyLoadFieldsOnInputEnabled]) {
EARL_GREY_TEST_SKIPPED(@"This test is not relevant when the fields "
@"are loaded dynamically on input.");
}
[SigninEarlGrey signinWithFakeIdentity:[FakeSystemIdentity fakeIdentity1]];
[AutofillAppInterface saveExampleAccountProfile];
[self openEditProfile:kProfileLabel];
// Switch on edit mode.
[[EarlGrey selectElementWithMatcher:NavigationBarEditButton()]
performAction:grey_tap()];
// Change text of state to empty.
[[EarlGrey
selectElementWithMatcher:chrome_test_util::TextFieldForCellWithLabelId(
IDS_IOS_AUTOFILL_STATE)]
performAction:grey_replaceText(@"")];
// The "Done" button should not be enabled now since "State" is a required
// field for "United States".
[[EarlGrey selectElementWithMatcher:NavigationBarDoneButton()]
assertWithMatcher:grey_not(grey_enabled())];
[[EarlGrey
selectElementWithMatcher:grey_accessibilityLabel(l10n_util::GetNSString(
IDS_IOS_AUTOFILL_COUNTRY))]
performAction:grey_tap()];
// Focus the search bar.
[[EarlGrey selectElementWithMatcher:SearchBar()] performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SearchBar()]
performAction:grey_replaceText(kCountryForSelection)];
// Verify the `kCountryForSelection` country is visible.
[[EarlGrey selectElementWithMatcher:CountryEntry(kCountryForSelection)]
assertWithMatcher:grey_notNil()];
// Tap on `kCountryForSelection`.
[[EarlGrey selectElementWithMatcher:CountryEntry(kCountryForSelection)]
performAction:grey_tap()];
// The "Done" button should be enabled since "State" is not a required field
// for "Germany".
[[EarlGrey selectElementWithMatcher:NavigationBarDoneButton()]
assertWithMatcher:grey_enabled()];
// Tap on Country and select "India" now.
[[EarlGrey
selectElementWithMatcher:grey_accessibilityLabel(l10n_util::GetNSString(
IDS_IOS_AUTOFILL_COUNTRY))]
performAction:grey_tap()];
// Focus the search bar.
[[EarlGrey selectElementWithMatcher:SearchBar()] performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SearchBar()]
performAction:grey_replaceText(@"India")];
// Verify the "India" is visible.
[[EarlGrey selectElementWithMatcher:CountryEntry(@"India")]
assertWithMatcher:grey_notNil()];
// Tap on "India".
[[EarlGrey selectElementWithMatcher:CountryEntry(@"India")]
performAction:grey_tap()];
// The "Done" button should not be enabled now since "State" is a required
// field for "India".
[[EarlGrey selectElementWithMatcher:NavigationBarDoneButton()]
assertWithMatcher:grey_not(grey_enabled())];
[SigninEarlGrey signOut];
}
// Tests that the footer text is correctly displayed when there are multiple
// required empty fields.
- (void)testFooterWithMultipleErrors {
if ([AutofillAppInterface isDynamicallyLoadFieldsOnInputEnabled]) {
EARL_GREY_TEST_SKIPPED(@"This test is not relevant when the fields "
@"are loaded dynamically on input.");
}
[SigninEarlGrey signinWithFakeIdentity:[FakeSystemIdentity fakeIdentity1]];
[AutofillAppInterface saveExampleAccountProfile];
[self openEditProfile:kProfileLabel];
// Change text of city to empty.
[[EarlGrey
selectElementWithMatcher:chrome_test_util::TextFieldForCellWithLabelId(
IDS_IOS_AUTOFILL_CITY)]
performAction:grey_replaceText(@"")];
[[EarlGrey
selectElementWithMatcher:[self footerWithCountOfEmptyRequiredFields:1]]
assertWithMatcher:grey_nil()];
// Change text of state to empty.
[[EarlGrey
selectElementWithMatcher:chrome_test_util::TextFieldForCellWithLabelId(
IDS_IOS_AUTOFILL_STATE)]
performAction:grey_replaceText(@"")];
[[EarlGrey
selectElementWithMatcher:[self footerWithCountOfEmptyRequiredFields:2]]
assertWithMatcher:grey_nil()];
[SigninEarlGrey signOut];
}
// Tests that the local profile is migrated to account.
- (void)testMigrateToAccount {
[SigninEarlGrey signinWithFakeIdentity:[FakeSystemIdentity fakeIdentity1]];
[AutofillAppInterface saveExampleProfile];
[self
openEditProfile:
[NSString
stringWithFormat:@"%@, %@", kProfileLabel,
l10n_util::GetNSString(
IDS_IOS_LOCAL_ADDRESS_ACCESSIBILITY_LABEL)]];
if ([ChromeEarlGrey isIPadIdiom]) {
// Scroll to the bottom for ipad.
[self scrollDownWithMatcher:grey_accessibilityID(
kAutofillProfileEditTableViewId)];
}
[[EarlGrey selectElementWithMatcher:MigrateToAccountButton()]
performAction:grey_tap()];
// Wait for the snackbar to appear.
id<GREYMatcher> snackbar_matcher =
grey_accessibilityID(@"MDCSnackbarMessageTitleAutomationIdentifier");
ConditionBlock wait_for_appearance = ^{
NSError* error = nil;
[[EarlGrey selectElementWithMatcher:snackbar_matcher]
assertWithMatcher:grey_notNil()
error:&error];
return error == nil;
};
GREYAssert(base::test::ios::WaitUntilConditionOrTimeout(
kSnackbarAppearanceTimeout, wait_for_appearance),
@"Snackbar did not appear.");
// Wait for the snackbar to disappear.
ConditionBlock wait_for_disappearance = ^{
NSError* error = nil;
[[EarlGrey selectElementWithMatcher:snackbar_matcher]
assertWithMatcher:grey_nil()
error:&error];
return error == nil;
};
GREYAssert(base::test::ios::WaitUntilConditionOrTimeout(
kSnackbarDisappearanceTimeout, wait_for_disappearance),
@"Snackbar did not disappear.");
// Go back to the list view page.
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(0)]
performAction:grey_tap()];
// Open the profile view.
[[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(kProfileLabel)]
performAction:grey_tap()];
id<GREYMatcher> accountProfileFooterMatcher =
grey_text(l10n_util::GetNSStringF(
IDS_IOS_SETTINGS_AUTOFILL_ACCOUNT_ADDRESS_FOOTER_TEXT,
u"[email protected]"));
// Switch on edit mode to make sure the page has opened.
[[EarlGrey selectElementWithMatcher:NavigationBarEditButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:accountProfileFooterMatcher]
assertWithMatcher:grey_sufficientlyVisible()];
[SigninEarlGrey signOut];
}
// Tests that a local incomplete profile can be migrated to account after
// editing the profile.
- (void)testIncompleteProfileMigrateToAccount {
if ([AutofillAppInterface isDynamicallyLoadFieldsOnInputEnabled]) {
EARL_GREY_TEST_SKIPPED(@"This test is not relevant when the fields "
@"are loaded dynamically on input.");
}
[SigninEarlGrey signinWithFakeIdentity:[FakeSystemIdentity fakeIdentity1]];
[AutofillAppInterface saveExampleProfile];
[self
openEditProfile:
[NSString
stringWithFormat:@"%@, %@", kProfileLabel,
l10n_util::GetNSString(
IDS_IOS_LOCAL_ADDRESS_ACCESSIBILITY_LABEL)]];
// Switch on edit mode.
[[EarlGrey selectElementWithMatcher:NavigationBarEditButton()]
performAction:grey_tap()];
// Change text of city to empty.
[[EarlGrey
selectElementWithMatcher:chrome_test_util::TextFieldForCellWithLabelId(
IDS_IOS_AUTOFILL_CITY)]
performAction:grey_replaceText(@"")];
// Save the profile.
[[EarlGrey selectElementWithMatcher:NavigationBarDoneButton()]
performAction:grey_tap()];
if ([ChromeEarlGrey isIPadIdiom]) {
// Scroll to the bottom for ipad.
[self scrollDownWithMatcher:grey_accessibilityID(
kAutofillProfileEditTableViewId)];
}
[[EarlGrey selectElementWithMatcher:MigrateToAccountButton()]
performAction:grey_tap()];
// Change text of city to empty.
[[EarlGrey
selectElementWithMatcher:chrome_test_util::TextFieldForCellWithLabelId(
IDS_IOS_AUTOFILL_CITY)]
performAction:grey_replaceText(@"New York")];
// Save the profile.
[[EarlGrey selectElementWithMatcher:NavigationBarDoneButton()]
performAction:grey_tap()];
// Wait for the snackbar to appear.
id<GREYMatcher> snackbar_matcher =
grey_accessibilityID(@"MDCSnackbarMessageTitleAutomationIdentifier");
ConditionBlock wait_for_appearance = ^{
NSError* error = nil;
[[EarlGrey selectElementWithMatcher:snackbar_matcher]
assertWithMatcher:grey_notNil()
error:&error];
return error == nil;
};
GREYAssert(base::test::ios::WaitUntilConditionOrTimeout(
kSnackbarAppearanceTimeout, wait_for_appearance),
@"Snackbar did not appear.");
// Wait for the snackbar to disappear.
ConditionBlock wait_for_disappearance = ^{
NSError* error = nil;
[[EarlGrey selectElementWithMatcher:snackbar_matcher]
assertWithMatcher:grey_nil()
error:&error];
return error == nil;
};
GREYAssert(base::test::ios::WaitUntilConditionOrTimeout(
kSnackbarDisappearanceTimeout, wait_for_disappearance),
@"Snackbar did not disappear.");
// Go back to the list view page.
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(0)]
performAction:grey_tap()];
// Open the profile view.
[[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(kProfileLabel)]
performAction:grey_tap()];
id<GREYMatcher> accountProfileFooterMatcher =
grey_text(l10n_util::GetNSStringF(
IDS_IOS_SETTINGS_AUTOFILL_ACCOUNT_ADDRESS_FOOTER_TEXT,
u"[email protected]"));
// Switch on edit mode to make sure the page has opened.
[[EarlGrey selectElementWithMatcher:NavigationBarEditButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:accountProfileFooterMatcher]
assertWithMatcher:grey_sufficientlyVisible()];
[SigninEarlGrey signOut];
}
@end