Capybara #has_selector? fails where Nokogiri#css_at works

34 views
Skip to first unread message

Jack Royal-Gordon

unread,
Feb 19, 2021, 3:09:19 PM2/19/21
to Capybara
I have the attached HTML document which I am trying to verify with Capybara 3.9.0.

Here are my results:

(byebug) Nokogiri::HTML.parse(@response.body).at 'input#book_user_already_notified'

#<Nokogiri::XML::Element:0x3fe86cc348f0 name="input" attributes=[#<Nokogiri::XML::Attr:0x3fe86cc34774 name="value" value="true">, #<Nokogiri::XML::Attr:0x3fe86cc34760 name="type" value="hidden">, #<Nokogiri::XML::Attr:0x3fe86cc34724 name="name" value="book[user_already_notified]">, #<Nokogiri::XML::Attr:0x3fe86cc34710 name="id" value="book_user_already_notified">]>

(byebug) Capybara::Node::Simple.new(@response.body).has_selector? 'input#book_user_already_notified'

false

Also, the selector "input" works, but "input[type=hidden]" does not work, even though there are three input fields of type "hidden". But all of the following succeed:
  • Capybara::Node::Simple.new(@response.body).has_selector? 'div#flash'
  • Capybara::Node::Simple.new(@response.body).has_selector? 'nav#tabs'
  • Capybara::Node::Simple.new(@response.body).has_selector? 'li#dashboard-tab'
  • Capybara::Node::Simple.new(@response.body).has_selector? 'div#help'
  • Capybara::Node::Simple.new(@response.body).has_selector? 'div#body'
  • Capybara::Node::Simple.new(@response.body).has_selector? 'div.columns'
  • Capybara::Node::Simple.new(@response.body).has_selector? 'div.buttons'
  • Capybara::Node::Simple.new(@response.body).has_selector? 'form'
  • Capybara::Node::Simple.new(@response.body).has_selector? 'input'
  • Capybara::Node::Simple.new(@response.body).has_selector? 'input[type]'

capybara_testing.html

Thomas Walpole

unread,
Feb 19, 2021, 11:45:34 PM2/19/21
to Capybara
By default Capybara doesn't find elements that are non-visible to a user, because it's aimed at testing what a user can see/interact with.  When using Node::Simple it can't be as accurate about what's visible/not-visible as when using one of the browser drivers because it can't interpret all the CSS but it does know the input[type='hidden'] elements are non-visible.  If you really need to check for type='hidden' elements (why?) you can pass visible: false to has_selector? to turn off visibility checking

Capybara::Node::Simple.new(@response.body).has_selector? 'input#book_user_already_notified', visible: false

Also note that rather than directly using Capybara::Node::Simple you can use the helper 

Capybara.string(@response.body).has_selector? 'input#book_user_already_notified', visible: false

Jack Royal-Gordon

unread,
Feb 20, 2021, 12:55:00 AM2/20/21
to ruby-c...@googlegroups.com
Thanks, Thomas. I was just about to answer my own question, as further work in other contexts led me to that discovery. 

I do have a related issue, that some selectors that work with Nokogiri don’t work with Capybara (specifically, “a[href=/uploads]” — I know I can use #has_link?(“a”, href: ‘/uploads’, but when the code is table-driven and I’m mixing links with input fields), I’d rather be able to use one call with different arguments.

-- 
You received this message because you are subscribed to a topic in the Google Groups "Capybara" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ruby-capybara/o9XK9QNaXtk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ruby-capybar...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ruby-capybara/22860a1b-c705-4dd8-9f93-1099201fb4d9n%40googlegroups.com.

Thomas Walpole

unread,
Feb 20, 2021, 1:54:55 AM2/20/21
to Capybara
When using `string` or Node::Simple if a CSS selector works with Nokogiri it should work with Capybara (unless Capybara is calculating it as non-visible) because Capybara is just passing the selector through to Nokogiri, so would need to see a reproducible example of any issue you're having. 
`has_link?` builds an XPath query, but then passes that through to Nokogiri as well.  Also, it's not clear what exactly you're doing, but if you're writing tests to verify existence of elements you're going to be much better off using the Capybara provided assertions or expectations that the predicate methods because you'll actually get useful error messages rather than "expected true got false"

Reply all
Reply to author
Forward
0 new messages