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 +4 -4
- data/lib/holdify/feedback.rb +28 -24
- data/lib/holdify/hold.rb +1 -7
- data/lib/holdify/store.rb +8 -9
- data/lib/holdify.rb +33 -10
- data/lib/minitest/holdify_plugin.rb +27 -12
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4fb43344c6f2a11991bd6ec2b71e7fabcb8a8c5f77bd2048cbac1f9c94b85448
|
|
4
|
+
data.tar.gz: d8c9580c6701d82c50e11b96bd4bf0bc8fe9efeb98f7287057c6f8220519425d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b9420de8747442f0c2853caed136ac08bbd8066af4aa7d429efdec534a7e081b4a12b7bf7f5652de887f73c478a085f0f7032c34c5befd6b558b81128eff6583
|
|
7
|
+
data.tar.gz: 1c78694729ccf6de3192648f1d0657fcf7cbcb3d471fbb82ffd4e18e6a9378a58eea0ea23a7ee057a6206ecd474bd56455506f765bef2fa1d9a2633644c012f2
|
data/lib/holdify/feedback.rb
CHANGED
|
@@ -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.
|
|
17
|
+
@yaml_ref = Holdify.relativize("#{yaml_path}:#{@yaml_lno}")
|
|
22
18
|
|
|
23
|
-
@hold_ref = Holdify.
|
|
24
|
-
test_ref = Holdify.
|
|
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.
|
|
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,
|
|
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 = ["
|
|
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}
|
|
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(
|
|
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
|
-
|
|
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
|
|
136
|
+
def dye(color, string) = "#{SGR[color]}#{string}#{SGR[:clear]}"
|
|
131
137
|
|
|
132
138
|
def file_refs
|
|
133
139
|
refs = super
|
|
134
|
-
[
|
|
140
|
+
[dye(:red, refs.shift), *refs.map { dye(:green, _1) }]
|
|
135
141
|
end
|
|
136
142
|
|
|
137
|
-
def diff = [
|
|
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
|
-
@
|
|
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}
|
|
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.
|
|
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, :
|
|
18
|
+
attr_accessor :reconcile, :quiet, :git_diff, :pwd, :color, :rel_paths, :store_ext
|
|
14
19
|
|
|
15
|
-
def
|
|
20
|
+
def push_fresh(test_ref)
|
|
21
|
+
@fresh_mutex.synchronize do
|
|
22
|
+
@fresh << test_ref
|
|
23
|
+
end
|
|
24
|
+
end
|
|
16
25
|
|
|
17
|
-
def
|
|
18
|
-
return
|
|
26
|
+
def fresh_report
|
|
27
|
+
return if quiet
|
|
19
28
|
|
|
20
|
-
|
|
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
|
-
|
|
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-
|
|
23
|
-
options[:
|
|
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.
|
|
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[:
|
|
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
|
|
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 = +%([
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|