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 +18 -0
- data/Manifest.txt +6 -2
- 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/features/steps_formatter.feature +2 -1
- data/lib/cucumber/ast.rb +1 -0
- data/lib/cucumber/ast/table.rb +4 -4
- data/lib/cucumber/ast/tree_walker.rb +185 -0
- 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/core_ext/string.rb +0 -22
- 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 +6 -7
- data/lib/cucumber/formatter/tag_cloud.rb +7 -6
- data/lib/cucumber/formatter/usage.rb +7 -10
- data/lib/cucumber/language_support/step_definition_methods.rb +4 -4
- data/lib/cucumber/rails/action_controller.rb +1 -1
- data/lib/cucumber/rails/active_record.rb +27 -14
- data/lib/cucumber/rb_support/rb_language.rb +5 -0
- data/lib/cucumber/rb_support/rb_step_definition.rb +9 -16
- 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 +24 -5
- data/lib/cucumber/version.rb +1 -1
- data/rails_generators/cucumber/templates/env.rb +14 -0
- 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/ast/tree_walker_spec.rb +18 -0
- 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 +8 -4
- data/lib/cucumber/rb_support/rb_group.rb +0 -11
- data/spec/cucumber/core_ext/string_spec.rb +0 -41
data/lib/cucumber/version.rb
CHANGED
@@ -3,6 +3,20 @@ ENV["RAILS_ENV"] ||= "cucumber"
|
|
3
3
|
require File.expand_path(File.dirname(__FILE__) + '/../../config/environment')
|
4
4
|
require 'cucumber/rails/world'
|
5
5
|
|
6
|
+
# Whether or not to run each scenario within a database transaction.
|
7
|
+
#
|
8
|
+
# If you leave this to true, you can turn off traqnsactions on a
|
9
|
+
# per-scenario basis, simply tagging it with @no-txn
|
10
|
+
Cucumber::Rails::World.use_transactional_fixtures = true
|
11
|
+
|
12
|
+
# Whether or not to allow Rails to rescue errors and render them on
|
13
|
+
# an error page. Default is false, which will cause an error to be
|
14
|
+
# raised.
|
15
|
+
#
|
16
|
+
# If you leave this to false, you can turn on Rails rescuing on a
|
17
|
+
# per-scenario basis, simply tagging it with @allow-rescue
|
18
|
+
ActionController::Base.allow_rescue = false
|
19
|
+
|
6
20
|
# Comment out the next line if you don't want Cucumber Unicode support
|
7
21
|
require 'cucumber/formatter/unicode'
|
8
22
|
|
@@ -57,14 +57,15 @@ module Cucumber
|
|
57
57
|
end
|
58
58
|
|
59
59
|
it "should replace all variables and call outline once for each table row" do
|
60
|
-
visitor =
|
60
|
+
visitor = TreeWalker.new(@step_mother)
|
61
61
|
visitor.should_receive(:visit_table_row).exactly(3).times
|
62
62
|
visitor.visit_feature_element(@scenario_outline)
|
63
63
|
end
|
64
64
|
|
65
65
|
it "should pretty print" do
|
66
66
|
require 'cucumber/formatter/pretty'
|
67
|
-
|
67
|
+
formatter = Formatter::Pretty.new(@step_mother, STDOUT, {:comment => true, :tag_names => {}})
|
68
|
+
visitor = TreeWalker.new(@step_mother, [formatter])
|
68
69
|
visitor.visit_feature_element(@scenario_outline)
|
69
70
|
end
|
70
71
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
module Cucumber::Ast
|
4
|
+
describe TreeWalker do
|
5
|
+
describe "when one of the listeners implements the method #visit_features" do
|
6
|
+
it "should issue a warning about that interface being deprecated" do
|
7
|
+
tw = TreeWalker.new(nil, [mock('listener', :visit_features => nil)], {})
|
8
|
+
tw.should_receive(:warn).with /no longer supported/
|
9
|
+
tw.visit_features(mock('features', :accept => nil))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
it "should visit features" do
|
13
|
+
tw = TreeWalker.new(nil, [mock('listener', :before_visit_features => nil)], {})
|
14
|
+
tw.should_not_receive(:warn)
|
15
|
+
tw.visit_features(mock('features', :accept => nil))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -1,16 +1,235 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
2
|
require 'cucumber/formatter/html'
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'cucumber/rb_support/rb_language'
|
3
5
|
|
4
6
|
module Cucumber
|
5
7
|
module Formatter
|
8
|
+
module SpecHelperDsl
|
9
|
+
attr_reader :feature_content, :step_defs
|
10
|
+
|
11
|
+
def define_feature(string)
|
12
|
+
@feature_content = string
|
13
|
+
end
|
14
|
+
|
15
|
+
def define_steps(&block)
|
16
|
+
@step_defs = block
|
17
|
+
end
|
18
|
+
end
|
19
|
+
module SpecHelper
|
20
|
+
def load_features(content)
|
21
|
+
feature_file = FeatureFile.new(nil, content)
|
22
|
+
features = Ast::Features.new
|
23
|
+
features.add_feature feature_file.parse(@step_mother, {})
|
24
|
+
features
|
25
|
+
end
|
26
|
+
|
27
|
+
def run(features)
|
28
|
+
# options = { :verbose => true }
|
29
|
+
options = {}
|
30
|
+
tree_walker = Cucumber::Ast::TreeWalker.new(@step_mother, [@formatter], options, STDOUT)
|
31
|
+
tree_walker.visit_features(features)
|
32
|
+
end
|
33
|
+
|
34
|
+
def define_steps
|
35
|
+
return unless step_defs = self.class.step_defs
|
36
|
+
rb = @step_mother.load_programming_language('rb')
|
37
|
+
dsl = Object.new
|
38
|
+
dsl.extend RbSupport::RbDsl
|
39
|
+
dsl.instance_exec &step_defs
|
40
|
+
@step_mother.register_step_definitions(rb.step_definitions)
|
41
|
+
end
|
42
|
+
|
43
|
+
Spec::Matchers.define :have_css_node do |css, regexp|
|
44
|
+
match do |doc|
|
45
|
+
nodes = doc.css(css)
|
46
|
+
nodes.detect{ |node| node.text =~ regexp }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
6
51
|
describe Html do
|
7
52
|
before(:each) do
|
8
53
|
@out = StringIO.new
|
9
|
-
@
|
54
|
+
@formatter = Html.new(mock("step mother"), @out, {})
|
55
|
+
@step_mother = StepMother.new
|
10
56
|
end
|
57
|
+
|
58
|
+
extend SpecHelperDsl
|
59
|
+
include SpecHelper
|
11
60
|
|
12
61
|
it "should not raise an error when visiting a blank feature name" do
|
13
|
-
lambda { @
|
62
|
+
lambda { @formatter.feature_name("") }.should_not raise_error
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "given a single feature" do
|
66
|
+
before(:each) do
|
67
|
+
features = load_features(self.class.feature_content || raise("No feature content defined!"))
|
68
|
+
define_steps
|
69
|
+
run(features)
|
70
|
+
@doc = Nokogiri.HTML(@out.string)
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "with a comment" do
|
74
|
+
define_feature <<-FEATURE
|
75
|
+
# Healthy
|
76
|
+
FEATURE
|
77
|
+
|
78
|
+
it { @out.string.should =~ /^\<!DOCTYPE/ }
|
79
|
+
it { @out.string.should =~ /\<\/html\>$/ }
|
80
|
+
it { @doc.should have_css_node('.feature .comment', /Healthy/) }
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "with a tag" do
|
84
|
+
define_feature <<-FEATURE
|
85
|
+
@foo
|
86
|
+
FEATURE
|
87
|
+
|
88
|
+
it { @doc.should have_css_node('.feature .tag', /foo/) }
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "with a narrative" do
|
92
|
+
define_feature <<-FEATURE
|
93
|
+
Feature: Bananas
|
94
|
+
In order to find my inner monkey
|
95
|
+
As a human
|
96
|
+
I must eat bananas
|
97
|
+
FEATURE
|
98
|
+
|
99
|
+
it { @doc.should have_css_node('.feature h2', /Bananas/) }
|
100
|
+
it { @doc.should have_css_node('.feature .narrative', /must eat bananas/) }
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "with a background" do
|
104
|
+
define_feature <<-FEATURE
|
105
|
+
Feature: Bananas
|
106
|
+
|
107
|
+
Background:
|
108
|
+
Given there are bananas
|
109
|
+
FEATURE
|
110
|
+
|
111
|
+
it { @doc.should have_css_node('.feature .background', /there are bananas/) }
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "with a scenario" do
|
115
|
+
define_feature <<-FEATURE
|
116
|
+
Scenario: Monkey eats banana
|
117
|
+
Given there are bananas
|
118
|
+
FEATURE
|
119
|
+
|
120
|
+
it { @doc.should have_css_node('.feature h3', /Monkey eats banana/) }
|
121
|
+
it { @doc.should have_css_node('.feature .scenario .step', /there are bananas/) }
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "with a scenario outline" do
|
125
|
+
define_feature <<-FEATURE
|
126
|
+
Scenario Outline: Monkey eats a balanced diet
|
127
|
+
Given there are <Things>
|
128
|
+
|
129
|
+
Examples: Fruit
|
130
|
+
| Things |
|
131
|
+
| apples |
|
132
|
+
| bananas |
|
133
|
+
Examples: Vegetables
|
134
|
+
| Things |
|
135
|
+
| broccoli |
|
136
|
+
| carrots |
|
137
|
+
FEATURE
|
138
|
+
|
139
|
+
it { @doc.should have_css_node('.feature .scenario.outline h4', /Fruit/) }
|
140
|
+
it { @doc.should have_css_node('.feature .scenario.outline h4', /Vegetables/) }
|
141
|
+
it { @doc.css('.feature .scenario.outline h4').length.should == 2}
|
142
|
+
it { @doc.should have_css_node('.feature .scenario.outline table', //) }
|
143
|
+
it { @doc.should have_css_node('.feature .scenario.outline table td', /carrots/) }
|
144
|
+
end
|
145
|
+
|
146
|
+
describe "with a step with a py string" do
|
147
|
+
define_feature <<-FEATURE
|
148
|
+
Scenario: Monkey goes to town
|
149
|
+
Given there is a monkey called:
|
150
|
+
"""
|
151
|
+
foo
|
152
|
+
"""
|
153
|
+
FEATURE
|
154
|
+
|
155
|
+
it { @doc.should have_css_node('.feature .scenario .val', /foo/) }
|
156
|
+
end
|
157
|
+
|
158
|
+
describe "with a multiline step arg" do
|
159
|
+
define_feature <<-FEATURE
|
160
|
+
Scenario: Monkey goes to town
|
161
|
+
Given there are monkeys:
|
162
|
+
| name |
|
163
|
+
| foo |
|
164
|
+
| bar |
|
165
|
+
FEATURE
|
166
|
+
|
167
|
+
it { @doc.should have_css_node('.feature .scenario table td', /foo/) }
|
168
|
+
end
|
169
|
+
|
170
|
+
describe "with a table in the background and the scenario" do
|
171
|
+
define_feature <<-FEATURE
|
172
|
+
Background:
|
173
|
+
Given table:
|
174
|
+
| a | b |
|
175
|
+
| c | d |
|
176
|
+
Scenario:
|
177
|
+
Given another table:
|
178
|
+
| e | f |
|
179
|
+
| g | h |
|
180
|
+
FEATURE
|
181
|
+
|
182
|
+
it { @doc.css('td').length.should == 8 }
|
183
|
+
end
|
184
|
+
|
185
|
+
describe "with a py string in the background and the scenario" do
|
186
|
+
define_feature <<-FEATURE
|
187
|
+
Background:
|
188
|
+
Given stuff:
|
189
|
+
"""
|
190
|
+
foo
|
191
|
+
"""
|
192
|
+
Scenario:
|
193
|
+
Given more stuff:
|
194
|
+
"""
|
195
|
+
bar
|
196
|
+
"""
|
197
|
+
FEATURE
|
198
|
+
|
199
|
+
it { @doc.css('.feature .background pre.val').length.should == 1 }
|
200
|
+
it { @doc.css('.feature .scenario pre.val').length.should == 1 }
|
201
|
+
end
|
202
|
+
|
203
|
+
describe "with a step that fails in the scenario" do
|
204
|
+
define_steps do
|
205
|
+
Given(/boo/) { raise 'eek' }
|
206
|
+
end
|
207
|
+
|
208
|
+
define_feature(<<-FEATURE)
|
209
|
+
Scenario: Monkey gets a fright
|
210
|
+
Given boo
|
211
|
+
FEATURE
|
212
|
+
|
213
|
+
it { @doc.should have_css_node('.feature .scenario .step.failed', /eek/) }
|
214
|
+
end
|
215
|
+
|
216
|
+
describe "with a step that fails in the backgound" do
|
217
|
+
define_steps do
|
218
|
+
Given(/boo/) { raise 'eek' }
|
219
|
+
end
|
220
|
+
|
221
|
+
define_feature(<<-FEATURE)
|
222
|
+
Background:
|
223
|
+
Given boo
|
224
|
+
Scenario:
|
225
|
+
Given yay
|
226
|
+
FEATURE
|
227
|
+
|
228
|
+
it { @doc.should have_css_node('.feature .background .step.failed', /eek/) }
|
229
|
+
it { @doc.should_not have_css_node('.feature .scenario .step.failed', //) }
|
230
|
+
it { @doc.should have_css_node('.feature .scenario .step.undefined', /yay/) }
|
231
|
+
end
|
232
|
+
|
14
233
|
end
|
15
234
|
end
|
16
235
|
end
|
@@ -8,13 +8,18 @@ module Cucumber
|
|
8
8
|
before(:each) do
|
9
9
|
Term::ANSIColor.coloring = false
|
10
10
|
@out = StringIO.new
|
11
|
-
|
11
|
+
progress = Progress.new(mock("step mother"), @out, {})
|
12
|
+
@visitor = Ast::TreeWalker.new(nil, [progress])
|
12
13
|
end
|
13
14
|
|
14
15
|
describe "visiting a table cell value without a status" do
|
15
16
|
it "should take the status from the last run step" do
|
16
|
-
@
|
17
|
-
|
17
|
+
@visitor.visit_step_result('', '', nil, :failed, nil, 10, nil)
|
18
|
+
outline_table = mock()
|
19
|
+
outline_table.should_receive(:accept) do |visitor|
|
20
|
+
visitor.visit_table_cell_value('value', nil)
|
21
|
+
end
|
22
|
+
@visitor.visit_outline_table(outline_table)
|
18
23
|
|
19
24
|
@out.string.should == "FF"
|
20
25
|
end
|
@@ -22,7 +27,7 @@ module Cucumber
|
|
22
27
|
|
23
28
|
describe "visiting a table cell which is a table header" do
|
24
29
|
it "should not output anything" do
|
25
|
-
@
|
30
|
+
@visitor.visit_table_cell_value('value', :skipped_param)
|
26
31
|
|
27
32
|
@out.string.should == ""
|
28
33
|
end
|
@@ -361,34 +361,38 @@ Given I am a step
|
|
361
361
|
|
362
362
|
describe "Filtering" do
|
363
363
|
it "should filter outline tables" do
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
364
|
+
path = '/self_test/features/outline_sample.feature'
|
365
|
+
f = parse_example_file("#{path}:12")
|
366
|
+
actual_sexp = f.to_sexp
|
367
|
+
|
368
|
+
# check path is equivalent, if not same
|
369
|
+
File.expand_path(actual_sexp[1]).should == File.expand_path(File.dirname(__FILE__) + "/../../../examples#{path}")
|
370
|
+
actual_sexp[1] = 'made/up/path.feature'
|
371
|
+
actual_sexp.should ==
|
368
372
|
[:feature,
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
373
|
+
'made/up/path.feature',
|
374
|
+
"Feature: Outline Sample",
|
375
|
+
[:scenario_outline,
|
376
|
+
"Scenario Outline:",
|
377
|
+
"Test state",
|
378
|
+
[:step, 6, "Given", "<state> without a table"],
|
379
|
+
[:step, 7, "Given", "<other_state> without a table"],
|
380
|
+
[:examples,
|
381
|
+
"Examples:",
|
382
|
+
"Rainbow colours",
|
383
|
+
[:table,
|
384
|
+
[:row, 9,
|
385
|
+
[:cell, "state"],
|
386
|
+
[:cell, "other_state"]
|
387
|
+
],
|
388
|
+
[:row, 12,
|
389
|
+
[:cell, "failing"],
|
390
|
+
[:cell, "passing"]
|
391
|
+
]
|
392
|
+
]
|
393
|
+
]
|
394
|
+
]
|
395
|
+
]
|
392
396
|
end
|
393
397
|
end
|
394
398
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
require 'cucumber/rb_support/regexp_argument_matcher'
|
3
|
+
|
4
|
+
module Cucumber
|
5
|
+
module RbSupport
|
6
|
+
describe RegexpArgumentMatcher do
|
7
|
+
it "should create 2 arguments" do
|
8
|
+
arguments = RegexpArgumentMatcher.arguments_from(/I (\w+) (\w+)/, "I like fish")
|
9
|
+
arguments.map{|argument| [argument.val, argument.pos]}.should == [["like", 2], ["fish", 7]]
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should create 2 arguments when first group is optional" do
|
13
|
+
arguments = RegexpArgumentMatcher.arguments_from(/should( not)? be flashed '([^']*?)'$/, "I should be flashed 'Login failed.'")
|
14
|
+
arguments.map{|argument| [argument.val, argument.pos]}.should == [[nil, nil], ["Login failed.", 21]]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require 'cucumber/rb_support/rb_step_definition'
|
3
|
+
require 'cucumber/rb_support/rb_language'
|
4
|
+
|
5
|
+
module Cucumber
|
6
|
+
describe StepMatch do
|
7
|
+
before do
|
8
|
+
@rb_language = RbSupport::RbLanguage.new(nil)
|
9
|
+
end
|
10
|
+
|
11
|
+
def stepdef(regexp)
|
12
|
+
RbSupport::RbStepDefinition.new(@rb_language, regexp, lambda{})
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should format groups with format string" do
|
16
|
+
m = stepdef(/I (\w+) (\d+) (\w+) this (\w+)/).step_match("I ate 1 egg this morning", nil)
|
17
|
+
m.format_args("<span>%s</span>").should == "I <span>ate</span> <span>1</span> <span>egg</span> this <span>morning</span>"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should format groups with format string when there are dupes" do
|
21
|
+
m = stepdef(/I (\w+) (\d+) (\w+) this (\w+)/).step_match("I bob 1 bo this bobs", nil)
|
22
|
+
m.format_args("<span>%s</span>").should == "I <span>bob</span> <span>1</span> <span>bo</span> this <span>bobs</span>"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should format groups with block" do
|
26
|
+
m = stepdef(/I (\w+) (\d+) (\w+) this (\w+)/).step_match("I ate 1 egg this morning", nil)
|
27
|
+
m.format_args(&lambda{|m| "<span>#{m}</span>"}).should == "I <span>ate</span> <span>1</span> <span>egg</span> this <span>morning</span>"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should format groups with proc object" do
|
31
|
+
m = stepdef(/I (\w+) (\d+) (\w+) this (\w+)/).step_match("I ate 1 egg this morning", nil)
|
32
|
+
m.format_args(lambda{|m| "<span>#{m}</span>"}).should == "I <span>ate</span> <span>1</span> <span>egg</span> this <span>morning</span>"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should format groups even when first group is optional and not matched" do
|
36
|
+
m = stepdef(/should( not)? be flashed '([^']*?)'$/).step_match("I should be flashed 'Login failed.'", nil)
|
37
|
+
m.format_args("<span>%s</span>").should == "I should be flashed '<span>Login failed.</span>'"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|