| // Copyright 2023 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/strings/escape.h" |
| #import "base/strings/stringprintf.h" |
| #import "base/strings/sys_string_conversions.h" |
| #import "components/autofill/core/common/autofill_features.h" |
| #import "components/feature_engagement/public/feature_constants.h" |
| #import "components/plus_addresses/core/browser/grit/plus_addresses_strings.h" |
| #import "components/plus_addresses/core/browser/metrics/plus_address_metrics.h" |
| #import "components/plus_addresses/core/browser/plus_address_test_utils.h" |
| #import "components/plus_addresses/core/common/features.h" |
| #import "components/strings/grit/components_strings.h" |
| #import "ios/chrome/browser/authentication/test/signin_earl_grey.h" |
| #import "ios/chrome/browser/authentication/test/signin_earl_grey_ui_test_util.h" |
| #import "ios/chrome/browser/metrics/model/metrics_app_interface.h" |
| #import "ios/chrome/browser/plus_addresses/ui/plus_address_app_interface.h" |
| #import "ios/chrome/browser/plus_addresses/ui/plus_address_bottom_sheet_constants.h" |
| #import "ios/chrome/browser/settings/ui_bundled/settings_table_view_controller_constants.h" |
| #import "ios/chrome/browser/signin/model/fake_system_identity.h" |
| #import "ios/chrome/common/string_util.h" |
| #import "ios/chrome/test/earl_grey/chrome_actions.h" |
| #import "ios/chrome/test/earl_grey/chrome_actions_app_interface.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/web_http_server_chrome_test_case.h" |
| #import "ios/chrome/test/scoped_eg_synchronization_disabler.h" |
| #import "ios/testing/earl_grey/app_launch_manager.h" |
| #import "ios/testing/earl_grey/earl_grey_test.h" |
| #import "ios/testing/earl_grey/matchers.h" |
| #import "net/test/embedded_test_server/default_handlers.h" |
| #import "net/test/embedded_test_server/request_handler_util.h" |
| #import "ui/base/l10n/l10n_util_mac.h" |
| |
| namespace { |
| |
| constexpr char kEmailFormUrl[] = "/email_signup_form.html"; |
| constexpr char kEmailFieldId[] = "email"; |
| |
| // Assert that a given plus address modal event of type `event_type` occurred |
| // `count` times. |
| void ExpectModalHistogram( |
| plus_addresses::metrics::PlusAddressModalEvent event_type, |
| int count) { |
| NSError* error = |
| [MetricsAppInterface expectCount:count |
| forBucket:static_cast<int>(event_type) |
| forHistogram:@"PlusAddresses.Modal.Events"]; |
| chrome_test_util::GREYAssertErrorNil(error); |
| } |
| |
| // Assert that the bottom sheet shown duration metrics is recorded. |
| // Actual duration is not assessed to avoid unnecessary clock mocking. |
| void ExpectModalTimeSample( |
| plus_addresses::metrics::PlusAddressModalCompletionStatus status, |
| int count) { |
| NSString* modalStatus = [NSString |
| stringWithUTF8String:plus_addresses::metrics:: |
| PlusAddressModalCompletionStatusToString(status) |
| .c_str()]; |
| NSString* name = [NSString |
| stringWithFormat:@"PlusAddresses.Modal.%@.ShownDuration", modalStatus]; |
| |
| NSError* error = [MetricsAppInterface expectTotalCount:count |
| forHistogram:name]; |
| chrome_test_util::GREYAssertErrorNil(error); |
| } |
| |
| } // namespace |
| |
| // Test suite that tests plus addresses functionality. |
| @interface PlusAddressesTestCase : WebHttpServerChromeTestCase |
| @end |
| |
| @implementation PlusAddressesTestCase { |
| FakeSystemIdentity* _fakeIdentity; |
| } |
| |
| - (void)setUp { |
| [super setUp]; |
| GREYAssertTrue(self.testServer->Start(), @"Server did not start."); |
| |
| chrome_test_util::GREYAssertErrorNil( |
| [MetricsAppInterface setupHistogramTester]); |
| |
| // Ensure a fake identity is available, as this is required by the |
| // plus_addresses feature. |
| _fakeIdentity = [FakeSystemIdentity fakeIdentity1]; |
| [SigninEarlGrey signinWithFakeIdentity:_fakeIdentity]; |
| |
| // To prevent any flakiness. |
| [PlusAddressAppInterface clearState]; |
| [PlusAddressAppInterface setUserHasAcceptedNotice]; |
| [PlusAddressAppInterface setPlusAddressFillingEnabled:YES]; |
| |
| [self loadPlusAddressEligiblePage]; |
| } |
| |
| - (void)tearDownHelper { |
| [super tearDownHelper]; |
| chrome_test_util::GREYAssertErrorNil( |
| [MetricsAppInterface releaseHistogramTester]); |
| } |
| |
| - (AppLaunchConfiguration)appConfigurationForTestCase { |
| AppLaunchConfiguration config; |
| |
| std::string fakeLocalUrl = |
| base::EscapeQueryParamValue("chrome://version", /*use_plus=*/false); |
| config.features_enabled_and_params.push_back( |
| {plus_addresses::features::kPlusAddressesEnabled, |
| {{ |
| {"server-url", {fakeLocalUrl}}, |
| {"manage-url", {fakeLocalUrl}}, |
| }}}); |
| |
| if ([self isRunningTest:@selector(testCreatePlusAddressIPH)]) { |
| config.iph_feature_enabled = |
| feature_engagement::kIPHPlusAddressCreateSuggestionFeature.name; |
| } |
| |
| config.features_disabled.push_back( |
| autofill::features::test::kAutofillServerCommunication); |
| |
| return config; |
| } |
| |
| #pragma mark - Helper methods |
| |
| // Loads simple page on localhost, ensuring that it is eligible for the |
| // plus_addresses feature. |
| - (void)loadPlusAddressEligiblePage { |
| [ChromeEarlGrey loadURL:self.testServer->GetURL(kEmailFormUrl)]; |
| [ChromeEarlGrey waitForWebStateContainingText:"Signup form"]; |
| } |
| |
| // Taps on the create plus address suggestion to open the bottom sheet. |
| - (void)openCreatePlusAddressBottomSheet { |
| // So that, create is offered. |
| [PlusAddressAppInterface setShouldOfferPlusAddressCreation:YES]; |
| |
| // Tap an element that is eligible for plus_address autofilling. |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:chrome_test_util::TapWebElementWithId(kEmailFieldId)]; |
| |
| NSString* suggestionLabel = |
| l10n_util::GetNSString(IDS_PLUS_ADDRESS_CREATE_SUGGESTION_MAIN_TEXT); |
| NSString* suggestionSubLabel = |
| l10n_util::GetNSString(IDS_PLUS_ADDRESS_CREATE_SUGGESTION_SECONDARY_TEXT); |
| id<GREYMatcher> userChip = grey_accessibilityLabel([NSString |
| stringWithFormat:@"%@, %@", suggestionLabel, suggestionSubLabel]); |
| |
| // Ensure the plus_address suggestion appears. |
| [ChromeEarlGrey waitForUIElementToAppearWithMatcher:userChip]; |
| |
| // Tapping it will trigger the UI. |
| [[EarlGrey selectElementWithMatcher:userChip] performAction:grey_tap()]; |
| } |
| |
| // Returns a matcher for the email description. |
| id<GREYMatcher> GetMatcherForEmailDescription(NSString* email) { |
| NSString* message = |
| l10n_util::GetNSStringF(IDS_PLUS_ADDRESS_BOTTOMSHEET_DESCRIPTION_IOS, |
| base::SysNSStringToUTF16(email)); |
| return grey_allOf( |
| // The link is within |
| // kPlusAddressSheetDescriptionAccessibilityIdentifier. |
| grey_text(message), |
| grey_accessibilityID(kPlusAddressSheetDescriptionAccessibilityIdentifier), |
| nil); |
| } |
| |
| // Returns a matcher for the plus address field. |
| id<GREYMatcher> GetMatcherForPlusAddressLabel(NSString* labelText) { |
| return grey_allOf( |
| // The link is within |
| // kPlusAddressLabelAccessibilityIdentifier. |
| grey_accessibilityID(kPlusAddressLabelAccessibilityIdentifier), |
| grey_text(labelText), |
| grey_accessibilityTrait(UIAccessibilityTraitStaticText), nil); |
| } |
| |
| // Verifies that field with the html `id` has been filled with `value`. |
| - (void)verifyFieldWithIdHasBeenFilled:(std::string)id value:(NSString*)value { |
| NSString* condition = [NSString |
| stringWithFormat:@"window.document.getElementById('%s').value === '%@'", |
| id.c_str(), value]; |
| [ChromeEarlGrey waitForJavaScriptCondition:condition]; |
| } |
| |
| #pragma mark - Tests |
| |
| // TODO(crbug.com/394490489): Test is flaky. |
| // Tests showing up a bottom sheet to confirm a plus address. Once, the plus |
| // address is confirmed checks if it is filled in the file. |
| - (void)DISABLED_testConfirmPlusAddressUsingBottomSheet { |
| [self openCreatePlusAddressBottomSheet]; |
| |
| id<GREYMatcher> plusAddressLabelMatcher = GetMatcherForPlusAddressLabel( |
| base::SysUTF8ToNSString(plus_addresses::test::kFakePlusAddress)); |
| [ChromeEarlGrey waitForUIElementToAppearWithMatcher:plusAddressLabelMatcher]; |
| |
| id<GREYMatcher> confirmButton = |
| chrome_test_util::ButtonWithAccessibilityLabelId( |
| IDS_PLUS_ADDRESS_BOTTOMSHEET_OK_TEXT_IOS); |
| |
| // Click the okay button, confirming the plus address. |
| [[EarlGrey selectElementWithMatcher:confirmButton] performAction:grey_tap()]; |
| |
| [self verifyFieldWithIdHasBeenFilled:kEmailFieldId |
| value:base::SysUTF8ToNSString( |
| plus_addresses::test:: |
| kFakePlusAddress)]; |
| |
| ExpectModalHistogram( |
| plus_addresses::metrics::PlusAddressModalEvent::kModalShown, 1); |
| ExpectModalHistogram( |
| plus_addresses::metrics::PlusAddressModalEvent::kModalConfirmed, 1); |
| |
| ExpectModalTimeSample(plus_addresses::metrics:: |
| PlusAddressModalCompletionStatus::kModalConfirmed, |
| 1); |
| } |
| |
| - (void)DISABLED_testSwipeToDismiss { |
| // TODO(crbug.com/40949085): Test fails on iPad. |
| if ([ChromeEarlGrey isIPadIdiom]) { |
| EARL_GREY_TEST_DISABLED(@"Fails on iPad."); |
| } |
| |
| [self openCreatePlusAddressBottomSheet]; |
| |
| id<GREYMatcher> emailDescription = |
| GetMatcherForEmailDescription(_fakeIdentity.userEmail); |
| // The primary email address should be shown. |
| [ChromeEarlGrey waitForUIElementToAppearWithMatcher:emailDescription]; |
| |
| // Then, swipe down on the bottom sheet. |
| [[EarlGrey selectElementWithMatcher:emailDescription] |
| performAction:grey_swipeSlowInDirection(kGREYDirectionDown)]; |
| // It should no longer be shown. |
| [[EarlGrey selectElementWithMatcher:emailDescription] |
| assertWithMatcher:grey_notVisible()]; |
| |
| ExpectModalHistogram( |
| plus_addresses::metrics::PlusAddressModalEvent::kModalShown, 1); |
| // TODO(crbug.com/40276862): separate out the cancel click from other exit |
| // patterns, on all platforms. |
| ExpectModalHistogram( |
| plus_addresses::metrics::PlusAddressModalEvent::kModalCanceled, 1); |
| ExpectModalTimeSample( |
| plus_addresses::metrics::PlusAddressModalCompletionStatus:: |
| kReservePlusAddressError, |
| 1); |
| } |
| |
| // A test to check the refresh plus address functionality. |
| - (void)testRefresh { |
| [self openCreatePlusAddressBottomSheet]; |
| |
| id<GREYMatcher> plusAddressLabelMatcher = GetMatcherForPlusAddressLabel( |
| base::SysUTF8ToNSString(plus_addresses::test::kFakePlusAddress)); |
| [ChromeEarlGrey waitForUIElementToAppearWithMatcher:plusAddressLabelMatcher]; |
| |
| id<GREYMatcher> refreshButton = grey_allOf( |
| grey_accessibilityID(kPlusAddressRefreshButtonAccessibilityIdentifier), |
| grey_accessibilityTrait(UIAccessibilityTraitButton), nil); |
| |
| // Tap on the refresh button |
| [[EarlGrey selectElementWithMatcher:refreshButton] performAction:grey_tap()]; |
| |
| id<GREYMatcher> refreshed_plus_address = GetMatcherForPlusAddressLabel( |
| base::SysUTF8ToNSString(plus_addresses::test::kFakePlusAddressRefresh)); |
| // Test that the plus address has been refreshed. |
| [ChromeEarlGrey waitForUIElementToAppearWithMatcher:refreshed_plus_address]; |
| |
| // Ensure the cancel button is shown. |
| id<GREYMatcher> cancelButton = |
| chrome_test_util::ButtonWithAccessibilityLabelId( |
| IDS_PLUS_ADDRESS_MODAL_CANCEL_TEXT); |
| |
| // Click the cancel button, dismissing the bottom sheet. |
| [[EarlGrey selectElementWithMatcher:cancelButton] performAction:grey_tap()]; |
| } |
| |
| // A test to check the plus address create suggestion IPH feature. |
| - (void)testCreatePlusAddressIPH { |
| [PlusAddressAppInterface setShouldOfferPlusAddressCreation:YES]; |
| |
| // Synchronization off because the tap on element 'kEmailFieldId' completes |
| // only after the IPH has already disappeared. This leads to a subsequent |
| // error when trying to verify that the IPH appeared. |
| ScopedSynchronizationDisabler disabler; |
| |
| // Tap an element that is eligible for plus_address autofilling. |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:chrome_test_util::TapWebElementWithId(kEmailFieldId)]; |
| id<GREYMatcher> iph_chip = grey_text( |
| l10n_util::GetNSString(IDS_PLUS_ADDRESS_CREATE_SUGGESTION_IPH_IOS)); |
| |
| // Ensure the plus_address suggestion IPH appears. |
| [ChromeEarlGrey waitForUIElementToAppearWithMatcher:iph_chip]; |
| } |
| |
| // Tests that an error alert is shown if the plus address quota has been reached |
| // on confirming plus address. |
| - (void)testQuotaErrorAlertOnConfirm { |
| [self openCreatePlusAddressBottomSheet]; |
| |
| // Set up after the reserve has been called so that it fails on confirm. |
| [PlusAddressAppInterface setShouldReturnQuotaError:YES]; |
| |
| id<GREYMatcher> plusAddressLabelMatcher = GetMatcherForPlusAddressLabel( |
| base::SysUTF8ToNSString(plus_addresses::test::kFakePlusAddress)); |
| [ChromeEarlGrey waitForUIElementToAppearWithMatcher:plusAddressLabelMatcher]; |
| |
| id<GREYMatcher> confirmButton = |
| chrome_test_util::ButtonWithAccessibilityLabelId( |
| IDS_PLUS_ADDRESS_BOTTOMSHEET_OK_TEXT_IOS); |
| |
| // Click the okay button, confirming the plus address. |
| [[EarlGrey selectElementWithMatcher:confirmButton] performAction:grey_tap()]; |
| |
| id<GREYMatcher> error_alert = grey_text( |
| l10n_util::GetNSString(IDS_PLUS_ADDRESS_QUOTA_ERROR_ALERT_MESSAGE_IOS)); |
| |
| // Ensure the error alert is shown. |
| [ChromeEarlGrey waitForUIElementToAppearWithMatcher:error_alert]; |
| |
| [[EarlGrey selectElementWithMatcher: |
| chrome_test_util::AlertItemWithAccessibilityLabelId(IDS_OK)] |
| performAction:grey_tap()]; |
| } |
| |
| // Tests that the alert is shown and filled when an affiliated site contains the |
| // plus address during the creation. |
| // |
| // TODO(crbug.com/386193395): This test is flaky. |
| - (void)FLAKY_testAffiliationError { |
| [PlusAddressAppInterface setShouldReturnAffiliatedPlusProfileOnConfirm:YES]; |
| [self openCreatePlusAddressBottomSheet]; |
| |
| id<GREYMatcher> plusAddressLabelMatcher = GetMatcherForPlusAddressLabel( |
| base::SysUTF8ToNSString(plus_addresses::test::kFakePlusAddress)); |
| [ChromeEarlGrey waitForUIElementToAppearWithMatcher:plusAddressLabelMatcher]; |
| |
| id<GREYMatcher> confirmButton = |
| chrome_test_util::ButtonWithAccessibilityLabelId( |
| IDS_PLUS_ADDRESS_BOTTOMSHEET_OK_TEXT_IOS); |
| |
| // Click the okay button, confirming the plus address. |
| [[EarlGrey selectElementWithMatcher:confirmButton] performAction:grey_tap()]; |
| |
| NSString* message = l10n_util::GetNSStringF( |
| IDS_PLUS_ADDRESS_AFFILIATION_ERROR_ALERT_MESSAGE_IOS, |
| plus_addresses::test::kAffiliatedFacetWithoutSchemeU16, |
| plus_addresses::test::kFakeAffiliatedPlusAddressU16); |
| |
| // Ensure the error alert is shown. |
| [ChromeEarlGrey waitForUIElementToAppearWithMatcher:grey_text(message)]; |
| |
| // Click on "Use existing" button. |
| id<GREYMatcher> useExitingButton = |
| chrome_test_util::ButtonWithAccessibilityLabelId( |
| IDS_PLUS_ADDRESS_AFFILIATION_ERROR_PRIMARY_BUTTON_IOS); |
| [[EarlGrey selectElementWithMatcher:useExitingButton] |
| performAction:grey_tap()]; |
| |
| // Verify that the affiliated address has been filled. |
| [self verifyFieldWithIdHasBeenFilled:kEmailFieldId |
| value:base::SysUTF8ToNSString( |
| plus_addresses::test:: |
| kFakeAffiliatedPlusAddress)]; |
| } |
| |
| // Tests that a generic alert is shown when the plus address is failed to |
| // confirm. |
| - (void)testGenericAlertOnConfirm { |
| [self openCreatePlusAddressBottomSheet]; |
| |
| id<GREYMatcher> plusAddressLabelMatcher = GetMatcherForPlusAddressLabel( |
| base::SysUTF8ToNSString(plus_addresses::test::kFakePlusAddress)); |
| [ChromeEarlGrey waitForUIElementToAppearWithMatcher:plusAddressLabelMatcher]; |
| |
| // Set up after the reserve has been called so that it fails on confirm. |
| [PlusAddressAppInterface setShouldFailToConfirm:YES]; |
| |
| id<GREYMatcher> confirmButton = |
| chrome_test_util::ButtonWithAccessibilityLabelId( |
| IDS_PLUS_ADDRESS_BOTTOMSHEET_OK_TEXT_IOS); |
| |
| // Click the okay button, confirming the plus address. |
| [[EarlGrey selectElementWithMatcher:confirmButton] performAction:grey_tap()]; |
| |
| id<GREYMatcher> error_alert = grey_text( |
| l10n_util::GetNSString(IDS_PLUS_ADDRESS_GENERIC_ERROR_ALERT_MESSAGE_IOS)); |
| |
| // Ensure the error alert is shown. |
| [ChromeEarlGrey waitForUIElementToAppearWithMatcher:error_alert]; |
| |
| // Ensure that "Try again" is successful. |
| [PlusAddressAppInterface setShouldFailToConfirm:NO]; |
| |
| id<GREYMatcher> tryAgainButton = grey_text(l10n_util::GetNSString( |
| IDS_PLUS_ADDRESS_ERROR_TRY_AGAIN_PRIMARY_BUTTON_IOS)); |
| [[EarlGrey selectElementWithMatcher:tryAgainButton] performAction:grey_tap()]; |
| |
| [self verifyFieldWithIdHasBeenFilled:kEmailFieldId |
| value:base::SysUTF8ToNSString( |
| plus_addresses::test:: |
| kFakePlusAddress)]; |
| } |
| |
| // Tests that a timeout alert is shown when the plus address is failed to |
| // confirm. |
| - (void)testTimeOutAlertOnConfirm { |
| [self openCreatePlusAddressBottomSheet]; |
| |
| id<GREYMatcher> plusAddressLabelMatcher = GetMatcherForPlusAddressLabel( |
| base::SysUTF8ToNSString(plus_addresses::test::kFakePlusAddress)); |
| [ChromeEarlGrey waitForUIElementToAppearWithMatcher:plusAddressLabelMatcher]; |
| |
| // Set up after the reserve has been called so that it fails on confirm. |
| [PlusAddressAppInterface setShouldReturnTimeoutError:YES]; |
| |
| id<GREYMatcher> confirmButton = |
| chrome_test_util::ButtonWithAccessibilityLabelId( |
| IDS_PLUS_ADDRESS_BOTTOMSHEET_OK_TEXT_IOS); |
| |
| // Click the okay button, confirming the plus address. |
| [[EarlGrey selectElementWithMatcher:confirmButton] performAction:grey_tap()]; |
| |
| id<GREYMatcher> error_alert = grey_text( |
| l10n_util::GetNSString(IDS_PLUS_ADDRESS_TIMEOUT_ERROR_ALERT_MESSAGE_IOS)); |
| |
| // Ensure the error alert is shown. |
| [ChromeEarlGrey waitForUIElementToAppearWithMatcher:error_alert]; |
| } |
| |
| // Tests that an error alert is shown if the plus address quota has been reached |
| // on reserving plus address. |
| - (void)testQuotaErrorAlertOnReserve { |
| [PlusAddressAppInterface setShouldReturnQuotaError:YES]; |
| |
| [self openCreatePlusAddressBottomSheet]; |
| |
| id<GREYMatcher> error_alert = grey_text( |
| l10n_util::GetNSString(IDS_PLUS_ADDRESS_QUOTA_ERROR_ALERT_MESSAGE_IOS)); |
| |
| // Ensure the error alert is shown. |
| [ChromeEarlGrey waitForUIElementToAppearWithMatcher:error_alert]; |
| |
| [[EarlGrey selectElementWithMatcher: |
| chrome_test_util::AlertItemWithAccessibilityLabelId(IDS_OK)] |
| performAction:grey_tap()]; |
| } |
| |
| // Tests that a timeout alert is shown when the plus address is failed to |
| // reserve. |
| - (void)testTimeoutErrorAlertOnReserve { |
| [PlusAddressAppInterface setShouldReturnTimeoutError:YES]; |
| |
| [self openCreatePlusAddressBottomSheet]; |
| |
| id<GREYMatcher> error_alert = grey_text( |
| l10n_util::GetNSString(IDS_PLUS_ADDRESS_TIMEOUT_ERROR_ALERT_MESSAGE_IOS)); |
| // Ensure the error alert is shown. |
| [ChromeEarlGrey waitForUIElementToAppearWithMatcher:error_alert]; |
| |
| // Click on "Try again". |
| id<GREYMatcher> tryAgainButton = grey_text(l10n_util::GetNSString( |
| IDS_PLUS_ADDRESS_ERROR_TRY_AGAIN_PRIMARY_BUTTON_IOS)); |
| [[EarlGrey selectElementWithMatcher:tryAgainButton] performAction:grey_tap()]; |
| |
| // The error alert is shown again. |
| [ChromeEarlGrey waitForUIElementToAppearWithMatcher:error_alert]; |
| |
| // Clear out the error state. |
| [PlusAddressAppInterface setShouldReturnTimeoutError:NO]; |
| |
| // "Try again" |
| [[EarlGrey selectElementWithMatcher:tryAgainButton] performAction:grey_tap()]; |
| |
| // Plus address sheet is opened and label is shown. |
| id<GREYMatcher> plusAddressLabelMatcher = GetMatcherForPlusAddressLabel( |
| base::SysUTF8ToNSString(plus_addresses::test::kFakePlusAddress)); |
| [ChromeEarlGrey waitForUIElementToAppearWithMatcher:plusAddressLabelMatcher]; |
| |
| id<GREYMatcher> confirmButton = |
| chrome_test_util::ButtonWithAccessibilityLabelId( |
| IDS_PLUS_ADDRESS_BOTTOMSHEET_OK_TEXT_IOS); |
| |
| // Click the okay button, confirming the plus address. |
| [[EarlGrey selectElementWithMatcher:confirmButton] performAction:grey_tap()]; |
| |
| [self verifyFieldWithIdHasBeenFilled:kEmailFieldId |
| value:base::SysUTF8ToNSString( |
| plus_addresses::test:: |
| kFakePlusAddress)]; |
| } |
| |
| // Tests that a generic alert is shown when the plus address is failed to |
| // reserve. |
| - (void)testGenericAlertOnReserve { |
| [PlusAddressAppInterface setShouldFailToReserve:YES]; |
| [self openCreatePlusAddressBottomSheet]; |
| |
| id<GREYMatcher> error_alert = grey_text( |
| l10n_util::GetNSString(IDS_PLUS_ADDRESS_GENERIC_ERROR_ALERT_MESSAGE_IOS)); |
| |
| // Ensure the error alert is shown. |
| [ChromeEarlGrey waitForUIElementToAppearWithMatcher:error_alert]; |
| } |
| |
| @end |