rspec-rails 2.14.2 → 4.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) 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 +6 -57
  6. data/Changelog.md +715 -37
  7. data/{License.txt → LICENSE.md} +5 -2
  8. data/README.md +287 -362
  9. data/lib/generators/rspec/channel/channel_generator.rb +12 -0
  10. data/lib/generators/rspec/channel/templates/channel_spec.rb.erb +7 -0
  11. data/lib/generators/rspec/controller/controller_generator.rb +23 -5
  12. data/lib/generators/rspec/controller/templates/controller_spec.rb +5 -5
  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 +2 -2
  16. data/lib/generators/rspec/feature/feature_generator.rb +29 -0
  17. data/lib/generators/rspec/feature/templates/feature_singular_spec.rb +5 -0
  18. data/lib/generators/rspec/feature/templates/feature_spec.rb +5 -0
  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 +2 -1
  22. data/lib/generators/rspec/helper/templates/helper_spec.rb +2 -2
  23. data/lib/generators/rspec/install/install_generator.rb +44 -5
  24. data/lib/generators/rspec/install/templates/spec/rails_helper.rb +79 -0
  25. data/lib/generators/rspec/integration/integration_generator.rb +8 -13
  26. data/lib/generators/rspec/integration/templates/request_spec.rb +4 -9
  27. data/lib/generators/rspec/job/job_generator.rb +12 -0
  28. data/lib/generators/rspec/{observer/templates/observer_spec.rb → job/templates/job_spec.rb.erb} +2 -2
  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 +9 -1
  32. data/lib/generators/rspec/mailer/templates/mailer_spec.rb +7 -7
  33. data/lib/generators/rspec/mailer/templates/preview.rb +13 -0
  34. data/lib/generators/rspec/model/model_generator.rb +21 -6
  35. data/lib/generators/rspec/model/templates/fixtures.yml +1 -1
  36. data/lib/generators/rspec/model/templates/model_spec.rb +2 -2
  37. data/lib/generators/rspec/request/request_generator.rb +10 -0
  38. data/lib/generators/rspec/scaffold/scaffold_generator.rb +88 -148
  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 +105 -80
  42. data/lib/generators/rspec/scaffold/templates/edit_spec.rb +10 -14
  43. data/lib/generators/rspec/scaffold/templates/index_spec.rb +5 -12
  44. data/lib/generators/rspec/scaffold/templates/new_spec.rb +11 -15
  45. data/lib/generators/rspec/scaffold/templates/request_spec.rb +137 -0
  46. data/lib/generators/rspec/scaffold/templates/routing_spec.rb +19 -12
  47. data/lib/generators/rspec/scaffold/templates/show_spec.rb +5 -12
  48. data/lib/generators/rspec/system/system_generator.rb +26 -0
  49. data/lib/generators/rspec/system/templates/system_spec.rb +9 -0
  50. data/lib/generators/rspec/view/templates/view_spec.rb +2 -2
  51. data/lib/generators/rspec/view/view_generator.rb +3 -2
  52. data/lib/generators/rspec.rb +18 -10
  53. data/lib/rspec/rails/active_record.rb +25 -0
  54. data/lib/rspec/rails/adapters.rb +49 -47
  55. data/lib/rspec/rails/configuration.rb +194 -0
  56. data/lib/rspec/rails/example/channel_example_group.rb +93 -0
  57. data/lib/rspec/rails/example/controller_example_group.rb +188 -138
  58. data/lib/rspec/rails/example/feature_example_group.rb +43 -20
  59. data/lib/rspec/rails/example/helper_example_group.rb +28 -26
  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 +30 -14
  63. data/lib/rspec/rails/example/model_example_group.rb +8 -7
  64. data/lib/rspec/rails/example/rails_example_group.rb +4 -2
  65. data/lib/rspec/rails/example/request_example_group.rb +23 -16
  66. data/lib/rspec/rails/example/routing_example_group.rb +49 -40
  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 -33
  70. data/lib/rspec/rails/extensions/active_record/proxy.rb +5 -11
  71. data/lib/rspec/rails/extensions.rb +0 -1
  72. data/lib/rspec/rails/feature_check.rb +47 -0
  73. data/lib/rspec/rails/file_fixture_support.rb +17 -0
  74. data/lib/rspec/rails/fixture_file_upload_support.rb +35 -0
  75. data/lib/rspec/rails/fixture_support.rb +54 -23
  76. data/lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb +170 -0
  77. data/lib/rspec/rails/matchers/action_cable/have_streams.rb +58 -0
  78. data/lib/rspec/rails/matchers/action_cable.rb +65 -0
  79. data/lib/rspec/rails/matchers/action_mailbox.rb +64 -0
  80. data/lib/rspec/rails/matchers/active_job.rb +465 -0
  81. data/lib/rspec/rails/matchers/base_matcher.rb +179 -0
  82. data/lib/rspec/rails/matchers/be_a_new.rb +69 -62
  83. data/lib/rspec/rails/matchers/be_new_record.rb +24 -21
  84. data/lib/rspec/rails/matchers/be_valid.rb +42 -33
  85. data/lib/rspec/rails/matchers/have_enqueued_mail.rb +198 -0
  86. data/lib/rspec/rails/matchers/have_http_status.rb +385 -0
  87. data/lib/rspec/rails/matchers/have_rendered.rb +55 -31
  88. data/lib/rspec/rails/matchers/redirect_to.rb +30 -29
  89. data/lib/rspec/rails/matchers/relation_match_array.rb +2 -2
  90. data/lib/rspec/rails/matchers/routing_matchers.rb +107 -93
  91. data/lib/rspec/rails/matchers.rb +22 -14
  92. data/lib/rspec/rails/tasks/rspec.rake +8 -18
  93. data/lib/rspec/rails/vendor/capybara.rb +12 -11
  94. data/lib/rspec/rails/version.rb +3 -1
  95. data/lib/rspec/rails/view_assigns.rb +18 -18
  96. data/lib/rspec/rails/view_path_builder.rb +29 -0
  97. data/lib/rspec/rails/view_rendering.rb +100 -63
  98. data/lib/rspec/rails/view_spec_methods.rb +56 -0
  99. data/lib/rspec/rails.rb +10 -10
  100. data/lib/rspec-rails.rb +67 -3
  101. data.tar.gz.sig +0 -0
  102. metadata +121 -94
  103. metadata.gz.sig +0 -0
  104. data/lib/autotest/rails_rspec2.rb +0 -85
  105. data/lib/generators/rspec/install/templates/.rspec +0 -1
  106. data/lib/generators/rspec/install/templates/spec/spec_helper.rb.tt +0 -49
  107. data/lib/generators/rspec/observer/observer_generator.rb +0 -12
  108. data/lib/rspec/rails/extensions/active_record/base.rb +0 -58
  109. data/lib/rspec/rails/matchers/have_extension.rb +0 -36
  110. data/lib/rspec/rails/mocks.rb +0 -274
  111. data/lib/rspec/rails/module_inclusion.rb +0 -19
  112. data/lib/rspec/rails/vendor/webrat.rb +0 -33
