cucumber 0.3.98 → 0.3.99

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/History.txt CHANGED
@@ -1,3 +1,12 @@
1
+ == 0.3.99 2009-09-03
2
+
3
+ === New Features
4
+ * Support for Croatian (Bkrsta)
5
+ * Make #feature available from scenario so you can do: Before{|scenario| scenario.feature}. (Aslak Hellesøy)
6
+ * cucumber.yml parsing supports ERB syntax (#427 Gregory Hnatiuk)
7
+ * New AfterConfiguration hook added; a block can be specified that takes Cucumber::Cli::Configuration (#423 Brent Snook)
8
+ * Cucumber::Cli::Configuration#feature_dirs and #out_stream exposed as public attributes so that they may be used in AfterConfiguration hook (#423 Brent Snook)
9
+
1
10
  == 0.3.98 2009-08-25
2
11
 
3
12
  Just a small release to help Cuke4Duke, which will be presented at Agile2009
data/Manifest.txt CHANGED
@@ -269,6 +269,7 @@ features/html_formatter/a.html
269
269
  features/junit_formatter.feature
270
270
  features/language_from_header.feature
271
271
  features/multiline_names.feature
272
+ features/post_configuration_hook.feature
272
273
  features/profiles.feature
273
274
  features/rake_task.feature
274
275
  features/report_called_undefined_steps.feature
@@ -0,0 +1,37 @@
1
+ Feature: Post Configuration Hook [#423]
2
+
3
+ In order to extend Cucumber
4
+ As a developer
5
+ I want to manipulate the Cucumber configuration after it has been created
6
+
7
+ Scenario: configuration modified to use HTML formatter
8
+
9
+ Given a standard Cucumber project directory structure
10
+ And a file named "features/support/env.rb" with:
11
+ """
12
+ AfterConfiguration do |config|
13
+ config.options[:formats] << ['html', config.out_stream]
14
+ end
15
+ """
16
+ When I run cucumber features
17
+ Then STDERR should be empty
18
+ And the output should contain
19
+ """
20
+ html
21
+ """
22
+
23
+ Scenario: feature directories read from configuration
24
+
25
+ Given a standard Cucumber project directory structure
26
+ And a file named "features/support/env.rb" with:
27
+ """
28
+ AfterConfiguration do |config|
29
+ config.out_stream << "AfterConfiguration hook read feature directories: #{config.feature_dirs}"
30
+ end
31
+ """
32
+ When I run cucumber features
33
+ Then STDERR should be empty
34
+ And the output should contain
35
+ """
36
+ AfterConfiguration hook read feature directories: features
37
+ """
@@ -30,6 +30,19 @@ Feature: Profiles
30
30
  """
31
31
  And exactly these files should be loaded: features/support/super_env.rb
32
32
 
33
+ Scenario: Explicitly defining a profile defined in an ERB formatted file
34
+ Given the following profiles are defined:
35
+ """
36
+ <% requires = "--require features/support/super_env.rb" %>
37
+ super: <%= "features/sample.feature #{requires} -v" %>
38
+ """
39
+ When I run cucumber features/sample.feature --profile super
40
+ Then the output should contain
41
+ """
42
+ Using the super profile...
43
+ """
44
+ And exactly these files should be loaded: features/support/super_env.rb
45
+
33
46
  Scenario: Defining multiple profiles to run
34
47
  When I run cucumber features/sample.feature --profile default --profile super
35
48
  Then the output should contain
@@ -96,7 +96,7 @@ module Autotest::CucumberMixin
96
96
  $stdout.sync = old_sync
97
97
  end
98
98
  self.features_to_run = dirty_features_file.read.strip
99
- self.tainted = true unless self.features_to_run == []
99
+ self.tainted = true unless self.features_to_run == ''
100
100
  end
101
101
  hook :ran_features
102
102
  end
@@ -122,4 +122,4 @@ module Autotest::CucumberMixin
122
122
 
123
123
  return "#{Cucumber::RUBY_BINARY} #{Cucumber::BINARY} #{args}"
124
124
  end
125
- end
125
+ end
@@ -2,7 +2,7 @@ require 'enumerator'
2
2
 
3
3
  module Cucumber
4
4
  module FeatureElement #:nodoc:
5
- attr_writer :feature
5
+ attr_accessor :feature
6
6
 
7
7
  def attach_steps(steps)
8
8
  steps.each {|step| step.feature_element = self}
@@ -10,7 +10,7 @@ module Cucumber
10
10
  class Configuration
11
11
  include Constantize
12
12
 
13
- attr_reader :options
13
+ attr_reader :options, :out_stream
14
14
 
15
15
  def initialize(out_stream = STDOUT, error_stream = STDERR)
16
16
  @out_stream = out_stream
@@ -94,21 +94,29 @@ module Cucumber
94
94
  end
95
95
  end
96
96
 
97
- def step_defs_to_load
97
+ def all_files_to_load
98
98
  requires = @options[:require].empty? ? require_dirs : @options[:require]
99
99
  files = requires.map do |path|
100
100
  path = path.gsub(/\\/, '/') # In case we're on windows. Globs don't work with backslashes.
101
101
  path = path.gsub(/\/$/, '') # Strip trailing slash.
102
102
  File.directory?(path) ? Dir["#{path}/**/*"] : path
103
103
  end.flatten.uniq
104
- sorted_files = files.sort { |a,b| (b =~ %r{/support/} || -1) <=> (a =~ %r{/support/} || -1) }.reject{|f| f =~ /^http/}
105
- env_files = sorted_files.select {|f| f =~ %r{/support/env\..*} }
106
- files = env_files + sorted_files.reject {|f| f =~ %r{/support/env\..*} }
107
104
  remove_excluded_files_from(files)
108
105
  files.reject! {|f| !File.file?(f)}
109
106
  files.reject! {|f| File.extname(f) == '.feature' }
110
- files.reject! {|f| f =~ %r{/support/env\..*} } if @options[:dry_run]
111
- files
107
+ files.reject! {|f| f =~ /^http/}
108
+ files
109
+ end
110
+
111
+ def step_defs_to_load
112
+ all_files_to_load.reject {|f| f =~ %r{/support/} }
113
+ end
114
+
115
+ def support_to_load
116
+ support_files = all_files_to_load.select {|f| f =~ %r{/support/} }
117
+ env_files = support_files.select {|f| f =~ %r{/support/env\..*} }
118
+ other_files = support_files - env_files
119
+ @options[:dry_run] ? other_files : env_files + other_files
112
120
  end
113
121
 
114
122
  def feature_files
@@ -120,6 +128,10 @@ module Cucumber
120
128
  remove_excluded_files_from(potential_feature_files)
121
129
  potential_feature_files
122
130
  end
131
+
132
+ def feature_dirs
133
+ paths.map { |f| File.directory?(f) ? f : File.dirname(f) }.uniq
134
+ end
123
135
 
124
136
  private
125
137
 
@@ -136,8 +148,9 @@ module Cucumber
136
148
  def arrange_formats
137
149
  @options[:formats] << ['pretty', @out_stream] if @options[:formats].empty?
138
150
  @options[:formats] = @options[:formats].sort_by{|f| f[1] == @out_stream ? -1 : 1}
139
- if @options[:formats].length > 1 && @options[:formats][1][1] == @out_stream
140
- raise "All but one formatter must use --out, only one can print to STDOUT"
151
+ streams = @options[:formats].map { |(_, stream)| stream }
152
+ if streams != streams.uniq
153
+ raise "All but one formatter must use --out, only one can print to each stream (or STDOUT)"
141
154
  end
142
155
  end
143
156
 
@@ -145,10 +158,6 @@ module Cucumber
145
158
  files.reject! {|path| @options[:excludes].detect {|pattern| path =~ pattern } }
146
159
  end
147
160
 
148
- def feature_dirs
149
- paths.map { |f| File.directory?(f) ? f : File.dirname(f) }.uniq
150
- end
151
-
152
161
  def require_dirs
153
162
  feature_dirs + Dir['vendor/{gems,plugins}/*/cucumber']
154
163
  end
@@ -53,10 +53,8 @@ module Cucumber
53
53
  logger.level = Logger::DEBUG if configuration.verbose?
54
54
  step_mother.log = logger
55
55
 
56
- # Feature files must be loaded before files are required.
57
- # This is because i18n step methods are only aliased when
58
- # features are loaded. If we swap the order, the requires
59
- # will fail.
56
+ step_mother.load_code_files(configuration.support_to_load)
57
+ step_mother.after_configuration(configuration)
60
58
  features = step_mother.load_plain_text_features(configuration.feature_files)
61
59
  step_mother.load_code_files(configuration.step_defs_to_load)
62
60
  enable_diffing
@@ -43,9 +43,16 @@ Defined profiles in cucumber.yml:
43
43
  raise(ProfilesNotDefinedError,"cucumber.yml was not found. Please refer to cucumber's documentation on defining profiles in cucumber.yml. You must define a 'default' profile to use the cucumber command without any arguments.\nType 'cucumber --help' for usage.\n")
44
44
  end
45
45
 
46
+ require 'erb'
46
47
  require 'yaml'
48
+ begin
49
+ @cucumber_erb = ERB.new(IO.read('cucumber.yml')).result
50
+ rescue Exception => e
51
+ raise(YmlLoadError,"cucumber.yml was found, but could not be parsed with ERB. Please refer to cucumber's documentation on correct profile usage.\n#{$!.inspect}")
52
+ end
53
+
47
54
  begin
48
- @cucumber_yml = YAML::load(IO.read('cucumber.yml'))
55
+ @cucumber_yml = YAML::load(@cucumber_erb)
49
56
  rescue StandardError => e
50
57
  raise(YmlLoadError,"cucumber.yml was found, but could not be parsed. Please refer to cucumber's documentation on correct profile usage.\n")
51
58
  end
@@ -10,6 +10,12 @@ module Cucumber
10
10
  execute_after(scenario)
11
11
  end_scenario
12
12
  end
13
+
14
+ def after_configuration(configuration)
15
+ hooks[:after_configuration].each do |hook|
16
+ hook.invoke('AfterConfiguration', configuration)
17
+ end
18
+ end
13
19
 
14
20
  def execute_after_step(scenario)
15
21
  hooks_for(:after_step, scenario).each do |hook|
@@ -1,3 +1,5 @@
1
+ require 'cucumber/core_ext/string'
2
+
1
3
  module Cucumber
2
4
  module LanguageSupport
3
5
  module StepDefinitionMethods
@@ -251,6 +251,21 @@
251
251
  and: וגם
252
252
  but: אבל
253
253
  space_after_keyword: true
254
+ "hr":
255
+ name: Croatian
256
+ native: hrvatski
257
+ encoding: UTF-8
258
+ feature: Osobina|Mogućnost|Mogucnost
259
+ background: Pozadina
260
+ scenario: Scenarij
261
+ scenario_outline: Skica|Koncept
262
+ examples: Primjeri|Scenariji
263
+ given: Zadan|Zadani|Zadano
264
+ when: Kada|Kad
265
+ then: Onda
266
+ and: I
267
+ but: Ali
268
+ space_after_keyword: true
254
269
  "hu":
255
270
  name: Hungarian
256
271
  native: magyar
@@ -65,6 +65,12 @@ module Cucumber
65
65
  def AfterStep(*tag_names, &proc)
66
66
  RbDsl.register_rb_hook('after_step', tag_names, proc)
67
67
  end
68
+
69
+ # Registers a proc that will run after Cucumber is configured. You can register as
70
+ # as you want (typically from ruby scripts under <tt>support/hooks.rb</tt>).
71
+ def AfterConfiguration(&proc)
72
+ RbDsl.register_rb_hook('after_configuration', [], proc)
73
+ end
68
74
 
69
75
  # Registers a new Ruby StepDefinition. This method is aliased
70
76
  # to <tt>Given</tt>, <tt>When</tt> and <tt>Then</tt>, and
@@ -10,8 +10,8 @@ module Cucumber
10
10
  @proc = proc
11
11
  end
12
12
 
13
- def invoke(location, scenario)
14
- @rb_language.current_world.cucumber_instance_exec(false, location, scenario, &@proc)
13
+ def invoke(location, argument)
14
+ @rb_language.current_world.cucumber_instance_exec(false, location, argument, &@proc)
15
15
  end
16
16
  end
17
17
  end
@@ -233,6 +233,12 @@ module Cucumber
233
233
  end
234
234
  end
235
235
 
236
+ def after_configuration(configuration) #:nodoc
237
+ @programming_languages.each do |programming_language|
238
+ programming_language.after_configuration(configuration)
239
+ end
240
+ end
241
+
236
242
  private
237
243
 
238
244
  # Registers a StepDefinition. This can be a Ruby StepDefintion,
@@ -2,7 +2,7 @@ module Cucumber #:nodoc:
2
2
  class VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 3
5
- TINY = 98
5
+ TINY = 99
6
6
  PATCH = nil # Set to nil for official release
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PATCH].compact.join('.')
@@ -7,12 +7,12 @@ begin
7
7
  namespace :cucumber do
8
8
  Cucumber::Rake::Task.new({:ok => 'db:test:prepare'}, 'Run features that should pass') do |t|
9
9
  t.fork = true # You may get faster startup if you set this to false
10
- t.cucumber_opts = "--tags ~@wip --strict --format #{ENV['CUCUMBER_FORMAT'] || 'pretty'}<%= spork? ? ' --drb' : '' %>"
10
+ t.cucumber_opts = "--color --tags ~@wip --strict --format #{ENV['CUCUMBER_FORMAT'] || 'pretty'}<%= spork? ? ' --drb' : '' %>"
11
11
  end
12
12
 
13
13
  Cucumber::Rake::Task.new({:wip => 'db:test:prepare'}, 'Run features that are being worked on') do |t|
14
14
  t.fork = true # You may get faster startup if you set this to false
15
- t.cucumber_opts = "--tags @wip:2 --wip --format #{ENV['CUCUMBER_FORMAT'] || 'pretty'}<%= spork? ? ' --drb' : '' %>"
15
+ t.cucumber_opts = "--color --tags @wip:2 --wip --format #{ENV['CUCUMBER_FORMAT'] || 'pretty'}<%= spork? ? ' --drb' : '' %>"
16
16
  end
17
17
 
18
18
  desc 'Run all features'
@@ -18,7 +18,6 @@ module Cli
18
18
  end
19
19
 
20
20
  before(:each) do
21
- #given_cucumber_yml_defined_as({'default' => '-q'})
22
21
  File.stub!(:exist?).and_return(false) # Meaning, no cucumber.yml exists
23
22
  Kernel.stub!(:exit).and_return(nil)
24
23
  end
@@ -33,24 +32,12 @@ module Cli
33
32
 
34
33
  attr_reader :out, :error
35
34
 
36
-
37
- it "should require files in support paths first" do
38
- given_the_following_files("/features/step_definitions/foo.rb","/features/support/bar.rb")
39
-
40
- config.parse!(%w{--require /features})
41
-
42
- config.step_defs_to_load.should == [
43
- "/features/support/bar.rb",
44
- "/features/step_definitions/foo.rb"
45
- ]
46
- end
47
-
48
35
  it "should require env.rb files first" do
49
36
  given_the_following_files("/features/support/a_file.rb","/features/support/env.rb")
50
37
 
51
38
  config.parse!(%w{--require /features})
52
39
 
53
- config.step_defs_to_load.should == [
40
+ config.support_to_load.should == [
54
41
  "/features/support/env.rb",
55
42
  "/features/support/a_file.rb"
56
43
  ]
@@ -61,7 +48,7 @@ module Cli
61
48
 
62
49
  config.parse!(%w{--require /features --dry-run})
63
50
 
64
- config.step_defs_to_load.should == [
51
+ config.support_to_load.should == [
65
52
  "/features/support/a_file.rb"
66
53
  ]
67
54
  end
@@ -85,7 +72,7 @@ module Cli
85
72
 
86
73
  config.parse!(%w{--require /features --exclude a_file.rb})
87
74
 
88
- config.step_defs_to_load.should == [
75
+ config.all_files_to_load.should == [
89
76
  "/features/support/env.rb"
90
77
  ]
91
78
  end
@@ -97,7 +84,7 @@ module Cli
97
84
 
98
85
  config.parse!(%w{--require /features --exclude foo[df] --exclude blah})
99
86
 
100
- config.step_defs_to_load.should == [
87
+ config.all_files_to_load.should == [
101
88
  "/features/support/bar.rb",
102
89
  "/features/support/fooz.rb"
103
90
  ]
@@ -152,6 +139,13 @@ module Cli
152
139
  config.parse!([])
153
140
  config.options[:require].should == ['from/yml']
154
141
  end
142
+
143
+ it "parses ERB syntax in the cucumber.yml file" do
144
+ given_cucumber_yml_defined_as({'default' => '<%="--require some_file"%>'})
145
+
146
+ config.parse!([])
147
+ config.options[:require].should include('some_file')
148
+ end
155
149
 
156
150
  it "provides a helpful error message when a specified profile does not exists in cucumber.yml" do
157
151
  given_cucumber_yml_defined_as({'default' => '--require from/yml', 'html_report' => '--format html'})
@@ -183,9 +177,7 @@ END_OF_MESSAGE
183
177
 
184
178
 
185
179
  ["--no-profile", "-P"].each do |flag|
186
-
187
180
  context 'when none is specified with #{flag}' do
188
-
189
181
  it "disables profiles" do
190
182
  given_cucumber_yml_defined_as({'default' => '-v --require file_specified_in_default_profile.rb'})
191
183
 
@@ -199,13 +191,9 @@ END_OF_MESSAGE
199
191
  config.parse!("#{flag} --require some_file.rb".split(" "))
200
192
  out.string.should =~ /Disabling profiles.../
201
193
  end
202
-
203
194
  end
204
-
205
195
  end
206
196
 
207
-
208
-
209
197
  it "issues a helpful error message when a specified profile exists but is nil or blank" do
210
198
  [nil, ' '].each do |bad_input|
211
199
  given_cucumber_yml_defined_as({'foo' => bad_input})
@@ -240,6 +228,13 @@ END_OF_MESSAGE
240
228
 
241
229
  lambda{config.parse!([])}.should raise_error(expected_error_message)
242
230
  end
231
+
232
+ it "issues a helpful error message when cucumber.yml can not be parsed by ERB" do
233
+ expected_error_message = /cucumber.yml was found, but could not be parsed with ERB. Please refer to cucumber's documentation on correct profile usage./
234
+ given_cucumber_yml_defined_as("<% this_fails %>")
235
+
236
+ lambda{config.parse!([])}.should raise_error(expected_error_message)
237
+ end
243
238
  end
244
239
 
245
240
 
@@ -291,7 +286,13 @@ END_OF_MESSAGE
291
286
  it "should not accept multiple --format options when both use implicit STDOUT" do
292
287
  lambda do
293
288
  config.parse!(%w{--format pretty --format progress})
294
- end.should raise_error("All but one formatter must use --out, only one can print to STDOUT")
289
+ end.should raise_error("All but one formatter must use --out, only one can print to each stream (or STDOUT)")
290
+ end
291
+
292
+ it "should not accept multiple --out streams pointing to the same place" do
293
+ lambda do
294
+ config.parse!(%w{--format pretty --out file1 --format progress --out file1})
295
+ end.should raise_error("All but one formatter must use --out, only one can print to each stream (or STDOUT)")
295
296
  end
296
297
 
297
298
  it "should associate --out to previous --format" do
@@ -86,6 +86,36 @@ module Cucumber
86
86
  end
87
87
  end
88
88
 
89
+ describe "setup step sequence" do
90
+
91
+ it "should load files and execute hooks in order" do
92
+ Configuration.stub!(:new).and_return(configuration = mock('configuration', :null_object => true))
93
+ step_mother = mock('step mother', :null_object => true)
94
+ configuration.stub!(:drb?).and_return false
95
+ cli = Main.new(%w{--verbose example.feature}, @out)
96
+ cli.stub!(:require)
97
+
98
+ configuration.stub!(:support_to_load).and_return(['support'])
99
+ configuration.stub!(:step_defs_to_load).and_return(['step defs'])
100
+
101
+ # Support must be loaded first to ensure post configuration hook can
102
+ # run before anything else.
103
+ step_mother.should_receive(:load_code_files).with(['support']).ordered
104
+ # The post configuration hook/s (if any) need to be run next to enable
105
+ # extensions to do their thing before features are loaded
106
+ step_mother.should_receive(:after_configuration).with(configuration).ordered
107
+ # Feature files must be loaded before step definitions are required.
108
+ # This is because i18n step methods are only aliased when
109
+ # features are loaded. If we swap the order, the requires
110
+ # will fail.
111
+ step_mother.should_receive(:load_plain_text_features).ordered
112
+ step_mother.should_receive(:load_code_files).with(['step defs']).ordered
113
+
114
+ cli.execute!(step_mother)
115
+ end
116
+
117
+ end
118
+
89
119
  [ProfilesNotDefinedError, YmlLoadError, ProfileNotFound].each do |exception_klass|
90
120
 
91
121
  it "rescues #{exception_klass}, prints the message to the error stream and returns true" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cucumber
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.98
4
+ version: 0.3.99
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Aslak Helles\xC3\xB8y"
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-25 00:00:00 -05:00
12
+ date: 2009-09-03 00:00:00 +02:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -346,6 +346,7 @@ files:
346
346
  - features/junit_formatter.feature
347
347
  - features/language_from_header.feature
348
348
  - features/multiline_names.feature
349
+ - features/post_configuration_hook.feature
349
350
  - features/profiles.feature
350
351
  - features/rake_task.feature
351
352
  - features/report_called_undefined_steps.feature