rspec-rails 2.14.2 → 3.9.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 (99) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.document +1 -1
  4. data/.yardopts +4 -2
  5. data/Capybara.md +2 -4
  6. data/Changelog.md +592 -34
  7. data/{License.txt → LICENSE.md} +5 -2
  8. data/README.md +290 -369
  9. data/lib/generators/rspec/controller/controller_generator.rb +1 -0
  10. data/lib/generators/rspec/controller/templates/controller_spec.rb +5 -5
  11. data/lib/generators/rspec/controller/templates/view_spec.rb +2 -2
  12. data/lib/generators/rspec/feature/feature_generator.rb +29 -0
  13. data/lib/generators/rspec/feature/templates/feature_singular_spec.rb +5 -0
  14. data/lib/generators/rspec/feature/templates/feature_spec.rb +5 -0
  15. data/lib/generators/rspec/generators/generator_generator.rb +24 -0
  16. data/lib/generators/rspec/generators/templates/generator_spec.rb +6 -0
  17. data/lib/generators/rspec/helper/helper_generator.rb +1 -0
  18. data/lib/generators/rspec/helper/templates/helper_spec.rb +2 -2
  19. data/lib/generators/rspec/install/install_generator.rb +44 -5
  20. data/lib/generators/rspec/install/templates/spec/rails_helper.rb +78 -0
  21. data/lib/generators/rspec/integration/integration_generator.rb +8 -13
  22. data/lib/generators/rspec/integration/templates/request_spec.rb +4 -9
  23. data/lib/generators/rspec/job/job_generator.rb +12 -0
  24. data/lib/generators/rspec/job/templates/job_spec.rb.erb +7 -0
  25. data/lib/generators/rspec/mailer/mailer_generator.rb +7 -0
  26. data/lib/generators/rspec/mailer/templates/mailer_spec.rb +7 -7
  27. data/lib/generators/rspec/mailer/templates/preview.rb +13 -0
  28. data/lib/generators/rspec/model/model_generator.rb +19 -5
  29. data/lib/generators/rspec/model/templates/fixtures.yml +1 -1
  30. data/lib/generators/rspec/model/templates/model_spec.rb +2 -2
  31. data/lib/generators/rspec/observer/observer_generator.rb +1 -0
  32. data/lib/generators/rspec/observer/templates/observer_spec.rb +2 -2
  33. data/lib/generators/rspec/request/request_generator.rb +10 -0
  34. data/lib/generators/rspec/scaffold/scaffold_generator.rb +68 -138
  35. data/lib/generators/rspec/scaffold/templates/api_controller_spec.rb +165 -0
  36. data/lib/generators/rspec/scaffold/templates/controller_spec.rb +98 -73
  37. data/lib/generators/rspec/scaffold/templates/edit_spec.rb +9 -13
  38. data/lib/generators/rspec/scaffold/templates/index_spec.rb +3 -10
  39. data/lib/generators/rspec/scaffold/templates/new_spec.rb +10 -14
  40. data/lib/generators/rspec/scaffold/templates/routing_spec.rb +21 -12
  41. data/lib/generators/rspec/scaffold/templates/show_spec.rb +4 -11
  42. data/lib/generators/rspec/system/system_generator.rb +26 -0
  43. data/lib/generators/rspec/system/templates/system_spec.rb +9 -0
  44. data/lib/generators/rspec/view/templates/view_spec.rb +2 -2
  45. data/lib/generators/rspec/view/view_generator.rb +1 -0
  46. data/lib/generators/rspec.rb +20 -6
  47. data/lib/rspec/rails/active_record.rb +25 -0
  48. data/lib/rspec/rails/adapters.rb +104 -37
  49. data/lib/rspec/rails/configuration.rb +148 -0
  50. data/lib/rspec/rails/example/controller_example_group.rb +188 -138
  51. data/lib/rspec/rails/example/feature_example_group.rb +63 -20
  52. data/lib/rspec/rails/example/helper_example_group.rb +35 -26
  53. data/lib/rspec/rails/example/job_example_group.rb +23 -0
  54. data/lib/rspec/rails/example/mailer_example_group.rb +30 -14
  55. data/lib/rspec/rails/example/model_example_group.rb +8 -7
  56. data/lib/rspec/rails/example/rails_example_group.rb +3 -1
  57. data/lib/rspec/rails/example/request_example_group.rb +23 -16
  58. data/lib/rspec/rails/example/routing_example_group.rb +49 -40
  59. data/lib/rspec/rails/example/system_example_group.rb +108 -0
  60. data/lib/rspec/rails/example/view_example_group.rb +168 -135
  61. data/lib/rspec/rails/example.rb +2 -33
  62. data/lib/rspec/rails/extensions/active_record/proxy.rb +0 -1
  63. data/lib/rspec/rails/extensions.rb +0 -1
  64. data/lib/rspec/rails/feature_check.rb +64 -0
  65. data/lib/rspec/rails/file_fixture_support.rb +17 -0
  66. data/lib/rspec/rails/fixture_file_upload_support.rb +40 -0
  67. data/lib/rspec/rails/fixture_support.rb +32 -13
  68. data/lib/rspec/rails/matchers/active_job.rb +317 -0
  69. data/lib/rspec/rails/matchers/base_matcher.rb +184 -0
  70. data/lib/rspec/rails/matchers/be_a_new.rb +69 -62
  71. data/lib/rspec/rails/matchers/be_new_record.rb +24 -21
  72. data/lib/rspec/rails/matchers/be_valid.rb +42 -33
  73. data/lib/rspec/rails/matchers/have_enqueued_mail.rb +174 -0
  74. data/lib/rspec/rails/matchers/have_http_status.rb +381 -0
  75. data/lib/rspec/rails/matchers/have_rendered.rb +54 -31
  76. data/lib/rspec/rails/matchers/redirect_to.rb +30 -29
  77. data/lib/rspec/rails/matchers/relation_match_array.rb +1 -1
  78. data/lib/rspec/rails/matchers/routing_matchers.rb +107 -93
  79. data/lib/rspec/rails/matchers.rb +13 -14
  80. data/lib/rspec/rails/tasks/rspec.rake +1 -1
  81. data/lib/rspec/rails/vendor/capybara.rb +10 -4
  82. data/lib/rspec/rails/version.rb +3 -1
  83. data/lib/rspec/rails/view_assigns.rb +18 -18
  84. data/lib/rspec/rails/view_path_builder.rb +29 -0
  85. data/lib/rspec/rails/view_rendering.rb +89 -63
  86. data/lib/rspec/rails/view_spec_methods.rb +56 -0
  87. data/lib/rspec/rails.rb +10 -10
  88. data/lib/rspec-rails.rb +66 -1
  89. data.tar.gz.sig +0 -0
  90. metadata +92 -77
  91. metadata.gz.sig +0 -0
  92. data/lib/autotest/rails_rspec2.rb +0 -85
  93. data/lib/generators/rspec/install/templates/.rspec +0 -1
  94. data/lib/generators/rspec/install/templates/spec/spec_helper.rb.tt +0 -49
  95. data/lib/rspec/rails/extensions/active_record/base.rb +0 -58
  96. data/lib/rspec/rails/matchers/have_extension.rb +0 -36
  97. data/lib/rspec/rails/mocks.rb +0 -274
  98. data/lib/rspec/rails/module_inclusion.rb +0 -19
  99. data/lib/rspec/rails/vendor/webrat.rb +0 -33
