lib/watir-webdriver/locators/element_locator.rb in watir-webdriver-0.5.3 vs lib/watir-webdriver/locators/element_locator.rb in watir-webdriver-0.5.4
- old
+ new
@@ -8,11 +8,11 @@
:class_name,
:css,
:id,
:link,
:link_text,
- :name,
+ # :name, # deliberately excluded to be watirspec compliant
:partial_link_text,
:tag_name,
:xpath
]
@@ -73,18 +73,18 @@
def find_first_by_multiple
selector = normalized_selector
idx = selector.delete(:index)
- xpath = given_xpath(selector) || build_xpath(selector)
+ how, what = given_xpath(selector) || build_wd_selector(selector)
- if xpath
+ if how
# could build xpath for selector
if idx
- @wd.find_elements(:xpath, xpath)[idx]
+ @wd.find_elements(how, what)[idx]
else
- @wd.find_element(:xpath, xpath)
+ @wd.find_element(how, what)
end
else
# can't use xpath, probably a regexp in there
if idx
wd_find_by_regexp_selector(selector, :select)[idx]
@@ -99,13 +99,13 @@
if selector.has_key? :index
raise ArgumentError, "can't locate all elements by :index"
end
- xpath = given_xpath(selector) || build_xpath(selector)
- if xpath
- @wd.find_elements(:xpath, xpath)
+ how, what = given_xpath(selector) || build_wd_selector(selector)
+ if how
+ @wd.find_elements(how, what)
else
wd_find_by_regexp_selector(selector, :select)
end
end
@@ -130,13 +130,17 @@
if rx_selector.has_key?(:label) && should_use_label_element?
selector[:id] = id_from_label(rx_selector.delete(:label)) || return
end
- xpath = build_xpath(selector) || raise("internal error: unable to build xpath from #{selector.inspect}")
+ how, what = build_wd_selector(selector)
- elements = @wd.find_elements(:xpath, xpath)
+ unless how
+ raise Error, "internal error: unable to build WebDriver selector from #{selector.inspect}"
+ end
+
+ elements = @wd.find_elements(how, what)
elements.__send__(method) { |el| matches_selector?(el, rx_selector) }
end
VALID_WHATS = [String, Regexp]
@@ -262,17 +266,21 @@
def should_use_label_element?
@selector[:tag_name] != "option"
end
- def build_xpath(selectors)
- return if selectors.values.any? { |e| e.kind_of? Regexp }
+ def build_wd_selector(selectors)
+ unless selectors.values.any? { |e| e.kind_of? Regexp }
+ build_css(selectors) || build_xpath(selectors)
+ end
+ end
+ def build_xpath(selectors)
xpath = ".//"
xpath << (selectors.delete(:tag_name) || '*').to_s
- idx = selectors.delete(:index)
+ idx = selectors.delete :index
# the remaining entries should be attributes
unless selectors.empty?
xpath << "[" << attribute_expression(selectors) << "]"
end
@@ -281,23 +289,69 @@
xpath << "[#{idx + 1}]"
end
p :xpath => xpath, :selectors => selectors if $DEBUG
- xpath
+ [:xpath, xpath]
end
+ def build_css(selectors)
+ return unless use_css?(selectors)
+
+ css = ''
+ css << (selectors.delete(:tag_name) || '')
+
+ klass = selectors.delete(:class)
+ if klass
+ if klass.include? ' '
+ css << %([class="#{css_escape klass}"])
+ else
+ css << ".#{klass}"
+ end
+ end
+
+ href = selectors.delete(:href)
+ if href
+ css << %([href~="#{css_escape href}"])
+ end
+
+ selectors.each do |key, value|
+ key = key.to_s.gsub("_", "-")
+ css << %([#{key}="#{css_escape value}"]) # TODO: proper escaping
+ end
+
+ [:css, css]
+ end
+
+ def use_css?(selectors)
+ return false unless Watir.prefer_css?
+
+ if selectors.has_key?(:text) || selectors.has_key?(:label) || selectors.has_key?(:index)
+ return false
+ end
+
+ if selectors.has_key?(:class) && selectors[:class] !~ /^[\w-]+$/ui
+ return false
+ end
+
+ true
+ end
+
def attribute_expression(selectors)
selectors.map do |key, val|
if val.kind_of?(Array)
"(" + val.map { |v| equal_pair(key, v) }.join(" or ") + ")"
else
equal_pair(key, val)
end
end.join(" and ")
end
+ def css_escape(str)
+ str.gsub('"', '\\"')
+ end
+
def equal_pair(key, value)
if key == :class
klass = XpathSupport.escape " #{value} "
"contains(concat(' ', @class, ' '), #{klass})"
elsif key == :label && should_use_label_element?
@@ -338,10 +392,10 @@
unless selector.empty? || can_be_combined_with_xpath?(selector)
raise ArgumentError, ":xpath cannot be combined with other selectors (#{selector.inspect})"
end
- xpath
+ [:xpath, xpath]
end
def can_be_combined_with_xpath?(selector)
# ouch - is this worth it?
keys = selector.keys