rspec-rails 3.0.2 → 5.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.document +1 -1
  4. data/.yardopts +3 -1
  5. data/Capybara.md +6 -55
  6. data/Changelog.md +619 -43
  7. data/{License.txt → LICENSE.md} +5 -3
  8. data/README.md +278 -444
  9. data/lib/generators/rspec/channel/channel_generator.rb +12 -0
  10. data/lib/generators/rspec/{observer/templates/observer_spec.rb → channel/templates/channel_spec.rb.erb} +1 -1
  11. data/lib/generators/rspec/controller/controller_generator.rb +22 -5
  12. data/lib/generators/rspec/controller/templates/controller_spec.rb +3 -3
  13. data/lib/generators/rspec/controller/templates/request_spec.rb +19 -0
  14. data/lib/generators/rspec/controller/templates/routing_spec.rb +13 -0
  15. data/lib/generators/rspec/controller/templates/view_spec.rb +1 -1
  16. data/lib/generators/rspec/feature/feature_generator.rb +15 -2
  17. data/lib/generators/rspec/feature/templates/feature_singular_spec.rb +5 -0
  18. data/lib/generators/rspec/feature/templates/feature_spec.rb +1 -1
  19. data/lib/generators/rspec/generator/generator_generator.rb +24 -0
  20. data/lib/generators/rspec/generator/templates/generator_spec.rb +6 -0
  21. data/lib/generators/rspec/helper/helper_generator.rb +1 -1
  22. data/lib/generators/rspec/helper/templates/helper_spec.rb +1 -1
  23. data/lib/generators/rspec/install/install_generator.rb +22 -5
  24. data/lib/generators/rspec/install/templates/spec/rails_helper.rb +43 -14
  25. data/lib/generators/rspec/integration/integration_generator.rb +7 -2
  26. data/lib/generators/rspec/integration/templates/request_spec.rb +3 -3
  27. data/lib/generators/rspec/job/job_generator.rb +13 -0
  28. data/lib/generators/rspec/job/templates/job_spec.rb.erb +7 -0
  29. data/lib/generators/rspec/mailbox/mailbox_generator.rb +14 -0
  30. data/lib/generators/rspec/mailbox/templates/mailbox_spec.rb.erb +7 -0
  31. data/lib/generators/rspec/mailer/mailer_generator.rb +8 -1
  32. data/lib/generators/rspec/mailer/templates/mailer_spec.rb +2 -2
  33. data/lib/generators/rspec/mailer/templates/preview.rb +13 -0
  34. data/lib/generators/rspec/model/model_generator.rb +20 -6
  35. data/lib/generators/rspec/model/templates/fixtures.yml +1 -1
  36. data/lib/generators/rspec/model/templates/model_spec.rb +1 -1
  37. data/lib/generators/rspec/request/request_generator.rb +10 -0
  38. data/lib/generators/rspec/scaffold/scaffold_generator.rb +90 -113
  39. data/lib/generators/rspec/scaffold/templates/api_controller_spec.rb +129 -0
  40. data/lib/generators/rspec/scaffold/templates/api_request_spec.rb +131 -0
  41. data/lib/generators/rspec/scaffold/templates/controller_spec.rb +46 -64
  42. data/lib/generators/rspec/scaffold/templates/edit_spec.rb +3 -3
  43. data/lib/generators/rspec/scaffold/templates/index_spec.rb +3 -3
  44. data/lib/generators/rspec/scaffold/templates/new_spec.rb +3 -3
  45. data/lib/generators/rspec/scaffold/templates/request_spec.rb +138 -0
  46. data/lib/generators/rspec/scaffold/templates/routing_spec.rb +18 -11
  47. data/lib/generators/rspec/scaffold/templates/show_spec.rb +2 -2
  48. data/lib/generators/rspec/system/system_generator.rb +24 -0
  49. data/lib/generators/rspec/system/templates/system_spec.rb +9 -0
  50. data/lib/generators/rspec/view/templates/view_spec.rb +1 -1
  51. data/lib/generators/rspec/view/view_generator.rb +2 -2
  52. data/lib/generators/rspec.rb +12 -10
  53. data/lib/rspec/rails/active_record.rb +25 -0
  54. data/lib/rspec/rails/adapters.rb +34 -28
  55. data/lib/rspec/rails/configuration.rb +135 -40
  56. data/lib/rspec/rails/example/channel_example_group.rb +93 -0
  57. data/lib/rspec/rails/example/controller_example_group.rb +185 -149
  58. data/lib/rspec/rails/example/feature_example_group.rb +43 -23
  59. data/lib/rspec/rails/example/helper_example_group.rb +28 -25
  60. data/lib/rspec/rails/example/job_example_group.rb +23 -0
  61. data/lib/rspec/rails/example/mailbox_example_group.rb +80 -0
  62. data/lib/rspec/rails/example/mailer_example_group.rb +27 -22
  63. data/lib/rspec/rails/example/model_example_group.rb +9 -6
  64. data/lib/rspec/rails/example/rails_example_group.rb +3 -2
  65. data/lib/rspec/rails/example/request_example_group.rb +21 -17
  66. data/lib/rspec/rails/example/routing_example_group.rb +49 -39
  67. data/lib/rspec/rails/example/system_example_group.rb +125 -0
  68. data/lib/rspec/rails/example/view_example_group.rb +178 -134
  69. data/lib/rspec/rails/example.rb +4 -0
  70. data/lib/rspec/rails/extensions/active_record/proxy.rb +5 -11
  71. data/lib/rspec/rails/feature_check.rb +47 -0
  72. data/lib/rspec/rails/file_fixture_support.rb +15 -0
  73. data/lib/rspec/rails/fixture_file_upload_support.rb +56 -0
  74. data/lib/rspec/rails/fixture_support.rb +42 -13
  75. data/lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb +170 -0
  76. data/lib/rspec/rails/matchers/action_cable/have_streams.rb +58 -0
  77. data/lib/rspec/rails/matchers/action_cable.rb +65 -0
  78. data/lib/rspec/rails/matchers/action_mailbox.rb +73 -0
  79. data/lib/rspec/rails/matchers/active_job.rb +465 -0
  80. data/lib/rspec/rails/matchers/base_matcher.rb +179 -0
  81. data/lib/rspec/rails/matchers/be_a_new.rb +70 -64
  82. data/lib/rspec/rails/matchers/be_new_record.rb +25 -20
  83. data/lib/rspec/rails/matchers/be_valid.rb +39 -34
  84. data/lib/rspec/rails/matchers/have_enqueued_mail.rb +226 -0
  85. data/lib/rspec/rails/matchers/have_http_status.rb +363 -333
  86. data/lib/rspec/rails/matchers/have_rendered.rb +55 -32
  87. data/lib/rspec/rails/matchers/redirect_to.rb +30 -27
  88. data/lib/rspec/rails/matchers/relation_match_array.rb +1 -1
  89. data/lib/rspec/rails/matchers/routing_matchers.rb +107 -101
  90. data/lib/rspec/rails/matchers.rb +20 -12
  91. data/lib/rspec/rails/tasks/rspec.rake +7 -17
  92. data/lib/rspec/rails/vendor/capybara.rb +12 -11
  93. data/lib/rspec/rails/version.rb +1 -1
  94. data/lib/rspec/rails/view_assigns.rb +1 -2
  95. data/lib/rspec/rails/view_path_builder.rb +29 -0
  96. data/lib/rspec/rails/view_rendering.rb +87 -27
  97. data/lib/rspec/rails/view_spec_methods.rb +56 -0
  98. data/lib/rspec/rails.rb +9 -1
  99. data/lib/rspec-rails.rb +62 -3
  100. data.tar.gz.sig +0 -0
  101. metadata +118 -72
  102. metadata.gz.sig +0 -0
  103. data/lib/generators/rspec/observer/observer_generator.rb +0 -13
