assert2 0.4.5 → 0.4.6
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/assert2/xhtml.rb +71 -34
- metadata +2 -2
data/lib/assert2/xhtml.rb
CHANGED
@@ -89,45 +89,90 @@ class BeHtmlWith
|
|
89
89
|
|
90
90
|
def match_regexp(reference, sample)
|
91
91
|
reference =~ /^\(\?/ and
|
92
|
-
|
92
|
+
Regexp.new(reference) =~ sample
|
93
93
|
end
|
94
94
|
|
95
95
|
def match_text(ref, sam)
|
96
96
|
ref_text = get_texts(ref)
|
97
|
-
|
97
|
+
|
98
98
|
ref_text.empty? or ( ref_text - (sam_text = get_texts(sam)) ).empty? or
|
99
99
|
(ref_text.length == 1 and
|
100
100
|
match_regexp(ref_text.first, sam_text.join) )
|
101
101
|
end # The irony _is_ lost on us
|
102
102
|
|
103
|
-
def
|
103
|
+
def verbose_spew(reference, sample)
|
104
|
+
if reference['verbose!'] == 'true' and
|
105
|
+
@spewed[yo_path = sample.path] == nil
|
106
|
+
puts
|
107
|
+
puts '-' * 60
|
108
|
+
p yo_path
|
109
|
+
puts sample.to_xhtml
|
110
|
+
@spewed[yo_path] = true
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def match_class(attr_name, ref, sam)
|
115
|
+
return false unless attr_name == 'class'
|
116
|
+
return " #{sam} ".index(" #{ref} ")
|
117
|
+
end # NOTE if you call it a class, but ref contains
|
118
|
+
# something fruity, you are on your own!
|
119
|
+
|
120
|
+
def match_attributes(reference, sample)
|
104
121
|
reference.attribute_nodes.each do |attr|
|
105
|
-
|
106
|
-
|
107
|
-
|
122
|
+
unless %w( xpath! verbose! ).include? attr.name
|
123
|
+
ref, sam = deAmpAmp(attr.value),
|
124
|
+
deAmpAmp(sample[attr.name])
|
125
|
+
|
126
|
+
ref == sam or
|
127
|
+
match_regexp(ref, sam) or
|
128
|
+
match_class(attr.name, ref, sam) or
|
129
|
+
return false
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
return true
|
134
|
+
end
|
135
|
+
|
136
|
+
def match_xpath(reference, sample)
|
137
|
+
if value = reference['xpath!']
|
138
|
+
matches = sample.parent.xpath("*[ #{value} ]")
|
139
|
+
match_paths = matches.map{|m| m.path }
|
140
|
+
return match_paths.include? sample.path
|
108
141
|
end
|
109
142
|
|
110
|
-
return
|
143
|
+
return true
|
144
|
+
end
|
145
|
+
|
146
|
+
def match_attributes_and_text(reference, sample)
|
147
|
+
if match_attributes(reference, sample) and
|
148
|
+
match_text(reference, sample) and
|
149
|
+
match_xpath(reference, sample)
|
150
|
+
|
151
|
+
verbose_spew(reference, sample)
|
152
|
+
return true
|
153
|
+
end
|
154
|
+
|
155
|
+
return false
|
111
156
|
end
|
112
157
|
|
113
158
|
def elements_equal(element_1, element_2)
|
114
159
|
raise 'programming error: mismatched elements' unless element_1.document == element_2.document
|
115
160
|
element_1.path == element_2.path
|
116
161
|
end
|
117
|
-
|
118
|
-
# end # TODO more "elements" less "nodes"
|
119
162
|
|
120
163
|
def collect_samples(elements, index)
|
121
164
|
samples = elements.find_all do |element|
|
122
165
|
match_attributes_and_text(@references[index], element)
|
123
166
|
end
|
124
167
|
|
125
|
-
@first_samples +=
|
168
|
+
@first_samples += elements # if index == 0
|
169
|
+
# TODO this could use more testage, and it could enforce a link to the parent
|
126
170
|
return samples
|
127
171
|
end
|
128
172
|
|
129
173
|
attr_accessor :doc,
|
130
|
-
:scope
|
174
|
+
:scope,
|
175
|
+
:builder
|
131
176
|
|
132
177
|
def assemble_complaint
|
133
178
|
@first_samples << @doc.root if @first_samples.empty? # TODO test the first_samples system
|
@@ -140,7 +185,6 @@ class BeHtmlWith
|
|
140
185
|
@builder = Nokogiri::HTML::Builder.new(&bwock)
|
141
186
|
|
142
187
|
@builder.doc.children.each do |child|
|
143
|
-
# @first_samples = []
|
144
188
|
@path = build_deep_xpath(child)
|
145
189
|
next if @path == "//descendant::html[ refer(., '0') ]" # CONSIDER wtf is this?
|
146
190
|
paths << @path
|
@@ -150,7 +194,7 @@ class BeHtmlWith
|
|
150
194
|
end # TODO refactor more to actually use this
|
151
195
|
|
152
196
|
def matches?(stwing, &block)
|
153
|
-
@scope.wrap_expectation self do
|
197
|
+
@scope.wrap_expectation self do
|
154
198
|
begin
|
155
199
|
paths = build_xpaths(&block)
|
156
200
|
@doc = Nokogiri::HTML(stwing)
|
@@ -158,6 +202,7 @@ class BeHtmlWith
|
|
158
202
|
|
159
203
|
@builder.doc.children.each do |child|
|
160
204
|
@first_samples = []
|
205
|
+
@spewed = {}
|
161
206
|
@path = build_deep_xpath(child)
|
162
207
|
next if @path == "//descendant::html[ refer(., '0') ]" # CONSIDER wtf is this?
|
163
208
|
|
@@ -180,7 +225,7 @@ class BeHtmlWith
|
|
180
225
|
@references = []
|
181
226
|
path = build_xpath(element)
|
182
227
|
if path.index('not') == 0
|
183
|
-
return '/*[ ' + path + ' ]'
|
228
|
+
return '/*[ ' + path + ' ]' # ERGO uh, is there a cleaner way?
|
184
229
|
end
|
185
230
|
return '//' + path
|
186
231
|
end
|
@@ -198,14 +243,8 @@ class BeHtmlWith
|
|
198
243
|
element_kids = element.children.grep(Nokogiri::XML::Element)
|
199
244
|
|
200
245
|
if element_kids.any?
|
201
|
-
path << element_kids.map{|child|
|
202
|
-
|
203
|
-
# 'not( ' + build_predicate(child) + '1=1 )'
|
204
|
-
# else
|
205
|
-
build_xpath(child)
|
206
|
-
# end
|
207
|
-
}.join(conjunction)
|
208
|
-
path << ' and ' # conjunction
|
246
|
+
path << element_kids.map{|child| build_xpath(child) }.join(conjunction)
|
247
|
+
path << ' and '
|
209
248
|
end
|
210
249
|
|
211
250
|
return path
|
@@ -223,6 +262,8 @@ class BeHtmlWith
|
|
223
262
|
path << '[ '
|
224
263
|
path << build_predicate(element)
|
225
264
|
path << "refer(., '#{count}') ]" # last so boolean short-circuiting optimizes
|
265
|
+
# xpath = element['xpath!']
|
266
|
+
# path << "[ #{ xpath } ]" if xpath
|
226
267
|
return path
|
227
268
|
end
|
228
269
|
end
|
@@ -238,8 +279,6 @@ class BeHtmlWith
|
|
238
279
|
if element_kids.length > 0
|
239
280
|
child = element_kids[0]
|
240
281
|
path << './descendant::' + build_xpath_too(child)
|
241
|
-
# }.join(' and ')
|
242
|
-
# path << ' and '
|
243
282
|
end
|
244
283
|
|
245
284
|
if element_kids.length > 1
|
@@ -274,15 +313,6 @@ class BeHtmlWith
|
|
274
313
|
return nil
|
275
314
|
end # TODO use or lose these
|
276
315
|
|
277
|
-
# TODO does a multi-modal top axis work?
|
278
|
-
# TODO this_match = node.xpath('preceding::*').length
|
279
|
-
|
280
|
-
# http://www.zvon.org/xxl/XPathTutorial/Output/example18.html
|
281
|
-
# The preceding axis contains all nodes in the same document
|
282
|
-
# as the context node that are before the context node in
|
283
|
-
# document order, excluding any ancestors and excluding
|
284
|
-
# attribute nodes and namespace nodes
|
285
|
-
|
286
316
|
attr_accessor :failure_message
|
287
317
|
|
288
318
|
def negative_failure_message
|
@@ -331,4 +361,11 @@ class Nokogiri::XML::Node
|
|
331
361
|
def content= string
|
332
362
|
self.native_content = encode_special_chars(string.to_s)
|
333
363
|
end
|
334
|
-
end
|
364
|
+
end
|
365
|
+
|
366
|
+
class Nokogiri::XML::Builder
|
367
|
+
def text(string)
|
368
|
+
node = Nokogiri::XML::Text.new(string.to_s, @doc)
|
369
|
+
insert(node)
|
370
|
+
end
|
371
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: assert2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Phlip
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-03-
|
12
|
+
date: 2009-03-22 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|