square-cucumber 0.3.12.2 → 0.3.93.1

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 (91) hide show
  1. data/History.txt +117 -4
  2. data/Manifest.txt +11 -0
  3. data/Rakefile +1 -1
  4. data/config/hoe.rb +3 -2
  5. data/cucumber.yml +2 -2
  6. data/examples/i18n/ko/features/addition.feature +5 -5
  7. data/examples/i18n/ko/features/step_definitons/calculator_steps.rb +1 -1
  8. data/examples/i18n/no/features/step_definitons/kalkulator_steps.rb +1 -1
  9. data/examples/i18n/pt/features/adicao.feature +4 -4
  10. data/examples/self_test/features/support/env.rb +2 -1
  11. data/examples/sinatra/features/support/env.rb +7 -1
  12. data/examples/steps_library/features/step_definitions/steps_lib1.rb +8 -0
  13. data/examples/steps_library/features/step_definitions/steps_lib2.rb +8 -0
  14. data/examples/tickets/features/step_definitons/tickets_steps.rb +15 -0
  15. data/examples/tickets/features/table_diffing.feature +13 -0
  16. data/examples/watir/features/step_definitons/search_steps.rb +5 -1
  17. data/features/cucumber_cli_diff_disabled.feature +2 -1
  18. data/features/html_formatter/a.html +5 -7
  19. data/features/junit_formatter.feature +21 -14
  20. data/features/profiles.feature +99 -0
  21. data/features/rake_task.feature +28 -0
  22. data/features/step_definitions/cucumber_steps.rb +28 -15
  23. data/features/steps_formatter.feature +25 -0
  24. data/features/support/env.rb +9 -5
  25. data/features/table_diffing.feature +45 -0
  26. data/features/unicode_table.feature +35 -0
  27. data/features/work_in_progress.feature +1 -0
  28. data/gem_tasks/contributors.rake +4 -0
  29. data/lib/cucumber/ast/background.rb +1 -0
  30. data/lib/cucumber/ast/comment.rb +1 -0
  31. data/lib/cucumber/ast/examples.rb +1 -0
  32. data/lib/cucumber/ast/feature.rb +10 -0
  33. data/lib/cucumber/ast/features.rb +6 -1
  34. data/lib/cucumber/ast/outline_table.rb +4 -1
  35. data/lib/cucumber/ast/py_string.rb +1 -1
  36. data/lib/cucumber/ast/scenario.rb +1 -0
  37. data/lib/cucumber/ast/scenario_outline.rb +2 -0
  38. data/lib/cucumber/ast/step.rb +5 -1
  39. data/lib/cucumber/ast/step_collection.rb +1 -0
  40. data/lib/cucumber/ast/step_invocation.rb +1 -0
  41. data/lib/cucumber/ast/table.rb +306 -52
  42. data/lib/cucumber/ast/tags.rb +1 -0
  43. data/lib/cucumber/ast/visitor.rb +2 -1
  44. data/lib/cucumber/cli/configuration.rb +28 -278
  45. data/lib/cucumber/cli/drb_client.rb +3 -1
  46. data/lib/cucumber/cli/language_help_formatter.rb +9 -7
  47. data/lib/cucumber/cli/main.rb +16 -2
  48. data/lib/cucumber/cli/options.rb +370 -0
  49. data/lib/cucumber/cli/profile_loader.rb +65 -0
  50. data/lib/cucumber/core_ext/instance_exec.rb +8 -5
  51. data/lib/cucumber/feature_file.rb +7 -1
  52. data/lib/cucumber/filter.rb +2 -2
  53. data/lib/cucumber/formatter/ansicolor.rb +42 -9
  54. data/lib/cucumber/formatter/console.rb +1 -1
  55. data/lib/cucumber/formatter/html.rb +12 -10
  56. data/lib/cucumber/formatter/junit.rb +63 -26
  57. data/lib/cucumber/formatter/pretty.rb +20 -5
  58. data/lib/cucumber/formatter/progress.rb +1 -1
  59. data/lib/cucumber/formatter/steps.rb +49 -0
  60. data/lib/cucumber/languages.yml +6 -6
  61. data/lib/cucumber/parser/feature.rb +90 -63
  62. data/lib/cucumber/parser/feature.tt +28 -1
  63. data/lib/cucumber/parser/i18n/language.rb +12 -5
  64. data/lib/cucumber/parser/table.rb +25 -25
  65. data/lib/cucumber/rake/task.rb +9 -3
  66. data/lib/cucumber/step_definition.rb +1 -1
  67. data/lib/cucumber/step_match.rb +1 -1
  68. data/lib/cucumber/step_mother.rb +3 -1
  69. data/lib/cucumber/version.rb +2 -2
  70. data/lib/cucumber/webrat/table_locator.rb +66 -0
  71. data/rails_generators/cucumber/cucumber_generator.rb +5 -1
  72. data/rails_generators/cucumber/templates/cucumber +3 -2
  73. data/rails_generators/cucumber/templates/cucumber.rake +18 -6
  74. data/rails_generators/cucumber/templates/cucumber_environment.rb +7 -4
  75. data/rails_generators/cucumber/templates/env.rb +1 -0
  76. data/rails_generators/cucumber/templates/spork_env.rb +1 -0
  77. data/rails_generators/cucumber/templates/webrat_steps.rb +22 -0
  78. data/rails_generators/feature/templates/feature.erb +1 -1
  79. data/rails_generators/feature/templates/steps.erb +2 -8
  80. data/spec/cucumber/ast/table_spec.rb +169 -0
  81. data/spec/cucumber/cli/configuration_spec.rb +144 -101
  82. data/spec/cucumber/cli/main_spec.rb +14 -5
  83. data/spec/cucumber/cli/options_spec.rb +311 -0
  84. data/spec/cucumber/cli/profile_loader_spec.rb +10 -0
  85. data/spec/cucumber/core_ext/proc_spec.rb +16 -2
  86. data/spec/cucumber/formatter/html_spec.rb +18 -0
  87. data/spec/cucumber/formatter/progress_spec.rb +2 -2
  88. data/spec/cucumber/parser/table_parser_spec.rb +1 -1
  89. data/spec/spec.opts +3 -1
  90. metadata +18 -4
  91. data/lib/cucumber/webrat/mechanize_world.rb +0 -82
