cucumber 0.8.5 → 0.8.6

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 (181) hide show
  1. data/.rspec +1 -1
  2. data/LICENSE +1 -1
  3. data/Rakefile +5 -51
  4. data/bin/cucumber +7 -1
  5. data/cucumber.gemspec +463 -679
  6. data/examples/i18n/ar/features/step_definitons/calculator_steps.rb +1 -1
  7. data/examples/i18n/he/features/step_definitons/calculator_steps.rb +1 -1
  8. data/examples/i18n/ro/features/step_definitons/calculator_steps.rb +4 -7
  9. data/examples/i18n/ru/features/division.feature +2 -2
  10. data/examples/i18n/tr/features/step_definitons/hesap_makinesi_adimlari.rb +3 -3
  11. data/examples/sinatra/features/support/env.rb +2 -5
  12. data/examples/v8/features/fibonacci.feature +1 -1
  13. data/examples/watir/features/step_definitions/search_steps.rb +1 -1
  14. data/features/background.feature +284 -95
  15. data/features/custom_formatter.feature +3 -73
  16. data/features/json_formatter.feature +160 -245
  17. data/features/step_definitions/cucumber_steps.rb +7 -153
  18. data/features/support/env.rb +18 -140
  19. data/fixtures/junit/features/pending.feature +3 -1
  20. data/fixtures/self_test/features/support/env.rb +8 -0
  21. data/fixtures/tickets/features.html +1 -1
  22. data/gem_tasks/examples.rake +1 -1
  23. data/lib/cucumber.rb +12 -0
  24. data/lib/cucumber/ast.rb +1 -1
  25. data/lib/cucumber/ast/background.rb +21 -5
  26. data/lib/cucumber/ast/examples.rb +12 -4
  27. data/lib/cucumber/ast/feature.rb +13 -5
  28. data/lib/cucumber/ast/feature_element.rb +9 -4
  29. data/lib/cucumber/ast/outline_table.rb +4 -4
  30. data/lib/cucumber/ast/scenario.rb +7 -5
  31. data/lib/cucumber/ast/scenario_outline.rb +23 -15
  32. data/lib/cucumber/ast/step.rb +5 -0
  33. data/lib/cucumber/ast/step_invocation.rb +21 -15
  34. data/lib/cucumber/ast/table.rb +14 -8
  35. data/lib/cucumber/ast/tree_walker.rb +10 -48
  36. data/lib/cucumber/cli/configuration.rb +33 -8
  37. data/lib/cucumber/cli/main.rb +20 -35
  38. data/lib/cucumber/cli/options.rb +8 -7
  39. data/lib/cucumber/cli/profile_loader.rb +2 -0
  40. data/lib/cucumber/core_ext/proc.rb +2 -1
  41. data/lib/cucumber/feature_file.rb +47 -15
  42. data/lib/cucumber/formatter/ansicolor.rb +3 -5
  43. data/lib/cucumber/formatter/console.rb +27 -23
  44. data/lib/cucumber/formatter/cucumber.css +34 -17
  45. data/lib/cucumber/formatter/cucumber.sass +173 -182
  46. data/lib/cucumber/formatter/html.rb +46 -11
  47. data/lib/cucumber/formatter/io.rb +2 -4
  48. data/lib/cucumber/formatter/json.rb +15 -152
  49. data/lib/cucumber/formatter/json_pretty.rb +5 -6
  50. data/lib/cucumber/formatter/junit.rb +28 -22
  51. data/lib/cucumber/formatter/pdf.rb +6 -6
  52. data/lib/cucumber/formatter/pretty.rb +5 -5
  53. data/lib/cucumber/formatter/rerun.rb +22 -11
  54. data/lib/cucumber/formatter/unicode.rb +41 -20
  55. data/lib/cucumber/js_support/js_dsl.js +4 -4
  56. data/lib/cucumber/js_support/js_language.rb +9 -5
  57. data/lib/cucumber/js_support/js_snippets.rb +2 -2
  58. data/lib/cucumber/language_support.rb +2 -2
  59. data/lib/cucumber/parser/gherkin_builder.rb +35 -30
  60. data/lib/cucumber/platform.rb +8 -8
  61. data/lib/cucumber/py_support/py_language.rb +2 -2
  62. data/lib/cucumber/rake/task.rb +80 -31
  63. data/lib/cucumber/rb_support/rb_dsl.rb +1 -0
  64. data/lib/cucumber/rb_support/rb_language.rb +10 -8
  65. data/lib/cucumber/rb_support/rb_step_definition.rb +8 -0
  66. data/lib/cucumber/rb_support/rb_transform.rb +17 -0
  67. data/lib/cucumber/rb_support/rb_world.rb +26 -18
  68. data/lib/cucumber/rspec/doubles.rb +3 -3
  69. data/lib/cucumber/step_match.rb +6 -2
  70. data/lib/cucumber/step_mother.rb +6 -427
  71. data/lib/cucumber/wire_support/configuration.rb +4 -1
  72. data/lib/cucumber/wire_support/wire_language.rb +3 -10
  73. data/spec/cucumber/ast/background_spec.rb +68 -6
  74. data/spec/cucumber/ast/feature_factory.rb +5 -4
  75. data/spec/cucumber/ast/feature_spec.rb +4 -4
  76. data/spec/cucumber/ast/outline_table_spec.rb +1 -1
  77. data/spec/cucumber/ast/scenario_outline_spec.rb +15 -11
  78. data/spec/cucumber/ast/scenario_spec.rb +4 -4
  79. data/spec/cucumber/ast/step_spec.rb +3 -3
  80. data/spec/cucumber/ast/table_spec.rb +38 -2
  81. data/spec/cucumber/ast/tree_walker_spec.rb +2 -2
  82. data/spec/cucumber/broadcaster_spec.rb +1 -1
  83. data/spec/cucumber/cli/configuration_spec.rb +32 -6
  84. data/spec/cucumber/cli/drb_client_spec.rb +2 -3
  85. data/spec/cucumber/cli/main_spec.rb +43 -43
  86. data/spec/cucumber/cli/options_spec.rb +28 -1
  87. data/spec/cucumber/cli/profile_loader_spec.rb +1 -1
  88. data/spec/cucumber/core_ext/proc_spec.rb +1 -1
  89. data/spec/cucumber/formatter/ansicolor_spec.rb +1 -1
  90. data/spec/cucumber/formatter/duration_spec.rb +1 -1
  91. data/spec/cucumber/formatter/html_spec.rb +3 -5
  92. data/spec/cucumber/formatter/junit_spec.rb +16 -2
  93. data/spec/cucumber/formatter/progress_spec.rb +1 -1
  94. data/spec/cucumber/formatter/spec_helper.rb +11 -12
  95. data/spec/cucumber/rb_support/rb_language_spec.rb +241 -28
  96. data/spec/cucumber/rb_support/rb_step_definition_spec.rb +33 -28
  97. data/spec/cucumber/rb_support/regexp_argument_matcher_spec.rb +1 -1
  98. data/spec/cucumber/step_match_spec.rb +11 -9
  99. data/spec/cucumber/wire_support/configuration_spec.rb +1 -1
  100. data/spec/cucumber/wire_support/connection_spec.rb +1 -1
  101. data/spec/cucumber/wire_support/wire_exception_spec.rb +1 -1
  102. data/spec/cucumber/wire_support/wire_language_spec.rb +1 -1
  103. data/spec/cucumber/wire_support/wire_packet_spec.rb +1 -1
  104. data/spec/cucumber/wire_support/wire_step_definition_spec.rb +1 -1
  105. data/spec/cucumber/world/pending_spec.rb +2 -2
  106. data/spec/spec_helper.rb +13 -20
  107. metadata +11 -222
  108. data/.gitignore +0 -20
  109. data/Caliper.yml +0 -4
  110. data/History.txt +0 -1552
  111. data/README.rdoc +0 -26
  112. data/VERSION.yml +0 -5
  113. data/examples/i18n/ro/features/suma.feature +0 -11
  114. data/features/announce.feature +0 -164
  115. data/features/around_hooks.feature +0 -232
  116. data/features/bug_371.feature +0 -32
  117. data/features/bug_464.feature +0 -16
  118. data/features/bug_475.feature +0 -42
  119. data/features/bug_585_tab_indentation.feature +0 -22
  120. data/features/bug_600.feature +0 -67
  121. data/features/call_steps_from_stepdefs.feature +0 -154
  122. data/features/cucumber_cli.feature +0 -591
  123. data/features/cucumber_cli_outlines.feature +0 -117
  124. data/features/default_snippets.feature +0 -42
  125. data/features/diffing.feature +0 -25
  126. data/features/drb_server_integration.feature +0 -174
  127. data/features/exception_in_after_block.feature +0 -127
  128. data/features/exception_in_after_step_block.feature +0 -104
  129. data/features/exception_in_before_block.feature +0 -98
  130. data/features/exclude_files.feature +0 -20
  131. data/features/expand.feature +0 -60
  132. data/features/html_formatter.feature +0 -8
  133. data/features/html_formatter/a.html +0 -582
  134. data/features/junit_formatter.feature +0 -88
  135. data/features/language_from_header.feature +0 -30
  136. data/features/language_help.feature +0 -78
  137. data/features/listener_debugger_formatter.feature +0 -42
  138. data/features/multiline_names.feature +0 -44
  139. data/features/negative_tagged_hooks.feature +0 -60
  140. data/features/post_configuration_hook.feature +0 -37
  141. data/features/profiles.feature +0 -126
  142. data/features/rake_task.feature +0 -152
  143. data/features/report_called_undefined_steps.feature +0 -34
  144. data/features/rerun_formatter.feature +0 -45
  145. data/features/simplest.feature +0 -11
  146. data/features/snippet.feature +0 -23
  147. data/features/snippets_when_using_star_keyword.feature +0 -36
  148. data/features/step_definitions/extra_steps.rb +0 -2
  149. data/features/step_definitions/simplest_steps.rb +0 -3
  150. data/features/step_definitions/wire_steps.rb +0 -32
  151. data/features/support/env.rb.simplest +0 -7
  152. data/features/support/fake_wire_server.rb +0 -77
  153. data/features/table_diffing.feature +0 -45
  154. data/features/table_mapping.feature +0 -34
  155. data/features/tag_logic.feature +0 -258
  156. data/features/transform.feature +0 -245
  157. data/features/unicode_table.feature +0 -35
  158. data/features/usage_and_stepdefs_formatter.feature +0 -169
  159. data/features/wire_protocol.feature +0 -332
  160. data/features/wire_protocol_table_diffing.feature +0 -119
  161. data/features/wire_protocol_tags.feature +0 -87
  162. data/features/wire_protocol_timeouts.feature +0 -63
  163. data/features/work_in_progress.feature +0 -156
  164. data/fixtures/json/features/pystring.feature +0 -8
  165. data/fixtures/self_test/features/background/background_tagged_before_on_outline.feature +0 -12
  166. data/fixtures/self_test/features/background/background_with_name.feature +0 -7
  167. data/fixtures/self_test/features/background/failing_background.feature +0 -12
  168. data/fixtures/self_test/features/background/failing_background_after_success.feature +0 -11
  169. data/fixtures/self_test/features/background/multiline_args_background.feature +0 -32
  170. data/fixtures/self_test/features/background/passing_background.feature +0 -10
  171. data/fixtures/self_test/features/background/pending_background.feature +0 -10
  172. data/fixtures/self_test/features/background/scenario_outline_failing_background.feature +0 -16
  173. data/fixtures/self_test/features/background/scenario_outline_passing_background.feature +0 -16
  174. data/gem_tasks/features.rake +0 -14
  175. data/gem_tasks/sdoc.rake +0 -12
  176. data/lib/cucumber/ast/py_string.rb +0 -80
  177. data/lib/cucumber/formatter/color_io.rb +0 -23
  178. data/lib/cucumber/formatter/tag_cloud.rb +0 -35
  179. data/spec/cucumber/ast/py_string_spec.rb +0 -40
  180. data/spec/cucumber/formatter/color_io_spec.rb +0 -29
  181. data/spec/cucumber/step_mother_spec.rb +0 -302
