<!doctype html>
<meta charset="utf8">
<link rel="help" href="https://w3c.github.io/payment-request/#dom-paymentresponse-complete()">
<title>
  PaymentResponse.prototype.complete() method
</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="helpers.js"></script>
<script>
async function runManualTest({ completeWith: result }, button) {
  button.disabled = true;
  const { response, request } = await getPaymentRequestResponse();
  promise_test(async t => {
    try {
      // We .complete() as normal, using the passed test value
      const completePromise = response.complete(result);
      assert_true(completePromise instanceof Promise, "returns a promise");
      // Immediately calling complete() again yields a rejected promise.
      const invalidComplete = response.complete(result);
      await promise_rejects(t, "InvalidStateError", invalidComplete);
      // but the original promise is unaffected
      const returnedValue = await completePromise;
      assert_equals(
        returnedValue,
        undefined,
        "Returned value must always be undefined"
      );
      // We now call .complete() again, to force an exception
      // because [[complete]] is true.
      const afterComplete = response.complete(result);
      await promise_rejects(t, "InvalidStateError", afterComplete);
      button.innerHTML = `✅  ${button.textContent}`;
    } catch (err) {
      button.innerHTML = `❌  ${button.textContent}`;
      assert_unreached("Unexpected exception: " + err.message);
    }
    const allPromises = new Set([
      completePromise,
      invalidComplete,
      afterComplete,
    ]);
    assert_equals(
      allPromises.length,
      3,
      "Calling complete() multiple times is always a new object."
    );
  }, button.textContent.trim());
}
</script>

<h2>
    Manual Tests for PaymentResponse.complete() - Please run in order!
</h2>
<p>
  Click on each button in sequence from top to bottom without refreshing the page.
  Each button will bring up the Payment Request UI window.
</p>
<p>
  When presented with the payment sheet, use any credit card select to "Pay".
  Also confirm any prompts that come up.
</p>
<ol>
  <li>
    <button onclick="runManualTest({completeWith: 'success'}, this)">
      If the value of the internal slot [[completeCalled]] is true,
      reject promise with an "InvalidStateError" DOMException.
    </button>
  </li>
  <li>
    <button onclick="runManualTest({completeWith: 'unknown'}, this)">
      Passing no argument defaults to "unknown",
      eventually closing the sheet and doesn't throw.
    </button>
  </li>
  <li>
    <button onclick="runManualTest({completeWith: 'success'}, this)">
      Passing "success" eventually closes the sheet and doesn't throw.
    </button>
  </li>
  <li>
    <button onclick="runManualTest({completeWith: 'fail'}, this).then(done)">
      Passing "fail" eventually closes the sheet and doesn't throw.
    </button>
  </li>
</ol>
<small>
  If you find a buggy test, please <a href="https://github.com/web-platform-tests/wpt/issues">file a bug</a>
  and tag one of the <a href="https://github.com/web-platform-tests/wpt/blob/master/payment-request/META.yml">suggested reviewers</a>.
</small>
