factory_trace 1.1.2 → 3.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: ba2e796c2bf1d78c202f054bc79172f40f83769943c868189236a9f4a3aab73f
4
- data.tar.gz: 165a48e486568f84f5e1c79f4c45a5f24499e8dca2304ab302cf06c619609966
3
+ metadata.gz: bd70e8ea6fe8ffb3e815147ea925478d36f4d298b9bbbd5b359b7d5e900d5265
4
+ data.tar.gz: e838d1f5525179c4fba7fa6daba3baf7ab8b23d27e981076069c3a4d33268472
5
5
  SHA512:
6
- metadata.gz: 13ab8c7bac357337789b4f406b910cfc58c26a48de5508b4e0ec63f90e93626abc714ef0e07b2ef64262e838b08f90829fb114be065b56b2a0248feedbdd736b
7
- data.tar.gz: f1beb66903bf3b102c62b3d5907edd9082fd88f1144e8711a17a0fde1be6bece115a1b33d91692659eb4f339b20920f1195831e7502fd36c6091349de54d46f1
6
+ metadata.gz: 0a0b4c5d0b471d570a4ab18567feed01559f861363779e4ba5010e8eb1b1a75a159d3affe54b0742da8c1909095df14cee0ec45eb7fbefcf3e594b8a58140037
7
+ data.tar.gz: 54b1804ed50d4ba0f327e9f18d100ad9c95c39c7ce6a373ed846aa5bbf8c6a9e7f5b42560db21b7922927aa135574a8f6d1acef6b39179b56bc911ba00dba151
@@ -2,7 +2,7 @@
2
2
 
3
3
  module FactoryTrace
4
4
  class Configuration
5
- attr_accessor :path, :enabled, :color, :mode, :trace_definition
5
+ attr_accessor :path, :enabled, :color, :mode, :trace_definition, :fixture_path
6
6
 
7
7
  def initialize
8
8
  @enabled = ENV.key?("FB_TRACE") || ENV.key?("FB_TRACE_FILE")
@@ -10,6 +10,7 @@ module FactoryTrace
10
10
  @color = path.nil?
11
11
  @mode = extract_mode(ENV["FB_TRACE"]) || :full
12
12
  @trace_definition = true
13
+ @fixture_path = "test/fixtures"
13
14
  end
14
15
 
15
16
  def trace_definition?
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FactoryTrace
4
+ class FixtureTracker
5
+ attr_reader :storage
6
+
7
+ def initialize
8
+ @storage = {}
9
+ end
10
+
11
+ def track!
12
+ tracker_storage = @storage
13
+
14
+ ::ActiveRecord::FixtureSet.prepend(Module.new do
15
+ define_method(:[]) do |fixture_name|
16
+ if fixture_name
17
+ tracker_storage[name] ||= Set.new
18
+ tracker_storage[name].add(fixture_name.to_s)
19
+ end
20
+ super(fixture_name)
21
+ end
22
+ end)
23
+ end
24
+ end
25
+ end
@@ -10,7 +10,7 @@ module FactoryTrace
10
10
  proxy = FactoryBot::DefinitionProxy.new(factory.definition)
11
11
  proxy.instance_eval(&block) if block
12
12
 
13
- REGISTER.register_factory(factory)
13
+ FactoryTrace.factory_bot_register.register_factory(factory)
14
14
 
15
15
  proxy.child_factories.each do |(child_name, child_caller_location, child_options, child_block)|
16
16
  parent_factory = child_options.delete(:parent) || name
@@ -19,7 +19,7 @@ module FactoryTrace
19
19
  end
20
20
 
21
21
  def trait(name, &block)
22
- REGISTER.register_trait(FactoryBot::Trait.new(name, Helpers::Caller.location, &block))
22
+ FactoryTrace.factory_bot_register.register_trait(FactoryBot::Trait.new(name, Helpers::Caller.location, &block))
23
23
  end
24
24
  end
25
25
  end
@@ -2,6 +2,5 @@
2
2
 
3
3
  module FactoryTrace
4
4
  module MonkeyPatches
5
- REGISTER = (FactoryBot::VERSION >= "5.1.0") ? FactoryBot::Internal : FactoryBot
6
5
  end
7
6
  end
@@ -7,7 +7,7 @@ module FactoryTrace
7
7
  def self.call
8
8
  collection = FactoryTrace::Structures::Collection.new
