rspec-rails 4.0.0.beta2 → 4.0.0.beta3
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/Changelog.md +105 -83
- data/README.md +1 -1
- data/lib/generators/rspec/channel/channel_generator.rb +12 -0
- data/lib/generators/rspec/channel/templates/channel_spec.rb.erb +7 -0
- data/lib/generators/rspec/controller/controller_generator.rb +11 -2
- data/lib/generators/rspec/controller/templates/routing_spec.rb +13 -0
- data/lib/generators/rspec/mailbox/mailbox_generator.rb +14 -0
- data/lib/generators/rspec/mailbox/templates/mailbox_spec.rb.erb +7 -0
- data/lib/generators/rspec/model/templates/fixtures.yml +1 -1
- data/lib/rspec/rails/configuration.rb +15 -5
- data/lib/rspec/rails/example.rb +2 -0
- data/lib/rspec/rails/example/channel_example_group.rb +93 -0
- data/lib/rspec/rails/example/feature_example_group.rb +1 -1
- data/lib/rspec/rails/example/mailbox_example_group.rb +80 -0
- data/lib/rspec/rails/example/mailer_example_group.rb +1 -1
- data/lib/rspec/rails/example/system_example_group.rb +14 -2
- data/lib/rspec/rails/example/view_example_group.rb +29 -8
- data/lib/rspec/rails/feature_check.rb +16 -0
- data/lib/rspec/rails/matchers.rb +10 -0
- data/lib/rspec/rails/matchers/action_cable.rb +65 -0
- data/lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb +170 -0
- data/lib/rspec/rails/matchers/action_cable/have_streams.rb +58 -0
- data/lib/rspec/rails/matchers/action_mailbox.rb +64 -0
- data/lib/rspec/rails/matchers/active_job.rb +16 -5
- data/lib/rspec/rails/matchers/have_enqueued_mail.rb +44 -22
- data/lib/rspec/rails/matchers/routing_matchers.rb +1 -1
- data/lib/rspec/rails/version.rb +1 -1
- metadata +15 -4
- metadata.gz.sig +0 -0
data/README.md
CHANGED
@@ -12,7 +12,7 @@ Use **[`rspec-rails` 1.x][]** for Rails 2.x.
|
|
12
12
|
|
13
13
|
[Build Status]: https://secure.travis-ci.org/rspec/rspec-rails.svg?branch=master
|
14
14
|
[travis-ci]: https://travis-ci.org/rspec/rspec-rails
|
15
|
-
[Code Climate]: https://
|
15
|
+
[Code Climate]: https://codeclimate.com/github/rspec/rspec-rails.svg
|
16
16
|
[code-climate]: https://codeclimate.com/github/rspec/rspec-rails
|
17
17
|
[Gem Version]: https://badge.fury.io/rb/rspec-rails.svg
|
18
18
|
[gem-version]: https://badge.fury.io/rb/rspec-rails
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'generators/rspec'
|
2
|
+
|
3
|
+
module Rspec
|
4
|
+
module Generators
|
5
|
+
# @private
|
6
|
+
class ChannelGenerator < Base
|
7
|
+
def create_channel_spec
|
8
|
+
template 'channel_spec.rb.erb', File.join('spec/channels', class_path, "#{file_name}_channel_spec.rb")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -7,8 +7,9 @@ module Rspec
|
|
7
7
|
argument :actions, :type => :array, :default => [], :banner => "action action"
|
8
8
|
|
9
9
|
class_option :template_engine, :desc => "Template engine to generate view files"
|
10
|
-
class_option :controller_specs, :type => :boolean, :default => true
|
11
|
-
class_option :view_specs, :type => :boolean, :default => true
|
10
|
+
class_option :controller_specs, :type => :boolean, :default => true, :desc => "Generate controller specs"
|
11
|
+
class_option :view_specs, :type => :boolean, :default => true, :desc => "Generate view specs"
|
12
|
+
class_option :routing_specs, :type => :boolean, :default => false, :desc => "Generate routing specs"
|
12
13
|
|
13
14
|
def generate_controller_spec
|
14
15
|
return unless options[:controller_specs]
|
@@ -29,6 +30,14 @@ module Rspec
|
|
29
30
|
File.join("spec", "views", file_path, "#{@action}.html.#{options[:template_engine]}_spec.rb")
|
30
31
|
end
|
31
32
|
end
|
33
|
+
|
34
|
+
def generate_routing_spec
|
35
|
+
return if actions.empty?
|
36
|
+
return unless options[:routing_specs]
|
37
|
+
|
38
|
+
template 'routing_spec.rb',
|
39
|
+
File.join('spec/routing', class_path, "#{file_name}_routing_spec.rb")
|
40
|
+
end
|
32
41
|
end
|
33
42
|
end
|
34
43
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
<% module_namespacing do -%>
|
4
|
+
RSpec.describe '<%= class_name %>Controller', <%= type_metatag(:routing) %> do
|
5
|
+
describe 'routing' do
|
6
|
+
<% for action in actions -%>
|
7
|
+
it 'routes to #<%= action %>' do
|
8
|
+
expect(:get => "/<%= class_name.underscore %>/<%= action %>").to route_to("<%= class_name.underscore %>#<%= action %>")
|
9
|
+
end
|
10
|
+
<% end -%>
|
11
|
+
end
|
12
|
+
end
|
13
|
+
<% end -%>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'generators/rspec'
|
2
|
+
|
3
|
+
module Rspec
|
4
|
+
module Generators
|
5
|
+
# @private
|
6
|
+
class MailboxGenerator < Base
|
7
|
+
def create_mailbox_spec
|
8
|
+
template('mailbox_spec.rb.erb',
|
9
|
+
File.join('spec/mailboxes', class_path, "#{file_name}_mailbox_spec.rb")
|
10
|
+
)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -25,6 +25,7 @@ module RSpec
|
|
25
25
|
#
|
26
26
|
# @api private
|
27
27
|
DIRECTORY_MAPPINGS = {
|
28
|
+
:channel => %w[spec channels],
|
28
29
|
:controller => %w[spec controllers],
|
29
30
|
:helper => %w[spec helpers],
|
30
31
|
:job => %w[spec jobs],
|
@@ -34,7 +35,8 @@ module RSpec
|
|
34
35
|
:routing => %w[spec routing],
|
35
36
|
:view => %w[spec views],
|
36
37
|
:feature => %w[spec features],
|
37
|
-
:system => %w[spec system]
|
38
|
+
:system => %w[spec system],
|
39
|
+
:mailbox => %w[spec mailboxes]
|
38
40
|
}
|
39
41
|
|
40
42
|
# Sets up the different example group modules for the different spec types
|
@@ -53,7 +55,7 @@ module RSpec
|
|
53
55
|
end
|
54
56
|
|
55
57
|
# @private
|
56
|
-
# rubocop:disable
|
58
|
+
# rubocop:disable Metrics/MethodLength
|
57
59
|
def self.initialize_configuration(config)
|
58
60
|
config.backtrace_exclusion_patterns << /vendor\//
|
59
61
|
config.backtrace_exclusion_patterns << %r{lib/rspec/rails}
|
@@ -133,15 +135,23 @@ module RSpec
|
|
133
135
|
end
|
134
136
|
end
|
135
137
|
|
136
|
-
if
|
138
|
+
if RSpec::Rails::FeatureCheck.has_action_mailer?
|
137
139
|
config.include RSpec::Rails::MailerExampleGroup, :type => :mailer
|
138
140
|
end
|
139
141
|
|
140
|
-
if
|
142
|
+
if RSpec::Rails::FeatureCheck.has_active_job?
|
141
143
|
config.include RSpec::Rails::JobExampleGroup, :type => :job
|
142
144
|
end
|
145
|
+
|
146
|
+
if RSpec::Rails::FeatureCheck.has_action_cable_testing?
|
147
|
+
config.include RSpec::Rails::ChannelExampleGroup, :type => :channel
|
148
|
+
end
|
149
|
+
|
150
|
+
if RSpec::Rails::FeatureCheck.has_action_mailbox?
|
151
|
+
config.include RSpec::Rails::MailboxExampleGroup, :type => :mailbox
|
152
|
+
end
|
143
153
|
end
|
144
|
-
# rubocop:enable
|
154
|
+
# rubocop:enable Metrics/MethodLength
|
145
155
|
|
146
156
|
initialize_configuration RSpec.configuration
|
147
157
|
end
|
data/lib/rspec/rails/example.rb
CHANGED
@@ -9,3 +9,5 @@ require 'rspec/rails/example/model_example_group'
|
|
9
9
|
require 'rspec/rails/example/job_example_group'
|
10
10
|
require 'rspec/rails/example/feature_example_group'
|
11
11
|
require 'rspec/rails/example/system_example_group'
|
12
|
+
require 'rspec/rails/example/channel_example_group'
|
13
|
+
require 'rspec/rails/example/mailbox_example_group'
|
@@ -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
|
@@ -40,7 +40,7 @@ unless RSpec.respond_to?(:feature)
|
|
40
40
|
:capybara_feature => true,
|
41
41
|
:type => :feature,
|
42
42
|
:skip => <<-EOT.squish
|
43
|
-
Feature specs require the Capybara (
|
43
|
+
Feature specs require the Capybara (https://github.com/jnicklas/capybara)
|
44
44
|
gem, version 2.2.0 or later. We recommend version 2.4.0 or later to avoid
|
45
45
|
some deprecation warnings and have support for
|
46
46
|
`config.expose_dsl_globally = false`.
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Rails
|
3
|
+
# @api public
|
4
|
+
# Container module for mailbox spec functionality.
|
5
|
+
module MailboxExampleGroup
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
if RSpec::Rails::FeatureCheck.has_action_mailbox?
|
9
|
+
require 'action_mailbox/test_helper'
|
10
|
+
extend ::ActionMailbox::TestHelper
|
11
|
+
|
12
|
+
# @private
|
13
|
+
def self.create_inbound_email(arg)
|
14
|
+
case arg
|
15
|
+
when Hash
|
16
|
+
create_inbound_email_from_mail(arg)
|
17
|
+
else
|
18
|
+
create_inbound_email_from_source(arg.to_s)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
else
|
22
|
+
def self.create_inbound_email(_arg)
|
23
|
+
raise "Could not load ActionMailer::TestHelper"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class_methods do
|
28
|
+
# @private
|
29
|
+
def mailbox_class
|
30
|
+
described_class
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
included do
|
35
|
+
subject { described_class }
|
36
|
+
end
|
37
|
+
|
38
|
+
# @api public
|
39
|
+
# Passes if the inbound email was delivered
|
40
|
+
#
|
41
|
+
# @example
|
42
|
+
# inbound_email = process(args)
|
43
|
+
# expect(inbound_email).to have_been_delivered
|
44
|
+
def have_been_delivered
|
45
|
+
satisfy('have been delivered', &:delivered?)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @api public
|
49
|
+
# Passes if the inbound email bounced during processing
|
50
|
+
#
|
51
|
+
# @example
|
52
|
+
# inbound_email = process(args)
|
53
|
+
# expect(inbound_email).to have_bounced
|
54
|
+
def have_bounced
|
55
|
+
satisfy('have bounced', &:bounced?)
|
56
|
+
end
|
57
|
+
|
58
|
+
# @api public
|
59
|
+
# Passes if the inbound email failed to process
|
60
|
+
#
|
61
|
+
# @example
|
62
|
+
# inbound_email = process(args)
|
63
|
+
# expect(inbound_email).to have_failed
|
64
|
+
def have_failed
|
65
|
+
satisfy('have failed', &:failed?)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Process an inbound email message directly, bypassing routing.
|
69
|
+
#
|
70
|
+
# @param message [Hash, Mail::Message] a mail message or hash of
|
71
|
+
# attributes used to build one
|
72
|
+
# @return [ActionMaibox::InboundMessage]
|
73
|
+
def process(message)
|
74
|
+
MailboxExampleGroup.create_inbound_email(message).tap do |mail|
|
75
|
+
self.class.mailbox_class.receive(mail)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -22,7 +22,7 @@ if defined?(ActionMailer)
|
|
22
22
|
included do
|
23
23
|
include ::Rails.application.routes.url_helpers
|
24
24
|
options = ::Rails.configuration.action_mailer.default_url_options
|
25
|
-
options
|
25
|
+
options&.each { |key, value| default_url_options[key] = value }
|
26
26
|
end
|
27
27
|
|
28
28
|
# Class-level DSL for mailer specs.
|
@@ -15,7 +15,11 @@ module RSpec
|
|
15
15
|
CHARS_TO_TRANSLATE = ['/', '.', ':', ',', "'", '"', " "].freeze
|
16
16
|
|
17
17
|
# @private
|
18
|
-
module
|
18
|
+
module BlowAwayTeardownHooks
|
19
|
+
# @private
|
20
|
+
def before_teardown
|
21
|
+
end
|
22
|
+
|
19
23
|
# @private
|
20
24
|
def after_teardown
|
21
25
|
end
|
@@ -59,13 +63,18 @@ module RSpec
|
|
59
63
|
""".gsub(/\s+/, ' ').strip
|
60
64
|
end
|
61
65
|
|
66
|
+
if ::Rails::VERSION::STRING >= '6.0'
|
67
|
+
original_before_teardown =
|
68
|
+
::ActionDispatch::SystemTesting::TestHelpers::SetupAndTeardown.instance_method(:before_teardown)
|
69
|
+
end
|
70
|
+
|
62
71
|
original_after_teardown =
|
63
72
|
::ActionDispatch::SystemTesting::TestHelpers::SetupAndTeardown.instance_method(:after_teardown)
|
64
73
|
|
65
74
|
other.include ActionDispatch::IntegrationTest::Behavior
|
66
75
|
other.include ::ActionDispatch::SystemTesting::TestHelpers::SetupAndTeardown
|
67
76
|
other.include ::ActionDispatch::SystemTesting::TestHelpers::ScreenshotHelper
|
68
|
-
other.include
|
77
|
+
other.include BlowAwayTeardownHooks
|
69
78
|
|
70
79
|
attr_reader :driver
|
71
80
|
|
@@ -93,6 +102,9 @@ module RSpec
|
|
93
102
|
orig_stdout = $stdout
|
94
103
|
$stdout = StringIO.new
|
95
104
|
begin
|
105
|
+
if ::Rails::VERSION::STRING >= '6.0'
|
106
|
+
original_before_teardown.bind(self).call
|
107
|
+
end
|
96
108
|
original_after_teardown.bind(self).call
|
97
109
|
ensure
|
98
110
|
myio = $stdout
|
@@ -129,14 +129,35 @@ module RSpec
|
|
129
129
|
|
130
130
|
def _default_render_options
|
131
131
|
if ::Rails::VERSION::STRING >= '3.2'
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
132
|
+
formats = if ActionView::Template::Types.respond_to?(:symbols)
|
133
|
+
ActionView::Template::Types.symbols
|
134
|
+
else
|
135
|
+
[:html, :text, :js, :css, :xml, :json].map(&:to_s)
|
136
|
+
end.map { |x| Regexp.escape(x) }.join("|")
|
137
|
+
|
138
|
+
handlers = ActionView::Template::Handlers.extensions.map { |x| Regexp.escape(x) }.join("|")
|
139
|
+
locales = "[a-z]{2}(?:-[A-Z]{2})?"
|
140
|
+
variants = "[^.]*"
|
141
|
+
path_regex = %r{
|
142
|
+
\A
|
143
|
+
(?<template>.*?)
|
144
|
+
(?:\.(?<locale>#{locales}))??
|
145
|
+
(?:\.(?<format>#{formats}))??
|
146
|
+
(?:\+(?<variant>#{variants}))??
|
147
|
+
(?:\.(?<handler>#{handlers}))?
|
148
|
+
\z
|
149
|
+
}x
|
150
|
+
|
151
|
+
# This regex should always find a match.
|
152
|
+
# Worst case, everything will be nil, and :template will just be
|
153
|
+
# the original string.
|
154
|
+
match = path_regex.match(_default_file_to_render)
|
155
|
+
|
156
|
+
render_options = { :template => match[:template] }
|
157
|
+
render_options[:handlers] = [match[:handler]] if match[:handler]
|
158
|
+
render_options[:formats] = [match[:format].to_sym] if match[:format]
|
159
|
+
render_options[:locales] = [match[:locale]] if match[:locale]
|
160
|
+
render_options[:variants] = [match[:variant]] if match[:variant]
|
140
161
|
|
141
162
|
render_options
|
142
163
|
else
|