report_builder_fix 0.3 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a78950cbfaf4f00b2e1946d22a53ecefbc11503e42e326e8d851731a2111b718
4
- data.tar.gz: 2bcfc2bcb264bf9ee8d6afb1f6f416bb17beb0227dc3ec1212fcf0b2b22b1722
3
+ metadata.gz: 8c7e0aa0fce00a40e7f73b0caf3afab44b258df6a8b0ac85b4e03a341ed8cc89
4
+ data.tar.gz: c2a0627eb5ad90c8d80886b554be1e34d718dea3893060010b392112c8e19d80
5
5
  SHA512:
6
- metadata.gz: 237faaec36ac3fdb1666719e1d106a56640ee1377896b81f9997dcd2e564c3e3570517d8b4f9b99e4e4738af13a9b02e381bc2060dd2e3c62ac2d98dd13059d4
7
- data.tar.gz: 05043ba14ced62c43b901f0ea51ebe5653dfc715f866436153392eb6c0d375321372b7ccf63cc839b965a814a35d2bdcbf96b0b62686f99d7bf2377356c2884d
6
+ metadata.gz: 97200d64868e061f0a59d8e4dd89d6552e521e4d5994fb6780ef7e7c5afeb7d745bd56c0ce6602dd24866f7871e4784e773e5208bd9c36daac12ea109ba3a573
7
+ data.tar.gz: dedaacfc0f2a12294a5f7f9a2c70bf726e505f8d2c609272e129af750c1d6baae057881da6813b81ce82d997b4d8e44cfa09db1705f7f766fe1c001bf3b16fea
data/bin/report_builder CHANGED
@@ -74,7 +74,7 @@ opt_parser = OptionParser.new do |opts|
74
74
  end
75
75
 
76
76
  opts.on_tail('-v', '--version', 'Show version') do
77
- puts 'ReportBuilder v' + Gem.loaded_specs['report_builder'].version.to_s rescue puts "Something want wrong. \nUse 'gem list report_builder'"
77
+ puts 'ReportBuilderFix v' + Gem.loaded_specs['report_builder_fix'].version.to_s rescue puts "Something want wrong. \nUse 'gem list report_builder'"
78
78
  exit
79
79
  end
80
80
  end
@@ -74,7 +74,7 @@ opt_parser = OptionParser.new do |opts|
74
74
  end
75
75
 
76
76
  opts.on_tail('-v', '--version', 'Show version') do
77
- puts 'ReportBuilder v' + Gem.loaded_specs['report_builder'].version.to_s rescue puts "Something want wrong. \nUse 'gem list report_builder'"
77
+ puts 'ReportBuilderFix v' + Gem.loaded_specs['report_builder_fix'].version.to_s rescue puts "Something want wrong. \nUse 'gem list report_builder'"
78
78
  exit
79
79
  end
80
80
  end
