Bug 1483156 - Currency of PaymentItem total should be 'USD', but got BOB r=edenchuang

--HG--
extra : amend_source : 8bfb03ef649733c587b1b04bfea6260fb5b2b4fd
This commit is contained in:
Marcos Cáceres 2018-08-21 20:16:00 +03:00
parent 10a0917d53
commit d9c9ac71d9
2 changed files with 355 additions and 372 deletions

View file

@ -3,46 +3,52 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
const paymentSrv = Cc[
"@mozilla.org/dom/payments/payment-request-service;1"
].getService(Ci.nsIPaymentRequestService);
const InvalidDetailsUIService = {
showPayment: function(requestId) {
showPayment(requestId) {
paymentSrv.changeShippingOption(requestId, "");
},
abortPayment: function(requestId) {
let abortResponse = Cc["@mozilla.org/dom/payments/payment-abort-action-response;1"].
createInstance(Ci.nsIPaymentAbortActionResponse);
abortPayment(requestId) {
const abortResponse = Cc[
"@mozilla.org/dom/payments/payment-abort-action-response;1"
].createInstance(Ci.nsIPaymentAbortActionResponse);
abortResponse.init(requestId, Ci.nsIPaymentActionResponse.ABORT_SUCCEEDED);
paymentSrv.respondPayment(abortResponse.QueryInterface(Ci.nsIPaymentActionResponse));
},
completePayment: function(requestId) {
},
updatePayment: function(requestId) {
paymentSrv.respondPayment(
abortResponse.QueryInterface(Ci.nsIPaymentActionResponse)
);
},
completePayment(requestId) {},
updatePayment(requestId) {},
QueryInterface: ChromeUtils.generateQI([Ci.nsIPaymentUIService]),
};
function emitTestFail(message) {
sendAsyncMessage("test-fail", message);
}
function checkLowerCaseCurrency() {
const paymentEnum = paymentSrv.enumerate();
if (!paymentEnum.hasMoreElements()) {
emitTestFail("PaymentRequestService should have at least one payment request.");
const msg =
"PaymentRequestService should have at least one payment request.";
sendAsyncMessage("test-fail", msg);
}
while (paymentEnum.hasMoreElements()) {
let payRequest = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
const payRequest = paymentEnum
.getNext()
.QueryInterface(Ci.nsIPaymentRequest);
if (!payRequest) {
emitTestFail("Fail to get existing payment request.");
sendAsyncMessage("test-fail", "Fail to get existing payment request.");
break;
}
if (payRequest.paymentDetails.totalItem.amount.currency != "USD") {
emitTestFail("Currency of PaymentItem total should be 'USD', but got " +
payRequest.paymentDetails.totalItem.amount.currency + ".");
const { currency } = payRequest.paymentDetails.totalItem.amount;
if (currency != "USD") {
const msg =
"Currency of PaymentItem total should be 'USD', but got ${currency}";
sendAsyncMessage("check-complete");
}
}
paymentSrv.cleanup();
@ -51,10 +57,10 @@ function checkLowerCaseCurrency() {
addMessageListener("check-lower-case-currency", checkLowerCaseCurrency);
addMessageListener("set-update-with-invalid-details-ui-service", function() {
paymentSrv.setTestingUIService(InvalidDetailsUIService.QueryInterface(Ci.nsIPaymentUIService));
addMessageListener("set-update-with-invalid-details-ui-service", () => {
paymentSrv.setTestingUIService(
InvalidDetailsUIService.QueryInterface(Ci.nsIPaymentUIService)
);
});
addMessageListener("teardown", function() {
sendAsyncMessage("teardown-complete");
});
addMessageListener("teardown", () => sendAsyncMessage("teardown-complete"));

View file

@ -1,376 +1,353 @@
<!DOCTYPE HTML>
<html>
<meta charset="utf-8">
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1367669
https://bugzilla.mozilla.org/show_bug.cgi?id=1388661
-->
<head>
<meta charset="utf-8">
<title>Test for PaymentRequest API currency amount validation</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript">
<title>Test for PaymentRequest API currency amount validation</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script>
"use strict";
SimpleTest.waitForExplicitFinish();
"use strict";
SimpleTest.waitForExplicitFinish();
const gUrl = SimpleTest.getTestFileURL(
"CurrencyAmountValidationChromeScript.js"
);
const gScript = SpecialPowers.loadChromeScript(gUrl);
var gUrl = SimpleTest.getTestFileURL('CurrencyAmountValidationChromeScript.js');
var gScript = SpecialPowers.loadChromeScript(gUrl);
function testFailHandler(message) {
ok(false, message);
}
gScript.addMessageListener("test-fail", testFailHandler);
function testFailHandler(message) {
ok(false, message);
}
gScript.addMessageListener("test-fail", testFailHandler);
const defaultMethods = [{
const defaultMethods = [
{
supportedMethods: "basic-card",
}];
const defaultDetails = {
total: {
label: "total",
amount: {
currency: "usd",
value: "1.00",
},
},
];
const defaultDetails = {
total: {
label: "total",
amount: {
currency: "usd",
value: "1.00",
},
};
},
};
const specialAmountDetails = {
total: {
label: "total",
amount: {
currency: "usd",
value: {
toString() {
throw "42";
},
const specialAmountDetails = {
total: {
label: "total",
amount: {
currency: "usd",
value: {
toString() {
throw "42";
},
},
},
};
},
};
const wellFormedCurrencyCodes = [
"BOB",
"EUR",
"usd", // currency codes are case-insensitive
"XdR",
"xTs",
];
const wellFormedCurrencyCodes = [
"BOB",
"EUR",
"usd", // currency codes are case-insensitive
"XdR",
"xTs",
];
const invalidCurrencyCodes = [
"",
"€",
"$",
"SFr.",
"DM",
"KR₩",
"702",
"ßP",
"ınr",
"invalid",
"in",
"123",
];
const invalidCurrencyCodes = [
"",
"€",
"$",
"SFr.",
"DM",
"KR₩",
"702",
"ßP",
"ınr",
"invalid",
"in",
"123",
];
const updatedInvalidCurrencyDetails = {
total: {
label: "Total",
amount: {
currency: "Invalid",
value: "1.00"
}
const updatedInvalidCurrencyDetails = {
total: {
label: "Total",
amount: {
currency: "Invalid",
value: "1.00",
},
};
},
};
const updatedInvalidAmountDetails = {
total: {
label: "Total",
amount: {
currency: "USD",
value: "-1.00",
},
const updatedInvalidAmountDetails = {
total: {
label: "Total",
amount: {
currency: "USD",
value: "-1.00",
},
}
},
};
const invalidAmounts = [
"-",
"notdigits",
"ALSONOTDIGITS",
"10.",
".99",
"-10.",
"-.99",
"10-",
"1-0",
"1.0.0",
"1/3",
"",
null,
" 1.0 ",
" 1.0 ",
"1.0 ",
"USD$1.0",
"$1.0",
{
toString() {
return " 1.0";
},
const invalidAmounts = [
"-",
"notdigits",
"ALSONOTDIGITS",
"10.",
".99",
"-10.",
"-.99",
"10-",
"1-0",
"1.0.0",
"1/3",
"",
null,
" 1.0 ",
" 1.0 ",
"1.0 ",
"USD$1.0",
"$1.0",
{
toString() {
return " 1.0";
},
undefined,
];
const invalidTotalAmounts = invalidAmounts.concat([
"-1",
"-1.0",
"-1.00",
"-1000.000",
]);
},
undefined,
];
const invalidTotalAmounts = invalidAmounts.concat([
"-1",
"-1.0",
"-1.00",
"-1000.000",
]);
function updateWithInvalidCurrency() {
return new Promise((resolve, reject) => {
resolve(updatedInvalidCurrencyDetails);
});
}
function updateWithInvalidAmount() {
return new Promise((resolve, reject) => {
resolve(updatedInvalidAmountDetails);
});
}
function updateWithInvalidAmount() {
return new Promise((resolve, reject) => {
resolve(updatedInvalidAmountDetails);
});
}
function testWithLowerCaseCurrency() {
return new Promise((resolve, reject) => {
const payRequest = new PaymentRequest(defaultMethods, defaultDetails);
ok(payRequest, "PaymentRequest should be created");
gScript.addMessageListener("check-complete", function checkCompleteHandler() {
async function testWithLowerCaseCurrency() {
const payRequest = new PaymentRequest(defaultMethods, defaultDetails);
return new Promise(resolve => {
gScript.addMessageListener(
"check-complete",
function checkCompleteHandler() {
gScript.removeMessageListener("check-complete", checkCompleteHandler);
resolve();
});
gScript.sendAsyncMessage("check-lower-case-currency");
});
}
function testWithWellFormedCurrencyCodes() {
return new Promise((resolve, reject) => {
for (const currency of wellFormedCurrencyCodes) {
let details = {
total: {
label: "Well Formed Currency",
amount: {
currency: currency,
value: "1.00",
},
},
};
try {
const payRequest = new PaymentRequest(defaultMethods, details);
} catch (e) {
ok(false, "Unexpected error while creating payment request with well formed currency("
+ currency + ") " + e.name + ".");
}
}
resolve();
});
}
function testWithInvalidCurrencyCodes() {
return new Promise((resolve, reject) => {
for (const invalidCurrency of invalidCurrencyCodes) {
let invalidDetails = {
total: {
label: "Invalid Currency",
amount: {
currency: invalidCurrency,
value: "1.00",
},
},
};
try {
const payRequest = new PaymentRequest(defaultMethods, invalidDetails);
ok(false, "Expected fail to create PaymentRequest with invalid currency(" + invalidCurrency + ").");
} catch (e) {
is(e.name, "RangeError", "Expected rejected with 'RangeError', but got " + e.name + ".");
}
}
resolve();
});
}
function testUpdateWithInvalidCurrency() {
const handler = SpecialPowers.getDOMWindowUtils(window).setHandlingUserInput(true);
gScript.sendAsyncMessage("set-update-with-invalid-details-ui-service");
return new Promise((resolve, reject) => {
const payRequest = new PaymentRequest(defaultMethods, defaultDetails);
payRequest.addEventListener("shippingaddresschange", event => {
event.updateWith(updateWithInvalidCurrency());
});
payRequest.addEventListener("shippingoptionchange", event => {
event.updateWith(updateWithInvalidCurrency());
});
payRequest.show().then((result) => {
ok(false, "Should be rejected with 'RangeError', but got resolved");
resolve();
}, (result) => {
is(result.name, "RangeError", "Should be rejected with 'RangeError', but got " + result.name + ".");
resolve();
}).catch(e => {
ok(false, "Unexpected error: " + e.name);
resolve();
}).finally(handler.destruct);
});
}
function testUpdateWithInvalidAmount() {
const handler = SpecialPowers.getDOMWindowUtils(window).setHandlingUserInput(true);
gScript.sendAsyncMessage("set-update-with-invalid-details-ui-service");
return new Promise((resolve, reject) => {
const payRequest = new PaymentRequest(defaultMethods, defaultDetails);
payRequest.addEventListener("shippingaddresschange", event => {
event.updateWith(updateWithInvalidAmount());
});
payRequest.addEventListener("shippingoptionchange", event => {
event.updateWith(updateWithInvalidAmount());
});
payRequest.show().then((result) => {
ok(false, "Should be rejected with 'TypeError', but got resolved");
resolve();
}, (result) => {
is(result.name, "TypeError", "Should be rejected with 'TypeError', but got " + result.name + ".");
resolve();
}).catch(e => {
ok(false, "Unexpected error: " + e.name);
resolve();
}).finally(handler.destruct);
});
}
function testSpecialAmount() {
return new Promise((resolve, reject) => {
try {
new PaymentRequest([{supportedMethods: "basic-card"}],
specialAmountDetails);
ok(false, "Should throw '42', but got resolved.");
resolve();
} catch (e) {
is(e, "42", "Expected throw '42'. but got " + e);
resolve();
}
});
}
function testInvalidTotalAmounts() {
return new Promise((resolve, reject) => {
for (const amount of invalidTotalAmounts) {
try {
new PaymentRequest(
[
{
supportedMethods: "basic-card",
},
],
{
total: {
label: "",
amount: {
currency: "USD",
value: amount,
},
},
}
);
ok(false, "Should throw 'TypeError', but got resolved.");
resolve();
}
catch (err) {
is(err.name, "TypeError",
"Expected 'TypeError', but got '" + err.name + "'");
resolve();
};
}
});
}
function testInvalidAmounts() {
return new Promise((resolve, reject) => {
for (const amount of invalidAmounts) {
try {
new PaymentRequest(
[
{
supportedMethods: "basic-card",
},
],
{
total: {
label: "",
amount: {
currency: "USD",
value: "1.00",
},
},
displayItems: [
{
label: "",
amount: {
currency: "USD",
value: amount,
},
},
],
}
);
ok(false, "Should throw 'TypeError', but got resolved.");
resolve();
}
catch (err) {
is(err.name, "TypeError",
"Expected 'TypeError', but got '" + err.name + "'");
resolve();
};
}
});
}
function teardown() {
gScript.addMessageListener("teardown-complete", function teardownCompleteHandler() {
gScript.removeMessageListener("teardown-complete", teardownCompleteHandler);
gScript.removeMessageListener("test-fail", testFailHandler)
gScript.destroy();
SimpleTest.finish();
});
gScript.sendAsyncMessage("teardown");
}
function runTests() {
testInvalidTotalAmounts()
.then(testSpecialAmount)
.then(testInvalidAmounts)
.then(testWithLowerCaseCurrency)
.then(testWithWellFormedCurrencyCodes)
.then(testWithInvalidCurrencyCodes)
.then(testUpdateWithInvalidAmount)
.then(testUpdateWithInvalidCurrency)
.then(teardown)
.catch( e => {
ok(false, "Unexpected error: " + e.name);
SimpleTest.finish();
});
}
window.addEventListener('load', function() {
SpecialPowers.pushPrefEnv({
'set': [
['dom.payments.request.enabled', true],
]
}, runTests);
);
gScript.sendAsyncMessage("check-lower-case-currency");
});
}
</script>
</head>
function testWithWellFormedCurrencyCodes() {
for (const currency of wellFormedCurrencyCodes) {
const details = {
total: {
label: "Well Formed Currency",
amount: {
currency: currency,
value: "1.00",
},
},
};
try {
const payRequest = new PaymentRequest(defaultMethods, details);
} catch (e) {
const msg = `Unexpected error while creating payment request with well-formed currency (${currency}) ${
e.name
}`;
ok(false, msg);
}
}
}
function testWithInvalidCurrencyCodes() {
for (const invalidCurrency of invalidCurrencyCodes) {
const invalidDetails = {
total: {
label: "Invalid Currency",
amount: {
currency: invalidCurrency,
value: "1.00",
},
},
};
try {
const payRequest = new PaymentRequest(defaultMethods, invalidDetails);
ok(
false,
`Creating a Payment Request with invalid currency (${invalidCurrency}) must throw.`
);
} catch (e) {
is(
e.name,
"RangeError",
`Expected rejected with 'RangeError', but got '${e.name}'.`
);
}
}
}
async function testUpdateWithInvalidCurrency() {
const handler = SpecialPowers.getDOMWindowUtils(window).setHandlingUserInput(
true
);
gScript.sendAsyncMessage("set-update-with-invalid-details-ui-service");
const payRequest = new PaymentRequest(defaultMethods, defaultDetails);
payRequest.addEventListener("shippingaddresschange", event => {
event.updateWith(Promise.resolve(updatedInvalidCurrencyDetails));
});
payRequest.addEventListener("shippingoptionchange", event => {
event.updateWith(updatedInvalidCurrencyDetails);
});
try {
await payRequest.show();
ok(false, "Should have rejected with 'RangeError'");
} catch (err) {
is(
err.name,
"RangeError",
`Should be rejected with 'RangeError', but got '${err.name}'.`
);
}
handler.destruct();
}
async function testUpdateWithInvalidAmount() {
const handler = SpecialPowers.getDOMWindowUtils(window).setHandlingUserInput(
true
);
gScript.sendAsyncMessage("set-update-with-invalid-details-ui-service");
const payRequest = new PaymentRequest(defaultMethods, defaultDetails);
payRequest.addEventListener("shippingaddresschange", event => {
event.updateWith(updateWithInvalidAmount());
});
payRequest.addEventListener("shippingoptionchange", event => {
event.updateWith(updateWithInvalidAmount());
});
try {
await payRequest.show();
ok(false, "Should be rejected with 'TypeError'");
} catch (err) {
is(
err.name,
"TypeError",
`Should be rejected with 'TypeError', but got ${err.name}.`
);
}
handler.destruct();
}
function testSpecialAmount() {
try {
new PaymentRequest(defaultMethods, specialAmountDetails);
ok(false, "Should throw '42', but got resolved.");
} catch (e) {
is(e, "42", "Expected throw '42'. but got " + e);
}
}
function testInvalidTotalAmounts() {
for (const invalidAmount of invalidTotalAmounts) {
try {
const invalidDetails = {
total: {
label: "",
amount: {
currency: "USD",
value: invalidAmount,
},
},
};
new PaymentRequest(defaultMethods, invalidDetails);
ok(false, "Should throw 'TypeError', but got resolved.");
} catch (err) {
is(err.name, "TypeError", `Expected 'TypeError', but got '${err.name}'`);
}
}
}
function testInvalidAmounts() {
for (const invalidAmount of invalidAmounts) {
try {
new PaymentRequest(defaultMethods, {
total: {
label: "",
amount: {
currency: "USD",
value: "1.00",
},
},
displayItems: [
{
label: "",
amount: {
currency: "USD",
value: invalidAmount,
},
},
],
});
ok(false, "Should throw 'TypeError', but got resolved.");
} catch (err) {
is(err.name, "TypeError", `Expected 'TypeError', but got '${err.name}'.`);
}
}
}
function teardown() {
return new Promise(resolve => {
gScript.addMessageListener(
"teardown-complete",
function teardownCompleteHandler() {
gScript.removeMessageListener(
"teardown-complete",
teardownCompleteHandler
);
gScript.removeMessageListener("test-fail", testFailHandler);
gScript.destroy();
SimpleTest.finish();
resolve();
}
);
gScript.sendAsyncMessage("teardown");
});
}
async function runTests() {
try {
testInvalidTotalAmounts();
testSpecialAmount();
testInvalidAmounts();
testWithWellFormedCurrencyCodes();
testWithInvalidCurrencyCodes();
await testUpdateWithInvalidAmount();
await testUpdateWithInvalidCurrency();
await testWithLowerCaseCurrency();
await teardown();
} catch (e) {
console.error(e);
ok(false, "Unexpected error: " + e.name);
SimpleTest.finish();
}
}
window.addEventListener("load", () => {
SpecialPowers.pushPrefEnv(
{
set: [["dom.payments.request.enabled", true]],
},
runTests
);
});
</script>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1367669">Mozilla Bug 1367669</a>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1388661">Mozilla Bug 1388661</a>
</body>
</html>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1388661">Mozilla Bug 1388661</a>