aslakhellesoy-cucumber 0.1.9 → 0.1.10

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.
Files changed (43) hide show
  1. data/History.txt +36 -3
  2. data/Manifest.txt +15 -0
  3. data/bin/cucumber +2 -1
  4. data/config/hoe.rb +2 -1
  5. data/examples/calculator_ruby_features/features/addition.rb +1 -1
  6. data/examples/i18n/ar/features/step_definitons/calculator_steps.rb +1 -0
  7. data/examples/i18n/de/Rakefile +6 -0
  8. data/examples/i18n/de/features/addition.feature +17 -0
  9. data/examples/i18n/de/features/division.feature +10 -0
  10. data/examples/i18n/de/features/step_definitons/calculator_steps.rb +30 -0
  11. data/examples/i18n/de/lib/calculator.rb +14 -0
  12. data/examples/i18n/en/Rakefile +1 -0
  13. data/examples/i18n/lt/Rakefile +6 -0
  14. data/examples/i18n/lt/features/addition.feature +17 -0
  15. data/examples/i18n/lt/features/division.feature +10 -0
  16. data/examples/i18n/lt/features/step_definitons/calculator_steps.rb +31 -0
  17. data/examples/i18n/lt/lib/calculator.rb +14 -0
  18. data/examples/test_unit/Rakefile +6 -0
  19. data/examples/test_unit/features/step_definitions/test_unit_steps.rb +26 -0
  20. data/examples/test_unit/features/test_unit.feature +9 -0
  21. data/examples/tickets/features/tickets.feature +4 -2
  22. data/lib/autotest/discover.rb +1 -1
  23. data/lib/cucumber.rb +3 -3
  24. data/lib/cucumber/cli.rb +51 -17
  25. data/lib/cucumber/core_ext/proc.rb +31 -16
  26. data/lib/cucumber/executor.rb +35 -15
  27. data/lib/cucumber/formatters/ansicolor.rb +11 -13
  28. data/lib/cucumber/languages.yml +24 -1
  29. data/lib/cucumber/platform.rb +12 -0
  30. data/lib/cucumber/step_mother.rb +7 -1
  31. data/lib/cucumber/tree/feature.rb +3 -1
  32. data/lib/cucumber/tree/scenario.rb +17 -1
  33. data/lib/cucumber/treetop_parser/feature_de.rb +8 -8
  34. data/lib/cucumber/treetop_parser/feature_lt.rb +1591 -0
  35. data/rails_generators/cucumber/templates/webrat_steps.rb +49 -0
  36. data/rails_generators/feature/templates/feature.erb +3 -3
  37. data/spec/cucumber/cli_spec.rb +172 -2
  38. data/spec/cucumber/executor_spec.rb +104 -28
  39. data/spec/cucumber/step_mother_spec.rb +7 -7
  40. data/spec/cucumber/tree/feature_spec.rb +31 -0
  41. data/spec/cucumber/tree/row_scenario_spec.rb +30 -0
  42. data/spec/spec_helper.rb +1 -0
  43. metadata +21 -6
@@ -1,6 +1,8 @@
1
1
  # Commonly used webrat steps
2
2
  # http://github.com/brynary/webrat
3
3
 
4
+ require 'webrat' if !defined?(Webrat) # Because some people have it installed as a Gem
5
+
4
6
  When /^I press "(.*)"$/ do |button|
5
7
  clicks_button(button)
6
8
  end
@@ -17,6 +19,53 @@ When /^I select "(.*)" from "(.*)"$/ do |value, field|
17
19
  selects(value, :from => field)
18
20
  end
19
21
 
