1
0
Fork 0
mirror of https://github.com/teamcapybara/capybara.git synced 2022-11-09 12:08:07 -05:00

Reduce wirecalls in selenium path generation

This commit is contained in:
Thomas Walpole 2018-12-29 13:13:33 -08:00
parent d12b375d49
commit 3cb656af8c
2 changed files with 33 additions and 19 deletions

View file

@ -161,22 +161,7 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
end
def path
path = find_xpath(XPath.ancestor_or_self).reverse
result = []
default_ns = path.last[:namespaceURI]
while (node = path.shift)
parent = path.first
selector = node[:tagName]
if node[:namespaceURI] != default_ns
selector = XPath.child.where((XPath.local_name == selector) & (XPath.namespace_uri == node[:namespaceURI])).to_s
end
selector += sibling_index(parent, node, selector) if parent
result.push selector
end
'/' + result.reverse.join('/')
driver.evaluate_script GET_XPATH_SCRIPT, self
end
protected
@ -357,6 +342,35 @@ private
end
end
GET_XPATH_SCRIPT = <<~'JS'
(function(el, xml){
var xpath = '';
var pos, tempitem2;
while(el !== xml.documentElement) {
pos = 0;
tempitem2 = el;
while(tempitem2) {
if (tempitem2.nodeType === 1 && tempitem2.nodeName === el.nodeName) { // If it is ELEMENT_NODE of the same name
pos += 1;
}
tempitem2 = tempitem2.previousSibling;
}
if (el.namespaceURI != xml.documentElement.namespaceURI) {
xpath = "*[local-name()='"+el.nodeName+"' and namespace-uri()='"+(el.namespaceURI===null?'':el.namespaceURI)+"']["+pos+']'+'/'+xpath;
} else {
xpath = el.nodeName.toUpperCase()+"["+pos+"]/"+xpath;
}
el = el.parentNode;
}
xpath = '/'+xml.documentElement.nodeName.toUpperCase()+'/'+xpath;
xpath = xpath.replace(/\/$/, '');
return xpath;
})(arguments[0], document)
JS
# SettableValue encapsulates time/date field formatting
class SettableValue
attr_reader :value

View file

@ -199,14 +199,14 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
# this is here because it is testing for an XPath that is specific to the algorithm used in the selenium driver
session.visit('/path')
element = session.find(:link, 'Second Link')
expect(element.path).to eq('/HTML/BODY/DIV[2]/A[1]')
expect(element.path).to eq('/HTML/BODY[1]/DIV[2]/A[1]')
end
it 'handles namespaces in xhtml' do
pending "IE 11 doesn't handle all XPath querys (namespace-uri, etc)" if ie?(session)
session.visit '/with_namespace'
rect = session.find(:css, 'div svg rect:first-of-type')
expect(rect.path).to eq("/HTML/BODY/DIV/./*[((local-name(.) = 'svg') and (namespace-uri(.) = 'http://www.w3.org/2000/svg'))]/./*[((local-name(.) = 'rect') and (namespace-uri(.) = 'http://www.w3.org/2000/svg'))][1]")
expect(rect.path).to eq("/HTML/BODY[1]/DIV[1]/*[local-name()='svg' and namespace-uri()='http://www.w3.org/2000/svg'][1]/*[local-name()='rect' and namespace-uri()='http://www.w3.org/2000/svg'][1]")
expect(session.find(:xpath, rect.path)).to eq rect
end
@ -214,7 +214,7 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
pending "IE 11 doesn't handle all XPath querys (namespace-uri, etc)" if ie?(session)
session.visit '/with_html5_svg'
rect = session.find(:css, 'div svg rect:first-of-type')
expect(rect.path).to eq("/HTML/BODY/DIV/./*[((local-name(.) = 'svg') and (namespace-uri(.) = 'http://www.w3.org/2000/svg'))]/./*[((local-name(.) = 'rect') and (namespace-uri(.) = 'http://www.w3.org/2000/svg'))][1]")
expect(rect.path).to eq("/HTML/BODY[1]/DIV[1]/*[local-name()='svg' and namespace-uri()='http://www.w3.org/2000/svg'][1]/*[local-name()='rect' and namespace-uri()='http://www.w3.org/2000/svg'][1]")
expect(session.find(:xpath, rect.path)).to eq rect
end