<!DOCTYPE html>
<!--  Copyright © 2017 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang).  -->
<!--  Copyright (C) 2017 Apple Inc. All rights reserved.  -->
<!-- FIXME: Upstream this test to web-platform-tests/payment-request/. -->
<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="/js-test-resources/ui-helper.js"></script>
<script src="/resources/payment-request.js"></script>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const applePay = Object.freeze({
    supportedMethods: "https://apple.com/apple-pay",
    data: {
        version: 2,
        merchantIdentifier: "",
        merchantCapabilities: ["supports3DS"],
        supportedNetworks: ["visa", "masterCard"],
        countryCode: "US",
    }
});
const invalidApplePay = Object.freeze({
    supportedMethods: "https://apple.com/apple-pay",
    data: {
    }
});
const defaultMethods = Object.freeze([applePay]);
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.`);

user_activation_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.`);

user_activation_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."
    );
  }
}, `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 request = new PaymentRequest([invalidApplePay], defaultDetails);
  assert_false(await request.canMakePayment(), "Apple Pay with invalid data should not be supported");
}, `If a payment method identifier is supported but its serialized parts are not, resolve promise with false.`);

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_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_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.`);
</script>
