5
votes

In Cucumber, with Rspec and Capybara I have a test to check that a button has a class. Here it is

expect(@some_button).to have_css(".in-cart")

it fails, but

@some_button['class']

returns

'btn product in-cart'

so the button definitely has the 'in-cart' class.

As a temporary measure I've changed my test to be;-

expect(@some_button['class']).to match /in-cart/

Which is obviously insane. But why should 'have_css', or 'has_css?' return false for a DOM element that clearly has the expected class?

Also page.all('.in-cart') includes the button, so Capybara can definitely find it.

Incidentally I also tried 'button.in-cart', 'in-cart',expect (etc).to have_selector, expect(etc.has_selector?('.in-cart')).to be_truthy and all combinations.

3
what happens when you try expect(@some_button).to have_css("btn.product.in-cart")Richlewis

3 Answers

9
votes

have_css matcher is expected to be applied to the parent container instead of the actual element

# your view
<div id="container">
  <div class="in_cart product"></div>
</div>

# your step definition
parent = page.find('div#container')
expect(parent).to have_css(".in-cart")
# => returns true, as there is nested div.in_cart
expect('div#container div').to have_css(".in-cart")
# => returns false, as there is no such selector inside of the latter div

As of matching attributes of the exact object, you've got to stick with simple quering by key

element = page.find('div#container div')
element['class'].should include('in-cart')
expect(element['class']).to match /in-cart/

Same logic applies to all of the RSpecMatchers.

5
votes

In newer versions of Capybara/Rspec, by default, expect(page) will query the entire page looking for a match; however, sometimes we may not want that and instead will prefer to target a specific class/region of the page. For those cases, narrow down the context of page using within:

within('.container') do
  expect(page).to have_css(".in-cart")
end

Assuming, the parent has a class container Capybara will only search within this element.

-1
votes

expect(page).to have_css('button.in-cart')