| // Copyright 2019 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/macros.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "build/build_config.h" |
| #include "chrome/browser/payments/personal_data_manager_test_util.h" |
| #include "chrome/test/base/chrome_test_utils.h" |
| #include "chrome/test/payments/payment_request_test_controller.h" |
| #include "components/autofill/core/browser/autofill_test_utils.h" |
| #include "components/autofill/core/browser/test_event_waiter.h" |
| #include "components/network_session_configurator/common/network_switches.h" |
| #include "components/payments/content/service_worker_payment_app_finder.h" |
| #include "components/payments/core/journey_logger.h" |
| #include "components/payments/core/test_payment_manifest_downloader.h" |
| #include "components/ukm/test_ukm_recorder.h" |
| #include "content/public/browser/browser_context.h" |
| #include "content/public/browser/storage_partition.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/test/browser_test_utils.h" |
| #include "content/public/test/content_browser_test_utils.h" |
| #include "net/dns/mock_host_resolver.h" |
| #include "net/test/embedded_test_server/embedded_test_server.h" |
| #include "services/metrics/public/cpp/ukm_builders.h" |
| #include "services/metrics/public/cpp/ukm_source.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| #if defined(OS_ANDROID) |
| #include "chrome/browser/flags/android/chrome_feature_list.h" |
| #include "chrome/test/base/android/android_browser_test.h" |
| #else |
| #include "chrome/test/base/in_process_browser_test.h" |
| #endif |
| |
| namespace payments { |
| namespace { |
| |
| autofill::CreditCard GetCardWithBillingAddress( |
| const autofill::AutofillProfile& profile) { |
| autofill::CreditCard card = autofill::test::GetCreditCard(); |
| card.set_billing_address_id(profile.guid()); |
| return card; |
| } |
| |
| } // namespace |
| |
| class JourneyLoggerTest : public PlatformBrowserTest, |
| public PaymentRequestTestObserver { |
| public: |
| // PaymentRequestTestObserver events that can be waited on by the EventWaiter. |
| enum TestEvent : int { |
| SHOW_APPS_READY, |
| }; |
| |
| JourneyLoggerTest() |
| : https_server_(net::EmbeddedTestServer::TYPE_HTTPS), |
| gpay_server_(net::EmbeddedTestServer::TYPE_HTTPS) { |
| test_controller_.SetObserver(this); |
| } |
| |
| ~JourneyLoggerTest() override {} |
| |
| void SetUpCommandLine(base::CommandLine* command_line) override { |
| // HTTPS server only serves a valid cert for localhost, so this is needed to |
| // load pages from the fake "google.com" without an interstitial. |
| command_line->AppendSwitch(switches::kIgnoreCertificateErrors); |
| } |
| |
| void PreRunTestOnMainThread() override { |
| PlatformBrowserTest::PreRunTestOnMainThread(); |
| |
| test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>(); |
| } |
| |
| void SetUpOnMainThread() override { |
| // Map all out-going DNS lookups to the local server. This must be used in |
| // conjunction with switches::kIgnoreCertificateErrors to work. |
| host_resolver()->AddRule("*", "127.0.0.1"); |
| |
| gpay_server_.ServeFilesFromSourceDirectory( |
| "components/test/data/payments/google.com/"); |
| ASSERT_TRUE(gpay_server_.Start()); |
| |
| // Set up test manifest downloader that knows how to fake origin. |
| content::BrowserContext* context = |
| GetActiveWebContents()->GetBrowserContext(); |
| auto downloader = std::make_unique<TestDownloader>( |
| content::BrowserContext::GetDefaultStoragePartition(context) |
| ->GetURLLoaderFactoryForBrowserProcess()); |
| downloader->AddTestServerURL("https://google.com/", |
| gpay_server_.GetURL("google.com", "/")); |
| ServiceWorkerPaymentAppFinder::GetInstance() |
| ->SetDownloaderAndIgnorePortInOriginComparisonForTesting( |
| std::move(downloader)); |
| |
| https_server_.ServeFilesFromSourceDirectory( |
| "components/test/data/payments"); |
| ASSERT_TRUE(https_server_.Start()); |
| |
| main_frame_url_ = https_server_.GetURL("/journey_logger_test.html"); |
| ASSERT_TRUE( |
| content::NavigateToURL(GetActiveWebContents(), main_frame_url_)); |
| |
| test_controller_.SetUpOnMainThread(); |
| PlatformBrowserTest::SetUpOnMainThread(); |
| } |
| |
| content::WebContents* GetActiveWebContents() { |
| return chrome_test_utils::GetActiveWebContents(this); |
| } |
| |
| // PaymentRequestTestObserver implementation. |
| void OnShowAppsReady() override { |
| if (event_waiter_) |
| event_waiter_->OnEvent(TestEvent::SHOW_APPS_READY); |
| } |
| |
| void ResetEventWaiterForSequence(std::list<TestEvent> event_sequence) { |
| event_waiter_ = std::make_unique<autofill::EventWaiter<TestEvent>>( |
| std::move(event_sequence)); |
| } |
| |
| void WaitForObservedEvent() { event_waiter_->Wait(); } |
| |
| const GURL& main_frame_url() const { return main_frame_url_; } |
| |
| ukm::TestAutoSetUkmRecorder* test_ukm_recorder() { |
| return test_ukm_recorder_.get(); |
| } |
| |
| protected: |
| net::EmbeddedTestServer https_server_; |
| |
| private: |
| PaymentRequestTestController test_controller_; |
| net::EmbeddedTestServer gpay_server_; |
| std::unique_ptr<autofill::EventWaiter<TestEvent>> event_waiter_; |
| GURL main_frame_url_; |
| std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_; |
| |
| DISALLOW_COPY_AND_ASSIGN(JourneyLoggerTest); |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(JourneyLoggerTest, NoPaymentMethodSupported) { |
| base::HistogramTester histogram_tester; |
| |
| ResetEventWaiterForSequence({TestEvent::SHOW_APPS_READY}); |
| EXPECT_TRUE(content::ExecJs(GetActiveWebContents(), "testBasicCard()")); |
| WaitForObservedEvent(); |
| |
| EXPECT_TRUE(content::ExecJs(GetActiveWebContents(), "abort()")); |
| |
| std::vector<base::Bucket> buckets = |
| histogram_tester.GetAllSamples("PaymentRequest.Events"); |
| ASSERT_EQ(1U, buckets.size()); |
| EXPECT_FALSE(buckets[0].min & |
| JourneyLogger::EVENT_AVAILABLE_METHOD_BASIC_CARD); |
| EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_AVAILABLE_METHOD_GOOGLE); |
| EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_AVAILABLE_METHOD_OTHER); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(JourneyLoggerTest, BasicCardOnly) { |
| autofill::AutofillProfile address = autofill::test::GetFullProfile(); |
| test::AddAutofillProfile(GetActiveWebContents()->GetBrowserContext(), |
| address); |
| test::AddCreditCard(GetActiveWebContents()->GetBrowserContext(), |
| GetCardWithBillingAddress(address)); |
| |
| base::HistogramTester histogram_tester; |
| |
| ResetEventWaiterForSequence({TestEvent::SHOW_APPS_READY}); |
| EXPECT_TRUE(content::ExecJs(GetActiveWebContents(), "testBasicCard()")); |
| WaitForObservedEvent(); |
| |
| EXPECT_EQ(true, content::EvalJs(GetActiveWebContents(), "abort()")); |
| |
| std::vector<base::Bucket> buckets = |
| histogram_tester.GetAllSamples("PaymentRequest.Events"); |
| ASSERT_EQ(1U, buckets.size()); |
| EXPECT_TRUE(buckets[0].min & |
| JourneyLogger::EVENT_AVAILABLE_METHOD_BASIC_CARD); |
| EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_AVAILABLE_METHOD_GOOGLE); |
| EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_AVAILABLE_METHOD_OTHER); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(JourneyLoggerTest, GooglePaymentApp) { |
| base::HistogramTester histogram_tester; |
| |
| EXPECT_EQ("{\"apiVersion\":1}", |
| content::EvalJs(GetActiveWebContents(), "testGPay()")); |
| |
| std::vector<base::Bucket> buckets = |
| histogram_tester.GetAllSamples("PaymentRequest.Events"); |
| ASSERT_EQ(1U, buckets.size()); |
| EXPECT_FALSE(buckets[0].min & |
| JourneyLogger::EVENT_AVAILABLE_METHOD_BASIC_CARD); |
| EXPECT_TRUE(buckets[0].min & JourneyLogger::EVENT_AVAILABLE_METHOD_GOOGLE); |
| EXPECT_FALSE(buckets[0].min & JourneyLogger::EVENT_AVAILABLE_METHOD_OTHER); |
| } |
| |
| // Make sure the UKM was logged correctly. |
| IN_PROC_BROWSER_TEST_F(JourneyLoggerTest, UKMTransactionAmountRecorded) { |
| EXPECT_EQ("{\"apiVersion\":1}", |
| content::EvalJs(GetActiveWebContents(), "testGPay()")); |
| |
| auto entries = test_ukm_recorder()->GetEntriesByName( |
| ukm::builders::PaymentRequest_TransactionAmount::kEntryName); |
| size_t num_entries = entries.size(); |
| EXPECT_EQ(2u, num_entries); |
| for (size_t i = 0; i < num_entries; i++) { |
| test_ukm_recorder()->ExpectEntrySourceHasUrl(entries[i], main_frame_url()); |
| EXPECT_EQ(2U, entries[i]->metrics.size()); |
| test_ukm_recorder()->ExpectEntryMetric( |
| entries[i], |
| ukm::builders::PaymentRequest_TransactionAmount::kCompletionStatusName, |
| i != 0 /* completed */); |
| test_ukm_recorder()->ExpectEntryMetric( |
| entries[i], |
| ukm::builders::PaymentRequest_TransactionAmount::kCategoryName, |
| static_cast<int64_t>( |
| JourneyLogger::TransactionSize::kRegularTransaction)); |
| } |
| } |
| |
| } // namespace payments |