forked from mirrors/gecko-dev
		
	This was generated with the script at https://bug1544051.bmoattachments.org/attachment.cgi?id=9058672 Differential Revision: https://phabricator.services.mozilla.com/D27761 --HG-- extra : moz-landing-system : lando
		
			
				
	
	
		
			360 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			360 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<!DOCTYPE HTML>
 | 
						|
<html>
 | 
						|
<!--
 | 
						|
Test the payment-dialog custom element
 | 
						|
-->
 | 
						|
<head>
 | 
						|
  <meta charset="utf-8">
 | 
						|
  <title>Test the payment-dialog element</title>
 | 
						|
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
 | 
						|
  <script src="/tests/SimpleTest/EventUtils.js"></script>
 | 
						|
  <script src="sinon-7.2.7.js"></script>
 | 
						|
  <script src="payments_common.js"></script>
 | 
						|
  <script src="../../res/unprivileged-fallbacks.js"></script>
 | 
						|
  <script src="autofillEditForms.js"></script>
 | 
						|
 | 
						|
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 | 
						|
  <link rel="stylesheet" type="text/css" href="../../res/paymentRequest.css"/>
 | 
						|
  <link rel="stylesheet" type="text/css" href="../../res/containers/rich-picker.css"/>
 | 
						|
</head>
 | 
						|
<body>
 | 
						|
  <p id="display" style="height: 100vh; margin: 0;">
 | 
						|
    <iframe id="templateFrame" src="paymentRequest.xhtml" width="0" height="0"
 | 
						|
            sandbox="allow-same-origin"
 | 
						|
            style="float: left;"></iframe>
 | 
						|
  </p>
 | 
						|
<div id="content" style="display: none">
 | 
						|
 | 
						|
</div>
 | 
						|
<pre id="test">
 | 
						|
</pre>
 | 
						|
<script type="module">
 | 
						|
/** Test the payment-dialog element **/
 | 
						|
 | 
						|
/* global sinon */
 | 
						|
 | 
						|
import PaymentDialog from "../../res/containers/payment-dialog.js";
 | 
						|
 | 
						|
let el1;
 | 
						|
 | 
						|
add_task(async function setup_once() {
 | 
						|
  let templateFrame = document.getElementById("templateFrame");
 | 
						|
  await SimpleTest.promiseFocus(templateFrame.contentWindow);
 | 
						|
  let displayEl = document.getElementById("display");
 | 
						|
  importDialogDependencies(templateFrame, displayEl);
 | 
						|
 | 
						|
  el1 = new PaymentDialog();
 | 
						|
  displayEl.appendChild(el1);
 | 
						|
 | 
						|
  sinon.spy(el1, "render");
 | 
						|
  sinon.spy(el1, "stateChangeCallback");
 | 
						|
});
 | 
						|
 | 
						|
async function setup() {
 | 
						|
  let {request} = el1.requestStore.getState();
 | 
						|
  await el1.requestStore.setState({
 | 
						|
    changesPrevented: false,
 | 
						|
    request: Object.assign({}, request, {completeStatus: ""}),
 | 
						|
    orderDetailsShowing: false,
 | 
						|
    page: {
 | 
						|
      id: "payment-summary",
 | 
						|
    },
 | 
						|
  });
 | 
						|
 | 
						|
  el1.render.reset();
 | 
						|
  el1.stateChangeCallback.reset();
 | 
						|
}
 | 
						|
 | 
						|
add_task(async function test_initialState() {
 | 
						|
  await setup();
 | 
						|
  let initialState = el1.requestStore.getState();
 | 
						|
  let elDetails = el1._orderDetailsOverlay;
 | 
						|
 | 
						|
  is(initialState.orderDetailsShowing, false, "orderDetailsShowing is initially false");
 | 
						|
  ok(elDetails.hasAttribute("hidden"), "Check details are hidden");
 | 
						|
  is(initialState.page.id, "payment-summary", "Check initial page");
 | 
						|
});
 | 
						|
 | 
						|
add_task(async function test_viewAllButtonVisibility() {
 | 
						|
  await setup();
 | 
						|
 | 
						|
  let button = el1._viewAllButton;
 | 
						|
  ok(button.hidden, "Button is initially hidden when there are no items to show");
 | 
						|
  ok(isHidden(button), "Button should be visibly hidden since bug 1469464");
 | 
						|
 | 
						|
  // Add a display item.
 | 
						|
  let request = deepClone(el1.requestStore.getState().request);
 | 
						|
  request.paymentDetails.displayItems = [
 | 
						|
    {
 | 
						|
      "label": "Triangle",
 | 
						|
      "amount": {
 | 
						|
        "currency": "CAD",
 | 
						|
        "value": "3",
 | 
						|
      },
 | 
						|
    },
 | 
						|
  ];
 | 
						|
  await el1.requestStore.setState({ request });
 | 
						|
  await asyncElementRendered();
 | 
						|
 | 
						|
  // Check if the "View all items" button is visible.
 | 
						|
  ok(!button.hidden, "Button is visible");
 | 
						|
});
 | 
						|
 | 
						|
