rspec-html-matchers
¶ ↑
RSpec matchers for testing your html (for RSpec 2 use 0.5.x version).
Goals¶ ↑
-
designed for testing complex html output. If you plan to perform simple matching, consider using:
-
developer-friendly output in error messages
-
built on top of nokogiri
-
has support for capybara, see below
-
syntax is similar to
have_tag
matcher from rspec-rails 1.x, but with own syntactic sugar -
framework agnostic, as input should be
String
(or capybara’s page, see below)
Install¶ ↑
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.
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 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:
ruby # 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:
ruby # 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
:
ruby # 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:
“‘ruby 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:
ruby expect(page).to have_tag( ... )
where page
is an instance of Capybara::Session
-
also included shorthand matchers for form inputs:
-
have_form
-
with_checkbox
-
with_email_field
-
with_file_field
-
with_hidden_field
-
with_option
-
with_password_field
-
with_radio_button
-
with_button
-
with_select
-
with_submit
-
with_text_area
-
with_text_field
-
with_url_field
-
with_number_field
-
with_range_field
-
with_date_field
and of course you can use the without_
matchers, for more info take a look at documentation
rspec 1 partial backwards compatibility:¶ ↑
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}[https://old.rspec.info/rails/writing/views.html]
Matching Tag Attributes¶ ↑
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!='']")
More info¶ ↑
You can find more on documentation
Also, please read CHANGELOG and issues, might be helpful.
Contribution¶ ↑
-
Fork the repository
-
Add tests for your feature
-
Write the code
-
Add documentation for your contribution
-
Send a pull request