report_builder 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/report_builder.rb +301 -302
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 601a48967da3d12319d801c9febed718aa5a856a
4
- data.tar.gz: 253cda6a5c4fc55185f11789ac6c8892296a0008
3
+ metadata.gz: 3548db4c70ef0f5d6fae4c9b69fd3da24fd09a7c
4
+ data.tar.gz: ee9feecdbb0c1ed8574b7e87d89bde602906a4b5
5
5
  SHA512:
6
- metadata.gz: faa57482fbc784b5d48d30a64fd67b6533acff31077cd5d7e630d6a7689584871442f13b36061f531a6987a54471f6470d082bb78bde259e235ad6d48b3203e9
7
- data.tar.gz: fcf99dddafcf2f6c177304bf4c52fde0197d4933e5c91bf5d3613eb992d70747ac41e4b21a46606227539d2c12a1aa3222ac420f11b096bb65f153aa77f20e48
6
+ metadata.gz: 81ef540f7558c9f8c3f1e37b7a2b9cf5effe24cc0b23499f16163b563859ffc2d833212622d30aaf51f3a63b1deffd48fc571d4a018dc19602c51f8880aa7902
7
+ data.tar.gz: 23ea000736d6905ac1195d209a1a7fc0830d7bd13e77a7ff66d033fc8f0ac321bbc80a89795a7c0b356d2efa0d8876497a5843bd1bf0903e5cf4e9636753a7fa
@@ -1,5 +1,6 @@
1
1
  require 'json'
2
2
  require 'builder'
3
+ require 'base64'
3
4
 
4
5
  # Add except method to Hash
5
6
  class Hash
@@ -17,16 +18,27 @@ end
17
18
  class ReportBuilder
18
19
 
19
20
  # report_builder:
20
- # ReportBuilder.build_report('path/of/json/files/dir')
21
21
  #
22
- # ReportBuilder.build_report('path/of/json/file.json')
22
+ # ReportBuilder.build_report()
23
+ # ReportBuilder.build_report('path/of/json/files/dir')
24
+ # ReportBuilder.build_report('path/of/json/files/dir','my_test_report_name','json_html')
25
+ # ReportBuilder.build_report('path/of/json/files/dir','my_test_report_name','json')
26
+ # ReportBuilder.build_report('path/of/json/files/dir','my_test_report_name','html')
23
27
  #
24
- # ReportBuilder.build_report(['path/of/json/file1.json','path/of/json/file2.json','path/of/json/files/dir/'])
25
28
  #
26
- # ReportBuilder.build_report()
29
+ # ReportBuilder.build_report('path/of/json/cucumber.json')
27
30
  #
28
- # ReportBuilder::COLOR[:passed] = '#ffffff'
29
- # ReportBuilder.build_report()
31
+ #
32
+ # ReportBuilder.build_report([
33
+ # 'path/of/json/cucumber1.json',
34
+ # 'path/of/json/cucumber2.json',
35
+ # 'path/of/json/files/dir/'
36
+ # ])
37
+ #
38
+ #
39
+ # ReportBuilder::COLOR[:passed] = '#ffffff'
40
+ # ReportBuilder::COLOR[:failed] = '#000000'
41
+ # ReportBuilder.build_report()
30
42
 
31
43
 
32
44
  # colors corresponding to status
@@ -38,7 +50,8 @@ class ReportBuilder
38
50
  undefined: '#e4d354',
39
51
  unknown: '#e4d354',
40
52
  pending: '#f7a35c',
41
- skipped: '#7cb5ec'
53
+ skipped: '#7cb5ec',
54
+ output: '#007fff'
42
55
  }
43
56
 
44
57
  # @param [Object] file_or_dir json file, array of json files or path, json files path
@@ -49,14 +62,10 @@ class ReportBuilder
49
62
  input = files file_or_dir
50
63
  all_features = features input rescue (raise 'ReportBuilderParsingError')
51
64
 
52
- if output_file_type.include? 'json'
53
- File.open(output_file_name + '.json', "w") do |file|
54
- file.write JSON.pretty_generate all_features
55
- end
65
+ File.open(output_file_name + '.json', 'w') do |file|
66
+ file.write JSON.pretty_generate all_features
56
67
  puts "JSON test report generated: '#{output_file_name}.json'"
57
- end
58
-
59
- return unless output_file_type.include? 'html'
68
+ end if output_file_type.to_s.upcase.include? 'JSON'
60
69
 
