rspec-rails 3.0.2 → 7.1.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 (105) 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 +805 -47
  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 +24 -7
  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 +5 -0
  21. data/lib/generators/rspec/helper/helper_generator.rb +2 -2
  22. data/lib/generators/rspec/helper/templates/helper_spec.rb +1 -1
  23. data/lib/generators/rspec/install/install_generator.rb +41 -7
  24. data/lib/generators/rspec/install/templates/spec/rails_helper.rb +63 -22
  25. data/lib/generators/rspec/job/job_generator.rb +13 -0
  26. data/lib/generators/rspec/job/templates/job_spec.rb.erb +7 -0
  27. data/lib/generators/rspec/mailbox/mailbox_generator.rb +14 -0
  28. data/lib/generators/rspec/mailbox/templates/mailbox_spec.rb.erb +7 -0
  29. data/lib/generators/rspec/mailer/mailer_generator.rb +12 -3
  30. data/lib/generators/rspec/mailer/templates/mailer_spec.rb +2 -2
  31. data/lib/generators/rspec/mailer/templates/preview.rb +13 -0
  32. data/lib/generators/rspec/model/model_generator.rb +20 -6
  33. data/lib/generators/rspec/model/templates/fixtures.yml +1 -1
  34. data/lib/generators/rspec/model/templates/model_spec.rb +1 -1
  35. data/lib/generators/rspec/request/request_generator.rb +17 -0
  36. data/lib/generators/rspec/request/templates/request_spec.rb +10 -0
  37. data/lib/generators/rspec/scaffold/scaffold_generator.rb +90 -113
  38. data/lib/generators/rspec/scaffold/templates/api_controller_spec.rb +129 -0
  39. data/lib/generators/rspec/scaffold/templates/api_request_spec.rb +131 -0
  40. data/lib/generators/rspec/scaffold/templates/controller_spec.rb +46 -64
  41. data/lib/generators/rspec/scaffold/templates/edit_spec.rb +11 -7
  42. data/lib/generators/rspec/scaffold/templates/index_spec.rb +4 -3
  43. data/lib/generators/rspec/scaffold/templates/new_spec.rb +4 -4
  44. data/lib/generators/rspec/scaffold/templates/request_spec.rb +138 -0
  45. data/lib/generators/rspec/scaffold/templates/routing_spec.rb +18 -11
  46. data/lib/generators/rspec/scaffold/templates/show_spec.rb +3 -3
  47. data/lib/generators/rspec/system/system_generator.rb +24 -0
  48. data/lib/generators/rspec/system/templates/system_spec.rb +9 -0
  49. data/lib/generators/rspec/view/templates/view_spec.rb +1 -1
  50. data/lib/generators/rspec/view/view_generator.rb +4 -4
  51. data/lib/generators/rspec.rb +30 -11
  52. data/lib/rspec/rails/active_record.rb +25 -0
  53. data/lib/rspec/rails/adapters.rb +46 -29
  54. data/lib/rspec/rails/configuration.rb +165 -41
  55. data/lib/rspec/rails/example/channel_example_group.rb +93 -0
  56. data/lib/rspec/rails/example/controller_example_group.rb +185 -149
  57. data/lib/rspec/rails/example/feature_example_group.rb +43 -23
  58. data/lib/rspec/rails/example/helper_example_group.rb +28 -25
  59. data/lib/rspec/rails/example/job_example_group.rb +23 -0
  60. data/lib/rspec/rails/example/mailbox_example_group.rb +80 -0
  61. data/lib/rspec/rails/example/mailer_example_group.rb +27 -22
  62. data/lib/rspec/rails/example/model_example_group.rb +9 -6
  63. data/lib/rspec/rails/example/rails_example_group.rb +9 -2
  64. data/lib/rspec/rails/example/request_example_group.rb +21 -17
  65. data/lib/rspec/rails/example/routing_example_group.rb +47 -39
  66. data/lib/rspec/rails/example/system_example_group.rb +180 -0
  67. data/lib/rspec/rails/example/view_example_group.rb +179 -134
  68. data/lib/rspec/rails/example.rb +4 -0
  69. data/lib/rspec/rails/extensions/active_record/proxy.rb +5 -11
  70. data/lib/rspec/rails/feature_check.rb +51 -0
  71. data/lib/rspec/rails/file_fixture_support.rb +18 -0
  72. data/lib/rspec/rails/fixture_file_upload_support.rb +45 -0
  73. data/lib/rspec/rails/fixture_support.rb +70 -14
  74. data/lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb +180 -0
  75. data/lib/rspec/rails/matchers/action_cable/have_streams.rb +58 -0
  76. data/lib/rspec/rails/matchers/action_cable.rb +70 -0
  77. data/lib/rspec/rails/matchers/action_mailbox.rb +73 -0
  78. data/lib/rspec/rails/matchers/active_job.rb +526 -0
  79. data/lib/rspec/rails/matchers/base_matcher.rb +179 -0
  80. data/lib/rspec/rails/matchers/be_a_new.rb +70 -64
  81. data/lib/rspec/rails/matchers/be_new_record.rb +25 -20
  82. data/lib/rspec/rails/matchers/be_valid.rb +39 -34
  83. data/lib/rspec/rails/matchers/have_enqueued_mail.rb +259 -0
  84. data/lib/rspec/rails/matchers/have_http_status.rb +359 -333
  85. data/lib/rspec/rails/matchers/have_rendered.rb +55 -32
  86. data/lib/rspec/rails/matchers/redirect_to.rb +30 -27
  87. data/lib/rspec/rails/matchers/relation_match_array.rb +1 -1
  88. data/lib/rspec/rails/matchers/routing_matchers.rb +107 -101
  89. data/lib/rspec/rails/matchers/send_email.rb +122 -0
  90. data/lib/rspec/rails/matchers.rb +21 -12
  91. data/lib/rspec/rails/tasks/rspec.rake +9 -17
  92. data/lib/rspec/rails/vendor/capybara.rb +10 -11
  93. data/lib/rspec/rails/version.rb +1 -1
  94. data/lib/rspec/rails/view_assigns.rb +1 -20
  95. data/lib/rspec/rails/view_path_builder.rb +29 -0
  96. data/lib/rspec/rails/view_rendering.rb +89 -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 +83 -3
  100. data.tar.gz.sig +0 -0
  101. metadata +108 -78
  102. metadata.gz.sig +3 -2
  103. data/lib/generators/rspec/integration/integration_generator.rb +0 -17
  104. data/lib/generators/rspec/integration/templates/request_spec.rb +0 -10
  105. data/lib/generators/rspec/observer/observer_generator.rb +0 -13
