Assert Xhtml

assert_xhtml{} is a system to TDD HTML by example.

Suppose your HTML output contained this:

  <div id='toprated_posts'>
    <ul>
      <li id="post_23">
        <a href="/post/23">Goofy LolCats</a>
      </li>
      <li id="post_24">
        <a href="/post/24">Dark LolCats</a>
      </li>
    </ul>
  </div>

Now suppose your (wildly innovative!!;) blog categorizes its LOLs, and lets the user pick LolCats or LolDogs. Testing that the view contains only cats, not dogs, can be problematic.

(After testing the Model and Controller) you can test the View with this RubyOnRails assertion:

    a_lolcat = posts(:Goofy_Lolcats).id
    a_loldog = posts(:Sick_LolDogs).id
    get :category, :topic_name => 'LolCats'

assert_xhtml do div.toprated_content! do # .! is a shortcut for an ID li :id => :"video_#{a_lolcat}" without!{ li :id => :"video_#{a_loldog}" } end end

The content between the do-end tags is raw Ruby. The do-end tags [use a magic thing called Nokogiri::HTML::Builder to] convert the Ruby into an HTML example.

assert_xhtml then simply detects that your @response.body (per MockTheWebServer?) contains HTML with that example HTML as a subset. Any extra elements or attributes are ignored.

This allows you to skip over the details liable to change - and the details too boring or glitzy to test - and only focus on the parts of your HTML that reflect your BusinessRules.

Get it with AssertTwoPointOh. Oh, and it also works on AjaxWebApplications, like this:

  def test_deleting_a_staff_sets_active_flag_to_false_instead_of_destroying_it
    aaron = staff(:aaron)
    xhr :post, :xhr_delete_staff, :staff_id => aaron.id

assert_rjs_ :replace_html, :staff_list, /quentin/ do # detects Element.update("staff_list", "..html..") on the wire form :name => :staff_access, :verbose! => false do without!{ tr :id => "staff_#{ aaron.id }" } end end

assert{ Staff.find_by_id(aaron.id).active? == false } end

Version 0.5.3 will be able to do this:

  test 'clicking the plus-minus toggles you' do
    a = assert_xhtml{|x|  x.a :href => '#'  }
    assert_rjs_ a[:onclick], :toggle, 'account'
  end

That reaches into a page and finds an <a href='#' onclick='Element.toggle("account");; return false;'>. Then it returns the a as a Nokogiri node, letting us pull out the a[:onclick]

assert_rjs_ lets you pass the raw JavaScript as the first argument. Then this matches the :toggle to the RJS .toggle command which generated that JavaScript.

Not too shabby, huh? The good news is these techniques push up the value of your WaTir tests, by catching all the dumb JavaScript bugs rapidly and efficiently, before they ever get to a real web browser...


EditText of this page (last edited May 10, 2009) or FindPage with title or text search