61
70
  all_scenarios = scenarios all_features
62
71
  all_steps = steps all_scenarios
@@ -65,334 +74,320 @@ class ReportBuilder
65
74
  scenario_data = data all_scenarios
66
75
  step_data = data all_steps
67
76
 
68
- file = File.open(output_file_name + '.html', 'w:UTF-8')
77
+ File.open(output_file_name + '.html', 'w:UTF-8') do |file|
78
+ @builder = Builder::XmlMarkup.new(:target => file, :indent => 0)
79
+ @builder.declare!(:DOCTYPE, :html)
80
+ @builder << '<html>'
69
81
 
70
- builder = Builder::XmlMarkup.new(:target => file, :indent => 0)
71
- builder.declare!(:DOCTYPE, :html)
72
- builder << '<html>'
82
+ @builder.head do
83
+ @builder.meta(charset: 'UTF-8')
84
+ @builder.title 'Test Results'
73
85
 
74
- builder.head do
75
- builder.meta(charset: 'UTF-8')
76
- builder.title 'Test Results'
86
+ @builder.style(:type => 'text/css') do
87
+ @builder << File.read(File.dirname(__FILE__) + '/../vendor/assets/stylesheets/jquery-ui.min.css')
88
+ COLOR.each do |color|
89
+ @builder << ".#{color[0].to_s}{background:#{color[1]};color:#434348;padding:2px}"
90
+ end
91
+ @builder << '.summary{border: 1px solid #c5c5c5;border-radius:4px;text-align:right;background:#f1f1f1;color:#434348;padding:4px}'
92
+ end
77
93
 
78
- builder.style(:type => 'text/css') do
79
- builder << File.read(File.dirname(__FILE__) + '/../vendor/assets/stylesheets/jquery-ui.min.css')
80
- COLOR.each do |color|
81
- builder << ".#{color[0].to_s}{background:#{color[1]};color:#434348;padding:2px}"
94
+ @builder.script(:type => 'text/javascript') do
95
+ %w(jquery-min jquery-ui.min highcharts highcharts-3d).each do |js|
96
+ @builder << File.read(File.dirname(__FILE__) + '/../vendor/assets/javascripts/' + js + '.js')
97
+ end
98
+ @builder << '$(function(){$("#results").tabs();});'
99
+ @builder << "$(function(){$('#features').accordion({collapsible: true, heightStyle: 'content', active: false, icons: false});});"
100
+ (0..all_scenarios.size).each do |n|
101
+ @builder << "$(function(){$('#scenario#{n}').accordion({collapsible: true, heightStyle: 'content', active: false, icons: false});});"
102
+ end
103
+ @builder << "$(function(){$('#status').accordion({collapsible: true, heightStyle: 'content', active: false, icons: false});});"
104
+ scenario_data.each do |data|
105
+ @builder << "$(function(){$('##{data[:name]}').accordion({collapsible: true, heightStyle: 'content', active: false, icons: false});});"
106
+ end
82
107
  end
83
- builder << '.summary{border: 1px solid #c5c5c5;border-radius:4px;text-align:right;background:#f1f1f1;color:#434348;padding:4px}'
84
108
  end
85
109
 
86
- builder.script(:type => 'text/javascript') do
87
- %w(jquery-min jquery-ui.min highcharts highcharts-3d).each do |file|
88
- builder << File.read(File.dirname(__FILE__) + '/../vendor/assets/javascripts/' + file + '.js')
89
- end
90
- builder << '$(function(){$("#results").tabs();});'
91
- builder << "$(function(){$('#features').accordion({collapsible: true, heightStyle: 'content', active: false, icons: false});});"
92
- (0..all_scenarios.size).each do |n|
93
- builder << "$(function(){$('#scenario#{n}').accordion({collapsible: true, heightStyle: 'content', active: false, icons: false});});"
110
+ @builder << '<body>'
111
+
112
+ @builder.h4(:class => 'summary') do
113
+ @builder << all_features.size.to_s + ' feature ('
114
+ feature_data.each do |data|
115
+ @builder << ' ' + data[:count].to_s + ' ' + data[:name]
94
116
  end
95
- builder << "$(function(){$('#status').accordion({collapsible: true, heightStyle: 'content', active: false, icons: false});});"
117
+ @builder << ') ~ ' + all_scenarios.size.to_s + ' scenario ('
96
118
  scenario_data.each do |data|
