factory_trace 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 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