commit d210ff281f35b299fca956f2555cb6064e2cc679 parent 71c0a6f4dcb25c5a92a9d1e95d00982103297307 Author: Atila Butkovits <abutkovits@mozilla.com> Date: Tue, 11 Nov 2025 18:14:06 +0200 Revert "Bug 1848958 - [wdspec] Update tests for dispatching mouse events via the parent process. r=jdescottes" for causing failures at pointer_dblclick.py. This reverts commit 4a2e13581c2d0ca4f75835d0a2e2338d9e3c9a96. Revert "Bug 1848958 - [remote] Use async (widget) mouse events for async-event-dispatching jobs in CI. r=jgraham,jdescottes" This reverts commit cc2c0ff3147c3f7041dc03f6718ff4cceb2426a8. Revert "Bug 1848958 - [remote] Add support for mouse widget events to Marionette and WebDriver BiDi. r=jdescottes" This reverts commit 2c38d9a8558669749e305d9911aa3390a3310872. Revert "Bug 1848958 - [remote] Ignore error from finalize action if browsing context no longer exists. r=jdescottes" This reverts commit 9e80bc22f2168fea0c1cc1b85fbac1dfe73a9d72. Diffstat:
20 files changed, 150 insertions(+), 284 deletions(-)
diff --git a/remote/marionette/actors/MarionetteCommandsChild.sys.mjs b/remote/marionette/actors/MarionetteCommandsChild.sys.mjs @@ -87,7 +87,7 @@ export class MarionetteCommandsChild extends JSWindowActorChild { lazy.event.sendKeyUp(details.eventData, win); break; case "synthesizeMouseAtPoint": - await lazy.event.synthesizeMouseAtPoint( + lazy.event.synthesizeMouseAtPoint( details.x, details.y, details.eventData, diff --git a/remote/marionette/driver.sys.mjs b/remote/marionette/driver.sys.mjs @@ -158,12 +158,10 @@ class ActionsHelper { */ dispatchEvent(eventName, browsingContext, details) { if ( - (eventName === "synthesizeWheelAtPoint" && - lazy.actions.useAsyncWheelEvents) || - (eventName == "synthesizeMouseAtPoint" && - lazy.actions.useAsyncMouseEvents) + eventName === "synthesizeWheelAtPoint" && + lazy.actions.useAsyncWheelEvents ) { - browsingContext = browsingContext.topChromeWindow?.browsingContext; + browsingContext = browsingContext.topChromeWindow.browsingContext; details.eventData.asyncEnabled = true; } @@ -175,16 +173,12 @@ class ActionsHelper { * * @param {BrowsingContext} browsingContext * The browsing context to dispatch the event to. + * + * @returns {Promise} + * Promise that resolves when the finalization is done. */ - async finalizeAction(browsingContext) { - try { - await this.#getActor(browsingContext).finalizeAction(); - } catch (e) { - // Ignore the error if the underlying browsing context is already gone. - if (e.name !== lazy.error.NoSuchWindowError.name) { - throw e; - } - } + finalizeAction(browsingContext) { + return this.#getActor(browsingContext).finalizeAction(); } /** diff --git a/remote/marionette/interaction.sys.mjs b/remote/marionette/interaction.sys.mjs @@ -190,7 +190,7 @@ async function webdriverClickElement(el, a11y) { interaction.selectOption(el); } else { // Synthesize a pointerMove action. - await lazy.event.synthesizeMouseAtPoint( + lazy.event.synthesizeMouseAtPoint( clickPoint.x, clickPoint.y, { @@ -204,7 +204,7 @@ async function webdriverClickElement(el, a11y) { // Special handling is required if the mousemove started a drag session. // In this case, mousedown event shouldn't be fired, and the mouseup should // end the session. Therefore, we should synthesize only mouseup. - await lazy.event.synthesizeMouseAtPoint( + lazy.event.synthesizeMouseAtPoint( clickPoint.x, clickPoint.y, { @@ -218,7 +218,7 @@ async function webdriverClickElement(el, a11y) { let clicked = interaction.flushEventLoop(containerEl); // Synthesize a pointerDown + pointerUp action. - await lazy.event.synthesizeMouseAtPoint( + lazy.event.synthesizeMouseAtPoint( clickPoint.x, clickPoint.y, { allowToHandleDragDrop: true }, @@ -278,7 +278,7 @@ async function seleniumClickElement(el, a11y) { let rects = el.getClientRects(); let centre = lazy.dom.getInViewCentrePoint(rects[0], win); let opts = {}; - await lazy.event.synthesizeMouseAtPoint(centre.x, centre.y, opts, win); + lazy.event.synthesizeMouseAtPoint(centre.x, centre.y, opts, win); } } diff --git a/remote/shared/webdriver/Actions.sys.mjs b/remote/shared/webdriver/Actions.sys.mjs @@ -49,14 +49,6 @@ const MODIFIER_NAME_LOOKUP = { Meta: "meta", }; -// Flag, that indicates if an async widget event should be used when dispatching a mouse event. -XPCOMUtils.defineLazyPreferenceGetter( - actions, - "useAsyncMouseEvents", - "remote.events.async.mouse.enabled", - false -); - // Flag, that indicates if an async widget event should be used when dispatching a wheel scroll event. XPCOMUtils.defineLazyPreferenceGetter( actions, @@ -515,10 +507,6 @@ class KeyInputSource extends InputSource { * Input state associated with a pointer-type device. */ class PointerInputSource extends InputSource { - #initialized; - #x; - #y; - static type = "pointer"; /** @@ -533,23 +521,9 @@ class PointerInputSource extends InputSource { super(id); this.pointer = pointer; + this.x = 0; + this.y = 0; this.pressed = new Set(); - - this.#initialized = false; - this.#x = 0; - this.#y = 0; - } - - get initialized() { - return this.#initialized; - } - - get x() { - return this.#x; - } - - get y() { - return this.#y; } /** @@ -570,12 +544,6 @@ class PointerInputSource extends InputSource { return this.pressed.has(button); } - moveTo(x, y) { - this.#initialized = true; - this.#x = x; - this.#y = y; - } - /** * Add |button| to the set of pressed keys. * @@ -1400,15 +1368,14 @@ class PointerDownAction extends PointerAction { * Promise that is resolved once the action is complete. */ async dispatch(state, inputSource, tickDuration, options) { + lazy.logger.trace( + `Dispatch ${this.constructor.name} ${inputSource.pointer.type} with id: ${this.id} button: ${this.button}` + ); + if (inputSource.isPressed(this.button)) { return; } - lazy.logger.trace( - `Dispatch ${this.constructor.name} ${inputSource.pointer.type} with id: ${this.id} ` + - `button: ${this.button} async: ${actions.useAsyncMouseEvents}` - ); - inputSource.press(this.button); await inputSource.pointer.pointerDown(state, inputSource, this, options); @@ -1505,15 +1472,14 @@ class PointerUpAction extends PointerAction { * Promise that is resolved once the action is complete. */ async dispatch(state, inputSource, tickDuration, options) { + lazy.logger.trace( + `Dispatch ${this.constructor.name} ${inputSource.pointer.type} with id: ${this.id} button: ${this.button}` + ); + if (!inputSource.isPressed(this.button)) { return; } - lazy.logger.trace( - `Dispatch ${this.constructor.name} ${inputSource.pointer.type} with id: ${this.id} ` + - `button: ${this.button} async: ${actions.useAsyncMouseEvents}` - ); - inputSource.release(this.button); await inputSource.pointer.pointerUp(state, inputSource, this, options); @@ -1615,38 +1581,23 @@ class PointerMoveAction extends PointerAction { * Promise that is resolved once the action is complete. */ async dispatch(state, inputSource, tickDuration, options) { - const { assertInViewPort, context, toBrowserWindowCoordinates } = options; + const { assertInViewPort, context } = options; + + lazy.logger.trace( + `Dispatch ${this.constructor.name} ${inputSource.pointer.type} with id: ${this.id} x: ${this.x} y: ${this.y}` + ); - let moveCoordinates = await this.origin.getTargetCoordinates( + const target = await this.origin.getTargetCoordinates( inputSource, [this.x, this.y], options ); - await assertInViewPort(moveCoordinates, context); - - lazy.logger.trace( - `Dispatch ${this.constructor.name} ${inputSource.pointer.type} with id: ${this.id} ` + - `x: ${moveCoordinates[0]} y: ${moveCoordinates[1]} ` + - `async: ${actions.useAsyncMouseEvents}` - ); - - // Only convert coordinates if these are for a content process, and are not - // relative to an already initialized pointer source. - if ( - !(this.origin instanceof PointerOrigin && inputSource.initialized) && - context.isContent && - actions.useAsyncMouseEvents - ) { - moveCoordinates = await toBrowserWindowCoordinates( - moveCoordinates, - context - ); - } + await assertInViewPort(target, context); return moveOverTime( [[inputSource.x, inputSource.y]], - [moveCoordinates], + [target], this.duration ?? tickDuration, async _target => await this.performPointerMoveStep(state, inputSource, _target, options) @@ -1675,13 +1626,12 @@ class PointerMoveAction extends PointerAction { } const target = targets[0]; - if (target[0] == inputSource.x && target[1] == inputSource.y) { - return; - } - lazy.logger.trace( `PointerMoveAction.performPointerMoveStep ${JSON.stringify(target)}` ); + if (target[0] == inputSource.x && target[1] == inputSource.y) { + return; + } await inputSource.pointer.pointerMove( state, @@ -1692,7 +1642,8 @@ class PointerMoveAction extends PointerAction { options ); - inputSource.moveTo(target[0], target[1]); + inputSource.x = target[0]; + inputSource.y = target[1]; } /** @@ -2287,7 +2238,8 @@ class PointerMoveTouchActionGroup extends TouchActionGroup { const eventData = new MultiTouchEventData("touchmove"); for (const [inputSource, action, target] of perPointerData) { - inputSource.moveTo(target[0], target[1]); + inputSource.x = target[0]; + inputSource.y = target[1]; eventData.addPointerEventData(inputSource, action); eventData.update(state, inputSource); } diff --git a/remote/shared/webdriver/Event.sys.mjs b/remote/shared/webdriver/Event.sys.mjs @@ -59,40 +59,26 @@ event.MouseButton = { }; /** - * Synthesize a mouse event in `win` at a point. + * Synthesise a mouse event at a point. * - * If the type is specified in `event`, a mouse event of that type is + * If the type is specified in opts, an mouse event of that type is * fired. Otherwise, a mousedown followed by a mouseup is performed. * - * @param {number} left - Value for the X offset in CSS pixels. - * @param {number} top - Value for the Y offset in CSS pixels. - * @param {module:EventUtils~MouseEventData} event - Details of the mouse event - * to dispatch. - * @param {DOMWindow} win - DOM window used to dispatch the event. + * @param {number} left + * Offset from viewport left, in CSS pixels + * @param {number} top + * Offset from viewport top, in CSS pixels + * @param {object} opts + * Object which may contain the properties "shiftKey", "ctrlKey", + * "altKey", "metaKey", "accessKey", "clickCount", "button", and + * "type". + * @param {Window} win + * Window object. * - * @returns {Promise<boolean>} Promise that resolves to a boolean, - * indicating whether the event had preventDefault() called on it. + * @returns {boolean} defaultPrevented */ -event.synthesizeMouseAtPoint = function (left, top, event, win) { - if (!event.asyncEnabled) { - return Promise.resolve( - _getEventUtils(win).synthesizeMouseAtPoint(left, top, event, win) - ); - } - - // A callback must be used when handling events with the `asyncEnabled` - // flag set to `true`, as these events are synthesized in the parent process. - // We need to wait for them to be fully dispatched to the content process - // before continuing. - return new Promise(resolve => { - const preventDefault = _getEventUtils(win).synthesizeMouseAtPoint( - left, - top, - event, - win, - () => resolve(preventDefault) - ); - }); +event.synthesizeMouseAtPoint = function (left, top, opts, win) { + return _getEventUtils(win).synthesizeMouseAtPoint(left, top, opts, win); }; /** diff --git a/remote/shared/webdriver/test/xpcshell/test_Actions.js b/remote/shared/webdriver/test/xpcshell/test_Actions.js @@ -314,7 +314,8 @@ add_task(async function test_computePointerDestinationViewport() { const actionItem = chain[0][0]; const inputSource = state.getInputSource(actionItem.id); // these values should not affect the outcome - inputSource.moveTo(99, 10); + inputSource.x = "99"; + inputSource.y = "10"; const target = await actionItem.origin.getTargetCoordinates( inputSource, [actionItem.x, actionItem.y], @@ -342,7 +343,8 @@ add_task(async function test_computePointerDestinationPointer() { ); const actionItem = chain[0][0]; const inputSource = state.getInputSource(actionItem.id); - inputSource.moveTo(10, 99); + inputSource.x = 10; + inputSource.y = 99; const target = await actionItem.origin.getTargetCoordinates( inputSource, [actionItem.x, actionItem.y], diff --git a/remote/webdriver-bidi/modules/root/input.sys.mjs b/remote/webdriver-bidi/modules/root/input.sys.mjs @@ -9,9 +9,7 @@ const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { actions: "chrome://remote/content/shared/webdriver/Actions.sys.mjs", assert: "chrome://remote/content/shared/webdriver/Assert.sys.mjs", - error: "chrome://remote/content/shared/webdriver/Errors.sys.mjs", event: "chrome://remote/content/shared/webdriver/Event.sys.mjs", - NavigableManager: "chrome://remote/content/shared/NavigableManager.sys.mjs", pprint: "chrome://remote/content/shared/Format.sys.mjs", }); @@ -78,31 +76,17 @@ class InputModule extends RootBiDiModule { * Promise that resolves once the event is dispatched. */ async #dispatchEvent(eventName, context, details) { - details.eventData.asyncEnabled = - (eventName === "synthesizeWheelAtPoint" && - lazy.actions.useAsyncWheelEvents) || - (eventName == "synthesizeMouseAtPoint" && - lazy.actions.useAsyncMouseEvents); + if ( + eventName === "synthesizeWheelAtPoint" && + lazy.actions.useAsyncWheelEvents + ) { + details.eventData.asyncEnabled = true; + } // TODO: Call the _dispatchEvent method of the windowglobal module once // chrome support was added for the message handler. if (details.eventData.asyncEnabled) { - if (!context || context.isDiscarded) { - const id = lazy.NavigableManager.getIdForBrowsingContext(context); - throw new lazy.error.NoSuchFrameError( - `Browsing Context with id ${id} not found` - ); - } - switch (eventName) { - case "synthesizeMouseAtPoint": - await lazy.event.synthesizeMouseAtPoint( - details.x, - details.y, - details.eventData, - context.topChromeWindow - ); - break; case "synthesizeWheelAtPoint": await lazy.event.synthesizeWheelAtPoint( details.x, @@ -129,16 +113,12 @@ class InputModule extends RootBiDiModule { * * @param {BrowsingContext} context * The browsing context to forward the command to. + * + * @returns {Promise} + * Promise that resolves when the finalization is done. */ - async #finalizeAction(context) { - try { - await this._forwardToWindowGlobal("_finalizeAction", context.id); - } catch (e) { - // Ignore the error if the underlying browsing context is already gone. - if (e.name !== "DiscardedBrowsingContextError") { - throw e; - } - } + #finalizeAction(context) { + return this._forwardToWindowGlobal("_finalizeAction", context.id); } /** diff --git a/remote/webdriver-bidi/modules/windowglobal/input.sys.mjs b/remote/webdriver-bidi/modules/windowglobal/input.sys.mjs @@ -69,7 +69,7 @@ class InputModule extends WindowGlobalBiDiModule { lazy.event.sendKeyUp(details.eventData, this.messageHandler.window); break; case "synthesizeMouseAtPoint": - await lazy.event.synthesizeMouseAtPoint( + lazy.event.synthesizeMouseAtPoint( details.x, details.y, details.eventData, diff --git a/taskcluster/test_configs/variants.yml b/taskcluster/test_configs/variants.yml @@ -523,7 +523,6 @@ async-event-dispatching: merge: mozharness: extra-options: - - "--setpref=remote.events.async.mouse.enabled=true" - "--setpref=remote.events.async.wheel.enabled=true" vertical-tabs: diff --git a/testing/web-platform/meta/webdriver/tests/bidi/input/perform_actions/pointer_mouse.py.ini b/testing/web-platform/meta/webdriver/tests/bidi/input/perform_actions/pointer_mouse.py.ini @@ -1,4 +1,24 @@ [pointer_mouse.py] - [test_move_to_position_in_viewport[default value\]] - expected: - if not remoteAsyncEvents: FAIL # Cannot be fixed when dispatching the event in the content process + [test_drag_and_drop[10-15-0\]] + disabled: + if os == "android": bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1762119 + + [test_drag_and_drop[10-15-300\]] + disabled: + if os == "android": bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1762119 + + [test_drag_and_drop[10-15-800\]] + disabled: + if os == "android": bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1762119 + + [test_drag_and_drop[10--15-0\]] + disabled: + if os == "android": bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1762119 + + [test_drag_and_drop[10--15-300\]] + disabled: + if os == "android": bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1762119 + + [test_drag_and_drop[10--15-800\]] + disabled: + if os == "android": bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1762119 diff --git a/testing/web-platform/meta/webdriver/tests/classic/perform_actions/pointer_dblclick.py.ini b/testing/web-platform/meta/webdriver/tests/classic/perform_actions/pointer_dblclick.py.ini @@ -1,12 +0,0 @@ -[pointer_dblclick.py] - [test_dblclick_at_coordinates[0\]] - bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1999380 - expected: - if os == "android": FAIL - PASS - - [test_dblclick_at_coordinates[200\]] - bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1999380 - expected: - if os == "android": FAIL - PASS diff --git a/testing/web-platform/meta/webdriver/tests/classic/perform_actions/pointer_mouse.py.ini b/testing/web-platform/meta/webdriver/tests/classic/perform_actions/pointer_mouse.py.ini @@ -1,12 +0,0 @@ -[pointer_mouse.py] - [test_move_to_position_in_viewport[default value\]] - expected: - if not remoteAsyncEvents: FAIL # Cannot be fixed when dispatching the event in the content process - - [test_down_closes_browsing_context[without up\]] - bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1998260 - expected: - if remoteAsyncEvents: PASS - if (os == "android") and not debug: [PASS, FAIL] - if (os == "linux"): [PASS, FAIL] - FAIL diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox.py @@ -240,8 +240,7 @@ def run_info_extras(logger, default_prefs=None, **kwargs): "swgl": bool_pref("gfx.webrender.software"), "useDrawSnapshot": bool_pref("reftest.use-draw-snapshot"), "privateBrowsing": bool_pref("browser.privatebrowsing.autostart"), - "remoteAsyncEvents": (bool_pref("remote.events.async.mouse.enabled") or - bool_pref("remote.events.async.wheel.enabled")), + "remoteAsyncEvents": bool_pref("remote.events.async.wheel.enabled"), "incOriginInit": os.environ.get("MOZ_ENABLE_INC_ORIGIN_INIT") == "1", "navigationApi": bool_pref("dom.navigation.webidl.enabled"), } diff --git a/testing/web-platform/tests/webdriver/tests/bidi/input/perform_actions/pointer_mouse.py b/testing/web-platform/tests/webdriver/tests/bidi/input/perform_actions/pointer_mouse.py @@ -20,27 +20,20 @@ pytestmark = pytest.mark.asyncio CONTEXT_LOAD_EVENT = "browsingContext.load" -@pytest.mark.parametrize("mouse_up", [False, True], ids=["without up", "with up"]) -async def test_down_closes_browsing_context( - bidi_session, - configuration, - get_element, - top_context, - inline, - subscribe_events, - wait_for_event, - mouse_up +async def test_pointer_down_closes_browsing_context( + bidi_session, configuration, get_element, new_tab, inline, subscribe_events, + wait_for_event ): - url = inline("""<input onmousedown="window.close()">close</input>""") + url = inline("""<input onpointerdown="window.close()">close</input>""") - # Opening a new context via `window.open` is required - # for the script to be able to close it. + # Opening a new context via `window.open` is required for script to be able + # to close it. await subscribe_events(events=[CONTEXT_LOAD_EVENT]) on_load = wait_for_event(CONTEXT_LOAD_EVENT) await bidi_session.script.evaluate( expression=f"window.open('{url}')", - target=ContextTarget(top_context["context"]), + target=ContextTarget(new_tab["context"]), await_promise=True ) # Wait for the new context to be created and get it. @@ -49,35 +42,20 @@ async def test_down_closes_browsing_context( element = await get_element("input", context=new_context) origin = get_element_origin(element) - if mouse_up: - actions = Actions() - ( - actions.add_pointer() - .pointer_move(0, 0, origin=origin) - .pointer_down(button=0) - .pause(250 * configuration["timeout_multiplier"]) - .pointer_up(button=0) - ) - - with pytest.raises(NoSuchFrameException): - await bidi_session.input.perform_actions( - actions=actions, context=new_context["context"] - ) - else: - actions = Actions() - ( - actions.add_pointer() - .pointer_move(0, 0, origin=origin) - .pointer_down(button=0) - ) + actions = Actions() + ( + actions.add_pointer() + .pointer_move(0, 0, origin=origin) + .pointer_down(button=0) + .pause(250 * configuration["timeout_multiplier"]) + .pointer_up(button=0) + ) + with pytest.raises(NoSuchFrameException): await bidi_session.input.perform_actions( actions=actions, context=new_context["context"] ) - with pytest.raises(NoSuchFrameException): - await bidi_session.browsing_context.get_tree(root=new_context["context"], max_depth=0) - async def test_click_at_coordinates(bidi_session, top_context, load_static_test_page): await load_static_test_page(page="test_actions.html") @@ -383,13 +361,13 @@ async def test_click_navigation( assert event["url"] == destination -@pytest.mark.parametrize("x, y", [ - (0, 0), - (1, 0), - (0, 1), +@pytest.mark.parametrize("x, y, event_count", [ + (0, 0, 0), + (1, 0, 1), + (0, 1, 1), ], ids=["default value", "x", "y"]) async def test_move_to_position_in_viewport( - bidi_session, load_static_test_page, top_context, x, y + bidi_session, load_static_test_page, top_context, x, y, event_count ): await load_static_test_page(page="test_actions.html") @@ -401,7 +379,7 @@ async def test_move_to_position_in_viewport( ) events = await get_events(bidi_session, top_context["context"]) - assert len(events) == 1 + assert len(events) == event_count # Move again to check that no further mouse move event is emitted. actions = Actions() @@ -412,7 +390,7 @@ async def test_move_to_position_in_viewport( ) events = await get_events(bidi_session, top_context["context"]) - assert len(events) == 1 + assert len(events) == event_count @pytest.mark.parametrize("origin", ["viewport", "pointer", "element"]) diff --git a/testing/web-platform/tests/webdriver/tests/bidi/input/perform_actions/pointer_mouse_modifier.py b/testing/web-platform/tests/webdriver/tests/bidi/input/perform_actions/pointer_mouse_modifier.py @@ -126,8 +126,7 @@ async def test_control_click_release( ] all_events = await get_events(bidi_session, top_context["context"]) events = [filter_dict(e, expected[0]) for e in all_events] - for expected_event in expected: - assert expected_event in events + assert events == expected async def test_many_modifiers_click( diff --git a/testing/web-platform/tests/webdriver/tests/classic/perform_actions/pointer_contextmenu.py b/testing/web-platform/tests/webdriver/tests/classic/perform_actions/pointer_contextmenu.py @@ -75,5 +75,4 @@ def test_release_control_click(session, key_reporter, key_chain, mouse_chain): {"type": "keyup"}, ] events = [filter_dict(e, expected[0]) for e in get_events(session)] - for expected_event in expected: - assert expected_event in events + assert events == expected diff --git a/testing/web-platform/tests/webdriver/tests/classic/perform_actions/pointer_mouse.py b/testing/web-platform/tests/webdriver/tests/classic/perform_actions/pointer_mouse.py @@ -33,33 +33,20 @@ def test_no_browsing_context(session, closed_frame, mouse_chain): mouse_chain.click().perform() -@pytest.mark.parametrize("mouse_up", [False, True], ids=["without up", "with up"]) -def test_down_closes_browsing_context( - session, configuration, inline, mouse_chain, mouse_up +def test_pointer_down_closes_browsing_context( + session, configuration, http_new_tab, inline, mouse_chain ): - # Opening a new tab/window via `window.open` is required - # for the script to be able to close it. - new_window = session.execute_script(f"return window.open()") - session.window_handle = new_window.id - session.url = inline("""<input onmousedown="window.close()">close</input>""") - + session.url = inline( + """<input onpointerdown="window.close()">close</input>""") origin = session.find.css("input", all=False) - if mouse_up: - with pytest.raises(NoSuchWindowException): - mouse_chain.pointer_move(0, 0, origin=origin) \ - .pointer_down(button=0) \ - .pause(100 * configuration["timeout_multiplier"]) \ - .pointer_up(button=0) \ - .perform() - else: + with pytest.raises(NoSuchWindowException): mouse_chain.pointer_move(0, 0, origin=origin) \ .pointer_down(button=0) \ + .pause(100 * configuration["timeout_multiplier"]) \ + .pointer_up(button=0) \ .perform() - with pytest.raises(NoSuchWindowException): - session.url - @pytest.mark.parametrize("as_frame", [False, True], ids=["top_context", "child_context"]) def test_stale_element_reference(session, stale_element, mouse_chain, as_frame): @@ -87,17 +74,13 @@ def test_click_at_coordinates(session, test_actions_page, mouse_chain): .pointer_move(div_point["x"], div_point["y"], duration=1000) \ .click() \ .perform() - events = get_events(session) assert len(events) == 4 - assert_move_to_coordinates(div_point, "outer", events) - for e in events: if e["type"] != "mousedown": assert e["buttons"] == 0 assert e["button"] == 0 - expected = [ {"type": "mousedown", "buttons": 1}, {"type": "mouseup", "buttons": 0}, @@ -170,10 +153,8 @@ def test_click_element_center(session, test_actions_page, mouse_chain): outer = session.find.css("#outer", all=False) center = get_inview_center(outer.rect, get_viewport_rect(session)) mouse_chain.click(element=outer).perform() - events = get_events(session) assert len(events) == 4 - event_types = [e["type"] for e in events] assert ["mousemove", "mousedown", "mouseup", "click"] == event_types for e in events: @@ -240,27 +221,29 @@ def test_click_navigation(session, url, inline): wait.until(assert_page_loaded) -@pytest.mark.parametrize("x, y", [ - (0, 0), - (1, 0), - (0, 1), +@pytest.mark.parametrize("x, y, event_count", [ + (0, 0, 0), + (1, 0, 1), + (0, 1, 1), ], ids=["default value", "x", "y"]) -def test_move_to_position_in_viewport(session, test_actions_page, mouse_chain, x, y): +def test_move_to_position_in_viewport( + session, test_actions_page, mouse_chain, x, y, event_count +): mouse_chain.pointer_move(x, y).perform() events = get_events(session) - assert len(events) == 1 + assert len(events) == event_count # Move again to check that no further mouse move event is emitted. mouse_chain.pointer_move(x, y).perform() events = get_events(session) - assert len(events) == 1 + assert len(events) == event_count def test_move_to_fractional_position(session, inline, mouse_chain): session.url = inline(""" <script> var allEvents = { events: [] }; - window.addEventListener("mousemove", ev => { + window.addEventListener("pointermove", ev => { allEvents.events.push({ "type": event.type, "pageX": event.pageX, @@ -284,6 +267,7 @@ def test_move_to_fractional_position(session, inline, mouse_chain): # For now we are allowing any of floor, ceil, or precise values, because # it's unclear what the actual spec requirements really are + assert events[0]["type"] == "pointermove" assert events[0]["pageX"] == pytest.approx(target_point["x"], abs=1.0) assert events[0]["pageY"] == pytest.approx(target_point["y"], abs=1.0) diff --git a/testing/web-platform/tests/webdriver/tests/classic/perform_actions/pointer_mouse_drag.py b/testing/web-platform/tests/webdriver/tests/classic/perform_actions/pointer_mouse_drag.py @@ -33,11 +33,11 @@ def test_drag_and_drop(session, .pointer_move(80, 50, duration=100, origin="pointer") \ .perform() - # `mouseup` that ends the drag is at the expected destination - events = get_events(session) - assert events[1]["type"] == "mouseup" - assert events[1]["pageX"] == pytest.approx(initial_center["x"] + dx, abs=1.0) - assert events[1]["pageY"] == pytest.approx(initial_center["y"] + dy, abs=1.0) + # mouseup that ends the drag is at the expected destination + e = get_events(session)[1] + assert e["type"] == "mouseup" + assert e["pageX"] == pytest.approx(initial_center["x"] + dx, abs=1.0) + assert e["pageY"] == pytest.approx(initial_center["y"] + dy, abs=1.0) def check_final_position(_): assert drag_target.rect["x"] == pytest.approx( @@ -70,12 +70,12 @@ def test_drag_and_drop_with_draggable_element(session_new_window, .pointer_move(80, 50, duration=100, origin="pointer") \ .perform() # mouseup that ends the drag is at the expected destination - events = get_events(session_new_window) - assert len(events) >= 5 - assert events[1]["type"] == "dragstart", "Events captured were {}".format(events) - assert events[2]["type"] == "dragover", "Events captured were {}".format(events) + e = get_events(new_session) + assert len(e) >= 5 + assert e[1]["type"] == "dragstart", "Events captured were {}".format(e) + assert e[2]["type"] == "dragover", "Events captured were {}".format(e) drag_events_captured = [ - ev["type"] for ev in events if ev["type"].startswith("drag") or ev["type"].startswith("drop") + ev["type"] for ev in e if ev["type"].startswith("drag") or ev["type"].startswith("drop") ] assert "dragend" in drag_events_captured assert "dragenter" in drag_events_captured diff --git a/testing/web-platform/tests/webdriver/tests/classic/perform_actions/pointer_origin.py b/testing/web-platform/tests/webdriver/tests/classic/perform_actions/pointer_origin.py @@ -37,11 +37,9 @@ def test_pointer_inside(session, mouse_chain, get_actions_origin_page): session.url = get_actions_origin_page( "width: 100px; height: 50px; background: green;" ) - (mouse_chain - .pointer_move(start_point["x"], start_point["y"]) - .pointer_move(offset["x"], offset["y"], origin="pointer") - .perform() - ) + mouse_chain.pointer_move(start_point["x"], start_point["y"]).pointer_move( + offset["x"], offset["y"], origin="pointer" + ).perform() click_coords = session.execute_script("return window.coords;") assert click_coords["x"] == pytest.approx(start_point["x"] + offset["x"], abs=1.0) diff --git a/testing/web-platform/tests/webdriver/tests/support/fixtures.py b/testing/web-platform/tests/webdriver/tests/support/fixtures.py @@ -330,7 +330,7 @@ def iframe(inline): @pytest.fixture def get_actions_origin_page(inline): - """Create a test page for action origin tests, recording mouse coordinates + """Create a test pagefor action origin tests, recording mouse coordinates automatically on window.coords.""" def get_actions_origin_page(inner_style, outer_style=""):