97
- builder << "$(function(){$('##{data[:name]}').accordion({collapsible: true, heightStyle: 'content', active: false, icons: false});});"
119
+ @builder << ' ' + data[:count].to_s + ' ' + data[:name]
98
120
  end
121
+ @builder << ') ~ ' + all_steps.size.to_s + ' step ('
122
+ step_data.each do |data|
123
+ @builder << ' ' + data[:count].to_s + ' ' + data[:name]
124
+ end
125
+ @builder << ') ~ ' + duration(total_time).to_s
99
126
  end
100
- end
101
-
102
- builder << '<body>'
103
-
104
- builder.h4(:class => 'summary') do
105
- builder << all_features.size.to_s + ' feature ('
106
- feature_data.each do |data|
107
- builder << ' ' + data[:count].to_s + ' ' + data[:name]
108
- end
109
- builder << ') ~ ' + all_scenarios.size.to_s + ' scenario ('
110
- scenario_data.each do |data|
111
- builder << ' ' + data[:count].to_s + ' ' + data[:name]
112
- end
113
- builder << ') ~ ' + all_steps.size.to_s + ' step ('
114
- step_data.each do |data|
115
- builder << ' ' + data[:count].to_s + ' ' + data[:name]
116
- end
117
- builder << ') ~ ' + duration(total_time).to_s
118
- end
119
127
 
120
- builder.div(:id => 'results') do
128
+ @builder.div(:id => 'results') do
129
+ build_menu %w(overview features scenarios errors)
121
130
 
122
- builder.ul do
123
- %w(overview features scenarios errors).each do |tab|
124
- builder.li do
125
- builder.a(:href => "##{tab}Tab") do
126
- builder << tab.capitalize
127
- end
128
- end
131
+ @builder.div(:id => 'overviewTab') do
132
+ @builder << "<div id='featurePieChart'></div>"
133
+ @builder << "<div id='scenarioPieChart'></div>"
134
+ @builder << "<div id='stepPieChart'></div>"
129
135
  end
130
- end
131
-
132
- builder.div(:id => 'overviewTab') do
133
- builder << "<div id='featurePieChart'></div>"
134
- builder << "<div id='scenarioPieChart'></div>"
135
- builder << "<div id='stepPieChart'></div>"
136
- end
137
136
 
138
- builder.div(:id => 'featuresTab') do
139
- builder.div(:id => 'features') do
140
- all_features.each_with_index do |feature, n|
141
- builder.h3 do
142
- builder.span(:class => feature['status']) do
143
- builder << "<strong>#{feature['keyword']}</strong> #{feature['name']} (#{duration(feature['duration'])})"
137
+ @builder.div(:id => 'featuresTab') do
138
+ @builder.div(:id => 'features') do
139
+ all_features.each_with_index do |feature, n|
140
+ @builder.h3 do
141
+ @builder.span(:class => feature['status']) do
142
+ @builder << "<strong>#{feature['keyword']}</strong> #{feature['name']} (#{duration(feature['duration'])})"
143
+ end
144
144
  end
