summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/payment-method-basic-card
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /testing/web-platform/tests/payment-method-basic-card
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/payment-method-basic-card')
-rw-r--r--testing/web-platform/tests/payment-method-basic-card/META.yml4
-rw-r--r--testing/web-platform/tests/payment-method-basic-card/apply_the_modifiers.html152
-rw-r--r--testing/web-platform/tests/payment-method-basic-card/billing-address-is-null-manual.https.html150
-rw-r--r--testing/web-platform/tests/payment-method-basic-card/empty-data-manual.https.html133
-rw-r--r--testing/web-platform/tests/payment-method-basic-card/historical.https.html25
-rw-r--r--testing/web-platform/tests/payment-method-basic-card/payment-request-canmakepayment-method.https.html89
-rw-r--r--testing/web-platform/tests/payment-method-basic-card/steps_for_selecting_the_payment_handler.html110
7 files changed, 663 insertions, 0 deletions
diff --git a/testing/web-platform/tests/payment-method-basic-card/META.yml b/testing/web-platform/tests/payment-method-basic-card/META.yml
new file mode 100644
index 0000000000..ca2a57e752
--- /dev/null
+++ b/testing/web-platform/tests/payment-method-basic-card/META.yml
@@ -0,0 +1,4 @@
+spec: https://w3c.github.io/payment-method-basic-card/
+suggested_reviewers:
+ - marcoscaceres
+ - rsolomakhin
diff --git a/testing/web-platform/tests/payment-method-basic-card/apply_the_modifiers.html b/testing/web-platform/tests/payment-method-basic-card/apply_the_modifiers.html
new file mode 100644
index 0000000000..f1b59dda4a
--- /dev/null
+++ b/testing/web-platform/tests/payment-method-basic-card/apply_the_modifiers.html
@@ -0,0 +1,152 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>
+ Payment Method Basic Card: apply the modifiers
+</title>
+<link
+ rel="help"
+ href="https://w3c.github.io/payment-method-basic-card/#applying-the-modifiers"
+/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ setup({ explicit_done: true, explicit_timeout: true });
+ const basicCard = [{ supportedMethods: "basic-card" }];
+ const defaultDetails = {
+ total: {
+ label: "FAIL - SHOWING DEFAULT!",
+ amount: {
+ currency: "USD",
+ value: "0.0",
+ },
+ },
+ };
+
+ const failModifier = {
+ supportedMethods: "basic-card",
+ total: {
+ label: "FAIL",
+ amount: { currency: "USD", value: "test" },
+ },
+ additionalDisplayItems: [
+ {
+ label: "FAIL - ADDITIONAL DISPLAY ITEM",
+ amount: { currency: "USD", value: "54321" },
+ },
+ ],
+ };
+
+ const notBasicCardModifier = {
+ supportedMethods: "this-doesnt-apply",
+ total: {
+ label: "FAIL - this-doesnt-apply",
+ amount: { currency: "USD", value: "54321" },
+ },
+ };
+
+ const modifier = {
+ supportedMethods: "basic-card",
+ total: {
+ label: "PASS",
+ amount: { currency: "USD", value: "12345" },
+ },
+ additionalDisplayItems: [
+ {
+ label: "PASS - ADDITIONAL DISPLAY ITEM",
+ amount: { currency: "USD", value: "12345" },
+ },
+ ],
+ };
+
+ function defaultModifierApplies(testableAssertion) {
+ promise_test(async t => {
+ const visaModifier = Object.assign({}, modifier, {
+ data: { supportedNetworks: ["visa"] },
+ });
+ visaModifier.total.label = "PASS - VISA MODIFIED";
+ const details = Object.assign({}, defaultDetails, {
+ modifiers: [visaModifier],
+ });
+ const showPromise = new PaymentRequest(basicCard, defaultDetails).show();
+ await promise_rejects_dom(t, "AbortError", showPromise);
+ }, testableAssertion.trim());
+ }
+
+ function modifierWithNoDataAppliesToAll(testableAssertion) {
+ promise_test(async t => {
+ const details = Object.assign({}, defaultDetails, {
+ modifiers: [modifier],
+ });
+ const showPromise = new PaymentRequest(basicCard, defaultDetails).show();
+ await promise_rejects_dom(t, "AbortError", showPromise);
+ }, testableAssertion.trim());
+ }
+
+ function modifierWithObjectAppliesToAll(testableAssertion) {
+ promise_test(async t => {
+ const modifiers = [Object.assign({}, modifier, { data: {} })];
+ const details = Object.assign({}, defaultDetails, { modifiers });
+ const showPromise = new PaymentRequest(basicCard, defaultDetails).show();
+ await promise_rejects_dom(t, "AbortError", showPromise);
+ }, testableAssertion.trim());
+ }
+
+ function modifierWithEmptySupportedNetworksAppliesToAll(testableAssertion) {
+ promise_test(async t => {
+ const modifiers = [
+ Object.assign({}, modifier, { data: { supportedNetworks: [] } }),
+ ];
+ const details = Object.assign({}, defaultDetails, { modifiers });
+ const showPromise = new PaymentRequest(basicCard, defaultDetails).show();
+ await promise_rejects_dom(t, "AbortError", showPromise);
+ }, testableAssertion.trim());
+ }
+
+ function modifierLastOneWins(testableAssertion) {
+ promise_test(async t => {
+ const modifiers = [failModifier, modifier, notBasicCardModifier];
+ const details = Object.assign({}, defaultDetails, { modifiers });
+ const showPromise = new PaymentRequest(basicCard, defaultDetails).show();
+ await promise_rejects_dom(t, "AbortError", showPromise);
+ }, testableAssertion.trim());
+ }
+</script>
+<h1>Manual tests</h1>
+<p>
+ <strong>Note:</strong> this test requires that there is at at least one
+ registered "visa" card. If the payment-sheet total's
+ label displays "PASS", and the value US$12345, then a test has passed.
+</p>
+<ol>
+ <li>
+ <button onclick="defaultModifierApplies(this.textContent.trim())">
+ A modifier is applied by default to a card.
+ </button>
+ </li>
+ <li>
+ <button onclick="modifierWithNoDataAppliesToAll(this.textContent.trim())">
+ Missing PaymentDetailsModifier.data is same as passing default
+ BasicCardRequest.
+ </button>
+ </li>
+ <li>
+ <button onclick="modifierWithNoDataAppliesToAll(this.textContent.trim())">
+ PaymentDetailsModifier.data with empty object is same as passing default
+ BasicCardRequest.
+ </button>
+ </li>
+ <li>
+ <button
+ onclick="modifierWithEmptySupportedNetworksAppliesToAll(this.textContent.trim())"
+ >
+ A modified with a BasicCardRequest whose supportedNetworks is an empty
+ array applies to all.
+ </button>
+ </li>
+ <li>
+ <button onclick="modifierLastOneWins(this.textContent.trim())">
+ Given a set of modifiers, the last applicable "basic-card" wins.
+ </button>
+ </li>
+ <li><button onclick="done()">Done!</button></li>
+</ol>
diff --git a/testing/web-platform/tests/payment-method-basic-card/billing-address-is-null-manual.https.html b/testing/web-platform/tests/payment-method-basic-card/billing-address-is-null-manual.https.html
new file mode 100644
index 0000000000..3250e0a2c5
--- /dev/null
+++ b/testing/web-platform/tests/payment-method-basic-card/billing-address-is-null-manual.https.html
@@ -0,0 +1,150 @@
+<!DOCTYPE html> <meta charset="utf-8" />
+<title>Test for requesting billing address</title>
+<link
+ rel="help"
+ href="https://github.com/w3c/payment-method-basic-card/pull/65"
+/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ setup({
+ explicit_done: true,
+ explicit_timeout: true,
+ });
+ const basicCard = { supportedMethods: "basic-card" };
+ const details = {
+ total: {
+ label: "label",
+ amount: { currency: "USD", value: "5.00" },
+ },
+ };
+
+ // Smoke tests
+ test(() => {
+ assert_true(
+ "onpaymentmethodchange" in PaymentRequest.prototype,
+ "The paymentmethodchange event handler is not supported on PaymentRequest"
+ );
+ assert_true(
+ "PaymentMethodChangeEvent" in window,
+ "The PaymentMethodChangeEvent is not supported"
+ );
+ }, "PaymentMethodChangeEvent support");
+
+ function dontRequestBillingAddress(options) {
+ promise_test(async t => {
+ const request = new PaymentRequest([basicCard], details, {
+ requestBillingAddress: false,
+ });
+ const showPromise = request.show();
+
+ // Let's check the method data from PaymentMethodChangeEvent.
+ const event = await new Promise(resolve =>
+ request.addEventListener("paymentmethodchange", resolve)
+ );
+ assert_true(
+ event instanceof PaymentMethodChangeEvent,
+ "Expected instance of PaymentMethodChangeEvent"
+ );
+ assert_equals(
+ event.methodDetails.billingAddress,
+ null,
+ "Expected methodDetails.billingAddress to be null"
+ );
+
+ // Let's check the billingAddress in the response
+ const response = await showPromise;
+ const {
+ details: { billingAddress: responseBillingAddress },
+ } = response;
+
+ assert_equals(
+ responseBillingAddress,
+ null,
+ "Expected PaymentResponse.data.billingAddress to be null"
+ );
+
+ // And we are done
+ await response.complete("success");
+ });
+ }
+
+ function requestBillingAddress() {
+ promise_test(async t => {
+ const request = new PaymentRequest([basicCard], details, {
+ requestBillingAddress: true,
+ });
+ const showPromise = request.show();
+
+ // Let's check the methodDetails from event.
+ const event = await new Promise(resolve =>
+ request.addEventListener("paymentmethodchange", resolve)
+ );
+ assert_true(
+ event instanceof PaymentMethodChangeEvent,
+ "Expected instance of PaymentMethodChangeEvent"
+ );
+ const { billingAddress: eventBillingAddress } = event.methodDetails;
+ checkRedactList(eventBillingAddress);
+
+ // Let's check the billingAddress in the response.
+ const response = await showPromise;
+ const {
+ details: { billingAddress: responseBillingAddress },
+ } = await showPromise;
+ checkRedactList(responseBillingAddress);
+
+ // And we are done.
+ await response.complete("success");
+ });
+ }
+
+ function checkRedaction(billingAddress) {
+ assert_true(
+ billingAddress instanceof PaymentAddress,
+ "Expected instance of PaymentAddress"
+ );
+ for (const item of ["organization", "phone", "recipient"]) {
+ assert_equals(
+ billingAddress[item],
+ "",
+ `Expected billingAddress's "${item}" attribute to equal null (redacted).`
+ );
+ }
+ }
+</script>
+
+<h2>Request billing address</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 the payment sheet is presented, select a payment method (e.g., a credit
+ card), and press "Pay".
+</p>
+<ol>
+ <li>
+ <button onclick="dontRequestBillingAddress()">
+ When no billing address is requested,
+ `PaymentMethodChangeEvent.methodData.billingAddress` is null.
+ </button>
+ </li>
+ <li>
+ <button onclick="requestBillingAddress()">
+ When billing address is
+ requested,`PaymentMethodChangeEvent.methodData.billingAddress` is a
+ `PaymentAddress`.
+ </button>
+ </li>
+ <li><button onclick="done()">Done!</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>
diff --git a/testing/web-platform/tests/payment-method-basic-card/empty-data-manual.https.html b/testing/web-platform/tests/payment-method-basic-card/empty-data-manual.https.html
new file mode 100644
index 0000000000..ba881ee236
--- /dev/null
+++ b/testing/web-platform/tests/payment-method-basic-card/empty-data-manual.https.html
@@ -0,0 +1,133 @@
+<!doctype html>
+<meta charset="utf8">
+<title>Payment Method Basic Card - test passing empty BasicCardRequest members</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+setup({ explicit_done: true, explicit_timeout: true });
+
+const amount = { value: "1.0", currency: "USD" };
+const details = {
+ total: {
+ label: "Total",
+ amount,
+ },
+};
+const method = {
+ supportedMethods: "basic-card",
+};
+
+const defaultBillingAddress = {
+ country: 'AF',
+ addressLine: '1 wpt street',
+ region: '',
+ city: 'Kabul',
+ dependentLocality: '',
+ postalCode: '1001',
+ sortingCode: '',
+ organization: 'w3c',
+ recipient: 'web platform test',
+ phone: '+93555555555',
+};
+
+const visaCredit = {
+ cardNumber: "4111111111111111",
+ cardSecurityCode: "123",
+ cardholderName: "web platform test",
+ expiryMonth: "01",
+ expiryYear: "2026",
+};
+
+async function getCardResponse(data) {
+ const payMethod = Object.assign({ data }, method);
+ const response = await new PaymentRequest([payMethod], details).show();
+ await response.complete("success");
+ return response.details;
+}
+
+/**
+ * All tests expect the same return data, so we can just check the
+ * same result over and over again.
+ */
+function runPromiseTest(button, data, expectedCard = visaCredit, expectedAddress = defaultBillingAddress ) {
+ button.disabled = true;
+ promise_test(async () => {
+ const card = await getCardResponse(data);
+ for (const [member, expectedValue] of Object.entries(expectedCard)) {
+ const msg = `Expected "card.${member}" to equal "${expectedValue}".`;
+ assert_equals(card[member], expectedValue, msg);
+ }
+ const { billingAddress } = card;
+ for (const [member, expectedValue] of Object.entries(expectedAddress)) {
+ const msg = `billingAddress.${member} to equal ${expectedValue}.`;
+ assert_equals(billingAddress[member], expectedValue);
+ }
+ }, button.textContent.trim());
+}
+</script>
+<h2>
+ Payment Method Basic Card - test passing empty BasicCardRequest values
+</h2>
+<p>
+ This test checks that the Basic Card payment handler can accept any card.
+</p>
+<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.
+ The test expects the following credit card.
+</p>
+<ol>
+ <li>Add card:
+ <dl>
+ <dt>Cardholder name:</dt>
+ <dd>web platform test</dd>
+ <dt>Card number:</dt>
+ <dd>4111111111111111</dd>
+ <dt>Security code (CVV):</dt>
+ <dd>123</dd>
+ <dt>Expiry month:</dt>
+ <dd>01</dd>
+ <dt>Expiry year:</dt>
+ <dd>2026</dd>
+ </dl>
+ </li>
+ <li>Add billing address:
+ <dl>
+ <dt>Recipient:</dt>
+ <dd>web platform test</dd>
+ <dt>Address:</dt>
+ <dd>1 web st</dd>
+ <dt>Post code:</dt>
+ <dd>1234</dd>
+ <dt>Country:</dt>
+ <dd>Afghanistan</dd>
+ <dt>City:</dt>
+ <dd>w3c</dd>
+ <dt>Phone</dt>
+ <dd>+12345678910</dd>
+ </dl>
+ </li>
+</ol>
+<hr>
+<ol>
+ <li>
+ <button onclick="runPromiseTest(this, {});">
+ When passed BasicCardRequest without members, allow the user to input a card on any network.
+ </button>
+ </li>
+ <li>
+ <button onclick="runPromiseTest(this, { supportedNetworks: [] });">
+ Returns a card on any network, because zero length supportedNetworks.
+ </button>
+ </li>
+ <li>
+ <button onclick="done();">
+ Done!
+ </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>
diff --git a/testing/web-platform/tests/payment-method-basic-card/historical.https.html b/testing/web-platform/tests/payment-method-basic-card/historical.https.html
new file mode 100644
index 0000000000..e24def172a
--- /dev/null
+++ b/testing/web-platform/tests/payment-method-basic-card/historical.https.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Historical Basic Card Changes</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+// https://github.com/w3c/payment-method-basic-card/pull/62
+test(() => {
+ try {
+ new PaymentRequest(
+ [
+ {
+ supportedMethods: "basic-card",
+ supportedTypes: [
+ "this was an enum value once - so this would have thrown",
+ ],
+ },
+ ],
+ { total: { label: "bar", amount: { currency: "BAZ", value: "0" } } }
+ );
+ } catch (err) {
+ assert_unreached("Unexpected error");
+ }
+}, "supportedTypes and BasicCardType enum were removed from the spec");
+</script>
diff --git a/testing/web-platform/tests/payment-method-basic-card/payment-request-canmakepayment-method.https.html b/testing/web-platform/tests/payment-method-basic-card/payment-request-canmakepayment-method.https.html
new file mode 100644
index 0000000000..f1b0c28abb
--- /dev/null
+++ b/testing/web-platform/tests/payment-method-basic-card/payment-request-canmakepayment-method.https.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<!-- Copyright © 2017 World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
+<meta charset="utf-8">
+<title>Payment Method Basic Card: Tests that basic card is a supported 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", data: {} });
+const defaultMethods = Object.freeze([basicCard]);
+const defaultDetails = Object.freeze({
+ total: {
+ label: "Total",
+ amount: {
+ currency: "USD",
+ value: "1.00",
+ },
+ },
+});
+
+const notSupportedMethod = Object.freeze({
+ supportedMethods: "this-is-not-supported",
+});
+
+promise_test(async t => {
+ const request = new PaymentRequest([notSupportedMethod], defaultDetails);
+ assert_false(
+ await request.canMakePayment(),
+ `canMakePaymentPromise should be false`
+ );
+}, `Must return false when the PMI is not supported at by the user agent.`);
+
+function* pmiGenerator(howMany = 256) {
+ for (i = 0; i < howMany; i++) {
+ yield {
+ supportedMethods: `this-is-not-supported`,
+ data: { key: "value" },
+ };
+ }
+}
+
+promise_test(async t => {
+ //Smoke test
+ const canMakePaymentPromise = new PaymentRequest(
+ [notSupportedMethod],
+ defaultDetails
+ ).canMakePayment();
+ assert_false(
+ await canMakePaymentPromise,
+ "Expected canMakePaymentPromise smoke test to resolve with false"
+ );
+ // Actual test - Make a big array with random PMIs,
+ // put basic-card in the middle of it!
+ const pmis = []
+ .concat(Array.from(pmiGenerator(250)))
+ .concat(basicCard)
+ .concat(Array.from(pmiGenerator(250)));
+ const request = new PaymentRequest(pmis, defaultDetails);
+ assert_true(
+ await request.canMakePayment(),
+ `canMakePaymentPromise should be true, because basic-card is present`
+ );
+}, `Must return true when basic-card is amongst unsupported PMIs.`);
+
+promise_test(async t => {
+ const request = new PaymentRequest(defaultMethods, defaultDetails);
+ try {
+ assert_true(
+ await request.canMakePayment(),
+ `canMakePaymentPromise must resolve to true`
+ );
+ assert_true(
+ await request.canMakePayment(),
+ `canMakePaymentPromise must resolve to true`
+ );
+ // try to trigger optional behavior
+ for (let i = 0; i < 1024; i++) {
+ const temp = new PaymentRequest(defaultMethods, defaultDetails);
+ await Promise.all([temp.canMakePayment(), request.canMakePayment()]);
+ }
+ } catch (err) {
+ assert_equals(
+ err.name,
+ "NotAllowedError",
+ "if it throws, then it must be a NotAllowedError."
+ );
+ }
+}, `If basic-card is supported, then return a promise that resolves to true.`);
+</script>
diff --git a/testing/web-platform/tests/payment-method-basic-card/steps_for_selecting_the_payment_handler.html b/testing/web-platform/tests/payment-method-basic-card/steps_for_selecting_the_payment_handler.html
new file mode 100644
index 0000000000..913e784a4a
--- /dev/null
+++ b/testing/web-platform/tests/payment-method-basic-card/steps_for_selecting_the_payment_handler.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>
+ Payment Method Basic Card: steps for selecting the payment handler
+</title>
+<link
+ rel="help"
+ href="https://w3c.github.io/payment-method-basic-card/#selecting-the-payment-handler"
+/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ setup({ explicit_done: true, explicit_timeout: true });
+ const defaultDetails = {
+ total: {
+ label: "Total",
+ amount: {
+ currency: "USD",
+ value: "1.00",
+ },
+ },
+ };
+
+ function emptyDataIsAllNetworks(testableAssertion) {
+ promise_test(async t => {
+ const methodData = [
+ {
+ supportedMethods: "basic-card",
+ },
+ ];
+ const showPromise = new PaymentRequest(methodData, defaultDetails).show();
+ await promise_rejects_dom(t, "AbortError", showPromise);
+ }, testableAssertion.trim());
+ }
+
+ function mixedPMILastOneWins(testableAssertion) {
+ promise_test(async t => {
+ const methodData = [
+ {
+ supportedMethods: "basic-card",
+ data: {
+ supportedNetworks: [],
+ },
+ },
+ {
+ supportedMethods: "basic-card",
+ data: {
+ supportedNetworks: ["visa"],
+ },
+ },
+ {
+ supportedMethods: "https://example.com/bobpay",
+ },
+ ];
+ const showPromise = new PaymentRequest(methodData, defaultDetails).show();
+ await promise_rejects_dom(t, "AbortError", showPromise);
+ }, testableAssertion.trim());
+ }
+
+ function lastOneWinsEvenIfDataIsMissing(testableAssertion) {
+ promise_test(async t => {
+ const methodData = [
+ {
+ supportedMethods: "basic-card",
+ data: {
+ supportedNetworks: ["visa"],
+ },
+ },
+ // Same as data: { supportedNetworks: [] }
+ {
+ supportedMethods: "basic-card",
+ },
+ ];
+ const showPromise = new PaymentRequest(methodData, defaultDetails).show();
+ await promise_rejects_dom(t, "AbortError", showPromise);
+ }, testableAssertion.trim());
+ }
+</script>
+<h1>Manual tests</h1>
+<ol>
+ <li>
+ <p>
+ To pass, this test must show the payment sheet and allow paying with any
+ card.
+ </p>
+ <button onclick="emptyDataIsAllNetworks(this.textContent.trim())">
+ If no data is passed, it's the same as passing an empty BasicCardRequest
+ (i.e., allow all networks).
+ </button>
+ </li>
+ <li>
+ <p>
+ To pass, this test must show the payment sheet and restrict to "visa"
+ credit cards.
+ </p>
+ <button onclick="mixedPMILastOneWins(this.textContent.trim())">
+ It ignores unknown PMIs and last "basic-card" wins - in this case, "visa".
+ </button>
+ </li>
+ <li>
+ <p>
+ To pass, this test must show the payment sheet and allow paying with any
+ card.
+ </p>
+ <button onclick="lastOneWinsEvenIfDataIsMissing(this.textContent.trim())">
+ "Last one wins" even if data is missing.
+ </button>
+ </li>
+ <li><button onclick="done()">Done!</button></li>
+</ol>