minitest-heat 0.0.5 → 0.0.9
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/.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 +79 -0
- data/lib/minitest/heat/issue.rb +49 -34
- data/lib/minitest/heat/line.rb +74 -0
- data/lib/minitest/heat/location.rb +20 -14
- data/lib/minitest/heat/map.rb +7 -34
- data/lib/minitest/heat/output/backtrace.rb +32 -32
- data/lib/minitest/heat/output/issue.rb +144 -0
- data/lib/minitest/heat/output/map.rb +59 -3
- data/lib/minitest/heat/output/marker.rb +50 -0
- data/lib/minitest/heat/output/results.rb +44 -22
- 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 +23 -120
- data/lib/minitest/heat/results.rb +19 -75
- data/lib/minitest/heat/timer.rb +81 -0
- data/lib/minitest/heat/version.rb +3 -1
- data/lib/minitest/heat.rb +3 -0
- data/lib/minitest/heat_plugin.rb +5 -5
- data/lib/minitest/heat_reporter.rb +50 -26
- data/minitest-heat.gemspec +4 -2
- metadata +64 -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,55 +3,28 @@
|
|
3
3
|
module Minitest
|
4
4
|
module Heat
|
5
5
|
class Map
|
6
|
-
|
6
|
+
MAXIMUM_FILES_TO_SHOW = 5
|
7
7
|
|
8
|
-
|
9
|
-
# trying to fix something. These are ranked based on the possibility they represent ripple
|
10
|
-
# effects where fixing one problem could potentially fix multiple other failures.
|
11
|
-
#
|
12
|
-
# For example, if there's an exception in the file, start there. Broken code can't run. If a
|
13
|
-
# test is broken (i.e. raising an exception), that's a special sort of failure that would be
|
14
|
-
# misleading. It doesn't represent a proper failure, but rather a test that doesn't work.
|
15
|
-
WEIGHTS = {
|
16
|
-
error: 3, # exceptions from source code have the highest liklihood of a ripple effect
|
17
|
-
broken: 1, # broken tests won't have ripple effects but can't help if they can't run
|
18
|
-
failure: 1, # failures are kind of the whole point, and they could have ripple effects
|
19
|
-
skipped: 0, # skips aren't failures, but they shouldn't go ignored
|
20
|
-
painful: 0, # slow tests aren't failures, but they shouldn't be ignored
|
21
|
-
slow: 0,
|
22
|
-
}
|
8
|
+
attr_reader :hits
|
23
9
|
|
24
10
|
def initialize
|
25
11
|
@hits = {}
|
26
12
|
end
|
27
13
|
|
28
14
|
def add(filename, line_number, type)
|
29
|
-
@hits[filename] ||=
|
30
|
-
@hits[filename][:total] += 1
|
31
|
-
@hits[filename][:weight] += WEIGHTS[type]
|
15
|
+
@hits[filename] ||= Hit.new(filename)
|
32
16
|
|
33
|
-
@hits[filename]
|
34
|
-
@hits[filename][type] << line_number
|
17
|
+
@hits[filename].log(type, line_number)
|
35
18
|
end
|
36
19
|
|
37
|
-
def
|
38
|
-
hot_files
|
39
|
-
.sort_by { |filename, weight| weight }
|
40
|
-
.reverse
|
41
|
-
.take(5)
|
20
|
+
def file_hits
|
21
|
+
hot_files.take(MAXIMUM_FILES_TO_SHOW)
|
42
22
|
end
|
43
23
|
|
44
24
|
private
|
45
25
|
|
46
26
|
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
|
27
|
+
hits.values.sort_by(&:weight).reverse
|
55
28
|
end
|
56
29
|
end
|
57
30
|
end
|
@@ -5,7 +5,7 @@ module Minitest
|
|
5
5
|
class Output
|
6
6
|
# Builds the collection of tokens for a backtrace when an exception occurs
|
7
7
|
class Backtrace
|
8
|
-
DEFAULT_LINE_COUNT =
|
8
|
+
DEFAULT_LINE_COUNT = 10
|
9
9
|
DEFAULT_INDENTATION_SPACES = 2
|
10
10
|
|
11
11
|
attr_accessor :location, :backtrace
|
@@ -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
|
-
|
32
|
-
source_code_line_token(source_code)
|
28
|
+
path_token(backtrace_entry),
|
29
|
+
*file_and_line_number_tokens(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
|
+
all_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.
|
74
|
-
end
|
75
|
-
|
76
|
-
def all_lines
|
77
|
-
backtrace.parsed_lines.take(line_count)
|
68
|
+
def project_entries
|
69
|
+
backtrace.project_entries.take(line_count)
|
78
70
|
end
|
79
71
|
|
80
|
-
def
|
81
|
-
|
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
|
@@ -93,25 +83,31 @@ module Minitest
|
|
93
83
|
end
|
94
84
|
|
95
85
|
def path_token(line)
|
86
|
+
style = line.to_s.include?(Dir.pwd) ? :default : :muted
|
96
87
|
path = "#{line.path}/"
|
97
88
|
|
98
89
|
# If all of the backtrace lines are from the project, no point in the added redundant
|
99
90
|
# noise of showing the project root directory over and over again
|
100
|
-
path = path.delete_prefix(project_root_dir) if
|
91
|
+
path = path.delete_prefix(project_root_dir) if all_backtrace_entries_from_project?
|
101
92
|
|
102
|
-
[
|
93
|
+
[style, path]
|
103
94
|
end
|
104
95
|
|
105
|
-
def
|
106
|
-
|
96
|
+
def file_and_line_number_tokens(backtrace_entry)
|
97
|
+
style = backtrace_entry.to_s.include?(Dir.pwd) ? :bold : :muted
|
98
|
+
[
|
99
|
+
[style, backtrace_entry.file],
|
100
|
+
[:muted, ':'],
|
101
|
+
[style, backtrace_entry.line_number]
|
102
|
+
]
|
107
103
|
end
|
108
104
|
|
109
105
|
def source_code_line_token(source_code)
|
110
|
-
[:muted, " `#{source_code.line.strip}`"]
|
106
|
+
[:muted, " #{Output::SYMBOLS[:arrow]} `#{source_code.line.strip}`"]
|
111
107
|
end
|
112
108
|
|
113
|
-
def file_freshness(
|
114
|
-
[:
|
109
|
+
def file_freshness(_line)
|
110
|
+
[:default, " #{Output::SYMBOLS[:middot]} Most Recently Modified File"]
|
115
111
|
end
|
116
112
|
|
117
113
|
# The number of spaces each line of code should be indented. Currently defaults to 2 in
|
@@ -125,6 +121,10 @@ module Minitest
|
|
125
121
|
def indentation
|
126
122
|
DEFAULT_INDENTATION_SPACES
|
127
123
|
end
|
124
|
+
|
125
|
+
def style_for(path)
|
126
|
+
style = path.to_s.include?(Dir.pwd) ? :default : :muted
|
127
|
+
end
|
128
128
|
end
|
129
129
|
end
|
130
130
|
end
|
@@ -11,7 +11,151 @@ module Minitest
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def tokens
|
14
|
+
case issue.type
|
15
|
+
when :error then error_tokens
|
16
|
+
when :broken then broken_tokens
|
17
|
+
when :failure then failure_tokens
|
18
|
+
when :skipped then skipped_tokens
|
19
|
+
when :painful then painful_tokens
|
20
|
+
when :slow then slow_tokens
|
21
|
+
end
|
14
22
|
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def error_tokens
|
27
|
+
[
|
28
|
+
headline_tokens,
|
29
|
+
test_location_tokens,
|
30
|
+
summary_tokens,
|
31
|
+
*backtrace_tokens,
|
32
|
+
newline_tokens
|
33
|
+
]
|
34
|
+
end
|
35
|
+
|
36
|
+
def broken_tokens
|
37
|
+
[
|
38
|
+
headline_tokens,
|
39
|
+
test_location_tokens,
|
40
|
+
summary_tokens,
|
41
|
+
*backtrace_tokens,
|
42
|
+
newline_tokens
|
43
|
+
]
|
44
|
+
end
|
45
|
+
|
46
|
+
def failure_tokens
|
47
|
+
[
|
48
|
+
headline_tokens,
|
49
|
+
test_location_tokens,
|
50
|
+
summary_tokens,
|
51
|
+
newline_tokens
|
52
|
+
]
|
53
|
+
end
|
54
|
+
|
55
|
+
def skipped_tokens
|
56
|
+
[
|
57
|
+
headline_tokens,
|
58
|
+
test_location_tokens,
|
59
|
+
newline_tokens
|
60
|
+
]
|
61
|
+
end
|
62
|
+
|
63
|
+
def painful_tokens
|
64
|
+
[
|
65
|
+
headline_tokens,
|
66
|
+
slowness_summary_tokens,
|
67
|
+
newline_tokens
|
68
|
+
]
|
69
|
+
end
|
70
|
+
|
71
|
+
def slow_tokens
|
72
|
+
[
|
73
|
+
headline_tokens,
|
74
|
+
slowness_summary_tokens,
|
75
|
+
newline_tokens
|
76
|
+
]
|
77
|
+
end
|
78
|
+
|
79
|
+
def headline_tokens
|
80
|
+
[[issue.type, issue.label], spacer_token, [:default, issue.test_name]]
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_name_and_class_tokens
|
84
|
+
[[:default, issue.test_class], *test_location_tokens ]
|
85
|
+
end
|
86
|
+
|
87
|
+
def backtrace_tokens
|
88
|
+
backtrace = ::Minitest::Heat::Output::Backtrace.new(issue.location)
|
89
|
+
|
90
|
+
backtrace.tokens
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_location_tokens
|
94
|
+
[[:default, test_file_short_location], [:muted, ':'], [:default, issue.test_definition_line], arrow_token, [:default, issue.test_failure_line], [:muted, test_line_source]]
|
95
|
+
end
|
96
|
+
|
97
|
+
def location_tokens
|
98
|
+
[[:default, most_relevant_short_location], [:muted, ':'], [:default, issue.location.most_relevant_failure_line], [:muted, most_relevant_line_source]]
|
99
|
+
end
|
100
|
+
|
101
|
+
def source_tokens
|
102
|
+
filename = issue.location.project_file
|
103
|
+
line_number = issue.location.project_failure_line
|
104
|
+
|
105
|
+
source = Minitest::Heat::Source.new(filename, line_number: line_number)
|
106
|
+
[[:muted, " #{Output::SYMBOLS[:arrow]} `#{source.line.strip}`"]]
|
107
|
+
end
|
108
|
+
|
109
|
+
def summary_tokens
|
110
|
+
[[:italicized, issue.summary.delete_suffix("---------------")]]
|
111
|
+
end
|
112
|
+
|
113
|
+
def slowness_summary_tokens
|
114
|
+
[
|
115
|
+
[:bold, issue.slowness],
|
116
|
+
spacer_token,
|
117
|
+
[:default, issue.location.test_file.to_s.delete_prefix(Dir.pwd)],
|
118
|
+
[:muted, ':'],
|
119
|
+
[:default, issue.location.test_definition_line]
|
120
|
+
]
|
121
|
+
end
|
122
|
+
|
123
|
+
def newline_tokens
|
124
|
+
[]
|
125
|
+
end
|
126
|
+
|
127
|
+
def most_relevant_short_location
|
128
|
+
issue.location.most_relevant_file.to_s.delete_prefix("#{Dir.pwd}/")
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_file_short_location
|
132
|
+
issue.location.test_file.to_s.delete_prefix("#{Dir.pwd}/")
|
133
|
+
end
|
134
|
+
|
135
|
+
def most_relevant_line_source
|
136
|
+
filename = issue.location.project_file
|
137
|
+
line_number = issue.location.project_failure_line
|
138
|
+
|
139
|
+
source = Minitest::Heat::Source.new(filename, line_number: line_number)
|
140
|
+
"\n #{source.line.strip}"
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_line_source
|
144
|
+
filename = issue.location.test_file
|
145
|
+
line_number = issue.location.test_failure_line
|
146
|
+
|
147
|
+
source = Minitest::Heat::Source.new(filename, line_number: line_number)
|
148
|
+
"\n #{source.line.strip}"
|
149
|
+
end
|
150
|
+
|
151
|
+
def spacer_token
|
152
|
+
Output::TOKENS[:spacer]
|
153
|
+
end
|
154
|
+
|
155
|
+
def arrow_token
|
156
|
+
Output::TOKENS[:muted_arrow]
|
157
|
+
end
|
158
|
+
|
15
159
|
end
|
16
160
|
end
|
17
161
|
end
|
@@ -4,16 +4,72 @@ module Minitest
|
|
4
4
|
module Heat
|
5
5
|
class Output
|
6
6
|
class Map
|
7
|
-
attr_accessor :
|
7
|
+
attr_accessor :results
|
8
8
|
|
9
|
-
def initialize(
|
10
|
-
@
|
9
|
+
def initialize(results)
|
10
|
+
@results = results
|
11
|
+
@tokens = []
|
11
12
|
end
|
12
13
|
|
13
14
|
def tokens
|
15
|
+
map.file_hits.each do |hit|
|
16
|
+
file_tokens = pathname(hit)
|
17
|
+
line_number_tokens = line_numbers(hit)
|
18
|
+
|
19
|
+
next if line_number_tokens.empty?
|
20
|
+
|
21
|
+
@tokens << [
|
22
|
+
*file_tokens,
|
23
|
+
*line_number_tokens
|
24
|
+
]
|
25
|
+
end
|
26
|
+
|
27
|
+
@tokens
|
14
28
|
end
|
15
29
|
|
16
30
|
private
|
31
|
+
|
32
|
+
def map
|
33
|
+
results.heat_map
|
34
|
+
end
|
35
|
+
|
36
|
+
def relevant_issue_types
|
37
|
+
issue_types = %i[error broken failure]
|
38
|
+
|
39
|
+
issue_types << :skipped unless results.problems?
|
40
|
+
issue_types << :painful unless results.problems? || results.skips.any?
|
41
|
+
issue_types << :slow unless results.problems? || results.skips.any?
|
42
|
+
|
43
|
+
issue_types
|
44
|
+
end
|
45
|
+
|
46
|
+
def pathname(file)
|
47
|
+
directory = "#{file.pathname.dirname.to_s.delete_prefix(Dir.pwd)}/"
|
48
|
+
filename = file.pathname.basename.to_s
|
49
|
+
|
50
|
+
[
|
51
|
+
[:default, directory],
|
52
|
+
[:bold, filename],
|
53
|
+
[:default, ' · ']
|
54
|
+
]
|
55
|
+
end
|
56
|
+
|
57
|
+
def hit_line_numbers(file, issue_type)
|
58
|
+
numbers = []
|
59
|
+
line_numbers_for_issue_type = file.issues.fetch(issue_type) { [] }
|
60
|
+
line_numbers_for_issue_type.sort.map do |line_number|
|
61
|
+
numbers << [issue_type, "#{line_number} "]
|
62
|
+
end
|
63
|
+
numbers
|
64
|
+
end
|
65
|
+
|
66
|
+
def line_numbers(file)
|
67
|
+
line_number_tokens = []
|
68
|
+
relevant_issue_types.each do |issue_type|
|
69
|
+
line_number_tokens += hit_line_numbers(file, issue_type)
|
70
|
+
end
|
71
|
+
line_number_tokens.compact.sort_by { |number_token| number_token[1] }
|
72
|
+
end
|
17
73
|
end
|
18
74
|
end
|
19
75
|
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
|