@@ -1,8 +1,11 @@
1
- module RSpec::Rails
2
- # Container class for model spec functionality. Does not provide anything
3
- # special over the common RailsExampleGroup currently.
4
- module ModelExampleGroup
5
- extend ActiveSupport::Concern
6
- include RSpec::Rails::RailsExampleGroup
1
+ module RSpec
2
+ module Rails
3
+ # @api public
4
+ # Container class for model spec functionality. Does not provide anything
5
+ # special over the common RailsExampleGroup currently.
6
+ module ModelExampleGroup
7
+ extend ActiveSupport::Concern
8
+ include RSpec::Rails::RailsExampleGroup
9
+ end
7
10
  end
8
11
  end
@@ -4,13 +4,14 @@ require 'rspec/rails/matchers'
4
4
 
5
5
  module RSpec
6
6
  module Rails
7
+ # @api public
7
8
  # Common rails example functionality.
8
9
  module RailsExampleGroup
9
10
  extend ActiveSupport::Concern
10
11
  include RSpec::Rails::SetupAndTeardownAdapter
11
- include RSpec::Rails::MinitestLifecycleAdapter if ::Rails::VERSION::STRING >= '4'
12
+ include RSpec::Rails::MinitestLifecycleAdapter
12
13
  include RSpec::Rails::MinitestAssertionAdapter
