rubocop-rspec 1.29.1 → 1.30.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5bb37f4e34447ecf1e1f30484aa0d861a624e71e60b2c21d16c67f5a20d95b13
4
- data.tar.gz: db2a1555891ba75ac4ee956c6e9d97e85b95923edde3e7584f818d2fe2cddc85
3
+ metadata.gz: 0a59e8fa42b2cb3434cc923508e5fb7fb23959eea5912588425575216966173c
4
+ data.tar.gz: e0a0419763273fba02709cd92c1c86c6704398e24947d29d9499df29cf60efec
5
5
  SHA512:
6
- metadata.gz: 7db598400632086657e6b590ff999aee6a9ce46e3443edaa133af3e8d0411d0669a2ed360cc05360b8748c6694ad0d5a3dd5783dc39e06be7136dcf8554673e4
7
- data.tar.gz: 83815cc74d3261b5e05cb0d3ab760dfa0c5c3448ac0595d70392ed4d45d9ccc388c1026ae4202a72128c5945976d6eba04ac60f0729fc8c0f4df8b5a2c63e2c0
6
+ metadata.gz: 9bc9fa634cc51edc446f4ea65f8590fedafbcb754b5667383aa3f0b71cc5a8aaff114f40d093d261a43b642efdb23f8ac2a39047fab2b9104c768362ab0c2569
7
+ data.tar.gz: b5c52f755b673b2f0fd1a3075a1b1a61060f4216f2b1548a24e4622da5a93f9ada94c39d4abc9644d92bae22cd5019c89693a3d1d6cd32952c748dbfdf8b554f
@@ -2,6 +2,14 @@
2
2
 
3
3
  ## Master (Unreleased)
4
4
 
5
+ ## 1.30.0 (2018-10-08)
6
+
7
+ * Add config to `RSpec/VerifiedDoubles` to enforcement of verification on unnamed doubles. ([@BrentWheeldon][])
8
+ * Fix `FactoryBot/AttributeDefinedStatically` not working when there is a non-symbol key. ([@vzvu3k6k][])
9
+ * Fix false positive in `RSpec/ImplicitSubject` when `is_expected` is used inside `its()` block. ([@Darhazer][])
10
+ * Add `single_statement_only` style to `RSpec/ImplicitSubject` as a more relaxed alternative to `single_line_only`. ([@Darhazer][])
11
+ * Add `RSpec/UnspecifiedException` as a default cop to encourage more-specific `expect{}.to raise_error(ExceptionType)`, or `raise_exception` style handling of exceptions. ([@daveworth][])
12
+
5
13
  ## 1.29.1 (2018-09-01)
6
14
 
7
15
  * Fix false negative in `FactoryBot/AttributeDefinedStatically` when attribute is defined on `self`. ([@Darhazer][])
@@ -374,3 +382,6 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
374
382
  [@tdeo]: https://github.com/tdeo
375
383
  [@composerinteralia]: https://github.com/composerinteralia
376
384
  [@seanpdoyle]: https://github.com/seanpdoyle
385
+ [@vzvu3k6k]: https://github.com/vzvu3k6k
386
+ [@BrentWheeldon]: https://github.com/BrentWheeldon
387
+ [@daveworth]: https://github.com/daveworth
@@ -10,16 +10,6 @@ AllCops:
10
10
  - spec/factories/**/*.rb
11
11
  - features/support/factories/**/*.rb
12
12
 
13
- RSpec/AnyInstance:
14
- Description: Check that instances are not being stubbed globally.
15
- Enabled: true
16
- StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AnyInstance
17
-
18
- RSpec/AroundBlock:
19
- Description: Checks that around blocks actually run the test.
20
- Enabled: true
21
- StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AroundBlock
22
-
23
13
  RSpec/AlignLeftLetBrace:
24
14
  Description: Checks that left braces for adjacent single line lets are aligned.
25
15
  Enabled: false
@@ -30,6 +20,16 @@ RSpec/AlignRightLetBrace:
30
20
  Enabled: false
31
21
  StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AlignRightLetBrace
32
22
 
23
+ RSpec/AnyInstance:
24
+ Description: Check that instances are not being stubbed globally.
25
+ Enabled: true
26
+ StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AnyInstance
27
+
28
+ RSpec/AroundBlock:
29
+ Description: Checks that around blocks actually run the test.
30
+ Enabled: true
31
+ StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/AroundBlock
32
+
33
33
  RSpec/Be:
