rails-dom-testing 2.0.3 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,14 +1,14 @@
1
- require 'active_support/deprecation'
2
- require_relative 'selector_assertions/count_describable'
3
- require_relative 'selector_assertions/html_selector'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "selector_assertions/html_selector"
4
4
 
5
5
  module Rails
6
6
  module Dom
7
7
  module Testing
8
8
  module Assertions
9
- # Adds the +assert_select+ method for use in Rails functional
9
+ # Adds the +assert_dom+ method for use in Rails functional
10
10
  # test cases, which can be used to make assertions on the response HTML of a controller
11
- # action. You can also call +assert_select+ within another +assert_select+ to
11
+ # action. You can also call +assert_dom+ within another +assert_dom+ to
12
12
  # make assertions on elements selected by the enclosing assertion.
13
13
  #
14
14
  # Use +css_select+ to select elements without making an assertions, either
@@ -16,261 +16,298 @@ module Rails
16
16
  #
17
17
  # In addition to HTML responses, you can make the following assertions:
18
18
  #
19
- # * +assert_select_encoded+ - Assertions on HTML encoded inside XML, for example for dealing with feed item descriptions.
20
- # * +assert_select_email+ - Assertions on the HTML body of an e-mail.
19
+ # * +assert_dom_encoded+ - Assertions on HTML encoded inside XML, for example for dealing with feed item descriptions.
20
+ # * +assert_dom_email+ - Assertions on the HTML body of an e-mail.
21
21
  module SelectorAssertions
22
+ # Select and return all matching elements.
23
+ #
24
+ # If called with a single argument, uses that argument as a selector.
25
+ # Called without an element +css_select+ selects from
26
+ # the element returned in +document_root_element+
27
+ #
28
+ # The default implementation of +document_root_element+ raises an exception explaining this.
29
+ #
30
+ # Returns an empty Nokogiri::XML::NodeSet if no match is found.
31
+ #
32
+ # If called with two arguments, uses the first argument as the root
33
+ # element and the second argument as the selector. Attempts to match the
34
+ # root element and any of its children.
35
+ # Returns an empty Nokogiri::XML::NodeSet if no match is found.
36
+ #
37
+ # The selector may be a CSS selector expression (String).
38
+ # css_select returns nil if called with an invalid css selector.
39
+ #
40
+ # # Selects all div tags
41
+ # divs = css_select("div")
42
+ #
43
+ # # Selects all paragraph tags and does something interesting
44
+ # pars = css_select("p")
45
+ # pars.each do |par|
46
+ # # Do something fun with paragraphs here...
47
+ # end
48
+ #
49
+ # # Selects all list items in unordered lists
50
+ # items = css_select("ul>li")
51
+ #
52
+ # # Selects all form tags and then all inputs inside the form
53
+ # forms = css_select("form")
54
+ # forms.each do |form|
55
+ # inputs = css_select(form, "input")
56
+ # ...
57
+ # end
58
+ def css_select(*args)
59
+ raise ArgumentError, "you at least need a selector argument" if args.empty?
22
60
 
23
- # Select and return all matching elements.
24
- #
25
- # If called with a single argument, uses that argument as a selector.
26
- # Called without an element +css_select+ selects from
27
- # the element returned in +document_root_element+
28
- #
29
- # The default implementation of +document_root_element+ raises an exception explaining this.
30
- #
31
- # Returns an empty Nokogiri::XML::NodeSet if no match is found.
32
- #
33
- # If called with two arguments, uses the first argument as the root
34
- # element and the second argument as the selector. Attempts to match the
35
- # root element and any of its children.
36
- # Returns an empty Nokogiri::XML::NodeSet if no match is found.
37
- #
38
- # The selector may be a CSS selector expression (String).
39
- # css_select returns nil if called with an invalid css selector.
40
- #
41
- # # Selects all div tags
42
- # divs = css_select("div")
43
- #
44
- # # Selects all paragraph tags and does something interesting
45
- # pars = css_select("p")
46
- # pars.each do |par|
47
- # # Do something fun with paragraphs here...
48
- # end
49
- #
50
- # # Selects all list items in unordered lists
51
- # items = css_select("ul>li")
52
- #
53
- # # Selects all form tags and then all inputs inside the form
54
- # forms = css_select("form")
55
- # forms.each do |form|
56
- # inputs = css_select(form, "input")
57
- # ...
58
- # end
59
- def css_select(*args)
60
- raise ArgumentError, "you at least need a selector argument" if args.empty?
61
+ root = args.size == 1 ? document_root_element : args.shift
61
62
 
