minitest-holdify 1.1.2 → 1.1.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: 633215ac6e960bb4fe8e63dbf22d1247b9b684da3a2300611882b5a1251ca0ad
4
- data.tar.gz: a80e8995767b2b3438dc809f494a473e4376da664924ba6ee117aa26ccc2d274
3
+ metadata.gz: 7560a67982ab6acf747a90307f0fc5fca6ff30c4675aefaf92c973afaa01fe65
4
+ data.tar.gz: 928f88bd3d8711d13817c924a5c587117e9e61d1cb3a7301b2a097f7cfafb95a
5
5
  SHA512:
6
- metadata.gz: '0129f206eddc8ba5683d64e6ac5c4273dd83818a43ef636a5493706816143b6b35c567bcb407aed623c3c761f0a1d954ac23b2c691c6e81b6f1affcdad0d4ac5'
7
- data.tar.gz: e1980a9bfd4f392c40c13194bb35c6d375f26bcef76a93ac4d1173305da5d3c557e8ecf69e659194ce1515b89b8ae2f423f204db883ff0c092c13db467c9e395
6
+ metadata.gz: b2cb240ed6c9d90797003b00508b4640d694617b78661fd8ff59a7533eb771a58e12d1f24024cf09d71224c490446c92f325b3bc4b0217ee2c2774d3f78ab4f9
7
+ data.tar.gz: aa038a10daa87f5d4700d7778dd86e75049d06036f2435b769c455b2f4f37e08fac5a21a91d7a375f06a53dda9a5c2ac50858f4e26cdde27e4d2a6732976fa7c
data/lib/holdify/hold.rb CHANGED
@@ -8,37 +8,37 @@ module Holdify
8
8
  def initialize(test)
9
9
  @test = test
10
10
  @path, = test.method(test.name).source_location
11
- @store = Holdify.stores[@path] ||= Store.new(@path)
11
+ @store = Holdify.stores(@path)
12
12
  @session = Hash.new { |h, k| h[k] = [] } # { line => [values] }
13
- @forced = [] # [ "file:line" ]
14
- @added = [] # [ "file:line" ]
13
+ @forced = [] # [ line ]
14
+ @added = [] # [ line ]
15
15
  end
16
16
 
17
17
  def call(actual, force: false)
18
18
  location = find_location
19
19
  line = location.lineno
20
- raise "Could not find holdify statement at line #{line}" unless @store.xxh_at(line)
20
+ raise "Could not find holdify statement at line #{line}" unless @store.xxh(line)
21
21
 
22
- @session[line] << actual
23
- @forced << "#{@path}:#{line}" if force
22
+ @forced << line if force
24
23
 
25
- return actual if force || Holdify.reconcile
26
-
27
- # Expected value
28
24
  values = @store.get(line)
29
- index = @session[line].size - 1
30
- return values[index] if values && index < values.size
31
-
32
- @added << "#{@path}:#{line}"
33
- actual
25
+ index = @session[line].size
26
+ value = if force || Holdify.reconcile
27
+ actual
28
+ elsif values && index < values.size
29
+ values[index]
30
+ else
31
+ @added << line
32
+ actual
33
+ end
34
+
35
+ @session[line] << value
36
+ value
34
37
  end
35
38
 
36
39
  def save
37
- return unless @test.failures.empty?
38
-
39
- @added.each { |loc| warn "[holdify] Held new value for #{loc}" } unless Holdify.quiet
40
+ @added.each { |line| warn "[holdify] Held new value for #{@path}:#{line}" } unless Holdify.quiet
40
41
  @session.each { |line, values| @store.set(line, values) }
41
- @store.save
42
42
  end
43
43
 
44
44
  # Find the location in the test that triggered the hold
@@ -9,28 +9,26 @@ module Holdify
9
9
  def initialize(path, source)
10
10
  @path = "#{path}#{CONFIG[:ext]}"
11
11
  @source = source