13
- include RSpec::Rails::Matchers
14
+ include RSpec::Rails::FixtureSupport
14
15
  end
15
16
  end
16
17
  end
@@ -1,22 +1,26 @@
1
- module RSpec::Rails
2
- # Container class for request spec functionality.
3
- module RequestExampleGroup
4
- extend ActiveSupport::Concern
5
- include RSpec::Rails::RailsExampleGroup
6
- include ActionDispatch::Integration::Runner
7
- include ActionDispatch::Assertions
8
- include RSpec::Rails::Matchers::RedirectTo
9
- include RSpec::Rails::Matchers::RenderTemplate
10
- include ActionController::TemplateAssertions
1
+ module RSpec
2
+ module Rails
3
+ # @api public
4
+ # Container class for request spec functionality.
5
+ module RequestExampleGroup
6
+ extend ActiveSupport::Concern
7
+ include RSpec::Rails::RailsExampleGroup
8
+ include ActionDispatch::Integration::Runner
9
+ include ActionDispatch::Assertions
10
+ include RSpec::Rails::Matchers::RedirectTo
11
+ include RSpec::Rails::Matchers::RenderTemplate
12
+ include ActionController::TemplateAssertions
13
+ include ActionDispatch::IntegrationTest::Behavior
11
14
 
12
- # Delegates to `Rails.application`.
13
- def app
14
- ::Rails.application
15
- end
15
+ # Delegates to `Rails.application`.
16
+ def app
17
+ ::Rails.application
18
+ end
16
19
 
17
- included do
18
- before do
19
- @routes = ::Rails.application.routes
20
+ included do
21
+ before do
22
+ @routes = ::Rails.application.routes
23
+ end
20
24
  end
21
25
  end
22
26
  end
@@ -1,53 +1,63 @@
1
1
  require "action_dispatch/testing/assertions/routing"
2
2
 