@@ -0,0 +1,148 @@
1
+ module RSpec
2
+ module Rails
3
+ # Fake class to document RSpec Rails configuration options. In practice,
4
+ # these are dynamically added to the normal RSpec configuration object.
5
+ class Configuration
6
+ # @!method infer_spec_type_from_file_location!
7
+ # Automatically tag specs in conventional directories with matching `type`
8
+ # metadata so that they have relevant helpers available to them. See
9
+ # `RSpec::Rails::DIRECTORY_MAPPINGS` for details on which metadata is
10
+ # applied to each directory.
11
+
12
+ # @!method render_views=(val)
13
+ #
14
+ # When set to `true`, controller specs will render the relevant view as
15
+ # well. Defaults to `false`.
16
+
17
+ # @!method render_views(val)
18
+ # Enables view rendering for controllers specs.
19
+
20
+ # @!method render_views?
21
+ # Reader for currently value of `render_views` setting.
22
+ end
23
+
24
+ # Mappings used by `infer_spec_type_from_file_location!`.
25
+ #
26
+ # @api private
27
+ DIRECTORY_MAPPINGS = {
28
+ :controller => %w[spec controllers],
29
+ :helper => %w[spec helpers],
30
+ :job => %w[spec jobs],
31
+ :mailer => %w[spec mailers],
32
+ :model => %w[spec models],
33
+ :request => %w[spec (requests|integration|api)],
34
+ :routing => %w[spec routing],
35
+ :view => %w[spec views],
36
+ :feature => %w[spec features],
37
+ :system => %w[spec system]
38
+ }
39
+
40
+ # Sets up the different example group modules for the different spec types
41
+ #
42
+ # @api private
43
+ def self.add_test_type_configurations(config)
44
+ config.include RSpec::Rails::ControllerExampleGroup, :type => :controller
45
+ config.include RSpec::Rails::HelperExampleGroup, :type => :helper
46
+ config.include RSpec::Rails::ModelExampleGroup, :type => :model
47
+ config.include RSpec::Rails::RequestExampleGroup, :type => :request
48
+ config.include RSpec::Rails::RoutingExampleGroup, :type => :routing
49
+ config.include RSpec::Rails::ViewExampleGroup, :type => :view
50
+ config.include RSpec::Rails::FeatureExampleGroup, :type => :feature
51
+ config.include RSpec::Rails::Matchers
52
+ config.include RSpec::Rails::SystemExampleGroup, :type => :system
53
+ end
54
+
55
+ # @private
56
+ # rubocop:disable Style/MethodLength
57
+ def self.initialize_configuration(config)
58
+ config.backtrace_exclusion_patterns << /vendor\//
59
+ config.backtrace_exclusion_patterns << %r{lib/rspec/rails}
60
+
61
+ # controller settings
62
+ config.add_setting :infer_base_class_for_anonymous_controllers, :default => true
63
+
64
+ # fixture support
65
+ config.add_setting :use_transactional_fixtures, :alias_with => :use_transactional_examples
66
+ config.add_setting :use_instantiated_fixtures
67
+ config.add_setting :global_fixtures
68
+ config.add_setting :fixture_path
69
+ config.include RSpec::Rails::FixtureSupport, :use_fixtures
70
+
71
+ # We'll need to create a deprecated module in order to properly report to
72
+ # gems / projects which are relying on this being loaded globally.
73
+ #
74
+ # See rspec/rspec-rails#1355 for history
75
+ #
76
+ # @deprecated Include `RSpec::Rails::RailsExampleGroup` or
77
+ # `RSpec::Rails::FixtureSupport` directly instead
78
+ config.include RSpec::Rails::FixtureSupport
79
+
80
+ if ::Rails::VERSION::STRING > '5'
81
+ config.add_setting :file_fixture_path, :default => 'spec/fixtures/files'
82
+ config.include RSpec::Rails::FileFixtureSupport
83
+ end
84
+
85
+ # Add support for fixture_path on fixture_file_upload
86
+ config.include RSpec::Rails::FixtureFileUploadSupport
87
+
88
+ # This allows us to expose `render_views` as a config option even though it
89
+ # breaks the convention of other options by using `render_views` as a
90
+ # command (i.e. `render_views = true`), where it would normally be used
91
+ # as a getter. This makes it easier for rspec-rails users because we use
92
+ # `render_views` directly in example groups, so this aligns the two APIs,
93
+ # but requires this workaround:
94
+ config.add_setting :rendering_views, :default => false
95
+
96
+ config.instance_exec do
97
+ def render_views=(val)
98
+ self.rendering_views = val
99
+ end
100
+
101
+ def render_views
102
+ self.rendering_views = true
103
+ end
104
+
105
+ def render_views?
106
+ rendering_views
107
+ end
108
+
109
+ def infer_spec_type_from_file_location!
110
+ DIRECTORY_MAPPINGS.each do |type, dir_parts|
111
+ escaped_path = Regexp.compile(dir_parts.join('[\\\/]') + '[\\\/]')
112
+ define_derived_metadata(:file_path => escaped_path) do |metadata|
113
+ metadata[:type] ||= type
114
+ end
115
+ end
116
+ end
117
+
118
+ # Adds exclusion filters for gems included with Rails
119
+ def filter_rails_from_backtrace!
120
+ filter_gems_from_backtrace "actionmailer", "actionpack", "actionview"
121
+ filter_gems_from_backtrace "activemodel", "activerecord",
122
+ "activesupport", "activejob"
123
+ end
124
+ end
125
+
126
+ add_test_type_configurations(config)
127
+
128
+ if defined?(::Rails::Controller::Testing)
129
+ [:controller, :view, :request].each do |type|
130
+ config.include ::Rails::Controller::Testing::TestProcess, :type => type
131
+ config.include ::Rails::Controller::Testing::TemplateAssertions, :type => type
132
+ config.include ::Rails::Controller::Testing::Integration, :type => type
133
+ end
134
+ end
135
+
136
+ if defined?(ActionMailer)
137
+ config.include RSpec::Rails::MailerExampleGroup, :type => :mailer
138
+ end
139
+
140
+ if defined?(ActiveJob)
141
+ config.include RSpec::Rails::JobExampleGroup, :type => :job
142
+ end
143
+ end
144
+ # rubocop:enable Style/MethodLength
145
+
146
+ initialize_configuration RSpec.configuration
147
+ end
148
+ end
@@ -1,164 +1,214 @@
1
- RSpec.configure do |config|
2
- config.add_setting :infer_base_class_for_anonymous_controllers, :default => false
3
- end
4
-
5
- module RSpec::Rails
6
- module ControllerExampleGroup
7
- extend ActiveSupport::Concern
8
- include RSpec::Rails::RailsExampleGroup
9
- include ActionController::TestCase::Behavior
10
- include RSpec::Rails::ViewRendering
11
- include RSpec::Rails::Matchers::RedirectTo
12
- include RSpec::Rails::Matchers::RenderTemplate
13
- include RSpec::Rails::Matchers::RoutingMatchers
14
- include RSpec::Rails::AssertionDelegator.new(ActionDispatch::Assertions::RoutingAssertions)
15
-
16
- module ClassMethods
17
- # @private
18
- def controller_class
19
- described_class
20
- end
1
+ module RSpec
2
+ module Rails
3
+ # @private
4
+ ControllerAssertionDelegator = RSpec::Rails::AssertionDelegator.new(
5
+ ActionDispatch::Assertions::RoutingAssertions
6
+ )
7
+
8
+ # @api public
9
+ # Container module for controller spec functionality.
10
+ module ControllerExampleGroup
11
+ extend ActiveSupport::Concern
12
+ include RSpec::Rails::RailsExampleGroup
13
+ include ActionController::TestCase::Behavior
14
+ include RSpec::Rails::ViewRendering
15
+ include RSpec::Rails::Matchers::RedirectTo
16
+ include RSpec::Rails::Matchers::RenderTemplate
17
+ include RSpec::Rails::Matchers::RoutingMatchers
18
+ include ControllerAssertionDelegator
19
+
20
+ # Class-level DSL for controller specs.
21
+ module ClassMethods
22
+ # @private
23
+ def controller_class
24
+ described_class
25
+ end
21
26
 
