The RSpec matcher tests if two HTML fragments are equivalent. Equivalency means:
- Whitespace is ignored
- Types of attribute quotes are irrelevant
- Attribute order is irrelevant
- Comments are ignored
You use it like this:
html = ...
expect(html).to match_html(<<~HTML)
  <p>
    Expected content
  </p>  
HTML
You may override options from CompareXML Show archive.org snapshot by passing keyword arguments after the HTML string:
html = ...
expect(html).to match_html(<<~HTML, ignore_text_nodes: true)
  <p>
    Expected content
  </p>  
HTML
Installing the matcher
The matcher requires these two gems in your Gemfile:
gem 'nokogiri'
gem 'compare-xml'
Here is the matcher:
require 'nokogiri'
require 'compare-xml'
RSpec::Matchers.define :match_html do |expected_html, **options|
  match do |actual_html|
    expected_doc = Nokogiri::HTML5.fragment(expected_html)
    actual_doc = Nokogiri::HTML5.fragment(actual_html)
    # Options documented here: https://github.com/vkononov/compare-xml
    default_options = {
      collapse_whitespace: true,
      ignore_attr_order: true,
      ignore_comments: true,
    }
    options = default_options.merge(options).merge(verbose: true)
    diff = CompareXML.equivalent?(expected_doc, actual_doc, **options)
    diff.blank?
  end
end
Alternatives
To use Capybara matchers like have_css on an HTML fragment, use 
  Capybara.string(html)
  
    Show archive.org snapshot
  
.
Posted by Henning Koch to makandra dev (2021-09-29 08:53)