summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/payment-request/payment-request-constructor.https.sub.html
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /testing/web-platform/tests/payment-request/payment-request-constructor.https.sub.html
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/payment-request/payment-request-constructor.https.sub.html')
-rw-r--r--testing/web-platform/tests/payment-request/payment-request-constructor.https.sub.html477
1 files changed, 477 insertions, 0 deletions
diff --git a/testing/web-platform/tests/payment-request/payment-request-constructor.https.sub.html b/testing/web-platform/tests/payment-request/payment-request-constructor.https.sub.html
new file mode 100644
index 0000000000..c1ecc22583
--- /dev/null
+++ b/testing/web-platform/tests/payment-request/payment-request-constructor.https.sub.html
@@ -0,0 +1,477 @@
+<!DOCTYPE html>
+<!-- Copyright © 2017 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
+<meta charset="utf-8">
+<title>Test for PaymentRequest Constructor</title>
+<link rel="help" href="https://w3c.github.io/browser-payment-api/#constructor">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+"use strict";
+const testMethod = Object.freeze({
+ supportedMethods: "https://{{domains[nonexistent]}}/payment-request",
+});
+const defaultMethods = Object.freeze([testMethod]);
+const defaultAmount = Object.freeze({
+ currency: "USD",
+ value: "1.0",
+});
+const defaultNumberAmount = Object.freeze({
+ currency: "USD",
+ value: 1.0,
+});
+const defaultTotal = Object.freeze({
+ label: "Default Total",
+ amount: defaultAmount,
+});
+const defaultNumberTotal = Object.freeze({
+ label: "Default Number Total",
+ amount: defaultNumberAmount,
+});
+const defaultDetails = Object.freeze({
+ total: defaultTotal,
+ displayItems: [
+ {
+ label: "Default Display Item",
+ amount: defaultAmount,
+ },
+ ],
+});
+const defaultNumberDetails = Object.freeze({
+ total: defaultNumberTotal,
+ displayItems: [
+ {
+ label: "Default Display Item",
+ amount: defaultNumberAmount,
+ },
+ ],
+});
+
+// Avoid false positives, this should always pass
+function smokeTest() {
+ new PaymentRequest(defaultMethods, defaultDetails);
+ new PaymentRequest(defaultMethods, defaultNumberDetails);
+}
+test(() => {
+ smokeTest();
+ const request = new PaymentRequest(defaultMethods, defaultDetails);
+ assert_true(Boolean(request.id), "must be some truthy value");
+}, "If details.id is missing, assign an identifier");
+
+test(() => {
+ smokeTest();
+ const request1 = new PaymentRequest(defaultMethods, defaultDetails);
+ const request2 = new PaymentRequest(defaultMethods, defaultDetails);
+ assert_not_equals(request1.id, request2.id, "UA generated ID must be unique");
+ const seen = new Set();
+ // Let's try creating lots of requests, and make sure they are all unique
+ for (let i = 0; i < 1024; i++) {
+ const request = new PaymentRequest(defaultMethods, defaultDetails);
+ assert_false(
+ seen.has(request.id),
+ `UA generated ID must be unique, but got duplicate! (${request.id})`
+ );
+ seen.add(request.id);
+ }
+}, "If details.id is missing, assign a unique identifier");
+
+test(() => {
+ smokeTest();
+ const newDetails = Object.assign({}, defaultDetails, { id: "test123" });
+ const request1 = new PaymentRequest(defaultMethods, newDetails);
+ const request2 = new PaymentRequest(defaultMethods, newDetails);
+ assert_equals(request1.id, newDetails.id, `id must be ${newDetails.id}`);
+ assert_equals(request2.id, newDetails.id, `id must be ${newDetails.id}`);
+ assert_equals(request1.id, request2.id, "ids need to be the same");
+}, "If the same id is provided, then use it");
+
+test(() => {
+ smokeTest();
+ const newDetails = Object.assign({}, defaultDetails, {
+ id: "".padStart(1024, "a"),
+ });
+ const request = new PaymentRequest(defaultMethods, newDetails);
+ assert_equals(
+ request.id,
+ newDetails.id,
+ `id must be provided value, even if very long and contain spaces`
+ );
+}, "Use ids even if they are strange");
+
+test(() => {
+ smokeTest();
+ const request = new PaymentRequest(
+ defaultMethods,
+ Object.assign({}, defaultDetails, { id: "foo" })
+ );
+ assert_equals(request.id, "foo");
+}, "Use provided request ID");
+
+test(() => {
+ smokeTest();
+ assert_throws_js(TypeError, () => new PaymentRequest([], defaultDetails));
+}, "If the length of the methodData sequence is zero, then throw a TypeError");
+
+test(() => {
+ smokeTest();
+ const duplicateMethods = [
+ {
+ supportedMethods: "https://{{domains[nonexistent]}}/payment-request",
+ },
+ {
+ supportedMethods: "https://{{domains[nonexistent]}}/payment-request",
+ },
+ ];
+ assert_throws_js(RangeError, () => new PaymentRequest(duplicateMethods, defaultDetails));
+}, "If payment method is duplicate, then throw a RangeError");
+
+test(() => {
+ smokeTest();
+ const JSONSerializables = [[], { object: {} }];
+ for (const data of JSONSerializables) {
+ try {
+ const methods = [
+ {
+ supportedMethods: "https://{{domains[nonexistent]}}/payment-request",
+ data,
+ },
+ ];
+ new PaymentRequest(methods, defaultDetails);
+ } catch (err) {
+ assert_unreached(
+ `Unexpected error parsing stringifiable JSON: ${JSON.stringify(
+ data
+ )}: ${err.message}`
+ );
+ }
+ }
+}, "Modifier method data must be JSON-serializable object");
+
+test(() => {
+ smokeTest();
+ const recursiveDictionary = {};
+ recursiveDictionary.foo = recursiveDictionary;
+ assert_throws_js(TypeError, () => {
+ const methods = [
+ {
+ supportedMethods: "https://{{domains[nonexistent]}}/payment-request",
+ data: recursiveDictionary,
+ },
+ ];
+ new PaymentRequest(methods, defaultDetails);
+ });
+ assert_throws_js(TypeError, () => {
+ const methods = [
+ {
+ supportedMethods: "https://{{domains[nonexistent]}}/payment-request",
+ data: "a string",
+ },
+ ];
+ new PaymentRequest(methods, defaultDetails);
+ });
+ assert_throws_js(
+ TypeError,
+ () => {
+ const methods = [
+ {
+ supportedMethods: "https://{{domains[nonexistent]}}/payment-request",
+ data: null,
+ },
+ ];
+ new PaymentRequest(methods, defaultDetails);
+ },
+ "Even though null is JSON-serializable, it's not type 'Object' per ES spec"
+ );
+}, "Rethrow any exceptions of JSON-serializing paymentMethod.data into a string");
+
+// process total
+const invalidAmounts = [
+ "-",
+ "notdigits",
+ "ALSONOTDIGITS",
+ "10.",
+ ".99",
+ "-10.",
+ "-.99",
+ "10-",
+ "1-0",
+ "1.0.0",
+ "1/3",
+ "",
+ null,
+ " 1.0 ",
+ " 1.0 ",
+ "1.0 ",
+ "USD$1.0",
+ "$1.0",
+ {
+ toString() {
+ return " 1.0";
+ },
+ },
+];
+const invalidTotalAmounts = invalidAmounts.concat([
+ "-1",
+ "-1.0",
+ "-1.00",
+ "-1000.000",
+ -10,
+]);
+test(() => {
+ smokeTest();
+ for (const invalidAmount of invalidTotalAmounts) {
+ const invalidDetails = {
+ total: {
+ label: "",
+ amount: {
+ currency: "USD",
+ value: invalidAmount,
+ },
+ },
+ };
+ assert_throws_js(
+ TypeError,
+ () => {
+ new PaymentRequest(defaultMethods, invalidDetails);
+ },
+ `Expect TypeError when details.total.amount.value is ${invalidAmount}`
+ );
+ }
+}, `If details.total.amount.value is not a valid decimal monetary value, then throw a TypeError`);
+
+test(() => {
+ smokeTest();
+ for (const prop in ["displayItems", "modifiers"]) {
+ try {
+ const details = Object.assign({}, defaultDetails, { [prop]: [] });
+ new PaymentRequest(defaultMethods, details);
+ assert_unreached(`PaymentDetailsBase.${prop} can be zero length`);
+ } catch (err) {}
+ }
+}, `PaymentDetailsBase members can be 0 length`);
+
+test(() => {
+ smokeTest();
+ assert_throws_js(TypeError, () => {
+ new PaymentRequest(defaultMethods, {
+ total: {
+ label: "",
+ amount: {
+ currency: "USD",
+ value: "-1.00",
+ },
+ },
+ });
+ });
+}, "If the first character of details.total.amount.value is U+002D HYPHEN-MINUS, then throw a TypeError");
+
+test(() => {
+ smokeTest();
+ for (const invalidAmount of invalidAmounts) {
+ const invalidDetails = {
+ total: defaultAmount,
+ displayItems: [
+ {
+ label: "",
+ amount: {
+ currency: "USD",
+ value: invalidAmount,
+ },
+ },
+ ],
+ };
+ assert_throws_js(
+ TypeError,
+ () => {
+ new PaymentRequest(defaultMethods, invalidDetails);
+ },
+ `Expected TypeError when item.amount.value is "${invalidAmount}"`
+ );
+ }
+}, `For each item in details.displayItems: if item.amount.value is not a valid decimal monetary value, then throw a TypeError`);
+
+test(() => {
+ smokeTest();
+ try {
+ new PaymentRequest(
+ [
+ {
+ supportedMethods: "https://{{domains[nonexistent]}}/payment-request",
+ },
+ ],
+ {
+ total: defaultTotal,
+ displayItems: [
+ {
+ label: "",
+ amount: {
+ currency: "USD",
+ value: "-1000",
+ },
+ },
+ {
+ label: "",
+ amount: {
+ currency: "AUD",
+ value: "-2000.00",
+ },
+ },
+ ],
+ }
+ );
+ } catch (err) {
+ assert_unreached(
+ `shouldn't throw when given a negative value: ${err.message}`
+ );
+ }
+}, "Negative values are allowed for displayItems.amount.value, irrespective of total amount");
+
+test(() => {
+ smokeTest();
+ const largeMoney = "1".repeat(510);
+ try {
+ new PaymentRequest(defaultMethods, {
+ total: {
+ label: "",
+ amount: {
+ currency: "USD",
+ value: `${largeMoney}.${largeMoney}`,
+ },
+ },
+ displayItems: [
+ {
+ label: "",
+ amount: {
+ currency: "USD",
+ value: `-${largeMoney}`,
+ },
+ },
+ {
+ label: "",
+ amount: {
+ currency: "AUD",
+ value: `-${largeMoney}.${largeMoney}`,
+ },
+ },
+ ],
+ });
+ } catch (err) {
+ assert_unreached(
+ `shouldn't throw when given absurd monetary values: ${err.message}`
+ );
+ }
+}, "it handles high precision currency values without throwing");
+
+// Process payment details modifiers:
+test(() => {
+ smokeTest();
+ for (const invalidTotal of invalidTotalAmounts) {
+ const invalidModifier = {
+ supportedMethods: "https://{{domains[nonexistent]}}/payment-request",
+ total: {
+ label: "",
+ amount: {
+ currency: "USD",
+ value: invalidTotal,
+ },
+ },
+ };
+ assert_throws_js(
+ TypeError,
+ () => {
+ new PaymentRequest(defaultMethods, {
+ modifiers: [invalidModifier],
+ total: defaultTotal,
+ });
+ },
+ `Expected TypeError for modifier.total.amount.value: "${invalidTotal}"`
+ );
+ }
+}, `Throw TypeError if modifier.total.amount.value is not a valid decimal monetary value`);
+
+test(() => {
+ smokeTest();
+ for (const invalidAmount of invalidAmounts) {
+ const invalidModifier = {
+ supportedMethods: "https://{{domains[nonexistent]}}/payment-request",
+ total: defaultTotal,
+ additionalDisplayItems: [
+ {
+ label: "",
+ amount: {
+ currency: "USD",
+ value: invalidAmount,
+ },
+ },
+ ],
+ };
+ assert_throws_js(
+ TypeError,
+ () => {
+ new PaymentRequest(defaultMethods, {
+ modifiers: [invalidModifier],
+ total: defaultTotal,
+ });
+ },
+ `Expected TypeError when given bogus modifier.additionalDisplayItems.amount of "${invalidModifier}"`
+ );
+ }
+}, `If amount.value of additionalDisplayItems is not a valid decimal monetary value, then throw a TypeError`);
+
+test(() => {
+ smokeTest();
+ const modifiedDetails = Object.assign({}, defaultDetails, {
+ modifiers: [
+ {
+ supportedMethods: "https://{{domains[nonexistent]}}/payment-request",
+ data: ["some-data"],
+ },
+ ],
+ });
+ try {
+ new PaymentRequest(defaultMethods, modifiedDetails);
+ } catch (err) {
+ assert_unreached(
+ `Unexpected exception thrown when given a list: ${err.message}`
+ );
+ }
+}, "Modifier data must be JSON-serializable object (an Array in this case)");
+
+test(() => {
+ smokeTest();
+ const modifiedDetails = Object.assign({}, defaultDetails, {
+ modifiers: [
+ {
+ supportedMethods: "https://{{domains[nonexistent]}}/payment-request",
+ data: {
+ some: "data",
+ },
+ },
+ ],
+ });
+ try {
+ new PaymentRequest(defaultMethods, modifiedDetails);
+ } catch (err) {
+ assert_unreached(
+ `shouldn't throw when given an object value: ${err.message}`
+ );
+ }
+}, "Modifier data must be JSON-serializable object (an Object in this case)");
+
+test(() => {
+ smokeTest();
+ const recursiveDictionary = {};
+ recursiveDictionary.foo = recursiveDictionary;
+ const modifiedDetails = Object.assign({}, defaultDetails, {
+ modifiers: [
+ {
+ supportedMethods: "https://{{domains[nonexistent]}}/payment-request",
+ data: recursiveDictionary,
+ },
+ ],
+ });
+ assert_throws_js(TypeError, () => {
+ new PaymentRequest(defaultMethods, modifiedDetails);
+ });
+}, "Rethrow any exceptions of JSON-serializing modifier.data");
+
+</script>