teamcapybara--capybara/lib/capybara/xpath.rb

132 lines
3.1 KiB
Ruby
Raw Normal View History

2009-12-09 18:03:55 +00:00
module Capybara
# this is a class for generating XPath queries, use it like this:
# Xpath.text_field('foo').link('blah').to_s
# this will generate an XPath that matches either a text field or a link
class XPath
class << self
def from_css(css)
Nokogiri::CSS.xpath_for(css).first
end
alias_method :for_css, :from_css
2010-01-01 16:48:39 +00:00
def wrap(path)
if path.is_a?(self)
path
else
new(path.to_s)
end
end
2010-01-01 16:48:39 +00:00
2009-12-09 18:03:55 +00:00
def respond_to?(method)
new.respond_to?(method)
end
def method_missing(*args)
new.send(*args)
end
end
attr_reader :paths
def initialize(*paths)
@paths = paths
end
2009-12-09 18:03:55 +00:00
def field(locator)
fillable_field(locator).file_field(locator).checkbox(locator).radio_button(locator).select(locator)
end
def fillable_field(locator)
text_field(locator).password_field(locator).text_area(locator)
end
2010-01-01 16:48:39 +00:00
def content(locator)
append("/descendant-or-self::*[contains(.,#{s(locator)})]")
end
2010-01-01 16:48:39 +00:00
def table(locator)
append("//table[@id=#{s(locator)} or contains(caption,#{s(locator)})]")
end
2010-01-01 16:48:39 +00:00
def fieldset(locator)
append("//fieldset[@id=#{s(locator)} or contains(legend,#{s(locator)})]")
end
2010-01-01 16:48:39 +00:00
def link(locator)
append("//a[@id=#{s(locator)} or contains(.,#{s(locator)}) or @title=#{s(locator)}]")
end
2010-01-01 16:48:39 +00:00
def button(locator)
xpath = append("//input[@type='submit' or @type='image'][@id=#{s(locator)} or contains(@value,#{s(locator)})]")
xpath.append("//button[@id=#{s(locator)} or contains(@value,#{s(locator)}) or contains(.,#{s(locator)})]")
end
2009-12-09 18:03:55 +00:00
def text_field(locator)
2009-12-15 22:27:52 +00:00
add_field(locator, "//input[@type='text']")
2009-12-09 18:03:55 +00:00
end
def password_field(locator)
2009-12-15 22:27:52 +00:00
add_field(locator, "//input[@type='password']")
2009-12-09 18:03:55 +00:00
end
def text_area(locator)
2009-12-15 22:27:52 +00:00
add_field(locator, "//textarea")
2009-12-09 18:03:55 +00:00
end
def radio_button(locator)
2009-12-15 22:27:52 +00:00
add_field(locator, "//input[@type='radio']")
2009-12-09 18:03:55 +00:00
end
def checkbox(locator)
2009-12-15 22:27:52 +00:00
add_field(locator, "//input[@type='checkbox']")
2009-12-09 18:03:55 +00:00
end
def select(locator)
2009-12-15 22:27:52 +00:00
add_field(locator, "//select")
2009-12-09 18:03:55 +00:00
end
def file_field(locator)
2009-12-15 22:27:52 +00:00
add_field(locator, "//input[@type='file']")
2009-12-09 18:03:55 +00:00
end
2010-01-01 16:48:39 +00:00
def scope(scope)
XPath.new(*paths.map { |p| scope + p })
end
2009-12-09 18:03:55 +00:00
def to_s
@paths.join(' | ')
end
2010-01-01 16:48:39 +00:00
def append(path)
XPath.new(*[@paths, XPath.wrap(path).paths].flatten)
end
2010-01-01 16:48:39 +00:00
def prepend(path)
XPath.new(*[XPath.wrap(path).paths, @paths].flatten)
end
2009-12-09 18:03:55 +00:00
protected
2010-01-01 16:48:39 +00:00
2009-12-15 22:27:52 +00:00
def add_field(locator, field)
xpath = append("#{field}[@id=#{s(locator)}]")
xpath = xpath.append("#{field}[@id=//label[contains(.,#{s(locator)})]/@for]")
xpath = xpath.append("//label[contains(.,#{s(locator)})]#{field}")
2009-12-15 22:27:52 +00:00
xpath.prepend("#{field}[@id=//label[text()=#{s(locator)}]/@for]")
end
2010-01-01 16:48:39 +00:00
# Sanitize a String for putting it into an xpath query
def s(string)
if string.include?("'")
string = string.split("'", -1).map do |substr|
"'#{substr}'"
end.join(%q{,"'",})
"concat(#{string})"
else
"'#{string}'"
end
2010-01-01 16:48:39 +00:00
end
2009-12-09 18:03:55 +00:00
end
end