Support HTML5 drag-and-drop and drag modifier keys - #315
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds HTML5-native drag-and-drop support (including DataTransfer + dragstart/dragover/drop/dragend sequencing) and held modifier-key support to Cuprite’s Node#drag_to, enabling previously force-skipped Capybara shared drag specs to run.
Changes:
- Unskips the previously skipped Capybara
#drag_tospecs inspec/spec_helper.rb. - Extends
Node#drag_toto acceptdrop_modifiers(with aliases) and routes through an updated browserdragcommand. - Adds HTML5 drag emulation via injected JS (
lib/capybara/cuprite/javascripts/drag.js) and runtime detection helpers injavascripts/index.js, with browser-side routing between legacy mouse drag vs HTML5 emulation.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| spec/spec_helper.rb | Removes forced skips so Capybara drag shared specs execute again. |
| lib/capybara/cuprite/node.rb | Adds drop_modifiers alias normalization and passes drag options to the browser command. |
| lib/capybara/cuprite/browser.rb | Implements legacy-vs-HTML5 routing, uses Ferrum mouse modifier bitfield on legacy path, and injects HTML5 drag emulation JS. |
| lib/capybara/cuprite/javascripts/index.js | Adds _cuprite helpers to track mousedown preventDefault and decide legacy vs HTML5 path. |
| lib/capybara/cuprite/javascripts/drag.js | New HTML5 drag event emulation script (ported approach) used by the HTML5 drag path. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
`Node#drag_to` drove only real mouse events, which never fire the HTML5 drag sequence (dragstart/dragover/drop/dragend + DataTransfer), so suites exercising HTML5 drag-and-drop had to fall back to Selenium. Route drag_to between two paths after the initial mouse-down: a legacy path (real Ferrum mouse events, now applying held modifier keys via the public mouse modifier bitfield) and an HTML5 path (a JS emulation dispatching the drag events with a shared DataTransfer). Detection mirrors Capybara: a draggable source or ancestor takes the HTML5 path, otherwise legacy. The emulation is ported from Capybara's Selenium Html5Drag extension and lives in javascripts/drag.js. Un-skips the 15 Capybara shared drag specs (12 HTML5 + 3 mouse modifier). Uses only public Ferrum API. Element#drop (files/strings) remains out of scope. Closes rubycdp#314
ce9e678 to
dbe3eb1
Compare
|
@route this is one way of supporting HTML 5 drag-and-drop - basically porting Selenium's support to Cuprite. The advantage is that it should behave the same as Selenium, including any behaviour quirks. A potentially more robust solution would be to use CDP, e.g. In any case, I would be keen to get your thoughts! Lack of Drag and Drop support is a big reason we have to switch back to Selenium in our large spec suite. |
|
I guess let's stick to this at least for now, we can improve later on! |
What
Adds HTML5 native drag-and-drop and held modifier-key support to
Node#drag_to, un-skipping the 15 Capybara shared drag specs that were previously force-skipped inspec/spec_helper.rb.Why
Node#drag_todrove only real mouse events (move/down/move/up). Those never fire the HTML5 drag sequence (dragstart/dragover/drop/dragend+ aDataTransfer), so any suite exercising HTML5 drag-and-drop had to fall back to Selenium.Downstream motivation: opf/openproject#23218 currently switches to Selenium for its HTML5 drag-and-drop feature specs.
How
drag_tonow routes between two paths after the initial mouse-down:drop_modifiersvia Ferrum's public mouse modifier bitfield (keyboard.modifiers+mouse.up(modifiers:)).DataTransfer, ported near-verbatim from Capybara's SeleniumHtml5Dragextension (HTML5_DRAG_DROP_SCRIPT). It lives inlib/capybara/cuprite/javascripts/drag.jsand carries a header noting its provenance; it is kept close to the source (including a few inherited quirks) to ease future syncs.Detection mirrors Capybara's
LEGACY_DRAG_CHECK: the HTML5 path is taken when the source (or an ancestor) isdraggableand the initialmousedownwas notdefaultPrevented; otherwise the legacy path runs.Notes
command()calls or reach-ins into Ferrum internals (per the direction in Cuprite 1.0 #307).Element#drop(files/strings/pathname) remains out of scope and is tracked separately.Testing
#drag_tospecs (12 HTML5 + 3 mouse modifier) now pass.main(the two#has_fieldvalidation-message failures are pre-existing and unrelated — Chrome locale wording).bundle exec rubocopclean.Closes #314. Part of #307.
🤖 Authored with agent assistance.