rubocop-rspec 1.29.1 → 1.30.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.
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