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 +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
|