factory_trace 0.3.2 → 1.0.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: d1a24e77768b29dad3fe548612611e571e6d482ef20452710030c2630b458b3c
4
- data.tar.gz: 9d1dc6c12a05a3a0ea3828525a5d7e6b77e7f7be993eb06fe19e3ac3b8f9640d
3
+ metadata.gz: fc2882cfec07c5a45a8cf464027b593f4e97891b4a959b49a061acec3728bd41
4
+ data.tar.gz: dbcfce3c2e80b177a108f7761477b09f404818cf3794f15ae30b4c1c286ac2a8
5
5
  SHA512:
6
- metadata.gz: 81d359402ed19825baba0e7e7433272a83ecd7cd17b6b8d9968eeb600129b2afba676bd8257e10b6ad4c22f8cf1397f89116493eea9841ede8c802d6622986b6
7
- data.tar.gz: 4f8c7509c59504a83f54de7a036368b5d233f4a9a1a1075cf344fff158edd441ca816445605c1b1e5b22fefd507e377d3f05c42c01eef37dbac6acf47d1475c0
6
+ metadata.gz: 06a0383bfda293f51aac40e74c5a45512652832c7911be4ca751da4940d889c99cd442008433addee8040f60e271276579bb5db34c6d668813e53e6e00a8793e
7
+ data.tar.gz: cf7d58dd17a8be295da9aa51acba56c4cfa4ba353055ff5d75bb5d6bead9ce125c99e588c19fc9f5ec25bba9c945557fec15ce86cb1901232fd52e5f43046888
data/exe/factory_trace CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  $LOAD_PATH.unshift("#{__dir__}/../lib")
4
- require 'factory_trace'
5
+ require "factory_trace"
5
6
 
6
7
  fail "You should pass at least one file with traced information.\nYou can generate it using only_trace mode." if ARGV.empty?
7
8
 
@@ -1,18 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FactoryTrace
2
4
  class Configuration
3
- attr_accessor :path, :enabled, :color, :mode
5
+ attr_accessor :path, :enabled, :color, :mode, :trace_definition
4
6
 
5
7
  def initialize
6
- @enabled = ENV.key?('FB_TRACE') || ENV.key?('FB_TRACE_FILE')
7
- @path = ENV['FB_TRACE_FILE']
8
+ @enabled = ENV.key?("FB_TRACE") || ENV.key?("FB_TRACE_FILE")
9
+ @path = ENV["FB_TRACE_FILE"]
8
10
  @color = path.nil?
9
- @mode = extract_mode(ENV['FB_TRACE']) || :full
11
+ @mode = extract_mode(ENV["FB_TRACE"]) || :full
12
+ @trace_definition = true
13
+ end
14
+
15
+ def trace_definition?
16
+ @trace_definition
10
17
  end
11
18
 
12
19
  def out
13
- return STDOUT unless path
20
+ return $stdout unless path
14
21
 
15
- File.open(path, 'w')
22
+ File.open(path, "w")
16
23
  end
17
24
 
18
25
  def mode?(*args)
@@ -22,7 +29,7 @@ module FactoryTrace
22
29
  private
23
30
 
24
31
  def extract_mode(value)
25
- matcher = value && value.match(/full|trace_only/)
32
+ matcher = value&.match(/full|trace_only/)
26
33
  matcher && matcher[0].to_sym
27
34
  end
28
35
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FactoryTrace
4
+ module Helpers
5
+ module Caller
6
+ module_function
7
+
8
+ # @return [String] file and line where the original method was called
9
+ def location
10
+ location = caller_locations(2..2).first
11
+
12
+ base = Pathname.new(Dir.pwd)
13
+ method = Pathname.new(location.path)
14
+
15
+ "#{method.relative_path_from(base)}:#{location.lineno}"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FactoryTrace
2
4
  module Helpers
3
5
  module Converter
@@ -9,7 +11,8 @@ module FactoryTrace
9
11
  def trait(trait)