22
- # Supports a simple DSL for specifying behavior of ApplicationController.
23
- # Creates an anonymous subclass of ApplicationController and evals the
24
- # `body` in that context. Also sets up implicit routes for this
25
- # controller, that are separate from those defined in "config/routes.rb".
26
- #
27
- # @note Due to Ruby 1.8 scoping rules in anoymous subclasses, constants
28
- # defined in `ApplicationController` must be fully qualified (e.g.
29
- # `ApplicationController::AccessDenied`) in the block passed to the
30
- # `controller` method. Any instance methods, filters, etc, that are
31
- # defined in `ApplicationController`, however, are accessible from
32
- # within the block.
33
- #
34
- # @example
35
- #
36
- # describe ApplicationController do
37
- # controller do
38
- # def index
39
- # raise ApplicationController::AccessDenied
40
- # end
41
- # end
42
- #
43
- # describe "handling AccessDenied exceptions" do
44
- # it "redirects to the /401.html page" do
45
- # get :index
46
- # response.should redirect_to("/401.html")
47
- # end
48
- # end
49
- # end
50
- #
51
- # If you would like to spec a subclass of ApplicationController, call
52
- # controller like so:
53
- #
54
- # controller(ApplicationControllerSubclass) do
55
- # # ....
56
- # end
57
- def controller(base_class = nil, &body)
58
- root_controller = defined?(ApplicationController) ? ApplicationController : ActionController::Base
59
- base_class ||= RSpec.configuration.infer_base_class_for_anonymous_controllers? ?
60
- controller_class :
61
- root_controller
62
-
63
- metadata[:example_group][:described_class] = Class.new(base_class) do
64
- def self.name; "AnonymousController"; end
27
+ # Supports a simple DSL for specifying behavior of ApplicationController.
28
+ # Creates an anonymous subclass of ApplicationController and evals the
29
+ # `body` in that context. Also sets up implicit routes for this
30
+ # controller, that are separate from those defined in "config/routes.rb".
31
+ #
32
+ # @note Due to Ruby 1.8 scoping rules in anonymous subclasses, constants
33
+ # defined in `ApplicationController` must be fully qualified (e.g.
34
+ # `ApplicationController::AccessDenied`) in the block passed to the
35
+ # `controller` method. Any instance methods, filters, etc, that are
36
+ # defined in `ApplicationController`, however, are accessible from
37
+ # within the block.
38
+ #
39
+ # @example
40
+ # describe ApplicationController do
41
+ # controller do
42
+ # def index
43
+ # raise ApplicationController::AccessDenied
44
+ # end
45
+ # end
46
+ #
47
+ # describe "handling AccessDenied exceptions" do
48
+ # it "redirects to the /401.html page" do
49
+ # get :index
50
+ # response.should redirect_to("/401.html")
51
+ # end
52
+ # end
53
+ # end
54
+ #
55
+ # If you would like to spec a subclass of ApplicationController, call
56
+ # controller like so:
57
+ #
58
+ # controller(ApplicationControllerSubclass) do
59
+ # # ....
60
+ # end
61
+ def controller(base_class = nil, &body)
62
+ if RSpec.configuration.infer_base_class_for_anonymous_controllers?
63
+ base_class ||= controller_class
64
+ end
65
+ base_class ||= defined?(ApplicationController) ? ApplicationController : ActionController::Base
66
+
67
+ new_controller_class = Class.new(base_class) do
68
+ def self.name
69
+ root_controller = defined?(ApplicationController) ? ApplicationController : ActionController::Base
70
+ if superclass == root_controller || superclass.abstract?
71
+ "AnonymousController"
72
+ else
73
+ superclass.name
74
+ end
75
+ end
76
+ end
77
+ new_controller_class.class_exec(&body)
78
+ (class << self; self; end).__send__(:define_method, :controller_class) { new_controller_class }
79
+
80
+ before do
81
+ @orig_routes = routes
82
+ resource_name = if @controller.respond_to?(:controller_name)
83
+ @controller.controller_name.to_sym
84
+ else
85
+ :anonymous
86
+ end
87
+ resource_path = if @controller.respond_to?(:controller_path)
88
+ @controller.controller_path
89
+ else
90
+ resource_name.to_s
91
+ end
92
+ resource_module = resource_path.rpartition('/').first.presence
93
+ resource_as = 'anonymous_' + resource_path.tr('/', '_')
94
+ self.routes = ActionDispatch::Routing::RouteSet.new.tap do |r|
95
+ r.draw do
96
+ resources resource_name,
97
+ :as => resource_as,
98
+ :module => resource_module,
99
+ :path => resource_path
100
+ end
101
+ end
102
+ end
103
+
104
+ after do
105
+ self.routes = @orig_routes
106
+ @orig_routes = nil
107
+ end
65
108
  end
