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 +4 -4
- data/exe/factory_trace +2 -1
- data/lib/factory_trace/configuration.rb +14 -7
- data/lib/factory_trace/helpers/caller.rb +19 -0
- data/lib/factory_trace/helpers/converter.rb +14 -2
- data/lib/factory_trace/helpers/statusable.rb +2 -0
- data/lib/factory_trace/monkey_patches/definition_proxy.rb +15 -0
- data/lib/factory_trace/monkey_patches/dsl.rb +27 -0
- data/lib/factory_trace/monkey_patches/factory.rb +14 -0
- data/lib/factory_trace/monkey_patches/monkey_patches.rb +7 -0
- data/lib/factory_trace/monkey_patches/trait.rb +14 -0
- data/lib/factory_trace/preprocessors/extract_defined.rb +3 -1
- data/lib/factory_trace/preprocessors/extract_used.rb +2 -0
- data/lib/factory_trace/processors/find_unused.rb +93 -81
- data/lib/factory_trace/readers/trace_reader.rb +13 -10
- data/lib/factory_trace/structures/collection.rb +5 -3
- data/lib/factory_trace/structures/factory.rb +15 -9
- data/lib/factory_trace/structures/trait.rb +11 -6
- data/lib/factory_trace/tracker.rb +5 -1
- data/lib/factory_trace/version.rb +3 -1
- data/lib/factory_trace/writers/report_writer.rb +18 -10
- data/lib/factory_trace/writers/trace_writer.rb +2 -0
- data/lib/factory_trace/writers/writer.rb +2 -0
- data/lib/factory_trace.rb +38 -19
- data/lib/integrations/rspec.rb +2 -1
- metadata +23 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fc2882cfec07c5a45a8cf464027b593f4e97891b4a959b49a061acec3728bd41
|
|
4
|
+
data.tar.gz: dbcfce3c2e80b177a108f7761477b09f404818cf3794f15ae30b4c1c286ac2a8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
|
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?(
|
|
7
|
-
@path = ENV[
|
|
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[
|
|
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
|
|
20
|
+
return $stdout unless path
|
|
14
21
|
|
|
15
|
-
File.open(path,
|
|
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
|
|
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
|
|
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
|
|
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
|
|
@@ -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,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
|
-
|
|
10
|
+
MonkeyPatches::REGISTER.traits.each do |trait|
|
|
9
11
|
collection.add(FactoryTrace::Helpers::Converter.trait(trait))
|
|
10
12
|
end
|
|
11
13
|
|
|
@@ -1,107 +1,119 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module FactoryTrace
|
|
2
4
|
module Processors
|
|
3
5
|
class FindUnused
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
28
|
-
|
|
30
|
+
output.unshift(code: :unused, value: output.size)
|
|
31
|
+
output.unshift(code: :used, value: defined.total - (output.size - 1))
|
|
29
32
|
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
output
|
|
34
|
+
end
|
|
32
35
|
|
|
33
|
-
|
|
36
|
+
private
|
|
34
37
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
68
|
-
|
|
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
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
|
|
77
|
-
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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,
|
|
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[
|
|
38
|
-
used: parse_collection(hash[
|
|
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[
|
|
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[
|
|
51
|
-
hash[
|
|
52
|
-
parent_name: hash[
|
|
53
|
-
declaration_names: hash[
|
|
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[
|
|
63
|
+
hash["factories"].each do |h|
|
|
61
64
|
collection.add(parse_factory(h))
|
|
62
65
|
end
|
|
63
66
|
|
|
64
|
-
hash[
|
|
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 ==(
|
|
73
|
-
return false unless
|
|
74
|
+
def ==(other)
|
|
75
|
+
return false unless other.is_a?(FactoryTrace::Structures::Collection)
|
|
74
76
|
|
|
75
|
-
factories ==
|
|
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
|
-
|
|
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 ==(
|
|
40
|
-
return false unless
|
|
44
|
+
def ==(other)
|
|
45
|
+
return false unless other.is_a?(FactoryTrace::Structures::Factory)
|
|
41
46
|
|
|
42
|
-
names ==
|
|
43
|
-
traits ==
|
|
44
|
-
parent_name ==
|
|
45
|
-
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
|
-
|
|
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 ==(
|
|
25
|
-
return false unless
|
|
29
|
+
def ==(other)
|
|
30
|
+
return false unless other.is_a?(FactoryTrace::Structures::Trait)
|
|
26
31
|
|
|
27
|
-
name ==
|
|
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(
|
|
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
4
|
module Writers
|
|
3
5
|
class ReportWriter < Writer
|
|
@@ -9,8 +11,8 @@ module FactoryTrace
|
|
|
9
11
|
}.freeze
|
|
10
12
|
|
|
11
13
|
CODES = {
|
|
12
|
-
used:
|
|
13
|
-
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
|
-
|
|
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
|
-
|
|
34
|
-
"#{humanize_code(result[:code])} trait #{colorize(:blue, result[:trait_name])} of factory #{list(result[:factory_names])}"
|
|
35
|
-
|
|
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
|
data/lib/factory_trace.rb
CHANGED
|
@@ -1,34 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# External dependencies
|
|
2
|
-
require
|
|
3
|
-
require
|
|
4
|
-
require
|
|
4
|
+
require "factory_bot"
|
|
5
|
+
require "json"
|
|
6
|
+
require "set"
|
|
7
|
+
require "pathname"
|
|
5
8
|
# Library
|
|
6
|
-
require
|
|
7
|
-
require
|
|
8
|
-
require
|
|
9
|
-
require
|
|
10
|
-
require
|
|
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
|
|
13
|
-
require 'factory_trace/structures/trait'
|
|
14
|
-
require 'factory_trace/structures/collection'
|
|
23
|
+
require "factory_trace/processors/find_unused"
|
|
15
24
|
|
|
16
|
-
require
|
|
17
|
-
require
|
|
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
|
|
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
|
|
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
|
data/lib/integrations/rspec.rb
CHANGED
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.
|
|
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:
|
|
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
|
-
|
|
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
|