Skip to content
Browse files

Stub template content in controller specs instead of using NullResolver

- this requires templates to exist, but ...
- still isolates specs from template content

Thanks to José Valim for the assist.
  • Loading branch information...
1 parent 471d6d8 commit 61f5bcc8a79d2199759563f4fd12c1b6948c9e11 @dchelimsky dchelimsky committed Jun 27, 2010
View
11 README.markdown
@@ -88,11 +88,12 @@ available from Rails.
You can use RSpec expectations/matchers or Test::Unit assertions.
## `render_views`
-By default, controller specs do not render views (as of beta.9).
-This supports specifying controllers without concern for whether
-the views they render work correctly or even exist. If you prefer
-to render the views (a la Rails' functional tests), you can use the
-`render_views` declaration in each example group:
+By default, controller specs do not render views. This supports specifying
+controllers without concern for whether the views they render work correctly
+(NOTE: the template must exist, unlike rspec-rails-1. See Upgrade.markdown for
+more information about this). If you prefer to render the views (a la Rails'
+functional tests), you can use the `render_views` declaration in each example
+group:
describe SomeController do
render_views
View
26 Upgrade.markdown
@@ -2,23 +2,23 @@
## Controller specs
-### render_views
+### islation from view templates
-Controller specs, by default, do _not_ render views. This helps keep the
-controller specs focused on the controller. Use `render_views` instead of
-rspec-1's `integrate_views` to tell the spec to render the views:
+By default, controller specs do _not_ render view templates. This keeps
+controller specs isolated from the content of views and their requirements.
- describe WidgetController do
- render_views
-
- describe "GET index" do
- ...
+NOTE that the template must exist, but it will not be rendered. This is
+different from rspec-rails-1.x, in which the template didn't need to exist, but
+ActionController makes a number of new decisions in Rails 3 based on the
+existence of the template. To keep the RSpec code free of monkey patches, and
+to keep the rspec user experience simpler, we decided that this would be a fair
+trade-off.
## View specs
-Rails changed the way it renders partials, so to set an expectation that a partial
-gets rendered:
+Rails changed the way it renders partials, so to set an expectation that a
+partial gets rendered:
- view.should_receive(:_render_partial).
- with(hash_including(:partial => "widget/row"))
+ render
+ view.should render_template(:partial => "widget/_row")
View
23 ...troller_specs/do_not_render_views.feature → ...roller_specs/isolation_from_views.feature
@@ -1,11 +1,12 @@
Feature: do not render views
- By default, controller specs do not render views. This
- allows you specify which view template an action should
- try to render regardless of whether that template exists
- or compiles cleanly.
+ By default, controller specs do not render views. This allows you specify
+ which view template an action should try to render regardless of whether or
+ not the template compiles cleanly.
- Scenario: expect template that exists and is rendered by controller (passes)
+ NOTE: unlike rspec-rails-1.x, the template must exist.
+
+ Scenario: expect template that rendered by controller (passes)
Given a file named "spec/controllers/widgets_controller_spec.rb" with:
"""
require "spec_helper.rb"
@@ -26,7 +27,7 @@ Feature: do not render views
When I run "rspec ./spec"
Then I should see "2 examples, 0 failures"
- Scenario: expect template that exists but is not rendered by controller (fails)
+ Scenario: expect template that is not rendered by controller (fails)
Given a file named "spec/controllers/widgets_controller_spec.rb" with:
"""
require "spec_helper.rb"
@@ -43,19 +44,19 @@ Feature: do not render views
When I run "rspec ./spec"
Then I should see "1 example, 1 failure"
- Scenario: expect template that does not exist and is not rendered by controller (fails)
+ Scenario: set expectation about template content (fails with helpful message)
Given a file named "spec/controllers/widgets_controller_spec.rb" with:
"""
require "spec_helper.rb"
describe WidgetsController do
describe "index" do
- it "renders a template that does not exist" do
+ it "renders the 'new' template" do
get :index
- response.should render_template("does_not_exist")
+ response.should contain("foo")
end
end
end
"""
- When I run "rspec ./spec"
- Then I should see "1 example, 1 failure"
+ When I run "rspec spec"
+ Then I should see "Template source generated by RSpec"
View
48 lib/rspec/rails/view_rendering.rb
@@ -20,17 +20,55 @@ def render_views?
end
end
+ module ::ActionView
+ # Delegates find_all to the submitted controller's view_paths and then
+ # returns templates with modified source
+ class PathSetDelegatorResolver < Resolver
+ attr_reader :path_set
+
+ def initialize(controller)
+ @controller = controller
+ @path_set = controller.class.view_paths
+ end
+
+ def find_all(*args)
+ template_source = <<-SOURCE
+#{"*"*80}
+Template source generated by RSpec. If you prefer to render view templates
+in your specs, add render_views to the example group, like this:
+
+ describe MyController do
+ render_views
+
+Debug info:
+
+ controller: #{@controller.class}
+ resolver: #{self.class}
+ args: #{args.inspect}
+#{"*"*80}
+SOURCE
+
+ templates = @path_set.find_all(*args)
+ templates.each do |t|
+ t.singleton_class.__send__ :define_method, :source do |*|
+ template_source
+ end
+ end
+ end
+ end
+ end
+
included do
before do
- @_view_paths = controller.class.view_paths
- controller.class.view_paths = [ActionView::NullResolver.new()] unless
- self.class.render_views?
+ @_path_set_delegator_resolver = ::ActionView::PathSetDelegatorResolver.new(@controller)
+ @controller.class.view_paths = ::ActionView::PathSet.new.push(@_path_set_delegator_resolver)
end
-
+
after do
- controller.class.view_paths = @_view_paths
+ @controller.class.view_paths = @_path_set_delegator_resolver.path_set
end
end
+
end
end
end

0 comments on commit 61f5bcc

Please sign in to comment.
Something went wrong with that request. Please try again.