cucumber 0.3.102 → 0.3.103

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.
Files changed (47) hide show
  1. data/History.txt +18 -0
  2. data/Manifest.txt +6 -2
  3. data/examples/java/README.textile +3 -3
  4. data/examples/self_test/features/sample.feature +1 -1
  5. data/examples/self_test/features/search_sample.feature +1 -1
  6. data/features/custom_formatter.feature +4 -4
  7. data/features/steps_formatter.feature +2 -1
  8. data/lib/cucumber/ast.rb +1 -0
  9. data/lib/cucumber/ast/table.rb +4 -4
  10. data/lib/cucumber/ast/tree_walker.rb +185 -0
  11. data/lib/cucumber/ast/visitor.rb +2 -106
  12. data/lib/cucumber/cli/configuration.rb +28 -28
  13. data/lib/cucumber/cli/language_help_formatter.rb +5 -7
  14. data/lib/cucumber/cli/main.rb +3 -3
  15. data/lib/cucumber/core_ext/string.rb +0 -22
  16. data/lib/cucumber/formatter/html.rb +203 -113
  17. data/lib/cucumber/formatter/junit.rb +29 -23
  18. data/lib/cucumber/formatter/pdf.rb +74 -69
  19. data/lib/cucumber/formatter/pretty.rb +93 -78
  20. data/lib/cucumber/formatter/profile.rb +2 -2
  21. data/lib/cucumber/formatter/progress.rb +16 -10
  22. data/lib/cucumber/formatter/rerun.rb +4 -5
  23. data/lib/cucumber/formatter/steps.rb +6 -7
  24. data/lib/cucumber/formatter/tag_cloud.rb +7 -6
  25. data/lib/cucumber/formatter/usage.rb +7 -10
  26. data/lib/cucumber/language_support/step_definition_methods.rb +4 -4
  27. data/lib/cucumber/rails/action_controller.rb +1 -1
  28. data/lib/cucumber/rails/active_record.rb +27 -14
  29. data/lib/cucumber/rb_support/rb_language.rb +5 -0
  30. data/lib/cucumber/rb_support/rb_step_definition.rb +9 -16
  31. data/lib/cucumber/rb_support/regexp_argument_matcher.rb +21 -0
  32. data/lib/cucumber/step_argument.rb +9 -0
  33. data/lib/cucumber/step_match.rb +24 -5
  34. data/lib/cucumber/version.rb +1 -1
  35. data/rails_generators/cucumber/templates/env.rb +14 -0
  36. data/spec/cucumber/ast/background_spec.rb +1 -2
  37. data/spec/cucumber/ast/scenario_outline_spec.rb +3 -2
  38. data/spec/cucumber/ast/scenario_spec.rb +1 -1
  39. data/spec/cucumber/ast/tree_walker_spec.rb +18 -0
  40. data/spec/cucumber/formatter/html_spec.rb +221 -2
  41. data/spec/cucumber/formatter/progress_spec.rb +9 -4
  42. data/spec/cucumber/parser/feature_parser_spec.rb +31 -27
  43. data/spec/cucumber/rb_support/regexp_argument_matcher_spec.rb +18 -0
  44. data/spec/cucumber/step_match_spec.rb +40 -0
  45. metadata +8 -4
  46. data/lib/cucumber/rb_support/rb_group.rb +0 -11
  47. data/spec/cucumber/core_ext/string_spec.rb +0 -41
@@ -3,21 +3,20 @@ require 'cucumber/formatter/ordered_xml_markup'
3
3
  module Cucumber
4
4
  module Formatter
5
5
  # The formatter used for <tt>--format junit</tt>
6
- class Junit < Cucumber::Ast::Visitor
7
-
6
+ class Junit
8
7
  def initialize(step_mother, io, options)
9
- super(step_mother)
10
8
  raise "You *must* specify --out DIR for the junit formatter" unless String === io && File.directory?(io)
11
9
  @reportdir = io
12
10
  @options = options
13
11
  end
14
12
 
15
- def visit_feature(feature)
13
+ def before_feature(feature)
16
14
  @failures = @errors = @tests = 0
17
15
  @builder = OrderedXmlMarkup.new( :indent => 2 )
18
16
  @time = 0
19
- super
20
-
17
+ end
18
+
19
+ def after_feature(feature)
21
20
  @testsuite = OrderedXmlMarkup.new( :indent => 2 )