145
- end
146
- builder.div do
147
- builder.div(:id => "scenario#{n}") do
148
- feature['elements'].each do |scenario|
149
- builder.h3 do
150
- builder.span(:class => scenario['status']) do
151
- builder << "<strong>#{scenario['keyword']}</strong> #{scenario['name']} (#{duration(scenario['duration'])})"
152
- end
153
- end
154
- builder.div do
155
- scenario['before'].each do |before|
156
- if before['status'] == 'failed'
157
- builder << "<strong style=color:#{COLOR[:failed]}>Error: </strong>"
158
- error = before['result']['error_message'].split("\n")
159
- builder.span(:style => "color:#{COLOR[:failed]}") do
160
- error[0..-2].each do |line|
161
- builder << line + '<br/>'
162
- end
163
- end
164
- builder << "<strong>Hook: </strong>#{error[-1]} <br/>"
165
- end
166
- end
167
- scenario['steps'].each do |step|
168
- builder.span(:class => step['status']) do
169
- builder << "<strong>#{step['keyword']}</strong> #{step['name']} (#{duration(step['duration'])})"
170
- end
171
- step['output'].each do |output|
172
- builder << "<br/> <span style='color:#{COLOR[:skipped]}'>#{output}</span>"
173
- end if step['output'] && step['output'].is_a?(Array)
174
- if step['status'] == 'failed' && step['result']['error_message']
175
- builder << "<br/><strong style=color:#{COLOR[:failed]}>Error: </strong>"
176
- error = step['result']['error_message'].split("\n")
177
- builder.span(:style => "color:#{COLOR[:failed]}") do
178
- error[0..-3].each do |line|
179
- builder << line + '<br/>'
180
- end
181
- end
182
- builder << "<strong>SD: </strong>#{error[-2]} <br/>"
183
- builder << "<strong>FF: </strong>#{error[-1]}"
184
- end
185
- step['after'].each do |after|
186
- after['output'].each do |output|
187
- builder << "<br/> <span style='color:#{COLOR[:skipped]}'>#{output}</span>"
188
- end if after['output'] && after['output'].is_a?(Array)
189
- if after['result']['error_message']
190
- builder << "<br/><strong style=color:#{COLOR[:failed]}>Error: </strong>"
191
- error = after['result']['error_message'].split("\n")
192
- builder.span(:style => "color:#{COLOR[:failed]}") do
193
- (scenario['keyword'] == 'Scenario Outline' ? error[0..-6] : error[0..-4]).each do |line|
194
- builder << line + '<br/>'
195
- end
196
- end
197
- builder << "<strong>Hook: </strong>#{scenario['keyword'] == 'Scenario Outline' ? error[-5] : error[-3]} <br/>"
198
- builder << "<strong>FF: </strong>#{error[-2]} <br/>"
199
- end
200
- end if step['after']
201
- builder << '<br/>'
202
- end
203
- scenario['after'].each do |after|
204
- after['output'].each do |output|
205
- builder << "<br/> <span style='color:#{COLOR[:skipped]}'>#{output}</span>"
206
- end if after['output'] && after['output'].is_a?(Array)
207
- if after['status'] == 'failed'
208
- builder << "<br/><strong style=color:#{COLOR[:failed]}>Error: </strong>"
209
- error = after['result']['error_message'].split("\n")
210
- builder.span(:style => "color:#{COLOR[:failed]}") do
211
- error[0..-2].each do |line|
212
- builder << line + '<br/>'
213
- end
214
- end
215
- builder << "<strong>Hook: </strong>#{error[-1]}"
216
- end
217
- end
218
- end
145
+ @builder.div do
146
+ @builder.div(:id => "scenario#{n}") do
147
+ feature['elements'].each{|scenario| build_scenario scenario}
219
148
  end
220
149
  end
221
150
  end
222
151
  end
152
+ @builder << "<div id='featureTabPieChart'></div>"
223
153
  end
224
- builder << "<div id='featureTabPieChart'></div>"
225
- end
226
154
 
227
- builder.div(:id => 'scenariosTab') do
228
- builder.div(:id => 'status') do
229
- all_scenarios.group_by{|scenario| scenario['status']}.each do |data|
230
- builder.h3 do
231
- builder.sapn(:class => data[0]) do
232
- builder << "<strong>#{data[0].capitalize} scenarios (Count: #{data[1].size})</strong>"
155
+ @builder.div(:id => 'scenariosTab') do
156
+ @builder.div(:id => 'status') do
157
+ all_scenarios.group_by{|scenario| scenario['status']}.each do |data|
158
+ @builder.h3 do
159
+ @builder.sapn(:class => data[0]) do
160
+ @builder << "<strong>#{data[0].capitalize} scenarios (Count: #{data[1].size})</strong>"
161
+ end
233
162
  end