10
12
  FactoryTrace::Structures::Trait.new(
11
13
  trait.name.to_s,
12
- declaration_names: trait.definition.declarations.grep(FactoryBot::Declaration::Implicit).map(&:name).map(&:to_s)
14
+ declaration_names: extract_declarations(trait),
15
+ definition_path: (trait.definition_path if trait.respond_to?(:definition_path))
13
16
  )
14
17
  end
15
18
 
@@ -21,9 +24,18 @@ module FactoryTrace
21
24
  factory.names.map(&:to_s),
22
25
  factory.defined_traits.map(&method(:trait)),
23
26
  parent_name: factory.send(:parent).respond_to?(:name) ? factory.send(:parent).name.to_s : nil,
24
- declaration_names: factory.definition.declarations.grep(FactoryBot::Declaration::Implicit).map(&:name).map(&:to_s)
27
+ declaration_names: extract_declarations(factory),
28
+ definition_path: (factory.definition_path if factory.respond_to?(:definition_path))
25
29
  )
26
30
  end
31
+
32
+ # @param [FactoryBot::Factory|FactoryBot::Trait]
33
+ #
34
+ # @return [Array<String>]
35
+ def extract_declarations(structure)
36
+ (structure.definition.declarations.grep(FactoryBot::Declaration::Implicit).map(&:name).map(&:to_s) +
37
+ structure.definition.instance_variable_get(:@base_traits).map(&:to_s)).uniq
38
+ end
27
39
  end
28
40
  end
29
41
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FactoryTrace
2
4
  module Helpers
3
5
  module Statusable
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FactoryTrace
4
+ module MonkeyPatches
5
+ module DefinitionProxy
6
+ def factory(name, options = {}, &block)
7
+ @child_factories << [name, Helpers::Caller.location, options, block]
8
+ end
9
+
10
+ def trait(name, &block)
11
+ @definition.define_trait(FactoryBot::Trait.new(name, Helpers::Caller.location, &block))
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FactoryTrace
4
+ module MonkeyPatches
5
+ module Default
6
+ module DSL
7
+ def factory(name, options = {}, &block)
8
+ caller_location = options.delete(:caller_location) || Helpers::Caller.location
9
+ factory = FactoryBot::Factory.new(name, caller_location, options)
10
+ proxy = FactoryBot::DefinitionProxy.new(factory.definition)
11
+ proxy.instance_eval(&block) if block
12
+
13
+ REGISTER.register_factory(factory)
14
+
15
+ proxy.child_factories.each do |(child_name, child_caller_location, child_options, child_block)|
16
+ parent_factory = child_options.delete(:parent) || name
17
+ factory(child_name, child_options.merge(parent: parent_factory, caller_location: child_caller_location), &child_block)
18
+ end
19
+ end
20
+
21
+ def trait(name, &block)
22
+ REGISTER.register_trait(FactoryBot::Trait.new(name, Helpers::Caller.location, &block))
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FactoryTrace
4
+ module MonkeyPatches
5
+ module Factory
6
+ attr_reader :definition_path
7
+
8
+ def initialize(name, definition_path, options = {})
9
+ @definition_path = definition_path
10
+ super(name, options)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FactoryTrace
4
+ module MonkeyPatches
5
+ REGISTER = FactoryBot::VERSION >= "5.1.0" ? FactoryBot::Internal : FactoryBot
6
+ end
7
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FactoryTrace
4
+ module MonkeyPatches
5
+ module Trait
6
+ attr_reader :definition_path
7
+
8
+ def initialize(name, definition_path, &block)
9
+ @definition_path = definition_path
10
+ super(name, &block)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FactoryTrace
2
4
  module Preprocessors
3
5
  class ExtractDefined
@@ -5,7 +7,7 @@ module FactoryTrace
5
7
  def self.call
6
8
  collection = FactoryTrace::Structures::Collection.new
7
9
 
8
- FactoryBot.traits.each do |trait|
10
+ MonkeyPatches::REGISTER.traits.each do |trait|
9
11
  collection.add(FactoryTrace::Helpers::Converter.trait(trait))
10
12
  end
11
13
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FactoryTrace
2
4
  module Preprocessors