22
21
  @testsuite.instruct!
23
22
  @testsuite.testsuite(
@@ -25,7 +24,7 @@ module Cucumber
25
24
  :errors => @errors,
26
25
  :tests => @tests,
27
26
  :time => "%.6f" % @time,
28
- :name => @feature_name ) do
27
+ :name => @feature_name ) do
29
28
  @testsuite << @builder.target!
30
29
  end
31
30
 
@@ -34,18 +33,20 @@ module Cucumber
34
33
  File.open(feature_filename, 'w') { |file| file.write(@testsuite.target!) }
35
34
  end
36
35
 
37
- def visit_background(name)
36
+ def before_background(*args)
38
37
  @in_background = true
39
- super
38
+ end
39
+
40
+ def after_background(*args)
40
41
  @in_background = false
41
42
  end
42
43
 
43
- def visit_feature_name(name)
44
+ def feature_name(name)
44
45
  lines = name.split(/\r?\n/)
45
46
  @feature_name = lines[0].sub(/Feature\:/, '').strip
46
47
  end
47
48
 
48
- def visit_scenario_name(keyword, name, file_colon_line, source_indent)
49
+ def scenario_name(keyword, name, file_colon_line, source_indent)
49
50
  scenario_name = name.strip.delete(".\r\n")
50
51
  scenario_name = "Unnamed scenario" if name.blank?
51
52
  @scenario = scenario_name
@@ -53,11 +54,13 @@ module Cucumber
53
54
  @output = "Scenario#{ " outline" if @outline}: #{@scenario}\n\n"
54
55
  end
55
56
 
56
- def visit_steps(steps)
57
+ def before_steps(steps)
58
+ @steps_start = Time.now
59
+ end
60
+
61
+ def after_steps(steps)
57
62
  return if @in_background
58
- start = Time.now
59
- super
60
- duration = Time.now - start
63
+ duration = Time.now - @steps_start
61
64
  unless @outline
62
65
  if steps.failed?
63
66
  steps.each { |step| @output += "#{step.keyword} #{step.name}\n" }
@@ -67,16 +70,21 @@ module Cucumber
67
70
  end
68
71
  end
69
72
 
70
- def visit_outline_table(outline_table)
73
+ def before_outline_table(outline_table)
71
74
  @header_row = true
72
- super(outline_table)
73
75
  end
74
76
 
75
- def visit_table_row(table_row)
77
+ def before_table_row(table_row)
78
+ if @outline
79
+ @table_start = Time.now
80
+ end
81
+
82
+ @header_row = false
83
+ end
84
+
85
+ def after_table_row(table_row)
76
86
  if @outline
77
- start = Time.now
78
- super(table_row)
79
- duration = Time.now - start
87
+ duration = Time.now - @table_start
80
88
  unless @header_row
81
89
  name_suffix = " (outline example : #{table_row.name})"
82
90
  if table_row.failed?
@@ -85,8 +93,6 @@ module Cucumber
85
93
  end
86
94
  build_testcase(duration, table_row.status, table_row.exception, name_suffix)
87
95
  end
88
- else
89
- super(table_row)
90
96
  end
91
97
  @header_row = false
92
98
  end
@@ -10,13 +10,13 @@ module Cucumber
10
10
  BLACK = '000000'
11
11
  GREY = '999999'
12
12
 
13
- class Pdf < Ast::Visitor
13
+ class Pdf
14
14
  include FileUtils
15
15
  include Console
16
16
  attr_writer :indent
17
17
 
18
18
  def initialize(step_mother, io, options)
19
- super(step_mother)
19
+ @step_mother = step_mother
20
20
  raise "You *must* specify --out FILE for the pdf formatter" unless File === io
21
21
 
22
22
  if(options[:dry_run])
@@ -53,41 +53,12 @@ module Cucumber
53
53
  end
54
54
  end
55
55
 