22
+ # Use this step in conjunction with Rail's datetime_select helper. For example:
23
+ # When I select "December 25, 2008 10:00" as the date and time
24
+ When /^I select "(.*)" as the date and time$/ do |time|
25
+ selects_datetime(time)
26
+ end
27
+
28
+ # Use this step when using multiple datetime_select helpers on a page or
29
+ # you want to specify which datetime to select. Given the following view:
30
+ # <%= f.label :preferred %><br />
31
+ # <%= f.datetime_select :preferred %>
32
+ # <%= f.label :alternative %><br />
33
+ # <%= f.datetime_select :alternative %>
34
+ # The following steps would fill out the form:
35
+ # When I select "November 23, 2004 11:20" as the "Preferred" data and time
36
+ # And I select "November 25, 2004 10:30" as the "Alternative" data and time
37
+ When /^I select "(.*)" as the "(.*)" date and time$/ do |datetime, datetime_label|
38
+ selects_datetime(datetime, :from => datetime_label)
39
+ end
40
+
41
+ # Use this step in conjuction with Rail's time_select helper. For example:
42
+ # When I select "2:20PM" as the time
43
+ # Note: Rail's default time helper provides 24-hour time-- not 12 hour time. Webrat
44
+ # will convert the 2:20PM to 14:20 and then select it.
45
+ When /^I select "(.*)" as the time$/ do |time|
46
+ selects_time(time)
47
+ end
48
+
49
+ # Use this step when using multiple time_select helpers on a page or you want to
50
+ # specify the name of the time on the form. For example:
51
+ # When I select "7:30AM" as the "Gym" time
52
+ When /^I select "(.*)" as the "(.*)" time$/ do |time, time_label|
53
+ selects_time(time, :from => time_label)
54
+ end
55
+
56
+ # Use this step in conjuction with Rail's date_select helper. For example:
57
+ # When I select "February 20, 1981" as the date
58
+ When /^I select "(.*)" as the date$/ do |date|
59
+ selects_date(date)
60
+ end
61
+
62
+ # Use this step when using multiple date_select helpers on one page or
63
+ # you want to specify the name of the date on the form. For example:
64
+ # When I select "April 26, 1982" as the "Date of Birth" date
65
+ When /^I select "(.*)" as the "(.*)" date$/ do |date, date_label|
66
+ selects_date(date, :from => date_label)
67
+ end
68
+
20
69
  When /^I check "(.*)"$/ do |field|
21
70
  checks(field)
22
71
  end
@@ -1,7 +1,7 @@
1
1
  Feature: Manage <%= plural_name %>
2
- In order to keep track of <%= plural_name %>
3
- A <%= singular_name %> mechanic
4
- Should be able to manage several <%= plural_name %>
2
+ In order to [goal]
3
+ [stakeholder]
4
+ wants [behaviour]
5
5
 
6
6
  Scenario: Register new <%= singular_name %>
7
7
  Given I am on the new <%= singular_name %> page
@@ -5,13 +5,17 @@ module Cucumber
5
5
  describe CLI do
6
6
 
7
7
  def mock_executor(stubs = {})
8
- stub('executor', {:visit_features => nil, :failed => false, :formatters= => nil}.merge(stubs))
8
+ stub('executor', {:visit_features => nil, :lines_for_features= => nil, :failed => false, :formatters= => nil}.merge(stubs))
9
9
  end
10
10
 
11
11
  def mock_broadcaster(stubs = {})
12
12
  stub(Broadcaster, {:register => nil}.merge(stubs))
13
13
  end
14
14
 
15
+ def mock_features(stubs ={})
16
+ stub('features', {:<< => nil}.merge(stubs))
17
+ end
18
+
15
19
  before(:each) do
16
20
  Kernel.stub!(:exit)
17
21
  end
@@ -101,6 +105,40 @@ Defined profiles in cucumber.yml:
101
105
  cli.options[:source].should be_false
102
106
  end
103
107
 
108
+ it "should accept --verbose option" do
109
+ cli = CLI.new
110
+ cli.parse_options!(%w{--verbose})
111
+
112
+ cli.options[:verbose].should be_true
113
+ end
114
+
115
+ describe "verbose mode" do
116
+
117
+ before(:each) do
118
+ @out = StringIO.new
119
+ @cli = CLI.new(@out)
120
+ @cli.stub!(:require)
121
+ Dir.stub!(:[])
122
+ end
123
+
124
+ it "should show ruby files required" do
125
+ @cli.parse_options!(%w{--verbose --require example.rb})
126
+ @cli.execute!(stub('step mother'), mock_executor, mock_features)
127
+
128
+ @out.string.should include('example.rb')
129
+ end
130
+
131
+ it "should show feature files parsed" do
132
+ TreetopParser::FeatureParser.stub!(:new).and_return(mock("feature parser", :parse_feature => nil))
133
+
134
+ @cli.parse_options!(%w{--verbose example.feature})
135
+ @cli.execute!(stub('step mother'), mock_executor, mock_features)
136
+
137
+ @out.string.should include('example.feature')
138
+ end
139
+
140
+ end
141
+
104
142
  it "should accept --out option" do