234
- end
235
- builder.div do
236
- builder.div(:id => data[0]) do
237
- data[1].each do |scenario|
238
- builder.h3 do
239
- builder.span(:class => data[0]) do
240
- builder << "<strong>#{scenario['keyword']}</strong> #{scenario['name']} (#{duration(scenario['duration'])})"
241
- end
242
- end
243
- builder.div do
244
- scenario['before'].each do |before|
245
- if before['status'] == 'failed'
246
- builder << "<strong style=color:#{COLOR[:failed]}>Error: </strong>"
247
- error = before['result']['error_message'].split("\n")
248
- builder.span(:style => "color:#{COLOR[:failed]}") do
249
- error[0..-2].each do |line|
250
- builder << line + '<br/>'
251
- end
252
- end
253
- builder << "<strong>Hook: </strong>#{error[-1]} <br/>"
254
- end
255
- end
256
- scenario['steps'].each do |step|
257
- builder.span(:class => step['status']) do
258
- builder << "<strong>#{step['keyword']}</strong> #{step['name']} (#{duration(step['duration'])})"
259
- end
260
- step['output'].each do |output|
261
- builder << "<br/> <span style='color:#{COLOR[:skipped]}'>#{output}</span>"
262
- end if step['output'] && step['output'].is_a?(Array)
263
- if step['status'] == 'failed' && step['result']['error_message']
264
- builder << "<br/><strong style=color:#{COLOR[:failed]}>Error: </strong>"
265
- error = step['result']['error_message'].split("\n")
266
- builder.span(:style => "color:#{COLOR[:failed]}") do
267
- error[0..-3].each do |line|
268
- builder << line + '<br/>'
269
- end
270
- end
271
- builder << "<strong>SD: </strong>#{error[-2]} <br/>"
272
- builder << "<strong>FF: </strong>#{error[-1]}"
273
- end
274
- step['after'].each do |after|
275
- after['output'].each do |output|
276
- builder << "<br/> <span style='color:#{COLOR[:skipped]}'>#{output}</span>"
277
- end if after['output'] && after['output'].is_a?(Array)
278
- if after['result']['error_message']
279
- builder << "<br/><strong style=color:#{COLOR[:failed]}>Error: </strong>"
280
- error = after['result']['error_message'].split("\n")
281
- builder.span(:style => "color:#{COLOR[:failed]}") do
282
- (scenario['keyword'] == 'Scenario Outline' ? error[0..-6] : error[0..-4]).each do |line|
283
- builder << line + '<br/>'
284
- end
285
- end
286
- builder << "<strong>Hook: </strong>#{scenario['keyword'] == 'Scenario Outline' ? error[-5] : error[-3]} <br/>"
287
- builder << "<strong>FF: </strong>#{error[-2]} <br/>"
288
- end
289
- end if step['after']
290
- builder << '<br>'
291
- end
292
- scenario['after'].each do |after|
293
- after['output'].each do |output|
294
- builder << "<br/> <span style='color:#{COLOR[:skipped]}'>#{output}</span>"
295
- end if after['output'] && after['output'].is_a?(Array)
296
- if after['status'] == 'failed'
297
- builder << "<br/><strong style=color:#{COLOR[:failed]}>Error: </strong>"
298
- error = after['result']['error_message'].split("\n")
299
- builder.span(:style => "color:#{COLOR[:failed]}") do
300
- error[0..-2].each do |line|
301
- builder << line + '<br/>'
302
- end
303
- end
304
- builder << "<strong>Hook: </strong>#{error[-1]}"
305
- end
306
- end
307
- end
163
+ @builder.div do
164
+ @builder.div(:id => data[0]) do
165
+ data[1].each{|scenario| build_scenario scenario}
308
166
  end
309
167
  end
310
168
  end
311
169
  end
170
+ @builder << "<div id='scenarioTabPieChart'></div>"
171
+ end
172
+
173
+ @builder.div(:id => 'errorsTab') do
174
+ @builder.ol do
175
+ all_scenarios.each{|scenario| build_error_list scenario}
176
+ end
312
177
  end
313
- builder << "<div id='scenarioTabPieChart'></div>"
314
178
  end
315
179
 
