cucumber 0.8.7 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|