105
143
  cli = CLI.new
106
144
  File.should_receive(:open).with('jalla.txt', 'w')
@@ -180,6 +218,106 @@ Defined profiles in cucumber.yml:
180
218
  cli.execute!(stub('step mother'), mock_executor, stub('features'))
181
219
  end
182
220
 
221
+ describe "external formatter" do
222
+
223
+ describe "exists and valid constructor" do
224
+
225
+ before(:each) do
226
+ @mock_formatter_class = mock('formatter class')
227
+ Kernel.stub!(:const_get).and_return(@mock_formatter_class)
228
+ end
229
+
230
+ it "should create the formatter" do
231
+ cli = CLI.new
232
+ mock_formatter = mock('magical formatter')
233
+ cli.parse_options!(%w{--format magical})
234
+
235
+ @mock_formatter_class.should_receive(:new)
236
+
237
+ cli.execute!(stub('step mother'), mock_executor, stub('features'))
238
+ end
239
+
240
+ it "should register the formatter with broadcaster" do
241
+ cli = CLI.new
242
+ broadcaster = Broadcaster.new
243
+ mock_formatter = mock('magical formatter')
244
+ Broadcaster.stub!(:new).and_return(broadcaster, stub("output broadcaster", :register => nil))
245
+ @mock_formatter_class.stub!(:new).and_return(mock_formatter)
246
+ cli.parse_options!(%w{--format magical})
247
+
248
+ broadcaster.should_receive(:register).with(mock_formatter)
249
+
250
+ cli.execute!(stub('step mother'), mock_executor, stub('features'))
251
+ end
252
+
253
+ end
254
+
255
+ describe "exists but invalid constructor" do
256
+
257
+ before(:each) do
258
+ @out = StringIO.new
259
+ @error = StringIO.new
260
+ @cli = CLI.new(@out, @error)
261
+
262
+ mock_formatter_class = stub('formatter class')
263
+ mock_formatter_class.stub!(:new).and_raise("No such method")
264
+ Kernel.stub!(:const_get).and_return(mock_formatter_class)
265
+
266
+ @cli.parse_options!(%w{--format exists_but_evil})
267
+ end
268
+
269
+ it "should show exception" do
270
+ Kernel.stub!(:exit)
271
+
272
+ @cli.execute!(stub('step mother'), mock_executor, stub('features'))
273
+
274
+ @error.string.should include("No such method")
275
+ end
276
+
277
+ it "should exit" do
278
+ Kernel.should_receive(:exit)
279
+
280
+ @cli.execute!(stub('step mother'), mock_executor, stub('features'))
281
+ end
282
+
283
+ end
284
+
285
+ describe "non-existent" do
286
+
287
+ before(:each) do
288
+ @out = StringIO.new
289
+ @error = StringIO.new
290
+ @cli = CLI.new(@out, @error)
291
+
292
+ @cli.parse_options!(%w{--format invalid})
293
+ end
294
+
295
+ it "should display a format error" do
296
+ Kernel.stub!(:exit)
297
+
298
+ @cli.execute!(stub('step mother'), mock_executor, stub('features'))
299
+
300
+ @error.string.should include("Invalid format: invalid\n")
301
+ end
302
+
303
+ it "should display --help" do
304
+ Kernel.stub!(:exit)
305
+
306
+ @cli.execute!(stub('step mother'), mock_executor, stub('features'))
307
+
308
+ @out.string.should include("Usage: cucumber")
309
+ end
310
+
311
+ it "should exit" do
312
+ Kernel.should_receive(:exit)
313
+
314
+ @cli.execute!(stub('step mother'), mock_executor, stub('features'))
315
+ end
316
+
317
+ end
318
+
319
+ end
320
+
183
321
  it "should accept multiple --scenario options" do
184
322
  cli = CLI.new
185
323
  cli.parse_options!(['--scenario', "User logs in", '--scenario', "User signs up"])
@@ -227,6 +365,38 @@ Defined profiles in cucumber.yml:
227
365
  cli.execute!(stub('step mother'), mock_executor, stub('features'))
228
366
  end
229
367
 
