within_any?

1 view
Skip to first unread message

RubyRedRick

unread,
Nov 9, 2009, 9:36:52 AM11/9/09
to webrat
I just recently got into using webrat in earnest, driven by cucumber.

I was a bit surprised by the behavior of the webrat step:

Then /^I should see "([^\"]*)" within "([^\"]*)"$/ do |text,
selector|
within(selector) do |content|
content.should contain(text)
end
end

I had expected that if I said something like:

Then I should see "Shazbot" within "div.catchphrase"

it would be interpreted, "there should be some div on the page with
class 'catchphrase', containing "Shazbot".

But the way this is implemented it looks like it only examines the
FIRST such div. My mental picture is that within works like $() in
Prototype and yields a single element, while I expected more jQuery
semantics, a collection of matching dom elements.

I understand that within is normaly used in webrat to select the
target for an action, and the semantics makes sense for that, I guess.

I'd like to implement a cucumber step which looks for content in all
dom elements which match the selector,

Maybe
Then I should see "Shazbot" within any "div.catchphrase"

but I can't quite figure out the right approach for the underlying
use of webrat.

Ideally it should work with and without Selenium, and it would be
nice if it could be nested.


Any ideas?

Damian Janowski

unread,
Nov 9, 2009, 10:13:49 PM11/9/09
to web...@googlegroups.com
On Mon, Nov 9, 2009 at 11:36 AM, RubyRedRick <rick.d...@gmail.com> wrote:
>
> I just recently got into using webrat in earnest, driven by cucumber.
>
> I was a bit surprised by the behavior of the webrat step:
>
>   Then /^I should see "([^\"]*)" within "([^\"]*)"$/ do |text,
> selector|
>       within(selector) do |content|
>         content.should contain(text)
>       end
>   end
>
> I had expected that if I said something like:
>
>    Then I should see "Shazbot" within "div.catchphrase"
>

Really? Expressed like that in a written-by-the-client, natural
language feature file?

Anyway... I do use #within to restrict some assertions to avoid false
positives. But I wouldn't make it that specific, it only makes your
integration tests brittle. So I do:

within "#some_big_container" do
assert_contain "Foo"
end

If you really want it, you could use :nth-child or the XPath
equivalents, they should work...

Rick DeNatale

unread,
Nov 10, 2009, 7:11:43 AM11/10/09
to web...@googlegroups.com
On Mon, Nov 9, 2009 at 10:13 PM, Damian Janowski
<damian....@gmail.com> wrote:
>
> On Mon, Nov 9, 2009 at 11:36 AM, RubyRedRick <rick.d...@gmail.com> wrote:
>>
>> I just recently got into using webrat in earnest, driven by cucumber.
>>
>> I was a bit surprised by the behavior of the webrat step:
>>
>>   Then /^I should see "([^\"]*)" within "([^\"]*)"$/ do |text,
>> selector|
>>       within(selector) do |content|
>>         content.should contain(text)
>>       end
>>   end
>>
>> I had expected that if I said something like:
>>
>>    Then I should see "Shazbot" within "div.catchphrase"
>>
>
> Really? Expressed like that in a written-by-the-client, natural
> language feature file?

Yes really. I think that it's a valid interpretation. I don't read
any ordering of which div.catchphrase it should be in.

but as I said a bit later, just to make it clearer, I'd write a
different step so that I could say

I should see "foo" within any "whatever"

or maybe within some/


>
> Anyway... I do use #within to restrict some assertions to avoid false
> positives. But I wouldn't make it that specific, it only makes your
> integration tests brittle. So I do:
>
> within "#some_big_container" do
>  assert_contain "Foo"
> end
>
> If you really want it, you could use :nth-child or the XPath
> equivalents, they should work...

my whole goal is to allow what I need to express without making things
brittle. If the ordering is truly unimportant, then using :nth-child
will break if the order changes.

In fact I did use :nth-child as a workaround, and I now have to change
the story because the ordering just did in fact change.


--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Damian Janowski

unread,
Nov 10, 2009, 8:21:29 AM11/10/09
to web...@googlegroups.com
On Tue, Nov 10, 2009 at 9:11 AM, Rick DeNatale <rick.d...@gmail.com> wrote:
> my whole goal is to allow what I need to express without making things
> brittle.  If the ordering is truly unimportant, then using :nth-child
> will break if the order changes.
>
> In fact I did use :nth-child as a workaround, and I now have to change
> the story because the ordering just did in fact change.

Then maybe something like this?

def assert_contain_in_any(content, selector)
hc = HasContent.new(content)

elements = Nokogiri::HTML(last_response.body).search(selector)

assert elements.any? { |el| hc.matches?(el.inner_text) }
end

Reply all
Reply to author
Forward
0 new messages