9
9
 
10
- MonkeyPatches::REGISTER.traits.each do |trait|
10
+ FactoryTrace.factory_bot_register.traits.each do |trait|
11
11
  collection.add(FactoryTrace::Helpers::Converter.trait(trait))
12
12
  end
13
13
 
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FactoryTrace
4
+ module Preprocessors
5
+ class ExtractDefinedFixtures
6
+ # Extracts all defined fixture sets and their entries from fixture YAML files
7
+ #
8
+ # @param [String, Array<String>] fixture_path path(s) to directories containing fixture YAML files
9
+ #
10
+ # @return [FactoryTrace::Structures::Collection]
11
+ def self.call(fixture_path)
12
+ collection = FactoryTrace::Structures::Collection.new
13
+
14
+ Array(fixture_path).each do |path|
15
+ Dir.glob(File.join(path, "**", "*.yml")).sort.each do |file|
16
+ fixture_set_name = File.basename(file, ".yml")
17
+ entries = parse_fixture_file(file)
18
+
19
+ traits = entries.map do |entry_name, definition_path|
20
+ FactoryTrace::Structures::Trait.new(entry_name, definition_path: definition_path)
21
+ end
22
+
23
+ factory = FactoryTrace::Structures::Factory.new(
24
+ [fixture_set_name],
25
+ traits,
26
+ definition_path: "#{file}:1"
27
+ )
28
+
29
+ collection.add(factory)
30
+ end
31
+ end
32
+
33
+ collection
34
+ end
35
+
36
+ # Parses a fixture YAML file and returns a hash of entry names to definition paths
37
+ #
38
+ # @param [String] file_path
39
+ #
40
+ # @return [Hash<String, String>]
41
+ def self.parse_fixture_file(file_path)
42
+ entries = {}
43
+ lineno = 1
44
+
45
+ File.foreach(file_path) do |line|
46
+ if (match = line.match(/\A(\w+):(?:\s|$)/))
47
+ entries[match[1]] = "#{file_path}:#{lineno}"
48
+ end
49
+ lineno += 1
50
+ end
51
+
52
+ entries
53
+ end
54
+
55
+ private_class_method :parse_fixture_file
56
+ end
57
+ end
58
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FactoryTrace
4
- VERSION = "1.1.2"
4
+ VERSION = "3.0.0"
5
5
  end
@@ -16,11 +16,14 @@ module FactoryTrace
16
16
  }.freeze
17
17
 
18
18
  # @param [Array<Hash>] results
19
- def write(results)
19
+ # @param [Symbol] kind - :factory (default) or :fixture
20
+ def write(results, kind:)
21
+ io.puts("")
22
+
20
23
  total_color = (results.any? { |result| result[:code] == :unused && !result.key?(:value) }) ? :red : :green
21
24
 
22
25
  results.each do |result|
23
- io.puts(convert(result, total_color: total_color))
26
+ io.puts(convert(result, total_color: total_color, kind: kind))
24
27
  end
25
28
  end
26
29
 
@@ -28,13 +31,23 @@ module FactoryTrace
28
31
 
29
32
  # @param [Hash<Symbol, Object>] result
30
33
  # @param [Symbol] total_color
31
- def convert(result, total_color:)
34
+ # @param [Symbol] kind - :factory_bot or :fixtures
35
+ def convert(result, total_color:, kind:)
32
36
  if result[:value]
33
- colorize(total_color, "total number of unique #{humanize_code(result[:code])} factories & traits: #{result[:value]}")
37
+ label = (kind == :fixtures) ? "fixture sets & entries" : "factories & traits"
38
+ colorize(total_color, "total number of unique #{humanize_code(result[:code])} #{label}: #{result[:value]}")
34
39
  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])}" }
40
+ if kind == :fixtures
41
+ append_definition_path(result) { "#{humanize_code(result[:code])} fixture entry #{colorize(:blue, result[:trait_name])} of fixture set #{list(result[:factory_names])}" }
42
+ else
43
+ append_definition_path(result) { "#{humanize_code(result[:code])} trait #{colorize(:blue, result[:trait_name])} of factory #{list(result[:factory_names])}" }
44
+ end
36
45
  elsif result[:factory_names]
