cucumber 0.7.2 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,9 @@
1
+ == 0.7.3
2
+
3
+ === New Features
4
+ * Table cells can now contain escaped bars - \| and escaped backslashes - \\. (Gregory Hnatiuk, Aslak Hellesøy)
5
+ * Added support for Around hooks. (#605 John Firebaugh)
6
+
1
7
  == 0.7.2 (2010-05-03)
2
8
 
3
9
  === Bugfixes
data/Rakefile CHANGED
@@ -16,7 +16,7 @@ begin
16
16
  gem.homepage = "http://cukes.info"
17
17
  gem.authors = ["Aslak Hellesøy"]
18
18
 
19
- gem.add_dependency 'gherkin', '>= 1.0.24'
19
+ gem.add_dependency 'gherkin', '>= 1.0.27'
20
20
  gem.add_dependency 'term-ansicolor', '>= 1.0.4'
21
21
  gem.add_dependency 'builder', '>= 2.1.2'
22
22
  gem.add_dependency 'diff-lcs', '>= 1.1.2'
@@ -1,5 +1,5 @@
1
1
  ---
2
- :patch: 2
2
+ :patch: 3
3
3
  :build:
4
4
  :major: 0
5
5
  :minor: 7
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{cucumber}
8
- s.version = "0.7.2"
8
+ s.version = "0.7.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Aslak Helles\303\270y"]
12
- s.date = %q{2010-05-04}
12
+ s.date = %q{2010-05-18}
13
13
  s.default_executable = %q{cucumber}
14
14
  s.description = %q{Behaviour Driven Development with elegance and joy}
15
15
  s.email = %q{cukes@googlegroups.com}
@@ -342,6 +342,7 @@ Gem::Specification.new do |s|
342
342
  "examples/webrat/features/step_definitions/kvasir_steps.rb",
343
343
  "examples/webrat/features/support/env.rb",
344
344
  "features/announce.feature",
345
+ "features/around_hooks.feature",
345
346
  "features/background.feature",
346
347
  "features/bug_371.feature",
347
348
  "features/bug_464.feature",
@@ -541,7 +542,7 @@ Gem::Specification.new do |s|
541
542
 
542
543
  (::) U P G R A D I N G (::)
543
544
 
544
- Thank you for installing cucumber-0.7.2.
545
+ Thank you for installing cucumber-0.7.3.
545
546
  Please be sure to read http://wiki.github.com/aslakhellesoy/cucumber/upgrading
546
547
  for important information about this release. Happy cuking!
547
548
 
@@ -681,6 +682,7 @@ for important information about this release. Happy cuking!
681
682
  "examples/ruby2python/features/support/env.rb",
682
683
  "examples/self_test/features/step_definitions/sample_steps.rb",
683
684
  "examples/self_test/features/support/env.rb",
685
+ "examples/self_test/tmp/features/step_definitions/steps.rb",
684
686
  "examples/sinatra/app.rb",
685
687
  "examples/sinatra/features/step_definitions/add_steps.rb",
686
688
  "examples/sinatra/features/support/env.rb",
@@ -713,7 +715,7 @@ for important information about this release. Happy cuking!
713
715
  s.specification_version = 3
714
716
 
715
717
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
716
- s.add_runtime_dependency(%q<gherkin>, [">= 1.0.24"])
718
+ s.add_runtime_dependency(%q<gherkin>, [">= 1.0.27"])
717
719
  s.add_runtime_dependency(%q<term-ansicolor>, [">= 1.0.4"])
718
720
  s.add_runtime_dependency(%q<builder>, [">= 2.1.2"])
719
721
  s.add_runtime_dependency(%q<diff-lcs>, [">= 1.1.2"])
@@ -726,7 +728,7 @@ for important information about this release. Happy cuking!
726
728
  s.add_development_dependency(%q<syntax>, [">= 1.0.0"])
727
729
  s.add_development_dependency(%q<spork>, [">= 0.8.3"])
728
730
  else
729
- s.add_dependency(%q<gherkin>, [">= 1.0.24"])
731
+ s.add_dependency(%q<gherkin>, [">= 1.0.27"])
730
732
  s.add_dependency(%q<term-ansicolor>, [">= 1.0.4"])
