factory_trace 0.2.2 → 0.2.3

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: 484192f056c62919a10db1bcabe6d3f769fc7be2973e1278e9eff0874c5a0d96
4
- data.tar.gz: 1b339e7c7b1d0a0fa8828631fff9a33926347cdafc22446061aa57b7483c2686
3
+ metadata.gz: eb1219bf45bfd040c463c2c49694f615bad866afe0042a1036feb02cd2a09d46
4
+ data.tar.gz: 326e1995408175cd60bbdf36a0e091b9111b3a3566034d920e42d04bf3eb5baf
5
5
  SHA512:
6
- metadata.gz: 866ba5578d028ca9eb9c623ea38c03ac5df59383831d3d0b11ee765e9f181e69260e49621fea2d353836361f8b6836b6b092fe73f7be948757e0782a6b5f0e05
7
- data.tar.gz: dd8cf671469977ab78a6821398a27e39c999b981eb6938bf016ab41be56684d16f259cce7663c154f6f9fd1c1b1d94f62288177e6a3e6e31a841affeb8c3f3b9
6
+ metadata.gz: 18d6d00e731569b979c8158927a8ee42d1177c8ada0da28173d48253d4185fc00aa957f258d06ad6c2b3a55ec581527aeadc176ea2ded9e3f3a5449c88bbf710
7
+ data.tar.gz: 1996554340f1aec3c1c997706679dce4ca5d4a43d6bdc3c45e3001d52d5ee26894201960cb5d6b1ae4dc78f93106aff2b43da12aabe91b1195c2b73d09f081e3
data/exe/factory_trace CHANGED
@@ -6,9 +6,9 @@ require 'factory_trace'
6
6
  fail "You should pass at least one file with traced information.\nYou can generate it using only_trace mode." if ARGV.empty?
7
7
 
8
8
  config = FactoryTrace.configuration
9
- data = FactoryTrace::TraceReader.read_from_files(*ARGV)
10
- data = FactoryTrace::FindUnused.call(data)
11
- code = data.size > 2 ? 1 : 0
9
+ hash = FactoryTrace::Readers::TraceReader.read_from_files(*ARGV)
10
+ reports = FactoryTrace::Processors::FindUnused.call(hash[:defined], hash[:used])
11
+ code = reports.any? { |report| report[:code] == :unused } ? 1 : 0
12
12
 
13
- FactoryTrace::ReportWriter.new(config.out, config: config).write(data)
13
+ FactoryTrace::Writers::ReportWriter.new(config.out, config).write(reports)
14
14
  exit(code)
