blob: e10885168236bb699d0bddfbbc46db27b1dd02d1 [file] [log] [blame]
// Copyright 2020 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 "third_party/blink/renderer/modules/payments/payment_request.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/payments/payment_request.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/event_type_names.h"
#include "third_party/blink/renderer/modules/payments/payment_test_helper.h"
#include "third_party/blink/renderer/platform/bindings/exception_code.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
namespace blink {
namespace {
class MockPaymentProvider : public payments::mojom::blink::PaymentRequest {
public:
// mojom::PaymentRequest
#if defined(OS_ANDROID)
void Init(
mojo::PendingRemote<payments::mojom::blink::PaymentRequestClient> client,
WTF::Vector<payments::mojom::blink::PaymentMethodDataPtr> method_data,
payments::mojom::blink::PaymentDetailsPtr details,
payments::mojom::blink::PaymentOptionsPtr options,
bool google_pay_bridge_eligible) override {
details_ = std::move(details);
}
#else
void Init(
mojo::PendingRemote<payments::mojom::blink::PaymentRequestClient> client,
WTF::Vector<payments::mojom::blink::PaymentMethodDataPtr> method_data,
payments::mojom::blink::PaymentDetailsPtr details,
payments::mojom::blink::PaymentOptionsPtr options) override {
details_ = std::move(details);
}
#endif
void Show(bool is_user_gesture, bool wait_for_updated_details) override {
NOTREACHED();
}
void Retry(
payments::mojom::blink::PaymentValidationErrorsPtr errors) override {
NOTREACHED();
}
void UpdateWith(
payments::mojom::blink::PaymentDetailsPtr update_with_details) override {
NOTREACHED();
}
void OnPaymentDetailsNotUpdated() override { NOTREACHED(); }
void Abort() override { NOTREACHED(); }
void Complete(payments::mojom::PaymentComplete result) override {
NOTREACHED();
}
void CanMakePayment() override { NOTREACHED(); }
void HasEnrolledInstrument() override { NOTREACHED(); }
mojo::PendingRemote<payments::mojom::blink::PaymentRequest>
CreatePendingRemoteAndBind() {
mojo::PendingRemote<payments::mojom::blink::PaymentRequest> remote;
receiver_.Bind(remote.InitWithNewPipeAndPassReceiver());
return remote;
}
payments::mojom::blink::PaymentDetailsPtr& GetDetails() { return details_; }
private:
mojo::Receiver<payments::mojom::blink::PaymentRequest> receiver_{this};
payments::mojom::blink::PaymentDetailsPtr details_;
};
// This test suite is about the optional total parameter of the PaymentRequest
// constructor.
class PaymentRequestOptionalTotalTest : public testing::Test {
public:
void SetUp() override {
payment_provider_ = std::make_unique<MockPaymentProvider>();
}
std::unique_ptr<MockPaymentProvider> payment_provider_;
ScopedTestingPlatformSupport<TestingPlatformSupport> platform_;
};
// This test requests a mix of app-store billing methods and normal payment
// methods. Total is required in this scenario.
TEST_F(PaymentRequestOptionalTotalTest,
AppStoreBillingFlagEnabledTotalIsRequiredWhenMixMethods) {
RuntimeEnabledFeatures::SetDigitalGoodsEnabled(true);
PaymentRequestV8TestingScope scope;
// Intentionally leaves the total of details unset.
PaymentDetailsInit* details = PaymentDetailsInit::Create();
HeapVector<Member<PaymentMethodData>> method_data(2);
method_data[0] = PaymentMethodData::Create();
method_data[0]->setSupportedMethod("foo");
method_data[1] = PaymentMethodData::Create();
method_data[1]->setSupportedMethod("https://play.google.com/billing");
PaymentRequest::Create(scope.GetExecutionContext(), method_data, details,
scope.GetExceptionState());
EXPECT_TRUE(scope.GetExceptionState().HadException());
EXPECT_EQ("required member details is undefined.",
scope.GetExceptionState().Message());
EXPECT_FALSE(payment_provider_->GetDetails());
}
// When the DigitalGoods flag is disabled: although this test requests a
// app-store billing methods, total is required.
TEST_F(PaymentRequestOptionalTotalTest,
AppStoreBillingFlagDisabledTotalIsRequiredWhenMixMethods) {
RuntimeEnabledFeatures::SetDigitalGoodsEnabled(false);
PaymentRequestV8TestingScope scope;
// Intentionally leaves the total of details unset.
PaymentDetailsInit* details = PaymentDetailsInit::Create();
HeapVector<Member<PaymentMethodData>> method_data(1);
method_data[0] = PaymentMethodData::Create();
method_data[0]->setSupportedMethod("https://play.google.com/billing");
PaymentRequest::Create(scope.GetExecutionContext(), method_data, details,
scope.GetExceptionState());
EXPECT_TRUE(scope.GetExceptionState().HadException());
EXPECT_EQ("required member details is undefined.",
scope.GetExceptionState().Message());
EXPECT_FALSE(payment_provider_->GetDetails());
}
// When the DigitalGoods flag is enabled: undefined total gets a place holder
// when only requesting app-store billing methods.
TEST_F(PaymentRequestOptionalTotalTest,
AppStoreBillingFlagEnabledTotalGetPlaceHolder) {
RuntimeEnabledFeatures::SetDigitalGoodsEnabled(true);
PaymentRequestV8TestingScope scope;
// Intentionally leaves the total of details unset.
PaymentDetailsInit* details = PaymentDetailsInit::Create();
HeapVector<Member<PaymentMethodData>> method_data(
1, PaymentMethodData::Create());
method_data[0]->setSupportedMethod("https://play.google.com/billing");
MakeGarbageCollected<PaymentRequest>(
scope.GetExecutionContext(), method_data, details,
PaymentOptions::Create(), payment_provider_->CreatePendingRemoteAndBind(),
ASSERT_NO_EXCEPTION);
platform_->RunUntilIdle();
EXPECT_FALSE(scope.GetExceptionState().HadException());
EXPECT_EQ("0", payment_provider_->GetDetails()->total->amount->value);
EXPECT_EQ("ZZZ", payment_provider_->GetDetails()->total->amount->currency);
}
// When the DigitalGoods flag is disabled: undefined total is rejected.
TEST_F(PaymentRequestOptionalTotalTest,
AppStoreBillingFlagDisabledTotalGetRejected) {
RuntimeEnabledFeatures::SetDigitalGoodsEnabled(false);
PaymentRequestV8TestingScope scope;
// Intentionally leaves the total of details unset.
PaymentDetailsInit* details = PaymentDetailsInit::Create();
HeapVector<Member<PaymentMethodData>> method_data(
1, PaymentMethodData::Create());
method_data[0]->setSupportedMethod("https://play.google.com/billing");
MakeGarbageCollected<PaymentRequest>(
scope.GetExecutionContext(), method_data, details,
PaymentOptions::Create(), payment_provider_->CreatePendingRemoteAndBind(),
scope.GetExceptionState());
platform_->RunUntilIdle();
// Verify that total is required.
EXPECT_TRUE(scope.GetExceptionState().HadException());
EXPECT_EQ("required member details is undefined.",
scope.GetExceptionState().Message());
EXPECT_FALSE(payment_provider_->GetDetails());
}
// When the DigitalGoods flag is enabled: total get overridden when only
// requesting app-store billing methods.
TEST_F(PaymentRequestOptionalTotalTest,
AppStoreBillingFlagEnabledTotalGetOverridden) {
RuntimeEnabledFeatures::SetDigitalGoodsEnabled(true);
PaymentRequestV8TestingScope scope;
PaymentDetailsInit* details = PaymentDetailsInit::Create();
// Set a non-empty total.
details->setTotal((BuildPaymentItemForTest()));
HeapVector<Member<PaymentMethodData>> method_data(
1, PaymentMethodData::Create());
method_data[0]->setSupportedMethod("https://play.google.com/billing");
MakeGarbageCollected<PaymentRequest>(
scope.GetExecutionContext(), method_data, details,
PaymentOptions::Create(), payment_provider_->CreatePendingRemoteAndBind(),
ASSERT_NO_EXCEPTION);
platform_->RunUntilIdle();
EXPECT_FALSE(scope.GetExceptionState().HadException());
// Verify that the total get overridden.
EXPECT_EQ("0", payment_provider_->GetDetails()->total->amount->value);
EXPECT_EQ("ZZZ", payment_provider_->GetDetails()->total->amount->currency);
}
// When the DigitalGoods flag is disabled: total does not get overridden when
// only requesting app-store billing methods.
TEST_F(PaymentRequestOptionalTotalTest,
AppStoreBillingFlagDisabledTotalNotGetOverridden) {
RuntimeEnabledFeatures::SetDigitalGoodsEnabled(false);
PaymentRequestV8TestingScope scope;
PaymentDetailsInit* details = PaymentDetailsInit::Create();
// Set a non-empty total.
details->setTotal(BuildPaymentItemForTest());
HeapVector<Member<PaymentMethodData>> method_data(
1, PaymentMethodData::Create());
method_data[0]->setSupportedMethod("https://play.google.com/billing");
MakeGarbageCollected<PaymentRequest>(
scope.GetExecutionContext(), method_data, details,
PaymentOptions::Create(), payment_provider_->CreatePendingRemoteAndBind(),
ASSERT_NO_EXCEPTION);
platform_->RunUntilIdle();
// Verify that the total is set.
EXPECT_FALSE(scope.GetExceptionState().HadException());
EXPECT_TRUE(payment_provider_->GetDetails()->total);
}
} // namespace
} // namespace blink