12
- File.delete(@path) if Holdify.reconcile && File.exist?(@path)
13
- @data = load_and_align
12
+ FileUtils.rm_f(@path) if Holdify.reconcile
13
+ @data = File.exist?(@path) ? load_and_align : {}
14
14
  end
15
15
 
16
16
  def get(line) = @data[line]
17
17
 
18
18
  def set(line, values) = (@data[line] = values)
19
19
 
20
- def save
20
+ def persist
21
21
  return FileUtils.rm_f(@path) if @data.empty?
22
22
 
23
23
  output = {}
24
24
  @data.keys.sort.each do |line|
25
- sha = @source.xxh_at(line)
26
- next unless sha
25
+ xxh = @source.xxh(line)
26
+ next unless xxh
27
27
 
28
- output["L#{line} #{sha}"] = @data[line]
28
+ output["L#{line} #{xxh}"] = @data[line]
29
29
  end
30
30
 
31
31
  content = YAML.dump(output, line_width: 78) # Ensure 80 columns (including pretty gutter)
32
- return if File.exist?(@path) && File.read(@path) == content
33
-
34
32
  File.write(@path, content)
35
33
  end
36
34
 
@@ -38,19 +36,19 @@ module Holdify
38
36
 
39
37
  def load_and_align
40
38
  {}.tap do |aligned|
41
- raw_data = (File.exist?(@path) && YAML.unsafe_load_file(@path)) || {}
42
- raw_data.group_by { |k, _| k.split.last }.each do |sha, entries|
43
- target_lines = @source.lines_with(sha)
44
- next if target_lines.empty?
45
-
46
- # Old data
47
- candidates = entries.map { |key, values| { line: key[/\d+/].to_i, values: values } }
48
- exact, moved = candidates.partition { |c| target_lines.include?(c[:line]) }
39
+ data = YAML.unsafe_load_file(@path) || {}
40
+ data.group_by { |k, _| k.split.last }.each do |xxh, entries|
41
+ lines = @source.lines(xxh)
42
+ next if lines.empty?
43
+
44
+ # Position of the held lines compared to the source lines
45
+ stayed, moved = entries.map { |key, values| { line: key[/\d+/].to_i, values: values } }
46
+ .partition { |c| lines.include?(c[:line]) }
49
47
  moved.sort_by! { |c| c[:line] }
50
48
 
51
- # New aligned data
52
- target_lines.each do |line|
53
- match = exact.find { |c| c[:line] == line } || moved.shift
49
+ # Align lines
50
+ lines.each do |line|
51
+ match = stayed.find { |c| c[:line] == line } || moved.shift
54
52
  aligned[line] = match[:values] if match
55
53
  end
56
54
  end
@@ -1,32 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'xxhash'
3
+ require 'digest/xxhash'
4
4
 
5
5
  module Holdify
6
6
  # Represents the current state of the source file
7
7
  class Source
8
- def initialize(path) = (@line_sha, @sha_lines = parse(path))
8
+ def initialize(path) = (@line_xxh, @xxh_lines = parse(path))
9
9
 
10
- def xxh_at(line) = @line_sha[line]
10
+ def xxh(line) = @line_xxh[line]
11
11
 
12
- def lines_with(sha) = @sha_lines[sha]
12
+ def lines(xxh) = @xxh_lines[xxh]
13
13
 
14
14
  private
15
15
 
16
16
  def parse(path)
17
- line_sha = {}
18
- sha_lines = Hash.new { |h, k| h[k] = [] }
17
+ line_xxh = {}
18
+ xxh_lines = Hash.new { |h, k| h[k] = [] }
19
19
 
20
20
  File.foreach(path).with_index(1) do |text, line|
21
21
  content = text.strip
22
22
  next if content.empty?
23
23
 
24
- sha = XXhash.xxh32(content).to_s
25
- line_sha[line] = sha
26
- sha_lines[sha] << line
24
+ xxh = Digest::XXH3_64bits.hexdigest(content)
25
+ line_xxh[line] = xxh
26
+ xxh_lines[xxh] << line
27
27
  end
