Read more

RSpec matcher to compare two HTML fragments

Henning Koch
September 29, 2021Software engineer at makandra GmbH

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
Illustration online protection

Rails Long Term Support

Rails LTS provides security patches for old versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2)

  • Prevents you from data breaches and liability risks
  • Upgrade at your own pace
  • Works with modern Rubies
Read more Show snapshot

You use it like this:

html = ...
expect(html).to match_html(<<~HTML)
    Expected content

You may override options from CompareXML Show snapshot by passing keyword arguments after the HTML string:

html = ...
expect(html).to match_html(<<~HTML, ignore_text_nodes: true)
    Expected content

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:
    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)



To use Capybara matchers like have_css on an HTML fragment, use Capybara.string(html) Show snapshot .

Henning Koch
September 29, 2021Software engineer at makandra GmbH
Posted by Henning Koch to makandra dev (2021-09-29 10:53)