rails-dom-testing 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d8720c7b560a8e3acaa5ae87a7dbfb587fe47c156d8f49b9d319b2c089a3d987
4
- data.tar.gz: f482fcae81574f5fedc71d6e46ce372f8f273eac9df50a40d565696db1a02209
3
+ metadata.gz: 92842b3fcd4006daf9f8047da3d90a171ead6f39900c2d4f491d3c3ac0658845
4
+ data.tar.gz: 67b13526065e8c54acc109945f9566947f1976c601e44bb2295eaab79d7fcfe4
5
5
  SHA512:
6
- metadata.gz: bb404e501783f50dfd614101ee141ccc08665e2410fbd3c2e62c6859e4ed2edd2097169373b86d6deaefb63192385cf895d1ae0c512c69f65de760d38a8b6542
7
- data.tar.gz: afc3f0247a26905b8aeb37fd94a9a0bd79f09b2ed334b539129f9566d3c25aed44e0e3a6a34f73c4ad0c6c485a24ae30e205b0aac14ff7e60b942be5d32d7663
6
+ metadata.gz: d16235fedf30e46ccc6f0fc4463f567917d12084d6d8a0b67cfce316ae7cdd5100b78d84f314e856ff56904e4ffa628628e0c2b5fee11cf1b287ddffdb04431c
7
+ data.tar.gz: 93e996ac52d49ead86b8a04ae43299303c3c02231adc0911158142e7defb49e5afc3b4584f66bb437e9983d910fc70f8bacdddfb79f648c8f1f27cd003532b87
data/README.md CHANGED
@@ -24,6 +24,9 @@ css_select '.hello' # => Nokogiri::XML::NodeSet of elements with hello class
24
24
  # select from a supplied node. assert_dom asserts elements exist.
25
25
  assert_dom document_root_element.at('.hello'), '.goodbye'
26
26
 
27
+ # select from a supplied node. assert_not_dom asserts elements do not exist.
28
+ assert_not_dom document_root_element.at('.hello'), '.goodbye'
29
+
27
30
  # elements in CDATA encoded sections can also be selected
28
31
  assert_dom_encoded '#out-of-your-element'
29
32
 
@@ -70,6 +70,7 @@ module Rails
70
70
  message ||= "Expected: #{expected}\nActual: #{actual}"
71
71
  assert_not compare_doms(expected_dom, actual_dom, strict), message
72
72
  end
73
+ alias_method :refute_dom_equal, :assert_dom_not_equal
73
74
 
74
75
  protected
75
76
  def compare_doms(expected, actual, strict)
@@ -14,11 +14,11 @@ module Rails
14
14
 
15
15
  include Minitest::Assertions
16
16
 
17
- def initialize(values, previous_selection = nil, &root_fallback)
17
+ def initialize(values, previous_selection = nil, refute: false, &root_fallback)
18
18
  @values = values
19
19
  @root = extract_root(previous_selection, root_fallback)
20
20
  extract_selectors
21
- @tests = extract_equality_tests
21
+ @tests = extract_equality_tests(refute)
22
22
  @message = @values.shift
23
23
 
24
24
  if @message.is_a?(Hash)
@@ -51,14 +51,16 @@ module Rails
51
51
 
52
52
  content_mismatch = nil
53
53
  text_matches = tests.has_key?(:text)
54
+ html_matches = tests.has_key?(:html)
54
55
  regex_matching = match_with.is_a?(Regexp)
55
56
 
56
57
  remaining = matches.reject do |match|
57
58
  # Preserve markup with to_s for html elements
58
- content = text_matches ? match.text : match.children.to_s
59
+ content = text_matches ? match.text : match.inner_html
59
60
 
60
61
  content.strip! unless NO_STRIP.include?(match.name)
61
62
  content.delete_prefix!("\n") if text_matches && match.name == "textarea"
63
+ collapse_html_whitespace!(content) unless NO_STRIP.include?(match.name) || html_matches
62
64
 
63
65
  next if regex_matching ? (content =~ match_with) : (content == match_with)
