cavalle-rspec-rails 1.2.2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +7 -0
- data/History.rdoc +207 -0
- data/License.txt +33 -0
- data/Manifest.txt +167 -0
- data/README.rdoc +45 -0
- data/Rakefile +79 -0
- data/TODO.txt +1 -0
- data/Upgrade.rdoc +103 -0
- data/features/step_definitions/people.rb +6 -0
- data/features/support/env.rb +13 -0
- data/features/transactions/transactions_should_rollback.feature +16 -0
- data/generators/rspec/CHANGES +1 -0
- data/generators/rspec/rspec_generator.rb +54 -0
- data/generators/rspec/templates/previous_failures.txt +0 -0
- data/generators/rspec/templates/rcov.opts +2 -0
- data/generators/rspec/templates/rspec.rake +165 -0
- data/generators/rspec/templates/script/autospec +6 -0
- data/generators/rspec/templates/script/spec +10 -0
- data/generators/rspec/templates/script/spec_server +9 -0
- data/generators/rspec/templates/spec.opts +4 -0
- data/generators/rspec/templates/spec_helper.rb +47 -0
- data/generators/rspec_controller/USAGE +33 -0
- data/generators/rspec_controller/rspec_controller_generator.rb +45 -0
- data/generators/rspec_controller/templates/controller_spec.rb +25 -0
- data/generators/rspec_controller/templates/helper_spec.rb +11 -0
- data/generators/rspec_controller/templates/view_spec.rb +12 -0
- data/generators/rspec_default_values.rb +19 -0
- data/generators/rspec_model/USAGE +18 -0
- data/generators/rspec_model/rspec_model_generator.rb +35 -0
- data/generators/rspec_model/templates/model_spec.rb +15 -0
- data/generators/rspec_scaffold/rspec_scaffold_generator.rb +150 -0
- data/generators/rspec_scaffold/templates/controller_spec.rb +171 -0
- data/generators/rspec_scaffold/templates/edit_erb_spec.rb +27 -0
- data/generators/rspec_scaffold/templates/helper_spec.rb +11 -0
- data/generators/rspec_scaffold/templates/index_erb_spec.rb +28 -0
- data/generators/rspec_scaffold/templates/new_erb_spec.rb +27 -0
- data/generators/rspec_scaffold/templates/routing_spec.rb +63 -0
- data/generators/rspec_scaffold/templates/show_erb_spec.rb +23 -0
- data/init.rb +9 -0
- data/lib/autotest/discover.rb +1 -0
- data/lib/autotest/rails_rspec.rb +76 -0
- data/lib/spec/rails/example/assigns_hash_proxy.rb +39 -0
- data/lib/spec/rails/example/controller_example_group.rb +247 -0
- data/lib/spec/rails/example/cookies_proxy.rb +29 -0
- data/lib/spec/rails/example/functional_example_group.rb +84 -0
- data/lib/spec/rails/example/helper_example_group.rb +153 -0
- data/lib/spec/rails/example/model_example_group.rb +14 -0
- data/lib/spec/rails/example/render_observer.rb +67 -0
- data/lib/spec/rails/example/routing_example_group.rb +13 -0
- data/lib/spec/rails/example/routing_helpers.rb +70 -0
- data/lib/spec/rails/example/view_example_group.rb +186 -0
- data/lib/spec/rails/example.rb +47 -0
- data/lib/spec/rails/extensions/action_controller/rescue.rb +42 -0
- data/lib/spec/rails/extensions/action_controller/test_case.rb +16 -0
- data/lib/spec/rails/extensions/action_controller/test_response.rb +21 -0
- data/lib/spec/rails/extensions/action_view/base.rb +33 -0
- data/lib/spec/rails/extensions/active_record/base.rb +45 -0
- data/lib/spec/rails/extensions/active_support/test_case.rb +7 -0
- data/lib/spec/rails/extensions/spec/matchers/have.rb +23 -0
- data/lib/spec/rails/extensions/spec/runner/configuration.rb +44 -0
- data/lib/spec/rails/extensions.rb +11 -0
- data/lib/spec/rails/interop/testcase.rb +14 -0
- data/lib/spec/rails/matchers/ar_be_valid.rb +44 -0
- data/lib/spec/rails/matchers/assert_select.rb +146 -0
- data/lib/spec/rails/matchers/change.rb +11 -0
- data/lib/spec/rails/matchers/have_text.rb +57 -0
- data/lib/spec/rails/matchers/include_text.rb +54 -0
- data/lib/spec/rails/matchers/redirect_to.rb +126 -0
- data/lib/spec/rails/matchers/render_template.rb +114 -0
- data/lib/spec/rails/matchers.rb +32 -0
- data/lib/spec/rails/mocks.rb +135 -0
- data/lib/spec/rails/spec_server.rb +127 -0
- data/lib/spec/rails/story_adapter.rb +79 -0
- data/lib/spec/rails/version.rb +15 -0
- data/lib/spec/rails.rb +28 -0
- data/rspec-rails.gemspec +57 -0
- data/spec/autotest/mappings_spec.rb +86 -0
- data/spec/rails_suite.rb +7 -0
- data/spec/resources/controllers/action_view_base_spec_controller.rb +2 -0
- data/spec/resources/controllers/application.rb +9 -0
- data/spec/resources/controllers/controller_spec_controller.rb +120 -0
- data/spec/resources/controllers/example.txt +1 -0
- data/spec/resources/controllers/redirect_spec_controller.rb +70 -0
- data/spec/resources/controllers/render_spec_controller.rb +30 -0
- data/spec/resources/controllers/rjs_spec_controller.rb +58 -0
- data/spec/resources/helpers/addition_helper.rb +5 -0
- data/spec/resources/helpers/explicit_helper.rb +46 -0
- data/spec/resources/helpers/more_explicit_helper.rb +5 -0
- data/spec/resources/helpers/plugin_application_helper.rb +6 -0
- data/spec/resources/helpers/view_spec_helper.rb +13 -0
- data/spec/resources/models/animal.rb +4 -0
- data/spec/resources/models/person.rb +18 -0
- data/spec/resources/models/thing.rb +3 -0
- data/spec/resources/views/controller_spec/_partial.html.erb +0 -0
- data/spec/resources/views/controller_spec/action_setting_flash_after_session_reset.html.erb +1 -0
- data/spec/resources/views/controller_spec/action_setting_flash_before_session_reset.html.erb +1 -0
- data/spec/resources/views/controller_spec/action_setting_the_assigns_hash.html.erb +0 -0
- data/spec/resources/views/controller_spec/action_with_errors_in_template.html.erb +1 -0
- data/spec/resources/views/controller_spec/action_with_template.html.erb +1 -0
- data/spec/resources/views/layouts/application.html.erb +0 -0
- data/spec/resources/views/layouts/simple.html.erb +0 -0
- data/spec/resources/views/objects/_object.html.erb +1 -0
- data/spec/resources/views/render_spec/_a_partial.html.erb +0 -0
- data/spec/resources/views/render_spec/action_with_alternate_layout.html.erb +0 -0
- data/spec/resources/views/render_spec/some_action.html.erb +0 -0
- data/spec/resources/views/render_spec/some_action.js.rjs +1 -0
- data/spec/resources/views/rjs_spec/_replacement_partial.html.erb +1 -0
- data/spec/resources/views/rjs_spec/hide_div.js.rjs +1 -0
- data/spec/resources/views/rjs_spec/hide_page_element.js.rjs +1 -0
- data/spec/resources/views/rjs_spec/insert_html.js.rjs +1 -0
- data/spec/resources/views/rjs_spec/replace.js.rjs +1 -0
- data/spec/resources/views/rjs_spec/replace_html.js.rjs +1 -0
- data/spec/resources/views/rjs_spec/replace_html_with_partial.js.rjs +1 -0
- data/spec/resources/views/rjs_spec/visual_effect.js.rjs +1 -0
- data/spec/resources/views/rjs_spec/visual_toggle_effect.js.rjs +1 -0
- data/spec/resources/views/tag_spec/no_tags.html.erb +1 -0
- data/spec/resources/views/tag_spec/single_div_with_no_attributes.html.erb +1 -0
- data/spec/resources/views/tag_spec/single_div_with_one_attribute.html.erb +1 -0
- data/spec/resources/views/view_spec/_partial.html.erb +2 -0
- data/spec/resources/views/view_spec/_partial_used_twice.html.erb +0 -0
- data/spec/resources/views/view_spec/_partial_with_local_variable.html.erb +1 -0
- data/spec/resources/views/view_spec/_partial_with_sub_partial.html.erb +1 -0
- data/spec/resources/views/view_spec/_spacer.html.erb +1 -0
- data/spec/resources/views/view_spec/accessor.html.erb +5 -0
- data/spec/resources/views/view_spec/block_helper.html.erb +3 -0
- data/spec/resources/views/view_spec/entry_form.html.erb +2 -0
- data/spec/resources/views/view_spec/explicit_helper.html.erb +2 -0
- data/spec/resources/views/view_spec/foo/show.html.erb +1 -0
- data/spec/resources/views/view_spec/implicit_helper.html.erb +2 -0
- data/spec/resources/views/view_spec/multiple_helpers.html.erb +3 -0
- data/spec/resources/views/view_spec/path_params.html.erb +1 -0
- data/spec/resources/views/view_spec/should_not_receive.html.erb +3 -0
- data/spec/resources/views/view_spec/template_with_partial.html.erb +5 -0
- data/spec/resources/views/view_spec/template_with_partial_using_collection.html.erb +3 -0
- data/spec/resources/views/view_spec/template_with_partial_with_array.html.erb +1 -0
- data/spec/spec/rails/example/assigns_hash_proxy_spec.rb +109 -0
- data/spec/spec/rails/example/configuration_spec.rb +65 -0
- data/spec/spec/rails/example/controller_example_group_spec.rb +299 -0
- data/spec/spec/rails/example/controller_isolation_spec.rb +56 -0
- data/spec/spec/rails/example/cookies_proxy_spec.rb +87 -0
- data/spec/spec/rails/example/error_handling_spec.rb +90 -0
- data/spec/spec/rails/example/example_group_factory_spec.rb +112 -0
- data/spec/spec/rails/example/helper_example_group_spec.rb +233 -0
- data/spec/spec/rails/example/model_example_group_spec.rb +20 -0
- data/spec/spec/rails/example/routing_example_group_spec.rb +9 -0
- data/spec/spec/rails/example/shared_routing_example_group_examples.rb +44 -0
- data/spec/spec/rails/example/test_unit_assertion_accessibility_spec.rb +33 -0
- data/spec/spec/rails/example/view_example_group_spec.rb +335 -0
- data/spec/spec/rails/extensions/action_view_base_spec.rb +48 -0
- data/spec/spec/rails/extensions/active_record_spec.rb +14 -0
- data/spec/spec/rails/interop/testcase_spec.rb +70 -0
- data/spec/spec/rails/matchers/ar_be_valid_spec.rb +45 -0
- data/spec/spec/rails/matchers/assert_select_spec.rb +809 -0
- data/spec/spec/rails/matchers/errors_on_spec.rb +25 -0
- data/spec/spec/rails/matchers/have_text_spec.rb +70 -0
- data/spec/spec/rails/matchers/include_text_spec.rb +62 -0
- data/spec/spec/rails/matchers/redirect_to_spec.rb +253 -0
- data/spec/spec/rails/matchers/render_template_spec.rb +191 -0
- data/spec/spec/rails/matchers/should_change_spec.rb +15 -0
- data/spec/spec/rails/mocks/ar_classes.rb +10 -0
- data/spec/spec/rails/mocks/mock_model_spec.rb +106 -0
- data/spec/spec/rails/mocks/stub_model_spec.rb +80 -0
- data/spec/spec/rails/sample_modified_fixture.rb +8 -0
- data/spec/spec/rails/sample_spec.rb +8 -0
- data/spec/spec/rails/spec_server_spec.rb +107 -0
- data/spec/spec/rails/spec_spec.rb +11 -0
- data/spec/spec_helper.rb +79 -0
- metadata +277 -0
@@ -0,0 +1,247 @@
|
|
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,
|
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.
|
14
|
+
#
|
15
|
+
# == Isolation mode (default)
|
16
|
+
#
|
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.
|
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
|
+
#
|
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.
|
38
|
+
#
|
39
|
+
# == Expecting Errors
|
40
|
+
#
|
41
|
+
# Rspec on Rails will raise errors that occur in controller actions and
|
42
|
+
# are not rescued or handeled with rescue_from.
|
43
|
+
#
|
44
|
+
class ControllerExampleGroup < FunctionalExampleGroup
|
45
|
+
class << self
|
46
|
+
|
47
|
+
# Use integrate_views to instruct RSpec to render views in
|
48
|
+
# your controller examples in Integration mode.
|
49
|
+
#
|
50
|
+
# describe ThingController do
|
51
|
+
# integrate_views
|
52
|
+
# ...
|
53
|
+
#
|
54
|
+
# See Spec::Rails::Example::ControllerExampleGroup for more
|
55
|
+
# information about Integration and Isolation modes.
|
56
|
+
def integrate_views(integrate_views = true)
|
57
|
+
@integrate_views = integrate_views
|
58
|
+
end
|
59
|
+
|
60
|
+
def integrate_views? # :nodoc:
|
61
|
+
@integrate_views
|
62
|
+
end
|
63
|
+
|
64
|
+
def inherited(klass) # :nodoc:
|
65
|
+
klass.integrate_views(integrate_views?)
|
66
|
+
klass.subject { controller }
|
67
|
+
super
|
68
|
+
end
|
69
|
+
|
70
|
+
def set_description(*args) # :nodoc:
|
71
|
+
super
|
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
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
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
|
87
|
+
# your controller specs:
|
88
|
+
#
|
89
|
+
# describe "ThingController" do
|
90
|
+
# controller_name :thing
|
91
|
+
# ...
|
92
|
+
def controller_name(name)
|
93
|
+
tests "#{name}_controller".camelize.constantize
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
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)
|
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
|
117
|
+
end
|
118
|
+
@controller.extend ControllerInstanceMethods
|
119
|
+
@controller.integrate_views! if integrate_views?
|
120
|
+
@controller.session = session
|
121
|
+
end
|
122
|
+
|
123
|
+
attr_reader :response, :request, :controller
|
124
|
+
|
125
|
+
def integrate_views?
|
126
|
+
@integrate_views || self.class.integrate_views?
|
127
|
+
end
|
128
|
+
|
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
|
+
|
147
|
+
protected
|
148
|
+
|
149
|
+
def _assigns_hash_proxy
|
150
|
+
@_assigns_hash_proxy ||= AssignsHashProxy.new(self) {@response.template}
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
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)
|
169
|
+
return super if Hash === args.last && args.last[:inline]
|
170
|
+
@_rendered ? record_render(args[0]) : super
|
171
|
+
end
|
172
|
+
|
173
|
+
private
|
174
|
+
|
175
|
+
def record_render(opts)
|
176
|
+
(@_rendered[:template] ||= opts[:file]) if opts[:file]
|
177
|
+
(@_rendered[:partials][opts[:partial]] += 1) if opts[:partial]
|
178
|
+
end
|
179
|
+
|
180
|
+
# Returned by _pick_template when running controller examples in isolation mode.
|
181
|
+
class PickedTemplate
|
182
|
+
# Do nothing when running controller examples in isolation mode.
|
183
|
+
def render_template(*ignore_args); end
|
184
|
+
# Do nothing when running controller examples in isolation mode.
|
185
|
+
def render_partial(*ignore_args); end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
module ControllerInstanceMethods # :nodoc:
|
190
|
+
include Spec::Rails::Example::RenderObserver
|
191
|
+
|
192
|
+
# === render(options = nil, extra_options={}, &block)
|
193
|
+
#
|
194
|
+
# This gets added to the controller's singleton meta class,
|
195
|
+
# allowing Controller Examples to run in two modes, freely switching
|
196
|
+
# from example group to example group.
|
197
|
+
def render(options=nil, extra_options={}, &block)
|
198
|
+
unless block_given?
|
199
|
+
unless integrate_views?
|
200
|
+
@template.extend TemplateIsolationExtensions
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
if matching_message_expectation_exists(options)
|
205
|
+
render_proxy.render(options, &block)
|
206
|
+
@performed_render = true
|
207
|
+
else
|
208
|
+
if matching_stub_exists(options)
|
209
|
+
@performed_render = true
|
210
|
+
else
|
211
|
+
super
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def response(&block)
|
217
|
+
# NOTE - we're setting @update for the assert_select_spec - kinda weird, huh?
|
218
|
+
@update = block
|
219
|
+
super
|
220
|
+
end
|
221
|
+
|
222
|
+
def integrate_views!
|
223
|
+
@integrate_views = true
|
224
|
+
end
|
225
|
+
|
226
|
+
private
|
227
|
+
|
228
|
+
def integrate_views?
|
229
|
+
@integrate_views
|
230
|
+
end
|
231
|
+
|
232
|
+
def matching_message_expectation_exists(options)
|
233
|
+
render_proxy.__send__(:__mock_proxy).__send__(:find_matching_expectation, :render, options)
|
234
|
+
end
|
235
|
+
|
236
|
+
def matching_stub_exists(options)
|
237
|
+
render_proxy.__send__(:__mock_proxy).__send__(:find_matching_method_stub, :render, options)
|
238
|
+
end
|
239
|
+
|
240
|
+
end
|
241
|
+
|
242
|
+
Spec::Example::ExampleGroupFactory.register(:controller, self)
|
243
|
+
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'action_controller/cookies'
|
2
|
+
|
3
|
+
module Spec
|
4
|
+
module Rails
|
5
|
+
module Example
|
6
|
+
class CookiesProxy
|
7
|
+
def initialize(example)
|
8
|
+
@example = example
|
9
|
+
end
|
10
|
+
|
11
|
+
def[]=(name, value)
|
12
|
+
if ::Rails::VERSION::STRING >= '2.3'
|
13
|
+
@example.request.cookies[name.to_s] = value
|
14
|
+
else
|
15
|
+
@example.request.cookies[name.to_s] = CGI::Cookie.new(name.to_s, value)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def [](name)
|
20
|
+
@example.response.cookies[name.to_s]
|
21
|
+
end
|
22
|
+
|
23
|
+
def delete(name)
|
24
|
+
@example.response.cookies.delete(name.to_s)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'action_controller/test_case'
|
2
|
+
|
3
|
+
module Spec
|
4
|
+
module Rails
|
5
|
+
module Example
|
6
|
+
class FunctionalExampleGroup < ActionController::TestCase
|
7
|
+
def setup
|
8
|
+
# no-op to override AC::TC's setup w/ conflicts with the before(:each) below
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :request, :response
|
12
|
+
|
13
|
+
def params
|
14
|
+
request.parameters
|
15
|
+
end
|
16
|
+
|
17
|
+
def flash
|
18
|
+
@controller.__send__ :flash
|
19
|
+
end
|
20
|
+
|
21
|
+
def session
|
22
|
+
request.session
|
23
|
+
end
|
24
|
+
|
25
|
+
# Overrides the <tt>cookies()</tt> method in
|
26
|
+
# ActionController::TestResponseBehaviour, returning a proxy that
|
27
|
+
# accesses the requests cookies when setting a cookie and the
|
28
|
+
# responses cookies when reading one. This allows you to set and read
|
29
|
+
# cookies in examples using the same API with which you set and read
|
30
|
+
# them in controllers.
|
31
|
+
#
|
32
|
+
# == Examples (Rails 2.0 > 2.2)
|
33
|
+
#
|
34
|
+
# cookies[:user_id] = {:value => '1234', :expires => 1.minute.ago}
|
35
|
+
# get :index
|
36
|
+
# response.should be_redirect
|
37
|
+
#
|
38
|
+
# == Examples (Rails 2.3)
|
39
|
+
#
|
40
|
+
# Rails 2.3 changes the way cookies are made available to functional
|
41
|
+
# tests (and therefore rspec controller specs), only making single
|
42
|
+
# values available with no access to other aspects of the cookie. This
|
43
|
+
# is backwards-incompatible, so you have to change your examples to
|
44
|
+
# look like this:
|
45
|
+
#
|
46
|
+
# cookies[:foo] = 'bar'
|
47
|
+
# get :index
|
48
|
+
# cookies[:foo].should == 'bar'
|
49
|
+
def cookies
|
50
|
+
@cookies ||= Spec::Rails::Example::CookiesProxy.new(self)
|
51
|
+
end
|
52
|
+
|
53
|
+
alias_method :orig_assigns, :assigns
|
54
|
+
|
55
|
+
# :call-seq:
|
56
|
+
# assigns()
|
57
|
+
#
|
58
|
+
# Hash of instance variables to values that are made available to
|
59
|
+
# views. == Examples
|
60
|
+
#
|
61
|
+
# #in thing_controller.rb
|
62
|
+
# def new
|
63
|
+
# @thing = Thing.new
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# #in thing_controller_spec
|
67
|
+
# get 'new'
|
68
|
+
# assigns[:registration].should == Thing.new
|
69
|
+
#--
|
70
|
+
# NOTE - Even though docs only use assigns[:key] format, this supports
|
71
|
+
# assigns(:key) for backwards compatibility.
|
72
|
+
#++
|
73
|
+
def assigns(key = nil)
|
74
|
+
if key.nil?
|
75
|
+
_assigns_hash_proxy
|
76
|
+
else
|
77
|
+
_assigns_hash_proxy[key]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
module Spec
|
2
|
+
module Rails
|
3
|
+
module Example
|
4
|
+
class HelperExampleGroupController < ApplicationController #:nodoc:
|
5
|
+
attr_accessor :request, :url
|
6
|
+
end
|
7
|
+
|
8
|
+
# Helper Specs live in $RAILS_ROOT/spec/helpers/.
|
9
|
+
#
|
10
|
+
# Helper Specs use Spec::Rails::Example::HelperExampleGroup, which allows you to
|
11
|
+
# include your Helper directly in the context and write specs directly
|
12
|
+
# against its methods.
|
13
|
+
#
|
14
|
+
# HelperExampleGroup also includes the standard lot of ActionView::Helpers in case your
|
15
|
+
# helpers rely on any of those.
|
16
|
+
#
|
17
|
+
# == Example
|
18
|
+
#
|
19
|
+
# module ThingHelper
|
20
|
+
# def number_of_things
|
21
|
+
# Thing.count
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# describe "ThingHelper example_group" do
|
26
|
+
# include ThingHelper
|
27
|
+
# it "should tell you the number of things" do
|
28
|
+
# Thing.should_receive(:count).and_return(37)
|
29
|
+
# number_of_things.should == 37
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
class HelperExampleGroup < FunctionalExampleGroup
|
33
|
+
tests HelperExampleGroupController
|
34
|
+
attr_accessor :output_buffer
|
35
|
+
|
36
|
+
class HelperObject < ActionView::Base
|
37
|
+
def initialize(*args)
|
38
|
+
@template = self
|
39
|
+
super
|
40
|
+
end
|
41
|
+
def protect_against_forgery?
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
attr_writer :session, :request, :flash, :params, :controller
|
46
|
+
|
47
|
+
private
|
48
|
+
attr_reader :session, :request, :flash, :params, :controller
|
49
|
+
end
|
50
|
+
|
51
|
+
class << self
|
52
|
+
# The helper name....
|
53
|
+
def helper_name(name=nil)
|
54
|
+
@helper_being_described = "#{name}_helper".camelize.constantize
|
55
|
+
send :include, @helper_being_described
|
56
|
+
end
|
57
|
+
|
58
|
+
def helper
|
59
|
+
@helper_object ||= returning HelperObject.new do |helper_object|
|
60
|
+
if @helper_being_described.nil?
|
61
|
+
if described_type.class == Module
|
62
|
+
helper_object.extend described_type
|
63
|
+
end
|
64
|
+
else
|
65
|
+
helper_object.extend @helper_being_described
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Returns an instance of ActionView::Base with the helper being spec'd
|
72
|
+
# included.
|
73
|
+
#
|
74
|
+
# == Example
|
75
|
+
#
|
76
|
+
# describe PersonHelper do
|
77
|
+
# it "should write a link to person with the name" do
|
78
|
+
# assigns[:person] = mock_model(Person, :full_name => "Full Name", :id => 37, :new_record? => false)
|
79
|
+
# helper.link_to_person.should == %{<a href="/people/37">Full Name</a>}
|
80
|
+
# end
|
81
|
+
# end
|
82
|
+
#
|
83
|
+
# module PersonHelper
|
84
|
+
# def link_to_person
|
85
|
+
# link_to person.full_name, url_for(person)
|
86
|
+
# end
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
def helper
|
90
|
+
self.class.helper
|
91
|
+
end
|
92
|
+
|
93
|
+
def orig_assigns
|
94
|
+
helper.assigns
|
95
|
+
end
|
96
|
+
|
97
|
+
# Reverse the load order so that custom helpers which are defined last
|
98
|
+
# are also loaded last.
|
99
|
+
ActionView::Base.included_modules.reverse.each do |mod|
|
100
|
+
include mod if mod.parents.include?(ActionView::Helpers)
|
101
|
+
end
|
102
|
+
|
103
|
+
before(:each) do
|
104
|
+
@controller.request = @request
|
105
|
+
@controller.url = ActionController::UrlRewriter.new @request, {} # url_for
|
106
|
+
|
107
|
+
@flash = ActionController::Flash::FlashHash.new
|
108
|
+
session['flash'] = @flash
|
109
|
+
|
110
|
+
@output_buffer = ""
|
111
|
+
@template = helper
|
112
|
+
ActionView::Helpers::AssetTagHelper::reset_javascript_include_default
|
113
|
+
|
114
|
+
helper.session = session
|
115
|
+
helper.request = @request
|
116
|
+
helper.flash = flash
|
117
|
+
helper.params = params
|
118
|
+
helper.controller = @controller
|
119
|
+
end
|
120
|
+
|
121
|
+
def flash
|
122
|
+
@flash
|
123
|
+
end
|
124
|
+
|
125
|
+
def eval_erb(text)
|
126
|
+
erb_args = [text]
|
127
|
+
if helper.respond_to?(:output_buffer)
|
128
|
+
erb_args += [nil, nil, '@output_buffer']
|
129
|
+
end
|
130
|
+
|
131
|
+
helper.instance_eval do
|
132
|
+
ERB.new(*erb_args).result(binding)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# TODO: BT - Helper Examples should proxy method_missing to a Rails View instance.
|
137
|
+
# When that is done, remove this method
|
138
|
+
def protect_against_forgery?
|
139
|
+
false
|
140
|
+
end
|
141
|
+
|
142
|
+
Spec::Example::ExampleGroupFactory.register(:helper, self)
|
143
|
+
|
144
|
+
protected
|
145
|
+
|
146
|
+
def _assigns_hash_proxy
|
147
|
+
@_assigns_hash_proxy ||= AssignsHashProxy.new(self) {helper}
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Spec
|
2
|
+
module Rails
|
3
|
+
module Example
|
4
|
+
# Model examples live in $RAILS_ROOT/spec/models/.
|
5
|
+
#
|
6
|
+
# Model examples use Spec::Rails::Example::ModelExampleGroup, which
|
7
|
+
# provides support for fixtures and some custom expectations via extensions
|
8
|
+
# to ActiveRecord::Base.
|
9
|
+
class ModelExampleGroup < ActiveSupport::TestCase
|
10
|
+
Spec::Example::ExampleGroupFactory.register(:model, self)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec/mocks/framework'
|
2
|
+
|
3
|
+
module Spec
|
4
|
+
module Rails
|
5
|
+
module Example
|
6
|
+
# Extends the #should_receive, #should_not_receive and #stub! methods in rspec's
|
7
|
+
# mocking framework to handle #render calls to controller in controller examples
|
8
|
+
# and template and view examples
|
9
|
+
module RenderObserver
|
10
|
+
|
11
|
+
def verify_rendered # :nodoc:
|
12
|
+
render_proxy.rspec_verify
|
13
|
+
end
|
14
|
+
|
15
|
+
def unregister_verify_after_each #:nodoc:
|
16
|
+
proc = verify_rendered_proc
|
17
|
+
Spec::Example::ExampleGroup.remove_after(:each, &proc)
|
18
|
+
end
|
19
|
+
|
20
|
+
def should_receive(*args)
|
21
|
+
if args[0] == :render
|
22
|
+
register_verify_after_each
|
23
|
+
render_proxy.should_receive(:render, :expected_from => caller(1)[0])
|
24
|
+
else
|
25
|
+
super
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def should_not_receive(*args)
|
30
|
+
if args[0] == :render
|
31
|
+
register_verify_after_each
|
32
|
+
render_proxy.should_not_receive(:render)
|
33
|
+
else
|
34
|
+
super
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def stub!(*args)
|
39
|
+
if args[0] == :render
|
40
|
+
register_verify_after_each
|
41
|
+
render_proxy.stub!(:render, :expected_from => caller(1)[0])
|
42
|
+
else
|
43
|
+
super
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def verify_rendered_proc #:nodoc:
|
48
|
+
template = self
|
49
|
+
@verify_rendered_proc ||= Proc.new do
|
50
|
+
template.verify_rendered
|
51
|
+
template.unregister_verify_after_each
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def register_verify_after_each #:nodoc:
|
56
|
+
proc = verify_rendered_proc
|
57
|
+
Spec::Example::ExampleGroup.after(:each, &proc)
|
58
|
+
end
|
59
|
+
|
60
|
+
def render_proxy #:nodoc:
|
61
|
+
@render_proxy ||= Spec::Mocks::Mock.new("render_proxy")
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Spec
|
2
|
+
module Rails
|
3
|
+
module Example
|
4
|
+
module RoutingHelpers
|
5
|
+
|
6
|
+
module ParamsFromQueryString # :nodoc:
|
7
|
+
def params_from_querystring(querystring) # :nodoc:
|
8
|
+
params = {}
|
9
|
+
querystring.split('&').each do |piece|
|
10
|
+
key, value = piece.split('=')
|
11
|
+
params[key.to_sym] = value
|
12
|
+
end
|
13
|
+
params
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class RouteFor
|
18
|
+
include ::Spec::Rails::Example::RoutingHelpers::ParamsFromQueryString
|
19
|
+
def initialize(example, options)
|
20
|
+
@example, @options = example, options
|
21
|
+
end
|
22
|
+
|
23
|
+
def ==(expected)
|
24
|
+
if Hash === expected
|
25
|
+
path, querystring = expected[:path].split('?')
|
26
|
+
path = expected.merge(:path => path)
|
27
|
+
else
|
28
|
+
path, querystring = expected.split('?')
|
29
|
+
end
|
30
|
+
params = querystring.blank? ? {} : @example.params_from_querystring(querystring)
|
31
|
+
@example.assert_recognizes(@options, path, params)
|
32
|
+
true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Uses ActionController::Routing::Routes to generate
|
37
|
+
# the correct route for a given set of options.
|
38
|
+
# == Examples
|
39
|
+
# route_for(:controller => 'registrations', :action => 'edit', :id => '1')
|
40
|
+
# => '/registrations/1/edit'
|
41
|
+
# route_for(:controller => 'registrations', :action => 'create')
|
42
|
+
# => {:path => "/registrations", :method => :post}
|
43
|
+
def route_for(options)
|
44
|
+
RouteFor.new(self, options)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Uses ActionController::Routing::Routes to parse
|
48
|
+
# an incoming path so the parameters it generates can be checked
|
49
|
+
# == Example
|
50
|
+
# params_from(:get, '/registrations/1/edit')
|
51
|
+
# => :controller => 'registrations', :action => 'edit', :id => '1'
|
52
|
+
def params_from(method, path)
|
53
|
+
ensure_that_routes_are_loaded
|
54
|
+
path, querystring = path.split('?')
|
55
|
+
params = ActionController::Routing::Routes.recognize_path(path, :method => method)
|
56
|
+
querystring.blank? ? params : params.merge(params_from_querystring(querystring))
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
include ParamsFromQueryString
|
62
|
+
|
63
|
+
def ensure_that_routes_are_loaded
|
64
|
+
ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty?
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|