cucumber 0.9.2 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,9 +8,7 @@ module Cucumber
8
8
  end
9
9
 
10
10
  def to_json
11
- @support_code.step_definitions.map do |step_definition|
12
- step_definition.regexp_source
13
- end.to_json
11
+ @support_code.step_definitions.map{|stepdef| stepdef.to_hash}.to_json
14
12
  end
15
13
  end
16
14
  end
@@ -11,6 +11,35 @@ module Cucumber
11
11
  File.stub!(:exist?).and_return(false) # When Configuration checks for cucumber.yml
12
12
  Dir.stub!(:[]).and_return([]) # to prevent cucumber's features dir to being laoded
13
13
  end
14
+
15
+ let(:args) { [] }
16
+ let(:out_stream) { nil }
17
+ let(:err_stream) { nil }
18
+ subject { Main.new(args, out_stream, err_stream)}
19
+
20
+ describe "#execute!" do
21
+ context "passed an existing runtime" do
22
+ let(:existing_runtime) { double('runtime').as_null_object }
23
+
24
+ def do_execute
25
+ subject.execute!(existing_runtime)
26
+ end
27
+
28
+ it "configures that runtime" do
29
+ expected_configuration = double('Configuration', :drb? => false).as_null_object
30
+ Configuration.stub!(:new => expected_configuration)
31
+ existing_runtime.should_receive(:configure).with(expected_configuration)
32
+ do_execute
33
+ end
34
+
35
+ it "uses that runtime for running and reporting results" do
36
+ expected_results = double('results', :failure? => true)
37
+ existing_runtime.should_receive(:run!)
38
+ existing_runtime.stub!(:results).and_return(expected_results)
39
+ do_execute.should == expected_results.failure?
40
+ end
41
+ end
42
+ end
14
43
 
15
44
  describe "verbose mode" do
16
45
 
@@ -32,9 +61,7 @@ module Cucumber
32
61
  end
33
62
 
34
63
  describe "--format with class" do
35
-
36
- describe "in module" do
37
-
64
+ describe "in module" do
38
65
  it "should resolve each module until it gets Formatter class" do
39
66
  cli = Main.new(%w{--format ZooModule::MonkeyFormatterClass}, nil)
40
67
  mock_module = mock('module')
@@ -48,7 +75,6 @@ module Cucumber
48
75
 
49
76
  cli.execute!
50
77
  end
51
-
52
78
  end
53
79
  end
54
80
 
@@ -35,14 +35,14 @@ module Cucumber
35
35
 
36
36
  def run(features)
37
37
  configuration = Cucumber::Configuration.default
38
- tree_walker = Cucumber::Ast::TreeWalker.new(@step_mother, [@formatter], configuration)
38
+ tree_walker = Cucumber::Ast::TreeWalker.new(step_mother, [@formatter], configuration)
39
39
  tree_walker.visit_features(features)
40
40
  end
41
41
 
42
42
  def define_steps
43
43
  return unless step_defs = self.class.step_defs
44
- rb = @step_mother.load_programming_language('rb')
45
- dsl = Object.new
44
+ rb = step_mother.load_programming_language('rb')
45
+ dsl = Object.new
46
46
  dsl.extend RbSupport::RbDsl
47
47
  dsl.instance_exec &step_defs
48
48
  end
@@ -6,65 +6,74 @@ 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 }
10
- before do
11
- @rb = runtime.load_programming_language('rb')
9
+ let(:user_interface) { double('user interface') }
10
+ let(:rb) { support_code.load_programming_language('rb')}
11
+ let(:support_code) do
12
+ Cucumber::Runtime::SupportCode.new(user_interface, {})
13
+ end
14
+ let(:dsl) do
15
+ rb
16
+ Object.new.extend(RbSupport::RbDsl)
12
17
  end
13
18
 
14
19
  def unindented(s)
15
20
  s.split("\n")[1..-2].join("\n").indent(-10)
16
21
  end
22
+
23
+ describe "snippets" do
17
24
 