64
66
  content_mismatch ||= diff(match_with, content)
@@ -97,7 +99,7 @@ module Rails
97
99
  @selector = context.substitute!(selector, @values)
98
100
  end
99
101
 
100
- def extract_equality_tests
102
+ def extract_equality_tests(refute)
101
103
  comparisons = {}
102
104
  case comparator = @values.shift
103
105
  when Hash
@@ -113,7 +115,16 @@ module Rails
113
115
  comparisons[:count] = 0
114
116
  when NilClass, TrueClass
115
117
  comparisons[:minimum] = 1
116
- else raise ArgumentError, "I don't understand what you're trying to match"
118
+ else
119
+ raise ArgumentError, "I don't understand what you're trying to match"
120
+ end
121
+
122
+ if refute
123
+ if comparisons[:count] || (comparisons[:minimum] && !comparator.nil?) || comparisons[:maximum]
124
+ raise ArgumentError, "Cannot use true, false, Integer, Range, :count, :minimum and :maximum when asserting that a selector does not match"
125
+ end
126
+
127
+ comparisons[:count] = 0
117
128
  end
118
129
 
119
130
  # By default we're looking for at least one match.
@@ -122,8 +133,19 @@ module Rails
122
133
  else
123
134
  comparisons[:minimum] ||= 1
124
135
  end
136
+
137
+ if comparisons[:minimum] && comparisons[:maximum] && comparisons[:minimum] > comparisons[:maximum]
138
+ raise ArgumentError, "Range begin or :minimum cannot be greater than Range end or :maximum"
139
+ end
140
+
141
+ @strict = comparisons[:strict]
142
+
125
143
  comparisons
126
144
  end
145
+
146
+ def collapse_html_whitespace!(text)
147
+ text.gsub!(/\s+/, " ")
148
+ end
127
149
  end
128
150
  end
129
151
  end
@@ -164,20 +164,53 @@ module Rails
164
164
  @selected ||= nil
165
165
 
166
166
  selector = HTMLSelector.new(args, @selected) { nodeset document_root_element }
167
+ dom_assertions(selector, &block)
168
+ end
169
+ alias_method :assert_select, :assert_dom
170
+
171
+ # The negated form of +assert_dom+.
172
+ #
173
+ # === Equality Tests
174
+ #
175
+ # Supports the same equality tests as +assert_dom+ except for:
176
+ # * <tt>true</tt>
177
+ # * <tt>false</tt>
178
+ # * <tt>Integer</tt>
179
+ # * <tt>Range</tt>
180
+ # * <tt>:count</tt>
181
+ # * <tt>:minimum</tt>
182
+ # * <tt>:maximum</tt>
183
+ def assert_not_dom(*args, &block)
184
+ @selected ||= nil
167
185
 
186
+ selector = HTMLSelector.new(args, @selected, refute: true) { nodeset document_root_element }
187
+ dom_assertions(selector, &block)
188
+ end
189
+ alias_method :refute_dom, :assert_not_dom
190
+ alias_method :assert_not_select, :assert_not_dom
191
+ alias_method :refute_select, :assert_not_dom
192
+
193
+ private def dom_assertions(selector, &block)
168
194
  if selector.selecting_no_body?
169
195
  assert true
170
196
  return
171
197
  end
172
198
 
199
+ count, max = selector.tests.slice(:count, :maximum).values
200
+
173
201
  selector.select.tap do |matches|
174
202
  assert_size_match!(matches.size, selector.tests,
175
203
  selector.css_selector, selector.message)
176
204
 
177
- nest_selection(matches, &block) if block_given? && !matches.empty?
205
+ if block_given?
206
+ if count&.zero? || max&.zero?
207
+ raise ArgumentError, "Cannot be called with a block when asserting that a selector does not match"
208
+ end
209
+
210
+ nest_selection(matches, &block) unless matches.empty?
211
+ end
178
212
  end
179
213
  end
180
- alias_method :assert_select, :assert_dom
181
214
 
182
215
  # Extracts the content of an element, treats it as encoded HTML and runs
