summaryrefslogtreecommitdiff
path: root/rubocop/cop/rspec/factory_bot/local_static_assignment.rb
blob: 1a26bc31c78e30f0da5c0a759ce900d6c4ecdbc6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# frozen_string_literal: true

require 'rubocop-rspec'

module RuboCop
  module Cop
    module RSpec
      module FactoryBot
        # Flags local assignments during factory "load time". This leads to
        # static data definitions.
        #
        # Move these definitions into attribute block or
        # `transient` block to ensure that the data is evaluated during
        # "runtime" and remains dynamic.
        #
        # @example
        #   # bad
        #   factory :foo do
        #     random = rand(23)
        #     baz { "baz-#{random}" }
        #
        #     trait :a_trait do
        #       random = rand(23)
        #       baz { "baz-#{random}" }
        #     end
        #
        #     transient do
        #       random = rand(23)
        #       baz { "baz-#{random}" }
        #     end
        #   end
        #
        #   # good
        #   factory :foo do
        #     baz { "baz-#{random}" }
        #
        #     trait :a_trait do
        #       baz { "baz-#{random}" }
        #     end
        #
        #     transient do
        #       random { rand(23) }
        #     end
        #   end
        class LocalStaticAssignment < RuboCop::Cop::Base
          MSG = 'Avoid local static assignemnts in factories which lead to static data definitions.'

          RESTRICT_ON_SEND = %i[factory transient trait].freeze

          def_node_search :local_assignment, <<~PATTERN
            (begin $(lvasgn ...))
          PATTERN

          def on_send(node)
            return unless node.parent&.block_type?

            node.parent.each_child_node(:begin) do |begin_node|
              begin_node.each_child_node(:lvasgn) do |lvasgn_node|
                add_offense(lvasgn_node)
              end
            end
          end
        end
      end
    end
  end
end