@@ -1,31 +1,33 @@
1
1
  require 'delegate'
2
2
  require 'active_support'
3
3
  require 'active_support/concern'
4
+ require 'active_support/core_ext/string'
4
5
 
5
6
  module RSpec
6
7
  module Rails
7
- if ::Rails::VERSION::STRING >= '4.1.0'
8
- if defined?(Kernel.gem)
9
- gem 'minitest'
10
- else
11
- require 'minitest'
12
- end
13
- require 'minitest/assertions'
14
- # Constant aliased to either Minitest or TestUnit, depending on what is
15
- # loaded.
16
- Assertions = Minitest::Assertions
8
+ # @private
9
+ def self.disable_testunit_autorun
10
+ # `Test::Unit::AutoRunner.need_auto_run=` was introduced to the test-unit
11
+ # gem in version 2.4.9. Previous to this version `Test::Unit.run=` was
12
+ # used. The implementation of test-unit included with Ruby has neither
13
+ # method.
14
+ if defined?(Test::Unit::AutoRunner.need_auto_run = ())
15
+ Test::Unit::AutoRunner.need_auto_run = false
16
+ elsif defined?(Test::Unit.run = ())
17
+ Test::Unit.run = false
18
+ end
19
+ end
20
+ private_class_method :disable_testunit_autorun
21
+
22
+ if defined?(Kernel.gem)
23
+ gem 'minitest'
17
24
  else
18
- begin
19
- require 'test/unit/assertions'
20
- rescue LoadError
21
- # work around for Rubinius not having a std std-lib
22
- require 'rubysl-test-unit' if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
23
- require 'test/unit/assertions'
24
- end
25
- # Constant aliased to either Minitest or TestUnit, depending on what is
26
- # loaded.
27
- Assertions = Test::Unit::Assertions
25
+ require 'minitest'
28
26
  end
