rubocop-rspec 1.5.2 → 1.5.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|