183
216
  # nested assertion on it.
@@ -3,7 +3,7 @@
3
3
  module Rails
4
4
  module Dom
5
5
  module Testing
6
- VERSION = "2.2.0"
6
+ VERSION = "2.3.0"
7
7
  end
8
8
  end
9
9
  end
@@ -16,7 +16,7 @@ class AssertSelectTest < ActiveSupport::TestCase
16
16
  end
17
17
 
18
18
  #
19
- # Test assert select.
19
+ # Test assert_select.
20
20
  #
21
21
 
22
22
  def test_assert_select
@@ -122,6 +122,19 @@ class AssertSelectTest < ActiveSupport::TestCase
122
122
  end
123
123
  end
124
124
 
125
+ def test_zero_counts_with_block
126
+ render_html "<div>foo</div>"
127
+
128
+ errors = [
129
+ assert_raises(ArgumentError) { assert_select("p", false) { nil } },
130
+ assert_raises(ArgumentError) { assert_select("p", 0) { nil } },
131
+ assert_raises(ArgumentError) { assert_select("p", count: 0) { nil } },
132
+ assert_raises(ArgumentError) { assert_select("p", 0..0) { nil } },
133
+ assert_raises(ArgumentError) { assert_select("p", minimum: 0, maximum: 0) { nil } }
134
+ ]
135
+ assert_equal ["Cannot be called with a block when asserting that a selector does not match"], errors.map(&:message).uniq
136
+ end
137
+
125
138
  def test_substitution_values
126
139
  render_html '<div id="1">foo</div><div id="2">foo</div>'
127
140
  assert_select "div:match('id', ?)", /\d+/ do |elements|
@@ -210,6 +223,115 @@ class AssertSelectTest < ActiveSupport::TestCase
210
223
  end
211
224
  end
212
225
 
