aslakhellesoy-cucumber 0.1.99.15 → 0.1.99.17

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.
@@ -41,7 +41,7 @@ module Cucumber
41
41
  # * <tt>skipped</tt> - defaults to <tt>cyan</tt>
42
42
  # * <tt>skipped_param</tt> - defaults to <tt>cyan,bold</tt>
43
43
  # * <tt>comment</tt> - defaults to <tt>grey</tt>
44
- # * <tt>tag</tt> - defaults to <tt>blue</tt>
44
+ # * <tt>tag</tt> - defaults to <tt>cyan</tt>
45
45
  #
46
46
  # For instance, if your shell has a black background and a green font (like the
47
47
  # "Homebrew" settings for OS X' Terminal.app), you may want to override passed
@@ -81,7 +81,7 @@ module Cucumber
81
81
  'outline' => 'cyan',
82
82
  'skipped' => 'cyan',
83
83
  'comment' => 'grey',
84
- 'tag' => 'blue'
84
+ 'tag' => 'cyan'
85
85
  })
86
86
 
87
87
  if ENV['CUCUMBER_COLORS'] # Example: export CUCUMBER_COLORS="passed=red:failed=yellow"
@@ -82,7 +82,7 @@ module Cucumber
82
82
  undefined = features.steps[:undefined]
83
83
  return if undefined.empty?
84
84
  snippets = undefined.map do |step|
85
- step_name = StepMother::Undefined === step.exception ? step.exception.step_name : step.name
85
+ step_name = Undefined === step.exception ? step.exception.step_name : step.name
86
86
  snippet = @step_mother.snippet_text(step.actual_keyword, step_name)
87
87
  snippet
88
88
  end.compact.uniq
@@ -1,6 +1,9 @@
1
1
  module Cucumber
2
2
  module Parser
3
3
  # TIP: When you hack on the grammar, just delete feature.rb in this directory.
4
+ # Also make sure you have uninstalled all cucumber gems (don't forget xxx-cucumber
5
+ # github gems).
6
+ #
4
7
  # Treetop will then generate the parser in-memory. When you're happy, just generate
5
8
  # the rb file with tt feature.tt
6
9
  module Feature
@@ -49,6 +52,7 @@ module Cucumber
49
52
  def feature_elements
50
53
  elements[7]
51
54
  end
55
+
52
56
  end
53
57
 
54
58
  module Feature2
@@ -150,6 +154,15 @@ module Cucumber
150
154
  if r14
151
155
  r16 = _nt_feature_elements
152
156
  s0 << r16
157
+ if r16
158
+ r18 = _nt_comment
159
+ if r18
160
+ r17 = r18
161
+ else
162
+ r17 = SyntaxNode.new(input, index...index)
163
+ end
164
+ s0 << r17
165
+ end
153
166
  end
154
167
  end
155
168
  end
@@ -336,6 +349,9 @@ module Cucumber
336
349
  elements[0]
337
350
  end
338
351
 
352
+ def white
353
+ elements[1]
354
+ end
339
355
  end
340
356
 
341
357
  module Comment1
@@ -358,21 +374,7 @@ module Cucumber
358
374
  r2 = _nt_comment_line
359
375
  s1 << r2
360
376
  if r2
361
- s3, i3 = [], index
362
- loop do
363
- r4 = _nt_eol
364
- if r4
365
- s3 << r4
366
- else
367
- break
368
- end
369
- end
370
- if s3.empty?
371
- self.index = i3
372
- r3 = nil
373
- else
374
- r3 = SyntaxNode.new(input, i3...index, s3)
375
- end
377
+ r3 = _nt_white
376
378
  s1 << r3
377
379
  end
378
380
  if s1.last
@@ -612,6 +614,10 @@ module Cucumber
612
614
  def steps
613
615
  elements[7]
614
616
  end
617
+
618
+ def white
619
+ elements[8]
620
+ end
615
621
  end
616
622
 
617
623
  module Scenario1
@@ -694,6 +700,10 @@ module Cucumber
694
700
  if r8
695
701
  r12 = _nt_steps
696
702
  s0 << r12
