Pulling attribute conditions up from have_selector to have_xpath

This commit is contained in:
Bryan Helmkamp 2009-02-23 20:47:02 -05:00
parent 1625e3e9ba
commit 29c40bd73c
3 changed files with 75 additions and 25 deletions

View File

@ -18,6 +18,7 @@ module Webrat
def tag_inspect def tag_inspect
options = @options.dup options = @options.dup
count = options.delete(:count)
content = options.delete(:content) content = options.delete(:content)
html = "<#{@expected}" html = "<#{@expected}"
@ -35,29 +36,7 @@ module Webrat
end end
def query def query
options = @options.dup Nokogiri::CSS::Parser.parse(@expected.to_s).map { |ast| ast.to_xpath }.first
selector = @expected.to_s
options.each do |key, value|
next if [:content, :count].include?(key)
selector << "[#{key}='#{value}']"
end
Nokogiri::CSS::Parser.parse(selector).map { |ast| ast.to_xpath }.first
end
def xpath_escape(string)
if string.include?("'") && string.include?('"')
parts = string.split("'").map do |part|
"'#{part}'"
end
"concat(" + parts.join(", \"'\", ") + ")"
elsif string.include?("'")
"\"#{string}\""
else
"'#{string}'"
end
end end
end end

View File

@ -37,6 +37,21 @@ module Webrat
@query = query @query = query
end end
attribute_conditions = []
@options.each do |key, value|
next if [:content, :count].include?(key)
attribute_conditions << "@#{key} = #{xpath_escape(value)}"
end
if attribute_conditions.any?
@query.first << "[#{attribute_conditions.join(' and ')}]"
end
if @options[:content]
@query.first << "[contains(., #{xpath_escape(@options[:content])})]"
end
@document = Webrat.rexml_document(stringlike) @document = Webrat.rexml_document(stringlike)
@query.map do |q| @query.map do |q|
@ -55,8 +70,19 @@ module Webrat
@query = query @query = query
end end
attribute_conditions = []
@options.each do |key, value|
next if [:content, :count].include?(key)
attribute_conditions << "@#{key} = #{xpath_escape(value)}"
end
if attribute_conditions.any?
@query.first << "[#{attribute_conditions.join(' and ')}]"
end
if @options[:content] if @options[:content]
query << "[contains(., #{xpath_escape(@options[:content])})]" @query.first << "[contains(., #{xpath_escape(@options[:content])})]"
end end
@document = Webrat::XML.document(stringlike) @document = Webrat::XML.document(stringlike)
@ -77,7 +103,24 @@ module Webrat
# String:: The failure message to be displayed in negative matches. # String:: The failure message to be displayed in negative matches.
def negative_failure_message def negative_failure_message
"expected following text to not match xpath #{@expected}:\n#{@document}" "expected following text to not match xpath #{@expected}:\n#{@document}"
end end
protected
def xpath_escape(string)
if string.include?("'") && string.include?('"')
parts = string.split("'").map do |part|
"'#{part}'"
end
"concat(" + parts.join(", \"'\", ") + ")"
elsif string.include?("'")
"\"#{string}\""
else
"'#{string}'"
end
end
end end
# Matches HTML content against an XPath query # Matches HTML content against an XPath query

View File

@ -22,6 +22,34 @@ describe "have_xpath" do
@body.should have_xpath("//div") @body.should have_xpath("//div")
end end
it "should be able to match an XPATH with attributes" do
@body.should have_xpath("//div", :class => "inner")
end
it "should be able to match an XPATH with content" do
@body.should have_xpath("//div", :content => "hello, world!")
end
it "should not match an XPATH without content" do
@body.should_not have_xpath("//div", :content => "not present")
end
it "should be able to match an XPATH with content and class" do
@body.should have_xpath("//div", :class => "inner", :content => "hello, world!")
end
it "should not match an XPATH with content and wrong class" do
@body.should_not have_xpath("//div", :class => "outer", :content => "hello, world!")
end
it "should not match an XPATH with wrong content and class" do
@body.should_not have_xpath("//div", :class => "inner", :content => "wrong")
end
it "should not match an XPATH with wrong content and wrong class" do
@body.should_not have_xpath("//div", :class => "outer", :content => "wrong")
end
it "should not match a XPATH that does not exist" do it "should not match a XPATH that does not exist" do
@body.should_not have_xpath("//p") @body.should_not have_xpath("//p")
end end