rubocop-factory_bot 2.22.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 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