@@ -0,0 +1,29 @@
1
+ module FactoryTrace
2
+ module Helpers
3
+ module Converter
4
+ module_function
5
+
6
+ # @param [FactoryBot::Trait] trait
7
+ # @param [FactoryBot::Factory] owner
8
+ #
9
+ # @return [FactoryTrace::Structures::Trait]
10
+ def trait(trait, owner = nil)
11
+ FactoryTrace::Structures::Trait.new(
12
+ trait.name.to_s,
13
+ owner && owner.name.to_s
14
+ )
15
+ end
16
+
17
+ # @param [FactoryBot::Factory] factory
18
+ #
19
+ # @return [FactoryTrace::Structures::Factory]
20
+ def factory(factory)
21
+ FactoryTrace::Structures::Factory.new(
22
+ factory.name.to_s,
23
+ factory.send(:parent).respond_to?(:name) ? factory.send(:parent).name.to_s : nil,
24
+ factory.defined_traits.map(&:name).map(&:to_s)
25
+ )
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,20 @@
1
+ module FactoryTrace
2
+ module Preprocessors
3
+ class ExtractDefined
4
+ # @return [FactoryTrace::Structures::Collection]
5
+ def self.call
6
+ collection = FactoryTrace::Structures::Collection.new
7
+
8
+ FactoryBot.traits.each do |trait|
9
+ collection.add(FactoryTrace::Helpers::Converter.trait(trait))
10
+ end
11
+
12
+ FactoryBot.factories.each do |factory|
13
+ collection.add(FactoryTrace::Helpers::Converter.factory(factory))
14
+ end
15
+
16
+ collection
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ module FactoryTrace
2
+ module Preprocessors
3
+ class ExtractUsed
4
+ # Returns a collection with used factories and traits gathered from trace
5
+ #
6
+ # @param [Hash<String, Set<String>>]
7
+ #
8
+ # @return [FactoryTrace::Structures::Collection]
9
+ def self.call(trace)
10
+ collection = FactoryTrace::Structures::Collection.new
11
+
12
+ trace.each do |factory_name, trait_names|
13
+ collection.add(FactoryTrace::Structures::Factory.new(factory_name, nil, trait_names.to_a))
14
+ end
15
+
16
+ collection
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,118 @@
1
+ module FactoryTrace
2
+ module Processors
3
+ 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
+ used_inherited_traits = used_inherited_traits(defined, used)
12
+ used_child_factories = used_child_factories(defined, used)
13
+
14
+ output = []
15
+
16
+ defined.factories.each_value do |factory|
17
+ unless used.factories[factory.name]
18
+ if used_child_factories[factory.name]
19
+ output << {code: :used_indirectly, factory_name: factory.name, child_factories_names: used_child_factories[factory.name]}
20
+ else
21
+ output << {code: :unused, factory_name: factory.name}
22
+ end
23
+ end
24
+
25
+ factory.trait_names.each do |trait_name|
26
+ unless trait_used?(used, factory.name, trait_name) || trait_used?(used_inherited_traits, factory.name, trait_name)
27
+ output << {code: :unused, factory_name: factory.name, trait_name: trait_name}
28
+ end
29
+ end
30
+ end
31
+
32
+ defined.traits.each_value do |trait|
33
+ unless used_inherited_traits.traits[trait.name]
34
+ output << {code: :unused, trait_name: trait.name}
35
+ next
36
+ end
37
+ end
38
+
39
+ unused_count = output.count { |result| result[:code] == :unused }
40
+ used_indirectly_count = output.count { |result| result[:code] == :used_indirectly }
41
+
42
+ output.unshift(code: :unused, value: unused_count)
43
+ output.unshift(code: :used_indirectly, value: used_indirectly_count)
44
+ output.unshift(code: :used, value: defined.total - unused_count - used_indirectly_count)
45
+
46
+ output
47
+ end
48
+
49
+ private
50
+
51
+ # Checks if factory of the collection contains a trait
52
+ #
53
+ # @param [FactoryTrace::Structures::Collection] collection
54
+ # @param [String] factory_name
55
+ # @param [String] trait_name
56
+ #
57
+ # @return [Boolean]
58
+ def self.trait_used?(collection, factory_name, trait_name)
59
+ collection.factories[factory_name] && collection.factories[factory_name].trait_names.include?(trait_name)
60
+ end
61
+
62
+ # Returns a new collection where traits which were used moved to their owner factory
63
+ #
64
+ # @param [FactoryTrace::Structures::Collection] defined
65
+ # @param [FactoryTrace::Structures::Collection] used
66
+ #
67
+ # @return [FactoryTrace::Structures::Collection]
68
+ def self.used_inherited_traits(defined, used)
69
+ collection = FactoryTrace::Structures::Collection.new
70
+
71
+ used.factories.each_value do |factory|
72
+ factory.trait_names.each do |trait_name|
73
+ possible_owner_name = factory.name
74
+
75
+ while possible_owner_name
76
+ break if defined.factories[possible_owner_name].trait_names.include?(trait_name)
77
+ possible_owner_name = defined.factories[possible_owner_name].parent_name
78
+ end
79
+
80
+ if possible_owner_name
81
+ factory = collection.factories[possible_owner_name]
82
+ factory ||= collection.add(FactoryTrace::Structures::Factory.new(possible_owner_name, nil, []))
83
+
84
+ factory.trait_names << trait_name unless factory.trait_names.include?(trait_name)
85
+ else
86
+ collection.add(FactoryTrace::Structures::Trait.new(trait_name, nil))
87
+ end
88
+ end
89
+ end
90
+
91
+ collection
92
+ end
93
+
94
+ # Returns a hash:
95
+ # - key is factory name
96
+ # - value is factory names which where used and are children of the factory
97
+ #
98
+ # @param [FactoryTrace::Structures::Collection] defined
99
+ # @param [FactoryTrace::Structures::Collection] used
100
+ #
101
+ # @return [Hash<String, Array<String>]
102
+ def self.used_child_factories(defined, used)
103
+ hash = {}
104
+
105
+ used.factories.each_value do |factory|
106
+ parent_name = defined.factories[factory.name].parent_name
107
+
108
+ if parent_name
109
+ hash[parent_name] ||= []
110
+ hash[parent_name] << factory.name
111
+ end
112
+ end
113
+
114
+ hash
115
+ end
116
+ end
117
+ end
118
+ end
@@ -1,52 +1,59 @@
1
- require 'set'
2
-
3
1
  module FactoryTrace