28
28
 
29
- [line_sha, sha_lines]
29
+ [line_xxh, xxh_lines]
30
30
  end
31
31
  end
32
32
  end
data/lib/holdify/store.rb CHANGED
@@ -14,7 +14,7 @@ module Holdify
14
14
  @ledger = Ledger.new(path, @source)
15
15
  end
16
16
 
17
- def_delegator :@source, :xxh_at
18
- def_delegators :@ledger, :get, :set, :save
17
+ def_delegator :@source, :xxh
18
+ def_delegators :@ledger, :get, :set, :persist
19
19
  end
20
20
  end
data/lib/holdify.rb CHANGED
@@ -5,14 +5,24 @@ require_relative 'holdify/hold'
5
5
 
6
6
  # The container module
7
7
  module Holdify
8
- VERSION = '1.1.2'
8
+ VERSION = '1.1.3'
9
9
  CONFIG = { ext: '.yaml' }.freeze
10
10
 
11
11
  class << self
12
12
  attr_accessor :reconcile, :quiet
13
13
  attr_writer :pretty
14
14
 
15
- def stores = @stores ||= {}
15
+ def stores(path = nil)
16
+ return @stores unless path
17
+
18
+ @mutex.synchronize do
19
+ @stores[path] ||= Store.new(path)
20
+ end
21
+ end
22
+
23
+ def persist_all!
24
+ @stores&.each_value(&:persist)
25
+ end
16
26
 
17
27
  def pretty
18
28
  return @pretty unless @pretty.nil?
@@ -21,4 +31,6 @@ module Holdify
21
31
  system('git --version', out: File::NULL, err: File::NULL)
22
32
  end
23
33
  end
34
+ @mutex = Mutex.new
35
+ @stores = {}
24
36
  end
@@ -5,6 +5,11 @@ require 'holdify/pretty'
5
5
 
6
6
  # Implement the minitest plugin
7
7
  module Minitest
8
+ # Register the after_run hook to persist all data
9
+ def self.plugin_holdify_init(_options)
10
+ Minitest.after_run { Holdify.persist_all! }
11
+ end
12
+
8
13
  # Set the Holdify options
9
14
  def self.plugin_holdify_options(opts, _options)
10
15
  opts.on '--holdify-reconcile', 'Reconcile the held values with the new ones' do
@@ -26,12 +31,15 @@ module Minitest
26
31
  # Ensure store is tidied and saved after the test runs
27
32
  def before_teardown
28
33
  super
29
- @hold&.save
30
- return unless @hold&.forced&.any? && failures.empty?
34
+ return unless failures.empty? && @hold
35
+
36
+ @hold.save
37
+ return unless @hold.forced.any?
31
38
 
39
+ path, = method(name).source_location
32
40
  msg = <<~MSG.chomp
33
41
  [holdify] the value has been stored: remove the "!" suffix to pass the test
34
- #{@hold.forced.uniq.map { |l| " #{l}" }.join("\n")}
42
+ #{@hold.forced.uniq.map { |l| " #{path}:#{l}" }.join("\n")}
35
43
  MSG
36
44
  raise Minitest::Assertion, msg
37
45
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minitest-holdify
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Domizio Demichelis
@@ -10,33 +10,33 @@ cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
- name: minitest
13
+ name: digest-xxhash
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: 5.0.0
18
+ version: 0.2.9
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: 5.0.0
25
+ version: 0.2.9
26
26
  - !ruby/object:Gem::Dependency
27
- name: xxhash
27
+ name: minitest
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 0.7.0
32
+ version: 5.0.0
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
- version: 0.7.0
39
+ version: 5.0.0
40
40
  description: Stop maintaining large expected values in your test/fixture files! Hold
41
41
  them automatically. Update them effortlessly.
42
42
  email: