<!DOCTYPE html>
<!-- Copyright © 2017 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
<meta charset="utf-8">
<title>Tests for PaymentRequest.canMakePayment() method</title>
<link rel="help" href="https://w3c.github.io/browser-payment-api/#show-method">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const basicCard = Object.freeze({ supportedMethods: ["basic-card"] });
const defaultMethods = Object.freeze([basicCard]);
const defaultDetails = Object.freeze({
  total: {
    label: "Total",
    amount: {
      currency: "USD",
      value: "1.00",
    },
  },
});

promise_test(async t => {
  const request = new PaymentRequest(defaultMethods, defaultDetails);
  try {
    assert_true(
      await request.canMakePayment(),
      `canMakePaymentPromise should be true`
    );
    assert_true(
      await request.canMakePayment(),
      `canMakePaymentPromise should be true`
    );
  } catch (err) {
    assert_equal(
      err.name,
      "NotAllowedError",
      "if it throws, then it must be a NotAllowedError."
    );
  }
}, `If request.[[state]] is "created", then return a promise that resolves to true for known method.`);

promise_test(async t => {
  const request = new PaymentRequest(defaultMethods, defaultDetails);
  const acceptPromise = request.show(); // Sets state to "interactive"
  const canMakePaymentPromise = request.canMakePayment();
  try {
    const result = await canMakePaymentPromise;
    assert_true(
      false,
      `canMakePaymentPromise should have thrown InvalidStateError`
    );
  } catch (err) {
    await promise_rejects(t, "InvalidStateError", canMakePaymentPromise);
  } finally {
    await request.abort();
    await promise_rejects(t, "AbortError", acceptPromise);
  }
  // The state should be "closed"
  await promise_rejects(t, "InvalidStateError", request.canMakePayment());
}, `If request.[[state]] is "interactive", then return a promise rejected with an "InvalidStateError" DOMException.`);

promise_test(async t => {
  const request = new PaymentRequest(defaultMethods, defaultDetails);
  const acceptPromise = request.show(); // The state is now "interactive"
  acceptPromise.catch(() => {}); // no-op, just to silence unhandled rejection in devtools.
  await request.abort(); // The state is now "closed"
  await promise_rejects(t, "InvalidStateError", request.canMakePayment());
  try {
    const result = await request.canMakePayment();
    assert_true(
      false,
      `should have thrown InvalidStateError, but instead returned "${result}"`
    );
  } catch (err) {
    assert_equal(
      err.name,
      "InvalidStateError",
      "must be an InvalidStateError."
    );
  }
}, `If request.[[state]] is "closed", then return a promise rejected with an "InvalidStateError" DOMException.`);

promise_test(async t => {
  const request = new PaymentRequest(defaultMethods, defaultDetails);
  assert_true(await request.canMakePayment(), "basic-card should be supported");
}, `If payment method identifier and serialized parts are supported, resolve promise with true.`);

promise_test(async t => {
  const unsupportedMethods = [
    "this-is-not-supported",
    "https://not.supported",
    "basic-card?not-really",
    "basic-card://not-ok",
    "basic card",
    "/basic card/",
    "BaSicCarD",
    "BASIC-CARD",
    " basic-card ",
    "this is not supported",
    " ",
  ];
  for (const method of unsupportedMethods) {
    try {
      const request = new PaymentRequest(
        [{ supportedMethods: [method] }],
        defaultDetails
      );
      assert_false(
        await request.canMakePayment(),
        `method "${method}" must not be supported`
      );
    } catch (err) {
      assert_true(
        false,
        `Unexpected exception testing method ${method}, expected false. See error console.`
      );
    }
  }
}, `If payment method identifier is unknown, resolve promise with false.`);

promise_test(async t => {
  // This test might never actually hit its assertion, but that's allowed.
  const request = new PaymentRequest(defaultMethods, defaultDetails);
  for (let i = 0; i < 1000; i++) {
    try {
      await request.canMakePayment();
    } catch (err) {
      assert_equal(
        err.name,
        "NotAllowedError",
        "if it throws, then it must be a NotAllowedError."
      );
      break;
    }
  }
  for (let i = 0; i < 1000; i++) {
    try {
      await new PaymentRequest(defaultMethods, defaultDetails).canMakePayment();
    } catch (err) {
      assert_equal(
        err.name,
        "NotAllowedError",
        "if it throws, then it must be a NotAllowedError."
      );
      break;
    }
  }
}, `Optionally, at the user agent's discretion, return a promise rejected with a "NotAllowedError" DOMException.`);
</script>
