blob: ff31dfb15215e59d354b63ce98518e49c6b25324 [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/payments/content/payment_request.h"
#include <vector>
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/test/test_browser_dialog.h"
#include "chrome/browser/ui/views/payments/payment_request_browsertest_base.h"
#include "chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/autofill/core/browser/data_model/addresses/autofill_profile.h"
#include "components/autofill/core/browser/data_model/payments/credit_card.h"
#include "components/autofill/core/browser/test_utils/autofill_test_utils.h"
#include "components/web_modal/web_contents_modal_dialog_manager.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "ui/views/controls/link.h"
#include "ui/views/controls/styled_label.h"
#include "url/gurl.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "chrome/browser/ash/system_web_apps/system_web_app_manager.h"
#endif
namespace payments {
namespace {
using ::testing::UnorderedElementsAre;
class PaymentRequestTest : public PaymentRequestBrowserTestBase {};
// If the page creates multiple PaymentRequest objects, it should not crash.
IN_PROC_BROWSER_TEST_F(PaymentRequestTest, MultipleRequests) {
NavigateTo("/payment_request_multiple_requests.html");
const std::vector<PaymentRequest*> payment_requests = GetPaymentRequests();
EXPECT_EQ(5U, payment_requests.size());
}
class PaymentRequestNoShippingTest : public PaymentRequestBrowserTestBase {
public:
PaymentRequestNoShippingTest(const PaymentRequestNoShippingTest&) = delete;
PaymentRequestNoShippingTest& operator=(const PaymentRequestNoShippingTest&) =
delete;
protected:
PaymentRequestNoShippingTest() = default;
void OpenPaymentRequestDialog() {
// Installs two apps so that the Payment Request UI will be shown.
std::string a_method_name;
InstallPaymentApp("a.com", "/payment_request_success_responder.js",
&a_method_name);
std::string b_method_name;
InstallPaymentApp("b.com", "/payment_request_success_responder.js",
&b_method_name);
NavigateTo("/payment_request_no_shipping_test.html");
InvokePaymentRequestUIWithJs(content::JsReplace(
"buyWithMethods([{supportedMethods:$1}, {supportedMethods:$2}]);",
a_method_name, b_method_name));
}
};
IN_PROC_BROWSER_TEST_F(PaymentRequestNoShippingTest, OpenAndNavigateTo404) {
OpenPaymentRequestDialog();
ResetEventWaiter(DialogEvent::DIALOG_CLOSED);
NavigateTo("/non-existent.html");
ASSERT_TRUE(WaitForObservedEvent());
}
IN_PROC_BROWSER_TEST_F(PaymentRequestNoShippingTest, OpenAndNavigateToSame) {
OpenPaymentRequestDialog();
ResetEventWaiter(DialogEvent::DIALOG_CLOSED);
NavigateTo("/payment_request_no_shipping_test.html");
ASSERT_TRUE(WaitForObservedEvent());
}
IN_PROC_BROWSER_TEST_F(PaymentRequestNoShippingTest, OpenAndReload) {
OpenPaymentRequestDialog();
ResetEventWaiter(DialogEvent::DIALOG_CLOSED);
chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
ASSERT_TRUE(WaitForObservedEvent());
}
IN_PROC_BROWSER_TEST_F(PaymentRequestNoShippingTest, OpenAndClickCancel) {
OpenPaymentRequestDialog();
ResetEventWaiter(DialogEvent::DIALOG_CLOSED);
ClickOnDialogViewAndWait(DialogViewID::CANCEL_BUTTON,
/*wait_for_animation=*/false);
}
IN_PROC_BROWSER_TEST_F(PaymentRequestNoShippingTest,
OrderSummaryAndClickCancel) {
OpenPaymentRequestDialog();
OpenOrderSummaryScreen();
ResetEventWaiter(DialogEvent::DIALOG_CLOSED);
ClickOnDialogViewAndWait(DialogViewID::CANCEL_BUTTON,
/*wait_for_animation=*/false);
}
// TODO(crbug.com/40924925): Fix and re-enable.
IN_PROC_BROWSER_TEST_F(PaymentRequestNoShippingTest,
DISABLED_InactiveBrowserWindow) {
std::string a_method_name;
InstallPaymentApp("a.com", "/payment_request_success_responder.js",
&a_method_name);
std::string b_method_name;
InstallPaymentApp("b.com", "/payment_request_success_responder.js",
&b_method_name);
NavigateTo("/payment_request_no_shipping_test.html");
SetBrowserWindowInactive();
EXPECT_EQ(
"Cannot show PaymentRequest UI in a preview page or a background tab.",
content::EvalJs(
GetActiveWebContents(),
content::JsReplace(
"buyWithMethods([{supportedMethods:$1}, {supportedMethods:$2}]);",
a_method_name, b_method_name)));
}
IN_PROC_BROWSER_TEST_F(PaymentRequestNoShippingTest, InvalidSSL) {
std::string a_method_name;
InstallPaymentApp("a.com", "/payment_request_success_responder.js",
&a_method_name);
std::string b_method_name;
InstallPaymentApp("b.com", "/payment_request_success_responder.js",
&b_method_name);
NavigateTo("/payment_request_no_shipping_test.html");
SetInvalidSsl();
EXPECT_EQ(
"Invalid SSL certificate",
content::EvalJs(
GetActiveWebContents(),
content::JsReplace(
"buyWithMethods([{supportedMethods:$1}, {supportedMethods:$2}]);",
a_method_name, b_method_name)));
}
using PaymentRequestAbortTest = PaymentRequestBrowserTestBase;
// Testing the use of the abort() JS API.
IN_PROC_BROWSER_TEST_F(PaymentRequestAbortTest, OpenThenAbort) {
// Installs two apps so that the Payment Request UI will be shown.
std::string a_method_name;
InstallPaymentApp("a.com", "/payment_request_success_responder.js",
&a_method_name);
std::string b_method_name;
InstallPaymentApp("b.com", "/payment_request_success_responder.js",
&b_method_name);
NavigateTo("/payment_request_abort_test.html");
InvokePaymentRequestUIWithJs(content::JsReplace(
"buyWithMethods([{supportedMethods:$1}, {supportedMethods:$2}]);",
a_method_name, b_method_name));
ResetEventWaiterForSequence(
{DialogEvent::ABORT_CALLED, DialogEvent::DIALOG_CLOSED});
content::WebContents* web_contents = GetActiveWebContents();
const std::string click_buy_button_js =
"(function() { document.getElementById('abort').click(); })();";
ASSERT_TRUE(content::ExecJs(web_contents, click_buy_button_js));
ASSERT_TRUE(WaitForObservedEvent());
ExpectBodyContains({"Aborted"});
// The web-modal dialog should now be closed.
web_modal::WebContentsModalDialogManager* web_contents_modal_dialog_manager =
web_modal::WebContentsModalDialogManager::FromWebContents(web_contents);
EXPECT_FALSE(web_contents_modal_dialog_manager->IsDialogActive());
}
using PaymentRequestPaymentMethodIdentifierTest = PaymentRequestBrowserTestBase;
// A url-based payment method identifier is only supported if it has an https
// scheme.
IN_PROC_BROWSER_TEST_F(PaymentRequestPaymentMethodIdentifierTest, Url_Valid) {
// Installs two apps so that the Payment Request UI will be shown.
std::string a_method_name;
InstallPaymentApp("a.com", "/payment_request_success_responder.js",
&a_method_name);
std::string b_method_name;
InstallPaymentApp("b.com", "/payment_request_success_responder.js",
&b_method_name);
NavigateTo("/payment_request_payment_method_identifier_test.html");
InvokePaymentRequestUIWithJs(content::JsReplace(
"buyHelper([{supportedMethods:$1}, {supportedMethods:$2}]);",
a_method_name, b_method_name));
std::vector<PaymentRequest*> requests = GetPaymentRequests();
EXPECT_EQ(1u, requests.size());
std::vector<GURL> url_payment_method_identifiers =
requests[0]->spec()->url_payment_method_identifiers();
EXPECT_EQ(2u, url_payment_method_identifiers.size());
EXPECT_EQ("https://", url_payment_method_identifiers[0].spec().substr(0, 8));
}
// Test harness integrating with DialogBrowserTest to present the dialog in an
// interactive manner for visual testing.
class PaymentsRequestVisualTest
: public SupportsTestDialog<PaymentRequestNoShippingTest> {
public:
PaymentsRequestVisualTest(const PaymentsRequestVisualTest&) = delete;
PaymentsRequestVisualTest& operator=(const PaymentsRequestVisualTest&) =
delete;
protected:
PaymentsRequestVisualTest() = default;
// TestBrowserDialog:
void ShowUi(const std::string& name) override {
InvokePaymentRequestUIWithJs(content::JsReplace(
"buyWithMethods([{supportedMethods:$1}, {supportedMethods:$2}]);",
a_method_name_, b_method_name_));
}
bool AlwaysCloseAsynchronously() override {
// Bypassing Widget::CanClose() causes payments::JourneyLogger to see the
// show, but not the close, resulting in a DCHECK in its destructor.
return true;
}
std::string a_method_name_;
std::string b_method_name_;
};
IN_PROC_BROWSER_TEST_F(PaymentsRequestVisualTest, InvokeUi_NoShipping) {
// Installs two apps so that the Payment Request UI will be shown.
std::string a_method_name;
InstallPaymentApp("a.com", "/payment_request_success_responder.js",
&a_method_name_);
std::string b_method_name;
InstallPaymentApp("b.com", "/payment_request_success_responder.js",
&b_method_name_);
NavigateTo("/payment_request_no_shipping_test.html");
ShowAndVerifyUi();
}
using PaymentRequestSettingsLinkTest = PaymentRequestBrowserTestBase;
// Tests that clicking the settings link brings the user to settings.
IN_PROC_BROWSER_TEST_F(PaymentRequestSettingsLinkTest, ClickSettingsLink) {
#if BUILDFLAG(IS_CHROMEOS)
// Install the Settings App.
ash::SystemWebAppManager::GetForTest(browser()->profile())
->InstallSystemAppsForTesting();
#endif
// Installs two apps so that the Payment Request UI will be shown.
std::string a_method_name;
InstallPaymentApp("a.com", "/payment_request_success_responder.js",
&a_method_name);
std::string b_method_name;
InstallPaymentApp("b.com", "/payment_request_success_responder.js",
&b_method_name);
NavigateTo("/payment_request_no_shipping_test.html");
// Click on the settings link in the payment request dialog window.
InvokePaymentRequestUIWithJs(content::JsReplace(
"buyWithMethods([{supportedMethods:$1}, {supportedMethods:$2}]);",
a_method_name, b_method_name));
views::StyledLabel* styled_label =
static_cast<views::StyledLabel*>(dialog_view()->GetViewByID(
static_cast<int>(DialogViewID::DATA_SOURCE_LABEL)));
EXPECT_TRUE(styled_label);
content::WebContentsAddedObserver web_contents_added_observer;
styled_label->ClickFirstLinkForTesting();
content::WebContents* new_tab_contents =
web_contents_added_observer.GetWebContents();
EXPECT_EQ(
std::string(chrome::kChromeUISettingsURL) + chrome::kPaymentsSubPage,
new_tab_contents->GetVisibleURL().spec());
}
} // namespace
} // namespace payments