aslakhellesoy-cucumber 0.3.103 → 0.3.104

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 (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)