368
+ describe "example.feature:line file arguments" do
369
+
370
+ it "should extract line numbers" do
371
+ cli = CLI.new
372
+ cli.parse_options!(%w{example.feature:10})
373
+
374
+ cli.options[:lines_for_features]['example.feature'].should == [10]
375
+ end
376
+
377
+ it "should remove line numbers" do
378
+ cli = CLI.new
379
+ cli.parse_options!(%w{example.feature:10})
380
+
381
+ cli.paths.should == ["example.feature"]
382
+ end
383
+
384
+ it "should support multiple feature:line numbers" do
385
+ cli = CLI.new
386
+ cli.parse_options!(%w{example.feature:11 another_example.feature:12})
387
+
388
+ cli.options[:lines_for_features].should == {'another_example.feature' => [12], 'example.feature' => [11]}
389
+ end
390
+
391
+ it "should accept multiple line numbers for a single feature" do
392
+ cli = CLI.new
393
+ cli.parse_options!(%w{example.feature:11:12})
394
+
395
+ cli.options[:lines_for_features].should == {'example.feature' => [11, 12]}
396
+ end
397
+
398
+ end
399
+
230
400
  it "should search for all features in the specified directory" do
231
401
  cli = CLI.new
232
402
 
@@ -235,7 +405,7 @@ Defined profiles in cucumber.yml:
235
405
 
236
406
  Dir.should_receive(:[]).with("feature_directory/**/*.feature").any_number_of_times.and_return([])
237
407
 
238
- cli.execute!(stub('step mother'), mock_executor, stub('features', :<< => nil))
408
+ cli.execute!(stub('step mother'), mock_executor, mock_features)
239
409
  end
240
410
 
241
411
  end
@@ -3,6 +3,17 @@ require 'stringio'
3
3
 
4
4
  module Cucumber
5
5
  describe Executor do
6
+
7
+ def mock_scenario(stubs = {})
8
+ @scenario ||= stub("scenario", {
9
+ :row? => false,
10
+ :name => 'test',
11
+ :accept => nil,
12
+ :steps => [],
13
+ :pending? => true
14
+ }.merge(stubs))
15
+ end
16
+
6
17
  before do # TODO: Way more setup and duplication of lib code. Use lib code!
7
18
  @io = StringIO.new
8
19
  @step_mother = StepMother.new
@@ -35,19 +46,47 @@ module Cucumber
35
46
 
36
47
  1)
37
48
  dang
38
- #{__FILE__}:32:in `Then /I should owe (\\d*) cucumbers/'
49
+ #{__FILE__}:43:in `Then /I should owe (\\d*) cucumbers/'
39
50
  #{@feature_file}:9:in `Then I should owe 7 cucumbers'
40
51
  })
41
52
  end
42
53
 
43
- # it "should allow calling of other steps from steps" do
44
- # @executor.register_step_proc("call me please") { @x = 1 }
45
- # @executor.register_step_proc("I will call you") { @executor.register_step_proc("call me please") }
46
- # @executor.register_step_proc(/I should owe (\d*) cucumbers/) { |n| @n.should == -n.to_i }
47
- # @feature.accept(@executor)
48
- # @formatters.each { |formatter| formatter.dump }
49
- # @io.string.should == "...\n"
50
- # end
54
+ describe "creating a world" do
55
+ module DoitExtension
56
+ def doit
57
+ "dunit"
58
+ end
59
+ end
60
+
61
+ module BeatitExtension
62
+ def beatit
63
+ "beatenit"
64
+ end
65
+ end
66
+
67
+ it "should yield an Object to the world proc" do
68
+ @executor.register_world_proc do |world|
69
+ world.extend(DoitExtension)
70
+ end
71
+ @executor.register_world_proc do |world|
72
+ world.extend(BeatitExtension)
73
+ end
74
+ world = @executor.create_world
75
+ world.doit.should == "dunit"
76
+ world.beatit.should == "beatenit"
77
+ end
78
+ end
79
+
80
+ describe "visiting feature" do
81
+
82
+ it "should set the feature file being visited" do
83
+ mock_feature = mock('feature', :file => 'womble.feature', :scenarios => [])
84
+ @executor.visit_feature(mock_feature)
85
+
86
+ @executor.instance_variable_get('@feature_file').should == 'womble.feature'
87
+ end
88
+
89
+ end
51
90
 
