rubocop-rspec 1.33.0 → 1.34.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -2
  3. data/README.md +10 -2
  4. data/config/default.yml +6 -1
  5. data/lib/rubocop/cop/rspec/any_instance.rb +0 -1
  6. data/lib/rubocop/cop/rspec/around_block.rb +1 -2
  7. data/lib/rubocop/cop/rspec/before_after_all.rb +0 -1
  8. data/lib/rubocop/cop/rspec/context_wording.rb +18 -17
  9. data/lib/rubocop/cop/rspec/describe_class.rb +1 -1
  10. data/lib/rubocop/cop/rspec/describe_method.rb +1 -1
  11. data/lib/rubocop/cop/rspec/describe_symbol.rb +1 -1
  12. data/lib/rubocop/cop/rspec/described_class.rb +79 -13
  13. data/lib/rubocop/cop/rspec/empty_example_group.rb +1 -1
  14. data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +1 -1
  15. data/lib/rubocop/cop/rspec/example_length.rb +1 -1
  16. data/lib/rubocop/cop/rspec/example_wording.rb +6 -4
  17. data/lib/rubocop/cop/rspec/expect_actual.rb +1 -1
  18. data/lib/rubocop/cop/rspec/expect_output.rb +2 -0
  19. data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +1 -1
  20. data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +1 -2
  21. data/lib/rubocop/cop/rspec/file_path.rb +0 -1
  22. data/lib/rubocop/cop/rspec/focus.rb +1 -1
  23. data/lib/rubocop/cop/rspec/hook_argument.rb +0 -1
  24. data/lib/rubocop/cop/rspec/instance_spy.rb +1 -1
  25. data/lib/rubocop/cop/rspec/instance_variable.rb +1 -1
  26. data/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb +1 -1
  27. data/lib/rubocop/cop/rspec/it_behaves_like.rb +1 -1
  28. data/lib/rubocop/cop/rspec/iterated_expectation.rb +1 -1
  29. data/lib/rubocop/cop/rspec/leading_subject.rb +0 -1
  30. data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +128 -0
  31. data/lib/rubocop/cop/rspec/let_before_examples.rb +1 -1
  32. data/lib/rubocop/cop/rspec/let_setup.rb +2 -4
  33. data/lib/rubocop/cop/rspec/missing_example_group_argument.rb +1 -2
  34. data/lib/rubocop/cop/rspec/multiple_describes.rb +1 -1
  35. data/lib/rubocop/cop/rspec/multiple_expectations.rb +32 -16
  36. data/lib/rubocop/cop/rspec/multiple_subjects.rb +1 -1
  37. data/lib/rubocop/cop/rspec/nested_groups.rb +0 -1
  38. data/lib/rubocop/cop/rspec/overwriting_setup.rb +0 -1
  39. data/lib/rubocop/cop/rspec/pending.rb +1 -1
  40. data/lib/rubocop/cop/rspec/predicate_matcher.rb +0 -3
  41. data/lib/rubocop/cop/rspec/repeated_description.rb +1 -1
  42. data/lib/rubocop/cop/rspec/repeated_example.rb +1 -1
  43. data/lib/rubocop/cop/rspec/scattered_let.rb +1 -1
  44. data/lib/rubocop/cop/rspec/scattered_setup.rb +1 -1
  45. data/lib/rubocop/cop/rspec/shared_context.rb +0 -1
  46. data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +1 -1
  47. data/lib/rubocop/cop/rspec/subject_stub.rb +17 -20
  48. data/lib/rubocop/cop/rspec/unspecified_exception.rb +1 -4
  49. data/lib/rubocop/cop/rspec/verified_doubles.rb +1 -1
  50. data/lib/rubocop/cop/rspec/void_expect.rb +1 -1
  51. data/lib/rubocop/cop/rspec_cops.rb +1 -0
  52. data/lib/rubocop/rspec/language.rb +1 -1
  53. data/lib/rubocop/rspec/top_level_describe.rb +0 -4
  54. data/lib/rubocop/rspec/version.rb +1 -1
  55. data/spec/rubocop/cop/rspec/cop_spec.rb +3 -3
  56. data/spec/rubocop/cop/rspec/describe_class_spec.rb +7 -0
  57. data/spec/rubocop/cop/rspec/described_class_spec.rb +113 -80
  58. data/spec/rubocop/cop/rspec/example_wording_spec.rb +33 -0
  59. data/spec/rubocop/cop/rspec/leaky_constant_declaration_spec.rb +91 -0
  60. data/spec/rubocop/cop/rspec/let_setup_spec.rb +2 -2
  61. data/spec/rubocop/cop/rspec/multiple_expectations_spec.rb +64 -37
  62. data/spec/rubocop/cop/rspec/subject_stub_spec.rb +113 -14
  63. data/spec/rubocop/rspec/language/selector_set_spec.rb +2 -2
  64. metadata +5 -2