37
- append_definition_path(result) { "#{humanize_code(result[:code])} factory #{list(result[:factory_names])}" }
46
+ if kind == :fixtures
47
+ append_definition_path(result) { "#{humanize_code(result[:code])} fixture set #{list(result[:factory_names])}" }
48
+ else
49
+ append_definition_path(result) { "#{humanize_code(result[:code])} factory #{list(result[:factory_names])}" }
50
+ end
38
51
  else
39
52
  append_definition_path(result) { "#{humanize_code(result[:code])} global trait #{colorize(:blue, result[:trait_name])}" }
40
53
  end
@@ -5,7 +5,14 @@ module FactoryTrace
5
5
  class TraceWriter < Writer
6
6
  # @param [FactoryTrace::Structures::Collection] defined
7
7
  # @param [FactoryTrace::Structures::Collection] used
8
- def write(defined, used)
8
+ def write(defined, used, kind:)
9
+ io.puts("")
10
+ text =
11
+ case kind
12
+ when :factory_bot then "FactoryBot"
13
+ when :fixtures then "Fixtures"
14
+ end
15
+ io.puts("#{text} definitions and usages:")
9
16
  io.puts(JSON.pretty_generate(defined: defined.to_h, used: used.to_h))
10
17
  end
11
18
  end
data/lib/factory_trace.rb CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  # External dependencies
4
4
  require "active_support"
5
- require "factory_bot"
6
5
  require "json"
7
6
  require "set"
8
7
  require "pathname"
@@ -13,6 +12,7 @@ require "factory_trace/helpers/converter"
13
12
  require "factory_trace/helpers/statusable"
14
13
  require "factory_trace/helpers/caller"
15
14
  require "factory_trace/tracker"
15
+ require "factory_trace/fixture_tracker"
16
16
 
17
17
  require "factory_trace/structures/factory"
18
18
  require "factory_trace/structures/trait"
@@ -20,6 +20,7 @@ require "factory_trace/structures/collection"
20
20
 
21
21
  require "factory_trace/preprocessors/extract_defined"
22
22
  require "factory_trace/preprocessors/extract_used"
23
+ require "factory_trace/preprocessors/extract_defined_fixtures"
23
24
 
24
25
  require "factory_trace/processors/find_unused"
25
26
 
@@ -36,6 +37,7 @@ require "factory_trace/monkey_patches/dsl"
36
37
 
37
38
  # Integrations
38
39
  require "integrations/rspec" if defined?(RSpec::Core)
40
+ require "integrations/minitest" if defined?(Minitest)
39
41
 
40
42
  module FactoryTrace
41
43
  class << self
@@ -43,19 +45,24 @@ module FactoryTrace
43
45
  return unless configuration.enabled
44
46
  trace_definitions! if configuration.trace_definition?
45
47
 
46
- tracker.track!
48
+ tracker.track! if factory_bot?
49
+ fixture_tracker.track! if fixtures?
47
50
  end
48
51
 
49
52
  def stop
50
53
  return unless configuration.enabled
51
54
 
52
55
  # This is required to exclude parent traits from +defined_traits+
53
- FactoryBot.reload
56
+ FactoryBot.reload if factory_bot?
54
57
 
55
58
  if configuration.mode?(:full)
56
- Writers::ReportWriter.new(configuration.out, configuration).write(Processors::FindUnused.call(defined, used))
59
+ writer = Writers::ReportWriter.new(configuration.out, configuration)
60
+ writer.write(Processors::FindUnused.call(defined, used), kind: :factory_bot) if factory_bot?
61
+ writer.write(Processors::FindUnused.call(defined_fixtures, used_fixtures), kind: :fixtures) if fixtures?
57
62
  elsif configuration.mode?(:trace_only)
58
- Writers::TraceWriter.new(configuration.out, configuration).write(defined, used)
63
+ writer = Writers::TraceWriter.new(configuration.out, configuration)
64
+ writer.write(defined, used, kind: :factory_bot) if factory_bot?
65
+ writer.write(defined_fixtures, used_fixtures, kind: :fixtures) if fixtures?
59
66
  end
60
67
  end
61
68
 
@@ -67,6 +74,10 @@ module FactoryTrace
67
74
  @configuration ||= Configuration.new
68
75
  end
69
76
 
77
+ def factory_bot_register
78
+ @factory_bot_register ||= (FactoryBot::VERSION >= "5.1.0") ? FactoryBot::Internal : FactoryBot
79
+ end
80
+
70
81
  private
71
82
 
72
83
  def used
