Bug 1437923 [wpt PR 9467] - Tests for PaymentInstruments., a=testonly

Automatic update from web-platform-testsMerge pull request #9467 from rsolomakhin/payment-handler

Tests for PaymentInstruments.

wpt-commits: ae54e16121fd9939277e67c9df6d842caa98e63e
wpt-pr: 9467
wpt-commits: ae54e16121fd9939277e67c9df6d842caa98e63e
wpt-pr: 9467
This commit is contained in:
Rouslan Solomakhin 2018-03-26 13:26:14 +00:00 committed by James Graham
parent 1f024667e5
commit 3c49b5cffa
7 changed files with 677 additions and 0 deletions

View File

@ -286809,6 +286809,26 @@
{} {}
] ]
], ],
"payment-handler/basic-card.js": [
[
{}
]
],
"payment-handler/basic-card.json": [
[
{}
]
],
"payment-handler/payment-app/payment.html": [
[
{}
]
],
"payment-handler/register-and-activate-service-worker.js": [
[
{}
]
],
"payment-method-basic-card/OWNERS": [ "payment-method-basic-card/OWNERS": [
[ [
{} {}
@ -348925,6 +348945,18 @@
{} {}
] ]
], ],
"payment-handler/payment-instruments.https.html": [
[
"/payment-handler/payment-instruments.https.html",
{}
]
],
"payment-handler/payment-request-event.https.html": [
[
"/payment-handler/payment-request-event.https.html",
{}
]
],
"payment-method-basic-card/payment-request-canmakepayment-method.https.html": [ "payment-method-basic-card/payment-request-canmakepayment-method.https.html": [
[ [
"/payment-method-basic-card/payment-request-canmakepayment-method.https.html", "/payment-method-basic-card/payment-request-canmakepayment-method.https.html",
@ -579278,10 +579310,34 @@
"c5e5d0fd086bbe946f99aa8836785c81a2bccb3d", "c5e5d0fd086bbe946f99aa8836785c81a2bccb3d",
"support" "support"
], ],
"payment-handler/basic-card.js": [
"40165fc47d8681622cde490a9a8ec3c8eaded43f",
"support"
],
"payment-handler/basic-card.json": [
"dbed6dd422b57b7c343b2171aeb9ad921eb3231c",
"support"
],
"payment-handler/interfaces.https.any.js": [ "payment-handler/interfaces.https.any.js": [
"a20a5909c9a94120049e45e543cc623b875ea7f5", "a20a5909c9a94120049e45e543cc623b875ea7f5",
"testharness" "testharness"
], ],
"payment-handler/payment-app/payment.html": [
"b2c68838b3d5df98f17ccfd1bf65c4de6579ae65",
"support"
],
"payment-handler/payment-instruments.https.html": [
"14a67dbd2670c661d61ac8dc61c950e572369279",
"testharness"
],
"payment-handler/payment-request-event.https.html": [
"f9556317297607b5e5f649343ae6f365a4df9552",
"testharness"
],
"payment-handler/register-and-activate-service-worker.js": [
"be0cc9201508bb936dc87307b12ee7545020778b",
"support"
],
"payment-method-basic-card/OWNERS": [ "payment-method-basic-card/OWNERS": [
"ee0b02c59588d15b6efdb983c492ebbf50127e1c", "ee0b02c59588d15b6efdb983c492ebbf50127e1c",
"support" "support"

View File

@ -0,0 +1,117 @@
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 expectedMethodName = 'basic-card';
if (methodData.supportedMethods !== expectedMethodName) {
const msg = `Expected payment method name "${expectedMethodName}", but got "${
methodData.supportedMethods
}"`;
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;
}
const supportedTypes = methodData.data.supportedTypes;
if (!supportedTypes) {
const msg = 'Expected supported types in payment method specific data';
event.respondWith(Promise.reject(new Error(msg)));
return;
}
if (supportedTypes.length !== 1) {
const msg = `Expected one supported type, but got ${
supportedTypes.length
} instead`;
event.respondWith(Promise.reject(new Error(msg)));
return;
}
const supportedType = supportedTypes[0];
const expectedSupportedType = 'prepaid';
if (supportedType !== expectedSupportedType) {
const msg = `Expected supported type "${expectedSupportedType}", but got "${supportedType}"`;
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: 'basic-card',
details: {
billingAddress: {
addressLine: ['1875 Explorer St #1000'],
city: 'Reston',
country: 'US',
dependentLocality: '',
languageCode: '',
organization: 'Google',
phone: '+15555555555',
postalCode: '20190',
recipient: 'Jon Doe',
region: 'VA',
sortingCode: '',
},
cardNumber: '4111111111111111',
cardSecurityCode: '123',
cardholderName: 'Jon Doe',
expiryMonth: '12',
expiryYear: '2028',
},
});
});

View File

@ -0,0 +1,10 @@
{
"name": "Test Basic Card Payment Handler",
"icons": [
{
"src": "/images/rgrg-256x256.png",
"sizes": "256x256",
"type": "image/png"
}
]
}

View File

@ -0,0 +1,5 @@
<!doctype html>
<meta charset="utf-8">
<title>Test Payment App</title>
<p>Account balance: $10.00</p>
<button>Authorize</button>

View File

@ -0,0 +1,356 @@
<!doctype html>
<meta charset="utf-8">
<title>Tests for PaymentInstruments interface</title>
<link rel="help" href="https://w3c.github.io/payment-handler/#paymentinstruments-interface">
<link rel="manifest" href="basic-card.json">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="register-and-activate-service-worker.js"></script>
<script>
function runTests(registration) {
promise_test(async t => {
await registration.paymentManager.instruments.clear();
await registration.paymentManager.instruments.set('instrument-key-1', {
name: 'Instrument Name 1',
});
await registration.paymentManager.instruments.set('instrument-key-2', {
name: 'Instrument Name 2',
});
await registration.paymentManager.instruments.delete('instrument-key-1');
await registration.paymentManager.instruments.set('instrument-key-1', {
name: 'Instrument Name 1',
});
const keys = await registration.paymentManager.instruments.keys();
assert_array_equals(keys, ['instrument-key-2', 'instrument-key-1']);
}, 'Instrument keys are returned in the original insertion order');
promise_test(async t => {
await registration.paymentManager.instruments.clear();
await registration.paymentManager.instruments.set(
'existing-instrument-key',
{
name: 'Instrument Name',
},
);
const result = await registration.paymentManager.instruments.delete(
'existing-instrument-key',
);
assert_true(result);
}, 'Deleting an existing instrument returns true');
promise_test(async t => {
await registration.paymentManager.instruments.clear();
await registration.paymentManager.instruments.set(
'existing-instrument-key',
{
name: 'Instrument Name',
},
);
await registration.paymentManager.instruments.delete(
'existing-instrument-key',
);
const result = await registration.paymentManager.instruments.delete(
'existing-instrument-key',
);
assert_false(result);
}, 'Deleting an existing instrument the second time returns false');
promise_test(async t => {
await registration.paymentManager.instruments.clear();
const result = await registration.paymentManager.instruments.delete(
'non-existing-instrument-key',
);
assert_false(result);
}, 'Deleting a non-existing instrument returns false');
promise_test(async t => {
await registration.paymentManager.instruments.clear();
await registration.paymentManager.instruments.set(
'existing-instrument-key',
{
name: 'Instrument Name',
icons: [
{
src: '/images/rgrg-256x256.png',
sizes: '256x256',
type: 'image/png',
},
],
enabledMethods: ['basic-card'],
capabilities: {supportedNetworks: ['mir'], supportedTypes: ['prepaid']},
},
);
const result = await registration.paymentManager.instruments.get(
'existing-instrument-key',
);
assert_equals(result.name, 'Instrument Name');
}, 'Getting an existing instrument returns the instrument');
promise_test(async t => {
await registration.paymentManager.instruments.clear();
const result = await registration.paymentManager.instruments.get(
'non-existing-instrument-key',
);
assert_equals(result, undefined);
}, 'Getting a non-existing instrument returns undefined');
promise_test(async t => {
await registration.paymentManager.instruments.clear();
await registration.paymentManager.instruments.set(
'existing-instrument-key',
{
name: 'Instrument Name v1',
icons: [
{src: '/images/green-16x16.png', sizes: '16x16', type: 'image/png'},
],
enabledMethods: ['basic-card'],
capabilities: {supportedNetworks: ['mir'], supportedTypes: ['prepaid']},
},
);
let result = await registration.paymentManager.instruments.get(
'existing-instrument-key',
);
assert_equals(result.name, 'Instrument Name v1');
assert_equals(result.icons.length, 1);
assert_equals(
result.icons[0].src,
new URL('/images/green-16x16.png', window.location.href).href,
);
assert_equals(result.icons[0].sizes, '16x16');
assert_equals(result.icons[0].type, 'image/png');
assert_array_equals(result.enabledMethods, ['basic-card']);
assert_array_equals(result.capabilities.supportedNetworks, ['mir']);
assert_array_equals(result.capabilities.supportedTypes, ['prepaid']);
await registration.paymentManager.instruments.set(
'existing-instrument-key',
{
name: 'Instrument Name v2',
icons: [
{
src: '/images/rgrg-256x256.png',
sizes: '256x256',
type: 'image/png',
},
],
enabledMethods: ['basic-card'],
capabilities: {supportedNetworks: ['visa'], supportedTypes: ['credit']},
},
);
result = await registration.paymentManager.instruments.get(
'existing-instrument-key',
);
assert_equals(result.name, 'Instrument Name v2');
assert_equals(result.icons.length, 1);
assert_equals(
result.icons[0].src,
new URL('/images/rgrg-256x256.png', window.location.href).href,
);
assert_equals(result.icons[0].sizes, '256x256');
assert_equals(result.icons[0].type, 'image/png');
assert_array_equals(result.enabledMethods, ['basic-card']);
assert_array_equals(result.capabilities.supportedNetworks, ['visa']);
assert_array_equals(result.capabilities.supportedTypes, ['credit']);
}, 'Resetting an existing instrument updates the instrument');
promise_test(async t => {
await registration.paymentManager.instruments.clear();
await registration.paymentManager.instruments.set(
'existing-instrument-key',
{
name: 'Instrument Name',
icons: [
{
src: '/images/rgrg-256x256.png',
sizes: '256x256',
type: 'image/png',
},
],
enabledMethods: ['basic-card'],
capabilities: {supportedNetworks: ['mir'], supportedTypes: ['prepaid']},
},
);
await registration.paymentManager.instruments.clear();
const result = await registration.paymentManager.instruments.get(
'existing-instrument-key',
);
assert_equals(result, undefined);
}, 'Clearing the instruments');
promise_test(async t => {
await registration.paymentManager.instruments.clear();
const setPromise = registration.paymentManager.instruments.set(
'instrument-key',
{
name: 'Instrument Name',
icons: [
{
src: '/images/rgrg-256x256.png',
sizes: '256x256',
type: 'image/jif',
},
],
enabledMethods: ['basic-card'],
},
);
return promise_rejects(t, new TypeError(), setPromise);
}, 'Cannot register instruments with invalid icon media type image/jif');
promise_test(async t => {
await registration.paymentManager.instruments.clear();
const setPromise = registration.paymentManager.instruments.set(
'instrument-key',
{
name: 'Instrument Name',
icons: [
{
src: '/images/rgrg-256x256.png',
sizes: '256x256',
type: 'image/pn' + 'g'.repeat(1000),
},
],
enabledMethods: ['basic-card'],
},
);
return promise_rejects(t, new TypeError(), setPromise);
}, "Don't crash when registering instruments with very long icon media type image/pngggggg...");
promise_test(async t => {
await registration.paymentManager.instruments.clear();
return registration.paymentManager.instruments.set('instrument-key', {
name: 'Instrument Name',
icons: [
{
src: '/images/rgrg-256x256.png',
sizes: '8'.repeat(100000) + 'x' + '8'.repeat(100000),
type: 'image/png',
},
],
enabledMethods: ['basic-card'],
});
}, "Don't crash when registering an instrument with a very long icon size 888...x888...");
promise_test(async t => {
await registration.paymentManager.instruments.clear();
const setPromise = registration.paymentManager.instruments.set(
'instrument-key',
{
name: 'Instrument Name',
icons: [
{
src: '/images/rgrg-256x256.png',
sizes: '256 256',
type: 'image/png',
},
],
enabledMethods: ['basic-card'],
},
);
return promise_rejects(t, new TypeError(), setPromise);
}, 'Cannot register instruments with invalid icon size "256 256" (missing "x")');
promise_test(async t => {
await registration.paymentManager.instruments.clear();
const setPromise = registration.paymentManager.instruments.set(
'instrument-key',
{
name: 'Instrument Name',
icons: [
{
src: '/images/rg\0rg-256x256.png',
sizes: '256x256',
type: 'image/png',
},
],
enabledMethods: ['basic-card'],
},
);
return promise_rejects(t, new TypeError(), setPromise);
}, 'Cannot register instruments with invalid icon URL (has a null character)');
promise_test(async t => {
await registration.paymentManager.instruments.clear();
const setPromise = registration.paymentManager.instruments.set(
'instrument-key',
{
name: 'Instrument Name',
icons: [
{
src: 'http://test.example/images/rgrg-256x256.png',
sizes: '256x256',
type: 'image/png',
},
],
enabledMethods: ['basic-card'],
},
);
return promise_rejects(t, new TypeError(), setPromise);
}, 'Cannot register instruments with non-existing non-https icon URL');
promise_test(async t => {
await registration.paymentManager.instruments.clear();
const setPromise = registration.paymentManager.instruments.set(
'instrument-key',
{
name: 'Instrument Name',
icons: [
{
src:
'http://www.chromium.org/_/rsrc/1438879449147/config/customLogo.gif',
sizes: '48x48',
type: 'image/gif',
},
],
enabledMethods: ['basic-card'],
},
);
return promise_rejects(t, new TypeError(), setPromise);
}, 'Cannot register instruments with an existing non-https icon URL');
async function testUnusualStrings(existingKey, nonExistingKey) {
await registration.paymentManager.instruments.clear();
await registration.paymentManager.instruments.set(existingKey, {
name: existingKey,
icons: [
{src: '/images/rgrg-256x256.png', sizes: '256x256', type: 'image/png'},
],
enabledMethods: [existingKey],
capabilities: {aCapabilityName: existingKey},
});
const hasExistingInstrument = await registration.paymentManager.instruments.has(
existingKey,
);
assert_true(hasExistingInstrument);
const hasNonExistingInstrument = await registration.paymentManager.instruments.has(
nonExistingKey,
);
assert_false(hasNonExistingInstrument);
const existingInstrument = await registration.paymentManager.instruments.get(
existingKey,
);
assert_equals(existingInstrument.name, existingKey);
const nonExistingInstrument = await registration.paymentManager.instruments.get(
nonExistingKey,
);
assert_equals(nonExistingInstrument, undefined);
const deletedExistingInstrument = await registration.paymentManager.instruments.delete(
existingKey,
);
assert_true(deletedExistingInstrument);
const deletedNonExistingInstrument = await registration.paymentManager.instruments.delete(
nonExistingKey,
);
assert_false(deletedNonExistingInstrument);
}
promise_test(async t => {
const length = 100000;
await testUnusualStrings('0'.repeat(length), '1'.repeat(length));
}, "Don't crash on very long key, name, method, and capability strings.");
promise_test(async t => {
await testUnusualStrings('foo\0bar', 'foo\0baz');
}, "Don't crash on null characters in key, name, method, and capability strings.");
}
registerAndActiveServiceWorker('basic-card.js', 'payment-app/', runTests);
</script>

View File

@ -0,0 +1,105 @@
<!doctype html>
<meta charset="utf-8">
<title>Tests for PaymentRequestEvent</title>
<link rel="help" href="https://w3c.github.io/payment-handler/#the-paymentrequestevent">
<link rel="manifest" href="/payment-handler/basic-card.json">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="register-and-activate-service-worker.js"></script>
<p>When the payment sheet is shown, please authorize the mock payment.</p>
<script>
async function setInstrumentsAndRunTests(registration) {
await registration.paymentManager.instruments.clear();
await registration.paymentManager.instruments.set('instrument-key', {
name: 'Instrument Name',
icons: [
{src: '/images/rgrg-256x256.png', sizes: '256x256', type: 'image/png'},
],
enabledMethods: ['basic-card'],
capabilities: {supportedNetworks: ['mir'], supportedTypes: ['prepaid']},
});
runTests();
}
function runTests() {
promise_test(async t => {
const response = await new PaymentRequest(
[
{supportedMethods: 'basic-card', data: {supportedTypes: ['prepaid']}},
{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: 'basic-card',
data: {supportedNetworks: ['mir']},
total: {
label: 'MIR total',
amount: {currency: 'USD', value: '0.0099'},
},
additionalDisplayItems: [
{label: 'Item 3', amount: {currency: 'GBP', value: '-0.0001'}},
],
},
{
supportedMethods: 'basic-card',
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: {supportedTypes: ['prepaid']},
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, 'basic-card');
assert_array_equals(response.details.billingAddress.addressLine, [
'1875 Explorer St #1000',
]);
assert_equals(response.details.billingAddress.city, 'Reston');
assert_equals(response.details.billingAddress.country, 'US');
assert_equals(response.details.billingAddress.dependentLocality, '');
assert_equals(response.details.billingAddress.languageCode, '');
assert_equals(response.details.billingAddress.organization, 'Google');
assert_equals(response.details.billingAddress.phone, '+15555555555');
assert_equals(response.details.billingAddress.postalCode, '20190');
assert_equals(response.details.billingAddress.recipient, 'Jon Doe');
assert_equals(response.details.billingAddress.region, 'VA');
assert_equals(response.details.billingAddress.sortingCode, '');
assert_equals(response.details.cardNumber, '4111111111111111');
assert_equals(response.details.cardSecurityCode, '123');
assert_equals(response.details.cardholderName, 'Jon Doe');
assert_equals(response.details.expiryMonth, '12');
assert_equals(response.details.expiryYear, '2028');
return promise;
}, 'Can perform payment');
}
registerAndActiveServiceWorker(
'basic-card.js',
'payment-app/',
setInstrumentsAndRunTests,
);
</script>

View File

@ -0,0 +1,28 @@
async function registerAndActiveServiceWorker(script, scope, callback) {
const registration = await navigator.serviceWorker.register(script, {scope});
const serviceWorker =
registration.installing || registration.waiting || registration.active;
if (serviceWorker) {
waitForServiceWorkerActivation(scope, callback);
return;
}
registration.addEventListener('updatefound', event => {
waitForServiceWorkerActivation(scope, callback);
});
}
async function waitForServiceWorkerActivation(scope, callback) {
const registration = await navigator.serviceWorker.getRegistration(scope);
if (registration.active) {
callback(registration);
return;
}
const serviceWorker = registration.installing || registration.waiting;
serviceWorker.addEventListener('statechange', event => {
if (event.target.state == 'activated') {
callback(registration);
}
});
}