diff options
Diffstat (limited to 'components/autofill/content/browser/autocheckout_manager_unittest.cc')
-rw-r--r-- | components/autofill/content/browser/autocheckout_manager_unittest.cc | 804 |
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(¬_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 |