Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 247 lines (219 sloc) 9.308 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 #
6 # Controller Examples use Spec::Rails::Example::ControllerExampleGroup, which supports running specs for
7 # Controllers in two modes, which represent the tension between the more granular
8 # testing common in TDD and the more high level testing built into
9 # rails. BDD sits somewhere in between: we want to a balance between
10 # specs that are close enough to the code to enable quick fault
11 # isolation and far enough away from the code to enable refactoring
12 # with minimal changes to the existing specs.
13 #
14 # == Isolation mode (default)
15 #
16 # No dependencies on views because none are ever rendered. The
17 # benefit of this mode is that can spec the controller completely
18 # independent of the view, allowing that responsibility to be
19 # handled later, or by somebody else. Combined w/ separate view
20 # specs, this also provides better fault isolation.
21 #
22 # == Integration mode
23 #
24 # To run in this mode, include the +integrate_views+ declaration
25 # in your controller context:
26 #
27 # describe ThingController do
28 # integrate_views
29 # ...
30 #
31 # In this mode, controller specs are run in the same way that
32 # rails functional tests run - one set of tests for both the
33 # controllers and the views. The benefit of this approach is that
34 # you get wider coverage from each spec. Experienced rails
35 # developers may find this an easier approach to begin with, however
36 # we encourage you to explore using the isolation mode and revel
37 # in its benefits.
38 #
39 # == Expecting Errors
40 #
e98e0c7 @bkeepers 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
6d673c2 Made the following renames:
btakita authored
47 # Use this to instruct RSpec to render views in your controller examples (Integration Mode).
48 #
49 # describe ThingController do
50 # integrate_views
51 # ...
52 #
53 # See Spec::Rails::Example::ControllerExampleGroup for more information about
54 # Integration and Isolation modes.
4df2c72 @patmaddox got nested integrate_views working
patmaddox authored
55 def integrate_views(integrate_views = true)
56 @integrate_views = integrate_views
6d673c2 Made the following renames:
btakita authored
57 end
4df2c72 @patmaddox got nested integrate_views working
patmaddox authored
58
6d673c2 Made the following renames:
btakita authored
59 def integrate_views? # :nodoc:
60 @integrate_views
61 end
4df2c72 @patmaddox got nested integrate_views working
patmaddox authored
62
63 def inherited(klass) # :nodoc:
2dd2e9f @patmaddox tiny tidy
patmaddox authored
64 klass.controller_class_name = controller_class_name
4df2c72 @patmaddox got nested integrate_views working
patmaddox authored
65 klass.integrate_views(integrate_views?)
66 super
67 end
6d673c2 Made the following renames:
btakita authored
68
69 # You MUST provide a controller_name within the context of
70 # your controller specs:
71 #
72 # describe "ThingController" do
73 # controller_name :thing
74 # ...
75 def controller_name(name)
76 @controller_class_name = "#{name}_controller".camelize
77 end
78 attr_accessor :controller_class_name # :nodoc:
79 end
80
81 before(:each) do
82 # Some Rails apps explicitly disable ActionMailer in environment.rb
83 if defined?(ActionMailer)
84 @deliveries = []
85 ActionMailer::Base.deliveries = @deliveries
86 end
87
88 unless @controller.class.ancestors.include?(ActionController::Base)
89 Spec::Expectations.fail_with <<-EOE
90 You have to declare the controller name in controller specs. For example:
91 describe "The ExampleController" do
92 controller_name "example" #invokes the ExampleController
93 end
94 EOE
95 end
d89f9ec moved metaclass method from Object to module that gets included where it...
dchelimsky authored
96 (class << @controller; self; end).class_eval do
6d673c2 Made the following renames:
btakita authored
97 def controller_path #:nodoc:
98 self.class.name.underscore.gsub('_controller', '')
99 end
100 include ControllerInstanceMethods
101 end
102 @controller.integrate_views! if @integrate_views
103 @controller.session = session
104 end
105
106 attr_reader :response, :request, :controller
107
d7c0773 @dchelimsky add options hash for ExampleGroupMethods.initialize
authored
108 def initialize(defined_description, options={}, &implementation) #:nodoc:
6d673c2 Made the following renames:
btakita authored
109 super
110 controller_class_name = self.class.controller_class_name
111 if controller_class_name
112 @controller_class_name = controller_class_name.to_s
113 else
114 @controller_class_name = self.class.described_type.to_s
115 end
116 @integrate_views = self.class.integrate_views?
117 end
118
119 # Uses ActionController::Routing::Routes to generate
120 # the correct route for a given set of options.
121 # == Example
122 # route_for(:controller => 'registrations', :action => 'edit', :id => 1)
123 # => '/registrations/1;edit'
124 def route_for(options)
125 ensure_that_routes_are_loaded
126 ActionController::Routing::Routes.generate(options)
127 end
128
129 # Uses ActionController::Routing::Routes to parse
130 # an incoming path so the parameters it generates can be checked
131 # == Example
132 # params_from(:get, '/registrations/1;edit')
133 # => :controller => 'registrations', :action => 'edit', :id => 1
134 def params_from(method, path)
135 ensure_that_routes_are_loaded
136 ActionController::Routing::Routes.recognize_path(path, :method => method)
137 end
138
139 protected
8bffabe Added #helper method to helper specs.
dchelimsky authored
140 def _assigns_hash_proxy
5bb22b4 @dchelimsky Modified AssignsHashProxy to work w/ changes on edge rails as well as al...
authored
141 @_assigns_hash_proxy ||= AssignsHashProxy.new self do
142 @response.template
143 end
6d673c2 Made the following renames:
btakita authored
144 end
145
146 private
147 def ensure_that_routes_are_loaded
148 ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty?
149 end
150
151 module ControllerInstanceMethods #:nodoc:
152 include Spec::Rails::Example::RenderObserver
153
ae83544 Applied patch from Rick Olson to get rspec_on_rails working with rails e...
dchelimsky authored
154 # === render(options = nil, deprecated_status_or_extra_options = nil, &block)
6d673c2 Made the following renames:
btakita authored
155 #
156 # This gets added to the controller's singleton meta class,
157 # allowing Controller Examples to run in two modes, freely switching
158 # from context to context.
2a42334 @dchelimsky get rid of deprecated_status_or_extra_options which were removed in rail...
authored
159 def render(options=nil, &block)
ae83544 Applied patch from Rick Olson to get rspec_on_rails working with rails e...
dchelimsky authored
160
6d673c2 Made the following renames:
btakita authored
161 unless block_given?
162 unless integrate_views?
9def451 Patch from Ian White to get rspec working with edge rails (8804). Also a...
dchelimsky authored
163 if @template.respond_to?(:finder)
d89f9ec moved metaclass method from Object to module that gets included where it...
dchelimsky authored
164 (class << @template.finder; self; end).class_eval do
e11c5b5 'should render_template' ignores layouts [#508 state:resolved]
David Chelimsky authored
165 define_method :file_exists? do; true; end
9def451 Patch from Ian White to get rspec working with edge rails (8804). Also a...
dchelimsky authored
166 end
167 else
d89f9ec moved metaclass method from Object to module that gets included where it...
dchelimsky authored
168 (class << @template; self; end).class_eval do
e11c5b5 'should render_template' ignores layouts [#508 state:resolved]
David Chelimsky authored
169 define_method :file_exists? do; true; end
6d673c2 Made the following renames:
btakita authored
170 end
9def451 Patch from Ian White to get rspec working with edge rails (8804). Also a...
dchelimsky authored
171 end
d89f9ec moved metaclass method from Object to module that gets included where it...
dchelimsky authored
172 (class << @template; self; end).class_eval do
6d673c2 Made the following renames:
btakita authored
173 define_method :render_file do |*args|
e11c5b5 'should render_template' ignores layouts [#508 state:resolved]
David Chelimsky authored
174 @first_render ||= args[0] unless args[0] =~ /^layouts/
fbb0347 change pick_template to _pick_template
David Chelimsky authored
175 @_first_render ||= args[0] unless args[0] =~ /^layouts/
f909c0d got rspec-rails working against edge rails (as of e48e77e0222292176cd9f6...
David Chelimsky authored
176 end
177
fbb0347 change pick_template to _pick_template
David Chelimsky authored
178 define_method :_pick_template do |*args|
e11c5b5 'should render_template' ignores layouts [#508 state:resolved]
David Chelimsky authored
179 @_first_render ||= args[0] unless args[0] =~ /^layouts/
180 PickedTemplate.new
6d673c2 Made the following renames:
btakita authored
181 end
8cb529c @dchelimsky Record calls to render and check rendered[:template] and rendered[:parti...
authored
182
183 define_method :render do |*args|
184 if @_rendered
185 opts = args[0]
186 (@_rendered[:template] ||= opts[:file]) if opts[:file]
187 (@_rendered[:partials][opts[:partial]] += 1) if opts[:partial]
188 else
189 super
190 end
191 end
6d673c2 Made the following renames:
btakita authored
192 end
193 end
194 end
195
42cb7ce Pass block to mock_proxy if and_yield is used in expect_render on a cont...
dchelimsky authored
196 if matching_message_expectation_exists(options)
eb53fc0 @dchelimsky deprecate expect_render and stub_render in favor of rails-specific exten...
authored
197 render_proxy.render(options, &block)
6d673c2 Made the following renames:
btakita authored
198 @performed_render = true
199 else
f909c0d got rspec-rails working against edge rails (as of e48e77e0222292176cd9f6...
David Chelimsky authored
200 if matching_stub_exists(options)
201 @performed_render = true
202 else
2a42334 @dchelimsky get rid of deprecated_status_or_extra_options which were removed in rail...
authored
203 super(options, &block)
6d673c2 Made the following renames:
btakita authored
204 end
205 end
206 end
42cb7ce Pass block to mock_proxy if and_yield is used in expect_render on a cont...
dchelimsky authored
207
6d673c2 Made the following renames:
btakita authored
208 def response(&block)
209 # NOTE - we're setting @update for the assert_select_spec - kinda weird, huh?
210 @update = block
211 @_response || @response
212 end
213
214 def integrate_views!
215 @integrate_views = true
216 end
217
218 private
219
220 def integrate_views?
221 @integrate_views
222 end
6bbe80f @dchelimsky Decouple mock framework from global extensions used by rspec.
authored
223
224 def matching_message_expectation_exists(options)
eb53fc0 @dchelimsky deprecate expect_render and stub_render in favor of rails-specific exten...
authored
225 render_proxy.send(:__mock_proxy).send(:find_matching_expectation, :render, options)
6bbe80f @dchelimsky Decouple mock framework from global extensions used by rspec.
authored
226 end
227
228 def matching_stub_exists(options)
eb53fc0 @dchelimsky deprecate expect_render and stub_render in favor of rails-specific exten...
authored
229 render_proxy.send(:__mock_proxy).send(:find_matching_method_stub, :render, options)
6bbe80f @dchelimsky Decouple mock framework from global extensions used by rspec.
authored
230 end
231
6d673c2 Made the following renames:
btakita authored
232 end
233
234 Spec::Example::ExampleGroupFactory.register(:controller, self)
235 end
e11c5b5 'should render_template' ignores layouts [#508 state:resolved]
David Chelimsky authored
236
05b4ab0 @dchelimsky tweak rdoc for render_template
authored
237 # Returned by _pick_template when running controller examples in isolation mode.
238 class PickedTemplate
239 # Do nothing when running controller examples in isolation mode.
e11c5b5 'should render_template' ignores layouts [#508 state:resolved]
David Chelimsky authored
240 def render_template(*ignore_args); end
05b4ab0 @dchelimsky tweak rdoc for render_template
authored
241 # Do nothing when running controller examples in isolation mode.
e11c5b5 'should render_template' ignores layouts [#508 state:resolved]
David Chelimsky authored
242 def render_partial(*ignore_args); end
243 end
6d673c2 Made the following renames:
btakita authored
244 end
245 end
246 end
Something went wrong with that request. Please try again.