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.
Files changed (168) hide show
  1. data/.document +7 -0
  2. data/History.rdoc +207 -0
  3. data/License.txt +33 -0
  4. data/Manifest.txt +167 -0
  5. data/README.rdoc +45 -0
  6. data/Rakefile +79 -0
  7. data/TODO.txt +1 -0
  8. data/Upgrade.rdoc +103 -0
  9. data/features/step_definitions/people.rb +6 -0
  10. data/features/support/env.rb +13 -0
  11. data/features/transactions/transactions_should_rollback.feature +16 -0
  12. data/generators/rspec/CHANGES +1 -0
  13. data/generators/rspec/rspec_generator.rb +54 -0
  14. data/generators/rspec/templates/previous_failures.txt +0 -0
  15. data/generators/rspec/templates/rcov.opts +2 -0
  16. data/generators/rspec/templates/rspec.rake +165 -0
  17. data/generators/rspec/templates/script/autospec +6 -0
  18. data/generators/rspec/templates/script/spec +10 -0
  19. data/generators/rspec/templates/script/spec_server +9 -0
  20. data/generators/rspec/templates/spec.opts +4 -0
  21. data/generators/rspec/templates/spec_helper.rb +47 -0
  22. data/generators/rspec_controller/USAGE +33 -0
  23. data/generators/rspec_controller/rspec_controller_generator.rb +45 -0
  24. data/generators/rspec_controller/templates/controller_spec.rb +25 -0
  25. data/generators/rspec_controller/templates/helper_spec.rb +11 -0
  26. data/generators/rspec_controller/templates/view_spec.rb +12 -0
  27. data/generators/rspec_default_values.rb +19 -0
  28. data/generators/rspec_model/USAGE +18 -0
  29. data/generators/rspec_model/rspec_model_generator.rb +35 -0
  30. data/generators/rspec_model/templates/model_spec.rb +15 -0
  31. data/generators/rspec_scaffold/rspec_scaffold_generator.rb +150 -0
  32. data/generators/rspec_scaffold/templates/controller_spec.rb +171 -0
  33. data/generators/rspec_scaffold/templates/edit_erb_spec.rb +27 -0
  34. data/generators/rspec_scaffold/templates/helper_spec.rb +11 -0
  35. data/generators/rspec_scaffold/templates/index_erb_spec.rb +28 -0
  36. data/generators/rspec_scaffold/templates/new_erb_spec.rb +27 -0
  37. data/generators/rspec_scaffold/templates/routing_spec.rb +63 -0
  38. data/generators/rspec_scaffold/templates/show_erb_spec.rb +23 -0
  39. data/init.rb +9 -0
  40. data/lib/autotest/discover.rb +1 -0
  41. data/lib/autotest/rails_rspec.rb +76 -0
  42. data/lib/spec/rails/example/assigns_hash_proxy.rb +39 -0
  43. data/lib/spec/rails/example/controller_example_group.rb +247 -0
  44. data/lib/spec/rails/example/cookies_proxy.rb +29 -0
  45. data/lib/spec/rails/example/functional_example_group.rb +84 -0
  46. data/lib/spec/rails/example/helper_example_group.rb +153 -0
  47. data/lib/spec/rails/example/model_example_group.rb +14 -0
  48. data/lib/spec/rails/example/render_observer.rb +67 -0
  49. data/lib/spec/rails/example/routing_example_group.rb +13 -0
  50. data/lib/spec/rails/example/routing_helpers.rb +70 -0
  51. data/lib/spec/rails/example/view_example_group.rb +186 -0
  52. data/lib/spec/rails/example.rb +47 -0
  53. data/lib/spec/rails/extensions/action_controller/rescue.rb +42 -0
  54. data/lib/spec/rails/extensions/action_controller/test_case.rb +16 -0
  55. data/lib/spec/rails/extensions/action_controller/test_response.rb +21 -0
  56. data/lib/spec/rails/extensions/action_view/base.rb +33 -0
  57. data/lib/spec/rails/extensions/active_record/base.rb +45 -0
  58. data/lib/spec/rails/extensions/active_support/test_case.rb +7 -0
  59. data/lib/spec/rails/extensions/spec/matchers/have.rb +23 -0
  60. data/lib/spec/rails/extensions/spec/runner/configuration.rb +44 -0
  61. data/lib/spec/rails/extensions.rb +11 -0
  62. data/lib/spec/rails/interop/testcase.rb +14 -0
  63. data/lib/spec/rails/matchers/ar_be_valid.rb +44 -0
  64. data/lib/spec/rails/matchers/assert_select.rb +146 -0
  65. data/lib/spec/rails/matchers/change.rb +11 -0
  66. data/lib/spec/rails/matchers/have_text.rb +57 -0
  67. data/lib/spec/rails/matchers/include_text.rb +54 -0
  68. data/lib/spec/rails/matchers/redirect_to.rb +126 -0
  69. data/lib/spec/rails/matchers/render_template.rb +114 -0
  70. data/lib/spec/rails/matchers.rb +32 -0
  71. data/lib/spec/rails/mocks.rb +135 -0
  72. data/lib/spec/rails/spec_server.rb +127 -0
  73. data/lib/spec/rails/story_adapter.rb +79 -0
  74. data/lib/spec/rails/version.rb +15 -0
  75. data/lib/spec/rails.rb +28 -0
  76. data/rspec-rails.gemspec +57 -0
  77. data/spec/autotest/mappings_spec.rb +86 -0
  78. data/spec/rails_suite.rb +7 -0
  79. data/spec/resources/controllers/action_view_base_spec_controller.rb +2 -0
  80. data/spec/resources/controllers/application.rb +9 -0
  81. data/spec/resources/controllers/controller_spec_controller.rb +120 -0
  82. data/spec/resources/controllers/example.txt +1 -0
  83. data/spec/resources/controllers/redirect_spec_controller.rb +70 -0
  84. data/spec/resources/controllers/render_spec_controller.rb +30 -0
  85. data/spec/resources/controllers/rjs_spec_controller.rb +58 -0
  86. data/spec/resources/helpers/addition_helper.rb +5 -0
  87. data/spec/resources/helpers/explicit_helper.rb +46 -0
  88. data/spec/resources/helpers/more_explicit_helper.rb +5 -0
  89. data/spec/resources/helpers/plugin_application_helper.rb +6 -0
  90. data/spec/resources/helpers/view_spec_helper.rb +13 -0
  91. data/spec/resources/models/animal.rb +4 -0
  92. data/spec/resources/models/person.rb +18 -0
  93. data/spec/resources/models/thing.rb +3 -0
  94. data/spec/resources/views/controller_spec/_partial.html.erb +0 -0
  95. data/spec/resources/views/controller_spec/action_setting_flash_after_session_reset.html.erb +1 -0
  96. data/spec/resources/views/controller_spec/action_setting_flash_before_session_reset.html.erb +1 -0
  97. data/spec/resources/views/controller_spec/action_setting_the_assigns_hash.html.erb +0 -0
  98. data/spec/resources/views/controller_spec/action_with_errors_in_template.html.erb +1 -0
  99. data/spec/resources/views/controller_spec/action_with_template.html.erb +1 -0
  100. data/spec/resources/views/layouts/application.html.erb +0 -0
  101. data/spec/resources/views/layouts/simple.html.erb +0 -0
  102. data/spec/resources/views/objects/_object.html.erb +1 -0
  103. data/spec/resources/views/render_spec/_a_partial.html.erb +0 -0
  104. data/spec/resources/views/render_spec/action_with_alternate_layout.html.erb +0 -0
  105. data/spec/resources/views/render_spec/some_action.html.erb +0 -0
  106. data/spec/resources/views/render_spec/some_action.js.rjs +1 -0
  107. data/spec/resources/views/rjs_spec/_replacement_partial.html.erb +1 -0
  108. data/spec/resources/views/rjs_spec/hide_div.js.rjs +1 -0
  109. data/spec/resources/views/rjs_spec/hide_page_element.js.rjs +1 -0
  110. data/spec/resources/views/rjs_spec/insert_html.js.rjs +1 -0
  111. data/spec/resources/views/rjs_spec/replace.js.rjs +1 -0
  112. data/spec/resources/views/rjs_spec/replace_html.js.rjs +1 -0
  113. data/spec/resources/views/rjs_spec/replace_html_with_partial.js.rjs +1 -0
  114. data/spec/resources/views/rjs_spec/visual_effect.js.rjs +1 -0
  115. data/spec/resources/views/rjs_spec/visual_toggle_effect.js.rjs +1 -0
  116. data/spec/resources/views/tag_spec/no_tags.html.erb +1 -0
  117. data/spec/resources/views/tag_spec/single_div_with_no_attributes.html.erb +1 -0
  118. data/spec/resources/views/tag_spec/single_div_with_one_attribute.html.erb +1 -0
  119. data/spec/resources/views/view_spec/_partial.html.erb +2 -0
  120. data/spec/resources/views/view_spec/_partial_used_twice.html.erb +0 -0
  121. data/spec/resources/views/view_spec/_partial_with_local_variable.html.erb +1 -0
  122. data/spec/resources/views/view_spec/_partial_with_sub_partial.html.erb +1 -0
  123. data/spec/resources/views/view_spec/_spacer.html.erb +1 -0
  124. data/spec/resources/views/view_spec/accessor.html.erb +5 -0
  125. data/spec/resources/views/view_spec/block_helper.html.erb +3 -0
  126. data/spec/resources/views/view_spec/entry_form.html.erb +2 -0
  127. data/spec/resources/views/view_spec/explicit_helper.html.erb +2 -0
  128. data/spec/resources/views/view_spec/foo/show.html.erb +1 -0
  129. data/spec/resources/views/view_spec/implicit_helper.html.erb +2 -0
  130. data/spec/resources/views/view_spec/multiple_helpers.html.erb +3 -0
  131. data/spec/resources/views/view_spec/path_params.html.erb +1 -0
  132. data/spec/resources/views/view_spec/should_not_receive.html.erb +3 -0
  133. data/spec/resources/views/view_spec/template_with_partial.html.erb +5 -0
  134. data/spec/resources/views/view_spec/template_with_partial_using_collection.html.erb +3 -0
  135. data/spec/resources/views/view_spec/template_with_partial_with_array.html.erb +1 -0
  136. data/spec/spec/rails/example/assigns_hash_proxy_spec.rb +109 -0
  137. data/spec/spec/rails/example/configuration_spec.rb +65 -0
  138. data/spec/spec/rails/example/controller_example_group_spec.rb +299 -0
  139. data/spec/spec/rails/example/controller_isolation_spec.rb +56 -0
  140. data/spec/spec/rails/example/cookies_proxy_spec.rb +87 -0
  141. data/spec/spec/rails/example/error_handling_spec.rb +90 -0
  142. data/spec/spec/rails/example/example_group_factory_spec.rb +112 -0
  143. data/spec/spec/rails/example/helper_example_group_spec.rb +233 -0
  144. data/spec/spec/rails/example/model_example_group_spec.rb +20 -0
  145. data/spec/spec/rails/example/routing_example_group_spec.rb +9 -0
  146. data/spec/spec/rails/example/shared_routing_example_group_examples.rb +44 -0
  147. data/spec/spec/rails/example/test_unit_assertion_accessibility_spec.rb +33 -0
  148. data/spec/spec/rails/example/view_example_group_spec.rb +335 -0
  149. data/spec/spec/rails/extensions/action_view_base_spec.rb +48 -0
  150. data/spec/spec/rails/extensions/active_record_spec.rb +14 -0
  151. data/spec/spec/rails/interop/testcase_spec.rb +70 -0
  152. data/spec/spec/rails/matchers/ar_be_valid_spec.rb +45 -0
  153. data/spec/spec/rails/matchers/assert_select_spec.rb +809 -0
  154. data/spec/spec/rails/matchers/errors_on_spec.rb +25 -0
  155. data/spec/spec/rails/matchers/have_text_spec.rb +70 -0
  156. data/spec/spec/rails/matchers/include_text_spec.rb +62 -0
  157. data/spec/spec/rails/matchers/redirect_to_spec.rb +253 -0
  158. data/spec/spec/rails/matchers/render_template_spec.rb +191 -0
  159. data/spec/spec/rails/matchers/should_change_spec.rb +15 -0
  160. data/spec/spec/rails/mocks/ar_classes.rb +10 -0
  161. data/spec/spec/rails/mocks/mock_model_spec.rb +106 -0
  162. data/spec/spec/rails/mocks/stub_model_spec.rb +80 -0
  163. data/spec/spec/rails/sample_modified_fixture.rb +8 -0
  164. data/spec/spec/rails/sample_spec.rb +8 -0
  165. data/spec/spec/rails/spec_server_spec.rb +107 -0
  166. data/spec/spec/rails/spec_spec.rb +11 -0
  167. data/spec/spec_helper.rb +79 -0
  168. 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,13 @@
1
+ module Spec
2
+ module Rails
3
+ module Example
4
+
5
+ class RoutingExampleGroup < ActionController::TestCase
6
+ tests Class.new(ActionController::Base)
7
+
8
+ Spec::Example::ExampleGroupFactory.register(:routing, self)
9
+ end
10
+
11
+ end
12
+ end
13
+ 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