4
- class TraceReader
5
- # Read the data from files and merge it
6
- # First hash - all factories
7
- # Second hash - used factories
8
- #
9
- # @return [Array<Hash>]
10
- def self.read_from_files(*file_names, config: Configuration.new)
11
- file_names.reduce([{}, {}]) do |array, file_name|
12
- reader = new(File.open(file_name, 'r'), config: config)
13
- new = reader.read
14
- array.each_with_index.map do |hash, index|
15
- hash.merge(new[index]) { |_key, v1, v2| v1 | v2 }
2
+ module Readers
3
+ class TraceReader
4
+ attr_reader :io, :configuration
5
+
6
+ # Read the data from files and merge it
7
+ #
8
+ # @return [Hash<Symbol, FactoryTrace::Structures::Collection>]
9
+ def self.read_from_files(*file_names, configuration: Configuration.new)
10
+ result = {defined: FactoryTrace::Structures::Collection.new, used: FactoryTrace::Structures::Collection.new}
11
+
12
+ file_names.each do |file_name|
13
+ File.open(file_name, 'r') do |file|
14
+ data = new(file, configuration: configuration).read
15
+
16
+ result.each do |key, collection|
17
+ collection.merge!(data[key])
18
+ end
19
+ end
16
20
  end
21
+
22
+ result
17
23
  end
18
- end
19
24
 
20
- def initialize(io, config: Configuration.new)
21
- @io = io
22
- @config = config
23
- end
25
+ def initialize(io, configuration: Configuration.new)
26
+ @io = io
27
+ @configuration = configuration
28
+ end
24
29
 
25
- # Read the data from file
26
- # First hash - all factories
27
- # Second hash - used factories
28
- #
29
- # @return [Array<Hash>]
30
- def read
31
- data = [{}, {}]
32
- point = -1
30
+ # Read the data from file
31
+ #
32
+ # @return [Hash<Symbol, FactoryTrace::Structures::Collection>]
33
+ def read
34
+ hash = JSON.parse(io.read)
33
35
 
34
- io.each_line do |line|
35
- next point += 1 if line.match?(/-all-|-used-/)
36
+ {
37
+ defined: parse_collection(hash['defined']),
38
+ used: parse_collection(hash['used'])
39
+ }
40
+ end
36
41
 
37
- factory, *traits = line.strip.split(',')
42
+ private
38
43
 
39
- if factory
40
- data[point][factory] ||= Set.new
41
- data[point][factory] |= traits
42
- end
43
- end
44
+ def parse_collection(hash)
45
+ collection = FactoryTrace::Structures::Collection.new
44
46
 
45
- data
46
- end
47
+ hash['factories'].each do |h|
48
+ collection.add(FactoryTrace::Structures::Factory.new(h['name'], h['parent_name'], h['trait_names']))
49
+ end
47
50
 
48
- private
51
+ hash['traits'].each do |h|
52
+ collection.add(FactoryTrace::Structures::Trait.new(h['name'], h['owner_name']))
53
+ end
49
54
 
50
- attr_reader :io, :config
55
+ collection
56
+ end
57
+ end
51
58
  end
52
59
  end