56
- def keep_with(&block)
57
- @buffer << block
58
- end
59
-
60
- def render(doc)
61
- @doc = doc
62
- @buffer.each do |proc|
63
- proc.call
64
- end
65
- end
66
-
67
- # This method does a 'test' rendering on a blank page, to see the rendered height of the buffer
68
- # if that too high for the space left on the age in the real document, we do a page break.
69
- # This obviously doesn't work if a scenario is longer than a whole page (God forbid)
70
- def flush
71
- @scrap.start_new_page
72
- oldy = @scrap.y
73
- render @scrap
74
- height = (oldy - @scrap.y) + 36 # whops magic number
75
- if ((@pdf.y - height) < @pdf.bounds.bottom)
76
- @pdf.start_new_page
77
- end
78
- render @pdf
79
- @pdf.move_down(20)
80
- @buffer = []
81
- end
82
-
83
- # regular visitor entries
84
- def visit_features(features)
85
- super
56
+ def after_features(features)
86
57
  @pdf.render_file(@io.path)
87
58
  puts "\ndone"
88
59
  end
89
60
 
90
- def visit_feature_name(name)
61
+ def feature_name(name)
91
62
  @pdf.start_new_page
92
63
  name["Feature:"] = "" if name["Feature:"]
93
64
  names = name.split("\n")
@@ -106,18 +77,19 @@ module Cucumber
106
77
  @pdf.move_down(30)
107
78
  end
108
79
 
109
- def visit_feature_element(feature_element)
80
+ def before_feature_element(feature_element)
110
81
  record_tag_occurrences(feature_element, @options)
111
- super
82
+ end
83
+
84
+ def after_feature_element(feature_element)
112
85
  flush
113
86
  end
114
87
 
115
- def visit_feature(feature)
116
- super
88
+ def after_feature(feature)
117
89
  flush
118
90
  end
119
91
 
120
- def visit_feature_element_name(keyword, name)
92
+ def feature_element_name(keyword, name)
121
93
  names = name.empty? ? [name] : name.split("\n")
122
94
  print "."
123
95
  STDOUT.flush
@@ -133,53 +105,55 @@ module Cucumber
133
105
  end
134
106
  end
135
107
 
136
- def visit_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
108
+ def step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
109
+ @hide_this_step = false
137
110
  if exception
138
- return if @exceptions.index(exception)
111
+ if @exceptions.include?(exception)
112
+ @hide_this_step = true
113
+ return
114
+ end
139
115
  @exceptions << exception
140
116
  end
141
- return if status != :failed && @in_background ^ background
142
- @status = status
143
- super
144
- end
145
-
146
- def colorize(text, status)
147
- keep_with do
148
- @doc.fill_color(@status_colors[status] || BLACK)
149
- @doc.text(text)
150
- @doc.fill_color(BLACK)
117
+ if status != :failed && @in_background ^ background
118
+ @hide_this_step = true
119
+ return
151
120
  end
152
121
  end
153
122
 
154
- def visit_step_name(keyword, step_match, status, source_indent, background)
123
+ def step_name(keyword, step_match, status, source_indent, background)
124
+ return if @hide_this_step
155
125
  line = "<b>#{keyword}</b> #{step_match.format_args("%s").gsub('<', '&lt;').gsub('>', '&gt;')}"
156
126
  colorize(line, status)
157
127
  end
158
128
 
159
- def visit_background(background)
129
+ def before_background(background)
160
130
  @in_background = true
161
- super
131
+ end
132
+
133
+ def after_background(background)
162
134
  @in_background = nil
163
135
  end
164
136
 
165
- def visit_multiline_arg(table)
137
+ def before_multiline_arg(table)
138
+ return if @hide_this_step
166
139
  if(table.kind_of? Cucumber::Ast::Table)
167
140
  keep_with do
168
141
  @doc.table(table.rows << table.headers , :position => :center, :row_colors => ['ffffff', 'f0f0f0'])
169
142
  end
170
143
  end
171
- super
172
144
  end
173
145
 
174
146
  #using row_color hack to highlight each row correctly
175
- def visit_outline_table(table)
147
+ def before_outline_table(table)
148
+ return if @hide_this_step
176
149
  row_colors = table.example_rows.map { |r| @status_colors[r.status] unless r.status == :skipped}
177
150
  keep_with do
178
151
  @doc.table(table.rows, :headers => table.headers, :position => :center, :row_colors => row_colors)
179
152
  end
180
153
  end
181
154
 
182
- def visit_py_string(string)
155
+ def before_py_string(string)
156
+ return if @hide_this_step
183
157
  s = %{"""\n#{string}\n"""}.indent(10)
184
158
  s = s.split("\n").map{|l| l =~ /^\s+$/ ? '' : l}
185
159
  s.each do |line|