52
91
  describe "visiting steps" do
53
92
  def make_regex(a,b,c)
@@ -139,21 +178,22 @@ dang
139
178
  describe "without having first run the matching regular scenario" do
140
179
 
141
180
  before(:each) do
142
- @scenario = Tree::Scenario.new(nil, 'test', 1)
143
- @executor.line=5
144
- @executor.visit_regular_scenario(@scenario)
181
+ @regular_scenario = Tree::Scenario.new(nil, 'test', 1)
182
+ @executor.lines_for_features = Hash.new([5])
183
+ @executor.visit_regular_scenario(@regular_scenario)
145
184
  end
146
185
 
147
186
  it "should run the regular scenario before the row scenario" do
148
- @scenario.should_receive(:accept)
149
-
150
- @executor.visit_row_scenario(mock_row_scenario(:name => 'test', :at_line? => true, :accept => nil))
187
+ @regular_scenario.should_receive(:accept)
188
+ row_scenario = mock_row_scenario(:name => 'test', :at_line? => true)
189
+ row_scenario.should_receive(:accept)
190
+ @executor.visit_row_scenario(row_scenario)
151
191
  end
152
192
 
153
193
  it "should run the row scenario after running the regular scenario" do
154
- mock_row_scenario(:at_line? => true).should_receive(:accept)
155
-
156
- @executor.visit_row_scenario(mock_row_scenario)
194
+ row_scenario = mock_row_scenario(:at_line? => true)
195
+ row_scenario.should_receive(:accept)
196
+ @executor.visit_row_scenario(row_scenario)
157
197
  end
158
198
 
159
199
  end
@@ -172,18 +212,53 @@ dang
172
212
  end
173
213
  end
174
214
 
175
- describe "caching visited scenarios" do
215
+ describe "visiting scenarios" do
216
+
217
+ it "should check if a scenario is at the specified line number" do
218
+ mock_scenario = mock('scenario', :null_object => true)
219
+ @executor.lines_for_features = Hash.new([1])
176
220
 
177
- def mock_scenario(stubs = {})
178
- @scenario ||= stub("scenario", {
179
- :row? => false,
180
- :name => 'test',
181
- :accept => nil,
182
- :steps => [],
183
- :pending? => true
184
- }.merge(stubs))
221
+ mock_scenario.should_receive(:at_line?).with(1)
222
+
223
+ @executor.visit_scenario(mock_scenario)
185
224
  end
186
-
225
+
226
+ describe "with specific features and lines" do
227
+
228
+ it "should check if a scenario is at the specified feature line number" do
229
+ @executor.instance_variable_set('@feature_file', 'sell_cucumbers.feature')
230
+ @executor.lines_for_features = {'sell_cucumbers.feature' => [11]}
231
+
232
+ mock_scenario.should_receive(:at_line?).with(11).and_return(false)
233
+
234
+ @executor.visit_scenario(mock_scenario)
235
+ end
236
+
237
+ it "should not check feature line numbers if --line is already set" do
238
+ @executor.instance_variable_set('@feature_file', 'sell_cucumbers.feature')
239
+ @executor.lines_for_features = {'sell_cucumbers.feature' => [11]}
240
+ @executor.lines_for_features = Hash.new([5])
241
+
242
+ mock_scenario.should_not_receive(:at_line?).with(11).and_return(false)
243
+
244
+ @executor.visit_scenario(mock_scenario)
245
+ end
246
+
247
+ it "should not check feature line numbers if the current feature file does not have lines specified" do
248
+ @executor.instance_variable_set('@feature_file', 'beetlejuice.feature')
249
+ @executor.lines_for_features = {'sell_cucumbers.feature' => [11]}
250
+
251
+ mock_scenario.should_not_receive(:at_line?).with(11).and_return(false)
252
+
253
+ @executor.visit_scenario(mock_scenario)
254
+ end
255
+
256
+ end
257
+
258
+ end
259
+
260
+ describe "caching visited scenarios" do
261
+
187
262
  it "should reset cache after each feature visit" do
188
263
  Tree::Scenario.stub!(:new).and_return(mock_scenario)
189
264
 
@@ -218,5 +293,6 @@ dang
218
293
  @executor.visit_features(@features)
219
294
  end
220
295
  end
296
+
221
297
  end
222
298
  end