aslakhellesoy-cucumber 0.3.103 → 0.3.104

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/History.txt +27 -2
  2. data/Manifest.txt +10 -4
  3. data/examples/ramaze/README.textile +7 -0
  4. data/examples/ramaze/Rakefile +6 -0
  5. data/examples/ramaze/app.rb +21 -0
  6. data/examples/ramaze/features/add.feature +11 -0
  7. data/examples/ramaze/features/step_definitions/add_steps.rb +15 -0
  8. data/examples/ramaze/features/support/env.rb +32 -0
  9. data/examples/ramaze/layout/default.html.erb +8 -0
  10. data/examples/ramaze/view/index.html.erb +5 -0
  11. data/examples/sinatra/features/support/env.rb +1 -1
  12. data/features/cucumber_cli.feature +5 -5
  13. data/features/usage_and_stepdefs_formatter.feature +169 -0
  14. data/lib/cucumber/ast/step_invocation.rb +7 -0
  15. data/lib/cucumber/ast/tags.rb +6 -1
  16. data/lib/cucumber/ast/tree_walker.rb +179 -0
  17. data/lib/cucumber/cli/options.rb +20 -11
  18. data/lib/cucumber/formatter/html.rb +0 -2
  19. data/lib/cucumber/formatter/stepdefs.rb +14 -0
  20. data/lib/cucumber/formatter/usage.rb +106 -50
  21. data/lib/cucumber/language_support/language_methods.rb +6 -9
  22. data/lib/cucumber/rb_support/rb_language.rb +16 -3
  23. data/lib/cucumber/rb_support/rb_step_definition.rb +7 -1
  24. data/lib/cucumber/step_match.rb +4 -0
  25. data/lib/cucumber/step_mother.rb +8 -37
  26. data/lib/cucumber/version.rb +1 -1
  27. data/spec/cucumber/ast/background_spec.rb +0 -6
  28. data/spec/cucumber/ast/tree_walker_spec.rb +11 -0
  29. data/spec/cucumber/cli/options_spec.rb +12 -0
  30. data/spec/cucumber/formatter/html_spec.rb +0 -1
  31. data/spec/cucumber/rb_support/rb_step_definition_spec.rb +0 -9
  32. data/spec/cucumber/step_mother_spec.rb +13 -34
  33. metadata +14 -6
  34. data/features/steps_formatter.feature +0 -26
  35. data/features/usage.feature +0 -126
  36. data/lib/cucumber/formatter/profile.rb +0 -78
  37. data/lib/cucumber/formatters/unicode.rb +0 -7
@@ -1,6 +1,12 @@
1
+ require 'cucumber/step_match'
2
+
1
3
  module Cucumber
2
4
  module LanguageSupport
3
5
  module LanguageMethods
6
+ def create_step_match(step_definition, step_name, formatted_step_name, step_arguments)
7
+ StepMatch.new(step_definition, step_name, formatted_step_name, step_arguments)
8
+ end
9
+
4
10
  def before(scenario)
5
11
  begin_scenario
6
12
  execute_before(scenario)
@@ -41,15 +47,6 @@ module Cucumber
41
47
  transform
42
48
  end
43
49
 
44
- def add_step_definition(step_definition)
45
- step_definitions << step_definition
46
- step_definition
47
- end
48
-
49
- def step_definitions
50
- @step_definitions ||= []
51
- end
52
-
53
50
  def hooks_for(phase, scenario) #:nodoc:
54
51
  hooks[phase.to_sym].select{|hook| scenario.accept_hook?(hook)}
55
52
  end
@@ -34,6 +34,7 @@ module Cucumber
34
34
 
35
35
  def initialize(step_mother)
36
36
  @step_mother = step_mother
37
+ @step_definitions = []
37
38
  RbDsl.rb_language = self
38
39
  end
39
40
 
@@ -56,10 +57,20 @@ module Cucumber
56
57
  end
57
58
  end
58
59
 
60
+ def step_matches(step_name, formatted_step_name)
61
+ @step_definitions.map do |step_definition|
62
+ step_definition.step_match(step_name, formatted_step_name)
63
+ end.compact
64
+ end
65
+
59
66
  def arguments_from(regexp, step_name)
60
67
  @regexp_argument_matcher.arguments_from(regexp, step_name)
61
68
  end
62
69
 
70
+ def unmatched_step_definitions
71
+ @step_definitions.select{|step_definition| !step_definition.matched?}
72
+ end
73
+
63
74
  def snippet_text(step_keyword, step_name, multiline_arg_class = nil)
