diff options
Diffstat (limited to 'testing/web-platform/tests/payment-handler')
33 files changed, 1622 insertions, 0 deletions
diff --git a/testing/web-platform/tests/payment-handler/META.yml b/testing/web-platform/tests/payment-handler/META.yml new file mode 100644 index 0000000000..eff7624d05 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/META.yml @@ -0,0 +1,4 @@ +spec: https://w3c.github.io/payment-handler/ +suggested_reviewers: + - marcoscaceres + - rsolomakhin diff --git a/testing/web-platform/tests/payment-handler/app-can-make-payment.js b/testing/web-platform/tests/payment-handler/app-can-make-payment.js new file mode 100644 index 0000000000..6b060dffb7 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/app-can-make-payment.js @@ -0,0 +1,57 @@ +let responseType = 'canMakePayment-true'; + +self.addEventListener('canmakepayment', event => { + if (event.methodData) { + const msg = 'Expected no method data.'; + event.respondWith(Promise.reject(new Error(msg))); + return; + } + + if (event.modifiers) { + const msg = 'Expected no modifiers'; + event.respondWith(Promise.reject(new Error(msg))); + return; + } + + if (event.topOrigin) { + const msg = `Unexpected topOrigin.`; + event.respondWith(Promise.reject(new Error(msg))); + return; + } + + if (event.paymentRequestOrigin) { + const msg = `Unexpected iframe origin.`; + event.respondWith(Promise.reject(new Error(msg))); + return; + } + + switch (responseType) { + case 'canMakePayment-true': + event.respondWith(true); + break; + case 'canMakePayment-false': + event.respondWith(false); + break; + case 'canMakePayment-promise-true': + event.respondWith(Promise.resolve(true)); + break; + case 'canMakePayment-promise-false': + event.respondWith(Promise.resolve(false)); + break; + case 'canMakePayment-custom-error': + event.respondWith(Promise.reject(new Error('Custom error'))); + break; + default: + const msg = `Unrecognized payment method name "${methodName}".`; + event.respondWith(Promise.reject(new Error(msg))); + break; + } +}); + +self.addEventListener('paymentrequest', event => { + responseType = event.methodData[0].data.responseType; + event.respondWith({ + methodName: event.methodData[0].supportedMethods, + details: {status: 'success'}, + }); +}); diff --git a/testing/web-platform/tests/payment-handler/app-change-payment-method.js b/testing/web-platform/tests/payment-handler/app-change-payment-method.js new file mode 100644 index 0000000000..0e5a4768e7 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/app-change-payment-method.js @@ -0,0 +1,30 @@ +self.addEventListener('canmakepayment', (event) => { + event.respondWith(true); +}); + +async function responder(event) { + const methodName = event.methodData[0].supportedMethods; + if (!event.changePaymentMethod) { + return { + methodName, + details: { + changePaymentMethodReturned: + 'The changePaymentMethod() method is not implemented.', + }, + }; + } + let changePaymentMethodReturned; + try { + const response = await event.changePaymentMethod(methodName, { + country: 'US', + }); + changePaymentMethodReturned = response; + } catch (err) { + changePaymentMethodReturned = err.message; + } + return {methodName, details: {changePaymentMethodReturned}}; +} + +self.addEventListener('paymentrequest', (event) => { + event.respondWith(responder(event)); +}); diff --git a/testing/web-platform/tests/payment-handler/app-change-shipping-address.js b/testing/web-platform/tests/payment-handler/app-change-shipping-address.js new file mode 100644 index 0000000000..df39258dc9 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/app-change-shipping-address.js @@ -0,0 +1,44 @@ +self.addEventListener('canmakepayment', (event) => { + event.respondWith(true); +}); + +async function responder(event) { + const methodName = event.methodData[0].supportedMethods; + const shippingOption = event.shippingOptions[0].id; + const shippingAddress = { + addressLine: [ + '1875 Explorer St #1000', + ], + city: 'Reston', + country: 'US', + dependentLocality: '', + organization: 'Google', + phone: '+15555555555', + postalCode: '20190', + recipient: 'John Smith', + region: 'VA', + sortingCode: '', + }; + if (!event.changeShippingAddress) { + return { + methodName, + details: { + changeShippingAddressReturned: + 'The changeShippingAddress() method is not implemented.', + }, + }; + } + let changeShippingAddressReturned; + try { + const response = await event.changeShippingAddress(shippingAddress); + changeShippingAddressReturned = response; + } catch (err) { + changeShippingAddressReturned = err.message; + } + return {methodName, details: {changeShippingAddressReturned}, shippingAddress, + shippingOption}; +} + +self.addEventListener('paymentrequest', (event) => { + event.respondWith(responder(event)); +}); diff --git a/testing/web-platform/tests/payment-handler/app-change-shipping-option.js b/testing/web-platform/tests/payment-handler/app-change-shipping-option.js new file mode 100644 index 0000000000..ac3307b619 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/app-change-shipping-option.js @@ -0,0 +1,44 @@ +self.addEventListener('canmakepayment', (event) => { + event.respondWith(true); +}); + +async function responder(event) { + const methodName = event.methodData[0].supportedMethods; + const shippingOption = event.shippingOptions[0].id; + const shippingAddress = { + addressLine: [ + '1875 Explorer St #1000', + ], + city: 'Reston', + country: 'US', + dependentLocality: '', + organization: 'Google', + phone: '+15555555555', + postalCode: '20190', + recipient: 'John Smith', + region: 'VA', + sortingCode: '', + }; + if (!event.changeShippingOption) { + return { + methodName, + details: { + changeShippingOptionReturned: + 'The changeShippingOption() method is not implemented.', + }, + }; + } + let changeShippingOptionReturned; + try { + const response = await event.changeShippingOption(shippingOption); + changeShippingOptionReturned = response; + } catch (err) { + changeShippingOptionReturned = err.message; + } + return {methodName, details: {changeShippingOptionReturned}, shippingAddress, + shippingOption}; +} + +self.addEventListener('paymentrequest', (event) => { + event.respondWith(responder(event)); +}); diff --git a/testing/web-platform/tests/payment-handler/app-simple.js b/testing/web-platform/tests/payment-handler/app-simple.js new file mode 100644 index 0000000000..9e70c08246 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/app-simple.js @@ -0,0 +1,84 @@ +self.addEventListener('canmakepayment', event => { + event.respondWith(true); +}); + +self.addEventListener('paymentrequest', event => { + const expectedId = 'test-payment-request-identifier'; + if (event.paymentRequestId !== expectedId) { + const msg = `Expected payment request identifier "${expectedId}", but got "${ + event.paymentRequestId + }"`; + event.respondWith(Promise.reject(new Error(msg))); + return; + } + + if (event.methodData.length !== 1) { + const msg = `Expected one method data, but got ${ + event.methodData.length + } instead`; + event.respondWith(Promise.reject(new Error(msg))); + return; + } + + const methodData = event.methodData[0]; + const expectedMethodNamePrefix = 'http'; + if (!methodData.supportedMethods.startsWith(expectedMethodNamePrefix)) { + const msg = `Expected payment method name "${methodData.supportedMethods}" to start with ${expectedMethodNamePrefix}"`; + event.respondWith(Promise.reject(new Error(msg))); + return; + } + + const expectedMethodNameSuffix = '/payment-handler/payment-request-event-manual-manifest.json'; + if (!methodData.supportedMethods.endsWith(expectedMethodNameSuffix)) { + const msg = `Expected payment method name "${methodData.supportedMethods}" to end with ${expectedMethodNameSuffix}"`; + event.respondWith(Promise.reject(new Error(msg))); + return; + } + + if (methodData.data.supportedNetworks) { + const msg = + 'Expected no supported networks in payment method specific data'; + event.respondWith(Promise.reject(new Error(msg))); + return; + } + + if (methodData.displayItems) { + const msg = 'Expected no display items'; + event.respondWith(Promise.reject(new Error(msg))); + return; + } + + const total = event.total; + if (!total) { + const msg = 'Expected total'; + event.respondWith(Promise.reject(new Error(msg))); + return; + } + + if (total.label) { + const msg = 'Expected no total label'; + event.respondWith(Promise.reject(new Error(msg))); + return; + } + + const expectedCurrency = 'USD'; + if (total.currency !== expectedCurrency) { + const msg = `Expected currency "${expectedCurrency}", but got "${ + total.currency + }"`; + event.respondWith(Promise.reject(new Error(msg))); + return; + } + + const expectedValue = '0.01'; + if (total.value !== expectedValue) { + const msg = `Expected value "${expectedValue}", but got "${total.value}"`; + event.respondWith(Promise.reject(new Error(msg))); + return; + } + + event.respondWith({ + methodName: methodData.supportedMethods, + details: {status: 'success'}, + }); +}); diff --git a/testing/web-platform/tests/payment-handler/app-supports-shipping-contact-delegation.js b/testing/web-platform/tests/payment-handler/app-supports-shipping-contact-delegation.js new file mode 100644 index 0000000000..770e2de64f --- /dev/null +++ b/testing/web-platform/tests/payment-handler/app-supports-shipping-contact-delegation.js @@ -0,0 +1,44 @@ +self.addEventListener('canmakepayment', (event) => { + event.respondWith(true); +}); + +function responder(event) { + const methodName = event.methodData[0].supportedMethods; + const shippingOption = event.paymentOptions.requestShipping + ? event.shippingOptions[0].id + : ''; + const payerName = + event.paymentOptions.requestPayerName ? 'John Smith' : ''; + const payerEmail = + event.paymentOptions.requestPayerEmail ? 'smith@gmail.com' : ''; + const payerPhone = + event.paymentOptions.requestPayerPhone ? '+15555555555' : ''; + const shippingAddress = event.paymentOptions.requestShipping ? { + addressLine: [ + '1875 Explorer St #1000', + ], + city: 'Reston', + country: 'US', + dependentLocality: '', + organization: 'Google', + phone: '+15555555555', + postalCode: '20190', + recipient: 'John Smith', + region: 'VA', + sortingCode: '', + } : {}; + + return { + methodName, + details: { token: '123456789'}, + payerName, + payerEmail, + payerPhone, + shippingAddress, + shippingOption + }; +} + +self.addEventListener('paymentrequest', (event) => { + event.respondWith(responder(event)); +}); diff --git a/testing/web-platform/tests/payment-handler/can-make-payment-event-constructor.https.html b/testing/web-platform/tests/payment-handler/can-make-payment-event-constructor.https.html new file mode 100644 index 0000000000..6892f01aa9 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/can-make-payment-event-constructor.https.html @@ -0,0 +1,14 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Test for CanMakePaymentEvent Constructor</title> +<link rel="help" href="https://w3c.github.io/payment-handler/#dom-canmakepaymentevent"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script> +<script> + +test(() => { + assert_false('CanMakePaymentEvent' in window); +}, 'CanMakePaymentEvent constructor must not be exposed in window'); + +</script> diff --git a/testing/web-platform/tests/payment-handler/can-make-payment-event-constructor.https.serviceworker.html b/testing/web-platform/tests/payment-handler/can-make-payment-event-constructor.https.serviceworker.html new file mode 100644 index 0000000000..afff850dc4 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/can-make-payment-event-constructor.https.serviceworker.html @@ -0,0 +1,13 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Test for CanMakePaymentEvent Constructor</title> +<link rel="help" href="https://w3c.github.io/payment-handler/#dom-canmakepaymentevent"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script> +<script> + +service_worker_test('can-make-payment-event-constructor.https.serviceworker.js', + 'CanMakePaymentEvent can be constructed in service worker'); + +</script> diff --git a/testing/web-platform/tests/payment-handler/can-make-payment-event-constructor.https.serviceworker.js b/testing/web-platform/tests/payment-handler/can-make-payment-event-constructor.https.serviceworker.js new file mode 100644 index 0000000000..5b334d9c3a --- /dev/null +++ b/testing/web-platform/tests/payment-handler/can-make-payment-event-constructor.https.serviceworker.js @@ -0,0 +1,47 @@ +importScripts('/resources/testharness.js'); + +test(() => { + try { + new CanMakePaymentEvent('test', undefined); + new CanMakePaymentEvent('test', null); + new CanMakePaymentEvent('test', {}); + } catch (err) { + assert_unreached(`Unexpected exception: ${err.message}`); + } +}, 'CanMakePaymentEvent can be constructed in service worker.'); + +test(() => { + const ev = new CanMakePaymentEvent('test', { + bubbles: true, + cancelable: true, + composed: true, + }); + assert_false(ev.isTrusted, 'constructed in script, so not be 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'); +}, 'CanMakePaymentEvent can be constructed with an EventInitDict, even if not trusted'); + +test(() => { + const ev = new CanMakePaymentEvent('test', { + topOrigin: 'https://foo.com', + paymentRequestOrigin: 'https://bar.com', + methodData: [], + modifiers: [], + }); + assert_false(ev.isTrusted, 'constructed in script, so not be trusted'); + assert_equals(ev.topOrigin, undefined); + assert_equals(ev.paymentRequestOrigin, undefined); + assert_equals(ev.methodData, undefined); + assert_equals(ev.modifiers, undefined); +}, 'CanMakePaymentEvent can be constructed with a CanMakePaymentEventInit, even if not trusted'); + +test(() => { + const ev = new CanMakePaymentEvent('test', {}); + self.addEventListener('test', evt => { + assert_equals(ev, evt); + }); + self.dispatchEvent(ev); +}, 'CanMakePaymentEvent can be dispatched, even if not trusted'); diff --git a/testing/web-platform/tests/payment-handler/can-make-payment-event-constructor.https.worker.js b/testing/web-platform/tests/payment-handler/can-make-payment-event-constructor.https.worker.js new file mode 100644 index 0000000000..d88bddceaf --- /dev/null +++ b/testing/web-platform/tests/payment-handler/can-make-payment-event-constructor.https.worker.js @@ -0,0 +1,7 @@ +importScripts('/resources/testharness.js'); + +test(() => { + assert_false('CanMakePaymentEvent' in self); +}, 'CanMakePaymentEvent constructor must not be exposed in worker'); + +done(); diff --git a/testing/web-platform/tests/payment-handler/can-make-payment-event-manifest.json b/testing/web-platform/tests/payment-handler/can-make-payment-event-manifest.json new file mode 100644 index 0000000000..b31ea5ce08 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/can-make-payment-event-manifest.json @@ -0,0 +1,15 @@ +{ + "default_applications": ["can-make-payment-event-manifest.json"], + "name": "Test Payment Handler", + "icons": [ + { + "src": "/images/rgrg-256x256.png", + "sizes": "256x256", + "type": "image/png" + } + ], + "serviceworker": { + "src": "app-can-make-payment.js", + "scope": "can-make-payment-event-payment-app/" + } +} diff --git a/testing/web-platform/tests/payment-handler/can-make-payment-event.https.html b/testing/web-platform/tests/payment-handler/can-make-payment-event.https.html new file mode 100644 index 0000000000..776c68be43 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/can-make-payment-event.https.html @@ -0,0 +1,270 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Tests for CanMakePaymentEvent</title> +<link rel="help" href="https://w3c.github.io/payment-handler/#the-canmakepaymentevent"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script> +const DEFAULT_METHOD_NAME = window.location.origin + '/payment-handler/' + + 'can-make-payment-event-manifest.json'; + +async function registerApp(responseType = 'canMakePayment-true') { + const request = new PaymentRequest( + [{supportedMethods: DEFAULT_METHOD_NAME, data: {responseType}}], + {total: {label: 'Total', amount: {currency: 'USD', value: '0.01'}}}); + const response = await test_driver.bless('installing a payment app', () => + request.show() + ); + return response.complete('success'); +} + +function buildPaymentRequest(methodName = DEFAULT_METHOD_NAME) { + const unsupportedMethodName = methodName + '/unsupported'; + return new PaymentRequest( + [ + { + supportedMethods: methodName, + data: { + defaultParameter: 'defaultValue', + }, + }, + { + supportedMethods: unsupportedMethodName, + data: { + defaultUnsupportedParameter: 'defaultUnsupportedValue', + }, + }, + ], + { + total: { + label: 'Total', + amount: { + currency: 'USD', + value: '0', + }, + }, + displayItems: [ + { + label: 'Nada', + amount: {currency: 'USD', value: '0'}, + }, + ], + modifiers: [ + { + supportedMethods: [methodName], + data: { + modifiedParameter: 'modifiedValue', + }, + total: { + label: 'Modified Total', + amount: { + currency: 'USD', + value: '0.0001', + }, + }, + additionalDisplayItems: [ + { + label: 'Something', + amount: {currency: 'USD', value: '0.0001'}, + }, + ], + }, + { + supportedMethods: [unsupportedMethodName], + data: { + modifiedUnsupportedParameter: 'modifiedUnsupportedValue', + }, + total: { + label: 'Modified Unsupported Total', + amount: { + currency: 'USD', + value: '10', + }, + }, + additionalDisplayItems: [ + { + label: 'Something Unsupported', + amount: {currency: 'USD', value: '10'}, + }, + ], + }, + ], + }, + ); +} + +promise_test(async t => { + // Intentionally do not install the payment app. + const request = buildPaymentRequest(); + assert_not_equals(request, undefined); + let paymentRequestCanMakePaymentResult; + try { + paymentRequestCanMakePaymentResult = await request.canMakePayment(); + } catch (err) { + assert_equals( + err.name, + 'NotAllowedError', + 'If it throws, then it must be NotAllowedError', + ); + } + assert_true( + paymentRequestCanMakePaymentResult, + 'canMakePayment() must return true.', + ); + + await test_driver.bless('installing a payment app just-in-time'); + const response = await request.show(); + assert_equals('success', response.details.status); + return response.complete('success'); +}, 'If a payment handler is not installed, but can be installed just-in-time, then the payment method is supported.'); + +promise_test(async t => { + // Intentionally do not install the payment app. + const request = buildPaymentRequest(DEFAULT_METHOD_NAME + '/non-existent'); + assert_not_equals(request, undefined); + let paymentRequestCanMakePaymentResult; + try { + paymentRequestCanMakePaymentResult = await request.canMakePayment(); + } catch (err) { + assert_equals( + err.name, + 'NotAllowedError', + 'If it throws, then it must be NotAllowedError', + ); + } + assert_false( + paymentRequestCanMakePaymentResult, + 'canMakePayment() must return false.', + ); + + const response = await test_driver.bless('invoking a payemnt app'); + await promise_rejects_dom(t, 'NotSupportedError', request.show()); +}, 'If a payment handler is not installed and cannot be installed just-in-time, then the payment method is not supported.'); + +promise_test(async t => { + await registerApp('canMakePayment-false'); + const request = buildPaymentRequest(); + assert_not_equals(request, undefined); + let paymentRequestCanMakePaymentResult; + try { + paymentRequestCanMakePaymentResult = await request.canMakePayment(); + } catch (err) { + assert_equals( + err.name, + 'NotAllowedError', + 'If it throws, then it must be NotAllowedError', + ); + } + assert_true( + paymentRequestCanMakePaymentResult, + 'canMakePayment() must return true.', + ); + + await test_driver.bless('invoking a payment app'); + const response = await request.show(); + assert_equals('success', response.details.status); + return response.complete('success'); +}, 'If CanMakePaymentEvent.respondWith(false) is called, then canMakePayment() still returns true and the app can still be invoked.'); + +promise_test(async t => { + await registerApp('canMakePayment-promise-false'); + const request = buildPaymentRequest(); + assert_not_equals(request, undefined); + let paymentRequestCanMakePaymentResult; + try { + paymentRequestCanMakePaymentResult = await request.canMakePayment(); + } catch (err) { + assert_equals( + err.name, + 'NotAllowedError', + 'If it throws, then it must be NotAllowedError', + ); + } + assert_true( + paymentRequestCanMakePaymentResult, + 'canMakePayment() must return true.', + ); + + await test_driver.bless('invoking a payment app'); + const response = await request.show(); + assert_equals('success', response.details.status); + return response.complete('success'); +}, 'If CanMakePaymentEvent.respondWith(Promise.resolve(false)) is called, then canMakePayment() still returns true and the app can still be invoked.'); + +promise_test(async t => { + await registerApp('canMakePayment-true'); + const request = buildPaymentRequest(); + assert_not_equals(request, undefined); + let paymentRequestCanMakePaymentResult; + try { + paymentRequestCanMakePaymentResult = await request.canMakePayment(); + } catch (err) { + assert_equals( + err.name, + 'NotAllowedError', + 'If it throws, then it must be NotAllowedError', + ); + } + assert_true( + paymentRequestCanMakePaymentResult, + 'canMakePayment() must return true.', + ); + + await test_driver.bless('invoking a payment app'); + const response = await request.show(); + assert_equals('success', response.details.status); + return response.complete('success'); +}, 'If CanMakePaymentEvent.respondWith(true) is called, then canMakePayment() returns true and the app can be invoked.'); + +promise_test(async t => { + await registerApp('canMakePayment-promise-true'); + const request = buildPaymentRequest(); + assert_not_equals(request, undefined); + let paymentRequestCanMakePaymentResult; + try { + paymentRequestCanMakePaymentResult = await request.canMakePayment(); + } catch (err) { + assert_equals( + err.name, + 'NotAllowedError', + 'If it throws, then it must be NotAllowedError', + ); + } + assert_true( + paymentRequestCanMakePaymentResult, + 'canMakePayment() must return true.', + ); + + await test_driver.bless('invoking a payment app'); + const response = await request.show(); + assert_equals('success', response.details.status); + return response.complete('success'); +}, 'If CanMakePaymentEvent.respondWith(Promise.resolve(true)) is called, then canMakePayment() returns true and the app can be invoked.'); + +promise_test(async t => { + await registerApp('canMakePayment-custom-error'); + const request = buildPaymentRequest(); + assert_not_equals(request, undefined); + let paymentRequestCanMakePaymentResult; + try { + paymentRequestCanMakePaymentResult = await request.canMakePayment(); + } catch (err) { + assert_equals( + err.name, + 'NotAllowedError', + 'If it throws, then it must be NotAllowedError', + ); + } + assert_true( + paymentRequestCanMakePaymentResult, + 'canMakePayment() must return true.', + ); + + await test_driver.bless('invoking a payment app'); + const response = await request.show(); + assert_equals('success', response.details.status); + return response.complete('success'); +}, 'If CanMakePaymentEvent.respondWith(Promise.reject(error)) is called, then canMakePayment() still returns true and the app can still be invoked.'); +</script> diff --git a/testing/web-platform/tests/payment-handler/change-payment-method-manual-manifest.json b/testing/web-platform/tests/payment-handler/change-payment-method-manual-manifest.json new file mode 100644 index 0000000000..7a4f5d6f7e --- /dev/null +++ b/testing/web-platform/tests/payment-handler/change-payment-method-manual-manifest.json @@ -0,0 +1,15 @@ +{ + "default_applications": ["change-payment-method-manual-manifest.json"], + "name": "Test Payment Handler", + "icons": [ + { + "src": "/images/rgrg-256x256.png", + "sizes": "256x256", + "type": "image/png" + } + ], + "serviceworker": { + "src": "app-change-payment-method.js", + "scope": "change-payment-method-manual-payment-app/" + } +} diff --git a/testing/web-platform/tests/payment-handler/change-payment-method-manual.https.html b/testing/web-platform/tests/payment-handler/change-payment-method-manual.https.html new file mode 100644 index 0000000000..15165b91d7 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/change-payment-method-manual.https.html @@ -0,0 +1,156 @@ +<!DOCTYPE html> +<meta charset="utf-8" /> +<title>Tests for PaymentRequestEvent.changePaymentMethod()</title> +<link + rel="help" + href="https://w3c.github.io/payment-handler/#changepaymentmethod-method" +/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<p>If the payment sheet is shown, please authorize the mock payment.</p> +<script> +const methodName = window.location.origin + + '/payment-handler/change-payment-method-manual-manifest.json'; + +promise_test(async (t) => { + const request = new PaymentRequest([{supportedMethods: methodName}], { + total: {label: 'Total', amount: {currency: 'USD', value: '0.01'}}, + }); + // Intentionally do not respond to the 'paymentmethodchange' event. + const response = await test_driver.bless('showing a payment sheet', () => + request.show() + ); + const complete_promise = response.complete('success'); + + assert_equals(response.details.changePaymentMethodReturned, null); + + return complete_promise; +}, 'If updateWith(details) is not run, changePaymentMethod() returns null.'); + +promise_test(async (t) => { + const request = new PaymentRequest([{supportedMethods: methodName}], { + total: {label: 'Total', amount: {currency: 'USD', value: '0.01'}}, + }); + request.addEventListener('paymentmethodchange', (event) => { + assert_equals(event.methodName, methodName); + assert_equals(event.methodDetails.country, 'US'); + event.updateWith(Promise.reject('Error')); + }); + const response_promise = test_driver.bless( + 'showing a payment sheet', + () => request.show() + ); + + return promise_rejects_dom(t, 'AbortError', response_promise); +}, 'If updateWith(details) is rejected, abort the PaymentRequest.show().'); + +promise_test(async (t) => { + const request = new PaymentRequest([{supportedMethods: methodName}], { + total: {label: 'Total', amount: {currency: 'USD', value: '0.01'}}, + }); + request.addEventListener('paymentmethodchange', (event) => { + assert_equals(event.methodName, methodName); + assert_equals(event.methodDetails.country, 'US'); + event.updateWith( + new Promise(() => { + throw 'Error for test'; + }) + ); + }); + const response_promise = test_driver.bless( + 'showing a payment sheet', + () => request.show() + ); + + return promise_rejects_dom(t, 'AbortError', response_promise); +}, 'If updateWith(details) throws inside of the promise, abort the PaymentRequest.show().'); + +promise_test(async (t) => { + const request = new PaymentRequest([{supportedMethods: methodName}], { + total: {label: 'Total', amount: {currency: 'USD', value: '0.01'}}, + }); + request.addEventListener('paymentmethodchange', (event) => { + assert_equals(event.methodName, methodName); + assert_equals(event.methodDetails.country, 'US'); + event.updateWith({ + total: {label: 'Total', amount: {currency: 'GBP', value: '0.02'}}, + error: 'Error for test', + modifiers: [ + { + supportedMethods: methodName, + data: {soup: 'potato'}, + total: { + label: 'Modified total', + amount: {currency: 'EUR', value: '0.03'}, + }, + additionalDisplayItems: [ + { + label: 'Modified display item', + amount: {currency: 'INR', value: '0.06'}, + }, + ], + }, + { + supportedMethods: methodName + '2', + data: {soup: 'tomato'}, + total: { + label: 'Modified total #2', + amount: {currency: 'CHF', value: '0.07'}, + }, + additionalDisplayItems: [ + { + label: 'Modified display item #2', + amount: {currency: 'CAD', value: '0.08'}, + }, + ], + }, + ], + paymentMethodErrors: {country: 'Unsupported country'}, + displayItems: [ + { + label: 'Display item', + amount: {currency: 'CNY', value: '0.04'}, + }, + ], + shippingOptions: [ + { + label: 'Shipping option', + id: 'id', + amount: {currency: 'JPY', value: '0.05'}, + }, + ], + }); + }); + const response = await test_driver.bless('showing a payment sheet', () => + request.show() + ); + const complete_promise = response.complete('success'); + const changePaymentMethodReturned = + response.details.changePaymentMethodReturned; + + assert_equals(changePaymentMethodReturned.total.currency, 'GBP'); + assert_equals(changePaymentMethodReturned.total.value, '0.02'); + assert_equals(changePaymentMethodReturned.total.label, undefined); + assert_equals(changePaymentMethodReturned.error, 'Error for test'); + assert_equals(changePaymentMethodReturned.modifiers.length, 1); + assert_equals(changePaymentMethodReturned.displayItems, undefined); + assert_equals(changePaymentMethodReturned.shippingOptions, undefined); + assert_equals( + changePaymentMethodReturned.paymentMethodErrors.country, + 'Unsupported country' + ); + + const modifier = changePaymentMethodReturned.modifiers[0]; + + assert_equals(modifier.supportedMethods, methodName); + assert_equals(modifier.data.soup, 'potato'); + assert_equals(modifier.total.label, ''); + assert_equals(modifier.total.amount.currency, 'EUR'); + assert_equals(modifier.total.amount.value, '0.03'); + assert_equals(modifier.additionalDisplayItems, undefined); + + return complete_promise; +}, 'The changePaymentMethod() returns some details from the "paymentmethodchange" event\'s updateWith(details) call.'); +</script> diff --git a/testing/web-platform/tests/payment-handler/change-shipping-address-manual-manifest.json b/testing/web-platform/tests/payment-handler/change-shipping-address-manual-manifest.json new file mode 100644 index 0000000000..08b034e825 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/change-shipping-address-manual-manifest.json @@ -0,0 +1,20 @@ +{ + "default_applications": ["change-shipping-address-manual-manifest.json"], + "name": "Test Payment Handler", + "icons": [ + { + "src": "/images/rgrg-256x256.png", + "sizes": "256x256", + "type": "image/png" + } + ], + "serviceworker": { + "src": "app-change-shipping-address.js", + "scope": "change-shipping-address-manual-payment-app/" + }, + "payment": { + "supported_delegations": [ + "shippingAddress" + ] + } +} diff --git a/testing/web-platform/tests/payment-handler/change-shipping-address-manual.https.html b/testing/web-platform/tests/payment-handler/change-shipping-address-manual.https.html new file mode 100644 index 0000000000..e8817459c3 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/change-shipping-address-manual.https.html @@ -0,0 +1,145 @@ +<!DOCTYPE html> +<meta charset="utf-8" /> +<title>Tests for PaymentRequestEvent.changeShippingAddress()</title> +<link + rel="help" + href="https://w3c.github.io/payment-handler/#changeshippingaddress-method" +/> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<p>If the payment sheet is shown, please authorize the mock payment.</p> +<script> +const methodName = window.location.origin + + '/payment-handler/change-shipping-address-manual-manifest.json'; +function createRequest() { + return new PaymentRequest([{supportedMethods: methodName}], { + total: {label: 'Total', amount: {currency: 'USD', value: '0.01'}}, + shippingOptions: [{ + id: 'freeShippingOption', + label: 'Free global shipping', + amount: { + currency: 'USD', + value: '0', + }, + selected: false, + }], + }, {requestShipping: true}); +} + +promise_test(async (t) => { + const request = createRequest(); + // Intentionally do not respond to the 'shippingaddresschange' event. + const response = await test_driver.bless('showing a payment sheet', () => + request.show() + ); + const complete_promise = response.complete('success'); + + assert_equals(response.details.changeShippingAddressReturned, null); + + return complete_promise; +}, 'If updateWith(details) is not run, changeShippingAddress() returns null.'); + +promise_test(async (t) => { + const request = createRequest(); + request.addEventListener('shippingaddresschange', (event) => { + assert_equals(request.shippingAddress.organization, '', 'organization should be redacted'); + assert_equals(request.shippingAddress.phone, '', 'phone should be redacted'); + assert_equals(request.shippingAddress.recipient, '', 'recipient should be redacted'); + assert_equals(request.shippingAddress.addressLine.length, 0, 'addressLine should be redacted'); + assert_equals(request.shippingAddress.city, 'Reston'); + assert_equals(request.shippingAddress.country, 'US'); + assert_equals(request.shippingAddress.postalCode, '20190'); + assert_equals(request.shippingAddress.region, 'VA'); + event.updateWith({ + total: {label: 'Total', amount: {currency: 'GBP', value: '0.02'}}, + error: 'Error for test', + modifiers: [ + { + supportedMethods: methodName, + data: {soup: 'potato'}, + total: { + label: 'Modified total', + amount: {currency: 'EUR', value: '0.03'}, + }, + additionalDisplayItems: [ + { + label: 'Modified display item', + amount: {currency: 'INR', value: '0.06'}, + }, + ], + }, + { + supportedMethods: methodName + '2', + data: {soup: 'tomato'}, + total: { + label: 'Modified total #2', + amount: {currency: 'CHF', value: '0.07'}, + }, + additionalDisplayItems: [ + { + label: 'Modified display item #2', + amount: {currency: 'CAD', value: '0.08'}, + }, + ], + }, + ], + displayItems: [ + { + label: 'Display item', + amount: {currency: 'CNY', value: '0.04'}, + }, + ], + shippingOptions: [ + { + id: 'freeShippingOption', + label: 'express global shipping', + amount: { + currency: 'USD', + value: '0', + }, + selected: true, + } + ], + shippingAddressErrors: { + country: 'US only shipping', + } + }); + }); + const response = await test_driver.bless('showing a payment sheet', () => + request.show() + ); + const complete_promise = response.complete('success'); + const changeShippingAddressReturned = + response.details.changeShippingAddressReturned; + + assert_equals(changeShippingAddressReturned.total.currency, 'GBP'); + assert_equals(changeShippingAddressReturned.total.value, '0.02'); + assert_equals(changeShippingAddressReturned.total.label, undefined); + assert_equals(changeShippingAddressReturned.error, 'Error for test'); + assert_equals(changeShippingAddressReturned.modifiers.length, 1); + assert_equals(changeShippingAddressReturned.displayItems, undefined); + assert_equals(changeShippingAddressReturned.shippingOptions.length, 1); + assert_equals(changeShippingAddressReturned.paymentMethodErrors, undefined); + assert_equals(changeShippingAddressReturned.shippingAddressErrors.country, 'US only shipping'); + + const shipping_option = changeShippingAddressReturned.shippingOptions[0]; + assert_equals(shipping_option.id, 'freeShippingOption' ); + assert_equals(shipping_option.label, 'express global shipping'); + assert_equals(shipping_option.amount.currency, 'USD'); + assert_equals(shipping_option.amount.value, '0'); + assert_true(shipping_option.selected); + + const modifier = changeShippingAddressReturned.modifiers[0]; + assert_equals(modifier.supportedMethods, methodName); + assert_equals(modifier.data.soup, 'potato'); + assert_equals(modifier.total.label, ''); + assert_equals(modifier.total.amount.currency, 'EUR'); + assert_equals(modifier.total.amount.value, '0.03'); + assert_equals(modifier.additionalDisplayItems, undefined); + + return complete_promise; +}, 'The changeShippingAddress() returns some details from the "shippingaddresschange" event\'s updateWith(details) call.'); +</script> diff --git a/testing/web-platform/tests/payment-handler/change-shipping-option-manual-manifest.json b/testing/web-platform/tests/payment-handler/change-shipping-option-manual-manifest.json new file mode 100644 index 0000000000..2c023902b2 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/change-shipping-option-manual-manifest.json @@ -0,0 +1,20 @@ +{ + "default_applications": ["change-shipping-option-manual-manifest.json"], + "name": "Test Payment Handler", + "icons": [ + { + "src": "/images/rgrg-256x256.png", + "sizes": "256x256", + "type": "image/png" + } + ], + "serviceworker": { + "src": "app-change-shipping-option.js", + "scope": "change-shipping-option-manual-payment-app/" + }, + "payment": { + "supported_delegations": [ + "shippingAddress" + ] + } +} diff --git a/testing/web-platform/tests/payment-handler/change-shipping-option-manual.https.html b/testing/web-platform/tests/payment-handler/change-shipping-option-manual.https.html new file mode 100644 index 0000000000..6e97f2878a --- /dev/null +++ b/testing/web-platform/tests/payment-handler/change-shipping-option-manual.https.html @@ -0,0 +1,144 @@ +<!DOCTYPE html> +<meta charset="utf-8" /> +<title>Tests for PaymentRequestEvent.changeShippingOption()</title> +<link + rel="help" + href="https://w3c.github.io/payment-handler/#changeshippingoption-method" +/> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<p>If the payment sheet is shown, please authorize the mock payment.</p> +<script> +const methodName = window.location.origin + + '/payment-handler/change-shipping-option-manual-manifest.json'; +function createRequest() { + return new PaymentRequest([{supportedMethods: methodName}], { + total: {label: 'Total', amount: {currency: 'USD', value: '0.01'}}, + shippingOptions: [{ + id: 'freeShippingOption', + label: 'Free global shipping', + amount: { + currency: 'USD', + value: '0', + }, + selected: false, + }, + { + id: 'expressShippingOption', + label: 'express global shipping', + amount: { + currency: 'USD', + value: '0', + }, + selected: true, + }], + }, {requestShipping: true}); +} + +promise_test(async (t) => { + const request = createRequest(); + // Intentionally do not respond to the 'shippingoptionchange' event. + const response = await test_driver.bless('showing a payment sheet', () => + request.show() + ); + const complete_promise = response.complete('success'); + + assert_equals(response.details.changeShippingOptionReturned, null); + + return complete_promise; +}, 'If updateWith(details) is not run, changeShippingOption() returns null.'); + +promise_test(async (t) => { + const request = createRequest(); + request.addEventListener('shippingoptionchange', (event) => { + assert_equals(request.shippingOption, 'freeShippingOption'); + event.updateWith({ + total: {label: 'Total', amount: {currency: 'GBP', value: '0.02'}}, + error: 'Error for test', + modifiers: [ + { + supportedMethods: methodName, + data: {soup: 'potato'}, + total: { + label: 'Modified total', + amount: {currency: 'EUR', value: '0.03'}, + }, + additionalDisplayItems: [ + { + label: 'Modified display item', + amount: {currency: 'INR', value: '0.06'}, + }, + ], + }, + { + supportedMethods: methodName + '2', + data: {soup: 'tomato'}, + total: { + label: 'Modified total #2', + amount: {currency: 'CHF', value: '0.07'}, + }, + additionalDisplayItems: [ + { + label: 'Modified display item #2', + amount: {currency: 'CAD', value: '0.08'}, + }, + ], + }, + ], + displayItems: [ + { + label: 'Display item', + amount: {currency: 'CNY', value: '0.04'}, + }, + ], + shippingOptions: [ + { + id: 'freeShippingOption', + label: 'express global shipping', + amount: { + currency: 'USD', + value: '0', + }, + selected: true, + } + ], + }); + }); + const response = await test_driver.bless('showing a payment sheet', () => + request.show() + ); + const complete_promise = response.complete('success'); + const changeShippingOptionReturned = + response.details.changeShippingOptionReturned; + + assert_equals(changeShippingOptionReturned.total.currency, 'GBP'); + assert_equals(changeShippingOptionReturned.total.value, '0.02'); + assert_equals(changeShippingOptionReturned.total.label, undefined); + assert_equals(changeShippingOptionReturned.error, 'Error for test'); + assert_equals(changeShippingOptionReturned.modifiers.length, 1); + assert_equals(changeShippingOptionReturned.displayItems, undefined); + assert_equals(changeShippingOptionReturned.shippingOptions.length, 1); + assert_equals(changeShippingOptionReturned.paymentMethodErrors, undefined); + assert_equals(changeShippingOptionReturned.shippingAddressErrors, undefined); + + const shipping_option = changeShippingOptionReturned.shippingOptions[0]; + assert_equals(shipping_option.id, 'freeShippingOption' ); + assert_equals(shipping_option.label, 'express global shipping'); + assert_equals(shipping_option.amount.currency, 'USD'); + assert_equals(shipping_option.amount.value, '0'); + assert_true(shipping_option.selected); + + const modifier = changeShippingOptionReturned.modifiers[0]; + assert_equals(modifier.supportedMethods, methodName); + assert_equals(modifier.data.soup, 'potato'); + assert_equals(modifier.total.label, ''); + assert_equals(modifier.total.amount.currency, 'EUR'); + assert_equals(modifier.total.amount.value, '0.03'); + assert_equals(modifier.additionalDisplayItems, undefined); + + return complete_promise; +}, 'The changeShippingOption() returns some details from the "shippingoptionchange" event\'s updateWith(details) call.'); +</script> diff --git a/testing/web-platform/tests/payment-handler/idlharness.https.any.js b/testing/web-platform/tests/payment-handler/idlharness.https.any.js new file mode 100644 index 0000000000..d34e20630b --- /dev/null +++ b/testing/web-platform/tests/payment-handler/idlharness.https.any.js @@ -0,0 +1,45 @@ +// META: global=window,worker +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js +// META: script=/service-workers/service-worker/resources/test-helpers.sub.js +// META: timeout=long + +'use strict'; + +// https://w3c.github.io/payment-handler/ + +idl_test( + ['payment-handler'], + ['service-workers', 'html', 'dom'], + async (idl_array, t) => { + const isWindow = self.GLOBAL.isWindow(); + const isServiceWorker = 'ServiceWorkerGlobalScope' in self; + const hasRegistration = isServiceWorker || isWindow; + + if (hasRegistration) { + idl_array.add_objects({ + ServiceWorkerRegistration: ['registration'], + PaymentManager: ['paymentManager'], + }); + } + if (isServiceWorker) { + idl_array.add_objects({ + ServiceWorkerGlobalScope: ['self'], + CanMakePaymentEvent: ['new CanMakePaymentEvent("type")'], + PaymentRequestEvent: ['new PaymentRequestEvent("type")'], + }) + } + + if (isWindow) { + const scope = '/service-workers/service-worker/resources/'; + const reg = await service_worker_unregister_and_register( + t, '/service-workers/service-worker/resources/empty-worker.js', scope); + self.registration = reg; + await wait_for_state(t, reg.installing, "activated"); + add_completion_callback(() => reg.unregister()); + } + if (hasRegistration) { + self.paymentManager = self.registration.paymentManager; + } + } +); diff --git a/testing/web-platform/tests/payment-handler/manifest.json b/testing/web-platform/tests/payment-handler/manifest.json new file mode 100644 index 0000000000..875d74b663 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/manifest.json @@ -0,0 +1,10 @@ +{ + "name": "Test Payment Handler", + "icons": [ + { + "src": "/images/rgrg-256x256.png", + "sizes": "256x256", + "type": "image/png" + } + ] +} diff --git a/testing/web-platform/tests/payment-handler/payment-app/payment.html b/testing/web-platform/tests/payment-handler/payment-app/payment.html new file mode 100644 index 0000000000..37d2452ed9 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/payment-app/payment.html @@ -0,0 +1,5 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Test Payment App</title> +<p>Account balance: $10.00</p> +<button>Authorize</button> diff --git a/testing/web-platform/tests/payment-handler/payment-request-event-constructor.https.html b/testing/web-platform/tests/payment-handler/payment-request-event-constructor.https.html new file mode 100644 index 0000000000..31ac8cafa7 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/payment-request-event-constructor.https.html @@ -0,0 +1,14 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Test for PaymentRequestEvent Constructor</title> +<link rel="help" href="https://w3c.github.io/payment-handler/#the-paymentrequestevent"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script> +<script> + +test(() => { + assert_false('PaymentRequestEvent' in window); +}, 'PaymentRequestEvent constructor must not be exposed in window'); + +</script> diff --git a/testing/web-platform/tests/payment-handler/payment-request-event-constructor.https.serviceworker.html b/testing/web-platform/tests/payment-handler/payment-request-event-constructor.https.serviceworker.html new file mode 100644 index 0000000000..a64c4290e0 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/payment-request-event-constructor.https.serviceworker.html @@ -0,0 +1,13 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Test for PaymentRequestEvent Constructor</title> +<link rel="help" href="https://w3c.github.io/payment-handler/#the-paymentrequestevent"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script> +<script> + +service_worker_test('payment-request-event-constructor.https.serviceworker.js', + 'PaymentRequestEvent can be constructed in service worker'); + +</script> diff --git a/testing/web-platform/tests/payment-handler/payment-request-event-constructor.https.serviceworker.js b/testing/web-platform/tests/payment-handler/payment-request-event-constructor.https.serviceworker.js new file mode 100644 index 0000000000..1aea7000c1 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/payment-request-event-constructor.https.serviceworker.js @@ -0,0 +1,45 @@ +importScripts('/resources/testharness.js'); + +test(() => { + try { + new PaymentRequestEvent('test', undefined); + new PaymentRequestEvent('test', null); + new PaymentRequestEvent('test', {}); + } catch (err) { + assert_unreached(`Unexpected exception: ${err.message}`); + } +}, 'PaymentRequestEvent can be constucted in service worker.'); + +test(() => { + const ev = new PaymentRequestEvent('test', { + bubbles: true, + cancelable: true, + composed: true, + }); + assert_false(ev.isTrusted, 'constructed in script, so not be 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'); +}, 'PaymentRequestEvent can be constructed with an EventInitDict, even if not trusted'); + +test(() => { + const ev = new PaymentRequestEvent('test', { + topOrigin: 'https://foo.com', + paymentRequestOrigin: 'https://bar.com', + methodData: [], + modifiers: [], + }); + assert_false(ev.isTrusted, 'constructed in script, so not be trusted'); + assert_equals(ev.topOrigin, 'https://foo.com'); + assert_equals(ev.paymentRequestOrigin, 'https://bar.com'); +}, 'PaymentRequestEvent can be constructed with a PaymentRequestEventInit, even if not trusted'); + +test(() => { + const ev = new PaymentRequestEvent('test', {}); + self.addEventListener('test', evt => { + assert_equals(ev, evt); + }); + self.dispatchEvent(ev); +}, 'PaymentRequestEvent can be dispatched, even if not trusted'); diff --git a/testing/web-platform/tests/payment-handler/payment-request-event-constructor.https.worker.js b/testing/web-platform/tests/payment-handler/payment-request-event-constructor.https.worker.js new file mode 100644 index 0000000000..fdb71aa845 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/payment-request-event-constructor.https.worker.js @@ -0,0 +1,7 @@ +importScripts('/resources/testharness.js'); + +test(() => { + assert_false('PaymentRequestEvent' in self); +}, 'PaymentRequestEvent constructor must not be exposed in worker'); + +done(); diff --git a/testing/web-platform/tests/payment-handler/payment-request-event-manual-manifest.json b/testing/web-platform/tests/payment-handler/payment-request-event-manual-manifest.json new file mode 100644 index 0000000000..f97229762c --- /dev/null +++ b/testing/web-platform/tests/payment-handler/payment-request-event-manual-manifest.json @@ -0,0 +1,15 @@ +{ + "default_applications": ["payment-request-event-manual-manifest.json"], + "name": "Test Payment Handler", + "icons": [ + { + "src": "/images/rgrg-256x256.png", + "sizes": "256x256", + "type": "image/png" + } + ], + "serviceworker": { + "src": "app-simple.js", + "scope": "payment-request-event-manual-payment-app/" + } +} diff --git a/testing/web-platform/tests/payment-handler/payment-request-event-manual.https.html b/testing/web-platform/tests/payment-handler/payment-request-event-manual.https.html new file mode 100644 index 0000000000..9cd2035463 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/payment-request-event-manual.https.html @@ -0,0 +1,69 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Tests for PaymentRequestEvent</title> +<link rel="help" href="https://w3c.github.io/payment-handler/#the-paymentrequestevent"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<p>When the payment sheet is shown, please authorize the mock payment.</p> +<script> +promise_test(async t => { + const methodName = window.location.origin + '/payment-handler/' + + 'payment-request-event-manual-manifest.json'; + await test_driver.bless('invoking a payment app'); + const response = await new PaymentRequest( + [ + {supportedMethods: methodName, data: {}}, + {supportedMethods: 'interledger', data: {supportedNetworks: ['mir']}}, + ], + { + id: 'test-payment-request-identifier', + total: {label: 'Total', amount: {currency: 'USD', value: '0.01'}}, + displayItems: [ + {label: 'Item 1', amount: {currency: 'CAD', value: '0.005'}}, + {label: 'Item 2', amount: {currency: 'EUR', value: '0.005'}}, + ], + modifiers: [ + { + supportedMethods: methodName, + data: {supportedNetworks: ['mir']}, + total: { + label: 'MIR total', + amount: {currency: 'USD', value: '0.0099'}, + }, + additionalDisplayItems: [ + {label: 'Item 3', amount: {currency: 'GBP', value: '-0.0001'}}, + ], + }, + { + supportedMethods: methodName, + data: {supportedNetworks: ['visa']}, + total: { + label: 'VISA total', + amount: {currency: 'USD', value: '0.0098'}, + }, + additionalDisplayItems: [ + {label: 'Item 4', amount: {currency: 'CNY', value: '-0.0002'}}, + ], + }, + { + supportedMethods: 'interledger', + data: {}, + total: { + label: 'Prepaid total', + amount: {currency: 'USD', value: '0.0097'}, + }, + additionalDisplayItems: [ + {label: 'Item 5', amount: {currency: 'JPY', value: '-0.0003'}}, + ], + }, + ], + }, + ).show(); + const promise = response.complete('success'); + assert_equals(response.requestId, 'test-payment-request-identifier'); + assert_equals(response.methodName, methodName); + return promise; +}, 'Can perform payment'); +</script> diff --git a/testing/web-platform/tests/payment-handler/same-object-attributes.https.html b/testing/web-platform/tests/payment-handler/same-object-attributes.https.html new file mode 100644 index 0000000000..27c2044843 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/same-object-attributes.https.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<link rel="help" href="https://w3c.github.io/payment-handler/"> +<title>Test for [SameObject] attributes</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script> +<script> + +promise_test(async t => { + const registration = await service_worker_unregister_and_register( + t, 'app-simple.js', 'payment-app/'); + await wait_for_state(t, registration.installing, 'activated'); + + assert_equals(registration.paymentManager, registration.paymentManager); +}); + +</script> diff --git a/testing/web-platform/tests/payment-handler/supports-shipping-contact-delegation-manual-manifest.json b/testing/web-platform/tests/payment-handler/supports-shipping-contact-delegation-manual-manifest.json new file mode 100644 index 0000000000..fd6bc89ef6 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/supports-shipping-contact-delegation-manual-manifest.json @@ -0,0 +1,23 @@ +{ + "default_applications": ["supports-shipping-contact-delegation-manual-manifest.json"], + "name": "Test Payment Handler", + "icons": [ + { + "src": "/images/rgrg-256x256.png", + "sizes": "256x256", + "type": "image/png" + } + ], + "serviceworker": { + "src": "app-supports-shipping-contact-delegation.js", + "scope": "supports-shipping-contact-delegation-manual-payment-app/" + }, + "payment": { + "supported_delegations": [ + "shippingAddress", + "payerName", + "payerPhone", + "payerEmail" + ] + } +} diff --git a/testing/web-platform/tests/payment-handler/supports-shipping-contact-delegation-manual.https.html b/testing/web-platform/tests/payment-handler/supports-shipping-contact-delegation-manual.https.html new file mode 100644 index 0000000000..e3074b4e5e --- /dev/null +++ b/testing/web-platform/tests/payment-handler/supports-shipping-contact-delegation-manual.https.html @@ -0,0 +1,70 @@ +<!DOCTYPE html> +<meta charset="utf-8" /> +<title>Tests for Delegation of shipping and contact collection to PH</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<p>If the payment sheet is shown, please authorize the mock payment.</p> +<script> +const methodName = window.location.origin + '/payment-handler/' + + 'supports-shipping-contact-delegation-manual-manifest.json'; +promise_test(async (t) => { + const request = new PaymentRequest([{supportedMethods: methodName}], { + total: {label: 'Total', amount: {currency: 'USD', value: '0.01'}}, + shippingOptions: [{ + id: 'freeShippingOption', + label: 'Free global shipping', + amount: { + currency: 'USD', + value: '0', + }, + selected: true, + }], + }, {requestShipping: true}); + + const response = await test_driver.bless('showing a payment sheet', () => + request.show() + ); + const complete_promise = response.complete('success'); + + // Validate response + assert_equals('freeShippingOption', response.shippingOption); + assert_equals('Reston', response.shippingAddress.city); + assert_equals('US', response.shippingAddress.country); + assert_equals('20190', response.shippingAddress.postalCode); + assert_equals('VA', response.shippingAddress.region); + + return complete_promise; +}, 'Payment handler response should include shipping address and selected shipping option id.'); + +promise_test(async (t) => { + const request = new PaymentRequest([{ + supportedMethods: methodName + }], { + total: { + label: 'Total', + amount: { + currency: 'USD', + value: '0.01' + } + } + }, { + requestPayerName: true, + requestPayerEmail: true, + requestPayerPhone: true + }); + + const response = await test_driver.bless('showing a payment sheet', () => + request.show() + ); + const complete_promise = response.complete('success'); + + // Validate response. + assert_equals('John Smith', response.payerName); + assert_equals('smith@gmail.com', response.payerEmail); + assert_equals('+15555555555', response.payerPhone); + + return complete_promise; +}, 'Payment handler response should include payer\'s contact information.'); +</script> diff --git a/testing/web-platform/tests/payment-handler/untrusted-event.https.html b/testing/web-platform/tests/payment-handler/untrusted-event.https.html new file mode 100644 index 0000000000..900ac79d0d --- /dev/null +++ b/testing/web-platform/tests/payment-handler/untrusted-event.https.html @@ -0,0 +1,56 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<link rel="help" href="https://w3c.github.io/payment-handler/"> +<title>Test for untrusted event</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script> +<script> + +async function getResultFromSW(serviceWorkerContainer) { + return new Promise((resolve, reject) => { + serviceWorkerContainer.addEventListener('message', listener = e => { + serviceWorkerContainer.removeEventListener('message', listener); + if (e.data) { + resolve(e.data); + } else { + reject(); + } + }); + }); +} + +promise_test(async t => { + const registration = await service_worker_unregister_and_register( + t, 'untrusted-event.js', 'payment-app/'); + await wait_for_state(t, registration.installing, 'activated'); + + const controlled_window = (await with_iframe('payment-app/payment.html')).contentWindow; + + // Test for untrusted PaymentRequestEvent + { + const result = getResultFromSW(controlled_window.navigator.serviceWorker); + controlled_window.navigator.serviceWorker.controller.postMessage('paymentrequest'); + + const expected = [ + "InvalidStateError", /* respondWith */ + "InvalidStateError" /* openWindow */ + ]; + + assert_array_equals(await result, expected); + } + + // Test for untrusted CanMakePaymentEvent + { + const result = getResultFromSW(controlled_window.navigator.serviceWorker); + controlled_window.navigator.serviceWorker.controller.postMessage('canmakepayment'); + + const expected = [ + "InvalidStateError", /* respondWith */ + ]; + + assert_array_equals(await result, expected); + } +}); + +</script> diff --git a/testing/web-platform/tests/payment-handler/untrusted-event.js b/testing/web-platform/tests/payment-handler/untrusted-event.js new file mode 100644 index 0000000000..e067952cc3 --- /dev/null +++ b/testing/web-platform/tests/payment-handler/untrusted-event.js @@ -0,0 +1,59 @@ +let sender = null; + +self.addEventListener('message', e => { + sender = e.source; + + if (e.data == 'paymentrequest') { + self.dispatchEvent(new PaymentRequestEvent('paymentrequest', { + methodData: [{ + supportedMethods: 'https://example.com/pay' + }], + total: { + currency: 'USD', + value: '100' + }, + modifiers: [{ + supportedMethods: 'https://example.com/pay' + }] + })); + } else if (e.data == 'canmakepayment') { + self.dispatchEvent(new CanMakePaymentEvent('canmakepayment', { + methodData: [{ + supportedMethods: 'https://example.com/pay' + }], + modifiers: [{ + supportedMethods: 'https://example.com/pay' + }] + })); + } +}); + +self.addEventListener('paymentrequest', async e => { + const result = []; + + try { + e.respondWith({}); + } catch (exception) { + result.push(exception.name); + } + + try { + await e.openWindow('payment-app/payment.html'); + } catch (exception) { + result.push(exception.name); + } + + sender.postMessage(result); +}); + +self.addEventListener('canmakepayment', async e => { + const result = []; + + try { + e.respondWith({}); + } catch (exception) { + result.push(exception.name); + } + + sender.postMessage(result); +}); |