Search code examples
ruby-on-railstestingrubygemsrspecformtastic

How do I test a Formtastic custom input with rspec?


I have a rubygem that defines a custom SemanticFormBuilder class which adds a new Formtastic input type. The code works as expected, but I cannot figure out how to add tests for it. I was thinking I could do something like load up Formtastic, call semantic_form_for, and then ad ann input that uses my custom :as type, but I have no idea where to begin.

Does anyone know of any gems that do something like this that I could take a look at the source for? Any suggestions on where to begin?

My gem requires Rails 2.3.x

The source for my custom input looks like this, and I'm including it in an initializer in my application:

module ClassyEnumHelper
  class SemanticFormBuilder < Formtastic::SemanticFormBuilder
    def enum_select_input(method, options)
      enum_class = object.send(method)

      unless enum_class.respond_to? :base_class
        raise "#{method} does not refer to a defined ClassyEnum object" 
      end

      options[:collection] = enum_class.base_class.all_with_name
      options[:selected] = enum_class.to_s

      select_input(method, options)
    end
  end
end

Not sure if any of my other source code would help, but it can be found here http://github.com/beerlington/classy_enum


Solution

  • Testing your output

    Our team has had success with this approach, which I think we originally borrowed from Formtastic's own tests.

    First, create a buffer to capture the output you want to test.

    # spec/support/spec_output_buffer.rb
    class SpecOutputBuffer
      attr_reader :output
    
      def initialize
        @output = ''.html_safe
      end
    
      def concat(value)
        @output << value.html_safe
      end
    end
    

    Then call semantic_form_for in your test, capturing the output to your buffer. Once you've done that, you can test that the output was what you expected.

    Here's an example where I overrode StringInput to add an integer CSS class to inputs for integer model properties.

    # spec/inputs/string_input_spec.rb
    require 'spec_helper'
    
    describe 'StringInput' do
    
      # Make view helper methods available, like `semantic_for_for`
      include RSpec::Rails::HelperExampleGroup
    
      describe "classes for JS hooks" do
    
        before :all do
          @mothra = Mothra.new
        end
    
        before :each do
          @buffer = SpecOutputBuffer.new
          @buffer.concat(helper.semantic_form_for(@mothra, :url => '', as: 'monster') do |builder|
            builder.input(:legs).html_safe +
            builder.input(:girth).html_safe
          end)
        end
    
        it "should put an 'integer' class on integer inputs" do
          @buffer.output.should have_selector('form input#monster_legs.integer')
        end
      end
    end