| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <title>Test currency code usage in PaymentRequest Constructor</title> | |
| <link rel="help" href="https://w3c.github.io/browser-payment-api/#constructor"> | |
| <script src="/resources/testharness.js"></script> | |
| <script src="/resources/testharnessreport.js"></script> | |
| <script> | |
| const defaultMethods = [ | |
| Object.freeze({ | |
| supportedMethods: "https://{{domains[nonexistent]}}", | |
| }), | |
| ]; | |
| const defaultAmount = Object.freeze({ | |
| currency: "USD", | |
| value: "1.00", | |
| }); | |
| const defaultTotal = Object.freeze({ | |
| label: "Total", | |
| amount: defaultAmount, | |
| }); | |
| const defaultDetails = Object.freeze({ | |
| total: Object.freeze({ | |
| label: "", | |
| amount: defaultAmount, | |
| }), | |
| }); | |
| // The following are the same set of valid/invalid codes that are used in | |
| // the ECMAScript Internationalization API Specification (ECMA-402) test suite. | |
| const wellFormedCurrencyCodes = [ | |
| "BOB", | |
| "EUR", | |
| "usd", // currency codes are case-insensitive | |
| "XdR", | |
| "xTs", | |
| ]; | |
| const invalidCurrencyCodes = [ | |
| "", | |
| "€", | |
| "$", | |
| "SFr.", | |
| "DM", | |
| "KR₩", | |
| "702", | |
| "ßP", | |
| "ınr", | |
| ]; | |
| const RANGE_ERROR = RangeError; | |
| const invalidAmount = Object.freeze({ | |
| currency: "¡INVALID!", | |
| value: "1.00", | |
| }); | |
| const invalidTotal = { | |
| total: { | |
| label: "Invalid total", | |
| amount: invalidAmount, | |
| }, | |
| }; | |
| // Ensure we don't get false positives | |
| function smokeTest() { | |
| new PaymentRequest(defaultMethods, invalidTotal); | |
| } | |
| // Process the total: | |
| test(() => { | |
| assert_throws_js(RANGE_ERROR, smokeTest, "Expected smoke test to throw."); | |
| for (const validCurrency of wellFormedCurrencyCodes) { | |
| const amount = { | |
| currency: validCurrency, | |
| value: "1.00", | |
| }; | |
| const total = { | |
| label: "Total", | |
| amount, | |
| }; | |
| const details = { | |
| total, | |
| }; | |
| try { | |
| new PaymentRequest(defaultMethods, details); | |
| } catch (err) { | |
| assert_unreached( | |
| `Unexpected exception for details.total.amount "${validCurrency}": ${err.message}` | |
| ); | |
| } | |
| } | |
| }, "Check and canonicalize valid details.total.amount"); | |
| test(() => { | |
| assert_throws_js(RANGE_ERROR, smokeTest, "Expected smoke test to throw."); | |
| for (const invalidCurrency of invalidCurrencyCodes) { | |
| const amount = { | |
| currency: invalidCurrency, | |
| value: "1.00", | |
| }; | |
| const total = { | |
| label: "Total", | |
| amount, | |
| }; | |
| const details = { | |
| total, | |
| }; | |
| assert_throws_js( | |
| RANGE_ERROR, | |
| () => { | |
| new PaymentRequest(defaultMethods, details); | |
| }, | |
| `Expected RangeError for details.total.amount given ("${invalidCurrency}").` | |
| ); | |
| } | |
| }, "Check and canonicalize invalid details.total.amount and rethrow any exceptions."); | |
| // If the displayItems member of details is present, then for each item in details.displayItems: | |
| test(() => { | |
| assert_throws_js(RANGE_ERROR, smokeTest, "Expected smoke test to throw."); | |
| const displayItems = []; | |
| for (const validCurrency of wellFormedCurrencyCodes) { | |
| const amount = { | |
| currency: validCurrency, | |
| value: "123", | |
| }; | |
| const displayItem = { | |
| amount, | |
| label: "valid currency", | |
| }; | |
| const details = { | |
| total: defaultTotal, | |
| displayItems: [displayItem], | |
| }; | |
| try { | |
| new PaymentRequest(defaultMethods, details); | |
| } catch (err) { | |
| assert_unreached( | |
| `Unexpected error with displayItem that had a valid currency "${validCurrency}": ${err.message}` | |
| ); | |
| } | |
| displayItems.push(displayItem); | |
| } | |
| // Let's make sure it doesn't throw given a list of valid displayItems | |
| try { | |
| const details = Object.assign({}, defaultDetails, { displayItems }); | |
| new PaymentRequest(defaultMethods, details); | |
| } catch (err) { | |
| assert_unreached( | |
| `Unexpected error with multiple valid displayItems: ${err.message}` | |
| ); | |
| } | |
| }, "Check and canonicalize valid details.displayItems amount"); | |
| test(() => { | |
| assert_throws_js(RANGE_ERROR, smokeTest, "Expected smoke test to throw."); | |
| for (const invalidCurrency of invalidCurrencyCodes) { | |
| const amount = { | |
| currency: invalidCurrency, | |
| value: "123", | |
| }; | |
| const displayItem = { | |
| amount, | |
| label: "invalid currency", | |
| }; | |
| const details = { | |
| total: defaultTotal, | |
| displayItems: [displayItem], | |
| }; | |
| assert_throws_js( | |
| RANGE_ERROR, | |
| () => { | |
| new PaymentRequest(defaultMethods, details); | |
| }, | |
| `Expected RangeError with invalid displayItem currency "${invalidCurrency}".` | |
| ); | |
| } | |
| }, "Check and canonicalize invalid details.displayItems amount and rethrow RangeError."); | |
| // Process payment details modifiers: | |
| test(() => { | |
| assert_throws_js(RANGE_ERROR, smokeTest, "Expected smoke test to throw."); | |
| for (const validCurrency of wellFormedCurrencyCodes) { | |
| const modifier = { | |
| supportedMethods: "https://{{domains[nonexistent]}}", | |
| total: { | |
| label: "Total due", | |
| amount: { currency: validCurrency, value: "68.00" }, | |
| }, | |
| }; | |
| const details = { | |
| total: defaultTotal, | |
| modifiers: [modifier], | |
| }; | |
| try { | |
| new PaymentRequest(defaultMethods, details); | |
| } catch (err) { | |
| assert_unreached( | |
| `Unexpected error with valid modifier currency code "${validCurrency}": ${err.message}` | |
| ); | |
| } | |
| } | |
| }, "Check and canonicalize valid modifiers[n].total amount."); | |
| test(() => { | |
| assert_throws_js(RANGE_ERROR, smokeTest, "Expected smoke test to throw."); | |
| for (const invalidCurrency of invalidCurrencyCodes) { | |
| const modifier = { | |
| supportedMethods: "https://{{domains[nonexistent]}}", | |
| total: { | |
| label: "Total due", | |
| amount: { currency: invalidCurrency, value: "68.00" }, | |
| }, | |
| }; | |
| const details = { | |
| total: defaultTotal, | |
| modifiers: [modifier], | |
| }; | |
| assert_throws_js( | |
| RANGE_ERROR, | |
| () => { | |
| new PaymentRequest(defaultMethods, details); | |
| }, | |
| `Expected RangeError with invalid modifier currency code "${invalidCurrency}".` | |
| ); | |
| } | |
| }, "Check and canonicalize invalid modifiers[n].total amount and rethrow RangeError."); | |
| // Process payment details modifiers: | |
| test(() => { | |
| assert_throws_js(RANGE_ERROR, smokeTest, "Expected smoke test to throw."); | |
| for (const validCurrency of wellFormedCurrencyCodes) { | |
| const additionalItem = { | |
| label: "additionalItem", | |
| amount: { currency: validCurrency, value: "3.00" }, | |
| }; | |
| const modifier = { | |
| supportedMethods: "https://{{domains[nonexistent]}}", | |
| total: defaultTotal, | |
| additionalDisplayItems: [additionalItem], | |
| }; | |
| const details = { | |
| total: defaultTotal, | |
| modifiers: [modifier], | |
| }; | |
| try { | |
| new PaymentRequest(defaultMethods, details); | |
| } catch (err) { | |
| assert_unreached( | |
| `Unexpected error with valid additionalDisplayItems[n] currency code "${validCurrency}": ${err.message}` | |
| ); | |
| } | |
| } | |
| }, "Check and canonicalize valid modifiers[n].additionaDisplayItem amount."); | |
| test(() => { | |
| assert_throws_js(RANGE_ERROR, smokeTest, "Expected smoke test to throw."); | |
| for (const invalidCurrency of invalidCurrencyCodes) { | |
| const additionalItem = { | |
| label: "additionalItem", | |
| amount: { currency: invalidCurrency, value: "3.00" }, | |
| }; | |
| const modifier = { | |
| supportedMethods: "https://{{domains[nonexistent]}}", | |
| total: defaultTotal, | |
| additionalDisplayItems: [additionalItem], | |
| }; | |
| const details = { | |
| total: defaultTotal, | |
| modifiers: [modifier], | |
| }; | |
| assert_throws_js( | |
| RANGE_ERROR, | |
| () => { | |
| new PaymentRequest(defaultMethods, details); | |
| }, | |
| `Expected RangeError with invalid additionalDisplayItems[n] currency code "${invalidCurrency}".` | |
| ); | |
| } | |
| }, "Check and canonicalize invalid modifiers[n].additionaDisplayItem amount and rethrow RangeError."); | |
| </script> |