Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 268 lines (231 sloc) 9.152 kb
6d673c2 Made the following renames:
btakita authored
1 module Spec
2 module Rails
3 module Example
4 # Controller Examples live in $RAILS_ROOT/spec/controllers/.
5 #
6853e88 David Chelimsky general cleanup
authored
6 # Controller Examples use Spec::Rails::Example::ControllerExampleGroup,
7 # which supports running specs for Controllers in two modes, which
8 # represent the tension between the more granular testing common in TDD
9 # and the more high level testing built into rails. BDD sits somewhere
10 # in between: we want to a balance between specs that are close enough
11 # to the code to enable quick fault isolation and far enough away from
12 # the code to enable refactoring with minimal changes to the existing
13 # specs.
6d673c2 Made the following renames:
btakita authored
14 #
15 # == Isolation mode (default)
16 #
6853e88 David Chelimsky general cleanup
authored
17 # No dependencies on views because none are ever rendered. The benefit
18 # of this mode is that can spec the controller completely independent of
19 # the view, allowing that responsibility to be handled later, or by
20 # somebody else. Combined w/ separate view specs, this also provides
21 # better fault isolation.
6d673c2 Made the following renames:
btakita authored
22 #
23 # == Integration mode
24 #
25 # To run in this mode, include the +integrate_views+ declaration
26 # in your controller context:
27 #
28 # describe ThingController do
29 # integrate_views
30 # ...
31 #
6853e88 David Chelimsky general cleanup
authored
32 # In this mode, controller specs are run in the same way that rails
33 # functional tests run - one set of tests for both the controllers and
34 # the views. The benefit of this approach is that you get wider coverage
35 # from each spec. Experienced rails developers may find this an easier
36 # approach to begin with, however we encourage you to explore using the
37 # isolation mode and revel in its benefits.
6d673c2 Made the following renames:
btakita authored
38 #
39 # == Expecting Errors
40 #
e98e0c7 Brandon Keepers Add failing code examples to show that errors captured by rescue_from
bkeepers authored
41 # Rspec on Rails will raise errors that occur in controller actions and
42 # are not rescued or handeled with rescue_from.
6d673c2 Made the following renames:
btakita authored
43 #
44 class ControllerExampleGroup < FunctionalExampleGroup
45 class << self
c3321ac better examples (and a better fix) for http://rspec.lighthouseapp.com/pr...
dchelimsky authored
46
6853e88 David Chelimsky general cleanup
authored
47 # Use integrate_views to instruct RSpec to render views in
48 # your controller examples in Integration mode.
6d673c2 Made the following renames:
btakita authored
49 #
50 # describe ThingController do
51 # integrate_views
52 # ...
53 #
6853e88 David Chelimsky general cleanup
authored
54 # See Spec::Rails::Example::ControllerExampleGroup for more
55 # information about Integration and Isolation modes.
4df2c72 Pat Maddox got nested integrate_views working
patmaddox authored
56 def integrate_views(integrate_views = true)
57 @integrate_views = integrate_views
6d673c2 Made the following renames:
btakita authored
58 end
4df2c72 Pat Maddox got nested integrate_views working
patmaddox authored
59
6d673c2 Made the following renames:
btakita authored
60 def integrate_views? # :nodoc:
61 @integrate_views
62 end
4df2c72 Pat Maddox got nested integrate_views working
patmaddox authored
63
64 def inherited(klass) # :nodoc:
65 klass.integrate_views(integrate_views?)
5d114be Joe Ferris Changed ControllerExampleGroup to use controller as the implicit subject...
jferris authored
66 klass.subject { controller }
4df2c72 Pat Maddox got nested integrate_views working
patmaddox authored
67 super
68 end
08f32ac Zach Dennis fixed issue where ControllerExampleGroup wasn't respecting #controller_n...
zdennis authored
69
6853e88 David Chelimsky general cleanup
authored
70 def set_description(*args) # :nodoc:
98f7d8a David Chelimsky cleaning up example group classes - remove controller_class_name
authored
71 super
08f32ac Zach Dennis fixed issue where ControllerExampleGroup wasn't respecting #controller_n...
zdennis authored
72 if described_class && described_class.ancestors.include?(ActionController::Base)
73 controller_klass = if superclass.controller_class.ancestors.include?(ActionController::Base)
74 superclass.controller_class
75 else
76 described_class
77 end
78 tests controller_klass
98f7d8a David Chelimsky cleaning up example group classes - remove controller_class_name
authored
79 end
80 end
08f32ac Zach Dennis fixed issue where ControllerExampleGroup wasn't respecting #controller_n...
zdennis authored
81
6853e88 David Chelimsky general cleanup
authored
82 # When you don't pass a controller to describe, like this:
83 #
84 # describe ThingsController do
85 #
86 # ... then you must provide a controller_name within the context of
6d673c2 Made the following renames:
btakita authored
87 # your controller specs:
88 #
89 # describe "ThingController" do
90 # controller_name :thing
91 # ...
92 def controller_name(name)
98f7d8a David Chelimsky cleaning up example group classes - remove controller_class_name
authored
93 tests "#{name}_controller".camelize.constantize
6d673c2 Made the following renames:
btakita authored
94 end
95 end
9fd1279 David Chelimsky Derive example group classes from the rails test cases
authored
96
6d673c2 Made the following renames:
btakita authored
97 before(:each) do
98 # Some Rails apps explicitly disable ActionMailer in environment.rb
99 if defined?(ActionMailer)
100 @deliveries = []
101 ActionMailer::Base.deliveries = @deliveries
102 end
103
104 unless @controller.class.ancestors.include?(ActionController::Base)
6853e88 David Chelimsky general cleanup
authored
105 Spec::Expectations.fail_with <<-MESSAGE
106 Controller specs need to know what controller is being specified. You can
107 indicate this by passing the controller to describe():
108
109 describe MyController do
110
111 or by declaring the controller's name
112
113 describe "a MyController" do
114 controller_name :my #invokes the MyController
115 end
116 MESSAGE
6d673c2 Made the following renames:
btakita authored
117 end
6853e88 David Chelimsky general cleanup
authored
118 @controller.extend ControllerInstanceMethods
d0d2afc David Chelimsky remove initialize method to reduce dependency on rspec-core internals
authored
119 @controller.integrate_views! if integrate_views?
6d673c2 Made the following renames:
btakita authored
120 @controller.session = session
121 end
122
123 attr_reader :response, :request, :controller
939d745 David Chelimsky Delegate route_for to assert_recognizes.
authored
124
d0d2afc David Chelimsky remove initialize method to reduce dependency on rspec-core internals
authored
125 def integrate_views?
126 @integrate_views || self.class.integrate_views?
127 end
128
40ce2c3 David Chelimsky Add bypass_rescue for controller specs
authored
129 # Bypasses any error rescues defined with rescue_from. Useful
130 # in cases in which you want to specify errors coming out of
131 # actions that might be caught by a rescue_from clause that is
132 # specified separately.
133 #
134 # Note that this will override the effect of rescue_action_in_public
135 def bypass_rescue
136 if ::Rails::VERSION::STRING >= '2.2'
137 def controller.rescue_action(exception)
138 raise exception
139 end
140 else
141 def controller.rescue_action_with_handler(exception)
142 raise exception
143 end
144 end
145 end
146
de90533 David Chelimsky refactor BEFORE running the full build, remember?
authored
147 protected
148
149 def _assigns_hash_proxy
6853e88 David Chelimsky general cleanup
authored
150 @_assigns_hash_proxy ||= AssignsHashProxy.new(self) {@response.template}
de90533 David Chelimsky refactor BEFORE running the full build, remember?
authored
151 end
152
153 private
b578d76 David Chelimsky clean up template extensions related to isolation
authored
154
155 module TemplateIsolationExtensions
156 def file_exists?(ignore); true; end
157
158 def render_file(*args)
159 @first_render ||= args[0] unless args[0] =~ /^layouts/
160 end
161
162 # Rails 2.2
163 def _pick_template(*args)
164 @_first_render ||= args[0] unless args[0] =~ /^layouts/
165 PickedTemplate.new
166 end
167
168 def render(*args)
7feca16 David Chelimsky FINALLY figured out how to restore ability for isolated controller specs
authored
169 if file = args.last[:file].instance_eval{@template_path}
170 record_render :file => file
171 elsif args.last[:inline]
172 super
173 elsif @_rendered
174 record_render(args[0])
175 else
176 super
177 end
6853e88 David Chelimsky general cleanup
authored
178 end
179
180 private
181
182 def record_render(opts)
183 (@_rendered[:template] ||= opts[:file]) if opts[:file]
184 (@_rendered[:partials][opts[:partial]] += 1) if opts[:partial]
185 end
186
187 # Returned by _pick_template when running controller examples in isolation mode.
188 class PickedTemplate
189 # Do nothing when running controller examples in isolation mode.
190 def render_template(*ignore_args); end
191 # Do nothing when running controller examples in isolation mode.
192 def render_partial(*ignore_args); end
b578d76 David Chelimsky clean up template extensions related to isolation
authored
193 end
194 end
6853e88 David Chelimsky general cleanup
authored
195
196 module ControllerInstanceMethods # :nodoc:
6d673c2 Made the following renames:
btakita authored
197 include Spec::Rails::Example::RenderObserver
198
b578d76 David Chelimsky clean up template extensions related to isolation
authored
199 # === render(options = nil, extra_options={}, &block)
6d673c2 Made the following renames:
btakita authored
200 #
201 # This gets added to the controller's singleton meta class,
202 # allowing Controller Examples to run in two modes, freely switching
6853e88 David Chelimsky general cleanup
authored
203 # from example group to example group.
b702dfb David Chelimsky support 2 arg version of ActionController::Base#render
authored
204 def render(options=nil, extra_options={}, &block)
6d673c2 Made the following renames:
btakita authored
205 unless block_given?
206 unless integrate_views?
b578d76 David Chelimsky clean up template extensions related to isolation
authored
207 @template.extend TemplateIsolationExtensions
6d673c2 Made the following renames:
btakita authored
208 end
209 end
210
42cb7ce Pass block to mock_proxy if and_yield is used in expect_render on a cont...
dchelimsky authored
211 if matching_message_expectation_exists(options)
eb53fc0 David Chelimsky deprecate expect_render and stub_render in favor of rails-specific exten...
authored
212 render_proxy.render(options, &block)
6d673c2 Made the following renames:
btakita authored
213 @performed_render = true
214 else
f909c0d got rspec-rails working against edge rails (as of e48e77e0222292176cd9f6...
David Chelimsky authored
215 if matching_stub_exists(options)
216 @performed_render = true
217 else
b702dfb David Chelimsky support 2 arg version of ActionController::Base#render
authored
218 super
6d673c2 Made the following renames:
btakita authored
219 end
220 end
221 end
42cb7ce Pass block to mock_proxy if and_yield is used in expect_render on a cont...
dchelimsky authored
222
7feca16 David Chelimsky FINALLY figured out how to restore ability for isolated controller specs
authored
223 # Rails 2.3
224 def default_template(action_name = self.action_name)
225 if integrate_views?
226 super
227 else
228 begin
229 super
230 rescue ActionView::MissingTemplate
231 "#{self.class.name.sub(/Controller$/,'').underscore}/#{action_name}"
232 end
233 end
234 end
235
6d673c2 Made the following renames:
btakita authored
236 def response(&block)
237 # NOTE - we're setting @update for the assert_select_spec - kinda weird, huh?
238 @update = block
1857415 David Chelimsky add example specifying template extension (rails-2.3 only for now)
authored
239 super
6d673c2 Made the following renames:
btakita authored
240 end
241
242 def integrate_views!
243 @integrate_views = true
244 end
245
6853e88 David Chelimsky general cleanup
authored
246 private
1857415 David Chelimsky add example specifying template extension (rails-2.3 only for now)
authored
247
6d673c2 Made the following renames:
btakita authored
248 def integrate_views?
249 @integrate_views
250 end
6bbe80f David Chelimsky Decouple mock framework from global extensions used by rspec.
authored
251
252 def matching_message_expectation_exists(options)
6853e88 David Chelimsky general cleanup
authored
253 render_proxy.__send__(:__mock_proxy).__send__(:find_matching_expectation, :render, options)
6bbe80f David Chelimsky Decouple mock framework from global extensions used by rspec.
authored
254 end
255
256 def matching_stub_exists(options)
6853e88 David Chelimsky general cleanup
authored
257 render_proxy.__send__(:__mock_proxy).__send__(:find_matching_method_stub, :render, options)
6bbe80f David Chelimsky Decouple mock framework from global extensions used by rspec.
authored
258 end
259
6d673c2 Made the following renames:
btakita authored
260 end
261
262 Spec::Example::ExampleGroupFactory.register(:controller, self)
6853e88 David Chelimsky general cleanup
authored
263
e11c5b5 'should render_template' ignores layouts [#508 state:resolved]
David Chelimsky authored
264 end
6d673c2 Made the following renames:
btakita authored
265 end
266 end
267 end
Something went wrong with that request. Please try again.