@@ -28,6 +28,19 @@ RSpec.describe RuboCop::Cop::RSpec::ExampleWording, :config do
28
28
  RUBY
29
29
  end
30
30
 
31
+ it 'finds interpolated description with `should` at the beginning' do
32
+ expect_offense(<<-'RUBY')
33
+ it "should do #{:stuff}" do
34
+ ^^^^^^^^^^^^^^^^^^^ Do not use should when describing your tests.
35
+ end
36
+ RUBY
37
+
38
+ expect_correction(<<-'RUBY')
39
+ it "does #{:stuff}" do
40
+ end
41
+ RUBY
42
+ end
43
+
31
44
  it 'finds description with `Should` at the beginning' do
32
45
  expect_offense(<<-RUBY)
33
46
  it 'Should do something' do
@@ -106,6 +119,19 @@ RSpec.describe RuboCop::Cop::RSpec::ExampleWording, :config do
106
119
  RUBY
107
120
  end
108
121
 
122
+ it 'finds leading it in interpolated description' do
123
+ expect_offense(<<-'RUBY')
124
+ it "it does #{action}" do
125
+ ^^^^^^^^^^^^^^^^^ Do not repeat 'it' when describing your tests.
126
+ end
127
+ RUBY
128
+
129
+ expect_correction(<<-'RUBY')
130
+ it "does #{action}" do
131
+ end
132
+ RUBY
133
+ end
134
+
109
135
  it "skips words beginning with 'it'" do
110
136
  expect_no_offenses(<<-RUBY)
111
137
  it 'itemizes items' do
@@ -126,6 +152,13 @@ RSpec.describe RuboCop::Cop::RSpec::ExampleWording, :config do
126
152
  end
127
153
  RUBY
128
154
  end
155
+
156
+ it 'skips interpolated description without literal `should` at the start' do
157
+ expect_no_offenses(<<-'RUBY')
158
+ it "#{should} not be here" do
159
+ end
160
+ RUBY
161
+ end
129
162
  end
130
163
 
131
164
  context 'when configuration is empty' do
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe RuboCop::Cop::RSpec::LeakyConstantDeclaration do
4
+ subject(:cop) { described_class.new }
5
+
6
+ describe 'constant assignment' do
7
+ it 'flags inside an example group' do
8
+ expect_offense(<<-RUBY)
9
+ describe SomeClass do
10
+ CONSTANT = "Accessible as ::CONSTANT".freeze
11
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Stub constant instead of declaring explicitly.
12
+ end
13
+ RUBY
14
+ end
15
+
16
+ it 'flags inside shared example group' do
17
+ expect_offense(<<-RUBY)
18
+ RSpec.shared_examples 'shared example' do
19
+ CONSTANT = "Accessible as ::CONSTANT".freeze
20
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Stub constant instead of declaring explicitly.
21
+ end
22
+ RUBY
23
+ end
24
+
25
+ it 'flags inside an example' do
26
+ expect_offense(<<-RUBY)
27
+ describe SomeClass do
28
+ specify do
29
+ CONSTANT = "Accessible as ::CONSTANT".freeze
30
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Stub constant instead of declaring explicitly.
31
+ end
32
+ end
33
+ RUBY
34
+ end
35
+
36
+ it 'ignores outside of example/shared group' do
37
+ expect_no_offenses(<<-RUBY)
38
+ factory :some_class do
39
+ CONSTANT = "Accessible as ::CONSTANT".freeze
40
+ end
41
+ RUBY
42
+ end
43
+ end
44
+
45
+ describe 'class defined' do
46
+ it 'flags inside an example group' do
47
+ expect_offense(<<-RUBY)
48
+ describe SomeClass do
49
+ class DummyClass < described_class
50
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Stub class constant instead of declaring explicitly.
51
+ end
52
+ end
53
+ RUBY
54
+ end
55
+
56
+ it 'ignores anonymous classes' do
57
+ expect_no_offenses(<<-RUBY)
58
+ describe SomeClass do
59
+ let(:dummy_playbook) do
60
+ Class.new do
61
+ def method
62
+ end
63
+ end
64
+ end
65
+ end
66
+ RUBY
67
+ end
68
+
69
+ it 'flags namespaced class' do
70
+ expect_offense(<<-RUBY)
71
+ describe SomeClass do
72
+ class SomeModule::AnotherModule::DummyClass
73
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Stub class constant instead of declaring explicitly.
74
+ end
75
+ end
76
+ RUBY
77
+ end
78
+ end
79
+
80
+ describe 'module defined' do
81
+ it 'flags inside an example group' do
82
+ expect_offense(<<-RUBY)
83
+ describe SomeClass do
84
+ module DummyModule
85
+ ^^^^^^^^^^^^^^^^^^ Stub module constant instead of declaring explicitly.
86
+ end
87
+ end
88
+ RUBY
89
+ end
90
+ end
91
+ end
@@ -7,7 +7,7 @@ RSpec.describe RuboCop::Cop::RSpec::LetSetup do
7
7
  expect_offense(<<-RUBY)