@@ -81,7 +92,29 @@ module FactoryTrace
81
92
  @tracker ||= Tracker.new
82
93
  end
83
94
 
95
+ def fixture_tracker
96
+ @fixture_tracker ||= FixtureTracker.new
97
+ end
98
+
99
+ def defined_fixtures
100
+ @defined_fixtures ||= Preprocessors::ExtractDefinedFixtures.call(configuration.fixture_path)
101
+ end
102
+
103
+ def used_fixtures
104
+ @used_fixtures ||= Preprocessors::ExtractUsed.call(fixture_tracker.storage)
105
+ end
106
+
107
+ def factory_bot?
108
+ defined?(FactoryBot)
109
+ end
110
+
111
+ def fixtures?
112
+ defined?(ActiveRecord::FixtureSet)
113
+ end
114
+
84
115
  def trace_definitions!
116
+ return unless factory_bot?
117
+
85
118
  FactoryBot::Factory.prepend(FactoryTrace::MonkeyPatches::Factory)
86
119
  FactoryBot::Trait.prepend(FactoryTrace::MonkeyPatches::Trait)
87
120
  FactoryBot::Syntax::Default::DSL.prepend(FactoryTrace::MonkeyPatches::Default::DSL)
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ Minitest.after_run { FactoryTrace.stop }
4
+
5
+ module Minitest
6
+ class << self
7
+ prepend(Module.new do
8
+ def run(args = [])
9
+ FactoryTrace.start
10
+ super
11
+ end
12
+ end)
13
+ end
14
+ end
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: factory_trace
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - djezzzl
8
+ autorequire:
8
9
  bindir: exe
9
10
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
11
+ date: 2026-03-18 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
14
  name: factory_bot
@@ -16,7 +17,21 @@ dependencies:
16
17
  - - ">="
17
18
  - !ruby/object:Gem::Version
18
19
  version: '4.0'
19
- type: :runtime
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '4.0'
34
+ type: :development
20
35
  prerelease: false
21
36
  version_requirements: !ruby/object:Gem::Requirement
22
37
  requirements:
@@ -79,6 +94,7 @@ dependencies:
79
94
  - - "~>"
80
95
  - !ruby/object:Gem::Version
81
96
  version: '0.4'
97
+ description:
82
98
  email:
83
99
  - lawliet.djez@gmail.com
84
100
  executables:
@@ -89,6 +105,7 @@ files:
89
105
  - exe/factory_trace
90
106
  - lib/factory_trace.rb
91
107
  - lib/factory_trace/configuration.rb
108
+ - lib/factory_trace/fixture_tracker.rb
92
109
  - lib/factory_trace/helpers/caller.rb
93
110
  - lib/factory_trace/helpers/converter.rb
94
111
  - lib/factory_trace/helpers/statusable.rb
@@ -98,6 +115,7 @@ files:
98
115
  - lib/factory_trace/monkey_patches/monkey_patches.rb
99
116
  - lib/factory_trace/monkey_patches/trait.rb
100
117
  - lib/factory_trace/preprocessors/extract_defined.rb
118
+ - lib/factory_trace/preprocessors/extract_defined_fixtures.rb
101
119
  - lib/factory_trace/preprocessors/extract_used.rb
102
120
  - lib/factory_trace/processors/find_unused.rb
103
121
  - lib/factory_trace/readers/trace_reader.rb
@@ -109,12 +127,14 @@ files:
109
127
  - lib/factory_trace/writers/report_writer.rb
110
128
  - lib/factory_trace/writers/trace_writer.rb
111
129
  - lib/factory_trace/writers/writer.rb
130
+ - lib/integrations/minitest.rb
112
131
  - lib/integrations/rspec.rb
113
132
  homepage: https://github.com/djezzzl/factory_trace
114
133
  licenses:
115
134
  - MIT
116
135
  metadata:
117
136
  funding_uri: https://opencollective.com/factory_trace#support
137
+ post_install_message:
118
138
  rdoc_options: []
119
139
  require_paths:
120
140
  - lib
@@ -129,7 +149,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
129
149
  - !ruby/object:Gem::Version
130
150
  version: '0'
131
151
  requirements: []
132
- rubygems_version: 3.6.9
152
+ rubygems_version: 3.1.6
153
+ signing_key:
133
154
  specification_version: 4
134
155
  summary: Provide an easy way to maintain factories and traits from FactoryBot
135
156
  test_files: []