factory_trace 0.3.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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