27
+ require 'minitest/assertions'
28
+ # Constant aliased to either Minitest or TestUnit, depending on what is
29
+ # loaded.
30
+ Assertions = Minitest::Assertions
29
31
 
30
32
  # @private
31
33
  class AssertionDelegator < Module
@@ -48,6 +50,7 @@ module RSpec
48
50
  assertion_modules.each do |mod|
49
51
  mod.public_instance_methods.each do |method|
50
52
  next if method == :method_missing || method == "method_missing"
53
+
51
54
  define_method(method.to_sym) do |*args, &block|
52
55
  assertion_instance.send(method.to_sym, *args, &block)
53
56
  end
@@ -89,13 +92,10 @@ module RSpec
89
92
 
90
93
  # @private
91
94
  module MinitestCounters
95
+ attr_writer :assertions
92
96
  def assertions
93
97
  @assertions ||= 0
94
98
  end
95
-
96
- def assertions=(assertions)
97
- @assertions = assertions
98
- end
99
99
  end
100
100
 
101
101
  # @private
@@ -105,7 +105,7 @@ module RSpec
105
105
  module ClassMethods
106
106
  # Wraps `setup` calls from within Rails' testing framework in `before`
107
107
  # hooks.
108
- def setup(*methods)
108
+ def setup(*methods, &block)
109
109
  methods.each do |method|
110
110
  if method.to_s =~ /^setup_(with_controller|fixtures|controller_request_and_response)$/
111
111
  prepend_before { __send__ method }
@@ -113,18 +113,21 @@ module RSpec
113
113
  before { __send__ method }
114
114
  end
115
115
  end
116
+ before(&block) if block
116
117
  end
117
118
 
118
119
  # @api private
119
120
  #
120
121
  # Wraps `teardown` calls from within Rails' testing framework in
121
122
  # `after` hooks.
122
- def teardown(*methods)
123
+ def teardown(*methods, &block)
123
124
  methods.each { |method| after { __send__ method } }
125
+ after(&block) if block
124
126
  end
125
127
  end
126
128
 
127
- def initialize
129
+ def initialize(*args)
130
+ super
128
131
  @example = nil
129
132
  end
130
133
 
@@ -143,8 +146,11 @@ module RSpec
143
146
  # examples without exposing non-assertion methods in Test::Unit or
144
147
  # Minitest.
145
148
  def assertion_method_names
146
- ::RSpec::Rails::Assertions.public_instance_methods.select{|m| m.to_s =~ /^(assert|flunk|refute)/} +
147
- [:build_message]
149
+ ::RSpec::Rails::Assertions
150
+ .public_instance_methods
151
+ .select do |m|
152
+ m.to_s =~ /^(assert|flunk|refute)/
153
+ end
148
154
  end
149
155
 
150
156
  def define_assertion_delegators
@@ -175,5 +181,16 @@ module RSpec
175
181
  #
176
182
  # @private
177
183
  TestUnitAssertionAdapter = MinitestAssertionAdapter
184
+
185
+ # @private
186
+ module TaggedLoggingAdapter
187
+ private
188
+ # Vendored from activesupport/lib/active_support/testing/tagged_logging.rb
189
+ # This implements the tagged_logger method where it is expected, but
190
+ # doesn't call `name` or set it up like Rails does.
191
+ def tagged_logger
192
+ @tagged_logger ||= (defined?(Rails.logger) && Rails.logger)
193
+ end
194
+ end
178
195
  end
179
196
  end
@@ -1,5 +1,5 @@
1
+ # rubocop: disable Metrics/ModuleLength
1
2
  module RSpec
2
-
3
3
  module Rails
4
4
  # Fake class to document RSpec Rails configuration options. In practice,
5
5
  # these are dynamically added to the normal RSpec configuration object.
@@ -26,42 +26,72 @@ module RSpec
26
26
  #
27
27
  # @api private