703
+ if r12
704
+ r13 = _nt_white
705
+ s0 << r13
706
+ end
697
707
  end
698
708
  end
699
709
  end
@@ -747,6 +757,10 @@ module Cucumber
747
757
  def examples_sections
748
758
  elements[8]
749
759
  end
760
+
761
+ def white
762
+ elements[9]
763
+ end
750
764
  end
751
765
 
752
766
  module ScenarioOutline1
@@ -807,6 +821,10 @@ module Cucumber
807
821
  if r9
808
822
  r10 = _nt_examples_sections
809
823
  s0 << r10
824
+ if r10
825
+ r11 = _nt_white
826
+ s0 << r11
827
+ end
810
828
  end
811
829
  end
812
830
  end
@@ -1190,12 +1208,7 @@ module Cucumber
1190
1208
  break
1191
1209
  end
1192
1210
  end
1193
- if s0.empty?
1194
- self.index = i0
1195
- r0 = nil
1196
- else
1197
- r0 = SyntaxNode.new(input, i0...index, s0)
1198
- end
1211
+ r0 = SyntaxNode.new(input, i0...index, s0)
1199
1212
 
1200
1213
  node_cache[:line_to_eol][start_index] = r0
1201
1214
 
@@ -1,6 +1,9 @@
1
1
  module Cucumber
2
2
  module Parser
3
3
  # TIP: When you hack on the grammar, just delete feature.rb in this directory.
4
+ # Also make sure you have uninstalled all cucumber gems (don't forget xxx-cucumber
5
+ # github gems).
6
+ #
4
7
  # Treetop will then generate the parser in-memory. When you're happy, just generate
5
8
  # the rb file with tt feature.tt
6
9
  grammar Feature
@@ -8,7 +11,15 @@ module Cucumber
8
11
  include Table
9
12
 
10
13
  rule feature