@@ -4,12 +4,14 @@ require 'rspec/rails/matchers'
4
4
 
5
5
  module RSpec
6
6
  module Rails
7
+ # @api public
8
+ # Common rails example functionality.
7
9
  module RailsExampleGroup
8
10
  extend ActiveSupport::Concern
9
11
  include RSpec::Rails::SetupAndTeardownAdapter
10
- include RSpec::Rails::MinitestLifecycleAdapter if ::Rails::VERSION::STRING >= '4'
12
+ include RSpec::Rails::MinitestLifecycleAdapter
11
13
  include RSpec::Rails::MinitestAssertionAdapter
12
- include RSpec::Rails::Matchers
14
+ include RSpec::Rails::FixtureSupport
13
15
  end
14
16
  end
15
17
  end
@@ -1,22 +1,29 @@
1
- module RSpec::Rails
2
- module RequestExampleGroup
3
- extend ActiveSupport::Concern
4
- include RSpec::Rails::RailsExampleGroup
5
- include ActionDispatch::Integration::Runner
6
- include ActionDispatch::Assertions
7
- include RSpec::Rails::Matchers::RedirectTo
8
- include RSpec::Rails::Matchers::RenderTemplate
9
- 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
10
13
 
11
- def app
12
- ::Rails.application
13
- end
14
+ if ActionPack::VERSION::MAJOR >= 5
15
+ include ActionDispatch::IntegrationTest::Behavior
16
+ end
14
17
 
15
- included do
16
- metadata[:type] = :request
18
+ # Delegates to `Rails.application`.
19
+ def app
20
+ ::Rails.application
21
+ end
17
22
 
