kosmas58-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.
- data/History.txt +8 -2
- data/Manifest.txt +6 -1
- data/examples/java/README.textile +3 -3
- 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/language_support/step_definition_methods.rb +2 -2
- data/lib/cucumber/rb_support/rb_language.rb +5 -0
- data/lib/cucumber/rb_support/rb_step_definition.rb +3 -3
- data/lib/cucumber/rb_support/regexp_argument_matcher.rb +21 -0
- data/lib/cucumber/step_argument.rb +9 -0
- data/lib/cucumber/step_match.rb +12 -14
- data/lib/cucumber/version.rb +1 -1
- 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
- data/spec/cucumber/rb_support/regexp_argument_matcher_spec.rb +18 -0
- data/spec/cucumber/step_match_spec.rb +40 -0
- metadata +6 -3
- data/lib/cucumber/rb_support/rb_group.rb +0 -32
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,10 +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
|
+
=== Bugfixes
|
14
|
+
* Gracefully handle cases when optional regexp groups are not matched. Ex: /should( not)? be flashed '([^']*?)'$/ (Aslak Hellesøy)
|
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
|
+
|
13
19
|
== 2009-09-22
|
14
20
|
|
15
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
|
@@ -385,13 +386,14 @@ lib/cucumber/rails/test_unit.rb
|
|
385
386
|
lib/cucumber/rails/world.rb
|
386
387
|
lib/cucumber/rake/task.rb
|
387
388
|
lib/cucumber/rb_support/rb_dsl.rb
|
388
|
-
lib/cucumber/rb_support/rb_group.rb
|
389
389
|
lib/cucumber/rb_support/rb_hook.rb
|
390
390
|
lib/cucumber/rb_support/rb_language.rb
|
391
391
|
lib/cucumber/rb_support/rb_step_definition.rb
|
392
392
|
lib/cucumber/rb_support/rb_transform.rb
|
393
393
|
lib/cucumber/rb_support/rb_world.rb
|
394
|
+
lib/cucumber/rb_support/regexp_argument_matcher.rb
|
394
395
|
lib/cucumber/rspec_neuter.rb
|
396
|
+
lib/cucumber/step_argument.rb
|
395
397
|
lib/cucumber/step_match.rb
|
396
398
|
lib/cucumber/step_mother.rb
|
397
399
|
lib/cucumber/version.rb
|
@@ -422,6 +424,7 @@ spec/cucumber/ast/scenario_spec.rb
|
|
422
424
|
spec/cucumber/ast/step_collection_spec.rb
|
423
425
|
spec/cucumber/ast/step_spec.rb
|
424
426
|
spec/cucumber/ast/table_spec.rb
|
427
|
+
spec/cucumber/ast/tree_walker_spec.rb
|
425
428
|
spec/cucumber/broadcaster_spec.rb
|
426
429
|
spec/cucumber/cli/configuration_spec.rb
|
427
430
|
spec/cucumber/cli/drb_client_spec.rb
|
@@ -437,7 +440,9 @@ spec/cucumber/formatter/progress_spec.rb
|
|
437
440
|
spec/cucumber/parser/feature_parser_spec.rb
|
438
441
|
spec/cucumber/parser/table_parser_spec.rb
|
439
442
|
spec/cucumber/rb_support/rb_step_definition_spec.rb
|
443
|
+
spec/cucumber/rb_support/regexp_argument_matcher_spec.rb
|
440
444
|
spec/cucumber/sell_cucumbers.feature
|
445
|
+
spec/cucumber/step_match_spec.rb
|
441
446
|
spec/cucumber/step_mother_spec.rb
|
442
447
|
spec/cucumber/treetop_parser/empty_feature.feature
|
443
448
|
spec/cucumber/treetop_parser/empty_scenario.feature
|
@@ -11,8 +11,8 @@ h2. Running the scenarios
|
|
11
11
|
|
12
12
|
Open a shell in this directory (java) and execute the following command:
|
13
13
|
|
14
|
-
<pre
|
15
|
-
ant
|
16
|
-
</code></pre>
|
14
|
+
<pre>ant</pre>
|
17
15
|
|
18
16
|
There is a deliberate error. See if you can fix it!
|
17
|
+
|
18
|
+
Also see "Cuke4Duke":http://wiki.github.com/aslakhellesoy/cuke4duke for more powerful JVM and Java support for Cucumber.
|
@@ -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
|