3
5
  class ExtractUsed
@@ -1,107 +1,119 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FactoryTrace
2
4
  module Processors
3
5
  class FindUnused
4
- # Finds unused factories and traits
5
- #
6
- # @param [FactoryTrace::Structures::Collection] defined
7
- # @param [FactoryTrace::Structures::Collection] used
8
- #
9
- # @return [Array<Hash>]
10
- def self.call(defined, used)
11
- mark_as_used(defined, used)
12
-
13
- output = []
14
-
15
- defined.factories.each do |factory|
16
- output << {code: :unused, factory_names: factory.names} unless factory.status
17
-
18
- factory.traits.each do |trait|
19
- output << {code: :unused, factory_names: factory.names, trait_name: trait.name} unless trait.status
6
+ class << self
7
+ # Finds unused factories and traits
8
+ #
9
+ # @param [FactoryTrace::Structures::Collection] defined
10
+ # @param [FactoryTrace::Structures::Collection] used
11
+ #
12
+ # @return [Array<Hash>]
13
+ def call(defined, used)
14
+ mark_as_used(defined, used)
15
+
16
+ output = []
17
+
18
+ defined.factories.each do |factory|
19
+ output << append_definition_path({code: :unused, factory_names: factory.names}, factory) unless factory.status
20
+
21
+ factory.traits.each do |trait|
22
+ output << append_definition_path({code: :unused, factory_names: factory.names, trait_name: trait.name}, trait) unless trait.status
23
+ end
20
24
  end
21
- end
22
25
 
23
- defined.traits.each do |trait|
24
- output << {code: :unused, trait_name: trait.name} unless trait.status
25
- end
26
+ defined.traits.each do |trait|
27
+ output << append_definition_path({code: :unused, trait_name: trait.name}, trait) unless trait.status
28
+ end
26
29
 
27
- output.unshift(code: :unused, value: output.size)
28
- output.unshift(code: :used, value: defined.total - (output.size - 1))
30
+ output.unshift(code: :unused, value: output.size)
31
+ output.unshift(code: :used, value: defined.total - (output.size - 1))
29
32
 
30
- output
31
- end
33
+ output
34
+ end
32
35
 
33
- private
36
+ private
34
37
 
35
- # @param [FactoryTrace::Structures::Collection] defined
36
- # @param [FactoryTrace::Structures::Collection] used
37
- def self.mark_as_used(defined, used)
38
- used.factories.each do |used_factory|
39
- defined_factory = defined.find_factory_by_names(used_factory.names)
40
- mark_factory(defined_factory, defined, status: :used)
38
+ # @param [FactoryTrace::Structures::Collection] defined
39
+ # @param [FactoryTrace::Structures::Collection] used
40
+ def mark_as_used(defined, used)
41
+ used.factories.each do |used_factory|
42
+ defined_factory = defined.find_factory_by_names(used_factory.names)
43
+ mark_factory(defined_factory, defined, status: :used)
41
44
 
42
- used_factory.traits.each do |used_trait|
43
- trait_owner, defined_trait = defined_trait_by_name(defined, used_factory, used_trait.name)
44
- mark_trait(defined_trait, trait_owner, defined, status: :used)
45
+ used_factory.traits.each do |used_trait|
46
+ trait_owner, defined_trait = defined_trait_by_name(defined, used_factory, used_trait.name)
47
+ mark_trait(defined_trait, trait_owner, defined, status: :used)
48
+ end
45
49
  end
46
50
  end
47
- end
48
51
 