@@ -0,0 +1,82 @@
1
+ module FactoryTrace
2
+ module Structures
3
+ class Collection
4
+ attr_reader :factories, :traits
5
+
6
+ # @param [Hash<String, FactoryTrace::Structures::Factory>]
7
+ # @param [Hash<String, FactoryTrace::Structures::Trait>]
8
+ def initialize(factories = {}, traits = {})
9
+ @factories = factories
10
+ @traits = traits
11
+ end
12
+
13
+ # @param [FactoryTrace::Structures::Factory, FactoryTrace::Structures::Trait] element
14
+ #
15
+ # @return [FactoryTrace::Structures::Factory, FactoryTrace::Structures::Trait]
16
+ def add(element)
17
+ case element
18
+ when FactoryTrace::Structures::Factory then store(factories, element)
19
+ when FactoryTrace::Structures::Trait then store(traits, element)
20
+ else
21
+ fail "Unknown element: #{element.inspect}"
22
+ end
23
+ end
24
+
25
+ # Merge passed collection into self
26
+ #
27
+ # @param [FactoryTrace::Structures::Collection]
28
+ #
29
+ # @return [FactoryTrace::Structures::Collection]
30
+ def merge!(collection)
31
+ collection.factories.each_value do |factory|
32
+ if factories[factory.name]
33
+ factories[factory.name].merge!(factory)
34
+ else
35
+ add(FactoryTrace::Structures::Factory.new(factory.name, factory.parent_name, factory.trait_names))
36
+ end
37
+ end
38
+
39
+ collection.traits.each_value do |trait|
40
+ add(FactoryTrace::Structures::Trait.new(trait.name, trait.owner_name)) unless traits[trait.name]
41
+ end
42
+ end
43
+
44
+ # @return [Hash]
45
+ def to_h
46
+ {
47
+ factories: convert(factories),
48
+ traits: convert(traits)
49
+ }
50
+ end
51
+
52
+ # Total number of factories and traits
53
+ #
54
+ # @return [Integer]
55
+ def total
56
+ traits.size + factories.size + factories.values.sum { |factory| factory.trait_names.size }
57
+ end
58
+
59
+ # @return [Boolean]
60
+ def ==(collection)
61
+ return false unless collection.is_a?(FactoryTrace::Structures::Collection)
62
+
63
+ factories == collection.factories && traits == collection.traits
64
+ end
65
+
66
+ private
67
+
68
+ # @param [Hash] hash
69
+ # @param [FactoryTrace::Structures::Factory, FactoryTrace::Structures::Trait] element
70
+ #
71
+ # @return [FactoryTrace::Structures::Factory, FactoryTrace::Structures::Trait] element
72
+ def store(hash, element)
73
+ hash[element.name] = element
74
+ end
75
+
76
+ # @return [Hash]
77
+ def convert(hash)
78
+ hash.each_value.map(&:to_h)
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,41 @@
1
+ module FactoryTrace
2
+ module Structures
3
+ class Factory
4
+ attr_reader :name, :parent_name, :trait_names
5
+
6
+ # @param [String] name
7
+ # @param [String, nil] parent_name
8
+ # @param [Array<String>] trait_names
9
+ def initialize(name, parent_name, trait_names)
10
+ @name = name
11
+ @parent_name = parent_name
12
+ @trait_names = trait_names
13
+ end
14
+
15
+ # @return [Hash<Symbol, String>]
16
+ def to_h
17
+ {
18
+ name: name,
19
+ parent_name: parent_name,
20
+ trait_names: trait_names
21
+ }
22
+ end
23
+
24
+ # Merge passed factory into self
25
+ #
26
+ # @param [FactoryTrace::Structures::Factory]
27
+ #
28
+ # @return [FactoryTrace::Structures::Factory]
29
+ def merge!(factory)
30
+ @trait_names = (trait_names + factory.trait_names).uniq
31
+ end
32
+
33
+ # @return [Boolean]
34
+ def ==(factory)
35
+ return false unless factory.is_a?(FactoryTrace::Structures::Factory)
36
+
37
+ name == factory.name && parent_name == factory.parent_name && trait_names == factory.trait_names
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,29 @@
1
+ module FactoryTrace
2
+ module Structures
3
+ class Trait
4
+ attr_reader :name, :owner_name
5
+
6
+ # @param [String] name
7
+ # @param [String, nil] owner_name
8
+ def initialize(name, owner_name)
9
+ @name = name
10
+ @owner_name = owner_name
11
+ end
12
+
13
+ # @return [Hash<Symbol, String>]
14
+ def to_h
15
+ {
16
+ name: name,
17
+ owner_name: owner_name
18
+ }
19
+ end
20
+
21
+ # @return [Boolean]
22
+ def ==(trait)
23
+ return false unless trait.is_a?(FactoryTrace::Structures::Trait)
24
+
25
+ name == trait.name && owner_name == trait.owner_name
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,5 +1,3 @@
1
- require 'set'
2
-
3
1
  module FactoryTrace
4
2
  class Tracker
5
3
  attr_reader :storage
@@ -10,8 +8,8 @@ module FactoryTrace
10
8
 