add_task(async function test_viewAllButton() {
 | 
						|
  await setup();
 | 
						|
 | 
						|
  let elDetails = el1._orderDetailsOverlay;
 | 
						|
  let button = el1._viewAllButton;
 | 
						|
 | 
						|
  button.click();
 | 
						|
  await asyncElementRendered();
 | 
						|
 | 
						|
  ok(el1.stateChangeCallback.calledOnce, "stateChangeCallback called once");
 | 
						|
  ok(el1.render.calledOnce, "render called once");
 | 
						|
 | 
						|
  let state = el1.requestStore.getState();
 | 
						|
  is(state.orderDetailsShowing, true, "orderDetailsShowing becomes true");
 | 
						|
  ok(!elDetails.hasAttribute("hidden"), "Check details aren't hidden");
 | 
						|
});
 | 
						|
 | 
						|
add_task(async function test_changesPrevented() {
 | 
						|
  await setup();
 | 
						|
  let state = el1.requestStore.getState();
 | 
						|
  is(state.changesPrevented, false, "changesPrevented is initially false");
 | 
						|
  let disabledOverlay = document.getElementById("disabled-overlay");
 | 
						|
  ok(disabledOverlay.hidden, "Overlay should initially be hidden");
 | 
						|
  await el1.requestStore.setState({changesPrevented: true});
 | 
						|
  await asyncElementRendered();
 | 
						|
  ok(!disabledOverlay.hidden, "Overlay should prevent changes");
 | 
						|
});
 | 
						|
 | 
						|
add_task(async function test_initial_completeStatus() {
 | 
						|
  await setup();
 | 
						|
  let {request, page} = el1.requestStore.getState();
 | 
						|
  is(request.completeStatus, "", "completeStatus is initially empty");
 | 
						|
 | 
						|
  let payButton = document.getElementById("pay");
 | 
						|
  is(payButton, document.querySelector(`#${page.id} button.primary`),
 | 
						|
     "Primary button is the pay button in the initial state");
 | 
						|
  is(payButton.textContent, "Pay", "Check default label");
 | 
						|
  ok(payButton.disabled, "Button is disabled by default");
 | 
						|
});
 | 
						|
 | 
						|
add_task(async function test_generic_errors() {
 | 
						|
  await setup();
 | 
						|
  const SHIPPING_GENERIC_ERROR = "Can't ship to that address";
 | 
						|
  el1._errorText.dataset.shippingGenericError = SHIPPING_GENERIC_ERROR;
 | 
						|
  el1.requestStore.setState({
 | 
						|
    savedAddresses: {
 | 
						|
      "48bnds6854t": {
 | 
						|
        "address-level1": "MI",
 | 
						|
        "address-level2": "Some City",
 | 
						|
        "country": "US",
 | 
						|
        "guid": "48bnds6854t",
 | 
						|
        "name": "Mr. Foo",
 | 
						|
        "postal-code": "90210",
 | 
						|
        "street-address": "123 Sesame Street,\nApt 40",
 | 
						|
        "tel": "+1 519 555-5555",
 | 
						|
      },
 | 
						|
      "68gjdh354j": {
 | 
						|
        "address-level1": "CA",
 | 
						|
        "address-level2": "Mountain View",
 | 
						|
        "country": "US",
 | 
						|
        "guid": "68gjdh354j",
 | 
						|
        "name": "Mrs. Bar",
 | 
						|
        "postal-code": "94041",
 | 
						|
        "street-address": "P.O. Box 123",
 | 
						|
        "tel": "+1 650 555-5555",
 | 
						|
      },
 | 
						|
    },
 | 
						|
    selectedShippingAddress: "48bnds6854t",
 | 
						|
  });
 | 
						|
  await asyncElementRendered();
 | 
						|
 | 
						|
  let picker = el1._shippingAddressPicker;
 | 
						|
  ok(picker.selectedOption, "Address picker should have a selected option");
 | 
						|
  is(el1._errorText.textContent, SHIPPING_GENERIC_ERROR,
 | 
						|
     "Generic error message should be shown when no shipping options or error are provided");
 | 
						|
});
 | 
						|
 | 
						|
