blob: 3cc11e6cbf3985334113185724d547c50059b37d [file] [log] [blame]
// Copyright 2017 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 "components/payments/core/payment_details.h"
#include "base/values.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace payments {
// Tests the success case when populating a PaymentDetails from a dictionary.
TEST(PaymentRequestTest, PaymentDetailsFromValueSuccess) {
PaymentDetails expected;
expected.error = "Error in details";
base::Value details_dict(base::Value::Type::DICTIONARY);
details_dict.SetStringKey("error", "Error in details");
PaymentDetails actual;
EXPECT_TRUE(actual.FromValue(details_dict, /*requires_total=*/false));
EXPECT_EQ(expected, actual);
expected.total = std::make_unique<PaymentItem>();
expected.total->label = "TOTAL";
expected.total->amount->currency = "GBP";
expected.total->amount->value = "6.66";
base::Value total_dict(base::Value::Type::DICTIONARY);
total_dict.SetStringKey("label", "TOTAL");
base::Value amount_dict(base::Value::Type::DICTIONARY);
amount_dict.SetStringKey("currency", "GBP");
amount_dict.SetStringKey("value", "6.66");
total_dict.SetKey("amount", std::move(amount_dict));
details_dict.SetKey("total", std::move(total_dict));
PaymentItem display1;
display1.label = "Handling";
display1.amount->currency = "GBP";
display1.amount->value = "1.23";
display1.pending = true;
expected.display_items.push_back(display1);
base::Value display_items_list(base::Value::Type::LIST);
display_items_list.Append(display1.ToValue());
details_dict.SetKey("displayItems", std::move(display_items_list));
PaymentShippingOption expect_shipping_option;
expect_shipping_option.id = "Post office";
expect_shipping_option.label = "Post office, one-week ground";
expect_shipping_option.amount = mojom::PaymentCurrencyAmount::New();
expect_shipping_option.amount->currency = "USD";
expect_shipping_option.amount->value = "5.0";
expected.shipping_options.push_back(std::move(expect_shipping_option));
base::Value shipping_options_list(base::Value::Type::LIST);
base::Value shipping_option(base::Value::Type::DICTIONARY);
shipping_option.SetStringKey("id", "Post office");
shipping_option.SetStringKey("label", "Post office, one-week ground");
base::Value shipping_amount(base::Value::Type::DICTIONARY);
shipping_amount.SetStringKey("currency", "USD");
shipping_amount.SetStringKey("value", "5.0");
shipping_option.SetKey("amount", std::move(shipping_amount));
shipping_options_list.Append(std::move(shipping_option));
details_dict.SetKey("shippingOptions", std::move(shipping_options_list));
EXPECT_TRUE(actual.FromValue(details_dict, /*requires_total=*/false));
EXPECT_EQ(expected, actual);
EXPECT_TRUE(actual.FromValue(details_dict, /*requires_total=*/true));
EXPECT_EQ(expected, actual);
// Test specifying ID.
details_dict.SetStringKey("id", "1234");
expected.id = "1234";
EXPECT_TRUE(actual.FromValue(details_dict, /*requires_total=*/false));
EXPECT_EQ(expected, actual);
// Test without total when not requiring it.
{
PaymentDetails actual2;
expected.total.reset();
details_dict.RemoveKey("total");
EXPECT_TRUE(actual2.FromValue(details_dict, /*requires_total=*/false));
EXPECT_EQ(expected, actual2);
}
}
// Tests the failure case when populating a PaymentDetails from a dictionary.
TEST(PaymentRequestTest, PaymentDetailsFromValueFailure) {
base::Value details_dict(base::Value::Type::DICTIONARY);
details_dict.SetStringKey("error", "Error in details");
PaymentDetails actual;
EXPECT_FALSE(actual.FromValue(details_dict, /*requires_total=*/true));
// Invalid total.
base::Value total_dict(base::Value::Type::DICTIONARY);
details_dict.SetKey("total", std::move(total_dict));
EXPECT_FALSE(actual.FromValue(details_dict, /*requires_total=*/false));
details_dict.RemoveKey("total");
// Invalid display item.
base::Value display_items_list(base::Value::Type::LIST);
display_items_list.Append("huh");
details_dict.SetKey("displayItems", std::move(display_items_list));
EXPECT_FALSE(actual.FromValue(details_dict, /*requires_total=*/false));
details_dict.RemoveKey("displayItems");
// Invalid shipping option.
base::Value shipping_options_list(base::Value::Type::LIST);
shipping_options_list.Append("nonsense");
details_dict.SetKey("shippingOptions", std::move(shipping_options_list));
EXPECT_FALSE(actual.FromValue(details_dict, /*requires_total=*/false));
details_dict.RemoveKey("shippingOptions");
// Invalid modifiers.
base::Value modifiers_list(base::Value::Type::LIST);
modifiers_list.Append("not a payment method dict");
details_dict.SetKey("modifiers", std::move(modifiers_list));
EXPECT_FALSE(actual.FromValue(details_dict, /*requires_total=*/false));
// Invalid modifier total.
details_dict.FindKey("modifiers")->ClearList();
base::Value payment_method(base::Value::Type::DICTIONARY);
payment_method.SetStringKey("supportedMethods", "MuenterCard");
base::Value invalid_total_dict(base::Value::Type::DICTIONARY);
payment_method.SetKey("total", std::move(invalid_total_dict));
details_dict.FindKey("modifiers")->Append(std::move(payment_method));
EXPECT_FALSE(actual.FromValue(details_dict, /*requires_total=*/false));
details_dict.FindKey("modifiers")->GetList()[0].RemoveKey("total");
// Invalid additional_display_item in modifiers.
base::Value additional_display_items_list(base::Value::Type::LIST);
additional_display_items_list.Append("not a payment item");
details_dict.FindKey("modifiers")
->GetList()[0]
.SetKey("additionalDisplayItems",
std::move(additional_display_items_list));
EXPECT_FALSE(actual.FromValue(details_dict, /*requires_total=*/false));
// Check error-handling of non-dictionary input value.
EXPECT_FALSE(actual.FromValue(base::Value("hi"), /*requires_total=*/false));
}
// Tests that two payment details objects are not equal if their property values
// differ or one is missing a value present in the other, and equal otherwise.
// Doesn't test all properties of child objects, relying instead on their
// respective tests.
TEST(PaymentRequestTest, PaymentDetailsEquality) {
PaymentDetails details1;
PaymentDetails details2;
EXPECT_EQ(details1, details2);
details1.id = "12345";
EXPECT_NE(details1, details2);
details2.id = "54321";
EXPECT_NE(details1, details2);
details2.id = details1.id;
EXPECT_EQ(details1, details2);
details1.total = std::make_unique<PaymentItem>();
details1.total->label = "Total";
EXPECT_NE(details1, details2);
details2.total = std::make_unique<PaymentItem>();
details2.total->label = "Shipping";
EXPECT_NE(details1, details2);
details2.total->label = "Total";
EXPECT_EQ(details1, details2);
details1.error = "Foo";
EXPECT_NE(details1, details2);
details2.error = "Bar";
EXPECT_NE(details1, details2);
details2.error = "Foo";
EXPECT_EQ(details1, details2);
PaymentItem payment_item;
payment_item.label = "Tax";
std::vector<PaymentItem> display_items1;
display_items1.push_back(payment_item);
details1.display_items = display_items1;
EXPECT_NE(details1, details2);
std::vector<PaymentItem> display_items2;
display_items2.push_back(payment_item);
display_items2.push_back(payment_item);
details2.display_items = display_items2;
EXPECT_NE(details1, details2);
details2.display_items = display_items1;
EXPECT_EQ(details1, details2);
PaymentShippingOption shipping_option;
shipping_option.label = "Overnight";
std::vector<PaymentShippingOption> shipping_options1;
shipping_options1.push_back(shipping_option);
details1.shipping_options = shipping_options1;
EXPECT_NE(details1, details2);
std::vector<PaymentShippingOption> shipping_options2;
shipping_options2.push_back(shipping_option);
shipping_options2.push_back(shipping_option);
details2.shipping_options = shipping_options2;
EXPECT_NE(details1, details2);
details2.shipping_options = shipping_options1;
EXPECT_EQ(details1, details2);
PaymentDetailsModifier details_modifier;
details_modifier.total = std::make_unique<PaymentItem>();
details_modifier.total->label = "Total";
details1.modifiers.push_back(details_modifier);
EXPECT_NE(details1, details2);
details2.modifiers.push_back(details_modifier);
EXPECT_EQ(details1, details2);
}
} // namespace payments