11
9
  def track!
12
10
  ActiveSupport::Notifications.subscribe('factory_bot.run_factory') do |_name, _start, _finish, _id, payload|
13
- name = payload[:name]
14
- traits = payload[:traits]
11
+ name = payload[:name].to_s
12
+ traits = payload[:traits].map(&:to_s)
15
13
 
16
14
  storage[name] ||= Set.new
17
15
  storage[name] |= traits
@@ -1,3 +1,3 @@
1
1
  module FactoryTrace
2
- VERSION = '0.2.2'
2
+ VERSION = '0.2.3'
3
3
  end
@@ -1,41 +1,67 @@
1
1
  module FactoryTrace
2
- class ReportWriter < Writer
3
- COLORS = {
4
- blue: "\e[34m",
5
- green: "\e[32m",
6
- red: "\e[31m"
7
- }.freeze
8
-
9
- # @param [Array<Hash>] results
10
- def write(results)
11
- total_color = results.size == 2 ? :green : :red
12
-
13
- results.each do |result|
14
- io.puts(convert(result, total_color: total_color))
2
+ module Writers
3
+ class ReportWriter < Writer
4
+ COLORS = {
5
+ blue: "\e[34m",
6
+ yellow: "\e[33m",
7
+ green: "\e[32m",
8
+ red: "\e[31m"
9
+ }.freeze
10
+
11
+ CODES = {
12
+ used: 'used',
13
+ unused: 'unused',
14
+ used_indirectly: 'used only indirectly'
15
+ }.freeze
16
+
17
+ # @param [Array<Hash>] results
18
+ def write(results)
19
+ total_color =
20
+ if results.any? { |result| result[:code] == :unused }
21
+ :red
22
+ elsif results.any? { |result| result[:code] == :used_indirectly }
23
+ :yellow
24
+ else
25
+ :green
26
+ end
27
+
28
+ results.each do |result|
29
+ io.puts(convert(result, total_color: total_color))
30
+ end
15
31
  end
16
- end
17
32
 
18
- private
19
-
20
- # @param [Hash<Symbol, Object>] result
21
- # @param [Symbol] total_color
22
- def convert(result, total_color:)
23
- case
24
- when result[:value]
25
- colorize(total_color, "total number of unique #{result[:code]} factories & traits: #{result[:value]}")
26
- when result[:factory_name] && result[:trait_name]
27
- "#{result[:code]} trait #{colorize(:blue, result[:trait_name])} of factory #{colorize(:blue, result[:factory_name])}"
28
- when result[:factory_name]
29
- "#{result[:code]} factory #{colorize(:blue, result[:factory_name])}"
30
- else
31
- "#{result[:code]} global trait #{colorize(:blue, result[:trait_name])}"
33
+ private
34
+
35
+ # @param [Hash<Symbol, Object>] result
36
+ # @param [Symbol] total_color
37
+ def convert(result, total_color:)
38
+ case
39
+ when result[:value]
40
+ colorize(total_color, "total number of unique #{humanize_code(result[:code])} factories & traits: #{result[:value]}")
41
+ when result[:factory_name] && result[:trait_name]
42
+ "#{humanize_code(result[:code])} trait #{colorize(:blue, result[:trait_name])} of factory #{colorize(:blue, result[:factory_name])}"
43
+ when result[:factory_name] && result[:child_factories_names]
44
+ "#{humanize_code(result[:code])} factory #{colorize(:blue, result[:factory_name])} as parent for #{list(result[:child_factories_names])}"
45
+ when result[:factory_name]
46
+ "#{humanize_code(result[:code])} factory #{colorize(:blue, result[:factory_name])}"
47
+ else
48
+ "#{humanize_code(result[:code])} global trait #{colorize(:blue, result[:trait_name])}"
49
+ end
32
50
  end
33
- end
34
51
 
35
- def colorize(color, msg)
36
- return msg unless config.color
52
+ def colorize(color, msg)
53
+ return msg unless configuration.color
37
54
 
38
- "#{COLORS[color]}#{msg}\e[0m"
55
+ "#{COLORS[color]}#{msg}\e[0m"
56
+ end
57
+
58
+ def humanize_code(code)
59
+ CODES[code]
60
+ end
61
+
62
+ def list(elements)
63
+ elements.map { |element| colorize(:blue, element) }.join(', ')
64
+ end
39
65
  end