@@ -189,28 +163,59 @@ module Cucumber
189
163
  end
190
164
  end
191
165
 
192
- def visit_comment(comment)
193
- comment.accept(self)
166
+ def tag_name(tag_name)
167
+ return if @hide_this_step
168
+ tag = format_string(tag_name, :tag).indent(@indent)
169
+ # TODO should we render tags at all? skipped for now. difficult to place due to page breaks
194
170
  end
195
171
 
196
- def visit_comment_line(comment_line)
172
+ def background_name(keyword, name, file_colon_line, source_indent)
173
+ feature_element_name(keyword, name)
197
174
  end
198
175
 
199
- def visit_tag_name(tag_name)
200
- tag = format_string(tag_name, :tag).indent(@indent)
201
- # TODO should we render tags at all? skipped for now. difficult to place due to page breaks
176
+ def examples_name(keyword, name)
177
+ feature_element_name(keyword, name)
202
178
  end
203
179
 
204
- def visit_background_name(keyword, name, file_colon_line, source_indent)
205
- visit_feature_element_name(keyword, name)
180
+ def scenario_name(keyword, name, file_colon_line, source_indent)
181
+ feature_element_name(keyword, name)
182
+ end
183
+
184
+ private
185
+
186
+ def colorize(text, status)
187
+ keep_with do
188
+ @doc.fill_color(@status_colors[status] || BLACK)
189
+ @doc.text(text)
190
+ @doc.fill_color(BLACK)
191
+ end
192
+ end
193
+
194
+ def keep_with(&block)
195
+ @buffer << block
206
196
  end
207
197
 
208
- def visit_examples_name(keyword, name)
209
- visit_feature_element_name(keyword, name)
198
+ def render(doc)
199
+ @doc = doc
200
+ @buffer.each do |proc|
201
+ proc.call
202
+ end
210
203
  end
211
204
 
212
- def visit_scenario_name(keyword, name, file_colon_line, source_indent)
213
- visit_feature_element_name(keyword, name)
205
+ # This method does a 'test' rendering on a blank page, to see the rendered height of the buffer
206
+ # if that too high for the space left on the age in the real document, we do a page break.
207
+ # This obviously doesn't work if a scenario is longer than a whole page (God forbid)
208
+ def flush
209
+ @scrap.start_new_page
210
+ oldy = @scrap.y
211
+ render @scrap
212
+ height = (oldy - @scrap.y) + 36 # whops magic number
213
+ if ((@pdf.y - height) < @pdf.bounds.bottom)
214
+ @pdf.start_new_page
215
+ end
216
+ render @pdf
217
+ @pdf.move_down(20)
218
+ @buffer = []
214
219
  end
215
220
  end
216
221
  end
@@ -10,191 +10,192 @@ module Cucumber
10
10
  #
11
11
  # If the output is STDOUT (and not a file), there are bright colours to watch too.
12
12
  #
13
- class Pretty < Ast::Visitor
13
+ class Pretty
14
14
  include FileUtils
15
15
  include Console
16
16
  attr_writer :indent
17
+ attr_reader :step_mother
17
18
 
18
19
  def initialize(step_mother, io, options)
19
- super(step_mother)
20
- @io = io
21
- @options = options
20
+ @step_mother, @io, @options = step_mother, io, options
22
21
  @exceptions = []
23
22
  @indent = 0
24
23
  @prefixes = options[:prefixes] || {}
25
24
  end
26
25
 
27
- def visit_features(features)
28
- super
26
+ def after_features(features)
29
27
  print_summary(features) unless @options[:autoformat]
30
28
  end
31
29
 
32
- def visit_feature(feature)
30
+ def before_feature(feature)
33
31
  @exceptions = []
34
32
  @indent = 0
35
33
  if @options[:autoformat]
36
34
  file = File.join(@options[:autoformat], feature.file)
37
35
  dir = File.dirname(file)
38
36
  mkdir_p(dir) unless File.directory?(dir)
39
- File.open(file, Cucumber.file_mode('w')) do |io|
40
- @io = io
41
- super
42
- end
43
- else
44
- super
37
+ @io = File.open(file, Cucumber.file_mode('w'))
45
38
  end
46
39
  end
47
-
48
- def visit_comment(comment)
49
- comment.accept(self)
40
+
41
+ def after_feature(*args)
42
+ @io.close if @options[:autoformat]
50
43
  end
