rubocop-rspec 1.33.0 → 1.34.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.
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