add_task(async function test_processing_completeStatus() {
 | 
						|
  // "processing": has overlay. Check button visibility
 | 
						|
  await setup();
 | 
						|
  let {request} = el1.requestStore.getState();
 | 
						|
  // this a transition state, set when waiting for a response from the merchant page
 | 
						|
  el1.requestStore.setState({
 | 
						|
    changesPrevented: true,
 | 
						|
    request: Object.assign({}, request, {completeStatus: "processing"}),
 | 
						|
  });
 | 
						|
  await asyncElementRendered();
 | 
						|
 | 
						|
  let primaryButtons = document.querySelectorAll("footer button.primary");
 | 
						|
  ok(Array.from(primaryButtons).every(el => isHidden(el) || el.disabled),
 | 
						|
     "all primary footer buttons are hidden or disabled");
 | 
						|
 | 
						|
  info("Got an update from the parent process with an error from .retry()");
 | 
						|
  request = el1.requestStore.getState().request;
 | 
						|
  let paymentDetails = deepClone(request.paymentDetails);
 | 
						|
  paymentDetails.error = "Sample retry error";
 | 
						|
  await el1.setStateFromParent({
 | 
						|
    request: Object.assign({}, request, {
 | 
						|
      completeStatus: "",
 | 
						|
      paymentDetails,
 | 
						|
    }),
 | 
						|
  });
 | 
						|
  await asyncElementRendered();
 | 
						|
 | 
						|
  let {changesPrevented, page} = el1.requestStore.getState();
 | 
						|
  ok(!changesPrevented, "Changes should no longer be prevented");
 | 
						|
  is(page.id, "payment-summary", "Check back on payment-summary");
 | 
						|
  ok(el1.innerText.includes("Sample retry error"), "Check error text is visible");
 | 
						|
});
 | 
						|
 | 
						|
add_task(async function test_success_unknown_completeStatus() {
 | 
						|
  // in the "success" and "unknown" completion states the dialog would normally be closed
 | 
						|
  // so just ensure it is left in a good state
 | 
						|
  for (let completeStatus of ["success", "unknown"]) {
 | 
						|
    await setup();
 | 
						|
    let {request} = el1.requestStore.getState();
 | 
						|
    el1.requestStore.setState({
 | 
						|
      request: Object.assign({}, request, {completeStatus}),
 | 
						|
    });
 | 
						|
    await asyncElementRendered();
 | 
						|
 | 
						|
    let {page} = el1.requestStore.getState();
 | 
						|
 | 
						|
    // this status doesnt change page
 | 
						|
    let payButton = document.getElementById("pay");
 | 
						|
    is(payButton, document.querySelector(`#${page.id} button.primary`),
 | 
						|
       `Primary button is the pay button in the ${completeStatus} state`);
 | 
						|
 | 
						|
    if (completeStatus == "success") {
 | 
						|
      is(payButton.textContent, "Done", "Check button label");
 | 
						|
    }
 | 
						|
    if (completeStatus == "unknown") {
 | 
						|
      is(payButton.textContent, "Unknown", "Check button label");
 | 
						|
    }
 | 
						|
    ok(payButton.disabled, "Button is disabled by default");
 | 
						|
  }
 | 
						|
});
 | 
						|
 | 
						|
add_task(async function test_timeout_fail_completeStatus() {
 | 
						|
  // in these states the dialog stays open and presents a single
 | 
						|
  // button for acknowledgement
 | 
						|
  for (let completeStatus of ["fail", "timeout"]) {
 | 
						|
    await setup();
 | 
						|
    let {request} = el1.requestStore.getState();
 | 
						|
    el1.requestStore.setState({
 | 
						|
      request: Object.assign({}, request, {completeStatus}),
 | 
						|
      page: {
 | 
						|
        id: `completion-${completeStatus}-error`,
 | 
						|
      },
 | 
						|
    });
 | 
						|
    await asyncElementRendered();
 | 
						|
 | 
						|
    let {page} = el1.requestStore.getState();
 | 
						|
    let pageElem = document.querySelector(`#${page.id}`);
 | 
						|
    let payButton = document.getElementById("pay");
 | 
						|
    let primaryButton = pageElem.querySelector("button.primary");
 | 
						|
 | 
						|
    ok(pageElem && !isHidden(pageElem, `page element for ${page.id} exists and is visible`));
 | 
						|
    ok(!isHidden(primaryButton), "Primary button is visible");
 | 
						|
    ok(payButton != primaryButton,
 | 
						|
       `Primary button is the not pay button in the ${completeStatus} state`);
 | 
						|
    ok(isHidden(payButton), "Pay button is not visible");
 | 
						|
    is(primaryButton.textContent, "Close", "Check button label");
 | 
						|
 | 
						|
    let rect = primaryButton.getBoundingClientRect();
 | 
						|
    let visibleElement =
 | 
						|
      document.elementFromPoint(rect.x + rect.width / 2, rect.y + rect.height / 2);
 | 
						|
    ok(primaryButton === visibleElement, "Primary button is on top of the overlay");
 | 
						|
  }
 | 
						|
});
 | 
						|
 | 
						|
