minitest-holdify 1.3.0 → 1.3.2

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: b2fecbc870f5205d62da0200a806adc5dc5d47b99a81e53c1af4d50f3f8aaa21
4
- data.tar.gz: 06aed82a631a3632c531ef311a53f89e339a00d122fbc75eb31c52f1723e8d24
3
+ metadata.gz: 4fb43344c6f2a11991bd6ec2b71e7fabcb8a8c5f77bd2048cbac1f9c94b85448
4
+ data.tar.gz: d8c9580c6701d82c50e11b96bd4bf0bc8fe9efeb98f7287057c6f8220519425d
5
5
  SHA512:
6
- metadata.gz: ebd7c7cbf15fc450a1a657affe961399ac916c3d57aafc74a89067638ba2d569c59ea134eecd811361d6970989a227dc6814bc1bec07673ee5ea2ca86ea5f877
7
- data.tar.gz: c14c8219c1fbaaf1f10a6f28eef93f4696f71d59020090f85d96afe0ae431fa6a52db0a91d6f37f713ea266a6ef61369589bd85544a70c681f73c1902f0055eb
6
+ metadata.gz: b9420de8747442f0c2853caed136ac08bbd8066af4aa7d429efdec534a7e081b4a12b7bf7f5652de887f73c478a085f0f7032c34c5befd6b558b81128eff6583
7
+ data.tar.gz: 1c78694729ccf6de3192648f1d0657fcf7cbcb3d471fbb82ffd4e18e6a9378a58eea0ea23a7ee057a6206ecd474bd56455506f765bef2fa1d9a2633644c012f2
@@ -7,34 +7,30 @@ require 'open3'
7
7
  module Holdify
8
8
  # Feedback report on failure
9
9
  class Feedback
10
- attr_reader :xxhi_ref
11
-
12
10
  def initialize(hold, hold_ref, *args)
13
11
  test_lno = hold.test_loc.lineno
14
12
  index = hold.session[test_lno].size - 1 # current index
15
13
  xxh = hold.store.xxh(test_lno)
16
14
  yaml_path = hold.store.path
17
15
 
18
- @xxhi_ref = "<<< @xxh[i] --> #{xxh}[#{index}]"
19
-
20
16
  @yaml_lno = find_yaml_lno(yaml_path, test_lno, xxh, index)
21
- @yaml_ref = Holdify.relative("#{yaml_path}:#{@yaml_lno}")
17
+ @yaml_ref = Holdify.relativize("#{yaml_path}:#{@yaml_lno}")
22
18
 
23
- @hold_ref = Holdify.relative(hold_ref)
24
- test_ref = Holdify.relative(hold.test_loc.to_s.sub(/:in .*$/, ''))
19
+ @hold_ref = Holdify.relativize(hold_ref)
20
+ test_ref = Holdify.relativize(hold.test_loc.to_s.sub(/:in .*$/, ''))
25
21
  @test_ref = test_ref unless @hold_ref == test_ref
26
22
 
27
23
  @expected, @actual, @message = *args
28
24
 
29
25
  # Extend with features
30
26
  extend(Color) if Holdify.color
31
- return unless Holdify.git
27
+ return unless Holdify.git_diff
32
28
 
33
29
  extend GitDiff
34
30
  extend(Color::GitDiff) if Holdify.color
35
31
  end
36
32
 
37
- def message = [@message, xxhi_ref, *file_refs, *diff, ''].join("\n")
33
+ def message = [@message, *file_refs, *diff, ''].join("\n")
38
34
 
39
35
  def file_refs
40
36
  ["--- @stored --> #{@yaml_ref}", "+++ @tested --> #{@hold_ref}"].tap do |refs|
@@ -42,7 +38,7 @@ module Holdify
42
38
  end
43
39
  end
44
40
 
45
- def diff = ["- #{@expected.inspect}", "+ #{@actual.inspect}"]
41
+ def diff = ["-#{@expected.inspect}", "+#{@actual.inspect}"]
46
42
 
47
43
  private
48
44
 
@@ -58,7 +54,7 @@ module Holdify
58
54
 
59
55
  return ln
60
56
  else
