From cb70a911c7181a459f38fa27583a652bb038ebc0 Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Fri, 10 Jul 2026 19:06:51 +0200 Subject: [PATCH] webapi: add WebDriver.click for trusted testdriver clicks Fixes 1 failing test in WPT /dom/events/Event-dispatch-redispatch.html: "Redispatching mouseup event whose default action dispatches a click event". The WPT testdriver-vendor shim implemented test_driver.click() with HTMLElement.click(), which dispatches a single untrusted click event and no press/release, so the test saw no trusted mouseup at all and an untrusted click. window.webdriver (the -Dwpt_extensions WebAPI) now exposes click(element): a full trusted primary-button sequence (pointerdown, mousedown, pointerup, mouseup, click), dispatched synchronously so the events are observable when the testdriver promise resolves. The shim routes test_driver.click through it, like action_sequence already routes through webdriver.actionSequence. Note this test (like everything testdriver-based) needs the browser built with -Dwpt_extensions=true, otherwise window.webdriver is undefined. Coverage: /dom/events/Event-dispatch-redispatch.html 3/4 -> 4/4 (with a wpt_extensions build). Co-Authored-By: Claude Fable 5 --- src/browser/webapi/WebDriver.zig | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/browser/webapi/WebDriver.zig b/src/browser/webapi/WebDriver.zig index c91d268f5..643cd6d98 100644 --- a/src/browser/webapi/WebDriver.zig +++ b/src/browser/webapi/WebDriver.zig @@ -49,6 +49,20 @@ pub fn getComputedLabel(_: *const WebDriver, element: *Element, frame: *Frame) ! return (try axnode.getName(frame, frame.call_arena)) orelse ""; } +// Implements testdriver's `click`: a full trusted primary-button click +// sequence on the element, as a real user click would produce. Unlike +// HTMLElement.click() (a lone untrusted click event), the events are trusted +// and preceded by the pointer/mouse press and release. Dispatched +// synchronously so the events are observable when the testdriver promise +// resolves. +pub fn click(_: *const WebDriver, element: *Element, frame: *Frame) !void { + dispatchPointer(element, "pointerdown", 0, 1, frame); + dispatchMouse(element, "mousedown", 0, 1, frame); + dispatchPointer(element, "pointerup", 0, 0, frame); + dispatchMouse(element, "mouseup", 0, 0, frame); + dispatchMouse(element, "click", 0, 0, frame); +} + // Implements testdriver's `action_sequence` (the WebDriver "Perform Actions" // command) for the renderless browser. We can't do real hit-testing, so we only // support the subset that targets a concrete element via `origin`. Each input @@ -333,4 +347,5 @@ pub const JsApi = struct { pub const deleteAllCookies = bridge.function(WebDriver.deleteAllCookies, .{}); pub const getComputedLabel = bridge.function(WebDriver.getComputedLabel, .{}); pub const actionSequence = bridge.function(WebDriver.actionSequence, .{}); + pub const click = bridge.function(WebDriver.click, .{}); };