49
- # @param [FactoryTrace::Structures::Collection] defined
50
- # @param [FactoryTrace::Structures::Factory|nil] factory
51
- # @param [String] trait_name
52
- #
53
- # @return [Array<Object>]
54
- def self.defined_trait_by_name(defined, factory, trait_name)
55
- if factory
56
- possible_owner = defined.find_factory_by_names(factory.names)
57
-
58
- while possible_owner
59
- if (trait = possible_owner.traits.find { |t| t.name == trait_name })
60
- return [possible_owner, trait]
52
+ # @param [FactoryTrace::Structures::Collection] defined
53
+ # @param [FactoryTrace::Structures::Factory|nil] factory
54
+ # @param [String] trait_name
55
+ #
56
+ # @return [Array<Object>]
57
+ def defined_trait_by_name(defined, factory, trait_name)
58
+ if factory
59
+ possible_owner = defined.find_factory_by_names(factory.names)
60
+
61
+ while possible_owner
62
+ if (trait = possible_owner.traits.find { |t| t.name == trait_name })
63
+ return [possible_owner, trait]
64
+ end
65
+ possible_owner = defined.find_factory_by_names([possible_owner.parent_name])
61
66
  end
62
- possible_owner = defined.find_factory_by_names([possible_owner.parent_name])
63
67
  end
68
+
69
+ [nil, defined.find_trait_by_name(trait_name)]
64
70
  end
65
71
 
72
+ # @param [FactoryTrace::Structures::Factory] factory
73
+ # @param [FactoryTrace::Structures::Collection] collection
74
+ # @param [Symbol] status
75
+ def mark_factory(factory, collection, status:)
76
+ return if factory.has_prioritized_status?(status)
66
77
 
67
- [nil, defined.find_trait_by_name(trait_name)]
68
- end
78
+ factory.status = status
79
+ if (parent = collection.find_factory_by_names([factory.parent_name]))
80
+ mark_factory(parent, collection, status: :indirectly_used)
81
+ end
82
+ mark_declarations(factory.declaration_names, factory, collection, status: :indirectly_used)
83
+ end
69
84
 
70
- # @param [FactoryTrace::Structures::Factory] factory
71
- # @param [FactoryTrace::Structures::Collection] collection
72
- # @param [Symbol] status
73
- def self.mark_factory(factory, collection, status:)
74
- return if factory.has_prioritized_status?(status)
85
+ # @param [FactoryTrace::Structures::Trait] trait
86
+ # @param [FactoryTrace::Structures::Factory|nil] factory which trait belongs to
87
+ # @param [FactoryTrace::Structures::Collection] collection
88
+ # @param [Symbol] status
89
+ def mark_trait(trait, factory, collection, status:)
90
+ return if trait.has_prioritized_status?(status)
75
91
 
76
- factory.status = status
77
- if (parent = collection.find_factory_by_names([factory.parent_name]))
78
- mark_factory(parent, collection, status: :indirectly_used)
92
+ trait.status = status
93
+ mark_declarations(trait.declaration_names, factory, collection, status: :indirectly_used)
79
94
  end
80
- mark_declarations(factory.declaration_names, factory, collection, status: :indirectly_used)
81
- end
82
95
 
83
- # @param [FactoryTrace::Structures::Trait] trait
84
- # @param [FactoryTrace::Structures::Factory|nil] factory which trait belongs to
85
- # @param [FactoryTrace::Structures::Collection] collection
86
- # @param [Symbol] status
87
- def self.mark_trait(trait, factory, collection, status:)
88
- return if trait.has_prioritized_status?(status)
89
-
90
- trait.status = status
91
- mark_declarations(trait.declaration_names, factory, collection, status: :indirectly_used)
92
- end
96
+ # @param [Array<String>] declaration_names
97
+ # @param [FactoryTrace::Structures::Factory|nil] factory
98
+ # @param [FactoryTrace::Structures::Collection] collection
99
+ # @param [Symbol] status
100
+ def mark_declarations(declaration_names, factory, collection, status:)
101
+ declaration_names.each do |declaration_name|
102
+ declaration_factory = collection.find_factory_by_names([declaration_name])
103
+ next mark_factory(declaration_factory, collection, status: status) if declaration_factory
104
+
105
+ declaration_factory, declaration_trait = defined_trait_by_name(collection, factory, declaration_name)
106
+ mark_trait(declaration_trait, declaration_factory, collection, status: status) if declaration_trait
107
+ end
108
+ end
93
109
 