66
- metadata[:example_group][:described_class].class_eval(&body)
67
109
 
68
- before do
69
- @orig_routes = self.routes
70
- self.routes = ActionDispatch::Routing::RouteSet.new.tap { |r|
71
- r.draw { resources :anonymous }
72
- }
110
+ # Specifies the routeset that will be used for the example group. This
111
+ # is most useful when testing Rails engines.
112
+ #
113
+ # @example
114
+ # describe MyEngine::PostsController do
115
+ # routes { MyEngine::Engine.routes }
116
+ #
117
+ # # ...
118
+ # end
119
+ def routes
120
+ before do
121
+ self.routes = yield
122
+ end
73
123
  end
124
+ end
125
+
126
+ # @!attribute [r]
127
+ # Returns the controller object instance under test.
128
+ attr_reader :controller
74
129
 
75
- after do
76
- self.routes = @orig_routes
77
- @orig_routes = nil
130
+ # @!attribute [r]
131
+ # Returns the Rails routes used for the spec.
132
+ attr_reader :routes
133
+
134
+ # @private
135
+ #
136
+ # RSpec Rails uses this to make Rails routes easily available to specs.
137
+ def routes=(routes)
138
+ @routes = routes
139
+ assertion_instance.instance_variable_set(:@routes, routes)
140
+ end
141
+
142
+ # @private
143
+ module BypassRescue
144
+ def rescue_with_handler(exception)
145
+ raise exception
78
146
  end