8
8
  describe Foo do
9
9
  let!(:foo) { bar }
10
- ^^^^^^^^^^ Do not use `let!` for test setup.
10
+ ^^^^^^^^^^ Do not use `let!` to setup objects not referenced in tests.
11
11
 
12
12
  it 'does not use foo' do
13
13
  expect(baz).to eq(qux)
@@ -50,7 +50,7 @@ RSpec.describe RuboCop::Cop::RSpec::LetSetup do
50
50
  describe Foo do
51
51
  context 'when something special happens' do
52
52
  let!(:foo) { bar }
53
- ^^^^^^^^^^ Do not use `let!` for test setup.
53
+ ^^^^^^^^^^ Do not use `let!` to setup objects not referenced in tests.
54
54
 
55
55
  it 'does not use foo' do
56
56
  expect(baz).to eq(qux)
@@ -96,11 +96,11 @@ RSpec.describe RuboCop::Cop::RSpec::MultipleExpectations, :config do
96
96
  end
97
97
  end
98
98
 
99
- context 'with meta data' do
99
+ context 'with metadata' do
100
100
  it 'ignores examples with `:aggregate_failures`' do
101
101
  expect_no_offenses(<<-RUBY)
102
102
  describe Foo do
103
- it 'uses expect twice', :aggregate_failures do
103
+ it 'uses expect twice', :foo, :aggregate_failures do
104
104
  expect(foo).to eq(bar)
105
105
  expect(baz).to eq(bar)
106
106
  end
@@ -108,10 +108,10 @@ RSpec.describe RuboCop::Cop::RSpec::MultipleExpectations, :config do
108
108
  RUBY
109
109
  end
110
110
 
111
- it 'ignores examples with `aggregate_failures: true`' do
111
+ it 'ignores example groups with `:aggregate_failures`' do
112
112
  expect_no_offenses(<<-RUBY)
113
- describe Foo do
114
- it 'uses expect twice', aggregate_failures: true do
113
+ describe Foo, :foo, :aggregate_failures do
114
+ it 'uses expect twice' do
115
115
  expect(foo).to eq(bar)
116
116
  expect(baz).to eq(bar)
117
117
  end
@@ -119,27 +119,20 @@ RSpec.describe RuboCop::Cop::RSpec::MultipleExpectations, :config do
119
119
  RUBY
120
120
  end
121
121
 
122
- it 'checks examples with `aggregate_failures: false`' do
123
- expect_offense(<<-RUBY)
122
+ it 'ignores examples with `aggregate_failures: true`' do
123
+ expect_no_offenses(<<-RUBY)
124
124
  describe Foo do
125
- it 'uses expect twice', aggregate_failures: false do
126
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Example has too many expectations [2/1].
125
+ it 'uses expect twice', :foo, bar: 1, aggregate_failures: true do
127
126
  expect(foo).to eq(bar)
128
127
  expect(baz).to eq(bar)
129
128
  end
130
129
  end
131
130
  RUBY
132
131
  end
133
- end
134
132
 