@@ -13,13 +13,13 @@ module Cucumber
13
13
  @out = StringIO.new
14
14
  @err = StringIO.new
15
15
  Kernel.stub!(:exit).and_return(nil)
16
+ File.stub!(:exist?).and_return(false) # When Configuration checks for cucumber.yml
16
17
  end
17
18
 
18
19
  describe "verbose mode" do
19
20
 
20
21
  before(:each) do
21
22
  @empty_feature = Ast::Feature.new(nil, Ast::Comment.new(''), Ast::Tags.new(2, []), "Feature", [])
22
- Dir.stub!(:[])
23
23
  end
24
24
 
25
25
  it "should show ruby files required" do
@@ -94,6 +94,19 @@ module Cucumber
94
94
  end
95
95
  end
96
96
 
97
+ [ProfilesNotDefinedError, YmlLoadError, ProfileNotFound].each do |exception_klass|
98
+
99
+ it "rescues #{exception_klass}, prints the message to the error stream and returns true" do
100
+ Configuration.stub!(:new).and_return(configuration = mock('configuration'))
101
+ configuration.stub!(:parse!).and_raise(exception_klass.new("error message"))
102
+
103
+ main = Main.new('', out = StringIO.new, error = StringIO.new)
104
+ main.execute!(Object.new.extend(StepMother)).should be_true
105
+ error.string.should == "error message\n"
106
+ end
107
+ end
108
+
109
+
97
110
  context "--drb" do
98
111
  before(:each) do
99
112
  @configuration = mock('Configuration', :drb? => true, :null_object => true)
@@ -129,10 +142,6 @@ module Cucumber
129
142
  @err.string.should include("WARNING: error message. Running features locally:")
130
143
  end
131
144
 
132
- it "reparses the configuration since the --drb flag causes the initial parsing to short circuit" do
133
- @configuration.should_receive(:parse!).exactly(:twice)
134
- @cli.execute!(@step_mother)
135
- end
136
145
  end
