tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

payment-request-ctor-currency-code-checks.https.sub.html (9707B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8">
      3 <title>Test currency code usage in PaymentRequest Constructor</title>
      4 <link rel="help" href="https://w3c.github.io/browser-payment-api/#constructor">
      5 <script src="/resources/testharness.js"></script>
      6 <script src="/resources/testharnessreport.js"></script>
      7 <script>
      8 const defaultMethods = [
      9  Object.freeze({
     10    supportedMethods: "https://{{domains[nonexistent]}}",
     11  }),
     12 ];
     13 const defaultAmount = Object.freeze({
     14  currency: "USD",
     15  value: "1.00",
     16 });
     17 const defaultTotal = Object.freeze({
     18  label: "Total",
     19  amount: defaultAmount,
     20 });
     21 
     22 const defaultDetails = Object.freeze({
     23  total: Object.freeze({
     24    label: "",
     25    amount: defaultAmount,
     26  }),
     27 });
     28 
     29 // The following are the same set of valid/invalid codes that are used in
     30 // the ECMAScript Internationalization API Specification (ECMA-402) test suite.
     31 const wellFormedCurrencyCodes = [
     32  "BOB",
     33  "EUR",
     34  "usd", // currency codes are case-insensitive
     35  "XdR",
     36  "xTs",
     37 ];
     38 
     39 const invalidCurrencyCodes = [
     40  "",
     41  "€",
     42  "$",
     43  "SFr.",
     44  "DM",
     45  "KR₩",
     46  "702",
     47  "ßP",
     48  "ınr",
     49 ];
     50 
     51 const RANGE_ERROR = RangeError;
     52 
     53 const invalidAmount = Object.freeze({
     54  currency: "¡INVALID!",
     55  value: "1.00",
     56 });
     57 
     58 const invalidTotal = {
     59  total: {
     60    label: "Invalid total",
     61    amount: invalidAmount,
     62  },
     63 };
     64 
     65 // Ensure we don't get false positives
     66 function smokeTest() {
     67  new PaymentRequest(defaultMethods, invalidTotal);
     68 }
     69 
     70 // Process the total:
     71 test(() => {
     72  assert_throws_js(RANGE_ERROR, smokeTest, "Expected smoke test to throw.");
     73  for (const validCurrency of wellFormedCurrencyCodes) {
     74    const amount = {
     75      currency: validCurrency,
     76      value: "1.00",
     77    };
     78    const total = {
     79      label: "Total",
     80      amount,
     81    };
     82    const details = {
     83      total,
     84    };
     85    try {
     86      new PaymentRequest(defaultMethods, details);
     87    } catch (err) {
     88      assert_unreached(
     89        `Unexpected exception for details.total.amount "${validCurrency}": ${err.message}`
     90      );
     91    }
     92  }
     93 }, "Check and canonicalize valid details.total.amount");
     94 
     95 test(() => {
     96  assert_throws_js(RANGE_ERROR, smokeTest, "Expected smoke test to throw.");
     97  for (const invalidCurrency of invalidCurrencyCodes) {
     98    const amount = {
     99      currency: invalidCurrency,
    100      value: "1.00",
    101    };
    102    const total = {
    103      label: "Total",
    104      amount,
    105    };
    106    const details = {
    107      total,
    108    };
    109    assert_throws_js(
    110      RANGE_ERROR,
    111      () => {
    112        new PaymentRequest(defaultMethods, details);
    113      },
    114      `Expected RangeError for details.total.amount given ("${invalidCurrency}").`
    115    );
    116  }
    117 }, "Check and canonicalize invalid details.total.amount and rethrow any exceptions.");
    118 
    119 // If the displayItems member of details is present, then for each item in details.displayItems:
    120 test(() => {
    121  assert_throws_js(RANGE_ERROR, smokeTest, "Expected smoke test to throw.");
    122  const displayItems = [];
    123  for (const validCurrency of wellFormedCurrencyCodes) {
    124    const amount = {
    125      currency: validCurrency,
    126      value: "123",
    127    };
    128    const displayItem = {
    129      amount,
    130      label: "valid currency",
    131    };
    132    const details = {
    133      total: defaultTotal,
    134      displayItems: [displayItem],
    135    };
    136    try {
    137      new PaymentRequest(defaultMethods, details);
    138    } catch (err) {
    139      assert_unreached(
    140        `Unexpected error with displayItem that had a valid currency "${validCurrency}": ${err.message}`
    141      );
    142    }
    143    displayItems.push(displayItem);
    144  }
    145  // Let's make sure it doesn't throw given a list of valid displayItems
    146  try {
    147    const details = Object.assign({}, defaultDetails, { displayItems });
    148    new PaymentRequest(defaultMethods, details);
    149  } catch (err) {
    150    assert_unreached(
    151      `Unexpected error with multiple valid displayItems: ${err.message}`
    152    );
    153  }
    154 }, "Check and canonicalize valid details.displayItems amount");
    155 
    156 test(() => {
    157  assert_throws_js(RANGE_ERROR, smokeTest, "Expected smoke test to throw.");
    158  for (const invalidCurrency of invalidCurrencyCodes) {
    159    const amount = {
    160      currency: invalidCurrency,
    161      value: "123",
    162    };
    163    const displayItem = {
    164      amount,
    165      label: "invalid currency",
    166    };
    167    const details = {
    168      total: defaultTotal,
    169      displayItems: [displayItem],
    170    };
    171    assert_throws_js(
    172      RANGE_ERROR,
    173      () => {
    174        new PaymentRequest(defaultMethods, details);
    175      },
    176      `Expected RangeError with invalid displayItem currency "${invalidCurrency}".`
    177    );
    178  }
    179 }, "Check and canonicalize invalid details.displayItems amount and rethrow RangeError.");
    180 
    181 // Process shipping options:
    182 test(() => {
    183  assert_throws_js(RANGE_ERROR, smokeTest, "Expected smoke test to throw.");
    184  const shippingOptions = [];
    185  for (const validCurrency of wellFormedCurrencyCodes) {
    186    const shippingOption = {
    187      id: `test` + Math.random(),
    188      label: "shipping option",
    189      amount: { currency: validCurrency, value: "5.00" },
    190      selected: !shippingOptions.length,
    191    };
    192    const details = {
    193      total: defaultTotal,
    194      shippingOptions: [shippingOption],
    195    };
    196    try {
    197      new PaymentRequest(defaultMethods, details, { requestShipping: true });
    198    } catch (err) {
    199      assert_unreached(
    200        `Unexpected exception with valid shippingOption currency code "${validCurrency}": ${err.message}.`
    201      );
    202    }
    203    shippingOptions.push(shippingOption);
    204  }
    205  try {
    206    const details = Object.assign({}, defaultDetails, { shippingOptions });
    207    new PaymentRequest(defaultMethods, details, { requestShipping: true });
    208  } catch (err) {
    209    assert_unreached(
    210      `Unexpected error with multiple valid shppingOptions: ${err.message}.`
    211    );
    212  }
    213 }, "Check and canonicalize valid details.shippingOptions amount.");
    214 
    215 test(() => {
    216  assert_throws_js(RANGE_ERROR, smokeTest, "Expected smoke test to throw.");
    217  for (const invalidCurrency of invalidCurrencyCodes) {
    218    const shippingOption = {
    219      id: "test",
    220      label: "shipping option",
    221      amount: { currency: invalidCurrency, value: "5.00" },
    222      selected: true,
    223    };
    224    const details = {
    225      total: defaultTotal,
    226      shippingOptions: [shippingOption],
    227    };
    228    assert_throws_js(
    229      RANGE_ERROR,
    230      () => {
    231        new PaymentRequest(defaultMethods, details, { requestShipping: true });
    232      },
    233      `Expected RangeError with invalid shippingOption currency code "${invalidCurrency}".`
    234    );
    235  }
    236 }, "Check and canonicalize invalid details.shippingOptions amount and rethrow RangeError.");
    237 
    238 // Process payment details modifiers:
    239 test(() => {
    240  assert_throws_js(RANGE_ERROR, smokeTest, "Expected smoke test to throw.");
    241  for (const validCurrency of wellFormedCurrencyCodes) {
    242    const modifier = {
    243      supportedMethods: "https://{{domains[nonexistent]}}",
    244      total: {
    245        label: "Total due",
    246        amount: { currency: validCurrency, value: "68.00" },
    247      },
    248    };
    249    const details = {
    250      total: defaultTotal,
    251      modifiers: [modifier],
    252    };
    253    try {
    254      new PaymentRequest(defaultMethods, details);
    255    } catch (err) {
    256      assert_unreached(
    257        `Unexpected error with valid modifier currency code "${validCurrency}": ${err.message}`
    258      );
    259    }
    260  }
    261 }, "Check and canonicalize valid modifiers[n].total amount.");
    262 
    263 test(() => {
    264  assert_throws_js(RANGE_ERROR, smokeTest, "Expected smoke test to throw.");
    265  for (const invalidCurrency of invalidCurrencyCodes) {
    266    const modifier = {
    267      supportedMethods: "https://{{domains[nonexistent]}}",
    268      total: {
    269        label: "Total due",
    270        amount: { currency: invalidCurrency, value: "68.00" },
    271      },
    272    };
    273    const details = {
    274      total: defaultTotal,
    275      modifiers: [modifier],
    276    };
    277    assert_throws_js(
    278      RANGE_ERROR,
    279      () => {
    280        new PaymentRequest(defaultMethods, details);
    281      },
    282      `Expected RangeError with invalid modifier currency code "${invalidCurrency}".`
    283    );
    284  }
    285 }, "Check and canonicalize invalid modifiers[n].total amount and rethrow RangeError.");
    286 
    287 // Process payment details modifiers:
    288 test(() => {
    289  assert_throws_js(RANGE_ERROR, smokeTest, "Expected smoke test to throw.");
    290  for (const validCurrency of wellFormedCurrencyCodes) {
    291    const additionalItem = {
    292      label: "additionalItem",
    293      amount: { currency: validCurrency, value: "3.00" },
    294    };
    295    const modifier = {
    296      supportedMethods: "https://{{domains[nonexistent]}}",
    297      total: defaultTotal,
    298      additionalDisplayItems: [additionalItem],
    299    };
    300    const details = {
    301      total: defaultTotal,
    302      modifiers: [modifier],
    303    };
    304    try {
    305      new PaymentRequest(defaultMethods, details);
    306    } catch (err) {
    307      assert_unreached(
    308        `Unexpected error with valid additionalDisplayItems[n] currency code "${validCurrency}": ${err.message}`
    309      );
    310    }
    311  }
    312 }, "Check and canonicalize valid modifiers[n].additionaDisplayItem amount.");
    313 
    314 test(() => {
    315  assert_throws_js(RANGE_ERROR, smokeTest, "Expected smoke test to throw.");
    316  for (const invalidCurrency of invalidCurrencyCodes) {
    317    const additionalItem = {
    318      label: "additionalItem",
    319      amount: { currency: invalidCurrency, value: "3.00" },
    320    };
    321    const modifier = {
    322      supportedMethods: "https://{{domains[nonexistent]}}",
    323      total: defaultTotal,
    324      additionalDisplayItems: [additionalItem],
    325    };
    326    const details = {
    327      total: defaultTotal,
    328      modifiers: [modifier],
    329    };
    330    assert_throws_js(
    331      RANGE_ERROR,
    332      () => {
    333        new PaymentRequest(defaultMethods, details);
    334      },
    335      `Expected RangeError with invalid additionalDisplayItems[n] currency code "${invalidCurrency}".`
    336    );
    337  }
    338 }, "Check and canonicalize invalid modifiers[n].additionaDisplayItem amount and rethrow RangeError.");
    339 </script>