rspec-rails 4.0.0.beta2 → 4.0.0.beta3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|