On Sun, Mar 8, 2009 at 12:00 PM, Phlip <phlip2...@gmail.com> 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 > > �...@scope.wrap_expectation self do > �...@scope.assert_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 > rspec-users@rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users > _______________________________________________ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users