Ruby / RSpec / RSpec::HTMLMatchers



Github Repo

Introduction

RSpec 3 matchers for testing your html (for RSpec 2 use 0.5.x version).

Goals

Install

Add to your Gemfile in the :test group:

gem 'rspec-html-matchers'

and somewhere in RSpec configuration:

RSpec.configure do |config|
  config.include RSpecHtmlMatchers
end

or just in you spec(s):

describe "my view spec" do
  include RSpecHtmlMatchers

  it "has tags" do
    expect(rendered).to have_tag('div')
  end

end

Cucumber configuration:

World RSpecHtmlMatchers

as this gem requires nokogiri, here instructions for installing it.

Usage

so perhaps your code produces following output:

<h1>Simple Form</h1>
<form action="/users" method="post">
<p>
  <input type="email" name="user[email]" />
</p>
<p>
  <input type="submit" id="special_submit" />
</p>
</form>

so you test it with following:

expect(rendered).to have_tag('form', :with => { :action => '/users', :method => 'post' }) do
  with_tag "input", :with => { :name => "user[email]", :type => 'email' }
  with_tag "input#special_submit", :count => 1
  without_tag "h1", :text => 'unneeded tag'
  without_tag "p",  :text => /content/i
end

Example about should be self-descriptive, but if not refer to have_tag documentation

Input could be any html string. Let's take a look at these examples:

matching tags by css:

Simple examples:

expect('<p class="qwe rty" id="qwerty">Paragraph</p>').to have_tag('p')
expect('<p class="qwe rty" id="qwerty">Paragraph</p>').to have_tag(:p)
expect('<p class="qwe rty" id="qwerty">Paragraph</p>').to have_tag('p#qwerty')
expect('<p class="qwe rty" id="qwerty">Paragraph</p>').to have_tag('p.qwe.rty')

More complicated examples:

expect('<p class="qwe rty" id="qwerty"><strong>Para</strong>graph</p>').to have_tag('p strong')
expect('<p class="qwe rty" id="qwerty"><strong>Para</strong>graph</p>').to have_tag('p#qwerty strong')
expect('<p class="qwe rty" id="qwerty"><strong>Para</strong>graph</p>').to have_tag('p.qwe.rty strong')

or you can use another syntax for examples above

expect('<p class="qwe rty" id="qwerty"><strong>Para</strong>graph</p>').to have_tag('p') do
  with_tag('strong')
end

expect('<p class="qwe rty" id="qwerty"><strong>Para</strong>graph</p>').to have_tag('p#qwerty') do
  with_tag('strong')
end

expect('<p class="qwe rty" id="qwerty"><strong>Para</strong>graph</p>').to have_tag('p.qwe.rty') do
  with_tag('strong')
end

Special case for classes matching:

 # all of these are equivalent:
expect('<p class="qwe rty" id="qwerty">Paragraph</p>').to have_tag('p', :with => { :class => 'qwe rty' })
expect('<p class="qwe rty" id="qwerty">Paragraph</p>').to have_tag('p', :with => { :class => 'rty qwe' })
expect('<p class="qwe rty" id="qwerty">Paragraph</p>').to have_tag('p', :with => { :class => ['rty', 'qwe'] })
expect('<p class="qwe rty" id="qwerty">Paragraph</p>').to have_tag('p', :with => { :class => ['qwe', 'rty'] })

The same works with :without:

 # all of these are equivalent:
expect('<p class="qwe rty" id="qwerty">Paragraph</p>').to have_tag('p', :without => { :class => 'qwe rty' })
expect('<p class="qwe rty" id="qwerty">Paragraph</p>').to have_tag('p', :without => { :class => 'rty qwe' })
expect('<p class="qwe rty" id="qwerty">Paragraph</p>').to have_tag('p', :without => { :class => ['rty', 'qwe'] })
expect('<p class="qwe rty" id="qwerty">Paragraph</p>').to have_tag('p', :without => { :class => ['qwe', 'rty'] })

Content matching:

expect('<p> Some content&nbsphere</p>').to have_tag('p', :text => ' Some content here')

or

expect('<p> Some content&nbsphere</p>').to have_tag('p') do
  with_text ' Some content here'
end

expect('<p> Some content&nbsphere</p>').to have_tag('p', :text => /Some content here/)

or

expect('<p> Some content&nbsphere</p>').to have_tag('p') do
  with_text /Some content here/
end

 # mymock.text == 'Some content here'
expect('<p> Some content&nbsphere</p>').to have_tag('p', :content => mymock.text)

or

expect('<p> Some content&nbsphere</p>').to have_tag('p') do
  with_content mymock.text
end

Usage with Capybara and Cucumber:

expect(page).to have_tag( ... )

where page is an instance of Capybara::Session

Shorthand matchers for Form inputs:

and of course you can use the without_ matchers (see the documentation).

More info

You can find more on RubyDoc, take a look at have_tag method.

Also, please read CHANGELOG, it might be helpful.


See Also