226
+ def test_assert_select_with_invalid_range
227
+ render_html "<div>foo</div>"
228
+ error = assert_raises(ArgumentError) { assert_select("div", 2..1) { nil } }
229
+ assert_equal "Range begin or :minimum cannot be greater than Range end or :maximum", error.message
230
+ end
231
+
232
+ def test_assert_select_with_invalid_minimum_and_maximum
233
+ render_html "<div>foo</div>"
234
+ error = assert_raises(ArgumentError) { assert_select("div", maximum: 0) { nil } }
235
+ assert_equal "Range begin or :minimum cannot be greater than Range end or :maximum", error.message
236
+ error = assert_raises(ArgumentError) { assert_select("div", minimum: 2, maximum: 1) { nil } }
237
+ assert_equal "Range begin or :minimum cannot be greater than Range end or :maximum", error.message
238
+ end
239
+
240
+ def test_assert_select_text_equality_collapses_whitespace
241
+ render_html "<p>Some\n line-broken\n text</p>"
242
+
243
+ assert_nothing_raised do
244
+ assert_select "p", {
245
+ text: "Some line-broken text",
246
+ }, "Whitespace was not collapsed from text"
247
+ end
248
+
249
+ render_html "<p>Some<br><br>line-broken<br><br>text</p>"
250
+
251
+ assert_nothing_raised do
252
+ assert_select "p", {
253
+ text: "Someline-brokentext",
254
+ }, "<br> was not removed from text"
255
+ end
256
+ end
257
+
258
+ def test_assert_select_html_equality_respects_whitespace
259
+ render_html "<p>Some\n line-broken\n text</p>"
260
+
261
+ assert_nothing_raised do
262
+ assert_select "p", {
263
+ html: "Some\n line-broken\n text",
264
+ }, "Whitespace was collapsed from html"
265
+ end
266
+
267
+ render_html "<p>Some<br><br>line-broken<br><br>text</p>"
268
+
269
+ assert_nothing_raised do
270
+ assert_select "p", {
271
+ html: "Some<br><br>line-broken<br><br>text",
272
+ }, "<br> was removed from html"
273
+ end
274
+ end
275
+
276
+ #
277
+ # Test assert_not_select.
278
+ #
279
+
280
+ def test_assert_not_select
281
+ render_html '<div id="1"></div>'
282
+ assert_not_select "p"
283
+ assert_failure(/Expected exactly 0 elements matching "div", found 1/) { assert_not_select "div" }
284
+ assert_failure(/Expected exactly 0 elements matching "div#1", found 1/) { assert_not_select "div#1" }
285
+ end
286
+
287
+ def test_assert_not_select_with_true
288
+ render_html '<div id="1"></div>'
289
+ error = assert_raises(ArgumentError) { assert_not_select "div", true }
290
+ assert_equal "Cannot use true, false, Integer, Range, :count, :minimum and :maximum when asserting that a selector does not match", error.message
291
+ end
292
+
293
+ def test_assert_not_select_with_false
294
+ render_html '<div id="1"></div>'
295
+ error = assert_raises(ArgumentError) { assert_not_select "div", false }
296
+ assert_equal "Cannot use true, false, Integer, Range, :count, :minimum and :maximum when asserting that a selector does not match", error.message
297
+ end
298
+
299
+ def test_assert_not_select_with_integer
300
+ render_html '<div id="1"></div>'
301
+ error = assert_raises(ArgumentError) { assert_not_select "div", 1 }
302
+ assert_equal "Cannot use true, false, Integer, Range, :count, :minimum and :maximum when asserting that a selector does not match", error.message
303
+ end
304
+
305
+ def test_assert_not_select_with_range
306
+ render_html '<div id="1"></div>'
307
+ error = assert_raises(ArgumentError) { assert_not_select "div", 1..5 }
308
+ assert_equal "Cannot use true, false, Integer, Range, :count, :minimum and :maximum when asserting that a selector does not match", error.message
309
+ end
310
+
311
+ def test_assert_not_select_with_count
312
+ render_html '<div id="1"></div>'
313
+ error = assert_raises(ArgumentError) { assert_not_select "div", count: 1 }
314
+ assert_equal "Cannot use true, false, Integer, Range, :count, :minimum and :maximum when asserting that a selector does not match", error.message
315
+ end
316
+
317
+ def test_assert_not_select_with_minimum
318
+ render_html '<div id="1"></div>'
319
+ error = assert_raises(ArgumentError) { assert_not_select "div", minimum: 1 }
320
+ assert_equal "Cannot use true, false, Integer, Range, :count, :minimum and :maximum when asserting that a selector does not match", error.message
321
+ end
322
+
323
+ def test_assert_not_select_with_maximum
324
+ render_html '<div id="1"></div>'
325
+ error = assert_raises(ArgumentError) { assert_not_select "div", maximum: 1 }
326
+ assert_equal "Cannot use true, false, Integer, Range, :count, :minimum and :maximum when asserting that a selector does not match", error.message
327
+ end
328
+
329
+ def test_assert_not_select_with_block
330
+ render_html "<div>foo</div>"
331
+ error = assert_raises(ArgumentError) { assert_not_select("p") { nil } }
332
+ assert_equal "Cannot be called with a block when asserting that a selector does not match", error.message
333
+ end
334
+
213
335
  #
214
336
  # Test css_select.
215
337
  #
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-dom-testing
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rafael Mendonça França
8
8
  - Kasper Timm Hansen
9
- autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2023-08-03 00:00:00.000000000 Z
11
+ date: 1980-01-02 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: activesupport
@@ -95,7 +94,6 @@ homepage: https://github.com/rails/rails-dom-testing
95
94
  licenses:
96
95
  - MIT
97
96
  metadata: {}
98
- post_install_message:
99
97
  rdoc_options: []
100
98
  require_paths:
101
99
  - lib
@@ -110,8 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
108
  - !ruby/object:Gem::Version
111
109
  version: '0'
112
110
  requirements: []
113
- rubygems_version: 3.4.10
114
- signing_key:
111
+ rubygems_version: 3.6.7
115
112
  specification_version: 4
116
113
  summary: Dom and Selector assertions for Rails applications
117
114
  test_files: