blob: 8a7c063698a1afd67e17359482eb494682f2941e [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <EarlGrey/EarlGrey.h>
#include <memory>
#include "base/logging.h"
#import "base/test/ios/wait_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/form_data_importer.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/common/autofill_payments_features.h"
#include "components/autofill/ios/browser/autofill_driver_ios.h"
#import "components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.h"
#include "components/autofill/ios/browser/ios_test_event_waiter.h"
#include "components/strings/grit/components_strings.h"
#include "ios/chrome/browser/autofill/personal_data_manager_factory.h"
#import "ios/chrome/browser/ui/autofill/save_card_infobar_controller.h"
#import "ios/chrome/test/app/chrome_test_util.h"
#import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
#import "ios/chrome/test/earl_grey/chrome_matchers.h"
#import "ios/chrome/test/earl_grey/chrome_test_case.h"
#include "ios/web/public/js_messaging/web_frame_util.h"
#import "ios/web/public/js_messaging/web_frames_manager.h"
#import "ios/web/public/test/http_server/http_server.h"
#import "ios/web/public/web_state/web_state.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
using base::test::ios::kWaitForDownloadTimeout;
using base::test::ios::kWaitForUIElementTimeout;
using base::test::ios::WaitUntilConditionOrTimeout;
// URLs of the test pages.
const char kCreditCardUploadForm[] =
"https://components/test/data/autofill/"
"credit_card_upload_form_address_and_cc.html";
// Google Payments server requests and responses.
const char kURLGetUploadDetailsRequest[] =
"https://payments.google.com/payments/apis/chromepaymentsservice/"
"getdetailsforsavecard";
const char kResponseGetUploadDetailsSuccess[] =
"{\"legal_message\":{\"line\":[{\"template\":\"Legal message template with "
"link: "
"{0}.\",\"template_parameter\":[{\"display_text\":\"Link\",\"url\":\"https:"
"//www.example.com/\"}]}]},\"context_token\":\"dummy_context_token\"}";
const char kResponseGetUploadDetailsFailure[] =
"{\"error\":{\"code\":\"FAILED_PRECONDITION\",\"user_error_message\":\"An "
"unexpected error has occurred. Please try again later.\"}}";
// CreditCardSaveManager events that can be waited on by the IOSTestEventWaiter.
enum InfobarEvent : int {
OFFERED_LOCAL_SAVE,
REQUESTED_UPLOAD_SAVE,
RECEIVED_GET_UPLOAD_DETAILS_RESPONSE,
SENT_UPLOAD_CARD_REQUEST,
RECEIVED_UPLOAD_CARD_RESPONSE,
STRIKE_CHANGE_COMPLETE
};
id<GREYMatcher> closeButtonMatcher() {
return chrome_test_util::ButtonWithAccessibilityLabelId(IDS_CLOSE);
}
id<GREYMatcher> saveButtonMatcher() {
return chrome_test_util::ButtonWithAccessibilityLabelId(
IDS_AUTOFILL_SAVE_CARD_INFOBAR_ACCEPT);
}
} // namepsace
namespace autofill {
// Helper class that provides access to private members of AutofillManager,
// FormDataImporter and CreditCardSaveManager.
class SaveCardInfobarEGTestHelper {
public:
SaveCardInfobarEGTestHelper() {}
~SaveCardInfobarEGTestHelper() {}
static CreditCardSaveManager* credit_card_save_manager() {
web::WebState* web_state = chrome_test_util::GetCurrentWebState();
web::WebFrame* main_frame = web::GetMainWebFrame(web_state);
DCHECK(web_state);
return AutofillDriverIOS::FromWebStateAndWebFrame(web_state, main_frame)
->autofill_manager()
->client()
->GetFormDataImporter()
->credit_card_save_manager_.get();
}
static payments::PaymentsClient* payments_client() {
web::WebState* web_state = chrome_test_util::GetCurrentWebState();
web::WebFrame* main_frame = web::GetMainWebFrame(web_state);
DCHECK(web_state);
return AutofillDriverIOS::FromWebStateAndWebFrame(web_state, main_frame)
->autofill_manager()
->client()
->GetPaymentsClient();
}
static void ClearCreditCardSaveStrikes() {
credit_card_save_manager()
->GetCreditCardSaveStrikeDatabase()
->ClearAllStrikes();
}
static void SetMaxStrikesOnFormFillCard() {
// The strike key is made of CreditCardSaveStrikeDatabase's project prefix
// and the last 4 digits of the card used in fillAndSubmitForm(), which can
// be found in credit_card_upload_form_address_and_cc.html.
credit_card_save_manager()
->GetCreditCardSaveStrikeDatabase()
->strike_database_->SetStrikeData("CreditCardSave__5454", 3);
}
private:
DISALLOW_COPY_AND_ASSIGN(SaveCardInfobarEGTestHelper);
};
} // namespace autofill
@interface SaveCardInfobarEGTest
: ChromeTestCase<CreditCardSaveManagerTestObserver> {
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
std::unique_ptr<autofill::CreditCardSaveManagerTestObserverBridge>
credit_card_save_manager_observer_;
std::unique_ptr<autofill::IOSTestEventWaiter<InfobarEvent>> event_waiter_;
autofill::PersonalDataManager* personal_data_manager_;
}
@end
@implementation SaveCardInfobarEGTest
- (void)setUp {
[super setUp];
personal_data_manager_ =
autofill::PersonalDataManagerFactory::GetForBrowserState(
chrome_test_util::GetOriginalBrowserState());
// Set up the URL loader factory for the PaymentsClient so we can intercept
// those network requests.
shared_url_loader_factory_ =
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory_);
autofill::payments::PaymentsClient* payments_client =
autofill::SaveCardInfobarEGTestHelper::payments_client();
payments_client->set_url_loader_factory_for_testing(
shared_url_loader_factory_);
// Observe actions in CreditCardSaveManager.
autofill::CreditCardSaveManager* credit_card_save_manager =
autofill::SaveCardInfobarEGTestHelper::credit_card_save_manager();
credit_card_save_manager_observer_ =
std::make_unique<autofill::CreditCardSaveManagerTestObserverBridge>(
credit_card_save_manager, self);
}
- (void)tearDown {
// Clear existing credit cards.
for (const auto* creditCard : personal_data_manager_->GetCreditCards()) {
personal_data_manager_->RemoveByGUID(creditCard->guid());
}
// Clear existing profiles.
for (const auto* profile : personal_data_manager_->GetProfiles()) {
personal_data_manager_->RemoveByGUID(profile->guid());
}
// Clear CreditCardSave StrikeDatabase.
autofill::SaveCardInfobarEGTestHelper::ClearCreditCardSaveStrikes();
[super tearDown];
}
#pragma mark - autofill::IOSTestEventWaiter helper methods
- (void)resetEventWaiterForEvents:(std::list<InfobarEvent>)events
timeout:(NSTimeInterval)timeout {
event_waiter_ = std::make_unique<autofill::IOSTestEventWaiter<InfobarEvent>>(
std::move(events), timeout);
}
- (void)onEvent:(InfobarEvent)event {
GREYAssertTrue(event_waiter_->OnEvent(event),
@"Unexpected event was observed.");
}
- (void)waitForEvents {
GREYAssertTrue(event_waiter_->Wait(),
@"One or more events were not observed.");
}
#pragma mark - CreditCardSaveManagerTestObserver
- (void)offeredLocalSave {
[self onEvent:InfobarEvent::OFFERED_LOCAL_SAVE];
}
- (void)decidedToRequestUploadSave {
[self onEvent:InfobarEvent::REQUESTED_UPLOAD_SAVE];
}
- (void)receivedGetUploadDetailsResponse {
[self onEvent:InfobarEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE];
}
- (void)sentUploadCardRequest {
[self onEvent:InfobarEvent::SENT_UPLOAD_CARD_REQUEST];
}
- (void)receivedUploadCardResponse {
[self onEvent:InfobarEvent::RECEIVED_UPLOAD_CARD_RESPONSE];
}
- (void)strikeChangeComplete {
[self onEvent:InfobarEvent::STRIKE_CHANGE_COMPLETE];
}
#pragma mark - Page interaction helper methods
- (void)fillAndSubmitFormWithCardDetailsOnly {
[ChromeEarlGrey tapWebStateElementWithID:@"fill_card_only"];
[self submitForm];
}
- (void)fillAndSubmitForm {
[ChromeEarlGrey tapWebStateElementWithID:@"fill_form"];
[self submitForm];
}
- (void)submitForm {
[ChromeEarlGrey tapWebStateElementWithID:@"submit"];
}
#pragma mark - Helper methods
- (BOOL)waitForUIElementToAppearOrTimeout:(NSString*)accessibilityIdentifier {
ConditionBlock condition = ^{
NSError* error = nil;
[[EarlGrey
selectElementWithMatcher:grey_accessibilityID(accessibilityIdentifier)]
assertWithMatcher:grey_notNil()
error:&error];
return error == nil;
};
return WaitUntilConditionOrTimeout(kWaitForUIElementTimeout, condition);
}
- (BOOL)waitForUIElementToDisappearOrTimeout:
(NSString*)accessibilityIdentifier {
ConditionBlock condition = ^{
NSError* error = nil;
[[EarlGrey
selectElementWithMatcher:grey_accessibilityID(accessibilityIdentifier)]
assertWithMatcher:grey_nil()
error:&error];
return error == nil;
};
return WaitUntilConditionOrTimeout(kWaitForUIElementTimeout, condition);
}
#pragma mark - Tests
// Upon completion, each test should have the SaveInfobar removed. This is
// because the tearDown() function, which is triggered after each test, removes
// SaveInfoBar and InfobarEvent::STRIKE_CHANGE_COMPLETE will be expected.
// Ensures that submitting the form should query Google Payments; and the
// fallback local save infobar becomes visible if the request unexpectedly fails
// but the form data is complete.
- (void)offerLocalSave_FullData_RequestFails {
[ChromeEarlGrey
loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)];
// Set up the Google Payments server response.
test_url_loader_factory_.AddResponse(kURLGetUploadDetailsRequest,
kResponseGetUploadDetailsSuccess,
net::HTTP_INTERNAL_SERVER_ERROR);
[self resetEventWaiterForEvents:
{InfobarEvent::REQUESTED_UPLOAD_SAVE,
InfobarEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE,
InfobarEvent::OFFERED_LOCAL_SAVE}
timeout:kWaitForDownloadTimeout];
[self fillAndSubmitForm];
[self waitForEvents];
// Wait until the save card infobar becomes visible.
GREYAssert([self waitForUIElementToAppearOrTimeout:
kSaveCardInfobarViewLocalAccessibilityID],
@"Save card infobar failed to show.");
[self resetEventWaiterForEvents:{InfobarEvent::STRIKE_CHANGE_COMPLETE}
timeout:kWaitForDownloadTimeout];
chrome_test_util::RemoveAllInfoBars();
[self waitForEvents];
}
// Ensures that submitting the form should query Google Payments; and the
// fallback local save infobar becomes visible if the request is declined but
// the form data is complete.
- (void)offerLocalSave_FullData_PaymentsDeclines {
[ChromeEarlGrey
loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)];
// Set up the Google Payments server response.
test_url_loader_factory_.AddResponse(kURLGetUploadDetailsRequest,
kResponseGetUploadDetailsFailure);
[self resetEventWaiterForEvents:
{InfobarEvent::REQUESTED_UPLOAD_SAVE,
InfobarEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE,
InfobarEvent::OFFERED_LOCAL_SAVE}
timeout:kWaitForDownloadTimeout];
[self fillAndSubmitForm];
[self waitForEvents];
// Wait until the save card infobar becomes visible.
GREYAssert([self waitForUIElementToAppearOrTimeout:
kSaveCardInfobarViewLocalAccessibilityID],
@"Save card infobar failed to show.");
[self resetEventWaiterForEvents:{InfobarEvent::STRIKE_CHANGE_COMPLETE}
timeout:kWaitForDownloadTimeout];
chrome_test_util::RemoveAllInfoBars();
[self waitForEvents];
}
// Ensures that submitting the form, even with only card number and expiration
// date, should query Google Payments; but the fallback local save infobar
// should not appear if the request is declined and the form data is incomplete.
- (void)testNotOfferLocalSave_PartialData_PaymentsDeclines {
[ChromeEarlGrey
loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)];
// Set up the Google Payments server response.
test_url_loader_factory_.AddResponse(kURLGetUploadDetailsRequest,
kResponseGetUploadDetailsFailure);
[self resetEventWaiterForEvents:
{InfobarEvent::REQUESTED_UPLOAD_SAVE,
InfobarEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}
timeout:kWaitForDownloadTimeout];
[self fillAndSubmitFormWithCardDetailsOnly];
[self waitForEvents];
// Make sure the save card infobar does not become visible.
GREYAssertFalse([self waitForUIElementToAppearOrTimeout:
kSaveCardInfobarViewLocalAccessibilityID],
@"Save card infobar should not show.");
}
// Ensures that submitting the form should query Google Payments; and the
// upstreaming infobar should appear if the request is accepted.
- (void)offerUpstream_FullData_PaymentsAccepts {
[ChromeEarlGrey
loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)];
// Set up the Google Payments server response.
test_url_loader_factory_.AddResponse(kURLGetUploadDetailsRequest,
kResponseGetUploadDetailsSuccess);
[self resetEventWaiterForEvents:
{InfobarEvent::REQUESTED_UPLOAD_SAVE,
InfobarEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}
timeout:kWaitForDownloadTimeout];
[self fillAndSubmitForm];
[self waitForEvents];
// Wait until the save card infobar becomes visible.
GREYAssert([self waitForUIElementToAppearOrTimeout:
kSaveCardInfobarViewUploadAccessibilityID],
@"Save card infobar failed to show.");
[self resetEventWaiterForEvents:{InfobarEvent::STRIKE_CHANGE_COMPLETE}
timeout:kWaitForDownloadTimeout];
chrome_test_util::RemoveAllInfoBars();
[self waitForEvents];
}
// Ensures that submitting the form, even with only card number and expiration
// date, should query Google Payments and the upstreaming infobar should appear
// if the request is accepted.
- (void)offerUpstream_PartialData_PaymentsAccepts {
[ChromeEarlGrey
loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)];
// Set up the Google Payments server response.
test_url_loader_factory_.AddResponse(kURLGetUploadDetailsRequest,
kResponseGetUploadDetailsSuccess);
[self resetEventWaiterForEvents:
{InfobarEvent::REQUESTED_UPLOAD_SAVE,
InfobarEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}
timeout:kWaitForDownloadTimeout];
[self fillAndSubmitForm];
[self waitForEvents];
// Wait until the save card infobar becomes visible.
GREYAssert([self waitForUIElementToAppearOrTimeout:
kSaveCardInfobarViewUploadAccessibilityID],
@"Save card infobar failed to show.");
[self resetEventWaiterForEvents:{InfobarEvent::STRIKE_CHANGE_COMPLETE}
timeout:kWaitForDownloadTimeout];
chrome_test_util::RemoveAllInfoBars();
[self waitForEvents];
}
// Ensures that the infobar goes away and UMA metrics are correctly logged if
// the user declines upload.
- (void)UMA_Upstream_UserDeclines {
// TODO(crbug.com/925670): re-enable when fixed.
EARL_GREY_TEST_DISABLED(@"Failing regularly on the bots.");
base::HistogramTester histogram_tester;
[ChromeEarlGrey
loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)];
// Set up the Google Payments server response.
test_url_loader_factory_.AddResponse(kURLGetUploadDetailsRequest,
kResponseGetUploadDetailsSuccess);
[self resetEventWaiterForEvents:
{InfobarEvent::REQUESTED_UPLOAD_SAVE,
InfobarEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}
timeout:kWaitForDownloadTimeout];
[self fillAndSubmitForm];
[self waitForEvents];
// Wait until the save card infobar becomes visible.
GREYAssert([self waitForUIElementToAppearOrTimeout:
kSaveCardInfobarViewUploadAccessibilityID],
@"Save card infobar failed to show.");
[self resetEventWaiterForEvents:{InfobarEvent::STRIKE_CHANGE_COMPLETE}
timeout:kWaitForDownloadTimeout];
// Tap the X button.
[[EarlGrey selectElementWithMatcher:closeButtonMatcher()]
performAction:grey_tap()];
[self waitForEvents];
// Wait until the save card infobar disappears.
GREYAssert([self waitForUIElementToDisappearOrTimeout:
kSaveCardInfobarViewUploadAccessibilityID],
@"Save card infobar failed to disappear.");
// Ensure that UMA was logged correctly.
histogram_tester.ExpectUniqueSample(
"Autofill.UploadOfferedCardOrigin",
autofill::AutofillMetrics::OFFERING_UPLOAD_OF_NEW_CARD, 1);
histogram_tester.ExpectTotalCount("Autofill.UploadAcceptedCardOrigin", 0);
}
// Ensures that the infobar goes away, an UploadCardRequest RPC is sent to
// Google Payments, and UMA metrics are correctly logged if the user accepts
// upload.
- (void)testUMA_Upstream_UserAccepts {
// TODO(crbug.com/895687): Re-enable this test after eliminating the need for
// disabling EarlGrey synchronization.
EARL_GREY_TEST_DISABLED(@"Test disabled.");
base::HistogramTester histogram_tester;
[ChromeEarlGrey
loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)];
// Set up the Google Payments server response.
test_url_loader_factory_.AddResponse(kURLGetUploadDetailsRequest,
kResponseGetUploadDetailsSuccess);
[self resetEventWaiterForEvents:
{InfobarEvent::REQUESTED_UPLOAD_SAVE,
InfobarEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}
timeout:kWaitForDownloadTimeout];
[self fillAndSubmitForm];
[self waitForEvents];
// Wait until the save card infobar becomes visible.
GREYAssert([self waitForUIElementToAppearOrTimeout:
kSaveCardInfobarViewUploadAccessibilityID],
@"Save card infobar failed to show.");
// Disable EarlGrey's synchronization since it's blocked by infobar animation.
[[GREYConfiguration sharedInstance]
setValue:@NO
forConfigKey:kGREYConfigKeySynchronizationEnabled];
[self resetEventWaiterForEvents:{InfobarEvent::SENT_UPLOAD_CARD_REQUEST}
timeout:kWaitForDownloadTimeout];
// Tap the save button.
[[EarlGrey selectElementWithMatcher:saveButtonMatcher()]
performAction:grey_tap()];
[self waitForEvents];
// Reenable synchronization now that the infobar animation is over.
[[GREYConfiguration sharedInstance]
setValue:@YES
forConfigKey:kGREYConfigKeySynchronizationEnabled];
// Wait until the save card infobar disappears.
GREYAssert([self waitForUIElementToDisappearOrTimeout:
kSaveCardInfobarViewUploadAccessibilityID],
@"Save card infobar failed to disappear.");
// Ensure that UMA was logged correctly.
histogram_tester.ExpectUniqueSample(
"Autofill.UploadOfferedCardOrigin",
autofill::AutofillMetrics::OFFERING_UPLOAD_OF_NEW_CARD, 1);
histogram_tester.ExpectUniqueSample(
"Autofill.UploadAcceptedCardOrigin",
autofill::AutofillMetrics::USER_ACCEPTED_UPLOAD_OF_NEW_CARD, 1);
}
// Ensures that the infobar goes away and no credit card is saved to Chrome if
// the user declines local save.
- (void)userData_LocalSave_UserDeclines {
[ChromeEarlGrey
loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)];
// Set up the Google Payments server response.
test_url_loader_factory_.AddResponse(kURLGetUploadDetailsRequest,
kResponseGetUploadDetailsFailure);
[self resetEventWaiterForEvents:
{InfobarEvent::REQUESTED_UPLOAD_SAVE,
InfobarEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE,
InfobarEvent::OFFERED_LOCAL_SAVE}
timeout:kWaitForDownloadTimeout];
[self fillAndSubmitForm];
[self waitForEvents];
// Wait until the save card infobar becomes visible.
GREYAssert([self waitForUIElementToAppearOrTimeout:
kSaveCardInfobarViewLocalAccessibilityID],
@"Save card infobar failed to show.");
[self resetEventWaiterForEvents:{InfobarEvent::STRIKE_CHANGE_COMPLETE}
timeout:kWaitForDownloadTimeout];
// Tap the X button.
[[EarlGrey selectElementWithMatcher:closeButtonMatcher()]
performAction:grey_tap()];
[self waitForEvents];
// Wait until the save card infobar disappears.
GREYAssert([self waitForUIElementToDisappearOrTimeout:
kSaveCardInfobarViewLocalAccessibilityID],
@"Save card infobar failed to disappear.");
// Ensure credit card is not saved locally.
GREYAssertEqual(0U, personal_data_manager_->GetCreditCards().size(),
@"No credit card should have been saved.");
}
// Ensures that the infobar goes away and the credit card is saved to Chrome if
// the user accepts local save.
- (void)testUserData_LocalSave_UserAccepts {
[ChromeEarlGrey
loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)];
// Ensure there are no saved credit cards.
GREYAssertEqual(0U, personal_data_manager_->GetCreditCards().size(),
@"There should be no saved credit card.");
// Set up the Google Payments server response.
test_url_loader_factory_.AddResponse(kURLGetUploadDetailsRequest,
kResponseGetUploadDetailsFailure);
[self resetEventWaiterForEvents:
{InfobarEvent::REQUESTED_UPLOAD_SAVE,
InfobarEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE,
InfobarEvent::OFFERED_LOCAL_SAVE}
timeout:kWaitForDownloadTimeout];
[self fillAndSubmitForm];
[self waitForEvents];
// Wait until the save card infobar becomes visible.
GREYAssert([self waitForUIElementToAppearOrTimeout:
kSaveCardInfobarViewLocalAccessibilityID],
@"Save card infobar failed to show.");
// Tap the save button.
[[EarlGrey selectElementWithMatcher:saveButtonMatcher()]
performAction:grey_tap()];
// Wait until the save card infobar disappears.
GREYAssert([self waitForUIElementToDisappearOrTimeout:
kSaveCardInfobarViewLocalAccessibilityID],
@"Save card infobar failed to disappear.");
// Ensure credit card is saved locally.
GREYAssertEqual(1U, personal_data_manager_->GetCreditCards().size(),
@"Credit card should have been saved.");
}
// Ensures that submitting the form should query Google Payments; but the
// fallback local save infobar should not appear if the maximum StrikeDatabase
// strike limit is reached.
// TODO(crbug.com/925670): remove SetMaxStrikesOnFormFillCard() and incur
// the maximum number of strikes by showing and declining save infobar instead.
- (void)testNotOfferLocalSave_MaxStrikesReached {
[ChromeEarlGrey
loadURL:web::test::HttpServer::MakeUrl(kCreditCardUploadForm)];
// Set up the Google Payments server response.
test_url_loader_factory_.AddResponse(kURLGetUploadDetailsRequest,
kResponseGetUploadDetailsFailure);
autofill::SaveCardInfobarEGTestHelper::SetMaxStrikesOnFormFillCard();
[self resetEventWaiterForEvents:
{InfobarEvent::REQUESTED_UPLOAD_SAVE,
InfobarEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE}
timeout:kWaitForDownloadTimeout];
[self fillAndSubmitForm];
[self waitForEvents];
// Make sure the save card infobar does not become visible.
GREYAssertFalse([self waitForUIElementToAppearOrTimeout:
kSaveCardInfobarViewLocalAccessibilityID],
@"Save card infobar should not show.");
}
@end