On Sun, Mar 8, 2009 at 12:00 PM, Phlip <[email protected]> wrote:
> RSpecsters:
>
> I like nested XPath expressions, because the outer XPath assertion can clip
> the diagnostic of the inner XPath assertion. You don't get the whole page
> spewed into your face when you fault!
>
> This specification, for example, tests Yury Kotlyarov's user login page,
> from:
>
> http://github.com/yura/howto-rspec-custom-matchers/tree/master
>
> it 'should have xpathic tags' do
> render '/users/new'
>
> response.body.should be_xml_with{
> xpath :form, :action => '/users' do
> xpath :fieldset do
> xpath :'legend[ contains(., "Personal Information") ]' and
> xpath :'label[ contains(., "First name") ]' and
> xpath :input, :type => 'text', :name => 'user[first_name]'
> end
> end
> }
> end
This is nice, but the abstractions are operating at different levels.
The keyword is "xpath" but the args passed to that look nothing like
xpath. How about something like:
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
>
> That tests this (otherwise innocuous) new.html.erb:
>
> <form action="/users">
> <fieldset>
> <legend>Personal Information</legend>
> <ol>
> <li id="control_user_first_name">
> <label for="user_first_name">First name</label>
> <input type="text" name="user[first_name]" id="user_first_name" />
> </li>
> </ol>
> </fieldset>
> </form>
>
> If that code had any major complex <%= erb %> activity, the tests^W
> specifications would keep it honest.
>
> Let's change the specification, to simulate a bug, and try it:
>
> xpath :input, :type => 'text', :name => 'user[first_nome]' # was _name
>
> That provides this mind-blast of errata:
>
> '/users/new should have xpathic tags' FAILED
> xpath: "descendant-or-self::inp...@type = $type and @name = $name]"
> arguments: {"name"=>"user[first_nome]", "type"=>"text"}
>
> xml context:
>
> <fieldset>
> <legend>
> Personal Information
> </legend>
> <ol>
> <li id='control_user_first_name'>
> <label for='user_first_name'>
> First name
> </label>
> <input name='user[first_name]' type='text' id='user_first_name'/>
> </li>
> </ol>
> </fieldset>
>
> assert{ ( ( xpath(:"legend[ contains(., \"Personal Information\") ]") ) and
> ( ( ( xpath(:"label[ contains(., \"First name\") ]") ) and
> ( xpath(:input, { :type => "text", :name => "user[first_nome]" }) ) ) ) )
> }
> --> nil - should pass
>
> xpath(:"legend[ contains(., \"Personal Information\") ]")
> --> <legend> ... </>
>
> xpath(:"label[ contains(., \"First name\") ]")
> --> <label for='user_first_name'> ... </>
>
> xpath(:input, { :type => "text", :name => "user[first_nome]" })
> --> nil
>
> ./spec/views/users/new.html.erb_spec.rb:63:
> script/spec:5:
>
> Finished in 0.116823 seconds
>
> 2 examples, 1 failure
>
> Note that the error message restricted itself to the XHTML inside the <form>
> tag. This is a major benefit when diagnosing a huge page that failed. (But
> also note that your HTML, like your code, should come in small reusable
> snippets, such as partials, and that these should get tested directly!)
>
> Soon I will upgrade this system to use Nokogiri instead of (>cough<) REXML.
>
> Now, while I go and put the "simple" matcher that does this onto Twitter,
> YouTube, Mingle, Facebook, Mindfuck, Reddit, Tumblog, LinkedIn, and Gist,
> you all can just read it below my sig.
>
> --
> Phlip
> http://www.zeroplayer.com/
>
> require File.dirname(__FILE__) + "/../../spec_helper"
> require 'assert2/xpath'
> require 'spec/matchers/wrap_expectation'
>
> Spec::Runner.configure do |c|
> c.include Test::Unit::Assertions
> end # TODO blog this
>
> describe "/users/new" do
>
> it "should have user form" do
> render '/users/new'
> response.should have_form('/users') do
> with_field_set 'Personal Information' do
> with_text_field 'First name', 'user', 'first_name'
> end
> end
> end
>
> class BeXmlWith
>
> def initialize(scope, &block)
> �...@scope, @block = scope, block
> end
>
> def matches?(stwing, &block)
> waz_xdoc = @xdoc
>
> �[email protected]_expectation self do
> �[email protected]_xhtml stwing
> return (block || @block || proc{}).call
> end
> ensure
> �...@xdoc = waz_xdoc
> end
>
> attr_accessor :failure_message
>
> def negative_failure_message
> "yack yack yack"
> end
> end
>
> def be_xml_with(&block)
> BeXmlWith.new(self, &block)
> end
>
> def be_xml_with_(&block)
> waz_xdoc = @xdoc
> simple_matcher 'yo' do |given, matcher|
> wrap_expectation matcher do
> assert_xhtml given # this works
> block.call # crashes with a nil.first error!
> end
> end
> ensure
> �...@xdoc = waz_xdoc
> end
>
> it 'should have xpathic tags' do
> render '/users/new'
>
> response.body.should be_xml_with{
> xpath :form, :action => '/users' do
> xpath :fieldset do
> xpath :'legend[ contains(., "Personal Information") ]' and
> xpath :'label[ contains(., "First name") ]' and
> xpath :input, :type => 'text', :name => 'user[first_name]'
> end
> end
> }
> end
>
> end
>
> _______________________________________________
> rspec-users mailing list
> [email protected]
> http://rubyforge.org/mailman/listinfo/rspec-users
>
_______________________________________________
rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users