28
28
  DIRECTORY_MAPPINGS = {
29
- :controller => %w[spec controllers],
30
- :helper => %w[spec helpers],
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]
29
+ channel: %w[spec channels],
30
+ controller: %w[spec controllers],
31
+ generator: %w[spec generator],
32
+ helper: %w[spec helpers],
33
+ job: %w[spec jobs],
34
+ mailer: %w[spec mailers],
35
+ model: %w[spec models],
36
+ request: %w[spec (requests|integration|api)],
37
+ routing: %w[spec routing],
38
+ view: %w[spec views],
39
+ feature: %w[spec features],
40
+ system: %w[spec system],
41
+ mailbox: %w[spec mailboxes]
37
42
  }
38
43
 
44
+ # Sets up the different example group modules for the different spec types
45
+ #
46
+ # @api private
47
+ def self.add_test_type_configurations(config)
48
+ config.include RSpec::Rails::ControllerExampleGroup, type: :controller
49
+ config.include RSpec::Rails::HelperExampleGroup, type: :helper
50
+ config.include RSpec::Rails::ModelExampleGroup, type: :model
51
+ config.include RSpec::Rails::RequestExampleGroup, type: :request
52
+ config.include RSpec::Rails::RoutingExampleGroup, type: :routing
53
+ config.include RSpec::Rails::ViewExampleGroup, type: :view
54
+ config.include RSpec::Rails::FeatureExampleGroup, type: :feature
55
+ config.include RSpec::Rails::Matchers
56
+ config.include RSpec::Rails::SystemExampleGroup, type: :system
57
+ end
58
+
39
59
  # @private
40
- def self.initialize_configuration(config)
60
+ def self.initialize_configuration(config) # rubocop:disable Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/AbcSize,Metrics/PerceivedComplexity
41
61
  config.backtrace_exclusion_patterns << /vendor\//
42
- config.backtrace_exclusion_patterns << /lib\/rspec\/rails/
43
-
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
-
52
- if defined?(ActionMailer)
53
- config.include RSpec::Rails::MailerExampleGroup, :type => :mailer
54
- end
62
+ config.backtrace_exclusion_patterns << %r{lib/rspec/rails}
55
63
 
56
64
  # controller settings
57
- config.add_setting :infer_base_class_for_anonymous_controllers, :default => true
65
+ config.add_setting :infer_base_class_for_anonymous_controllers, default: true
58
66
 
59
67
  # fixture support
60
- config.include RSpec::Rails::FixtureSupport
61
- config.add_setting :use_transactional_fixtures, :alias_with => :use_transactional_examples
68
+ config.add_setting :use_active_record, default: true
69
+ config.add_setting :use_transactional_fixtures, alias_with: :use_transactional_examples
62
70
  config.add_setting :use_instantiated_fixtures
63
71
  config.add_setting :global_fixtures
64
- config.add_setting :fixture_path
72
+
73
+ if ::Rails::VERSION::STRING < "7.1.0"
74
+ config.add_setting :fixture_path
75
+ else
76
+ config.add_setting :fixture_paths
77
+ end
78
+
79
+ config.include RSpec::Rails::FixtureSupport, :use_fixtures
80
+
81
+ # We'll need to create a deprecated module in order to properly report to
82
+ # gems / projects which are relying on this being loaded globally.
83
+ #
84
+ # See rspec/rspec-rails#1355 for history
85
+ #
86
+ # @deprecated Include `RSpec::Rails::RailsExampleGroup` or
87
+ # `RSpec::Rails::FixtureSupport` directly instead
88
+ config.include RSpec::Rails::FixtureSupport
89
+
90
+ config.add_setting :file_fixture_path, default: 'spec/fixtures/files'
91
+ config.include RSpec::Rails::FileFixtureSupport
92
+
93
+ # Add support for fixture_path on fixture_file_upload
94
+ config.include RSpec::Rails::FixtureFileUploadSupport
65
95
 
66
96
  # This allows us to expose `render_views` as a config option even though it
67
97
  # breaks the convention of other options by using `render_views` as a
@@ -69,30 +99,124 @@ module RSpec
69
99
  # as a getter. This makes it easier for rspec-rails users because we use
70
100
  # `render_views` directly in example groups, so this aligns the two APIs,
71
101
  # but requires this workaround:
72
- config.add_setting :rendering_views, :default => false
102
+ config.add_setting :rendering_views, default: false
103
+
104
+ config.instance_exec do
105
+ def render_views=(val)
106
+ self.rendering_views = val
107
+ end
108
+
109
+ def render_views
110
+ self.rendering_views = true
111
+ end
112
+
113
+ def render_views?
114
+ rendering_views?
115
+ end
116
+
117
+ undef :rendering_views? if respond_to?(:rendering_views?)
118
+ def rendering_views?
119
+ !!rendering_views
120
+ end
73
121
 