18
- before do
19
- @routes = ::Rails.application.routes
23
+ included do
24
+ before do
25
+ @routes = ::Rails.application.routes
26
+ end
20
27
  end
21
28
  end
22
29
  end
@@ -1,54 +1,63 @@
1
1
  require "action_dispatch/testing/assertions/routing"
2
2
 
3
- module RSpec::Rails
4
- module RoutingExampleGroup
5
- extend ActiveSupport::Concern
6
- include RSpec::Rails::RailsExampleGroup
7
- include RSpec::Rails::Matchers::RoutingMatchers
8
- include RSpec::Rails::Matchers::RoutingMatchers::RouteHelpers
9
- include RSpec::Rails::AssertionDelegator.new(ActionDispatch::Assertions::RoutingAssertions)
10
-
11
- module ClassMethods
12
- # Specifies the routeset that will be used for the example group. This
13
- # is most useful when testing Rails engines.
14
- #
15
- # @example
16
- #
17
- # describe MyEngine::PostsController do
18
- # routes { MyEngine::Engine.routes }
19
- #
20
- # it "routes posts#index" do
21
- # expect(:get => "/posts").to
22
- # route_to(:controller => "my_engine/posts", :action => "index")
23
- # end
24
- # end
25
- def routes(&blk)
26
- before do
27
- 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
28
37
  end
29
38
  end
30
- end
31
-
32
- included do
33
- metadata[:type] = :routing
34
39
 
35
- before do
36
- self.routes = ::Rails.application.routes
40
+ included do
41
+ before do
42
+ self.routes = ::Rails.application.routes
43
+ end
37
44
  end
38
- end
39
45
 
40
- attr_reader :routes
46
+ # @!attribute [r]
47
+ # @private
48
+ attr_reader :routes
41
49
 
42
- # @api private
43
- def routes=(routes)
44
- @routes = routes
45
- assertion_instance.instance_variable_set(:@routes, routes)
46
- end
50
+ # @private
51
+ def routes=(routes)
52
+ @routes = routes
53
+ assertion_instance.instance_variable_set(:@routes, routes)
54
+ end
47
55
 
48
56
  private
49
57
 
50
- def method_missing(m, *args, &block)
51
- 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
52
61
  end
53
62
  end
54
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, "_")[0...200] + "_#{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
- module ViewExampleGroup
5
- extend ActiveSupport::Concern
6
- include RSpec::Rails::RailsExampleGroup
7
- include ActionView::TestCase::Behavior
8
- include RSpec::Rails::ViewAssigns
9
- include RSpec::Rails::Matchers::RenderTemplate
10
-
11
- module ClassMethods
12
- def _default_helper
13
- base = metadata[:example_group][:description].split('/')[0..-2].join('/')
14
- (base.camelize + 'Helper').constantize if base
15
- rescue NameError
16
- nil
17
- end
18
-
19
- def _default_helpers
20
- helpers = [_default_helper].compact
21
- helpers << ApplicationHelper if Object.const_defined?('ApplicationHelper')
22
- helpers
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
23
22
  end
24
- end
25
23
 
26
- module ExampleMethods
27
- # @overload render
28
- # @overload render({:partial => path_to_file})
29
- # @overload render({:partial => path_to_file}, {... locals ...})
30
- # @overload render({:partial => path_to_file}, {... locals ...}) do ... end
31
- #
32
- # Delegates to ActionView::Base#render, so see documentation on that
33
- # for more info.
34
- #
35
- # The only addition is that you can call render with no arguments, and RSpec
36
- # will pass the top level description to render:
37
- #
38
- # describe "widgets/new.html.erb" do
39
- # it "shows all the widgets" do
40
- # render # => view.render(:file => "widgets/new.html.erb")
41
- # # ...
42
- # end
43
- # end
44
- def render(options={}, local_assigns={}, &block)
45
- options = _default_render_options if Hash === options and options.empty?
46
- super(options, local_assigns, &block)
47
- 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
48
32
 
49
- # The instance of `ActionView::Base` that is used to render the template.
50
- # Use this to stub methods _before_ calling `render`.
51
- #
52
- # describe "widgets/new.html.erb" do
53
- # it "shows all the widgets" do
54
- # view.stub(:foo) { "foo" }
55
- # render
56
- # # ...
57
- # end
58
- # end
59
- def view
60
- _view
33
+ def _default_helpers
34
+ helpers = [_default_helper].compact
35
+ helpers << ApplicationHelper if Object.const_defined?('ApplicationHelper')
36
+ helpers
37
+ end
61
38
  end
