<!DOCTYPE html>
<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>
setup({
  explicit_done: true,
  explicit_timeout: true,
});

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_equals(
      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);
  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",
    "e",
    "n6jzof05mk2g4lhxr-u-q-w1-c-i-pa-ty-bdvs9-ho-ae7-p-md8-s-wq3-h-qd-e-q-sa",
    "a-b-q-n-s-pw0",
    "m-u",
    "s-l5",
    "k9-f",
    "m-l",
    "u4-n-t",
    "i488jh6-g18-fck-yb-v7-i",
    "x-x-t-t-c34-o",
    "https://wpt",
    "https://wpt.fyi/",
    "https://wpt.fyi/payment",
    "https://wpt.fyi/payment-request",
    "https://wpt.fyi/payment-request?",
    "https://wpt.fyi/payment-request?this=is",
    "https://wpt.fyi/payment-request?this=is&totally",
    "https://wpt.fyi:443/payment-request?this=is&totally",
    "https://wpt.fyi:443/payment-request?this=is&totally#fine",
    "https://:@wpt.fyi:443/payment-request?this=is&totally#👍",
    " \thttps://wpt\n ",
    "https://xn--c1yn36f",
    "https://點看",
  ];
  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_equals(
        err.name,
        "NotAllowedError",
        "if it throws, then it must be a NotAllowedError."
      );
    }
  }
}, `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_equals(
        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_equals(
        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.`);

function manualTest1(elem){
  elem.disabled = true;
  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());
  }, elem.textContent.trim());
}

function manualTest2(elem){
 elem.disabled = true;
  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_equals(
        err.name,
        "InvalidStateError",
        "must be an InvalidStateError."
      );
    }
  }, elem.textContent.trim());
  done();
}
</script>

<h2>Tests for PaymentRequest.canMakePayment() method</h2>
<p>
  Click on each button in sequence from top to bottom without refreshing the page.
  No payment sheet will be shown, but the tests will run in the background.
</p>
<ol>
  <li>
    <button onclick="manualTest1(this)">
      If request.[[state]] is "interactive", then return a promise rejected with an "InvalidStateError" DOMException.
    </button>
  </li>
  <li>
    <button onclick="manualTest2(this)">
      If request.[[state]] is "closed", then return a promise rejected with an "InvalidStateError" DOMException.
    </button>
  </li>
</ol>
<small>
  If you find a buggy test, please <a href="https://github.com/w3c/web-platform-tests/issues">file a bug</a>
  and tag one of the <a href="https://github.com/w3c/web-platform-tests/blob/master/payment-request/OWNERS">owners</a>.
</small>