3
- module RSpec::Rails
4
- # Container module for routing spec functionality.
5
- module RoutingExampleGroup
6
- extend ActiveSupport::Concern
7
- include RSpec::Rails::RailsExampleGroup
8
- include RSpec::Rails::Matchers::RoutingMatchers
9
- include RSpec::Rails::Matchers::RoutingMatchers::RouteHelpers
10
- include RSpec::Rails::AssertionDelegator.new(ActionDispatch::Assertions::RoutingAssertions)
11
-
12
- # Class-level DSL for route specs.
13
- module ClassMethods
14
- # Specifies the routeset that will be used for the example group. This
15
- # is most useful when testing Rails engines.
16
- #
17
- # @example
18
- # describe MyEngine::PostsController do
19
- # routes { MyEngine::Engine.routes }
20
- #
21
- # it "routes posts#index" do
22
- # expect(:get => "/posts").to
23
- # route_to(:controller => "my_engine/posts", :action => "index")
24
- # end
25
- # end
26
- def routes(&blk)
27
- before do
28
- self.routes = blk.call
3
+ module RSpec
4
+ module Rails
5
+ # @private
6
+ RoutingAssertionDelegator = RSpec::Rails::AssertionDelegator.new(
7
+ ActionDispatch::Assertions::RoutingAssertions
8
+ )
9
+
10
+ # @api public
11
+ # Container module for routing spec functionality.
12
+ module RoutingExampleGroup
13
+ extend ActiveSupport::Concern
14
+ include RSpec::Rails::RailsExampleGroup
15
+ include RSpec::Rails::Matchers::RoutingMatchers
16
+ include RSpec::Rails::Matchers::RoutingMatchers::RouteHelpers
17
+ include RSpec::Rails::RoutingAssertionDelegator
18
+
19
+ # Class-level DSL for route specs.
20
+ module ClassMethods
21
+ # Specifies the routeset that will be used for the example group. This
22
+ # is most useful when testing Rails engines.
23
+ #
24
+ # @example
25
+ # describe MyEngine::PostsController do
26
+ # routes { MyEngine::Engine.routes }
27
+ #
28
+ # it "routes posts#index" do
29
+ # expect(:get => "/posts").to
30
+ # route_to(:controller => "my_engine/posts", :action => "index")
31
+ # end
32
+ # end
33
+ def routes
34
+ before do
35
+ self.routes = yield
36
+ end
29
37
  end
30
38
  end
31
- end
32
39
 
33
- included do
34
- before do
35
- self.routes = ::Rails.application.routes
40
+ included do
41
+ before do
42
+ self.routes = ::Rails.application.routes
43
+ end
36
44
  end
37
- end
38
45
 
39
- attr_reader :routes
46
+ # @!attribute [r]
47
+ # @private
48
+ attr_reader :routes
40
49
 
41
- # @private
42
- def routes=(routes)
43
- @routes = routes
44
- assertion_instance.instance_variable_set(:@routes, routes)
45
- end
50
+ # @private
51
+ def routes=(routes)
52
+ @routes = routes
53
+ assertion_instance.instance_variable_set(:@routes, routes)
54
+ end
46
55
 
47
56
  private
48
57
 
49
- def method_missing(m, *args, &block)
50
- routes.url_helpers.respond_to?(m) ? routes.url_helpers.send(m, *args) : super
58
+ def method_missing(m, *args, &block)
59
+ routes.url_helpers.respond_to?(m) ? routes.url_helpers.send(m, *args) : super
60
+ end
51
61
  end
52
62
  end
53
63
  end