18
- it "should recognise numbers in name and make according regexp" do
19
- @rb.snippet_text('Given', 'Cloud 9 yeah', nil).should == unindented(%{
25
+ it "should recognise numbers in name and make according regexp" do
26
+ rb.snippet_text('Given', 'Cloud 9 yeah', nil).should == unindented(%{
20
27
  Given /^Cloud (\\d+) yeah$/ do |arg1|
21
28
  pending # express the regexp above with the code you wish you had
22
29
  end
23
- })
24
- end
30
+ })
31
+ end
25
32
 
26
- it "should recognise a mix of ints, strings and why not a table too" do
27
- @rb.snippet_text('Given', 'I have 9 "awesome" cukes in 37 "boxes"', Cucumber::Ast::Table).should == unindented(%{
33
+ it "should recognise a mix of ints, strings and why not a table too" do
34
+ rb.snippet_text('Given', 'I have 9 "awesome" cukes in 37 "boxes"', Cucumber::Ast::Table).should == unindented(%{
28
35
  Given /^I have (\\d+) "([^"]*)" cukes in (\\d+) "([^"]*)"$/ do |arg1, arg2, arg3, arg4, table|
29
36
  # table is a Cucumber::Ast::Table
30
37
  pending # express the regexp above with the code you wish you had
31
38
  end
32
- })
33
- end
39
+ })
40
+ end
34
41
 
35
- it "should recognise quotes in name and make according regexp" do
36
- @rb.snippet_text('Given', 'A "first" arg', nil).should == unindented(%{
42
+ it "should recognise quotes in name and make according regexp" do
43
+ rb.snippet_text('Given', 'A "first" arg', nil).should == unindented(%{
37
44
  Given /^A "([^"]*)" arg$/ do |arg1|
38
45
  pending # express the regexp above with the code you wish you had
39
46
  end
40
- })
41
- end
47
+ })
48
+ end
42
49
 
43
- it "should recognise several quoted words in name and make according regexp and args" do
44
- @rb.snippet_text('Given', 'A "first" and "second" arg', nil).should == unindented(%{
50
+ it "should recognise several quoted words in name and make according regexp and args" do
51
+ rb.snippet_text('Given', 'A "first" and "second" arg', nil).should == unindented(%{
45
52
  Given /^A "([^"]*)" and "([^"]*)" arg$/ do |arg1, arg2|
46
53
  pending # express the regexp above with the code you wish you had
47
54
  end
48
- })
49
- end
55
+ })
56
+ end
50
57
 
51
- it "should not use quote group when there are no quotes" do
52
- @rb.snippet_text('Given', 'A first arg', nil).should == unindented(%{
58
+ it "should not use quote group when there are no quotes" do
59
+ rb.snippet_text('Given', 'A first arg', nil).should == unindented(%{
53
60
  Given /^A first arg$/ do
54
61
  pending # express the regexp above with the code you wish you had
55
62
  end
56
- })
57
- end
63
+ })
64
+ end
58
65
 
59
- it "should be helpful with tables" do
60
- @rb.snippet_text('Given', 'A "first" arg', Cucumber::Ast::Table).should == unindented(%{
66
+ it "should be helpful with tables" do
67
+ rb.snippet_text('Given', 'A "first" arg', Cucumber::Ast::Table).should == unindented(%{
61
68
  Given /^A "([^"]*)" arg$/ do |arg1, table|
62
69
  # table is a Cucumber::Ast::Table
63
70
  pending # express the regexp above with the code you wish you had
64
71
  end
65
- })
66
- end
72
+ })
73
+ end
67
74
 
75
+ end
76
+
68
77
  describe "#load_code_file" do
69
78
  after do
70
79
  FileUtils.rm_rf('tmp.rb')
@@ -81,17 +90,194 @@ module Cucumber
81
90
  "$foo = 1"
82
91
  end
83
92
 
84
- @rb.load_code_file('tmp.rb')
93
+ rb.load_code_file('tmp.rb')
85
94
  $foo.should == 1
86
95
 
87
96
  a_file_called('tmp.rb') do
88
97
  "$foo = 2"
89
98
  end
90
99
 
91
- @rb.load_code_file('tmp.rb')
100
+ rb.load_code_file('tmp.rb')
92
101
  $foo.should == 2
93
102
  end
94
103
  end
