HTML5 draggable elements shold be draggable from their children

This commit is contained in:
Thomas Walpole 2019-06-07 09:59:14 -07:00
parent c053ff60de
commit b9d1b8f3a4
4 changed files with 35 additions and 5 deletions

View File

@ -7,8 +7,8 @@ class Capybara::Selenium::Node
def drag_to(element, delay: 0.05)
driver.execute_script MOUSEDOWN_TRACKER
scroll_if_needed { browser_action.click_and_hold(native).perform }
if driver.evaluate_script('window.capybara_mousedown_prevented || !arguments[0].draggable', self)
perform_regular_drag(element)
if driver.evaluate_script(LEGACY_DRAG_CHECK, self)
perform_legacy_drag(element)
else
perform_html5_drag(element, delay)
end
@ -16,7 +16,7 @@ class Capybara::Selenium::Node
private
def perform_regular_drag(element)
def perform_legacy_drag(element)
element.scroll_if_needed { browser_action.move_to(element.native).release.perform }
end
@ -94,6 +94,16 @@ class Capybara::Selenium::Node
}, { once: true, passive: true })
JS
LEGACY_DRAG_CHECK = <<~JS
(function(el){
if (window.capybara_mousedown_prevented) return true;
do {
if (el.draggable) return false;
} while (el = el.parentElement );
return true;
})(arguments[0])
JS
HTML5_DRAG_DROP_SCRIPT = <<~JS
function rectCenter(rect){
return new DOMPoint(
@ -174,6 +184,10 @@ class Capybara::Selenium::Node
var dt = new DataTransfer();
var opts = { cancelable: true, bubbles: true, dataTransfer: dt };
while (source && !source.draggable) {
source = source.parentElement;
}
if (source.tagName == 'A'){
dt.setData('text/uri-list', source.href);
dt.setData('text', source.href);

View File

@ -57,7 +57,7 @@ class Capybara::Selenium::ChromeNode < Capybara::Selenium::Node
private
def perform_regular_drag(element)
def perform_legacy_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

View File

@ -438,6 +438,14 @@ Capybara::SpecHelper.spec 'node' do
expect(@session).to have_xpath('//div[contains(., "HTML5 Dropped string: text/plain drag_html5")]')
end
it 'should HTML5 drag and drop an object child' do
@session.visit('/with_js')
element = @session.find('//div[@id="drag_html5"]/p')
target = @session.find('//div[@id="drop_html5"]')
element.drag_to(target)
expect(@session).to have_xpath('//div[contains(., "HTML5 Dropped string: text/plain drag_html5")]')
end
it 'should set clientX/Y in dragover events' do
@session.visit('/with_js')
element = @session.find('//div[@id="drag_html5"]')
@ -481,6 +489,14 @@ Capybara::SpecHelper.spec 'node' do
expect(@session).to have_content(/Item 3.*Item 1/, normalize_ws: true)
end
end
it 'should drag HTML5 default draggable element child' do
@session.visit('/with_js')
source = @session.find_link('drag_link_html5').find(:css, 'p')
target = @session.find(:id, 'drop_html5')
source.drag_to target
expect(@session).to have_xpath('//div[contains(., "HTML5 Dropped")]')
end
end
end

View File

@ -28,7 +28,7 @@
<div id="drag_html5" draggable="true">
<p>This is an HTML5 draggable element.</p>
</div>
<a id="drag_link_html5" href="#">This is an HTML5 draggable link</a>
<a id="drag_link_html5" href="#"><p>This is an HTML5 draggable link</p></a>
<div id="drop_html5" class="drop">
<p>It should be dropped here.</p>
</div>