blob: 9339958e85a7181012838ed316d6bdccd756fab0 [file] [log] [blame] [edit]
<!DOCTYPE html>
<meta charset="utf-8">
<title>Tests for providing `deferredPaymentRequest` as part of `ApplePayModifier`.</title>
<script src="/js-test-resources/ui-helper.js"></script>
<script src="/resources/payment-request.js"></script>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script>
setup({ explicit_done: true, explicit_timeout: true });
test((test) => {
const method = validPaymentMethod();
method.data.features = ["paymentRequestDeferred"];
new PaymentRequest([method], validPaymentDetails());
}, "Should have a feature for `deferredPaymentRequest`.");
function daysFromToday(days) {
date = new Date();
date.setDate(date.getDate() + days);
return date;
}
const paymentDescription = "paymentDescription";
const deferredBilling = { label: "deferredBilling", amount: "5", type: "final", paymentTiming: "deferred", deferredPaymentDate: daysFromToday(14) };
const deferredBillingOut = { ...deferredBilling, recurringPaymentIntervalUnit: "month", recurringPaymentIntervalCount: 1 };
const billingAgreement = "billingAgreement";
const managementURL = "http://managementURL.com";
const tokenNotificationURL = "http://tokenNotificationURL.com";
const freeCancellationDate = daysFromToday(7);
const freeCancellationDateTimeZone = "America/Los_Angeles";
function modifiersWithData(data) {
return [ { supportedMethods: 'https://apple.com/apple-pay', data } ];
}
function testValidDeferredPaymentRequest(description, {initialDeferredPaymentRequest, expectedDeferredPaymentRequest}) {
user_activation_test(async (test) => {
let detailsInit = validPaymentDetails();
if (initialDeferredPaymentRequest !== undefined)
detailsInit.modifiers = modifiersWithData({ deferredPaymentRequest: initialDeferredPaymentRequest });
let request = new PaymentRequest([validPaymentMethod()], detailsInit);
request.addEventListener("merchantvalidation", (event) => {
event.complete({ });
});
request.addEventListener("shippingaddresschange", (event) => {
event.updateWith({ });
internals.mockPaymentCoordinator.acceptPayment();
});
let response = await request.show();
let actualDeferredPaymentRequest = internals.mockPaymentCoordinator.deferredPaymentRequest;
if (actualDeferredPaymentRequest)
assert_object_equals(actualDeferredPaymentRequest, expectedDeferredPaymentRequest, "check that the `deferredPaymentRequest` matches");
else
assert_equals(actualDeferredPaymentRequest, expectedDeferredPaymentRequest, "check that the `deferredPaymentRequest` matches");
await response.complete("success");
}, description + " as part of the request.");
user_activation_test(async (test) => {
let request = new PaymentRequest([validPaymentMethod()], validPaymentDetails());
request.addEventListener("merchantvalidation", (event) => {
event.complete({ });
});
request.addEventListener("shippingaddresschange", (event) => {
let detailsUpdate = { };
if (initialDeferredPaymentRequest !== undefined)
detailsUpdate.modifiers = modifiersWithData({ deferredPaymentRequest: initialDeferredPaymentRequest });
event.updateWith(detailsUpdate);
internals.mockPaymentCoordinator.acceptPayment();
});
let response = await request.show();
let actualDeferredPaymentRequest = internals.mockPaymentCoordinator.deferredPaymentRequest;
if (actualDeferredPaymentRequest)
assert_object_equals(actualDeferredPaymentRequest, expectedDeferredPaymentRequest, "check that the `deferredPaymentRequest` matches");
else
assert_equals(actualDeferredPaymentRequest, expectedDeferredPaymentRequest, "check that the `deferredPaymentRequest` matches");
await response.complete("success");
}, description + " as part of an update.");
}
testValidDeferredPaymentRequest("The default value of `deferredPaymentRequest` should be `null` if `data` is not provided", {
initialDeferredPaymentRequest: undefined,
expectedDeferredPaymentRequest: null,
});
testValidDeferredPaymentRequest("Should not error if optional properties are not provided", {
initialDeferredPaymentRequest: { paymentDescription, deferredBilling, managementURL },
expectedDeferredPaymentRequest: { paymentDescription, deferredBilling: deferredBillingOut, managementURL },
});
testValidDeferredPaymentRequest("Should not error if optional free-cancellation-date properties are not provided", {
initialDeferredPaymentRequest: { paymentDescription, deferredBilling, billingAgreement, managementURL, tokenNotificationURL },
expectedDeferredPaymentRequest: { paymentDescription, deferredBilling: deferredBillingOut, billingAgreement, managementURL, tokenNotificationURL },
});
testValidDeferredPaymentRequest("Should propagate all data", {
initialDeferredPaymentRequest: { paymentDescription, deferredBilling, billingAgreement, managementURL, tokenNotificationURL, freeCancellationDate, freeCancellationDateTimeZone },
expectedDeferredPaymentRequest: { paymentDescription, deferredBilling: deferredBillingOut, billingAgreement, managementURL, tokenNotificationURL, freeCancellationDate, freeCancellationDateTimeZone },
});
function testInvalidDeferredPaymentRequest(description, {deferredPaymentRequest, expectedErrorSubstring}) {
user_activation_test(async (test) => {
let detailsInit = validPaymentDetails();
detailsInit.modifiers = modifiersWithData({ deferredPaymentRequest });
let request = new PaymentRequest([validPaymentMethod()], detailsInit);
try {
let response = await request.show();
internals.mockPaymentCoordinator.cancelPayment();
assert_true(false, "should error about " + expectedErrorSubstring);
} catch (e) {
assert_true(e.message.includes(expectedErrorSubstring), "should error with '" + expectedErrorSubstring + "' but got '" + e.message + "'");
}
}, description + " as part of the request.");
user_activation_test(async (test) => {
let request = new PaymentRequest([validPaymentMethod()], validPaymentDetails());
request.addEventListener("merchantvalidation", (event) => {
event.complete({ });
});
request.addEventListener("shippingaddresschange", (event) => {
event.updateWith({ modifiers: modifiersWithData({ deferredPaymentRequest }) });
});
try {
let response = await request.show();
internals.mockPaymentCoordinator.cancelPayment();
assert_true(false, "should error about " + expectedErrorSubstring);
} catch (e) {
assert_true(e.message.includes(expectedErrorSubstring), "should error with '" + expectedErrorSubstring + "' but got '" + e.message + "'");
}
}, description + " as part of an update.");
}
testInvalidDeferredPaymentRequest("Should error when `deferredBilling` is missing `paymentTiming`", {
deferredPaymentRequest: { paymentDescription, deferredBilling: { } , managementURL },
expectedErrorSubstring: "'deferredBilling' must be a 'deferred' line item",
});
testInvalidDeferredPaymentRequest("Should error when `deferredBilling` has an invalid `paymentTiming`", {
deferredPaymentRequest: { paymentDescription, deferredBilling: { paymentTiming: "whenever" } , managementURL },
expectedErrorSubstring: "Type error", // Would have preferred "'deferredBilling' must be a 'deferred' line item", but the enum parser caught it first.
});
testInvalidDeferredPaymentRequest("Should error when `deferredBilling.paymentTiming` is not 'deferred'", {
deferredPaymentRequest: { paymentDescription, deferredBilling: { paymentTiming: "immediate" } , managementURL },
expectedErrorSubstring: "must be a 'deferred' line item",
});
testInvalidDeferredPaymentRequest("Should error when `deferredBilling` is missing `label`", {
deferredPaymentRequest: { paymentDescription, deferredBilling: { paymentTiming: "deferred" } , managementURL },
expectedErrorSubstring: "Missing label for 'deferredBilling'",
});
testInvalidDeferredPaymentRequest("Should error when `deferredBilling` is missing `amount`", {
deferredPaymentRequest: { paymentDescription, deferredBilling: { paymentTiming: "deferred", label: "deferredBillingBad" } , managementURL },
expectedErrorSubstring: "not a valid amount",
});
testInvalidDeferredPaymentRequest("Should error when `deferredBilling` has an invalid `amount`", {
deferredPaymentRequest: { paymentDescription, deferredBilling: { paymentTiming: "deferred", label: "deferredBillingBad", amount: "invalid" } , managementURL },
expectedErrorSubstring: "not a valid amount",
});
testInvalidDeferredPaymentRequest("Should error when there is a `freeCancellationDate` without `freeCancellationDateTimeZone`", {
deferredPaymentRequest: { paymentDescription, deferredBilling, managementURL, billingAgreement, freeCancellationDate },
expectedErrorSubstring: "Missing 'freeCancellationDateTimeZone' when 'freeCancellationDate' is set",
});
testInvalidDeferredPaymentRequest("Should error when there is a `freeCancellationDateTimeZone` without `freeCancellationDate`", {
deferredPaymentRequest: { paymentDescription, deferredBilling, managementURL, billingAgreement, freeCancellationDateTimeZone },
expectedErrorSubstring: "Unexpected 'freeCancellationDateTimeZone' when 'freeCancellationDate' is not set",
});
testInvalidDeferredPaymentRequest("Should error when `freeCancellationDate` is not a valid Date", {
deferredPaymentRequest: { paymentDescription, deferredBilling, managementURL, freeCancellationDate: "Tomorrow", freeCancellationDateTimeZone },
expectedErrorSubstring: "Unexpected 'freeCancellationDateTimeZone' when 'freeCancellationDate' is not set", // Would have preferred "not a valid date", but Date parser removed the property.
});
testInvalidDeferredPaymentRequest("Should error when `freeCancellationDateTimeZone` is not a valid time zone", {
deferredPaymentRequest: { paymentDescription, deferredBilling, managementURL, freeCancellationDate, freeCancellationDateTimeZone: "Backyard" },
expectedErrorSubstring: "not a valid time zone",
});
testInvalidDeferredPaymentRequest("Should error when `managementURL` is not a valid URL", {
deferredPaymentRequest: { paymentDescription, deferredBilling, managementURL: 42 },
expectedErrorSubstring: "not a valid URL",
});
testInvalidDeferredPaymentRequest("Should error when `tokenNotificationURL` is not a valid URL", {
deferredPaymentRequest: { paymentDescription, deferredBilling, managementURL, tokenNotificationURL: 42 },
expectedErrorSubstring: "not a valid URL",
});
done();
</script>