316
- builder.div(:id => 'errorsTab') do
317
- builder.ol do
318
- all_scenarios.each do |scenario|
319
- scenario['before'].each do |before|
320
- next unless before['status'] == 'failed'
321
- builder.li do
322
- error = before['result']['error_message'].split("\n")
323
- builder.span(:style => "color:#{COLOR[:failed]}") do
324
- error[0..-2].each do |line|
325
- builder << line + '<br/>'
326
- end
327
- end
328
- builder << "<strong>Hook: </strong>#{error[-1]} <br/>"
329
- builder << "<strong>Scenario: </strong>#{scenario['name']}"
330
- end
331
- end
332
- scenario['steps'].each do |step|
333
- step['after'].each do |after|
334
- next unless after['status'] == 'failed'
335
- builder.li do
336
- error = after['result']['error_message'].split("\n")
337
- builder.span(:style => "color:#{COLOR[:failed]}") do
338
- (scenario['keyword'] == 'Scenario Outline' ? error[0..-6] : error[0..-4]).each do |line|
339
- builder << line + '<br/>'
340
- end
341
- end
342
- builder << "<strong>Hook: </strong>#{scenario['keyword'] == 'Scenario Outline' ? error[-5] : error[-3]} <br/>"
343
- builder << "<strong>FF: </strong>#{error[-2]} <br/>"
344
- end
345
- end if step['after']
346
- next unless step['status'] == 'failed' && step['result']['error_message']
347
- builder.li do
348
- error = step['result']['error_message'].split("\n")
349
- builder.span(:style => "color:#{COLOR[:failed]}") do
350
- error[0..-3].each do |line|
351
- builder << line + '<br/>'
352
- end
353
- end
354
- builder << "<strong>SD: </strong>#{error[-2]} <br/>"
355
- builder << "<strong>FF: </strong>#{error[-1]}"
356
- end
357
- end
358
- scenario['after'].each do |after|
359
- next unless after['status'] == 'failed'
360
- builder.li do
361
- error = after['result']['error_message'].split("\n")
362
- builder.span(:style => "color:#{COLOR[:failed]}") do
363
- error[0..-2].each do |line|
364
- builder << line + '<br/>'
365
- end
366
- end
367
- builder << "<strong>Hook: </strong>#{error[-1]} <br/>"
368
- builder << "<strong>Scenario: </strong>#{scenario['name']}"
369
- end
370
- end
180
+ @builder.script(:type => 'text/javascript') do
181
+ @builder << pie_chart_js('featurePieChart', 'Features', feature_data)
182
+ @builder << donut_js('featureTabPieChart', 'Features', feature_data)
183
+ @builder << pie_chart_js('scenarioPieChart', 'Scenarios', scenario_data)
184
+ @builder << donut_js('scenarioTabPieChart', 'Scenarios', scenario_data)
185
+ @builder << pie_chart_js('stepPieChart', 'Steps', step_data)
186
+ end
187
+
188
+ @builder << '</body>'
189
+ @builder << '</html>'
190
+
191
+ puts "HTML test report generated: '#{output_file_name}.html'"
192
+ end if output_file_type.to_s.upcase.include? 'HTML'
193
+
194
+ [total_time, feature_data, scenario_data, step_data]
195
+ end
196
+
197
+ def self.build_menu(tabs)
198
+ @builder.ul do
199
+ tabs.each do |tab|
200
+ @builder.li do
201
+ @builder.a(:href => "##{tab}Tab") do
202
+ @builder << tab.capitalize
371
203
  end
372
204
  end
373
205
  end
374
206
  end
207
+ end
375
208
 
376
- builder.script(:type => 'text/javascript') do
377
- builder << pie_chart_js('featurePieChart', 'Features', feature_data)
378
- builder << donut_js('featureTabPieChart', 'Features', feature_data)
379
- builder << pie_chart_js('scenarioPieChart', 'Scenarios', scenario_data)
380
- builder << donut_js('scenarioTabPieChart', 'Scenarios', scenario_data)
381
- builder << pie_chart_js('stepPieChart', 'Steps', step_data)
209
+ def self.build_scenario(scenario)
210
+ @builder.h3 do
211
+ @builder.span(:class => scenario['status']) do
212
+ @builder << "<strong>#{scenario['keyword']}</strong> #{scenario['name']} (#{duration(scenario['duration'])})"
213
+ end
214
+ end
215
+ @builder.div do
216
+ scenario['before'].each do |before|
217
+ build_hook_error before
218
+ end
219
+ scenario['steps'].each do |step|
220
+ build_step step, scenario['keyword']
221
+ end
222
+ scenario['after'].each do |after|
223
+ build_output after['output']
224
+ build_hook_error after
225
+ build_embedding after['embeddings']
226
+ end
382
227
  end
228
+ end
383
229
 
384
- builder << '</body>'
385
- builder << '</html>'
230
+ def self.build_step(step, scenario_keyword)
231
+ @builder.span(:class => step['status']) do
232
+ @builder << "<strong>#{step['keyword']}</strong> #{step['name']} (#{duration(step['duration'])})"
233
+ end
234
+ build_output step['output']
235
+ build_step_error step
236
+ build_embedding step['embeddings']
237
+ step['after'].each do |after|
238
+ build_output after['output']
239
+ build_step_hook_error after, scenario_keyword
240
+ build_embedding after['embeddings']
241
+ end if step['after']
242
+ @builder << '<br/>'
243
+ end
386
244
 
387
- file.close
245
+ def self.build_output(outputs)
246
+ outputs.each do |output|
247
+ @builder << "<br/><span style='color:#{COLOR[:output]}'>#{output.gsub("\n",'</br>').gsub("\t",'&nbsp;&nbsp;').gsub(' ','&nbsp;')}</span>"
248
+ end if outputs.is_a?(Array)
249
+ end
388
250
 
