Assert_select - to do negative tests - need help with syntax please :)

Hi all,

I am trying to figure out how to use assert_select properly.

When I created a new resource in rails 3 called Brands, the view
specs for brands had a test which read:

# Run the generator again with the --webrat flag if you want to

use webrat matchers
assert_select “form”, :action => brands_path, :method => “post” do
assert_select “input#brand_name”, :name => “brand[name]”
assert_select “input#brand_description”, :name =>
“brand[description]”
assert_select “input#brand_created_by”, :name =>
“brand[created_by]”
end

With my project, I do not want the “created by” attribute
to be set from the new.html.erb entry form.

I read http://content.labnotes.org/assert_select/assert_select.html
and figured I need to use the ‘false’ equality operator.

It also says the following:

---------- extract starts --------------
assert_select(selector, *values, equality?, message?) { |elems| … }
assert_select(element, selector, *values, equality?, message?) { |
elems| … }
---------- extract ends --------------

Alas, my attempts at using it failed.

For a spec/statement such as ‘assert_select
input#brand_created_by", :name => "brand[created_by]’,
I would think that input#brand_created_by would be the ‘element’ and
the ‘selector’ combined.

Since I need to use the ‘false’ equality operator,

  1. how do i give null to *values? I have tried the following to no
    success and kept getting syntax errors:

a) assert_select “input#brand_created_by”, :name =>
“brand[created_by]”, ‘’, false → spec/views/brands/
new.html.erb_spec.rb:53: syntax error, unexpected ‘,’, expecting
tASSOC (SyntaxError) me => “brand[created_by]”, ‘’, false
b) assert_select “input#brand_created_by”, :name =>
“brand[created_by]”, nil, false →
spec/views/brands/new.html.erb_spec.rb:53: syntax error, unexpected
‘,’, expecting tASSOC (SyntaxError) …me => “brand[created_by]”,
nil, false
c) assert_select “input#brand_created_by”, :name =>
“brand[created_by]”, , false → spec/views/brands/
new.html.erb_spec.rb:53: syntax error, unexpected ‘,’, expecting
keyword_end (SyntaxError) …:name => “brand[created_by]”, , false

It looks as if any attempts I make to denote that I have no ‘values’
to give to it is not working.

Can someone please tell me what the right syntax is for saying, “i
expect not to see the brand[created_by]” input attribute at all in the
rendered form for adding new entries?

Thank you :slight_smile:
Gordon

On Oct 12, 2011, at 12:58 AM, Gordon wrote:

 assert_select "input#brand_description", :name =>

“brand[description]”
assert_select “input#brand_created_by”, :name =>
“brand[created_by]”
end

With my project, I do not want the “created by” attribute to be set from the
new.html.erb entry form.

I read http://content.labnotes.org/assert_select/assert_select.html and figured
I need to use the ‘false’ equality operator.

That’s old. Check out
http://api.rubyonrails.org/classes/ActionDispatch/Assertions/SelectorAssertions.html#method-i-assert_select
for the latest.

Alas, my attempts at using it failed.

For a spec/statement such as ‘assert_select
input#brand_created_by", :name => "brand[created_by]’,
I would think that input#brand_created_by would be the ‘element’ and
the ‘selector’ combined.

Correct.

a) assert_select “input#brand_created_by”, :name =>
“brand[created_by]”, ‘’, false → spec/views/brands/
new.html.erb_spec.rb:53: syntax error, unexpected ‘,’, expecting
tASSOC (SyntaxError) me => “brand[created_by]”, ‘’, false

This is a problem with Ruby argument ordering working against the
expressiveness you’re looking for. Keyword arguments have to come last.
So you can say:

do_something 1, 2, :a, thing, :b => 3

but you can’t say

do_something 1, :a, thing, :b => 3, 2

What will work is this:

assert_select “input#brand_created_by”, false

This leaves out the :name argument, but you don’t need it IMO. If you
really want it, you’d have to do this:

assert_select “input#brand_created_by”, false, :name =>
“brand[created_by]”

But that feels really awkward to me, since the negative assertion is
expressed in the middle of the argument list

Can someone please tell me what the right syntax is for saying, “i
expect not to see the brand[created_by]” input attribute at all in the
rendered form for adding new entries?

rendered.should_not have_selector(“input#brand_created_by”) # :wink:

You need Capybara for that, of course, but I think it’s easier to grok
than:

assert_select “input#brand_created_by”, false

HTH,
David

What will work is this:

assert_select “input#brand_created_by”, false

Hmmm. Sadly it does not work :frowning: See below:

---------------- extract start -------------------------

 Failure/Error: assert_select "input#brand_created_by", false, :name 

=>
“brand[created_by]”
ArgumentError:
assertion message must be String or Proc, but Hash was given.
# (eval):2:in assert' # ./spec/views/brands/new.html.erb_spec.rb:37:inblock (3 levels)
in
<top (required)>’
# ./spec/views/brands/new.html.erb_spec.rb:34:in `block (2 levels)
in
<top (required)

---------------- extract end -------------------------

This ^^ does include :name => “…”.

What happens when you just run

assert_select “input#brand_created_by”, false

this runs successfully but how do I do it with the :name? :frowning: I just want to
be complete and explicit :slight_smile:

On Oct 12, 2011, at 6:53 AM, Gordon Y. wrote:

What will work is this:

assert_select “input#brand_created_by”, false

This ^^ does not include :name => “…”

Hmmm. Sadly it does not work :frowning: See below:

---------------- extract start -------------------------

 Failure/Error: assert_select "input#brand_created_by", false, :name => 

“brand[created_by]”

This ^^ does include :name => “…”.

What happens when you just run

assert_select “input#brand_created_by”, false

I don’t know if you can. Maybe somebody on the Rails list knows.

If it can’t, it means that people can’t use assert_select to expect
NOT to find a given element with extra attributes (such as :name)
being defined. If that’s the case, i think assert_select was either
poorly written OR not completed yet. It’s like saying that “if”
conditional works but “if not” only works to a simple extend only :frowning: I
am sure it can be done.
Can someone please show us how?

See this
https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/testing/assertions/selector.rb#L186

seems the syntax is “[name=…]”

On Oct 13, 2011, at 4:40 AM, Gordon Y. wrote:

This ^^ does include :name => “…”.

What happens when you just run

assert_select “input#brand_created_by”, false

this runs successfully but how do I do it with the :name? :frowning: I just want to be
complete and explicit :slight_smile:

I don’t know if you can. Maybe somebody on the Rails list knows.

http://groups.google.com/group/rubyonrails-talk

On Oct 13, 2011, at 8:56 PM, Gordon wrote:

I don’t know if you can. Maybe somebody on the Rails list knows.

If it can’t, it means that people can’t use assert_select to expect
NOT to find a given element with extra attributes (such as :name)
being defined. If that’s the case, i think assert_select was either
poorly written OR not completed yet. It’s like saying that “if”
conditional works but “if not” only works to a simple extend only :frowning: I
am sure it can be done.
Can someone please show us how?

This is the main benefit of should and should_not vs assertions.
Virtually every matcher works in with both should and should_not (unless
it’s author explicitly makes it not work that way).

Again, assert_select is part of the Rails library, not RSpec. Please
post this question to http://groups.google.com/group/rubyonrails-talk
and I’m sure you’ll find someone who uses assert_select and can either
help you figure out how to do this, or help you work towards making it
work better.

Cheers,
David