94
- # @param [Array<String>] declaration_names
95
- # @param [FactoryTrace::Structures::Factory|nil] factory
96
- # @param [FactoryTrace::Structures::Collection] collection
97
- # @param [Symbol] status
98
- def self.mark_declarations(declaration_names, factory, collection, status:)
99
- declaration_names.each do |declaration_name|
100
- declaration_factory = collection.find_factory_by_names([declaration_name])
101
- next mark_factory(declaration_factory, collection, status: status) if declaration_factory
102
-
103
- declaration_factory, declaration_trait = defined_trait_by_name(collection, factory, declaration_name)
104
- mark_trait(declaration_trait, declaration_factory, collection, status: status) if declaration_trait
110
+ # @param [Hash]
111
+ # @param [FactoryTrace::Structures::Factory|FactoryTrace::Structures::Trait]
112
+ #
113
+ # @return [Hash]
114
+ def append_definition_path(hash, object)
115
+ hash[:definition_path] = object.definition_path if object.definition_path
116
+ hash
105
117
  end
106
118
  end
107
119
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FactoryTrace
2
4
  module Readers
3
5
  class TraceReader
@@ -10,7 +12,7 @@ module FactoryTrace
10
12
  result = {defined: FactoryTrace::Structures::Collection.new, used: FactoryTrace::Structures::Collection.new}
11
13
 
12
14
  file_names.each do |file_name|
13
- File.open(file_name, 'r') do |file|
15
+ File.open(file_name, "r") do |file|
14
16
  data = new(file, configuration: configuration).read
15
17
 
16
18
  [:defined, :used].each do |key|
@@ -34,34 +36,35 @@ module FactoryTrace
34
36
  hash = JSON.parse(io.read)
35
37
 
36
38
  {
37
- defined: parse_collection(hash['defined']),
38
- used: parse_collection(hash['used'])
39
+ defined: parse_collection(hash["defined"]),
40
+ used: parse_collection(hash["used"])
39
41
  }
40
42
  end
41
43
 
42
44
  private
43
45
 
44
46
  def parse_trait(hash)
45
- FactoryTrace::Structures::Trait.new(hash['name'], declaration_names: hash['declaration_names'])
47
+ FactoryTrace::Structures::Trait.new(hash["name"], declaration_names: hash["declaration_names"], definition_path: hash["definition_path"])
46
48
  end
47
49
 
48
50
  def parse_factory(hash)
49
51
  FactoryTrace::Structures::Factory.new(
50
- hash['names'],
51
- hash['traits'].map(&method(:parse_trait)),
52
- parent_name: hash['parent_name'],
53
- declaration_names: hash['declaration_names']
52
+ hash["names"],
53
+ hash["traits"].map(&method(:parse_trait)),
54
+ parent_name: hash["parent_name"],
55
+ declaration_names: hash["declaration_names"],
56
+ definition_path: hash["definition_path"]
54
57
  )
55
58
  end
56
59
 
57
60
  def parse_collection(hash)
58
61
  collection = FactoryTrace::Structures::Collection.new
59
62
 
60
- hash['factories'].each do |h|
63
+ hash["factories"].each do |h|
61
64
  collection.add(parse_factory(h))
62
65
  end
63
66
 
64
- hash['traits'].each do |h|
67
+ hash["traits"].each do |h|
65
68
  collection.add(parse_trait(h))
66
69
  end
67
70
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FactoryTrace
2
4
  module Structures
3
5
  class Collection
@@ -69,10 +71,10 @@ module FactoryTrace
69
71
  end
70
72
 
71
73
  # @return [Boolean]
72
- def ==(collection)
73
- return false unless collection.is_a?(FactoryTrace::Structures::Collection)
74
+ def ==(other)
75
+ return false unless other.is_a?(FactoryTrace::Structures::Collection)
74
76
 
75
- factories == collection.factories && traits == collection.traits
77
+ factories == other.factories && traits == other.traits
76
78
  end
77
79
  end
78
80
  end
@@ -1,19 +1,23 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FactoryTrace
2
4
  module Structures
3
5
  class Factory
4
6
  include Helpers::Statusable
5
7
 
