cucumber 0.8.7 → 0.9.0
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/.gitignore +24 -0
- data/Gemfile +5 -0
- data/History.txt +16 -3
- data/Rakefile +4 -50
- data/cucumber.gemspec +36 -600
- data/features/cucumber_cli.feature +1 -1
- data/features/json_formatter.feature +1 -1
- data/features/junit_formatter.feature +10 -6
- data/features/post_configuration_hook.feature +15 -2
- data/features/step_definitions/cucumber_steps.rb +5 -1
- data/features/step_definitions/wire_steps.rb +1 -0
- data/features/support/env.rb +2 -5
- data/features/wire_protocol.feature +1 -1
- data/lib/cucumber.rb +8 -0
- data/lib/cucumber/ast/outline_table.rb +4 -4
- data/lib/cucumber/ast/step_invocation.rb +14 -13
- data/lib/cucumber/ast/table.rb +2 -1
- data/lib/cucumber/ast/tree_walker.rb +3 -3
- data/lib/cucumber/cli/configuration.rb +32 -7
- data/lib/cucumber/cli/main.rb +26 -30
- data/lib/cucumber/cli/options.rb +1 -3
- data/lib/cucumber/cli/profile_loader.rb +2 -0
- data/lib/cucumber/configuration.rb +37 -0
- data/lib/cucumber/errors.rb +40 -0
- data/lib/cucumber/feature_file.rb +5 -12
- data/lib/cucumber/formatter/junit.rb +2 -2
- data/lib/cucumber/formatter/tag_cloud.rb +1 -1
- data/lib/cucumber/js_support/js_dsl.js +4 -4
- data/lib/cucumber/js_support/js_language.rb +9 -5
- data/lib/cucumber/language_support.rb +2 -2
- data/lib/cucumber/parser/gherkin_builder.rb +19 -19
- data/lib/cucumber/platform.rb +3 -4
- data/lib/cucumber/rake/task.rb +1 -7
- data/lib/cucumber/rb_support/rb_dsl.rb +1 -0
- data/lib/cucumber/rb_support/rb_language.rb +1 -0
- data/lib/cucumber/rspec/doubles.rb +3 -3
- data/lib/cucumber/runtime.rb +192 -0
- data/lib/cucumber/runtime/features_loader.rb +62 -0
- data/lib/cucumber/runtime/results.rb +46 -0
- data/lib/cucumber/runtime/support_code.rb +174 -0
- data/lib/cucumber/runtime/user_interface.rb +80 -0
- data/lib/cucumber/step_mother.rb +6 -427
- data/lib/cucumber/wire_support/configuration.rb +2 -0
- data/lib/cucumber/wire_support/wire_language.rb +1 -8
- data/spec/cucumber/ast/background_spec.rb +3 -3
- data/spec/cucumber/ast/feature_spec.rb +2 -2
- data/spec/cucumber/ast/scenario_outline_spec.rb +1 -1
- data/spec/cucumber/ast/scenario_spec.rb +1 -2
- data/spec/cucumber/ast/tree_walker_spec.rb +1 -1
- data/spec/cucumber/cli/configuration_spec.rb +31 -5
- data/spec/cucumber/cli/drb_client_spec.rb +1 -1
- data/spec/cucumber/cli/main_spec.rb +8 -37
- data/spec/cucumber/cli/options_spec.rb +20 -0
- data/spec/cucumber/formatter/spec_helper.rb +5 -7
- data/spec/cucumber/rb_support/rb_language_spec.rb +2 -2
- data/spec/cucumber/rb_support/rb_step_definition_spec.rb +1 -1
- data/spec/cucumber/runtime_spec.rb +294 -0
- data/spec/cucumber/step_match_spec.rb +10 -8
- data/spec/cucumber/world/pending_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -21
- metadata +215 -84
- data/Caliper.yml +0 -4
- data/VERSION.yml +0 -5
- data/spec/cucumber/step_mother_spec.rb +0 -302
@@ -1,12 +1,5 @@
|
|
1
1
|
require 'socket'
|
2
|
-
|
3
|
-
require 'json'
|
4
|
-
rescue LoadError
|
5
|
-
STDERR.puts <<-EOM
|
6
|
-
You must gem install #{defined?(JRUBY_VERSION) ? 'json_pure' : 'json'} before you can use the wire support.
|
7
|
-
EOM
|
8
|
-
exit(1)
|
9
|
-
end
|
2
|
+
require 'json'
|
10
3
|
require 'cucumber/wire_support/connection'
|
11
4
|
require 'cucumber/wire_support/configuration'
|
12
5
|
require 'cucumber/wire_support/wire_packet'
|
@@ -8,8 +8,8 @@ module Cucumber
|
|
8
8
|
|
9
9
|
before do
|
10
10
|
extend(Cucumber::RbSupport::RbDsl)
|
11
|
-
@
|
12
|
-
@rb = @
|
11
|
+
@runtime = Cucumber::Runtime.new
|
12
|
+
@rb = @runtime.load_programming_language('rb')
|
13
13
|
|
14
14
|
$x = $y = nil
|
15
15
|
Before do
|
@@ -19,7 +19,7 @@ module Cucumber
|
|
19
19
|
$y = $x * n.to_i
|
20
20
|
end
|
21
21
|
|
22
|
-
@visitor = TreeWalker.new(@
|
22
|
+
@visitor = TreeWalker.new(@runtime)
|
23
23
|
|
24
24
|
@feature = mock('feature', :visit? => true).as_null_object
|
25
25
|
end
|
@@ -7,7 +7,7 @@ module Cucumber
|
|
7
7
|
include FeatureFactory
|
8
8
|
|
9
9
|
it "should convert to sexp" do
|
10
|
-
step_mother = Cucumber::
|
10
|
+
step_mother = Cucumber::Runtime.new
|
11
11
|
step_mother.load_programming_language('rb')
|
12
12
|
dsl = Object.new
|
13
13
|
dsl.extend Cucumber::RbSupport::RbDsl
|
@@ -45,7 +45,7 @@ module Cucumber
|
|
45
45
|
end
|
46
46
|
|
47
47
|
it "should store OS specific file paths" do
|
48
|
-
step_mother = Cucumber::
|
48
|
+
step_mother = Cucumber::Runtime.new
|
49
49
|
step_mother.load_programming_language('rb')
|
50
50
|
dsl = Object.new
|
51
51
|
dsl.extend Cucumber::RbSupport::RbDsl
|
@@ -8,7 +8,7 @@ module Cucumber
|
|
8
8
|
module Ast
|
9
9
|
describe ScenarioOutline do
|
10
10
|
before do
|
11
|
-
@step_mother = Cucumber::
|
11
|
+
@step_mother = Cucumber::Runtime.new
|
12
12
|
@step_mother.load_programming_language('rb')
|
13
13
|
@dsl = Object.new
|
14
14
|
@dsl.extend(Cucumber::RbSupport::RbDsl)
|
@@ -7,7 +7,7 @@ module Cucumber
|
|
7
7
|
module Ast
|
8
8
|
describe Scenario do
|
9
9
|
before do
|
10
|
-
@step_mother = Cucumber::
|
10
|
+
@step_mother = Cucumber::Runtime.new
|
11
11
|
@step_mother.load_programming_language('rb')
|
12
12
|
@dsl = Object.new
|
13
13
|
@dsl.extend(Cucumber::RbSupport::RbDsl)
|
@@ -17,7 +17,6 @@ module Cucumber
|
|
17
17
|
$y = n.to_i
|
18
18
|
end
|
19
19
|
@visitor = TreeWalker.new(@step_mother)
|
20
|
-
@visitor.options = {}
|
21
20
|
end
|
22
21
|
|
23
22
|
it "should skip steps when previous is not passed" do
|
@@ -3,7 +3,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
3
3
|
module Cucumber::Ast
|
4
4
|
describe TreeWalker do
|
5
5
|
it "should visit features" do
|
6
|
-
tw = TreeWalker.new(nil, [mock('listener', :before_visit_features => nil)]
|
6
|
+
tw = TreeWalker.new(nil, [mock('listener', :before_visit_features => nil)])
|
7
7
|
tw.should_not_receive(:warn)
|
8
8
|
tw.visit_features(mock('features', :accept => nil))
|
9
9
|
end
|
@@ -4,6 +4,9 @@ require 'yaml'
|
|
4
4
|
module Cucumber
|
5
5
|
module Cli
|
6
6
|
describe Configuration do
|
7
|
+
module ExposesOptions
|
8
|
+
attr_reader :options
|
9
|
+
end
|
7
10
|
|
8
11
|
def given_cucumber_yml_defined_as(hash_or_string)
|
9
12
|
File.stub!(:exist?).and_return(true)
|
@@ -23,7 +26,7 @@ module Cli
|
|
23
26
|
end
|
24
27
|
|
25
28
|
def config
|
26
|
-
@config ||= Configuration.new(@out = StringIO.new, @error = StringIO.new)
|
29
|
+
@config ||= Configuration.new(@out = StringIO.new, @error = StringIO.new).extend(ExposesOptions)
|
27
30
|
end
|
28
31
|
|
29
32
|
def reset_config
|
@@ -287,17 +290,17 @@ END_OF_MESSAGE
|
|
287
290
|
|
288
291
|
it "should accept --out option" do
|
289
292
|
config.parse!(%w{--out jalla.txt})
|
290
|
-
config.
|
293
|
+
config.formats.should == [['pretty', 'jalla.txt']]
|
291
294
|
end
|
292
295
|
|
293
296
|
it "should accept multiple --out options" do
|
294
297
|
config.parse!(%w{--format progress --out file1 --out file2})
|
295
|
-
config.
|
298
|
+
config.formats.should == [['progress', 'file2']]
|
296
299
|
end
|
297
300
|
|
298
301
|
it "should accept multiple --format options and put the STDOUT one first so progress is seen" do
|
299
302
|
config.parse!(%w{--format pretty --out pretty.txt --format progress})
|
300
|
-
config.
|
303
|
+
config.formats.should == [['progress', out], ['pretty', 'pretty.txt']]
|
301
304
|
end
|
302
305
|
|
303
306
|
it "should not accept multiple --format options when both use implicit STDOUT" do
|
@@ -314,7 +317,7 @@ END_OF_MESSAGE
|
|
314
317
|
|
315
318
|
it "should associate --out to previous --format" do
|
316
319
|
config.parse!(%w{--format progress --out file1 --format profile --out file2})
|
317
|
-
config.
|
320
|
+
config.formats.should == [["progress", "file1"], ["profile" ,"file2"]]
|
318
321
|
end
|
319
322
|
|
320
323
|
it "should accept --color option" do
|
@@ -399,7 +402,30 @@ END_OF_MESSAGE
|
|
399
402
|
ENV["RAILS_ENV"].should == "selenium"
|
400
403
|
config.feature_files.should_not include('RAILS_ENV=selenium')
|
401
404
|
end
|
405
|
+
|
406
|
+
describe "#tag_expression" do
|
407
|
+
it "returns an empty expression when no tags are specified" do
|
408
|
+
config.parse!([])
|
409
|
+
config.tag_expression.should be_empty
|
410
|
+
end
|
402
411
|
|
412
|
+
it "returns an expression when tags are specified" do
|
413
|
+
config.parse!(['--tags','@foo'])
|
414
|
+
config.tag_expression.should_not be_empty
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
describe "#dry_run?" do
|
419
|
+
it "returns true when --dry-run was specified on in the arguments" do
|
420
|
+
config.parse!(['--dry-run'])
|
421
|
+
config.dry_run?.should be_true
|
422
|
+
end
|
423
|
+
|
424
|
+
it "returns false by default" do
|
425
|
+
config.parse!([])
|
426
|
+
config.dry_run?.should be_false
|
427
|
+
end
|
428
|
+
end
|
403
429
|
end
|
404
430
|
end
|
405
431
|
end
|
@@ -30,7 +30,7 @@ module Cucumber
|
|
30
30
|
|
31
31
|
it "returns raises an error when it can't connect to the server" do
|
32
32
|
DRbObject.stub!(:new_with_uri).and_raise(DRb::DRbConnError)
|
33
|
-
|
33
|
+
lambda { DRbClient.run(@args, @error_stream, @out_stream) }.should raise_error(DRbClientError, "No DRb server is running.")
|
34
34
|
end
|
35
35
|
|
36
36
|
it "returns the result from the DRb server call" do
|
@@ -24,7 +24,7 @@ module Cucumber
|
|
24
24
|
|
25
25
|
Cucumber::FeatureFile.stub!(:new).and_return(mock("feature file", :parse => @empty_feature))
|
26
26
|
|
27
|
-
@cli.execute!
|
27
|
+
@cli.execute!
|
28
28
|
|
29
29
|
@out.string.should include('example.feature')
|
30
30
|
end
|
@@ -46,42 +46,12 @@ module Cucumber
|
|
46
46
|
Object.should_receive(:const_get).with('ZooModule').and_return(mock_module)
|
47
47
|
mock_module.should_receive(:const_get).with('MonkeyFormatterClass').and_return(mock('formatter class', :new => f))
|
48
48
|
|
49
|
-
cli.execute!
|
49
|
+
cli.execute!
|
50
50
|
end
|
51
51
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
-
describe "setup step sequence" do
|
56
|
-
|
57
|
-
it "should load files and execute hooks in order" do
|
58
|
-
Configuration.stub!(:new).and_return(configuration = mock('configuration').as_null_object)
|
59
|
-
step_mother = mock('step mother').as_null_object
|
60
|
-
configuration.stub!(:drb?).and_return false
|
61
|
-
cli = Main.new(%w{--verbose example.feature}, @out)
|
62
|
-
cli.stub!(:require)
|
63
|
-
|
64
|
-
configuration.stub!(:support_to_load).and_return(['support'])
|
65
|
-
configuration.stub!(:step_defs_to_load).and_return(['step defs'])
|
66
|
-
|
67
|
-
# Support must be loaded first to ensure post configuration hook can
|
68
|
-
# run before anything else.
|
69
|
-
step_mother.should_receive(:load_code_files).with(['support']).ordered
|
70
|
-
# The post configuration hook/s (if any) need to be run next to enable
|
71
|
-
# extensions to do their thing before features are loaded
|
72
|
-
step_mother.should_receive(:after_configuration).with(configuration).ordered
|
73
|
-
# Feature files must be loaded before step definitions are required.
|
74
|
-
# This is because i18n step methods are only aliased when
|
75
|
-
# features are loaded. If we swap the order, the requires
|
76
|
-
# will fail.
|
77
|
-
step_mother.should_receive(:load_plain_text_features).ordered
|
78
|
-
step_mother.should_receive(:load_code_files).with(['step defs']).ordered
|
79
|
-
|
80
|
-
cli.execute!(step_mother)
|
81
|
-
end
|
82
|
-
|
83
|
-
end
|
84
|
-
|
85
55
|
[ProfilesNotDefinedError, YmlLoadError, ProfileNotFound].each do |exception_klass|
|
86
56
|
|
87
57
|
it "rescues #{exception_klass}, prints the message to the error stream and returns true" do
|
@@ -89,7 +59,7 @@ module Cucumber
|
|
89
59
|
configuration.stub!(:parse!).and_raise(exception_klass.new("error message"))
|
90
60
|
|
91
61
|
main = Main.new('', out = StringIO.new, error = StringIO.new)
|
92
|
-
main.execute
|
62
|
+
main.execute!.should be_true
|
93
63
|
error.string.should == "error message\n"
|
94
64
|
end
|
95
65
|
end
|
@@ -103,30 +73,31 @@ module Cucumber
|
|
103
73
|
|
104
74
|
@cli = Main.new(@args, @out, @err)
|
105
75
|
@step_mother = mock('StepMother').as_null_object
|
76
|
+
StepMother.stub!(:new).and_return(@step_mother)
|
106
77
|
end
|
107
78
|
|
108
79
|
it "delegates the execution to the DRB client passing the args and streams" do
|
109
80
|
@configuration.stub :drb_port => 1450
|
110
81
|
DRbClient.should_receive(:run).with(@args, @err, @out, 1450).and_return(true)
|
111
|
-
@cli.execute!
|
82
|
+
@cli.execute!
|
112
83
|
end
|
113
84
|
|
114
85
|
it "returns the result from the DRbClient" do
|
115
86
|
DRbClient.stub!(:run).and_return('foo')
|
116
|
-
@cli.execute
|
87
|
+
@cli.execute!.should == 'foo'
|
117
88
|
end
|
118
89
|
|
119
90
|
it "ceases execution if the DrbClient is able to perform the execution" do
|
120
91
|
DRbClient.stub!(:run).and_return(true)
|
121
92
|
@configuration.should_not_receive(:build_formatter_broadcaster)
|
122
|
-
@cli.execute!
|
93
|
+
@cli.execute!
|
123
94
|
end
|
124
95
|
|
125
96
|
context "when the DrbClient is unable to perfrom the execution" do
|
126
97
|
before { DRbClient.stub!(:run).and_raise(DRbClientError.new('error message.')) }
|
127
98
|
|
128
99
|
it "alerts the user that execution will be performed locally" do
|
129
|
-
@cli.execute!
|
100
|
+
@cli.execute!
|
130
101
|
@err.string.should include("WARNING: error message. Running features locally:")
|
131
102
|
end
|
132
103
|
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
2
|
require 'yaml'
|
3
|
+
require 'cucumber/cli/options'
|
3
4
|
|
4
5
|
module Cucumber
|
5
6
|
module Cli
|
@@ -324,6 +325,25 @@ module Cli
|
|
324
325
|
|
325
326
|
end
|
326
327
|
|
328
|
+
describe "dry-run" do
|
329
|
+
it "should have the default value for snippets" do
|
330
|
+
given_cucumber_yml_defined_as({'foo' => %w[--dry-run]})
|
331
|
+
options.parse!(%w{--dry-run})
|
332
|
+
options[:snippets].should == true
|
333
|
+
end
|
334
|
+
|
335
|
+
it "should set snippets to false when no-snippets provided after dry-run" do
|
336
|
+
given_cucumber_yml_defined_as({'foo' => %w[--dry-run --no-snippets]})
|
337
|
+
options.parse!(%w{--dry-run --no-snippets})
|
338
|
+
options[:snippets].should == false
|
339
|
+
end
|
340
|
+
|
341
|
+
it "should set snippets to false when no-snippets provided before dry-run" do
|
342
|
+
given_cucumber_yml_defined_as({'foo' => %w[--no-snippet --dry-run]})
|
343
|
+
options.parse!(%w{--no-snippets --dry-run})
|
344
|
+
options[:snippets].should == false
|
345
|
+
end
|
346
|
+
end
|
327
347
|
end
|
328
348
|
|
329
349
|
end
|
@@ -21,19 +21,21 @@ module Cucumber
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def step_mother
|
24
|
-
@step_mother ||=
|
24
|
+
@step_mother ||= Runtime.new
|
25
25
|
end
|
26
26
|
|
27
27
|
def load_features(content)
|
28
28
|
feature_file = FeatureFile.new('spec.feature', content)
|
29
29
|
features = Ast::Features.new
|
30
|
-
|
30
|
+
filters = []
|
31
|
+
feature = feature_file.parse(filters, {})
|
31
32
|
features.add_feature(feature) if feature
|
32
33
|
features
|
33
34
|
end
|
34
35
|
|
35
36
|
def run(features)
|
36
|
-
|
37
|
+
configuration = Cucumber::Configuration.default
|
38
|
+
tree_walker = Cucumber::Ast::TreeWalker.new(@step_mother, [@formatter], configuration)
|
37
39
|
tree_walker.visit_features(features)
|
38
40
|
end
|
39
41
|
|
@@ -44,10 +46,6 @@ module Cucumber
|
|
44
46
|
dsl.extend RbSupport::RbDsl
|
45
47
|
dsl.instance_exec &step_defs
|
46
48
|
end
|
47
|
-
|
48
|
-
def options
|
49
|
-
@options ||= mock(Cucumber::Cli::Options, :filters => [], :[] => nil)
|
50
|
-
end
|
51
49
|
end
|
52
50
|
end
|
53
51
|
end
|
@@ -6,9 +6,9 @@ require 'cucumber/rb_support/rb_language'
|
|
6
6
|
module Cucumber
|
7
7
|
module RbSupport
|
8
8
|
describe RbStepDefinition do
|
9
|
+
let(:runtime) { Cucumber::Runtime.new }
|
9
10
|
before do
|
10
|
-
@
|
11
|
-
@rb = @step_mother.load_programming_language('rb')
|
11
|
+
@rb = runtime.load_programming_language('rb')
|
12
12
|
end
|
13
13
|
|
14
14
|
def unindented(s)
|
@@ -8,7 +8,7 @@ module Cucumber
|
|
8
8
|
module RbSupport
|
9
9
|
describe RbStepDefinition do
|
10
10
|
before do
|
11
|
-
@step_mother = Cucumber::
|
11
|
+
@step_mother = Cucumber::Runtime.new
|
12
12
|
@rb = @step_mother.load_programming_language('rb')
|
13
13
|
@dsl = Object.new
|
14
14
|
@dsl.extend Cucumber::RbSupport::RbDsl
|
@@ -0,0 +1,294 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Cucumber
|
4
|
+
describe Runtime do
|
5
|
+
subject { Runtime.new(options) }
|
6
|
+
let(:options) { {} }
|
7
|
+
let(:dsl) do
|
8
|
+
@rb = subject.load_programming_language('rb')
|
9
|
+
Object.new.extend(RbSupport::RbDsl)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should format step names" do
|
13
|
+
dsl.Given(/it (.*) in (.*)/) { |what, month| }
|
14
|
+
dsl.Given(/nope something else/) { |what, month| }
|
15
|
+
|
16
|
+
format = subject.step_match("it snows in april").format_args("[%s]")
|
17
|
+
format.should == "it [snows] in [april]"
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#features_paths" do
|
21
|
+
let(:options) { {:paths => ['foo/bar/baz.feature', 'foo/bar/features/baz.feature', 'other_features'] } }
|
22
|
+
it "returns the value from configuration.paths" do
|
23
|
+
subject.features_paths.should == options[:paths]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "resolving step defintion matches" do
|
28
|
+
|
29
|
+
it "should raise Ambiguous error with guess hint when multiple step definitions match" do
|
30
|
+
expected_error = %{Ambiguous match of "Three blind mice":
|
31
|
+
|
32
|
+
spec/cucumber/runtime_spec.rb:\\d+:in `/Three (.*) mice/'
|
33
|
+
spec/cucumber/runtime_spec.rb:\\d+:in `/Three blind (.*)/'
|
34
|
+
|
35
|
+
You can run again with --guess to make Cucumber be more smart about it
|
36
|
+
}
|
37
|
+
dsl.Given(/Three (.*) mice/) {|disability|}
|
38
|
+
dsl.Given(/Three blind (.*)/) {|animal|}
|
39
|
+
|
40
|
+
lambda do
|
41
|
+
subject.step_match("Three blind mice")
|
42
|
+
end.should raise_error(Ambiguous, /#{expected_error}/)
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "when --guess is used" do
|
46
|
+
let(:options) { {:guess => true} }
|
47
|
+
|
48
|
+
it "should not show --guess hint" do
|
49
|
+
expected_error = %{Ambiguous match of "Three cute mice":
|
50
|
+
|
51
|
+
spec/cucumber/runtime_spec.rb:\\d+:in `/Three (.*) mice/'
|
52
|
+
spec/cucumber/runtime_spec.rb:\\d+:in `/Three cute (.*)/'
|
53
|
+
|
54
|
+
}
|
55
|
+
dsl.Given(/Three (.*) mice/) {|disability|}
|
56
|
+
dsl.Given(/Three cute (.*)/) {|animal|}
|
57
|
+
|
58
|
+
lambda do
|
59
|
+
subject.step_match("Three cute mice")
|
60
|
+
end.should raise_error(Ambiguous, /#{expected_error}/)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should not raise Ambiguous error when multiple step definitions match" do
|
64
|
+
dsl.Given(/Three (.*) mice/) {|disability|}
|
65
|
+
dsl.Given(/Three (.*)/) {|animal|}
|
66
|
+
|
67
|
+
lambda do
|
68
|
+
subject.step_match("Three blind mice")
|
69
|
+
end.should_not raise_error
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should not raise NoMethodError when guessing from multiple step definitions with nil fields" do
|
73
|
+
dsl.Given(/Three (.*) mice( cannot find food)?/) {|disability, is_disastrous|}
|
74
|
+
dsl.Given(/Three (.*)?/) {|animal|}
|
75
|
+
|
76
|
+
lambda do
|
77
|
+
subject.step_match("Three blind mice")
|
78
|
+
end.should_not raise_error
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should pick right step definition when an equal number of capture groups" do
|
82
|
+
right = dsl.Given(/Three (.*) mice/) {|disability|}
|
83
|
+
wrong = dsl.Given(/Three (.*)/) {|animal|}
|
84
|
+
|
85
|
+
subject.step_match("Three blind mice").step_definition.should == right
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should pick right step definition when an unequal number of capture groups" do
|
89
|
+
right = dsl.Given(/Three (.*) mice ran (.*)/) {|disability|}
|
90
|
+
wrong = dsl.Given(/Three (.*)/) {|animal|}
|
91
|
+
|
92
|
+
subject.step_match("Three blind mice ran far").step_definition.should == right
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should pick most specific step definition when an unequal number of capture groups" do
|
96
|
+
general = dsl.Given(/Three (.*) mice ran (.*)/) {|disability|}
|
97
|
+
specific = dsl.Given(/Three blind mice ran far/) do; end
|
98
|
+
more_specific = dsl.Given(/^Three blind mice ran far$/) do; end
|
99
|
+
|
100
|
+
subject.step_match("Three blind mice ran far").step_definition.should == more_specific
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should raise Undefined error when no step definitions match" do
|
105
|
+
lambda do
|
106
|
+
subject.step_match("Three blind mice")
|
107
|
+
end.should raise_error(Undefined)
|
108
|
+
end
|
109
|
+
|
110
|
+
# http://railsforum.com/viewtopic.php?pid=93881
|
111
|
+
it "should not raise Redundant unless it's really redundant" do
|
112
|
+
dsl.Given(/^(.*) (.*) user named '(.*)'$/) {|a,b,c|}
|
113
|
+
dsl.Given(/^there is no (.*) user named '(.*)'$/) {|a,b|}
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "Handling the World" do
|
118
|
+
|
119
|
+
it "should raise an error if the world is nil" do
|
120
|
+
dsl.World {}
|
121
|
+
|
122
|
+
begin
|
123
|
+
subject.before_and_after(nil) do; end
|
124
|
+
raise "Should fail"
|
125
|
+
rescue RbSupport::NilWorld => e
|
126
|
+
e.message.should == "World procs should never return nil"
|
127
|
+
e.backtrace.length.should == 1
|
128
|
+
e.backtrace[0].should =~ /spec\/cucumber\/runtime_spec\.rb\:\d+\:in `World'/
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
module ModuleOne
|
133
|
+
end
|
134
|
+
|
135
|
+
module ModuleTwo
|
136
|
+
end
|
137
|
+
|
138
|
+
class ClassOne
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should implicitly extend world with modules" do
|
142
|
+
dsl.World(ModuleOne, ModuleTwo)
|
143
|
+
subject.before(mock('scenario').as_null_object)
|
144
|
+
class << @rb.current_world
|
145
|
+
included_modules.inspect.should =~ /ModuleOne/ # Workaround for RSpec/Ruby 1.9 issue with namespaces
|
146
|
+
included_modules.inspect.should =~ /ModuleTwo/
|
147
|
+
end
|
148
|
+
@rb.current_world.class.should == Object
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should raise error when we try to register more than one World proc" do
|
152
|
+
expected_error = %{You can only pass a proc to #World once, but it's happening
|
153
|
+
in 2 places:
|
154
|
+
|
155
|
+
spec/cucumber/runtime_spec.rb:\\d+:in `World'
|
156
|
+
spec/cucumber/runtime_spec.rb:\\d+:in `World'
|
157
|
+
|
158
|
+
Use Ruby modules instead to extend your worlds. See the Cucumber::RbSupport::RbDsl#World RDoc
|
159
|
+
or http://wiki.github.com/aslakhellesoy/cucumber/a-whole-new-world.
|
160
|
+
|
161
|
+
}
|
162
|
+
dsl.World { Hash.new }
|
163
|
+
lambda do
|
164
|
+
dsl.World { Array.new }
|
165
|
+
end.should raise_error(RbSupport::MultipleWorld, /#{expected_error}/)
|
166
|
+
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
describe "hooks" do
|
171
|
+
|
172
|
+
it "should find before hooks" do
|
173
|
+
fish = dsl.Before('@fish'){}
|
174
|
+
meat = dsl.Before('@meat'){}
|
175
|
+
|
176
|
+
scenario = mock('Scenario')
|
177
|
+
scenario.should_receive(:accept_hook?).with(fish).and_return(true)
|
178
|
+
scenario.should_receive(:accept_hook?).with(meat).and_return(false)
|
179
|
+
|
180
|
+
@rb.hooks_for(:before, scenario).should == [fish]
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should find around hooks" do
|
184
|
+
a = dsl.Around do |scenario, block|
|
185
|
+
end
|
186
|
+
|
187
|
+
b = dsl.Around('@tag') do |scenario, block|
|
188
|
+
end
|
189
|
+
|
190
|
+
scenario = mock('Scenario')
|
191
|
+
scenario.should_receive(:accept_hook?).with(a).and_return(true)
|
192
|
+
scenario.should_receive(:accept_hook?).with(b).and_return(false)
|
193
|
+
|
194
|
+
@rb.hooks_for(:around, scenario).should == [a]
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
describe "step argument transformations" do
|
199
|
+
|
200
|
+
describe "without capture groups" do
|
201
|
+
it "complains when registering with a with no transform block" do
|
202
|
+
lambda do
|
203
|
+
dsl.Transform('^abc$')
|
204
|
+
end.should raise_error(Cucumber::RbSupport::RbTransform::MissingProc)
|
205
|
+
end
|
206
|
+
|
207
|
+
it "complains when registering with a zero-arg transform block" do
|
208
|
+
lambda do
|
209
|
+
dsl.Transform('^abc$') {42}
|
210
|
+
end.should raise_error(Cucumber::RbSupport::RbTransform::MissingProc)
|
211
|
+
end
|
212
|
+
|
213
|
+
it "complains when registering with a splat-arg transform block" do
|
214
|
+
lambda do
|
215
|
+
dsl.Transform('^abc$') {|*splat| 42 }
|
216
|
+
end.should raise_error(Cucumber::RbSupport::RbTransform::MissingProc)
|
217
|
+
end
|
218
|
+
|
219
|
+
it "complains when transforming with an arity mismatch" do
|
220
|
+
lambda do
|
221
|
+
dsl.Transform('^abc$') {|one, two| 42 }
|
222
|
+
@rb.execute_transforms(['abc'])
|
223
|
+
end.should raise_error(Cucumber::ArityMismatchError)
|
224
|
+
end
|
225
|
+
|
226
|
+
it "allows registering a regexp pattern that yields the step_arg matched" do
|
227
|
+
dsl.Transform(/^ab*c$/) {|arg| 42}
|
228
|
+
@rb.execute_transforms(['ab']).should == ['ab']
|
229
|
+
@rb.execute_transforms(['ac']).should == [42]
|
230
|
+
@rb.execute_transforms(['abc']).should == [42]
|
231
|
+
@rb.execute_transforms(['abbc']).should == [42]
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
describe "with capture groups" do
|
236
|
+
it "complains when registering with a with no transform block" do
|
237
|
+
lambda do
|
238
|
+
dsl.Transform('^a(.)c$')
|
239
|
+
end.should raise_error(Cucumber::RbSupport::RbTransform::MissingProc)
|
240
|
+
end
|
241
|
+
|
242
|
+
it "complains when registering with a zero-arg transform block" do
|
243
|
+
lambda do
|
244
|
+
dsl.Transform('^a(.)c$') { 42 }
|
245
|
+
end.should raise_error(Cucumber::RbSupport::RbTransform::MissingProc)
|
246
|
+
end
|
247
|
+
|
248
|
+
it "complains when registering with a splat-arg transform block" do
|
249
|
+
lambda do
|
250
|
+
dsl.Transform('^a(.)c$') {|*splat| 42 }
|
251
|
+
end.should raise_error(Cucumber::RbSupport::RbTransform::MissingProc)
|
252
|
+
end
|
253
|
+
|
254
|
+
it "complains when transforming with an arity mismatch" do
|
255
|
+
lambda do
|
256
|
+
dsl.Transform('^a(.)c$') {|one, two| 42 }
|
257
|
+
@rb.execute_transforms(['abc'])
|
258
|
+
end.should raise_error(Cucumber::ArityMismatchError)
|
259
|
+
end
|
260
|
+
|
261
|
+
it "allows registering a regexp pattern that yields capture groups" do
|
262
|
+
dsl.Transform(/^shape: (.+), color: (.+)$/) do |shape, color|
|
263
|
+
{shape.to_sym => color.to_sym}
|
264
|
+
end
|
265
|
+
@rb.execute_transforms(['shape: circle, color: blue']).should == [{:circle => :blue}]
|
266
|
+
@rb.execute_transforms(['shape: square, color: red']).should == [{:square => :red}]
|
267
|
+
@rb.execute_transforms(['not shape: square, not color: red']).should == ['not shape: square, not color: red']
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
it "allows registering a string pattern" do
|
272
|
+
dsl.Transform('^ab*c$') {|arg| 42}
|
273
|
+
@rb.execute_transforms(['ab']).should == ['ab']
|
274
|
+
@rb.execute_transforms(['ac']).should == [42]
|
275
|
+
@rb.execute_transforms(['abc']).should == [42]
|
276
|
+
@rb.execute_transforms(['abbc']).should == [42]
|
277
|
+
end
|
278
|
+
|
279
|
+
it "gives match priority to transforms defined last" do
|
280
|
+
dsl.Transform(/^transform_me$/) {|arg| :foo }
|
281
|
+
dsl.Transform(/^transform_me$/) {|arg| :bar }
|
282
|
+
dsl.Transform(/^transform_me$/) {|arg| :baz }
|
283
|
+
@rb.execute_transforms(['transform_me']).should == [:baz]
|
284
|
+
end
|
285
|
+
|
286
|
+
it "allows registering a transform which returns nil" do
|
287
|
+
dsl.Transform('^ac$') {|arg| nil}
|
288
|
+
@rb.execute_transforms(['ab']).should == ['ab']
|
289
|
+
@rb.execute_transforms(['ac']).should == [nil]
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
end
|
294
|
+
end
|