// 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 "base/ios/ios_util.h"
#import "base/strings/sys_string_conversions.h"
#import "base/test/ios/wait_util.h"
#import "components/autofill/core/browser/autofill_test_utils.h"
#import "components/autofill/core/common/autofill_payments_features.h"
#import "ios/chrome/browser/autofill/ui_bundled/autofill_app_interface.h"
#import "ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_app_interface.h"
#import "ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_constants.h"
#import "ios/chrome/browser/autofill/ui_bundled/manual_fill/manual_fill_matchers.h"
#import "ios/chrome/browser/metrics/model/metrics_app_interface.h"
#import "ios/chrome/browser/shared/public/features/features.h"
#import "ios/chrome/common/ui/elements/form_input_accessory_view.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/app_launch_configuration.h"
#import "ios/testing/earl_grey/earl_grey_test.h"
#import "ios/web/public/test/element_selector.h"
#import "net/test/embedded_test_server/embedded_test_server.h"
#import "ui/base/l10n/l10n_util.h"
#import "url/gurl.h"
using chrome_test_util::ButtonWithAccessibilityLabelId;
using chrome_test_util::CancelButton;
using chrome_test_util::NavigationBarCancelButton;
using chrome_test_util::NavigationBarDoneButton;
using chrome_test_util::SettingsCreditCardMatcher;
using chrome_test_util::StaticTextWithAccessibilityLabelId;
using chrome_test_util::TapWebElementWithId;
namespace {
const char kFormElementName[] = "CCName";
const char kFormElementCardNumber[] = "CCNo";
const char kFormElementCardExpirationMonth[] = "CCExpiresMonth";
const char kFormElementCardExpirationYear[] = "CCExpiresYear";
NSString* kLocalCardNumber = @"4111111111111111";
NSString* kLocalCardHolder = @"Test User";
// The local card's expiration month and year (only the last two digits) are set
// with next month and next year.
NSString* kLocalCardExpirationMonth =
base::SysUTF8ToNSString(autofill::test::NextMonth());
NSString* kLocalCardExpirationYear =
base::SysUTF8ToNSString(autofill::test::NextYear().substr(2, 2));
// Unicode characters used in card number:
// - 0x0020 - Space.
// - 0x2060 - WORD-JOINER (makes string undivisible).
constexpr char16_t separator[] = {0x2060, 0x0020, 0};
constexpr char16_t kMidlineEllipsis[] = {
0x2022, 0x2060, 0x2006, 0x2060, 0x2022, 0x2060, 0x2006, 0x2060, 0x2022,
0x2060, 0x2006, 0x2060, 0x2022, 0x2060, 0x2006, 0x2060, 0};
NSString* kObfuscatedNumberPrefix = base::SysUTF16ToNSString(
kMidlineEllipsis + std::u16string(separator) + kMidlineEllipsis +
std::u16string(separator) + kMidlineEllipsis + std::u16string(separator));
NSString* kLocalNumberObfuscated =
[NSString stringWithFormat:@"%@1111", kObfuscatedNumberPrefix];
NSString* kServerNumberObfuscated =
[NSString stringWithFormat:@"%@2109", kObfuscatedNumberPrefix];
NSString* kCvcObfuscated =
base::SysUTF16ToNSString(autofill::CreditCard::GetMidlineEllipsisDots(3));
const char kFormHTMLFile[] = "/credit_card.html";
// Matcher for the not secure website alert.
id<GREYMatcher> NotSecureWebsiteAlert() {
return StaticTextWithAccessibilityLabelId(
IDS_IOS_MANUAL_FALLBACK_NOT_SECURE_TITLE);
}
// Opens the payment method manual fill view and verifies that the card view
// controller is visible afterwards.
void OpenPaymentMethodManualFillView() {
id<GREYMatcher> button_to_tap;
if ([AutofillAppInterface isKeyboardAccessoryUpgradeEnabled]) {
button_to_tap = grey_accessibilityLabel(
l10n_util::GetNSString(IDS_IOS_AUTOFILL_ACCNAME_AUTOFILL_DATA));
} else {
button_to_tap = manual_fill::CreditCardIconMatcher();
[[EarlGrey
selectElementWithMatcher:manual_fill::FormSuggestionViewMatcher()]
performAction:grey_scrollToContentEdge(kGREYContentEdgeRight)];
}
// Tap the button that'll open the payment method manual fill view.
[[EarlGrey selectElementWithMatcher:button_to_tap] performAction:grey_tap()];
// Verify the card table view controller is visible.
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
assertWithMatcher:grey_sufficientlyVisible()];
}
// Matcher for the expanded credit card manual fill view button.
id<GREYMatcher> CreditCardManualFillViewButton() {
return grey_allOf(grey_accessibilityLabel(l10n_util::GetNSString(
IDS_IOS_AUTOFILL_CREDIT_CARD_AUTOFILL_DATA)),
grey_ancestor(grey_accessibilityID(
kFormInputAccessoryViewAccessibilityID)),
nil);
}
// Matcher for the credit card tab in the manual fill view.
id<GREYMatcher> CreditCardManualFillViewTab() {
return grey_allOf(
grey_accessibilityLabel(l10n_util::GetNSString(
IDS_IOS_EXPANDED_MANUAL_FILL_PAYMENT_TAB_ACCESSIBILITY_LABEL)),
grey_ancestor(
grey_accessibilityID(manual_fill::kExpandedManualFillHeaderViewID)),
nil);
}
// Matcher for the overflow menu button shown in the payment method cells.
id<GREYMatcher> OverflowMenuButton() {
return grey_allOf(
grey_accessibilityID(manual_fill::kExpandedManualFillOverflowMenuID),
grey_interactable(), nullptr);
}
// Matcher for the "Edit" action made available by the overflow menu button.
id<GREYMatcher> OverflowMenuEditAction() {
return grey_allOf(ButtonWithAccessibilityLabelId(IDS_IOS_EDIT_ACTION_TITLE),
grey_interactable(), nullptr);
}
// Matcher for the "Show Details" action made available by the overflow menu
// button.
id<GREYMatcher> OverflowMenuShowDetailsAction() {
return grey_allOf(
ButtonWithAccessibilityLabelId(IDS_IOS_SHOW_DETAILS_ACTION_TITLE),
grey_interactable(), nullptr);
}
// Matcher for the "Autofill Form" button shown in the payment method cells.
id<GREYMatcher> AutofillFormButton() {
return grey_allOf(grey_accessibilityID(
manual_fill::kExpandedManualFillAutofillFormButtonID),
grey_interactable(), nullptr);
}
// Matcher for the GPay icon shown in the server card cells.
id<GREYMatcher> GPayIcon(NSString* network_and_last_four_digits) {
return grey_accessibilityID([NSString
stringWithFormat:@"%@ %@", manual_fill::kPaymentManualFillGPayLogoID,
network_and_last_four_digits]);
}
// Matcher for the card number chip button.
id<GREYMatcher> LocalCardNumberChipButton() {
NSString* accessibility_label;
if ([AutofillAppInterface isKeyboardAccessoryUpgradeEnabled]) {
NSString* last_four_digits =
[kLocalCardNumber substringFromIndex:kLocalCardNumber.length - 4];
NSString* last_four_digits_split = [NSString
stringWithFormat:@"%C %C %C %C", [last_four_digits characterAtIndex:0],
[last_four_digits characterAtIndex:1],
[last_four_digits characterAtIndex:2],
[last_four_digits characterAtIndex:3]];
accessibility_label = l10n_util::GetNSStringF(
IDS_IOS_MANUAL_FALLBACK_CARD_NUMBER_CHIP_ACCESSIBILITY_LABEL,
base::SysNSStringToUTF16(last_four_digits_split));
} else {
accessibility_label = kLocalNumberObfuscated;
}
return grey_allOf(
chrome_test_util::ButtonWithAccessibilityLabel(accessibility_label),
grey_interactable(), nullptr);
}
// Matcher for the expiration month chip button.
id<GREYMatcher> ExpirationMonthChipButton(std::u16string title) {
NSString* accessibility_label =
[AutofillAppInterface isKeyboardAccessoryUpgradeEnabled]
? l10n_util::GetNSStringF(
IDS_IOS_MANUAL_FALLBACK_EXPIRATION_MONTH_CHIP_ACCESSIBILITY_LABEL,
title)
: base::SysUTF16ToNSString(title);
return grey_allOf(
chrome_test_util::ButtonWithAccessibilityLabel(accessibility_label),
grey_interactable(), nullptr);
}
// Matcher for the expiration month chip button.
id<GREYMatcher> ExpirationYearChipButton(std::u16string title) {
NSString* accessibility_label =
[AutofillAppInterface isKeyboardAccessoryUpgradeEnabled]
? l10n_util::GetNSStringF(
IDS_IOS_MANUAL_FALLBACK_EXPIRATION_YEAR_CHIP_ACCESSIBILITY_LABEL,
title)
: base::SysUTF16ToNSString(title);
return grey_allOf(
chrome_test_util::ButtonWithAccessibilityLabel(accessibility_label),
grey_interactable(), nullptr);
}
// Matcher for the cardholder month chip button.
id<GREYMatcher> CardholderChipButton(std::u16string title) {
NSString* accessibility_label =
[AutofillAppInterface isKeyboardAccessoryUpgradeEnabled]
? l10n_util::GetNSStringF(
IDS_IOS_MANUAL_FALLBACK_CARDHOLDER_CHIP_ACCESSIBILITY_LABEL,
title)
: base::SysUTF16ToNSString(title);
return grey_allOf(
chrome_test_util::ButtonWithAccessibilityLabel(accessibility_label),
grey_interactable(), nullptr);
}
// Matcher for the cvc chip button.
id<GREYMatcher> CvcChipButton() {
NSString* accessibility_label =
[AutofillAppInterface isKeyboardAccessoryUpgradeEnabled]
? l10n_util::GetNSString(
IDS_IOS_MANUAL_FALLBACK_CVC_CHIP_ACCESSIBILITY_LABEL)
: kCvcObfuscated;
return grey_allOf(
chrome_test_util::ButtonWithAccessibilityLabel(accessibility_label),
grey_interactable(), nullptr);
}
// Verifies that the number of accepted suggestions recorded for the given
// `suggestion_index` is as expected.
void CheckAutofillSuggestionAcceptedIndexMetricsCount(
NSInteger suggestion_index) {
GREYAssertNil(
[MetricsAppInterface
expectUniqueSampleWithCount:1
forBucket:suggestion_index
forHistogram:
@"Autofill.SuggestionAcceptedIndex.CreditCard"],
@"Unexpected histogram count for accepted card suggestion index.");
GREYAssertNil(
[MetricsAppInterface
expectUniqueSampleWithCount:1
forBucket:suggestion_index
forHistogram:@"Autofill.UserAcceptedSuggestionAtIndex."
@"CreditCard.ManualFallback"],
@"Unexpected histogram count for manual fallback accepted card "
@"suggestion index.");
}
// Checks that the chip buttons of the local card are all visible.
void CheckChipButtonsOfLocalCard() {
autofill::CreditCard card = autofill::test::GetCreditCard();
std::string locale = l10n_util::GetLocaleOverride();
[[EarlGrey selectElementWithMatcher:LocalCardNumberChipButton()]
assertWithMatcher:grey_sufficientlyVisible()];
[[EarlGrey
selectElementWithMatcher:ExpirationMonthChipButton(card.GetInfo(
autofill::CREDIT_CARD_EXP_MONTH, locale))]
assertWithMatcher:grey_sufficientlyVisible()];
[[EarlGrey
selectElementWithMatcher:ExpirationYearChipButton(card.GetInfo(
autofill::CREDIT_CARD_EXP_2_DIGIT_YEAR,
locale))]
assertWithMatcher:grey_sufficientlyVisible()];
[[EarlGrey
selectElementWithMatcher:CardholderChipButton(card.GetInfo(
autofill::CREDIT_CARD_NAME_FULL, locale))]
assertWithMatcher:grey_sufficientlyVisible()];
}
// Opens the payment method manual fill view when there are no saved payment
// methods and verifies that the card view controller is visible afterwards.
// Only useful when the `kIOSKeyboardAccessoryUpgrade` feature is enabled.
void OpenPaymentMethodManualFillViewWithNoSavedPaymentMethods() {
// Tap the button to open the expanded manual fill view.
[[EarlGrey selectElementWithMatcher:CreditCardManualFillViewButton()]
performAction:grey_tap()];
// Tap the payment method tab from the segmented control.
[[EarlGrey selectElementWithMatcher:CreditCardManualFillViewTab()]
performAction:grey_tap()];
// Verify the card table view controller is visible.
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
assertWithMatcher:grey_sufficientlyVisible()];
}
// Dismisses the payment bottom sheet by tapping the "Use Keyboard" button.
void DismissPaymentBottomSheet() {
id<GREYMatcher> useKeyboardButton =
chrome_test_util::ButtonWithAccessibilityLabelId(
IDS_IOS_PAYMENT_BOTTOM_SHEET_USE_KEYBOARD);
[[EarlGrey selectElementWithMatcher:useKeyboardButton]
performAction:grey_tap()];
}
} // namespace
// Integration Tests for Manual Fallback credit cards View Controller.
@interface CreditCardViewControllerTestCase : ChromeTestCase
@end
@implementation CreditCardViewControllerTestCase
- (BOOL)shouldEnableKeyboardAccessoryUpgradeFeature {
return YES;
}
- (void)setUp {
[super setUp];
GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
const GURL URL = self.testServer->GetURL(kFormHTMLFile);
[self loadURL];
[AutofillAppInterface clearCreditCardStore];
[AutofillAppInterface clearAllServerDataForTesting];
[AutofillAppInterface considerCreditCardFormSecureForTesting];
// Set up histogram tester.
GREYAssertNil([MetricsAppInterface setupHistogramTester],
@"Cannot setup histogram tester.");
[MetricsAppInterface overrideMetricsAndCrashReportingForTesting];
}
- (void)tearDown {
[AutofillAppInterface clearCreditCardStore];
[AutofillAppInterface clearAllServerDataForTesting];
[EarlGrey rotateDeviceToOrientation:UIDeviceOrientationPortrait error:nil];
// Clean up histogram tester.
[MetricsAppInterface stopOverridingMetricsAndCrashReportingForTesting];
GREYAssertNil([MetricsAppInterface releaseHistogramTester],
@"Failed to release histogram tester.");
[super tearDown];
}
- (AppLaunchConfiguration)appConfigurationForTestCase {
AppLaunchConfiguration config;
config.features_enabled.push_back(
autofill::features::kAutofillEnableVirtualCards);
if ([self shouldEnableKeyboardAccessoryUpgradeFeature]) {
config.features_enabled.push_back(kIOSKeyboardAccessoryUpgrade);
} else {
config.features_disabled.push_back(kIOSKeyboardAccessoryUpgrade);
}
if ([self isRunningTest:@selector
(testCardChipButtonsAreAllVisibleWithVirtualCardsDisabled)]) {
config.features_disabled.push_back(
autofill::features::kAutofillEnableVirtualCards);
}
return config;
}
#pragma mark - Tests
// Tests that the credit card view button is absent when there are no cards
// available.
- (void)testCreditCardsButtonAbsentWhenNoCreditCardsAvailable {
if ([AutofillAppInterface isKeyboardAccessoryUpgradeEnabled]) {
EARL_GREY_TEST_SKIPPED(@"This test is not relevant when the Keyboard "
@"Accessory Upgrade feature is enabled.");
}
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
// Verify there's no credit card icon.
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardIconMatcher()]
assertWithMatcher:grey_notVisible()];
}
// Tests that the credit card view controller appears on screen.
- (void)testCreditCardsViewControllerIsPresented {
[AutofillAppInterface saveLocalCreditCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
// Open the payment method manual fill view and verify that the card table
// view controller is visible.
OpenPaymentMethodManualFillView();
// Verify that the number of visible suggestions in the keyboard accessory was
// correctly recorded.
NSString* histogram =
[AutofillAppInterface isKeyboardAccessoryUpgradeEnabled]
? @"ManualFallback.VisibleSuggestions.ExpandIcon.OpenPaymentMethods"
: @"ManualFallback.VisibleSuggestions.OpenCreditCards";
GREYAssertNil(
[MetricsAppInterface expectUniqueSampleWithCount:1
forBucket:1
forHistogram:histogram],
@"Unexpected histogram error for number of visible suggestions.");
}
// Tests that the saved card chip buttons are all visible in the card
// table view controller, and that they have the right accessibility label.
- (void)testCardChipButtonsAreAllVisible {
[AutofillAppInterface saveLocalCreditCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
CheckChipButtonsOfLocalCard();
}
// Tests that the saved card chip buttons are all visible in the card
// table view controller, and that they have the right accessibility label when
// the Virtual Cards feature is disabled. TODO(crbug.com/335736927): Delete this
// test once the Virtual Cards feature is launched.
- (void)testCardChipButtonsAreAllVisibleWithVirtualCardsDisabled {
[AutofillAppInterface saveLocalCreditCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
CheckChipButtonsOfLocalCard();
}
// Tests that the the "no payment methods found" message is visible when no
// payment method suggestions are available.
- (void)testNoPaymentMethodsFoundMessageIsVisibleWhenNoSuggestions {
if (![AutofillAppInterface isKeyboardAccessoryUpgradeEnabled]) {
EARL_GREY_TEST_SKIPPED(@"This test is not relevant when the Keyboard "
@"Accessory Upgrade feature is disabled.");
}
[AutofillAppInterface clearCreditCardStore];
// Bring up the keyboard.
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillViewWithNoSavedPaymentMethods();
// Assert that the "no payment methods found" message is visible.
id<GREYMatcher> noPaymentMethodsFoundMessage = grey_accessibilityLabel(
l10n_util::GetNSString(IDS_IOS_MANUAL_FALLBACK_NO_PAYMENT_METHODS));
[[EarlGrey selectElementWithMatcher:noPaymentMethodsFoundMessage]
assertWithMatcher:grey_sufficientlyVisible()];
// Verify that the number of visible suggestions in the keyboard accessory was
// correctly recorded.
GREYAssertNil(
[MetricsAppInterface
expectUniqueSampleWithCount:1
forBucket:0
forHistogram:@"ManualFallback.VisibleSuggestions."
@"OpenCreditCards"],
@"Unexpected histogram error for number of visible suggestions.");
}
// Tests that the cards view controller contains the "Manage Payment
// Methods..." action.
- (void)testCreditCardsViewControllerContainsManagePaymentMethodsAction {
[AutofillAppInterface saveLocalCreditCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
// Try to scroll.
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)];
// Verify the payment methods controller contains the "Manage Payment
// Methods..." action.
[[EarlGrey
selectElementWithMatcher:manual_fill::ManagePaymentMethodsMatcher()]
assertWithMatcher:grey_interactable()];
}
// Tests that the manual fallback view shows both a virtual card and the
// original card for a credit card with a virtual card status of enrolled.
- (void)testManualFallbackShowsVirtualCards {
// Create & save credit card enrolled in virtual card program.
[AutofillAppInterface saveMaskedCreditCardEnrolledInVirtualCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
if (![AutofillAppInterface isKeyboardAccessoryUpgradeEnabled]) {
// Scroll to the right to reach the credit card icon.
[[EarlGrey
selectElementWithMatcher:manual_fill::FormSuggestionViewMatcher()]
performAction:grey_scrollToContentEdge(kGREYContentEdgeRight)];
}
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
// Refresh the view by scrolling to the top as the virtual card and regular
// card cells are otherwise superimposed. We don't think this issue is likely
// to happen in production, but it's worth investigating further.
// TODO(crbug.com/359542780): Remove when rendering issue is fixed.
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
performAction:grey_scrollToContentEdge(kGREYContentEdgeTop)];
// Assert presence of virtual card.
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(
@"Mastercard \nVirtual card")]
assertWithMatcher:grey_sufficientlyVisible()];
// Scroll down to show the CVC chip button for virtual cards.
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
performAction:grey_scrollInDirection(kGREYDirectionDown, 100)];
[[EarlGrey selectElementWithMatcher:CvcChipButton()]
assertWithMatcher:grey_sufficientlyVisible()];
// Scroll down to show original card.
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
performAction:grey_scrollInDirection(kGREYDirectionDown, 200)];
// Assert presence of original card.
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Mastercard ")]
assertWithMatcher:grey_sufficientlyVisible()];
// Clear server cards.
[AutofillAppInterface clearAllServerDataForTesting];
}
// Tests that the manual fallback view for credit cards shows a label for each
// button.
- (void)testManualFallbackShowsCardLabeledButtons {
// Create & save local credit card.
[AutofillAppInterface saveLocalCreditCard];
// Bring up the keyboard.
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
if (![AutofillAppInterface isKeyboardAccessoryUpgradeEnabled]) {
// Scroll to the right to reach the credit card icon.
[[EarlGrey
selectElementWithMatcher:manual_fill::FormSuggestionViewMatcher()]
performAction:grey_scrollToContentEdge(kGREYContentEdgeRight)];
}
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
// Assert card number label.
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Card number:")]
assertWithMatcher:grey_sufficientlyVisible()];
// Assert card number button.
[[EarlGrey
selectElementWithMatcher:grey_accessibilityID(kLocalNumberObfuscated)]
assertWithMatcher:grey_sufficientlyVisible()];
// Assert expiration date label.
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Expiration date:")]
assertWithMatcher:grey_sufficientlyVisible()];
// Assert expiration month button.
[[EarlGrey
selectElementWithMatcher:grey_accessibilityID(kLocalCardExpirationMonth)]
assertWithMatcher:grey_sufficientlyVisible()];
// Assert expiration year button.
[[EarlGrey
selectElementWithMatcher:grey_accessibilityID(kLocalCardExpirationYear)]
assertWithMatcher:grey_sufficientlyVisible()];
// Assert card holder name label.
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Name on card:")]
assertWithMatcher:grey_sufficientlyVisible()];
// Assert card holder name button.
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(kLocalCardHolder)]
assertWithMatcher:grey_sufficientlyVisible()];
}
// Tests that the "Manage Payment Methods..." action works.
- (void)testManagePaymentMethodsActionOpensPaymentMethodSettings {
[AutofillAppInterface saveLocalCreditCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
// Try to scroll.
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)];
// Tap the "Manage Payment Methods..." action.
[[EarlGrey
selectElementWithMatcher:manual_fill::ManagePaymentMethodsMatcher()]
performAction:grey_tap()];
// Verify the payment method settings opened.
[[EarlGrey selectElementWithMatcher:SettingsCreditCardMatcher()]
assertWithMatcher:grey_sufficientlyVisible()];
}
// Tests that the manual fallback view and icon is not highlighted after
// presenting the manage payment methods view.
- (void)testCreditCardsStateAfterPresentingPaymentMethodSettings {
if ([AutofillAppInterface isKeyboardAccessoryUpgradeEnabled]) {
EARL_GREY_TEST_SKIPPED(@"This test is not relevant when the Keyboard "
@"Accessory Upgrade feature is enabled.");
}
[AutofillAppInterface saveLocalCreditCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
// Scroll to the right.
[[EarlGrey selectElementWithMatcher:manual_fill::FormSuggestionViewMatcher()]
performAction:grey_scrollToContentEdge(kGREYContentEdgeRight)];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
// Verify the status of the icon.
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardIconMatcher()]
assertWithMatcher:grey_not(grey_userInteractionEnabled())];
// Try to scroll.
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)];
// Tap the "Manage Payment Methods..." action.
[[EarlGrey
selectElementWithMatcher:manual_fill::ManagePaymentMethodsMatcher()]
performAction:grey_tap()];
// Tap Cancel Button.
[[EarlGrey selectElementWithMatcher:NavigationBarCancelButton()]
performAction:grey_tap()];
// TODO(crbug.com/332956674): Keyboard and keyboard accessory are not present
// on iOS 17.4+, remove version check once fixed.
if (@available(iOS 17.4, *)) {
// Skip verifications.
} else {
// Verify the status of the icons.
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardIconMatcher()]
assertWithMatcher:grey_sufficientlyVisible()];
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardIconMatcher()]
assertWithMatcher:grey_userInteractionEnabled()];
[[EarlGrey selectElementWithMatcher:manual_fill::KeyboardIconMatcher()]
assertWithMatcher:grey_not(grey_sufficientlyVisible())];
// Verify the keyboard is not cover by the cards view.
[[EarlGrey
selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
assertWithMatcher:grey_notVisible()];
}
}
// Tests that the "Add Payment Method..." action works.
- (void)testAddPaymentMethodActionOpensAddPaymentMethodSettings {
[AutofillAppInterface saveLocalCreditCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
if (![ChromeEarlGrey isIPadIdiom]) {
// Try to scroll on iPhone.
[[EarlGrey
selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)];
}
// Tap the "Add Payment Method..." action.
[[EarlGrey selectElementWithMatcher:manual_fill::AddPaymentMethodMatcher()]
performAction:grey_tap()];
// Verify the payment method settings opened.
[[EarlGrey selectElementWithMatcher:chrome_test_util::AddCreditCardView()]
assertWithMatcher:grey_sufficientlyVisible()];
}
// Tests that the "Add Payment Method..." action works on OTR.
- (void)testOTRAddPaymentMethodActionOpensAddPaymentMethodSettings {
// Open a tab in incognito.
[ChromeEarlGrey openNewIncognitoTab];
[self loadURL];
[AutofillAppInterface considerCreditCardFormSecureForTesting];
[AutofillAppInterface saveLocalCreditCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
// Scroll if not iPad.
if (![ChromeEarlGrey isIPadIdiom]) {
[[EarlGrey
selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)];
}
// Tap the "Add Payment Method..." action.
[[EarlGrey selectElementWithMatcher:manual_fill::AddPaymentMethodMatcher()]
performAction:grey_tap()];
// Verify the payment method settings opened.
[[EarlGrey selectElementWithMatcher:chrome_test_util::AddCreditCardView()]
assertWithMatcher:grey_sufficientlyVisible()];
}
// Tests that the manual fallback view icon is not highlighted after presenting
// the add credit card view.
- (void)testCreditCardsButtonStateAfterPresentingAddCreditCard {
if ([AutofillAppInterface isKeyboardAccessoryUpgradeEnabled]) {
EARL_GREY_TEST_SKIPPED(@"This test is not relevant when the Keyboard "
@"Accessory Upgrade feature is enabled.");
}
[AutofillAppInterface saveLocalCreditCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
// Scroll to the right.
[[EarlGrey selectElementWithMatcher:manual_fill::FormSuggestionViewMatcher()]
performAction:grey_scrollToContentEdge(kGREYContentEdgeRight)];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
// Verify the status of the icon.
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardIconMatcher()]
assertWithMatcher:grey_not(grey_userInteractionEnabled())];
// Try to scroll.
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)];
// Tap the "Add Payment Method..." action.
[[EarlGrey selectElementWithMatcher:manual_fill::AddPaymentMethodMatcher()]
performAction:grey_tap()];
// Tap Cancel Button.
[[EarlGrey selectElementWithMatcher:NavigationBarCancelButton()]
performAction:grey_tap()];
// TODO(crbug.com/332956674): Keyboard and keyboard accessory are not present
// on iOS 17.4+, remove version check once fixed.
if (@available(iOS 17.4, *)) {
// Skip verifications.
} else {
// Verify the status of the icons.
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardIconMatcher()]
assertWithMatcher:grey_sufficientlyVisible()];
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardIconMatcher()]
assertWithMatcher:grey_userInteractionEnabled()];
[[EarlGrey selectElementWithMatcher:manual_fill::KeyboardIconMatcher()]
assertWithMatcher:grey_not(grey_sufficientlyVisible())];
// Verify the keyboard is not cover by the cards view.
[[EarlGrey
selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
assertWithMatcher:grey_notVisible()];
}
}
// Tests that the credit card View Controller is dismissed when tapping the
// keyboard icon.
- (void)testKeyboardIconDismissCreditCardController {
if ([ChromeEarlGrey isIPadIdiom] ||
[AutofillAppInterface isKeyboardAccessoryUpgradeEnabled]) {
EARL_GREY_TEST_SKIPPED(
@"The keyboard icon is never present on iPads or when the Keyboard "
@"Accessory Upgrade feature is enabled.");
}
[AutofillAppInterface saveLocalCreditCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
// Tap on the keyboard icon.
[[EarlGrey selectElementWithMatcher:manual_fill::KeyboardIconMatcher()]
performAction:grey_tap()];
// Verify the credit card controller table view and the credit card icon is
// NOT visible.
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
assertWithMatcher:grey_notVisible()];
[[EarlGrey selectElementWithMatcher:manual_fill::KeyboardIconMatcher()]
assertWithMatcher:grey_notVisible()];
}
// Tests that the credit card View Controller is dismissed when tapping the
// outside the popover on iPad.
- (void)testIPadTappingOutsidePopOverDismissCreditCardController {
if (![ChromeEarlGrey isIPadIdiom]) {
return;
}
[AutofillAppInterface saveLocalCreditCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
// Tap on a point outside of the popover.
// The way EarlGrey taps doesn't go through the window hierarchy. Because of
// this, the tap needs to be done in the same window as the popover.
[[EarlGrey
selectElementWithMatcher:manual_fill::CreditCardTableViewWindowMatcher()]
performAction:grey_tapAtPoint(CGPointMake(0, 0))];
// Verify the credit card controller table view and the credit card icon is
// NOT visible.
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
assertWithMatcher:grey_notVisible()];
[[EarlGrey selectElementWithMatcher:manual_fill::KeyboardIconMatcher()]
assertWithMatcher:grey_notVisible()];
}
// Tests that the credit card View Controller is dismissed when tapping the
// keyboard.
// TODO(crbug.com/40250530): reenable this flaky test.
- (void)DISABLED_testTappingKeyboardDismissCreditCardControllerPopOver {
if (![ChromeEarlGrey isIPadIdiom]) {
return;
}
[AutofillAppInterface saveLocalCreditCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
// Tap a keyboard key directly. Typing with EG helpers do not trigger physical
// keyboard presses.
[[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(@"G")]
performAction:grey_tap()];
// As of Xcode 14 beta 2, tapping the keyboard does not dismiss the
// accessory view popup.
bool systemDismissesView = true;
#if defined(__IPHONE_16_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_16_0
if (@available(iOS 16, *)) {
systemDismissesView = false;
}
#endif // defined(__IPHONE_16_0)
if (systemDismissesView) {
// Verify the credit card controller table view and the credit card icon is
// not visible.
[[EarlGrey
selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
assertWithMatcher:grey_notVisible()];
[[EarlGrey selectElementWithMatcher:manual_fill::KeyboardIconMatcher()]
assertWithMatcher:grey_notVisible()];
} else {
[[EarlGrey
selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
assertWithMatcher:grey_sufficientlyVisible()];
}
}
// Tests that, after switching fields, the content size of the table view didn't
// grow.
- (void)testCreditCardControllerKeepsRightSize {
[AutofillAppInterface saveLocalCreditCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
// Tap the second element.
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementCardNumber)];
// Try to scroll.
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)];
}
// Tests that the credit card View Controller stays on rotation.
- (void)testCreditCardControllerSupportsRotation {
[AutofillAppInterface saveLocalCreditCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
[EarlGrey rotateDeviceToOrientation:UIDeviceOrientationLandscapeLeft
error:nil];
// Verify the credit card controller table view is still visible.
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
assertWithMatcher:grey_sufficientlyVisible()];
}
// Tests that credit card number (for local card) is injected.
// TODO(crbug.com/40577448): maybe figure a way to test successfull injection
// when page is https, but right now if we use the https embedded server,
// there's a warning page that stops the flow because of a
// NET::ERR_CERT_AUTHORITY_INVALID.
- (void)testCreditCardLocalNumberDoesntInjectOnHttp {
[self verifyCreditCardButtonWithTitle:kLocalNumberObfuscated
doesInjectValue:@""];
// Dismiss the warning alert.
[[EarlGrey selectElementWithMatcher:chrome_test_util::OKButton()]
performAction:grey_tap()];
[ChromeEarlGreyUI cleanupAfterShowingAlert];
}
// Tests an alert is shown warning the user when trying to fill a credit card
// number in an HTTP form.
- (void)testCreditCardLocalNumberShowsWarningOnHttp {
[self verifyCreditCardButtonWithTitle:kLocalNumberObfuscated
doesInjectValue:@""];
// Look for the alert.
[[EarlGrey selectElementWithMatcher:NotSecureWebsiteAlert()]
assertWithMatcher:grey_not(grey_nil())];
// Dismiss the alert.
[[EarlGrey selectElementWithMatcher:chrome_test_util::OKButton()]
performAction:grey_tap()];
[ChromeEarlGreyUI cleanupAfterShowingAlert];
}
// Tests that credit card cardholder is injected.
- (void)testCreditCardCardHolderInjectsCorrectly {
[self verifyCreditCardButtonWithTitle:kLocalCardHolder
doesInjectValue:kLocalCardHolder];
}
// Tests that credit card expiration month is injected.
- (void)testCreditCardExpirationMonthInjectsCorrectly {
[self verifyCreditCardButtonWithTitle:kLocalCardExpirationMonth
doesInjectValue:kLocalCardExpirationMonth];
}
// Tests that credit card expiration year is injected.
- (void)testCreditCardExpirationYearInjectsCorrectly {
[self verifyCreditCardButtonWithTitle:kLocalCardExpirationYear
doesInjectValue:kLocalCardExpirationYear];
}
// Tests that masked credit card offer CVC input.
// TODO(crbug.com/41428751) can't test this one until https tests are possible.
- (void)DISABLED_testCreditCardServerNumberRequiresCVC {
[AutofillAppInterface saveMaskedCreditCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
// Wait for the accessory icon to appear.
[ChromeEarlGrey waitForKeyboardToAppear];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
// Select a the masked number.
[[EarlGrey selectElementWithMatcher:grey_buttonTitle(kServerNumberObfuscated)]
performAction:grey_tap()];
// Verify the CVC requester is visible.
[[EarlGrey selectElementWithMatcher:grey_text(@"Confirm Card")]
assertWithMatcher:grey_notNil()];
// TODO(crbug.com/40577448): maybe figure a way to enter CVC and get the
// unlocked card result.
}
// Tests that the overflow menu button is only visible when the Keyboard
// Accessory Upgrade feature is enabled.
- (void)testOverflowMenuVisibility {
// Save a card.
[AutofillAppInterface saveLocalCreditCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
[ChromeEarlGrey waitForKeyboardToAppear];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
if ([AutofillAppInterface isKeyboardAccessoryUpgradeEnabled]) {
[[EarlGrey selectElementWithMatcher:OverflowMenuButton()]
assertWithMatcher:grey_sufficientlyVisible()];
} else {
[[EarlGrey selectElementWithMatcher:OverflowMenuButton()]
assertWithMatcher:grey_notVisible()];
}
}
// Tests that the overflow menu button is never visible in virtual card cells.
- (void)testOverflowMenuVisibilityForVirtualCards {
// Create & save credit card enrolled in virtual card program.
[AutofillAppInterface saveMaskedCreditCardEnrolledInVirtualCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
[ChromeEarlGrey waitForKeyboardToAppear];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
// Refresh the view by scrolling to the top as the virtual card and regular
// card cells are otherwise superimposed. We don't think this issue is likely
// to happen in production, but it's worth investigating further.
// TODO(crbug.com/359542780): Remove when rendering issue is fixed.
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
performAction:grey_scrollToContentEdge(kGREYContentEdgeTop)];
// Assert presence of virtual card.
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(
@"Mastercard \nVirtual card")]
assertWithMatcher:grey_sufficientlyVisible()];
// The overflow menu button should not be visible.
[[EarlGrey selectElementWithMatcher:OverflowMenuButton()]
assertWithMatcher:grey_notVisible()];
}
// Tests that the "Edit" action of a local card's overflow menu button displays
// the card's details in edit mode.
- (void)testEditLocalCardFromOverflowMenu {
if (![AutofillAppInterface isKeyboardAccessoryUpgradeEnabled]) {
EARL_GREY_TEST_DISABLED(@"This test is not relevant when the Keyboard "
@"Accessory Upgrade feature is disabled.")
}
[FormInputAccessoryAppInterface setUpMockReauthenticationModule];
[FormInputAccessoryAppInterface mockReauthenticationModuleExpectedResult:
ReauthenticationResult::kSuccess];
// Save a local card.
[AutofillAppInterface saveLocalCreditCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
[ChromeEarlGrey waitForKeyboardToAppear];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
// Tap the overflow menu button and select the "Edit" action.
[[EarlGrey selectElementWithMatcher:OverflowMenuButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:OverflowMenuEditAction()]
performAction:grey_tap()];
// Verify that the card's details page is visible.
[[EarlGrey selectElementWithMatcher:chrome_test_util::
AutofillCreditCardEditTableView()]
assertWithMatcher:grey_sufficientlyVisible()];
// Edit the name.
[[EarlGrey selectElementWithMatcher:grey_text(@"Test User")]
performAction:grey_replaceText(@"New Name")];
// Tap Done Button.
[[EarlGrey selectElementWithMatcher:NavigationBarDoneButton()]
performAction:grey_tap()];
[FormInputAccessoryAppInterface removeMockReauthenticationModule];
// TODO(crbug.com/332956674): Check that the updated suggestion is visible.
}
// Tests that the "Edit" action of a server card overflow menu button opens a
// new tab page.
- (void)testEditServerCardFromOverflowMenu {
if (![AutofillAppInterface isKeyboardAccessoryUpgradeEnabled]) {
EARL_GREY_TEST_DISABLED(@"This test is not relevant when the Keyboard "
@"Accessory Upgrade feature is disabled.")
}
// Save a server card.
[AutofillAppInterface saveMaskedCreditCard];
[self loadURL];
[AutofillAppInterface considerCreditCardFormSecureForTesting];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
DismissPaymentBottomSheet();
[ChromeEarlGrey waitForKeyboardToAppear];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
// Tap the overflow menu button and select the "Edit" action.
[[EarlGrey selectElementWithMatcher:OverflowMenuButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:OverflowMenuEditAction()]
performAction:grey_tap()];
// Tapping on "Edit" should have opened the Payments web page. Verify that the
// card's details page wasn't opened and that the card table view controller
// is no longer visible.
[[EarlGrey selectElementWithMatcher:chrome_test_util::
AutofillCreditCardEditTableView()]
assertWithMatcher:grey_notVisible()];
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
assertWithMatcher:grey_notVisible()];
}
// Tests the "Show Details" action of the overflow menu button displays the
// card's details.
- (void)testShowCardDetailsFromOverflowMenu {
if (![AutofillAppInterface isKeyboardAccessoryUpgradeEnabled]) {
EARL_GREY_TEST_DISABLED(@"This test is not relevant when the Keyboard "
@"Accessory Upgrade feature is disabled.")
}
[FormInputAccessoryAppInterface setUpMockReauthenticationModule];
[FormInputAccessoryAppInterface mockReauthenticationModuleExpectedResult:
ReauthenticationResult::kSuccess];
// Save a card.
[AutofillAppInterface saveLocalCreditCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
[ChromeEarlGrey waitForKeyboardToAppear];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
// Tap the overflow menu button and select the "Show Details" action.
[[EarlGrey selectElementWithMatcher:OverflowMenuButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:OverflowMenuShowDetailsAction()]
performAction:grey_tap()];
// Verify that the card's details are visible.
[[EarlGrey selectElementWithMatcher:chrome_test_util::
AutofillCreditCardEditTableView()]
assertWithMatcher:grey_sufficientlyVisible()];
// Tap Cancel Button.
[[EarlGrey selectElementWithMatcher:NavigationBarCancelButton()]
performAction:grey_tap()];
[FormInputAccessoryAppInterface removeMockReauthenticationModule];
// TODO(crbug.com/332956674): Check that the expanded view is still visible.
}
// Tests that tapping the "Autofill Form" button fills the payment form with
// the right data.
- (void)testAutofillFormButtonFillsForm {
if (![AutofillAppInterface isKeyboardAccessoryUpgradeEnabled]) {
EARL_GREY_TEST_DISABLED(@"This test is not relevant when the Keyboard "
@"Accessory Upgrade feature is disabled.")
}
[AutofillAppInterface setUpMockReauthenticationModule];
[AutofillAppInterface mockReauthenticationModuleCanAttempt:YES];
[AutofillAppInterface mockReauthenticationModuleExpectedResult:
ReauthenticationResult::kSuccess];
// Save a card.
[AutofillAppInterface saveLocalCreditCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
[ChromeEarlGrey waitForKeyboardToAppear];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
// Tap the "Autofill Form" button.
[[EarlGrey selectElementWithMatcher:AutofillFormButton()]
performAction:grey_tap()];
// Verify that the page is filled properly.
[self verifyCreditCardInfosHaveBeenFilled:autofill::test::GetCreditCard()];
// Verify that the acceptance of the card suggestion at index 0 was correctly
// recorded.
CheckAutofillSuggestionAcceptedIndexMetricsCount(/*suggestion_index=*/0);
[AutofillAppInterface clearMockReauthenticationModule];
}
// Tests that the GPay icon is only visible when the Keyboard Accessory Upgrade
// feature is enabled and the card is a server card.
- (void)testGPayIconVisibility {
// Save a local and a masked card.
NSString* local_card_last_digits = [AutofillAppInterface saveLocalCreditCard];
NSString* masked_card_last_digits =
[AutofillAppInterface saveMaskedCreditCard];
[self loadURL];
[AutofillAppInterface considerCreditCardFormSecureForTesting];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
DismissPaymentBottomSheet();
[ChromeEarlGrey waitForKeyboardToAppear];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
// Check that the GPay icon is only visible in the masked card cell when the
// Keyboard Accessory Upgrade feature is enabled.
[[EarlGrey selectElementWithMatcher:GPayIcon(masked_card_last_digits)]
assertWithMatcher:[AutofillAppInterface isKeyboardAccessoryUpgradeEnabled]
? grey_sufficientlyVisible()
: grey_notVisible()];
// Scroll down to show the local card.
[[EarlGrey selectElementWithMatcher:manual_fill::CreditCardTableViewMatcher()]
performAction:grey_scrollInDirection(kGREYDirectionDown, 200)];
// Check that the GPay icon is not visible in the local card cell.
[[EarlGrey selectElementWithMatcher:GPayIcon(local_card_last_digits)]
assertWithMatcher:grey_notVisible()];
}
#pragma mark - Private
- (void)loadURL {
const GURL URL = self.testServer->GetURL(kFormHTMLFile);
[ChromeEarlGrey loadURL:URL];
[ChromeEarlGrey waitForWebStateContainingText:"Autofill Test"];
}
- (void)verifyCreditCardButtonWithTitle:(NSString*)title
doesInjectValue:(NSString*)result {
[AutofillAppInterface saveLocalCreditCard];
// Bring up the keyboard
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormElementName)];
// Wait for the accessory icon to appear.
[ChromeEarlGrey waitForKeyboardToAppear];
// Open the payment method manual fill view.
OpenPaymentMethodManualFillView();
// Select a field.
[[EarlGrey selectElementWithMatcher:grey_buttonTitle(title)]
performAction:grey_tap()];
// Verify Web Content.
NSString* javaScriptCondition = [NSString
stringWithFormat:@"window.document.getElementById('%s').value === '%@'",
kFormElementName, result];
[ChromeEarlGrey waitForJavaScriptCondition:javaScriptCondition];
}
// Verify credit card infos are filled.
- (void)verifyCreditCardInfosHaveBeenFilled:(autofill::CreditCard)card {
std::string locale = l10n_util::GetLocaleOverride();
// Credit card name.
NSString* name = base::SysUTF16ToNSString(
card.GetInfo(autofill::CREDIT_CARD_NAME_FULL, locale));
NSString* condition = [NSString
stringWithFormat:@"window.document.getElementById('%s').value === '%@'",
kFormElementName, name];
[ChromeEarlGrey waitForJavaScriptCondition:condition];
// Credit card number.
NSString* number = base::SysUTF16ToNSString(
card.GetInfo(autofill::CREDIT_CARD_NUMBER, locale));
condition = [NSString
stringWithFormat:@"window.document.getElementById('%s').value === '%@'",
kFormElementCardNumber, number];
[ChromeEarlGrey waitForJavaScriptCondition:condition];
// Credit card expiration month.
NSString* expMonth = base::SysUTF16ToNSString(
card.GetInfo(autofill::CREDIT_CARD_EXP_MONTH, locale));
condition = [NSString
stringWithFormat:@"window.document.getElementById('%s').value === '%@'",
kFormElementCardExpirationMonth, expMonth];
[ChromeEarlGrey waitForJavaScriptCondition:condition];
// Credit card expiration year.
NSString* expYear = base::SysUTF16ToNSString(
card.GetInfo(autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR, locale));
condition = [NSString
stringWithFormat:@"window.document.getElementById('%s').value === '%@'",
kFormElementCardExpirationYear, expYear];
[ChromeEarlGrey waitForJavaScriptCondition:condition];
}
@end
// Rerun all the tests in this file but with kIOSKeyboardAccessoryUpgrade
// disabled. This will be removed once that feature launches fully, but ensures
// regressions aren't introduced in the meantime.
@interface CreditCardViewControllerKeyboardAccessoryUpgradeDisabledTestCase
: CreditCardViewControllerTestCase
@end
@implementation CreditCardViewControllerKeyboardAccessoryUpgradeDisabledTestCase
- (BOOL)shouldEnableKeyboardAccessoryUpgradeFeature {
return NO;
}
// This causes the test case to actually be detected as a test case. The actual
// tests are all inherited from the parent class.
- (void)testEmpty {
}
@end