Workaround Chrome issue with mouse button state when dragging
This commit is contained in:
parent
29e86bd9fc
commit
c053ff60de
|
@ -8,15 +8,23 @@ class Capybara::Selenium::Node
|
||||||
driver.execute_script MOUSEDOWN_TRACKER
|
driver.execute_script MOUSEDOWN_TRACKER
|
||||||
scroll_if_needed { browser_action.click_and_hold(native).perform }
|
scroll_if_needed { browser_action.click_and_hold(native).perform }
|
||||||
if driver.evaluate_script('window.capybara_mousedown_prevented || !arguments[0].draggable', self)
|
if driver.evaluate_script('window.capybara_mousedown_prevented || !arguments[0].draggable', self)
|
||||||
element.scroll_if_needed { browser_action.move_to(element.native).release.perform }
|
perform_regular_drag(element)
|
||||||
else
|
else
|
||||||
driver.evaluate_async_script HTML5_DRAG_DROP_SCRIPT, self, element, delay * 1000
|
perform_html5_drag(element, delay)
|
||||||
browser_action.release.perform
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def perform_regular_drag(element)
|
||||||
|
element.scroll_if_needed { browser_action.move_to(element.native).release.perform }
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform_html5_drag(element, delay)
|
||||||
|
driver.evaluate_async_script HTML5_DRAG_DROP_SCRIPT, self, element, delay * 1000
|
||||||
|
browser_action.release.perform
|
||||||
|
end
|
||||||
|
|
||||||
def html5_drop(*args)
|
def html5_drop(*args)
|
||||||
if args[0].is_a? String
|
if args[0].is_a? String
|
||||||
input = driver.evaluate_script ATTACH_FILE
|
input = driver.evaluate_script ATTACH_FILE
|
||||||
|
|
|
@ -188,6 +188,21 @@ protected
|
||||||
yield
|
yield
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def scroll_to_center
|
||||||
|
script = <<-'JS'
|
||||||
|
try {
|
||||||
|
arguments[0].scrollIntoView({behavior: 'instant', block: 'center', inline: 'center'});
|
||||||
|
} catch(e) {
|
||||||
|
arguments[0].scrollIntoView(true);
|
||||||
|
}
|
||||||
|
JS
|
||||||
|
begin
|
||||||
|
driver.execute_script(script, self)
|
||||||
|
rescue StandardError # rubocop:disable Lint/HandleExceptions
|
||||||
|
# Swallow error if scrollIntoView with options isn't supported
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def sibling_index(parent, node, selector)
|
def sibling_index(parent, node, selector)
|
||||||
|
@ -241,21 +256,6 @@ private
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def scroll_to_center
|
|
||||||
script = <<-'JS'
|
|
||||||
try {
|
|
||||||
arguments[0].scrollIntoView({behavior: 'instant', block: 'center', inline: 'center'});
|
|
||||||
} catch(e) {
|
|
||||||
arguments[0].scrollIntoView(true);
|
|
||||||
}
|
|
||||||
JS
|
|
||||||
begin
|
|
||||||
driver.execute_script(script, self)
|
|
||||||
rescue StandardError # rubocop:disable Lint/HandleExceptions
|
|
||||||
# Swallow error if scrollIntoView with options isn't supported
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_date(value) # rubocop:disable Naming/AccessorMethodName
|
def set_date(value) # rubocop:disable Naming/AccessorMethodName
|
||||||
value = SettableValue.new(value)
|
value = SettableValue.new(value)
|
||||||
return set_text(value) unless value.dateable?
|
return set_text(value) unless value.dateable?
|
||||||
|
|
|
@ -57,6 +57,15 @@ class Capybara::Selenium::ChromeNode < Capybara::Selenium::Node
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def perform_regular_drag(element)
|
||||||
|
return super unless (browser_version < 77.0) && w3c? && !element.obscured?
|
||||||
|
|
||||||
|
# W3C Chrome/chromedriver < 77 doesn't maintain mouse button state across actions API performs
|
||||||
|
# https://bugs.chromium.org/p/chromedriver/issues/detail?id=2981
|
||||||
|
browser_action.release.perform
|
||||||
|
browser_action.click_and_hold(native).move_to(element.native).release.perform
|
||||||
|
end
|
||||||
|
|
||||||
def file_errors
|
def file_errors
|
||||||
@file_errors = ::Selenium::WebDriver.logger.suppress_deprecations do
|
@file_errors = ::Selenium::WebDriver.logger.suppress_deprecations do
|
||||||
[::Selenium::WebDriver::Error::ExpectedError]
|
[::Selenium::WebDriver::Error::ExpectedError]
|
||||||
|
|
|
@ -419,6 +419,16 @@ Capybara::SpecHelper.spec 'node' do
|
||||||
expect(@session).to have_xpath('//div[contains(., "Dropped!")]')
|
expect(@session).to have_xpath('//div[contains(., "Dropped!")]')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'should work with Dragula' do
|
||||||
|
@session.visit('/with_dragula')
|
||||||
|
@session.within(:css, '#sortable') do
|
||||||
|
src = @session.find('div', text: 'Item 1')
|
||||||
|
target = @session.find('div', text: 'Item 3')
|
||||||
|
src.drag_to target
|
||||||
|
expect(@session).to have_content(/Item 2.*Item 1/, normalize_ws: true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'HTML5', requires: %i[js html5_drag] do
|
context 'HTML5', requires: %i[js html5_drag] do
|
||||||
it 'should HTML5 drag and drop an object' do
|
it 'should HTML5 drag and drop an object' do
|
||||||
@session.visit('/with_js')
|
@session.visit('/with_js')
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
|
||||||
|
<title>with_dragula</title>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body id="with_dragula">
|
||||||
|
<div id="sortable">
|
||||||
|
<div class="item1">Item 1</div>
|
||||||
|
<div class="item2">Item 2</div>
|
||||||
|
<div class="item3">Item 3</div>
|
||||||
|
<div class="item4">Item 4</div>
|
||||||
|
<div class="item5">Item 5</div>
|
||||||
|
</div>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/dragula/3.7.2/dragula.js" type="text/javascript"></script>
|
||||||
|
<script>
|
||||||
|
dragula([document.getElementById("sortable")]);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
Loading…
Reference in New Issue