| <!doctype html> |
| <meta charset="utf-8"> |
| <title>Tests for CanMakePaymentEvent</title> |
| <link rel="help" href="https://w3c.github.io/payment-handler/#the-canmakepaymentevent"> |
| <link rel="manifest" href="manifest.json"> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <p>The "basic-card" test requires that you don't have a prepaid MIR card stored |
| in the browser. If you do, please remove it for the duration of the test.</p> |
| <script> |
| const instrumentKey = 'instrument-key'; |
| |
| async function registerApp(methodName) { |
| await navigator.serviceWorker.register('app-can-make-payment.js'); |
| const registration = await navigator.serviceWorker.ready; |
| if (!registration.paymentManager) { |
| return; |
| } |
| if (registration.paymentManager.requestPermission) { |
| const permission = await registration.paymentManager.requestPermission(); |
| if (permission !== 'granted') { |
| return; |
| } |
| } |
| await registration.paymentManager.instruments.set(instrumentKey, { |
| name: 'Test Payment Method', |
| method: methodName, |
| }); |
| return registration; |
| } |
| |
| function buildPaymentRequest(methodName) { |
| 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 => { |
| const methodName = window.location.origin + '/canMakePayment-true'; |
| // Intentionally do not install the payment app. |
| const request = buildPaymentRequest(methodName); |
| 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.', |
| ); |
| await promise_rejects(t, 'NotSupportedError', request.show()); |
| }, 'If a payment handler is not installed, then the payment method is not supported.'); |
| |
| promise_test(async t => { |
| const methodName = window.location.origin + '/canMakePayment-false'; |
| await registerApp(methodName); |
| const request = buildPaymentRequest(methodName); |
| 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.', |
| ); |
| await promise_rejects(t, 'NotSupportedError', request.show()); |
| }, 'If CanMakePaymentEvent.respondWith(false) is called, then the payment method is not supported.'); |
| |
| promise_test(async t => { |
| const methodName = window.location.origin + '/canMakePayment-promise-false'; |
| await registerApp(methodName); |
| const request = buildPaymentRequest(methodName); |
| 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.', |
| ); |
| await promise_rejects(t, 'NotSupportedError', request.show()); |
| }, 'If CanMakePaymentEvent.respondWith(Promise.resolve(false)) is called, then the payment method is not supported.'); |
| |
| promise_test(async t => { |
| const methodName = window.location.origin + '/canMakePayment-true'; |
| await registerApp(methodName); |
| const request = buildPaymentRequest(methodName); |
| 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.', |
| ); |
| const acceptPromise = request.show(); |
| await request.abort(); |
| await promise_rejects(t, 'AbortError', acceptPromise); |
| }, 'If CanMakePaymentEvent.respondWith(true) is called, then the payment method is supported.'); |
| |
| promise_test(async t => { |
| const methodName = window.location.origin + '/canMakePayment-promise-true'; |
| await registerApp(methodName); |
| const request = buildPaymentRequest(methodName); |
| 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.', |
| ); |
| const acceptPromise = request.show(); |
| await request.abort(); |
| await promise_rejects(t, 'AbortError', acceptPromise); |
| }, 'If CanMakePaymentEvent.respondWith(Promise.resolve(true)) is called, then the payment method is supported.'); |
| |
| promise_test(async t => { |
| const methodName = window.location.origin + '/canMakePayment-custom-error'; |
| await registerApp(methodName); |
| const request = buildPaymentRequest(methodName); |
| 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.', |
| ); |
| await promise_rejects(t, 'NotSupportedError', request.show()); |
| }, 'If CanMakePaymentEvent.respondWith(Promise.reject(error)) is called, then the payment method is not supported.'); |
| |
| promise_test(async t => { |
| const methodName = 'basic-card'; |
| await registerApp(methodName); |
| const request = buildPaymentRequest(methodName); |
| 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 due to capability matching in the browser.', |
| ); |
| }, 'If an app supports "basic-card" in general and that\'s what merchant requests as well, then capability filtering should make the app available for use. CanMakePaymentEvent should not be fired for "basic-card".'); |
| |
| promise_test(async t => { |
| const methodName = 'basic-card'; |
| await registerApp(methodName); |
| const cardNetwork = 'mir'; |
| const request = new PaymentRequest( |
| [ |
| { |
| supportedMethods: methodName, |
| data: { |
| supportedNetworks: [cardNetwork], |
| }, |
| }, |
| ], |
| { |
| total: { |
| label: 'Total', |
| amount: { |
| currency: 'USD', |
| value: '0', |
| }, |
| }, |
| }, |
| ); |
| 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 due to capability matching in the browser.', |
| ); |
| }, 'If an app has less specific "basic-card" capabilites than merchant\'s request, capability filtering should not make the app available for use. CanMakePaymentEvent should not be fired for "basic-card". '); |
| |
| promise_test(async t => { |
| const methodName = 'basic-card'; |
| const cardNetwork = 'mir'; |
| const registration = await registerApp(methodName); |
| await registration.paymentManager.instruments.set(instrumentKey, { |
| name: 'Test Payment Method', |
| method: methodName, |
| capabilities: { |
| supportedNetworks: [cardNetwork], |
| }, |
| }); |
| const request = new PaymentRequest( |
| [ |
| { |
| supportedMethods: methodName, |
| data: { |
| supportedNetworks: [cardNetwork], |
| }, |
| }, |
| ], |
| { |
| total: { |
| label: 'Total', |
| amount: { |
| currency: 'USD', |
| value: '0', |
| }, |
| }, |
| }, |
| ); |
| 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 due to capability matching in the browser.', |
| ); |
| }, 'If an app has the exact "basic-card" capabilities that a merchant requested, capability filtering should make the app available for use. CanMakePaymentEvent should not be fired for "basic-card".'); |
| |
| promise_test(async t => { |
| const methodName = 'basic-card'; |
| const cardNetwork = 'mir'; |
| const registration = await registerApp(methodName); |
| await registration.paymentManager.instruments.set(instrumentKey, { |
| name: 'Test Payment Method', |
| method: methodName, |
| capabilities: { |
| supportedNetworks: [cardNetwork], |
| }, |
| }); |
| const request = buildPaymentRequest(methodName); |
| 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 due to capability matching in the browser.', |
| ); |
| }, 'If an app has more specific "basic-card" capabilities than merchant\'s request, capability filtering should make the app available for use. CanMakePaymentEvent should not be fired for "basic-card".'); |
| </script> |