Class: Cucumber::Formatter::Html

Inherits:
Object
  • Object
show all
Includes:
Duration, Io, ERB::Util
Defined in:
lib/cucumber/formatter/html.rb

Defined Under Namespace

Classes: SnippetExtractor

Instance Method Summary collapse

Methods included from Io

#ensure_dir, #ensure_file, #ensure_io

Methods included from Duration

#format_duration

Constructor Details

#initialize(runtime, path_or_io, options) ⇒ Html

Returns a new instance of Html.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/cucumber/formatter/html.rb', line 13

def initialize(runtime, path_or_io, options)
  @io = ensure_io(path_or_io, "html")
  @runtime = runtime
  @options = options
  @buffer = {}
  @builder = create_builder(@io)
  @feature_number = 0
  @scenario_number = 0
  @step_number = 0
  @header_red = nil
  @delayed_messages = []
  @img_id = 0
  @inside_outline = false
end

Instance Method Details

#after_background(background) ⇒ Object



144
145
146
147
# File 'lib/cucumber/formatter/html.rb', line 144

def after_background(background)
  @in_background = nil
  @builder << '</div>'
end

#after_comment(comment) ⇒ Object



106
107
108
# File 'lib/cucumber/formatter/html.rb', line 106

def after_comment(comment)
  @builder << '</pre>'
end

#after_examples(examples) ⇒ Object



201
202
203
# File 'lib/cucumber/formatter/html.rb', line 201

def after_examples(examples)
  @builder << '</div>'
end

#after_feature(feature) ⇒ Object



98
99
100
# File 'lib/cucumber/formatter/html.rb', line 98

def after_feature(feature)
  @builder << '</div>'
end

#after_feature_element(feature_element) ⇒ Object



168
169
170
171
# File 'lib/cucumber/formatter/html.rb', line 168

def after_feature_element(feature_element)
  @builder << '</div>'
  @open_step_list = true
end

#after_features(features) ⇒ Object



86
87
88
89
90
91
# File 'lib/cucumber/formatter/html.rb', line 86

def after_features(features)
  print_stats(features)
  @builder << '</div>'
  @builder << '</body>'
  @builder << '</html>'
end

#after_multiline_arg(multiline_arg) ⇒ Object



291
292
293
294
295
296
# File 'lib/cucumber/formatter/html.rb', line 291

def after_multiline_arg(multiline_arg)
  return if @hide_this_step || @skip_step
  if Ast::Table === multiline_arg
    @builder << '</table>'
  end
end

#after_outline_table(outline_table) ⇒ Object



191
192
193
194
195
# File 'lib/cucumber/formatter/html.rb', line 191

def after_outline_table(outline_table)
  @builder << '</table>'
  @outline_row = nil
  @inside_outline = false
end

#after_step(step) ⇒ Object



227
228
229
# File 'lib/cucumber/formatter/html.rb', line 227

def after_step(step)
  move_progress
end

#after_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line) ⇒ Object



251
252
253
254
255
256
257
258
259
260
261
262
263
# File 'lib/cucumber/formatter/html.rb', line 251

def after_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line)
  return if @hide_this_step
  # print snippet for undefined steps
  if status == :undefined
    keyword = @step.actual_keyword if @step.respond_to?(:actual_keyword)
    step_multiline_class = @step.multiline_arg ? @step.multiline_arg.class : nil
    @builder.pre do |pre|
      pre << @runtime.snippet_text(keyword,step_match.instance_variable_get("@name") || '',step_multiline_class)
    end
  end
  @builder << '</li>'
  print_messages
end

#after_steps(steps) ⇒ Object



217
218
219
# File 'lib/cucumber/formatter/html.rb', line 217

def after_steps(steps)
  @builder << '</ol>'
end

#after_table_row(table_row) ⇒ Object



313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
# File 'lib/cucumber/formatter/html.rb', line 313

def after_table_row(table_row)
  return if @hide_this_step
  print_table_row_messages
  @builder << '</tr>'
  if table_row.exception
    @builder.tr do
      @builder.td(:colspan => @col_index.to_s, :class => 'failed') do
        @builder.pre do |pre|
          pre << h(format_exception(table_row.exception))
        end
      end
    end
    if table_row.exception.is_a? ::Cucumber::Pending
      set_scenario_color_pending
    else
      set_scenario_color_failed
    end
  end
  if @outline_row
    @outline_row += 1
  end
  @step_number += 1
  move_progress
end

#after_tags(tags) ⇒ Object



115
116
117
# File 'lib/cucumber/formatter/html.rb', line 115

def after_tags(tags)
  @tag_spacer = nil
end

#background_name(keyword, name, file_colon_line, source_indent) ⇒ Object



149
150
151
152
153
154
155
156
# File 'lib/cucumber/formatter/html.rb', line 149

def background_name(keyword, name, file_colon_line, source_indent)
  @listing_background = true
  @builder.h3(:id => "background_#{@scenario_number}") do |h3|
    @builder.span(keyword, :class => 'keyword')
    @builder.text!(' ')
    @builder.span(name, :class => 'val')
  end
end