6
- attr_reader :names, :parent_name, :traits, :declaration_names
8
+ attr_reader :names, :parent_name, :traits, :declaration_names, :definition_path
7
9
 
8
10
  # @param [Array<String>] names
9
11
  # @param [Array<FactoryTrace::Structure::Trait>] traits
10
12
  # @param [String|nil] parent_name
11
13
  # @param [Array<String>] declaration_names
12
- def initialize(names, traits, parent_name: nil, declaration_names: [])
14
+ # @param [String] definition_path
15
+ def initialize(names, traits, parent_name: nil, declaration_names: [], definition_path: nil)
13
16
  @names = names
14
17
  @traits = traits
15
18
  @parent_name = parent_name
16
19
  @declaration_names = declaration_names
20
+ @definition_path = definition_path
17
21
  end
18
22
 
19
23
  # @return [Hash<Symbol, Object>]
@@ -22,7 +26,8 @@ module FactoryTrace
22
26
  names: names,
23
27
  traits: traits.map(&:to_h),
24
28
  parent_name: parent_name,
25
- declaration_names: declaration_names
29
+ declaration_names: declaration_names,
30
+ definition_path: definition_path
26
31
  }
27
32
  end
28
33
 
@@ -36,13 +41,14 @@ module FactoryTrace
36
41
  end
37
42
 
38
43
  # @return [Boolean]
39
- def ==(factory)
40
- return false unless factory.is_a?(FactoryTrace::Structures::Factory)
44
+ def ==(other)
45
+ return false unless other.is_a?(FactoryTrace::Structures::Factory)
41
46
 
42
- names == factory.names &&
43
- traits == factory.traits &&
44
- parent_name == factory.parent_name &&
45
- declaration_names == factory.declaration_names
47
+ names == other.names &&
48
+ traits == other.traits &&
49
+ parent_name == other.parent_name &&
50
+ declaration_names == other.declaration_names &&
51
+ definition_path == other.definition_path
46
52
  end
47
53
  end
48
54
  end
@@ -1,30 +1,35 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FactoryTrace
2
4
  module Structures
3
5
  class Trait
4
6
  include Helpers::Statusable
5
7
 
6
- attr_reader :name, :declaration_names
8
+ attr_reader :name, :declaration_names, :definition_path
7
9
 
8
10
  # @param [String] name
9
11
  # @param [Array<String>] declaration_names
10
- def initialize(name, declaration_names: [])
12
+ # @param [String] definition_path
13
+ def initialize(name, declaration_names: [], definition_path: nil)
11
14
  @name = name
12
15
  @declaration_names = declaration_names
16
+ @definition_path = definition_path
13
17
  end
14
18
 
15
19
  # @return [Hash<Symbol, Object>]
16
20
  def to_h
17
21
  {
18
22
  name: name,
19
- declaration_names: declaration_names
23
+ declaration_names: declaration_names,
24
+ definition_path: definition_path
20
25
  }
21
26
  end
22
27
 
23
28
  # @return [Boolean]
24
- def ==(trait)
25
- return false unless trait.is_a?(FactoryTrace::Structures::Trait)
29
+ def ==(other)
30
+ return false unless other.is_a?(FactoryTrace::Structures::Trait)
26
31
 
27
- name == trait.name && declaration_names == trait.declaration_names
32
+ name == other.name && declaration_names == other.declaration_names && definition_path == other.definition_path
28
33
  end
29
34
  end
30
35
  end
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support"
4
+
1
5
  module FactoryTrace
2
6
  class Tracker
3
7
  attr_reader :storage
@@ -7,7 +11,7 @@ module FactoryTrace
7
11
  end
8
12
 
9
13
  def track!
10
- ActiveSupport::Notifications.subscribe('factory_bot.run_factory') do |_name, _start, _finish, _id, payload|
14
+ ActiveSupport::Notifications.subscribe("factory_bot.run_factory") do |_name, _start, _finish, _id, payload|
11
15
  name = payload[:name].to_s
12
16
  traits = payload[:traits].map(&:to_s)
