How to get parent node in Capybara?

I work with many jQuery plugins that often create DOM elements without an identifier or other identification properties, and the only way to get them in Capybara (for example, to click) is to get your neighbor (another child from his ancestor). But I did not find anything, Capybara supports such things, for example:

find('#some_button').parent.fill_in "Name:", :with => name 

?

+68
ruby ruby-on-rails bdd cucumber capybara
Feb 01 '11 at 11:18
source share
8 answers

I really found jamuraa's answer useful, but switching to full xpath gave me a string nightmare in my case, so I gladly took advantage of the concatenation ability found in Capybara, which allowed me to mix css and xpath choices. Your example would look like this:

 find('#some_button').find(:xpath,".//..").fill_in "Name:", :with => name 

Updating Capybara 2.0 : find(:xpath,".//..") will most likely result in an Ambiguous match error. In this case, use first(:xpath,".//..") .

+98
Jul 07 2018-11-11T00:
source share

There is no way to do this with capybara and CSS. I have used XPath in the past to achieve this, although it has a way to get the parent and is supported by Capybara:

 find(:xpath, '//*[@id="some_button"]/..').fill_in "Name:", :with => name 
+37
Feb 01 2018-11-11T00:
source share

This did not work for me with an error:

 Ambiguous match, found 2 elements matching xpath ".//.." 

I found the following that works:

 find(:xpath, '..') 

Capybara has been updated to support this.

https://github.com/jnicklas/capybara/pull/505

+20
Aug 16 '12 at 1:11
source share

If you stumbled upon this while trying to figure out how to find the parent (as with the ancestor) of the node (as indicated in the @ vrish88 comment on @Pascal Lindelauf's answer):

 find('#some_button').find(:xpath, 'ancestor::div[@id="some_div_id"]') 
+6
Jan 08 '14 at 0:07
source share

This answer relates to how to manipulate the brother element, which, it seems to me, relates to the original question, relates to

Your question hypothesis works with a minor tweak. If a dynamically generated field looks like this and does not have an identifier:

 <div> <input></input> <button>Test</button> </div> 

Then your request:

 find('button', text: 'Test').find(:xpath, "..").find('input').set('whatever') 

If dynamically generated input is connected using the id element (be careful with them, as in angular, they usually change depending on adding and removing elements), it will be something like this:

 find('button', text: 'Test').find(:xpath, "..").fill_in('#input_1', with: 'whatever') 

Hope this helps.

+4
Mar 08 '16 at 20:35
source share

I take a different approach by first finding the parent element using the text inside this parent element:

 find("<parent element>", text: "text within your #some_button").fill_in "Name:", with: name 

Perhaps this is useful in a similar situation.

+3
Apr 25 2018-12-12T00:
source share

I needed to find the ancestor with the css class, although it was undefined if the target ancestor had one or more CSS classes, so I did not see a way to make a deterministic xpath request. Instead, I worked on this:

 def find_ancestor_with_class(field, cssClass) ancestor = field loop do ancestor = ancestor.find(:xpath, '..') break if ancestor.nil? break if ancestor.has_css? cssClass end ancestor end 

Warning: use this sparingly, it can cost you a lot of time in tests, so make sure that the ancestor is only a few jumps away.

+2
Nov 06 '14 at
source share
-5
Jan 30 '13 at 15:04
source share



All Articles