@@ -2,11 +2,11 @@ module Cucumber
2
2
  module Ast
3
3
  # Walks the AST, executing steps and notifying listeners
4
4
  class TreeWalker
5
- attr_accessor :options #:nodoc:
5
+ attr_accessor :configuration #:nodoc:
6
6
  attr_reader :step_mother #:nodoc:
7
7
 
8
- def initialize(step_mother, listeners = [], options = {}, io = STDOUT)
9
- @step_mother, @listeners, @options, @io = step_mother, listeners, options, io
8
+ def initialize(step_mother, listeners = [], configuration = Cucumber::Configuration.default)
9
+ @step_mother, @listeners, @configuration = step_mother, listeners, configuration
10
10
  end
11
11
 
12
12
  def visit_features(features)
@@ -122,7 +122,7 @@ module Cucumber
122
122
  broadcast(exception, status)
123
123
  end
124
124
 
125
- def visit_py_string(string)
125
+ def visit_doc_string(string)
126
126
  broadcast(string)
127
127
  end
128
128
 
@@ -142,15 +142,15 @@ module Cucumber
142
142
  broadcast(value, status)
143
143
  end
144
144
 
145
- # Print +announcement+. This method can be called from within StepDefinitions.
146
- def announce(announcement)
147
- broadcast(announcement)
145
+ # Print +messages+. This method can be called from within StepDefinitions.
146
+ def puts(*messages)
147
+ broadcast(*messages)
148
148
  end