51
44
 
52
- def visit_comment_line(comment_line)
45
+ def comment_line(comment_line)
53
46
  @io.puts(comment_line.indent(@indent))
54
47
  @io.flush
55
48
  end
56
49
 
57
- def visit_tags(tags)
58
- tags.accept(self)
50
+ def after_tags(tags)
59
51
  if @indent == 1
60
52
  @io.puts
61
53
  @io.flush
62
54
  end
63
55
  end
64
56
 
65
- def visit_tag_name(tag_name)
57
+ def tag_name(tag_name)
66
58
  tag = format_string(tag_name, :tag).indent(@indent)
67
59
  @io.print(tag)
68
60
  @io.flush
69
61
  @indent = 1
70
62
  end
71
63
 
72
- def visit_feature_name(name)
64
+ def feature_name(name)
73
65
  @io.puts(name)
74
66
  @io.puts
75
67
  @io.flush
76
68
  end
77
69
 
78
- def visit_feature_element(feature_element)
70
+ def before_feature_element(feature_element)
79
71
  record_tag_occurrences(feature_element, @options)
80
72
  @indent = 2
81
73
  @scenario_indent = 2
82
- super
74
+ end
75
+
76
+ def after_feature_element(feature_element)
83
77
  @io.puts
84
78
  @io.flush
85
79
  end
86
80
 
87
- def visit_background(background)
81
+ def before_background(background)
88
82
  @indent = 2
89
83
  @scenario_indent = 2
90
84
  @in_background = true
91
- super
85
+ end
86
+
87
+ def after_background(background)
92
88
  @in_background = nil
93
89
  @io.puts
94
90
  @io.flush
95
91
  end
96
92
 
97
- def visit_background_name(keyword, name, file_colon_line, source_indent)
98
- visit_feature_element_name(keyword, name, file_colon_line, source_indent)
93
+ def background_name(keyword, name, file_colon_line, source_indent)
94
+ print_feature_element_name(keyword, name, file_colon_line, source_indent)
99
95
  end
100
96
 
101
- def visit_examples_array(examples_array)
97
+ def before_examples_array(examples_array)
102
98
  @indent = 4
103
99
  @io.puts
104
- examples_array[0..-2].each { |ea| super(ea) }
105
- @last_example = true
106
- super(examples_array.last)
107
- @last_example = nil
100
+ @visiting_first_example_name = true
108
101
  end
109
102
 
110
- def visit_examples_name(keyword, name)
111
- names = name.strip.empty? ? [name.strip] : name.split("\n")
103
+ def examples_name(keyword, name)
104
+ puts unless @visiting_first_example_name
105
+ @visiting_first_example_name = false
106
+ names = name.strip.empty? ? [name.strip] : name.split("\n")
112
107
  @io.puts(" #{keyword} #{names[0]}")
113
108
  names[1..-1].each {|s| @io.puts " #{s}" } unless names.empty?
114
109
  @io.flush
115
110
  @indent = 6
116
111
  @scenario_indent = 6
117
112
  end
113
+
114
+ def before_outline_table(outline_table)
115
+ @table = outline_table
116
+ end
118
117
 
119
- def visit_outline_table(outline_table)
120
- super
118
+ def after_outline_table(outline_table)
119
+ @table = nil
121
120
  @indent = 4
122
- @io.puts unless @last_example
123
121
  end
124
122
 
125
- def visit_scenario_name(keyword, name, file_colon_line, source_indent)
126
- visit_feature_element_name(keyword, name, file_colon_line, source_indent)
127
- end
128
-
129
- def visit_feature_element_name(keyword, name, file_colon_line, source_indent)
130
- @io.puts if @scenario_indent == 6
131
- names = name.empty? ? [name] : name.split("\n")
132
- line = "#{keyword} #{names[0]}".indent(@scenario_indent)
133
- @io.print(line)
134
- if @options[:source]
135
- line_comment = " # #{file_colon_line}".indent(source_indent)
136
- @io.print(format_string(line_comment, :comment))
137
- end
138
- @io.puts
139
- names[1..-1].each {|s| @io.puts " #{s}"}
140
- @io.flush
123
+ def scenario_name(keyword, name, file_colon_line, source_indent)
124
+ print_feature_element_name keyword, name, file_colon_line, source_indent
141
125
  end
142
126
 