64
75
  escaped = Regexp.escape(step_name).gsub('\ ', ' ').gsub('/', '\/')
65
76
  escaped = escaped.gsub(PARAM_PATTERN, ESCAPED_PARAM_PATTERN)
@@ -94,7 +105,9 @@ module Cucumber
94
105
  end
95
106
 
96
107
  def register_rb_step_definition(regexp, proc)
97
- add_step_definition(RbStepDefinition.new(self, regexp, proc))
108
+ step_definition = RbStepDefinition.new(self, regexp, proc)
109
+ @step_definitions << step_definition
110
+ step_definition
98
111
  end
99
112
 
100
113
  def build_rb_world_factory(world_modules, proc)
@@ -106,12 +119,12 @@ module Cucumber
106
119
  @world_modules += world_modules
107
120
  end
108
121
 
109
- protected
110
-
111
122
  def load_code_file(code_file)
112
123
  require code_file # This will cause self.add_step_definition, self.add_hook, and self.add_transform to be called from RbDsl
113
124
  end
114
125
 
126
+ protected
127
+
115
128
  def begin_scenario
116
129
  begin_rb_scenario
117
130
  end
@@ -42,7 +42,9 @@ module Cucumber
42
42
  end
43
43
 
44
44
  def arguments_from(step_name)
45
- RegexpArgumentMatcher.arguments_from(@regexp, step_name)
45
+ args = RegexpArgumentMatcher.arguments_from(@regexp, step_name)
46
+ @matched = true if args
47
+ args
46
48
  end
47
49
 
48
50
  def invoke(args)
@@ -56,6 +58,10 @@ module Cucumber
56
58
  end
57
59
  end
58
60
 
61
+ def matched?
62
+ @matched
63
+ end
64
+
59
65
  def file_colon_line
60
66
  @proc.file_colon_line
61
67
  end
@@ -69,6 +69,10 @@ module Cucumber
69
69
  end
70
70
  s
71
71
  end
72
+
73
+ def inspect #:nodoc:
74
+ sprintf("#<%s:0x%x>", self.class, self.object_id)
75
+ end
72
76
  end
73
77
 
74
78
  class NoStepMatch #:nodoc:
@@ -38,16 +38,6 @@ module Cucumber
38
38
  end
39
39
  end
40
40
 
41
- # Raised when 2 or more StepDefinition have the same Regexp
42
- class Redundant < StandardError
43
- def initialize(step_def_1, step_def_2)
44
- message = "Multiple step definitions have the same Regexp:\n\n"
45
- message << step_def_1.backtrace_line << "\n"
46
- message << step_def_2.backtrace_line << "\n\n"
47
- super(message)
48
- end
49
- end
50
-
51
41
  # This is the meaty part of Cucumber that ties everything together.
52
42
  class StepMother
53
43
  include Constantize
@@ -87,17 +77,12 @@ module Cucumber
87
77
  def load_code_file(step_def_file)
88
78
  if programming_language = programming_language_for(step_def_file)
89
79
  log.debug(" * #{step_def_file}\n")
90
- step_definitions = programming_language.step_definitions_for(step_def_file)
91
- register_step_definitions(step_definitions)
80
+ programming_language.load_code_file(step_def_file)
92
81
  else
93
82
  log.debug(" * #{step_def_file} [NOT SUPPORTED]\n")
94
83
  end
95
84
  end
96
85
 
97
- def register_step_definitions(step_definitions)
98
- step_definitions.each{|step_definition| register_step_definition(step_definition)}
99
- end
100
-
101
86
  # Loads and registers programming language implementation.
102
87
  # Instances are cached, so calling with the same argument
103
88
  # twice will return the same instance.
@@ -152,7 +137,9 @@ module Cucumber
152
137
  end
153
138
 
154
139
  def step_match(step_name, formatted_step_name=nil) #:nodoc:
155
- matches = step_definitions.map { |d| d.step_match(step_name, formatted_step_name) }.compact
140
+ matches = @programming_languages.map do |programming_language|
141
+ programming_language.step_matches(step_name, formatted_step_name)
142
+ end.flatten
156
143
  raise Undefined.new(step_name) if matches.empty?
157
144
  matches = best_matches(step_name, matches) if matches.size > 1 && options[:guess]
158
145
  raise Ambiguous.new(step_name, matches, options[:guess]) if matches.size > 1
@@ -174,16 +161,11 @@ module Cucumber
174
161
  top_groups