@@ -0,0 +1,125 @@
1
+ module RSpec
2
+ module Rails
3
+ # @api public
4
+ # Container class for system tests
5
+ module SystemExampleGroup
6
+ extend ActiveSupport::Concern
7
+ include RSpec::Rails::RailsExampleGroup
8
+ include RSpec::Rails::Matchers::RedirectTo
9
+ include RSpec::Rails::Matchers::RenderTemplate
10
+ include ActionDispatch::Integration::Runner
11
+ include ActionDispatch::Assertions
12
+ include ActionController::TemplateAssertions
13
+
14
+ # Special characters to translate into underscores for #method_name
15
+ CHARS_TO_TRANSLATE = ['/', '.', ':', ',', "'", '"', " "].freeze
16
+
17
+ # @private
18
+ module BlowAwayTeardownHooks
19
+ # @private
20
+ def before_teardown
21
+ end
22
+
23
+ # @private
24
+ def after_teardown
25
+ end
26
+ end
27
+
28
+ # for the SystemTesting Screenshot situation
29
+ def passed?
30
+ return false if RSpec.current_example.exception
31
+ return true unless defined?(::RSpec::Expectations::FailureAggregator)
32
+
33
+ failure_notifier = ::RSpec::Support.failure_notifier
34
+ return true unless failure_notifier.is_a?(::RSpec::Expectations::FailureAggregator)
35
+
36
+ failure_notifier.failures.empty? && failure_notifier.other_errors.empty?
37
+ end
38
+
39
+ # @private
40
+ def method_name
41
+ @method_name ||= [
42
+ self.class.name.underscore,
43
+ RSpec.current_example.description.underscore
44
+ ].join("_").tr(CHARS_TO_TRANSLATE.join, "_").byteslice(0...200).scrub("") + "_#{rand(1000)}"
45
+ end
46
+
47
+ # Delegates to `Rails.application`.
48
+ def app
49
+ ::Rails.application
50
+ end
51
+
52
+ included do |other|
53
+ ActiveSupport.on_load(:action_dispatch_system_test_case) do
54
+ ActionDispatch::SystemTesting::Server.silence_puma = true
55
+ end
56
+
57
+ begin
58
+ require 'capybara'
59
+ require 'action_dispatch/system_test_case'
60
+ rescue LoadError => e
61
+ abort """
62
+ LoadError: #{e.message}
63
+ System test integration requires Rails >= 5.1 and has a hard
64
+ dependency on a webserver and `capybara`, please add capybara to
65
+ your Gemfile and configure a webserver (e.g. `Capybara.server =
66
+ :webrick`) before attempting to use system specs.
67
+ """.gsub(/\s+/, ' ').strip
68
+ end
69
+
70
+ if ::Rails::VERSION::STRING >= '6.0'
71
+ original_before_teardown =
72
+ ::ActionDispatch::SystemTesting::TestHelpers::SetupAndTeardown.instance_method(:before_teardown)
73
+ end
74
+
75
+ original_after_teardown =
76
+ ::ActionDispatch::SystemTesting::TestHelpers::SetupAndTeardown.instance_method(:after_teardown)
77
+
78
+ other.include ::ActionDispatch::SystemTesting::TestHelpers::SetupAndTeardown
79
+ other.include ::ActionDispatch::SystemTesting::TestHelpers::ScreenshotHelper
80
+ other.include BlowAwayTeardownHooks
81
+
82
+ attr_reader :driver
83
+
84
+ if ActionDispatch::SystemTesting::Server.respond_to?(:silence_puma=)
85
+ ActionDispatch::SystemTesting::Server.silence_puma = true
86
+ end
87
+
88
+ def initialize(*args, &blk)
89
+ super(*args, &blk)
90
+ @driver = nil
91
+
92
+ self.class.before do
93
+ # A user may have already set the driver, so only default if driver
94
+ # is not set
95
+ driven_by(:selenium) unless @driver
96
+ end
97
+ end
98
+
99
+ def driven_by(driver, **driver_options, &blk)
100
+ @driver = ::ActionDispatch::SystemTestCase.driven_by(driver, **driver_options, &blk).tap(&:use)
101
+ end
102
+
103
+ before do
104
+ @routes = ::Rails.application.routes
105
+ end
106
+
107
+ after do
108
+ orig_stdout = $stdout
109
+ $stdout = StringIO.new
110
+ begin
111
+ if ::Rails::VERSION::STRING >= '6.0'
112
+ original_before_teardown.bind(self).call
113
+ end
114
+ original_after_teardown.bind(self).call
115
+ ensure
116
+ myio = $stdout
117
+ myio.rewind
118
+ RSpec.current_example.metadata[:extra_failure_lines] = myio.readlines
119
+ $stdout = orig_stdout
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -1,169 +1,213 @@
1
1
  require 'rspec/rails/view_assigns'
2
-
3
- module RSpec::Rails
4
- # Container class for view spec functionality.
5
- module ViewExampleGroup
6
- extend ActiveSupport::Concern
7
- include RSpec::Rails::RailsExampleGroup
8
- include ActionView::TestCase::Behavior
9
- include RSpec::Rails::ViewAssigns
10
- include RSpec::Rails::Matchers::RenderTemplate
11
-
12
- # @private
13
- module ClassMethods
14
- def _default_helper
15
- base = metadata[:description].split('/')[0..-2].join('/')
16
- (base.camelize + 'Helper').constantize if base
17
- rescue NameError
18
- nil
2
+ require 'rspec/rails/view_spec_methods'
3
+ require 'rspec/rails/view_path_builder'
4
+
5
+ module RSpec
6
+ module Rails
7
+ # @api public
8
+ # Container class for view spec functionality.
9
+ module ViewExampleGroup
10
+ extend ActiveSupport::Concern
11
+ include RSpec::Rails::RailsExampleGroup
12
+ include ActionView::TestCase::Behavior
13
+ include RSpec::Rails::ViewAssigns
14
+ include RSpec::Rails::Matchers::RenderTemplate
15
+
16
+ # @private
17
+ module StubResolverCache
18
+ def self.resolver_for(hash)
19
+ @resolvers ||= {}
20
+ @resolvers[hash] ||= ActionView::FixtureResolver.new(hash)
21
+ end
19
22
  end