389
- puts "HTML test report generated: '#{output_file_name}.html'"
390
- [total_time, feature_data, scenario_data, step_data]
251
+ def self.build_step_error(step)
252
+ if step['status'] == 'failed' && step['result']['error_message']
253
+ @builder << "<br/><strong style=color:#{COLOR[:failed]}>Error: </strong>"
254
+ error = step['result']['error_message'].split("\n")
255
+ @builder.span(:style => "color:#{COLOR[:failed]}") do
256
+ error[0..-3].each do |line|
257
+ @builder << line + '<br/>'
258
+ end
259
+ end
260
+ @builder << "<strong>SD: </strong>#{error[-2]} <br/>"
261
+ @builder << "<strong>FF: </strong>#{error[-1]}"
262
+ end
263
+ end
264
+
265
+ def self.build_hook_error(hook)
266
+ if hook['status'] == 'failed'
267
+ @builder << "<br/><strong style=color:#{COLOR[:failed]}>Error: </strong>"
268
+ error = hook['result']['error_message'].split("\n")
269
+ @builder.span(:style => "color:#{COLOR[:failed]}") do
270
+ error[0..-2].each do |line|
271
+ @builder << line + '<br/>'
272
+ end
273
+ end
274
+ @builder << "<strong>Hook: </strong>#{error[-1]}<br/>"
275
+ end
276
+ end
277
+
278
+ def self.build_step_hook_error(hook, scenario_keyword)
279
+ if hook['result']['error_message']
280
+ @builder << "<br/><strong style=color:#{COLOR[:failed]}>Error: </strong>"
281
+ error = hook['result']['error_message'].split("\n")
282
+ @builder.span(:style => "color:#{COLOR[:failed]}") do
283
+ (scenario_keyword == 'Scenario Outline' ? error[0..-6] : error[0..-4]).each do |line|
284
+ @builder << line + '<br/>'
285
+ end
286
+ end
287
+ @builder << "<strong>Hook: </strong>#{scenario_keyword == 'Scenario Outline' ? error[-5] : error[-3]} <br/>"
288
+ @builder << "<strong>FF: </strong>#{error[-2]}"
289
+ end
290
+ end
291
+
292
+ def self.build_embedding(embeddings)
293
+ @embedding_count ||= 0
294
+ embeddings.each do |embedding|
295
+ id = "embedding_#{@embedding_count}"
296
+ if embedding['mime_type'] =~ /^image\/(png|gif|jpg|jpeg)/
297
+ @builder.span(:class => 'image') do
298
+ @builder << '<br/>'
299
+ @builder.a(:href => '', :style => 'text-decoration: none;', :onclick => "img=document.getElementById('#{id}');img.style.display = (img.style.display == 'none' ? 'block' : 'none');return false") do
300
+ @builder.span(:style => "color: #{COLOR[:output]}; font-weight: bold; border-bottom: 1px solid #{COLOR[:output]};") do
301
+ @builder << 'Screenshot'
302
+ end
303
+ end
304
+ @builder << '<br/>'
305
+ begin
306
+ src = Base64.decode64(embedding['data'])
307
+ src = 'data:' + embedding['mime_type'] + ';base64,' + src unless src =~ /^data:image\/(png|gif|jpg|jpeg);base64,/
308
+ @builder << %{<img id='#{id}' style='display: none; border: 1px solid #{COLOR[:output]};' src='#{src}'/>}
309
+ rescue
310
+ src = embedding['data']
311
+ src = 'data:' + embedding['mime_type'] + ';base64,' + src unless src =~ /^data:image\/(png|gif|jpg|jpeg);base64,/
312
+ @builder << %{<img id='#{id}' style='display: none; border: 1px solid #{COLOR[:output]};' src='#{src}'/>}
313
+ end rescue puts('Image embedding skipped!')
314
+ end
315
+ elsif embedding['mime_type'] =~ /^text\/plain/
316
+ @builder.span(:class => 'link') do
317
+ @builder << '<br/>'
318
+ src = Base64.decode64(embedding['data'])
319
+ @builder.a(:id => id, :style => 'text-decoration: none;', :href => src, :title => 'Link') do
320
+ @builder.span(:style => "color: #{COLOR[:output]}; font-weight: bold; border-bottom: 1px solid #{COLOR[:output]};") do
321
+ @builder << src
322
+ end
323
+ end
324
+ @builder << '<br/>'
325
+ end rescue puts('Link embedding skipped!')
326
+ end
327
+ @embedding_count += 1
328
+ end if embeddings.is_a?(Array)
329
+ end
330
+
331
+ def self.build_error_list(scenario)
332
+ scenario['before'].each do |before|
333
+ next unless before['status'] == 'failed'
334
+ @builder.li do
335
+ error = before['result']['error_message'].split("\n")
336
+ @builder.span(:style => "color:#{COLOR[:failed]}") do
337
+ error[0..-2].each do |line|
338
+ @builder << line + '<br/>'
339
+ end
340
+ end
341
+ @builder << "<strong>Hook: </strong>#{error[-1]} <br/>"
342
+ @builder << "<strong>Scenario: </strong>#{scenario['name']} <br/><hr/>"
343
+ end
344
+ end
345
+ scenario['steps'].each do |step|
346
+ step['after'].each do |after|
347
+ next unless after['status'] == 'failed'
348
+ @builder.li do
349
+ error = after['result']['error_message'].split("\n")
350
+ @builder.span(:style => "color:#{COLOR[:failed]}") do
351
+ (scenario['keyword'] == 'Scenario Outline' ? error[0..-6] : error[0..-4]).each do |line|
352
+ @builder << line + '<br/>'
353
+ end
354
+ end
355
+ @builder << "<strong>Hook: </strong>#{scenario['keyword'] == 'Scenario Outline' ? error[-5] : error[-3]} <br/>"
356
+ @builder << "<strong>FF: </strong>#{error[-2]} <br/><hr/>"
357
+ end
358
+ end if step['after']
359
+ next unless step['status'] == 'failed' && step['result']['error_message']
360
+ @builder.li do
361
+ error = step['result']['error_message'].split("\n")
362
+ @builder.span(:style => "color:#{COLOR[:failed]}") do
363
+ error[0..-3].each do |line|
364
+ @builder << line + '<br/>'
365
+ end
366
+ end
367
+ @builder << "<strong>SD: </strong>#{error[-2]} <br/>"
368
+ @builder << "<strong>FF: </strong>#{error[-1]} <br/><hr/>"
369
+ end
370
+ end
371
+ scenario['after'].each do |after|
372
+ next unless after['status'] == 'failed'
373
+ @builder.li do
374
+ error = after['result']['error_message'].split("\n")
375
+ @builder.span(:style => "color:#{COLOR[:failed]}") do
376
+ error[0..-2].each do |line|
377
+ @builder << line + '<br/>'
378
+ end
379
+ end
380
+ @builder << "<strong>Hook: </strong>#{error[-1]} <br/>"
381
+ @builder << "<strong>Scenario: </strong>#{scenario['name']} <br/><hr/>"
382
+ end
383
+ end
391
384
  end
