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.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data/.document +1 -1
- data/.yardopts +3 -1
- data/Capybara.md +6 -55
- data/Changelog.md +805 -47
- data/{License.txt → LICENSE.md} +5 -3
- data/README.md +278 -444
- data/lib/generators/rspec/channel/channel_generator.rb +12 -0
- data/lib/generators/rspec/{observer/templates/observer_spec.rb → channel/templates/channel_spec.rb.erb} +1 -1
- data/lib/generators/rspec/controller/controller_generator.rb +24 -7
- data/lib/generators/rspec/controller/templates/controller_spec.rb +3 -3
- data/lib/generators/rspec/controller/templates/request_spec.rb +19 -0
- data/lib/generators/rspec/controller/templates/routing_spec.rb +13 -0
- data/lib/generators/rspec/controller/templates/view_spec.rb +1 -1
- data/lib/generators/rspec/feature/feature_generator.rb +15 -2
- data/lib/generators/rspec/feature/templates/feature_singular_spec.rb +5 -0
- data/lib/generators/rspec/feature/templates/feature_spec.rb +1 -1
- data/lib/generators/rspec/generator/generator_generator.rb +24 -0
- data/lib/generators/rspec/generator/templates/generator_spec.rb +5 -0
- data/lib/generators/rspec/helper/helper_generator.rb +2 -2
- data/lib/generators/rspec/helper/templates/helper_spec.rb +1 -1
- data/lib/generators/rspec/install/install_generator.rb +41 -7
- data/lib/generators/rspec/install/templates/spec/rails_helper.rb +63 -22
- data/lib/generators/rspec/job/job_generator.rb +13 -0
- data/lib/generators/rspec/job/templates/job_spec.rb.erb +7 -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/mailer/mailer_generator.rb +12 -3
- data/lib/generators/rspec/mailer/templates/mailer_spec.rb +2 -2
- data/lib/generators/rspec/mailer/templates/preview.rb +13 -0
- data/lib/generators/rspec/model/model_generator.rb +20 -6
- data/lib/generators/rspec/model/templates/fixtures.yml +1 -1
- data/lib/generators/rspec/model/templates/model_spec.rb +1 -1
- data/lib/generators/rspec/request/request_generator.rb +17 -0
- data/lib/generators/rspec/request/templates/request_spec.rb +10 -0
- data/lib/generators/rspec/scaffold/scaffold_generator.rb +90 -113
- data/lib/generators/rspec/scaffold/templates/api_controller_spec.rb +129 -0
- data/lib/generators/rspec/scaffold/templates/api_request_spec.rb +131 -0
- data/lib/generators/rspec/scaffold/templates/controller_spec.rb +46 -64
- data/lib/generators/rspec/scaffold/templates/edit_spec.rb +11 -7
- data/lib/generators/rspec/scaffold/templates/index_spec.rb +4 -3
- data/lib/generators/rspec/scaffold/templates/new_spec.rb +4 -4
- data/lib/generators/rspec/scaffold/templates/request_spec.rb +138 -0
- data/lib/generators/rspec/scaffold/templates/routing_spec.rb +18 -11
- data/lib/generators/rspec/scaffold/templates/show_spec.rb +3 -3
- data/lib/generators/rspec/system/system_generator.rb +24 -0
- data/lib/generators/rspec/system/templates/system_spec.rb +9 -0
- data/lib/generators/rspec/view/templates/view_spec.rb +1 -1
- data/lib/generators/rspec/view/view_generator.rb +4 -4
- data/lib/generators/rspec.rb +30 -11
- data/lib/rspec/rails/active_record.rb +25 -0
- data/lib/rspec/rails/adapters.rb +46 -29
- data/lib/rspec/rails/configuration.rb +165 -41
- data/lib/rspec/rails/example/channel_example_group.rb +93 -0
- data/lib/rspec/rails/example/controller_example_group.rb +185 -149
- data/lib/rspec/rails/example/feature_example_group.rb +43 -23
- data/lib/rspec/rails/example/helper_example_group.rb +28 -25
- data/lib/rspec/rails/example/job_example_group.rb +23 -0
- data/lib/rspec/rails/example/mailbox_example_group.rb +80 -0
- data/lib/rspec/rails/example/mailer_example_group.rb +27 -22
- data/lib/rspec/rails/example/model_example_group.rb +9 -6
- data/lib/rspec/rails/example/rails_example_group.rb +9 -2
- data/lib/rspec/rails/example/request_example_group.rb +21 -17
- data/lib/rspec/rails/example/routing_example_group.rb +47 -39
- data/lib/rspec/rails/example/system_example_group.rb +180 -0
- data/lib/rspec/rails/example/view_example_group.rb +179 -134
- data/lib/rspec/rails/example.rb +4 -0
- data/lib/rspec/rails/extensions/active_record/proxy.rb +5 -11
- data/lib/rspec/rails/feature_check.rb +51 -0
- data/lib/rspec/rails/file_fixture_support.rb +18 -0
- data/lib/rspec/rails/fixture_file_upload_support.rb +45 -0
- data/lib/rspec/rails/fixture_support.rb +70 -14
- data/lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb +180 -0
- data/lib/rspec/rails/matchers/action_cable/have_streams.rb +58 -0
- data/lib/rspec/rails/matchers/action_cable.rb +70 -0
- data/lib/rspec/rails/matchers/action_mailbox.rb +73 -0
- data/lib/rspec/rails/matchers/active_job.rb +526 -0
- data/lib/rspec/rails/matchers/base_matcher.rb +179 -0
- data/lib/rspec/rails/matchers/be_a_new.rb +70 -64
- data/lib/rspec/rails/matchers/be_new_record.rb +25 -20
- data/lib/rspec/rails/matchers/be_valid.rb +39 -34
- data/lib/rspec/rails/matchers/have_enqueued_mail.rb +259 -0
- data/lib/rspec/rails/matchers/have_http_status.rb +359 -333
- data/lib/rspec/rails/matchers/have_rendered.rb +55 -32
- data/lib/rspec/rails/matchers/redirect_to.rb +30 -27
- data/lib/rspec/rails/matchers/relation_match_array.rb +1 -1
- data/lib/rspec/rails/matchers/routing_matchers.rb +107 -101
- data/lib/rspec/rails/matchers/send_email.rb +122 -0
- data/lib/rspec/rails/matchers.rb +21 -12
- data/lib/rspec/rails/tasks/rspec.rake +9 -17
- data/lib/rspec/rails/vendor/capybara.rb +10 -11
- data/lib/rspec/rails/version.rb +1 -1
- data/lib/rspec/rails/view_assigns.rb +1 -20
- data/lib/rspec/rails/view_path_builder.rb +29 -0
- data/lib/rspec/rails/view_rendering.rb +89 -27
- data/lib/rspec/rails/view_spec_methods.rb +56 -0
- data/lib/rspec/rails.rb +9 -1
- data/lib/rspec-rails.rb +83 -3
- data.tar.gz.sig +0 -0
- metadata +108 -78
- metadata.gz.sig +3 -2
- data/lib/generators/rspec/integration/integration_generator.rb +0 -17
- data/lib/generators/rspec/integration/templates/request_spec.rb +0 -10
- data/lib/generators/rspec/observer/observer_generator.rb +0 -13
@@ -0,0 +1,180 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Rails
|
3
|
+
module Matchers
|
4
|
+
module ActionCable
|
5
|
+
# rubocop: disable Metrics/ClassLength
|
6
|
+
# @private
|
7
|
+
class HaveBroadcastedTo < RSpec::Matchers::BuiltIn::BaseMatcher
|
8
|
+
def initialize(target, channel:)
|
9
|
+
@target = target
|
10
|
+
@channel = channel
|
11
|
+
@block = proc { }
|
12
|
+
@data = nil
|
13
|
+
set_expected_number(:exactly, 1)
|
14
|
+
end
|
15
|
+
|
16
|
+
def with(data = nil, &block)
|
17
|
+
@data = data
|
18
|
+
@data = @data.with_indifferent_access if @data.is_a?(Hash)
|
19
|
+
@block = block if block
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def exactly(count)
|
24
|
+
set_expected_number(:exactly, count)
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def at_least(count)
|
29
|
+
set_expected_number(:at_least, count)
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def at_most(count)
|
34
|
+
set_expected_number(:at_most, count)
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def times
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
def once
|
43
|
+
exactly(:once)
|
44
|
+
end
|
45
|
+
|
46
|
+
def twice
|
47
|
+
exactly(:twice)
|
48
|
+
end
|
49
|
+
|
50
|
+
def thrice
|
51
|
+
exactly(:thrice)
|
52
|
+
end
|
53
|
+
|
54
|
+
def description
|
55
|
+
"have broadcasted #{base_description}"
|
56
|
+
end
|
57
|
+
|
58
|
+
def failure_message
|
59
|
+
"expected to broadcast #{base_message}".tap do |msg|
|
60
|
+
if @unmatching_msgs.any?
|
61
|
+
msg << "\nBroadcasted messages to #{stream}:"
|
62
|
+
@unmatching_msgs.each do |data|
|
63
|
+
msg << "\n #{data}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def failure_message_when_negated
|
70
|
+
"expected not to broadcast #{base_message}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def message_expectation_modifier
|
74
|
+
case @expectation_type
|
75
|
+
when :exactly then "exactly"
|
76
|
+
when :at_most then "at most"
|
77
|
+
when :at_least then "at least"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def supports_block_expectations?
|
82
|
+
true
|
83
|
+
end
|
84
|
+
|
85
|
+
def matches?(proc)
|
86
|
+
raise ArgumentError, "have_broadcasted_to and broadcast_to only support block expectations" unless Proc === proc
|
87
|
+
|
88
|
+
original_sent_messages_count = pubsub_adapter.broadcasts(stream).size
|
89
|
+
proc.call
|
90
|
+
in_block_messages = pubsub_adapter.broadcasts(stream).drop(original_sent_messages_count)
|
91
|
+
|
92
|
+
check(in_block_messages)
|
93
|
+
end
|
94
|
+
|
95
|
+
def from_channel(channel)
|
96
|
+
@channel = channel
|
97
|
+
self
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def stream
|
103
|
+
@stream ||= case @target
|
104
|
+
when String
|
105
|
+
@target
|
106
|
+
when Symbol
|
107
|
+
@target.to_s
|
108
|
+
else
|
109
|
+
check_channel_presence
|
110
|
+
@channel.broadcasting_for(@target)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def check(messages)
|
115
|
+
@matching_msgs, @unmatching_msgs = messages.partition do |msg|
|
116
|
+
decoded = ActiveSupport::JSON.decode(msg)
|
117
|
+
decoded = decoded.with_indifferent_access if decoded.is_a?(Hash)
|
118
|
+
|
119
|
+
if @data.nil? || values_match?(@data, decoded)
|
120
|
+
@block.call(decoded)
|
121
|
+
true
|
122
|
+
else
|
123
|
+
false
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
@matching_msgs_count = @matching_msgs.size
|
128
|
+
|
129
|
+
case @expectation_type
|
130
|
+
when :exactly then @expected_number == @matching_msgs_count
|
131
|
+
when :at_most then @expected_number >= @matching_msgs_count
|
132
|
+
when :at_least then @expected_number <= @matching_msgs_count
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def set_expected_number(relativity, count)
|
137
|
+
@expectation_type = relativity
|
138
|
+
@expected_number =
|
139
|
+
case count
|
140
|
+
when :once then 1
|
141
|
+
when :twice then 2
|
142
|
+
when :thrice then 3
|
143
|
+
else Integer(count)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def base_description
|
148
|
+
"#{message_expectation_modifier} #{@expected_number} messages to #{stream}".tap do |msg|
|
149
|
+
msg << " with #{data_description(@data)}" unless @data.nil?
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def base_message
|
154
|
+
"#{base_description}, but broadcast #{@matching_msgs_count}"
|
155
|
+
end
|
156
|
+
|
157
|
+
def data_description(data)
|
158
|
+
if data.is_a?(RSpec::Matchers::Composable)
|
159
|
+
data.description
|
160
|
+
else
|
161
|
+
data.inspect
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def pubsub_adapter
|
166
|
+
::ActionCable.server.pubsub
|
167
|
+
end
|
168
|
+
|
169
|
+
def check_channel_presence
|
170
|
+
return if @channel.present? && @channel.respond_to?(:channel_name)
|
171
|
+
|
172
|
+
error_msg = "Broadcasting channel can't be inferred. Please, specify it with `from_channel`"
|
173
|
+
raise ArgumentError, error_msg
|
174
|
+
end
|
175
|
+
end
|
176
|
+
# rubocop: enable Metrics/ClassLength
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Rails
|
3
|
+
module Matchers
|
4
|
+
module ActionCable
|
5
|
+
# @api private
|
6
|
+
# Provides the implementation for `have_stream`, `have_stream_for`, and `have_stream_from`.
|
7
|
+
# Not intended to be instantiated directly.
|
8
|
+
class HaveStream < RSpec::Matchers::BuiltIn::BaseMatcher
|
9
|
+
# @api private
|
10
|
+
# @return [String]
|
11
|
+
def failure_message
|
12
|
+
"expected to have #{base_message}"
|
13
|
+
end
|
14
|
+
|
15
|
+
# @api private
|
16
|
+
# @return [String]
|
17
|
+
def failure_message_when_negated
|
18
|
+
"expected not to have #{base_message}"
|
19
|
+
end
|
20
|
+
|
21
|
+
# @api private
|
22
|
+
# @return [Boolean]
|
23
|
+
def matches?(subscription)
|
24
|
+
raise(ArgumentError, "have_streams is used for negated expectations only") if no_expected?
|
25
|
+
|
26
|
+
match(subscription)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @api private
|
30
|
+
# @return [Boolean]
|
31
|
+
def does_not_match?(subscription)
|
32
|
+
!match(subscription)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def match(subscription)
|
38
|
+
case subscription
|
39
|
+
when ::ActionCable::Channel::Base
|
40
|
+
@actual = subscription.streams
|
41
|
+
no_expected? ? actual.any? : actual.any? { |i| expected === i }
|
42
|
+
else
|
43
|
+
raise ArgumentError, "have_stream, have_stream_from and have_stream_from support expectations on subscription only"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def base_message
|
48
|
+
no_expected? ? "any stream started" : "stream #{expected_formatted} started, but have #{actual_formatted}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def no_expected?
|
52
|
+
!defined?(@expected)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require "rspec/rails/matchers/action_cable/have_broadcasted_to"
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Rails
|
5
|
+
module Matchers
|
6
|
+
extend RSpec::Matchers::DSL
|
7
|
+
|
8
|
+
# Namespace for various implementations of ActionCable features
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
module ActionCable
|
12
|
+
end
|
13
|
+
|
14
|
+
# @api public
|
15
|
+
# Passes if a message has been sent to a stream/object inside a block.
|
16
|
+
# May chain `at_least`, `at_most` or `exactly` to specify a number of times.
|
17
|
+
# To specify channel from which message has been broadcasted to object use `from_channel`.
|
18
|
+
#
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# expect {
|
22
|
+
# ActionCable.server.broadcast "messages", text: 'Hi!'
|
23
|
+
# }.to have_broadcasted_to("messages")
|
24
|
+
#
|
25
|
+
# expect {
|
26
|
+
# SomeChannel.broadcast_to(user)
|
27
|
+
# }.to have_broadcasted_to(user).from_channel(SomeChannel)
|
28
|
+
#
|
29
|
+
# # Using alias
|
30
|
+
# expect {
|
31
|
+
# ActionCable.server.broadcast "messages", text: 'Hi!'
|
32
|
+
# }.to broadcast_to("messages")
|
33
|
+
#
|
34
|
+
# expect {
|
35
|
+
# ActionCable.server.broadcast "messages", text: 'Hi!'
|
36
|
+
# ActionCable.server.broadcast "all", text: 'Hi!'
|
37
|
+
# }.to have_broadcasted_to("messages").exactly(:once)
|
38
|
+
#
|
39
|
+
# expect {
|
40
|
+
# 3.times { ActionCable.server.broadcast "messages", text: 'Hi!' }
|
41
|
+
# }.to have_broadcasted_to("messages").at_least(2).times
|
42
|
+
#
|
43
|
+
# expect {
|
44
|
+
# ActionCable.server.broadcast "messages", text: 'Hi!'
|
45
|
+
# }.to have_broadcasted_to("messages").at_most(:twice)
|
46
|
+
#
|
47
|
+
# expect {
|
48
|
+
# ActionCable.server.broadcast "messages", text: 'Hi!'
|
49
|
+
# }.to have_broadcasted_to("messages").with(text: 'Hi!')
|
50
|
+
def have_broadcasted_to(target = nil)
|
51
|
+
check_action_cable_adapter
|
52
|
+
|
53
|
+
ActionCable::HaveBroadcastedTo.new(target, channel: described_class)
|
54
|
+
end
|
55
|
+
|
56
|
+
alias_matcher :broadcast_to, :have_broadcasted_to do |desc|
|
57
|
+
desc.gsub("have broadcasted", "broadcast")
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
# @private
|
63
|
+
def check_action_cable_adapter
|
64
|
+
return if ::ActionCable::SubscriptionAdapter::Test === ::ActionCable.server.pubsub
|
65
|
+
|
66
|
+
raise StandardError, "To use ActionCable matchers set `adapter: test` in your cable.yml"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Rails
|
3
|
+
module Matchers
|
4
|
+
# Namespace for various implementations of ActionMailbox features
|
5
|
+
#
|
6
|
+
# @api private
|
7
|
+
module ActionMailbox
|
8
|
+
# @private
|
9
|
+
class Base < RSpec::Rails::Matchers::BaseMatcher
|
10
|
+
private
|
11
|
+
|
12
|
+
def create_inbound_email(message)
|
13
|
+
RSpec::Rails::MailboxExampleGroup.create_inbound_email(message)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# @private
|
18
|
+
class ReceiveInboundEmail < Base
|
19
|
+
def initialize(message)
|
20
|
+
super()
|
21
|
+
|
22
|
+
@inbound_email = create_inbound_email(message)
|
23
|
+
end
|
24
|
+
|
25
|
+
if defined?(::ApplicationMailbox) && ::ApplicationMailbox.router.respond_to?(:mailbox_for)
|
26
|
+
def matches?(mailbox)
|
27
|
+
@mailbox = mailbox
|
28
|
+
@receiver = ApplicationMailbox.router.mailbox_for(inbound_email)
|
29
|
+
|
30
|
+
@receiver == @mailbox
|
31
|
+
end
|
32
|
+
else
|
33
|
+
def matches?(mailbox)
|
34
|
+
@mailbox = mailbox
|
35
|
+
@receiver = ApplicationMailbox.router.send(:match_to_mailbox, inbound_email)
|
36
|
+
|
37
|
+
@receiver == @mailbox
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def failure_message
|
42
|
+
"expected #{describe_inbound_email} to route to #{mailbox}".tap do |msg|
|
43
|
+
if receiver
|
44
|
+
msg << ", but routed to #{receiver} instead"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def failure_message_when_negated
|
50
|
+
"expected #{describe_inbound_email} not to route to #{mailbox}"
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
attr_reader :inbound_email, :mailbox, :receiver
|
56
|
+
|
57
|
+
def describe_inbound_email
|
58
|
+
"mail to #{inbound_email.mail.to.to_sentence}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# @api public
|
64
|
+
# Passes if the given inbound email would be routed to the subject inbox.
|
65
|
+
#
|
66
|
+
# @param message [Hash, Mail::Message] a mail message or hash of
|
67
|
+
# attributes used to build one
|
68
|
+
def receive_inbound_email(message)
|
69
|
+
ActionMailbox::ReceiveInboundEmail.new(message)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|