20
23
 
21
- def _default_helpers
22
- helpers = [_default_helper].compact
23
- helpers << ApplicationHelper if Object.const_defined?('ApplicationHelper')
24
- helpers
25
- end
26
- end
24
+ # @private
25
+ module ClassMethods
26
+ def _default_helper
27
+ base = metadata[:description].split('/')[0..-2].join('/')
28
+ (base.camelize + 'Helper').constantize unless base.to_s.empty?
29
+ rescue NameError
30
+ nil
31
+ end
27
32
 
28
- # DSL exposed to view specs.
29
- module ExampleMethods
30
- # @overload render
31
- # @overload render({:partial => path_to_file})
32
- # @overload render({:partial => path_to_file}, {... locals ...})
33
- # @overload render({:partial => path_to_file}, {... locals ...}) do ... end
34
- #
35
- # Delegates to ActionView::Base#render, so see documentation on that
36
- # for more info.
37
- #
38
- # The only addition is that you can call render with no arguments, and RSpec
39
- # will pass the top level description to render:
40
- #
41
- # describe "widgets/new.html.erb" do
42
- # it "shows all the widgets" do
43
- # render # => view.render(:file => "widgets/new.html.erb")
44
- # # ...
45
- # end
46
- # end
47
- def render(options={}, local_assigns={}, &block)
48
- options = _default_render_options if Hash === options and options.empty?
49
- super(options, local_assigns, &block)
33
+ def _default_helpers
34
+ helpers = [_default_helper].compact
35
+ helpers << ApplicationHelper if Object.const_defined?('ApplicationHelper')
36
+ helpers
37
+ end
50
38
  end
51
39
 
52
- # The instance of `ActionView::Base` that is used to render the template.
53
- # Use this to stub methods _before_ calling `render`.
54
- #
55
- # describe "widgets/new.html.erb" do
56
- # it "shows all the widgets" do
57
- # view.stub(:foo) { "foo" }
58
- # render
59
- # # ...
60
- # end
61
- # end
62
- def view
63
- _view
64
- end
40
+ # DSL exposed to view specs.
41
+ module ExampleMethods
42
+ extend ActiveSupport::Concern
65
43
 
66
- # Simulates the presence of a template on the file system by adding a
67
- # Rails' FixtureResolver to the front of the view_paths list. Designed to
68
- # help isolate view examples from partials rendered by the view template
69
- # that is the subject of the example.
70
- #
71
- # stub_template("widgets/_widget.html.erb" => "This content.")
72
- def stub_template(hash)
73
- view.view_paths.unshift(ActionView::FixtureResolver.new(hash))
74
- end
44
+ included do
45
+ include ::Rails.application.routes.url_helpers
46
+ include ::Rails.application.routes.mounted_helpers
47
+ end
75
48
 
76
- # Provides access to the params hash that will be available within the
77
- # view.
78
- #
79
- # params[:foo] = 'bar'
80
- def params
81
- controller.params
82
- end
49
+ # @overload render
50
+ # @overload render({partial: path_to_file})
51
+ # @overload render({partial: path_to_file}, {... locals ...})
52
+ # @overload render({partial: path_to_file}, {... locals ...}) do ... end
53
+ #
54
+ # Delegates to ActionView::Base#render, so see documentation on that
55
+ # for more info.
56
+ #
57
+ # The only addition is that you can call render with no arguments, and
58
+ # RSpec will pass the top level description to render:
59
+ #
60
+ # describe "widgets/new.html.erb" do
61
+ # it "shows all the widgets" do
62
+ # render # => view.render(file: "widgets/new.html.erb")
63
+ # # ...
64
+ # end
65
+ # end
66
+ def render(options = {}, local_assigns = {}, &block)
67
+ options = _default_render_options if Hash === options && options.empty?
68
+ super(options, local_assigns, &block)
69
+ end
83
70
 