data/lib/.DS_Store CHANGED
Binary file
@@ -0,0 +1,284 @@
1
+ require 'json'
2
+ require 'erb'
3
+ require 'pathname'
4
+ require 'base64'
5
+ require 'ostruct'
6
+
7
+ require 'report_builder/core-ext/hash'
8
+
9
+ module ReportBuilder
10
+
11
+ ##
12
+ # ReportBuilder Main class
13
+ #
14
+ class Builder
15
+
16
+ ##
17
+ # ReportBuilder Main method
18
+ #
19
+ def build_report
20
+ options = ReportBuilder.options
21
+
22
+ groups = get_groups options[:input_path]
23
+
24
+ json_report_path = options[:json_report_path] || options[:report_path]
25
+ if options[:report_types].include? 'JSON'
26
+ File.open(json_report_path + '.json', 'w') do |file|
27
+ file.write JSON.pretty_generate(groups.size > 1 ? groups : groups.first['features'])
28
+ end
29
+ end
30
+
31
+ if options[:additional_css] and Pathname.new(options[:additional_css]).file?
32
+ options[:additional_css] = File.read(options[:additional_css])
33
+ end
34
+
35
+ if options[:additional_js] and Pathname.new(options[:additional_js]).file?
36
+ options[:additional_js] = File.read(options[:additional_js])
37
+ end
38
+
39
+ html_report_path = options[:html_report_path] || options[:report_path]
40
+ if options[:report_types].include? 'HTML'
41
+ File.open(html_report_path + '.html', 'w') do |file|
42
+ file.write get(groups.size > 1 ? 'group_report' : 'report').result(binding)
43
+ end
44
+ end
45
+
46
+ retry_report_path = options[:retry_report_path] || options[:report_path]
47
+ if options[:report_types].include? 'RETRY'
48
+ File.open(retry_report_path + '.retry', 'w') do |file|
49
+ groups.each do |group|
50
+ group['features'].each do |feature|
51
+ if feature['status'] == 'broken'
52
+ feature['elements'].each do |scenario|
53
+ file.puts "#{feature['uri']}:#{scenario['line']}" if scenario['status'] == 'failed'
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ [json_report_path, html_report_path, retry_report_path]
61
+ end
62
+
63
+ private
64
+
65
+ def get(template)
66
+ @erb ||= {}
67
+ template_text = File.read(File.dirname(__FILE__) + '/../../template/' + template + '.erb')
68
+
69
+ # TODO: Remove once older Rubies are not longer supported
70
+ # Only use the deprecated method parameters for older versions of Ruby
71
+ if RUBY_VERSION =~ /^2\.[012345]/
72
+ @erb[template] ||= ERB.new(template_text, nil, nil, '_' + template)
73
+ else
74
+ @erb[template] ||= ERB.new(template_text, eoutvar: '_' + template)
75
+ end
76
+ end
77
+
78
+ def get_groups(input_path)
79
+ groups = []
80
+ if input_path.is_a? Hash
81
+ input_path.each do |group_name, group_path|
82
+ files = get_files group_path
83
+ puts "Error:: No file(s) found at #{group_path}" if files.empty?
84
+ groups << {'name' => group_name, 'features' => get_features(files)}
85
+ end
86
+ else
87
+ files = get_files input_path
88
+ raise "Error:: No file(s) found at #{input_path}" if files.empty?
89
+ groups << {'features' => get_features(files)}
90
+ end
91
+ groups.each do |this_group|
92
+ this_group['features'].each do |feature|
93
+ feature['elements'] = feature['elements'].sort_by { |v| v['line']}
94
+ end
95
+ end
96
+ groups
97
+ end
98
+
99
+ def get_files(path)
100
+ if path.is_a?(String) and Pathname.new(path).exist?
101
+ if Pathname.new(path).directory?
102
+ Dir.glob("#{path}/*.json")
103
+ else
104
+ [path]
105
+ end
106
+ elsif path.is_a? Array
107
+ path.map do |file|
108
+ if Pathname.new(file).exist?
109
+ if Pathname.new(file).directory?
110
+ Dir.glob("#{file}/*.json")
111
+ else
112
+ file
113
+ end
114
+ else
115
+ []
116
+ end
117
+ end.flatten
118
+ else
119
+ []
120
+ end.uniq
121
+ end
122
+
123
+ def get_features(files)
124
+ files.each_with_object([]) do |file, features|
125
+ data = File.read(file)
126
+ next if data.empty?
127
+ begin
128
+ features << JSON.parse(data)
129
+ rescue StandardError
130
+ puts 'Warning:: Invalid Input File ' + file
131
+ puts 'JSON Error:: ' + $!.to_s
132
+ next
133
+ end
134
+ end.flatten.group_by do |feature|
135
+ feature['uri'] + feature['id'] + feature['line'].to_s
136
+ end.values.each_with_object([]) do |group, features|
137
+ features << group.first.except('elements').merge('elements' => group.map {|feature| feature['elements']}.flatten)
138
+ end.sort_by! do |feature|
139
+ feature['name']
140
+ end.each do |feature|
141
+ feature['name'] = ERB::Util.html_escape feature['name']
142
+ if feature['elements'][0]['type'] == 'background'
143
+ (0..feature['elements'].size-1).step(2) do |i|
144
+ feature['elements'][i]['steps'] ||= []
145
+ feature['elements'][i]['steps'].each {|step| step['name'] += (' (' + feature['elements'][i]['keyword'] + ')')}
146
+ if feature['elements'][i+1]
147
+ feature['elements'][i+1]['steps'] = feature['elements'][i]['steps'] + feature['elements'][i+1]['steps']
148
+ feature['elements'][i+1]['before'] = feature['elements'][i]['before'] if feature['elements'][i]['before']
149
+ end
150
+ end
151
+ feature['elements'].reject! do |element|
152
+ element['type'] == 'background'
153
+ end
154
+ end
155
+ feature['elements'].each do |scenario|
156
+ scenario['name'] = ERB::Util.html_escape scenario['name']
157
+ scenario['before'] ||= []
158
+ scenario['before'].each do |before|
159
+ before['result']['duration'] ||= 0
160
+ if before['embeddings']
161
+ before['embeddings'].map! do |embedding|
162
+ decode_embedding(embedding)
163
+ end
164
+ end
165
+ before.merge! 'status' => before['result']['status'], 'duration' => before['result']['duration']
166
+ end
167
+ scenario['steps'] ||= []
168
+ scenario['steps'].each do |step|
169
+ step['name'] = ERB::Util.html_escape step['name']
170
+ step['result']['duration'] ||= 0
171
+ duration = step['result']['duration']
172
+ status = step['result']['status']
173
+ if step['after']
174
+ step['after'].each do |after|
175
+ after['result']['duration'] ||= 0
176
+ duration += after['result']['duration']
177
+ status = 'failed' if after['result']['status'] == 'failed'
178
+ if after['embeddings']
179
+ after['embeddings'].map! do |embedding|
180
+ decode_embedding(embedding)
181
+ end
182
+ end
183
+ after.merge! 'status' => after['result']['status'], 'duration' => after['result']['duration']
184
+ end
185
+ end
186
+ if step['embeddings']
187
+ step['embeddings'].map! do |embedding|
188
+ decode_embedding(embedding)
189
+ end
190
+ end
191
+ step.merge! 'status' => status, 'duration' => duration
192
+ end
193
+ scenario['after'] ||= []
194
+ scenario['after'].each do |after|
195
+ after['result']['duration'] ||= 0
196
+ if after['embeddings']
197
+ after['embeddings'].map! do |embedding|
198
+ decode_embedding(embedding)
199
+ end
200
+ end
201
+ after.merge! 'status' => after['result']['status'], 'duration' => after['result']['duration']
202
+ end
203
+ scenario.merge! 'status' => scenario_status(scenario), 'duration' => total_time(scenario['before']) + total_time(scenario['steps']) + total_time(scenario['after'])
204
+ end
205
+ feature['elements'] = feature['elements'].group_by do |scenario|
206
+ scenario['id'] + ':' + scenario['line'].to_s
207
+ end.values.map do |scenario_group|
208
+ the_scenario = scenario_group.find do |scenario|
209
+ scenario['status'] == 'passed'
210
+ end || scenario_group.last
211
+ if scenario_group.size > 1
212
+ the_scenario['name'] += " (x#{scenario_group.size})"
213
+ end
214
+ the_scenario
215
+ end
216
+ feature.merge! 'status' => feature_status(feature), 'duration' => total_time(feature['elements'])
217
+ end
218
+ end
219
+
220
+ def feature_status(feature)
221
+ feature_status = 'working'
222
+ feature['elements'].each do |scenario|
223
+ status = scenario['status']
224
+ return 'broken' if status == 'failed'
225
+ feature_status = 'incomplete' if %w(undefined pending).include?(status)
226
+ end
227
+ feature_status
228
+ end
229
+
230
+ def scenario_status(scenario)
231
+ (scenario['before'] + scenario['steps'] + scenario['after']).each do |step|
232
+ status = step['status']
233
+ return status unless status == 'passed'
234
+ end
235
+ 'passed'
236
+ end
237
+
238
+ def decode_image(data)
239
+ base64 = %r{^([A-Za-z0-9+\/]{4})*([A-Za-z0-9+\/]{4}|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{2}==)$}
240
+ if data =~ base64
241
+ data_base64 = Base64.urlsafe_decode64(data).gsub(%r{^data:image\/(png|gif|jpg|jpeg)\;base64,}, '') rescue data
242
+ if data_base64 =~ base64
243
+ data_base64
244
+ else
245
+ data
246
+ end
247
+ else
248
+ ''
249
+ end
250
+ end
251
+
252
+ def decode_text(data)
253
+ Base64.urlsafe_decode64 data rescue ''
254
+ end
255
+
256
+ def decode_embedding(embedding)
257
+ if embedding['mime_type'] =~ /^image\/(png|gif|jpg|jpeg)/
258
+ embedding['data'] = decode_image(embedding['data'])
259
+ elsif embedding['mime_type'] =~ /^text\/(plain|html)/
260
+ embedding['data'] = decode_text(embedding['data'])
261
+ end
262
+ embedding
263
+ end
264
+
265
+ def total_time(data)
266
+ total_time = 0
267
+ data.each {|item| total_time += item['duration']}
268
+ total_time
269
+ end
270
+
271
+ def duration(ms)
272
+ s = ms.to_f/1000000000
273
+ m, s = s.divmod(60)
274
+ if m > 59
275
+ h, m = m.divmod(60)
276
+ "#{h}h #{m}m #{'%.2f' % s}s"
277
+ elsif m > 0
278
+ "#{m}m #{'%.2f' % s}s"
279
+ else
280
+ "#{'%.3f' % s}s"
281
+ end
282
+ end
283
+ end
284
+ end
@@ -0,0 +1,10 @@
1
+ class Hash
2
+ def except(*keys)
3
+ dup.except!(*keys)
4
+ end
5
+
6
+ def except!(*keys)
7
+ keys.each { |key| delete(key) }
8
+ self
9
+ end
10
+ end