diff options
Diffstat (limited to 'browser/components/payments/test/mochitest/payments_common.js')
-rw-r--r-- | browser/components/payments/test/mochitest/payments_common.js | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/browser/components/payments/test/mochitest/payments_common.js b/browser/components/payments/test/mochitest/payments_common.js new file mode 100644 index 0000000000..8e48585318 --- /dev/null +++ b/browser/components/payments/test/mochitest/payments_common.js @@ -0,0 +1,154 @@ +"use strict"; + +/* exported asyncElementRendered, promiseStateChange, promiseContentToChromeMessage, deepClone, + PTU, registerConsoleFilter, fillField, importDialogDependencies */ + +const PTU = SpecialPowers.Cu.import( + "resource://testing-common/PaymentTestUtils.jsm", + {} +).PaymentTestUtils; + +/** + * A helper to await on while waiting for an asynchronous rendering of a Custom + * Element. + * @returns {Promise} + */ +function asyncElementRendered() { + return Promise.resolve(); +} + +function promiseStateChange(store) { + return new Promise(resolve => { + store.subscribe({ + stateChangeCallback(state) { + store.unsubscribe(this); + resolve(state); + }, + }); + }); +} + +/** + * Wait for a message of `messageType` from content to chrome and resolve with the event details. + * @param {string} messageType of the expected message + * @returns {Promise} when the message is dispatched + */ +function promiseContentToChromeMessage(messageType) { + return new Promise(resolve => { + document.addEventListener("paymentContentToChrome", function onCToC(event) { + if (event.detail.messageType != messageType) { + return; + } + document.removeEventListener("paymentContentToChrome", onCToC); + resolve(event.detail); + }); + }); +} + +/** + * Import the templates and stylesheets from the real shipping dialog to avoid + * duplication in the tests. + * @param {HTMLIFrameElement} templateFrame - Frame to copy the resources from + * @param {HTMLElement} destinationEl - Where to append the copied resources + */ +function importDialogDependencies(templateFrame, destinationEl) { + let templates = templateFrame.contentDocument.querySelectorAll("template"); + isnot(templates, null, "Check some templates found"); + for (let template of templates) { + let imported = document.importNode(template, true); + destinationEl.appendChild(imported); + } + + let baseURL = new URL("../../res/", window.location.href); + let stylesheetLinks = templateFrame.contentDocument.querySelectorAll( + "link[rel~='stylesheet']" + ); + for (let stylesheet of stylesheetLinks) { + let imported = document.importNode(stylesheet, true); + imported.href = new URL(imported.getAttribute("href"), baseURL); + destinationEl.appendChild(imported); + } +} + +function deepClone(obj) { + return JSON.parse(JSON.stringify(obj)); +} + +/** + * @param {HTMLElement} field + * @param {string} value + * @note This is async in case we need to make it async to handle focus in the future. + * @note Keep in sync with the copy in head.js + */ +async function fillField(field, value) { + field.focus(); + if (field.localName == "select") { + if (field.value == value) { + // Do nothing + return; + } + field.value = value; + field.dispatchEvent(new Event("input", { bubbles: true })); + field.dispatchEvent(new Event("change", { bubbles: true })); + return; + } + while (field.value) { + sendKey("BACK_SPACE"); + } + sendString(value); +} + +/** + * If filterFunction is a function which returns true given a console message + * then the test won't fail from that message. + */ +let filterFunction = null; +function registerConsoleFilter(filterFn) { + filterFunction = filterFn; +} + +// Listen for errors to fail tests +SpecialPowers.registerConsoleListener(function onConsoleMessage(msg) { + if ( + msg.isWarning || + !msg.errorMessage || + msg.errorMessage == "paymentRequest.xhtml:" + ) { + // Ignore warnings and non-errors. + return; + } + if ( + msg.category == "CSP_CSPViolationWithURI" && + msg.errorMessage.includes("at inline") + ) { + // Ignore unknown CSP error. + return; + } + if ( + msg.message && + msg.message.includes("Security Error: Content at http://mochi.test:8888") + ) { + // Check for same-origin policy violations and ignore specific errors + if ( + msg.message.includes("icon-credit-card-generic.svg") || + msg.message.includes("accepted-cards.css") || + msg.message.includes("editDialog-shared.css") || + msg.message.includes("editAddress.css") || + msg.message.includes("editDialog.css") || + msg.message.includes("editCreditCard.css") + ) { + return; + } + } + if (msg.message == "SENTINEL") { + filterFunction = null; + } + if (filterFunction && filterFunction(msg)) { + return; + } + ok(false, msg.message || msg.errorMessage); +}); + +SimpleTest.registerCleanupFunction(function cleanup() { + SpecialPowers.postConsoleSentinel(); +}); |