diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /testing/web-platform/tests/resources/testdriver.js | |
parent | Initial commit. (diff) | |
download | firefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/resources/testdriver.js')
-rw-r--r-- | testing/web-platform/tests/resources/testdriver.js | 776 |
1 files changed, 776 insertions, 0 deletions
diff --git a/testing/web-platform/tests/resources/testdriver.js b/testing/web-platform/tests/resources/testdriver.js new file mode 100644 index 0000000000..76ae2834fd --- /dev/null +++ b/testing/web-platform/tests/resources/testdriver.js @@ -0,0 +1,776 @@ +(function() { + "use strict"; + var idCounter = 0; + let testharness_context = null; + + function getInViewCenterPoint(rect) { + var left = Math.max(0, rect.left); + var right = Math.min(window.innerWidth, rect.right); + var top = Math.max(0, rect.top); + var bottom = Math.min(window.innerHeight, rect.bottom); + + var x = 0.5 * (left + right); + var y = 0.5 * (top + bottom); + + return [x, y]; + } + + function getPointerInteractablePaintTree(element) { + let elementDocument = element.ownerDocument; + if (!elementDocument.contains(element)) { + return []; + } + + var rectangles = element.getClientRects(); + + if (rectangles.length === 0) { + return []; + } + + var centerPoint = getInViewCenterPoint(rectangles[0]); + + if ("elementsFromPoint" in elementDocument) { + return elementDocument.elementsFromPoint(centerPoint[0], centerPoint[1]); + } else if ("msElementsFromPoint" in elementDocument) { + var rv = elementDocument.msElementsFromPoint(centerPoint[0], centerPoint[1]); + return Array.prototype.slice.call(rv ? rv : []); + } else { + throw new Error("document.elementsFromPoint unsupported"); + } + } + + function inView(element) { + var pointerInteractablePaintTree = getPointerInteractablePaintTree(element); + return pointerInteractablePaintTree.indexOf(element) !== -1; + } + + + /** + * @namespace {test_driver} + */ + window.test_driver = { + /** + * Set the context in which testharness.js is loaded + * + * @param {WindowProxy} context - the window containing testharness.js + **/ + set_test_context: function(context) { + if (window.test_driver_internal.set_test_context) { + window.test_driver_internal.set_test_context(context); + } + testharness_context = context; + }, + + /** + * postMessage to the context containing testharness.js + * + * @param {Object} msg - the data to POST + **/ + message_test: function(msg) { + let target = testharness_context; + if (testharness_context === null) { + target = window; + } + target.postMessage(msg, "*"); + }, + + /** + * Trigger user interaction in order to grant additional privileges to + * a provided function. + * + * See `Tracking user activation + * <https://html.spec.whatwg.org/multipage/interaction.html#tracking-user-activation>`_. + * + * @example + * var mediaElement = document.createElement('video'); + * + * test_driver.bless('initiate media playback', function () { + * mediaElement.play(); + * }); + * + * @param {String} intent - a description of the action which must be + * triggered by user interaction + * @param {Function} action - code requiring escalated privileges + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} fulfilled following user interaction and + * execution of the provided `action` function; + * rejected if interaction fails or the provided + * function throws an error + */ + bless: function(intent, action, context=null) { + let contextDocument = context ? context.document : document; + var button = contextDocument.createElement("button"); + button.innerHTML = "This test requires user interaction.<br />" + + "Please click here to allow " + intent + "."; + button.id = "wpt-test-driver-bless-" + (idCounter += 1); + const elem = contextDocument.body || contextDocument.documentElement; + elem.appendChild(button); + + let wait_click = new Promise(resolve => button.addEventListener("click", resolve)); + + return test_driver.click(button) + .then(wait_click) + .then(function() { + button.remove(); + + if (typeof action === "function") { + return action(); + } + return null; + }); + }, + + /** + * Triggers a user-initiated click + * + * If ``element`` isn't inside the + * viewport, it will be scrolled into view before the click + * occurs. + * + * If ``element`` is from a different browsing context, the + * command will be run in that context. + * + * Matches the behaviour of the `Element Click + * <https://w3c.github.io/webdriver/#element-click>`_ + * WebDriver command. + * + * **Note:** If the element to be clicked does not have a + * unique ID, the document must not have any DOM mutations + * made between the function being called and the promise + * settling. + * + * @param {Element} element - element to be clicked + * @returns {Promise} fulfilled after click occurs, or rejected in + * the cases the WebDriver command errors + */ + click: function(element) { + if (!inView(element)) { + element.scrollIntoView({behavior: "instant", + block: "end", + inline: "nearest"}); + } + + var pointerInteractablePaintTree = getPointerInteractablePaintTree(element); + if (pointerInteractablePaintTree.length === 0 || + !element.contains(pointerInteractablePaintTree[0])) { + return Promise.reject(new Error("element click intercepted error")); + } + + var rect = element.getClientRects()[0]; + var centerPoint = getInViewCenterPoint(rect); + return window.test_driver_internal.click(element, + {x: centerPoint[0], + y: centerPoint[1]}); + }, + + /** + * Deletes all cookies. + * + * Matches the behaviour of the `Delete All Cookies + * <https://w3c.github.io/webdriver/#delete-all-cookies>`_ + * WebDriver command. + * + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} fulfilled after cookies are deleted, or rejected in + * the cases the WebDriver command errors + */ + delete_all_cookies: function(context=null) { + return window.test_driver_internal.delete_all_cookies(context); + }, + + /** + * Get details for all cookies in the current context. + * See https://w3c.github.io/webdriver/#get-all-cookies + * + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} Returns an array of cookies objects as defined in the spec: + * https://w3c.github.io/webdriver/#cookies + */ + get_all_cookies: function(context=null) { + return window.test_driver_internal.get_all_cookies(context); + }, + + /** + * Get details for a cookie in the current context by name if it exists. + * See https://w3c.github.io/webdriver/#get-named-cookie + * + * @param {String} name - The name of the cookie to get. + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} Returns the matching cookie as defined in the spec: + * https://w3c.github.io/webdriver/#cookies + * Rejected if no such cookie exists. + */ + get_named_cookie: async function(name, context=null) { + let cookie = await window.test_driver_internal.get_named_cookie(name, context); + if (!cookie) { + throw new Error("no such cookie"); + } + return cookie; + }, + + /** + * Send keys to an element. + * + * If ``element`` isn't inside the + * viewport, it will be scrolled into view before the click + * occurs. + * + * If ``element`` is from a different browsing context, the + * command will be run in that context. + * + * To send special keys, send the respective key's codepoint, + * as defined by `WebDriver + * <https://w3c.github.io/webdriver/#keyboard-actions>`_. For + * example, the "tab" key is represented as "``\uE004``". + * + * **Note:** these special-key codepoints are not necessarily + * what you would expect. For example, <kbd>Esc</kbd> is the + * invalid Unicode character ``\uE00C``, not the ``\u001B`` Escape + * character from ASCII. + * + * This matches the behaviour of the + * `Send Keys + * <https://w3c.github.io/webdriver/#element-send-keys>`_ + * WebDriver command. + * + * **Note:** If the element to be clicked does not have a + * unique ID, the document must not have any DOM mutations + * made between the function being called and the promise + * settling. + * + * @param {Element} element - element to send keys to + * @param {String} keys - keys to send to the element + * @returns {Promise} fulfilled after keys are sent, or rejected in + * the cases the WebDriver command errors + */ + send_keys: function(element, keys) { + if (!inView(element)) { + element.scrollIntoView({behavior: "instant", + block: "end", + inline: "nearest"}); + } + + var pointerInteractablePaintTree = getPointerInteractablePaintTree(element); + if (pointerInteractablePaintTree.length === 0 || + !element.contains(pointerInteractablePaintTree[0])) { + return Promise.reject(new Error("element send_keys intercepted error")); + } + + return window.test_driver_internal.send_keys(element, keys); + }, + + /** + * Freeze the current page + * + * The freeze function transitions the page from the HIDDEN state to + * the FROZEN state as described in `Lifecycle API for Web Pages + * <https://github.com/WICG/page-lifecycle/blob/master/README.md>`_. + * + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} fulfilled after the freeze request is sent, or rejected + * in case the WebDriver command errors + */ + freeze: function(context=null) { + return window.test_driver_internal.freeze(); + }, + + /** + * Minimizes the browser window. + * + * Matches the the behaviour of the `Minimize + * <https://www.w3.org/TR/webdriver/#minimize-window>`_ + * WebDriver command + * + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} fulfilled with the previous {@link + * https://www.w3.org/TR/webdriver/#dfn-windowrect-object|WindowRect} + * value, after the window is minimized. + */ + minimize_window: function(context=null) { + return window.test_driver_internal.minimize_window(context); + }, + + /** + * Restore the window from minimized/maximized state to a given rect. + * + * Matches the behaviour of the `Set Window Rect + * <https://www.w3.org/TR/webdriver/#set-window-rect>`_ + * WebDriver command + * + * @param {Object} rect - A {@link + * https://www.w3.org/TR/webdriver/#dfn-windowrect-object|WindowRect} + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} fulfilled after the window is restored to the given rect. + */ + set_window_rect: function(rect, context=null) { + return window.test_driver_internal.set_window_rect(rect, context); + }, + + /** + * Send a sequence of actions + * + * This function sends a sequence of actions to perform. + * + * Matches the behaviour of the `Actions + * <https://w3c.github.io/webdriver/#actions>`_ feature in + * WebDriver. + * + * Authors are encouraged to use the + * :js:class:`test_driver.Actions` builder rather than + * invoking this API directly. + * + * @param {Array} actions - an array of actions. The format is + * the same as the actions property + * of the `Perform Actions + * <https://w3c.github.io/webdriver/#perform-actions>`_ + * WebDriver command. Each element is + * an object representing an input + * source and each input source + * itself has an actions property + * detailing the behaviour of that + * source at each timestep (or + * tick). Authors are not expected to + * construct the actions sequence by + * hand, but to use the builder api + * provided in testdriver-actions.js + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} fulfilled after the actions are performed, or rejected in + * the cases the WebDriver command errors + */ + action_sequence: function(actions, context=null) { + return window.test_driver_internal.action_sequence(actions, context); + }, + + /** + * Generates a test report on the current page + * + * The generate_test_report function generates a report (to be + * observed by ReportingObserver) for testing purposes. + * + * Matches the `Generate Test Report + * <https://w3c.github.io/reporting/#generate-test-report-command>`_ + * WebDriver command. + * + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} fulfilled after the report is generated, or + * rejected if the report generation fails + */ + generate_test_report: function(message, context=null) { + return window.test_driver_internal.generate_test_report(message, context); + }, + + /** + * Sets the state of a permission + * + * This function simulates a user setting a permission into a + * particular state. + * + * Matches the `Set Permission + * <https://w3c.github.io/permissions/#set-permission-command>`_ + * WebDriver command. + * + * @example + * await test_driver.set_permission({ name: "background-fetch" }, "denied"); + * await test_driver.set_permission({ name: "push", userVisibleOnly: true }, "granted"); + * + * @param {PermissionDescriptor} descriptor - a `PermissionDescriptor + * <https://w3c.github.io/permissions/#dom-permissiondescriptor>`_ + * dictionary. + * @param {String} state - the state of the permission + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * @returns {Promise} fulfilled after the permission is set, or rejected if setting the + * permission fails + */ + set_permission: function(descriptor, state, context=null) { + let permission_params = { + descriptor, + state, + }; + return window.test_driver_internal.set_permission(permission_params, context); + }, + + /** + * Creates a virtual authenticator + * + * This function creates a virtual authenticator for use with + * the U2F and WebAuthn APIs. + * + * Matches the `Add Virtual Authenticator + * <https://w3c.github.io/webauthn/#sctn-automation-add-virtual-authenticator>`_ + * WebDriver command. + * + * @param {Object} config - an `Authenticator Configuration + * <https://w3c.github.io/webauthn/#authenticator-configuration>`_ + * object + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} fulfilled after the authenticator is added, or + * rejected in the cases the WebDriver command + * errors. Returns the ID of the authenticator + */ + add_virtual_authenticator: function(config, context=null) { + return window.test_driver_internal.add_virtual_authenticator(config, context); + }, + + /** + * Removes a virtual authenticator + * + * This function removes a virtual authenticator that has been + * created by :js:func:`add_virtual_authenticator`. + * + * Matches the `Remove Virtual Authenticator + * <https://w3c.github.io/webauthn/#sctn-automation-remove-virtual-authenticator>`_ + * WebDriver command. + * + * @param {String} authenticator_id - the ID of the authenticator to be + * removed. + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} fulfilled after the authenticator is removed, or + * rejected in the cases the WebDriver command + * errors + */ + remove_virtual_authenticator: function(authenticator_id, context=null) { + return window.test_driver_internal.remove_virtual_authenticator(authenticator_id, context); + }, + + /** + * Adds a credential to a virtual authenticator + * + * Matches the `Add Credential + * <https://w3c.github.io/webauthn/#sctn-automation-add-credential>`_ + * WebDriver command. + * + * @param {String} authenticator_id - the ID of the authenticator + * @param {Object} credential - A `Credential Parameters + * <https://w3c.github.io/webauthn/#credential-parameters>`_ + * object + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} fulfilled after the credential is added, or + * rejected in the cases the WebDriver command + * errors + */ + add_credential: function(authenticator_id, credential, context=null) { + return window.test_driver_internal.add_credential(authenticator_id, credential, context); + }, + + /** + * Gets all the credentials stored in an authenticator + * + * This function retrieves all the credentials (added via the U2F API, + * WebAuthn, or the add_credential function) stored in a virtual + * authenticator + * + * Matches the `Get Credentials + * <https://w3c.github.io/webauthn/#sctn-automation-get-credentials>`_ + * WebDriver command. + * + * @param {String} authenticator_id - the ID of the authenticator + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} fulfilled after the credentials are + * returned, or rejected in the cases the + * WebDriver command errors. Returns an + * array of `Credential Parameters + * <https://w3c.github.io/webauthn/#credential-parameters>`_ + */ + get_credentials: function(authenticator_id, context=null) { + return window.test_driver_internal.get_credentials(authenticator_id, context=null); + }, + + /** + * Remove a credential stored in an authenticator + * + * Matches the `Remove Credential + * <https://w3c.github.io/webauthn/#sctn-automation-remove-credential>`_ + * WebDriver command. + * + * @param {String} authenticator_id - the ID of the authenticator + * @param {String} credential_id - the ID of the credential + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} fulfilled after the credential is removed, or + * rejected in the cases the WebDriver command + * errors. + */ + remove_credential: function(authenticator_id, credential_id, context=null) { + return window.test_driver_internal.remove_credential(authenticator_id, credential_id, context); + }, + + /** + * Removes all the credentials stored in a virtual authenticator + * + * Matches the `Remove All Credentials + * <https://w3c.github.io/webauthn/#sctn-automation-remove-all-credentials>`_ + * WebDriver command. + * + * @param {String} authenticator_id - the ID of the authenticator + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} fulfilled after the credentials are removed, or + * rejected in the cases the WebDriver command + * errors. + */ + remove_all_credentials: function(authenticator_id, context=null) { + return window.test_driver_internal.remove_all_credentials(authenticator_id, context); + }, + + /** + * Sets the User Verified flag on an authenticator + * + * Sets whether requests requiring user verification will succeed or + * fail on a given virtual authenticator + * + * Matches the `Set User Verified + * <https://w3c.github.io/webauthn/#sctn-automation-set-user-verified>`_ + * WebDriver command. + * + * @param {String} authenticator_id - the ID of the authenticator + * @param {boolean} uv - the User Verified flag + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + */ + set_user_verified: function(authenticator_id, uv, context=null) { + return window.test_driver_internal.set_user_verified(authenticator_id, uv, context); + }, + + /** + * Sets the storage access rule for an origin when embedded + * in a third-party context. + * + * Matches the `Set Storage Access + * <https://privacycg.github.io/storage-access/#set-storage-access-command>`_ + * WebDriver command. + * + * @param {String} origin - A third-party origin to block or allow. + * May be "*" to indicate all origins. + * @param {String} embedding_origin - an embedding (first-party) origin + * on which {origin}'s access should + * be blocked or allowed. + * May be "*" to indicate all origins. + * @param {String} state - The storage access setting. + * Must be either "allowed" or "blocked". + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} Fulfilled after the storage access rule has been + * set, or rejected if setting the rule fails. + */ + set_storage_access: function(origin, embedding_origin, state, context=null) { + if (state !== "allowed" && state !== "blocked") { + throw new Error("storage access status must be 'allowed' or 'blocked'"); + } + const blocked = state === "blocked"; + return window.test_driver_internal.set_storage_access(origin, embedding_origin, blocked, context); + }, + + /** + * Sets the current transaction automation mode for Secure Payment + * Confirmation. + * + * This function places `Secure Payment + * Confirmation <https://w3c.github.io/secure-payment-confirmation>`_ into + * an automated 'autoaccept' or 'autoreject' mode, to allow testing + * without user interaction with the transaction UX prompt. + * + * Matches the `Set SPC Transaction Mode + * <https://w3c.github.io/secure-payment-confirmation/#sctn-automation-set-spc-transaction-mode>`_ + * WebDriver command. + * + * @example + * await test_driver.set_spc_transaction_mode("autoaccept"); + * test.add_cleanup(() => { + * return test_driver.set_spc_transaction_mode("none"); + * }); + * + * // Assumption: `request` is a PaymentRequest with a secure-payment-confirmation + * // payment method. + * const response = await request.show(); + * + * @param {String} mode - The `transaction mode + * <https://w3c.github.io/secure-payment-confirmation/#enumdef-transactionautomationmode>`_ + * to set. Must be one of "``none``", + * "``autoaccept``", or + * "``autoreject``". + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} Fulfilled after the transaction mode has been set, + * or rejected if setting the mode fails. + */ + set_spc_transaction_mode: function(mode, context=null) { + return window.test_driver_internal.set_spc_transaction_mode(mode, context); + }, + }; + + window.test_driver_internal = { + /** + * This flag should be set to `true` by any code which implements the + * internal methods defined below for automation purposes. Doing so + * allows the library to signal failure immediately when an automated + * implementation of one of the methods is not available. + */ + in_automation: false, + + click: function(element, coords) { + if (this.in_automation) { + return Promise.reject(new Error('Not implemented')); + } + + return new Promise(function(resolve, reject) { + element.addEventListener("click", resolve); + }); + }, + + delete_all_cookies: function(context=null) { + return Promise.reject(new Error("unimplemented")); + }, + + get_all_cookies: function(context=null) { + return Promise.reject(new Error("unimplemented")); + }, + + get_named_cookie: function(name, context=null) { + return Promise.reject(new Error("unimplemented")); + }, + + send_keys: function(element, keys) { + if (this.in_automation) { + return Promise.reject(new Error('Not implemented')); + } + + return new Promise(function(resolve, reject) { + var seen = ""; + + function remove() { + element.removeEventListener("keydown", onKeyDown); + } + + function onKeyDown(event) { + if (event.key.length > 1) { + return; + } + + seen += event.key; + + if (keys.indexOf(seen) !== 0) { + reject(new Error("Unexpected key sequence: " + seen)); + remove(); + } else if (seen === keys) { + resolve(); + remove(); + } + } + + element.addEventListener("keydown", onKeyDown); + }); + }, + + freeze: function(context=null) { + return Promise.reject(new Error("unimplemented")); + }, + + minimize_window: function(context=null) { + return Promise.reject(new Error("unimplemented")); + }, + + set_window_rect: function(rect, context=null) { + return Promise.reject(new Error("unimplemented")); + }, + + action_sequence: function(actions, context=null) { + return Promise.reject(new Error("unimplemented")); + }, + + generate_test_report: function(message, context=null) { + return Promise.reject(new Error("unimplemented")); + }, + + + set_permission: function(permission_params, context=null) { + return Promise.reject(new Error("unimplemented")); + }, + + add_virtual_authenticator: function(config, context=null) { + return Promise.reject(new Error("unimplemented")); + }, + + remove_virtual_authenticator: function(authenticator_id, context=null) { + return Promise.reject(new Error("unimplemented")); + }, + + add_credential: function(authenticator_id, credential, context=null) { + return Promise.reject(new Error("unimplemented")); + }, + + get_credentials: function(authenticator_id, context=null) { + return Promise.reject(new Error("unimplemented")); + }, + + remove_credential: function(authenticator_id, credential_id, context=null) { + return Promise.reject(new Error("unimplemented")); + }, + + remove_all_credentials: function(authenticator_id, context=null) { + return Promise.reject(new Error("unimplemented")); + }, + + set_user_verified: function(authenticator_id, uv, context=null) { + return Promise.reject(new Error("unimplemented")); + }, + + set_storage_access: function(origin, embedding_origin, blocked, context=null) { + return Promise.reject(new Error("unimplemented")); + }, + + set_spc_transaction_mode: function(mode, context=null) { + return Promise.reject(new Error("unimplemented")); + }, + + }; +})(); |