rubocop-rspec 1.5.2 → 1.5.3
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 +4 -0
- data/config/default.yml +4 -0
- data/lib/rubocop-rspec.rb +1 -0
- data/lib/rubocop/cop/rspec/named_subject.rb +67 -0
- data/lib/rubocop/rspec/version.rb +1 -1
- data/rubocop-rspec.gemspec +3 -0
- data/spec/expect_violation/expectation_spec.rb +85 -0
- data/spec/rubocop/cop/rspec/any_instance_spec.rb +18 -36
- data/spec/rubocop/cop/rspec/describe_class_spec.rb +65 -62
- data/spec/rubocop/cop/rspec/describe_method_spec.rb +17 -18
- data/spec/rubocop/cop/rspec/described_class_spec.rb +89 -139
- data/spec/rubocop/cop/rspec/example_wording_spec.rb +20 -29
- data/spec/rubocop/cop/rspec/focus_spec.rb +115 -63
- data/spec/rubocop/cop/rspec/instance_variable_spec.rb +23 -35
- data/spec/rubocop/cop/rspec/multiple_describes_spec.rb +16 -31
- data/spec/rubocop/cop/rspec/named_subject_spec.rb +62 -0
- data/spec/rubocop/cop/rspec/not_to_not_spec.rb +14 -16
- data/spec/rubocop/cop/rspec/verified_doubles_spec.rb +39 -43
- data/spec/spec_helper.rb +5 -0
- data/spec/support/expect_violation.rb +166 -0
- metadata +51 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a5f78eba0374bbe357f1de4227be9e3b6282116
|
4
|
+
data.tar.gz: 20fa1701861557f4c615613a9f3fe3300a758ac1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 098e42022cd531df17726bc09d7d392b990d08b63c22e59a4b71e28f7a7cc23613688d93fc1f5edc97cb9e97cea1bab92d6a03ddaa0405f74e822e74e02c7744
|
7
|
+
data.tar.gz: 2461baf4ad9f1eadff4264a786bdeff878a50c164ac6576558ebabdd2b2e7870a5cc05996d419a499e9c97d7f7b32be67fd645e16f0a6c233fccb53adb0a1b15
|
data/CHANGELOG.md
CHANGED
data/config/default.yml
CHANGED
data/lib/rubocop-rspec.rb
CHANGED
@@ -19,5 +19,6 @@ require 'rubocop/cop/rspec/focus'
|
|
19
19
|
require 'rubocop/cop/rspec/instance_variable'
|
20
20
|
require 'rubocop/cop/rspec/example_length'
|
21
21
|
require 'rubocop/cop/rspec/multiple_describes'
|
22
|
+
require 'rubocop/cop/rspec/named_subject'
|
22
23
|
require 'rubocop/cop/rspec/not_to_not'
|
23
24
|
require 'rubocop/cop/rspec/verified_doubles'
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
# Give `subject` a descriptive name if you reference it directly
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# RSpec.describe User do
|
11
|
+
# subject { described_class.new }
|
12
|
+
#
|
13
|
+
# it 'is valid' do
|
14
|
+
# expect(subject.valid?).to be(true)
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# # good
|
19
|
+
# RSpec.describe Foo do
|
20
|
+
# subject(:user) { described_class.new }
|
21
|
+
#
|
22
|
+
# it 'is valid' do
|
23
|
+
# expect(user.valid?).to be(true)
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# # also good
|
28
|
+
# RSpec.describe Foo do
|
29
|
+
# subject(:user) { described_class.new }
|
30
|
+
#
|
31
|
+
# it { should be_valid }
|
32
|
+
# end
|
33
|
+
class NamedSubject < Cop
|
34
|
+
MSG = 'Name your test subject if '\
|
35
|
+
'you need to reference it explicitly.'.freeze
|
36
|
+
|
37
|
+
def_node_matcher :rspec_block?, <<-PATTERN
|
38
|
+
(block
|
39
|
+
(send nil {:it :specify :before :after :around} ...)
|
40
|
+
...)
|
41
|
+
PATTERN
|
42
|
+
|
43
|
+
def_node_matcher :unnamed_subject, '$(send nil :subject)'
|
44
|
+
|
45
|
+
def on_block(node)
|
46
|
+
return unless rspec_block?(node)
|
47
|
+
|
48
|
+
subject_usage(node) do |subject_node|
|
49
|
+
add_offense(subject_node, :selector)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def subject_usage(node, &block)
|
56
|
+
return unless node.instance_of?(Node)
|
57
|
+
|
58
|
+
unnamed_subject(node, &block)
|
59
|
+
|
60
|
+
node.children.each do |child|
|
61
|
+
subject_usage(child, &block)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/rubocop-rspec.gemspec
CHANGED
@@ -35,4 +35,7 @@ Gem::Specification.new do |spec|
|
|
35
35
|
spec.add_development_dependency 'rake'
|
36
36
|
spec.add_development_dependency 'rspec', '>= 3.4'
|
37
37
|
spec.add_development_dependency 'simplecov'
|
38
|
+
spec.add_development_dependency 'anima'
|
39
|
+
spec.add_development_dependency 'concord'
|
40
|
+
spec.add_development_dependency 'adamantium'
|
38
41
|
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe ExpectViolation::Expectation do
|
4
|
+
subject(:expectation) { described_class.new(string) }
|
5
|
+
|
6
|
+
context 'when given a single assertion on class end' do
|
7
|
+
let(:string) do
|
8
|
+
<<-SRC
|
9
|
+
class Foo
|
10
|
+
end
|
11
|
+
^^^ The end of `Foo` should be annotated.
|
12
|
+
SRC
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:assertion) { expectation.assertions.first }
|
16
|
+
|
17
|
+
it 'has one assertion' do
|
18
|
+
expect(expectation.assertions.size).to be(1)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'has an assertion on line 2' do
|
22
|
+
expect(assertion.line_number).to be(2)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'has an assertion on column range 1-3' do
|
26
|
+
expect(assertion.column_range).to eql(6...9)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'has an assertion with correct violation message' do
|
30
|
+
expect(assertion.message).to eql('The end of `Foo` should be annotated.')
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'recreates source' do
|
34
|
+
expect(expectation.source).to eql(<<-RUBY)
|
35
|
+
class Foo
|
36
|
+
end
|
37
|
+
RUBY
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'when given many assertions on two lines' do
|
42
|
+
let(:string) do
|
43
|
+
<<-SRC
|
44
|
+
foo bar
|
45
|
+
^ Charlie
|
46
|
+
^^ Charlie
|
47
|
+
^^ Bronco
|
48
|
+
^^ Alpha
|
49
|
+
baz
|
50
|
+
^ Delta
|
51
|
+
SRC
|
52
|
+
end
|
53
|
+
|
54
|
+
let(:assertions) { expectation.assertions.sort }
|
55
|
+
|
56
|
+
it 'has two assertions' do
|
57
|
+
expect(expectation.assertions.size).to be(5)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'has assertions on lines 1 and 2' do
|
61
|
+
expect(assertions.map(&:line_number)).to eql(
|
62
|
+
[1, 1, 1, 1, 2]
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'has assertions on column range 1-3' do
|
67
|
+
expect(assertions.map(&:column_range)).to eql(
|
68
|
+
[9...11, 10...11, 10...12, 10...12, 6...7]
|
69
|
+
)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'has an assertion with correct violation message' do
|
73
|
+
expect(assertions.map(&:message)).to eql(
|
74
|
+
%w(Charlie Charlie Alpha Bronco Delta)
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'recreates source' do
|
79
|
+
expect(expectation.source).to eql(<<-RUBY)
|
80
|
+
foo bar
|
81
|
+
baz
|
82
|
+
RUBY
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -2,47 +2,29 @@ describe RuboCop::Cop::RSpec::AnyInstance do
|
|
2
2
|
subject(:cop) { described_class.new }
|
3
3
|
|
4
4
|
it 'finds `allow_any_instance_of` instead of an instance double' do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
]
|
12
|
-
)
|
13
|
-
expect(cop.messages)
|
14
|
-
.to eq(['Avoid stubbing using `allow_any_instance_of`'])
|
15
|
-
expect(cop.highlights).to eq(['allow_any_instance_of(Object)'])
|
16
|
-
expect(cop.offenses.map(&:line).sort).to eq([2])
|
5
|
+
expect_violation(<<-RUBY)
|
6
|
+
before do
|
7
|
+
allow_any_instance_of(Object).to receive(:foo)
|
8
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid stubbing using `allow_any_instance_of`
|
9
|
+
end
|
10
|
+
RUBY
|
17
11
|
end
|
18
12
|
|
19
13
|
it 'finds `expect_any_instance_of` instead of an instance double' do
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
]
|
27
|
-
)
|
28
|
-
expect(cop.messages)
|
29
|
-
.to eq(['Avoid stubbing using `expect_any_instance_of`'])
|
30
|
-
expect(cop.highlights).to eq(['expect_any_instance_of(Object)'])
|
31
|
-
expect(cop.offenses.map(&:line).sort).to eq([2])
|
14
|
+
expect_violation(<<-RUBY)
|
15
|
+
before do
|
16
|
+
expect_any_instance_of(Object).to receive(:foo)
|
17
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid stubbing using `expect_any_instance_of`
|
18
|
+
end
|
19
|
+
RUBY
|
32
20
|
end
|
33
21
|
|
34
22
|
it 'finds old `any_instance` syntax instead of an instance double' do
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
]
|
42
|
-
)
|
43
|
-
expect(cop.messages)
|
44
|
-
.to eq(['Avoid stubbing using `any_instance`'])
|
45
|
-
expect(cop.highlights).to eq(['Object.any_instance'])
|
46
|
-
expect(cop.offenses.map(&:line).sort).to eq([2])
|
23
|
+
expect_violation(<<-RUBY)
|
24
|
+
before do
|
25
|
+
Object.any_instance.should_receive(:foo)
|
26
|
+
^^^^^^^^^^^^^^^^^^^ Avoid stubbing using `any_instance`
|
27
|
+
end
|
28
|
+
RUBY
|
47
29
|
end
|
48
30
|
end
|
@@ -2,109 +2,112 @@ describe RuboCop::Cop::RSpec::DescribeClass do
|
|
2
2
|
subject(:cop) { described_class.new }
|
3
3
|
|
4
4
|
it 'checks first-line describe statements' do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
expect_violation(<<-RUBY)
|
6
|
+
describe "bad describe" do
|
7
|
+
^^^^^^^^^^^^^^ The first argument to describe should be the class or module being tested.
|
8
|
+
end
|
9
|
+
RUBY
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'supports RSpec.describe' do
|
13
|
-
|
14
|
-
|
13
|
+
expect_no_violations(<<-RUBY)
|
14
|
+
RSpec.describe Foo do
|
15
|
+
end
|
16
|
+
RUBY
|
15
17
|
end
|
16
18
|
|
17
19
|
it 'checks describe statements after a require' do
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
)
|
25
|
-
expect(cop.offenses.size).to eq(1)
|
26
|
-
expect(cop.offenses.map(&:line).sort).to eq([2])
|
27
|
-
expect(cop.messages).to eq(['The first argument to describe should be ' \
|
28
|
-
'the class or module being tested.'])
|
20
|
+
expect_violation(<<-RUBY)
|
21
|
+
require 'spec_helper'
|
22
|
+
describe "bad describe" do
|
23
|
+
^^^^^^^^^^^^^^ The first argument to describe should be the class or module being tested.
|
24
|
+
end
|
25
|
+
RUBY
|
29
26
|
end
|
30
27
|
|
31
28
|
it 'checks highlights the first argument of a describe' do
|
32
|
-
|
33
|
-
|
29
|
+
expect_violation(<<-RUBY)
|
30
|
+
describe "bad describe", "blah blah" do
|
31
|
+
^^^^^^^^^^^^^^ The first argument to describe should be the class or module being tested.
|
32
|
+
end
|
33
|
+
RUBY
|
34
34
|
end
|
35
35
|
|
36
36
|
it 'ignores nested describe statements' do
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
]
|
44
|
-
)
|
45
|
-
expect(cop.offenses).to be_empty
|
37
|
+
expect_no_violations(<<-RUBY)
|
38
|
+
describe Some::Class do
|
39
|
+
describe "bad describe" do
|
40
|
+
end
|
41
|
+
end
|
42
|
+
RUBY
|
46
43
|
end
|
47
44
|
|
48
45
|
it 'ignores request specs' do
|
49
|
-
|
50
|
-
|
46
|
+
expect_no_violations(<<-RUBY)
|
47
|
+
describe 'my new feature', type: :request do
|
48
|
+
end
|
49
|
+
RUBY
|
51
50
|
end
|
52
51
|
|
53
52
|
it 'ignores feature specs' do
|
54
|
-
|
55
|
-
|
53
|
+
expect_no_violations(<<-RUBY)
|
54
|
+
describe 'my new feature', type: :feature do
|
55
|
+
end
|
56
|
+
RUBY
|
56
57
|
end
|
57
58
|
|
58
59
|
it 'ignores feature specs when RSpec.describe is used' do
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
expect(cop.offenses).to be_empty
|
60
|
+
expect_no_violations(<<-RUBY)
|
61
|
+
RSpec.describe 'my new feature', type: :feature do
|
62
|
+
end
|
63
|
+
RUBY
|
65
64
|
end
|
66
65
|
|
67
66
|
it 'flags specs with non :type metadata' do
|
68
|
-
|
69
|
-
|
70
|
-
|
67
|
+
expect_violation(<<-RUBY)
|
68
|
+
describe 'my new feature', foo: :feature do
|
69
|
+
^^^^^^^^^^^^^^^^ The first argument to describe should be the class or module being tested.
|
70
|
+
end
|
71
|
+
RUBY
|
71
72
|
end
|
72
73
|
|
73
74
|
it 'flags normal metadata in describe' do
|
74
|
-
|
75
|
-
|
76
|
-
|
75
|
+
expect_violation(<<-RUBY)
|
76
|
+
describe 'my new feature', blah, type: :wow do
|
77
|
+
^^^^^^^^^^^^^^^^ The first argument to describe should be the class or module being tested.
|
78
|
+
end
|
79
|
+
RUBY
|
77
80
|
end
|
78
81
|
|
79
82
|
it 'ignores feature specs - also with complex options' do
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
' :test, :type => :feature, :foo => :bar do;',
|
85
|
-
'end'
|
86
|
-
]
|
87
|
-
)
|
88
|
-
expect(cop.offenses).to be_empty
|
83
|
+
expect_no_violations(<<-RUBY)
|
84
|
+
describe 'my new feature', :test, :type => :feature, :foo => :bar do
|
85
|
+
end
|
86
|
+
RUBY
|
89
87
|
end
|
90
88
|
|
91
89
|
it 'ignores an empty describe' do
|
92
|
-
|
93
|
-
|
90
|
+
expect_no_violations(<<-RUBY)
|
91
|
+
describe do
|
92
|
+
end
|
93
|
+
RUBY
|
94
94
|
end
|
95
95
|
|
96
96
|
it 'ignores routing specs' do
|
97
|
-
|
98
|
-
|
97
|
+
expect_no_violations(<<-RUBY)
|
98
|
+
describe 'my new route', type: :routing do
|
99
|
+
end
|
100
|
+
RUBY
|
99
101
|
end
|
100
102
|
|
101
103
|
it 'ignores view specs' do
|
102
|
-
|
103
|
-
|
104
|
+
expect_no_violations(<<-RUBY)
|
105
|
+
describe 'widgets/index', type: :view do
|
106
|
+
end
|
107
|
+
RUBY
|
104
108
|
end
|
105
109
|
|
106
110
|
it "doesn't blow up on single-line describes" do
|
107
|
-
|
108
|
-
expect(cop.offenses).to be_empty
|
111
|
+
expect_no_violations('describe Some::Class')
|
109
112
|
end
|
110
113
|
end
|