[rspec-users] Problem with Custom matcher and Blocks

Brandon Olivares programmer2188 at gmail.com
Wed Apr 1 21:25:32 EDT 2009


Hi,

I'm trying to write my first custom matcher.

Here's a bit of my example group.

describe "/contact/index" do
  include FormMatchers
  
  before(:each) do
    render 'contact/index'
  end
  
  it "should show the contact form" do
    response.should have_a_contact_form
  end
  
  describe "the contact form" do
    context "before it has been submitted" do
      it "should have a subject dropdown box" do
        response.should have_a_contact_form do |form|
          form.should have_a_subject_field
        end
      end # it "should have a subject dropdown box"

      # This should be failing
      it "should have a name field" do
        response.should have_a_contact_form do |form|
          form.should have_a_name_field
        end
      end # it "should have a name field"
    
      describe "the subject dropdown box" do
        it "should have a feedback option" do
          response.should have_a_contact_form do |form|
            form.should have_a_subject_field do |subject|
              subject.should have_selector('option', :content => 'Feedback')
            end
          end
        end # it "should have a feedback option"

        # Etc...
        
      end # describe "the subject dropdown box"
      
    end # context "before the form has been submitted"
    
  end # Describe "the contact form"
  
end # describe "/contact/index"

Right now, everything before the describe "the subject dropdown box" is
passing, even though the one testing the name field should not because I've
not added that field yet.

When it gets to the describe block for the subject, I get:

NoMethodError in '/contact/index the contact form before it has been
submitted the subject dropdown box should have a blank option'
undefined method `have_selector' for
#<FormMatchers::HaveAFormWithID:0x7f3260ac>

The have_a_contact_form method is as follows:

  def have_a_contact_form &block
    have_a_form_with_id 'contact', &block
  end

That calls a have_a_form_with_id method, which calls the haveAFormWithID
class.

module FormMatchers
  
  class HaveAFormWithID
    
    def initialize id, &block
      @id = id
      @block = block
    end
    
    def matches? response
      response.should have_selector('form#%s' % [@id]) do |form|
        !@block or @block.call form
      end
    end
      
    def description
      "have a form with id #{@id}"
    end
      
    def failure_message
      "expected to have a form with ID #{@id}"
    end
      
    def negative_failure_message
      "expected not to have a form with ID #{@id}"
    end
    
  end
  
  def have_a_form_with_id id, &block
    HaveAFormWithID.new id, &block
  end
  
end

Sorry for all the code. Again this is my first custom matcher, so I could be
doing something very wrong.

Any help much appreciated.

Thanks,
Brandon



More information about the rspec-users mailing list