392
385
 
393
386
  def self.features(files)
394
387
  files.each_with_object([]) { |file, features|
395
- features << JSON.parse(File.read(file))
388
+ data = File.read(file)
389
+ next if data.empty?
390
+ features << JSON.parse(data)
396
391
  }.flatten.group_by { |feature|
397
392
  feature['uri']+feature['id']+feature['line'].to_s
398
393
  }.values.each_with_object([]) { |group, features|
@@ -461,7 +456,7 @@ class ReportBuilder
461
456
  files = if path.is_a? String
462
457
  (path =~ /\.json$/) ? [path] : Dir.glob("#{path}/*.json")
463
458
  elsif path.nil?
464
- Dir.glob("*.json")
459
+ Dir.glob('*.json')
465
460
  elsif path.is_a? Array
466
461
  path.map do |file|
467
462
  (file =~ /\.json$/) ? file : Dir.glob("#{file}/*.json")
@@ -531,5 +526,9 @@ class ReportBuilder
531
526
  private_class_method :donut_js, :pie_chart_js, :files,
532
527
  :features, :feature_status,
533
528
  :scenarios, :scenario_status, :steps,
534
- :data, :duration, :total_time
529
+ :data, :duration, :total_time,
530
+ :build_scenario, :build_step,
531
+ :build_menu, :build_output, :build_embedding,
532
+ :build_error_list, :build_step_error,
533
+ :build_hook_error, :build_step_hook_error
535
534
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: report_builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rajat Thareja
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-10 00:00:00.000000000 Z
11
+ date: 2016-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: builder