#before_background(background) ⇒ Object



139
140
141
142
# File 'lib/cucumber/formatter/html.rb', line 139

def before_background(background)
  @in_background = true
  @builder << '<div class="background">'
end

#before_comment(comment) ⇒ Object



102
103
104
# File 'lib/cucumber/formatter/html.rb', line 102

def before_comment(comment)
  @builder << '<pre class="comment">'
end

#before_examples(examples) ⇒ Object



197
198
199
# File 'lib/cucumber/formatter/html.rb', line 197

def before_examples(examples)
   @builder << '<div class="examples">'
end

#before_feature(feature) ⇒ Object



93
94
95
96
# File 'lib/cucumber/formatter/html.rb', line 93

def before_feature(feature)
  @exceptions = []
  @builder << '<div class="feature">'
end

#before_feature_element(feature_element) ⇒ Object



158
159
160
161
162
163
164
165
166
# File 'lib/cucumber/formatter/html.rb', line 158

def before_feature_element(feature_element)
  @scenario_number+=1
  @scenario_red = false
  css_class = {
    Ast::Scenario        => 'scenario',
    Ast::ScenarioOutline => 'scenario outline'
  }[feature_element.class]
  @builder << "<div class='#{css_class}'>"
end

#before_features(features) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/cucumber/formatter/html.rb', line 49

def before_features(features)
  @step_count = features.step_count

  # <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  @builder.declare!(
    :DOCTYPE,
    :html,
    :PUBLIC,
    '-//W3C//DTD XHTML 1.0 Strict//EN',
    'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'
  )

  @builder << '<html xmlns ="http://www.w3.org/1999/xhtml">'
    @builder.head do
    @builder.meta('http-equiv' => 'Content-Type', :content => 'text/html;charset=utf-8')
    @builder.title 'Cucumber'
    inline_css
    inline_js
  end
  @builder << '<body>'
  @builder << "<!-- Step count #{@step_count}-->"
  @builder << '<div class="cucumber">'
  @builder.div(:id => 'cucumber-header') do
    @builder.div(:id => 'label') do
      @builder.h1('Cucumber Features')
    end
    @builder.div(:id => 'summary') do
      @builder.p('',:id => 'totals')
      @builder.p('',:id => 'duration')
      @builder.div(:id => 'expand-collapse') do
        @builder.p('Expand All', :id => 'expander')
        @builder.p('Collapse All', :id => 'collapser')
      end
    end
  end
end

#before_multiline_arg(multiline_arg) ⇒ Object



284
285
286
287
288
289
# File 'lib/cucumber/formatter/html.rb', line 284

def before_multiline_arg(multiline_arg)
  return if @hide_this_step || @skip_step
  if Ast::Table === multiline_arg
    @builder << '<table>'
  end
end

#before_outline_table(outline_table) ⇒ Object



185
186
187
188
189
# File 'lib/cucumber/formatter/html.rb', line 185

def before_outline_table(outline_table)
  @inside_outline = true
  @outline_row = 0
  @builder << '<table>'
end

#before_step(step) ⇒ Object



221
222
223
224
225
# File 'lib/cucumber/formatter/html.rb', line 221

def before_step(step)
  @step_id = step.dom_id
  @step_number += 1
  @step = step
end

#before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line) ⇒ Object



231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/cucumber/formatter/html.rb', line 231

def before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line)
  @step_match = step_match
  @hide_this_step = false
  if exception
    if @exceptions.include?(exception)
      @hide_this_step = true
      return
    end
    @exceptions << exception
  end
  if status != :failed && @in_background ^ background
    @hide_this_step = true
    return
  end
  @status = status
  return if @hide_this_step
  set_scenario_color(status)
  @builder << "<li id='#{@step_id}' class='step #{status}'>"
end

#before_steps(steps) ⇒ Object



213
214
215
# File 'lib/cucumber/formatter/html.rb', line 213

def before_steps(steps)
  @builder << '<ol>'
end

#before_table_row(table_row) ⇒ Object



306
307
308
309
310
311
# File 'lib/cucumber/formatter/html.rb', line 306

def before_table_row(table_row)
  @row_id = table_row.dom_id
  @col_index = 0
  return if @hide_this_step
  @builder << "<tr class='step' id='#{@row_id}'>"
end

#comment_line(comment_line) ⇒ Object



110
111
112
113
# File 'lib/cucumber/formatter/html.rb', line 110

def comment_line(comment_line)
  @builder.text!(comment_line)
  @builder.br
end

#doc_string(string) ⇒ Object



298
299
300
301
302
303
# File 'lib/cucumber/formatter/html.rb', line 298

def doc_string(string)
  return if @hide_this_step
  @builder.pre(:class => 'val') do |pre|
    @builder << h(string).gsub("\n", '&#x000A;')
  end
end

#embed(src, mime_type, label) ⇒ Object



28
29
30
31
32
33
34
35
36
37
# File 'lib/cucumber/formatter/html.rb', line 28