62
39
 
63
- # Simulates the presence of a template on the file system by adding a
64
- # Rails' FixtureResolver to the front of the view_paths list. Designed to
65
- # help isolate view examples from partials rendered by the view template
66
- # that is the subject of the example.
67
- #
68
- # @example
69
- #
70
- # stub_template("widgets/_widget.html.erb" => "This content.")
71
- def stub_template(hash)
72
- view.view_paths.unshift(ActionView::FixtureResolver.new(hash))
73
- end
40
+ # DSL exposed to view specs.
41
+ module ExampleMethods
42
+ extend ActiveSupport::Concern
74
43
 
75
- # Provides access to the params hash that will be available within the
76
- # view:
77
- #
78
- # params[:foo] = 'bar'
79
- def params
80
- controller.params
81
- end
44
+ included do
45
+ include ::Rails.application.routes.url_helpers
46
+ include ::Rails.application.routes.mounted_helpers
47
+ end
82
48
 
83
- # @deprecated Use `view` instead.
84
- def template
85
- RSpec.deprecate("template", :replacement => "view")
86
- view
87
- 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
88
70
 
89
- # @deprecated Use `rendered` instead.
90
- def response
91
- # `assert_template` expects `response` to implement a #body method
92
- # like an `ActionDispatch::Response` does to force the view to render.
93
- # For backwards compatibility, we use #response as an alias for
94
- # #rendered, but it needs to implement #body to avoid `assert_template`
95
- # raising a `NoMethodError`.
96
- unless rendered.respond_to?(:body)
97
- def rendered.body; self; 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
98
83
  end
99
84
 
100
- rendered
101
- 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))
93
+ end
102
94
 
103
- private
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
104
102
 
105
- def _default_file_to_render
106
- example.example_group.top_level_description
107
- end
103
+ # @deprecated Use `view` instead.
104
+ def template
105
+ RSpec.deprecate("template", replacement: "view")
106
+ view
107
+ end
108
108
 
109
- def _default_render_options
110
- if ::Rails::VERSION::STRING >= '3.2'
111
- # pluck the handler, format, and locale out of, eg, posts/index.de.html.haml
112
- template, *components = _default_file_to_render.split('.')
113
- 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
114
124
 
115
- render_options = {:template => template}
116
- render_options[:handlers] = [handler] if handler
117
- render_options[:formats] = [format] if format
118
- 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]
119
157
 
120
158
  render_options
121
- else
122
- {:template => _default_file_to_render}
123
159
  end
124
- end
125
160
 
126
- def _path_parts
127
- _default_file_to_render.split("/")
128
- end
161
+ def _path_parts
162
+ _default_file_to_render.split("/")
163
+ end
129
164
 
130
- def _controller_path
131
- _path_parts[0..-2].join("/")
132
- end
165
+ def _controller_path
166
+ _path_parts[0..-2].join("/")
167
+ end
133
168
 
134
- def _inferred_action
135
- _path_parts.last.split(".").first
136
- end
169
+ def _inferred_action
170
+ _path_parts.last.split(".").first
171
+ end
137
172
 
138
- def _include_controller_helpers
139
- helpers = controller._helpers
140
- view.singleton_class.class_eval do
141
- 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
142
178
  end
143
179
  end
144
- end
145
180
 
146
- included do
147
- include ExampleMethods
181
+ included do
182
+ include ExampleMethods
148
183
 
149
- metadata[:type] = :view
150
- helper(*_default_helpers)
184
+ helper(*_default_helpers)
151
185
 
152
- before do
153
- _include_controller_helpers
154
- if view.lookup_context.respond_to?(:prefixes)
155
- # rails 3.1
186
+ before do
187
+ _include_controller_helpers
156
188
  view.lookup_context.prefixes << _controller_path
189
+
190
+ controller.controller_path = _controller_path
191
+
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)
157
201
  end
158
202
 
159
- # fixes bug with differing formats
160
- view.lookup_context.view_paths.each(&:clear_cache)
203
+ after do
204
+ ViewSpecMethods.remove_from(::ActionView::TestCase::TestController)
205
+ end
161
206
 
162
- controller.controller_path = _controller_path
163
- controller.request.path_parameters[:controller] = _controller_path
164
- controller.request.path_parameters[:action] = _inferred_action unless _inferred_action =~ /^_/
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
-