40
66
  end
41
67
  end
@@ -1,20 +1,10 @@
1
1
  module FactoryTrace
2
- class TraceWriter < Writer
3
- # @param [Array<Hash>] results
4
- def write(results)
5
- io.puts('-all-')
6
- output(results[0])
7
- io.puts('-used-')
8
- output(results[1])
9
- end
10
-
11
- private
12
-
13
- # @param [Hash<Symbol, Set<Hash>>] data
14
- def output(data)
15
- data.each do |key, set|
16
- line = [key, set.to_a.join(',')].join(',')
17
- io.puts(line)
2
+ module Writers
3
+ class TraceWriter < Writer
4
+ # @param [FactoryTrace::Structures::Collection] defined
5
+ # @param [FactoryTrace::Structures::Collection] used
6
+ def write(defined, used)
7
+ io.puts(JSON.pretty_generate(defined: defined.to_h, used: used.to_h))
18
8
  end
19
9
  end
20
10
  end
@@ -1,23 +1,12 @@
1
1
  module FactoryTrace
2
- class Writer
3
- def self.factory(io, config: Configuration.new)
4
- writer =
5
- if config.mode?(:full)
6
- ReportWriter
7
- elsif config.mode?(:trace_only)
8
- TraceWriter
9
- end
10
-
11
- writer.new(io, config: config)
12
- end
13
-
14
- def initialize(io, config: Configuration.new)
15
- @io = io
16
- @config = config
2
+ module Writers
3
+ class Writer
4
+ attr_reader :io, :configuration
5
+
6
+ def initialize(io, configuration = Configuration.new)
7
+ @io = io
8
+ @configuration = configuration
9
+ end
17
10
  end
18
-
19
- private
20
-
21
- attr_reader :io, :config
22
11
  end
23
12
  end
data/lib/factory_trace.rb CHANGED
@@ -1,12 +1,21 @@
1
1
  # External dependencies
2
2
  require 'factory_bot'
3
+ require 'json'
4
+ require 'set'
3
5
  # Library
4
6
  require 'factory_trace/configuration'
5
7
  require 'factory_trace/version'
8
+ require 'factory_trace/helpers/converter'
6
9
  require 'factory_trace/tracker'
7
10
 
8
- require 'factory_trace/find_unused'
9
- require 'factory_trace/storage_handler'
11
+ require 'factory_trace/structures/factory'
12
+ require 'factory_trace/structures/trait'
13
+ require 'factory_trace/structures/collection'
14
+
15
+ require 'factory_trace/preprocessors/extract_defined'
16
+ require 'factory_trace/preprocessors/extract_used'
17
+
18
+ require 'factory_trace/processors/find_unused'
10
19
 
11
20
  require 'factory_trace/readers/trace_reader'
12
21
  require 'factory_trace/writers/writer'
@@ -29,7 +38,11 @@ module FactoryTrace
29
38
  # This is required to exclude parent traits from +defined_traits+
30
39
  FactoryBot.reload
31
40
 
32
- writer.write(results)
41
+ if configuration.mode?(:full)
42
+ Writers::ReportWriter.new(configuration.out, configuration).write(Processors::FindUnused.call(defined, used))
43
+ elsif configuration.mode?(:trace_only)
44
+ Writers::TraceWriter.new(configuration.out, configuration).write(defined, used)
45
+ end
33
46
  end
34
47
 
35
48
  def configure
@@ -42,24 +55,16 @@ module FactoryTrace
42
55
 
43
56
  private
44
57
 
45
- def results
46
- if configuration.mode?(:full)
47
- FindUnused.call(preprocessed)
48
- elsif configuration.mode?(:trace_only)
49
- preprocessed
50
- end
58
+ def used
59
+ @used ||= Preprocessors::ExtractUsed.call(tracker.storage)
51
60
  end
52
61
 
53
- def preprocessed
54
- @preprocessed ||= StorageHandler.prepare(tracker.storage)
62
+ def defined
63
+ @defined ||= Preprocessors::ExtractDefined.call
55
64
  end
56
65
 
57
66
  def tracker
58
67
  @tracker ||= Tracker.new
59
68
  end
60
-
61
- def writer
62
- @writer ||= Writer.factory(configuration.out, config: configuration)
63
- end
64
69
  end