62
- root = args.size == 1 ? document_root_element : args.shift
63
+ nodeset(root).css(args.first)
64
+ end
63
65
 
64
- nodeset(root).css(args.first)
65
- end
66
+ # An assertion that selects elements and makes one or more equality tests.
67
+ #
68
+ # If the first argument is an element, selects all matching elements
69
+ # starting from (and including) that element and all its children in
70
+ # depth-first order.
71
+ #
72
+ # If no element is specified +assert_dom+ selects from
73
+ # the element returned in +document_root_element+
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.
76
+ # The default implementation raises an exception explaining this.
77
+ #
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,
80
+ # runs the assertion on the complete set of elements selected by the enclosing assertion.
81
+ # Alternatively the array may be iterated through so that +assert_dom+ can be called
82
+ # separately for each element.
83
+ #
84
+ #
85
+ # ==== Example
86
+ # If the response contains two ordered lists, each with four list elements then:
87
+ # assert_dom "ol" do |elements|
88
+ # elements.each do |element|
89
+ # assert_dom element, "li", 4
90
+ # end
91
+ # end
92
+ #
93
+ # will pass, as will:
94
+ # assert_dom "ol" do
95
+ # assert_dom "li", 8
96
+ # end
97
+ #
98
+ # The selector may be a CSS selector expression (String, Symbol, or Numeric) or an expression
99
+ # with substitution values (Array).
100
+ # Substitution uses a custom pseudo class match. Pass in whatever attribute you want to match (enclosed in quotes) and a ? for the substitution.
101
+ # assert_dom returns nil if called with an invalid css selector.
102
+ #
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+/
107
+ #
108
+ # === Equality Tests
109
+ #
110
+ # The equality test may be one of the following:
111
+ # * <tt>true</tt> - Assertion is true if at least one element selected.
112
+ # * <tt>false</tt> - Assertion is true if no element selected.
113
+ # * <tt>String/Regexp</tt> - Assertion is true if the text value of at least
114
+ # one element matches the string or regular expression.
115
+ # * <tt>Integer</tt> - Assertion is true if exactly that number of
116
+ # elements are selected.
117
+ # * <tt>Range</tt> - Assertion is true if the number of selected
118
+ # elements fit the range.
119
+ # If no equality test specified, the assertion is true if at least one
120
+ # element selected.
121
+ #
122
+ # To perform more than one equality tests, use a hash with the following keys:
123
+ # * <tt>:text</tt> - Narrow the selection to elements that have this text
124
+ # value (string or regexp).
125
+ # * <tt>:html</tt> - Narrow the selection to elements that have this HTML
126
+ # content (string or regexp).
127
+ # * <tt>:count</tt> - Assertion is true if the number of selected elements
128
+ # is equal to this value.
129
+ # * <tt>:minimum</tt> - Assertion is true if the number of selected
130
+ # elements is at least this value.
131
+ # * <tt>:maximum</tt> - Assertion is true if the number of selected
132
+ # elements is at most this value.
133
+ #
134
+ # If the method is called with a block, once all equality tests are
135
+ # evaluated the block is called with an array of all matched elements.
136
+ #
137
+ # # At least one form element
138
+ # assert_dom "form"
139
+ #
140
+ # # Form element includes four input fields
141
+ # assert_dom "form input", 4
142
+ #
143
+ # # Page title is "Welcome"
144
+ # assert_dom "title", "Welcome"
145
+ #
146
+ # # Page title is "Welcome" and there is only one title element
147
+ # assert_dom "title", {count: 1, text: "Welcome"},
148
+ # "Wrong title or more than one title element"
149
+ #
150
+ # # Page contains no forms
151
+ # assert_dom "form", false, "This page must contain no forms"
152
+ #
153
+ # # Test the content and style
154
+ # assert_dom "body div.header ul.menu"
155
+ #
156
+ # # Use substitution values
157
+ # assert_dom "ol>li:match('id', ?)", /item-\d+/
158
+ #
159
+ # # All input fields in the form have a name
160
+ # assert_dom "form input" do
161
+ # assert_dom ":match('name', ?)", /.+/ # Not empty
162
+ # end
163
+ def assert_dom(*args, &block)
164
+ @selected ||= nil
66
165
 