143
- def visit_step(step)
127
+ def before_step(step)
128
+ @current_step = step
144
129
  @indent = 6
145
- super
146
130
  end
147
131
 
148
- def visit_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
132
+ def before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
133
+ @hide_this_step = false
149
134
  if exception
150
- return if @exceptions.index(exception)
135
+ if @exceptions.include?(exception)
136
+ @hide_this_step = true
137
+ return
138
+ end
151
139
  @exceptions << exception
152
140
  end
153
- return if status != :failed && @in_background ^ background
141
+ if status != :failed && @in_background ^ background
142
+ @hide_this_step = true
143
+ return
144
+ end
154
145
  @status = status
155
- super
156
146
  end
157
147
 
158
- def visit_step_name(keyword, step_match, status, source_indent, background)
148
+ def step_name(keyword, step_match, status, source_indent, background)
149
+ return if @hide_this_step
159
150
  source_indent = nil unless @options[:source]
160
151
  formatted_step_name = format_step(keyword, step_match, status, source_indent)
161
152
  @io.puts(formatted_step_name.indent(@scenario_indent + 2))
162
153
  end
163
154
 
164
- def visit_multiline_arg(multiline_arg)
165
- return if @options[:no_multiline]
166
- @table = multiline_arg
167
- super
155
+ def py_string(string)
156
+ return if @hide_this_step
157
+ s = %{"""\n#{string}\n"""}.indent(@indent)
158
+ s = s.split("\n").map{|l| l =~ /^\s+$/ ? '' : l}.join("\n")
159
+ @io.puts(format_string(s, @current_step.status))
160
+ @io.flush
168
161
  end
169
162
 
170
- def visit_exception(exception, status)
163
+ def exception(exception, status)
164
+ return if @hide_this_step
171
165
  print_exception(exception, status, @indent)
172
166
  @io.flush
173
167
  end
174
168
 
175
- def visit_table_row(table_row)
169
+ def before_multiline_arg(multiline_arg)
170
+ return if @options[:no_multiline] || @hide_this_step
171
+ @table = multiline_arg
172
+ end
173
+
174
+ def after_multiline_arg(multiline_arg)
175
+ @table = nil
176
+ end
177
+
178
+ def before_table_row(table_row)
179
+ return unless @table
176
180
  @col_index = 0
177
181
  @io.print ' |'.indent(@indent-2)
178
- super
182
+ end
183
+
184
+ def after_table_row(table_row)
185
+ return unless @table
179
186
  @io.puts
180
- if table_row.exception && !@exceptions.index(table_row.exception)
187
+ if table_row.exception && !@exceptions.include?(table_row.exception)
181
188
  print_exception(table_row.exception, :failed, @indent)
182
189
  end
183
190
  end
184
191
 
185
- def visit_py_string(string)
186
- s = %{"""\n#{string}\n"""}.indent(@indent)
187
- s = s.split("\n").map{|l| l =~ /^\s+$/ ? '' : l}.join("\n")
188
- @io.puts(format_string(s, @status))
189
- @io.flush
190
- end
191
-
192
- def visit_table_cell(cell)
193
- super
192
+ def after_table_cell(cell)
193
+ return unless @table
194
194
  @col_index += 1
195
195
  end
196
196
 
197
- def visit_table_cell_value(value, status)
197
+ def table_cell_value(value, status)
198
+ return unless @table
198
199
  status ||= @status || :passed
199
200
  width = @table.col_width(@col_index)
200
201
  cell_text = value.to_s || ''
@@ -205,6 +206,20 @@ module Cucumber
205
206
  end
206
207
 
207
208
  private
209
+
210
+ def print_feature_element_name(keyword, name, file_colon_line, source_indent)
211
+ @io.puts if @scenario_indent == 6
212
+ names = name.empty? ? [name] : name.split("\n")
213
+ line = "#{keyword} #{names[0]}".indent(@scenario_indent)
214
+ @io.print(line)
215
+ if @options[:source]
216
+ line_comment = " # #{file_colon_line}".indent(source_indent)
217
+ @io.print(format_string(line_comment, :comment))
218
+ end
219
+ @io.puts
220
+ names[1..-1].each {|s| @io.puts " #{s}"}
221
+ @io.flush
222
+ end
208
223
 
209
224
  def cell_prefix(status)
210
225
  @prefixes[status]