74
- def config.render_views=(val)
75
- self.rendering_views = val
122
+ # Define boolean predicates rather than relying on rspec-core due
123
+ # to the bug fix in rspec/rspec-core#2736, note some of these
124
+ # predicates are a bit nonsensical, but they exist for backwards
125
+ # compatibility, we can tidy these up in `rspec-rails` 5.
126
+ undef :fixture_path? if respond_to?(:fixture_path?)
127
+ def fixture_path?
128
+ !!fixture_path
129
+ end
130
+
131
+ undef :global_fixtures? if respond_to?(:global_fixtures?)
132
+ def global_fixtures?
133
+ !!global_fixtures
134
+ end
135
+
136
+ undef :infer_base_class_for_anonymous_controllers? if respond_to?(:infer_base_class_for_anonymous_controllers?)
137
+ def infer_base_class_for_anonymous_controllers?
138
+ !!infer_base_class_for_anonymous_controllers
139
+ end
140
+
141
+ undef :use_instantiated_fixtures? if respond_to?(:use_instantiated_fixtures?)
142
+ def use_instantiated_fixtures?
143
+ !!use_instantiated_fixtures
144
+ end
145
+
146
+ undef :use_transactional_fixtures? if respond_to?(:use_transactional_fixtures?)
147
+ def use_transactional_fixtures?
148
+ !!use_transactional_fixtures
149
+ end
150
+
151
+ def infer_spec_type_from_file_location!
152
+ DIRECTORY_MAPPINGS.each do |type, dir_parts|
153
+ escaped_path = Regexp.compile(dir_parts.join('[\\\/]') + '[\\\/]')
154
+ define_derived_metadata(file_path: escaped_path) do |metadata|
155
+ metadata[:type] ||= type
156
+ end
157
+ end
158
+ end
159
+
160
+ # Adds exclusion filters for gems included with Rails
161
+ def filter_rails_from_backtrace!
162
+ filter_gems_from_backtrace "actionmailer", "actionpack", "actionview"
163
+ filter_gems_from_backtrace "activemodel", "activerecord",
164
+ "activesupport", "activejob"
165
+ end
166
+
167
+ # @deprecated TestFixtures#fixture_path is deprecated and will be removed in Rails 7.2
168
+ if ::Rails::VERSION::STRING >= "7.1.0"
169
+ def fixture_path
170
+ RSpec.deprecate(
171
+ "config.fixture_path",
172
+ replacement: "config.fixture_paths",
173
+ message: "Rails 7.1 has deprecated the singular fixture_path in favour of an array." \
174
+ "You should migrate to plural:"
175
+ )
176
+ fixture_paths&.first
177
+ end
178
+
179
+ def fixture_path=(path)
180
+ RSpec.deprecate(
181
+ "config.fixture_path = #{path.inspect}",
182
+ replacement: "config.fixture_paths = [#{path.inspect}]",
183
+ message: "Rails 7.1 has deprecated the singular fixture_path in favour of an array." \
184
+ "You should migrate to plural:"
185
+ )
186
+ self.fixture_paths = Array(path)
187
+ end
188
+ end
189
+ end
190
+
191
+ add_test_type_configurations(config)
192
+
193
+ if defined?(::Rails::Controller::Testing)
194
+ [:controller, :view, :request].each do |type|
195
+ config.include ::Rails::Controller::Testing::TestProcess, type: type
196
+ config.include ::Rails::Controller::Testing::TemplateAssertions, type: type
197
+ config.include ::Rails::Controller::Testing::Integration, type: type
198
+ end
76
199
  end
77
200
 
78
- def config.render_views
79
- self.rendering_views = true
201
+ if RSpec::Rails::FeatureCheck.has_action_mailer?
202
+ config.include RSpec::Rails::MailerExampleGroup, type: :mailer
203
+ config.after { ActionMailer::Base.deliveries.clear }
80
204
  end
81
205
 