67
- # An assertion that selects elements and makes one or more equality tests.
68
- #
69
- # If the first argument is an element, selects all matching elements
70
- # starting from (and including) that element and all its children in
71
- # depth-first order.
72
- #
73
- # If no element is specified +assert_select+ selects from
74
- # the element returned in +document_root_element+
75
- # unless +assert_select+ is called from within an +assert_select+ block.
76
- # Override +document_root_element+ to tell +assert_select+ what to select from.
77
- # The default implementation raises an exception explaining this.
78
- #
79
- # When called with a block +assert_select+ passes an array of selected elements
80
- # to the block. Calling +assert_select+ from the block, with no element specified,
81
- # runs the assertion on the complete set of elements selected by the enclosing assertion.
82
- # Alternatively the array may be iterated through so that +assert_select+ can be called
83
- # separately for each element.
84
- #
85
- #
86
- # ==== Example
87
- # If the response contains two ordered lists, each with four list elements then:
88
- # assert_select "ol" do |elements|
89
- # elements.each do |element|
90
- # assert_select element, "li", 4
91
- # end
92
- # end
93
- #
94
- # will pass, as will:
95
- # assert_select "ol" do
96
- # assert_select "li", 8
97
- # end
98
- #
99
- # The selector may be a CSS selector expression (String) or an expression
100
- # with substitution values (Array).
101
- # Substitution uses a custom pseudo class match. Pass in whatever attribute you want to match (enclosed in quotes) and a ? for the substitution.
102
- # assert_select returns nil if called with an invalid css selector.
103
- #
104
- # assert_select "div:match('id', ?)", /\d+/
105
- #
106
- # === Equality Tests
107
- #
108
- # The equality test may be one of the following:
109
- # * <tt>true</tt> - Assertion is true if at least one element selected.
110
- # * <tt>false</tt> - Assertion is true if no element selected.
111
- # * <tt>String/Regexp</tt> - Assertion is true if the text value of at least
112
- # one element matches the string or regular expression.
113
- # * <tt>Integer</tt> - Assertion is true if exactly that number of
114
- # elements are selected.
115
- # * <tt>Range</tt> - Assertion is true if the number of selected
116
- # elements fit the range.
117
- # If no equality test specified, the assertion is true if at least one
118
- # element selected.
119
- #
120
- # To perform more than one equality tests, use a hash with the following keys:
121
- # * <tt>:text</tt> - Narrow the selection to elements that have this text
122
- # value (string or regexp).
123
- # * <tt>:html</tt> - Narrow the selection to elements that have this HTML
124
- # content (string or regexp).
125
- # * <tt>:count</tt> - Assertion is true if the number of selected elements
126
- # is equal to this value.
127
- # * <tt>:minimum</tt> - Assertion is true if the number of selected
128
- # elements is at least this value.
129
- # * <tt>:maximum</tt> - Assertion is true if the number of selected
130
- # elements is at most this value.
131
- #
132
- # If the method is called with a block, once all equality tests are
133
- # evaluated the block is called with an array of all matched elements.
134
- #
135
- # # At least one form element
136
- # assert_select "form"
137
- #
138
- # # Form element includes four input fields
139
- # assert_select "form input", 4
140
- #
141
- # # Page title is "Welcome"
142
- # assert_select "title", "Welcome"
143
- #
144
- # # Page title is "Welcome" and there is only one title element
145
- # assert_select "title", {count: 1, text: "Welcome"},
146
- # "Wrong title or more than one title element"
147
- #
148
- # # Page contains no forms
149
- # assert_select "form", false, "This page must contain no forms"
150
- #
151
- # # Test the content and style
152
- # assert_select "body div.header ul.menu"
153
- #
154
- # # Use substitution values
155
- # assert_select "ol>li:match('id', ?)", /item-\d+/
156
- #
157
- # # All input fields in the form have a name
158
- # assert_select "form input" do
159
- # assert_select ":match('name', ?)", /.+/ # Not empty
160
- # end
161
- def assert_select(*args, &block)
162
- @selected ||= nil
163
-
164
- selector = HTMLSelector.new(args, @selected) { nodeset document_root_element }
166
+ selector = HTMLSelector.new(args, @selected) { nodeset document_root_element }
165
167
 