add_task(async function test_scrollPaymentRequestPage() {
 | 
						|
  await setup();
 | 
						|
  info("making the payment-dialog container small to require scrolling");
 | 
						|
  el1.parentElement.style.height = "100px";
 | 
						|
  let summaryPageBody = document.querySelector("#payment-summary .page-body");
 | 
						|
  is(summaryPageBody.scrollTop, 0, "Page body not scrolled initially");
 | 
						|
  let securityCodeInput = summaryPageBody.querySelector("payment-method-picker input");
 | 
						|
  securityCodeInput.focus();
 | 
						|
  await new Promise(resolve => SimpleTest.executeSoon(resolve));
 | 
						|
  ok(summaryPageBody.scrollTop > 0, "Page body scrolled after focusing the CVV field");
 | 
						|
  el1.parentElement.style.height = "";
 | 
						|
});
 | 
						|
 | 
						|
add_task(async function test_acceptedCards() {
 | 
						|
  let initialState = el1.requestStore.getState();
 | 
						|
  let paymentMethods = [{
 | 
						|
    supportedMethods: "basic-card",
 | 
						|
    data: {
 | 
						|
      supportedNetworks: ["visa", "mastercard"],
 | 
						|
    },
 | 
						|
  }];
 | 
						|
  el1.requestStore.setState({
 | 
						|
    request: Object.assign({}, initialState.request, {
 | 
						|
      paymentMethods,
 | 
						|
    }),
 | 
						|
  });
 | 
						|
  await asyncElementRendered();
 | 
						|
 | 
						|
  let acceptedCards = el1._acceptedCardsList;
 | 
						|
  ok(acceptedCards && !isHidden(acceptedCards), "Accepted cards list is present and visible");
 | 
						|
 | 
						|
  paymentMethods = [{
 | 
						|
    supportedMethods: "basic-card",
 | 
						|
  }];
 | 
						|
  el1.requestStore.setState({
 | 
						|
    request: Object.assign({}, initialState.request, {
 | 
						|
      paymentMethods,
 | 
						|
    }),
 | 
						|
  });
 | 
						|
  await asyncElementRendered();
 | 
						|
 | 
						|
  acceptedCards = el1._acceptedCardsList;
 | 
						|
  ok(acceptedCards && isHidden(acceptedCards), "Accepted cards list is present but hidden");
 | 
						|
});
 | 
						|
 | 
						|
add_task(async function test_picker_labels() {
 | 
						|
  await setup();
 | 
						|
  let picker = el1._shippingOptionPicker;
 | 
						|
 | 
						|
  const SHIPPING_OPTIONS_LABEL = "Shipping options";
 | 
						|
  const DELIVERY_OPTIONS_LABEL = "Delivery options";
 | 
						|
  const PICKUP_OPTIONS_LABEL = "Pickup options";
 | 
						|
  picker.dataset.shippingOptionsLabel = SHIPPING_OPTIONS_LABEL;
 | 
						|
  picker.dataset.deliveryOptionsLabel = DELIVERY_OPTIONS_LABEL;
 | 
						|
  picker.dataset.pickupOptionsLabel = PICKUP_OPTIONS_LABEL;
 | 
						|
 | 
						|
  for (let [shippingType, label] of [
 | 
						|
    ["shipping", SHIPPING_OPTIONS_LABEL],
 | 
						|
    ["delivery", DELIVERY_OPTIONS_LABEL],
 | 
						|
    ["pickup", PICKUP_OPTIONS_LABEL],
 | 
						|
  ]) {
 | 
						|
    let request = deepClone(el1.requestStore.getState().request);
 | 
						|
    request.paymentOptions.requestShipping = true;
 | 
						|
    request.paymentOptions.shippingType = shippingType;
 | 
						|
    await el1.requestStore.setState({ request });
 | 
						|
    await asyncElementRendered();
 | 
						|
    is(picker.labelElement.textContent, label,
 | 
						|
       `Label should be appropriate for ${shippingType}`);
 | 
						|
  }
 | 
						|
});
 | 
						|
 | 
						|
add_task(async function test_disconnect() {
 | 
						|
  await setup();
 | 
						|
 | 
						|
  el1.remove();
 | 
						|
  await el1.requestStore.setState({orderDetailsShowing: true});
 | 
						|
  await asyncElementRendered();
 | 
						|
  ok(el1.stateChangeCallback.notCalled, "stateChangeCallback not called");
 | 
						|
  ok(el1.render.notCalled, "render not called");
 | 
						|
 | 
						|
  let elDetails = el1._orderDetailsOverlay;
 | 
						|
  ok(elDetails.hasAttribute("hidden"), "details overlay remains hidden");
 | 
						|
});
 | 
						|
</script>
 | 
						|
 | 
						|
</body>
 | 
						|
</html>
 |