175
162
  end
176
163
  end
177
-
178
- def clear! #:nodoc:
179
- step_definitions.clear
180
- hooks.clear
181
- steps.clear
182
- scenarios.clear
183
- end
184
164
 
185
- def step_definitions #:nodoc:
186
- @step_definitions ||= []
165
+ def unmatched_step_definitions
166
+ @programming_languages.map do |programming_language|
167
+ programming_language.unmatched_step_definitions
168
+ end.flatten
187
169
  end
188
170
 
189
171
  def snippet_text(step_keyword, step_name, multiline_arg_class) #:nodoc:
@@ -244,17 +226,6 @@ module Cucumber
244
226
 
245
227
  private
246
228
 
247
- # Registers a StepDefinition. This can be a Ruby StepDefintion,
248
- # or any other kind of object that implements the StepDefintion
249
- # contract (API).
250
- def register_step_definition(step_definition)
251
- step_definitions.each do |already|
252
- raise Redundant.new(already, step_definition) if already == step_definition
253
- end
254
- step_definitions << step_definition
255
- step_definition
256
- end
257
-
258
229
  def programming_language_for(step_def_file) #:nodoc:
259
230
  if ext = File.extname(step_def_file)[1..-1]
260
231
  return nil if @unsupported_programming_languages.index(ext)
@@ -2,7 +2,7 @@ module Cucumber #:nodoc:
2
2
  class VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 3
5
- TINY = 103
5
+ TINY = 104
6
6
  PATCH = nil # Set to nil for official release
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PATCH].compact.join('.')
@@ -20,17 +20,11 @@ module Cucumber
20
20
  $y = $x * n.to_i
21
21
  end
22
22
 
23
- register
24
-
25
23
  @visitor = TreeWalker.new(@step_mother)
26
24
 
27
25
  @feature = mock('feature', :visit? => true).as_null_object
28
26
  end
29
27
 
30
- def register
31
- @step_mother.register_step_definitions(@rb.step_definitions)
32
- end
33
-
34
28
  it "should execute Before blocks before background steps" do