149
149
 
150
150
  # Embed +file+ of +mime_type+ in the formatter. This method can be called from within StepDefinitions.
151
151
  # For most formatters this is a no-op.
152
- def embed(file, mime_type)
153
- broadcast(file, mime_type)
152
+ def embed(file, mime_type, label)
153
+ broadcast(file, mime_type, label)
154
154
  end
155
155
 
156
156
  private
@@ -171,48 +171,10 @@ module Cucumber
171
171
  def send_to_all(message, *args)
172
172
  @listeners.each do |listener|
173
173
  if listener.respond_to?(message)
174
- if legacy_listener?(listener)
175
- warn_legacy(listener)
176
- legacy_invoke(listener, message, *args)
177
- else
178
- listener.__send__(message, *args)
179
- end
174
+ listener.__send__(message, *args)
180
175
  end
181
176
  end
182
177
  end
183
-
184
- def legacy_listener?(listener)
185
- listener.respond_to?(:feature_name) &&
186
- (listener.method(:feature_name) rescue false) &&
187
- listener.method(:feature_name).arity == 1
188
- end
189
-
190
- def warn_legacy(listener)
191
- @warned_listeners ||= []
192
- unless @warned_listeners.index(listener)
193
- warn("#{listener.class} is using a deprecated formatter API. Starting with Cucumber 0.7.0 the signatures\n" +
194
- "that have changed are:\n" +
195
- " feature_name(keyword, name) # Two arguments. The keyword argument will not contain a colon.\n" +
196
- " scenario_name(keyword, name, file_colon_line, source_indent) # The keyword argument will not contain a colon.\n" +
197
- " examples_name(keyword, name) # The keyword argument will not contain a colon.\n"
198
- )
199
- end
200
- @warned_listeners << listener
201
- end
202
-
203
- def legacy_invoke(listener, message, *args)
204
- case message.to_sym
205
- when :feature_name
206
- listener.feature_name("#{args[0]}: #{args[1]}")
207
- when :scenario_name, :examples_name
208
- args_with_colon = args.dup
209
- args_with_colon[0] += ':'
210
- listener.__send__(message, *args_with_colon)
211
- else
212
- listener.__send__(message, *args)
213
- end
214
- end
215
-
216
178
  def extract_method_name_from(call_stack)
