Gmail Calendar Documents Reader Web more »
Recently Visited Groups | Help | Sign in
Google Groups Home
assert2-0.4.6 provides assert_xhtml, an alternative to assert_select
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  1 message - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Phlip  
View profile  
 More options Mar 26, 8:53 am
From: Phlip <phlip2...@gmail.com>
Date: Thu, 26 Mar 2009 05:53:35 -0700
Local: Thurs, Mar 26 2009 8:53 am
Subject: [ANN] assert2-0.4.6 provides assert_xhtml, an alternative to assert_select
Rubyists:

Consider the following monstrosity, coded using assert_select:

   assert_select "div#logo_box img[src=/0000/0001/logo.gif][alt=My Company]"

Now, behold it rewritten to use assert_xhtml:

   assert_xhtml do
     div.logo_box! do
       img :src => /logo.gif$/, :alt => 'My Company'
     end
   end

That sample contains more Ruby; it's not just one big string.

Still not convinced? Oh, I forgot the <a> around the <img>! Try this:

   assert_xhtml do
     div.logo_box! do
       a :href => '/' do
         img :src => /logo.gif$/, :alt => 'My Company'
       end
     end
   end

And we had an issue with the small logo sneaking into the logo_box once. Let's
exclude it:

   assert_xhtml do
     div.logo_box do
       a :href => '/' do
         img :src => /logo.gif$/, :alt => 'My Company'
       end
       without!{ img :src => /mini_logo.gif/ }
     end
   end

Imagine adding all that to assert_select - it would get much harder to read, and
more complex. assert_xhtml uses Nokogiri::HTML::Builder notation, so anything it
can build, you can query.

Version 0.4.6 adds all the following features. To begin, enter:

   gem install nokogiri assert2

== require 'assert2/xhtml' ==

All assert{ 2.0 } dependencies are optional. If you have Nokogiri
(>=1.2.2), you can test Rails views like this:

      user = users(:Moses)
      get :edit_user, :id =>  user.id

      assert_xhtml do

        form :action =>  '/users' do
          fieldset do
            legend 'Personal Information'
            label 'First name'
            input :type =>  'text',
                  :name =>  'user[first_name]'
                  :value =>  user.first_name
          end
        end

      end

That's a Rails functional test on a form. The assertion expects the form
to target the given action, and contain a fieldset, a legend, a label, and
a populated text input field. The assertion forgives any other details,
such as intervening structural tags, excess spaces, or extra attributes;
and complains if any required detail is missing, out of order, or ill-formed.

The DSL inside that block is Nokogiri::HTML::Builder notation. Generally
speaking, anything Nokogiri can build, you can specify.

=== arguments ===

Call assert_xhtml(my_xml){} to interrogate your XML. When called without
an argument, the method reads @response.body.

=== without! ===

Every assert* has a matching deny* method. assert_xhtml recognizes the
special element without! as a request to fail if the given elements
do indeed appear in your output:

     get :info, :record_id => record.id
     assert_xhtml do
       div :class => :content do
         without!{ div :class => :download }
       end
     end

That assertion will fail if the outer <div class='content'> tag does not
exist, or if any inner <div class='download'> does exist.

The without! element respects your document layout. This assertion
passes...

     assert_xhtml SAMPLE_LIST do
       ul{ li{ ul{ li 'Sales report'
           without!{ li 'All Sales report criteria' } } } }
     end

...even though the target document contains an <li>All Sales report
criteria</li>:

     <ul style='font-size: 18'>
       <li>model
         <ul>
           <li>Billings report</li>
           <li>Sales report</li>
           <li>Billings criteria</li>
           <li>Common system</li>
         </ul>
       </li>
       <li>controller
         <ul>
           <li>All Sales report criteria</li>
           <li>All Billings reports</li>
         </ul>
       </li>
     </ul>

The two <li> elements appear in different <ul> lists, so the assertion
does not associate them.

The committee does not yet know what without!{ without!{} } does, so please
do not rely on its current behavior, whatever that is!

=== escapes ===

