Implement click delay

This commit is contained in:
Thomas Walpole 2020-03-28 16:40:47 -07:00
parent 971eea9b23
commit a307120d3d
6 changed files with 68 additions and 7 deletions

View File

@ -1,3 +1,10 @@
# Version 3.32.0
Relesae date: unreleased
### Added
* Support `delay` setting on click and right_click with Selenium
# Version 3.31.1
Release date: unreleased

View File

@ -165,6 +165,7 @@ module Capybara
# offset will be from the element center, otherwise it will be from the top left corner of the element
# @option options [Integer] y Y coordinate to offset the click location. If {Capybara.configure w3c_click_offset} is `true` the
# offset will be from the element center, otherwise it will be from the top left corner of the element
# @option options [Float] delay Delay between the mouse down and mouse up events in seconds (0)
# @return [Capybara::Node::Element] The element
def click(*keys, **options)
perform_click_action(keys, **options) do |k, opts|
@ -178,6 +179,7 @@ module Capybara
#
# @macro action_waiting_behavior
# @macro click_modifiers
# @option options [Float] delay Delay between the mouse down and mouse up events in seconds (0)
# @return [Capybara::Node::Element] The element
def right_click(*keys, **options)
perform_click_action(keys, **options) do |k, opts|

View File

@ -104,7 +104,14 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
click_options = ClickOptions.new(keys, options)
return native.click if click_options.empty?
click_with_options(click_options)
perform_with_options(click_options) do |action|
target = click_options.coords? ? nil : native
if click_options.delay.zero?
action.click(target)
else
action.click_and_hold(target).pause(action.pointer_inputs.first, click_options.delay).release
end
end
rescue StandardError => e
if e.is_a?(::Selenium::WebDriver::Error::ElementClickInterceptedError) ||
e.message.match?(/Other element would receive the click/)
@ -116,14 +123,24 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
def right_click(keys = [], **options)
click_options = ClickOptions.new(keys, options)
click_with_options(click_options) do |action|
click_options.coords? ? action.context_click : action.context_click(native)
perform_with_options(click_options) do |action|
target = click_options.coords? ? nil : native
if click_options.delay.zero?
action.context_click(target)
else
action.move_to(target) if target
action.pointer_down(:right)
.pause(action.pointer_inputs.first, click_options.delay)
.pointer_up(:right)
end
end
end
def double_click(keys = [], **options)
click_options = ClickOptions.new(keys, options)
click_with_options(click_options) do |action|
raise ArgumentError, "double_click doesn't support a delay option" unless click_options.delay.zero?
perform_with_options(click_options) do |action|
click_options.coords? ? action.double_click : action.double_click(native)
end
end
@ -264,7 +281,9 @@ private
end
end
def click_with_options(click_options)
def perform_with_options(click_options, &block)
raise ArgumentError, 'A block must be provided' unless block
scroll_if_needed do
action_with_modifiers(click_options) do |action|
if block_given?
@ -550,7 +569,11 @@ private
end
def empty?
keys.empty? && !coords?
keys.empty? && !coords? && delay.zero?
end
def delay
options[:delay] || 0
end
end
private_constant :ClickOptions

View File

@ -85,7 +85,7 @@ private
(driver.options[:native_displayed] != false) && !ENV['DISABLE_CAPYBARA_SELENIUM_OPTIMIZATIONS']
end
def click_with_options(click_options)
def perform_with_options(click_options)
# Firefox/marionette has an issue clicking with offset near viewport edge
# scroll element to middle just in case
scroll_to_center if click_options.coords?

View File

@ -153,6 +153,7 @@ $(function() {
});
$('#click-test').on({
click: function(e) {
window.click_delay = ((new Date().getTime()) - window.mouse_down_time)/1000.0;
var desc = "";
if (e.altKey) desc += 'alt ';
if (e.ctrlKey) desc += 'control ';
@ -179,6 +180,16 @@ $(function() {
if (e.shiftKey) desc += 'shift ';
var pos = this.getBoundingClientRect();
$(this).after('<a id="has-been-right-clicked" href="#">Has been ' + desc + 'right clicked at ' + (e.clientX - pos.left) + ',' + (e.clientY - pos.top) + '</a>');
},
mousedown: function(e) {
window.click_delay = undefined;
window.right_click_delay = undefined;
window.mouse_down_time = new Date().getTime();
},
mouseup: function(e) {
if (e.button == 2){
window.right_click_delay = ((new Date().getTime()) - window.mouse_down_time)/1000.0;
}
}
});
$('#open-alert').click(function() {

View File

@ -856,6 +856,15 @@ Capybara::SpecHelper.spec 'node' do
end
end
end
context 'delay', requires: [:js] do
it 'should delay the mouse up' do
@session.visit('with_js')
@session.find(:css, '#click-test').click(delay: 2)
delay = @session.evaluate_script('window.click_delay')
expect(delay).to be >= 2
end
end
end
describe '#double_click', requires: [:js] do
@ -1028,6 +1037,15 @@ Capybara::SpecHelper.spec 'node' do
end
end
end
context 'delay', requires: [:js] do
it 'should delay the mouse up' do
@session.visit('with_js')
@session.find(:css, '#click-test').right_click(delay: 2)
delay = @session.evaluate_script('window.right_click_delay')
expect(delay).to be >= 2
end
end
end
describe '#send_keys', requires: [:send_keys] do