79
147
  end
80
148
 
81
- # Specifies the routeset that will be used for the example group. This
82
- # is most useful when testing Rails engines.
149
+ # Extends the controller with a module that overrides
150
+ # `rescue_with_handler` to raise the exception passed to it. Use this to
151
+ # specify that an action _should_ raise an exception given appropriate
152
+ # conditions.
83
153
  #
84
154
  # @example
155
+ # describe ProfilesController do
156
+ # it "raises a 403 when a non-admin user tries to view another user's profile" do
157
+ # profile = create_profile
158
+ # login_as profile.user
85
159
  #
86
- # describe MyEngine::PostsController do
87
- # routes { MyEngine::Engine.routes }
88
- #
89
- # # ...
160
+ # expect do
161
+ # bypass_rescue
162
+ # get :show, :id => profile.id + 1
163
+ # end.to raise_error(/403 Forbidden/)
164
+ # end
90
165
  # end
91
- def routes(&blk)
92
- before do
93
- self.routes = blk.call
166
+ def bypass_rescue
167
+ controller.extend(BypassRescue)
168
+ end
169
+
170
+ # If method is a named_route, delegates to the RouteSet associated with
171
+ # this controller.
172
+ def method_missing(method, *args, &block)
173
+ if route_available?(method)
174
+ controller.send(method, *args, &block)
175
+ else
176
+ super
94
177
  end