104
+
105
+ describe "Handling the World" do
106
+
107
+ it "should raise an error if the world is nil" do
108
+ dsl.World {}
109
+
110
+ begin
111
+ rb.before(nil)
112
+ raise "Should fail"
113
+ rescue RbSupport::NilWorld => e
114
+ e.message.should == "World procs should never return nil"
115
+ e.backtrace.length.should == 1
116
+ e.backtrace[0].should =~ /spec\/cucumber\/rb_support\/rb_language_spec\.rb\:\d+\:in `World'/
117
+ end
118
+ end
119
+
120
+ module ModuleOne
121
+ end
122
+
123
+ module ModuleTwo
124
+ end
125
+
126
+ class ClassOne
127
+ end
128
+
129
+ it "should implicitly extend world with modules" do
130
+ dsl.World(ModuleOne, ModuleTwo)
131
+ rb.before(mock('scenario').as_null_object)
132
+ class << rb.current_world
133
+ included_modules.inspect.should =~ /ModuleOne/ # Workaround for RSpec/Ruby 1.9 issue with namespaces
134
+ included_modules.inspect.should =~ /ModuleTwo/
135
+ end
136
+ rb.current_world.class.should == Object
137
+ end
138
+
139
+ it "should raise error when we try to register more than one World proc" do
140
+ expected_error = %{You can only pass a proc to #World once, but it's happening
141
+ in 2 places:
142
+
143
+ spec/cucumber/rb_support/rb_language_spec.rb:\\d+:in `World'
144
+ spec/cucumber/rb_support/rb_language_spec.rb:\\d+:in `World'
145
+
146
+ Use Ruby modules instead to extend your worlds. See the Cucumber::RbSupport::RbDsl#World RDoc
147
+ or http://wiki.github.com/aslakhellesoy/cucumber/a-whole-new-world.
148
+
149
+ }
150
+ dsl.World { Hash.new }
151
+ lambda do
152
+ dsl.World { Array.new }
153
+ end.should raise_error(RbSupport::MultipleWorld, /#{expected_error}/)
154
+
155
+ end
156
+ end
157
+
158
+ describe "step argument transformations" do
159
+
160
+ describe "without capture groups" do
161
+ it "complains when registering with a with no transform block" do
162
+ lambda do
163
+ dsl.Transform('^abc$')
164
+ end.should raise_error(Cucumber::RbSupport::RbTransform::MissingProc)
165
+ end
166
+
167
+ it "complains when registering with a zero-arg transform block" do
168
+ lambda do
169
+ dsl.Transform('^abc$') {42}
170
+ end.should raise_error(Cucumber::RbSupport::RbTransform::MissingProc)
171
+ end
172
+
173
+ it "complains when registering with a splat-arg transform block" do
174
+ lambda do
175
+ dsl.Transform('^abc$') {|*splat| 42 }
176
+ end.should raise_error(Cucumber::RbSupport::RbTransform::MissingProc)
177
+ end
178
+
179
+ it "complains when transforming with an arity mismatch" do
180
+ lambda do
181
+ dsl.Transform('^abc$') {|one, two| 42 }
182
+ rb.execute_transforms(['abc'])
183
+ end.should raise_error(Cucumber::ArityMismatchError)
184
+ end
185
+
186
+ it "allows registering a regexp pattern that yields the step_arg matched" do
187
+ dsl.Transform(/^ab*c$/) {|arg| 42}
188
+ rb.execute_transforms(['ab']).should == ['ab']
189
+ rb.execute_transforms(['ac']).should == [42]
190
+ rb.execute_transforms(['abc']).should == [42]
191
+ rb.execute_transforms(['abbc']).should == [42]
192
+ end
193
+ end
194
+
195
+ describe "with capture groups" do
196
+ it "complains when registering with a with no transform block" do
197
+ lambda do
198
+ dsl.Transform('^a(.)c$')
199
+ end.should raise_error(Cucumber::RbSupport::RbTransform::MissingProc)
200
+ end
201
+
202
+ it "complains when registering with a zero-arg transform block" do
203
+ lambda do
204
+ dsl.Transform('^a(.)c$') { 42 }
205
+ end.should raise_error(Cucumber::RbSupport::RbTransform::MissingProc)
206
+ end
207
+
208
+ it "complains when registering with a splat-arg transform block" do
209
+ lambda do
210
+ dsl.Transform('^a(.)c$') {|*splat| 42 }
211
+ end.should raise_error(Cucumber::RbSupport::RbTransform::MissingProc)
212
+ end
213
+
214
+ it "complains when transforming with an arity mismatch" do
215
+ lambda do
216
+ dsl.Transform('^a(.)c$') {|one, two| 42 }
217
+ rb.execute_transforms(['abc'])
218
+ end.should raise_error(Cucumber::ArityMismatchError)
219
+ end
220
+
221
+ it "allows registering a regexp pattern that yields capture groups" do
222
+ dsl.Transform(/^shape: (.+), color: (.+)$/) do |shape, color|
223
+ {shape.to_sym => color.to_sym}
224
+ end
225
+ rb.execute_transforms(['shape: circle, color: blue']).should == [{:circle => :blue}]
226
+ rb.execute_transforms(['shape: square, color: red']).should == [{:square => :red}]
227
+ rb.execute_transforms(['not shape: square, not color: red']).should == ['not shape: square, not color: red']
228
+ end
229
+ end
230
+
231
+ it "allows registering a string pattern" do
232
+ dsl.Transform('^ab*c$') {|arg| 42}
233
+ rb.execute_transforms(['ab']).should == ['ab']
234
+ rb.execute_transforms(['ac']).should == [42]
235
+ rb.execute_transforms(['abc']).should == [42]
236
+ rb.execute_transforms(['abbc']).should == [42]
237
+ end
238
+
239
+ it "gives match priority to transforms defined last" do
240
+ dsl.Transform(/^transform_me$/) {|arg| :foo }
241
+ dsl.Transform(/^transform_me$/) {|arg| :bar }
242
+ dsl.Transform(/^transform_me$/) {|arg| :baz }
243
+ rb.execute_transforms(['transform_me']).should == [:baz]
244
+ end
245
+
246
+ it "allows registering a transform which returns nil" do
247
+ dsl.Transform('^ac$') {|arg| nil}
248
+ rb.execute_transforms(['ab']).should == ['ab']
249
+ rb.execute_transforms(['ac']).should == [nil]
250
+ end
251
+ end
252
+
253
+ describe "hooks" do
254
+
255
+ it "should find before hooks" do
256
+ fish = dsl.Before('@fish'){}
257
+ meat = dsl.Before('@meat'){}
258
+
259
+ scenario = mock('Scenario')
260
+ scenario.should_receive(:accept_hook?).with(fish).and_return(true)
261
+ scenario.should_receive(:accept_hook?).with(meat).and_return(false)
262
+
263
+ rb.hooks_for(:before, scenario).should == [fish]
264
+ end
265
+
266
+ it "should find around hooks" do
267
+ a = dsl.Around do |scenario, block|
268
+ end
269
+
270
+ b = dsl.Around('@tag') do |scenario, block|
271
+ end
272
+
273
+ scenario = mock('Scenario')
274
+ scenario.should_receive(:accept_hook?).with(a).and_return(true)
275
+ scenario.should_receive(:accept_hook?).with(b).and_return(false)
276
+
277
+ rb.hooks_for(:around, scenario).should == [a]
278
+ end
279
+ end
280
+
95
281
  end
96
282
  end
97
283
  end
@@ -7,86 +7,92 @@ require 'cucumber/rb_support/rb_language'
7
7
  module Cucumber
8
8
  module RbSupport
9
9
  describe RbStepDefinition do
10
+ let(:user_interface) { double('user interface') }
11
+ let(:support_code) { Cucumber::Runtime::SupportCode.new(user_interface) }
12
+ let(:rb) { support_code.load_programming_language('rb')}
13
+ let(:dsl) do
14
+ rb
15
+ Object.new.extend(Cucumber::RbSupport::RbDsl)
16
+ end
17
+
10
18
  before do
11
- @step_mother = Cucumber::Runtime.new
12
- @rb = @step_mother.load_programming_language('rb')
13
- @dsl = Object.new
14
- @dsl.extend Cucumber::RbSupport::RbDsl
15
- @step_mother.before(mock('scenario').as_null_object)
19
+ rb.before(mock('scenario').as_null_object)
16
20
 
17
21
  $inside = nil
18
22
  end
19
23
 
20
24
  it "should allow calling of other steps" do
21
- @dsl.Given /Outside/ do
25
+ dsl.Given /Outside/ do
22
26
  Given "Inside"
23
27
  end
24
- @dsl.Given /Inside/ do
28
+ dsl.Given /Inside/ do
25
29
  $inside = true
26
30
  end
27
31
 
28
- @step_mother.step_match("Outside").invoke(nil)
32
+ support_code.step_match("Outside").invoke(nil)
29
33
  $inside.should == true
30
34
  end
31
35
 
32
36
  it "should allow calling of other steps with inline arg" do
33
- @dsl.Given /Outside/ do
37
+ dsl.Given /Outside/ do
34
38
  Given "Inside", Cucumber::Ast::Table.new([['inside']])
35
39
  end
36
- @dsl.Given /Inside/ do |table|
40
+ dsl.Given /Inside/ do |table|
37
41
  $inside = table.raw[0][0]
38
42
  end
39
43
 
40
- @step_mother.step_match("Outside").invoke(nil)
44
+ support_code.step_match("Outside").invoke(nil)
41
45
  $inside.should == 'inside'
42
46
  end
43
47
 
44
48
  it "should raise Undefined when inside step is not defined" do
45
- @dsl.Given /Outside/ do
49
+ dsl.Given /Outside/ do
46
50
  Given 'Inside'
47
51
  end
48
52
 
49
53
  lambda do
50
- @step_mother.step_match('Outside').invoke(nil)
54
+ support_code.step_match('Outside').invoke(nil)
51
55
  end.should raise_error(Cucumber::Undefined, 'Undefined step: "Inside"')
52
56
  end
53
57
 
54
58
  it "should allow forced pending" do
55
- @dsl.Given /Outside/ do
59
+ dsl.Given /Outside/ do
56
60
  pending("Do me!")
57
61
  end
58
62
 
59
63
  lambda do
60
- @step_mother.step_match("Outside").invoke(nil)
64
+ support_code.step_match("Outside").invoke(nil)
61
65
  end.should raise_error(Cucumber::Pending, "Do me!")
62
66
  end
63
67
 
64
68
  it "should raise ArityMismatchError when the number of capture groups differs from the number of step arguments" do
65
- @dsl.Given /No group: \w+/ do |arg|
69
+ dsl.Given /No group: \w+/ do |arg|
66
70
  end
67
71
 
68
72
  lambda do
69
- @step_mother.step_match("No group: arg").invoke(nil)
73
+ support_code.step_match("No group: arg").invoke(nil)
70
74
  end.should raise_error(Cucumber::ArityMismatchError)
71
75
  end
72
76
 
73
77
  it "should allow announce" do
74
- v = mock('visitor')
75
- v.should_receive(:announce).with('wasup')
76
- @step_mother.visitor = v
77
- @dsl.Given /Loud/ do
78
+ user_interface.should_receive(:announce).with('wasup')
79
+ dsl.Given /Loud/ do
78
80
  announce 'wasup'
79
81
  end
80
82
 
81
- @step_mother.step_match("Loud").invoke(nil)
83
+ support_code.step_match("Loud").invoke(nil)
82
84
  end
83
85
 
84
86
  it "should recognize $arg style captures" do
85
- @dsl.Given "capture this: $arg" do |arg|
87
+ dsl.Given "capture this: $arg" do |arg|
86
88
  arg.should == 'this'
87
89
  end
88
90
 
89
- @step_mother.step_match('capture this: this').invoke(nil)
91
+ support_code.step_match('capture this: this').invoke(nil)
92
+ end
93
+
94
+ it "should have a JSON representation of the signature" do
95
+ RbStepDefinition.new(rb, /I CAN HAZ (\d+) CUKES/i, lambda{}).to_hash.should == {'source' => "I CAN HAZ (\\d+) CUKES", 'flags' => 'i'}
90
96
  end
91
97
  end
92
98
  end