RSpec matchers for testing your html (for RSpec 2 use 0.5.x version).
have_tag
matcher from rspec-rails 1.x, but with own syntactic sugarString
(or capybara's page, see below)Add to your Gemfile in the :test
group:
gem 'rspec-html-matchers'
Include it in your RSpec configuration:
RSpec.configure do |config|
config.include RSpecHtmlMatchers
end
or just in your 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 are instructions for installing it.
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 the 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 above should be self-descriptive, if not, please refer to the have_tag
documentation
Input can 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 this 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 this 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 here</p>').to have_tag('p', :text => ' Some content here')
# or
expect('<p> Some content here</p>').to have_tag('p') do
with_text ' Some content here'
end
expect('<p> Some content here</p>').to have_tag('p', :text => /Some content here/)
# or
expect('<p> Some content here</p>').to have_tag('p') do
with_text /Some content here/
end
# mymock.text == 'Some content here'
expect('<p> Some content here</p>').to have_tag('p', :text => mymock.text)
# or
expect('<p> Some content here</p>').to have_tag('p') do
with_text mymock.text
end
# matching text content as it's seen by user:
rendered = <<HTML
<p>
content with ignored spaces around
</p>
HTML
expect(rendered).to have_tag('p', :seen => 'content with ignored spaces around')
usage with capybara and cucumber:
expect(page).to have_tag( ... )
where page
is an instance of Capybara::Session
also included shorthand matchers for form inputs:
and of course you can use the without_
matchers,
for more info take a look at documentation
you can match:
expect(response).to have_tag('div', 'expected content')
expect(response).to have_tag('div', /regexp matching expected content/)
RSpec 1 have_tag
documentation
You can also match the content of attributes by using selectors. For example, to ensure an img
tag has an alt
attribute, you can match:
expect(index).to have_tag("img[alt!='']")
You can find more on documentation
Also, please read CHANGELOG and issues, might be helpful.