217
179
  call_stack[0].match(/in `(.*)'/).captures[0]
218
180
  end
@@ -12,7 +12,7 @@ module Cucumber
12
12
  class Configuration
13
13
  include Constantize
14
14
 
15
- attr_reader :options, :out_stream
15
+ attr_reader :out_stream
16
16
 
17
17
  def initialize(out_stream = STDOUT, error_stream = STDERR)
18
18
  @out_stream = out_stream
@@ -56,8 +56,16 @@ module Cucumber
56
56
  @options[:drb_port].to_i if @options[:drb_port]
57
57
  end
58
58
 
59
- def build_runner(step_mother, io)
60
- Ast::TreeWalker.new(step_mother, formatters(step_mother), @options, io)
59
+ def dry_run?
60
+ @options[:dry_run]
61
+ end
62
+
63
+ def expand?
64
+ @options[:expand]
65
+ end
66
+
67
+ def build_tree_walker(step_mother)
68
+ Ast::TreeWalker.new(step_mother, formatters(step_mother), self)
61
69
  end
62
70
 
63
71
  def formatter_class(format)
@@ -98,7 +106,7 @@ module Cucumber
98
106
  path = path.gsub(/\\/, '/') # In case we're on windows. Globs don't work with backslashes.
99
107
  path = path.chomp('/')
100
108
  if File.directory?(path)
101
- Dir["#{path}/**/*.feature"]
109
+ Dir["#{path}/**/*.feature"].sort
102
110
  elsif path[0..0] == '@' and # @listfile.txt
103
111
  File.file?(path[1..-1]) # listfile.txt is a file
104
112
  IO.read(path[1..-1]).split
@@ -121,7 +129,27 @@ module Cucumber
121
129
  logger.level = Logger::DEBUG if self.verbose?
122
130
  logger
123
131
  end
124
-
132
+
133
+ def tag_expression
134
+ Gherkin::TagExpression.new(@options[:tag_expressions])
135
+ end
136
+
137
+ def filters
138
+ @options.filters
139
+ end
140
+
141
+ def formats
142
+ @options[:formats]
143
+ end
144
+
145
+ def options
146
+ warn("Deprecated: Configuration#options will be removed from the next release of Cucumber. Please use the configuration object directly instead.")
147
+ @options
148
+ end
149
+
150
+ def paths
151
+ @options[:paths].empty? ? ['features'] : @options[:paths]
152
+ end
125
153
  private
126
154
 
127
155
  def formatters(step_mother)
@@ -151,9 +179,6 @@ module Cucumber
151
179
  end
152
180
  end
153
181
 
154
- def paths
155
- @options[:paths].empty? ? ['features'] : @options[:paths]
156
- end
157
182
 
158
183
  def set_environment_variables
159
184
  @options[:env_vars].each do |var, value|
@@ -9,7 +9,6 @@ require 'cucumber'
9
9
  require 'logger'
10
10
  require 'cucumber/parser'
11
11
  require 'cucumber/feature_file'
12
- require 'cucumber/formatter/color_io'
13
12
  require 'cucumber/cli/configuration'
14
13
  require 'cucumber/cli/drb_client'
15
14
 
@@ -17,55 +16,32 @@ module Cucumber
17
16
  module Cli
18
17
  class Main
19
18
  class << self
20
- def step_mother
21
- @step_mother ||= StepMother.new
22
- end
23
-
24
19
  def execute(args)
25
- new(args).execute!(step_mother)
20
+ new(args).execute!
26
21
  end
27
22
  end
28
23
 
29
24
  def initialize(args, out_stream = STDOUT, error_stream = STDERR)
30
25
  @args = args
31
- if Cucumber::WINDOWS_MRI
32
- @out_stream = out_stream == STDOUT ? Formatter::ColorIO.new(Kernel, STDOUT) : out_stream
33
- else
34
- @out_stream = out_stream
35
- end
26
+ @out_stream = out_stream
36
27
 
37
28
  @error_stream = error_stream
38
29
  @configuration = nil
39
30
  end
40
31
 
41
- def execute!(step_mother)
32
+ def execute!(existing_runtime = nil)
42
33
  trap_interrupt
43
- if configuration.drb?
44
- begin
45
- return DRbClient.run(@args, @error_stream, @out_stream, configuration.drb_port)
46
- rescue DRbClientError => e
47
- @error_stream.puts "WARNING: #{e.message} Running features locally:"
48
- end
49
- end
50
- step_mother.options = configuration.options
51
- step_mother.log = configuration.log
52
-
53
- step_mother.load_code_files(configuration.support_to_load)
54
- step_mother.after_configuration(configuration)
55
- features = step_mother.load_plain_text_features(configuration.feature_files)
56
- step_mother.load_code_files(configuration.step_defs_to_load)
57
-
58
- runner = configuration.build_runner(step_mother, @out_stream)
59
- step_mother.visitor = runner # Needed to support World#announce
34
+ return @drb_output if run_drb_client
60
35
 
61
- runner.visit_features(features)
62
-
63
- failure = if configuration.wip?
64
- step_mother.scenarios(:passed).any?
36
+ runtime = if existing_runtime
37
+ existing_runtime.configure(configuration)
38
+ existing_runtime
65
39
  else
66
- step_mother.scenarios(:failed).any? ||
67
- (configuration.strict? && (step_mother.steps(:undefined).any? || step_mother.steps(:pending).any?))
40
+ Runtime.new(configuration)
68
41
  end
42
+
43
+ runtime.run!
44
+ runtime.results.failure?
69
45
  rescue ProfilesNotDefinedError, YmlLoadError, ProfileNotFound => e
70
46
  @error_stream.puts e.message
71
47
  true
@@ -76,10 +52,19 @@ module Cucumber
76
52
 
77
53
  @configuration = Configuration.new(@out_stream, @error_stream)
78
54
  @configuration.parse!(@args)
55
+ Cucumber.logger = @configuration.log
79
56
  @configuration
80
57
  end
81
58
 
82
59
  private
60
+
61
+ def run_drb_client
62
+ return false unless configuration.drb?
63
+ @drb_output = DRbClient.run(@args, @error_stream, @out_stream, configuration.drb_port)
64
+ true
65
+ rescue DRbClientError => e
66
+ @error_stream.puts "WARNING: #{e.message} Running features locally:"
67
+ end
83
68
 
84
69
  def trap_interrupt
85
70
  trap('INT') do
@@ -24,8 +24,7 @@ module Cucumber
24
24
  "#{INDENT}the usage formatter, except that steps are not printed."],
25
25
  'junit' => ['Cucumber::Formatter::Junit', 'Generates a report similar to Ant+JUnit.'],
26
26
  'json' => ['Cucumber::Formatter::Json', 'Prints the feature as JSON'],
27
- 'json_pretty' => ['Cucumber::Formatter::JsonPretty', 'Prints the feature as pretty JSON'],
28
- 'tag_cloud' => ['Cucumber::Formatter::TagCloud', 'Prints a tag cloud of tag usage.'],
27
+ 'json_pretty' => ['Cucumber::Formatter::JsonPretty', 'Prints the feature as prettified JSON'],
29
28
  'debug' => ['Cucumber::Formatter::Debug', 'For developing formatters - prints the calls made to the listeners.']
30
29
  }
31
30
  max = BUILTIN_FORMATS.keys.map{|s| s.length}.max
@@ -165,7 +164,7 @@ module Cucumber
165
164
  "This represents the boolean expression (@foo || !@bar) && @zap.",
166
165
  "\n",
167
166
  "Beware that if you want to use several negative tags to exclude several tags",
168
- "you have to use logical AND: --tags ~@fixme --tags @buggy.",
167
+ "you have to use logical AND: --tags ~@fixme --tags ~@buggy.",
169
168
  "\n",
170
169
  "Positive tags can be given a threshold to limit the number of occurrences.",
171
170
  "Example: --tags @qa:3 will fail if there are more than 3 occurrences of the @qa tag.",
@@ -199,10 +198,8 @@ module Cucumber
199
198
  Term::ANSIColor.coloring = v
200
199
  end
201
200
  opts.on("-d", "--dry-run", "Invokes formatters without executing the steps.",
202
- "This also omits the loading of your support/env.rb file if it exists.",
203
- "Implies --no-snippets.") do
201
+ "This also omits the loading of your support/env.rb file if it exists.") do
204
202
  @options[:dry_run] = true
205
- @options[:snippets] = false
206
203
  end
207
204
  opts.on("-a", "--autoformat DIR",
208
205
  "Reformats (pretty prints) feature files and write them to DIRECTORY.",
@@ -231,7 +228,7 @@ module Cucumber
231
228
  opts.on("-b", "--backtrace", "Show full backtrace for all errors.") do
232
229
  Cucumber.use_full_backtrace = true
233
230
  end
234
- opts.on("-S", "--strict", "Fail if there are any undefined steps.") do
231
+ opts.on("-S", "--strict", "Fail if there are any undefined or pending steps.") do
235
232
  @options[:strict] = true
236
233
  end
237
234
  opts.on("-w", "--wip", "Fail if there are any passing scenarios.") do
@@ -243,6 +240,9 @@ module Cucumber
243
240
  opts.on("-g", "--guess", "Guess best match for Ambiguous steps.") do
244
241
  @options[:guess] = true
245
242
  end
243
+ opts.on("-l", "--lines LINES", "Run given line numbers. Equivalent to FILE:LINE syntax") do |lines|
244
+ @options[:lines] = lines
245
+ end
246
246
  opts.on("-x", "--expand", "Expand Scenario Outline Tables in output.") do
247
247
  @options[:expand] = true
248
248
  end
@@ -268,6 +268,7 @@ module Cucumber
268
268
  @options[:snippets] = true if @options[:snippets].nil?
269
269
  @options[:source] = true if @options[:source].nil?
270
270
  end
271
+ @args.map! { |a| "#{a}:#{@options[:lines]}" } if @options[:lines]
271
272
 
272
273
  extract_environment_variables
273
274
  @options[:paths] = @args.dup #whatver is left over
@@ -1,3 +1,5 @@
1
+ require 'yaml'
2
+
1
3
  module Cucumber
2
4
  module Cli
3
5
 
@@ -1,6 +1,7 @@
1
1
  # Proc extension to get more location info out of a proc
2
2
  class Proc #:nodoc:
3
3
  PROC_PATTERN = /[\d\w]+@(.+):(\d+).*>/
4
+ PWD = Dir.pwd
4
5
 
5
6
  def to_comment_line
6
7
  "# #{file_colon_line}"
@@ -14,7 +15,7 @@ class Proc #:nodoc:
14
15
  def file_colon_line
15
16
  path, line = *to_s.match(PROC_PATTERN)[1..2]
16
17
  path = File.expand_path(path)
17
- pwd = File.expand_path(Dir.pwd)
18
+ pwd = File.expand_path(PWD)
18
19
  if path.index(pwd)
19
20
  path = path[pwd.length+1..-1]
20
21
  elsif path =~ /.*\/gems\/(.*\.rb)$/
@@ -2,14 +2,15 @@ require 'cucumber/parser/gherkin_builder'
2
2
  require 'gherkin/formatter/filter_formatter'
3
3
  require 'gherkin/formatter/tag_count_formatter'
4
4
  require 'gherkin/parser/parser'
5
- require 'gherkin/i18n_lexer'
6
5
 
7
6
  module Cucumber
8
7
  class FeatureFile
9
8
  FILE_COLON_LINE_PATTERN = /^([\w\W]*?):([\d:]+)$/ #:nodoc:
10
- LANGUAGE_PATTERN = /language:\s*(.*)/ #:nodoc:
9
+ DEFAULT_ENCODING = "UTF-8" #:nodoc:
10
+ COMMENT_OR_EMPTY_LINE_PATTERN = /^\s*#|^\s*$/ #:nodoc:
11
+ ENCODING_PATTERN = /^\s*#\s*encoding\s*:\s*([^\s]+)/ #:nodoc:
11
12
 
12
- # The +uri+ argument is the location of the source. It can ba a path
13
+ # The +uri+ argument is the location of the source. It can be a path
13
14
  # or a path:line1:line2 etc. If +source+ is passed, +uri+ is ignored.
14
15
  def initialize(uri, source=nil)
15
16
  @source = source
@@ -20,12 +21,12 @@ module Cucumber
20
21
  @path = uri
21
22
  end
22
23
  end
23
-
24
+
24
25
  # Parses a file and returns a Cucumber::Ast
25
- # If +options+ contains tags, the result will
26
+ # If +configuration_filters+ contains any filters, the result will
26
27
  # be filtered.
27
- def parse(options, tag_counts)
28
- filters = @lines || options.filters
28
+ def parse(configuration_filters, tag_counts)
29
+ filters = @lines || configuration_filters
29
30
 
30
31
  builder = Cucumber::Parser::GherkinBuilder.new
31
32
  filter_formatter = filters.empty? ? builder : Gherkin::Formatter::FilterFormatter.new(builder, filters)
@@ -39,7 +40,7 @@ module Cucumber
39
40
  ast.language = parser.i18n_language
40
41
  ast.file = @path
41
42
  ast
42
- rescue Gherkin::LexingError, Gherkin::Parser::ParseError => e
43
+ rescue Gherkin::Lexer::LexingError, Gherkin::Parser::ParseError => e
43
44
  e.message.insert(0, "#{@path}: ")
44
45
  raise e
45
46
  end
@@ -51,19 +52,50 @@ module Cucumber
51
52
  open(@path).read
52
53
  else
53
54
  begin
54
- File.open(@path, Cucumber.file_mode('r')).read
55
+ source = File.open(@path, Cucumber.file_mode('r', DEFAULT_ENCODING)).read
56
+ encoding = encoding_for(source)
57
+ if(DEFAULT_ENCODING.downcase != encoding.downcase)
58
+ # Read the file again - it's explicitly declaring a different encoding
59
+ source = File.open(@path, Cucumber.file_mode('r', encoding)).read
60
+ source = to_default_encoding(source, encoding)
61
+ end
62
+ source
55
63
  rescue Errno::EACCES => e
56
- p = File.expand_path(@path)
57
- e.message << "\nCouldn't open #{p}"
64
+ e.message << "\nCouldn't open #{File.expand_path(@path)}"
65
+ raise e
66
+ rescue Errno::ENOENT => e
67
+ # special-case opening features, because this could be a new user:
68
+ if(@path == 'features')
69
+ STDERR.puts("You don't have a 'features' directory. Please create one to get started.",
70
+ "See http://cukes.info/ for more information.")
71
+ exit 1
72
+ end
58
73
  raise e
59
74
  end
60
75
  end
61
76
  end
62
-
77
+
63
78
  private
64
79
 
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
80
+ def encoding_for(source)
81
+ encoding = DEFAULT_ENCODING
82
+ source.each_line do |line|
83
+ break unless COMMENT_OR_EMPTY_LINE_PATTERN =~ line
84
+ if ENCODING_PATTERN =~ line
85
+ encoding = $1
86
+ break
87
+ end
88
+ end
89
+ encoding
90
+ end
91
+
92
+ def to_default_encoding(string, encoding)
93
+ if string.respond_to?(:encode)
94
+ string.encode(DEFAULT_ENCODING)
95
+ else
96
+ require 'iconv'
97
+ Iconv.new(DEFAULT_ENCODING, encoding).iconv(string)
98
+ end
99
+ end
68
100
  end
69
101
  end
@@ -15,15 +15,13 @@ if Cucumber::IRONRUBY
15
15
  end
16
16
 
17
17
  if Cucumber::WINDOWS_MRI
18
- begin
19
- require 'Win32/Console/ANSI'
20
- rescue LoadError
21
- STDERR.puts %{*** WARNING: You must "gem install win32console" (1.2.0 or higher) to get coloured output on MRI/Windows}
18
+ unless ENV['ANSICON']
19
+ STDERR.puts %{*** WARNING: You must use ANSICON 1.31 or higher (http://adoxa.110mb.com/ansicon) to get coloured output on Windows}
22
20
  Term::ANSIColor.coloring = false
23
21
  end
24
22
  end
25
23
 
26
- Term::ANSIColor.coloring = false if !STDOUT.tty? && !ENV.has_key?("AUTOTEST")
24
+ Term::ANSIColor.coloring = false if !STDOUT.tty? && !ENV.has_key?('AUTOTEST')
27
25
 
28
26
  module Cucumber
29
27
  module Formatter