How can I find a specific item that appears immediately after another item with Capybara?

I am trying to use Learn Capybara to perform a scraping task. I have so far used it only for testing. There are a million things that I want to learn, but in the most basic part I want to know how to find a certain element that is a sibling, and comes for another element that I can find?

Take this page:

<body> <h3>Name1</h3> <table> ... </table> <h3>Name2</h3> <table> ... </table> <h3>Name3</h3> <table> ... </table> </body> 

I want to return the <table> element that appears after the <h3> element with the text Name2.

I know how to iterate over elements with all , and I know how to use first instead of find , but I don't know how to "find the first element of X following a specific element of Y".

+5
source share
1 answer

CSS

In CSS you can use a selector. They allow you to choose the elements of marriage; or those that are on the same nesting level and with the same parent element. There are two types of selectors:

  • '+' adjacent sibling selector
  • '~' general sibling selector (adjacent or non-adjacent siblings)

It is usually ideal to avoid overlapping text whenever possible. (This makes writing your specifications easier and also means that text changes are less likely to violate your specifications.) In this ideal world, your β€œh3” elements can have identifiers on them, and we could simply:

 find('h3#name2+table') 

However, in your example, they do not have identifiers, so let’s connect a couple of requests to the scope for what we want.

 find('h3', text: 'Name2').find('+table') 

First, we found the correct element "h3" (using text matching), and then with this query, as a basis, we request the element "table" sibling.

You may also notice that if you used the general "~" selector, you would get an ambiguous element error; Capybara found all the elements of the table, not just the neighboring ones.

XPath

Sometimes XPath is actually easier to use if you are really forced to select text elements. So you could instead:

 find(:xpath, "//h3[contains(text(),'Name2')]/following-sibling::table") 

It’s harder to read, but it does the same. First find "h3" with the text "Name2" and then select the sibling element "table".

+5
source

All Articles