34
34
  Description: Check for expectations where `be` is used without argument.
35
35
  Enabled: true
@@ -63,16 +63,6 @@ RSpec/DescribeClass:
63
63
  Enabled: true
64
64
  StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeClass
65
65
 
66
- RSpec/DescribedClass:
67
- Description: Checks that tests use `described_class`.
68
- SkipBlocks: false
69
- Enabled: true
70
- EnforcedStyle: described_class
71
- SupportedStyles:
72
- - described_class
73
- - explicit
74
- StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribedClass
75
-
76
66
  RSpec/DescribeMethod:
77
67
  Description: Checks that the second argument to `describe` specifies a method.
78
68
  Enabled: true
@@ -83,10 +73,15 @@ RSpec/DescribeSymbol:
83
73
  Enabled: true
84
74
  StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribeSymbol
85
75
 
86
- RSpec/IteratedExpectation:
87
- Description: Check that `all` matcher is used instead of iterating over an array.
76
+ RSpec/DescribedClass:
77
+ Description: Checks that tests use `described_class`.
78
+ SkipBlocks: false
88
79
  Enabled: true
89
- StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IteratedExpectation
80
+ EnforcedStyle: described_class
81
+ SupportedStyles:
82
+ - described_class
83
+ - explicit
84
+ StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DescribedClass
90
85
 
91
86
  RSpec/EmptyExampleGroup:
92
87
  Description: Checks if an example group does not include any tests.
@@ -211,6 +206,7 @@ RSpec/ImplicitSubject:
211
206
  EnforcedStyle: single_line_only
212
207
  SupportedStyles:
213
208
  - single_line_only
209
+ - single_statement_only
214
210
  - disallow
215
211
  StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ImplicitSubject
216
212
 
@@ -239,6 +235,11 @@ RSpec/ItBehavesLike:
239
235
  - it_should_behave_like
240
236
  StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ItBehavesLike
241
237
 
238
+ RSpec/IteratedExpectation:
239
+ Description: Check that `all` matcher is used instead of iterating over an array.
240
+ Enabled: true
241
+ StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/IteratedExpectation
242
+
242
243
  RSpec/LeadingSubject:
243
244
  Description: Enforce that subject is the first definition in the test.
244
245
  Enabled: true
@@ -329,6 +330,16 @@ RSpec/Pending:
329
330
  Description: Checks for any pending or skipped examples.
330
331
  StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Pending
331
332
 
333
+ RSpec/PredicateMatcher:
334
+ Description: Prefer using predicate matcher over using predicate method directly.
335
+ Enabled: true
336
+ Strict: true
337
+ EnforcedStyle: inflected
338
+ SupportedStyles:
339
+ - inflected
340
+ - explicit
341
+ StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/PredicateMatcher
342
+
332
343
  RSpec/ReceiveCounts:
333
344
  Enabled: true
334
345
  Description: Check for `once` and `twice` receive counts matchers usage.
@@ -358,6 +369,16 @@ RSpec/ReturnFromStub:
358
369
  - block
359
370
  StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ReturnFromStub
360
371
 
372
+ RSpec/ScatteredLet:
373
+ Description: Checks for let scattered across the example group.
374
+ Enabled: true
375
+ StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ScatteredLet
376
+
377
+ RSpec/ScatteredSetup:
378
+ Description: Checks for setup scattered across multiple hooks in an example group.
379
+ Enabled: true
380
+ StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ScatteredSetup
381
+
361
382
  RSpec/SharedContext:
362
383
  Description: Checks for proper shared_context and shared_examples usage.
363
384
  Enabled: true
@@ -373,34 +394,20 @@ RSpec/SingleArgumentMessageChain:
373
394
  Enabled: true
374
395
  StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SingleArgumentMessageChain
375
396
 
376
- RSpec/ScatteredLet:
377
- Description: Checks for let scattered across the example group.
378
- Enabled: true
379
- StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ScatteredLet
380
-
381
- RSpec/ScatteredSetup:
382
- Description: Checks for setup scattered across multiple hooks in an example group.
383
- Enabled: true
384
- StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ScatteredSetup
385
-
386
397
  RSpec/SubjectStub:
387
398
  Description: Checks for stubbed test subjects.
