Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions lib/ferrum/mouse.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@
module Ferrum
class Mouse
CLICK_WAIT = ENV.fetch("FERRUM_CLICK_WAIT", 0.1).to_f
VALID_BUTTONS = %w[none left middle right back forward].freeze
BUTTON_MASKS = {
"none" => 0,
"left" => 1,
"right" => 2,
"middle" => 4,
"back" => 8,
"forward" => 16
}.freeze

def initialize(page)
@page = page
@x = @y = 0
@buttons = 0
end

#
Expand Down Expand Up @@ -130,7 +138,8 @@ def move(x:, y:, steps: 1)
slowmoable: true,
type: "mouseMoved",
x: new_x.to_i,
y: new_y.to_i)
y: new_y.to_i,
buttons: @buttons)
end

self
Expand All @@ -140,16 +149,26 @@ def move(x:, y:, steps: 1)

def mouse_event(type:, button: :left, count: 1, modifiers: nil, wait: 0)
button = validate_button(button)
options = { x: @x, y: @y, type: type, button: button, clickCount: count }
register_event_button(type, button)
options = { x: @x, y: @y, type: type, button: button, buttons: @buttons, clickCount: count }
options.merge!(modifiers: modifiers) if modifiers
@page.command("Input.dispatchMouseEvent", wait: wait, slowmoable: true, **options)
end

def validate_button(button)
button = button.to_s
raise "Invalid button: #{button}" unless VALID_BUTTONS.include?(button)
raise "Invalid button: #{button}" unless BUTTON_MASKS.key?(button)

button
end

def register_event_button(type, button)
case type
when "mousePressed"
@buttons |= BUTTON_MASKS[button]
when "mouseReleased"
@buttons &= ~BUTTON_MASKS[button]
end
end
end
end
49 changes: 41 additions & 8 deletions spec/mouse_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,16 @@
end

describe "#move" do
let(:tracking_code) do
<<~JS
it "splits into steps" do
browser.go_to("/ferrum/simple")
browser.mouse.move(x: 100, y: 100)
browser.evaluate_async(<<~JS, browser.timeout)
window.result = [];
document.addEventListener("mousemove", e => {
window.result.push([e.clientX, e.clientY]);
});
arguments[0]();
JS
end

it "splits into steps" do
browser.go_to("/ferrum/simple")
browser.mouse.move(x: 100, y: 100)
browser.evaluate_async(tracking_code, browser.timeout)

browser.mouse.move(x: 200, y: 300, steps: 5)

Expand All @@ -69,6 +65,43 @@
[200, 300]
])
end

it "sets buttons property" do
browser.go_to("/ferrum/simple")
browser.mouse.move(x: 100, y: 100)
browser.evaluate_async(<<~JS, browser.timeout)
window.result = [];
["move", "up", "down"].forEach(type =>
document.addEventListener(`mouse${type}`, e => {
window.result.push([type, e.clientX, e.clientY, e.buttons]);
})
);
arguments[0]();
JS

browser.mouse
.move(x: 101, y: 102)
.down(button: :left)
.move(x: 103, y: 104)
.down(button: :right)
.move(x: 105, y: 106)
.up(button: :left)
.move(x: 107, y: 108)
.up(button: :right)
.move(x: 109, y: 110)

expect(browser.evaluate("window.result")).to eq([
["move", 101, 102, 0], # none pressed
["down", 101, 102, 1], # left down
["move", 103, 104, 1], # left pressed
["down", 103, 104, 3], # right down, left pressed
["move", 105, 106, 3], # both pressed
["up", 105, 106, 2], # left up, right pressed
["move", 107, 108, 2], # right pressed
["up", 107, 108, 0], # right up
["move", 109, 110, 0] # none pressed
])
end
end

context "mouse support", skip: true do
Expand Down
Loading