1

I'm trying to chain find methods in Capybara and not having much luck. I would expect the second find to only look for text in the output of the first find. However, the second find searches the entire document.

element = page_foo.find('.bar')
element.find('div', :text => "name")

=> All divs with the text "name" on the page.

A solution using xpath was described here:

capybara - Find with xPath is leaving the within scope

However, I am not too familiar with xpath and hope to find a way to work around it.

Additional details:

HTML:

<div data-id="tabMeListProducts">
  <div class=" title">My BMW 5-SERIES GRAN TURISMO.</div>
</div>

<div data-id="tabMeListPosts">
  <div class="name">My BMW 5-SERIES GRAN TURISMO.</div>
</div>

RSPEC:

element = page_foo.find('[data-id="tabMeListProducts"]')
  =>#<Capybara::Element tag="div">
element.find('div', :text => "My BMW 5-SERIES GRAN TURISMO.")
  =>Capybara::Ambiguous: Ambiguous match, found 2 elements matching css "div" with text "My BMW 5-SERIES GRAN TURISMO."

As you can see from the example above the second find's scope is the entire page and is not contained within the element passed in by the initial find.

I would expect the find to only look within the div contained in the variable "element".

Community
  • 1
  • 1
lcharbon
  • 3,030
  • 2
  • 16
  • 18
  • Can you please explain: what you are trying to do with your find? Some sample data, and what should be the results that you expect - and what are the results you are getting instead? – Taryn East May 11 '15 at 23:58
  • Also: have you considered using "within" ? eg `within find('.bar') { find('div', :text => "name") }` – Taryn East May 11 '15 at 23:59
  • Hi Taryn, I appreciate you trying to help. The question has been updated based on your feedback. – lcharbon May 12 '15 at 15:49

2 Answers2

3

I remember nested find calls working in past versions of Cucumber or Capybara. However, things change with every version. Regardless, your example is more easily handled with nested CSS expressions instead of relying on multiple finds.

For example:

page_foo.find('[data-id="tabMeListProducts"] .title')

or

page_foo.find('[data-id="tabMeListProducts"] div', :text => "My BMW 5-SERIES GRAN TURISMO.")

If there are multiple occurrences, I would use all instead of find and run my own Ruby checking logic on the collection.

Also, within usually works as an alternative (no need to call find with it as one response mentioned, you can add CSS directly next to it):

  element.find('div', :text => "My BMW 5-SERIES GRAN TURISMO.")
end

Lastly, if you insist on using nested find calls, try doing them on the same Ruby line as mentioned by the Capybara documentation: page.find('#foo').find('.bar') It's possible it's lazy fetched, but activates at the end of a Ruby line (through meta-programming checks for line number).

If all else fails, open a GitHub issue: http://www.rubydoc.info/github/jnicklas/capybara/Capybara/Node/Finders#find-instance_method

M--
  • 25,431
  • 8
  • 61
  • 93
Andy Maleh
  • 31
  • 5
1

I agree with @Taryn, You need to use within syntex. i.e

within(".bar")do
     find('div', :text => "name")
end 
Raza Hussain
  • 762
  • 8
  • 18
  • The way my testing is set up, I am passed the variable "element" containing the element to be searched as a parameter and must perform a search using this variable. Would it be possible to do anything similar to. `within(element) do find('div', :text => "name") end` – lcharbon May 12 '15 at 15:54