13
17
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FactoryTrace
2
- VERSION = '0.3.2'
4
+ VERSION = "1.0.0"
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FactoryTrace
2
4
  module Writers
3
5
  class ReportWriter < Writer
@@ -9,8 +11,8 @@ module FactoryTrace
9
11
  }.freeze
10
12
 
11
13
  CODES = {
12
- used: 'used',
13
- unused: 'unused',
14
+ used: "used",
15
+ unused: "unused"
14
16
  }.freeze
15
17
 
16
18
  # @param [Array<Hash>] results
@@ -27,15 +29,14 @@ module FactoryTrace
27
29
  # @param [Hash<Symbol, Object>] result
28
30
  # @param [Symbol] total_color
29
31
  def convert(result, total_color:)
30
- case
31
- when result[:value]
32
+ if result[:value]
32
33
  colorize(total_color, "total number of unique #{humanize_code(result[:code])} factories & traits: #{result[:value]}")
33
- when result[:factory_names] && result[:trait_name]
34
- "#{humanize_code(result[:code])} trait #{colorize(:blue, result[:trait_name])} of factory #{list(result[:factory_names])}"
35
- when result[:factory_names]
36
- "#{humanize_code(result[:code])} factory #{list(result[:factory_names])}"
34
+ elsif result[:factory_names] && result[:trait_name]
35
+ append_definition_path(result) { "#{humanize_code(result[:code])} trait #{colorize(:blue, result[:trait_name])} of factory #{list(result[:factory_names])}" }
36
+ elsif result[:factory_names]
37
+ append_definition_path(result) { "#{humanize_code(result[:code])} factory #{list(result[:factory_names])}" }
37
38
  else
38
- "#{humanize_code(result[:code])} global trait #{colorize(:blue, result[:trait_name])}"
39
+ append_definition_path(result) { "#{humanize_code(result[:code])} global trait #{colorize(:blue, result[:trait_name])}" }
39
40
  end
40
41
  end
41
42
 
@@ -45,12 +46,19 @@ module FactoryTrace
45
46
  "#{COLORS[color]}#{msg}\e[0m"
46
47
  end
47
48
 
49
+ def append_definition_path(result)
50
+ msg = yield
51
+ return msg unless configuration.trace_definition? && result[:definition_path]
52
+
53
+ "#{msg} => #{result[:definition_path]}"
54
+ end
55
+
48
56
  def humanize_code(code)
49
57
  CODES[code]
50
58
  end
51
59
 
52
60
  def list(elements, color: :blue)
53
- elements.map { |element| colorize(color, element) }.join(', ')
61
+ elements.map { |element| colorize(color, element) }.join(", ")
54
62
  end
55
63
  end
56
64
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FactoryTrace
2
4
  module Writers
3
5
  class TraceWriter < Writer
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FactoryTrace
2
4
  module Writers
3
5
  class Writer
data/lib/factory_trace.rb CHANGED
@@ -1,34 +1,46 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # External dependencies
2
- require 'factory_bot'
3
- require 'json'
4
- require 'set'
4
+ require "factory_bot"
5
+ require "json"
6
+ require "set"
7
+ require "pathname"
5
8
  # Library
6
- require 'factory_trace/configuration'
7
- require 'factory_trace/version'
8
- require 'factory_trace/helpers/converter'
9
- require 'factory_trace/helpers/statusable'
10
- require 'factory_trace/tracker'
9
+ require "factory_trace/configuration"
10
+ require "factory_trace/version"
11
+ require "factory_trace/helpers/converter"
12
+ require "factory_trace/helpers/statusable"
13
+ require "factory_trace/helpers/caller"
14
+ require "factory_trace/tracker"
15
+
16
+ require "factory_trace/structures/factory"
17
+ require "factory_trace/structures/trait"
18
+ require "factory_trace/structures/collection"
19
+
20
+ require "factory_trace/preprocessors/extract_defined"
21
+ require "factory_trace/preprocessors/extract_used"
11
22
 
