-
Notifications
You must be signed in to change notification settings - Fork 279
/
have_xpath.rb
106 lines (88 loc) · 2.89 KB
/
have_xpath.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
require "webrat/core/xml/nokogiri"
require "webrat/core/xml/rexml"
module Webrat
module Matchers
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] && (!@block || @block.call(matched))
else
matched.any? && (!@block || @block.call(matched))
end
end
def matches(stringlike)
if Webrat.configuration.parse_with_nokogiri?
nokogiri_matches(stringlike)
else
rexml_matches(stringlike)
end
end
def rexml_matches(stringlike)
if REXML::Node === stringlike || Array === stringlike
@query = query.map { |q| q.gsub(%r'//', './') }
else
@query = query
end
@document = Webrat.rexml_document(stringlike)
@query.map do |q|
if @document.is_a?(Array)
@document.map { |d| REXML::XPath.match(d, q) }
else
REXML::XPath.match(@document, q)
end
end.flatten.compact
end
def nokogiri_matches(stringlike)
if Nokogiri::XML::NodeSet === stringlike
@query = query.map { |q| q.gsub(%r'//', './') }
else
@query = query
end
if @options[:content]
query << "[contains(., #{xpath_escape(@options[:content])})]"
end
@document = Webrat::XML.document(stringlike)
@document.xpath(*@query)
end
def query
[@expected].flatten.compact
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
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