11
- white comment white tags white header:(!(scenario_outline / scenario / background) .)* background:(background)? feature_elements {
14
+ white
15
+ comment
16
+ white
17
+ tags
18
+ white
19
+ header:(!(scenario_outline / scenario / background) .)*
20
+ background:(background)?
21
+ feature_elements
22
+ comment? {
12
23
  def build
13
24
  if background.respond_to?(:build)
14
25
  Ast::Feature.new(comment.build, tags.build, header.text_value, feature_elements.build, background.build)
@@ -33,7 +44,7 @@ module Cucumber
33
44
  end
34
45
 
35
46
  rule comment
36
- (comment_line eol+)* {
47
+ (comment_line white)* {
37
48
  def build
38
49
  Ast::Comment.new(text_value)
39
50
  end
@@ -66,7 +77,7 @@ module Cucumber
66
77
  end
67
78
 
68
79
  rule scenario
69
- comment tags white scenario_keyword space* name:line_to_eol (eol+ / eof) steps {
80
+ comment tags white scenario_keyword space* name:line_to_eol (eol+ / eof) steps white {
70
81
  def build
71
82
  Ast::Scenario.new(
72
83
  comment.build,
@@ -81,7 +92,7 @@ module Cucumber
81
92
  end
82
93
 
83
94
  rule scenario_outline
84
- comment tags white scenario_outline_keyword space* name:line_to_eol white steps examples_sections {
95
+ comment tags white scenario_outline_keyword space* name:line_to_eol white steps examples_sections white {
85
96
  def build
86
97
  Ast::ScenarioOutline.new(
87
98
  comment.build,
@@ -137,7 +148,7 @@ module Cucumber
137
148
  end
138
149
 
139
150
  rule line_to_eol
140
- (!eol .)+
151
+ (!eol .)*
141
152
  end
142
153
 
143
154
  rule py_string
@@ -1,5 +1,11 @@
1
1
  module Cucumber
2
2
  module Parser
3
+ # TIP: When you hack on the grammar, just delete feature.rb in this directory.
4
+ # Also make sure you have uninstalled all cucumber gems (don't forget xxx-cucumber
5
+ # github gems).
6
+ #
7
+ # Treetop will then generate the parser in-memory. When you're happy, just generate
8
+ # the rb file with tt feature.tt
3
9
  module Table
4
10
  include Treetop::Runtime
5
11
 
@@ -1,5 +1,11 @@
1
1
  module Cucumber
2
2
  module Parser
3
+ # TIP: When you hack on the grammar, just delete feature.rb in this directory.
4
+ # Also make sure you have uninstalled all cucumber gems (don't forget xxx-cucumber
5
+ # github gems).
6
+ #
7
+ # Treetop will then generate the parser in-memory. When you're happy, just generate
8
+ # the rb file with tt feature.tt
3
9
  grammar Table
4
10
 
5
11
  rule table
@@ -1,6 +1,14 @@
1
- require 'treetop'
2
- require 'treetop/runtime'
3
- require 'treetop/ruby_extensions'
1
+ begin
2
+ require 'treetop'
3
+ require 'treetop/runtime'
4
+ require 'treetop/ruby_extensions'
5
+ rescue LoadError
6
+ require "rubygems"
7
+ gem "treetop"
8
+ require 'treetop'
9
+ require 'treetop/runtime'
10
+ require 'treetop/ruby_extensions'
11
+ end
4
12
 
5
13
  module Cucumber
6
14
  module Parser
@@ -32,7 +40,7 @@ module Cucumber
32
40
  class SyntaxError < StandardError
33
41
  def initialize(parser, file, line_offset)
34
42
  tf = parser.terminal_failures
35
- expected = tf.size == 1 ? tf[0].expected_string.inspect : "one of #{tf.map{|f| f.expected_string}.uniq*', '}"
43
+ expected = tf.size == 1 ? tf[0].expected_string.inspect : "one of #{tf.map{|f| f.expected_string.inspect}.uniq*', '}"
36
44
  line = parser.failure_line + line_offset
37
45
  message = "#{file}:#{line}:#{parser.failure_column}: Parse error, expected #{expected}."
38
46
  super(message)
@@ -2,47 +2,48 @@ require 'cucumber/step_definition'
2
2
  require 'cucumber/core_ext/instance_exec'
3
3
 
4
4
  module Cucumber
5
- # This is the main interface for registering step definitions, which is done
6
- # from <tt>*_steps.rb</tt> files. This module is included right at the top-level
7
- # so #register_step_definition (and more interestingly - its aliases) are
8
- # available from the top-level.
9
- module StepMother
10
- attr_writer :snippet_generator
11
-
12
- class Undefined < StandardError
13
- attr_reader :step_name
5
+ class Undefined < StandardError
6
+ attr_reader :step_name
14
7
 
15
- def initialize(step_name)
16
- super %{Undefined step: "#{step_name}"}
17
- @step_name = step_name
18
- end
19
- Cucumber::EXCEPTION_STATUS[self] = :undefined
8
+ def initialize(step_name)
9
+ super %{Undefined step: "#{step_name}"}
10
+ @step_name = step_name
20
11
  end
12
+ Cucumber::EXCEPTION_STATUS[self] = :undefined
13
+ end
21
14
 
22
- class Pending < StandardError
23
- Cucumber::EXCEPTION_STATUS[self] = :pending
24
- end
15
+ class Pending < StandardError
16
+ Cucumber::EXCEPTION_STATUS[self] = :pending
17
+ end
25
18
 
26
- # Raised when a step matches 2 or more StepDefinition
27
- class Ambiguous < StandardError
28
- def initialize(step_name, step_definitions)
29
- message = "Ambiguous match of \"#{step_name}\":\n\n"
30
- message << step_definitions.map{|sd| sd.to_backtrace_line}.join("\n")
31
- message << "\n\n"
32
- super(message)
33
- end
19
+ # Raised when a step matches 2 or more StepDefinition
20
+ class Ambiguous < StandardError
21
+ def initialize(step_name, step_definitions)
22
+ message = "Ambiguous match of \"#{step_name}\":\n\n"
23
+ message << step_definitions.map{|sd| sd.to_backtrace_line}.join("\n")
24
+ message << "\n\n"
25
+ super(message)
34
26
  end
27
+ end
35
28
 
36
- # Raised when 2 or more StepDefinition have the same Regexp
37
- class Redundant < StandardError
38
- def initialize(step_def_1, step_def_2)
39
- message = "Multiple step definitions have the same Regexp:\n\n"
40
- message << step_def_1.to_backtrace_line << "\n"
41
- message << step_def_2.to_backtrace_line << "\n\n"
42
- super(message)
43
- end
29
+ # Raised when 2 or more StepDefinition have the same Regexp
30
+ class Redundant < StandardError
31
+ def initialize(step_def_1, step_def_2)
32
+ message = "Multiple step definitions have the same Regexp:\n\n"
33
+ message << step_def_1.to_backtrace_line << "\n"
34
+ message << step_def_2.to_backtrace_line << "\n\n"
35
+ super(message)
44
36
  end
37
+ end
45
38
 
39
+ # This is the main interface for registering step definitions, which is done
40
+ # from <tt>*_steps.rb</tt> files. This module is included right at the top-level
41
+ # so #register_step_definition (and more interestingly - its aliases) are
42
+ # available from the top-level.
43
+ module StepMother
44
+ attr_writer :snippet_generator
45
+ attr_writer :options
46
+
46
47
  # Registers a new StepDefinition. This method is aliased
47
48
  # to <tt>Given</tt>, <tt>When</tt> and <tt>Then</tt>.
48
49
  #
@@ -112,10 +113,22 @@ module Cucumber
112
113
  step_definition.match(step_name)
113
114
  end
114
115
  raise Undefined.new(step_name) if found.empty?
116
+ found = best_matches(step_name, found) if found.size > 1 && options[:guess]
115
117
  raise Ambiguous.new(step_name, found) if found.size > 1
116
118
  found[0]
117
119
  end
118
120
 
121
+ def best_matches(step_name, step_definitions)
122
+ top_group_score = step_definitions.map {|s| s.match(step_name).captures.length }.sort.last
123
+ top_groups = step_definitions.select {|s| s.match(step_name).captures.length == top_group_score }
124
+ if top_groups.size > 1
125
+ shortest_capture_length = top_groups.map {|s| s.match(step_name).captures.inject(0) {|sum, c| sum + c.length } }.sort.first
126
+ top_groups.select {|s| s.match(step_name).captures.inject(0) {|sum, c| sum + c.length } == shortest_capture_length }
127
+ else
128
+ top_groups
129
+ end
130
+ end
131
+
119
132
  def step_definitions
120
133
  @step_definitions ||= []
121
134
  end
@@ -124,6 +137,12 @@ module Cucumber
124
137
  @snippet_generator.snippet_text(step_keyword, step_name)
125
138
  end
126
139
 
140
+ private
141
+
142
+ def options
143
+ @options || {}
144
+ end
145
+
127
146
  module WorldMethods #:nodoc:
128
147
  attr_writer :__cucumber_step_mother, :__cucumber_current_step
129
148
 
@@ -3,7 +3,7 @@ module Cucumber #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
5
  TINY = 99
6
- PATCH = 15 # Set to nil for official release
6
+ PATCH = 17 # Set to nil for official release
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PATCH].compact.join('.')
9
9
  end
@@ -0,0 +1,239 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+ require 'yaml'
3
+
4
+ module Cucumber
5
+ module Cli
6
+ describe Configuration 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
+ Kernel.stub!(:exit).and_return(nil)
16
+ end
17
+
18
+ it "should require files in support paths first" do
19
+ File.stub!(:directory?).and_return(true)
20
+ Dir.stub!(:[]).and_return(["/features/step_definitions/foo.rb","/features/support/env.rb"])
21
+
22
+ config = Configuration.new(StringIO.new)
23
+ config.parse!(%w{--require /features})
24
+
25
+ config.files_to_require.should == [
26
+ "/features/support/env.rb",
27
+ "/features/step_definitions/foo.rb"
28
+ ]
29
+ end
30
+
31
+ it "should expand args from YAML file" do
32
+ given_cucumber_yml_defined_as({'bongo' => '--require from/yml'})
33
+
34
+ config = Configuration.new
35
+ config.parse!(%w{--format progress --profile bongo})
36
+ config.options[:formats].should == {'progress' => STDOUT}
37
+ config.options[:require].should == ['from/yml']
38
+ end
39
+
40
+ it "should expand args from YAML file's default if there are no args" do
41
+ given_cucumber_yml_defined_as({'default' => '--require from/yml'})
42
+
43
+ config = Configuration.new
44
+ config.parse!([])
45
+ config.options[:require].should == ['from/yml']
46
+ end
47
+
48
+ it "should provide a helpful error message when a specified profile does not exists in YAML file" do
49
+ given_cucumber_yml_defined_as({'default' => '--require from/yml', 'html_report' => '--format html'})
50
+
51
+ config = Configuration.new(StringIO.new, error = StringIO.new)
52
+ config.parse!(%w{--profile i_do_not_exist})
53
+
54
+ expected_message = <<-END_OF_MESSAGE
55
+ Could not find profile: 'i_do_not_exist'
56
+
57
+ Defined profiles in cucumber.yml:
58
+ * default
59
+ * html_report
60
+ END_OF_MESSAGE
61
+
62
+ error.string.should == expected_message
63
+ end
64
+
65
+ it "should provide a helpful error message when a specified profile is not a String" do
66
+ given_cucumber_yml_defined_as({'foo' => [1,2,3]})
67
+
68
+ config = Configuration.new(StringIO.new, error = StringIO.new)
69
+ config.parse!(%w{--profile foo})
70
+
71
+ error.string.should == "Profiles must be defined as a String. The 'foo' profile was [1, 2, 3] (Array).\n"
72
+ end
73
+
74
+ it "should provide a helpful error message when a specified profile exists but is nil or blank" do
75
+ [nil, ' '].each do |bad_input|
76
+ given_cucumber_yml_defined_as({'foo' => bad_input})
77
+
78
+ config = Configuration.new(StringIO.new, error = StringIO.new)
79
+ config.parse!(%w{--profile foo})
80
+
81
+ error.string.should match(/The 'foo' profile in cucumber.yml was blank. Please define the command line arguments for the 'foo' profile in cucumber.yml./)
82
+ end
83
+ end
84
+
85
+ it "should provide a helpful error message when no YAML file exists and a profile is specified" do
86
+ File.should_receive(:exist?).with('cucumber.yml').and_return(false)
87
+
88
+ config = Configuration.new(StringIO.new, error = StringIO.new)
89
+ config.parse!(%w{--profile i_do_not_exist})
90
+
91
+ error.string.should match(/cucumber.yml was not found. Please refer to cucumber's documentaion on defining profiles in cucumber.yml./)
92
+ end
93
+
94
+ it "should provide a helpful error message when cucumber.yml is blank or malformed" do
95
+ expected_error_message = /cucumber.yml was found, but was blank or malformed. Please refer to cucumber's documentaion on correct profile usage./
96
+
97
+ ['', 'sfsadfs', "--- \n- an\n- array\n", "---dddfd"].each do |bad_input|
98
+ given_cucumber_yml_defined_as(bad_input)
99
+
100
+ config = Configuration.new(StringIO.new, error = StringIO.new)
101
+ config.parse!([])
102
+
103
+ error.string.should match(expected_error_message)
104
+ end
105
+ end
106
+
107
+ it "should procide a helpful error message when the YAML can not be parsed" do
108
+ expected_error_message = /cucumber.yml was found, but could not be parsed. Please refer to cucumber's documentaion on correct profile usage./
109
+
110
+ given_cucumber_yml_defined_as("input that causes an exception in YAML loading")
111
+ YAML.should_receive(:load).and_raise Exception
112
+
113
+ config = Configuration.new(StringIO.new, error = StringIO.new)
114
+ config.parse!([])
115
+
116
+ error.string.should match(expected_error_message)
117
+ end
118
+
119
+ it "should accept --dry-run option" do
120
+ config = Configuration.new(StringIO.new)
121
+ config.parse!(%w{--dry-run})
122
+ config.options[:dry_run].should be_true
123
+ end
124
+
125
+ it "should accept --no-source option" do
126
+ config = Configuration.new
127
+ config.parse!(%w{--no-source})
128
+
129
+ config.options[:source].should be_false
130
+ end
131
+
132
+ it "should accept --no-snippets option" do
133
+ config = Configuration.new
134
+ config.parse!(%w{--no-snippets})
135
+
136
+ config.options[:snippets].should be_false
137
+ end
138
+
139
+ it "should set snippets and source to false with --quiet option" do
140
+ config = Configuration.new
141
+ config.parse!(%w{--quiet})
142
+
143
+ config.options[:snippets].should be_nil
144
+ config.options[:source].should be_nil
145
+ end
146
+
147
+ it "should accept --verbose option" do
148
+ config = Configuration.new
149
+ config.parse!(%w{--verbose})
150
+
151
+ config.options[:verbose].should be_true
152
+ end
153
+
154
+ it "should accept --out option" do
155
+ config = Configuration.new(StringIO.new)
156
+ config.parse!(%w{--out jalla.txt})
157
+ config.options[:formats]['pretty'].should == 'jalla.txt'
158
+ end
159
+
160
+ it "should accept multiple --out options" do
161
+ config = Configuration.new(StringIO.new)
162
+ config.parse!(%w{--format progress --out file1 --out file2})
163
+ config.options[:formats].should == {'progress' => 'file2'}
164
+ end
165
+
166
+ it "should accept multiple --format options" do
167
+ config = Configuration.new(StringIO.new)
168
+ config.parse!(%w{--format pretty --format progress})
169
+ config.options[:formats].should have_key('pretty')
170
+ config.options[:formats].should have_key('progress')
171
+ end
172
+
173
+ it "should associate --out to previous --format" do
174
+ config = Configuration.new(StringIO.new)
175
+ config.parse!(%w{--format progress --out file1 --format profile --out file2})
176
+ config.options[:formats].should == {"profile"=>"file2", "progress"=>"file1"}
177
+ end
178
+
179
+ it "should accept --color option" do
180
+ Term::ANSIColor.should_receive(:coloring=).with(true)
181
+ config = Configuration.new(StringIO.new)
182
+ config.parse!(['--color'])
183
+ end
184
+
185
+ it "should accept --no-color option" do
186
+ Term::ANSIColor.should_receive(:coloring=).with(false)
187
+ config = Configuration.new(StringIO.new)
188
+ config.parse!(['--no-color'])
189
+ end
190
+
191
+ describe "--backtrace" do
192
+ before do
193
+ Exception.cucumber_full_backtrace = false
194
+ end
195
+
196
+ it "should show full backtrace when --backtrace is present" do
197
+ config = Main.new(['--backtrace'])
198
+ begin
199
+ "x".should == "y"
200
+ rescue => e
201
+ e.backtrace[0].should_not == "#{__FILE__}:#{__LINE__ - 2}"
202
+ end
203
+ end
204
+
205
+ xit "should strip gems when --backtrace is absent" do
206
+ config = Main.new(['--'])
207
+ begin
208
+ "x".should == "y"
209
+ rescue => e
210
+ e.backtrace[0].should == "#{__FILE__}:#{__LINE__ - 2}"
211
+ end
212
+ end
213
+
214
+ after do
215
+ Exception.cucumber_full_backtrace = false
216
+ end
217
+ end
218
+
219
+ it "should accept multiple --scenario options" do
220
+ config = Configuration.new
221
+ config.parse!(['--scenario', "User logs in", '--scenario', "User signs up"])
222
+
223
+ config.options[:scenario_names].should include("User logs in")
224
+ config.options[:scenario_names].should include("User signs up")
225
+ end
226
+
227
+ it "should search for all features in the specified directory" do
228
+ File.stub!(:directory?).and_return(true)
229
+ Dir.should_receive(:[]).with("feature_directory/**/*.feature").any_number_of_times.and_return(["cucumber.feature"])
230
+
231
+ config = Configuration.new(StringIO)
232
+ config.parse!(%w{feature_directory/})
233
+
234
+ config.feature_files.should == ["cucumber.feature"]
235
+ end
236
+
237
+ end
238
+ end
239
+ end