95
178
  end
96
- end
97
179
 
98
- attr_reader :controller, :routes
180
+ included do
181
+ subject { controller }
99
182
 
100
- # @api private
101
- def routes=(routes)
102
- @routes = routes
103
- assertion_instance.instance_variable_set(:@routes, routes)
104
- end
183
+ before do
184
+ self.routes = ::Rails.application.routes
185
+ end
105
186
 
106
- module BypassRescue
107
- def rescue_with_handler(exception)
108
- raise exception
187
+ around do |ex|
188
+ previous_allow_forgery_protection_value = ActionController::Base.allow_forgery_protection
189
+ begin
190
+ ActionController::Base.allow_forgery_protection = false
191
+ ex.call
192
+ ensure
193
+ ActionController::Base.allow_forgery_protection = previous_allow_forgery_protection_value
194
+ end
195
+ end
109
196
  end
110
- end
111
197
 
112
- # Extends the controller with a module that overrides
113
- # `rescue_with_handler` to raise the exception passed to it. Use this to
114
- # specify that an action _should_ raise an exception given appropriate
115
- # conditions.
116
- #
117
- # @example
118
- #
119
- # describe ProfilesController do
120
- # it "raises a 403 when a non-admin user tries to view another user's profile" do
121
- # profile = create_profile
122
- # login_as profile.user
123
- #
124
- # expect do
125
- # bypass_rescue
126
- # get :show, :id => profile.id + 1
127
- # end.to raise_error(/403 Forbidden/)
128
- # end
129
- # end
130
- def bypass_rescue
131
- controller.extend(BypassRescue)
132
- end
198
+ private
133
199
 
