Mathieu
Mathieu

Reputation: 4797

Rspec/capybara - test presence of a class OR another class

In my ruby on Rails 4.2 app, on a page I have a conditional back end rule that translates into the page front end in a change in class

<div id="content">
    <i class='<% if x=true %>glyphicon glyphicon-thumbs-down<% else> glyphicon glyphicon-thumbs-up ><% end %>' </i>
       this is the message.
</div>

How to check presence with rspec 3/capybara that the page contains the class glyphicon-thumbs-down OR the class glyphicon-thumbs-up ?

I tried the code below but it fails:

it "should sheck one of the 2 classes presence" do
  expect(page).to have_css '.glyphicon-thumbs-down' || expect(page).to have_css '.glyphicon-thumbs-up'
end

I am getting the following error message:

syntax error, unexpected tIDENTIFIER, expecting keyword_end (SyntaxError)

Upvotes: 10

Views: 11699

Answers (4)

Philip lambok
Philip lambok

Reputation: 68

Maybe you can try to use option :count, in expect method like this:

it 'should contains 2 same selector' do
  expect(page).to have_css '.some-class', count: 2
end

Upvotes: 1

Thomas Walpole
Thomas Walpole

Reputation: 49950

Firstly, you're checking for a class name so you need a . in front of the class names to make it a CSS class selector. Then, you could use the RSpec or matcher combinator

expect(page).to have_css('.glyphicon-thumbs-down').or(have_css '.glyphicon-thumbs-up')

but it has the downside of the first one retrying/waiting for Capybara.default_max_wait_time seconds before checking the second. You could specify a 0/false wait time if you know the page is already loaded and therefore don't need retrying/waiting

 expect(page).to have_css('.glyphicon-thumbs-down', wait: false).or(have_css '.glyphicon-thumbs-up', wait: false)

However, it's probably fine to just check for either element using the normal CSS ,

 expect(page).to have_css('.glyphicon-thumbs-down, .glyphicon-thumbs-up')

Upvotes: 7

Matouš Bor&#225;k
Matouš Bor&#225;k

Reputation: 15954

Multiple OR-ed css selectors can be specified separated by a comma. Try the following:

it "should sheck one of the 2 classes presence" do
  expect(page).to have_css '#content i.glyphicon-thumbs-down,#content i.glyphicon-thumbs-up'
end

(I added the #content and i selectors so that the query is more specific.)

However, instead of doing this I would recommend trying to make the test behave in a precisely defined way and test for just a single class in the spec. Have a look at this SO question and its answers for various ways to stub or preset the random number generator in tests.

Upvotes: 12

max pleaner
max pleaner

Reputation: 26788

Your error is from this line:

  expect(page).to have_css 'glyphicon-thumbs-down' || expect(page).to have_css 'glyphicon-thumbs-up'

You just need to add some parens then it will be valid syntax:

expect(page).to(have_css('glyphicon-thumbs-down')) || expect(page).to(have_css('glyphicon-thumbs-up'))

that won't fix your issue though, because if the left condition fails then rspec will exit and not run the second half.

A working approach could be to evaluate the condition to a boolean variable, then pass it to a single rspec expectation. Doing this requires using the core Capybara method has_css to test for css presence, not have_css? from the rspec matchers package:

selectors = ['.glyphicon-thumbs-down', '.glyphicon-thumbs-up']
glyph_exists = selectors.any? do |selector|
  page.has_css? selector
end
expect(glyph_exists).to be true

Note also that I've added . to the selector strings which is necessary since it's a css class.

Upvotes: 1

Related Questions