388
399
  Enabled: true
389
400
  StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SubjectStub
390
401
 
391
- RSpec/PredicateMatcher:
392
- Description: Prefer using predicate matcher over using predicate method directly.
402
+ RSpec/UnspecifiedException:
403
+ Description: Checks for a specified error in checking raised errors.
393
404
  Enabled: true
394
- Strict: true
395
- EnforcedStyle: inflected
396
- SupportedStyles:
397
- - inflected
398
- - explicit
399
- StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/PredicateMatcher
405
+ StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/UnspecifiedException
400
406
 
401
407
  RSpec/VerifiedDoubles:
402
408
  Description: Prefer using verifying doubles over normal doubles.
403
409
  Enabled: true
410
+ IgnoreNameless: true
404
411
  IgnoreSymbolicNames: false
405
412
  StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/VerifiedDoubles
406
413
 
@@ -18,8 +18,6 @@ require_relative 'rubocop/rspec/example'
18
18
  require_relative 'rubocop/rspec/hook'
19
19
  require_relative 'rubocop/cop/rspec/cop'
20
20
  require_relative 'rubocop/rspec/align_let_brace'
21
- require_relative 'rubocop/rspec/capybara'
22
- require_relative 'rubocop/rspec/factory_bot'
23
21
  require_relative 'rubocop/rspec/final_end_location'
24
22
  require_relative 'rubocop/rspec/blank_line_separation'
25
23
 
@@ -56,6 +56,7 @@ module RuboCop
56
56
  def joined_prefixes
57
57
  quoted = prefixes.map { |prefix| "'#{prefix}'" }
58
58
  return quoted.first if quoted.size == 1
59
+
59
60
  quoted << "or #{quoted.pop}"
60
61
  quoted.join(', ')
61
62
  end
@@ -79,6 +79,7 @@ module RuboCop
79
79
 
80
80
  def rspec_pattern_config?
81
81
  return unless all_cops_config.key?('RSpec')
82
+
82
83
  all_cops_config.fetch('RSpec').key?('Patterns')
83
84
  end
84
85
 
@@ -23,11 +23,9 @@ module RuboCop
23
23
  MSG = 'The second argument to describe should be the method '\
24
24
  "being tested. '#instance' or '.class'.".freeze
25
25
 
