aslakhellesoy-cucumber 0.3.102.2 → 0.3.103
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +5 -2
- data/Manifest.txt +2 -0
- data/examples/self_test/features/sample.feature +1 -1
- data/examples/self_test/features/search_sample.feature +1 -1
- data/features/custom_formatter.feature +4 -4
- data/lib/cucumber/ast.rb +1 -0
- data/lib/cucumber/ast/table.rb +4 -4
- data/lib/cucumber/ast/visitor.rb +2 -106
- data/lib/cucumber/cli/configuration.rb +28 -28
- data/lib/cucumber/cli/language_help_formatter.rb +5 -7
- data/lib/cucumber/cli/main.rb +3 -3
- data/lib/cucumber/formatter/html.rb +203 -113
- data/lib/cucumber/formatter/junit.rb +29 -23
- data/lib/cucumber/formatter/pdf.rb +74 -69
- data/lib/cucumber/formatter/pretty.rb +93 -78
- data/lib/cucumber/formatter/profile.rb +2 -2
- data/lib/cucumber/formatter/progress.rb +16 -10
- data/lib/cucumber/formatter/rerun.rb +4 -5
- data/lib/cucumber/formatter/steps.rb +2 -3
- data/lib/cucumber/formatter/tag_cloud.rb +7 -6
- data/lib/cucumber/formatter/usage.rb +4 -7
- data/lib/cucumber/version.rb +2 -2
- data/spec/cucumber/ast/background_spec.rb +1 -2
- data/spec/cucumber/ast/scenario_outline_spec.rb +3 -2
- data/spec/cucumber/ast/scenario_spec.rb +1 -1
- data/spec/cucumber/formatter/html_spec.rb +221 -2
- data/spec/cucumber/formatter/progress_spec.rb +9 -4
- data/spec/cucumber/parser/feature_parser_spec.rb +31 -27
- metadata +1 -1
data/History.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
==
|
1
|
+
== 2009-09-24
|
2
2
|
|
3
3
|
This release gives you back some of the control over the Rails environment that was accidentally taken away from you in the
|
4
4
|
previous release.
|
@@ -6,13 +6,16 @@ previous release.
|
|
6
6
|
Using this release on a Rails project requires a rerun of script/generate cucumber.
|
7
7
|
|
8
8
|
=== New Features
|
9
|
-
* Added a new @no-txn tag to selectively turn off transactions for a
|
9
|
+
* Added a new @no-txn tag to selectively turn off transactions for a particlular scenario.
|
10
10
|
* Added back a way to globally turn off transactions.
|
11
11
|
* Renamed @allow_rescue tag to @allow-rescue.
|
12
12
|
|
13
13
|
=== Bugfixes
|
14
14
|
* Gracefully handle cases when optional regexp groups are not matched. Ex: /should( not)? be flashed '([^']*?)'$/ (Aslak Hellesøy)
|
15
15
|
|
16
|
+
=== Changed Features
|
17
|
+
* The Formatter API has completely changed. Formatters are no longer a double-dispacth visitor - just a single-dispatch listener (#438 Matt Wynne)
|
18
|
+
|
16
19
|
== 2009-09-22
|
17
20
|
|
18
21
|
This release has some changes in the Rails support, so make sure you run "script/generate cucumber" after you upgrade.
|
data/Manifest.txt
CHANGED
@@ -329,6 +329,7 @@ lib/cucumber/ast/step_collection.rb
|
|
329
329
|
lib/cucumber/ast/step_invocation.rb
|
330
330
|
lib/cucumber/ast/table.rb
|
331
331
|
lib/cucumber/ast/tags.rb
|
332
|
+
lib/cucumber/ast/tree_walker.rb
|
332
333
|
lib/cucumber/ast/visitor.rb
|
333
334
|
lib/cucumber/broadcaster.rb
|
334
335
|
lib/cucumber/cli/configuration.rb
|
@@ -421,6 +422,7 @@ spec/cucumber/ast/scenario_spec.rb
|
|
421
422
|
spec/cucumber/ast/step_collection_spec.rb
|
422
423
|
spec/cucumber/ast/step_spec.rb
|
423
424
|
spec/cucumber/ast/table_spec.rb
|
425
|
+
spec/cucumber/ast/tree_walker_spec.rb
|
424
426
|
spec/cucumber/broadcaster_spec.rb
|
425
427
|
spec/cucumber/cli/configuration_spec.rb
|
426
428
|
spec/cucumber/cli/drb_client_spec.rb
|
@@ -8,7 +8,7 @@ Feature: Custom Formatter
|
|
8
8
|
| 1 | 1 | 1 | 1 | 1 | 2 | 1 | 2 | 1 | 2 | 1 |
|
9
9
|
|
10
10
|
"""
|
11
|
-
|
11
|
+
|
12
12
|
Scenario: my own formatter
|
13
13
|
Given a standard Cucumber project directory structure
|
14
14
|
And a file named "features/f.feature" with:
|
@@ -25,13 +25,13 @@ Feature: Custom Formatter
|
|
25
25
|
And a file named "features/support/ze/formator.rb" with:
|
26
26
|
"""
|
27
27
|
module Ze
|
28
|
-
class Formator
|
28
|
+
class Formator
|
29
29
|
def initialize(step_mother, io, options)
|
30
|
-
|
30
|
+
@step_mother = step_mother
|
31
31
|
@io = io
|
32
32
|
end
|
33
33
|
|
34
|
-
def
|
34
|
+
def scenario_name(keyword, name, file_colon_line, source_indent)
|
35
35
|
@io.puts "$ #{name.upcase}"
|
36
36
|
end
|
37
37
|
end
|
data/lib/cucumber/ast.rb
CHANGED
@@ -13,6 +13,7 @@ require 'cucumber/ast/py_string'
|
|
13
13
|
require 'cucumber/ast/outline_table'
|
14
14
|
require 'cucumber/ast/examples'
|
15
15
|
require 'cucumber/ast/visitor'
|
16
|
+
require 'cucumber/ast/tree_walker'
|
16
17
|
|
17
18
|
module Cucumber
|
18
19
|
# Classes in this module represent the Abstract Syntax Tree (AST)
|
data/lib/cucumber/ast/table.rb
CHANGED
@@ -389,11 +389,11 @@ module Cucumber
|
|
389
389
|
|
390
390
|
c = Term::ANSIColor.coloring?
|
391
391
|
Term::ANSIColor.coloring = options[:color]
|
392
|
-
|
393
|
-
|
394
|
-
|
392
|
+
formatter = Formatter::Pretty.new(nil, io, options)
|
393
|
+
formatter.instance_variable_set('@indent', options[:indent])
|
394
|
+
TreeWalker.new(nil, [formatter]).visit_multiline_arg(self)
|
395
|
+
|
395
396
|
Term::ANSIColor.coloring = c
|
396
|
-
|
397
397
|
io.rewind
|
398
398
|
s = "\n" + io.read + (" " * (options[:indent] - 2))
|
399
399
|
s
|
data/lib/cucumber/ast/visitor.rb
CHANGED
@@ -1,115 +1,11 @@
|
|
1
1
|
module Cucumber
|
2
2
|
module Ast
|
3
|
-
# Base class for formatters. This class just walks the tree depth first.
|
4
|
-
# Just override the methods you care about. Remember to call super if you
|
5
|
-
# override a method.
|
6
3
|
class Visitor
|
7
|
-
|
8
|
-
attr_reader :step_mother #:nodoc:
|
4
|
+
DEPRECATION_WARNING = "Cucumber::Ast::Visitor is deprecated and will be removed. You no longer need to inherit from this class."
|
9
5
|
|
10
6
|
def initialize(step_mother)
|
11
|
-
|
12
|
-
@step_mother = step_mother
|
7
|
+
raise(DEPRECATION_WARNING)
|
13
8
|
end
|
14
|
-
|
15
|
-
def visit_features(features)
|
16
|
-
features.accept(self)
|
17
|
-
end
|
18
|
-
|
19
|
-
def visit_feature(feature)
|
20
|
-
feature.accept(self)
|
21
|
-
end
|
22
|
-
|
23
|
-
def visit_comment(comment)
|
24
|
-
comment.accept(self)
|
25
|
-
end
|
26
|
-
|
27
|
-
def visit_comment_line(comment_line)
|
28
|
-
end
|
29
|
-
|
30
|
-
def visit_tags(tags)
|
31
|
-
tags.accept(self)
|
32
|
-
end
|
33
|
-
|
34
|
-
def visit_tag_name(tag_name)
|
35
|
-
end
|
36
|
-
|
37
|
-
def visit_feature_name(name)
|
38
|
-
end
|
39
|
-
|
40
|
-
# +feature_element+ is either Scenario or ScenarioOutline
|
41
|
-
def visit_feature_element(feature_element)
|
42
|
-
feature_element.accept(self)
|
43
|
-
end
|
44
|
-
|
45
|
-
def visit_background(background)
|
46
|
-
background.accept(self)
|
47
|
-
end
|
48
|
-
|
49
|
-
def visit_background_name(keyword, name, file_colon_line, source_indent)
|
50
|
-
end
|
51
|
-
|
52
|
-
def visit_examples_array(examples_array)
|
53
|
-
examples_array.accept(self)
|
54
|
-
end
|
55
|
-
|
56
|
-
def visit_examples(examples)
|
57
|
-
examples.accept(self)
|
58
|
-
end
|
59
|
-
|
60
|
-
def visit_examples_name(keyword, name)
|
61
|
-
end
|
62
|
-
|
63
|
-
def visit_outline_table(outline_table)
|
64
|
-
@table = outline_table
|
65
|
-
outline_table.accept(self)
|
66
|
-
end
|
67
|
-
|
68
|
-
def visit_scenario_name(keyword, name, file_colon_line, source_indent)
|
69
|
-
end
|
70
|
-
|
71
|
-
def visit_steps(steps)
|
72
|
-
steps.accept(self)
|
73
|
-
end
|
74
|
-
|
75
|
-
def visit_step(step)
|
76
|
-
step.accept(self)
|
77
|
-
end
|
78
|
-
|
79
|
-
def visit_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
|
80
|
-
visit_step_name(keyword, step_match, status, source_indent, background)
|
81
|
-
visit_multiline_arg(multiline_arg) if multiline_arg
|
82
|
-
visit_exception(exception, status) if exception
|
83
|
-
end
|
84
|
-
|
85
|
-
def visit_step_name(keyword, step_match, status, source_indent, background) #:nodoc:
|
86
|
-
end
|
87
|
-
|
88
|
-
def visit_multiline_arg(multiline_arg) #:nodoc:
|
89
|
-
multiline_arg.accept(self)
|
90
|
-
end
|
91
|
-
|
92
|
-
def visit_exception(exception, status) #:nodoc:
|
93
|
-
end
|
94
|
-
|
95
|
-
def visit_py_string(string)
|
96
|
-
end
|
97
|
-
|
98
|
-
def visit_table_row(table_row)
|
99
|
-
table_row.accept(self)
|
100
|
-
end
|
101
|
-
|
102
|
-
def visit_table_cell(table_cell)
|
103
|
-
table_cell.accept(self)
|
104
|
-
end
|
105
|
-
|
106
|
-
def visit_table_cell_value(value, status)
|
107
|
-
end
|
108
|
-
|
109
|
-
# Print +announcement+. This method can be called from within StepDefinitions.
|
110
|
-
def announce(announcement)
|
111
|
-
end
|
112
|
-
|
113
9
|
end
|
114
10
|
end
|
115
11
|
end
|
@@ -57,34 +57,9 @@ module Cucumber
|
|
57
57
|
def drb_port
|
58
58
|
@options[:drb_port].to_i if @options[:drb_port]
|
59
59
|
end
|
60
|
-
|
61
|
-
def
|
62
|
-
|
63
|
-
formatters = @options[:formats].map do |format_and_out|
|
64
|
-
format = format_and_out[0]
|
65
|
-
out = format_and_out[1]
|
66
|
-
if String === out # file name
|
67
|
-
unless File.directory?(out)
|
68
|
-
out = File.open(out, Cucumber.file_mode('w'))
|
69
|
-
at_exit do
|
70
|
-
out.flush
|
71
|
-
out.close
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
begin
|
77
|
-
formatter_class = formatter_class(format)
|
78
|
-
formatter_class.new(step_mother, out, @options)
|
79
|
-
rescue Exception => e
|
80
|
-
e.message << "\nError creating formatter: #{format}"
|
81
|
-
raise e
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
broadcaster = Broadcaster.new(formatters)
|
86
|
-
broadcaster.options = @options
|
87
|
-
return broadcaster
|
60
|
+
|
61
|
+
def build_runner(step_mother, io)
|
62
|
+
Ast::TreeWalker.new(step_mother, formatters(step_mother), @options, io)
|
88
63
|
end
|
89
64
|
|
90
65
|
def formatter_class(format)
|
@@ -150,6 +125,31 @@ module Cucumber
|
|
150
125
|
end
|
151
126
|
|
152
127
|
private
|
128
|
+
|
129
|
+
def formatters(step_mother)
|
130
|
+
return [Formatter::Pretty.new(step_mother, nil, @options)] if @options[:autoformat]
|
131
|
+
@options[:formats].map do |format_and_out|
|
132
|
+
format = format_and_out[0]
|
133
|
+
out = format_and_out[1]
|
134
|
+
if String === out # file name
|
135
|
+
unless File.directory?(out)
|
136
|
+
out = File.open(out, Cucumber.file_mode('w'))
|
137
|
+
at_exit do
|
138
|
+
out.flush
|
139
|
+
out.close
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
begin
|
145
|
+
formatter_class = formatter_class(format)
|
146
|
+
formatter_class.new(step_mother, out, @options)
|
147
|
+
rescue Exception => e
|
148
|
+
e.message << "\nError creating formatter: #{format}"
|
149
|
+
raise e
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
153
|
|
154
154
|
class LogFormatter < ::Logger::Formatter
|
155
155
|
def call(severity, time, progname, msg)
|
@@ -19,7 +19,8 @@ http://wiki.github.com/aslakhellesoy/cucumber/spoken-languages
|
|
19
19
|
[lang, Cucumber::LANGUAGES[lang]['name'], Cucumber::LANGUAGES[lang]['native']]
|
20
20
|
end
|
21
21
|
table = Ast::Table.new(raw)
|
22
|
-
new(nil, io, {:check_lang=>true})
|
22
|
+
formatter = new(nil, io, {:check_lang=>true})
|
23
|
+
Ast::TreeWalker.new(nil, [formatter]).visit_multiline_arg(table)
|
23
24
|
end
|
24
25
|
|
25
26
|
def self.list_keywords(io, lang)
|
@@ -31,19 +32,17 @@ http://wiki.github.com/aslakhellesoy/cucumber/spoken-languages
|
|
31
32
|
new(nil, io, {:incomplete => language.incomplete?}).visit_multiline_arg(table)
|
32
33
|
end
|
33
34
|
|
34
|
-
def
|
35
|
+
def before_visit_multiline_arg(table)
|
35
36
|
if @options[:incomplete]
|
36
37
|
@io.puts(format_string(INCOMPLETE, :failed))
|
37
38
|
end
|
38
|
-
super
|
39
39
|
end
|
40
40
|
|
41
|
-
def
|
41
|
+
def before_visit_table_row(table_row)
|
42
42
|
@col = 1
|
43
|
-
super
|
44
43
|
end
|
45
44
|
|
46
|
-
def
|
45
|
+
def before_visit_table_cell_value(value, status)
|
47
46
|
if @col == 1
|
48
47
|
if(@options[:check_lang])
|
49
48
|
@incomplete = Parser::NaturalLanguage.get(nil, value).incomplete?
|
@@ -54,7 +53,6 @@ http://wiki.github.com/aslakhellesoy/cucumber/spoken-languages
|
|
54
53
|
end
|
55
54
|
|
56
55
|
@col += 1
|
57
|
-
super(value, status)
|
58
56
|
end
|
59
57
|
end
|
60
58
|
end
|
data/lib/cucumber/cli/main.rb
CHANGED
@@ -50,9 +50,9 @@ module Cucumber
|
|
50
50
|
|
51
51
|
enable_diffing
|
52
52
|
|
53
|
-
|
54
|
-
step_mother.visitor =
|
55
|
-
|
53
|
+
runner = configuration.build_runner(step_mother, @out_stream)
|
54
|
+
step_mother.visitor = runner # Needed to support World#announce
|
55
|
+
runner.visit_features(features)
|
56
56
|
|
57
57
|
failure = if exceeded_tag_limts?(features)
|
58
58
|
FAILURE
|
@@ -1,214 +1,278 @@
|
|
1
1
|
require 'cucumber/formatter/ordered_xml_markup'
|
2
2
|
require 'cucumber/formatter/duration'
|
3
|
+
require 'xml'
|
4
|
+
require 'ruby-debug'
|
3
5
|
|
4
6
|
module Cucumber
|
5
7
|
module Formatter
|
6
8
|
# The formatter used for <tt>--format html</tt>
|
7
|
-
class Html
|
9
|
+
class Html
|
8
10
|
include ERB::Util # for the #h method
|
9
11
|
include Duration
|
10
12
|
|
11
13
|
def initialize(step_mother, io, options)
|
12
|
-
|
14
|
+
@io = io
|
13
15
|
@options = options
|
14
|
-
@
|
16
|
+
@buffer = {}
|
17
|
+
@current_builder = create_builder(@io)
|
15
18
|
end
|
16
19
|
|
17
|
-
def
|
18
|
-
|
20
|
+
def before_features(features)
|
21
|
+
start_buffering :features
|
19
22
|
end
|
20
23
|
|
21
|
-
def
|
24
|
+
def after_features(features)
|
25
|
+
stop_buffering :features
|
22
26
|
# <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
23
|
-
|
27
|
+
builder.declare!(
|
24
28
|
:DOCTYPE,
|
25
29
|
:html,
|
26
30
|
:PUBLIC,
|
27
31
|
'-//W3C//DTD XHTML 1.0 Strict//EN',
|
28
32
|
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'
|
29
33
|
)
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
+
builder.html(:xmlns => 'http://www.w3.org/1999/xhtml') do
|
35
|
+
builder.head do
|
36
|
+
builder.meta(:content => 'text/html;charset=utf-8')
|
37
|
+
builder.title 'Cucumber'
|
34
38
|
inline_css
|
35
39
|
end
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
+
builder.body do
|
41
|
+
builder.div(:class => 'cucumber') do
|
42
|
+
builder << buffer(:features)
|
43
|
+
builder.div(format_duration(features.duration), :class => 'duration')
|
40
44
|
end
|
41
45
|
end
|
42
46
|
end
|
43
47
|
end
|
44
|
-
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
+
|
49
|
+
def before_feature(feature)
|
50
|
+
start_buffering :feature
|
51
|
+
@exceptions = []
|
52
|
+
end
|
53
|
+
|
54
|
+
def after_feature(feature)
|
55
|
+
stop_buffering :feature
|
56
|
+
builder.div(:class => 'feature') do
|
57
|
+
builder << buffer(:feature)
|
48
58
|
end
|
49
59
|
end
|
50
60
|
|
51
|
-
def
|
52
|
-
|
53
|
-
@builder.br
|
61
|
+
def before_comment(comment)
|
62
|
+
start_buffering :comment
|
54
63
|
end
|
55
64
|
|
56
|
-
def
|
57
|
-
|
58
|
-
|
59
|
-
|
65
|
+
def after_comment(comment)
|
66
|
+
stop_buffering :comment
|
67
|
+
builder.pre(:class => 'comment') do
|
68
|
+
builder << buffer(:comment)
|
60
69
|
end
|
61
70
|
end
|
62
71
|
|
63
|
-
def
|
64
|
-
|
72
|
+
def comment_line(comment_line)
|
73
|
+
builder.text!(comment_line)
|
74
|
+
builder.br
|
75
|
+
end
|
76
|
+
|
77
|
+
def after_tags(tags)
|
65
78
|
@tag_spacer = nil
|
66
79
|
end
|
67
|
-
|
68
|
-
def
|
69
|
-
|
80
|
+
|
81
|
+
def tag_name(tag_name)
|
82
|
+
builder.text!(@tag_spacer) if @tag_spacer
|
70
83
|
@tag_spacer = ' '
|
71
|
-
|
84
|
+
builder.span(tag_name, :class => 'tag')
|
72
85
|
end
|
73
86
|
|
74
|
-
def
|
87
|
+
def feature_name(name)
|
75
88
|
lines = name.split(/\r?\n/)
|
76
89
|
return if lines.empty?
|
77
|
-
|
78
|
-
|
90
|
+
builder.h2 do |h2|
|
91
|
+
builder.span(lines[0], :class => 'val')
|
79
92
|
end
|
80
|
-
|
93
|
+
builder.p(:class => 'narrative') do
|
81
94
|
lines[1..-1].each do |line|
|
82
|
-
|
83
|
-
|
95
|
+
builder.text!(line.strip)
|
96
|
+
builder.br
|
84
97
|
end
|
85
98
|
end
|
86
99
|
end
|
87
100
|
|
88
|
-
def
|
89
|
-
@
|
90
|
-
|
91
|
-
|
92
|
-
|
101
|
+
def before_background(background)
|
102
|
+
@in_background = true
|
103
|
+
start_buffering :background
|
104
|
+
end
|
105
|
+
|
106
|
+
def after_background(background)
|
107
|
+
stop_buffering :background
|
108
|
+
@in_background = nil
|
109
|
+
builder.div(:class => 'background') do
|
110
|
+
builder << buffer(:background)
|
93
111
|
end
|
94
112
|
end
|
95
113
|
|
96
|
-
def
|
114
|
+
def background_name(keyword, name, file_colon_line, source_indent)
|
97
115
|
@listing_background = true
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
116
|
+
builder.h3 do |h3|
|
117
|
+
builder.span(keyword, :class => 'keyword')
|
118
|
+
builder.text!(' ')
|
119
|
+
builder.span(name, :class => 'val')
|
102
120
|
end
|
103
121
|
end
|
104
122
|
|
105
|
-
def
|
123
|
+
def before_feature_element(feature_element)
|
124
|
+
start_buffering :feature_element
|
125
|
+
end
|
126
|
+
|
127
|
+
def after_feature_element(feature_element)
|
128
|
+
stop_buffering :feature_element
|
106
129
|
css_class = {
|
107
130
|
Ast::Scenario => 'scenario',
|
108
131
|
Ast::ScenarioOutline => 'scenario outline'
|
109
132
|
}[feature_element.class]
|
110
|
-
|
111
|
-
|
133
|
+
|
134
|
+
builder.div(:class => css_class) do
|
135
|
+
builder << buffer(:feature_element)
|
112
136
|
end
|
113
137
|
@open_step_list = true
|
114
138
|
end
|
115
|
-
|
116
|
-
def
|
139
|
+
|
140
|
+
def scenario_name(keyword, name, file_colon_line, source_indent)
|
117
141
|
@listing_background = false
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
142
|
+
builder.h3 do
|
143
|
+
builder.span(keyword, :class => 'keyword')
|
144
|
+
builder.text!(' ')
|
145
|
+
builder.span(name, :class => 'val')
|
122
146
|
end
|
123
147
|
end
|
124
|
-
|
125
|
-
def
|
148
|
+
|
149
|
+
def before_outline_table(outline_table)
|
126
150
|
@outline_row = 0
|
127
|
-
|
128
|
-
|
151
|
+
start_buffering :outline_table
|
152
|
+
end
|
153
|
+
|
154
|
+
def after_outline_table(outline_table)
|
155
|
+
stop_buffering :outline_table
|
156
|
+
builder.table do
|
157
|
+
builder << buffer(:outline_table)
|
129
158
|
end
|
130
159
|
@outline_row = nil
|
131
160
|
end
|
132
161
|
|
133
|
-
def
|
134
|
-
|
135
|
-
|
162
|
+
def before_examples(examples)
|
163
|
+
start_buffering :examples
|
164
|
+
end
|
165
|
+
|
166
|
+
def after_examples(examples)
|
167
|
+
stop_buffering :examples
|
168
|
+
builder.div(:class => 'examples') do
|
169
|
+
builder << buffer(:examples)
|
136
170
|
end
|
137
171
|
end
|
138
172
|
|
139
|
-
def
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
173
|
+
def examples_name(keyword, name)
|
174
|
+
builder.h4 do
|
175
|
+
builder.span(keyword, :class => 'keyword')
|
176
|
+
builder.text!(' ')
|
177
|
+
builder.span(name, :class => 'val')
|
144
178
|
end
|
145
179
|
end
|
146
180
|
|
147
|
-
def
|
148
|
-
|
149
|
-
|
181
|
+
def before_steps(steps)
|
182
|
+
start_buffering :steps
|
183
|
+
end
|
184
|
+
|
185
|
+
def after_steps(steps)
|
186
|
+
stop_buffering :steps
|
187
|
+
builder.ol do
|
188
|
+
builder << buffer(:steps)
|
150
189
|
end
|
151
190
|
end
|
152
|
-
|
153
|
-
def
|
191
|
+
|
192
|
+
def before_step(step)
|
154
193
|
@step_id = step.dom_id
|
155
|
-
super
|
156
194
|
end
|
157
195
|
|
158
|
-
def
|
196
|
+
def before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
|
197
|
+
start_buffering :step_result
|
198
|
+
@hide_this_step = false
|
159
199
|
if exception
|
160
|
-
|
200
|
+
if @exceptions.include?(exception)
|
201
|
+
@hide_this_step = true
|
202
|
+
return
|
203
|
+
end
|
161
204
|
@exceptions << exception
|
162
205
|
end
|
163
|
-
|
206
|
+
if status != :failed && @in_background ^ background
|
207
|
+
@hide_this_step = true
|
208
|
+
return
|
209
|
+
end
|
164
210
|
@status = status
|
165
|
-
|
166
|
-
|
211
|
+
end
|
212
|
+
|
213
|
+
def after_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
|
214
|
+
stop_buffering :step_result
|
215
|
+
return if @hide_this_step
|
216
|
+
builder.li(:id => @step_id, :class => "step #{status}") do
|
217
|
+
builder << buffer(:step_result)
|
167
218
|
end
|
168
219
|
end
|
169
220
|
|
170
|
-
def
|
221
|
+
def step_name(keyword, step_match, status, source_indent, background)
|
171
222
|
@step_matches ||= []
|
172
223
|
background_in_scenario = background && !@listing_background
|
173
224
|
@skip_step = @step_matches.index(step_match) || background_in_scenario
|
174
225
|
@step_matches << step_match
|
175
|
-
|
226
|
+
|
176
227
|
unless @skip_step
|
177
228
|
build_step(keyword, step_match, status)
|
178
229
|
end
|
179
230
|
end
|
180
231
|
|
181
|
-
def
|
182
|
-
|
232
|
+
def exception(exception, status)
|
233
|
+
return if @hide_this_step
|
234
|
+
builder.pre(format_exception(exception), :class => status)
|
235
|
+
end
|
236
|
+
|
237
|
+
def before_multiline_arg(multiline_arg)
|
238
|
+
start_buffering :multiline_arg
|
183
239
|
end
|
184
240
|
|
185
|
-
def
|
186
|
-
|
241
|
+
def after_multiline_arg(multiline_arg)
|
242
|
+
stop_buffering :multiline_arg
|
243
|
+
return if @hide_this_step || @skip_step
|
187
244
|
if Ast::Table === multiline_arg
|
188
|
-
|
189
|
-
|
245
|
+
builder.table do
|
246
|
+
builder << buffer(:multiline_arg)
|
190
247
|
end
|
191
248
|
else
|
192
|
-
|
249
|
+
builder << buffer(:multiline_arg)
|
193
250
|
end
|
194
251
|
end
|
195
252
|
|
196
|
-
def
|
197
|
-
|
198
|
-
|
253
|
+
def py_string(string)
|
254
|
+
return if @hide_this_step
|
255
|
+
builder.pre(:class => 'val') do |pre|
|
256
|
+
builder << string.gsub("\n", '
')
|
199
257
|
end
|
200
258
|
end
|
201
259
|
|
202
|
-
def
|
260
|
+
def before_table_row(table_row)
|
203
261
|
@row_id = table_row.dom_id
|
204
262
|
@col_index = 0
|
205
|
-
|
206
|
-
|
263
|
+
start_buffering :table_row
|
264
|
+
end
|
265
|
+
|
266
|
+
def after_table_row(table_row)
|
267
|
+
stop_buffering :table_row
|
268
|
+
return if @hide_this_step
|
269
|
+
builder.tr(:id => @row_id) do
|
270
|
+
builder << buffer(:table_row)
|
207
271
|
end
|
208
272
|
if table_row.exception
|
209
|
-
|
210
|
-
|
211
|
-
|
273
|
+
builder.tr do
|
274
|
+
builder.td(:colspan => @col_index.to_s, :class => 'failed') do
|
275
|
+
builder.pre do |pre|
|
212
276
|
pre << format_exception(table_row.exception)
|
213
277
|
end
|
214
278
|
end
|
@@ -217,45 +281,71 @@ module Cucumber
|
|
217
281
|
@outline_row += 1 if @outline_row
|
218
282
|
end
|
219
283
|
|
220
|
-
def
|
284
|
+
def table_cell_value(value, status)
|
285
|
+
return if @hide_this_step
|
286
|
+
|
221
287
|
cell_type = @outline_row == 0 ? :th : :td
|
222
288
|
attributes = {:id => "#{@row_id}_#{@col_index}", :class => 'val'}
|
223
289
|
attributes[:class] += " #{status}" if status
|
224
290
|
build_cell(cell_type, value, attributes)
|
225
291
|
@col_index += 1
|
226
292
|
end
|
227
|
-
|
293
|
+
|
228
294
|
def announce(announcement)
|
229
|
-
|
295
|
+
builder.pre(announcement, :class => 'announcement')
|
230
296
|
end
|
231
|
-
|
232
|
-
|
297
|
+
|
298
|
+
private
|
233
299
|
|
234
300
|
def build_step(keyword, step_match, status)
|
235
301
|
step_name = step_match.format_args(lambda{|param| %{<span class="param">#{param}</span>}})
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
302
|
+
builder.div do |div|
|
303
|
+
builder.span(keyword, :class => 'keyword')
|
304
|
+
builder.text!(' ')
|
305
|
+
builder.span(:class => 'step val') do |name|
|
240
306
|
name << h(step_name).gsub(/<span class="(.*?)">/, '<span class="\1">').gsub(/<\/span>/, '</span>')
|
241
307
|
end
|
242
308
|
end
|
243
309
|
end
|
244
|
-
|
310
|
+
|
245
311
|
def build_cell(cell_type, value, attributes)
|
246
|
-
|
312
|
+
builder.__send__(cell_type, value, attributes)
|
247
313
|
end
|
248
|
-
|
314
|
+
|
249
315
|
def inline_css
|
250
|
-
|
251
|
-
|
316
|
+
builder.style(:type => 'text/css') do
|
317
|
+
builder.text!(File.read(File.dirname(__FILE__) + '/cucumber.css'))
|
252
318
|
end
|
253
319
|
end
|
254
|
-
|
320
|
+
|
255
321
|
def format_exception(exception)
|
256
322
|
h((["#{exception.message} (#{exception.class})"] + exception.backtrace).join("\n"))
|
257
323
|
end
|
258
324
|
|
325
|
+
def builder
|
326
|
+
@current_builder
|
327
|
+
end
|
328
|
+
|
329
|
+
def buffer(label)
|
330
|
+
result = @buffer[label]
|
331
|
+
@buffer[label] = ''
|
332
|
+
result
|
333
|
+
end
|
334
|
+
|
335
|
+
def start_buffering(label)
|
336
|
+
@buffer[label] ||= ''
|
337
|
+
@parent_builder ||= {}
|
338
|
+
@parent_builder[label] = @current_builder
|
339
|
+
@current_builder = create_builder(@buffer[label])
|
340
|
+
end
|
341
|
+
|
342
|
+
def stop_buffering(label)
|
343
|
+
@current_builder = @parent_builder[label]
|
344
|
+
end
|
345
|
+
|
346
|
+
def create_builder(io)
|
347
|
+
OrderedXmlMarkup.new(:target => io, :indent => 0)
|
348
|
+
end
|
259
349
|
end
|
260
350
|
end
|
261
351
|
end
|