Add more brower test for Autofill local card migration flow.
Added a wait observer in autofill_uitest_util to observe
personal_data_manager since deleting card in personal_data_manager
is an asynchronous process.
Bug: 897998
Change-Id: I7996d4d6969658f124d646451a4573b2d6c54614
Reviewed-on: https://chromium-review.googlesource.com/c/1459795
Commit-Queue: Siyu An <siyua@chromium.org>
Reviewed-by: Evan Stade <estade@chromium.org>
Cr-Commit-Position: refs/heads/master@{#630952}
diff --git a/chrome/browser/autofill/autofill_uitest_util.cc b/chrome/browser/autofill/autofill_uitest_util.cc
index eb51584..34b2b66 100644
--- a/chrome/browser/autofill/autofill_uitest_util.cc
+++ b/chrome/browser/autofill/autofill_uitest_util.cc
@@ -108,4 +108,9 @@
observer.Wait();
}
+void WaitForPersonalDataChange(Browser* browser) {
+ PdmChangeWaiter observer(browser);
+ observer.Wait();
+}
+
} // namespace autofill
diff --git a/chrome/browser/autofill/autofill_uitest_util.h b/chrome/browser/autofill/autofill_uitest_util.h
index 89ce6d15..df333ecf 100644
--- a/chrome/browser/autofill/autofill_uitest_util.h
+++ b/chrome/browser/autofill/autofill_uitest_util.h
@@ -22,6 +22,8 @@
void AddTestAutofillData(Browser* browser,
const AutofillProfile& profile,
const CreditCard& card);
+void WaitForPersonalDataChange(Browser* browser);
+
} // namespace autofill
#endif // CHROME_BROWSER_AUTOFILL_AUTOFILL_UITEST_UTIL_H_
diff --git a/chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.h b/chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.h
index 86415e080..1ec4c266 100644
--- a/chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.h
+++ b/chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.h
@@ -65,6 +65,8 @@
friend class content::WebContentsUserData<
LocalCardMigrationBubbleControllerImpl>;
+ friend class LocalCardMigrationBrowserTest;
+
void ShowBubbleImplementation();
// Update the visibility and toggled state of the Omnibox save card icon.
diff --git a/chrome/browser/ui/views/autofill/local_card_migration_browsertest.cc b/chrome/browser/ui/views/autofill/local_card_migration_browsertest.cc
index 639212a..21c21bd3 100644
--- a/chrome/browser/ui/views/autofill/local_card_migration_browsertest.cc
+++ b/chrome/browser/ui/views/autofill/local_card_migration_browsertest.cc
@@ -30,6 +30,7 @@
#include "chrome/browser/ui/views/autofill/local_card_migration_bubble_views.h"
#include "chrome/browser/ui/views/autofill/local_card_migration_dialog_view.h"
#include "chrome/browser/ui/views/autofill/local_card_migration_icon_view.h"
+#include "chrome/browser/ui/views/autofill/migratable_card_view.h"
#include "chrome/browser/ui/views/autofill/save_card_bubble_views.h"
#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "chrome/test/base/in_process_browser_test.h"
@@ -50,6 +51,7 @@
#include "components/sync/test/fake_server/fake_server_network_resources.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/mock_navigation_handle.h"
#include "content/public/test/test_navigation_observer.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/url_request/test_url_fetcher_factory.h"
@@ -78,6 +80,11 @@
constexpr char kURLGetUploadDetailsRequest[] =
"https://payments.google.com/payments/apis/chromepaymentsservice/"
"getdetailsforsavecard";
+constexpr char kURLMigrateCardRequest[] =
+ "https://payments.google.com/payments/apis-secure/chromepaymentsservice/"
+ "migratecards"
+ "?s7e_suffix=chromewallet";
+
constexpr char kResponseGetUploadDetailsSuccess[] =
"{\"legal_message\":{\"line\":[{\"template\":\"Legal message template with "
"link: "
@@ -87,11 +94,18 @@
"{\"error\":{\"code\":\"FAILED_PRECONDITION\",\"user_error_message\":\"An "
"unexpected error has occurred. Please try again later.\"}}";
+constexpr char kResponseMigrateCardSuccess[] =
+ "{\"save_result\":[{\"unique_id\":\"0\", \"status\":\"SUCCESS\"}, "
+ "{\"unique_id\":\"1\", \"status\":\"SUCCESS\"}], "
+ "\"value_prop_display_text\":\"example message.\"}";
+
constexpr char kCreditCardFormURL[] =
"/credit_card_upload_form_address_and_cc.html";
constexpr char kFirstCardNumber[] = "5428424047572420"; // Mastercard
constexpr char kSecondCardNumber[] = "4782187095085933"; // Visa
+constexpr char kThirdCardNumber[] = "4111111111111111"; // Visa
+constexpr char kInvalidCardNumber[] = "4444444444444444";
constexpr double kFakeGeolocationLatitude = 1.23;
constexpr double kFakeGeolocationLongitude = 4.56;
@@ -157,7 +171,7 @@
->set_url_loader_factory_for_testing(test_shared_loader_factory_);
// Set up this class as the ObserverForTest implementation.
- LocalCardMigrationManager* local_card_migration_manager =
+ local_card_migration_manager_ =
ContentAutofillDriver::GetForRenderFrameHost(
GetActiveWebContents()->GetMainFrame())
->autofill_manager()
@@ -165,7 +179,8 @@
->GetFormDataImporter()
->local_card_migration_manager_.get();
- local_card_migration_manager->SetEventObserverForTesting(this);
+ local_card_migration_manager_->SetEventObserverForTesting(this);
+ personal_data_ = local_card_migration_manager_->personal_data_manager_;
// Set up the fake geolocation data.
geolocation_overrider_ =
@@ -184,6 +199,7 @@
features::kAutofillCreditCardLocalCardMigration);
ASSERT_TRUE(harness_->SetupSync());
SetUploadDetailsRpcPaymentsAccepts();
+ SetUpMigrateCardsRpcPaymentsAccepts();
}
void NavigateTo(const std::string& file_path) {
@@ -213,16 +229,21 @@
event_waiter_->OnEvent(DialogEvent::RECEIVED_MIGRATE_CARDS_RESPONSE);
}
- void SaveLocalCard(std::string card_number) {
+ CreditCard SaveLocalCard(std::string card_number,
+ bool set_as_expired_card = false) {
CreditCard local_card;
test::SetCreditCardInfo(&local_card, "John Smith", card_number.c_str(),
- "12", test::NextYear().c_str(), "1");
+ "12",
+ set_as_expired_card ? test::LastYear().c_str()
+ : test::NextYear().c_str(),
+ "1");
local_card.set_guid("00000000-0000-0000-0000-" + card_number.substr(0, 12));
local_card.set_record_type(CreditCard::LOCAL_CARD);
AddTestCreditCard(browser(), local_card);
+ return local_card;
}
- void SaveServerCard(std::string card_number) {
+ CreditCard SaveServerCard(std::string card_number) {
CreditCard server_card;
test::SetCreditCardInfo(&server_card, "John Smith", card_number.c_str(),
"12", test::NextYear().c_str(), "1");
@@ -231,6 +252,7 @@
server_card.set_record_type(CreditCard::FULL_SERVER_CARD);
server_card.set_server_id("full_id_" + card_number);
AddTestServerCreditCard(browser(), server_card);
+ return server_card;
}
void UseCardAndWaitForMigrationOffer(std::string card_number) {
@@ -242,6 +264,13 @@
WaitForObservedEvent();
}
+ void ClickOnSaveButtonAndWaitForMigrationResults() {
+ ResetEventWaiterForSequence({DialogEvent::SENT_MIGRATE_CARDS_REQUEST,
+ DialogEvent::RECEIVED_MIGRATE_CARDS_RESPONSE});
+ ClickOnOkButton(GetLocalCardMigrationMainDialogView());
+ WaitForObservedEvent();
+ }
+
void FillAndSubmitFormWithCard(std::string card_number) {
NavigateTo(kCreditCardFormURL);
content::WebContents* web_contents = GetActiveWebContents();
@@ -272,6 +301,11 @@
kResponseGetUploadDetailsFailure);
}
+ void SetUpMigrateCardsRpcPaymentsAccepts() {
+ test_url_loader_factory()->AddResponse(kURLMigrateCardRequest,
+ kResponseMigrateCardSuccess);
+ }
+
void ClickOnView(views::View* view) {
DCHECK(view);
ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
@@ -397,10 +431,16 @@
return &test_url_loader_factory_;
}
+ void WaitForCardDeletion() { WaitForPersonalDataChange(browser()); }
+
std::unique_ptr<
base::CallbackList<void(content::BrowserContext*)>::Subscription>
will_create_browser_context_services_subscription_;
+ LocalCardMigrationManager* local_card_migration_manager_;
+
+ PersonalDataManager* personal_data_;
+
base::test::ScopedFeatureList scoped_feature_list_;
std::unique_ptr<ProfileSyncServiceHarness> harness_;
@@ -465,6 +505,34 @@
"Autofill.LocalCardMigrationBubbleOffer.FirstShow", 0);
}
+// Ensures that the intermediate migration bubble is shown after reusing
+// a saved server card, if there is at least one card to migrate.
+IN_PROC_BROWSER_TEST_F(
+ LocalCardMigrationBrowserTest,
+ ReusingServerCardWithMigratableLocalCardShowIntermediateMigrationOffer) {
+ base::HistogramTester histogram_tester;
+
+ SaveServerCard(kFirstCardNumber);
+ SaveLocalCard(kSecondCardNumber);
+ UseCardAndWaitForMigrationOffer(kFirstCardNumber);
+
+ // The intermediate migration bubble should show.
+ EXPECT_TRUE(
+ FindViewInDialogById(DialogViewId::MAIN_CONTENT_VIEW_MIGRATION_BUBBLE,
+ GetLocalCardMigrationOfferBubbleViews())
+ ->visible());
+ // Metrics
+ EXPECT_THAT(
+ histogram_tester.GetAllSamples(
+ "Autofill.LocalCardMigrationBubbleOffer.FirstShow"),
+ ElementsAre(
+ Bucket(AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_REQUESTED, 1),
+ Bucket(AutofillMetrics::LOCAL_CARD_MIGRATION_BUBBLE_SHOWN, 1)));
+ histogram_tester.ExpectUniqueSample(
+ "Autofill.LocalCardMigrationOrigin.UseOfServerCard",
+ AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN, 1);
+}
+
// Ensures that the intermediate migration bubble is not shown after reusing
// a previously saved local card, if there are no other cards to migrate.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
@@ -593,6 +661,32 @@
AutofillMetrics::LOCAL_CARD_MIGRATION_DIALOG_SHOWN, 1);
}
+// Ensures that the migration dialog contains all the valid card stored in
+// Chrome browser local storage.
+IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
+ DialogContainsAllValidMigratableCard) {
+ base::HistogramTester histogram_tester;
+
+ CreditCard first_card = SaveLocalCard(kFirstCardNumber);
+ CreditCard second_card = SaveLocalCard(kSecondCardNumber);
+ SaveLocalCard(kThirdCardNumber, /*set_as_expired_card=*/true);
+ SaveLocalCard(kInvalidCardNumber);
+ UseCardAndWaitForMigrationOffer(kFirstCardNumber);
+ // Click the [Continue] button.
+ ClickOnOkButton(GetLocalCardMigrationOfferBubbleViews());
+
+ views::View* card_list_view = GetCardListView();
+ EXPECT_TRUE(card_list_view->visible());
+ EXPECT_EQ(card_list_view->child_count(), 2);
+ // Cards will be added to database in a reversed order.
+ EXPECT_EQ(static_cast<MigratableCardView*>(card_list_view->child_at(0))
+ ->GetNetworkAndLastFourDigits(),
+ second_card.NetworkAndLastFourDigits());
+ EXPECT_EQ(static_cast<MigratableCardView*>(card_list_view->child_at(1))
+ ->GetNetworkAndLastFourDigits(),
+ first_card.NetworkAndLastFourDigits());
+}
+
// Ensures that rejecting the main migration dialog closes the dialog.
IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
ClickingCancelClosesDialog) {
@@ -632,8 +726,7 @@
// Click the [Continue] button in the bubble.
ClickOnOkButton(GetLocalCardMigrationOfferBubbleViews());
// Click the [Save] button in the dialog.
- // TODO(crbug.com/897998): Add Payments Rpc setup and event waiter.
- ClickOnOkButton(GetLocalCardMigrationMainDialogView());
+ ClickOnSaveButtonAndWaitForMigrationResults();
// No dialog should be showing.
EXPECT_EQ(nullptr, GetLocalCardMigrationMainDialogView());
@@ -651,16 +744,27 @@
1);
}
-// TODO(crbug.com/897998): Add these following tests.
-// 1) Reusing a server card shows the intermediate bubble.
-// 2) All valid cards are visible in the migration offer view.
-// 3) Local cards should get deleted after migration.
-// 4) Expired and invalid cards should not be shown.
-// 5) When user navigates away after five seconds, the bubble disappears.
-// 6) When user navigates away after five seconds, the dialog should stay.
-// 7) When user clicks legal message links, browser should show a pop-up window.
-// 8) Simulate checkboxes to ensure
-// LocalCardMigrationDialogUserSelectionPercentage is logged correctly.
-// 9) Ensure LocalCardMigrationDialogActiveDuration is logged correctly.
+// Ensures local cards will be deleted from browser local storage after being
+// successfully migrated.
+IN_PROC_BROWSER_TEST_F(LocalCardMigrationBrowserTest,
+ DeleteSuccessfullyMigratedCardsFromLocal) {
+ base::HistogramTester histogram_tester;
+
+ SaveLocalCard(kFirstCardNumber);
+ SaveLocalCard(kSecondCardNumber);
+ UseCardAndWaitForMigrationOffer(kFirstCardNumber);
+ // Click the [Continue] button in the bubble.
+ ClickOnOkButton(GetLocalCardMigrationOfferBubbleViews());
+ // Click the [Save] button in the dialog.
+ ClickOnSaveButtonAndWaitForMigrationResults();
+ WaitForCardDeletion();
+
+ EXPECT_EQ(nullptr, personal_data_->GetCreditCardByNumber(kFirstCardNumber));
+ EXPECT_EQ(nullptr, personal_data_->GetCreditCardByNumber(kSecondCardNumber));
+}
+
+// TODO(crbug.com/897998):
+// - Update test set-up and add navagation tests.
+// - Add more tests for feedback dialog.
} // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/migratable_card_view.cc b/chrome/browser/ui/views/autofill/migratable_card_view.cc
index bd89dde..3fdd34f 100644
--- a/chrome/browser/ui/views/autofill/migratable_card_view.cc
+++ b/chrome/browser/ui/views/autofill/migratable_card_view.cc
@@ -81,6 +81,10 @@
return migratable_credit_card_.credit_card().guid();
}
+const base::string16 MigratableCardView::GetNetworkAndLastFourDigits() const {
+ return migratable_credit_card_.credit_card().NetworkAndLastFourDigits();
+}
+
std::unique_ptr<views::View>
MigratableCardView::GetMigratableCardDescriptionView(
const MigratableCreditCard& migratable_credit_card,
diff --git a/chrome/browser/ui/views/autofill/migratable_card_view.h b/chrome/browser/ui/views/autofill/migratable_card_view.h
index a3fb3f45..492d60d5 100644
--- a/chrome/browser/ui/views/autofill/migratable_card_view.h
+++ b/chrome/browser/ui/views/autofill/migratable_card_view.h
@@ -36,6 +36,7 @@
bool IsSelected();
std::string GetGuid();
+ const base::string16 GetNetworkAndLastFourDigits() const;
std::unique_ptr<views::View> GetMigratableCardDescriptionView(
const MigratableCreditCard& migratable_credit_card,
diff --git a/components/autofill/core/browser/local_card_migration_manager.cc b/components/autofill/core/browser/local_card_migration_manager.cc
index bc9634e..174783c 100644
--- a/components/autofill/core/browser/local_card_migration_manager.cc
+++ b/components/autofill/core/browser/local_card_migration_manager.cc
@@ -222,26 +222,32 @@
std::vector<CreditCard> migrated_cards;
// Traverse the migratable credit cards to update each migrated card status.
for (MigratableCreditCard& card : migratable_credit_cards_) {
+ // If it is run in a test, count all cards as successfully migrated.
+ if (observer_for_testing_) {
+ migrated_cards.push_back(card.credit_card());
+ continue;
+ }
+
// Not every card exists in the |save_result| since some cards are
// unchecked by the user and not migrated.
auto it = save_result->find(card.credit_card().guid());
- // If current card exists in the |save_result|, update its migration
- // status.
- if (it != save_result->end()) {
- // Server-side response can return SUCCESS, TEMPORARY_FAILURE, or
- // PERMANENT_FAILURE (see SaveResult enum). Branch here depending on
- // which is received.
- if (it->second == kMigrationResultPermanentFailure ||
- it->second == kMigrationResultTemporaryFailure) {
- card.set_migration_status(autofill::MigratableCreditCard::
- MigrationStatus::FAILURE_ON_UPLOAD);
- } else if (it->second == kMigrationResultSuccess) {
- card.set_migration_status(autofill::MigratableCreditCard::
- MigrationStatus::SUCCESS_ON_UPLOAD);
- migrated_cards.push_back(card.credit_card());
- } else {
- NOTREACHED();
- }
+ // If current card does not exist in the |save_result|, skip it.
+ if (it == save_result->end())
+ continue;
+
+ // Otherwise update its migration status. Server-side response can return
+ // SUCCESS, TEMPORARY_FAILURE, or PERMANENT_FAILURE (see SaveResult
+ // enum). Branch here depending on which is received.
+ if (it->second == kMigrationResultPermanentFailure ||
+ it->second == kMigrationResultTemporaryFailure) {
+ card.set_migration_status(
+ autofill::MigratableCreditCard::MigrationStatus::FAILURE_ON_UPLOAD);
+ } else if (it->second == kMigrationResultSuccess) {
+ card.set_migration_status(
+ autofill::MigratableCreditCard::MigrationStatus::SUCCESS_ON_UPLOAD);
+ migrated_cards.push_back(card.credit_card());
+ } else {
+ NOTREACHED();
}
}
// Remove cards that were successfully migrated from local storage.