84
- # @deprecated Use `view` instead.
85
- def template
86
- RSpec.deprecate("template", :replacement => "view")
87
- view
88
- end
71
+ # The instance of `ActionView::Base` that is used to render the template.
72
+ # Use this to stub methods _before_ calling `render`.
73
+ #
74
+ # describe "widgets/new.html.erb" do
75
+ # it "shows all the widgets" do
76
+ # view.stub(:foo) { "foo" }
77
+ # render
78
+ # # ...
79
+ # end
80
+ # end
81
+ def view
82
+ _view
83
+ end
89
84
 
90
- # @deprecated Use `rendered` instead.
91
- def response
92
- # `assert_template` expects `response` to implement a #body method
93
- # like an `ActionDispatch::Response` does to force the view to render.
94
- # For backwards compatibility, we use #response as an alias for
95
- # #rendered, but it needs to implement #body to avoid `assert_template`
96
- # raising a `NoMethodError`.
97
- unless rendered.respond_to?(:body)
98
- def rendered.body; self; end;
85
+ # Simulates the presence of a template on the file system by adding a
86
+ # Rails' FixtureResolver to the front of the view_paths list. Designed to
87
+ # help isolate view examples from partials rendered by the view template
88
+ # that is the subject of the example.
89
+ #
90
+ # stub_template("widgets/_widget.html.erb" => "This content.")
91
+ def stub_template(hash)
92
+ view.view_paths.unshift(StubResolverCache.resolver_for(hash))
99
93
  end
100
94
 
101
- rendered
102
- end
95
+ # Provides access to the params hash that will be available within the
96
+ # view.
97
+ #
98
+ # params[:foo] = 'bar'
99
+ def params
100
+ controller.params
101
+ end
103
102
 
104
- private
103
+ # @deprecated Use `view` instead.
104
+ def template
105
+ RSpec.deprecate("template", replacement: "view")
106
+ view
107
+ end
105
108
 
106
- def _default_render_options
107
- if ::Rails::VERSION::STRING >= '3.2'
108
- # pluck the handler, format, and locale out of, eg, posts/index.de.html.haml
109
- template, *components = _default_file_to_render.split('.')
110
- handler, format, locale = *components.reverse
109
+ # @deprecated Use `rendered` instead.
110
+ def response
111
+ # `assert_template` expects `response` to implement a #body method
112
+ # like an `ActionDispatch::Response` does to force the view to
113
+ # render. For backwards compatibility, we use #response as an alias
114
+ # for #rendered, but it needs to implement #body to avoid
115
+ # `assert_template` raising a `NoMethodError`.
116
+ unless rendered.respond_to?(:body)
117
+ def rendered.body
118
+ self
119
+ end
120
+ end
121
+
122
+ rendered
123
+ end
111
124
 
