Created
December 4, 2009 09:39
-
-
Save ngty/248932 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Steam | |
module Matchers | |
module HtmlUnit | |
class HasContent #:nodoc: | |
# nothing interesting, the original content remains | |
end | |
### | |
# Directly extracted from Webrat::Matchers::HaveXpath with minor edits to avoid | |
# calling webrat stuff | |
### | |
class HaveXpath #:nodoc: | |
def initialize(expected, options = {}, &block) | |
@expected = expected | |
@options = options | |
@block = block | |
end | |
def matches?(stringlike, &block) | |
@block ||= block | |
matched = matches(stringlike) | |
if @options[:count] | |
matched.size == @options[:count].to_i && (!@block || @block.call(matched)) | |
else | |
matched.any? && (!@block || @block.call(matched)) | |
end | |
end | |
def matches(stringlike) | |
nokogiri_matches(stringlike) | |
end | |
def nokogiri_matches(stringlike) | |
if Nokogiri::XML::NodeSet === stringlike | |
@query = query.gsub(%r'^//', './/') | |
else | |
@query = query | |
end | |
add_options_conditions_to(@query) | |
@document = | |
if stringlike.respond_to?(:dom) | |
stringlike.dom | |
elsif Nokogiri::HTML::Document === stringlike | |
stringlike | |
elsif Nokogiri::XML::NodeSet === stringlike | |
stringlike | |
elsif stringlike.respond_to?(:body) | |
Nokogiri::HTML(stringlike.body.to_s) | |
else | |
Nokogiri::HTML(stringlike.to_s) | |
end | |
@document.xpath(*@query) | |
end | |
def add_options_conditions_to(query) | |
add_attributes_conditions_to(query) | |
add_content_condition_to(query) | |
end | |
def add_attributes_conditions_to(query) | |
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 << "[#{attribute_conditions.join(' and ')}]" | |
end | |
end | |
def add_content_condition_to(query) | |
if @options[:content] | |
query << "[contains(., #{xpath_escape(@options[:content])})]" | |
end | |
end | |
def query | |
@expected | |
end | |
# ==== Returns | |
# String:: The failure message. | |
def failure_message | |
"expected following text to match xpath #{@expected}:\n#{@document}" | |
end | |
# ==== Returns | |
# String:: The failure message to be displayed in negative matches. | |
def negative_failure_message | |
"expected following text to not match xpath #{@expected}:\n#{@document}" | |
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 | |
# Matches HTML content against an XPath query | |
# | |
# ==== Parameters | |
# expected<String>:: The XPath query to look for. | |
# | |
# ==== Returns | |
# HaveXpath:: A new have xpath matcher. | |
def have_xpath(expected, options = {}, &block) | |
HaveXpath.new(expected, options, &block) | |
end | |
alias_method :match_xpath, :have_xpath | |
def assert_have_xpath(expected, options = {}, &block) | |
hs = HaveXpath.new(expected, options, &block) | |
assert hs.matches?(response_body), hs.failure_message | |
end | |
def assert_have_no_xpath(expected, options = {}, &block) | |
hs = HaveXpath.new(expected, options, &block) | |
assert !hs.matches?(response_body), hs.negative_failure_message | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment