rubocop-factory_bot 2.22.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 44482485fe839223a23464d6739cbd0160ebaffa5402c9057d2fdc0e3c9b3295
4
+ data.tar.gz: 035ac59bb998b1268bf0803bce35b9c2ab75ac6f232a427e28996f0ea857f386
5
+ SHA512:
6
+ metadata.gz: fd92b4d37f8a352e1acc98ae2bbbad05982248d3ef97dfb6b99edfe5173ba087a4259db3718e1e05c0b7951574652b657b694d2f02a5c34cf162d17fe427303a
7
+ data.tar.gz: 10cf9b7446c6fbd09a2ffcfe8629be12c2dc334132d6515acd8015b0f22a7e06e01d704f42316730e096901889f189adcaff8730571df86e401e7767688c07f3
data/CHANGELOG.md ADDED
@@ -0,0 +1,69 @@
1
+ # Changelog
2
+
3
+ ## Master (Unreleased)
4
+
5
+ ## 2.22.0 (2023-05-04)
6
+
7
+ - Extracted from `rubocop-rspec` into a separate repository for easier use with Minitest/Cucumber. ([@ydah])
8
+
9
+ ## Previously (see [rubocop-rspec's changelist](https://github.com/rubocop/rubocop-rspec/blob/70a97b1895ce4b9bcd6ff336d5d343ddc6175fe6/CHANGELOG.md) for details)
10
+
11
+ - Fix a false positive for `RSpec/FactoryBot/ConsistentParenthesesStyle` inside `&&`, `||` and `:?` when `omit_parentheses` is on ([@dmitrytsepelev])
12
+ - Add new `RSpec/FactoryBot/FactoryNameStyle` cop. ([@ydah])
13
+ - Fix wrong autocorrection in `n_times` style on `RSpec/FactoryBot/CreateList`. ([@r7kamura])
14
+ - Fix a false positive for `RSpec/FactoryBot/ConsistentParenthesesStyle` when using `generate` with multiple arguments. ([@ydah])
15
+ - Fix `RSpec/FactoryBot/ConsistentParenthesesStyle` to ignore calls without the first positional argument. ([@pirj])
16
+ - Fix `RSpec/FactoryBot/ConsistentParenthesesStyle` to ignore calls inside a Hash or an Array. ([@pirj])
17
+ - Fix an incorrect autocorrect for `FactoryBot/ConsistentParenthesesStyle` with `omit_parentheses` option when method name and first argument are not on same line. ([@ydah])
18
+ - Add `RSpec/FactoryBot/ConsistentParenthesesStyle` cop. ([@Liberatys])
19
+ - Support `Array.new(n)` on `RSpec/FactoryBot/CreateList` cop. ([@r7kamura])
20
+ - Fixed false offense detection in `FactoryBot/CreateList` when a n.times block is including method calls in the factory create arguments. ([@ngouy])
21
+ - Fix error in `RSpec/RSpec/FactoryBot/CreateList` cop for empty block. ([@tejasbubane])
22
+ - Fix `RSpec/FactoryBot/SyntaxMethods` and `RSpec/Capybara/FeatureMethods` to inspect shared groups. ([@pirj])
23
+ - Add new `RSpec/FactoryBot/SyntaxMethods` cop. ([@leoarnold])
24
+ - Change namespace of several cops (`Capybara/*` -> `RSpec/Capybara/*`, `FactoryBot/*` -> `RSpec/FactoryBot/*`, `Rails/*` -> `RSpec/Rails/*`). ([@pirj], [@bquorning])
25
+ - Fix `FactoryBot/AttributeDefinedStatically` to allow `#traits_for_enum` without a block. ([@harrylewis])
26
+ - Improve the performance of `FactoryBot/AttributeDefinedStatically`, `RSpec/InstanceVariable`, `RSpec/LetSetup`, `RSpec/NestedGroups` and `RSpec/ReturnFromStub`. ([@andrykonchin])
27
+ - Improve message and description of `FactoryBot/FactoryClassName`. ([@ybiquitous])
28
+ - Fix `FactoryBot/FactoryClassName` to ignore `Hash` and `OpenStruct`. ([@jfragoulis])
29
+ - Add `FactoryBot/FactoryClassName` cop. ([@jfragoulis])
30
+ - Fix `FactoryBot/AttributeDefinedStatically` not working with an explicit receiver. ([@composerinteralia])
31
+ - Fix `FactoryBot/CreateList` autocorrect crashing when the factory is called with a block=. ([@Darhazer])
32
+ - `FactoryBot/CreateList` now ignores `times` blocks with an argument. ([@Darhazer])
33
+ - Fix `FactoryBot/AttributeDefinedStatically` not working when there is a non-symbol key. ([@vzvu3k6k])
34
+ - Fix false negative in `FactoryBot/AttributeDefinedStatically` when attribute is defined on `self`. ([@Darhazer])
35
+ - `RSpec/FactoryBot` cops will now also inspect the `spec/factories.rb` path by default. ([@bquorning])
36
+ - Add `FactoryBot/AttributeDefinedStatically` cop to help FactoryBot users with the deprecation of static attributes. ([@composerinteralia], [@seanpdoyle])
37
+ - Remove `FactoryBot/DynamicAttributeDefinedStatically` and `FactoryBot/StaticAttributeDefinedDynamically` cops. ([@composerinteralia])
38
+ - Fix `FactoryBot/DynamicAttributeDefinedStatically` false positive when using symbol proc argument for a sequence. ([@tdeo])
39
+ - Add `FactoryBot/CreateList` cop. ([@Darhazer])
40
+ - Fix `FactoryBot/StaticAttributeDefinedDynamically` to handle empty block. ([@abrom])
41
+ - Fix false positive in `FactoryBot/DynamicAttributeDefinedStatically` when a before/after callback has a symbol proc argument. ([@abrom])
42
+ - Fix `FactoryBot/DynamicAttributeDefinedStatically` to handle dynamic attributes inside arrays/hashes. ([@abrom])
43
+ - Add `FactoryBot/StaticAttributeDefinedDynamically` (based on dynamic attribute cop). ([@abrom])
44
+ - Rename namespace `FactoryGirl` to `FactoryBot` following original library update. ([@walf443])
45
+ - Add `RSpec/FactoryGirl` namespace including the first cop for factories: `FactoryGirl/DynamicAttributeDefinedStatically`. ([@jonatas])
46
+
47
+ <!-- Contributors (alphabetically) -->
48
+
49
+ [@abrom]: https://github.com/abrom
50
+ [@andrykonchin]: https://github.com/andrykonchin
51
+ [@bquorning]: https://github.com/bquorning
52
+ [@composerinteralia]: https://github.com/composerinteralia
53
+ [@darhazer]: https://github.com/Darhazer
54
+ [@dmitrytsepelev]: https://github.com/dmitrytsepelev
55
+ [@harrylewis]: https://github.com/harrylewis
56
+ [@jfragoulis]: https://github.com/jfragoulis
57
+ [@jonatas]: https://github.com/jonatas
58
+ [@leoarnold]: https://github.com/leoarnold
59
+ [@liberatys]: https://github.com/Liberatys
60
+ [@ngouy]: https://github.com/ngouy
61
+ [@pirj]: https://github.com/pirj
62
+ [@r7kamura]: https://github.com/r7kamura
63
+ [@seanpdoyle]: https://github.com/seanpdoyle
64
+ [@tdeo]: https://github.com/tdeo
65
+ [@tejasbubane]: https://github.com/tejasbubane
66
+ [@vzvu3k6k]: https://github.com/vzvu3k6k
67
+ [@walf443]: https://github.com/walf443
68
+ [@ybiquitous]: https://github.com/ybiquitous
69
+ [@ydah]: https://github.com/ydah
@@ -0,0 +1,17 @@
1
+ # The RuboCop Community Code of Conduct
2
+
3
+ **Note:** We have picked the following code of conduct based on [Ruby's own
4
+ code of conduct](https://www.ruby-lang.org/en/conduct/).
5
+
6
+ This document provides a few simple community guidelines for a safe, respectful,
7
+ productive, and collaborative place for any person who is willing to contribute
8
+ to the RuboCop community. It applies to all "collaborative spaces", which are
9
+ defined as community communications channels (such as mailing lists, submitted
10
+ patches, commit comments, etc.).
11
+
12
+ - Participants will be tolerant of opposing views.
13
+ - Participants must ensure that their language and actions are free of personal
14
+ attacks and disparaging personal remarks.
15
+ - When interpreting the words and actions of others, participants should always
16
+ assume good intentions.
17
+ - Behaviour which can be reasonably considered harassment will not be tolerated.
data/MIT-LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ # The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Ian MacLeod <ian@nevir.net>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9
+ of the Software, and to permit persons to whom the Software is furnished to do
10
+ so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # RuboCop factory_bot
2
+
3
+ [![Join the chat at https://gitter.im/rubocop-rspec/Lobby](https://badges.gitter.im/rubocop-rspec/Lobby.svg)](https://gitter.im/rubocop-rspec/Lobby)
4
+ [![Gem Version](https://badge.fury.io/rb/rubocop-factory_bot.svg)](https://rubygems.org/gems/rubocop-factory_bot)
5
+ ![CI](https://github.com/rubocop/rubocop-factory_bot/workflows/CI/badge.svg)
6
+
7
+ [Factory Bot](https://www.rubydoc.info/gems/factory_bot)-specific analysis for your projects, as an extension to
8
+ [RuboCop](https://github.com/rubocop/rubocop).
9
+
10
+ ## Installation
11
+
12
+ Just install the `rubocop-factory_bot` gem
13
+
14
+ ```bash
15
+ gem install rubocop-factory_bot
16
+ ```
17
+
18
+ or if you use bundler put this in your `Gemfile`
19
+
20
+ ```
21
+ gem 'rubocop-factory_bot', require: false
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ You need to tell RuboCop to load the Factory Bot extension. There are three
27
+ ways to do this:
28
+
29
+ ### RuboCop configuration file
30
+
31
+ Put this into your `.rubocop.yml`.
32
+
33
+ ```yaml
34
+ require: rubocop-factory_bot
35
+ ```
36
+
37
+ Alternatively, use the following array notation when specifying multiple extensions.
38
+
39
+ ```yaml
40
+ require:
41
+ - rubocop-other-extension
42
+ - rubocop-factory_bot
43
+ ```
44
+
45
+ Now you can run `rubocop` and it will automatically load the RuboCop factory_bot
46
+ cops together with the standard cops.
47
+
48
+ ### Command line
49
+
50
+ ```bash
51
+ rubocop --require rubocop-factory_bot
52
+ ```
53
+
54
+ ### Rake task
55
+
56
+ ```ruby
57
+ RuboCop::RakeTask.new do |task|
58
+ task.requires << 'rubocop-factory_bot'
59
+ end
60
+ ```
61
+
62
+ ## Documentation
63
+
64
+ You can read more about RuboCop factory_bot in its [official manual](https://docs.rubocop.org/rubocop-factory_bot).
65
+
66
+ ## The Cops
67
+
68
+ All cops are located under
69
+ [`lib/rubocop/cop/factory_bot`](lib/rubocop/cop/factory_bot), and contain
70
+ examples/documentation.
71
+
72
+ In your `.rubocop.yml`, you may treat the Factory Bot cops just like any other
73
+ cop. For example:
74
+
75
+ ```yaml
76
+ FactoryBot/AttributeDefinedStatically:
77
+ Exclude:
78
+ - spec/factories/my_factory.rb
79
+ ```
80
+
81
+ ## Contributing
82
+
83
+ Checkout the [contribution guidelines](.github/CONTRIBUTING.md).
84
+
85
+ ## License
86
+
87
+ `rubocop-factory_bot` is MIT licensed. [See the accompanying file](MIT-LICENSE.md) for
88
+ the full text.
@@ -0,0 +1,75 @@
1
+ ---
2
+ FactoryBot:
3
+ Enabled: true
4
+ Include:
5
+ - "**/*_spec.rb"
6
+ - "**/spec/**/*"
7
+ - "**/test/**/*"
8
+ - "**/features/support/factories/**/*.rb"
9
+ DocumentationBaseURL: https://docs.rubocop.org/rubocop-factory_bot
10
+
11
+ FactoryBot/AttributeDefinedStatically:
12
+ Description: Always declare attribute values as blocks.
13
+ Enabled: true
14
+ Include:
15
+ - spec/factories.rb
16
+ - spec/factories/**/*.rb
17
+ - features/support/factories/**/*.rb
18
+ VersionAdded: '1.28'
19
+ VersionChanged: '2.0'
20
+ Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/AttributeDefinedStatically
21
+
22
+ FactoryBot/ConsistentParenthesesStyle:
23
+ Description: Use a consistent style for parentheses in factory bot calls.
24
+ Enabled: pending
25
+ EnforcedStyle: require_parentheses
26
+ SupportedStyles:
27
+ - require_parentheses
28
+ - omit_parentheses
29
+ VersionAdded: '2.14'
30
+ Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/ConsistentParenthesesStyle
31
+
32
+ FactoryBot/CreateList:
33
+ Description: Checks for create_list usage.
34
+ Enabled: true
35
+ Include:
36
+ - "**/*_spec.rb"
37
+ - "**/spec/**/*"
38
+ - spec/factories.rb
39
+ - spec/factories/**/*.rb
40
+ - features/support/factories/**/*.rb
41
+ EnforcedStyle: create_list
42
+ SupportedStyles:
43
+ - create_list
44
+ - n_times
45
+ VersionAdded: '1.25'
46
+ VersionChanged: '2.0'
47
+ Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/CreateList
48
+
49
+ FactoryBot/FactoryClassName:
50
+ Description: Use string value when setting the class attribute explicitly.
51
+ Enabled: true
52
+ Include:
53
+ - spec/factories.rb
54
+ - spec/factories/**/*.rb
55
+ - features/support/factories/**/*.rb
56
+ VersionAdded: '1.37'
57
+ VersionChanged: '2.0'
58
+ Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/FactoryClassName
59
+
60
+ FactoryBot/FactoryNameStyle:
61
+ Description: Checks for name style for argument of FactoryBot::Syntax::Methods.
62
+ Enabled: pending
63
+ VersionAdded: '2.16'
64
+ EnforcedStyle: symbol
65
+ SupportedStyles:
66
+ - symbol
67
+ - string
68
+ Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/FactoryNameStyle
69
+
70
+ FactoryBot/SyntaxMethods:
71
+ Description: Use shorthands from `FactoryBot::Syntax::Methods` in your specs.
72
+ Enabled: pending
73
+ SafeAutoCorrect: false
74
+ VersionAdded: '2.7'
75
+ Reference: https://www.rubydoc.info/gems/rubocop-factory_bot/RuboCop/Cop/FactoryBot/SyntaxMethods
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module FactoryBot
6
+ # Always declare attribute values as blocks.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # kind [:active, :rejected].sample
11
+ #
12
+ # # good
13
+ # kind { [:active, :rejected].sample }
14
+ #
15
+ # # bad
16
+ # closed_at 1.day.from_now
17
+ #
18
+ # # good
19
+ # closed_at { 1.day.from_now }
20
+ #
21
+ # # bad
22
+ # count 1
23
+ #
24
+ # # good
25
+ # count { 1 }
26
+ #
27
+ class AttributeDefinedStatically < ::RuboCop::Cop::Base
28
+ extend AutoCorrector
29
+
30
+ MSG = 'Use a block to declare attribute values.'
31
+
32
+ # @!method value_matcher(node)
33
+ def_node_matcher :value_matcher, <<-PATTERN
34
+ (send _ !#reserved_method? $...)
35
+ PATTERN
36
+
37
+ # @!method factory_attributes(node)
38
+ def_node_matcher :factory_attributes, <<-PATTERN
39
+ (block (send _ #attribute_defining_method? ...) _ { (begin $...) $(send ...) } )
40
+ PATTERN
41
+
42
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
43
+ attributes = factory_attributes(node) || []
44
+ attributes = [attributes] unless attributes.is_a?(Array) # rubocop:disable Style/ArrayCoercion, Lint/RedundantCopDisableDirective
45
+
46
+ attributes.each do |attribute|
47
+ next unless offensive_receiver?(attribute.receiver, node)
48
+ next if proc?(attribute) || association?(attribute.first_argument)
49
+
50
+ add_offense(attribute) do |corrector|
51
+ autocorrect(corrector, attribute)
52
+ end
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def autocorrect(corrector, node)
59
+ if node.parenthesized?
60
+ autocorrect_replacing_parens(corrector, node)
61
+ else
62
+ autocorrect_without_parens(corrector, node)
63
+ end
64
+ end
65
+
66
+ def offensive_receiver?(receiver, node)
67
+ receiver.nil? ||
68
+ receiver.self_type? ||
69
+ receiver_matches_first_block_argument?(receiver, node)
70
+ end
71
+
72
+ def receiver_matches_first_block_argument?(receiver, node)
73
+ first_block_argument = node.arguments.first
74
+
75
+ !first_block_argument.nil? &&
76
+ receiver.lvar_type? &&
77
+ receiver.node_parts == first_block_argument.node_parts
78
+ end
79
+
80
+ def proc?(attribute)
81
+ value_matcher(attribute).to_a.all?(&:block_pass_type?)
82
+ end
83
+
84
+ # @!method association?(node)
85
+ def_node_matcher :association?, '(hash <(pair (sym :factory) _) ...>)'
86
+
87
+ def autocorrect_replacing_parens(corrector, node)
88
+ left_braces, right_braces = braces(node)
89
+
90
+ corrector.replace(node.location.begin, " #{left_braces}")
91
+ corrector.replace(node.location.end, right_braces)
92
+ end
93
+
94
+ def autocorrect_without_parens(corrector, node)
95
+ left_braces, right_braces = braces(node)
96
+
97
+ argument = node.first_argument
98
+ expression = argument.source_range
99
+ corrector.insert_before(expression, left_braces)
100
+ corrector.insert_after(expression, right_braces)
101
+ end
102
+
103
+ def braces(node)
104
+ if value_hash_without_braces?(node.first_argument)
105
+ ['{ { ', ' } }']
106
+ else
107
+ ['{ ', ' }']
108
+ end
109
+ end
110
+
111
+ def value_hash_without_braces?(node)
112
+ node.hash_type? && !node.braces?
113
+ end
114
+
115
+ def reserved_method?(method_name)
116
+ RuboCop::FactoryBot.reserved_methods.include?(method_name)
117
+ end
118
+
119
+ def attribute_defining_method?(method_name)
120
+ RuboCop::FactoryBot.attribute_defining_methods
121
+ .include?(method_name)
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module FactoryBot
6
+ # Use a consistent style for parentheses in factory bot calls.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ # create :user
12
+ # build(:user)
13
+ # create(:login)
14
+ # create :login
15
+ #
16
+ # @example `EnforcedStyle: require_parentheses` (default)
17
+ #
18
+ # # good
19
+ # create(:user)
20
+ # create(:user)
21
+ # create(:login)
22
+ # build(:login)
23
+ #
24
+ # @example `EnforcedStyle: omit_parentheses`
25
+ #
26
+ # # good
27
+ # create :user
28
+ # build :user
29
+ # create :login
30
+ # create :login
31
+ #
32
+ # # also good
33
+ # # when method name and first argument are not on same line
34
+ # create(
35
+ # :user
36
+ # )
37
+ # build(
38
+ # :user,
39
+ # name: 'foo'
40
+ # )
41
+ #
42
+ class ConsistentParenthesesStyle < ::RuboCop::Cop::Base
43
+ extend AutoCorrector
44
+ include ConfigurableEnforcedStyle
45
+ include RuboCop::FactoryBot::Language
46
+ include RuboCop::Cop::Util
47
+
48
+ def self.autocorrect_incompatible_with
49
+ [Style::MethodCallWithArgsParentheses]
50
+ end
51
+
52
+ MSG_REQUIRE_PARENS = 'Prefer method call with parentheses'
53
+ MSG_OMIT_PARENS = 'Prefer method call without parentheses'
54
+
55
+ FACTORY_CALLS = RuboCop::FactoryBot::Language::METHODS
56
+
57
+ RESTRICT_ON_SEND = FACTORY_CALLS
58
+
59
+ # @!method factory_call(node)
60
+ def_node_matcher :factory_call, <<-PATTERN
61
+ (send
62
+ {#factory_bot? nil?} %FACTORY_CALLS
63
+ {sym str send lvar} _*
64
+ )
65
+ PATTERN
66
+
67
+ def on_send(node)
68
+ return if ambiguous_without_parentheses?(node)
69
+
70
+ factory_call(node) do
71
+ return if node.method?(:generate) && node.arguments.count > 1
72
+
73
+ if node.parenthesized?
74
+ process_with_parentheses(node)
75
+ else
76
+ process_without_parentheses(node)
77
+ end
78
+ end
79
+ end
80
+
81
+ private
82
+
83
+ def process_with_parentheses(node)
84
+ return unless style == :omit_parentheses
85
+ return unless same_line?(node, node.first_argument)
86
+
87
+ add_offense(node.loc.selector,
88
+ message: MSG_OMIT_PARENS) do |corrector|
89
+ remove_parentheses(corrector, node)
90
+ end
91
+ end
92
+
93
+ def process_without_parentheses(node)
94
+ return unless style == :require_parentheses
95
+
96
+ add_offense(node.loc.selector,
97
+ message: MSG_REQUIRE_PARENS) do |corrector|
98
+ add_parentheses(node, corrector)
99
+ end
100
+ end
101
+
102
+ AMBIGUOUS_TYPES = %i[send pair array and or if].freeze
103
+
104
+ def ambiguous_without_parentheses?(node)
105
+ node.parent && AMBIGUOUS_TYPES.include?(node.parent.type)
106
+ end
107
+
108
+ def remove_parentheses(corrector, node)
109
+ corrector.replace(node.location.begin, ' ')
110
+ corrector.remove(node.location.end)
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end