134
- # If method is a named_route, delegates to the RouteSet associated with
135
- # this controller.
136
- def method_missing(method, *args, &block)
137
- if @routes && @routes.named_routes.helpers.include?(method)
138
- controller.send(method, *args, &block)
139
- elsif defined?(@orig_routes) && @orig_routes && @orig_routes.named_routes.helpers.include?(method)
140
- controller.send(method, *args, &block)
141
- else
142
- super
200
+ def route_available?(method)
201
+ (defined?(@routes) && route_defined?(routes, method)) ||
202
+ (defined?(@orig_routes) && route_defined?(@orig_routes, method))
143
203
  end
144
- end
145
-
146
- included do
147
- subject { controller }
148
204
 
149
- metadata[:type] = :controller
150
-
151
- before do
152
- self.routes = ::Rails.application.routes
153
- end
205
+ def route_defined?(routes, method)
206
+ return false if routes.nil?
154
207
 
155
- around do |ex|
156
- previous_allow_forgery_protection_value = ActionController::Base.allow_forgery_protection
157
- begin
158
- ActionController::Base.allow_forgery_protection = false
159
- ex.call
160
- ensure
161
- ActionController::Base.allow_forgery_protection = previous_allow_forgery_protection_value
208
+ if routes.named_routes.respond_to?(:route_defined?)
209
+ routes.named_routes.route_defined?(method)
210
+ else
211
+ routes.named_routes.helpers.include?(method)
162
212
  end
163
213
  end
164
214
  end
@@ -1,30 +1,73 @@
1
- module RSpec::Rails
2
- module FeatureExampleGroup
3
- extend ActiveSupport::Concern
4
- include RSpec::Rails::RailsExampleGroup
1
+ module RSpec
2
+ module Rails
3
+ # @api public
4
+ # Container module for routing spec functionality.
5
+ module FeatureExampleGroup
6
+ extend ActiveSupport::Concern
7
+ include RSpec::Rails::RailsExampleGroup
5
8
 
6
- DEFAULT_HOST = "www.example.com"
9
+ # Default host to be used in Rails route helpers if none is specified.
10
+ DEFAULT_HOST = "www.example.com"
7
11
 
8
- included do
9
- metadata[:type] = :feature
12
+ included do
13
+ app = ::Rails.application
14
+ if app.respond_to?(:routes)
15
+ include app.routes.url_helpers if app.routes.respond_to?(:url_helpers)
16
+ include app.routes.mounted_helpers if app.routes.respond_to?(:mounted_helpers)
10
17
 
11
- app = ::Rails.application
12
- if app.respond_to?(:routes)
13
- include app.routes.url_helpers if app.routes.respond_to?(:url_helpers)
14
- include app.routes.mounted_helpers if app.routes.respond_to?(:mounted_helpers)
15
-
16
- if respond_to?(:default_url_options)
17
- default_url_options[:host] ||= ::RSpec::Rails::FeatureExampleGroup::DEFAULT_HOST
18
+ if respond_to?(:default_url_options)
19
+ default_url_options[:host] ||= ::RSpec::Rails::FeatureExampleGroup::DEFAULT_HOST
20
+ end
18
21
  end
19
22
  end
20
- end
21
23
 
22
- def visit(*)
23
- if defined?(super)
24
- super
25
- else
26
- raise "Capybara not loaded, please add it to your Gemfile:\n\ngem \"capybara\""
24
+ # Shim to check for presence of Capybara. Will delegate if present, raise
25
+ # if not. We assume here that in most cases `visit` will be the first
26
+ # Capybara method called in a spec.
27
+ def visit(*)
28
+ if defined?(super)
29
+ super
30
+ else
31
+ raise "Capybara not loaded, please add it to your Gemfile:\n\ngem \"capybara\""
32
+ end
27
33
  end
28
34
  end
29
35
  end
30
36
  end