166
- if selector.selecting_no_body?
167
- assert true
168
- return
169
- end
168
+ if selector.selecting_no_body?
169
+ assert true
170
+ return
171
+ end
170
172
 
171
- selector.select.tap do |matches|
172
- assert_size_match!(matches.size, selector.tests,
173
- selector.css_selector, selector.message)
173
+ selector.select.tap do |matches|
174
+ assert_size_match!(matches.size, selector.tests,
175
+ selector.css_selector, selector.message)
174
176
 
175
- nest_selection(matches, &block) if block_given? && !matches.empty?
177
+ nest_selection(matches, &block) if block_given? && !matches.empty?
178
+ end
176
179
  end
177
- end
180
+ alias_method :assert_select, :assert_dom
178
181
 
179
- # Extracts the content of an element, treats it as encoded HTML and runs
180
- # nested assertion on it.
181
- #
182
- # You typically call this method within another assertion to operate on
183
- # all currently selected elements. You can also pass an element or array
184
- # of elements.
185
- #
186
- # The content of each element is un-encoded, and wrapped in the root
187
- # element +encoded+. It then calls the block with all un-encoded elements.
188
- #
189
- # # Selects all bold tags from within the title of an Atom feed's entries (perhaps to nab a section name prefix)
190
- # assert_select "feed[xmlns='http://www.w3.org/2005/Atom']" do
191
- # # Select each entry item and then the title item
192
- # assert_select "entry>title" do
193
- # # Run assertions on the encoded title elements
194
- # assert_select_encoded do
195
- # assert_select "b"
196
- # end
197
- # end
198
- # end
199
- #
200
- #
201
- # # Selects all paragraph tags from within the description of an RSS feed
202
- # assert_select "rss[version=2.0]" do
203
- # # Select description element of each feed item.
204
- # assert_select "channel>item>description" do
205
- # # Run assertions on the encoded elements.
206
- # assert_select_encoded do
207
- # assert_select "p"
208
- # end
209
- # end
210
- # end
211
- def assert_select_encoded(element = nil, &block)
212
- if !element && !@selected
213
- raise ArgumentError, "Element is required when called from a nonnested assert_select"
214
- end
182
+ # Extracts the content of an element, treats it as encoded HTML and runs
183
+ # nested assertion on it.
184
+ #
185
+ # You typically call this method within another assertion to operate on
186
+ # all currently selected elements. You can also pass an element or array
187
+ # of elements.
188
+ #
189
+ # The content of each element is un-encoded, and wrapped in the root
190
+ # element +encoded+. It then calls the block with all un-encoded elements.
191
+ #
192
+ # # Selects all bold tags from within the title of an Atom feed's entries (perhaps to nab a section name prefix)
193
+ # assert_dom "feed[xmlns='http://www.w3.org/2005/Atom']" do
194
+ # # Select each entry item and then the title item
195
+ # assert_dom "entry>title" do
196
+ # # Run assertions on the encoded title elements
197
+ # assert_dom_encoded do
198
+ # assert_dom "b"
199
+ # end
200
+ # end
201
+ # end
202
+ #
203
+ #
204
+ # # Selects all paragraph tags from within the description of an RSS feed
205
+ # assert_dom "rss[version=2.0]" do
206
+ # # Select description element of each feed item.
207
+ # assert_dom "channel>item>description" do
208
+ # # Run assertions on the encoded elements.
209
+ # assert_dom_encoded do
210
+ # assert_dom "p"
211
+ # end
212
+ # end
213
+ # end
214
+ #
215
+ # The DOM is created using an HTML parser specified by
216
+ # Rails::Dom::Testing.default_html_version (either :html4 or :html5).
217
+ #
218
+ # When testing in a Rails application, the parser default can also be set by setting
219
+ # +Rails.application.config.dom_testing_default_html_version+.
220
+ #
221
+ # If you want to specify the HTML parser just for a particular assertion, pass
222
+ # <tt>html_version: :html4</tt> or <tt>html_version: :html5</tt> keyword arguments:
223
+ #
224
+ # assert_dom "feed[xmlns='http://www.w3.org/2005/Atom']" do
225
+ # assert_dom "entry>title" do
226
+ # assert_dom_encoded(html_version: :html5) do
227
+ # assert_dom "b"
228
+ # end
229
+ # end
230
+ # end
231
+ #
232
+ def assert_dom_encoded(element = nil, html_version: nil, &block)
233
+ if !element && !@selected
234
+ raise ArgumentError, "Element is required when called from a nonnested assert_dom"
235
+ end
215
236
 
