Search code examples
ruby-on-railsrspecruby-on-rails-2

How do I set up a custom RSpec 1 example group?


I'm using RSpec 1 and rspec-rails to test my Rails 2.3.14 application. In this same application, I'm using Draper to provide decorators for my models. I want to be able to test my decorators.

I've got specs in spec/decorators, but as best as I can tell, because rspec-rails doesn't recognize the decorators/ path, and therefore doesn't wire up any of the extra Rails stuff into the specs.

How do I set up RSpec to recognize my spec/decorators path, and cause it to include the functionality I need (which is going to be route/helper functionality)?

I notice that RSpec has things like HelperExampleGroup, ControllerExampleGroup, etc, and I suspect that these implicitly map to spec/helpers and spec/controllers and such, but I'm unclear as to how to leverage this to set up my own DecoratorHelperGroup.

I feel like I'm 90% of the way there, but can't quite make that final connection. Examples would be most valuable, but I'll take an abstract, as well.


Solution

  • Solved it. The magic sauce is Spec::Example::ExampleGroupFactory.register

    For the record, here's my complete spec/support/decorators.rb

    module Spec
      module Rails
        module Example
          class DecoratorExampleGroupController < ApplicationController
            attr_reader :template
    
            def view_context
              template
            end
          end
    
          # spec/decorators
          class DecoratorExampleGroup < FunctionalExampleGroup
            if ActionView::Base.respond_to?(:load_helpers) # Rails 2.0.x
              ActionView::Helpers.constants.each do |name|
                const = ActionView::Helpers.const_get(name)
                include const if name.include?("Helper") && Module === const
              end
            elsif ActionView::Base.respond_to?(:helper_modules) # Rails 2.1.x
              ActionView::Base.helper_modules.each do |helper_module|
                include helper_module
              end
            else # Rails 2.2.x
              include ActionView::Helpers
            end
    
            tests DecoratorExampleGroupController
    
            class << self
              def decorate(options = {})
                self.subject { described_class.new(yield, options) }
              end
            end
    
            before :each do
              @controller.template.request = @request
              @controller.set_current_view_context
            end
    
            Spec::Example::ExampleGroupFactory.register(:decorator, self)
    
          protected
            def _assigns_hash_proxy
              @_assigns_hash_proxy ||= AssignsHashProxy.new(self) {@response.template}
            end
          end
        end
      end
    end
    

    All this effectively does is register specs under spec/decorators to operate as view specs (which gets me all the pieces I need). Before each decorator spec, calling #set_current_view_context on the controller invokes the Draper bits necessary to wire helpers up into my decorators. I also added a decorate method to use the current described decorator class to decorate an arbitrary object, allowing easy decoration of objects for testing. Mission accomplished!