diff --git a/CHANGELOG.md b/CHANGELOG.md index ae0dc35..7f6a470 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ ### Changed ### Fixed +- `Node#drag_to` with `drop_modifiers:` holds the modifiers while moving to the target and sends keydown and keyup for + them, like Selenium does. They used to be set only on mouseup [rubycdp/ferrum#581] ### Removed diff --git a/Gemfile b/Gemfile index 73412cd..1fb65c0 100644 --- a/Gemfile +++ b/Gemfile @@ -4,6 +4,7 @@ source "https://rubygems.org" gem "byebug", "~> 11.1", platforms: %i[mri windows] gem "chunky_png", "~> 1.4" +gem "ferrum", github: "rubycdp/ferrum", branch: "fix/keyboard-modifier-down-up" gem "image_size", "~> 3.0" gem "launchy", "~> 2.5" gem "logger" diff --git a/lib/capybara/cuprite/browser.rb b/lib/capybara/cuprite/browser.rb index b3b82ee..401f0e8 100644 --- a/lib/capybara/cuprite/browser.rb +++ b/lib/capybara/cuprite/browser.rb @@ -171,13 +171,10 @@ def drag(node, other, drop_modifiers, options = {}) if html5 drag_html5(node, other, drop_modifiers, delay, drop_offset) else - modifiers = keyboard.modifiers(drop_modifiers) - other.scroll_into_view if scroll x2, y2 = other.find_position(**drop_offset.to_h) - mouse.move(x: x2, y: y2, steps: steps) - mouse.up(modifiers: modifiers) + keyboard.hold(*drop_modifiers) { mouse.move(x: x2, y: y2, steps: steps).up } end end diff --git a/spec/features/session_spec.rb b/spec/features/session_spec.rb index 224d013..7d57d87 100644 --- a/spec/features/session_spec.rb +++ b/spec/features/session_spec.rb @@ -851,6 +851,25 @@ expect(droppable).to have_content("Dropped") end + it "holds drop modifiers while moving to the target" do + @session.execute_script(<<~JS) + window.events = []; + ["keydown", "keyup", "mousedown", "mousemove", "mouseup"].forEach(type => + document.addEventListener(type, e => events.push(`${type}:${e.shiftKey}:${e.altKey}`))); + JS + draggable = @session.find(:css, "#drag_to #draggable") + droppable = @session.find(:css, "#drag_to #droppable") + + draggable.drag_to(droppable, drop_modifiers: %i[shift alt]) + + events = @session.evaluate_script("window.events").chunk_while { |a, b| a == b }.map(&:first) + expect(events).to eq( + %w[mousemove:false:false mousedown:false:false keydown:true:false keydown:true:true + mousemove:true:true mouseup:true:true keyup:true:false keyup:false:false] + ) + expect(droppable).to have_content("Dropped") + end + it "supports drag_by on native element" do draggable = @session.find(:css, "#drag_by .draggable")