58

I am writing an app where it is desirable to check if a view does not have some functionality - in particular because that functionality must be presented only to users in certain security group. I am looking for the opposite of assert_selects in order to see that a menu is not rendered.

Victor Pudeyev
  • 4,296
  • 6
  • 41
  • 67

4 Answers4

70

Take a look at the docs here:

http://apidock.com/rails/ActionController/Assertions/SelectorAssertions/assert_select

From the docs:

assert_select is an assertion that selects elements and makes one or more equality tests.

and from the equality tests sections:

The equality test may be one of the following:

true - Assertion is true if at least one element selected.

false - Assertion is true if no element selected.

String/Regexp - Assertion is true if the text value of at least one element matches the string or regular expression.

Integer - Assertion is true if exactly that number of elements are selected.

Range - Assertion is true if the number of selected elements fit the range.

If no equality test specified, the assertion is true if at least one element selected.

And a simple example:

   # Page contains no forms
   assert_select "form", false, "This page must contain no forms"
Maxim Fedotov
  • 1,349
  • 1
  • 18
  • 38
jordanpg
  • 6,386
  • 4
  • 46
  • 70
  • The solution from @Gant Laborde worked for me where I had to select the inner text to differentiated between two otherwise identical elements. Otherwise, I would recommend this solution. – Kevin Triplett Jan 31 '23 at 00:54
  • The dom testing methods were extracted to the new repository `rails-dom-testing`. Here's [the latest `assert_select` documentation](https://github.com/rails/rails-dom-testing/blob/master/lib/rails/dom/testing/assertions/selector_assertions.rb#L163). – software_writer Feb 01 '23 at 04:54
51

Don't forget you can always pass in the count, and set that to zero.

assert_select "a", {count: 0, text: "New"}, "This page must contain no anchors that say New"
Gant Laborde
  • 6,484
  • 1
  • 21
  • 30
2

I had this problem to ensure there WASN'T a 'Delete' button, out of many buttons. The accepted answer would not work in this situation because there are already several buttons.

assert_select '.button' do |btn|
  btn.each do |b|
    assert_no_match 'Delete', b.to_s
  end
end

However, I really like GantMan's answer better!

Chloe
  • 25,162
  • 40
  • 190
  • 357
1

You can easily define your own:

module ActionDispatch::Assertions::SelectorAssertions
  def refute_select(*a,&b)
    begin
      assert_select(*a,&b)
    rescue AssertionFailedError
      return
    end
    raise "fail" # there should be a better built-in alternative
  end
end
Jon Schneider
  • 25,758
  • 23
  • 142
  • 170
Alex D
  • 29,755
  • 7
  • 80
  • 126
  • This is not going to work as `AssertionFailedError` is raised before negation is evaluated. – gertas Sep 16 '12 at 18:40
  • You could name it `refute_select`? `refute` seems to be a commonly-used antonym for `assert` in Rails, e.g. https://apidock.com/ruby/v1_9_3_125/MiniTest/Assertions/refute – Jon Schneider May 03 '18 at 14:02
  • 1
    @JonSchneider, I like it. Please edit this answer if you want. – Alex D May 04 '18 at 14:49