On Sun, Mar 8, 2009 at 2:03 PM, David Chelimsky <[email protected]> wrote:
> 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
>
I like this a lot.
>
>
>
>>
>> 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
>
--
Zach Dennis
http://www.continuousthinking.com
http://www.mutuallyhuman.com
_______________________________________________
rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users