summaryrefslogtreecommitdiffstats
path: root/components/autofill/content/browser/autocheckout_manager_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'components/autofill/content/browser/autocheckout_manager_unittest.cc')
-rw-r--r--components/autofill/content/browser/autocheckout_manager_unittest.cc804
1 files changed, 804 insertions, 0 deletions
diff --git a/components/autofill/content/browser/autocheckout_manager_unittest.cc b/components/autofill/content/browser/autocheckout_manager_unittest.cc
new file mode 100644
index 0000000..bfcd7da
--- /dev/null
+++ b/components/autofill/content/browser/autocheckout_manager_unittest.cc
@@ -0,0 +1,804 @@
+// Copyright 2013 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.
+
+#include "base/strings/utf_string_conversions.h"
+#include "base/tuple.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/autofill/browser/autofill_common_test.h"
+#include "components/autofill/browser/autofill_manager.h"
+#include "components/autofill/browser/autofill_metrics.h"
+#include "components/autofill/browser/form_structure.h"
+#include "components/autofill/browser/test_autofill_manager_delegate.h"
+#include "components/autofill/common/autofill_messages.h"
+#include "components/autofill/common/form_data.h"
+#include "components/autofill/content/browser/autocheckout_manager.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_utils.h"
+#include "ipc/ipc_test_sink.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using content::BrowserThread;
+
+namespace autofill {
+
+namespace {
+
+typedef Tuple4<std::vector<FormData>,
+ std::vector<WebElementDescriptor>,
+ std::vector<WebElementDescriptor>,
+ WebElementDescriptor> AutofillParam;
+
+FormFieldData BuildFieldWithValue(
+ const std::string& autocomplete_attribute,
+ const std::string& value) {
+ FormFieldData field;
+ field.name = ASCIIToUTF16(autocomplete_attribute);
+ field.value = ASCIIToUTF16(value);
+ field.autocomplete_attribute = autocomplete_attribute;
+ field.form_control_type = "text";
+ return field;
+}
+
+FormFieldData BuildField(const std::string& autocomplete_attribute) {
+ return BuildFieldWithValue(autocomplete_attribute, autocomplete_attribute);
+}
+
+scoped_ptr<FormStructure> CreateTestFormStructure(
+ const std::vector<AutofillFieldType>& autofill_types) {
+ FormData form;
+ form.name = ASCIIToUTF16("MyForm");
+ form.method = ASCIIToUTF16("POST");
+ form.origin = GURL("https://myform.com/form.html");
+ form.action = GURL("https://myform.com/submit.html");
+ form.user_submitted = true;
+
+ // Add some fields, autocomplete_attribute is not important and we
+ // fake that server sends authoritative field mappings.
+ for (size_t i = 0; i < autofill_types.size(); ++i)
+ form.fields.push_back(BuildField("SomeField"));
+
+ scoped_ptr<FormStructure> form_structure(
+ new FormStructure(form, std::string()));
+
+ // Set mocked Autofill server field types.
+ for (size_t i = 0; i < autofill_types.size(); ++i) {
+ form_structure->field(i)->set_server_type(autofill_types[i]);
+ // Set heuristic type to make sure that server_types are used and not
+ // heuritic type.
+ form_structure->field(i)->set_heuristic_type(CREDIT_CARD_NUMBER);
+ }
+
+ return form_structure.Pass();
+}
+
+scoped_ptr<FormStructure> CreateTestAddressFormStructure() {
+ std::vector<AutofillFieldType> autofill_types;
+ autofill_types.push_back(NAME_FULL);
+ autofill_types.push_back(PHONE_HOME_WHOLE_NUMBER);
+ autofill_types.push_back(EMAIL_ADDRESS);
+ autofill_types.push_back(ADDRESS_HOME_LINE1);
+ autofill_types.push_back(ADDRESS_HOME_CITY);
+ autofill_types.push_back(ADDRESS_HOME_STATE);
+ autofill_types.push_back(ADDRESS_HOME_COUNTRY);
+ autofill_types.push_back(ADDRESS_HOME_ZIP);
+ autofill_types.push_back(NO_SERVER_DATA);
+ return CreateTestFormStructure(autofill_types);
+}
+
+scoped_ptr<FormStructure> CreateTestCreditCardFormStructure() {
+ std::vector<AutofillFieldType> autofill_types;
+ autofill_types.push_back(CREDIT_CARD_NAME);
+ autofill_types.push_back(CREDIT_CARD_NUMBER);
+ autofill_types.push_back(CREDIT_CARD_EXP_MONTH);
+ autofill_types.push_back(CREDIT_CARD_EXP_4_DIGIT_YEAR);
+ autofill_types.push_back(CREDIT_CARD_VERIFICATION_CODE);
+ autofill_types.push_back(ADDRESS_BILLING_LINE1);
+ autofill_types.push_back(ADDRESS_BILLING_CITY);
+ autofill_types.push_back(ADDRESS_BILLING_STATE);
+ autofill_types.push_back(ADDRESS_BILLING_COUNTRY);
+ autofill_types.push_back(ADDRESS_BILLING_ZIP);
+ return CreateTestFormStructure(autofill_types);
+}
+
+scoped_ptr<FormStructure> CreateTestFormStructureWithDefaultValues() {
+ FormData form;
+ form.name = ASCIIToUTF16("MyForm");
+ form.method = ASCIIToUTF16("POST");
+ form.origin = GURL("https://myform.com/form.html");
+ form.action = GURL("https://myform.com/submit.html");
+ form.user_submitted = true;
+
+ // Add two radio button fields.
+ FormFieldData male = BuildFieldWithValue("sex", "male");
+ male.is_checkable = true;
+ form.fields.push_back(male);
+ FormFieldData female = BuildFieldWithValue("sex", "female");
+ female.is_checkable = true;
+ form.fields.push_back(female);
+
+ scoped_ptr<FormStructure> form_structure(
+ new FormStructure(form, std::string()));
+
+ // Fake server response. Set all fields as fields with default value.
+ form_structure->field(0)->set_server_type(FIELD_WITH_DEFAULT_VALUE);
+ form_structure->field(0)->set_default_value("female");
+ form_structure->field(1)->set_server_type(FIELD_WITH_DEFAULT_VALUE);
+ form_structure->field(1)->set_default_value("female");
+
+ return form_structure.Pass();
+}
+
+void PopulateClickElement(WebElementDescriptor* proceed_element,
+ const std::string& descriptor) {
+ proceed_element->descriptor = descriptor;
+ proceed_element->retrieval_method = WebElementDescriptor::ID;
+}
+
+scoped_ptr<AutocheckoutPageMetaData> CreateStartOfFlowMetaData() {
+ scoped_ptr<AutocheckoutPageMetaData> start_of_flow(
+ new AutocheckoutPageMetaData());
+ start_of_flow->current_page_number = 0;
+ start_of_flow->total_pages = 3;
+ PopulateClickElement(&start_of_flow->proceed_element_descriptor, "#foo");
+ return start_of_flow.Pass();
+}
+
+scoped_ptr<AutocheckoutPageMetaData> CreateInFlowMetaData() {
+ scoped_ptr<AutocheckoutPageMetaData> in_flow(new AutocheckoutPageMetaData());
+ in_flow->current_page_number = 1;
+ in_flow->total_pages = 3;
+ PopulateClickElement(&in_flow->proceed_element_descriptor, "#foo");
+ return in_flow.Pass();
+}
+
+scoped_ptr<AutocheckoutPageMetaData> CreateNotInFlowMetaData() {
+ scoped_ptr<AutocheckoutPageMetaData> not_in_flow(
+ new AutocheckoutPageMetaData());
+ PopulateClickElement(&not_in_flow->proceed_element_descriptor, "#foo");
+ return not_in_flow.Pass();
+}
+
+scoped_ptr<AutocheckoutPageMetaData> CreateEndOfFlowMetaData() {
+ scoped_ptr<AutocheckoutPageMetaData> end_of_flow(
+ new AutocheckoutPageMetaData());
+ end_of_flow->current_page_number = 2;
+ end_of_flow->total_pages = 3;
+ PopulateClickElement(&end_of_flow->proceed_element_descriptor, "#foo");
+ return end_of_flow.Pass();
+}
+
+scoped_ptr<AutocheckoutPageMetaData> CreateOnePageFlowMetaData() {
+ scoped_ptr<AutocheckoutPageMetaData> one_page_flow(
+ new AutocheckoutPageMetaData());
+ one_page_flow->current_page_number = 0;
+ one_page_flow->total_pages = 1;
+ PopulateClickElement(&one_page_flow->proceed_element_descriptor, "#foo");
+ return one_page_flow.Pass();
+}
+
+scoped_ptr<AutocheckoutPageMetaData> CreateMissingProceedMetaData() {
+ scoped_ptr<AutocheckoutPageMetaData> missing_proceed(
+ new AutocheckoutPageMetaData());
+ missing_proceed->current_page_number = 1;
+ missing_proceed->total_pages = 3;
+ return missing_proceed.Pass();
+}
+
+scoped_ptr<AutocheckoutPageMetaData> CreateMultiClickMetaData() {
+ scoped_ptr<AutocheckoutPageMetaData> metadata(new AutocheckoutPageMetaData());
+ metadata->current_page_number = 1;
+ metadata->total_pages = 3;
+ PopulateClickElement(&metadata->proceed_element_descriptor, "#foo");
+ WebElementDescriptor element;
+ PopulateClickElement(&element, "#before_form_fill_1");
+ metadata->click_elements_before_form_fill.push_back(element);
+ PopulateClickElement(&element, "#before_form_fill_2");
+ metadata->click_elements_before_form_fill.push_back(element);
+ PopulateClickElement(&element, "#after_form_fill");
+ metadata->click_elements_after_form_fill.push_back(element);
+ return metadata.Pass();
+}
+
+struct TestField {
+ const char* const field_type;
+ const char* const field_value;
+ AutofillFieldType autofill_type;
+};
+
+const TestField kTestFields[] = {
+ {"name", "Test User", NAME_FULL},
+ {"tel", "650-123-9909", PHONE_HOME_WHOLE_NUMBER},
+ {"email", "blah@blah.com", EMAIL_ADDRESS},
+ {"cc-name", "Test User", CREDIT_CARD_NAME},
+ {"cc-number", "4444444444444448", CREDIT_CARD_NUMBER},
+ {"cc-exp-month", "10", CREDIT_CARD_EXP_MONTH},
+ {"cc-exp-year", "2020", CREDIT_CARD_EXP_4_DIGIT_YEAR},
+ {"cc-csc", "123", CREDIT_CARD_VERIFICATION_CODE},
+ {"street-address", "Fake Street", ADDRESS_HOME_LINE1},
+ {"locality", "Mocked City", ADDRESS_HOME_CITY},
+ {"region", "California", ADDRESS_HOME_STATE},
+ {"country", "USA", ADDRESS_HOME_COUNTRY},
+ {"postal-code", "49012", ADDRESS_HOME_ZIP},
+ {"billing-street-address", "Billing Street", ADDRESS_BILLING_LINE1},
+ {"billing-locality", "Billing City", ADDRESS_BILLING_CITY},
+ {"billing-region", "BillingState", ADDRESS_BILLING_STATE},
+ {"billing-country", "Canada", ADDRESS_BILLING_COUNTRY},
+ {"billing-postal-code", "11111", ADDRESS_BILLING_ZIP}
+};
+
+// Build Autocheckout specific form data to be consumed by
+// AutofillDialogController to show the Autocheckout specific UI.
+scoped_ptr<FormStructure> FakeUserSubmittedFormStructure() {
+ FormData formdata;
+ for (size_t i = 0; i < arraysize(kTestFields); i++) {
+ formdata.fields.push_back(
+ BuildFieldWithValue(kTestFields[i].field_type,
+ kTestFields[i].field_value));
+ }
+ scoped_ptr<FormStructure> form_structure;
+ form_structure.reset(new FormStructure(formdata, std::string()));
+ for (size_t i = 0; i < arraysize(kTestFields); ++i)
+ form_structure->field(i)->set_server_type(kTestFields[i].autofill_type);
+
+ return form_structure.Pass();
+}
+
+class MockAutofillManagerDelegate : public TestAutofillManagerDelegate {
+ public:
+ MockAutofillManagerDelegate()
+ : request_autocomplete_dialog_open_(false),
+ autocheckout_bubble_shown_(false) {}
+
+ virtual ~MockAutofillManagerDelegate() {}
+
+ virtual void HideRequestAutocompleteDialog() OVERRIDE {
+ request_autocomplete_dialog_open_ = false;
+ }
+
+ MOCK_METHOD0(OnAutocheckoutError, void());
+ MOCK_METHOD0(OnAutocheckoutSuccess, void());
+
+ virtual void ShowAutocheckoutBubble(
+ const gfx::RectF& bounds,
+ bool is_google_user,
+ const base::Callback<void(bool)>& callback) OVERRIDE {
+ autocheckout_bubble_shown_ = true;
+ callback.Run(true);
+ }
+
+ virtual void HideAutocheckoutBubble() OVERRIDE {}
+
+ virtual void ShowRequestAutocompleteDialog(
+ const FormData& form,
+ const GURL& source_url,
+ DialogType dialog_type,
+ const base::Callback<void(const FormStructure*,
+ const std::string&)>& callback) OVERRIDE {
+ request_autocomplete_dialog_open_ = true;
+ callback.Run(user_supplied_data_.get(), "google_transaction_id");
+ }
+
+ MOCK_METHOD1(UpdateProgressBar, void(double value));
+
+ void SetUserSuppliedData(scoped_ptr<FormStructure> user_supplied_data) {
+ user_supplied_data_.reset(user_supplied_data.release());
+ }
+
+ bool autocheckout_bubble_shown() const {
+ return autocheckout_bubble_shown_;
+ }
+
+ void set_autocheckout_bubble_shown(bool autocheckout_bubble_shown) {
+ autocheckout_bubble_shown_ = autocheckout_bubble_shown;
+ }
+
+ bool request_autocomplete_dialog_open() const {
+ return request_autocomplete_dialog_open_;
+ }
+
+ private:
+ bool request_autocomplete_dialog_open_;
+ bool autocheckout_bubble_shown_;
+ scoped_ptr<FormStructure> user_supplied_data_;
+};
+
+class TestAutofillManager : public AutofillManager {
+ public:
+ explicit TestAutofillManager(content::WebContents* contents,
+ AutofillManagerDelegate* delegate)
+ : AutofillManager(contents, delegate, NULL) {
+ }
+ virtual ~TestAutofillManager() {}
+
+ void SetFormStructure(scoped_ptr<FormStructure> form_structure) {
+ form_structures()->clear();
+ form_structures()->push_back(form_structure.release());
+ }
+};
+
+class MockAutofillMetrics : public AutofillMetrics {
+ public:
+ MockAutofillMetrics() {}
+ MOCK_CONST_METHOD1(LogAutocheckoutBubbleMetric, void(BubbleMetric));
+ MOCK_CONST_METHOD1(LogAutocheckoutBuyFlowMetric,
+ void(AutocheckoutBuyFlowMetric));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockAutofillMetrics);
+};
+
+class TestAutocheckoutManager: public AutocheckoutManager {
+ public:
+ explicit TestAutocheckoutManager(AutofillManager* autofill_manager)
+ : AutocheckoutManager(autofill_manager) {
+ set_metric_logger(scoped_ptr<AutofillMetrics>(new MockAutofillMetrics));
+ }
+
+ const MockAutofillMetrics& metric_logger() const {
+ return static_cast<const MockAutofillMetrics&>(
+ AutocheckoutManager::metric_logger());
+ }
+
+ using AutocheckoutManager::in_autocheckout_flow;
+ using AutocheckoutManager::autocheckout_offered;
+ using AutocheckoutManager::MaybeShowAutocheckoutDialog;
+};
+
+} // namespace
+
+class AutocheckoutManagerTest : public ChromeRenderViewHostTestHarness {
+ protected:
+ virtual void SetUp() OVERRIDE {
+ SetThreadBundleOptions(content::TestBrowserThreadBundle::REAL_IO_THREAD);
+ ChromeRenderViewHostTestHarness::SetUp();
+ profile()->CreateRequestContext();
+ autofill_manager_delegate_.reset(new MockAutofillManagerDelegate());
+ autofill_manager_.reset(new TestAutofillManager(
+ web_contents(),
+ autofill_manager_delegate_.get()));
+ autocheckout_manager_.reset(
+ new TestAutocheckoutManager(autofill_manager_.get()));
+ }
+
+ virtual void TearDown() OVERRIDE {
+ autocheckout_manager_.reset();
+ autofill_manager_delegate_.reset();
+ autofill_manager_.reset();
+ profile()->ResetRequestContext();
+ ChromeRenderViewHostTestHarness::TearDown();
+ }
+
+ std::vector<FormData> ReadFilledForms() {
+ uint32 kMsgID = AutofillMsg_FillFormsAndClick::ID;
+ const IPC::Message* message =
+ process()->sink().GetFirstMessageMatching(kMsgID);
+ AutofillParam autofill_param;
+ AutofillMsg_FillFormsAndClick::Read(message, &autofill_param);
+ return autofill_param.a;
+ }
+
+ void CheckFillFormsAndClickIpc() {
+ EXPECT_EQ(1U, process()->sink().message_count());
+ uint32 kMsgID = AutofillMsg_FillFormsAndClick::ID;
+ const IPC::Message* message =
+ process()->sink().GetFirstMessageMatching(kMsgID);
+ EXPECT_TRUE(message);
+ AutofillParam autofill_param;
+ AutofillMsg_FillFormsAndClick::Read(message, &autofill_param);
+ EXPECT_EQ(WebElementDescriptor::ID, autofill_param.d.retrieval_method);
+ EXPECT_EQ("#foo", autofill_param.d.descriptor);
+ ClearIpcSink();
+ }
+
+ void ClearIpcSink() {
+ process()->sink().ClearMessages();
+ }
+
+ void OpenRequestAutocompleteDialog() {
+ EXPECT_FALSE(autocheckout_manager_->in_autocheckout_flow());
+ EXPECT_FALSE(
+ autofill_manager_delegate_->request_autocomplete_dialog_open());
+ EXPECT_CALL(autocheckout_manager_->metric_logger(),
+ LogAutocheckoutBubbleMetric(
+ AutofillMetrics::BUBBLE_COULD_BE_DISPLAYED)).Times(1);
+ autocheckout_manager_->OnLoadedPageMetaData(CreateStartOfFlowMetaData());
+ // Simulate the user submitting some data via the requestAutocomplete UI.
+ autofill_manager_delegate_->SetUserSuppliedData(
+ FakeUserSubmittedFormStructure());
+ GURL frame_url;
+ content::SSLStatus ssl_status;
+ EXPECT_CALL(*autofill_manager_delegate_,
+ UpdateProgressBar(testing::DoubleEq(1.0/3.0))).Times(1);
+ EXPECT_CALL(autocheckout_manager_->metric_logger(),
+ LogAutocheckoutBuyFlowMetric(
+ AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_STARTED)).Times(1);
+ autocheckout_manager_->MaybeShowAutocheckoutDialog(frame_url,
+ ssl_status,
+ true);
+ CheckFillFormsAndClickIpc();
+ EXPECT_TRUE(autocheckout_manager_->in_autocheckout_flow());
+ EXPECT_TRUE(autofill_manager_delegate_->request_autocomplete_dialog_open());
+ }
+
+ void HideRequestAutocompleteDialog() {
+ EXPECT_TRUE(
+ autofill_manager_delegate_->request_autocomplete_dialog_open());
+ autofill_manager_delegate_->HideRequestAutocompleteDialog();
+ EXPECT_FALSE(
+ autofill_manager_delegate_->request_autocomplete_dialog_open());
+ }
+
+ protected:
+ scoped_ptr<TestAutofillManager> autofill_manager_;
+ scoped_ptr<TestAutocheckoutManager> autocheckout_manager_;
+ scoped_ptr<MockAutofillManagerDelegate> autofill_manager_delegate_;
+};
+
+TEST_F(AutocheckoutManagerTest, TestFillForms) {
+ OpenRequestAutocompleteDialog();
+
+ // Test if autocheckout manager can fill the first page.
+ autofill_manager_->SetFormStructure(CreateTestAddressFormStructure());
+
+ autocheckout_manager_->FillForms();
+
+ std::vector<FormData> filled_forms = ReadFilledForms();
+ ASSERT_EQ(1U, filled_forms.size());
+ ASSERT_EQ(9U, filled_forms[0].fields.size());
+ EXPECT_EQ(ASCIIToUTF16("Test User"), filled_forms[0].fields[0].value);
+ EXPECT_EQ(ASCIIToUTF16("650-123-9909"), filled_forms[0].fields[1].value);
+ EXPECT_EQ(ASCIIToUTF16("blah@blah.com"), filled_forms[0].fields[2].value);
+ EXPECT_EQ(ASCIIToUTF16("Fake Street"), filled_forms[0].fields[3].value);
+ EXPECT_EQ(ASCIIToUTF16("Mocked City"), filled_forms[0].fields[4].value);
+ EXPECT_EQ(ASCIIToUTF16("California"), filled_forms[0].fields[5].value);
+ EXPECT_EQ(ASCIIToUTF16("United States"), filled_forms[0].fields[6].value);
+ EXPECT_EQ(ASCIIToUTF16("49012"), filled_forms[0].fields[7].value);
+ // Last field should not be filled, because there is no server mapping
+ // available for it.
+ EXPECT_EQ(ASCIIToUTF16("SomeField"), filled_forms[0].fields[8].value);
+
+ filled_forms.clear();
+ ClearIpcSink();
+
+ // Test if autocheckout manager can fill form on second page.
+ autofill_manager_->SetFormStructure(CreateTestCreditCardFormStructure());
+
+ autocheckout_manager_->FillForms();
+
+ filled_forms = ReadFilledForms();
+ ASSERT_EQ(1U, filled_forms.size());
+ ASSERT_EQ(10U, filled_forms[0].fields.size());
+ EXPECT_EQ(ASCIIToUTF16("Test User"), filled_forms[0].fields[0].value);
+ EXPECT_EQ(ASCIIToUTF16("4444444444444448"), filled_forms[0].fields[1].value);
+ EXPECT_EQ(ASCIIToUTF16("10"), filled_forms[0].fields[2].value);
+ EXPECT_EQ(ASCIIToUTF16("2020"), filled_forms[0].fields[3].value);
+ EXPECT_EQ(ASCIIToUTF16("123"), filled_forms[0].fields[4].value);
+ EXPECT_EQ(ASCIIToUTF16("Billing Street"), filled_forms[0].fields[5].value);
+ EXPECT_EQ(ASCIIToUTF16("Billing City"), filled_forms[0].fields[6].value);
+ EXPECT_EQ(ASCIIToUTF16("BillingState"), filled_forms[0].fields[7].value);
+ EXPECT_EQ(ASCIIToUTF16("Canada"), filled_forms[0].fields[8].value);
+ EXPECT_EQ(ASCIIToUTF16("11111"), filled_forms[0].fields[9].value);
+
+ filled_forms.clear();
+ ClearIpcSink();
+
+ // Test form with default values.
+ autofill_manager_->SetFormStructure(
+ CreateTestFormStructureWithDefaultValues());
+
+ autocheckout_manager_->FillForms();
+
+ filled_forms = ReadFilledForms();
+ ASSERT_EQ(1U, filled_forms.size());
+ ASSERT_EQ(2U, filled_forms[0].fields.size());
+ EXPECT_FALSE(filled_forms[0].fields[0].is_checked);
+ EXPECT_EQ(ASCIIToUTF16("male"), filled_forms[0].fields[0].value);
+ EXPECT_TRUE(filled_forms[0].fields[1].is_checked);
+ EXPECT_EQ(ASCIIToUTF16("female"), filled_forms[0].fields[1].value);
+}
+
+TEST_F(AutocheckoutManagerTest, OnFormsSeenTest) {
+ GURL frame_url;
+ content::SSLStatus ssl_status;
+ gfx::RectF bounding_box;
+ EXPECT_CALL(autocheckout_manager_->metric_logger(),
+ LogAutocheckoutBubbleMetric(
+ AutofillMetrics::BUBBLE_COULD_BE_DISPLAYED)).Times(1);
+ autocheckout_manager_->OnLoadedPageMetaData(CreateStartOfFlowMetaData());
+ autocheckout_manager_->MaybeShowAutocheckoutBubble(frame_url,
+ ssl_status,
+ bounding_box);
+ content::RunAllPendingInMessageLoop(BrowserThread::IO);
+
+ EXPECT_TRUE(autocheckout_manager_->autocheckout_offered());
+ // OnFormsSeen resets whether or not the bubble was shown.
+ autocheckout_manager_->OnFormsSeen();
+ EXPECT_FALSE(autocheckout_manager_->autocheckout_offered());
+}
+
+TEST_F(AutocheckoutManagerTest, OnClickFailedTestMissingAdvance) {
+ OpenRequestAutocompleteDialog();
+
+ EXPECT_CALL(*autofill_manager_delegate_, OnAutocheckoutError()).Times(1);
+ EXPECT_CALL(
+ autocheckout_manager_->metric_logger(),
+ LogAutocheckoutBuyFlowMetric(
+ AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_MISSING_ADVANCE_ELEMENT))
+ .Times(1);
+ autocheckout_manager_->OnClickFailed(MISSING_ADVANCE);
+ EXPECT_FALSE(autocheckout_manager_->in_autocheckout_flow());
+ EXPECT_TRUE(
+ autofill_manager_delegate_->request_autocomplete_dialog_open());
+}
+
+TEST_F(AutocheckoutManagerTest, OnClickFailedTestMissingClickBeforeFilling) {
+ OpenRequestAutocompleteDialog();
+
+ EXPECT_CALL(*autofill_manager_delegate_, OnAutocheckoutError()).Times(1);
+ EXPECT_CALL(
+ autocheckout_manager_->metric_logger(),
+ LogAutocheckoutBuyFlowMetric(AutofillMetrics::
+ AUTOCHECKOUT_BUY_FLOW_MISSING_CLICK_ELEMENT_BEFORE_FORM_FILLING))
+ .Times(1);
+ autocheckout_manager_->OnClickFailed(
+ MISSING_CLICK_ELEMENT_BEFORE_FORM_FILLING);
+ EXPECT_FALSE(autocheckout_manager_->in_autocheckout_flow());
+ EXPECT_TRUE(
+ autofill_manager_delegate_->request_autocomplete_dialog_open());
+}
+
+TEST_F(AutocheckoutManagerTest, OnClickFailedTestMissingClickAfterFilling) {
+ OpenRequestAutocompleteDialog();
+
+ EXPECT_CALL(*autofill_manager_delegate_, OnAutocheckoutError()).Times(1);
+ EXPECT_CALL(
+ autocheckout_manager_->metric_logger(),
+ LogAutocheckoutBuyFlowMetric(AutofillMetrics::
+ AUTOCHECKOUT_BUY_FLOW_MISSING_CLICK_ELEMENT_AFTER_FORM_FILLING))
+ .Times(1);
+ autocheckout_manager_->OnClickFailed(
+ MISSING_CLICK_ELEMENT_AFTER_FORM_FILLING);
+ EXPECT_FALSE(autocheckout_manager_->in_autocheckout_flow());
+ EXPECT_TRUE(
+ autofill_manager_delegate_->request_autocomplete_dialog_open());
+}
+
+TEST_F(AutocheckoutManagerTest, MaybeShowAutocheckoutBubbleTest) {
+ GURL frame_url;
+ content::SSLStatus ssl_status;
+ gfx::RectF bounding_box;
+ EXPECT_CALL(autocheckout_manager_->metric_logger(),
+ LogAutocheckoutBubbleMetric(
+ AutofillMetrics::BUBBLE_COULD_BE_DISPLAYED)).Times(1);
+ autocheckout_manager_->OnLoadedPageMetaData(CreateStartOfFlowMetaData());
+ // MaybeShowAutocheckoutBubble shows bubble if it has not been shown.
+ autocheckout_manager_->MaybeShowAutocheckoutBubble(frame_url,
+ ssl_status,
+ bounding_box);
+ content::RunAllPendingInMessageLoop(BrowserThread::IO);
+ EXPECT_TRUE(autocheckout_manager_->autocheckout_offered());
+ EXPECT_TRUE(autofill_manager_delegate_->autocheckout_bubble_shown());
+
+ // Reset |autofill_manager_delegate_|.
+ HideRequestAutocompleteDialog();
+ autofill_manager_delegate_->set_autocheckout_bubble_shown(false);
+
+ // MaybeShowAutocheckoutBubble does nothing if the bubble was already shown
+ // for the current page.
+ autocheckout_manager_->MaybeShowAutocheckoutBubble(frame_url,
+ ssl_status,
+ bounding_box);
+ content::RunAllPendingInMessageLoop(BrowserThread::IO);
+ EXPECT_TRUE(autocheckout_manager_->autocheckout_offered());
+ EXPECT_FALSE(autofill_manager_delegate_->autocheckout_bubble_shown());
+ EXPECT_FALSE(autofill_manager_delegate_->request_autocomplete_dialog_open());
+}
+
+// Test no proceed element is being passed to the render if a page metadata
+// with no proceed element is loaded.
+TEST_F(AutocheckoutManagerTest, OnLoadedPageMetaDataMissingProceed) {
+ OpenRequestAutocompleteDialog();
+
+ // Go the second page with no proceed element.
+ EXPECT_CALL(*autofill_manager_delegate_,
+ UpdateProgressBar(testing::DoubleEq(2.0/3.0))).Times(1);
+ autocheckout_manager_->OnLoadedPageMetaData(CreateMissingProceedMetaData());
+
+ EXPECT_TRUE(autocheckout_manager_->in_autocheckout_flow());
+
+ EXPECT_EQ(1U, process()->sink().message_count());
+ uint32 kMsgID = AutofillMsg_FillFormsAndClick::ID;
+ const IPC::Message* message =
+ process()->sink().GetFirstMessageMatching(kMsgID);
+ EXPECT_TRUE(message);
+ AutofillParam autofill_param;
+ AutofillMsg_FillFormsAndClick::Read(message, &autofill_param);
+ // Ensure no proceed element is being passed to the render through IPC.
+ EXPECT_EQ(WebElementDescriptor::NONE, autofill_param.d.retrieval_method);
+ EXPECT_EQ("", autofill_param.d.descriptor);
+ ClearIpcSink();
+}
+
+// Test |click_elements_before_form_fill| and |click_elements_after_form_fill|
+// are passed to the render correctly through IPC.
+TEST_F(AutocheckoutManagerTest, OnLoadedPageMetaDataMultiClick) {
+ OpenRequestAutocompleteDialog();
+
+ // Go to the second page with multi-click elements.
+ EXPECT_CALL(*autofill_manager_delegate_,
+ UpdateProgressBar(testing::DoubleEq(2.0/3.0))).Times(1);
+ autocheckout_manager_->OnLoadedPageMetaData(CreateMultiClickMetaData());
+
+ EXPECT_TRUE(autocheckout_manager_->in_autocheckout_flow());
+
+ EXPECT_EQ(1U, process()->sink().message_count());
+ uint32 kMsgID = AutofillMsg_FillFormsAndClick::ID;
+ const IPC::Message* message =
+ process()->sink().GetFirstMessageMatching(kMsgID);
+ EXPECT_TRUE(message);
+ AutofillParam autofill_param;
+ AutofillMsg_FillFormsAndClick::Read(message, &autofill_param);
+ EXPECT_EQ(WebElementDescriptor::ID, autofill_param.d.retrieval_method);
+ EXPECT_EQ("#foo", autofill_param.d.descriptor);
+
+ // Verify |click_elements_before_form_fill|.
+ ASSERT_EQ(2U, autofill_param.b.size());
+ EXPECT_EQ(WebElementDescriptor::ID, autofill_param.b[0].retrieval_method);
+ EXPECT_EQ("#before_form_fill_1", autofill_param.b[0].descriptor);
+ EXPECT_EQ(WebElementDescriptor::ID, autofill_param.b[1].retrieval_method);
+ EXPECT_EQ("#before_form_fill_2", autofill_param.b[1].descriptor);
+
+ // Verify |click_elements_after_form_fill|.
+ ASSERT_EQ(1U, autofill_param.c.size());
+ EXPECT_EQ(WebElementDescriptor::ID, autofill_param.c[0].retrieval_method);
+ EXPECT_EQ("#after_form_fill", autofill_param.c[0].descriptor);
+ ClearIpcSink();
+}
+
+TEST_F(AutocheckoutManagerTest, OnLoadedPageMetaDataMissingMetaData) {
+ // Gettting no meta data after any autocheckout page is an error.
+ OpenRequestAutocompleteDialog();
+ EXPECT_CALL(*autofill_manager_delegate_, OnAutocheckoutError()).Times(1);
+ EXPECT_CALL(
+ autocheckout_manager_->metric_logger(),
+ LogAutocheckoutBuyFlowMetric(
+ AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_MISSING_FIELDMAPPING))
+ .Times(1);
+ autocheckout_manager_->OnLoadedPageMetaData(
+ scoped_ptr<AutocheckoutPageMetaData>());
+ EXPECT_FALSE(autocheckout_manager_->in_autocheckout_flow());
+ EXPECT_EQ(0U, process()->sink().message_count());
+ EXPECT_TRUE(
+ autofill_manager_delegate_->request_autocomplete_dialog_open());
+}
+
+TEST_F(AutocheckoutManagerTest, OnLoadedPageMetaDataRepeatedStartPage) {
+ // Getting start page twice in a row is an error.
+ OpenRequestAutocompleteDialog();
+ EXPECT_CALL(*autofill_manager_delegate_, OnAutocheckoutError()).Times(1);
+ EXPECT_CALL(
+ autocheckout_manager_->metric_logger(),
+ LogAutocheckoutBuyFlowMetric(
+ AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_CANNOT_PROCEED)).Times(1);
+ autocheckout_manager_->OnLoadedPageMetaData(CreateStartOfFlowMetaData());
+ EXPECT_FALSE(autocheckout_manager_->in_autocheckout_flow());
+ EXPECT_EQ(0U, process()->sink().message_count());
+ EXPECT_TRUE(
+ autofill_manager_delegate_->request_autocomplete_dialog_open());
+}
+
+TEST_F(AutocheckoutManagerTest, OnLoadedPageMetaDataRepeatedPage) {
+ // Repeating a page is an error.
+ OpenRequestAutocompleteDialog();
+ // Go to second page.
+ EXPECT_CALL(*autofill_manager_delegate_,
+ UpdateProgressBar(testing::DoubleEq(2.0/3.0))).Times(1);
+ autocheckout_manager_->OnLoadedPageMetaData(CreateInFlowMetaData());
+ EXPECT_TRUE(autocheckout_manager_->in_autocheckout_flow());
+ CheckFillFormsAndClickIpc();
+ EXPECT_CALL(*autofill_manager_delegate_, OnAutocheckoutError()).Times(1);
+ EXPECT_CALL(
+ autocheckout_manager_->metric_logger(),
+ LogAutocheckoutBuyFlowMetric(
+ AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_CANNOT_PROCEED)).Times(1);
+ autocheckout_manager_->OnLoadedPageMetaData(CreateInFlowMetaData());
+ EXPECT_FALSE(autocheckout_manager_->in_autocheckout_flow());
+ EXPECT_EQ(0U, process()->sink().message_count());
+ EXPECT_TRUE(
+ autofill_manager_delegate_->request_autocomplete_dialog_open());
+}
+
+TEST_F(AutocheckoutManagerTest, OnLoadedPageMetaDataNotInFlow) {
+ // Repeating a page is an error.
+ OpenRequestAutocompleteDialog();
+ // Go to second page.
+ EXPECT_CALL(*autofill_manager_delegate_,
+ UpdateProgressBar(testing::DoubleEq(2.0/3.0))).Times(1);
+ autocheckout_manager_->OnLoadedPageMetaData(CreateInFlowMetaData());
+ EXPECT_TRUE(autocheckout_manager_->in_autocheckout_flow());
+ CheckFillFormsAndClickIpc();
+ EXPECT_CALL(*autofill_manager_delegate_, OnAutocheckoutError()).Times(1);
+ EXPECT_CALL(
+ autocheckout_manager_->metric_logger(),
+ LogAutocheckoutBuyFlowMetric(
+ AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_MISSING_FIELDMAPPING))
+ .Times(1);
+ autocheckout_manager_->OnLoadedPageMetaData(CreateNotInFlowMetaData());
+ EXPECT_FALSE(autocheckout_manager_->in_autocheckout_flow());
+ EXPECT_EQ(0U, process()->sink().message_count());
+ EXPECT_TRUE(
+ autofill_manager_delegate_->request_autocomplete_dialog_open());
+}
+
+TEST_F(AutocheckoutManagerTest,
+ OnLoadedPageMetaDataShouldNotFillFormsIfNotInFlow) {
+ // If not in flow, OnLoadedPageMetaData does not fill forms.
+ EXPECT_CALL(autocheckout_manager_->metric_logger(),
+ LogAutocheckoutBubbleMetric(
+ AutofillMetrics::BUBBLE_COULD_BE_DISPLAYED)).Times(1);
+ autocheckout_manager_->OnLoadedPageMetaData(CreateStartOfFlowMetaData());
+ // Go to second page.
+ EXPECT_CALL(*autofill_manager_delegate_,
+ UpdateProgressBar(testing::_)).Times(0);
+ autocheckout_manager_->OnLoadedPageMetaData(CreateInFlowMetaData());
+ EXPECT_EQ(0U, process()->sink().message_count());
+}
+
+TEST_F(AutocheckoutManagerTest, FullAutocheckoutFlow) {
+ // Test for progression through last page.
+ OpenRequestAutocompleteDialog();
+ // Go to second page.
+ EXPECT_CALL(*autofill_manager_delegate_,
+ UpdateProgressBar(testing::DoubleEq(2.0/3.0))).Times(1);
+ EXPECT_CALL(*autofill_manager_delegate_, OnAutocheckoutSuccess()).Times(1);
+ autocheckout_manager_->OnLoadedPageMetaData(CreateInFlowMetaData());
+ EXPECT_TRUE(autocheckout_manager_->in_autocheckout_flow());
+ CheckFillFormsAndClickIpc();
+ // Go to third page.
+ EXPECT_CALL(*autofill_manager_delegate_, UpdateProgressBar(1)).Times(1);
+ EXPECT_CALL(autocheckout_manager_->metric_logger(),
+ LogAutocheckoutBuyFlowMetric(
+ AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_SUCCESS)).Times(1);
+ autocheckout_manager_->OnLoadedPageMetaData(CreateEndOfFlowMetaData());
+ CheckFillFormsAndClickIpc();
+ EXPECT_FALSE(autocheckout_manager_->in_autocheckout_flow());
+ EXPECT_TRUE(autofill_manager_delegate_->request_autocomplete_dialog_open());
+}
+
+TEST_F(AutocheckoutManagerTest, SinglePageFlow) {
+ // Test one page flow.
+ EXPECT_FALSE(autocheckout_manager_->in_autocheckout_flow());
+ EXPECT_FALSE(
+ autofill_manager_delegate_->request_autocomplete_dialog_open());
+ EXPECT_CALL(autocheckout_manager_->metric_logger(),
+ LogAutocheckoutBubbleMetric(
+ AutofillMetrics::BUBBLE_COULD_BE_DISPLAYED)).Times(1);
+ EXPECT_CALL(*autofill_manager_delegate_, OnAutocheckoutSuccess()).Times(1);
+ autocheckout_manager_->OnLoadedPageMetaData(CreateOnePageFlowMetaData());
+ // Simulate the user submitting some data via the requestAutocomplete UI.
+ autofill_manager_delegate_->SetUserSuppliedData(
+ FakeUserSubmittedFormStructure());
+ GURL frame_url;
+ content::SSLStatus ssl_status;
+ EXPECT_CALL(*autofill_manager_delegate_,
+ UpdateProgressBar(testing::DoubleEq(1))).Times(1);
+ EXPECT_CALL(autocheckout_manager_->metric_logger(),
+ LogAutocheckoutBuyFlowMetric(
+ AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_STARTED)).Times(1);
+ EXPECT_CALL(autocheckout_manager_->metric_logger(),
+ LogAutocheckoutBuyFlowMetric(
+ AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_SUCCESS)).Times(1);
+ autocheckout_manager_->MaybeShowAutocheckoutDialog(frame_url,
+ ssl_status,
+ true);
+ CheckFillFormsAndClickIpc();
+ EXPECT_FALSE(autocheckout_manager_->in_autocheckout_flow());
+ EXPECT_TRUE(autofill_manager_delegate_->request_autocomplete_dialog_open());
+}
+
+} // namespace autofill