26
- METHOD_STRING_MATCHER = /\A[\#\.].+/
27
-
28
26
  def on_top_level_describe(_node, (_, second_arg))
29
27
  return unless second_arg && second_arg.str_type?
30
- return if METHOD_STRING_MATCHER =~ second_arg.str_content
28
+ return if second_arg.str_content.start_with?('#', '.')
31
29
 
32
30
  add_offense(second_arg, location: :expression)
33
31
  end
@@ -73,6 +73,7 @@ module RuboCop
73
73
  def on_block(node)
74
74
  factory_attributes(node).to_a.flatten.each do |attribute|
75
75
  next if proc?(attribute) || association?(attribute)
76
+
76
77
  add_offense(attribute, location: :expression)
77
78
  end
78
79
  end
@@ -97,7 +98,7 @@ module RuboCop
97
98
  end
98
99
 
99
100
  def factory_key?(hash_node)
100
- hash_node.keys.any? { |key| key.value == :factory }
101
+ hash_node.keys.any? { |key| key.sym_type? && key.value == :factory }
101
102
  end
102
103
 
103
104
  def autocorrect_replacing_parens(node)
@@ -139,6 +139,7 @@ module RuboCop
139
139
 
140
140
  def format_receiver(receiver)
141
141
  return '' unless receiver
142
+
142
143
  "#{receiver.source}."
143
144
  end
144
145
  end
@@ -56,9 +56,20 @@ module RuboCop
56
56
  private
57
57
 
58
58
  def valid_usage?(node)
59
- return false unless style == :single_line_only
60
59
  example = node.ancestors.find { |parent| example?(parent) }
61
- example && example.single_line?
60
+ return false if example.nil?
61
+
62
+ example.method_name == :its || allowed_by_style?(example)
63
+ end
64
+
65
+ def allowed_by_style?(example)
66
+ if style == :single_line_only
67
+ example.single_line?
68
+ elsif style == :single_statement_only
69
+ !example.body.begin_type?
70
+ else
71
+ false
72
+ end
62
73
  end
63
74
  end
64
75
  end
@@ -72,6 +72,7 @@ module RuboCop
72
72
 
73
73
  node.each_child_node do |child|
74
74
  next if child.sibling_index < first_example.sibling_index
75
+
75
76
  add_offense(child, location: :expression) if let?(child)
76
77
  end
77
78
  end
@@ -58,6 +58,7 @@ module RuboCop
58
58
 
59
59
  def common_setup?(node)
60
60
  return false unless setup?(node)
61
+
61
62
  # Search only for setup with basic_literal arguments (e.g. :sym, :str)
62
63
  # or no arguments at all.
63
64
  node.send_node.arguments.all?(&:basic_literal?)
@@ -145,6 +145,7 @@ module RuboCop
145
145
  end
146
146
 
147
147
  return if part_of_ignored_node?(node)
148
+
148
149
  predicate_matcher?(node) do |_actual, matcher|
149
150
  add_offense(
150
151
  node,
@@ -337,6 +338,7 @@ module RuboCop
337
338
  def block_loc(send_node)
338
339
  parent = send_node.parent
339
340
  return unless parent.block_type?
341
+
340
342
  range_between(
341
343
  send_node.loc.expression.end_pos,
342
344
  parent.loc.expression.end_pos
@@ -41,6 +41,7 @@ module RuboCop
41
41
  http_status(node) do |ast_node|
42
42
  checker = checker_class.new(ast_node)
43
43
  return unless checker.offensive?
44
+
44
45
  add_offense(checker.node, message: checker.message)
45
46
  end
46
47
  end
@@ -43,6 +43,7 @@ module RuboCop
43
43
  first_let = lets.first
44
44
  lets.each_with_index do |node, idx|
45
45
  next if node.sibling_index == first_let.sibling_index + idx
46
+
46
47
  add_offense(node, location: :expression)
47
48
  end
48
49
  end
@@ -72,6 +72,7 @@ module RuboCop
72
72
 
73
73
  def expectation?(node)
74
74
  return if all_matcher?(node)
75
+
75
76
  receive_message?(node)
76
77
  end
77
78
 
@@ -0,0 +1,64 @@
1
+ module RuboCop
2
+ module Cop
3
+ module RSpec
4
+ # Checks for a specified error in checking raised errors.
5
+ #
6
+ # Enforces one of an Exception type, a string, or a regular
7
+ # expression to match against the exception message as a parameter
8
+ # to `raise_error`
9
+ #
10
+ # @example
11
+ #
12
+ # # bad
13
+ # expect {
14
+ # raise StandardError.new('error')
15
+ # }.to raise_error
16
+ #
17
+ # # good
18
+ # expect {
19
+ # raise StandardError.new('error')
20
+ # }.to raise_error(StandardError)
21
+ #
22
+ # expect {
23
+ # raise StandardError.new('error')
24
+ # }.to raise_error('error')
25
+ #
26
+ # expect {
27
+ # raise StandardError.new('error')
28
+ # }.to raise_error(/err/)
29
+ #
30
+ # expect { do_something }.not_to raise_error
31
+ class UnspecifiedException < Cop
32
+ MSG = 'Specify the exception being captured'.freeze
33
+
34
+ def_node_matcher :empty_raise_error_or_exception, <<-PATTERN.freeze
35
+ (send
36
+ (block
37
+ (send nil? :expect) ...)
38
+ :to
39
+ (send nil? {:raise_error :raise_exception})
40
+ )
41
+ PATTERN
42
+
43
+ def on_send(node)
44
+ return unless empty_exception_matcher?(node)
45
+
46
+ add_offense(
47
+ node.children.last,
48
+ location: :expression
49
+ )
50
+ end
51
+
52
+ def empty_exception_matcher?(node)
53
+ empty_raise_error_or_exception(node) && !block_with_args?(node.parent)
54
+ end
55
+
56
+ def block_with_args?(node)
57
+ return unless node && node.block_type?
58
+
59
+ node.arguments?
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -26,16 +26,23 @@ module RuboCop
26
26
  MSG = 'Prefer using verifying doubles over normal doubles.'.freeze
27
27
 
28
28
  def_node_matcher :unverified_double, <<-PATTERN
29
- {(send nil? {:double :spy} $_ ...) }
29
+ {(send nil? {:double :spy} $...)}
30
30
  PATTERN
31
31
 
32
32
  def on_send(node)
33
- unverified_double(node) do |name|
34
- return if name.sym_type? && cop_config['IgnoreSymbolicNames']
33
+ unverified_double(node) do |name, *_args|
34
+ return if name.nil? && cop_config['IgnoreNameless']
35
+ return if symbol?(name) && cop_config['IgnoreSymbolicNames']
35
36
 
36
37
  add_offense(node, location: :expression)
37
38
  end
38
39
  end
40
+
41
+ private
42
+
43
+ def symbol?(name)
44
+ name && name.sym_type?
45
+ end
39
46
  end
40
47
  end
41
48
  end
@@ -25,11 +25,13 @@ module RuboCop
25
25
 
26
26
  def on_send(node)
27
27
  return unless expect?(node)
28
+
28
29
  check_expect(node)
29
30
  end
30
31
 
31
32
  def on_block(node)
32
33
  return unless expect_block?(node)
34
+
33
35
  check_expect(node)
34
36
  end
35
37
 
@@ -37,6 +39,7 @@ module RuboCop
37
39
 
38
40
  def check_expect(node)
39
41
  return unless void?(node)
42
+
40
43
  add_offense(node, location: :expression)
41
44
  end
42
45
 
@@ -72,5 +72,6 @@ require_relative 'rspec/shared_context'
72
72
  require_relative 'rspec/shared_examples'
73
73
  require_relative 'rspec/single_argument_message_chain'
74
74
  require_relative 'rspec/subject_stub'
75
+ require_relative 'rspec/unspecified_exception'
75
76
  require_relative 'rspec/verified_doubles'
76
77
  require_relative 'rspec/void_expect'
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module RSpec
5
5
  # Version information for the RSpec RuboCop plugin.
6
6
  module Version
7
- STRING = '1.29.1'.freeze
7
+ STRING = '1.30.0'.freeze
8
8
  end
9
9
  end
10
10
  end
@@ -3,13 +3,16 @@ RSpec.describe 'config/default.yml' do
3
3
  RuboCop::ConfigLoader.load_file('config/default.yml')
4
4
  end
5
5
 
6
- let(:cop_names) do
7
- namespaces = {
6
+ let(:namespaces) do
7
+ {
8
8
  'rspec' => 'RSpec',
9
9
  'capybara' => 'Capybara',
10
10
  'factory_bot' => 'FactoryBot',
11
11
  'rails' => 'Rails'
12
12
  }
13
+ end
14
+
15
+ let(:cop_names) do
13
16
  glob = SpecHelper::ROOT.join('lib', 'rubocop', 'cop', 'rspec',
14
17
  '{,capybara,factory_bot,rails}', '*.rb')
15
18
  cop_names =
@@ -38,7 +41,17 @@ RSpec.describe 'config/default.yml' do
38
41
  end
39
42
 
40
43
  it 'has configuration for all cops' do
41
- expect(default_config.keys.sort).to eq(config_keys.sort)
44
+ expect(default_config.keys).to match_array(config_keys)
45
+ end
46
+
47
+ it 'sorts configuration keys alphabetically' do
48
+ namespaces.each do |_path, prefix|
49
+ expected = config_keys.select { |key| key.start_with?(prefix) }.sort
50
+ actual = default_config.keys.select { |key| key.start_with?(prefix) }
51
+ actual.each_with_index do |key, idx|
52
+ expect(key).to eq expected[idx]
53
+ end
54
+ end
42
55
  end
43
56
 
44
57
  it 'has descriptions for all cops' do
@@ -133,6 +133,7 @@ RSpec.describe RuboCop::Cop::RSpec::FactoryBot::AttributeDefinedStatically do #
133
133
  meta_tags(foo: Time.current)
134
134
  other_tags({ foo: Time.current })
135
135
  options color: :blue
136
+ other_options Tag::MAGIC => :magic
136
137
  self.end Date.tomorrow
137
138
 
138
139
  trait :old do
@@ -157,6 +158,7 @@ RSpec.describe RuboCop::Cop::RSpec::FactoryBot::AttributeDefinedStatically do #
157
158
  meta_tags { { foo: Time.current } }
158
159
  other_tags { { foo: Time.current } }
159
160
  options { { color: :blue } }
161
+ other_options { { Tag::MAGIC => :magic } }
160
162
  self.end { Date.tomorrow }
161
163
 
162
164
  trait :old do
@@ -17,6 +17,14 @@ RSpec.describe RuboCop::Cop::RSpec::ImplicitSubject, :config do
17
17
  RUBY
18
18
  end
19
19
 
20
+ it 'allows `is_expected` inside `its` block, in multi-line examples' do
21
+ expect_no_offenses(<<-RUBY)
22
+ its(:quality) do
23
+ is_expected.to be :high
24
+ end
25
+ RUBY
26
+ end
27
+
20
28
  it 'flags `should` in multi-line examples' do
21
29
  expect_offense(<<-RUBY)
22
30
  it 'expect subject to be used' do
@@ -92,6 +100,50 @@ RSpec.describe RuboCop::Cop::RSpec::ImplicitSubject, :config do
92
100
  good_code
93
101
  end
94
102
 
103
+ context 'with EnforcedStyle `single_statement_only`' do
104
+ let(:enforced_style) { 'single_statement_only' }
105
+
106
+ it 'allows `is_expected` in multi-line example with single statement' do
107
+ expect_no_offenses(<<-RUBY)
108
+ it 'expect subject to be used' do
109
+ is_expected.to be_good
110
+ end
111
+ RUBY
112
+ end
113
+
114
+ it 'flags `is_expected` in multi-statement examples' do
115
+ expect_offense(<<-RUBY)
116
+ it 'expect subject to be used' do
117
+ subject.age = 18
118
+ is_expected.to be_valid
119
+ ^^^^^^^^^^^ Don't use implicit subject.
120
+ end
121
+ RUBY
122
+ end
123
+
124
+ bad_code = <<-RUBY
125
+ it 'is valid' do
126
+ subject.age = 18
127
+ is_expected.to be_valid
128
+ end
129
+ RUBY
130
+
131
+ good_code = <<-RUBY
132
+ it 'is valid' do
133
+ subject.age = 18
134
+ expect(subject).to be_valid
135
+ end
136
+ RUBY
137
+
138
+ include_examples 'autocorrect',
139
+ bad_code,
140
+ good_code
141
+
142
+ include_examples 'autocorrect',
143
+ bad_code,
144
+ good_code
145
+ end
146
+
95
147
  context 'with EnforcedStyle `disallow`' do
96
148
  let(:enforced_style) { 'disallow' }
97
149
 
@@ -127,6 +179,12 @@ RSpec.describe RuboCop::Cop::RSpec::ImplicitSubject, :config do
127
179
  RUBY
128
180
  end
129
181
 
182
+ it 'allows `is_expected` inside `its` block' do
183
+ expect_no_offenses(<<-RUBY)
184
+ its(:quality) { is_expected.to be :high }
185
+ RUBY
186
+ end
187
+
130
188
  include_examples 'autocorrect',
131
189
  'it { is_expected.to be_truthy }',
132
190
  'it { expect(subject).to be_truthy }'
@@ -0,0 +1,175 @@
1
+ RSpec.describe RuboCop::Cop::RSpec::UnspecifiedException do
2
+ subject(:cop) { described_class.new }
3
+
4
+ context 'with raise_error matcher' do
5
+ it 'detects the `unspecified_exception` offense' do
6
+ expect_offense(<<-RUBY)
7
+ expect {
8
+ raise StandardError
9
+ }.to raise_error
10
+ ^^^^^^^^^^^ Specify the exception being captured
11
+ RUBY
12
+ end
13
+
14
+ it 'allows empty exception specification when not expecting an error' do
15
+ expect_no_offenses(<<-RUBY)
16
+ expect {
17
+ raise StandardError
18
+ }.not_to raise_error
19
+ RUBY
20
+ end
21
+
22
+ it 'allows exception classes' do
23
+ expect_no_offenses(<<-RUBY)
24
+ expect {
25
+ raise StandardError
26
+ }.to raise_error(StandardError)
27
+ RUBY
28
+ end
29
+
30
+ it 'allows exception messages' do
31
+ expect_no_offenses(<<-RUBY)
32
+ expect {
33
+ raise StandardError.new('error')
34
+ }.to raise_error('error')
35
+ RUBY
36
+ end
37
+
38
+ it 'allows exception types with messages' do
39
+ expect_no_offenses(<<-RUBY)
40
+ expect {
41
+ raise StandardError.new('error')
42
+ }.to raise_error(StandardError, 'error')
43
+ RUBY
44
+ end
45
+
46
+ it 'allows exception matching regular expressions' do
47
+ expect_no_offenses(<<-RUBY)
48
+ expect {
49
+ raise StandardError.new('error')
50
+ }.to raise_error(/err/)
51
+ RUBY
52
+ end
53
+
54
+ it 'allows exception types with matching regular expressions' do
55
+ expect_no_offenses(<<-RUBY)
56
+ expect {
57
+ raise StandardError.new('error')
58
+ }.to raise_error(StandardError, /err/)
59
+ RUBY
60
+ end
61
+
62
+ it 'allows classes with blocks with braces' do
63
+ expect_no_offenses(<<-RUBY)
64
+ expect {
65
+ raise StandardError.new('error')
66
+ }.to raise_error { |err| err.data }
67
+ RUBY
68
+ end
69
+
70
+ it 'allows classes with blocks with do/end' do
71
+ expect_no_offenses(<<-RUBY)
72
+ expect {
73
+ raise StandardError.new('error')
74
+ }.to raise_error do |error|
75
+ error.data
76
+ end
77
+ RUBY
78
+ end
79
+
80
+ it 'allows parameterized exceptions' do
81
+ expect_no_offenses(<<-RUBY)
82
+ my_exception = StandardError.new('my exception')
83
+ expect {
84
+ raise my_exception
85
+ }.to raise_error(my_exception)
86
+ RUBY
87
+ end
88
+ end
89
+
90
+ context 'with raise_exception matcher' do
91
+ it 'detects the `unspecified_exception` offense' do
92
+ expect_offense(<<-RUBY)
93
+ expect {
94
+ raise StandardError
95
+ }.to raise_exception
96
+ ^^^^^^^^^^^^^^^ Specify the exception being captured
97
+ RUBY
98
+ end
99
+
100
+ it 'allows empty exception specification when not expecting an error' do
101
+ expect_no_offenses(<<-RUBY)
102
+ expect {
103
+ raise StandardError
104
+ }.not_to raise_exception
105
+ RUBY
106
+ end
107
+
108
+ it 'allows exception classes' do
109
+ expect_no_offenses(<<-RUBY)
110
+ expect {
111
+ raise StandardError
112
+ }.to raise_exception(StandardError)
113
+ RUBY
114
+ end
115
+
116
+ it 'allows exception messages' do
117
+ expect_no_offenses(<<-RUBY)
118
+ expect {
119
+ raise StandardError.new('error')
120
+ }.to raise_exception('error')
121
+ RUBY
122
+ end
123
+
124
+ it 'allows exception types with messages' do
125
+ expect_no_offenses(<<-RUBY)
126
+ expect {
127
+ raise StandardError.new('error')
128
+ }.to raise_exception(StandardError, 'error')
129
+ RUBY
130
+ end
131
+
132
+ it 'allows exception matching regular expressions' do
133
+ expect_no_offenses(<<-RUBY)
134
+ expect {
135
+ raise StandardError.new('error')
136
+ }.to raise_exception(/err/)
137
+ RUBY
138
+ end
139
+
140
+ it 'allows exception types with matching regular expressions' do
141
+ expect_no_offenses(<<-RUBY)
142
+ expect {
143
+ raise StandardError.new('error')
144
+ }.to raise_exception(StandardError, /err/)
145
+ RUBY
146
+ end
147
+
148
+ it 'allows classes with blocks with braces' do
149
+ expect_no_offenses(<<-RUBY)
150
+ expect {
151
+ raise StandardError.new('error')
152
+ }.to raise_exception { |err| err.data }
153
+ RUBY
154
+ end
155
+
156
+ it 'allows classes with blocks with do/end' do
157
+ expect_no_offenses(<<-RUBY)
158
+ expect {
159
+ raise StandardError.new('error')
160
+ }.to raise_exception do |error|
161
+ error.data
162
+ end
163
+ RUBY
164
+ end
165
+
166
+ it 'allows parameterized exceptions' do
167
+ expect_no_offenses(<<-RUBY)
168
+ my_exception = StandardError.new('my exception')
169
+ expect {
170
+ raise my_exception
171
+ }.to raise_exception(my_exception)
172
+ RUBY
173
+ end
174
+ end
175
+ end
@@ -53,14 +53,27 @@ RSpec.describe RuboCop::Cop::RSpec::VerifiedDoubles, :config do
53
53
  end
54
54
  end
55
55
 
56
- it 'ignores doubles without a name' do
57
- expect_no_offenses(<<-RUBY)
56
+ it 'doubles that have no name specified' do
57
+ expect_offense(<<-RUBY)
58
58
  it do
59
59
  foo = double
60
+ ^^^^^^ Prefer using verifying doubles over normal doubles.
60
61
  end
61
62
  RUBY
62
63
  end
63
64
 
65
+ context 'when configured to ignore nameless doubles' do
66
+ let(:cop_config) { { 'IgnoreNameless' => true } }
67
+
68
+ it 'ignores doubles that have no name specified' do
69
+ expect_no_offenses(<<-RUBY)
70
+ it do
71
+ foo = double
72
+ end
73
+ RUBY
74
+ end
75
+ end
76
+
64
77
  it 'ignores instance_doubles' do
65
78
  expect_no_offenses(<<-RUBY)
66
79
  it do
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.29.1
4
+ version: 1.30.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: 2018-09-01 00:00:00.000000000 Z
13
+ date: 2018-10-08 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rubocop
@@ -184,19 +184,18 @@ files:
184
184
  - lib/rubocop/cop/rspec/shared_examples.rb
185
185
  - lib/rubocop/cop/rspec/single_argument_message_chain.rb
186
186
  - lib/rubocop/cop/rspec/subject_stub.rb
187
+ - lib/rubocop/cop/rspec/unspecified_exception.rb
187
188
  - lib/rubocop/cop/rspec/verified_doubles.rb
188
189
  - lib/rubocop/cop/rspec/void_expect.rb
189
190
  - lib/rubocop/cop/rspec_cops.rb
190
191
  - lib/rubocop/rspec.rb
191
192
  - lib/rubocop/rspec/align_let_brace.rb
192
193
  - lib/rubocop/rspec/blank_line_separation.rb
193
- - lib/rubocop/rspec/capybara.rb
194
194
  - lib/rubocop/rspec/concept.rb
195
195
  - lib/rubocop/rspec/config_formatter.rb
196
196
  - lib/rubocop/rspec/description_extractor.rb
197
197
  - lib/rubocop/rspec/example.rb
198
198
  - lib/rubocop/rspec/example_group.rb
199
- - lib/rubocop/rspec/factory_bot.rb
200
199
  - lib/rubocop/rspec/final_end_location.rb
201
200
  - lib/rubocop/rspec/hook.rb
202
201
  - lib/rubocop/rspec/inject.rb
@@ -279,6 +278,7 @@ files:
279
278
  - spec/rubocop/cop/rspec/shared_examples_spec.rb
280
279
  - spec/rubocop/cop/rspec/single_argument_message_chain_spec.rb
281
280
  - spec/rubocop/cop/rspec/subject_stub_spec.rb
281
+ - spec/rubocop/cop/rspec/unspecified_exception_spec.rb
282
282
  - spec/rubocop/cop/rspec/verified_doubles_spec.rb
283
283
  - spec/rubocop/cop/rspec/void_expect_spec.rb
284
284
  - spec/rubocop/rspec/config_formatter_spec.rb
@@ -396,6 +396,7 @@ test_files:
396
396
  - spec/rubocop/cop/rspec/shared_examples_spec.rb
397
397
  - spec/rubocop/cop/rspec/single_argument_message_chain_spec.rb
398
398
  - spec/rubocop/cop/rspec/subject_stub_spec.rb
399
+ - spec/rubocop/cop/rspec/unspecified_exception_spec.rb
399
400
  - spec/rubocop/cop/rspec/verified_doubles_spec.rb
400
401
  - spec/rubocop/cop/rspec/void_expect_spec.rb
401
402
  - spec/rubocop/rspec/config_formatter_spec.rb
@@ -1,7 +0,0 @@
1
- module RuboCop
2
- module RSpec
3
- # RuboCop Capybara project namespace
4
- module Capybara
5
- end
6
- end
7
- end
@@ -1,7 +0,0 @@
1
- module RuboCop
2
- module RSpec
3
- # RuboCop FactoryBot project namespace
4
- module FactoryBot
5
- end
6
- end
7
- end