65
70
  end
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.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - djezzzl
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-05-05 00:00:00.000000000 Z
11
+ date: 2019-05-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: factory_bot
@@ -77,9 +77,14 @@ files:
77
77
  - exe/factory_trace
78
78
  - lib/factory_trace.rb
79
79
  - lib/factory_trace/configuration.rb
80
- - lib/factory_trace/find_unused.rb
80
+ - lib/factory_trace/helpers/converter.rb
81
+ - lib/factory_trace/preprocessors/extract_defined.rb
82
+ - lib/factory_trace/preprocessors/extract_used.rb
83
+ - lib/factory_trace/processors/find_unused.rb
81
84
  - lib/factory_trace/readers/trace_reader.rb
82
- - lib/factory_trace/storage_handler.rb
85
+ - lib/factory_trace/structures/collection.rb
86
+ - lib/factory_trace/structures/factory.rb
87
+ - lib/factory_trace/structures/trait.rb
83
88
  - lib/factory_trace/tracker.rb
84
89
  - lib/factory_trace/version.rb
85
90
  - lib/factory_trace/writers/report_writer.rb
@@ -1,36 +0,0 @@
1
- module FactoryTrace
2
- class FindUnused
3
- # @param [Array<Hash>] initial_data
4
- # @return [Array<Hash>]
5
- def self.call(initial_data)
6
- all, used = initial_data
7
-
8
- output = []
9
-
10
- all.each do |factory_name, trait_names|
11
- unless used.key?(factory_name)
12
- output << {code: :unused, factory_name: factory_name}
13
- next
14
- end
15
-
16
- trait_names.each do |trait_name|
17
- unless used[factory_name].include?(trait_name)
18
- output << {code: :unused, trait_name: trait_name}.tap { |h| h[:factory_name] = factory_name unless factory_name == '_traits' }
19
- end
20
- end
21
- end
22
-
23
- output.unshift(code: :unused, value: output.size)
24
- output.unshift(code: :used, value: count_total(used))
25
-
26
- output
27
- end
28
-
29
- private
30
-
31
- # @param [Hash<Symbol, Set<Symbol>>]
32
- def self.count_total(data)
33
- data.reduce(0) { |result, (factory_name, trait_names)| result + (factory_name != '_traits' ? 1 : 0) + trait_names.size }
34
- end
35
- end
36
- end
@@ -1,61 +0,0 @@
1
- require 'set'
2
-
3
- module FactoryTrace
4
- class StorageHandler
5
- # @param [Hash<Symbol, Set<Symbol>>] initial_data
6
- #
7
- # First hash - all factories
8
- # Second hash - used factories
9
- #
10
- # @return [Array<Hash>]
11
- def self.prepare(initial_data)
12
- [collect_all, convert(initial_data)]
13
- end
14
-
15
- private
16
-
17
- def self.collect_all
18
- FactoryBot.factories.reduce({'_traits' => Set.new(FactoryBot.traits.map(&:name).map(&:to_s))}) do |hash, factory|
19
- hash[factory.name.to_s] = Set.new(factory.defined_traits.map(&:name).map(&:to_s))
20
- hash
21
- end
22
- end
23
-
24
- # Return new structure where each trait is moved to its own factory
25
- #
26
- # @param [Hash<Symbol, Set<Symbol>>]
27
- # @return [Hash<String, Set<String>>]
28
- def self.convert(data)
29
- # +_traits+ is for global traits
30
- output = {'_traits' => Set.new}
31
-
32
- data.each do |factory_name, trait_names|
33
- factory_name = factory_name.to_s
34
-
35
- output[factory_name] ||= Set.new
36
-
37
- trait_names.each do |trait_name|
38
- trait_name = trait_name.to_s
39
-
40
- factory = FactoryBot.factories[factory_name]
41
- trait_found = false
42
-
43
- until factory.is_a?(FactoryBot::NullFactory)
44
- if factory.defined_traits.any? { |trait| trait.name.to_s == trait_name }
45
- trait_found = true
46
- output[factory.name.to_s] ||= Set.new
47
- output[factory.name.to_s] << trait_name
48
- break
49
- end
50
- factory = factory.send(:parent)
51
- end
52
-
53
- # Belongs to global traits
54
- output['_traits'] << trait_name unless trait_found
55
- end
56
- end
57
-
58
- output
59
- end
60
- end
61
- end