rails-dom-testing 2.0.3 → 2.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +6 -6
- data/lib/rails/dom/testing/assertions/dom_assertions.rb +28 -10
- data/lib/rails/dom/testing/assertions/selector_assertions/count_describable.rb +0 -4
- data/lib/rails/dom/testing/assertions/selector_assertions/html_selector.rb +24 -16
- data/lib/rails/dom/testing/assertions/selector_assertions/substitution_context.rb +5 -8
- data/lib/rails/dom/testing/assertions/selector_assertions.rb +54 -48
- data/lib/rails/dom/testing/assertions.rb +3 -7
- data/lib/rails/dom/testing/version.rb +1 -1
- data/test/dom_assertions_test.rb +76 -1
- data/test/selector_assertions_test.rb +33 -0
- metadata +19 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: dc48c3a21ae3839cf5bbde901d06210fe2a4d1d58e6aae4048a26c19a6baf577
|
4
|
+
data.tar.gz: b082464768d961ef20cc41ec1da545691bd7e0caac93a16b8668128818855885
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 51f291660cac9014e810adbf636c5dfbf7da80db478c062191eecedebe5b77b4f795a12259b1b427fd04b548e0a9b1b524d550e514b8e8b561ae566c36471182
|
7
|
+
data.tar.gz: d5ac742ae523c62d565627f9c95553780286de17ba7a43f32972a5dcf2458d316b79c80edcfd3f4361b2d77a4dcfa541976f14cbb09b249bf681bfabf2c5696e
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
This gem is responsible for comparing HTML doms and asserting that DOM elements are present in Rails applications.
|
4
4
|
Doms are compared via `assert_dom_equal` and `assert_dom_not_equal`.
|
5
|
-
Elements are asserted via `
|
5
|
+
Elements are asserted via `assert_dom`, `assert_dom_encoded`, `assert_dom_email` and a subset of the dom can be selected with `css_select`.
|
6
6
|
The gem is developed for Rails 4.2 and above, and will not work on previous versions.
|
7
7
|
|
8
8
|
## Nokogiri::CSS::SyntaxError exceptions when upgrading to Rails 4.2:
|
@@ -41,21 +41,21 @@ assert_dom_not_equal '<h1>Portuguese</h1>', '<h1>Danish</h1>'
|
|
41
41
|
# implicitly selects from the document_root_element
|
42
42
|
css_select '.hello' # => Nokogiri::XML::NodeSet of elements with hello class
|
43
43
|
|
44
|
-
# select from a supplied node.
|
45
|
-
|
44
|
+
# select from a supplied node. assert_dom asserts elements exist.
|
45
|
+
assert_dom document_root_element.at('.hello'), '.goodbye'
|
46
46
|
|
47
47
|
# elements in CDATA encoded sections can also be selected
|
48
|
-
|
48
|
+
assert_dom_encoded '#out-of-your-element'
|
49
49
|
|
50
50
|
# assert elements within an html email exists
|
51
|
-
|
51
|
+
assert_dom_email '#you-got-mail'
|
52
52
|
```
|
53
53
|
|
54
54
|
The documentation in [selector_assertions.rb](https://github.com/rails/rails-dom-testing/blob/master/lib/rails/dom/testing/assertions/selector_assertions.rb) goes into a lot more detail of how selector assertions can be used.
|
55
55
|
|
56
56
|
## Read more
|
57
57
|
|
58
|
-
Under the hood the doms are parsed with Nokogiri and you'll generally be working with these two classes:
|
58
|
+
Under the hood the doms are parsed with Nokogiri, and you'll generally be working with these two classes:
|
59
59
|
- [`Nokogiri::XML::Node`](http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/Node)
|
60
60
|
- [`Nokogiri::XML::NodeSet`](http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/NodeSet)
|
61
61
|
|
@@ -7,43 +7,61 @@ module Rails
|
|
7
7
|
#
|
8
8
|
# # assert that the referenced method generates the appropriate HTML string
|
9
9
|
# assert_dom_equal '<a href="http://www.example.com">Apples</a>', link_to("Apples", "http://www.example.com")
|
10
|
-
def assert_dom_equal(expected, actual, message = nil)
|
10
|
+
def assert_dom_equal(expected, actual, message = nil, strict: false)
|
11
11
|
expected_dom, actual_dom = fragment(expected), fragment(actual)
|
12
12
|
message ||= "Expected: #{expected}\nActual: #{actual}"
|
13
|
-
assert compare_doms(expected_dom, actual_dom), message
|
13
|
+
assert compare_doms(expected_dom, actual_dom, strict), message
|
14
14
|
end
|
15
15
|
|
16
16
|
# The negated form of +assert_dom_equal+.
|
17
17
|
#
|
18
18
|
# # assert that the referenced method does not generate the specified HTML string
|
19
19
|
# assert_dom_not_equal '<a href="http://www.example.com">Apples</a>', link_to("Oranges", "http://www.example.com")
|
20
|
-
def assert_dom_not_equal(expected, actual, message = nil)
|
20
|
+
def assert_dom_not_equal(expected, actual, message = nil, strict: false)
|
21
21
|
expected_dom, actual_dom = fragment(expected), fragment(actual)
|
22
22
|
message ||= "Expected: #{expected}\nActual: #{actual}"
|
23
|
-
assert_not compare_doms(expected_dom, actual_dom), message
|
23
|
+
assert_not compare_doms(expected_dom, actual_dom, strict), message
|
24
24
|
end
|
25
25
|
|
26
26
|
protected
|
27
27
|
|
28
|
-
def compare_doms(expected, actual)
|
29
|
-
|
28
|
+
def compare_doms(expected, actual, strict)
|
29
|
+
expected_children = extract_children(expected, strict)
|
30
|
+
actual_children = extract_children(actual, strict)
|
31
|
+
return false unless expected_children.size == actual_children.size
|
30
32
|
|
31
|
-
|
32
|
-
return false unless equal_children?(child,
|
33
|
+
expected_children.each_with_index do |child, i|
|
34
|
+
return false unless equal_children?(child, actual_children[i], strict)
|
33
35
|
end
|
34
36
|
|
35
37
|
true
|
36
38
|
end
|
37
39
|
|
38
|
-
def
|
40
|
+
def extract_children(node, strict)
|
41
|
+
if strict
|
42
|
+
node.children
|
43
|
+
else
|
44
|
+
node.children.reject{|n| n.text? && n.text.blank?}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def equal_children?(child, other_child, strict)
|
39
49
|
return false unless child.type == other_child.type
|
40
50
|
|
41
51
|
if child.element?
|
42
52
|
child.name == other_child.name &&
|
43
53
|
equal_attribute_nodes?(child.attribute_nodes, other_child.attribute_nodes) &&
|
44
|
-
compare_doms(child, other_child)
|
54
|
+
compare_doms(child, other_child, strict)
|
45
55
|
else
|
56
|
+
equal_child?(child, other_child, strict)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def equal_child?(child, other_child, strict)
|
61
|
+
if strict
|
46
62
|
child.to_s == other_child.to_s
|
63
|
+
else
|
64
|
+
child.to_s.split == other_child.to_s.split
|
47
65
|
end
|
48
66
|
end
|
49
67
|
|
@@ -1,13 +1,9 @@
|
|
1
|
-
require 'active_support/concern'
|
2
|
-
|
3
1
|
module Rails
|
4
2
|
module Dom
|
5
3
|
module Testing
|
6
4
|
module Assertions
|
7
5
|
module SelectorAssertions
|
8
6
|
module CountDescribable
|
9
|
-
extend ActiveSupport::Concern
|
10
|
-
|
11
7
|
private
|
12
8
|
def count_description(min, max, count) #:nodoc:
|
13
9
|
if min && max && (max != min)
|
@@ -1,9 +1,13 @@
|
|
1
|
+
require 'minitest'
|
2
|
+
require 'active_support'
|
1
3
|
require 'active_support/core_ext/module/attribute_accessors'
|
2
4
|
require_relative 'substitution_context'
|
3
5
|
|
4
6
|
class HTMLSelector #:nodoc:
|
5
7
|
attr_reader :css_selector, :tests, :message
|
6
8
|
|
9
|
+
include Minitest::Assertions
|
10
|
+
|
7
11
|
def initialize(values, previous_selection = nil, &root_fallback)
|
8
12
|
@values = values
|
9
13
|
@root = extract_root(previous_selection, root_fallback)
|
@@ -11,6 +15,10 @@ class HTMLSelector #:nodoc:
|
|
11
15
|
@tests = extract_equality_tests
|
12
16
|
@message = @values.shift
|
13
17
|
|
18
|
+
if @message.is_a?(Hash)
|
19
|
+
raise ArgumentError, "Last argument was a Hash, which would be used for the assertion message. You probably want this to be a String, or you have the wrong type of arguments."
|
20
|
+
end
|
21
|
+
|
14
22
|
if @values.shift
|
15
23
|
raise ArgumentError, "Not expecting that last argument, you either have too many arguments, or they're the wrong type"
|
16
24
|
end
|
@@ -48,7 +56,7 @@ class HTMLSelector #:nodoc:
|
|
48
56
|
content.sub!(/\A\n/, '') if text_matches && match.name == "textarea"
|
49
57
|
|
50
58
|
next if regex_matching ? (content =~ match_with) : (content == match_with)
|
51
|
-
content_mismatch ||=
|
59
|
+
content_mismatch ||= diff(match_with, content)
|
52
60
|
true
|
53
61
|
end
|
54
62
|
|
@@ -61,7 +69,7 @@ class HTMLSelector #:nodoc:
|
|
61
69
|
|
62
70
|
if possible_root == nil
|
63
71
|
raise ArgumentError, 'First argument is either selector or element ' \
|
64
|
-
'to select, but nil found. Perhaps you called
|
72
|
+
'to select, but nil found. Perhaps you called assert_dom with ' \
|
65
73
|
'an element that does not exist?'
|
66
74
|
elsif possible_root.respond_to?(:css)
|
67
75
|
@values.shift # remove the root, so selector is the first argument
|
@@ -87,20 +95,20 @@ class HTMLSelector #:nodoc:
|
|
87
95
|
def extract_equality_tests
|
88
96
|
comparisons = {}
|
89
97
|
case comparator = @values.shift
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
98
|
+
when Hash
|
99
|
+
comparisons = comparator
|
100
|
+
when String, Regexp
|
101
|
+
comparisons[:text] = comparator
|
102
|
+
when Integer
|
103
|
+
comparisons[:count] = comparator
|
104
|
+
when Range
|
105
|
+
comparisons[:minimum] = comparator.begin
|
106
|
+
comparisons[:maximum] = comparator.end
|
107
|
+
when FalseClass
|
108
|
+
comparisons[:count] = 0
|
109
|
+
when NilClass, TrueClass
|
110
|
+
comparisons[:minimum] = 1
|
111
|
+
else raise ArgumentError, "I don't understand what you're trying to match"
|
104
112
|
end
|
105
113
|
|
106
114
|
# By default we're looking for at least one match.
|
@@ -4,13 +4,10 @@ class SubstitutionContext
|
|
4
4
|
end
|
5
5
|
|
6
6
|
def substitute!(selector, values, format_for_presentation = false)
|
7
|
-
selector
|
8
|
-
|
9
|
-
|
10
|
-
selector.sub! @substitute, matcher_for(values.shift, format_for_presentation)
|
7
|
+
selector.gsub @substitute do |match|
|
8
|
+
next match[0] if values.empty? || !substitutable?(values.first)
|
9
|
+
matcher_for(values.shift, format_for_presentation)
|
11
10
|
end
|
12
|
-
|
13
|
-
selector
|
14
11
|
end
|
15
12
|
|
16
13
|
def match(matches, attribute, matcher)
|
@@ -23,11 +20,11 @@ class SubstitutionContext
|
|
23
20
|
if format_for_presentation
|
24
21
|
value.inspect # Avoid to_s so Regexps aren't put in quotes.
|
25
22
|
else
|
26
|
-
value
|
23
|
+
"\"#{value}\""
|
27
24
|
end
|
28
25
|
end
|
29
26
|
|
30
27
|
def substitutable?(value)
|
31
|
-
|
28
|
+
[ Symbol, Numeric, String, Regexp ].any? { |type| value.is_a? type }
|
32
29
|
end
|
33
30
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'active_support/deprecation'
|
2
1
|
require_relative 'selector_assertions/count_describable'
|
3
2
|
require_relative 'selector_assertions/html_selector'
|
4
3
|
|
@@ -6,9 +5,9 @@ module Rails
|
|
6
5
|
module Dom
|
7
6
|
module Testing
|
8
7
|
module Assertions
|
9
|
-
# Adds the +
|
8
|
+
# Adds the +assert_dom+ method for use in Rails functional
|
10
9
|
# test cases, which can be used to make assertions on the response HTML of a controller
|
11
|
-
# action. You can also call +
|
10
|
+
# action. You can also call +assert_dom+ within another +assert_dom+ to
|
12
11
|
# make assertions on elements selected by the enclosing assertion.
|
13
12
|
#
|
14
13
|
# Use +css_select+ to select elements without making an assertions, either
|
@@ -16,8 +15,8 @@ module Rails
|
|
16
15
|
#
|
17
16
|
# In addition to HTML responses, you can make the following assertions:
|
18
17
|
#
|
19
|
-
# * +
|
20
|
-
# * +
|
18
|
+
# * +assert_dom_encoded+ - Assertions on HTML encoded inside XML, for example for dealing with feed item descriptions.
|
19
|
+
# * +assert_dom_email+ - Assertions on the HTML body of an e-mail.
|
21
20
|
module SelectorAssertions
|
22
21
|
|
23
22
|
# Select and return all matching elements.
|
@@ -70,38 +69,41 @@ module Rails
|
|
70
69
|
# starting from (and including) that element and all its children in
|
71
70
|
# depth-first order.
|
72
71
|
#
|
73
|
-
# If no element is specified +
|
72
|
+
# If no element is specified +assert_dom+ selects from
|
74
73
|
# the element returned in +document_root_element+
|
75
|
-
# unless +
|
76
|
-
# Override +document_root_element+ to tell +
|
74
|
+
# unless +assert_dom+ is called from within an +assert_dom+ block.
|
75
|
+
# Override +document_root_element+ to tell +assert_dom+ what to select from.
|
77
76
|
# The default implementation raises an exception explaining this.
|
78
77
|
#
|
79
|
-
# When called with a block +
|
80
|
-
# to the block. Calling +
|
78
|
+
# When called with a block +assert_dom+ passes an array of selected elements
|
79
|
+
# to the block. Calling +assert_dom+ from the block, with no element specified,
|
81
80
|
# runs the assertion on the complete set of elements selected by the enclosing assertion.
|
82
|
-
# Alternatively the array may be iterated through so that +
|
81
|
+
# Alternatively the array may be iterated through so that +assert_dom+ can be called
|
83
82
|
# separately for each element.
|
84
83
|
#
|
85
84
|
#
|
86
85
|
# ==== Example
|
87
86
|
# If the response contains two ordered lists, each with four list elements then:
|
88
|
-
#
|
87
|
+
# assert_dom "ol" do |elements|
|
89
88
|
# elements.each do |element|
|
90
|
-
#
|
89
|
+
# assert_dom element, "li", 4
|
91
90
|
# end
|
92
91
|
# end
|
93
92
|
#
|
94
93
|
# will pass, as will:
|
95
|
-
#
|
96
|
-
#
|
94
|
+
# assert_dom "ol" do
|
95
|
+
# assert_dom "li", 8
|
97
96
|
# end
|
98
97
|
#
|
99
|
-
# The selector may be a CSS selector expression (String) or an expression
|
98
|
+
# The selector may be a CSS selector expression (String, Symbol, or Numeric) or an expression
|
100
99
|
# with substitution values (Array).
|
101
100
|
# Substitution uses a custom pseudo class match. Pass in whatever attribute you want to match (enclosed in quotes) and a ? for the substitution.
|
102
|
-
#
|
101
|
+
# assert_dom returns nil if called with an invalid css selector.
|
103
102
|
#
|
104
|
-
#
|
103
|
+
# assert_dom "div:match('id', ?)", "id_string"
|
104
|
+
# assert_dom "div:match('id', ?)", :id_string
|
105
|
+
# assert_dom "div:match('id', ?)", 1
|
106
|
+
# assert_dom "div:match('id', ?)", /\d+/
|
105
107
|
#
|
106
108
|
# === Equality Tests
|
107
109
|
#
|
@@ -133,32 +135,32 @@ module Rails
|
|
133
135
|
# evaluated the block is called with an array of all matched elements.
|
134
136
|
#
|
135
137
|
# # At least one form element
|
136
|
-
#
|
138
|
+
# assert_dom "form"
|
137
139
|
#
|
138
140
|
# # Form element includes four input fields
|
139
|
-
#
|
141
|
+
# assert_dom "form input", 4
|
140
142
|
#
|
141
143
|
# # Page title is "Welcome"
|
142
|
-
#
|
144
|
+
# assert_dom "title", "Welcome"
|
143
145
|
#
|
144
146
|
# # Page title is "Welcome" and there is only one title element
|
145
|
-
#
|
147
|
+
# assert_dom "title", {count: 1, text: "Welcome"},
|
146
148
|
# "Wrong title or more than one title element"
|
147
149
|
#
|
148
150
|
# # Page contains no forms
|
149
|
-
#
|
151
|
+
# assert_dom "form", false, "This page must contain no forms"
|
150
152
|
#
|
151
153
|
# # Test the content and style
|
152
|
-
#
|
154
|
+
# assert_dom "body div.header ul.menu"
|
153
155
|
#
|
154
156
|
# # Use substitution values
|
155
|
-
#
|
157
|
+
# assert_dom "ol>li:match('id', ?)", /item-\d+/
|
156
158
|
#
|
157
159
|
# # All input fields in the form have a name
|
158
|
-
#
|
159
|
-
#
|
160
|
+
# assert_dom "form input" do
|
161
|
+
# assert_dom ":match('name', ?)", /.+/ # Not empty
|
160
162
|
# end
|
161
|
-
def
|
163
|
+
def assert_dom(*args, &block)
|
162
164
|
@selected ||= nil
|
163
165
|
|
164
166
|
selector = HTMLSelector.new(args, @selected) { nodeset document_root_element }
|
@@ -175,6 +177,7 @@ module Rails
|
|
175
177
|
nest_selection(matches, &block) if block_given? && !matches.empty?
|
176
178
|
end
|
177
179
|
end
|
180
|
+
alias_method :assert_select, :assert_dom
|
178
181
|
|
179
182
|
# Extracts the content of an element, treats it as encoded HTML and runs
|
180
183
|
# nested assertion on it.
|
@@ -187,30 +190,30 @@ module Rails
|
|
187
190
|
# element +encoded+. It then calls the block with all un-encoded elements.
|
188
191
|
#
|
189
192
|
# # Selects all bold tags from within the title of an Atom feed's entries (perhaps to nab a section name prefix)
|
190
|
-
#
|
193
|
+
# assert_dom "feed[xmlns='http://www.w3.org/2005/Atom']" do
|
191
194
|
# # Select each entry item and then the title item
|
192
|
-
#
|
195
|
+
# assert_dom "entry>title" do
|
193
196
|
# # Run assertions on the encoded title elements
|
194
|
-
#
|
195
|
-
#
|
197
|
+
# assert_dom_encoded do
|
198
|
+
# assert_dom "b"
|
196
199
|
# end
|
197
200
|
# end
|
198
201
|
# end
|
199
202
|
#
|
200
203
|
#
|
201
204
|
# # Selects all paragraph tags from within the description of an RSS feed
|
202
|
-
#
|
205
|
+
# assert_dom "rss[version=2.0]" do
|
203
206
|
# # Select description element of each feed item.
|
204
|
-
#
|
207
|
+
# assert_dom "channel>item>description" do
|
205
208
|
# # Run assertions on the encoded elements.
|
206
|
-
#
|
207
|
-
#
|
209
|
+
# assert_dom_encoded do
|
210
|
+
# assert_dom "p"
|
208
211
|
# end
|
209
212
|
# end
|
210
213
|
# end
|
211
|
-
def
|
214
|
+
def assert_dom_encoded(element = nil, &block)
|
212
215
|
if !element && !@selected
|
213
|
-
raise ArgumentError, "Element is required when called from a nonnested
|
216
|
+
raise ArgumentError, "Element is required when called from a nonnested assert_dom"
|
214
217
|
end
|
215
218
|
|
216
219
|
content = nodeset(element || @selected).map do |elem|
|
@@ -224,27 +227,28 @@ module Rails
|
|
224
227
|
if content.empty?
|
225
228
|
yield selected
|
226
229
|
else
|
227
|
-
|
230
|
+
assert_dom ":root", &block
|
228
231
|
end
|
229
232
|
end
|
230
233
|
end
|
234
|
+
alias_method :assert_select_encoded, :assert_dom_encoded
|
231
235
|
|
232
236
|
# Extracts the body of an email and runs nested assertions on it.
|
233
237
|
#
|
234
238
|
# You must enable deliveries for this assertion to work, use:
|
235
239
|
# ActionMailer::Base.perform_deliveries = true
|
236
240
|
#
|
237
|
-
#
|
238
|
-
#
|
241
|
+
# assert_dom_email do
|
242
|
+
# assert_dom "h1", "Email alert"
|
239
243
|
# end
|
240
244
|
#
|
241
|
-
#
|
242
|
-
# items =
|
245
|
+
# assert_dom_email do
|
246
|
+
# items = assert_dom "ol>li"
|
243
247
|
# items.each do
|
244
248
|
# # Work with items here...
|
245
249
|
# end
|
246
250
|
# end
|
247
|
-
def
|
251
|
+
def assert_dom_email(&block)
|
248
252
|
deliveries = ActionMailer::Base.deliveries
|
249
253
|
assert !deliveries.empty?, "No e-mail in delivery list"
|
250
254
|
|
@@ -252,25 +256,26 @@ module Rails
|
|
252
256
|
(delivery.parts.empty? ? [delivery] : delivery.parts).each do |part|
|
253
257
|
if part["Content-Type"].to_s =~ /^text\/html\W/
|
254
258
|
root = Nokogiri::HTML::DocumentFragment.parse(part.body.to_s)
|
255
|
-
|
259
|
+
assert_dom root, ":root", &block
|
256
260
|
end
|
257
261
|
end
|
258
262
|
end
|
259
263
|
end
|
264
|
+
alias_method :assert_select_email, :assert_dom_email
|
260
265
|
|
261
266
|
private
|
262
267
|
include CountDescribable
|
263
268
|
|
264
269
|
def document_root_element
|
265
270
|
raise NotImplementedError, 'Implementing document_root_element makes ' \
|
266
|
-
'
|
271
|
+
'assert_dom work without needing to specify an element to select from.'
|
267
272
|
end
|
268
273
|
|
269
274
|
# +equals+ must contain :minimum, :maximum and :count keys
|
270
275
|
def assert_size_match!(size, equals, css_selector, message = nil)
|
271
276
|
min, max, count = equals[:minimum], equals[:maximum], equals[:count]
|
272
277
|
|
273
|
-
message ||= %(Expected #{count_description(min, max, count)} matching
|
278
|
+
message ||= %(Expected #{count_description(min, max, count)} matching #{css_selector.inspect}, found #{size})
|
274
279
|
if count
|
275
280
|
assert_equal count, size, message
|
276
281
|
else
|
@@ -280,7 +285,7 @@ module Rails
|
|
280
285
|
end
|
281
286
|
|
282
287
|
def nest_selection(selection)
|
283
|
-
# Set @selected to allow nested
|
288
|
+
# Set @selected to allow nested assert_dom.
|
284
289
|
# Can be nested several levels deep.
|
285
290
|
old_selected, @selected = @selected, selection
|
286
291
|
yield @selected
|
@@ -292,6 +297,7 @@ module Rails
|
|
292
297
|
if node.is_a?(Nokogiri::XML::NodeSet)
|
293
298
|
node
|
294
299
|
else
|
300
|
+
node ||= Nokogiri::HTML::Document.new
|
295
301
|
Nokogiri::XML::NodeSet.new(node.document, [node])
|
296
302
|
end
|
297
303
|
end
|
@@ -1,18 +1,14 @@
|
|
1
|
-
require 'active_support/concern'
|
2
1
|
require 'nokogiri'
|
2
|
+
require 'rails/dom/testing/assertions/dom_assertions'
|
3
|
+
require 'rails/dom/testing/assertions/selector_assertions'
|
3
4
|
|
4
5
|
module Rails
|
5
6
|
module Dom
|
6
7
|
module Testing
|
7
8
|
module Assertions
|
8
|
-
autoload :DomAssertions, 'rails/dom/testing/assertions/dom_assertions'
|
9
|
-
autoload :SelectorAssertions, 'rails/dom/testing/assertions/selector_assertions'
|
10
|
-
|
11
|
-
extend ActiveSupport::Concern
|
12
|
-
|
13
9
|
include DomAssertions
|
14
10
|
include SelectorAssertions
|
15
11
|
end
|
16
12
|
end
|
17
13
|
end
|
18
|
-
end
|
14
|
+
end
|
data/test/dom_assertions_test.rb
CHANGED
@@ -47,4 +47,79 @@ class DomAssertionsTest < ActiveSupport::TestCase
|
|
47
47
|
%{<a><b c="2" /></a>}
|
48
48
|
)
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
|
+
def test_dom_equal_with_whitespace_strict
|
52
|
+
canonical = %{<a><b>hello</b> world</a>}
|
53
|
+
assert_dom_not_equal(canonical, %{<a>\n<b>hello\n </b> world</a>}, strict: true)
|
54
|
+
assert_dom_not_equal(canonical, %{<a> \n <b>\n hello</b> world</a>}, strict: true)
|
55
|
+
assert_dom_not_equal(canonical, %{<a>\n\t<b>hello</b> world</a>}, strict: true)
|
56
|
+
assert_dom_equal(canonical, %{<a><b>hello</b> world</a>}, strict: true)
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_dom_equal_with_whitespace
|
60
|
+
canonical = %{<a><b>hello</b> world</a>}
|
61
|
+
assert_dom_equal(canonical, %{<a>\n<b>hello\n </b> world</a>})
|
62
|
+
assert_dom_equal(canonical, %{<a>\n<b>hello </b>\nworld</a>})
|
63
|
+
assert_dom_equal(canonical, %{<a> \n <b>\n hello</b> world</a>})
|
64
|
+
assert_dom_equal(canonical, %{<a> \n <b> hello </b>world</a>})
|
65
|
+
assert_dom_equal(canonical, %{<a> \n <b>hello </b>world\n</a>\n})
|
66
|
+
assert_dom_equal(canonical, %{<a>\n\t<b>hello</b> world</a>})
|
67
|
+
assert_dom_equal(canonical, %{<a>\n\t<b>hello </b>\n\tworld</a>})
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_dom_equal_with_attribute_whitespace
|
71
|
+
canonical = %(<div data-wow="Don't strip this">)
|
72
|
+
assert_dom_equal(canonical, %(<div data-wow="Don't strip this">))
|
73
|
+
assert_dom_not_equal(canonical, %(<div data-wow="Don't strip this">))
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_dom_equal_with_indentation
|
77
|
+
canonical = %{<a>hello <b>cruel</b> world</a>}
|
78
|
+
assert_dom_equal(canonical, <<-HTML)
|
79
|
+
<a>
|
80
|
+
hello
|
81
|
+
<b>cruel</b>
|
82
|
+
world
|
83
|
+
</a>
|
84
|
+
HTML
|
85
|
+
|
86
|
+
assert_dom_equal(canonical, <<-HTML)
|
87
|
+
<a>
|
88
|
+
hello
|
89
|
+
<b>cruel</b>
|
90
|
+
world
|
91
|
+
</a>
|
92
|
+
HTML
|
93
|
+
|
94
|
+
assert_dom_equal(canonical, <<-HTML)
|
95
|
+
<a>hello
|
96
|
+
<b>
|
97
|
+
cruel
|
98
|
+
</b>
|
99
|
+
world</a>
|
100
|
+
HTML
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_dom_equal_with_surrounding_whitespace
|
104
|
+
canonical = %{<p>Lorem ipsum dolor</p><p>sit amet, consectetur adipiscing elit</p>}
|
105
|
+
assert_dom_equal(canonical, <<-HTML)
|
106
|
+
<p>
|
107
|
+
Lorem
|
108
|
+
ipsum
|
109
|
+
dolor
|
110
|
+
</p>
|
111
|
+
|
112
|
+
<p>
|
113
|
+
sit amet,
|
114
|
+
consectetur
|
115
|
+
adipiscing elit
|
116
|
+
</p>
|
117
|
+
HTML
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_dom_not_equal_with_interior_whitespace
|
121
|
+
with_space = %{<a><b>hello world</b></a>}
|
122
|
+
without_space = %{<a><b>helloworld</b></a>}
|
123
|
+
assert_dom_not_equal(with_space, without_space)
|
124
|
+
end
|
125
|
+
end
|
@@ -135,6 +135,21 @@ class AssertSelectTest < ActiveSupport::TestCase
|
|
135
135
|
end
|
136
136
|
end
|
137
137
|
|
138
|
+
def test_multiple_substitution_values
|
139
|
+
render_html '<input name="foo[12]" value="34">'
|
140
|
+
assert_select ":match('name', ?):match('value', ?)", /\w+\[\d+\]/, /\d+/
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_substitution_values_with_values_other_than_string_or_regexp
|
144
|
+
render_html %Q{<div id="id_string">symbol</div><div id="1">numeric</div>}
|
145
|
+
assert_select "div:match('id', ?)", :id_string do |elements|
|
146
|
+
assert_equal 1, elements.size
|
147
|
+
end
|
148
|
+
assert_select "div:match('id', ?)", 1 do |elements|
|
149
|
+
assert_equal 1, elements.size
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
138
153
|
def test_assert_select_root_html
|
139
154
|
render_html '<a></a>'
|
140
155
|
|
@@ -302,6 +317,24 @@ EOF
|
|
302
317
|
assert_select '.foo'
|
303
318
|
end
|
304
319
|
|
320
|
+
def test_assert_select_with_extra_argument
|
321
|
+
render_html '<html><head><title>Welcome</title></head><body><div></div></body></html>'
|
322
|
+
|
323
|
+
assert_raises ArgumentError do
|
324
|
+
assert_select "title", "Welcome", count: 1
|
325
|
+
end
|
326
|
+
|
327
|
+
assert_select "title", text: "Welcome", count: 1
|
328
|
+
end
|
329
|
+
|
330
|
+
def test_assert_select_on_blank_response
|
331
|
+
render_html ""
|
332
|
+
assert_select "div", 0
|
333
|
+
assert_failure(/Expected exactly 1 element matching \"div\", found 0./) do
|
334
|
+
assert_select "div", 1
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
305
338
|
protected
|
306
339
|
def render_html(html)
|
307
340
|
fake_render(:html, html)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-dom-testing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rafael Mendonça França
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2023-06-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|
@@ -31,14 +31,28 @@ dependencies:
|
|
31
31
|
requirements:
|
32
32
|
- - ">="
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version:
|
34
|
+
version: 5.0.0
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version:
|
41
|
+
version: 5.0.0
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: minitest
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
42
56
|
- !ruby/object:Gem::Dependency
|
43
57
|
name: bundler
|
44
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,8 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
136
|
- !ruby/object:Gem::Version
|
123
137
|
version: '0'
|
124
138
|
requirements: []
|
125
|
-
|
126
|
-
rubygems_version: 2.6.8
|
139
|
+
rubygems_version: 3.4.10
|
127
140
|
signing_key:
|
128
141
|
specification_version: 4
|
129
142
|
summary: Dom and Selector assertions for Rails applications
|