rubocop-rspec 1.27.0 → 1.28.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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/README.md +1 -1
  4. data/config/default.yml +15 -10
  5. data/lib/rubocop/cop/rspec/describe_method.rb +1 -1
  6. data/lib/rubocop/cop/rspec/empty_example_group.rb +1 -1
  7. data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +2 -4
  8. data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +1 -3
  9. data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +1 -3
  10. data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +1 -3
  11. data/lib/rubocop/cop/rspec/example_without_description.rb +3 -4
  12. data/lib/rubocop/cop/rspec/expect_in_hook.rb +8 -23
  13. data/lib/rubocop/cop/rspec/expect_output.rb +0 -2
  14. data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +146 -0
  15. data/lib/rubocop/cop/rspec/instance_spy.rb +0 -2
  16. data/lib/rubocop/cop/rspec/iterated_expectation.rb +1 -1
  17. data/lib/rubocop/cop/rspec/leading_subject.rb +1 -6
  18. data/lib/rubocop/cop/rspec/let_before_examples.rb +0 -2
  19. data/lib/rubocop/cop/rspec/missing_example_group_argument.rb +35 -0
  20. data/lib/rubocop/cop/rspec/multiple_expectations.rb +1 -1
  21. data/lib/rubocop/cop/rspec/multiple_subjects.rb +4 -4
  22. data/lib/rubocop/cop/rspec/nested_groups.rb +1 -1
  23. data/lib/rubocop/cop/rspec/pending.rb +1 -1
  24. data/lib/rubocop/cop/rspec/receive_never.rb +43 -0
  25. data/lib/rubocop/cop/rspec/scattered_let.rb +0 -2
  26. data/lib/rubocop/cop/rspec/shared_context.rb +3 -3
  27. data/lib/rubocop/cop/rspec/void_expect.rb +1 -1
  28. data/lib/rubocop/cop/rspec_cops.rb +4 -3
  29. data/lib/rubocop/rspec/align_let_brace.rb +1 -3
  30. data/lib/rubocop/rspec/blank_line_separation.rb +6 -0
  31. data/lib/rubocop/rspec/example_group.rb +0 -7
  32. data/lib/rubocop/rspec/language/node_pattern.rb +6 -0
  33. data/lib/rubocop/rspec/version.rb +1 -1
  34. data/rubocop-rspec.gemspec +2 -2
  35. data/spec/project/project_requires_spec.rb +13 -3
  36. data/spec/rubocop/cop/rspec/before_after_all_spec.rb +2 -2
  37. data/spec/rubocop/cop/rspec/empty_line_after_example_group_spec.rb +15 -0
  38. data/spec/rubocop/cop/rspec/factory_bot/attribute_defined_statically_spec.rb +156 -0
  39. data/spec/rubocop/cop/rspec/let_before_examples_spec.rb +0 -5
  40. data/spec/rubocop/cop/rspec/missing_example_group_argument_spec.rb +55 -0
  41. data/spec/rubocop/cop/rspec/overwriting_setup_spec.rb +0 -5
  42. data/spec/rubocop/cop/rspec/receive_never_spec.rb +45 -0
  43. data/spec/rubocop/cop/rspec/scattered_let_spec.rb +0 -5
  44. data/spec/shared/smoke_test_examples.rb +25 -0
  45. data/spec/smoke_tests/empty_spec.rb +0 -0
  46. data/spec/smoke_tests/factory_bot_spec.rb +11 -0
  47. data/spec/smoke_tests/no_tests_spec.rb +4 -0
  48. data/spec/smoke_tests/weird_rspec_spec.rb +233 -0
  49. data/spec/spec_helper.rb +4 -0
  50. metadata +24 -11
  51. data/lib/rubocop/cop/rspec/factory_bot/dynamic_attribute_defined_statically.rb +0 -93
  52. data/lib/rubocop/cop/rspec/factory_bot/static_attribute_defined_dynamically.rb +0 -81
  53. data/spec/rubocop/cop/rspec/factory_bot/dynamic_attribute_defined_statically_spec.rb +0 -139
  54. data/spec/rubocop/cop/rspec/factory_bot/static_attribute_defined_dynamically_spec.rb +0 -107
