<!doctype html>
<meta charset="utf8">
<link rel="help" href="https://w3c.github.io/payment-request/#user-accepts-the-payment-request-algorithm">
<title>
User accepts the payment request algorithm
</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
setup({ explicit_done: true, explicit_timeout: true });
const applePay = Object.freeze({
supportedMethods: "https://apple.com/apple-pay",
data: {
version: 3,
merchantIdentifier: "merchant.com.example",
countryCode: "US",
merchantCapabilities: ["supports3DS"],
supportedNetworks: ["visa"],
}
});
const basicCardMethod = Object.freeze({
supportedMethods: "basic-card",
});
const validMethod = Object.freeze({
supportedMethods: "this-is-just-for-testings-will-never-match",
});
const methods = Object.freeze([basicCardMethod, validMethod, applePay]);
const validAmount = Object.freeze({
currency: "USD",
value: "5.00",
});
const shippingOptions = [
Object.freeze({
id: "option1",
label: "Option 1",
amount: validAmount,
selected: false,
}),
Object.freeze({
id: "option 2",
label: "Option 2",
amount: validAmount,
selected: true,
}),
];
const detailsNoShippingOptions = Object.freeze({
total: {
label: "Total due",
amount: validAmount,
},
});
const detailsWithShippingOptions = Object.assign({}, detailsNoShippingOptions, {
shippingOptions,
});
const optionsRequestNothing = Object.freeze({
requestShipping: false,
requestPayerEmail: false,
requestPayerName: false,
requestPayerPhone: false,
});
const optionsRequestEverything = Object.freeze({
requestShipping: true,
requestPayerEmail: true,
requestPayerName: true,
requestPayerPhone: true,
});
test(() => {
// smoke test
try {
new PaymentRequest(methods, detailsNoShippingOptions);
} catch (err) {
done();
throw err;
}
}, "Must be able to construct a payment request (smoke test)");
function testAcceptRequestAlgorithm(
button,
details,
options = {},
expectedResponse = {}
) {
button.disabled = true;
promise_test(async t => {
const request = new PaymentRequest(methods, details, options);
const response = await request.show();
assert_true(
response instanceof PaymentResponse,
"Expected an instance of PaymentResponse."
);
// Response [[calledComplete]] is false, so this shouldn't throw
await response.complete("success");
// For good measure, test that subsequent complete()
for (const state of [undefined, "success", "fail", "unknown"]) {
await promise_rejects_dom(
t,
"InvalidStateError",
response.complete(state),
"Response [[calledComplete]] is true, so InvalidStateError"
);
}
assert_equals(
request.id,
response.requestId,
"Request and response ids must match."
);
assert_true(response.details instanceof Object, "Expected an object");
assert_equals(
response.shippingAddress,
request.shippingAddress,
"Request and response must reference same shippingAddress (or both null)."
);
assert_equals(
response.shippingOption,
request.shippingOption,
"Request and response must be the same value (or both null)."
);
if (options.requestShipping === true) {
assert_true(
response.shippingAddress instanceof ContactAddress,
"Expected an instance of ContactAddress."
);
}
const expected = {
methodName: "basic-card",
payerEmail: options.requestPayerEmail
? expectedResponse.payerEmail
: null,
payerName: options.requestPayerName ? expectedResponse.payerName : null,
payerPhone: options.requestPayerPhone
? expectedResponse.payerPhone
: null,
};
for (const [attr, expectedValue] of Object.entries(expected)) {
assert_equals(
response[attr],
expectedValue,
`response.${attr} must be ${expectedValue}`
);
}
await promise_rejects_dom(
t,
"InvalidStateError",
request.show(),
"Request [[state]] is closed, so InvalidStateError"
);
}, button.textContent.trim());
}
</script>
<section>
<h2 id="user-accepts-payment-request">User accepts payment request</h2>
<p>
Click on each button in sequence from top to bottom without refreshing the page.
Each button will bring up the Payment Request UI window.
</p>
<p>
When shown the payment sheet, please input a credit card and select Pay.
</p>
<ol>
<li>
<button onclick="
const detailsWithId = Object.assign({}, detailsNoShippingOptions, { id: 'pass' });
testAcceptRequestAlgorithm(this, detailsWithId, optionsRequestNothing);">
User accepts payment request, but not shipping is requested.
</button> Use any credit card to pay.
</li>
<li>
<button onclick="
const requestShipping = Object.assign({}, optionsRequestNothing, {requestShipping: true});
const expectedValues = { shippingOption: 'option 2' };
testAcceptRequestAlgorithm(this, detailsWithShippingOptions, requestShipping, expectedValues);">
User accepts payment request, merchant requests shipping.
</button> Select any shipping option, and use any credit card to pay.
</li>
<li>
<button onclick="
const requestPayerEmail = Object.assign({}, optionsRequestNothing, {requestPayerEmail: true});
const expectValues = { payerEmail: '[email protected]' };
testAcceptRequestAlgorithm(this, detailsNoShippingOptions, requestPayerEmail, expectValues);">
User accepts payment request, merchant requests email.
</button>
When prompted, please use "[email protected]" as the email.
</li>
<li>
<button onclick="
const requestPayerPhone = Object.assign({}, optionsRequestNothing, {requestPayerPhone: true});
const expectValues = { payerPhone: '+12345678910' };
testAcceptRequestAlgorithm(this, detailsNoShippingOptions, requestPayerPhone, expectValues);">
User accepts payment request, merchant requests phone.
</button>
When prompted, please use "+12345678910" as the phone number.
</li>
<li>
<button onclick="
const requestPayerName = Object.assign({}, optionsRequestNothing, {requestPayerName: true});
const expectValues = { payerName: 'web platform test' };
testAcceptRequestAlgorithm(this, detailsNoShippingOptions, requestPayerName, expectValues);">
User accepts payment request, merchant requests payer's name.
</button>
When prompted, please use "web platform test" as the payer name.
</li>
<li>
<button onclick="
const expectValues = {
payerEmail: '[email protected]',
payerName: 'web platform test',
payerPhone: '+12345678910',
shippingOption: 'option 2',
};
testAcceptRequestAlgorithm(this, detailsWithShippingOptions, optionsRequestEverything, expectValues);">
User accepts payment request, merchant requests everything.
</button>
When prompted, please use: "+12345678910" as the phone number, "web platform test" as the payer name, and "[email protected]" as the email. Then press Pay.
</li>
<li>
<button onclick="done()">Done</button>
</li>
</ol>
</section>
<small>
If you find a buggy test, please <a href="https://github.com/web-platform-tests/wpt/issues">file a bug</a>
and tag one of the <a href="https://github.com/web-platform-tests/wpt/blob/master/payment-request/META.yml">suggested reviewers</a>.
</small>