112
- render_options = {:template => template}
113
- render_options[:handlers] = [handler] if handler
114
- render_options[:formats] = [format] if format
115
- render_options[:locales] = [locale] if locale
125
+ private
126
+
127
+ def _default_render_options
128
+ formats = if ActionView::Template::Types.respond_to?(:symbols)
129
+ ActionView::Template::Types.symbols
130
+ else
131
+ [:html, :text, :js, :css, :xml, :json].map(&:to_s)
132
+ end.map { |x| Regexp.escape(x) }.join("|")
133
+
134
+ handlers = ActionView::Template::Handlers.extensions.map { |x| Regexp.escape(x) }.join("|")
135
+ locales = "[a-z]{2}(?:-[A-Z]{2})?"
136
+ variants = "[^.]*"
137
+ path_regex = %r{
138
+ \A
139
+ (?<template>.*?)
140
+ (?:\.(?<locale>#{locales}))??
141
+ (?:\.(?<format>#{formats}))??
142
+ (?:\+(?<variant>#{variants}))??
143
+ (?:\.(?<handler>#{handlers}))?
144
+ \z
145
+ }x
146
+
147
+ # This regex should always find a match.
148
+ # Worst case, everything will be nil, and :template will just be
149
+ # the original string.
150
+ match = path_regex.match(_default_file_to_render)
151
+
152
+ render_options = {template: match[:template]}
153
+ render_options[:handlers] = [match[:handler]] if match[:handler]
154
+ render_options[:formats] = [match[:format].to_sym] if match[:format]
155
+ render_options[:locales] = [match[:locale]] if match[:locale]
156
+ render_options[:variants] = [match[:variant]] if match[:variant]
116
157
 
117
158
  render_options
118
- else
119
- {:template => _default_file_to_render}
120
159
  end
121
- end
122
160
 
123
- def _path_parts
124
- _default_file_to_render.split("/")
125
- end
161
+ def _path_parts
162
+ _default_file_to_render.split("/")
163
+ end
126
164
 
127
- def _controller_path
128
- _path_parts[0..-2].join("/")
129
- end
165
+ def _controller_path
166
+ _path_parts[0..-2].join("/")
167
+ end
130
168
 
131
- def _inferred_action
132
- _path_parts.last.split(".").first
133
- end
169
+ def _inferred_action
170
+ _path_parts.last.split(".").first
171
+ end
134
172
 
135
- def _include_controller_helpers
136
- helpers = controller._helpers
137
- view.singleton_class.class_exec do
138
- include helpers unless included_modules.include?(helpers)
173
+ def _include_controller_helpers
174
+ helpers = controller._helpers
175
+ view.singleton_class.class_exec do
176
+ include helpers unless included_modules.include?(helpers)
177
+ end
139
178
  end
140
179
  end
141
- end
142
180
 
143
- included do
144
- include ExampleMethods
181
+ included do
182
+ include ExampleMethods
145
183
 
146
- helper(*_default_helpers)
184
+ helper(*_default_helpers)
147
185
 
148
- before do
149
- _include_controller_helpers
150
- if view.lookup_context.respond_to?(:prefixes)
151
- # rails 3.1
186
+ before do
187
+ _include_controller_helpers
152
188
  view.lookup_context.prefixes << _controller_path
153
- end
154
189
 
155
- # fixes bug with differing formats
156
- view.lookup_context.view_paths.each(&:clear_cache)
190
+ controller.controller_path = _controller_path
157
191
 
158
- controller.controller_path = _controller_path
159
- controller.request.path_parameters[:controller] = _controller_path
160
- controller.request.path_parameters[:action] = _inferred_action unless _inferred_action =~ /^_/
161
- end
192
+ path_params_to_merge = {}
193
+ path_params_to_merge[:controller] = _controller_path
194
+ path_params_to_merge[:action] = _inferred_action unless _inferred_action =~ /^_/
195
+
196
+ path_params = controller.request.path_parameters
197
+
198
+ controller.request.path_parameters = path_params.reverse_merge(path_params_to_merge)
199
+ controller.request.path = ViewPathBuilder.new(::Rails.application.routes).path_for(controller.request.path_parameters)
200
+ ViewSpecMethods.add_to(::ActionView::TestCase::TestController)
201
+ end
162
202
 
163
- let(:_default_file_to_render) do |example|
164
- example.example_group.top_level_description
203
+ after do
204
+ ViewSpecMethods.remove_from(::ActionView::TestCase::TestController)
205
+ end
206
+
207
+ let(:_default_file_to_render) do |example|
208
+ example.example_group.top_level_description
209
+ end
165
210
  end
166
211
  end
167
212
  end
168
213
  end
169
-
@@ -6,4 +6,8 @@ require 'rspec/rails/example/view_example_group'
6
6
  require 'rspec/rails/example/mailer_example_group'
7
7
  require 'rspec/rails/example/routing_example_group'
8
8
  require 'rspec/rails/example/model_example_group'
9
+ require 'rspec/rails/example/job_example_group'
9
10
  require 'rspec/rails/example/feature_example_group'
11
+ require 'rspec/rails/example/system_example_group'
12
+ require 'rspec/rails/example/channel_example_group'
13
+ require 'rspec/rails/example/mailbox_example_group'