135
- context 'with Max configuration' do
136
- let(:cop_config) do
137
- { 'Max' => '2' }
138
- end
139
-
140
- it 'permits two expectations' do
133
+ it 'ignores example groups with `aggregate_failures: true`' do
141
134
  expect_no_offenses(<<-RUBY)
142
- describe Foo do
135
+ describe Foo, :foo, bar: 1, aggregate_failures: true do
143
136
  it 'uses expect twice' do
144
137
  expect(foo).to eq(bar)
145
138
  expect(baz).to eq(bar)
@@ -148,29 +141,35 @@ RSpec.describe RuboCop::Cop::RSpec::MultipleExpectations, :config do
148
141
  RUBY
149
142
  end
150
143
 
151
- it 'flags three expectations' do
144
+ it 'prefers example metadata over example group metadata' do
152
145
  expect_offense(<<-RUBY)
153
- describe Foo do
154
- it 'uses expect three times' do
155
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Example has too many expectations [3/2].
146
+ describe Foo, aggregate_failures: true do
147
+ it 'uses expect twice', aggregate_failures: false do
148
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Example has too many expectations [2/1].
156
149
  expect(foo).to eq(bar)
157
150
  expect(baz).to eq(bar)
158
- expect(qux).to eq(bar)
159
151
  end
160
152
  end
161
153
  RUBY
162
154
  end
163
- end
164
155
 
165
- context 'with AggregateFailuresByDefault configuration' do
166
- let(:cop_config) do
167
- { 'AggregateFailuresByDefault' => true }
156
+ it 'checks examples with `aggregate_failures: false`' do
157
+ expect_offense(<<-RUBY)
158
+ describe Foo do
159
+ it 'uses expect twice', aggregate_failures: false do
160
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Example has too many expectations [2/1].
161
+ expect(foo).to eq(bar)
162
+ expect(baz).to eq(bar)
163
+ end
164
+ end
165
+ RUBY
168
166
  end
169
167
 
170
- it 'ignores examples without metadata' do
171
- expect_no_offenses(<<-RUBY)
172
- describe Foo do
168
+ it 'checks example groups with `aggregate_failures: false`' do
169
+ expect_offense(<<-RUBY)
170
+ describe Foo, aggregate_failures: false do
173
171
  it 'uses expect twice' do
172
+ ^^^^^^^^^^^^^^^^^^^^^^ Example has too many expectations [2/1].
174
173
  expect(foo).to eq(bar)
175
174
  expect(baz).to eq(bar)
176
175
  end
@@ -178,10 +177,15 @@ RSpec.describe RuboCop::Cop::RSpec::MultipleExpectations, :config do
178
177
  RUBY
179
178
  end
180
179
 
181
- it 'ignores examples with `:aggregate_failures`' do
182
- expect_no_offenses(<<-RUBY)
180
+ it 'checks examples with siblings with `aggregate_failures: true`' do
181
+ expect_offense(<<-RUBY)
183
182
  describe Foo do
184
- it 'uses expect twice', :aggregate_failures do
183
+ it 'uses expect twice' do
184
+ ^^^^^^^^^^^^^^^^^^^^^^ Example has too many expectations [2/1].
185
+ expect(foo).to eq(bar)
186
+ expect(baz).to eq(bar)
187
+ end
188
+ it 'with aggregate_failures', aggregate_failures: true do
185
189
  expect(foo).to eq(bar)
186
190
  expect(baz).to eq(bar)
187
191
  end
@@ -189,10 +193,32 @@ RSpec.describe RuboCop::Cop::RSpec::MultipleExpectations, :config do
189
193
  RUBY
190
194
  end
191
195
 
192
- it 'ignores examples with `aggregate_failures: true`' do
196
+ it 'ignores examples with `aggregate_failures: true` defined deeply' do
197
+ expect_no_offenses(<<-RUBY)
198
+ describe Bar, aggregate_failures: true do
199
+ describe Foo do
200
+ it 'uses expect twice' do
201
+ expect(foo).to eq(bar)
202
+ expect(baz).to eq(bar)
203
+ end
204
+ it 'with aggregate_failures', aggregate_failures: false do
205
+ expect(foo).to eq(bar)
206
+ end
207
+ end
208
+ end
209
+ RUBY
210
+ end
211
+ end
212
+
213
+ context 'with Max configuration' do
214
+ let(:cop_config) do
215
+ { 'Max' => '2' }
216
+ end
217
+
218
+ it 'permits two expectations' do
193
219
  expect_no_offenses(<<-RUBY)