@@ -1,93 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module RSpec
6
- module FactoryBot
7
- # Prefer declaring dynamic attribute values in a block.
8
- #
9
- # @see StaticAttributeDefinedDynamically
10
- #
11
- # @example
12
- # # bad
13
- # kind [:active, :rejected].sample
14
- #
15
- # # good
16
- # kind { [:active, :rejected].sample }
17
- #
18
- # # bad
19
- # closed_at 1.day.from_now
20
- #
21
- # # good
22
- # closed_at { 1.day.from_now }
23
- class DynamicAttributeDefinedStatically < Cop
24
- MSG = 'Use a block to set a dynamic value to an attribute.'.freeze
25
-
26
- def_node_matcher :value_matcher, <<-PATTERN
27
- (send nil? _ $...)
28
- PATTERN
29
-
30
- def_node_search :factory_attributes, <<-PATTERN
31
- (block (send nil? {:factory :trait} ...) _ { (begin $...) $(send ...) } )
32
- PATTERN
33
-
34
- def on_block(node)
35
- factory_attributes(node).to_a.flatten.each do |attribute|
36
- next if static_or_proc?(attribute)
37
- add_offense(attribute, location: :expression)
38
- end
39
- end
40
-
41
- def autocorrect(node)
42
- if !method_uses_parens?(node.location)
43
- autocorrect_without_parens(node)
44
- elsif value_hash_without_braces?(node.descendants.first)
45
- autocorrect_hash_without_braces(node)
46
- else
47
- autocorrect_replacing_parens(node)
48
- end
49
- end
50
-
51
- private
52
-
53
- def static_or_proc?(attribute)
54
- value_matcher(attribute).to_a.all? do |value|
55
- value.block_pass_type? || value.recursive_literal_or_const?
56
- end
57
- end
58
-
59
- def value_hash_without_braces?(node)
60
- node.hash_type? && !node.braces?
61
- end
62
-
63
- def method_uses_parens?(location)
64
- return false unless location.begin && location.end
65
- location.begin.source == '(' && location.end.source == ')'
66
- end
67
-
68
- def autocorrect_hash_without_braces(node)
69
- autocorrect_replacing_parens(node, ' { { ', ' } }')
70
- end
71
-
72
- def autocorrect_replacing_parens(node,
73
- start_token = ' { ',
74
- end_token = ' }')
75
- lambda do |corrector|
76
- corrector.replace(node.location.begin, start_token)
77
- corrector.replace(node.location.end, end_token)
78
- end
79
- end
80
-
81
- def autocorrect_without_parens(node)
82
- lambda do |corrector|
83
- arguments = node.descendants.first
84
- expression = arguments.location.expression
85
- corrector.insert_before(expression, '{ ')
86
- corrector.insert_after(expression, ' }')
87
- end
88
- end
89
- end
90
- end
91
- end
92
- end
93
- end
@@ -1,81 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module RSpec
6
- module FactoryBot
7
- # Prefer declaring static attribute values without a block.
8
- #
9
- # @see DynamicAttributeDefinedStatically
10
- #
11
- # @example
12
- # # bad
13
- # kind { :static }
14
- #
15
- # # good
16
- # kind :static
17
- #
18
- # # bad
19
- # comments_count { 0 }
20
- #
21
- # # good
22
- # comments_count 0
23
- #
24
- # # bad
25
- # type { User::MAGIC }
26
- #
27
- # # good
28
- # type User::MAGIC
29
- class StaticAttributeDefinedDynamically < Cop
30
- MSG = 'Do not use a block to set a static value ' \
31
- 'to an attribute.'.freeze
32
-
33
- def_node_matcher :block_value_matcher, <<-PATTERN
34
- (block (send nil? _) _ $...)
35
- PATTERN
36
-
37
- def_node_search :factory_attributes, <<-PATTERN
38
- (block (send nil? { :factory :trait } ...) _ { (begin $...) $(send ...) $(block ...) } )
39
- PATTERN
40
-
41
- def on_block(node)
42
- factory_attributes(node).to_a.flatten.each do |attribute|
43
- values = block_value_matcher(attribute)
44
- next if values.to_a.all? { |v| dynamic?(v) }
45
- add_offense(attribute, location: :expression)
46
- end
47
- end
48
-
49
- def autocorrect(node)
50
- lambda do |corrector|
51
- corrector.replace(
52
- node.loc.expression,
53
- autocorrected_source(node)
54
- )
55
- end
56
- end
57
-
58
- private
59
-
60
- def dynamic?(node)
61
- node && !node.recursive_literal_or_const?
62
- end
63
-
64
- def autocorrected_source(node)
65
- "#{node.send_node.source}#{autocorrected_attribute(node.body)}"
66
- end
67
-
68
- def autocorrected_attribute(body)
69
- if body.nil?
70
- ' nil'
71
- elsif body.hash_type?
72
- "(#{body.source})"
73
- else
74
- ' ' + body.source
75
- end
76
- end
77
- end
78
- end
79
- end
80
- end
81
- end
@@ -1,139 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # rubocop:disable Metrics/LineLength
4
- RSpec.describe RuboCop::Cop::RSpec::FactoryBot::DynamicAttributeDefinedStatically do
5
- # rubocop:enable Metrics/LineLength
6
-
7
- subject(:cop) { described_class.new(config) }
8
-
9
- let(:config) { RuboCop::Config.new }
10
-
11
- %w[FactoryBot FactoryGirl].each do |factory_bot|
12
- context "when using #{factory_bot}" do
13
- it 'registers an offense for offending code' do
14
- expect_offense(<<-RUBY)
15
- #{factory_bot}.define do
16
- factory :post do
17
- published_at 1.day.from_now
18
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use a block to set a dynamic value to an attribute.
19
- status [:draft, :published].sample
20
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use a block to set a dynamic value to an attribute.
21
- created_at 1.day.ago
22
- ^^^^^^^^^^^^^^^^^^^^ Use a block to set a dynamic value to an attribute.
23
- update_times [Time.current]
24
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use a block to set a dynamic value to an attribute.
25
- meta_tags(foo: Time.current)
26
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use a block to set a dynamic value to an attribute.
27
- end
28
- end
29
- RUBY
30
- end
31
-
32
- it 'registers an offense in a trait' do
33
- expect_offense(<<-RUBY)
34
- #{factory_bot}.define do
35
- factory :post do
36
- title "Something"
37
- trait :published do
38
- published_at 1.day.from_now
39
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use a block to set a dynamic value to an attribute.
40
- end
41
- end
42
- end
43
- RUBY
44
- end
45
-
46
- it 'accepts valid factory definitions' do
47
- expect_no_offenses(<<-RUBY)
48
- #{factory_bot}.define do
49
- factory :post do
50
- trait :published do
51
- published_at { 1.day.from_now }
52
- end
53
- created_at { 1.day.ago }
54
- status :draft
55
- comments_count 0
56
- title "Static"
57
- description { FFaker::Lorem.paragraph(10) }
58
- recent_statuses [:published, :draft]
59
- meta_tags(like_count: 2)
60
- other_tags({ foo: nil })
61
-
62
- before(:create, &:initialize_something)
63
- after(:create, &:rebuild_cache)
64
- end
65
- end
66
- RUBY
67
- end
68
-
69
- it 'accepts const as a static value' do
70
- expect_no_offenses(<<-RUBY)
71
- #{factory_bot}.define do
72
- factory(:post, class: PrivatePost) do
73
- tag Tag::MAGIC
74
- options({priority: Priotity::HIGH})
75
- end
76
- end
77
- RUBY
78
- end
79
-
80
- it 'does not add offense if out of factory girl block' do
81
- expect_no_offenses(<<-RUBY)
82
- status [:draft, :published].sample
83
- published_at 1.day.from_now
84
- created_at 1.day.ago
85
- update_times [Time.current]
86
- meta_tags(foo: Time.current)
87
- RUBY
88
- end
89
-
90
- it 'accepts valid sequence definition' do
91
- expect_no_offenses(<<-RUBY)
92
- #{factory_bot}.define do
93
- factory :post do
94
- sequence :negative_numbers, &:-@
95
- end
96
- end
97
- RUBY
98
- end
99
-
100
- bad = <<-RUBY
101
- #{factory_bot}.define do
102
- factory :post do
103
- status([:draft, :published].sample)
104
- published_at 1.day.from_now
105
- created_at(1.day.ago)
106
- updated_at Time.current
107
- update_times [Time.current]
108
- meta_tags(foo: Time.current)
109
- other_tags({ foo: Time.current })
110
-
111
- trait :old do
112
- published_at 1.week.ago
113
- end
114
- end
115
- end
116
- RUBY
117
-
118
- corrected = <<-RUBY
119
- #{factory_bot}.define do
120
- factory :post do
121
- status { [:draft, :published].sample }
122
- published_at { 1.day.from_now }
123
- created_at { 1.day.ago }
124
- updated_at { Time.current }
125
- update_times { [Time.current] }
126
- meta_tags { { foo: Time.current } }
127
- other_tags { { foo: Time.current } }
128
-
129
- trait :old do
130
- published_at { 1.week.ago }
131
- end
132
- end
133
- end
134
- RUBY
135
-
136
- include_examples 'autocorrect', bad, corrected
137
- end
138
- end
139
- end
@@ -1,107 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # rubocop:disable Metrics/LineLength
4
- RSpec.describe RuboCop::Cop::RSpec::FactoryBot::StaticAttributeDefinedDynamically do
5
- # rubocop:enable Metrics/LineLength
6
-
7
- subject(:cop) { described_class.new(config) }
8
-
9
- let(:config) { RuboCop::Config.new }
10
-
11
- %w[FactoryBot FactoryGirl].each do |factory_bot|
12
- context "when using #{factory_bot}" do
13
- it 'registers an offense for offending code' do
14
- expect_offense(<<-RUBY)
15
- #{factory_bot}.define do
16
- factory :post do
17
- kind { :static }
18
- ^^^^^^^^^^^^^^^^ Do not use a block to set a static value to an attribute.
19
- comments_count { 0 }
20
- ^^^^^^^^^^^^^^^^^^^^ Do not use a block to set a static value to an attribute.
21
- type { User::MAGIC }
22
- ^^^^^^^^^^^^^^^^^^^^ Do not use a block to set a static value to an attribute.
23
- description { nil }
24
- ^^^^^^^^^^^^^^^^^^^ Do not use a block to set a static value to an attribute.
25
- recent_statuses { [:published, :draft] }
26
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not use a block to set a static value to an attribute.
27
- meta_tags { { foo: 1 } }
28
- ^^^^^^^^^^^^^^^^^^^^^^^^ Do not use a block to set a static value to an attribute.
29
- title {}
30
- ^^^^^^^^ Do not use a block to set a static value to an attribute.
31
- end
32
- end
33
- RUBY
34
- end
35
-
36
- it 'registers an offense in a trait' do
37
- expect_offense(<<-RUBY)
38
- #{factory_bot}.define do
39
- factory :post do
40
- title "Something"
41
- trait :something_else do
42
- title { "Something Else" }
43
- ^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not use a block to set a static value to an attribute.
44
- end
45
- end
46
- end
47
- RUBY
48
- end
49
-
50
- it 'accepts valid factory definitions' do
51
- expect_no_offenses(<<-RUBY)
52
- #{factory_bot}.define do
53
- factory :post do
54
- trait :something_else do
55
- title "Something Else"
56
- end
57
- title "Something"
58
- comments_count 0
59
- description { FFaker::Lorem.paragraph(10) }
60
- tag Tag::MAGIC
61
- recent_updates { [Time.current] }
62
- meta_tags { { first_like: Time.current } }
63
- before(:create) { 'foo' }
64
- end
65
- end
66
- RUBY
67
- end
68
-
69
- it 'does not add offense if out of factory girl block' do
70
- expect_no_offenses(<<-RUBY)
71
- kind { :static }
72
- comments_count { 0 }
73
- type { User::MAGIC }
74
- description { nil }
75
- RUBY
76
- end
77
-
78
- bad = <<-RUBY
79
- #{factory_bot}.define do
80
- factory :post do
81
- comments_count { 0 }
82
- type { User::MAGIC }
83
- description { nil }
84
- title {}
85
- recent_statuses { [:published, :draft] }
86
- meta_tags { { foo: 1 } }
87
- end
88
- end
89
- RUBY
90
-
91
- corrected = <<-RUBY
92
- #{factory_bot}.define do
93
- factory :post do
94
- comments_count 0
95
- type User::MAGIC
96
- description nil
97
- title nil
98
- recent_statuses [:published, :draft]
99
- meta_tags({ foo: 1 })
100
- end
101
- end
102
- RUBY
103
-
104
- include_examples 'autocorrect', bad, corrected
105
- end
106
- end
107
- end