216
- content = nodeset(element || @selected).map do |elem|
217
- elem.children.select do |child|
218
- child.cdata? || (child.text? && !child.blank?)
219
- end.map(&:content)
220
- end.join
237
+ content = nodeset(element || @selected).map do |elem|
238
+ elem.children.select do |child|
239
+ child.cdata? || (child.text? && !child.blank?)
240
+ end.map(&:content)
241
+ end.join
221
242
 
222
- selected = Nokogiri::HTML::DocumentFragment.parse(content)
223
- nest_selection(selected) do
224
- if content.empty?
225
- yield selected
226
- else
227
- assert_select ":root", &block
243
+ selected = Rails::Dom::Testing.html_document_fragment(html_version: html_version).parse(content)
244
+ nest_selection(selected) do
245
+ if content.empty?
246
+ yield selected
247
+ else
248
+ assert_dom ":root", &block
249
+ end
228
250
  end
229
251
  end
230
- end
252
+ alias_method :assert_select_encoded, :assert_dom_encoded
231
253
 
232
- # Extracts the body of an email and runs nested assertions on it.
233
- #
234
- # You must enable deliveries for this assertion to work, use:
235
- # ActionMailer::Base.perform_deliveries = true
236
- #
237
- # assert_select_email do
238
- # assert_select "h1", "Email alert"
239
- # end
240
- #
241
- # assert_select_email do
242
- # items = assert_select "ol>li"
243
- # items.each do
244
- # # Work with items here...
245
- # end
246
- # end
247
- def assert_select_email(&block)
248
- deliveries = ActionMailer::Base.deliveries
249
- assert !deliveries.empty?, "No e-mail in delivery list"
254
+ # Extracts the body of an email and runs nested assertions on it.
255
+ #
256
+ # You must enable deliveries for this assertion to work, use:
257
+ # ActionMailer::Base.perform_deliveries = true
258
+ #
259
+ # Example usage:
260
+ #
261
+ # assert_dom_email do
262
+ # assert_dom "h1", "Email alert"
263
+ # end
264
+ #
265
+ # assert_dom_email do
266
+ # items = assert_dom "ol>li"
267
+ # items.each do
268
+ # # Work with items here...
269
+ # end
270
+ # end
271
+ #
272
+ # The DOM is created using an HTML parser specified by
273
+ # Rails::Dom::Testing.default_html_version (either :html4 or :html5).
274
+ #
275
+ # When testing in a Rails application, the parser default can also be set by setting
276
+ # +Rails.application.config.dom_testing_default_html_version+.
277
+ #
278
+ # If you want to specify the HTML parser just for a particular assertion, pass
279
+ # <tt>html_version: :html4</tt> or <tt>html_version: :html5</tt> keyword arguments:
280
+ #
281
+ # assert_dom_email(html_version: :html5) do
282
+ # assert_dom "h1", "Email alert"
283
+ # end
284
+ #
285
+ def assert_dom_email(html_version: nil, &block)
286
+ deliveries = ActionMailer::Base.deliveries
287
+ assert !deliveries.empty?, "No e-mail in delivery list"
250
288
 
