Custom, nested HTML matchers in RSpec


#1

Zach D. wrote:

response.body.should be_xml_with do
form :action => ‘/users’ do
fieldset do
legend “Personal Information”
label “First name”
input :type => ‘text’, :name => ‘user[first_name]’
end
end
end

I like this a lot.

Boom: http://gist.github.com/76136

it ‘should have a form with a fieldset’ do
render ‘/users/new’

 response.body.should be_html_with{
   form :action => '/users' do
     fieldset do
       legend 'Personal Information'
       label 'First name'
       input :type => 'text', :name => 'user[first_name]'
     end
   end
 }

end

I think I never got around to writing that because I just always assumed
someone
already had. I have to watch that about myself!

Only one feature is missing: At fault time, the matcher naturally prints
out a
diagnostic containing two snips of HTML - the specification’s reference,
and
your page’s sample. (Both, of course, are restricted to the fault’s
context -
not the whole page.) But…

The samples are not indented! The specification’s reference is all run
together,
and your page’s sample is (unfortunately!) exactly the way your View
system
generated it. I have a question out to Nokogiri about this…


Phlip
http://www.zeroplayer.com/


#2

http://gist.github.com/76136

response.body.should be_html_with{
  form :action => '/users' do
    fieldset do
      legend 'Personal Information'
      label 'First name'
      input :type => 'text', :name => 'user[first_name]'
    end
  end
}

Has anyone tried this? is it useful?


#3

On Mon, Mar 9, 2009 at 6:20 PM, Phlip removed_email_address@domain.invalid wrote:

}

Has anyone tried this? is it useful?

I haven’t tried it yet, but it does seem very useful. The project I’m
focused on right now is all json all the time, so I don’t personally
have a real world case for this at the moment. Anybody doing an app w/
html views willing to try this out?


#4

Has anyone tried this? is it useful?

It looks interesting, though it could be confused for trying to exactly
mimic the actual markup, not just specify interesting parts.


#5

On Mon, Mar 9, 2009 at 6:49 PM, Pat N. removed_email_address@domain.invalid
wrote:

Has anyone tried this? is it useful?

It looks interesting, though it could be confused for trying to exactly
mimic the actual markup, not just specify interesting parts.

What is the method name was be_html_including instead of be_html_with???


#6

Pat N. wrote:

Has anyone tried this? is it useful?

It looks interesting, though it could be confused for trying to exactly
mimic the actual markup, not just specify interesting parts.

It only specifies interesting parts. The gist writeup explained that,
for
example, it skipped over intermediate

  1. tags. And it naturally
    skips
    blanks in contents, and unlisted attributes.

    It is exactly the same as the XPath version I posted before. That used
    explicit
    XPath queries to skip over uninteresting parts.

    David C. wrote:

    What is the method name was be_html_including instead of
    be_html_with???

    (‘be_html_including’.length - ‘be_html_with’.length) / 17 =~ 30%.

    So 30% fewer people would bother to type it!


#7

I haven’t tried it yet, but it does seem very useful. The project I’m
focused on right now is all json all the time, so I don’t personally
have a real world case for this at the moment. Anybody doing an app w/
html views willing to try this out?

I put it into my current project today (as a >cough< TestCase
assertion),
replaced a couple of xpath assertions with it, and showed it to my
colleagues.

I injected a fault, and show the diagnostic with the two batches of HTML
in it -
the reference and sample.

One of them was like, “Nice, but where’s the syntax highlighting?”

This refers to eyes rolling --> @-/


#8

On Sun, Mar 15, 2009 at 1:05 PM, Phlip removed_email_address@domain.invalid wrote:

Has anyone tried this? is it useful?

The and live in different containers, so they are not peers
of each other. But the assertion specifies they are!

I didn’t have the expectation that they were peers of each other, just
that they both existed somewhere in a fieldset tag. Any helper or
matchers used for spec’ing views should be as liberal as possible
while still communicating enough about the semantics of the page for
the example to be meaningful.

I would not expect nor want a matcher to default to verifying direct
descendant, sibling, or adjacent nodes. Those are best verified by a
person looking at the page. What I do care about is that fields in are
within a fieldset (but not necessarily immediately next to each
other).

     end
   end
 end

}

I don’t like this, we are specifying the “li” but that provides no
meaning of the page, it’s strictly markup for presentation.

the substance submitted for analysis, and “reference” for the known sample
used to calibrate the test.)


Phlip


rspec-users mailing list
removed_email_address@domain.invalid
http://rubyforge.org/mailman/listinfo/rspec-users


Zach D.
http://www.continuousthinking.com
http://www.mutuallyhuman.com


#9

response.body.should be_html_with{
form :action => ‘/users’ do
fieldset do
legend ‘Personal Information’
label ‘First name’
input :type => ‘text’, :name => ‘user[first_name]’
end
end
}

Has anyone tried this? is it useful?

That assertion sucks! The actual sample HTML sez:

Personal Information
  1. First name

The and live in different containers, so they are not
peers of
each other. But the assertion specifies they are!

I think the assertion should fault until you specify at least this:

 response.body.should be_html_with{
   form :action => '/users' do
     fieldset do
       legend 'Personal Information'
       li do
         label 'First name'
         input :type => 'text', :name => 'user[first_name]'
       end
     end
   end
 }

Notice we have some conflicting requirements:

  • you can skip any tag
  • the reference should “look like” the sample (except it’s in Ruby)

But you should not be able to skip a tag if its absence makes the
reference
“look different” from the sample. Hence, the test should require at
least one of
the

  1. tags that separate the two contexts…

    (BTW the common verbiage for chemical tests of analytes here is “sample”
    for the
    substance submitted for analysis, and “reference” for the known sample
    used to
    calibrate the test.)


    Phlip


#10

Zach D. wrote:

other).
However, I constantly must write extra test code just to check things
are in the
right order. Specifically, I could not use my original assert_xhtml to
replace
tests that checked some values appeared in collating order.
(Yes, tests
on the model also checked those fields appeared in collating order, AND
tests on
the controller checked thru the “assigns” that those fields were in
collating
order…)

I am not going to target strict relationships, just the general order.
But I
have to draw the line somewhere!


#11

On Mar 15, 2009, at 10:33 AM, Zach D. wrote:

id=“user_first_name” />
matchers used for spec’ing views should be as liberal as possible
while still communicating enough about the semantics of the page for
the example to be meaningful.

I would not expect nor want a matcher to default to verifying direct
descendant, sibling, or adjacent nodes. Those are best verified by a
person looking at the page. What I do care about is that fields in are
within a fieldset (but not necessarily immediately next to each
other).

Both of those points make sense to me. What about

response.body.should be_html_with{
form :action => ‘/users’ do
fieldset do
legend ‘Personal Information’

     anything do
       label 'First name'
       input :type => 'text', :name => 'user[first_name]'

end
end
end
}

I dunno. Zach’s original attempt hardly “sucks”. But maybe you want
to make the structure a bit more explicit? Personally I think that it
becomes too coupled to the HTML, and “anything {}” is added noise, but
maybe that gets you moving in the right direction.

Pat


#12

Pat M. wrote:

I dunno. Zach’s original attempt hardly “sucks”.

That was David C.'s attempt - Zach seconded it. But I was
replying to myself.

More important, the tie-breaker here is very simple:

 When the assertion fails, can it
 tell you exactly how to fix things?

That means if you must make the assertion less strict, you should get a
clue
how to make it less strict!

maybe that gets you moving in the right direction.

Don’t make me tell you under what circumstances I learned graph theory.
(-:


Phlip