37
+
38
+ unless RSpec.respond_to?(:feature)
39
+ opts = {
40
+ :capybara_feature => true,
41
+ :type => :feature,
42
+ :skip => <<-EOT.squish
43
+ Feature specs require the Capybara (http://github.com/jnicklas/capybara)
44
+ gem, version 2.2.0 or later. We recommend version 2.4.0 or later to avoid
45
+ some deprecation warnings and have support for
46
+ `config.expose_dsl_globally = false`.
47
+ EOT
48
+ }
49
+
50
+ # Capybara's monkey patching causes us to have to jump through some hoops
51
+ top_level = self
52
+ main_feature = nil
53
+ if defined?(Capybara) && ::Capybara::VERSION.to_f < 2.4
54
+ # Capybara 2.2 and 2.3 do not use `alias_example_xyz`
55
+ opts[:skip] = <<-EOT.squish
56
+ Capybara < 2.4.0 does not support RSpec's namespace or
57
+ `config.expose_dsl_globally = false`. Upgrade to Capybara >= 2.4.0.
58
+ EOT
59
+ main_feature = top_level.method(:feature) if top_level.respond_to?(:feature)
60
+ end
61
+
62
+ RSpec.configure do |c|
63
+ main_feature = nil unless c.expose_dsl_globally?
64
+ c.alias_example_group_to :feature, opts
65
+ c.alias_example_to :scenario
66
+ c.alias_example_to :xscenario, :skip => 'Temporarily skipped with xscenario'
67
+ end
68
+
69
+ # Due to load order issues and `config.expose_dsl_globally?` defaulting to
70
+ # `true` we need to put Capybara's monkey patch method back. Otherwise,
71
+ # app upgrades have a high likelyhood of having all feature specs skipped.
72
+ top_level.define_singleton_method(:feature, &main_feature) if main_feature
73
+ end
@@ -1,39 +1,48 @@
1
1
  require 'rspec/rails/view_assigns'
2
2
 
3
- module RSpec::Rails
4
- module HelperExampleGroup
5
- extend ActiveSupport::Concern
6
- include RSpec::Rails::RailsExampleGroup
7
- include ActionView::TestCase::Behavior
8
- include RSpec::Rails::ViewAssigns
3
+ module RSpec
4
+ module Rails
5
+ # @api public
6
+ # Container module for helper specs.
7
+ module HelperExampleGroup
8
+ extend ActiveSupport::Concern
9
+ include RSpec::Rails::RailsExampleGroup
10
+ include ActionView::TestCase::Behavior
11
+ include RSpec::Rails::ViewAssigns
9
12
 
10
- module ClassMethods
11
- # @api private
12
- def determine_default_helper_class(ignore)
13
- described_class
13
+ # @private
14
+ module ClassMethods
15
+ if ::Rails::VERSION::MAJOR > 3
16
+ def determine_constant_from_test_name(_ignore)
17
+ described_class if yield(described_class)
18
+ end
19
+ else
20
+ def determine_default_helper_class(_ignore)
21
+ return unless Module === described_class && !(Class === described_class)
22
+ described_class
23
+ end
24
+ end
14
25
  end
15
- end
16
26
 
17
- # Returns an instance of ActionView::Base with the helper being specified
18
- # mixed in, along with any of the built-in rails helpers.
19
- def helper
20
- _view.tap do |v|
21
- v.extend(ApplicationHelper) if defined?(ApplicationHelper)
22
- v.assign(view_assigns)
27
+ # Returns an instance of ActionView::Base with the helper being specified
28
+ # mixed in, along with any of the built-in rails helpers.
29
+ def helper
30
+ _view.tap do |v|
31
+ v.extend(ApplicationHelper) if defined?(ApplicationHelper)
32
+ v.assign(view_assigns)
33
+ end
23
34
  end
24
- end
25
35
 
26
36
  private
27
37
 
28
- def _controller_path
29
- example.example_group.described_class.to_s.sub(/Helper/,'').underscore
30
- end
31
-
32
- included do
33
- metadata[:type] = :helper
38
+ def _controller_path(example)
39
+ example.example_group.described_class.to_s.sub(/Helper/, '').underscore
40
+ end
34
41
 
35
- before do
36
- controller.controller_path = _controller_path
42
+ included do
43
+ before do |example|
44
+ controller.controller_path = _controller_path(example)
45
+ end
37
46
  end
38
47
  end
39
48
  end