137
146
  end
138
147
  end
@@ -0,0 +1,311 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+ require 'yaml'
3
+
4
+ module Cucumber
5
+ module Cli
6
+ describe Options do
7
+
8
+ def given_cucumber_yml_defined_as(hash_or_string)
9
+ File.stub!(:exist?).and_return(true)
10
+ cucumber_yml = hash_or_string.is_a?(Hash) ? hash_or_string.to_yaml : hash_or_string
11
+ IO.stub!(:read).with('cucumber.yml').and_return(cucumber_yml)
12
+ end
13
+
14
+ before(:each) do
15
+ File.stub!(:exist?).and_return(false) # Meaning, no cucumber.yml exists
16
+ Kernel.stub!(:exit).and_return(nil)
17
+ end
18
+
19
+ def output_stream
20
+ @output_stream ||= StringIO.new
21
+ end
22
+
23
+ def error_stream
24
+ @error_stream ||= StringIO.new
25
+ end
26
+
27
+ def options
28
+ @options ||= Options.new(output_stream, error_stream)
29
+ end
30
+
31
+ def prepare_args(args)
32
+ args.is_a?(Array) ? args : args.split(' ')
33
+ end
34
+
35
+ describe 'parsing' do
36
+
37
+ def when_parsing(args)
38
+ yield
39
+ options.parse!(prepare_args(args))
40
+ end
41
+
42
+ def after_parsing(args)
43
+ options.parse!(prepare_args(args))
44
+ yield
45
+ end
46
+
47
+ context '-r or --require' do
48
+ it "collects all specified files into an array" do
49
+ after_parsing ('--require some_file.rb -r another_file.rb') do
50
+ options[:require].should == ['some_file.rb', 'another_file.rb']
51
+ end
52
+ end
53
+ end
54
+
55
+ context '-l LANG or --language LANG' do
56
+ context "with LANG specified as 'help'" do
57
+ it "lists all known langues" do
58
+ when_parsing '-l help' do
59
+ LanguageHelpFormatter.should_receive(:list_languages).with(output_stream)
60
+ end
61
+ end
62
+ it "exits the program" do
63
+ when_parsing('--language help') { Kernel.should_receive(:exit) }
64
+ end
65
+ end
66
+ it "sets the langauge" do
67
+ after_parsing('-l en') { options[:lang].should == 'en' }
68
+ end
69
+ end
70
+
71
+ context '-f FORMAT or --format FORMAT' do
72
+ it "defaults the output for the formatter to the output stream (STDOUT)" do
73
+ after_parsing('-f pretty') { options[:formats].should == [['pretty', output_stream]] }
74
+ end
75
+ end
76
+
77
+ context '-o [FILE|DIR] or --out [FILE|DIR]' do
78
+ it "defaults the formatter to 'pretty' when not specified earlier" do
79
+ after_parsing('-o file.txt') { options[:formats].should == [['pretty', 'file.txt']] }
80
+ end
81
+ it "sets the output for the formatter defined immediatly before it" do
82
+ after_parsing('-f profile --out file.txt -f pretty -o file2.txt') do
83
+ options[:formats].should == [['profile', 'file.txt'], ['pretty', 'file2.txt']]
84
+ end
85
+ end
86
+ end
87
+
88
+ context '-t TAGS --tags TAGS' do
89
+ it "removes the @ prefix" do
90
+ after_parsing('-t @foo,bar') { options[:include_tags].should == ['foo','bar'] }
91
+ end
92
+ it "designates tags prefixed with ~ as tags to be excluded" do
93
+ after_parsing('--tags ~@foo,bar') { options[:exclude_tags].should == ['foo'] }
94
+ end
95
+ end
96
+
97
+ context '-n NAME or --name NAME' do
98
+ it "stores the provided names as regular expressions" do
99
+ after_parsing('-n foo --name bar') { options[:name_regexps].should == [/foo/,/bar/] }
100
+ end
101
+ end
102
+
103
+ context '-e PATTERN or --exclude PATTERN' do
104
+ it "stores the provided exclusions as regular expressions" do
105
+ after_parsing('-e foo --exclude bar') { options[:excludes].should == [/foo/,/bar/] }
106
+ end
107
+ end
108
+
109
+ context '-p PROFILE or --profile PROFILE' do
110
+
111
+ it "notifies the user that an individual profile is being used" do
112
+ given_cucumber_yml_defined_as({'foo' => [1,2,3]})
113
+ options.parse!(%w{--profile foo})
114
+ output_stream.string.should =~ /Using the foo profile...\n/
115
+ end
116
+
117
+ it "notifies the user when multiple profiles are being used" do
118
+ given_cucumber_yml_defined_as({'foo' => [1,2,3], 'bar' => ['v'], 'dog' => ['v']})
119
+ options.parse!(%w{--profile foo --profile bar --profile dog})
120
+ output_stream.string.should =~ /Using the foo, bar and dog profiles...\n/
121
+ end
122
+
123
+ it "notifies the user of all profiles being used, even when they are nested" do
124
+ given_cucumber_yml_defined_as('foo' => '-p bar', 'bar' => 'features')
125
+ after_parsing('-p foo') do
126
+ output_stream.string.should =~ /Using the foo and bar profiles.../
127
+ end
128
+ end
129
+
130
+ it "uses the default profile passed in during initialization if none are specified by the user" do
131
+ given_cucumber_yml_defined_as({'default' => '--require some_file'})
132
+
133
+ options = Options.new(output_stream, error_stream, :default_profile => 'default')
134
+ options.parse!(%w{--format progress})
135
+ options[:require].should include('some_file')
136
+ end
137
+
138
+ it "merges all uniq values from both cmd line and the profile" do
139
+ given_cucumber_yml_defined_as('foo' => %w[--verbose])
140
+ options.parse!(%w[--wip --profile foo])
141
+ options[:wip].should be_true
142
+ options[:verbose].should be_true
143
+ end
144
+
145
+ it "gives precendene to the origianl options' paths" do
146
+ given_cucumber_yml_defined_as('foo' => %w[features])
147
+ options.parse!(%w[my.feature -p foo])
148
+ options[:paths].should == %w[my.feature]
149
+ end
150
+
151
+ it "combines the require files of both" do
152
+ given_cucumber_yml_defined_as('bar' => %w[--require features -r dog.rb])
153
+ options.parse!(%w[--require foo.rb -p bar])
154
+ options[:require].should == %w[foo.rb features dog.rb]
155
+ end
156
+
157
+ it "combines the include_tags of both" do
158
+ given_cucumber_yml_defined_as('baz' => %w[-t bar])
159
+ options.parse!(%w[--tags foo -p baz])
160
+ options[:include_tags].should == %w[foo bar]
161
+ end
162
+
163
+ it "combines the exclude_tags of both" do
164
+ given_cucumber_yml_defined_as('baz' => %w[-t ~bar])
165
+ options.parse!(%w[--tags ~foo -p baz])
166
+ options[:exclude_tags].should == %w[foo bar]
167
+ end
168
+
169
+ it "only takes the paths from the original options, and disgregards the profiles" do
170
+ given_cucumber_yml_defined_as('baz' => %w[features])
171
+ options.parse!(%w[my.feature -p baz])
172
+ options[:paths].should == ['my.feature']
173
+ end
174
+
175
+ it "uses the paths from the profile when none are specified originally" do
176
+ given_cucumber_yml_defined_as('baz' => %w[some.feature])
177
+ options.parse!(%w[-p baz])
178
+ options[:paths].should == ['some.feature']
179
+ end
180
+
181
+ it "combines environment variables from the profile but gives precendene to cmd line args" do
182
+ given_cucumber_yml_defined_as('baz' => %w[FOO=bar CHEESE=swiss])
183
+ options.parse!(%w[-p baz CHEESE=cheddar BAR=foo])
184
+ options[:env_vars].should == {'BAR' => 'foo', 'FOO' => 'bar', 'CHEESE' => 'cheddar'}
185
+ end
186
+
187
+ it "disregards STDOUT formatter defined in profile when another is passed in (via cmd line)" do
188
+ given_cucumber_yml_defined_as({'foo' => %w[--format pretty]})
189
+ options.parse!(%w{--format progress --profile foo})
190
+ options[:formats].should == [['progress', output_stream]]
191
+ end
192
+
193
+ it "includes any non-STDOUT formatters from the profile" do
194
+ given_cucumber_yml_defined_as({'html' => %w[--format html -o features.html]})
195
+ options.parse!(%w{--format progress --profile html})
196
+ options[:formats].should == [['progress', output_stream], ['html', 'features.html']]
197
+ end
198
+
199
+ it "assumes all of the formatters defined in the profile when none are specified on cmd line" do
200
+ given_cucumber_yml_defined_as({'html' => %w[--format progress --format html -o features.html]})
201
+ options.parse!(%w{--profile html})
202
+ options[:formats].should == [['progress', output_stream], ['html', 'features.html']]
203
+ end
204
+
205
+ it "respects --quiet when defined in the profile" do
206
+ given_cucumber_yml_defined_as('foo' => '-q')
207
+ options.parse!(%w[-p foo])
208
+ options[:snippets].should be_false
209
+ options[:source].should be_false
210
+ end
211
+
212
+ end
213
+
214
+ context '-P or --no-profile' do
215
+
216
+ it "disables profiles" do
217
+ given_cucumber_yml_defined_as({'default' => '-v --require file_specified_in_default_profile.rb'})
218
+
219
+ after_parsing("-P --require some_file.rb") do
220
+ options[:require].should == ['some_file.rb']
221
+ end
222
+ end
223
+
224
+ it "notifies the user that the profiles are being disabled" do
225
+ given_cucumber_yml_defined_as({'default' => '-v'})
226
+
227
+ after_parsing("--no-profile --require some_file.rb") do
228
+ output_stream.string.should =~ /Disabling profiles.../
229
+ end
230
+ end
231
+
232
+ end
233
+
234
+ context '-b or --backtrace' do
235
+ it "turns on cucumber's full backtrace" do
236
+ when_parsing("-b") do
237
+ Exception.should_receive(:cucumber_full_backtrace=).with(true)
238
+ end
239
+ end
240
+ end
241
+
242
+ context '--version' do
243
+ it "displays Cucumber's version" do
244
+ after_parsing('--version') do
245
+ output_stream.string.should =~ /#{VERSION::STRING}/
246
+ end
247
+ end
248
+ it "exits the program" do
249
+ when_parsing('--version') { Kernel.should_receive(:exit) }
250
+ end
251
+ end
252
+
253
+ context 'environment variables (i.e. MODE=webrat)' do
254
+ it "places all of the environment variables into a hash" do
255
+ after_parsing('MODE=webrat FOO=bar') do
256
+ options[:env_vars].should == {'MODE' => 'webrat', 'FOO' => 'bar'}
257
+ end
258
+ end
259
+ end
260
+
261
+ it "assigns any extra arguments as paths to features" do
262
+ after_parsing('-f pretty my_feature.feature my_other_features') do
263
+ options[:paths].should == ['my_feature.feature', 'my_other_features']
264
+ end
265
+ end
266
+
267
+ it "does not mistake environment variables as feature paths" do
268
+ after_parsing('my_feature.feature FOO=bar') do
269
+ options[:paths].should == ['my_feature.feature']
270
+ end
271
+ end
272
+ end
273
+
274
+ describe '#expanded_args_without_drb' do
275
+ it "returns the orginal args in additon to the args from any profiles" do
276
+ given_cucumber_yml_defined_as('foo' => '-v',
277
+ 'bar' => '--wip -p baz',
278
+ 'baz' => '-r some_file.rb')
279
+ options.parse!(%w[features -p foo --profile bar])
280
+
281
+ options.expanded_args_without_drb.should == %w[features -v --wip -r some_file.rb]
282
+ end
283
+
284
+ it "removes the --drb flag so that the args can be safely passed to the drb server" do
285
+ given_cucumber_yml_defined_as('default' => 'features -f pretty --drb')
286
+ options.parse!(%w[--profile default])
287
+
288
+ options.expanded_args_without_drb.should == %w[features -f pretty]
289
+ end
290
+
291
+ it "contains the environment variables" do
292
+ options.parse!(%w[features FOO=bar])
293
+ options.expanded_args_without_drb.should == %w[features FOO=bar]
294
+ end
295
+
296
+ it "ignores the paths from the profiles if one was specified on the command line" do
297
+ given_cucumber_yml_defined_as('foo' => 'features --drb')
298
+ options.parse!(%w[some_feature.feature -p foo])
299
+ options.expanded_args_without_drb.should == %w[some_feature.feature]
300
+ end
301
+
302
+
303
+
304
+
305
+ end
306
+
307
+ end
308
+
309
+ end
310
+ end
311
+
@@ -0,0 +1,10 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+ require 'yaml'
3
+
4
+ module Cucumber
5
+ module Cli
6
+ describe ProfileLoader do
7
+ it "should have all of its specs migrated from configuration_spec"
8
+ end
9
+ end
10
+ end
@@ -36,7 +36,7 @@ describe Proc do
36
36
  end
