rubocop-rspec 1.13.0 → 1.14.0
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
- data/CHANGELOG.md +9 -0
- data/config/default.yml +20 -0
- data/lib/rubocop-rspec.rb +5 -0
- data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +80 -0
- data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +47 -0
- data/lib/rubocop/cop/rspec/iterated_expectation.rb +52 -0
- data/lib/rubocop/cop/rspec/leading_subject.rb +26 -3
- data/lib/rubocop/cop/rspec/overwriting_setup.rb +54 -0
- data/lib/rubocop/cop/rspec/scattered_let.rb +58 -0
- data/lib/rubocop/rspec/version.rb +1 -1
- data/spec/project/changelog_spec.rb +5 -12
- data/spec/rubocop/cop/rspec/empty_line_after_final_let_spec.rb +142 -0
- data/spec/rubocop/cop/rspec/empty_line_after_subject_spec.rb +77 -0
- data/spec/rubocop/cop/rspec/iterated_expectation_spec.rb +72 -0
- data/spec/rubocop/cop/rspec/leading_subject_spec.rb +57 -0
- data/spec/rubocop/cop/rspec/overwriting_setup_spec.rb +46 -0
- data/spec/rubocop/cop/rspec/scattered_let_spec.rb +26 -0
- metadata +18 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0d76ad6b5a03029a44d0df0b733fd13816be3ffd
|
4
|
+
data.tar.gz: 430a2169a27502c780f3ab10d9e0bae261a31f94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 54815c238a360be303b16144d9dcb3338770948de917b0a5a6f292dd25721b9d48c042edab0361f203b050be82cb18bcd2dcd1250b4ee111f9e3f3d15dd1ed1d
|
7
|
+
data.tar.gz: 1d39b6af29a27b1cda1ae5f223e74dfba11f494381920ae821941546322d3688cd30e3666a245535c6bc8998c2b7bb13c4aafc378ebc7b3469ee434b60741db3
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
## Master (Unreleased)
|
4
4
|
|
5
|
+
## 1.14.0 (2017-03-24)
|
6
|
+
|
7
|
+
* Add `RSpec/OverwritingSetup` cop. ([@Darhazer][])
|
8
|
+
* Add autocorrect support for `RSpec/LeadingSubject` cop. ([@Darhazer][])
|
9
|
+
* Add `RSpec/ScatteredLet` cop. ([@Darhazer][])
|
10
|
+
* Add `RSpec/IteratedExpectation` cop. ([@Darhazer][])
|
11
|
+
* Add `RSpec/EmptyLineAfterSubject` cop. ([@Darhazer][])
|
12
|
+
* Add `RSpec/EmptyLineAfterFinalLet` cop. ([@Darhazer][])
|
13
|
+
|
5
14
|
## 1.13.0 (2017-03-07)
|
6
15
|
|
7
16
|
* Add repeated 'it' detection to `RSpec/ExampleWording` cop. ([@dgollahon][])
|
data/config/default.yml
CHANGED
@@ -42,11 +42,23 @@ RSpec/DescribeMethod:
|
|
42
42
|
Description: Checks that the second argument to `describe` specifies a method.
|
43
43
|
Enabled: true
|
44
44
|
|
45
|
+
RSpec/IteratedExpectation:
|
46
|
+
Description: Check that `all` matcher is used instead of iterating over an array.
|
47
|
+
Enabled: true
|
48
|
+
|
45
49
|
RSpec/EmptyExampleGroup:
|
46
50
|
Description: Checks if an example group does not include any tests.
|
47
51
|
Enabled: true
|
48
52
|
CustomIncludeMethods: []
|
49
53
|
|
54
|
+
RSpec/EmptyLineAfterFinalLet:
|
55
|
+
Description: Checks if there is an empty line after the last let block.
|
56
|
+
Enabled: true
|
57
|
+
|
58
|
+
RSpec/EmptyLineAfterSubject:
|
59
|
+
Description: Checks if there is an empty line after subject block.
|
60
|
+
Enabled: true
|
61
|
+
|
50
62
|
RSpec/ExampleLength:
|
51
63
|
Description: Checks for long examples.
|
52
64
|
Enabled: true
|
@@ -171,6 +183,10 @@ RSpec/NotToNot:
|
|
171
183
|
- to_not
|
172
184
|
Enabled: true
|
173
185
|
|
186
|
+
RSpec/OverwritingSetup:
|
187
|
+
Enabled: true
|
188
|
+
Description: Checks if there is a let/subject that overwrites an existing one.
|
189
|
+
|
174
190
|
RSpec/RepeatedDescription:
|
175
191
|
Enabled: true
|
176
192
|
Description: Check for repeated description strings in example groups.
|
@@ -187,6 +203,10 @@ RSpec/SingleArgumentMessageChain:
|
|
187
203
|
Description: Checks that chains of messages contain more than one element.
|
188
204
|
Enabled: true
|
189
205
|
|
206
|
+
RSpec/ScatteredLet:
|
207
|
+
Description: Checks for let scattered across the example group.
|
208
|
+
Enabled: true
|
209
|
+
|
190
210
|
RSpec/ScatteredSetup:
|
191
211
|
Description: Checks for setup scattered across multiple hooks in an example group.
|
192
212
|
Enabled: true
|
data/lib/rubocop-rspec.rb
CHANGED
@@ -28,6 +28,8 @@ require 'rubocop/cop/rspec/describe_class'
|
|
28
28
|
require 'rubocop/cop/rspec/describe_method'
|
29
29
|
require 'rubocop/cop/rspec/described_class'
|
30
30
|
require 'rubocop/cop/rspec/empty_example_group'
|
31
|
+
require 'rubocop/cop/rspec/empty_line_after_final_let'
|
32
|
+
require 'rubocop/cop/rspec/empty_line_after_subject'
|
31
33
|
require 'rubocop/cop/rspec/example_length'
|
32
34
|
require 'rubocop/cop/rspec/example_wording'
|
33
35
|
require 'rubocop/cop/rspec/expect_actual'
|
@@ -39,6 +41,7 @@ require 'rubocop/cop/rspec/implicit_expect'
|
|
39
41
|
require 'rubocop/cop/rspec/instance_spy'
|
40
42
|
require 'rubocop/cop/rspec/instance_variable'
|
41
43
|
require 'rubocop/cop/rspec/it_behaves_like'
|
44
|
+
require 'rubocop/cop/rspec/iterated_expectation'
|
42
45
|
require 'rubocop/cop/rspec/leading_subject'
|
43
46
|
require 'rubocop/cop/rspec/let_setup'
|
44
47
|
require 'rubocop/cop/rspec/message_chain'
|
@@ -49,8 +52,10 @@ require 'rubocop/cop/rspec/multiple_expectations'
|
|
49
52
|
require 'rubocop/cop/rspec/named_subject'
|
50
53
|
require 'rubocop/cop/rspec/nested_groups'
|
51
54
|
require 'rubocop/cop/rspec/not_to_not'
|
55
|
+
require 'rubocop/cop/rspec/overwriting_setup'
|
52
56
|
require 'rubocop/cop/rspec/repeated_description'
|
53
57
|
require 'rubocop/cop/rspec/repeated_example'
|
58
|
+
require 'rubocop/cop/rspec/scattered_let'
|
54
59
|
require 'rubocop/cop/rspec/scattered_setup'
|
55
60
|
require 'rubocop/cop/rspec/shared_context'
|
56
61
|
require 'rubocop/cop/rspec/single_argument_message_chain'
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks if there is an empty line after the last let block.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# let(:foo) { bar }
|
11
|
+
# let(:something) { other }
|
12
|
+
# it do
|
13
|
+
# ...
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# let(:foo) { bar }
|
18
|
+
# let(:something) { other }
|
19
|
+
#
|
20
|
+
# it do
|
21
|
+
# ...
|
22
|
+
# end
|
23
|
+
class EmptyLineAfterFinalLet < Cop
|
24
|
+
MSG = 'Add an empty line after the last `let` block.'.freeze
|
25
|
+
|
26
|
+
def_node_matcher :let?, '(block $(send nil {:let :let!} ...) args ...)'
|
27
|
+
|
28
|
+
def on_block(node)
|
29
|
+
return unless let?(node) && !in_spec_block?(node)
|
30
|
+
|
31
|
+
latest_let = node
|
32
|
+
node.parent.each_child_node do |sibling|
|
33
|
+
latest_let = sibling if let?(sibling)
|
34
|
+
end
|
35
|
+
|
36
|
+
return if latest_let.equal?(node.parent.children.last)
|
37
|
+
|
38
|
+
no_new_line_after(latest_let) do
|
39
|
+
add_offense(latest_let, :expression)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def autocorrect(node)
|
44
|
+
loc = last_node_loc(node)
|
45
|
+
->(corrector) { corrector.insert_after(loc.end, "\n") }
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def no_new_line_after(node)
|
51
|
+
loc = last_node_loc(node)
|
52
|
+
|
53
|
+
next_line = processed_source[loc.line]
|
54
|
+
|
55
|
+
yield unless next_line.blank?
|
56
|
+
end
|
57
|
+
|
58
|
+
def last_node_loc(node)
|
59
|
+
last_line = node.loc.end.line
|
60
|
+
heredoc_line(node) do |loc|
|
61
|
+
return loc if loc.line > last_line
|
62
|
+
end
|
63
|
+
node.loc.end
|
64
|
+
end
|
65
|
+
|
66
|
+
def heredoc_line(node, &block)
|
67
|
+
yield node.loc.heredoc_end if node.loc.respond_to?(:heredoc_end)
|
68
|
+
|
69
|
+
node.each_child_node { |child| heredoc_line(child, &block) }
|
70
|
+
end
|
71
|
+
|
72
|
+
def in_spec_block?(node)
|
73
|
+
node.each_ancestor(:block).any? do |ancestor|
|
74
|
+
Examples::ALL.include?(ancestor.method_name)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks if there is an empty line after subject block.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# subject(:obj) { described_class }
|
11
|
+
# let(:foo) { bar }
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# subject(:obj) { described_class }
|
15
|
+
#
|
16
|
+
# let(:foo) { bar }
|
17
|
+
class EmptyLineAfterSubject < Cop
|
18
|
+
MSG = 'Add empty line after `subject`.'.freeze
|
19
|
+
|
20
|
+
def_node_matcher :subject?, '(block $(send nil :subject ...) args ...)'
|
21
|
+
|
22
|
+
def on_block(node)
|
23
|
+
return unless subject?(node) && !in_spec_block?(node)
|
24
|
+
return if node.equal?(node.parent.children.last)
|
25
|
+
|
26
|
+
send_line = node.loc.end.line
|
27
|
+
next_line = processed_source[send_line]
|
28
|
+
return if next_line.blank?
|
29
|
+
|
30
|
+
add_offense(node, :expression, MSG)
|
31
|
+
end
|
32
|
+
|
33
|
+
def autocorrect(node)
|
34
|
+
->(corrector) { corrector.insert_after(node.loc.end, "\n") }
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def in_spec_block?(node)
|
40
|
+
node.each_ancestor(:block).any? do |ancestor|
|
41
|
+
Examples::ALL.include?(ancestor.method_name)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module RuboCop
|
2
|
+
module Cop
|
3
|
+
module RSpec
|
4
|
+
# Check that `all` matcher is used instead of iterating over an array.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# # bad
|
8
|
+
# it 'validates users' do
|
9
|
+
# [user1, user2, user3].each { |user| expect(user).to be_valid }
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# # good
|
13
|
+
# it 'validates users' do
|
14
|
+
# expect([user1, user2, user3]).to all(be_valid)
|
15
|
+
# end
|
16
|
+
class IteratedExpectation < Cop
|
17
|
+
MSG = 'Prefer using the `all` matcher instead ' \
|
18
|
+
'of iterating over an array.'.freeze
|
19
|
+
|
20
|
+
def_node_matcher :each?, <<-PATTERN
|
21
|
+
(block
|
22
|
+
(send ... :each)
|
23
|
+
(args (arg $_))
|
24
|
+
$(...)
|
25
|
+
)
|
26
|
+
PATTERN
|
27
|
+
|
28
|
+
def_node_matcher :expectation?, <<-PATTERN
|
29
|
+
(send (send nil :expect (lvar %)) :to ...)
|
30
|
+
PATTERN
|
31
|
+
|
32
|
+
def on_block(node)
|
33
|
+
each?(node) do |arg, body|
|
34
|
+
if single_expectation?(body, arg) || only_expectations?(body, arg)
|
35
|
+
add_offense(node.children.first, :expression)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def single_expectation?(body, arg)
|
43
|
+
expectation?(body, arg)
|
44
|
+
end
|
45
|
+
|
46
|
+
def only_expectations?(body, arg)
|
47
|
+
body.children.all? { |child| expectation?(child, arg) }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -37,14 +37,37 @@ module RuboCop
|
|
37
37
|
node.parent.each_child_node do |sibling|
|
38
38
|
break if sibling.equal?(node)
|
39
39
|
|
40
|
-
if
|
41
|
-
|
42
|
-
|
40
|
+
break add_offense(node, :expression) if let?(sibling)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def autocorrect(node)
|
45
|
+
lambda do |corrector|
|
46
|
+
first_let = find_first_let(node)
|
47
|
+
first_let_position = first_let.loc.expression
|
48
|
+
indent = "\n" + ' ' * first_let.loc.column
|
49
|
+
corrector.insert_before(first_let_position, node.source + indent)
|
50
|
+
corrector.remove(node_range(node))
|
43
51
|
end
|
44
52
|
end
|
45
53
|
|
46
54
|
private
|
47
55
|
|
56
|
+
def let?(node)
|
57
|
+
[:let, :let!].include?(node.method_name)
|
58
|
+
end
|
59
|
+
|
60
|
+
def find_first_let(node)
|
61
|
+
node.parent.children.find { |sibling| let?(sibling) }
|
62
|
+
end
|
63
|
+
|
64
|
+
def node_range(node)
|
65
|
+
range = node.source_range
|
66
|
+
range = range_with_surrounding_space(range, :left, false)
|
67
|
+
range = range_with_surrounding_space(range, :right, true)
|
68
|
+
range
|
69
|
+
end
|
70
|
+
|
48
71
|
def in_spec_block?(node)
|
49
72
|
node.each_ancestor(:block).any? do |ancestor|
|
50
73
|
Examples::ALL.include?(ancestor.method_name)
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks if there is a let/subject that overwrites an existing one.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# let(:foo) { bar }
|
11
|
+
# let(:foo) { baz }
|
12
|
+
#
|
13
|
+
# subject(:foo) { bar }
|
14
|
+
# let(:foo) { baz }
|
15
|
+
#
|
16
|
+
# let(:foo) { bar }
|
17
|
+
# let!(:foo) { baz }
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# subject(:test) { something }
|
21
|
+
# let(:foo) { bar }
|
22
|
+
# let(:baz) { baz }
|
23
|
+
# let!(:other) { other }
|
24
|
+
class OverwritingSetup < Cop
|
25
|
+
MSG = '`%{name}` is already defined.'.freeze
|
26
|
+
|
27
|
+
def_node_matcher :setup?, <<-PATTERN
|
28
|
+
(block (send nil {:let :let! :subject} (sym $_)) ...)
|
29
|
+
PATTERN
|
30
|
+
|
31
|
+
def on_block(node)
|
32
|
+
return unless example_group?(node)
|
33
|
+
|
34
|
+
_describe, _args, body = *node
|
35
|
+
|
36
|
+
find_duplicates(body) do |duplicate, name|
|
37
|
+
add_offense(duplicate, :expression, format(MSG, name: name))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def find_duplicates(node)
|
44
|
+
setup_expressions = Set.new
|
45
|
+
node.each_child_node do |child|
|
46
|
+
setup?(child) do |name|
|
47
|
+
yield child, name unless setup_expressions.add?(name)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Checks for let scattered across the example group.
|
7
|
+
#
|
8
|
+
# Group lets together
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# # bad
|
12
|
+
# describe Foo do
|
13
|
+
# let(:foo) { 1 }
|
14
|
+
# subject { Foo }
|
15
|
+
# let(:bar) { 2 }
|
16
|
+
# before { prepare }
|
17
|
+
# let!(:baz) { 3 }
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# describe Foo do
|
22
|
+
# subject { Foo }
|
23
|
+
# before { prepare }
|
24
|
+
# let(:foo) { 1 }
|
25
|
+
# let(:bar) { 2 }
|
26
|
+
# let!(:baz) { 3 }
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
class ScatteredLet < Cop
|
30
|
+
MSG = 'Group all let/let! blocks in the example group together.'.freeze
|
31
|
+
|
32
|
+
def_node_matcher :let?, '(block (send nil {:let :let!} ...) ...)'
|
33
|
+
|
34
|
+
def on_block(node)
|
35
|
+
return unless example_group?(node)
|
36
|
+
|
37
|
+
_describe, _args, body = *node
|
38
|
+
|
39
|
+
check_let_declarations(body)
|
40
|
+
end
|
41
|
+
|
42
|
+
def check_let_declarations(node)
|
43
|
+
let_found = false
|
44
|
+
mix_found = false
|
45
|
+
|
46
|
+
node.each_child_node do |child|
|
47
|
+
if let?(child)
|
48
|
+
add_offense(child, :expression) if mix_found
|
49
|
+
let_found = true
|
50
|
+
elsif let_found
|
51
|
+
mix_found = true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -10,18 +10,15 @@ RSpec.describe 'CHANGELOG.md' do
|
|
10
10
|
|
11
11
|
describe 'entry' do
|
12
12
|
subject(:entries) { lines.grep(/^\*/).map(&:chomp) }
|
13
|
+
|
13
14
|
let(:lines) { changelog.each_line }
|
14
15
|
|
15
16
|
it 'has a whitespace between the * and the body' do
|
16
|
-
entries.
|
17
|
-
expect(entry).to match(/^\* \S/)
|
18
|
-
end
|
17
|
+
expect(entries).to all(match(/^\* \S/))
|
19
18
|
end
|
20
19
|
|
21
20
|
it 'has a link to the contributors at the end' do
|
22
|
-
entries.
|
23
|
-
expect(entry).to match(/\(\[@\S+\]\[\](?:, \[@\S+\]\[\])*\)$/)
|
24
|
-
end
|
21
|
+
expect(entries).to all(match(/\(\[@\S+\]\[\](?:, \[@\S+\]\[\])*\)$/))
|
25
22
|
end
|
26
23
|
|
27
24
|
describe 'link to related issue on github' do
|
@@ -50,9 +47,7 @@ RSpec.describe 'CHANGELOG.md' do
|
|
50
47
|
entry.match(/^\*\s*\[/)
|
51
48
|
end
|
52
49
|
|
53
|
-
entries_including_issue_link.
|
54
|
-
expect(entry).to include('): ')
|
55
|
-
end
|
50
|
+
expect(entries_including_issue_link).to all(include('): '))
|
56
51
|
end
|
57
52
|
end
|
58
53
|
|
@@ -72,9 +67,7 @@ RSpec.describe 'CHANGELOG.md' do
|
|
72
67
|
end
|
73
68
|
|
74
69
|
it 'ends with a punctuation' do
|
75
|
-
bodies.
|
76
|
-
expect(body).to match(/[\.\!]$/)
|
77
|
-
end
|
70
|
+
expect(bodies).to all(match(/[\.\!]$/))
|
78
71
|
end
|
79
72
|
end
|
80
73
|
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe RuboCop::Cop::RSpec::EmptyLineAfterFinalLet do
|
4
|
+
subject(:cop) { described_class.new }
|
5
|
+
|
6
|
+
it 'checks for empty line after last let' do
|
7
|
+
expect_violation(<<-RUBY)
|
8
|
+
RSpec.describe User do
|
9
|
+
let(:a) { a }
|
10
|
+
let(:b) { b }
|
11
|
+
^^^^^^^^^^^^^ Add an empty line after the last `let` block.
|
12
|
+
it { expect(a).to eq(b) }
|
13
|
+
end
|
14
|
+
RUBY
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'check for empty line after the last `let!`' do
|
18
|
+
expect_violation(<<-RUBY)
|
19
|
+
RSpec.describe User do
|
20
|
+
let(:a) { a }
|
21
|
+
let!(:b) do
|
22
|
+
^^^^^^^^^^^ Add an empty line after the last `let` block.
|
23
|
+
b
|
24
|
+
end
|
25
|
+
it { expect(a).to eq(b) }
|
26
|
+
end
|
27
|
+
RUBY
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'approves empty line after let' do
|
31
|
+
expect_no_violations(<<-RUBY)
|
32
|
+
RSpec.describe User do
|
33
|
+
let(:a) { a }
|
34
|
+
let(:b) { b }
|
35
|
+
|
36
|
+
it { expect(a).to eq(b) }
|
37
|
+
end
|
38
|
+
RUBY
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'ignores empty lines between the lets' do
|
42
|
+
expect_violation(<<-RUBY)
|
43
|
+
RSpec.describe User do
|
44
|
+
let(:a) { a }
|
45
|
+
|
46
|
+
subject { described_class }
|
47
|
+
|
48
|
+
let!(:b) { b }
|
49
|
+
^^^^^^^^^^^^^^ Add an empty line after the last `let` block.
|
50
|
+
it { expect(a).to eq(b) }
|
51
|
+
end
|
52
|
+
RUBY
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'handles let in tests' do
|
56
|
+
expect_no_violations(<<-RUBY)
|
57
|
+
RSpec.describe User do
|
58
|
+
# This shouldn't really ever happen in a sane codebase but I still
|
59
|
+
# want to avoid false positives
|
60
|
+
it "doesn't mind me calling a method called let in the test" do
|
61
|
+
let(foo)
|
62
|
+
subject { bar }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
RUBY
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'handles multiline let block' do
|
69
|
+
expect_no_violations(<<-RUBY)
|
70
|
+
RSpec.describe User do
|
71
|
+
let(:a) { a }
|
72
|
+
let(:b) do
|
73
|
+
b
|
74
|
+
end
|
75
|
+
|
76
|
+
it { expect(a).to eq(b) }
|
77
|
+
end
|
78
|
+
RUBY
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'handles let being the latest node' do
|
82
|
+
expect_no_violations(<<-RUBY)
|
83
|
+
RSpec.describe User do
|
84
|
+
let(:a) { a }
|
85
|
+
let(:b) { b }
|
86
|
+
end
|
87
|
+
RUBY
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'handles HEREDOC for let' do
|
91
|
+
expect_no_violations(<<-RUBY)
|
92
|
+
RSpec.describe User do
|
93
|
+
let(:foo) do
|
94
|
+
<<-BAR
|
95
|
+
hello
|
96
|
+
world
|
97
|
+
BAR
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'uses heredoc' do
|
101
|
+
expect(foo).to eql(" hello\n world\n")
|
102
|
+
end
|
103
|
+
end
|
104
|
+
RUBY
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'handles silly HEREDOC syntax for let' do
|
108
|
+
expect_no_violations(<<-RUBY)
|
109
|
+
RSpec.describe 'silly heredoc syntax' do
|
110
|
+
let(:foo) { <<-BAR }
|
111
|
+
hello
|
112
|
+
world
|
113
|
+
BAR
|
114
|
+
|
115
|
+
it 'has tricky syntax' do
|
116
|
+
expect(foo).to eql(" hello\n world\n")
|
117
|
+
end
|
118
|
+
end
|
119
|
+
RUBY
|
120
|
+
end
|
121
|
+
|
122
|
+
bad_example = <<-RUBY
|
123
|
+
RSpec.describe User do
|
124
|
+
let(:params) { foo }
|
125
|
+
it 'has a new line' do
|
126
|
+
end
|
127
|
+
end
|
128
|
+
RUBY
|
129
|
+
|
130
|
+
good_example = <<-RUBY
|
131
|
+
RSpec.describe User do
|
132
|
+
let(:params) { foo }
|
133
|
+
|
134
|
+
it 'has a new line' do
|
135
|
+
end
|
136
|
+
end
|
137
|
+
RUBY
|
138
|
+
|
139
|
+
include_examples 'autocorrect',
|
140
|
+
bad_example,
|
141
|
+
good_example
|
142
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe RuboCop::Cop::RSpec::EmptyLineAfterSubject do
|
4
|
+
subject(:cop) { described_class.new }
|
5
|
+
|
6
|
+
it 'checks for empty line after subject' do
|
7
|
+
expect_violation(<<-RUBY)
|
8
|
+
RSpec.describe User do
|
9
|
+
subject { described_class.new }
|
10
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Add empty line after `subject`.
|
11
|
+
let(:params) { foo }
|
12
|
+
end
|
13
|
+
RUBY
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'approves empty line after subject' do
|
17
|
+
expect_no_violations(<<-RUBY)
|
18
|
+
RSpec.describe User do
|
19
|
+
subject { described_class.new }
|
20
|
+
|
21
|
+
let(:params) { foo }
|
22
|
+
end
|
23
|
+
RUBY
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'handles subjects in tests' do
|
27
|
+
expect_no_violations(<<-RUBY)
|
28
|
+
RSpec.describe User do
|
29
|
+
# This shouldn't really ever happen in a sane codebase but I still
|
30
|
+
# want to avoid false positives
|
31
|
+
it "doesn't mind me calling a method called subject in the test" do
|
32
|
+
subject { bar }
|
33
|
+
let(foo)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
RUBY
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'handles multiline subject block' do
|
40
|
+
expect_no_violations(<<-RUBY)
|
41
|
+
RSpec.describe User do
|
42
|
+
subject do
|
43
|
+
described_class.new
|
44
|
+
end
|
45
|
+
|
46
|
+
let(:params) { foo }
|
47
|
+
end
|
48
|
+
RUBY
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'handles let being the latest node' do
|
52
|
+
expect_no_violations(<<-RUBY)
|
53
|
+
RSpec.describe User do
|
54
|
+
subject { described_user }
|
55
|
+
end
|
56
|
+
RUBY
|
57
|
+
end
|
58
|
+
|
59
|
+
bad_example = <<-RUBY
|
60
|
+
RSpec.describe User do
|
61
|
+
subject { described_class.new }
|
62
|
+
let(:params) { foo }
|
63
|
+
end
|
64
|
+
RUBY
|
65
|
+
|
66
|
+
good_example = <<-RUBY
|
67
|
+
RSpec.describe User do
|
68
|
+
subject { described_class.new }
|
69
|
+
|
70
|
+
let(:params) { foo }
|
71
|
+
end
|
72
|
+
RUBY
|
73
|
+
|
74
|
+
include_examples 'autocorrect',
|
75
|
+
bad_example,
|
76
|
+
good_example
|
77
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
RSpec.describe RuboCop::Cop::RSpec::IteratedExpectation do
|
2
|
+
subject(:cop) { described_class.new }
|
3
|
+
|
4
|
+
it 'flags `each` with an expectation' do
|
5
|
+
expect_violation(<<-RUBY)
|
6
|
+
it 'validates users' do
|
7
|
+
[user1, user2, user3].each { |user| expect(user).to be_valid }
|
8
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using the `all` matcher instead of iterating over an array.
|
9
|
+
end
|
10
|
+
RUBY
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'flags `each` when expectation calls method with arguments' do
|
14
|
+
expect_violation(<<-RUBY)
|
15
|
+
it 'validates users' do
|
16
|
+
[user1, user2, user3].each { |user| expect(user).to be_a(User) }
|
17
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using the `all` matcher instead of iterating over an array.
|
18
|
+
end
|
19
|
+
RUBY
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'ignores `each` without expectation' do
|
23
|
+
expect_no_violations(<<-RUBY)
|
24
|
+
it 'validates users' do
|
25
|
+
[user1, user2, user3].each { |user| allow(user).to receive(:method) }
|
26
|
+
end
|
27
|
+
RUBY
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'flags `each` with multiple expectations' do
|
31
|
+
expect_violation(<<-RUBY)
|
32
|
+
it 'validates users' do
|
33
|
+
[user1, user2, user3].each do |user|
|
34
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer using the `all` matcher instead of iterating over an array.
|
35
|
+
expect(user).to receive(:method)
|
36
|
+
expect(user).to receive(:other_method)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
RUBY
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'ignore `each` when the body does not contain only expectations' do
|
43
|
+
expect_no_violations(<<-RUBY)
|
44
|
+
it 'validates users' do
|
45
|
+
[user1, user2, user3].each do |user|
|
46
|
+
allow(Something).to receive(:method).and_return(user)
|
47
|
+
expect(user).to receive(:method)
|
48
|
+
expect(user).to receive(:other_method)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
RUBY
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'ignores `each` with expectation on property' do
|
55
|
+
expect_no_violations(<<-RUBY)
|
56
|
+
it 'validates users' do
|
57
|
+
[user1, user2, user3].each { |user| expect(user.name).to be }
|
58
|
+
end
|
59
|
+
RUBY
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'ignores `each` when there is a negative expectation' do
|
63
|
+
expect_no_violations(<<-RUBY)
|
64
|
+
it 'validates users' do
|
65
|
+
[user1, user2, user3].each do |user|
|
66
|
+
expect(user).not_to receive(:method)
|
67
|
+
expect(user).to receive(:other_method)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
RUBY
|
71
|
+
end
|
72
|
+
end
|
@@ -14,6 +14,17 @@ RSpec.describe RuboCop::Cop::RSpec::LeadingSubject do
|
|
14
14
|
RUBY
|
15
15
|
end
|
16
16
|
|
17
|
+
it 'checks subject below let!' do
|
18
|
+
expect_violation(<<-RUBY)
|
19
|
+
RSpec.describe User do
|
20
|
+
let!(:params) { foo }
|
21
|
+
|
22
|
+
subject { described_class.new }
|
23
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Declare `subject` above any other `let` declarations.
|
24
|
+
end
|
25
|
+
RUBY
|
26
|
+
end
|
27
|
+
|
17
28
|
it 'approves of subject above let' do
|
18
29
|
expect_no_violations(<<-RUBY)
|
19
30
|
RSpec.describe User do
|
@@ -51,4 +62,50 @@ RSpec.describe RuboCop::Cop::RSpec::LeadingSubject do
|
|
51
62
|
end
|
52
63
|
RUBY
|
53
64
|
end
|
65
|
+
|
66
|
+
bad_code = <<-RUBY
|
67
|
+
RSpec.describe User do
|
68
|
+
let(:params) { foo }
|
69
|
+
let(:bar) { baz }
|
70
|
+
|
71
|
+
subject { described_class.new }
|
72
|
+
it { is_expected.to do_something }
|
73
|
+
end
|
74
|
+
RUBY
|
75
|
+
|
76
|
+
good_code = <<-RUBY
|
77
|
+
RSpec.describe User do
|
78
|
+
subject { described_class.new }
|
79
|
+
let(:params) { foo }
|
80
|
+
let(:bar) { baz }
|
81
|
+
|
82
|
+
it { is_expected.to do_something }
|
83
|
+
end
|
84
|
+
RUBY
|
85
|
+
|
86
|
+
include_examples 'autocorrect', bad_code, good_code
|
87
|
+
|
88
|
+
bad_code = <<-RUBY
|
89
|
+
RSpec.describe User do
|
90
|
+
let(:params) { foo }
|
91
|
+
let(:bar) { baz }
|
92
|
+
subject do
|
93
|
+
described_class.new
|
94
|
+
end
|
95
|
+
it { is_expected.to do_something }
|
96
|
+
end
|
97
|
+
RUBY
|
98
|
+
|
99
|
+
good_code = <<-RUBY
|
100
|
+
RSpec.describe User do
|
101
|
+
subject do
|
102
|
+
described_class.new
|
103
|
+
end
|
104
|
+
let(:params) { foo }
|
105
|
+
let(:bar) { baz }
|
106
|
+
it { is_expected.to do_something }
|
107
|
+
end
|
108
|
+
RUBY
|
109
|
+
|
110
|
+
include_examples 'autocorrect', bad_code, good_code
|
54
111
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
RSpec.describe RuboCop::Cop::RSpec::OverwritingSetup do
|
2
|
+
subject(:cop) { described_class.new }
|
3
|
+
|
4
|
+
it 'finds overwriten `let`' do
|
5
|
+
expect_violation(<<-RUBY)
|
6
|
+
RSpec.describe User do
|
7
|
+
let(:a) { a }
|
8
|
+
let(:a) { b }
|
9
|
+
^^^^^^^^^^^^^ `a` is already defined.
|
10
|
+
end
|
11
|
+
RUBY
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'finds overwriten `subject`' do
|
15
|
+
expect_violation(<<-RUBY)
|
16
|
+
RSpec.describe User do
|
17
|
+
subject(:a) { a }
|
18
|
+
|
19
|
+
let(:a) { b }
|
20
|
+
^^^^^^^^^^^^^ `a` is already defined.
|
21
|
+
end
|
22
|
+
RUBY
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'finds `let!` overwriting `let`' do
|
26
|
+
expect_violation(<<-RUBY)
|
27
|
+
RSpec.describe User do
|
28
|
+
let(:a) { b }
|
29
|
+
let!(:a) { b }
|
30
|
+
^^^^^^^^^^^^^^ `a` is already defined.
|
31
|
+
end
|
32
|
+
RUBY
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'ignores overwriting in different context' do
|
36
|
+
expect_no_violations(<<-RUBY)
|
37
|
+
RSpec.describe User do
|
38
|
+
let(:a) { a }
|
39
|
+
|
40
|
+
context `different` do
|
41
|
+
let(:a) { b }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
RUBY
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
RSpec.describe RuboCop::Cop::RSpec::ScatteredLet do
|
2
|
+
subject(:cop) { described_class.new }
|
3
|
+
|
4
|
+
it 'flags `let` after the first different node ' do
|
5
|
+
expect_violation(<<-RUBY)
|
6
|
+
RSpec.describe User do
|
7
|
+
let(:a) { a }
|
8
|
+
subject { User }
|
9
|
+
let(:b) { b }
|
10
|
+
^^^^^^^^^^^^^ Group all let/let! blocks in the example group together.
|
11
|
+
end
|
12
|
+
RUBY
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'doesnt flag `let!` in the middle of multiple `let`s' do
|
16
|
+
expect_no_violations(<<-RUBY)
|
17
|
+
RSpec.describe User do
|
18
|
+
subject { User }
|
19
|
+
|
20
|
+
let(:a) { a }
|
21
|
+
let!(:b) { b }
|
22
|
+
let(:c) { c }
|
23
|
+
end
|
24
|
+
RUBY
|
25
|
+
end
|
26
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop-rspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Backus
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2017-03-
|
13
|
+
date: 2017-03-24 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rubocop
|
@@ -153,6 +153,8 @@ files:
|
|
153
153
|
- lib/rubocop/cop/rspec/describe_method.rb
|
154
154
|
- lib/rubocop/cop/rspec/described_class.rb
|
155
155
|
- lib/rubocop/cop/rspec/empty_example_group.rb
|
156
|
+
- lib/rubocop/cop/rspec/empty_line_after_final_let.rb
|
157
|
+
- lib/rubocop/cop/rspec/empty_line_after_subject.rb
|
156
158
|
- lib/rubocop/cop/rspec/example_length.rb
|
157
159
|
- lib/rubocop/cop/rspec/example_wording.rb
|
158
160
|
- lib/rubocop/cop/rspec/expect_actual.rb
|
@@ -164,6 +166,7 @@ files:
|
|
164
166
|
- lib/rubocop/cop/rspec/instance_spy.rb
|
165
167
|
- lib/rubocop/cop/rspec/instance_variable.rb
|
166
168
|
- lib/rubocop/cop/rspec/it_behaves_like.rb
|
169
|
+
- lib/rubocop/cop/rspec/iterated_expectation.rb
|
167
170
|
- lib/rubocop/cop/rspec/leading_subject.rb
|
168
171
|
- lib/rubocop/cop/rspec/let_setup.rb
|
169
172
|
- lib/rubocop/cop/rspec/message_chain.rb
|
@@ -174,8 +177,10 @@ files:
|
|
174
177
|
- lib/rubocop/cop/rspec/named_subject.rb
|
175
178
|
- lib/rubocop/cop/rspec/nested_groups.rb
|
176
179
|
- lib/rubocop/cop/rspec/not_to_not.rb
|
180
|
+
- lib/rubocop/cop/rspec/overwriting_setup.rb
|
177
181
|
- lib/rubocop/cop/rspec/repeated_description.rb
|
178
182
|
- lib/rubocop/cop/rspec/repeated_example.rb
|
183
|
+
- lib/rubocop/cop/rspec/scattered_let.rb
|
179
184
|
- lib/rubocop/cop/rspec/scattered_setup.rb
|
180
185
|
- lib/rubocop/cop/rspec/shared_context.rb
|
181
186
|
- lib/rubocop/cop/rspec/single_argument_message_chain.rb
|
@@ -209,6 +214,8 @@ files:
|
|
209
214
|
- spec/rubocop/cop/rspec/describe_method_spec.rb
|
210
215
|
- spec/rubocop/cop/rspec/described_class_spec.rb
|
211
216
|
- spec/rubocop/cop/rspec/empty_example_group_spec.rb
|
217
|
+
- spec/rubocop/cop/rspec/empty_line_after_final_let_spec.rb
|
218
|
+
- spec/rubocop/cop/rspec/empty_line_after_subject_spec.rb
|
212
219
|
- spec/rubocop/cop/rspec/example_length_spec.rb
|
213
220
|
- spec/rubocop/cop/rspec/example_wording_spec.rb
|
214
221
|
- spec/rubocop/cop/rspec/expect_actual_spec.rb
|
@@ -220,6 +227,7 @@ files:
|
|
220
227
|
- spec/rubocop/cop/rspec/instance_spy_spec.rb
|
221
228
|
- spec/rubocop/cop/rspec/instance_variable_spec.rb
|
222
229
|
- spec/rubocop/cop/rspec/it_behaves_like_spec.rb
|
230
|
+
- spec/rubocop/cop/rspec/iterated_expectation_spec.rb
|
223
231
|
- spec/rubocop/cop/rspec/leading_subject_spec.rb
|
224
232
|
- spec/rubocop/cop/rspec/let_setup_spec.rb
|
225
233
|
- spec/rubocop/cop/rspec/message_chain_spec.rb
|
@@ -230,8 +238,10 @@ files:
|
|
230
238
|
- spec/rubocop/cop/rspec/named_subject_spec.rb
|
231
239
|
- spec/rubocop/cop/rspec/nested_groups_spec.rb
|
232
240
|
- spec/rubocop/cop/rspec/not_to_not_spec.rb
|
241
|
+
- spec/rubocop/cop/rspec/overwriting_setup_spec.rb
|
233
242
|
- spec/rubocop/cop/rspec/repeated_description_spec.rb
|
234
243
|
- spec/rubocop/cop/rspec/repeated_example_spec.rb
|
244
|
+
- spec/rubocop/cop/rspec/scattered_let_spec.rb
|
235
245
|
- spec/rubocop/cop/rspec/scattered_setup_spec.rb
|
236
246
|
- spec/rubocop/cop/rspec/shared_context_spec.rb
|
237
247
|
- spec/rubocop/cop/rspec/single_argument_message_chain_spec.rb
|
@@ -269,7 +279,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
269
279
|
version: '0'
|
270
280
|
requirements: []
|
271
281
|
rubyforge_project:
|
272
|
-
rubygems_version: 2.5.
|
282
|
+
rubygems_version: 2.5.2
|
273
283
|
signing_key:
|
274
284
|
specification_version: 4
|
275
285
|
summary: Code style checking for RSpec files
|
@@ -287,6 +297,8 @@ test_files:
|
|
287
297
|
- spec/rubocop/cop/rspec/describe_method_spec.rb
|
288
298
|
- spec/rubocop/cop/rspec/described_class_spec.rb
|
289
299
|
- spec/rubocop/cop/rspec/empty_example_group_spec.rb
|
300
|
+
- spec/rubocop/cop/rspec/empty_line_after_final_let_spec.rb
|
301
|
+
- spec/rubocop/cop/rspec/empty_line_after_subject_spec.rb
|
290
302
|
- spec/rubocop/cop/rspec/example_length_spec.rb
|
291
303
|
- spec/rubocop/cop/rspec/example_wording_spec.rb
|
292
304
|
- spec/rubocop/cop/rspec/expect_actual_spec.rb
|
@@ -298,6 +310,7 @@ test_files:
|
|
298
310
|
- spec/rubocop/cop/rspec/instance_spy_spec.rb
|
299
311
|
- spec/rubocop/cop/rspec/instance_variable_spec.rb
|
300
312
|
- spec/rubocop/cop/rspec/it_behaves_like_spec.rb
|
313
|
+
- spec/rubocop/cop/rspec/iterated_expectation_spec.rb
|
301
314
|
- spec/rubocop/cop/rspec/leading_subject_spec.rb
|
302
315
|
- spec/rubocop/cop/rspec/let_setup_spec.rb
|
303
316
|
- spec/rubocop/cop/rspec/message_chain_spec.rb
|
@@ -308,8 +321,10 @@ test_files:
|
|
308
321
|
- spec/rubocop/cop/rspec/named_subject_spec.rb
|
309
322
|
- spec/rubocop/cop/rspec/nested_groups_spec.rb
|
310
323
|
- spec/rubocop/cop/rspec/not_to_not_spec.rb
|
324
|
+
- spec/rubocop/cop/rspec/overwriting_setup_spec.rb
|
311
325
|
- spec/rubocop/cop/rspec/repeated_description_spec.rb
|
312
326
|
- spec/rubocop/cop/rspec/repeated_example_spec.rb
|
327
|
+
- spec/rubocop/cop/rspec/scattered_let_spec.rb
|
313
328
|
- spec/rubocop/cop/rspec/scattered_setup_spec.rb
|
314
329
|
- spec/rubocop/cop/rspec/shared_context_spec.rb
|
315
330
|
- spec/rubocop/cop/rspec/single_argument_message_chain_spec.rb
|