194
220
  describe Foo do
195
- it 'uses expect twice', aggregate_failures: true do
221
+ it 'uses expect twice' do
196
222
  expect(foo).to eq(bar)
197
223
  expect(baz).to eq(bar)
198
224
  end
@@ -200,13 +226,14 @@ RSpec.describe RuboCop::Cop::RSpec::MultipleExpectations, :config do
200
226
  RUBY
201
227
  end
202
228
 
203
- it 'checks examples with `aggregate_failures: false`' do
229
+ it 'flags three expectations' do
204
230
  expect_offense(<<-RUBY)
205
231
  describe Foo do
206
- it 'uses expect twice', aggregate_failures: false do
207
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Example has too many expectations [2/1].
232
+ it 'uses expect three times' do
233
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Example has too many expectations [3/2].
208
234
  expect(foo).to eq(bar)
209
235
  expect(baz).to eq(bar)
236
+ expect(qux).to eq(bar)
210
237
  end
211
238
  end
212
239
  RUBY
@@ -3,14 +3,14 @@
3
3
  RSpec.describe RuboCop::Cop::RSpec::SubjectStub do
4
4
  subject(:cop) { described_class.new }
5
5
 
6
- it 'complains when subject is stubbed' do
6
+ it 'flags when subject is stubbed' do
7
7
  expect_offense(<<-RUBY)
8
8
  describe Foo do
9
9
  subject(:foo) { described_class.new }
10
10
 
11
11
  before do
12
12
  allow(foo).to receive(:bar).and_return(baz)
13
- ^^^^^^^^^^ Do not stub your test subject.
13
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
14
14
  end
15
15
 
16
16
  it 'uses expect twice' do
@@ -20,20 +20,20 @@ RSpec.describe RuboCop::Cop::RSpec::SubjectStub do
20
20
  RUBY
21
21
  end
22
22
 
23
- it 'complains when subject is mocked' do
23
+ it 'flags when subject is mocked' do
24
24
  expect_offense(<<-RUBY)
25
25
  describe Foo do
26
26
  subject(:foo) { described_class.new }
27
27
 
28
28
  before do
29
29
  expect(foo).to receive(:bar).and_return(baz)
30
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub your test subject.
30
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
31
31
  expect(foo).to receive(:bar)
32
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub your test subject.
32
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
33
33
  expect(foo).to receive(:bar).with(1)
34
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub your test subject.
34
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
35
35
  expect(foo).to receive(:bar).with(1).and_return(2)
36
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub your test subject.
36
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
37
37
  end
38
38
 
39
39
  it 'uses expect twice' do
@@ -43,6 +43,45 @@ RSpec.describe RuboCop::Cop::RSpec::SubjectStub do
43
43
  RUBY
44
44
  end
45
45
 
46
+ it 'flags when an unnamed subject is mocked' do
47
+ expect_offense(<<-RUBY)
48
+ describe Foo do
49
+ subject { described_class.new }
50
+
51
+ it 'uses unnamed subject' do
52
+ expect(subject).to receive(:bar)
53
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
54
+ end
55
+ end
56
+ RUBY
57
+ end
58
+
59
+ it 'flags an expectation made on an unnamed subject' do
60
+ expect_offense(<<-RUBY)
61
+ describe Foo do
62
+ subject(:foo) { described_class.new }
63
+
64
+ it 'uses unnamed subject' do
65
+ expect(subject).to receive(:bar)
66
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
67
+ end
68
+ end
69
+ RUBY
70
+ end
71
+
72
+ it 'flags one-line expectcation syntax' do
73
+ expect_offense(<<-RUBY)
74
+ describe Foo do
75
+ subject(:foo) { described_class.new }
76
+
77
+ it 'uses one-line expectation syntax' do
78
+ is_expected.to receive(:bar)
79
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
80
+ end
81
+ end
82
+ RUBY
83
+ end
84
+
46
85
  it 'ignores stub within context where subject name changed' do
47
86
  expect_no_offenses(<<-RUBY)
48
87
  describe Foo do
@@ -59,12 +98,13 @@ RSpec.describe RuboCop::Cop::RSpec::SubjectStub do
59
98
  RUBY
