| <!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 MerchantValidationEvent Constructor</title> | |
| <link rel="help" href="https://w3c.github.io/browser-payment-api/#merchantvalidationevent-constructor"> | |
| <script src="/resources/testharness.js"></script> | |
| <script src="/resources/testharnessreport.js"></script> | |
| <script> | |
| const applePay = Object.freeze({ | |
| supportedMethods: "https://apple.com/apple-pay", | |
| data: { | |
| version: 3, | |
| merchantIdentifier: "merchant.com.example", | |
| countryCode: "US", | |
| merchantCapabilities: ["supports3DS"], | |
| supportedNetworks: ["visa"], | |
| } | |
| }); | |
| const examplePay = Object.freeze({ supportedMethods: "https://example.com/pay" }); | |
| const defaultMethods = Object.freeze([examplePay, applePay]); | |
| const defaultDetails = Object.freeze({ | |
| total: { | |
| label: "Total", | |
| amount: { | |
| currency: "USD", | |
| value: "1.00", | |
| }, | |
| }, | |
| }); | |
| test(() => { | |
| new MerchantValidationEvent("test"); | |
| }, "MerchantValidationEvent can be constructed in secure-context."); | |
| test(() => { | |
| const ev = new MerchantValidationEvent("test", { | |
| bubbles: true, | |
| cancelable: true, | |
| composed: true, | |
| }); | |
| assert_false(ev.isTrusted, "constructed in script, so not trusted"); | |
| assert_true(ev.bubbles, "set by EventInitDict"); | |
| assert_true(ev.cancelable, "set by EventInitDict"); | |
| assert_true(ev.composed, "set by EventInitDict"); | |
| assert_equals(ev.target, null, "initially null"); | |
| assert_equals(ev.type, "test"); | |
| }, "MerchantValidationEvent can be constructed with an EventInitDict, even if not trusted."); | |
| test(() => { | |
| const request = new PaymentRequest(defaultMethods, defaultDetails); | |
| const ev = new MerchantValidationEvent("test"); | |
| request.addEventListener("test", evt => { | |
| assert_equals(ev, evt); | |
| }); | |
| request.dispatchEvent(ev); | |
| }, "MerchantValidationEvent can be dispatched, even if not trusted."); | |
| test(() => { | |
| const validationURL = "https://pass.com"; | |
| const event = new MerchantValidationEvent("test", { validationURL }); | |
| assert_idl_attribute(event, "validationURL"); | |
| assert_equals(event.validationURL, "https://pass.com/"); | |
| }, "Must have a validationURL IDL attribute, which is initialized with to the validationURL dictionary value."); | |
| test(() => { | |
| const validationURL = "http://\u005B"; // invalid URL | |
| assert_throws_js(TypeError, () => { | |
| new MerchantValidationEvent("test", { validationURL }); | |
| }); | |
| }, "Must throw TypeError if initialized with an invalid URL."); | |
| test(() => { | |
| const validationURL = ""; | |
| const relativePaths = ["", ".", "/test"]; | |
| for (const path of relativePaths) { | |
| const event = new MerchantValidationEvent("test", { validationURL: path }); | |
| const expected = new URL(path, document.location.href).href; | |
| assert_equals(event.validationURL, expected); | |
| } | |
| }, "Relative validationURLs use the document as the base."); | |
| test(() => { | |
| const validationURL = "pass"; | |
| const base = document.createElement("base"); | |
| base.href = "https://pass.com"; | |
| document.head.append(base); | |
| const event = new MerchantValidationEvent("test", { validationURL }); | |
| try { | |
| assert_idl_attribute(event, "validationURL"); | |
| assert_equals(event.validationURL, "https://pass.com/pass"); | |
| } finally { | |
| base.remove(); | |
| } | |
| }, "Relative validationURLs use the document.baseURI as the base."); | |
| test(() => { | |
| const methodName = "https://pass.com"; | |
| const event = new MerchantValidationEvent("test", { methodName }); | |
| assert_idl_attribute(event, "methodName"); | |
| assert_equals(event.methodName, "https://pass.com"); | |
| }, "Must have a methodName IDL attribute, which is initialized with to the methodName dictionary value."); | |
| test(() => { | |
| const event = new MerchantValidationEvent("test", {}); | |
| assert_equals(event.methodName, ""); | |
| }, "When no methodName is passed, methodName attribute defaults to the empty string"); | |
| test(() => { | |
| const validPMIs = [ | |
| "https://example.com/pay", | |
| "https://example.com/pay?version=1", | |
| "https://example.com/pay/version/1", | |
| "secure-payment-confirmation", | |
| "https://apple.com/apple-pay", | |
| // special case for as default value | |
| "", | |
| ]; | |
| for (const methodName of validPMIs) { | |
| const event = new MerchantValidationEvent("test", { methodName }); | |
| assert_equals(event.methodName, methodName); | |
| } | |
| }, "MerchantValidationEvent can be constructed with valid PMIs"); | |
| test(() => { | |
| const invalidPMIs = [ | |
| // ❌ Contains Unicode character outside the valid ranges. | |
| "secure-💳", | |
| // ❌ Contains uppercase characters. | |
| "Secure-Payment-Confirmation", | |
| // ❌ Contains Unicode characters outside the valid ranges. | |
| "¡secure-*-payment-confirmation!", | |
| // ❌ Uses http://, a username, and a password. | |
| "http://username:password@example.com/pay", | |
| // ❌ Uses unknown URI scheme. | |
| "unknown://example.com/pay", | |
| ]; | |
| for (const methodName of invalidPMIs) { | |
| assert_throws_js( | |
| RangeError, | |
| () => { | |
| const event = new MerchantValidationEvent("test", { methodName }); | |
| }, | |
| `expected to throw when constructed with invalid PMI: '${methodName}'` | |
| ); | |
| } | |
| }, "MerchantValidationEvent can't be constructed with invalid PMIs"); | |
| </script> |