<= Home
RSPEC View tests that use helpers
RSpec 0.9.1 is out and is a great library for BDD. But I have some problems when testing views. The syntax is a bit clunky when a view calls a helper method. Lets say I have a view:
<%= if current_user.is?(:admin) %>
render some html for admins
<% end %>
When testing my view specs 9.1 enables helpers to be loaded using the :helpers option for the render method
Example (lifted straight from rspec_rails file view_spec_spec.rb):
describe "Given a view requiring an explicit helper", :behaviour_type => :view do
before(:each) do
render "view_spec/explicit_helper", :helper => 'explicit'
end
it "the helper should be included if specified" do
response.should have_tag('div', :content => "This is text from a method in the ExplicitHelper")
end
end
What this does is when the view is rendered it will mixin the helper ExplicitHelper dynamically. There are a couple problems with this but the main one being my view is now dependent on the helper's implementation. And since helpers are modules, gook luck trying to mock module methods. The second problem is in my example the current_user method is actually on the controller and not in a helper at all. So to resolve both issues I wanted to specify helper methods that I would mock with out depending on a helper module.
To do do this, the following code to the end of your spec_helper.rb.
module Spec
module Rails
module DSL
class ViewEvalContext < Spec::Rails::DSL::FunctionalEvalContext
def mock_helper_method method
@controller.template.expects(method)
end
end
end
end
end
This will allow you to right views that do not depend on any helper's implementation.
describe "/content/index", :behaviour_type => :view do
it "should allow editing content when user is admin"
mock_helper_method(:current_user).returns(mock)
render '/content/index'
response.should have_tag('div.edit-content')
end
end
Note: I am using the mocha library for mocking which uses the method 'expects'. If you are using rspec's built in mocking then replace:
@controller.template.expects(method)with
@controller.template.should_recieve(method)