37
37
 
38
38
  if Cucumber::RUBY_1_9
39
- it "should allow varargs" do
39
+ it "should allow varargs (expecting 0+)" do
40
40
  lambda {
41
41
  Object.new.cucumber_instance_exec(true, 'foo', 1) do |*args|
42
42
  end
@@ -44,11 +44,25 @@ describe Proc do
44
44
  end
45
45
  else
46
46
  # Ruby 1.8
47
- it "should not allow varargs because Ruby 1.8 reports same arity as with no args, so we can't really tell the difference." do
47
+ it "should not allow varargs 0+ because Ruby 1.8 reports same arity as with no args, so we can't really tell the difference." do
48
48
  lambda {
49
49
  Object.new.cucumber_instance_exec(true, 'foo', 1) do |*args|
50
50
  end
51
51
  }.should raise_error(Cucumber::ArityMismatchError, "Your block takes 0 arguments, but the Regexp matched 1 argument.")
52
52
  end
53
53
  end
54
+
55
+ it "should allow varargs (expecting 1+)" do
56
+ lambda {
57
+ Object.new.cucumber_instance_exec(true, 'foo', 1) do |arg,*args|
58
+ end
59
+ }.should_not raise_error(Cucumber::ArityMismatchError)
60
+ end
61
+
62
+ it "should raise ArityMismatchError for too few required args when using varargs (expecting 1+)" do
63
+ lambda {
64
+ Object.new.cucumber_instance_exec(true, nil) do |arg,*args|
65
+ end
66
+ }.should raise_error(Cucumber::ArityMismatchError, "Your block takes 1+ arguments, but the Regexp matched 0 arguments.")
67
+ end
54
68
  end
@@ -0,0 +1,18 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+ require 'cucumber/formatter/html'
3
+
4
+ module Cucumber
5
+ module Formatter
6
+ describe Html do
7
+ before(:each) do
8
+ @out = StringIO.new
9
+ @html = Html.new(mock("step mother"), @out, {})
10
+ end
11
+
12
+ it "should not raise an error when visiting a blank feature name" do
13
+ lambda { @html.visit_feature_name("") }.should_not raise_error
14
+ end
15
+ end
16
+ end
17
+ end
18
+
@@ -17,7 +17,7 @@ module Cucumber
17
17
  describe "visiting a table cell value without a status" do
18
18
  it "should take the status from the last run step" do
19
19
  @progress.visit_step_result('', '', nil, :failed, nil, 10, nil)
20
- @progress.visit_table_cell_value('value', 10, nil)
20
+ @progress.visit_table_cell_value('value', nil)
21
21
 
22
22
  @out.string.should == "FF"
23
23
  end
@@ -25,7 +25,7 @@ module Cucumber
25
25
 
26
26
  describe "visiting a table cell which is a table header" do
27
27
  it "should not output anything" do
28
- @progress.visit_table_cell_value('value', 10, :skipped_param)
28
+ @progress.visit_table_cell_value('value', :skipped_param)
29
29
 
30
30
  @out.string.should == ""
31
31
  end
@@ -45,4 +45,4 @@ module Cucumber
45
45
  end
46
46
  end
47
47
  end
48
- end
48
+ end