minitest-heat 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +23 -0
- data/Gemfile +5 -3
- data/Gemfile.lock +30 -1
- data/README.md +12 -3
- data/Rakefile +8 -6
- data/lib/minitest/heat/backtrace.rb +19 -74
- data/lib/minitest/heat/hit.rb +83 -0
- data/lib/minitest/heat/issue.rb +46 -31
- data/lib/minitest/heat/line.rb +74 -0
- data/lib/minitest/heat/location.rb +20 -14
- data/lib/minitest/heat/map.rb +10 -21
- data/lib/minitest/heat/output/backtrace.rb +19 -29
- data/lib/minitest/heat/output/issue.rb +110 -0
- data/lib/minitest/heat/output/map.rb +47 -0
- data/lib/minitest/heat/output/marker.rb +50 -0
- data/lib/minitest/heat/output/results.rb +17 -5
- data/lib/minitest/heat/output/source_code.rb +2 -2
- data/lib/minitest/heat/output/token.rb +15 -13
- data/lib/minitest/heat/output.rb +12 -121
- data/lib/minitest/heat/results.rb +16 -3
- data/lib/minitest/heat/version.rb +3 -1
- data/lib/minitest/heat.rb +2 -0
- data/lib/minitest/heat_plugin.rb +5 -5
- data/lib/minitest/heat_reporter.rb +25 -24
- data/minitest-heat.gemspec +4 -2
- metadata +63 -4
- data/lib/minitest/heat/output/location.rb +0 -20
@@ -14,10 +14,18 @@ module Minitest
|
|
14
14
|
# - 'most_relevant' represents the most specific file to investigate starting with the source
|
15
15
|
# code and then looking to the test code with final line of the backtrace as a fallback
|
16
16
|
class Location
|
17
|
+
TestDefinition = Struct.new(:pathname, :line_number) do
|
18
|
+
def initialize(pathname, line_number)
|
19
|
+
@pathname = Pathname(pathname)
|
20
|
+
@line_number = Integer(line_number)
|
21
|
+
super
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
17
25
|
attr_reader :test_location, :backtrace
|
18
26
|
|
19
27
|
def initialize(test_location, backtrace = [])
|
20
|
-
@test_location = test_location
|
28
|
+
@test_location = TestDefinition.new(*test_location)
|
21
29
|
@backtrace = Backtrace.new(backtrace)
|
22
30
|
end
|
23
31
|
|
@@ -58,28 +66,28 @@ module Minitest
|
|
58
66
|
#
|
59
67
|
# @return [String] the relative path to the file from the project root
|
60
68
|
def most_relevant_file
|
61
|
-
Pathname(most_relevant_location
|
69
|
+
Pathname(most_relevant_location.pathname)
|
62
70
|
end
|
63
71
|
|
64
72
|
# The line number of the `most_relevant_file` where the failure originated
|
65
73
|
#
|
66
74
|
# @return [Integer] line number
|
67
75
|
def most_relevant_failure_line
|
68
|
-
most_relevant_location
|
76
|
+
most_relevant_location.line_number
|
69
77
|
end
|
70
78
|
|
71
79
|
# The final location of the stacktrace regardless of whether it's from within the project
|
72
80
|
#
|
73
81
|
# @return [String] the relative path to the file from the project root
|
74
82
|
def final_file
|
75
|
-
Pathname(final_location
|
83
|
+
Pathname(final_location.pathname)
|
76
84
|
end
|
77
85
|
|
78
86
|
# The line number of the `final_file` where the failure originated
|
79
87
|
#
|
80
88
|
# @return [Integer] line number
|
81
89
|
def final_failure_line
|
82
|
-
final_location
|
90
|
+
final_location.line_number
|
83
91
|
end
|
84
92
|
|
85
93
|
# The final location of the stacktrace regardless of whether it's from within the project
|
@@ -100,7 +108,7 @@ module Minitest
|
|
100
108
|
#
|
101
109
|
# @return [String, nil] the relative path to the file from the project root
|
102
110
|
def source_code_file
|
103
|
-
return nil unless backtrace.
|
111
|
+
return nil unless backtrace.source_code_entries.any?
|
104
112
|
|
105
113
|
backtrace.final_source_code_location.pathname
|
106
114
|
end
|
@@ -109,30 +117,30 @@ module Minitest
|
|
109
117
|
#
|
110
118
|
# @return [Integer] line number
|
111
119
|
def source_code_failure_line
|
112
|
-
return nil unless backtrace.
|
120
|
+
return nil unless backtrace.source_code_entries.any?
|
113
121
|
|
114
|
-
backtrace.final_source_code_location.
|
122
|
+
backtrace.final_source_code_location.line_number
|
115
123
|
end
|
116
124
|
|
117
125
|
# The final location from the stacktrace that is within the project's test directory
|
118
126
|
#
|
119
127
|
# @return [String, nil] the relative path to the file from the project root
|
120
128
|
def test_file
|
121
|
-
Pathname(test_location
|
129
|
+
Pathname(test_location.pathname)
|
122
130
|
end
|
123
131
|
|
124
132
|
# The line number of the `test_file` where the test is defined
|
125
133
|
#
|
126
134
|
# @return [Integer] line number
|
127
135
|
def test_definition_line
|
128
|
-
test_location
|
136
|
+
test_location.line_number
|
129
137
|
end
|
130
138
|
|
131
139
|
# The line number from within the `test_file` test definition where the failure occurred
|
132
140
|
#
|
133
141
|
# @return [Integer] line number
|
134
142
|
def test_failure_line
|
135
|
-
backtrace.final_test_location&.
|
143
|
+
backtrace.final_test_location&.line_number || test_definition_line
|
136
144
|
end
|
137
145
|
|
138
146
|
# The line number from within the `test_file` test definition where the failure occurred
|
@@ -166,10 +174,8 @@ module Minitest
|
|
166
174
|
end
|
167
175
|
|
168
176
|
def backtrace?
|
169
|
-
backtrace.
|
177
|
+
backtrace.parsed_entries.any?
|
170
178
|
end
|
171
179
|
end
|
172
180
|
end
|
173
181
|
end
|
174
|
-
|
175
|
-
|
data/lib/minitest/heat/map.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
module Minitest
|
4
4
|
module Heat
|
5
5
|
class Map
|
6
|
+
MAXIMUM_FILES_TO_SHOW = 5
|
7
|
+
|
6
8
|
attr_reader :hits
|
7
9
|
|
8
10
|
# So we can sort hot spots by liklihood of being the most important spot to check out before
|
@@ -14,44 +16,31 @@ module Minitest
|
|
14
16
|
# misleading. It doesn't represent a proper failure, but rather a test that doesn't work.
|
15
17
|
WEIGHTS = {
|
16
18
|
error: 3, # exceptions from source code have the highest liklihood of a ripple effect
|
17
|
-
broken:
|
19
|
+
broken: 2, # broken tests won't have ripple effects but can't help if they can't run
|
18
20
|
failure: 1, # failures are kind of the whole point, and they could have ripple effects
|
19
21
|
skipped: 0, # skips aren't failures, but they shouldn't go ignored
|
20
22
|
painful: 0, # slow tests aren't failures, but they shouldn't be ignored
|
21
|
-
slow: 0
|
22
|
-
}
|
23
|
+
slow: 0
|
24
|
+
}.freeze
|
23
25
|
|
24
26
|
def initialize
|
25
27
|
@hits = {}
|
26
28
|
end
|
27
29
|
|
28
30
|
def add(filename, line_number, type)
|
29
|
-
@hits[filename] ||=
|
30
|
-
@hits[filename][:total] += 1
|
31
|
-
@hits[filename][:weight] += WEIGHTS[type]
|
31
|
+
@hits[filename] ||= Hit.new(filename)
|
32
32
|
|
33
|
-
@hits[filename]
|
34
|
-
@hits[filename][type] << line_number
|
33
|
+
@hits[filename].log(type, line_number)
|
35
34
|
end
|
36
35
|
|
37
|
-
def
|
38
|
-
hot_files
|
39
|
-
.sort_by { |filename, weight| weight }
|
40
|
-
.reverse
|
41
|
-
.take(5)
|
36
|
+
def file_hits
|
37
|
+
hot_files.take(MAXIMUM_FILES_TO_SHOW)
|
42
38
|
end
|
43
39
|
|
44
40
|
private
|
45
41
|
|
46
42
|
def hot_files
|
47
|
-
|
48
|
-
@hits.each_pair do |filename, details|
|
49
|
-
# Can't really be a "hot spot" with just a single issue
|
50
|
-
# next unless details[:weight] > 1
|
51
|
-
|
52
|
-
files[filename] = details[:weight]
|
53
|
-
end
|
54
|
-
files
|
43
|
+
hits.values.sort_by(&:weight).reverse
|
55
44
|
end
|
56
45
|
end
|
57
46
|
end
|
@@ -21,22 +21,18 @@ module Minitest
|
|
21
21
|
# final backtrace line if it might be relevant/helpful?
|
22
22
|
|
23
23
|
# Iterate over the selected lines from the backtrace
|
24
|
-
|
24
|
+
backtrace_entries.each do |backtrace_entry|
|
25
25
|
# Get the source code for the line from the backtrace
|
26
|
-
source_code = source_code_for(backtrace_line)
|
27
|
-
|
28
26
|
parts = [
|
29
27
|
indentation_token,
|
30
|
-
path_token(
|
31
|
-
file_and_line_number_token(
|
32
|
-
source_code_line_token(source_code)
|
28
|
+
path_token(backtrace_entry),
|
29
|
+
file_and_line_number_token(backtrace_entry),
|
30
|
+
source_code_line_token(backtrace_entry.source_code)
|
33
31
|
]
|
34
32
|
|
35
|
-
parts << file_freshness(
|
33
|
+
parts << file_freshness(backtrace_entry) if most_recently_modified?(backtrace_entry)
|
36
34
|
|
37
35
|
@tokens << parts
|
38
|
-
|
39
|
-
|
40
36
|
end
|
41
37
|
|
42
38
|
@tokens
|
@@ -55,37 +51,31 @@ module Minitest
|
|
55
51
|
# ...it could be influenced by a "compact" or "robust" reporter super-style?
|
56
52
|
# ...it's smart about exceptions that were raised outside of the project?
|
57
53
|
# ...it's smart about highlighting lines of code differently based on whether it's source code, test code, or external code?
|
58
|
-
def
|
59
|
-
|
54
|
+
def backtrace_entries
|
55
|
+
project_entries
|
60
56
|
end
|
61
57
|
|
62
58
|
private
|
63
59
|
|
64
|
-
def
|
65
|
-
|
60
|
+
def all_backtrace_entries_from_project?
|
61
|
+
backtrace_entries.all? { |line| line.path.to_s.include?(project_root_dir) }
|
66
62
|
end
|
67
63
|
|
68
64
|
def project_root_dir
|
69
65
|
Dir.pwd
|
70
66
|
end
|
71
67
|
|
72
|
-
def
|
73
|
-
backtrace.
|
68
|
+
def project_entries
|
69
|
+
backtrace.project_entries.take(line_count)
|
74
70
|
end
|
75
71
|
|
76
|
-
def
|
77
|
-
backtrace.
|
78
|
-
end
|
79
|
-
|
80
|
-
def source_code_for(line)
|
81
|
-
filename = "#{line.path}/#{line.file}"
|
82
|
-
|
83
|
-
Minitest::Heat::Source.new(filename, line_number: line.number, max_line_count: 1)
|
72
|
+
def all_entries
|
73
|
+
backtrace.parsed_entries.take(line_count)
|
84
74
|
end
|
85
75
|
|
86
76
|
def most_recently_modified?(line)
|
87
77
|
# If there's more than one line being displayed, and the current line is the freshest
|
88
|
-
|
78
|
+
backtrace_entries.size > 1 && line == backtrace.freshest_project_location
|
89
79
|
end
|
90
80
|
|
91
81
|
def indentation_token
|
@@ -97,21 +87,21 @@ module Minitest
|
|
97
87
|
|
98
88
|
# If all of the backtrace lines are from the project, no point in the added redundant
|
99
89
|
# noise of showing the project root directory over and over again
|
100
|
-
path = path.delete_prefix(project_root_dir) if
|
90
|
+
path = path.delete_prefix(project_root_dir) if all_backtrace_entries_from_project?
|
101
91
|
|
102
92
|
[:muted, path]
|
103
93
|
end
|
104
94
|
|
105
|
-
def file_and_line_number_token(
|
106
|
-
[:default, "#{
|
95
|
+
def file_and_line_number_token(backtrace_entry)
|
96
|
+
[:default, "#{backtrace_entry.file}:#{backtrace_entry.line_number}"]
|
107
97
|
end
|
108
98
|
|
109
99
|
def source_code_line_token(source_code)
|
110
100
|
[:muted, " `#{source_code.line.strip}`"]
|
111
101
|
end
|
112
102
|
|
113
|
-
def file_freshness(
|
114
|
-
[:bold,
|
103
|
+
def file_freshness(_line)
|
104
|
+
[:bold, ' < Most Recently Modified']
|
115
105
|
end
|
116
106
|
|
117
107
|
# The number of spaces each line of code should be indented. Currently defaults to 2 in
|
@@ -4,6 +4,11 @@ module Minitest
|
|
4
4
|
module Heat
|
5
5
|
class Output
|
6
6
|
class Issue
|
7
|
+
SHARED_SYMBOLS = {
|
8
|
+
spacer: ' · ',
|
9
|
+
arrow: ' > '
|
10
|
+
}.freeze
|
11
|
+
|
7
12
|
attr_accessor :issue
|
8
13
|
|
9
14
|
def initialize(issue)
|
@@ -11,6 +16,111 @@ module Minitest
|
|
11
16
|
end
|
12
17
|
|
13
18
|
def tokens
|
19
|
+
case issue.type
|
20
|
+
when :error then error_tokens
|
21
|
+
when :broken then broken_tokens
|
22
|
+
when :failure then failure_tokens
|
23
|
+
when :skipped then skipped_tokens
|
24
|
+
when :painful then painful_tokens
|
25
|
+
when :slow then slow_tokens
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def error_tokens
|
32
|
+
[
|
33
|
+
headline_tokens,
|
34
|
+
summary_tokens,
|
35
|
+
*backtrace_tokens,
|
36
|
+
newline_tokens
|
37
|
+
]
|
38
|
+
end
|
39
|
+
|
40
|
+
def broken_tokens
|
41
|
+
[
|
42
|
+
headline_tokens,
|
43
|
+
summary_tokens,
|
44
|
+
*backtrace_tokens,
|
45
|
+
newline_tokens
|
46
|
+
]
|
47
|
+
end
|
48
|
+
|
49
|
+
def failure_tokens
|
50
|
+
[
|
51
|
+
headline_tokens,
|
52
|
+
summary_tokens,
|
53
|
+
location_tokens,
|
54
|
+
*source_tokens,
|
55
|
+
newline_tokens
|
56
|
+
]
|
57
|
+
end
|
58
|
+
|
59
|
+
def skipped_tokens
|
60
|
+
[
|
61
|
+
headline_tokens,
|
62
|
+
summary_tokens,
|
63
|
+
newline_tokens
|
64
|
+
]
|
65
|
+
end
|
66
|
+
|
67
|
+
def painful_tokens
|
68
|
+
[
|
69
|
+
headline_tokens,
|
70
|
+
slowness_tokens,
|
71
|
+
newline_tokens
|
72
|
+
]
|
73
|
+
end
|
74
|
+
|
75
|
+
def slow_tokens
|
76
|
+
[
|
77
|
+
headline_tokens,
|
78
|
+
slowness_tokens,
|
79
|
+
newline_tokens
|
80
|
+
]
|
81
|
+
end
|
82
|
+
|
83
|
+
def headline_tokens
|
84
|
+
[[issue.type, issue.label], [:muted, spacer], [:default, issue.test_name], [:muted, spacer], [:muted, issue.test_class]]
|
85
|
+
end
|
86
|
+
|
87
|
+
def summary_tokens
|
88
|
+
[[:italicized, issue.summary]]
|
89
|
+
end
|
90
|
+
|
91
|
+
def backtrace_tokens
|
92
|
+
backtrace = ::Minitest::Heat::Output::Backtrace.new(issue.location)
|
93
|
+
|
94
|
+
backtrace.tokens
|
95
|
+
end
|
96
|
+
|
97
|
+
def location_tokens
|
98
|
+
[[:muted, issue.short_location]]
|
99
|
+
end
|
100
|
+
|
101
|
+
def source_tokens
|
102
|
+
filename = issue.location.project_file
|
103
|
+
line_number = issue.location.project_failure_line
|
104
|
+
|
105
|
+
source_code = ::Minitest::Heat::Output::SourceCode.new(filename, line_number)
|
106
|
+
|
107
|
+
source_code.tokens
|
108
|
+
end
|
109
|
+
|
110
|
+
def slowness_tokens
|
111
|
+
[[:bold, issue.slowness], [:muted, spacer], [:default, issue.short_location] ]
|
112
|
+
end
|
113
|
+
|
114
|
+
def newline_tokens
|
115
|
+
[]
|
116
|
+
end
|
117
|
+
|
118
|
+
def spacer
|
119
|
+
SHARED_SYMBOLS[:spacer]
|
120
|
+
end
|
121
|
+
|
122
|
+
def arrow
|
123
|
+
SHARED_SYMBOLS[:arrow]
|
14
124
|
end
|
15
125
|
end
|
16
126
|
end
|
@@ -4,16 +4,63 @@ module Minitest
|
|
4
4
|
module Heat
|
5
5
|
class Output
|
6
6
|
class Map
|
7
|
+
# extend Forwardable
|
8
|
+
|
7
9
|
attr_accessor :map
|
8
10
|
|
11
|
+
# def_delegators :@results, :errors, :brokens, :failures, :slows, :skips, :problems?, :slows?
|
12
|
+
|
9
13
|
def initialize(map)
|
10
14
|
@map = map
|
15
|
+
@tokens = []
|
11
16
|
end
|
12
17
|
|
13
18
|
def tokens
|
19
|
+
map.file_hits.each do |file|
|
20
|
+
@tokens << [
|
21
|
+
*pathname(file),
|
22
|
+
*line_numbers(file)
|
23
|
+
]
|
24
|
+
end
|
25
|
+
|
26
|
+
@tokens
|
14
27
|
end
|
15
28
|
|
16
29
|
private
|
30
|
+
|
31
|
+
def pathname(file)
|
32
|
+
directory = "#{file.pathname.dirname.to_s.delete_prefix(Dir.pwd)}/"
|
33
|
+
filename = file.pathname.basename.to_s
|
34
|
+
|
35
|
+
[
|
36
|
+
[:default, directory],
|
37
|
+
[:bold, filename],
|
38
|
+
[:default, ' · ']
|
39
|
+
]
|
40
|
+
end
|
41
|
+
|
42
|
+
def hit_line_numbers(file, issue_type)
|
43
|
+
line_numbers_for_issue_type = file.issues.fetch(issue_type) { [] }
|
44
|
+
|
45
|
+
return nil if line_numbers_for_issue_type.empty?
|
46
|
+
|
47
|
+
numbers = []
|
48
|
+
line_numbers_for_issue_type.sort.map do |line_number|
|
49
|
+
numbers << [issue_type, "#{line_number} "]
|
50
|
+
end
|
51
|
+
numbers
|
52
|
+
end
|
53
|
+
|
54
|
+
def line_numbers(file)
|
55
|
+
[
|
56
|
+
*hit_line_numbers(file, :error),
|
57
|
+
*hit_line_numbers(file, :broken),
|
58
|
+
*hit_line_numbers(file, :failure),
|
59
|
+
*hit_line_numbers(file, :skipped),
|
60
|
+
*hit_line_numbers(file, :painful),
|
61
|
+
*hit_line_numbers(file, :slow)
|
62
|
+
].compact.sort_by { |number_token| number_token[1] }
|
63
|
+
end
|
17
64
|
end
|
18
65
|
end
|
19
66
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Minitest
|
4
|
+
module Heat
|
5
|
+
# Friendly API for printing nicely-formatted output to the console
|
6
|
+
class Output
|
7
|
+
class Marker
|
8
|
+
SYMBOLS = {
|
9
|
+
success: '·',
|
10
|
+
slow: '♦',
|
11
|
+
painful: '♦',
|
12
|
+
broken: 'B',
|
13
|
+
error: 'E',
|
14
|
+
skipped: 'S',
|
15
|
+
failure: 'F'
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
STYLES = {
|
19
|
+
success: :success,
|
20
|
+
slow: :slow,
|
21
|
+
painful: :painful,
|
22
|
+
broken: :error,
|
23
|
+
error: :error,
|
24
|
+
skipped: :skipped,
|
25
|
+
failure: :failure
|
26
|
+
}.freeze
|
27
|
+
|
28
|
+
attr_accessor :issue_type
|
29
|
+
|
30
|
+
def initialize(issue_type)
|
31
|
+
@issue_type = issue_type
|
32
|
+
end
|
33
|
+
|
34
|
+
def token
|
35
|
+
[style, symbol]
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def style
|
41
|
+
STYLES.fetch(issue_type, :default)
|
42
|
+
end
|
43
|
+
|
44
|
+
def symbol
|
45
|
+
SYMBOLS.fetch(issue_type, '?')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -8,7 +8,7 @@ module Minitest
|
|
8
8
|
|
9
9
|
attr_accessor :results
|
10
10
|
|
11
|
-
def_delegators :@results, :errors, :brokens, :failures, :
|
11
|
+
def_delegators :@results, :errors, :brokens, :failures, :skips, :painfuls, :slows, :problems?, :slows?
|
12
12
|
|
13
13
|
def initialize(results)
|
14
14
|
@results = results
|
@@ -17,8 +17,8 @@ module Minitest
|
|
17
17
|
|
18
18
|
def tokens
|
19
19
|
@tokens << [*issue_counts_tokens] if issue_counts_tokens&.any?
|
20
|
-
@tokens << [assertions_count_token, test_count_token]
|
21
20
|
@tokens << [assertions_performance_token, tests_performance_token, timing_token]
|
21
|
+
@tokens << [assertions_count_token, test_count_token]
|
22
22
|
|
23
23
|
@tokens
|
24
24
|
end
|
@@ -35,14 +35,21 @@ module Minitest
|
|
35
35
|
def issue_counts_tokens
|
36
36
|
return unless problems? || slows?
|
37
37
|
|
38
|
-
counts = [
|
38
|
+
counts = [
|
39
|
+
error_count_token,
|
40
|
+
broken_count_token,
|
41
|
+
failure_count_token,
|
42
|
+
skip_count_token,
|
43
|
+
painful_count_token,
|
44
|
+
slow_count_token
|
45
|
+
].compact
|
39
46
|
|
40
47
|
# # Create an array of separator tokens one less than the total number of issue count tokens
|
41
48
|
separator_tokens = Array.new(counts.size, separator_token)
|
42
49
|
|
43
50
|
counts_with_separators = counts
|
44
|
-
|
45
|
-
|
51
|
+
.zip(separator_tokens) # Add separators between the counts
|
52
|
+
.flatten(1) # Flatten the zipped separators, but no more
|
46
53
|
|
47
54
|
counts_with_separators.pop # Remove the final trailing zipped separator that's not needed
|
48
55
|
|
@@ -66,6 +73,11 @@ module Minitest
|
|
66
73
|
issue_count_token(style, skips, name: 'Skip')
|
67
74
|
end
|
68
75
|
|
76
|
+
def painful_count_token
|
77
|
+
style = problems? ? :muted : :painful
|
78
|
+
issue_count_token(style, painfuls, name: 'Painfully Slow')
|
79
|
+
end
|
80
|
+
|
69
81
|
def slow_count_token
|
70
82
|
style = problems? ? :muted : :slow
|
71
83
|
issue_count_token(style, slows, name: 'Slow')
|
@@ -101,9 +101,9 @@ module Minitest
|
|
101
101
|
# @return [Array<Symbol>] the Token styles for the line number and line of code
|
102
102
|
def styles_for(line_of_code)
|
103
103
|
if line_of_code == source.line && highlight_key_line?
|
104
|
-
[
|
104
|
+
%i[default default]
|
105
105
|
else
|
106
|
-
[
|
106
|
+
%i[muted muted]
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Minitest
|
2
4
|
module Heat
|
3
5
|
# Friendly API for printing nicely-formatted output to the console
|
@@ -6,18 +8,18 @@ module Minitest
|
|
6
8
|
class InvalidStyle < ArgumentError; end
|
7
9
|
|
8
10
|
STYLES = {
|
9
|
-
success:
|
10
|
-
slow:
|
11
|
-
painful:
|
12
|
-
error:
|
13
|
-
broken:
|
14
|
-
failure:
|
15
|
-
skipped:
|
11
|
+
success: %i[default green],
|
12
|
+
slow: %i[default green],
|
13
|
+
painful: %i[bold green],
|
14
|
+
error: %i[bold red],
|
15
|
+
broken: %i[bold red],
|
16
|
+
failure: %i[default red],
|
17
|
+
skipped: %i[default yellow],
|
16
18
|
warning_light: %i[light yellow],
|
17
|
-
italicized:
|
18
|
-
bold:
|
19
|
-
default:
|
20
|
-
muted:
|
19
|
+
italicized: %i[italic gray],
|
20
|
+
bold: %i[bold default],
|
21
|
+
default: %i[default default],
|
22
|
+
muted: %i[light gray]
|
21
23
|
}.freeze
|
22
24
|
|
23
25
|
attr_accessor :style_key, :content
|
@@ -38,14 +40,14 @@ module Minitest
|
|
38
40
|
end
|
39
41
|
|
40
42
|
def eql?(other)
|
41
|
-
style_key == other.style_key &&
|
43
|
+
style_key == other.style_key && content == other.content
|
42
44
|
end
|
43
45
|
alias :== eql?
|
44
46
|
|
45
47
|
private
|
46
48
|
|
47
49
|
ESC_SEQUENCE = "\e["
|
48
|
-
END_SEQUENCE =
|
50
|
+
END_SEQUENCE = 'm'
|
49
51
|
|
50
52
|
WEIGHTS = {
|
51
53
|
default: 0,
|