35
29
  background = Background.new(
36
30
  comment=Comment.new(''),
@@ -0,0 +1,11 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ module Cucumber::Ast
4
+ describe TreeWalker do
5
+ it "should visit features" do
6
+ tw = TreeWalker.new(nil, [mock('listener', :before_visit_features => nil)], {})
7
+ tw.should_not_receive(:warn)
8
+ tw.visit_features(mock('features', :accept => nil))
9
+ end
10
+ end
11
+ end
@@ -193,6 +193,18 @@ module Cli
193
193
  options[:formats].should == [['progress', output_stream], ['html', 'features.html']]
194
194
  end
195
195
 
196
+ it "does not include STDOUT formatters from the profile if there is a STDOUT formatter in command line" do
197
+ given_cucumber_yml_defined_as({'html' => %w[--format html -o features.html --format pretty]})
198
+ options.parse!(%w{--format progress --profile html})
199
+ options[:formats].should == [['progress', output_stream], ['html', 'features.html']]
200
+ end
201
+
202
+ it "includes any STDOUT formatters from the profile if no STDOUT formatter was specified in command line" do
203
+ given_cucumber_yml_defined_as({'html' => %w[--format html]})
204
+ options.parse!(%w{--format rerun -o rerun.txt --profile html})
205
+ options[:formats].should == [['html', output_stream], ['rerun', 'rerun.txt']]
206
+ end
207
+
196
208
  it "assumes all of the formatters defined in the profile when none are specified on cmd line" do
197
209
  given_cucumber_yml_defined_as({'html' => %w[--format progress --format html -o features.html]})
198
210
  options.parse!(%w{--profile html})
@@ -37,7 +37,6 @@ module Cucumber
37
37
  dsl = Object.new
38
38
  dsl.extend RbSupport::RbDsl
39
39
  dsl.instance_exec &step_defs
40
- @step_mother.register_step_definitions(rb.step_definitions)
41
40
  end
42
41
 
43
42
  Spec::Matchers.define :have_css_node do |css, regexp|
@@ -18,10 +18,6 @@ module Cucumber
18
18
  $inside = nil
19
19
  end
20
20
 
21
- def register
22
- @step_mother.register_step_definitions(@rb.step_definitions)
23
- end
24
-
25
21
  it "should allow calling of other steps" do
26
22
  @dsl.Given /Outside/ do
27
23
  Given "Inside"
@@ -29,7 +25,6 @@ module Cucumber
29
25
  @dsl.Given /Inside/ do
30
26
  $inside = true
31
27
  end
32
- register
33
28
 
34
29
  @step_mother.step_match("Outside").invoke(nil)
35
30
  $inside.should == true
@@ -42,7 +37,6 @@ module Cucumber
42
37
  @dsl.Given /Inside/ do |table|
43
38
  $inside = table.raw[0][0]
44
39
  end
45
- register
46
40
 
47
41
  @step_mother.step_match("Outside").invoke(nil)
48
42
  $inside.should == 'inside'
@@ -52,7 +46,6 @@ module Cucumber
52
46
  @dsl.Given /Outside/ do
53
47
  Given 'Inside'
54
48
  end
55
- register
56
49
 
57
50
  lambda do
58
51
  @step_mother.step_match('Outside').invoke(nil)
@@ -63,7 +56,6 @@ module Cucumber
63
56
  @dsl.Given /Outside/ do
64
57
  pending("Do me!")
65
58
  end
66
- register
67
59
 
68
60
  lambda do
69
61
  @step_mother.step_match("Outside").invoke(nil)
@@ -77,7 +69,6 @@ module Cucumber
77
69
  @dsl.Given /Loud/ do
78
70
  announce 'wasup'
79
71
  end
80
- register
81
72
 
82
73
  @step_mother.step_match("Loud").invoke(nil)
83
74
  end
@@ -16,16 +16,11 @@ module Cucumber
16
16
  @visitor = mock('Visitor')
17
17
  end
18
18
 
19
- def register
20
- @step_mother.register_step_definitions(@rb.step_definitions)
21
- end
22
-
23
19
  it "should format step names" do
24
20
  @dsl.Given(/it (.*) in (.*)/) do |what, month|
25
21
  end
26
22
  @dsl.Given(/nope something else/) do |what, month|
27
23
  end
28
- register
29
24
 
30
25
  format = @step_mother.step_match("it snows in april").format_args("[%s]")
31
26
  format.should == "it [snows] in [april]"
@@ -34,14 +29,13 @@ module Cucumber
34
29
  it "should raise Ambiguous error with guess hint when multiple step definitions match" do
35
30
  @dsl.Given(/Three (.*) mice/) {|disability|}
36
31
  @dsl.Given(/Three blind (.*)/) {|animal|}
37
- register
38
32
 
39
33
  lambda do
40
34
  @step_mother.step_match("Three blind mice")
41
35
  end.should raise_error(Ambiguous, %{Ambiguous match of "Three blind mice":
42
36
 
43
- spec/cucumber/step_mother_spec.rb:35:in `/Three (.*) mice/'
44
- spec/cucumber/step_mother_spec.rb:36:in `/Three blind (.*)/'
37
+ spec/cucumber/step_mother_spec.rb:30:in `/Three (.*) mice/'
38
+ spec/cucumber/step_mother_spec.rb:31:in `/Three blind (.*)/'
45
39
 
46
40
  You can run again with --guess to make Cucumber be more smart about it
47
41
  })
@@ -52,14 +46,13 @@ You can run again with --guess to make Cucumber be more smart about it
52
46
 
53
47
  @dsl.Given(/Three (.*) mice/) {|disability|}
54
48
  @dsl.Given(/Three cute (.*)/) {|animal|}
55
- register
56
-
49
+
57
50
  lambda do
58
51
  @step_mother.step_match("Three cute mice")
59
52
  end.should raise_error(Ambiguous, %{Ambiguous match of "Three cute mice":
60
53
 
61
- spec/cucumber/step_mother_spec.rb:53:in `/Three (.*) mice/'
62
- spec/cucumber/step_mother_spec.rb:54:in `/Three cute (.*)/'
54
+ spec/cucumber/step_mother_spec.rb:47:in `/Three (.*) mice/'
55
+ spec/cucumber/step_mother_spec.rb:48:in `/Three cute (.*)/'
63
56
 
64
57
  })
65
58
  end
@@ -68,8 +61,7 @@ spec/cucumber/step_mother_spec.rb:54:in `/Three cute (.*)/'
68
61
  @step_mother.options = {:guess => true}
69
62
  @dsl.Given(/Three (.*) mice/) {|disability|}
70
63
  @dsl.Given(/Three (.*)/) {|animal|}
71
- register
72
-
64
+
73
65
  lambda do
74
66
  @step_mother.step_match("Three blind mice")
75
67
  end.should_not raise_error
@@ -79,8 +71,7 @@ spec/cucumber/step_mother_spec.rb:54:in `/Three cute (.*)/'
79
71
  @step_mother.options = {:guess => true}
80
72
  right = @dsl.Given(/Three (.*) mice/) {|disability|}
81
73
  wrong = @dsl.Given(/Three (.*)/) {|animal|}
82
- register
83
-
74
+
84
75
  @step_mother.step_match("Three blind mice").step_definition.should == right
85
76
  end
86
77
 
@@ -88,8 +79,7 @@ spec/cucumber/step_mother_spec.rb:54:in `/Three cute (.*)/'
88
79
  @step_mother.options = {:guess => true}
89
80
  right = @dsl.Given(/Three (.*) mice ran (.*)/) {|disability|}
90
81
  wrong = @dsl.Given(/Three (.*)/) {|animal|}
91
- register
92
-
82
+
93
83
  @step_mother.step_match("Three blind mice ran far").step_definition.should == right
94
84
  end
95
85
 
@@ -98,8 +88,7 @@ spec/cucumber/step_mother_spec.rb:54:in `/Three cute (.*)/'
98
88
  general = @dsl.Given(/Three (.*) mice ran (.*)/) {|disability|}
99
89
  specific = @dsl.Given(/Three blind mice ran far/) {}
100
90
  more_specific = @dsl.Given(/^Three blind mice ran far$/) {}
101
- register
102
-
91
+
103
92
  @step_mother.step_match("Three blind mice ran far").step_definition.should == more_specific
104
93
  end
105
94
 
@@ -109,19 +98,10 @@ spec/cucumber/step_mother_spec.rb:54:in `/Three cute (.*)/'
109
98
  end.should raise_error(Undefined)
110
99
  end
111
100
 
112
- it "should raise Redundant error when same regexp is registered twice" do
113
- @dsl.Given(/Three (.*) mice/) {|disability|}
114
- lambda do
115
- @dsl.Given(/Three (.*) mice/) {|disability|}
116
- register
117
- end.should raise_error(Redundant)
118
- end
119
-
120
101
  # http://railsforum.com/viewtopic.php?pid=93881
121
102
  it "should not raise Redundant unless it's really redundant" do
122
103
  @dsl.Given(/^(.*) (.*) user named '(.*)'$/) {|a,b,c|}
123
104
  @dsl.Given(/^there is no (.*) user named '(.*)'$/) {|a,b|}
124
- register
125
105
  end
126
106
 
127
107
  it "should raise an error if the world is nil" do
@@ -133,7 +113,7 @@ spec/cucumber/step_mother_spec.rb:54:in `/Three cute (.*)/'
133
113
  raise "Should fail"
134
114
  rescue RbSupport::NilWorld => e
135
115
  e.message.should == "World procs should never return nil"
136
- e.backtrace.should == ["spec/cucumber/step_mother_spec.rb:128:in `World'"]
116
+ e.backtrace.should == ["spec/cucumber/step_mother_spec.rb:108:in `World'"]
137
117
  end
138
118
  end
139
119
 
@@ -163,8 +143,8 @@ spec/cucumber/step_mother_spec.rb:54:in `/Three cute (.*)/'
163
143
  end.should raise_error(RbSupport::MultipleWorld, %{You can only pass a proc to #World once, but it's happening
164
144
  in 2 places:
165
145
 
166
- spec/cucumber/step_mother_spec.rb:160:in `World'
167
- spec/cucumber/step_mother_spec.rb:162:in `World'
146
+ spec/cucumber/step_mother_spec.rb:140:in `World'
147
+ spec/cucumber/step_mother_spec.rb:142:in `World'
168
148
 
169
149
  Use Ruby modules instead to extend your worlds. See the Cucumber::RbSupport::RbDsl#World RDoc
170
150
  or http://wiki.github.com/aslakhellesoy/cucumber/a-whole-new-world.
@@ -175,8 +155,7 @@ or http://wiki.github.com/aslakhellesoy/cucumber/a-whole-new-world.
175
155
  it "should find before hooks" do
176
156
  fish = @dsl.Before('@fish'){}
177
157
  meat = @dsl.Before('@meat'){}
178
- register
179
-
158
+
180
159
  scenario = mock('Scenario')
181
160
  scenario.should_receive(:accept_hook?).with(fish).and_return(true)
182
161
  scenario.should_receive(:accept_hook?).with(meat).and_return(false)