60
99
  end
61
100
 
62
- it 'ignores stub when inside all matcher' do
63
- expect_no_offenses(<<-RUBY)
101
+ it 'flags stub inside all matcher' do
102
+ expect_offense(<<-RUBY)
64
103
  describe Foo do
65
104
  subject(:foo) { [Object.new] }
66
105
  it 'tries to trick rubocop-rspec' do
67
106
  expect(foo).to all(receive(:baz))
107
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
68
108
  end
69
109
  end
70
110
  RUBY
@@ -80,7 +120,7 @@ RSpec.describe RuboCop::Cop::RSpec::SubjectStub do
80
120
 
81
121
  before do
82
122
  allow(foo).to receive(:wow)
83
- ^^^^^^^^^^ Do not stub your test subject.
123
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
84
124
  end
85
125
 
86
126
  it 'tries to trick rubocop-rspec' do
@@ -119,7 +159,7 @@ RSpec.describe RuboCop::Cop::RSpec::SubjectStub do
119
159
  context 'when I shake things up' do
120
160
  before do
121
161
  allow(foo).to receive(:wow)
122
- ^^^^^^^^^^ Do not stub your test subject.
162
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
123
163
  end
124
164
 
125
165
  it 'tries to trick rubocop-rspec' do
@@ -141,7 +181,7 @@ RSpec.describe RuboCop::Cop::RSpec::SubjectStub do
141
181
  before do
142
182
  allow(foo).to receive(:wow)
143
183
  allow(bar).to receive(:wow)
144
- ^^^^^^^^^^ Do not stub your test subject.
184
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
145
185
  end
146
186
 
147
187
  it 'tries to trick rubocop-rspec' do
@@ -163,7 +203,7 @@ RSpec.describe RuboCop::Cop::RSpec::SubjectStub do
163
203
 
164
204
  it 'still flags this test' do
165
205
  allow(foo).to receive(:blah)
166
- ^^^^^^^^^^ Do not stub your test subject.
206
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
167
207
  end
168
208
  end
169
209
  RUBY
@@ -184,11 +224,70 @@ RSpec.describe RuboCop::Cop::RSpec::SubjectStub do
184
224
  allow(foo).to receive(:wow)
185
225
  allow(bar).to receive(:wow)
186
226
  allow(baz).to receive(:wow)
187
- ^^^^^^^^^^ Do not stub your test subject.
227
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
188
228
  end
189
229
  end
190
230
  end
191
231
  end
192
232
  RUBY
193
233
  end
234
+
235
+ it 'flags negated runners' do
236
+ expect_offense(<<-RUBY)
237
+ describe Foo do
238
+ subject(:foo) { described_class.new }
239
+
240
+ specify do
241
+ expect(foo).not_to receive(:bar)
242
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
243
+ expect(foo).to_not receive(:bar)
244
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
245
+ expect(foo.bar).to eq(baz)
246
+ end
247
+ end
248
+ RUBY
249
+ end
250
+
251
+ it 'flags multiple-method stubs' do
252
+ expect_offense(<<-RUBY)
253
+ describe Foo do
254
+ subject(:foo) { described_class.new }
255
+
256
+ specify do
257
+ expect(foo).to receive_messages(bar: :baz, baz: :baz)
258
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
259
+ expect(foo.bar).to eq(baz)
260
+ end
261
+ end
262
+ RUBY
263
+ end
264
+
265
+ it 'flags chain stubs' do
266
+ expect_offense(<<-RUBY)
267
+ describe Foo do
268
+ subject(:foo) { described_class.new }
269
+
270
+ specify do
271
+ expect(foo).to receive_message_chain(:bar, baz: :baz)
272
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
273
+ expect(foo.bar.baz).to eq(baz)
274
+ end
275
+ end
276
+ RUBY
277
+ end
278
+
279
+ it 'flags spy subject stubs' do
280
+ expect_offense(<<-RUBY)
281
+ describe Foo do
282
+ subject(:foo) { described_class.new }
283
+
284
+ specify do
285
+ allow(foo).to some_matcher_that_allows_a_bar_message
286
+ expect(foo.bar).to eq(baz)
287
+ expect(foo).to have_received(:bar)
288
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not stub methods of the object under test.
289
+ end
290
+ end
291
+ RUBY
292
+ end
194
293
  end