82
- def config.render_views?
83
- rendering_views
206
+ if RSpec::Rails::FeatureCheck.has_active_job?
207
+ config.include RSpec::Rails::JobExampleGroup, type: :job
84
208
  end
85
209
 
86
- def config.infer_spec_type_from_file_location!
87
- DIRECTORY_MAPPINGS.each do |type, dir_parts|
88
- escaped_path = Regexp.compile(dir_parts.join('[\\\/]') + '[\\\/]')
89
- define_derived_metadata(:file_path => escaped_path) do |metadata|
90
- metadata[:type] ||= type
91
- end
92
- end
210
+ if RSpec::Rails::FeatureCheck.has_action_cable_testing?
211
+ config.include RSpec::Rails::ChannelExampleGroup, type: :channel
212
+ end
213
+
214
+ if RSpec::Rails::FeatureCheck.has_action_mailbox?
215
+ config.include RSpec::Rails::MailboxExampleGroup, type: :mailbox
93
216
  end
94
217
  end
95
218
 
96
219
  initialize_configuration RSpec.configuration
97
220
  end
98
221
  end
222
+ # rubocop: enable Metrics/ModuleLength
@@ -0,0 +1,93 @@
1
+ require "rspec/rails/matchers/action_cable/have_streams"
2
+
3
+ module RSpec
4
+ module Rails
5
+ # @api public
6
+ # Container module for channel spec functionality. It is only available if
7
+ # ActionCable has been loaded before it.
8
+ module ChannelExampleGroup
9
+ # @private
10
+ module ClassMethods
11
+ # These blank modules are only necessary for YARD processing. It doesn't
12
+ # handle the conditional check below very well and reports undocumented objects.
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ if RSpec::Rails::FeatureCheck.has_action_cable_testing?
19
+ module RSpec
20
+ module Rails
21
+ # @api public
22
+ # Container module for channel spec functionality.
23
+ module ChannelExampleGroup
24
+ extend ActiveSupport::Concern
25
+ include RSpec::Rails::RailsExampleGroup
26
+ include ActionCable::Connection::TestCase::Behavior
27
+ include ActionCable::Channel::TestCase::Behavior
28
+
29
+ # Class-level DSL for channel specs.
30
+ module ClassMethods
31
+ # @private
32
+ def channel_class
33
+ (_channel_class || described_class).tap do |klass|
34
+ next if klass <= ::ActionCable::Channel::Base
35
+
36
+ raise "Described class is not a channel class.\n" \
37
+ "Specify the channel class in the `describe` statement " \
38
+ "or set it manually using `tests MyChannelClass`"
39
+ end
40
+ end
41
+
42
+ # @private
43
+ def connection_class
44
+ (_connection_class || described_class).tap do |klass|
45
+ next if klass <= ::ActionCable::Connection::Base
46
+
47
+ raise "Described class is not a connection class.\n" \
48
+ "Specify the connection class in the `describe` statement " \
49
+ "or set it manually using `tests MyConnectionClass`"
50
+ end
51
+ end
52
+ end
53
+
54
+ # Checks that the connection attempt has been rejected.
55
+ #
56
+ # @example
57
+ # expect { connect }.to have_rejected_connection
58
+ def have_rejected_connection
59
+ raise_error(::ActionCable::Connection::Authorization::UnauthorizedError)
60
+ end
61
+
62
+ # Checks that the subscription is subscribed to at least one stream.
63
+ #
64
+ # @example
65
+ # expect(subscription).to have_streams
66
+ def have_streams
67
+ check_subscribed!
68
+
69
+ RSpec::Rails::Matchers::ActionCable::HaveStream.new
70
+ end
71
+
72
+ # Checks that the channel has been subscribed to the given stream
73
+ #
74
+ # @example
75
+ # expect(subscription).to have_stream_from("chat_1")
76
+ def have_stream_from(stream)
77
+ check_subscribed!
78
+
79
+ RSpec::Rails::Matchers::ActionCable::HaveStream.new(stream)
80
+ end
81
+
82
+ # Checks that the channel has been subscribed to a stream for the given model
83
+ #
84
+ # @example
85
+ # expect(subscription).to have_stream_for(user)
86
+ def have_stream_for(object)
87
+ check_subscribed!
88
+ RSpec::Rails::Matchers::ActionCable::HaveStream.new(broadcasting_for(object))
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end