Certain elements, such as <select> and <id>, have the same names as internal
methods. If you experience a bizarre error message, such as "wrong argument
type Hash (expected Array)", add a ! to the end of the element, like this:

     assert_xhtml do
       h2 'Sites'

       select! :id => 'sites',
               :name => 'sites[]',
               :multiple => :multiple,
               :size => SaleController::LIST_SIZE
     end

=== text ===

An element such as h3{ 'text' } will match <h3> text </h3>, with leading or
trailing blanks, but it won't match <h3><span>text</span></h3>. This rule
prevents runaway matches between high- and low-level elements.

The example for the next section illustrates how to mix text and attribute
specifications on the same element.

A text specification may be a /regexp/.

=== :xpath!=> ===

assert_xhtml works by throwing away structural information. If you need
more control over your structure, use an :xpath! attribute to apply raw
XPath specifications to your target elements.

This assertion detect the rather pedestrian fact that your <title>
element remains inside your <html><head> block - and it did not
escape and rampage off to somewhere else:

     assert_xhtml do
       title :xpath! => 'parent::head/parent::html' do
         text 'Chamber of Commerce - Info - Hope Orphanage'
       end
     end

Note the XPath evaluates as a predicate of the target <title>, so its parent
axis lists the familiar elements in reverse.

That code also shows the 'text' directive, inserting text contents directly
into the enclosing element. A future version of Nokogiri will allow the
element's first argument to specify its text.

An :xpath! of a number evaluates to the 1-based index of an item in its
parent. This assertion forces list items to appear in the correct order:

     assert_xhtml do
       ul :style => 'font-size: 18' do
         li 'model' do
           li(:xpath! => 1){ text 'Sales report'  }
           li(:xpath! => 2){ text 'Billings report' }
           li(:xpath! => 3){ text 'Billings criteria' }
         end
       end
     end

=== :verbose! => true ===

Sometimes when an assertion fails, you can't tell why. To see each
context the assertion considers, add :verbose! => true to the lowest
element you know works, and run the tests:

     assert_xhtml SAMPLE_FORM do
       fieldset do
         li :verbose! => true do
           label 'First name', :for => :user_first_name
         end
       end
     end

The verbose option works as "spew", not as a diagnostic, and it reports
each considered element's contents.

Because XPath evaluates the <label>, in our example, before the <li>, you
might need to comment the <label> out to see a successful spew on the <li>.

=== scope ===

assert_xhtml{} yields its block to Nokogiri::HTML::Builder, which turns
every method call into an HTML element. This freedom comes at a price -
you can't easily call your own methods!

Use this scope trick to pass your outer scope into the specification:

      get :edit_user, :id => users(:Moses).id
      scope = self

      assert_xhtml do
        form :action => '/users' do
          input :value => scope.users(:Moses).first_name
        end
      end

Notice we could improve that test by declaring a variable,
user = users(:Moses), in the outer scope, and simply passing
the user variable itself into the specification.

=== :class=> ===

The :class attribute is magic. This assertion passes...

     assert_xhtml SAMPLE_LIST do
       ul :class => :kalika do
         li 'Billings report'
       end
     end

...despite the actual HTML contains <ul class='kalika goddess'>. This feature
simulates the CSS Selector notation that matches classes by their cascading
effects.

=== class & ID shortcuts ===

Nokogiri expands div.rad.thing! to <div class='rad' id='thing'/>. That
means you don't need to write div :class => 'rad', :id => 'thing' (or
ul :class => :kalika). You can then put other arguments after the shortcut,
and the <div> in our example receives them, too.

=== diagnostic message ===

When this assertion fails, it attempts to print out...

  - your reference elements, rendered as HTML
  - each "near-miss" region of your sample HTML

The next version will feature much better diagnostics. Until they work, if these
diagnostics are not sufficient, put :verbose! on the lowest element you think
works, and comment out its contents...

=== RSpec ===

The matching "specification", in RSpec language, is be_html_with{}.
Its syntax and behavior are the same:

   it 'should have a cute form' do
     render '/users/new'

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

Good hunting!

--
   Phlip


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google