731
733
  s.add_dependency(%q<builder>, [">= 2.1.2"])
732
734
  s.add_dependency(%q<diff-lcs>, [">= 1.1.2"])
@@ -740,7 +742,7 @@ for important information about this release. Happy cuking!
740
742
  s.add_dependency(%q<spork>, [">= 0.8.3"])
741
743
  end
742
744
  else
743
- s.add_dependency(%q<gherkin>, [">= 1.0.24"])
745
+ s.add_dependency(%q<gherkin>, [">= 1.0.27"])
744
746
  s.add_dependency(%q<term-ansicolor>, [">= 1.0.4"])
745
747
  s.add_dependency(%q<builder>, [">= 2.1.2"])
746
748
  s.add_dependency(%q<diff-lcs>, [">= 1.1.2"])
@@ -37,5 +37,10 @@ Feature: Fibonacci
37
37
  Scenario: Single series with Before hook with a tag label
38
38
  Then it should give me [1, 1, 2]
39
39
 
40
+ @another-do-fibonnacci-in-before-hook
41
+ Scenario: Single series with Before hook with a tag label
42
+ Then it should give me [1, 1, 2]
43
+
44
+
40
45
  Scenario: Single series by calling a step from within a step
41
46
  Then it should give me [1, 1] via calling another step definition
@@ -2,7 +2,7 @@ Before(function(){
2
2
  fibResult = 0;
3
3
  });
4
4
 
