Skip to content

Support HTML5 drag-and-drop and drag modifier keys#315

Open
myabc wants to merge 1 commit into
rubycdp:mainfrom
myabc:feature/drag-and-drop
Open

Support HTML5 drag-and-drop and drag modifier keys#315
myabc wants to merge 1 commit into
rubycdp:mainfrom
myabc:feature/drag-and-drop

Conversation

@myabc

@myabc myabc commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

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 in spec/spec_helper.rb.

Why

Node#drag_to drove only real mouse events (move/down/move/up). Those never fire the HTML5 drag sequence (dragstart/dragover/drop/dragend + a DataTransfer), 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_to now routes between two paths after the initial mouse-down:

  • Legacy path — the existing real-mouse drag, now applying held drop_modifiers via Ferrum's public mouse modifier bitfield (keyboard.modifiers + mouse.up(modifiers:)).
  • HTML5 path — a JS emulation that dispatches the drag events with a shared DataTransfer, ported near-verbatim from Capybara's Selenium Html5Drag extension (HTML5_DRAG_DROP_SCRIPT). It lives in lib/capybara/cuprite/javascripts/drag.js and 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) is draggable and the initial mousedown was not defaultPrevented; otherwise the legacy path runs.

Notes

  • Uses only public Ferrum API — no raw CDP 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

  • The 15 previously-skipped #drag_to specs (12 HTML5 + 3 mouse modifier) now pass.
  • Full suite: no new failures versus main (the two #has_field validation-message failures are pre-existing and unrelated — Chrome locale wording).
  • bundle exec rubocop clean.

Closes #314. Part of #307.

🤖 Authored with agent assistance.

Copilot AI review requested due to automatic review settings July 9, 2026 15:47

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_to specs in spec/spec_helper.rb.
  • Extends Node#drag_to to accept drop_modifiers (with aliases) and routes through an updated browser drag command.
  • Adds HTML5 drag emulation via injected JS (lib/capybara/cuprite/javascripts/drag.js) and runtime detection helpers in javascripts/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.

Comment thread lib/capybara/cuprite/javascripts/drag.js
Comment thread lib/capybara/cuprite/javascripts/drag.js
Comment thread lib/capybara/cuprite/javascripts/drag.js
Comment thread lib/capybara/cuprite/javascripts/drag.js
Comment thread lib/capybara/cuprite/javascripts/index.js
Comment thread lib/capybara/cuprite/javascripts/index.js
`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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support Drag and Drop actions

2 participants