12
- require 'factory_trace/structures/factory'
13
- require 'factory_trace/structures/trait'
14
- require 'factory_trace/structures/collection'
23
+ require "factory_trace/processors/find_unused"
15
24
 
16
- require 'factory_trace/preprocessors/extract_defined'
17
- require 'factory_trace/preprocessors/extract_used'
25
+ require "factory_trace/readers/trace_reader"
26
+ require "factory_trace/writers/writer"
27
+ require "factory_trace/writers/report_writer"
28
+ require "factory_trace/writers/trace_writer"
18
29
 
19
- require 'factory_trace/processors/find_unused'
30
+ require "factory_trace/monkey_patches/monkey_patches"
31
+ require "factory_trace/monkey_patches/factory"
32
+ require "factory_trace/monkey_patches/trait"
33
+ require "factory_trace/monkey_patches/definition_proxy"
34
+ require "factory_trace/monkey_patches/dsl"
20
35
 
21
- require 'factory_trace/readers/trace_reader'
22
- require 'factory_trace/writers/writer'
23
- require 'factory_trace/writers/report_writer'
24
- require 'factory_trace/writers/trace_writer'
25
36
  # Integrations
26
- require 'integrations/rspec' if defined?(RSpec::Core)
37
+ require "integrations/rspec" if defined?(RSpec::Core)
27
38
 
28
39
  module FactoryTrace
29
40
  class << self
30
41
  def start
31
42
  return unless configuration.enabled
43
+ trace_definitions! if configuration.trace_definition?
32
44
 
33
45
  tracker.track!
34
46
  end
@@ -67,5 +79,12 @@ module FactoryTrace
67
79
  def tracker
68
80
  @tracker ||= Tracker.new
69
81
  end
82
+
83
+ def trace_definitions!
84
+ FactoryBot::Factory.prepend(FactoryTrace::MonkeyPatches::Factory)
85
+ FactoryBot::Trait.prepend(FactoryTrace::MonkeyPatches::Trait)
86
+ FactoryBot::Syntax::Default::DSL.prepend(FactoryTrace::MonkeyPatches::Default::DSL)
87
+ FactoryBot::DefinitionProxy.prepend(FactoryTrace::MonkeyPatches::DefinitionProxy)
88
+ end
70
89
  end
71
90
  end
@@ -1,5 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  RSpec.configure do |config|
2
4
  config.before(:suite) { FactoryTrace.start }
3
5
  config.after(:suite) { FactoryTrace.stop }
4
6
  end
5
-
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: factory_trace
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - djezzzl
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-06-12 00:00:00.000000000 Z
11
+ date: 2022-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: factory_bot
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec_junit_formatter
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.4'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.4'
69
83
  description:
70
84
  email:
71
85
  - lawliet.djez@gmail.com
@@ -77,8 +91,14 @@ files:
77
91
  - exe/factory_trace
78
92
  - lib/factory_trace.rb
79
93
  - lib/factory_trace/configuration.rb
94
+ - lib/factory_trace/helpers/caller.rb
80
95
  - lib/factory_trace/helpers/converter.rb
81
96
  - lib/factory_trace/helpers/statusable.rb
97
+ - lib/factory_trace/monkey_patches/definition_proxy.rb
98
+ - lib/factory_trace/monkey_patches/dsl.rb
99
+ - lib/factory_trace/monkey_patches/factory.rb
100
+ - lib/factory_trace/monkey_patches/monkey_patches.rb
101
+ - lib/factory_trace/monkey_patches/trait.rb
82
102
  - lib/factory_trace/preprocessors/extract_defined.rb
83
103
  - lib/factory_trace/preprocessors/extract_used.rb
84
104
  - lib/factory_trace/processors/find_unused.rb
@@ -111,8 +131,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
131
  - !ruby/object:Gem::Version
112
132
  version: '0'
113
133
  requirements: []
114
- rubyforge_project:
115
- rubygems_version: 2.7.9
134
+ rubygems_version: 3.1.6
116
135
  signing_key:
117
136
  specification_version: 4
118
137
  summary: Provide an easy way to maintain factories and traits from FactoryBot