def embed(src, mime_type, label)
  case(mime_type)
  when /^image\/(png|gif|jpg|jpeg)/
    unless File.file?(src) or src =~ /^data:image\/(png|gif|jpg|jpeg);base64,/
      type = mime_type =~ /;base[0-9]+$/ ? mime_type : mime_type + ";base64"
      src = "data:" + type + "," + src
    end
    embed_image(src, label)
  end
end

#embed_image(src, label) ⇒ Object



39
40
41
42
43
44
45
46
# File 'lib/cucumber/formatter/html.rb', line 39

def embed_image(src, label)
  id = "img_#{@img_id}"
  @img_id += 1
  @builder.span(:class => 'embed') do |pre|
    pre << %{<a href="" onclick="img=document.getElementById('#{id}'); img.style.display = (img.style.display == 'none' ? 'block' : 'none');return false">#{label}</a><br>&nbsp;
    <img id="#{id}" style="display: none" src="#{src}"/>}
  end
end

#empty_messagesObject



376
377
378
# File 'lib/cucumber/formatter/html.rb', line 376

def empty_messages
  @delayed_messages = []
end

#examples_name(keyword, name) ⇒ Object



205
206
207
208
209
210
211
# File 'lib/cucumber/formatter/html.rb', line 205

def examples_name(keyword, name)
  @builder.h4 do
    @builder.span(keyword, :class => 'keyword')
    @builder.text!(' ')
    @builder.span(name, :class => 'val')
  end
end

#exception(exception, status) ⇒ Object



274
275
276
277
# File 'lib/cucumber/formatter/html.rb', line 274

def exception(exception, status)
  return if @hide_this_step
  build_exception_detail(exception)
end

#extra_failure_content(file_colon_line) ⇒ Object



279
280
281
282
# File 'lib/cucumber/formatter/html.rb', line 279

def extra_failure_content(file_colon_line)
  @snippet_extractor ||= SnippetExtractor.new
  "<pre class=\"ruby\"><code>#{@snippet_extractor.snippet(file_colon_line)}</code></pre>"
end

#feature_name(keyword, name) ⇒ Object



125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/cucumber/formatter/html.rb', line 125

def feature_name(keyword, name)
  lines = name.split(/\r?\n/)
  return if lines.empty?
  @builder.h2 do |h2|
    @builder.span(keyword + ': ' + lines[0], :class => 'val')
  end
  @builder.p(:class => 'narrative') do
    lines[1..-1].each do |line|
      @builder.text!(line.strip)
      @builder.br
    end
  end
end


354
355
356
357
358
359
360
361
362
363
364
365
# File 'lib/cucumber/formatter/html.rb', line 354

def print_messages
  return if @delayed_messages.empty?

  #@builder.ol do
    @delayed_messages.each do |ann|
      @builder.li(:class => 'step message') do
        @builder << ann
      end
    end
  #end
  empty_messages
end


367
368
369
370
371
372
373
374
# File 'lib/cucumber/formatter/html.rb', line 367

def print_table_row_messages
  return if @delayed_messages.empty?

  @builder.td(:class => 'message') do
    @builder << @delayed_messages.join(", ")
  end
  empty_messages
end

#puts(message) ⇒ Object



349
350
351
352
# File 'lib/cucumber/formatter/html.rb', line 349

def puts(message)
  @delayed_messages << message
  #@builder.pre(message, :class => 'message')
end

#scenario_name(keyword, name, file_colon_line, source_indent) ⇒ Object



173
174
175
176
177
178
179
180
181
182
183
# File 'lib/cucumber/formatter/html.rb', line 173

def scenario_name(keyword, name, file_colon_line, source_indent)
  @builder.span(:class => 'scenario_file') do
    @builder << file_colon_line
  end
  @listing_background = false
  @builder.h3(:id => "scenario_#{@scenario_number}") do
    @builder.span(keyword + ':', :class => 'keyword')
    @builder.text!(' ')
    @builder.span(name, :class => 'val')
  end
end

#step_name(keyword, step_match, status, source_indent, background, file_colon_line) ⇒ Object



265
266
267
268
269
270
271
272
# File 'lib/cucumber/formatter/html.rb', line 265

def step_name(keyword, step_match, status, source_indent, background, file_colon_line)
  background_in_scenario = background && !@listing_background
  @skip_step = background_in_scenario

  unless @skip_step
    build_step(keyword, step_match, status)
  end
end

#table_cell_value(value, status) ⇒ Object



338
339
340
341
342
343
344
345
346
347
# File 'lib/cucumber/formatter/html.rb', line 338

def table_cell_value(value, status)
  return if @hide_this_step

  @cell_type = @outline_row == 0 ? :th : :td
  attributes = {:id => "#{@row_id}_#{@col_index}", :class => 'step'}
  attributes[:class] += " #{status}" if status
  build_cell(@cell_type, value, attributes)
  set_scenario_color(status) if @inside_outline
  @col_index += 1
end

#tag_name(tag_name) ⇒ Object



119
120
121
122
123
# File 'lib/cucumber/formatter/html.rb', line 119

def tag_name(tag_name)
  @builder.text!(@tag_spacer) if @tag_spacer
  @tag_spacer = ' '
  @builder.span(tag_name, :class => 'tag')
end