5
- Before('@do-fibonnacci-in-before-hook', function(){
5
+ Before(['@another-do-fibonnacci-in-before-hook,@do-fibonnacci-in-before-hook'], function(){
6
6
  fibResult = fibonacciSeries(3);
7
7
  });
8
8
 
@@ -38,7 +38,6 @@ Then(/^it should contain:$/, function(table){
38
38
  assertMatches(hashes[0]['cell 2'], fibResult);
39
39
  });
40
40
 
41
-
42
41
  Then(/^it should give me (\[.*\]) via calling another step definition$/, function(expectedResult){
43
42
  Given("I ask Javascript to calculate fibonacci up to 2");
44
43
  assertEqual(expectedResult, fibResult);
@@ -0,0 +1,188 @@
1
+ Feature: Around hooks
2
+ In order to support transactional scenarios for database libraries
3
+ that provide only a block syntax for transactions, Cucumber should
4
+ permit definition of Around hooks.
5
+
6
+ Scenario: A single Around hook
7
+ Given a standard Cucumber project directory structure
8
+ And a file named "features/step_definitions/steps.rb" with:
9
+ """
10
+ Then /^the hook is called$/ do
11
+ $hook_called.should == true
12
+ end
13
+ """
14
+ And a file named "features/support/hooks.rb" with:
15
+ """
16
+ Around do |scenario, block|
17
+ $hook_called = true
18
+ block.call
19
+ end
20
+ """
21
+ And a file named "features/f.feature" with:
22
+ """
23
+ Feature: Around hooks
24
+ Scenario: using hook
25
+ Then the hook is called
26
+ """
27
+ When I run cucumber features/f.feature
28
+ Then it should pass with
29
+ """
30
+ Feature: Around hooks
31
+
32
+ Scenario: using hook # features/f.feature:2
33
+ Then the hook is called # features/step_definitions/steps.rb:1
34
+
35
+ 1 scenario (1 passed)
36
+ 1 step (1 passed)
37
+
38
+ """
39
+
40
+ Scenario: Multiple Around hooks
41
+ Given a standard Cucumber project directory structure
42
+ And a file named "features/step_definitions/steps.rb" with:
43
+ """
44
+ Then /^the hooks are called in the correct order$/ do
45
+ $hooks_called.should == ['A', 'B', 'C']
46
+ end
47
+ """
48
+ And a file named "features/support/hooks.rb" with:
49
+ """
50
+ Around do |scenario, block|
51
+ $hooks_called ||= []
52
+ $hooks_called << 'A'
53
+ block.call
54
+ end
55
+
56
+ Around do |scenario, block|
57
+ $hooks_called ||= []
58
+ $hooks_called << 'B'
59
+ block.call
60
+ end
61
+
62
+ Around do |scenario, block|
63
+ $hooks_called ||= []
64
+ $hooks_called << 'C'
65
+ block.call
66
+ end
67
+ """
68
+ And a file named "features/f.feature" with:
69
+ """
70
+ Feature: Around hooks
71
+ Scenario: using multiple hooks
72
+ Then the hooks are called in the correct order
73
+ """
74
+ When I run cucumber features/f.feature
75
+ Then it should pass with
76
+ """
77
+ Feature: Around hooks
78
+
79
+ Scenario: using multiple hooks # features/f.feature:2
80
+ Then the hooks are called in the correct order # features/step_definitions/steps.rb:1
81
+
82
+ 1 scenario (1 passed)
83
+ 1 step (1 passed)
84
+
85
+ """
86
+
87
+ Scenario: Mixing Around, Before, and After hooks
88
+ Given a standard Cucumber project directory structure
89
+ And a file named "features/step_definitions/steps.rb" with:
90
+ """
91
+ Then /^the Around hook is called around Before and After hooks$/ do
92
+ $hooks_called.should == ['Around', 'Before']
93
+ end
94
+ """
95
+ And a file named "features/support/hooks.rb" with:
96
+ """
97
+ Around do |scenario, block|
98
+ $hooks_called ||= []
99
+ $hooks_called << 'Around'
100
+ block.call
101
+ $hooks_called << 'Around'
102
+ $hooks_called.should == ['Around', 'Before', 'After', 'Around']
103
+ end
104
+
105
+ Before do |scenario|
106
+ $hooks_called ||= []
107
+ $hooks_called << 'Before'
108
+ end
109
+
110
+ After do |scenario|
111
+ $hooks_called ||= []
112
+ $hooks_called << 'After'
113
+ $hooks_called.should == ['Around', 'Before', 'After']
114
+ end
115
+ """
116
+ And a file named "features/f.feature" with:
117
+ """
118
+ Feature: Around hooks
119
+ Scenario: Mixing Around, Before, and After hooks
120
+ Then the Around hook is called around Before and After hooks
121
+ """
122
+ When I run cucumber features/f.feature
123
+ Then it should pass with
124
+ """
125
+ Feature: Around hooks
126
+
127
+ Scenario: Mixing Around, Before, and After hooks # features/f.feature:2
128
+ Then the Around hook is called around Before and After hooks # features/step_definitions/steps.rb:1
129
+
130
+ 1 scenario (1 passed)
131
+ 1 step (1 passed)
132
+
133
+ """
134
+
135
+ Scenario: Around hooks with tags
136
+ Given a standard Cucumber project directory structure
137
+ And a file named "features/step_definitions/steps.rb" with:
138
+ """
139
+ Then /^the Around hooks with matching tags are called$/ do
140
+ $hooks_called.should == ['one', 'one or two']
141
+ end
142
+ """
143
+ And a file named "features/support/hooks.rb" with:
144
+ """
145
+ Around('@one') do |scenario, block|
146
+ $hooks_called ||= []
147
+ $hooks_called << 'one'
148
+ block.call
149
+ end
150
+
151
+ Around('@one,@two') do |scenario, block|
152
+ $hooks_called ||= []
153
+ $hooks_called << 'one or two'
154
+ block.call
155
+ end
156
+
157
+ Around('@one', '@two') do |scenario, block|
158
+ $hooks_called ||= []
159
+ $hooks_called << 'one and two'
160
+ block.call
161
+ end
162
+
163
+ Around('@two') do |scenario, block|
164
+ $hooks_called ||= []
165
+ $hooks_called << 'two'
166
+ block.call
167
+ end
168
+ """
169
+ And a file named "features/f.feature" with:
170
+ """
171
+ Feature: Around hooks
172
+ @one
173
+ Scenario: Around hooks with tags
174
+ Then the Around hooks with matching tags are called
175
+ """
176
+ When I run cucumber -q -t @one features/f.feature
177
+ Then it should pass with
178
+ """
179
+ Feature: Around hooks
180
+
181
+ @one
182
+ Scenario: Around hooks with tags
183
+ Then the Around hooks with matching tags are called
184
+
185
+ 1 scenario (1 passed)
186
+ 1 step (1 passed)
187
+
188
+ """
@@ -54,6 +54,7 @@ Feature: Language help
54
54
  | ja | Japanese | 日本語 |
55
55
  | ko | Korean | 한국어 |
56
56
  | lt | Lithuanian | lietuvių kalba |
57
+ | lu | Luxemburgish | Lëtzebuergesch |
57
58
  | lv | Latvian | latviešu |
58
59
  | nl | Dutch | Nederlands |
59
60
  | no | Norwegian | norsk |
@@ -28,13 +28,13 @@ module Cucumber
28
28
 
29
29
  def name_line_lengths
30
30
  if @name.strip.empty?
31
- [Ast::Step::INDENT + @keyword.jlength + ': '.jlength]
31
+ [Ast::Step::INDENT + @keyword.unpack('U*').length + ': '.length]
32
32
  else
33
33
  @name.split("\n").enum_for(:each_with_index).map do |line, line_number|
34
34
  if line_number == 0
35
- Ast::Step::INDENT + @keyword.jlength + ': '.jlength + line.jlength
35
+ Ast::Step::INDENT + @keyword.unpack('U*').length + ': '.length + line.unpack('U*').length
36
36
  else
37
- Ast::Step::INDENT + Ast::Step::INDENT + line.jlength
37
+ Ast::Step::INDENT + Ast::Step::INDENT + line.unpack('U*').length
38
38
  end
39
39
  end
40
40
  end
@@ -48,9 +48,11 @@ module Cucumber
48
48
  visitor.visit_scenario_name(@keyword, @name, file_colon_line(@line), source_indent(first_line_length))
49
49
 
50
50
  skip_invoke! if @background.failed?
51
- visitor.step_mother.before_and_after(self, skip_hooks?) do
52
- skip_invoke! if failed?
53
- visitor.visit_steps(@steps)
51
+ visitor.step_mother.around(self, skip_hooks?) do
52
+ visitor.step_mother.before_and_after(self, skip_hooks?) do
53
+ skip_invoke! if failed?
54
+ visitor.visit_steps(@steps)
55
+ end
54
56
  end
55
57
  @executed = true
56
58
  end
@@ -69,7 +69,7 @@ module Cucumber
69
69
  end
70
70
 
71
71
  def text_length(name=@name)
72
- INDENT + INDENT + @keyword.jlength + name.jlength
72
+ INDENT + INDENT + @keyword.unpack('U*').length + name.unpack('U*').length
73
73
  end
74
74
 
75
75
  def backtrace_line
@@ -1,4 +1,5 @@
1
1
  require 'gherkin/rubify'
2
+ require 'gherkin/formatter/escaping'
2
3
 
3
4
  module Cucumber
4
5
  module Ast
@@ -585,6 +586,8 @@ module Cucumber
585
586
  # Represents a row of cells or columns of cells
586
587
  class Cells #:nodoc:
587
588
  include Enumerable
589
+ include Gherkin::Formatter::Escaping
590
+
588
591
  attr_reader :exception
589
592
 
590
593
  def initialize(table, cells)
@@ -631,7 +634,7 @@ module Cucumber
631
634
  end
632
635
 
633
636
  def width
634
- map{|cell| cell.value ? cell.value.to_s.jlength : 0}.max
637
+ map{|cell| cell.value ? escape_cell(cell.value.to_s).unpack('U*').length : 0}.max
635
638
  end
636
639
 
637
640
  def each(&proc)
@@ -6,11 +6,4 @@ class String #:nodoc:
6
6
  gsub(/^ {0,#{-n}}/, "")
7
7
  end
8
8
  end
9
-
10
- if (Cucumber::JRUBY && Cucumber::RAILS) || Cucumber::RUBY_1_9
11
- # Workaround for http://tinyurl.com/55uu3u
12
- alias jlength length
13
- else
14
- require 'jcode'
15
- end
16
9
  end
@@ -32,7 +32,8 @@ module Cucumber
32
32
  lexer = Gherkin::I18nLexer.new(parser, false)
33
33
 
34
34
  begin
35
- lexer.scan(source)
35
+ s = ENV['FILTER_PML_CALLOUT'] ? source.gsub(C_CALLOUT, '') : source
36
+ lexer.scan(s)
36
37
  ast = builder.ast
37
38
  return nil if ast.nil? # Filter caused nothing to match
38
39
  ast.language = lexer.i18n_language
@@ -59,14 +60,10 @@ module Cucumber
59
60
  end
60
61
  end
61
62
 
62
- def lang
63
- # TODO: Gherkin has logic for this. Remove.
64
- line_one = source.split(/\n/)[0]
65
- if line_one =~ LANGUAGE_PATTERN
66
- $1.strip
67
- else
68
- nil
69
- end
70
- end
63
+ private
64
+
65
+ # Special PML markup that we want to filter out.
66
+ CO = %{\\s*<(label|callout)\s+id=".*?"\s*/>\\s*}
67
+ C_CALLOUT = %r{/\*#{CO}\*/|//#{CO}}o
71
68
  end
72
69
  end
@@ -1,6 +1,7 @@
1
+ require 'fileutils'
1
2
  require 'cucumber/formatter/console'
2
3
  require 'cucumber/formatter/io'
3
- require 'fileutils'
4
+ require 'gherkin/formatter/escaping'
4
5
 
5
6
  module Cucumber
6
7
  module Formatter
@@ -15,6 +16,7 @@ module Cucumber
15
16
  include FileUtils
16
17
  include Console
17
18
  include Io
19
+ include Gherkin::Formatter::Escaping
18
20
  attr_writer :indent
19
21
  attr_reader :step_mother
20
22
 
@@ -198,8 +200,8 @@ module Cucumber
198
200
  return if !@table || @hide_this_step
199
201
  status ||= @status || :passed
200
202
  width = @table.col_width(@col_index)
201
- cell_text = value.to_s || ''
202
- padded = cell_text + (' ' * (width - cell_text.jlength))
203
+ cell_text = escape_cell(value.to_s || '')
204
+ padded = cell_text + (' ' * (width - cell_text.unpack('U*').length))
203
205
  prefix = cell_prefix(status)
204
206
  @io.print(' ' + format_string("#{prefix}#{padded}", status) + ::Term::ANSIColor.reset(" |"))
205
207
  @io.flush
@@ -24,7 +24,7 @@ module Cucumber
24
24
  source_indent = source_indent(sources)
25
25
  sources.sort.each do |file_colon_line, regexp_source|
26
26
  @io.print regexp_source.indent(2)
27
- @io.print " # #{file_colon_line}".indent(source_indent - regexp_source.jlength)
27
+ @io.print " # #{file_colon_line}".indent(source_indent - regexp_source.unpack('U*').length)
28
28
  @io.puts
29
29
  end
30
30
  @io.puts
@@ -68,7 +68,7 @@ module Cucumber
68
68
  @io.print format_string(sprintf("%.7f", stepdef_key.mean_duration), :skipped) + " " unless @options[:dry_run]
69
69
  @io.print format_string(stepdef_key.regexp_source, stepdef_key.status)
70
70
  if @options[:source]
71
- indent = max_length - stepdef_key.regexp_source.jlength
71
+ indent = max_length - stepdef_key.regexp_source.unpack('U*').length
72
72
  line_comment = " # #{stepdef_key.file_colon_line}".indent(indent)
73
73
  @io.print(format_string(line_comment, :comment))
74
74
  end
@@ -81,7 +81,7 @@ module Cucumber
81
81
  @io.print format_string(sprintf("%.7f", step[:duration]), :skipped) + " " unless @options[:dry_run]
82
82
  @io.print format_step(step[:keyword], step[:step_match], step[:status], nil)
83
83
  if @options[:source]
84
- indent = max_length - (step[:keyword].jlength + step[:step_match].format_args.jlength)
84
+ indent = max_length - (step[:keyword].unpack('U*').length + step[:step_match].format_args.unpack('U*').length)
85
85
  line_comment = " # #{step[:file_colon_line]}".indent(indent)
86
86
  @io.print(format_string(line_comment, :comment))
87
87
  end
@@ -94,12 +94,12 @@ module Cucumber
94
94
  end
95
95
 
96
96
  def max_stepdef_length
97
- @stepdef_to_match.keys.flatten.map{|key| key.regexp_source.jlength}.max
97
+ @stepdef_to_match.keys.flatten.map{|key| key.regexp_source.unpack('U*').length}.max
98
98
  end
99
99
 
100
100
  def max_step_length
101
101
  @stepdef_to_match.values.to_a.flatten.map do |step|
102
- step[:keyword].jlength + step[:step_match].format_args.jlength
102
+ step[:keyword].unpack('U*').length + step[:step_match].format_args.unpack('U*').length
103
103
  end.max
104
104
  end
105
105
 
@@ -12,28 +12,27 @@ var CucumberJsDsl = {
12
12
  jsLanguage.registerJsTransform(regexp, func);
13
13
  },
14
14
 
15
- beforeHook: function(tag_or_func, func){
16
- CucumberJsDsl.__registerJsHook('before', tag_or_func, func);
15
+ beforeHook: function(tag_expressions_or_func, func){
16
+ CucumberJsDsl.__registerJsHook('before', tag_expressions_or_func, func);
17
17
  },
18
18
 
19
- afterHook: function(tag_or_func, func){
20
- CucumberJsDsl.__registerJsHook('after', tag_or_func, func);
19
+ afterHook: function(tag_expressions_or_func, func){
20
+ CucumberJsDsl.__registerJsHook('after', tag_expressions_or_func, func);
21
21
  },
22
22
 
23
23
  Table: function(raw_table){
24
24
  this.raw = raw_table;
25
25
  },
26
26
 
27
- __registerJsHook: function(label, tag_or_func, func){
27
+ __registerJsHook: function(label, tag_expressions_or_func, func){
28
28
  if(func != null){
29
29
  var hook_func = func;
30
- var tag = tag_or_func;
30
+ var tag_expressions = tag_expressions_or_func;
31
+ } else {
32
+ var hook_func = tag_expressions_or_func;
33
+ var tag_expressions = [];
31
34
  }
32
- else{
33
- var hook_func = tag_or_func;
34
- var tag = null;
35
- }
36
- jsLanguage.registerJsHook(label, hook_func, tag);
35
+ jsLanguage.registerJsHook(label, tag_expressions, hook_func);
37
36
  }
38
37
  }
39
38
 
@@ -58,12 +58,12 @@ module Cucumber
58
58
  end
59
59
 
60
60
  class JsHook
61
- def initialize(js_language, tag_names, js_function)
62
- @js_language, @tag_names, @js_function = js_language, tag_names, js_function
61
+ def initialize(js_language, tag_expressions, js_function)
62
+ @js_language, @tag_expressions, @js_function = js_language, tag_expressions, js_function
63
63
  end
64
64
 
65
65
  def tag_expressions
66
- @tag_names
66
+ @tag_expressions
67
67
  end
68
68
 
69
69
  def invoke(location, scenario)
@@ -145,10 +145,8 @@ module Cucumber
145
145
  @step_mother.step_match(name).invoke(multiline_argument)
146
146
  end
147
147
 
148
- #TODO: support multiple tag_names
149
- def register_js_hook(phase, js_function, tag_name = nil)
150
- tag_names = tag_name ? [tag_name] : []
151
- add_hook(phase, JsHook.new(self, tag_names, js_function))
148
+ def register_js_hook(phase, tag_expressions, js_function)
149
+ add_hook(phase, JsHook.new(self, tag_expressions, js_function))
152
150
  end
153
151
 
154
152
  def register_js_transform(regexp, js_function)
@@ -8,6 +8,12 @@ module Cucumber
8
8
  StepMatch.new(step_definition, step_name, name_to_report, step_arguments)
9
9
  end
10
10
 
11
+ def around(scenario)
12
+ execute_around(scenario) do
13
+ yield
14
+ end
15
+ end
16
+
11
17
  def before(scenario)
12
18
  begin_scenario(scenario)
13
19
  execute_before(scenario)
@@ -85,6 +91,16 @@ module Cucumber
85
91
  @transforms ||= []
86
92
  end
87
93
 
94
+ def execute_around(scenario, &block)
95
+ hooks_for(:around, scenario).reverse.inject(block) do |blk, hook|
96
+ proc do
97
+ invoke(hook, 'Around', scenario, true) do
98
+ blk.call(scenario)
99
+ end
100
+ end
101
+ end.call
102
+ end
103
+
88
104
  def execute_before(scenario)
89
105
  hooks_for(:before, scenario).each do |hook|
90
106
  invoke(hook, 'Before', scenario, true)
@@ -97,9 +113,9 @@ module Cucumber
97
113
  end
98
114
  end
99
115
 
100
- def invoke(hook, location, scenario, exception_fails_scenario)
116
+ def invoke(hook, location, scenario, exception_fails_scenario, &block)
101
117
  begin
102
- hook.invoke(location, scenario)
118
+ hook.invoke(location, scenario, &block)
103
119
  rescue Exception => exception
104
120
  if exception_fails_scenario
105
121
  scenario.fail!(exception)
@@ -50,18 +50,27 @@ module Cucumber
50
50
  RbDsl.build_rb_world_factory(world_modules, proc)
51
51
  end
52
52
 
53
- # Registers a proc that will run before each Scenario. You can register as
53
+ # Registers a proc that will run before each Scenario. You can register as many
54
54
  # as you want (typically from ruby scripts under <tt>support/hooks.rb</tt>).
55
55
  def Before(*tag_expressions, &proc)
56
56
  RbDsl.register_rb_hook('before', tag_expressions, proc)
57
57
  end
58
58
 
59
- # Registers a proc that will run after each Scenario. You can register as
59
+ # Registers a proc that will run after each Scenario. You can register as many
60
60
  # as you want (typically from ruby scripts under <tt>support/hooks.rb</tt>).
61
61
  def After(*tag_expressions, &proc)
62
62
  RbDsl.register_rb_hook('after', tag_expressions, proc)
63
63
  end
64
64
 
65
+ # Registers a proc that will be wrapped around each scenario. The proc
66
+ # should accept two arguments: two arguments: the scenario and a "block"
67
+ # argument (but passed as a regular argument, since blocks cannot accept
68
+ # blocks in 1.8), on which it should call the .call method. You can register
69
+ # as many as you want (typically from ruby scripts under <tt>support/hooks.rb</tt>).
70
+ def Around(*tag_expressions, &proc)
71
+ RbDsl.register_rb_hook('around', tag_expressions, proc)
72
+ end
73
+
65
74
  # Registers a proc that will run after each Step. You can register as
66
75
  # as you want (typically from ruby scripts under <tt>support/hooks.rb</tt>).
67
76
  def AfterStep(*tag_expressions, &proc)
@@ -10,8 +10,8 @@ module Cucumber
10
10
  @proc = proc
11
11
  end
12
12
 
13
- def invoke(location, argument)
14
- @rb_language.current_world.cucumber_instance_exec(false, location, argument, &@proc)
13
+ def invoke(location, argument, &block)
14
+ @rb_language.current_world.cucumber_instance_exec(false, location, *[argument, block].compact, &@proc)
15
15
  end
16
16
  end
17
17
  end
@@ -92,8 +92,8 @@ module Cucumber
92
92
  connect_world(scenario)
93
93
  end
94
94
 
95
- def register_rb_hook(phase, tag_names, proc)
96
- add_hook(phase, RbHook.new(self, tag_names, proc))
95
+ def register_rb_hook(phase, tag_expressions, proc)
96
+ add_hook(phase, RbHook.new(self, tag_expressions, proc))
97
97
  end
98
98
 
99
99
  def register_rb_transform(regexp, proc)
@@ -54,7 +54,7 @@ module Cucumber
54
54
  end
55
55
 
56
56
  def text_length
57
- @step_definition.regexp_source.jlength
57
+ @step_definition.regexp_source.unpack('U*').length
58
58
  end
59
59
 
60
60
  def replace_arguments(string, step_arguments, format, &proc)
@@ -72,7 +72,7 @@ module Cucumber
72
72
  end
73
73
 
74
74
  s[step_argument.byte_offset + offset, step_argument.val.length] = replacement
75
- offset += replacement.jlength - step_argument.val.jlength
75
+ offset += replacement.unpack('U*').length - step_argument.val.unpack('U*').length
76
76
  past_offset = step_argument.byte_offset + step_argument.val.length
77
77
  end
78
78
  s
@@ -311,6 +311,20 @@ module Cucumber
311
311
  @programming_languages.empty?
312
312
  end
313
313
 
314
+ def around(scenario, skip_hooks=false, &block) #:nodoc:
315
+ unless skip_hooks
316
+ @programming_languages.reverse.inject(block) do |blk, programming_language|
317
+ proc do
318
+ programming_language.around(scenario) do
319
+ blk.call(scenario)
320
+ end
321
+ end
322
+ end.call
323
+ else
324
+ yield
325
+ end
326
+ end
327
+
314
328
  def before_and_after(scenario, skip_hooks=false) #:nodoc:
315
329
  before(scenario) unless skip_hooks
316
330
  yield scenario
@@ -171,6 +171,20 @@ or http://wiki.github.com/aslakhellesoy/cucumber/a-whole-new-world.
171
171
 
172
172
  @rb.hooks_for(:before, scenario).should == [fish]
173
173
  end
174
+
175
+ it "should find around hooks" do
176
+ a = @dsl.Around do |scenario, block|
177
+ end
178
+
179
+ b = @dsl.Around('@tag') do |scenario, block|
180
+ end
181
+
182
+ scenario = mock('Scenario')
183
+ scenario.should_receive(:accept_hook?).with(a).and_return(true)
184
+ scenario.should_receive(:accept_hook?).with(b).and_return(false)
185
+
186
+ @rb.hooks_for(:around, scenario).should == [a]
187
+ end
174
188
  end
175
189
 
176
190
  describe StepMother, "step argument transformations" do
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 7
8
- - 2
9
- version: 0.7.2
8
+ - 3
9
+ version: 0.7.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - "Aslak Helles\xC3\xB8y"
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-04 00:00:00 +02:00
17
+ date: 2010-05-18 00:00:00 +02:00
18
18
  default_executable: cucumber
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -27,8 +27,8 @@ dependencies:
27
27
  segments:
28
28
  - 1
29
29
  - 0
30
- - 24
31
- version: 1.0.24
30
+ - 27
31
+ version: 1.0.27
32
32
  type: :runtime
33
33
  version_requirements: *id001
34
34
  - !ruby/object:Gem::Dependency
@@ -518,6 +518,7 @@ files:
518
518
  - examples/webrat/features/step_definitions/kvasir_steps.rb
519
519
  - examples/webrat/features/support/env.rb
520
520
  - features/announce.feature
521
+ - features/around_hooks.feature
521
522
  - features/background.feature
522
523
  - features/bug_371.feature
523
524
  - features/bug_464.feature
@@ -720,7 +721,7 @@ post_install_message: |+
720
721
 
721
722
  (::) U P G R A D I N G (::)
722
723
 
723
- Thank you for installing cucumber-0.7.2.
724
+ Thank you for installing cucumber-0.7.3.
724
725
  Please be sure to read http://wiki.github.com/aslakhellesoy/cucumber/upgrading
725
726
  for important information about this release. Happy cuking!
726
727
 
@@ -880,6 +881,7 @@ test_files:
880
881
  - examples/ruby2python/features/support/env.rb
881
882
  - examples/self_test/features/step_definitions/sample_steps.rb
882
883
  - examples/self_test/features/support/env.rb
884
+ - examples/self_test/tmp/features/step_definitions/steps.rb
883
885
  - examples/sinatra/app.rb
884
886
  - examples/sinatra/features/step_definitions/add_steps.rb
885
887
  - examples/sinatra/features/support/env.rb