I use rspec 2.6.0 and Capybara 1.1.1 for acceptance testing.
With a view like the following:
<tr >
<td>Team 3 Name</td>
<td>true</td>
<td><a href="/teams/3">Show</a></td>
<td><a href="/teams/3/edit">Edit</a></td>
<td><a href="/teams/3">Deactivate</a></td>
</tr>
<tr >
<td>Team 4 Name</td>
<td>true</td>
<td><a href="/teams/4">Show</a></td>
<td><a href="/teams/4/edit">Edit</a></td>
<td><a href="/teams/4">Deactivate</a></td>
</tr>
I want to write an acceptance test that states: "Team 3 does NOT have the 'Deactivate' link." I expect the following to fail:
within('tr', :text => 'Team 3 Name') do |ref|
page.should_not have_selector('a', :text => 'Deactivate')
end
But it passes. To further test what is going on, I wrote the absurd:
lock = false
within('tr', :text => 'Team 3 Name') do |ref|
page.should have_selector('a', :text => 'Deactivate')
page.should_not have_selector('a', :text => 'Deactivate')
lock = true
end
lock.should be_true
Which passes as well.
I am assuming from this that the scope the have_selector() call is using is not limited by the within() block, but I am not sure why this is. The capybara documentation uses this pattern and does not seem to mention any gotchas.
What is the correct way to use within to limit the scope of my select?
Thank you.
/Salernost
Best Answer
Still learning Capybara myself, but have you tried
have_link
instead ofhave_selector
? Also I don't think you need|ref|
. For example:Update October 13, 2012
Having come a little further with Capybara, I see several potential issues here:
within
may silently ignore thetext
field. You'll notice that the examples only show CSS or XPath finders without additional arguments.within
does usetext
, it may not work here because you are asking it to look at the<tr>
, but the text is in the<td>
.page
subject still targets the entire page even if you are in awithin
block. Thewithin
examples are mostly about usingfill_in
orclick
. The exception is the example under Beware the XPath // trap.As for creating a
within
block, you can either give your table rows unique ids and search for them using CSS, or you may be able to write a specific XPath targeting the first matching row.The problem with the latter is that you want use the
within
on the<tr>
, but the text you are using for your targeting is inside a<td>
subelement. So for example, this XPath should find the table cell containing the textTeam 3 Name
but then you are only workingwithin
that first cell, not the whole row.There are ways to "back up" to a parent element using XPath but I don't know how to do it and I've read that it's not good practice. I think your best bet here might be to just generate ids so your rows start like this:
then target them with a simple