[rspec-users] how to write complex matchers

Yury Kotlyarov yura at brainhouse.ru
Thu Feb 12 12:12:26 EST 2009


David Chelimsky wrote:
> On Thu, Feb 12, 2009 at 5:52 AM, Yury Kotlyarov <yura at brainhouse.ru> wrote:
>   
>> Hi,
>>
>> I am trying to write custom matcher which accepts block to spec views with
>> forms/fieldsets/inputs eg
>>
>> view:
>> ---
>> <form action='/users'>
>>  <fieldset>
>>   <legend>Personal Information</legend>
>>   <ol>
>>     <li>
>>       <label>First name</label>
>>       <input type="text" name="user[first_name]" />
>>     </li>
>>     ...
>>   </ol>
>>  </fieldset>
>> </form>
>>
>> spec:
>> ---
>>
>> it "should have form with input fields" do
>>  render ...
>>  response.should have_form(users_path) do
>>   with_field_set 'Personal Information' do
>>     with_text_field 'First name', 'user[first_name]'
>>     ...
>>   end
>>  end
>> end
>>
>> matches? of have_form:
>> ---
>>
>>   def matches?(response, &block)
>>     @block = block if block
>>     response.should @scope.have_tag('form[action=?]', @action) do
>>       @block.call.matches?(response)
>>     end
>>   end matches? of have_field_set: ---
>>
>>   def matches?(response, &block)
>>
>>     @block = block if block
>>     response.should @scope.with_tag('fieldset') do
>>       @scope.with_tag('legend', @legend) if @legend
>>       @scope.with_tag('ol') do
>>         @block.call.matches?(response)
>>       end
>>     end
>>   end but I get: NoMethodError in '/users/new should have form with input
>> fields' undefined method `matches?' for true:TrueClass
>> ./spec/views/users/../../custom_ui_matchers/with_field_set.rb:10:in
>> `matches?' ./spec/views/users/../../custom_ui_matchers/have_form.rb:11:in
>> `matches?' ./spec/views/users/../../custom_ui_matchers/have_form.rb:10:in
>> `matches?' ./spec/views/users/new.html.haml_spec.rb:17:
>> /usr/lib64/ruby/1.8/timeout.rb:53:in `timeout' something wrong with yielding
>> block? Gist: http://gist.github.com/62562 Thanks in advance, Yury
>>     
>
> What does initialize look like?
>
>   

initialize for have_form:

class HaveForm     def initialize(action, scope, &block)
      @action, @scope, @block = action, scope, block
    end ... end

  def have_form(action, &block)
    HaveForm.new(action, self, &block)
  end


initialize for have_field_set:
   
  class WithFieldSet
    def initialize(scope, legend = nil, &block)
      @scope, @legend, @block = scope, legend, block
    end
  end

  def with_field_set(legend = nil, &block)
    WithFieldSet.new(self, legend, &block)
  end



btw I put it on gist: http://gist.github.com/62562



More information about the rspec-users mailing list