23

Using Cucumber and Capybara, is there a way to verify that a string is NOT present on a page?

For example, how would I write the opposite of this step:

Then /^I should see "(.*?)"$/ do |arg1|
  page.should have_content(arg1)
end

This passes if arg1 is present.

How would I write a step that fails if arg1 is found?

dB'
  • 7,838
  • 15
  • 58
  • 101

5 Answers5

35

http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Matchers#has_no_text%3F-instance_method

There is a has_no_content matcher in Capybara. So you can write

  Then /^I should not see "(.*?)"$/ do |arg1|
    page.should have_no_content(arg1)
  end
Piotr Jakubowski
  • 1,760
  • 10
  • 16
16

In Rspec 3.4 currently (2016) this is the recommended way to test for not having content:

expect(page).not_to have_content(arg1)
Micah
  • 1,676
  • 16
  • 23
  • Where do you see that this is recommended over `expect(page).to have_no_content(arg1)`? It seems like there's no way for not_to to know not to wait for the content to be on the page, which is what `have_content` would do, I would think. – Ibrahim Dec 01 '16 at 01:05
  • Deprecation Warnings are shown when using ´expect(page).to have_no_content(arg1)´ – Rob Hughes Dec 18 '16 at 17:32
  • 2
    @RobHughes, the depreciation warnings you speak of must have been removed in rspec 3.5.4/capybara 2.6.2. Per the docs: https://github.com/teamcapybara/capybara#asynchronous-javascript-ajax-and-friends - `Capybara's RSpec matchers, however, are smart enough to handle either form. The two following statements are functionally equivalent: expect(page).not_to have_xpath('a'), expect(page).to have_no_xpath('a')` – seanriordan08 Apr 21 '17 at 13:27
  • With Hotwire ( rails7 ) I cant get any of these to work. `expect(page).not_to have_content('Company Mismatch', wait: 10)` Also doesnt work. I needed to put a `sleep 1` before the expect. this must be because of Hotwires DOM swapping shenanigans. – Brent Greeff Jun 01 '23 at 13:33
8

You can also use should_not if you want it read a little better:

Then /^I should not see "(.*?)"$/ do |arg1|
  page.should_not have_content(arg1)
end

Some more info: https://www.relishapp.com/rspec/rspec-expectations/docs

Adam Sheehan
  • 2,122
  • 23
  • 19
  • Note that this will only work properly for javascript tests if you have Capybara::RSpecMatchers included for your spec. I just ran into that problem here: http://stackoverflow.com/a/15253235/125377 – Ari Mar 06 '13 at 21:02
  • 13
    Use `has_no_content?` instead. That will trigger capybara's internal wait. Otherwise, it will prematurely fail if you're waiting for the content to disappear from the page. – keithepley Aug 20 '13 at 19:31
4

currently, you can use:

Then /^I not see "(.*?)"$/ do |arg1|
  expect(page).to have_no_content(arg1)
end

And if the content is found in the page, your test is red

Raphael Abreu
  • 211
  • 2
  • 5
-4

Oh, wait, I figured it out. This works:

Then /^I should see "(.*?)"$/ do |arg1|
  page.has_content?(arg1) == false
end
dB'
  • 7,838
  • 15
  • 58
  • 101
  • 5
    Your code does not assert the content. I guess that if you change false for true, your test will still pass. – Philippe Rathé Sep 04 '13 at 15:28
  • This had tripped me up several times. Either you use `assert page.has_content...` or `page.should have_content...` Can't mix the two styles together. Good call, @PhilippeRathé. – Tass Oct 09 '15 at 17:10