61
- found = line.match(/^L#{test_lno} #{xxh}:$/)
57
+ found = line.match(/^L#{test_lno}-#{xxh}:$/)
62
58
  end
63
59
  end
64
60
  end
@@ -68,8 +64,8 @@ module Holdify
68
64
  def git_command = "git diff --no-index --no-color --unified=1000 #{@exp_path} #{@act_path}"
69
65
 
70
66
  def diff
71
- @exp_path = create_tempfile(@expected).path
72
- @act_path = create_tempfile(@actual).path
67
+ @exp_path = create_tempfile(@expected, 'expected').path
68
+ @act_path = create_tempfile(@actual, 'actual').path
73
69
 
74
70
  stdout, = Open3.capture3(git_command)
75
71
  regex = /\A[^@]*\r?\n/m # cleanup git headers
@@ -83,9 +79,9 @@ module Holdify
83
79
  # :nocov:
84
80
  end
85
81
 
86
- def create_tempfile(obj)
82
+ def create_tempfile(obj, type)
87
83
  Tempfile.create.tap do |file|
88
- file.write(YAML.dump(obj))
84
+ file.write(Store.hold_dump(obj).sub(/(?=\n)/, type))
89
85
  file.close
90
86
  end
91
87
  end
@@ -94,17 +90,27 @@ module Holdify
94
90
  width = 0
95
91
  lineno = [@yaml_lno - 1]
96
92
  lines.map.with_index do |line, i|
97
- if i.zero? # @@ ... @@
98
- w = line.scan(/,(\d+)/).flatten.map(&:to_i).max
99
- width = (@yaml_lno + w).to_s.length
93
+ if i.zero? # @@ ... @@
94
+ width, line = render_hunk(line)
100
95
  next line
101
96
  end
102
- next if i == 1 # ---
97
+ next if i == 1 || (i == 2 && !Holdify.color) # ---
103
98
 
104
99
  render_line(line, lineno, width)
105
100
  end.compact
106
101
  end
107
102
 
103
+ def render_hunk(line)
104
+ width = 0
105
+ hunk = line.gsub(/([-+]\d+),(\d+)\s+([-+]\d+),(\d+)/) do
106
+ v1, = $2.to_i - 1 # rubocop:disable Style/PerlBackrefs
107
+ v2 = $4.to_i - 1 # rubocop:disable Style/PerlBackrefs
108
+ width = (@yaml_lno + [v1, v2].max).to_s.length
109
+ "#{$1},#{v1} #{$3},#{v2}" # rubocop:disable Style/PerlBackrefs
110
+ end
111
+ [width, hunk]
112
+ end
113
+
108
114
  def render_line(line, lineno, width)
109
115
  type = line[0]
110
116
  line = line[1..]
@@ -127,16 +133,14 @@ module Holdify
127
133
  yellow: "\e[33m",
128
134
  magenta: "\e[35m" }.freeze
129
135
 
130
- def wrap(color, string) = "#{SGR[color]}#{string}#{SGR[:clear]}"
136
+ def dye(color, string) = "#{SGR[color]}#{string}#{SGR[:clear]}"
131
137
 
132
138
  def file_refs
133
139
  refs = super
134
- [wrap(:red, refs.shift), *refs.map { wrap(:green, _1) }]
140
+ [dye(:red, refs.shift), *refs.map { dye(:green, _1) }]
135
141
  end
136
142
 
137
- def diff = [wrap(:red, "- #{@expected.inspect}"), wrap(:green, "+ #{@actual.inspect}")]
138
-
139
- def xxhi_ref = wrap(:magenta, @xxhi_ref)
143
+ def diff = [dye(:red, "-#{@expected.inspect}"), dye(:green, "+#{@actual.inspect}")]
140
144
 
141
145
  # Methods enabling the git-diff ANSI feedback
142
146
  module GitDiff
data/lib/holdify/hold.rb CHANGED
@@ -11,7 +11,6 @@ module Holdify
11
11
  @store = Holdify.stores(@path)
12
12
  @session = Hash.new { |h, k| h[k] = [] } # { lineno => [values] }
13
13
  @forced = [] # [ lines ]
14
- @added = [] # [ lines ]
15
14
  end
16
15
 
17
16
  def call(actual, force: false)
@@ -28,7 +27,7 @@ module Holdify
28
27
  elsif values && index < values.size
29
28
  values[index]
30
29
  else
31
- @added << lineno
30
+ Holdify.push_fresh("#{Holdify.relativize(@test_loc.path)}:#{lineno}")
32
31
  actual
33
32
  end
34
33
 
@@ -37,7 +36,6 @@ module Holdify
37
36
  end
38
37
 
39
38
  def save
40
- @added.each { |lineno| warn "[holdify] Held new value for #{Holdify.relative(@path)}:#{lineno}" } unless Holdify.quiet
41
39
  @session.each { |lineno, values| @store.set_values(lineno, values) }
42
40
  end
43
41
 
@@ -51,10 +49,6 @@ module Holdify
51
49
  end
52
50
  end
53
51
 
54
- def warn_for(actual)
55
- warn("[holdify] The value from #{Holdify.relative(@test_loc.path)}:#{@test_loc.lineno} is:\n[holdify] => #{actual.inspect}")
56
- end
57
-
58
52
  def feedback(*) = Feedback.new(self, *).message
59
53
  end
60
54
  end
data/lib/holdify/store.rb CHANGED
@@ -11,6 +11,11 @@ module Holdify
11
11
  def register(target, obj); end
12
12
  end
13
13
 
14
+ def self.hold_dump(obj)
15
+ visitor = NoAliasVisitor.create
16
+ visitor << obj
17
+ visitor.tree.to_yaml
18
+ end
14
19
  extend Forwardable
15
20
 
16
21
  def_delegator :@source, :xxh
@@ -35,24 +40,18 @@ module Holdify
35
40
  xxh = @source.xxh(lineno)
36
41
  next unless xxh
37
42
 
38
- output["L#{lineno} #{xxh}"] = @data[lineno]
43
+ output["L#{lineno}-#{xxh}"] = @data[lineno]
39
44
  end
40
45
 
41
- File.write(@path, hold_dump(output))
46
+ File.write(@path, self.class.hold_dump(output))
42
47
  end
43
48
 
44
49
  private
45
50
 
46
- def hold_dump(obj)
47
- visitor = NoAliasVisitor.create
48
- visitor << obj
49
- visitor.tree.to_yaml
50
- end
51
-
52
51
  def load_and_align
53
52
  {}.tap do |aligned|
54
53
  data = YAML.unsafe_load_file(@path) || {}
55
- data.group_by { |k, _| k.split.last }.each do |xxh, entries|
54
+ data.group_by { |k, _| k.split('-').last }.each do |xxh, entries|
56
55
  lines = @source.lines(xxh)
57
56
  next if lines.empty?
58
57
 
data/lib/holdify.rb CHANGED
@@ -7,27 +7,50 @@ require_relative 'holdify/store'
7
7
 
8
8
  # The container module
9
9
  module Holdify
10
- VERSION = '1.3.0'
10
+ VERSION = '1.3.2'
11
+
12
+ @fresh_mutex = Mutex.new
13
+ @fresh = []
14
+ @stores_mutex = Mutex.new
15
+ @stores = {}
11
16
 
12
17
  class << self
13
- attr_accessor :reconcile, :quiet, :git, :pwd, :color, :rel_paths, :store_ext
18
+ attr_accessor :reconcile, :quiet, :git_diff, :pwd, :color, :rel_paths, :store_ext
14
19
 
15
- def persist_all! = @stores&.each_value(&:persist)
20
+ def push_fresh(test_ref)
21
+ @fresh_mutex.synchronize do
22
+ @fresh << test_ref
23
+ end
24
+ end
16
25
 
17
- def relative(path)
18
- return path unless rel_paths
26
+ def fresh_report
27
+ return if quiet
19
28
 
20
- path.sub(%r{^#{pwd}/}, '')
29
+ @fresh_mutex.synchronize do
30
+ return if @fresh.empty?
31
+
32
+ warn "[HOLDIFY] Fresh value held for:\n#{@fresh.uniq.sort.map { " #{_1}" }.join("\n")}"
33
+ end
21
34
  end
22
35
 
23
36
  def stores(path = nil)
24
- return @stores unless path
37
+ @stores_mutex.synchronize do
38
+ return @stores unless path
25
39
 
26
- @mutex.synchronize do
27
40
  @stores[path] ||= Store.new(path)
28
41
  end
29
42
  end
43
+
44
+ def persist_stores!
45
+ @stores_mutex.synchronize do
46
+ @stores&.each_value(&:persist)
47
+ end
48
+ end
49
+
50
+ def relativize(path)
51
+ return path unless rel_paths
52
+
53
+ path.sub(%r{^#{pwd}/}, '')
54
+ end
30
55
  end
31
- @mutex = Mutex.new
32
- @stores = {}
33
56
  end
@@ -19,8 +19,8 @@ module Minitest
19
19
  opts.on '--holdify-no-color', 'Disable colored output' do
20
20
  options[:holdify_no_color] = true
21
21
  end
22
- opts.on '--holdify-no-rel-paths', 'Disable relative paths in file references' do
23
- options[:holdify_no_rel_paths] = true
22
+ opts.on '--holdify-no-relative-paths', 'Disable relative paths in file references' do
23
+ options[:holdify_no_relative_paths] = true
24
24
  end
25
25
  opts.on '--holdify-store-ext EXT', 'The yaml store extension (default .yaml)' do |ext|
26
26
  options[:holdify_store_ext] = ext
@@ -29,15 +29,28 @@ module Minitest
29
29
 
30
30
  # Register the after_run hook to persist all data
31
31
  def self.plugin_holdify_init(options)
32
+ # :nocov:
33
+ git = system('git --version', out: File::NULL, err: File::NULL)
34
+ Holdify.pwd = git ? `git rev-parse --show-toplevel`.strip : Dir.pwd
35
+ # :nocov:
36
+
32
37
  Holdify.reconcile = options[:holdify_reconcile]
33
38
  Holdify.quiet = options[:holdify_quiet]
34
- Holdify.git = system('git --version', out: File::NULL, err: File::NULL) unless options[:holdify_no_git_diff]
35
- Holdify.pwd = Holdify.git ? `git rev-parse --show-toplevel`.strip : Dir.pwd
39
+ Holdify.git_diff = git unless options[:holdify_no_git_diff]
36
40
  Holdify.color = !ENV.key?('NO_COLOR') unless options[:holdify_no_color]
37
- Holdify.rel_paths = true unless options[:holdify_no_rel_paths]
41
+ Holdify.rel_paths = true unless options[:holdify_no_relative_paths]
38
42
  Holdify.store_ext = options[:holdify_store_ext] || '.yaml'
39
43
 
40
- Minitest.after_run { Holdify.persist_all! }
44
+ Minitest.after_run do
45
+ Holdify.persist_stores!
46
+ Holdify.fresh_report
47
+ end
48
+ end
49
+
50
+ # Patching Minitest::Assertion
51
+ class Assertion
52
+ remove_const :RE
53
+ RE = /in [`'](?:[^']+[#.])?(?:assert|refute|flunk|pass|fail|raise|must|wont|to)/ # :nodoc:
41
54
  end
42
55
 
43
56
  # Reopen the minitest class
@@ -51,10 +64,10 @@ module Minitest
51
64
  return unless @hold.forced.any?
52
65
 
53
66
  path, = method(name).source_location
54
- msg = +%([holdify] the value has been stored: remove the "!" suffix to pass the test\n)
67
+ msg = +%([HOLDIFY] Reconciled values (Remove the "!" suffix to pass the test)\n)
55
68
  msg << @hold.forced.uniq.map { |lineno| " #{path}:#{lineno}" }.join("\n")
56
69
 
57
- raise Minitest::Assertion, msg
70
+ flunk msg
58
71
  end
59
72
  end
60
73
 
@@ -68,17 +81,19 @@ module Minitest
68
81
  expected = @hold.(actual, **)
69
82
 
70
83
  begin
71
- if actual.nil?
84
+ if inspect
85
+ message = ['[HOLDIFY] Inspect actual value (Remove the "?" suffix to pass the test)', message].compact.join(' ')
86
+ flunk(message)
87
+ elsif actual.nil?
72
88
  assert_nil expected, message
73
89
  else
74
90
  send(assertion || :assert_equal, expected, actual, message)
75
91
  end
76
92
  rescue Minitest::Assertion => e
77
- raise Minitest::Assertion, @hold.feedback(e.location, expected, actual, message)
93
+ feedback = @hold.feedback(e.location, expected, actual, message)
94
+ raise(Minitest::Assertion, feedback)
78
95
  end
79
96
 
80
- @hold.warn_for(actual) if inspect
81
-
82
97
  expected
83
98
  end
84
99
 
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.3.0
4
+ version: 1.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Domizio Demichelis