New Upstream Snapshot - ruby-rails-dom-testing

Ready changes

Summary

Merged new upstream version: 2.0.3+git20220714.1.8deceed (was: 2.0.3).

Resulting package

Built on 2023-01-07T17:16 (took 4m44s)

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-snapshots ruby-rails-dom-testing

Lintian Result

Diff

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..f75d5c4
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,99 @@
+Contributing to Rails::Dom::Testing
+=====================
+
+[![Build Status](https://travis-ci.org/rails/rails-dom-testing.svg?branch=master)](https://travis-ci.org/rails/rails-dom-testing)
+
+Rails::Dom::Testing is work of [many contributors](https://github.com/rails/rails-dom-testing/graphs/contributors). You're encouraged to submit [pull requests](https://github.com/rails/rails-dom-testing/pulls), [propose features and discuss issues](https://github.com/rails/rails-dom-testing/issues).
+
+#### Fork the Project
+
+Fork the [project on Github](https://github.com/rails/rails-dom-testing) and check out your copy.
+
+```
+git clone https://github.com/contributor/rails-dom-testing.git
+cd rails-dom-testing
+git remote add upstream https://github.com/rails/rails-dom-testing.git
+```
+
+#### Create a Topic Branch
+
+Make sure your fork is up-to-date and create a topic branch for your feature or bug fix.
+
+```
+git checkout master
+git pull upstream master
+git checkout -b my-feature-branch
+```
+
+#### Bundle Install and Test
+
+Ensure that you can build the project and run tests.
+
+```
+bundle install
+bundle exec rake test
+```
+
+#### Write Tests
+
+Try to write a test that reproduces the problem you're trying to fix or describes a feature that you want to build. Add to [test](test).
+
+We definitely appreciate pull requests that highlight or reproduce a problem, even without a fix.
+
+#### Write Code
+
+Implement your feature or bug fix.
+
+Make sure that `bundle exec rake test` completes without errors.
+
+#### Write Documentation
+
+Document any external behavior in the [README](README.md).
+
+#### Commit Changes
+
+Make sure git knows your name and email address:
+
+```
+git config --global user.name "Your Name"
+git config --global user.email "contributor@example.com"
+```
+
+Writing good commit logs is important. A commit log should describe what changed and why.
+
+```
+git add ...
+git commit
+```
+
+#### Push
+
+```
+git push origin my-feature-branch
+```
+
+#### Make a Pull Request
+
+Go to https://github.com/contributor/rails-dom-testing and select your feature branch. Click the 'Pull Request' button and fill out the form. Pull requests are usually reviewed within a few days.
+
+#### Rebase
+
+If you've been working on a change for a while, rebase with upstream/master.
+
+```
+git fetch upstream
+git rebase upstream/master
+git push origin my-feature-branch -f
+```
+
+#### Check on Your Pull Request
+
+Go back to your pull request after a few minutes and see whether it passed muster with Travis-CI. Everything should look green, otherwise fix issues and amend your commit as described above.
+
+#### Be Patient
+
+It's likely that your change will not be merged and that the nitpicky maintainers will ask you to do more, or fix seemingly benign problems. Hang on there!
+
+#### Thank You
+
+Please do know that we really appreciate and value your time and work. We love you, really.
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..0243083
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,4 @@
+source 'https://rubygems.org'
+
+# Specify your gem's dependencies in rails-dom-testing.gemspec
+gemspec
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 0000000..dc1b06f
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,39 @@
+PATH
+  remote: .
+  specs:
+    rails-dom-testing (2.0.3)
+      activesupport (>= 5.0.0)
+      nokogiri (>= 1.6)
+
+GEM
+  remote: https://rubygems.org/
+  specs:
+    activesupport (6.1.2.1)
+      concurrent-ruby (~> 1.0, >= 1.0.2)
+      i18n (>= 1.6, < 2)
+      minitest (>= 5.1)
+      tzinfo (~> 2.0)
+      zeitwerk (~> 2.3)
+    concurrent-ruby (1.1.8)
+    i18n (1.8.9)
+      concurrent-ruby (~> 1.0)
+    minitest (5.10.1)
+    nokogiri (1.11.1)
+      racc (~> 1.4)
+    racc (1.5.2)
+    rake (13.0.1)
+    tzinfo (2.0.4)
+      concurrent-ruby (~> 1.0)
+    zeitwerk (2.4.2)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  bundler (>= 1.3)
+  minitest
+  rails-dom-testing!
+  rake
+
+BUNDLED WITH
+   1.13.7
diff --git a/README.md b/README.md
index a256b79..6d62cf3 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
 
 This gem is responsible for comparing HTML doms and asserting that DOM elements are present in Rails applications.
 Doms are compared via `assert_dom_equal` and `assert_dom_not_equal`.
-Elements are asserted via `assert_select`, `assert_select_encoded`, `assert_select_email` and a subset of the dom can be selected with `css_select`.
+Elements are asserted via `assert_dom`, `assert_dom_encoded`, `assert_dom_email` and a subset of the dom can be selected with `css_select`.
 The gem is developed for Rails 4.2 and above, and will not work on previous versions.
 
 ## Nokogiri::CSS::SyntaxError exceptions when upgrading to Rails 4.2:
@@ -41,21 +41,21 @@ assert_dom_not_equal '<h1>Portuguese</h1>', '<h1>Danish</h1>'
 # implicitly selects from the document_root_element
 css_select '.hello' # => Nokogiri::XML::NodeSet of elements with hello class
 
-# select from a supplied node. assert_select asserts elements exist.
-assert_select document_root_element.at('.hello'), '.goodbye'
+# select from a supplied node. assert_dom asserts elements exist.
+assert_dom document_root_element.at('.hello'), '.goodbye'
 
 # elements in CDATA encoded sections can also be selected
-assert_select_encoded '#out-of-your-element'
+assert_dom_encoded '#out-of-your-element'
 
 # assert elements within an html email exists
-assert_select_email '#you-got-mail'
+assert_dom_email '#you-got-mail'
 ```
 
 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.
 
 ## Read more
 
-Under the hood the doms are parsed with Nokogiri and you'll generally be working with these two classes:
+Under the hood the doms are parsed with Nokogiri, and you'll generally be working with these two classes:
 - [`Nokogiri::XML::Node`](http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/Node)
 - [`Nokogiri::XML::NodeSet`](http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/NodeSet)
 
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..1fb331c
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,10 @@
+require "bundler/gem_tasks"
+require "rake/testtask"
+
+task :default => :test
+Rake::TestTask.new do |t|
+  t.libs << 'test'
+  t.pattern = 'test/**/*_test.rb'
+  t.warning = true
+  t.verbose = true
+end
\ No newline at end of file
diff --git a/debian/changelog b/debian/changelog
index 8e69d43..f7a2812 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,9 +1,10 @@
-ruby-rails-dom-testing (2.0.3-5) UNRELEASED; urgency=medium
+ruby-rails-dom-testing (2.0.3+git20220714.1.8deceed-1) UNRELEASED; urgency=medium
 
   * Bump debhelper from old 12 to 13.
   * Update standards version to 4.6.2, no changes needed.
+  * New upstream snapshot.
 
- -- Debian Janitor <janitor@jelmer.uk>  Sat, 07 Jan 2023 05:41:45 -0000
+ -- Debian Janitor <janitor@jelmer.uk>  Sat, 07 Jan 2023 17:13:04 -0000
 
 ruby-rails-dom-testing (2.0.3-4) unstable; urgency=medium
 
diff --git a/gemfiles/active_support_5.0.gemfile b/gemfiles/active_support_5.0.gemfile
new file mode 100644
index 0000000..cf2eb39
--- /dev/null
+++ b/gemfiles/active_support_5.0.gemfile
@@ -0,0 +1,7 @@
+source "https://rubygems.org"
+
+gem "activesupport", "~> 5.0.0"
+
+gem "nokogiri", ">= 1.7.0"
+
+gemspec path: "../"
diff --git a/gemfiles/active_support_5.2.gemfile b/gemfiles/active_support_5.2.gemfile
new file mode 100644
index 0000000..73dad63
--- /dev/null
+++ b/gemfiles/active_support_5.2.gemfile
@@ -0,0 +1,7 @@
+source "https://rubygems.org"
+
+gem "activesupport", "~> 5.2.0"
+
+gem "nokogiri", ">= 1.7.0"
+
+gemspec path: "../"
diff --git a/gemfiles/active_support_6.0.gemfile b/gemfiles/active_support_6.0.gemfile
new file mode 100644
index 0000000..7bcdecc
--- /dev/null
+++ b/gemfiles/active_support_6.0.gemfile
@@ -0,0 +1,7 @@
+source "https://rubygems.org"
+
+gem "activesupport", "~> 6.0.0"
+
+gem "nokogiri", ">= 1.7.0"
+
+gemspec path: "../"
diff --git a/gemfiles/active_support_6.1.gemfile b/gemfiles/active_support_6.1.gemfile
new file mode 100644
index 0000000..5c0da10
--- /dev/null
+++ b/gemfiles/active_support_6.1.gemfile
@@ -0,0 +1,7 @@
+source "https://rubygems.org"
+
+gem "activesupport", "~> 6.1.0"
+
+gem "nokogiri", ">= 1.7.0"
+
+gemspec path: "../"
diff --git a/gemfiles/active_support_7.0.gemfile b/gemfiles/active_support_7.0.gemfile
new file mode 100644
index 0000000..ba62cba
--- /dev/null
+++ b/gemfiles/active_support_7.0.gemfile
@@ -0,0 +1,7 @@
+source "https://rubygems.org"
+
+gem "activesupport", "~> 7.0.0"
+
+gem "nokogiri", ">= 1.7.0"
+
+gemspec path: "../"
diff --git a/lib/rails/dom/testing/assertions.rb b/lib/rails/dom/testing/assertions.rb
index 158b82d..862d2c2 100644
--- a/lib/rails/dom/testing/assertions.rb
+++ b/lib/rails/dom/testing/assertions.rb
@@ -1,18 +1,14 @@
-require 'active_support/concern'
 require 'nokogiri'
+require 'rails/dom/testing/assertions/dom_assertions'
+require 'rails/dom/testing/assertions/selector_assertions'
 
 module Rails
   module Dom
     module Testing
       module Assertions
-        autoload :DomAssertions, 'rails/dom/testing/assertions/dom_assertions'
-        autoload :SelectorAssertions, 'rails/dom/testing/assertions/selector_assertions'
-
-        extend ActiveSupport::Concern
-
         include DomAssertions
         include SelectorAssertions
       end
     end
   end
-end
\ No newline at end of file
+end
diff --git a/lib/rails/dom/testing/assertions/dom_assertions.rb b/lib/rails/dom/testing/assertions/dom_assertions.rb
index 7cc6c01..9c5721d 100644
--- a/lib/rails/dom/testing/assertions/dom_assertions.rb
+++ b/lib/rails/dom/testing/assertions/dom_assertions.rb
@@ -7,43 +7,61 @@ module Rails
           #
           #   # assert that the referenced method generates the appropriate HTML string
           #   assert_dom_equal '<a href="http://www.example.com">Apples</a>', link_to("Apples", "http://www.example.com")
-          def assert_dom_equal(expected, actual, message = nil)
+          def assert_dom_equal(expected, actual, message = nil, strict: false)
             expected_dom, actual_dom = fragment(expected), fragment(actual)
             message ||= "Expected: #{expected}\nActual: #{actual}"
-            assert compare_doms(expected_dom, actual_dom), message
+            assert compare_doms(expected_dom, actual_dom, strict), message
           end
 
           # The negated form of +assert_dom_equal+.
           #
           #   # assert that the referenced method does not generate the specified HTML string
           #   assert_dom_not_equal '<a href="http://www.example.com">Apples</a>', link_to("Oranges", "http://www.example.com")
-          def assert_dom_not_equal(expected, actual, message = nil)
+          def assert_dom_not_equal(expected, actual, message = nil, strict: false)
             expected_dom, actual_dom = fragment(expected), fragment(actual)
             message ||= "Expected: #{expected}\nActual: #{actual}"
-            assert_not compare_doms(expected_dom, actual_dom), message
+            assert_not compare_doms(expected_dom, actual_dom, strict), message
           end
 
           protected
 
-            def compare_doms(expected, actual)
-              return false unless expected.children.size == actual.children.size
+            def compare_doms(expected, actual, strict)
+              expected_children = extract_children(expected, strict)
+              actual_children   = extract_children(actual, strict)
+              return false unless expected_children.size == actual_children.size
 
-              expected.children.each_with_index do |child, i|
-                return false unless equal_children?(child, actual.children[i])
+              expected_children.each_with_index do |child, i|
+                return false unless equal_children?(child, actual_children[i], strict)
               end
 
               true
             end
 
-            def equal_children?(child, other_child)
+            def extract_children(node, strict)
+              if strict
+                node.children
+              else
+                node.children.reject{|n| n.text? && n.text.blank?}
+              end
+            end
+
+            def equal_children?(child, other_child, strict)
               return false unless child.type == other_child.type
 
               if child.element?
                 child.name == other_child.name &&
                     equal_attribute_nodes?(child.attribute_nodes, other_child.attribute_nodes) &&
-                    compare_doms(child, other_child)
+                    compare_doms(child, other_child, strict)
               else
+                equal_child?(child, other_child, strict)
+              end
+            end
+
+            def equal_child?(child, other_child, strict)
+              if strict
                 child.to_s == other_child.to_s
+              else
+                child.to_s.split == other_child.to_s.split
               end
             end
 
diff --git a/lib/rails/dom/testing/assertions/selector_assertions.rb b/lib/rails/dom/testing/assertions/selector_assertions.rb
index 8de6596..dab6233 100644
--- a/lib/rails/dom/testing/assertions/selector_assertions.rb
+++ b/lib/rails/dom/testing/assertions/selector_assertions.rb
@@ -1,4 +1,3 @@
-require 'active_support/deprecation'
 require_relative 'selector_assertions/count_describable'
 require_relative 'selector_assertions/html_selector'
 
@@ -6,9 +5,9 @@ module Rails
   module Dom
     module Testing
       module Assertions
-        # Adds the +assert_select+ method for use in Rails functional
+        # Adds the +assert_dom+ method for use in Rails functional
         # test cases, which can be used to make assertions on the response HTML of a controller
-        # action. You can also call +assert_select+ within another +assert_select+ to
+        # action. You can also call +assert_dom+ within another +assert_dom+ to
         # make assertions on elements selected by the enclosing assertion.
         #
         # Use +css_select+ to select elements without making an assertions, either
@@ -16,8 +15,8 @@ module Rails
         #
         # In addition to HTML responses, you can make the following assertions:
         #
-        # * +assert_select_encoded+ - Assertions on HTML encoded inside XML, for example for dealing with feed item descriptions.
-        # * +assert_select_email+ - Assertions on the HTML body of an e-mail.
+        # * +assert_dom_encoded+ - Assertions on HTML encoded inside XML, for example for dealing with feed item descriptions.
+        # * +assert_dom_email+ - Assertions on the HTML body of an e-mail.
         module SelectorAssertions
 
         # Select and return all matching elements.
@@ -70,38 +69,41 @@ module Rails
         # starting from (and including) that element and all its children in
         # depth-first order.
         #
-        # If no element is specified +assert_select+ selects from
+        # If no element is specified +assert_dom+ selects from
         # the element returned in +document_root_element+
-        # unless +assert_select+ is called from within an +assert_select+ block.
-        # Override +document_root_element+ to tell +assert_select+ what to select from.
+        # unless +assert_dom+ is called from within an +assert_dom+ block.
+        # Override +document_root_element+ to tell +assert_dom+ what to select from.
         # The default implementation raises an exception explaining this.
         #
-        # When called with a block +assert_select+ passes an array of selected elements
-        # to the block. Calling +assert_select+ from the block, with no element specified,
+        # When called with a block +assert_dom+ passes an array of selected elements
+        # to the block. Calling +assert_dom+ from the block, with no element specified,
         # runs the assertion on the complete set of elements selected by the enclosing assertion.
-        # Alternatively the array may be iterated through so that +assert_select+ can be called
+        # Alternatively the array may be iterated through so that +assert_dom+ can be called
         # separately for each element.
         #
         #
         # ==== Example
         # If the response contains two ordered lists, each with four list elements then:
-        #   assert_select "ol" do |elements|
+        #   assert_dom "ol" do |elements|
         #     elements.each do |element|
-        #       assert_select element, "li", 4
+        #       assert_dom element, "li", 4
         #     end
         #   end
         #
         # will pass, as will:
-        #   assert_select "ol" do
-        #     assert_select "li", 8
+        #   assert_dom "ol" do
+        #     assert_dom "li", 8
         #   end
         #
-        # The selector may be a CSS selector expression (String) or an expression
+        # The selector may be a CSS selector expression (String, Symbol, or Numeric) or an expression
         # with substitution values (Array).
         # Substitution uses a custom pseudo class match. Pass in whatever attribute you want to match (enclosed in quotes) and a ? for the substitution.
-        # assert_select returns nil if called with an invalid css selector.
+        # assert_dom returns nil if called with an invalid css selector.
         #
-        # assert_select "div:match('id', ?)", /\d+/
+        # assert_dom "div:match('id', ?)", "id_string"
+        # assert_dom "div:match('id', ?)", :id_string
+        # assert_dom "div:match('id', ?)", 1
+        # assert_dom "div:match('id', ?)", /\d+/
         #
         # === Equality Tests
         #
@@ -133,32 +135,32 @@ module Rails
         # evaluated the block is called with an array of all matched elements.
         #
         #   # At least one form element
-        #   assert_select "form"
+        #   assert_dom "form"
         #
         #   # Form element includes four input fields
-        #   assert_select "form input", 4
+        #   assert_dom "form input", 4
         #
         #   # Page title is "Welcome"
-        #   assert_select "title", "Welcome"
+        #   assert_dom "title", "Welcome"
         #
         #   # Page title is "Welcome" and there is only one title element
-        #   assert_select "title", {count: 1, text: "Welcome"},
+        #   assert_dom "title", {count: 1, text: "Welcome"},
         #       "Wrong title or more than one title element"
         #
         #   # Page contains no forms
-        #   assert_select "form", false, "This page must contain no forms"
+        #   assert_dom "form", false, "This page must contain no forms"
         #
         #   # Test the content and style
-        #   assert_select "body div.header ul.menu"
+        #   assert_dom "body div.header ul.menu"
         #
         #   # Use substitution values
-        #   assert_select "ol>li:match('id', ?)", /item-\d+/
+        #   assert_dom "ol>li:match('id', ?)", /item-\d+/
         #
         #   # All input fields in the form have a name
-        #   assert_select "form input" do
-        #     assert_select ":match('name', ?)", /.+/  # Not empty
+        #   assert_dom "form input" do
+        #     assert_dom ":match('name', ?)", /.+/  # Not empty
         #   end
-        def assert_select(*args, &block)
+        def assert_dom(*args, &block)
           @selected ||= nil
 
           selector = HTMLSelector.new(args, @selected) { nodeset document_root_element }
@@ -175,6 +177,7 @@ module Rails
             nest_selection(matches, &block) if block_given? && !matches.empty?
           end
         end
+        alias_method :assert_select, :assert_dom
 
         # Extracts the content of an element, treats it as encoded HTML and runs
         # nested assertion on it.
@@ -187,30 +190,30 @@ module Rails
         # element +encoded+. It then calls the block with all un-encoded elements.
         #
         #   # Selects all bold tags from within the title of an Atom feed's entries (perhaps to nab a section name prefix)
-        #   assert_select "feed[xmlns='http://www.w3.org/2005/Atom']" do
+        #   assert_dom "feed[xmlns='http://www.w3.org/2005/Atom']" do
         #     # Select each entry item and then the title item
-        #     assert_select "entry>title" do
+        #     assert_dom "entry>title" do
         #       # Run assertions on the encoded title elements
-        #       assert_select_encoded do
-        #         assert_select "b"
+        #       assert_dom_encoded do
+        #         assert_dom "b"
         #       end
         #     end
         #   end
         #
         #
         #   # Selects all paragraph tags from within the description of an RSS feed
-        #   assert_select "rss[version=2.0]" do
+        #   assert_dom "rss[version=2.0]" do
         #     # Select description element of each feed item.
-        #     assert_select "channel>item>description" do
+        #     assert_dom "channel>item>description" do
         #       # Run assertions on the encoded elements.
-        #       assert_select_encoded do
-        #         assert_select "p"
+        #       assert_dom_encoded do
+        #         assert_dom "p"
         #       end
         #     end
         #   end
-        def assert_select_encoded(element = nil, &block)
+        def assert_dom_encoded(element = nil, &block)
           if !element && !@selected
-            raise ArgumentError, "Element is required when called from a nonnested assert_select"
+            raise ArgumentError, "Element is required when called from a nonnested assert_dom"
           end
 
           content = nodeset(element || @selected).map do |elem|
@@ -224,27 +227,28 @@ module Rails
             if content.empty?
               yield selected
             else
-              assert_select ":root", &block
+              assert_dom ":root", &block
             end
           end
         end
+        alias_method :assert_select_encoded, :assert_dom_encoded
 
         # Extracts the body of an email and runs nested assertions on it.
         #
         # You must enable deliveries for this assertion to work, use:
         #   ActionMailer::Base.perform_deliveries = true
         #
-        #  assert_select_email do
-        #    assert_select "h1", "Email alert"
+        #  assert_dom_email do
+        #    assert_dom "h1", "Email alert"
         #  end
         #
-        #  assert_select_email do
-        #    items = assert_select "ol>li"
+        #  assert_dom_email do
+        #    items = assert_dom "ol>li"
         #    items.each do
         #       # Work with items here...
         #    end
         #  end
-        def assert_select_email(&block)
+        def assert_dom_email(&block)
           deliveries = ActionMailer::Base.deliveries
           assert !deliveries.empty?, "No e-mail in delivery list"
 
@@ -252,18 +256,19 @@ module Rails
             (delivery.parts.empty? ? [delivery] : delivery.parts).each do |part|
               if part["Content-Type"].to_s =~ /^text\/html\W/
                 root = Nokogiri::HTML::DocumentFragment.parse(part.body.to_s)
-                assert_select root, ":root", &block
+                assert_dom root, ":root", &block
               end
             end
           end
         end
+        alias_method :assert_select_email, :assert_dom_email
 
         private
           include CountDescribable
 
           def document_root_element
             raise NotImplementedError, 'Implementing document_root_element makes ' \
-              'assert_select work without needing to specify an element to select from.'
+              'assert_dom work without needing to specify an element to select from.'
           end
 
           # +equals+ must contain :minimum, :maximum and :count keys
@@ -280,7 +285,7 @@ module Rails
           end
 
           def nest_selection(selection)
-            # Set @selected to allow nested assert_select.
+            # Set @selected to allow nested assert_dom.
             # Can be nested several levels deep.
             old_selected, @selected = @selected, selection
             yield @selected
@@ -292,6 +297,7 @@ module Rails
             if node.is_a?(Nokogiri::XML::NodeSet)
               node
             else
+              node ||= Nokogiri::HTML::Document.new
               Nokogiri::XML::NodeSet.new(node.document, [node])
             end
           end
diff --git a/lib/rails/dom/testing/assertions/selector_assertions/count_describable.rb b/lib/rails/dom/testing/assertions/selector_assertions/count_describable.rb
index 67716ee..37d7234 100644
--- a/lib/rails/dom/testing/assertions/selector_assertions/count_describable.rb
+++ b/lib/rails/dom/testing/assertions/selector_assertions/count_describable.rb
@@ -1,13 +1,9 @@
-require 'active_support/concern'
-
 module Rails
   module Dom
     module Testing
       module Assertions
         module SelectorAssertions
           module CountDescribable
-            extend ActiveSupport::Concern
-
             private
               def count_description(min, max, count) #:nodoc:
                 if min && max && (max != min)
diff --git a/lib/rails/dom/testing/assertions/selector_assertions/html_selector.rb b/lib/rails/dom/testing/assertions/selector_assertions/html_selector.rb
index 4eb1462..7e927ce 100644
--- a/lib/rails/dom/testing/assertions/selector_assertions/html_selector.rb
+++ b/lib/rails/dom/testing/assertions/selector_assertions/html_selector.rb
@@ -11,6 +11,10 @@ class HTMLSelector #:nodoc:
     @tests = extract_equality_tests
     @message = @values.shift
 
+    if @message.is_a?(Hash)
+      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."
+    end
+
     if @values.shift
       raise ArgumentError, "Not expecting that last argument, you either have too many arguments, or they're the wrong type"
     end
@@ -48,7 +52,7 @@ class HTMLSelector #:nodoc:
       content.sub!(/\A\n/, '') if text_matches && match.name == "textarea"
 
       next if regex_matching ? (content =~ match_with) : (content == match_with)
-      content_mismatch ||= sprintf("<%s> expected but was\n<%s>.", match_with, content)
+      content_mismatch ||= sprintf("<%s> expected but was\n<%s>", match_with, content)
       true
     end
 
@@ -61,7 +65,7 @@ class HTMLSelector #:nodoc:
 
     if possible_root == nil
       raise ArgumentError, 'First argument is either selector or element ' \
-        'to select, but nil found. Perhaps you called assert_select with ' \
+        'to select, but nil found. Perhaps you called assert_dom with ' \
         'an element that does not exist?'
     elsif possible_root.respond_to?(:css)
       @values.shift # remove the root, so selector is the first argument
@@ -87,20 +91,20 @@ class HTMLSelector #:nodoc:
   def extract_equality_tests
     comparisons = {}
     case comparator = @values.shift
-      when Hash
-        comparisons = comparator
-      when String, Regexp
-        comparisons[:text] = comparator
-      when Integer
-        comparisons[:count] = comparator
-      when Range
-        comparisons[:minimum] = comparator.begin
-        comparisons[:maximum] = comparator.end
-      when FalseClass
-        comparisons[:count] = 0
-      when NilClass, TrueClass
-        comparisons[:minimum] = 1
-      else raise ArgumentError, "I don't understand what you're trying to match"
+    when Hash
+      comparisons = comparator
+    when String, Regexp
+      comparisons[:text] = comparator
+    when Integer
+      comparisons[:count] = comparator
+    when Range
+      comparisons[:minimum] = comparator.begin
+      comparisons[:maximum] = comparator.end
+    when FalseClass
+      comparisons[:count] = 0
+    when NilClass, TrueClass
+      comparisons[:minimum] = 1
+    else raise ArgumentError, "I don't understand what you're trying to match"
     end
 
     # By default we're looking for at least one match.
diff --git a/lib/rails/dom/testing/assertions/selector_assertions/substitution_context.rb b/lib/rails/dom/testing/assertions/selector_assertions/substitution_context.rb
index 0e140a0..ee36d89 100644
--- a/lib/rails/dom/testing/assertions/selector_assertions/substitution_context.rb
+++ b/lib/rails/dom/testing/assertions/selector_assertions/substitution_context.rb
@@ -4,13 +4,10 @@ class SubstitutionContext
   end
 
   def substitute!(selector, values, format_for_presentation = false)
-    selector = selector.dup
-
-    while !values.empty? && substitutable?(values.first) && selector.index(@substitute)
-      selector.sub! @substitute, matcher_for(values.shift, format_for_presentation)
+    selector.gsub @substitute do |match|
+      next match[0] if values.empty? || !substitutable?(values.first)
+      matcher_for(values.shift, format_for_presentation)
     end
-
-    selector
   end
 
   def match(matches, attribute, matcher)
@@ -23,11 +20,11 @@ class SubstitutionContext
       if format_for_presentation
         value.inspect # Avoid to_s so Regexps aren't put in quotes.
       else
-        value.to_s.inspect
+        "\"#{value}\""
       end
     end
 
     def substitutable?(value)
-      value.is_a?(String) || value.is_a?(Regexp)
+      [ Symbol, Numeric, String, Regexp ].any? { |type| value.is_a? type }
     end
 end
diff --git a/rails-dom-testing.gemspec b/rails-dom-testing.gemspec
index 01c4be0..7e08f4b 100644
--- a/rails-dom-testing.gemspec
+++ b/rails-dom-testing.gemspec
@@ -1,47 +1,26 @@
-#########################################################
-# This file has been automatically generated by gem2tgz #
-#########################################################
-# -*- encoding: utf-8 -*-
-# stub: rails-dom-testing 2.0.3 ruby lib
+# coding: utf-8
+lib = File.expand_path('../lib', __FILE__)
+$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
+require 'rails/dom/testing/version'
 
-Gem::Specification.new do |s|
-  s.name = "rails-dom-testing".freeze
-  s.version = "2.0.3"
+Gem::Specification.new do |spec|
+  spec.name          = "rails-dom-testing"
+  spec.version       = Rails::Dom::Testing::VERSION
+  spec.authors       = ["Rafael Mendonça França", "Kasper Timm Hansen"]
+  spec.email         = ["rafaelmfranca@gmail.com", "kaspth@gmail.com"]
+  spec.summary       = %q{ Dom and Selector assertions for Rails applications }
+  spec.description   = %q{ This gem can compare doms and assert certain elements exists in doms using Nokogiri. }
+  spec.homepage      = "https://github.com/rails/rails-dom-testing"
+  spec.license       = "MIT"
 
-  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
-  s.require_paths = ["lib".freeze]
-  s.authors = ["Rafael Mendon\u{e7}a Fran\u{e7}a".freeze, "Kasper Timm Hansen".freeze]
-  s.date = "2017-05-10"
-  s.description = " This gem can compare doms and assert certain elements exists in doms using Nokogiri. ".freeze
-  s.email = ["rafaelmfranca@gmail.com".freeze, "kaspth@gmail.com".freeze]
-  s.files = ["MIT-LICENSE".freeze, "README.md".freeze, "lib/rails-dom-testing.rb".freeze, "lib/rails/dom/testing/assertions.rb".freeze, "lib/rails/dom/testing/assertions/dom_assertions.rb".freeze, "lib/rails/dom/testing/assertions/selector_assertions.rb".freeze, "lib/rails/dom/testing/assertions/selector_assertions/count_describable.rb".freeze, "lib/rails/dom/testing/assertions/selector_assertions/html_selector.rb".freeze, "lib/rails/dom/testing/assertions/selector_assertions/substitution_context.rb".freeze, "lib/rails/dom/testing/version.rb".freeze, "test/dom_assertions_test.rb".freeze, "test/selector_assertions_test.rb".freeze, "test/test_helper.rb".freeze]
-  s.homepage = "https://github.com/rails/rails-dom-testing".freeze
-  s.licenses = ["MIT".freeze]
-  s.rubygems_version = "2.5.2.1".freeze
-  s.summary = "Dom and Selector assertions for Rails applications".freeze
-  s.test_files = ["test/dom_assertions_test.rb".freeze, "test/selector_assertions_test.rb".freeze, "test/test_helper.rb".freeze]
+  spec.files         = Dir["lib/**/*", "README.md", "MIT-LICENSE", "CHANGELOG.md"]
+  spec.test_files    = Dir["test/**/*"]
+  spec.require_paths = ["lib"]
 
-  if s.respond_to? :specification_version then
-    s.specification_version = 4
+  spec.add_dependency "nokogiri", ">= 1.6"
+  spec.add_dependency "activesupport",  ">= 5.0.0"
 
-    if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
-      s.add_runtime_dependency(%q<activesupport>.freeze, [">= 4.2.0"])
-      s.add_development_dependency(%q<bundler>.freeze, [">= 1.3"])
-      s.add_development_dependency(%q<minitest>.freeze, [">= 0"])
-      s.add_runtime_dependency(%q<nokogiri>.freeze, [">= 1.6"])
-      s.add_development_dependency(%q<rake>.freeze, [">= 0"])
-    else
-      s.add_dependency(%q<activesupport>.freeze, [">= 4.2.0"])
-      s.add_dependency(%q<bundler>.freeze, [">= 1.3"])
-      s.add_dependency(%q<minitest>.freeze, [">= 0"])
-      s.add_dependency(%q<nokogiri>.freeze, [">= 1.6"])
-      s.add_dependency(%q<rake>.freeze, [">= 0"])
-    end
-  else
-    s.add_dependency(%q<activesupport>.freeze, [">= 4.2.0"])
-    s.add_dependency(%q<bundler>.freeze, [">= 1.3"])
-    s.add_dependency(%q<minitest>.freeze, [">= 0"])
-    s.add_dependency(%q<nokogiri>.freeze, [">= 1.6"])
-    s.add_dependency(%q<rake>.freeze, [">= 0"])
-  end
+  spec.add_development_dependency "bundler", ">= 1.3"
+  spec.add_development_dependency "rake"
+  spec.add_development_dependency "minitest"
 end
diff --git a/test/dom_assertions_test.rb b/test/dom_assertions_test.rb
index 5b95609..f663e43 100644
--- a/test/dom_assertions_test.rb
+++ b/test/dom_assertions_test.rb
@@ -47,4 +47,79 @@ class DomAssertionsTest < ActiveSupport::TestCase
       %{<a><b c="2" /></a>}
     )
   end
-end
\ No newline at end of file
+
+  def test_dom_equal_with_whitespace_strict
+    canonical = %{<a><b>hello</b> world</a>}
+    assert_dom_not_equal(canonical, %{<a>\n<b>hello\n </b> world</a>}, strict: true)
+    assert_dom_not_equal(canonical, %{<a> \n <b>\n hello</b> world</a>}, strict: true)
+    assert_dom_not_equal(canonical, %{<a>\n\t<b>hello</b> world</a>}, strict: true)
+    assert_dom_equal(canonical, %{<a><b>hello</b> world</a>}, strict: true)
+  end
+
+  def test_dom_equal_with_whitespace
+    canonical = %{<a><b>hello</b> world</a>}
+    assert_dom_equal(canonical, %{<a>\n<b>hello\n </b> world</a>})
+    assert_dom_equal(canonical, %{<a>\n<b>hello </b>\nworld</a>})
+    assert_dom_equal(canonical, %{<a> \n <b>\n hello</b> world</a>})
+    assert_dom_equal(canonical, %{<a> \n <b> hello </b>world</a>})
+    assert_dom_equal(canonical, %{<a> \n <b>hello </b>world\n</a>\n})
+    assert_dom_equal(canonical, %{<a>\n\t<b>hello</b> world</a>})
+    assert_dom_equal(canonical, %{<a>\n\t<b>hello </b>\n\tworld</a>})
+  end
+
+  def test_dom_equal_with_attribute_whitespace
+    canonical = %(<div data-wow="Don't strip this">)
+    assert_dom_equal(canonical, %(<div data-wow="Don't strip this">))
+    assert_dom_not_equal(canonical, %(<div data-wow="Don't  strip this">))
+  end
+
+  def test_dom_equal_with_indentation
+    canonical = %{<a>hello <b>cruel</b> world</a>}
+    assert_dom_equal(canonical, <<-HTML)
+<a>
+  hello
+  <b>cruel</b>
+  world
+</a>
+    HTML
+
+    assert_dom_equal(canonical, <<-HTML)
+<a>
+hello
+<b>cruel</b>
+world
+</a>
+    HTML
+
+    assert_dom_equal(canonical, <<-HTML)
+<a>hello
+  <b>
+    cruel
+  </b>
+  world</a>
+    HTML
+  end
+
+  def test_dom_equal_with_surrounding_whitespace
+    canonical = %{<p>Lorem ipsum dolor</p><p>sit amet, consectetur adipiscing elit</p>}
+    assert_dom_equal(canonical, <<-HTML)
+<p>
+  Lorem
+  ipsum
+  dolor
+</p>
+
+<p>
+  sit amet,
+  consectetur
+  adipiscing elit
+</p>
+    HTML
+  end
+
+  def test_dom_not_equal_with_interior_whitespace
+    with_space    = %{<a><b>hello world</b></a>}
+    without_space = %{<a><b>helloworld</b></a>}
+    assert_dom_not_equal(with_space, without_space)
+  end
+end
diff --git a/test/selector_assertions_test.rb b/test/selector_assertions_test.rb
index ededb24..e87b8f3 100644
--- a/test/selector_assertions_test.rb
+++ b/test/selector_assertions_test.rb
@@ -135,6 +135,21 @@ class AssertSelectTest < ActiveSupport::TestCase
     end
   end
 
+  def test_multiple_substitution_values
+    render_html '<input name="foo[12]" value="34">'
+    assert_select ":match('name', ?):match('value', ?)", /\w+\[\d+\]/, /\d+/
+  end
+
+  def test_substitution_values_with_values_other_than_string_or_regexp
+    render_html %Q{<div id="id_string">symbol</div><div id="1">numeric</div>}
+    assert_select "div:match('id', ?)", :id_string do |elements|
+      assert_equal 1, elements.size
+    end
+    assert_select "div:match('id', ?)", 1 do |elements|
+      assert_equal 1, elements.size
+    end
+  end
+
   def test_assert_select_root_html
     render_html '<a></a>'
 
@@ -302,6 +317,24 @@ EOF
     assert_select '.foo'
   end
 
+  def test_assert_select_with_extra_argument
+    render_html '<html><head><title>Welcome</title></head><body><div></div></body></html>'
+
+    assert_raises ArgumentError do
+      assert_select "title", "Welcome", count: 1
+    end
+
+    assert_select "title", text: "Welcome", count: 1
+  end
+
+  def test_assert_select_on_blank_response
+    render_html ""
+    assert_select "div", 0
+    assert_failure(/Expected exactly 1 element matching \"div\", found 0./) do
+      assert_select "div", 1
+    end
+  end
+
   protected
     def render_html(html)
       fake_render(:html, html)

Debdiff

File lists identical (after any substitutions)

No differences were encountered in the control files

More details

Full run details