251
- deliveries.each do |delivery|
252
- (delivery.parts.empty? ? [delivery] : delivery.parts).each do |part|
253
- if part["Content-Type"].to_s =~ /^text\/html\W/
254
- root = Nokogiri::HTML::DocumentFragment.parse(part.body.to_s)
255
- assert_select root, ":root", &block
289
+ deliveries.each do |delivery|
290
+ (delivery.parts.empty? ? [delivery] : delivery.parts).each do |part|
291
+ if /^text\/html\W/.match?(part["Content-Type"].to_s)
292
+ root = Rails::Dom::Testing.html_document_fragment(html_version: html_version).parse(part.body.to_s)
293
+ assert_dom root, ":root", &block
294
+ end
256
295
  end
257
296
  end
258
297
  end
259
- end
298
+ alias_method :assert_select_email, :assert_dom_email
260
299
 
261
300
  private
262
- include CountDescribable
263
-
264
301
  def document_root_element
265
- raise NotImplementedError, 'Implementing document_root_element makes ' \
266
- 'assert_select work without needing to specify an element to select from.'
302
+ raise NotImplementedError, "Implementing document_root_element makes " \
303
+ "assert_dom work without needing to specify an element to select from."
267
304
  end
268
305
 
269
306
  # +equals+ must contain :minimum, :maximum and :count keys
270
307
  def assert_size_match!(size, equals, css_selector, message = nil)
271
308
  min, max, count = equals[:minimum], equals[:maximum], equals[:count]
272
309
 
273
- message ||= %(Expected #{count_description(min, max, count)} matching "#{css_selector}", found #{size}.)
310
+ message ||= %(Expected #{count_description(min, max, count)} matching #{css_selector.inspect}, found #{size})
274
311
  if count
275
312
  assert_equal count, size, message
276
313
  else
@@ -279,8 +316,24 @@ module Rails
279
316
  end
280
317
  end
281
318
 
319
+ def count_description(min, max, count)
320
+ if min && max && (max != min)
321
+ "between #{min} and #{max} elements"
322
+ elsif min && max && max == min && count
323
+ "exactly #{count} #{pluralize_element(min)}"
324
+ elsif min && !(min == 1 && max == 1)
325
+ "at least #{min} #{pluralize_element(min)}"
326
+ elsif max
327
+ "at most #{max} #{pluralize_element(max)}"
328
+ end
329
+ end
330
+
331
+ def pluralize_element(quantity)
332
+ quantity == 1 ? "element" : "elements"
333
+ end
334
+
282
335
  def nest_selection(selection)
283
- # Set @selected to allow nested assert_select.
336
+ # Set @selected to allow nested assert_dom.
284
337
  # Can be nested several levels deep.
285
338
  old_selected, @selected = @selected, selection
286
339
  yield @selected
@@ -292,6 +345,7 @@ module Rails
292
345
  if node.is_a?(Nokogiri::XML::NodeSet)
293
346
  node
294
347
  else
348
+ node ||= Nokogiri::HTML::Document.new
295
349
  Nokogiri::XML::NodeSet.new(node.document, [node])
296
350
  end
297
351
  end
@@ -1,18 +1,15 @@
1
- require 'active_support/concern'
2
- require 'nokogiri'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "assertions/dom_assertions"
4
+ require_relative "assertions/selector_assertions"
3
5
 
4
6
  module Rails
5
7
  module Dom
6
8
  module Testing
7
9
  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
10
  include DomAssertions
14
11
  include SelectorAssertions
15
12
  end
16
13
  end
17
14
  end
18
- end
15
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails
4
+ module Dom
5
+ module Testing
6
+ class Railtie < Rails::Railtie # :nodoc:
7
+ config.after_initialize do |app|
8
+ version = app.config.try(:dom_testing_default_html_version) # Rails 7.1+
9
+ Rails::Dom::Testing.default_html_version = version if version
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rails
2
4
  module Dom
3
5
  module Testing
4
- VERSION = "2.0.3"
6
+ VERSION = "2.2.0"
5
7
  end
6
8
  end
7
9
  end