Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/kucaahbe/rspec-html-matchers

Old school have_tag, with_tag(and more) matchers for rspec 3 (Nokogiri powered)
https://github.com/kucaahbe/rspec-html-matchers

rspec ruby testing

Last synced: 1 day ago
JSON representation

Old school have_tag, with_tag(and more) matchers for rspec 3 (Nokogiri powered)

Awesome Lists containing this project

README

        

# rspec-html-matchers [![Gem Version](https://badge.fury.io/rb/rspec-html-matchers.svg)](https://badge.fury.io/rb/rspec-html-matchers)

[RSpec](https://www.relishapp.com/rspec) matchers for testing your html (for [RSpec 2](https://www.relishapp.com/rspec/rspec-core/v/2-99/docs) use 0.5.x version).

[![RSpec MRI](https://github.com/kucaahbe/rspec-html-matchers/actions/workflows/rspec-mri.yml/badge.svg)](https://github.com/kucaahbe/rspec-html-matchers/actions/workflows/rspec-mri.yml)
[![RSpec JRuby](https://github.com/kucaahbe/rspec-html-matchers/actions/workflows/rspec-jruby.yml/badge.svg)](https://github.com/kucaahbe/rspec-html-matchers/actions/workflows/rspec-jruby.yml)
[![Cucumber MRI](https://github.com/kucaahbe/rspec-html-matchers/actions/workflows/cucumber-mri.yml/badge.svg)](https://github.com/kucaahbe/rspec-html-matchers/actions/workflows/cucumber-mri.yml)

Goals
-----

* designed for testing **complex** html output. If you plan to perform simple matching, consider using:
* [assert_select](https://api.rubyonrails.org/classes/ActionDispatch/Assertions/SelectorAssertions.html#method-i-assert_select)
* [matchers provided out of the box in rspec-rails](https://rspec.info/features/6-0/rspec-rails/view-specs/view-spec/)
* [matchers provided by capybara](https://rdoc.info/github/jnicklas/capybara/Capybara/Node/Matchers)
* developer-friendly output in error messages
* built on top of [nokogiri](https://www.nokogiri.org/)
* has support for [capybara](https://github.com/jnicklas/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:

```ruby
gem 'rspec-html-matchers'
```

Include it in your RSpec configuration:

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

or just in your spec(s):

```ruby
describe "my view spec" do
include RSpecHtmlMatchers

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

Cucumber configuration:

```ruby
World RSpecHtmlMatchers
```

as this gem requires **nokogiri**, here are [instructions for installing it](https://nokogiri.org/tutorials/installing_nokogiri.html).

Usage
-----

so perhaps your code produces following output:

```html

Simple Form






```

so you test it with the following:

```ruby
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`](https://www.rubydoc.info/gems/rspec-html-matchers/RSpecHtmlMatchers%3Ahave_tag) documentation

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

* matching tags by css:

```ruby
# simple examples:
expect('

Paragraph

').to have_tag('p')
expect('

Paragraph

').to have_tag(:p)
expect('

Paragraph

').to have_tag('p#qwerty')
expect('

Paragraph

').to have_tag('p.qwe.rty')
# more complicated examples:
expect('

Paragraph

').to have_tag('p strong')
expect('

Paragraph

').to have_tag('p#qwerty strong')
expect('

Paragraph

').to have_tag('p.qwe.rty strong')
# or you can use another syntax for examples above
expect('

Paragraph

').to have_tag('p') do
with_tag('strong')
end
expect('

Paragraph

').to have_tag('p#qwerty') do
with_tag('strong')
end
expect('

Paragraph

').to have_tag('p.qwe.rty') do
with_tag('strong')
end
```

* special case for classes matching:

```ruby
# all of this are equivalent:
expect('

Paragraph

').to have_tag('p', :with => { :class => 'qwe rty' })
expect('

Paragraph

').to have_tag('p', :with => { :class => 'rty qwe' })
expect('

Paragraph

').to have_tag('p', :with => { :class => ['rty', 'qwe'] })
expect('

Paragraph

').to have_tag('p', :with => { :class => ['qwe', 'rty'] })
```

The same works with `:without`:

```ruby
# all of this are equivalent:
expect('

Paragraph

').to have_tag('p', :without => { :class => 'qwe rty' })
expect('

Paragraph

').to have_tag('p', :without => { :class => 'rty qwe' })
expect('

Paragraph

').to have_tag('p', :without => { :class => ['rty', 'qwe'] })
expect('

Paragraph

').to have_tag('p', :without => { :class => ['qwe', 'rty'] })
```

* content matching:

```ruby
expect('

Some content&nbsphere

').to have_tag('p', :text => ' Some content here')
# or
expect('

Some content&nbsphere

').to have_tag('p') do
with_text ' Some content here'
end

expect('

Some content&nbsphere

').to have_tag('p', :text => /Some content here/)
# or
expect('

Some content&nbsphere

').to have_tag('p') do
with_text /Some content here/
end

# mymock.text == 'Some content here'
expect('

Some content&nbsphere

').to have_tag('p', :text => mymock.text)
# or
expect('

Some content&nbsphere

').to have_tag('p') do
with_text mymock.text
end

# matching text content as it's seen by user:
rendered = <
content with ignored spaces around

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](https://www.rubydoc.info/gems/rspec-html-matchers/RSpecHtmlMatchers)

### rspec 1 partial backwards compatibility:

you can match:

```ruby
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:

```ruby
expect(index).to have_tag("img[alt!='']")
```

More info
---------

You can find more on [documentation](https://www.rubydoc.info/gems/rspec-html-matchers/RSpecHtmlMatchers)

Also, please read [CHANGELOG](https://github.com/kucaahbe/rspec-html-matchers/blob/main/CHANGELOG.md) and [issues](https://github.com/kucaahbe/rspec-html-matchers/issues), might be helpful.

Contribution
============

1. Fork the repository
2. Add tests for your feature
3. Write the code
4. Add documentation for your contribution
5. Send a pull request

Contributors
============

- [Kelly Felkins](https://github.com/kellyfelkins)
- [Ryan Wilcox](https://github.com/rwilcox)
- [Simon Schoeters](https://github.com/cimm)
- [Felix Tjandrawibawa](https://github.com/cemenghttps://github.com/cemeng)
- [Szymon Przybył](https://github.com/apocalyptiq)
- [Manuel Meurer](https://github.com/manuelmeurer)
- [Andreas Riemer](https://github.com/arfl)