aslakhellesoy-cucumber 0.1.99.4 → 0.1.99.5

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 (254) hide show
  1. data/History.txt +4 -1
  2. data/Manifest.txt +2 -10
  3. data/cucumber.yml +1 -0
  4. data/examples/cs/README.textile +1 -0
  5. data/examples/cs/Rakefile +12 -0
  6. data/examples/cs/compile.bat +1 -0
  7. data/examples/cs/features/addition.feature +16 -0
  8. data/examples/cs/features/step_definitons/calculator_steps.rb +19 -0
  9. data/examples/cs/src/demo/Calculator.cs +20 -0
  10. data/examples/dos_line_endings/Rakefile +6 -0
  11. data/examples/dos_line_endings/features/dos_line_endings.feature +9 -0
  12. data/examples/i18n/README.textile +18 -0
  13. data/examples/i18n/Rakefile +32 -0
  14. data/examples/i18n/ar/Rakefile +6 -0
  15. data/examples/i18n/ar/features/addition.feature +17 -0
  16. data/examples/i18n/ar/features/step_definitons/calculator_steps.rb +28 -0
  17. data/examples/i18n/ar/lib/calculator.rb +10 -0
  18. data/examples/i18n/da/Rakefile +6 -0
  19. data/examples/i18n/da/features/step_definitons/kalkulator_steps.rb +24 -0
  20. data/examples/i18n/da/features/summering.feature +17 -0
  21. data/examples/i18n/da/lib/kalkulator.rb +11 -0
  22. data/examples/i18n/de/Rakefile +6 -0
  23. data/examples/i18n/de/features/addition.feature +16 -0
  24. data/examples/i18n/de/features/division.feature +9 -0
  25. data/examples/i18n/de/features/step_definitons/calculator_steps.rb +24 -0
  26. data/examples/i18n/de/lib/calculator.rb +14 -0
  27. data/examples/i18n/en/Rakefile +6 -0
  28. data/examples/i18n/en/features/addition.feature +16 -0
  29. data/examples/i18n/en/features/division.feature +9 -0
  30. data/examples/i18n/en/features/step_definitons/calculator_steps.rb +24 -0
  31. data/examples/i18n/en/lib/calculator.rb +14 -0
  32. data/examples/i18n/es/Rakefile +6 -0
  33. data/examples/i18n/es/features/adicion.feature +17 -0
  34. data/examples/i18n/es/features/step_definitons/calculador_steps.rb +24 -0
  35. data/examples/i18n/es/lib/calculador.rb +11 -0
  36. data/examples/i18n/et/Rakefile +6 -0
  37. data/examples/i18n/et/features/liitmine.feature +17 -0
  38. data/examples/i18n/et/features/step_definitions/kalkulaator_steps.rb +24 -0
  39. data/examples/i18n/et/lib/kalkulaator.rb +10 -0
  40. data/examples/i18n/fi/Rakefile +6 -0
  41. data/examples/i18n/fi/features/jakolasku.feature +9 -0
  42. data/examples/i18n/fi/features/step_definitons/laskin_steps.rb +24 -0
  43. data/examples/i18n/fi/features/yhteenlasku.feature +16 -0
  44. data/examples/i18n/fi/lib/laskin.rb +14 -0
  45. data/examples/i18n/fr/Rakefile +6 -0
  46. data/examples/i18n/fr/features/addition.feature +15 -0
  47. data/examples/i18n/fr/features/step_definitions/calculatrice_steps.rb +27 -0
  48. data/examples/i18n/fr/lib/calculatrice.rb +10 -0
  49. data/examples/i18n/id/Rakefile +6 -0
  50. data/examples/i18n/id/features/addition.feature +16 -0
  51. data/examples/i18n/id/features/division.feature +9 -0
  52. data/examples/i18n/id/features/step_definitons/calculator_steps.rb +24 -0
  53. data/examples/i18n/id/lib/calculator.rb +14 -0
  54. data/examples/i18n/it/Rakefile +6 -0
  55. data/examples/i18n/it/features/somma.feature +10 -0
  56. data/examples/i18n/it/features/step_definitons/calcolatrice_steps.rb +24 -0
  57. data/examples/i18n/it/lib/calcolatrice.rb +11 -0
  58. data/examples/i18n/ja/README.txt +5 -0
  59. data/examples/i18n/ja/Rakefile +6 -0
  60. data/examples/i18n/ja/features/addition.feature +16 -0
  61. data/examples/i18n/ja/features/division.feature +9 -0
  62. data/examples/i18n/ja/features/step_definitons/calculator_steps.rb +24 -0
  63. data/examples/i18n/ja/lib/calculator.rb +14 -0
  64. data/examples/i18n/ko/Rakefile +6 -0
  65. data/examples/i18n/ko/features/addition.feature +16 -0
  66. data/examples/i18n/ko/features/division.feature +10 -0
  67. data/examples/i18n/ko/features/step_definitons/calculator_steps.rb +24 -0
  68. data/examples/i18n/ko/lib/calculator.rb +14 -0
  69. data/examples/i18n/lt/Rakefile +6 -0
  70. data/examples/i18n/lt/features/addition.feature +17 -0
  71. data/examples/i18n/lt/features/division.feature +9 -0
  72. data/examples/i18n/lt/features/step_definitons/calculator_steps.rb +24 -0
  73. data/examples/i18n/lt/lib/calculator.rb +14 -0
  74. data/examples/i18n/no/Rakefile +6 -0
  75. data/examples/i18n/no/features/step_definitons/kalkulator_steps.rb +24 -0
  76. data/examples/i18n/no/features/summering.feature +18 -0
  77. data/examples/i18n/no/lib/kalkulator.rb +11 -0
  78. data/examples/i18n/pt/Rakefile +6 -0
  79. data/examples/i18n/pt/features/adicao.feature +10 -0
  80. data/examples/i18n/pt/features/step_definitions/calculadora_steps.rb +24 -0
  81. data/examples/i18n/pt/lib/calculadora.rb +10 -0
  82. data/examples/i18n/ro/Rakefile +6 -0
  83. data/examples/i18n/ro/features/step_definitons/calculator_steps.rb +24 -0
  84. data/examples/i18n/ro/features/suma.feature +10 -0
  85. data/examples/i18n/ro/lib/calculator.rb +11 -0
  86. data/examples/i18n/se/Rakefile +6 -0
  87. data/examples/i18n/se/features/step_definitons/kalkulator_steps.rb +24 -0
  88. data/examples/i18n/se/features/summering.feature +17 -0
  89. data/examples/i18n/se/lib/kalkulator.rb +11 -0
  90. data/examples/i18n/zh-CN/Rakefile +6 -0
  91. data/examples/i18n/zh-CN/features/addition.feature +17 -0
  92. data/examples/i18n/zh-CN/features/step_definitons/calculator_steps.rb +26 -0
  93. data/examples/i18n/zh-CN/lib/calculator.rb +10 -0
  94. data/examples/java/README.textile +22 -0
  95. data/examples/java/Rakefile +12 -0
  96. data/examples/java/features/hello.feature +11 -0
  97. data/examples/java/features/step_definitons/hello_steps.rb +25 -0
  98. data/examples/java/features/step_definitons/tree_steps.rb +14 -0
  99. data/examples/java/features/tree.feature +9 -0
  100. data/examples/java/src/cucumber/demo/Hello.java +16 -0
  101. data/examples/jbehave/README.textile +17 -0
  102. data/examples/jbehave/features/support/env.rb +7 -0
  103. data/examples/jbehave/features/trading.feature +24 -0
  104. data/examples/jbehave/pom.xml +48 -0
  105. data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/converters/TraderConverter.java +32 -0
  106. data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/model/Stock.java +42 -0
  107. data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/model/Trader.java +29 -0
  108. data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/persistence/TraderPersister.java +22 -0
  109. data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/scenarios/TraderSteps.java +65 -0
  110. data/examples/selenium/Rakefile +6 -0
  111. data/examples/selenium/features/search.feature +9 -0
  112. data/examples/selenium/features/step_definitons/stories_steps.rb +40 -0
  113. data/examples/self_test/README.textile +6 -0
  114. data/examples/self_test/features/call_undefined_step_from_step_def.feature +7 -0
  115. data/examples/self_test/features/lots_of_undefined.feature +8 -0
  116. data/examples/self_test/features/outline_sample.feature +15 -0
  117. data/examples/self_test/features/sample.feature +16 -0
  118. data/examples/self_test/features/step_definitions/sample_steps.rb +25 -0
  119. data/examples/test_unit/Rakefile +6 -0
  120. data/examples/test_unit/features/step_definitions/test_unit_steps.rb +26 -0
  121. data/examples/test_unit/features/test_unit.feature +9 -0
  122. data/examples/tickets/Rakefile +11 -0
  123. data/examples/tickets/cucumber.yml +2 -0
  124. data/examples/tickets/features/lib/eatting_machine.rb +18 -0
  125. data/examples/tickets/features/lib/pantry.rb +20 -0
  126. data/examples/tickets/features/scenario_outline.feature +95 -0
  127. data/examples/tickets/features/step_definitons/scenario_outline_steps.rb +42 -0
  128. data/examples/tickets/features/step_definitons/tickets_steps.rb +60 -0
  129. data/examples/tickets/features/tickets.feature +28 -0
  130. data/examples/watir/README.textile +16 -0
  131. data/examples/watir/Rakefile +6 -0
  132. data/examples/watir/features/search.feature +9 -0
  133. data/examples/watir/features/step_definitons/search_steps.rb +24 -0
  134. data/examples/watir/features/support/env.rb +32 -0
  135. data/features/cucumber_cli.feature +331 -0
  136. data/features/cucumber_cli_outlines.feature +90 -0
  137. data/features/report_called_undefined_steps.feature +32 -0
  138. data/features/step_definitions/cucumber_steps.rb +31 -0
  139. data/features/step_definitions/extra_steps.rb +2 -0
  140. data/features/support/env.rb +7 -0
  141. data/gem_tasks/deployment.rake +11 -0
  142. data/gem_tasks/environment.rake +7 -0
  143. data/gem_tasks/features.rake +6 -0
  144. data/gem_tasks/fix_cr_lf.rake +10 -0
  145. data/gem_tasks/flog.rake +4 -0
  146. data/gem_tasks/gemspec.rake +10 -0
  147. data/gem_tasks/rspec.rake +35 -0
  148. data/gem_tasks/yard.rake +8 -0
  149. data/lib/autotest/cucumber.rb +6 -0
  150. data/lib/autotest/cucumber_mixin.rb +124 -0
  151. data/lib/autotest/cucumber_rails.rb +6 -0
  152. data/lib/autotest/cucumber_rails_rspec.rb +6 -0
  153. data/lib/autotest/cucumber_rspec.rb +6 -0
  154. data/lib/autotest/discover.rb +9 -0
  155. data/lib/cucumber.rb +72 -0
  156. data/lib/cucumber/ast.rb +27 -0
  157. data/lib/cucumber/ast/comment.rb +26 -0
  158. data/lib/cucumber/ast/examples.rb +22 -0
  159. data/lib/cucumber/ast/feature.rb +60 -0
  160. data/lib/cucumber/ast/features.rb +39 -0
  161. data/lib/cucumber/ast/filter.rb +22 -0
  162. data/lib/cucumber/ast/outline_table.rb +49 -0
  163. data/lib/cucumber/ast/py_string.rb +52 -0
  164. data/lib/cucumber/ast/scenario.rb +95 -0
  165. data/lib/cucumber/ast/scenario_outline.rb +83 -0
  166. data/lib/cucumber/ast/step.rb +139 -0
  167. data/lib/cucumber/ast/table.rb +214 -0
  168. data/lib/cucumber/ast/tags.rb +33 -0
  169. data/lib/cucumber/ast/visitor.rb +93 -0
  170. data/lib/cucumber/broadcaster.rb +15 -0
  171. data/lib/cucumber/cli.rb +414 -0
  172. data/lib/cucumber/core_ext/exception.rb +53 -0
  173. data/lib/cucumber/core_ext/instance_exec.rb +54 -0
  174. data/lib/cucumber/core_ext/proc.rb +33 -0
  175. data/lib/cucumber/core_ext/string.rb +48 -0
  176. data/lib/cucumber/formatter.rb +1 -0
  177. data/lib/cucumber/formatter/ansicolor.rb +106 -0
  178. data/lib/cucumber/formatter/console.rb +116 -0
  179. data/lib/cucumber/formatter/pretty.rb +158 -0
  180. data/lib/cucumber/formatter/profile.rb +77 -0
  181. data/lib/cucumber/formatter/progress.rb +68 -0
  182. data/lib/cucumber/formatter/rerun.rb +35 -0
  183. data/lib/cucumber/formatters/unicode.rb +2 -0
  184. data/lib/cucumber/jbehave.rb +104 -0
  185. data/lib/cucumber/languages.yml +314 -0
  186. data/lib/cucumber/parser.rb +24 -0
  187. data/lib/cucumber/parser/basic.rb +0 -0
  188. data/lib/cucumber/parser/feature.rb +1351 -0
  189. data/lib/cucumber/parser/feature.tt +160 -0
  190. data/lib/cucumber/parser/i18n.tt +27 -0
  191. data/lib/cucumber/parser/table.rb +396 -0
  192. data/lib/cucumber/parser/table.tt +53 -0
  193. data/lib/cucumber/parser/treetop_ext.rb +67 -0
  194. data/lib/cucumber/platform.rb +18 -0
  195. data/lib/cucumber/rails/rspec.rb +5 -0
  196. data/lib/cucumber/rails/world.rb +73 -0
  197. data/lib/cucumber/rake/task.rb +106 -0
  198. data/lib/cucumber/step_definition.rb +87 -0
  199. data/lib/cucumber/step_mother.rb +164 -0
  200. data/lib/cucumber/version.rb +10 -0
  201. data/pretty.txt +486 -0
  202. data/rails_generators/cucumber/USAGE +11 -0
  203. data/rails_generators/cucumber/cucumber_generator.rb +31 -0
  204. data/rails_generators/cucumber/templates/cucumber +8 -0
  205. data/rails_generators/cucumber/templates/cucumber.rake +7 -0
  206. data/rails_generators/cucumber/templates/env.rb +16 -0
  207. data/rails_generators/cucumber/templates/paths.rb +12 -0
  208. data/rails_generators/cucumber/templates/webrat_steps.rb +99 -0
  209. data/rails_generators/feature/USAGE +12 -0
  210. data/rails_generators/feature/feature_generator.rb +36 -0
  211. data/rails_generators/feature/templates/feature.erb +31 -0
  212. data/rails_generators/feature/templates/steps.erb +24 -0
  213. data/spec/cucumber/ast/feature_factory.rb +54 -0
  214. data/spec/cucumber/ast/feature_spec.rb +60 -0
  215. data/spec/cucumber/ast/py_string_spec.rb +40 -0
  216. data/spec/cucumber/ast/scenario_outline_spec.rb +64 -0
  217. data/spec/cucumber/ast/scenario_spec.rb +82 -0
  218. data/spec/cucumber/ast/step_spec.rb +45 -0
  219. data/spec/cucumber/ast/table_spec.rb +81 -0
  220. data/spec/cucumber/broadcaster_spec.rb +14 -0
  221. data/spec/cucumber/cli_spec.rb +416 -0
  222. data/spec/cucumber/core_ext/proc_spec.rb +37 -0
  223. data/spec/cucumber/core_ext/string_spec.rb +42 -0
  224. data/spec/cucumber/formatter/ansicolor_spec.rb +35 -0
  225. data/spec/cucumber/formatter/html/cucumber.css +37 -0
  226. data/spec/cucumber/formatter/html/cucumber.js +13 -0
  227. data/spec/cucumber/formatter/html/index.html +45 -0
  228. data/spec/cucumber/formatter/html/jquery-1.3.min.js +19 -0
  229. data/spec/cucumber/formatter/html/jquery.uitableedit.js +100 -0
  230. data/spec/cucumber/formatters/profile_formatter_spec.rb +198 -0
  231. data/spec/cucumber/parser/feature_parser_spec.rb +247 -0
  232. data/spec/cucumber/parser/table_parser_spec.rb +48 -0
  233. data/spec/cucumber/rails/stubs/mini_rails.rb +18 -0
  234. data/spec/cucumber/rails/stubs/test_help.rb +1 -0
  235. data/spec/cucumber/rails/world_spec.rb +11 -0
  236. data/spec/cucumber/sell_cucumbers.feature +19 -0
  237. data/spec/cucumber/step_definition_spec.rb +62 -0
  238. data/spec/cucumber/treetop_parser/empty_feature.feature +4 -0
  239. data/spec/cucumber/treetop_parser/empty_scenario.feature +9 -0
  240. data/spec/cucumber/treetop_parser/empty_scenario_outline.feature +3 -0
  241. data/spec/cucumber/treetop_parser/fit_scenario.feature +8 -0
  242. data/spec/cucumber/treetop_parser/given_scenario.feature +9 -0
  243. data/spec/cucumber/treetop_parser/invalid_scenario_outlines.feature +7 -0
  244. data/spec/cucumber/treetop_parser/multiline_steps.feature +17 -0
  245. data/spec/cucumber/treetop_parser/multiple_tables.feature +27 -0
  246. data/spec/cucumber/treetop_parser/scenario_outline.feature +16 -0
  247. data/spec/cucumber/treetop_parser/spaces.feature +12 -0
  248. data/spec/cucumber/treetop_parser/test_dos.feature +25 -0
  249. data/spec/cucumber/treetop_parser/with_comments.feature +10 -0
  250. data/spec/cucumber/treetop_parser/with_tags.feature +18 -0
  251. data/spec/cucumber/world/pending_spec.rb +47 -0
  252. data/spec/spec.opts +2 -0
  253. data/spec/spec_helper.rb +21 -0
  254. metadata +7 -1
@@ -0,0 +1,53 @@
1
+ module Cucumber
2
+ module Parser
3
+ grammar Table
4
+
5
+ rule table
6
+ table_row+ {
7
+ def build
8
+ Ast::Table.new(raw)
9
+ end
10
+
11
+ def raw
12
+ elements.map{|e| e.build}
13
+ end
14
+ }
15
+ end
16
+
17
+ rule table_row
18
+ space* '|' cells:(cell '|')+ space* (eol+ / eof) {
19
+ def build
20
+ row = cells.elements.map do |elt|
21
+ value = elt.cell.text_value.strip
22
+ value.empty? ? nil : value
23
+ end
24
+
25
+ class << row
26
+ attr_accessor :line
27
+ end
28
+ row.line = cells.line
29
+
30
+ row
31
+ end
32
+ }
33
+ end
34
+
35
+ rule cell
36
+ (!('|' / eol) .)*
37
+ end
38
+
39
+ rule space
40
+ [ \t]
41
+ end
42
+
43
+ rule eol
44
+ "\n" / ("\r" "\n"?)
45
+ end
46
+
47
+ rule eof
48
+ !.
49
+ end
50
+
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,67 @@
1
+ require 'treetop'
2
+ require 'treetop/runtime'
3
+ require 'treetop/ruby_extensions'
4
+
5
+ module Cucumber
6
+ module Parser
7
+ module TreetopExt
8
+ FILE_LINE_PATTERN = /^([\w\W]*?):([\d:]+)$/
9
+
10
+ # Parses a file and returns a Cucumber::Ast
11
+ def parse_file(file)
12
+ _, path, lines = *FILE_LINE_PATTERN.match(file)
13
+ if path
14
+ lines = lines.split(':').map { |line| line.to_i }
15
+ else
16
+ path = file
17
+ lines = []
18
+ end
19
+
20
+ feature = File.open(path, Cucumber.file_mode('r')) do |io|
21
+ parse_or_fail(io.read, path)
22
+ end
23
+ feature.lines = lines
24
+ feature
25
+ end
26
+ end
27
+
28
+ class SyntaxError < StandardError
29
+ def initialize(parser, file, line_offset)
30
+ tf = parser.terminal_failures
31
+ expected = tf.size == 1 ? tf[0].expected_string.inspect : "one of #{tf.map{|f| f.expected_string.inspect}.uniq*', '}"
32
+ after = parser.input[parser.index...parser.failure_index]
33
+ found = parser.input[parser.failure_index..parser.failure_index]
34
+
35
+ line = parser.failure_line + line_offset
36
+ message = "#{file}:#{line}:#{parser.failure_column}: " +
37
+ "Parse error, expected #{expected}. After #{after.inspect}. Found: #{found.inspect}"
38
+ super(message)
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ module Treetop
45
+ module Runtime
46
+ class SyntaxNode
47
+ def line
48
+ input.line_of(interval.first)
49
+ end
50
+ end
51
+
52
+ class CompiledParser
53
+ include Cucumber::Parser::TreetopExt
54
+
55
+ def parse_or_fail(s, file=nil, line=0)
56
+ parse_tree = parse(s)
57
+ if parse_tree.nil?
58
+ raise Cucumber::Parser::SyntaxError.new(self, file, line)
59
+ else
60
+ ast = parse_tree.build
61
+ ast.file = file
62
+ ast
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,18 @@
1
+ # Detect the platform we're running on so we can tweak behaviour
2
+ # in various places.
3
+ require 'rbconfig'
4
+ require 'yaml'
5
+
6
+ module Cucumber
7
+ LANGUAGE_FILE = File.expand_path(File.dirname(__FILE__) + '/languages.yml')
8
+ LANGUAGES = YAML.load_file(LANGUAGE_FILE)
9
+ BINARY = File.expand_path(File.dirname(__FILE__) + '/../../bin/cucumber')
10
+ JRUBY = defined?(JRUBY_VERSION)
11
+ IRONRUBY = Config::CONFIG['sitedir'] =~ /IronRuby/
12
+ WINDOWS = Config::CONFIG['host_os'] =~ /mswin|mingw/
13
+ WINDOWS_MRI = WINDOWS && !JRUBY && !IRONRUBY
14
+ RAILS = defined?(Rails)
15
+ RUBY_BINARY = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
16
+ RUBY_1_9 = RUBY_VERSION =~ /^1\.9/
17
+ EXCEPTION_STATUS = Hash.new(:failed)
18
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec/expectations'
2
+ require 'spec/rails/matchers'
3
+
4
+ ActionController::Integration::Session.send(:include, Spec::Matchers)
5
+ ActionController::Integration::Session.send(:include, Spec::Rails::Matchers)
@@ -0,0 +1,73 @@
1
+ # Based on code from Brian Takita, Yurii Rashkovskii and Ben Mabey
2
+ # Adapted by Aslak Hellesøy
3
+
4
+ if defined?(ActiveRecord::Base)
5
+ require 'test_help'
6
+ else
7
+ require 'action_controller/test_process'
8
+ require 'action_controller/integration'
9
+ end
10
+ require 'test/unit/testresult'
11
+
12
+ # These allow exceptions to come through as opposed to being caught and having non-helpful responses returned.
13
+ ActionController::Base.class_eval do
14
+ def perform_action_with_rescue
15
+ perform_action_without_rescue
16
+ end
17
+ end
18
+ ActionController::Dispatcher.class_eval do
19
+ def self.failsafe_response(output, status, exception = nil)
20
+ raise exception
21
+ end
22
+ end
23
+
24
+ # So that Test::Unit doesn't launch at the end - makes it think it has already been run.
25
+ Test::Unit.run = true if Test::Unit.respond_to?(:run=)
26
+
27
+ $cucumber_toplevel = self
28
+
29
+ module Cucumber #:nodoc:
30
+ module Rails
31
+ # All scenarios will execute in the context of a new instance of World.
32
+ class World < ActionController::IntegrationTest
33
+ if defined?(ActiveRecord::Base)
34
+ self.use_transactional_fixtures = false
35
+ else
36
+ def self.fixture_table_names; []; end # Workaround for projects that don't use ActiveRecord
37
+ end
38
+
39
+ def initialize #:nodoc:
40
+ @_result = Test::Unit::TestResult.new
41
+ end
42
+ end
43
+
44
+ def self.use_transactional_fixtures
45
+ World.use_transactional_fixtures = true
46
+ if defined?(ActiveRecord::Base)
47
+ $cucumber_toplevel.Before do
48
+ if ActiveRecord::Base.connection.respond_to?(:increment_open_transactions)
49
+ ActiveRecord::Base.connection.increment_open_transactions
50
+ else
51
+ ActiveRecord::Base.__send__(:increment_open_transactions)
52
+ end
53
+ ActiveRecord::Base.connection.begin_db_transaction
54
+ ActionMailer::Base.deliveries = [] if defined?(ActionMailer::Base)
55
+ end
56
+
57
+ $cucumber_toplevel.After do
58
+ ActiveRecord::Base.connection.rollback_db_transaction
59
+ if ActiveRecord::Base.connection.respond_to?(:decrement_open_transactions)
60
+ ActiveRecord::Base.connection.decrement_open_transactions
61
+ else
62
+ ActiveRecord::Base.__send__(:decrement_open_transactions)
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ end
69
+ end
70
+
71
+ World do
72
+ Cucumber::Rails::World.new
73
+ end
@@ -0,0 +1,106 @@
1
+ require 'cucumber/platform'
2
+
3
+ module Cucumber
4
+ module Rake
5
+ # Defines a task for running features.
6
+ class Task
7
+ LIB = File.expand_path(File.dirname(__FILE__) + '/../..')
8
+
9
+ attr_accessor :libs
10
+ attr_accessor :binary
11
+ attr_accessor :step_list
12
+ attr_accessor :step_pattern
13
+ attr_accessor :feature_list
14
+ attr_accessor :feature_pattern
15
+ attr_accessor :cucumber_opts
16
+ attr_accessor :rcov
17
+ attr_accessor :rcov_opts
18
+
19
+ # Define a task
20
+ def initialize(task_name = "features", desc = "Run Features with Cucumber")
21
+ @task_name, @desc = task_name, desc
22
+ @libs = []
23
+ @rcov_opts = %w{--rails --exclude osx\/objc,gems\/}
24
+
25
+ yield self if block_given?
26
+
27
+ @feature_pattern = "features/**/*.feature" if feature_pattern.nil? && feature_list.nil?
28
+ @step_pattern = "features/**/*.rb" if step_pattern.nil? && step_list.nil?
29
+
30
+ @binary = binary.nil? ? Cucumber::BINARY : File.expand_path(binary)
31
+ @libs.insert(0, LIB) if binary == Cucumber::BINARY
32
+
33
+ define_task
34
+ end
35
+
36
+ def define_task
37
+ desc @desc
38
+ task @task_name do
39
+ ruby(arguments_for_ruby_execution.join(" ")) # ruby(*args) is broken on Windows
40
+ end
41
+ end
42
+
43
+ def arguments_for_ruby_execution(task_args = nil)
44
+ lib_args = ['"%s"' % libs.join(File::PATH_SEPARATOR)]
45
+ cucumber_bin = ['"%s"' % binary]
46
+ cuc_opts = [(ENV['CUCUMBER_OPTS'] || cucumber_opts)]
47
+
48
+ step_files(task_args).each do |step_file|
49
+ cuc_opts << '--require'
50
+ cuc_opts << step_file
51
+ end
52
+
53
+ if rcov
54
+ args = (['-I'] + lib_args + ['-S', 'rcov'] + rcov_opts +
55
+ cucumber_bin + ['--'] + cuc_opts + feature_files(task_args)).flatten
56
+ else
57
+ args = (['-I'] + lib_args + cucumber_bin + cuc_opts + feature_files(task_args)).flatten
58
+ end
59
+
60
+ args
61
+ end
62
+
63
+ def feature_files(task_args = nil) # :nodoc:
64
+ if ENV['FEATURE']
65
+ FileList[ ENV['FEATURE'] ]
66
+ else
67
+ result = []
68
+ result += feature_list.to_a if feature_list
69
+ result += FileList[feature_pattern].to_a if feature_pattern
70
+ FileList[result]
71
+ end
72
+ end
73
+
74
+ def step_files(task_args = nil) # :nodoc:
75
+ if ENV['STEPS']
76
+ FileList[ ENV['STEPS'] ]
77
+ else
78
+ result = []
79
+ result += Array(step_list) if step_list
80
+ result += Array(FileList[step_pattern]) if step_pattern
81
+ FileList[result]
82
+ end
83
+ end
84
+ end
85
+
86
+ class FeatureTask < Task
87
+
88
+ def initialize(task_name = "feature", desc = "Run a specified feature with Cucumber. #{task_name}[feature_name]")
89
+ super(task_name, desc)
90
+ end
91
+
92
+ def define_task
93
+ desc @desc
94
+ task @task_name, :feature_name do |t, args|
95
+ ruby(arguments_for_ruby_execution(args).join(" ")) # ruby(*args) is broken on Windows
96
+ end
97
+ end
98
+
99
+ def feature_files(task_arguments) # :nodoc:
100
+ FileList[File.join("features", "**", "#{task_arguments[:feature_name]}.feature")]
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+ end
@@ -0,0 +1,87 @@
1
+ require 'cucumber/core_ext/string'
2
+ require 'cucumber/core_ext/proc'
3
+
4
+ module Cucumber
5
+ # A Step Definition holds a Regexp and a Proc, and is created
6
+ # by calling <tt>Given</tt>, <tt>When</tt> or <tt>Then</tt>
7
+ # in the <tt>step_definitions</tt> ruby files - for example:
8
+ #
9
+ # Given /I have (\d+) cucumbers in my belly/ do
10
+ # # some code here
11
+ # end
12
+ #
13
+ class StepDefinition
14
+ def self.snippet_text(step_keyword, step_name)
15
+ escaped = Regexp.escape(step_name).gsub('\ ', ' ').gsub('/', '\/')
16
+ "#{step_keyword} /^#{escaped}$/ do\n pending\nend"
17
+ end
18
+
19
+ class MissingProc < StandardError
20
+ def message
21
+ "Step definitions must always have a proc"
22
+ end
23
+ end
24
+
25
+ attr_reader :regexp
26
+
27
+ def initialize(pattern, &proc)
28
+ raise MissingProc if proc.nil?
29
+ if String === pattern
30
+ p = pattern.gsub(/\$\w+/, '(.*)')
31
+ pattern = Regexp.new("^#{p}$")
32
+ end
33
+ @regexp, @proc = pattern, proc
34
+ end
35
+
36
+ #:stopdoc:
37
+
38
+ def match(step_name)
39
+ case step_name
40
+ when String then @regexp.match(step_name)
41
+ when Regexp then @regexp == step_name
42
+ end
43
+ end
44
+
45
+ # Formats the matched arguments of the associated Step. This method
46
+ # is usually called from visitors, which render output.
47
+ #
48
+ # The +format+ either be a String or a Proc.
49
+ #
50
+ # If it is a String it should be a format string according to
51
+ # <tt>Kernel#sprinf</tt>, for example:
52
+ #
53
+ # '<span class="param">%s</span></tt>'
54
+ #
55
+ # If it is a Proc, it should take one argument and return the formatted
56
+ # argument, for example:
57
+ #
58
+ # lambda { |param| "[#{param}]" }
59
+ #
60
+ def format_args(step_name, format)
61
+ step_name.gzub(@regexp, format)
62
+ end
63
+
64
+ def matched_args(step_name)
65
+ step_name.match(@regexp).captures
66
+ end
67
+
68
+ def execute(step_name, world, *args)
69
+ args = args.map{|arg| Ast::PyString === arg ? arg.to_s : arg}
70
+ begin
71
+ world.cucumber_instance_exec(true, @regexp.inspect, *args, &@proc)
72
+ rescue Cucumber::ArityMismatchError => e
73
+ e.backtrace.unshift(self.to_backtrace_line)
74
+ raise e
75
+ end
76
+ end
77
+
78
+ def to_backtrace_line
79
+ "#{file_colon_line}:in `#{@regexp.inspect}'"
80
+ end
81
+
82
+ def file_colon_line
83
+ @proc.file_colon_line
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,164 @@
1
+ require 'cucumber/step_definition'
2
+ require 'cucumber/core_ext/instance_exec'
3
+
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
14
+
15
+ def initialize(step_name)
16
+ super %{Undefined step: "#{step_name}"}
17
+ @step_name = step_name
18
+ end
19
+ Cucumber::EXCEPTION_STATUS[self] = :undefined
20
+ end
21
+
22
+ class Pending < StandardError
23
+ Cucumber::EXCEPTION_STATUS[self] = :pending
24
+ end
25
+
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
34
+ end
35
+
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
44
+ end
45
+
46
+ # Registers a new StepDefinition. This method is aliased
47
+ # to <tt>Given</tt>, <tt>When</tt> and <tt>Then</tt>.
48
+ #
49
+ # See Cucumber#alias_steps for details on how to
50
+ # create your own aliases.
51
+ #
52
+ # The +&proc+ gets executed in the context of a <tt>world</tt>
53
+ # object, which is defined by #World. A new <tt>world</tt>
54
+ # object is created for each scenario and is shared across
55
+ # step definitions within that scenario.
56
+ def register_step_definition(regexp, &proc)
57
+ step_definition = StepDefinition.new(regexp, &proc)
58
+ step_definitions.each do |already|
59
+ raise Redundant.new(already, step_definition) if already.match(regexp)
60
+ end
61
+ step_definitions << step_definition
62
+ step_definition
63
+ end
64
+
65
+ def world(scenario, &proc)
66
+ world = new_world
67
+ begin
68
+ (@before_procs ||= []).each do |proc|
69
+ world.cucumber_instance_exec(false, 'Before', scenario, &proc)
70
+ end
71
+ yield world
72
+ ensure
73
+ (@after_procs ||= []).each do |proc|
74
+ world.cucumber_instance_exec(false, 'After', scenario, &proc)
75
+ end
76
+ end
77
+ end
78
+
79
+ # Registers a Before proc. You can call this method as many times as you
80
+ # want (typically from ruby scripts under <tt>support</tt>).
81
+ def Before(&proc)
82
+ (@before_procs ||= []) << proc
83
+ end
84
+
85
+ def After(&proc)
86
+ (@after_procs ||= []) << proc
87
+ end
88
+
89
+ # Registers a World proc. You can call this method as many times as you
90
+ # want (typically from ruby scripts under <tt>support</tt>).
91
+ def World(&proc)
92
+ (@world_procs ||= []) << proc
93
+ end
94
+
95
+ # Creates a new world instance
96
+ def new_world #:nodoc:
97
+ world = Object.new
98
+ (@world_procs ||= []).each do |proc|
99
+ world = proc.call(world)
100
+ end
101
+
102
+ world.extend(WorldMethods)
103
+ world.__cucumber_step_mother = self
104
+
105
+ world.extend(::Spec::Matchers) if defined?(::Spec::Matchers)
106
+ world
107
+ end
108
+
109
+ # Looks up the StepDefinition that matches +step_name+
110
+ def step_definition(step_name) #:nodoc:
111
+ found = step_definitions.select do |step_definition|
112
+ step_definition.match(step_name)
113
+ end
114
+ raise Undefined.new(step_name) if found.empty?
115
+ raise Ambiguous.new(step_name, found) if found.size > 1
116
+ found[0]
117
+ end
118
+
119
+ def step_definitions
120
+ @step_definitions ||= []
121
+ end
122
+
123
+ def snippet_text(step_keyword, step_name)
124
+ @snippet_generator.snippet_text(step_keyword, step_name)
125
+ end
126
+
127
+ module WorldMethods #:nodoc:
128
+ attr_writer :__cucumber_step_mother, :__cucumber_current_step
129
+
130
+ # Call a step from within a step definition
131
+ def __cucumber_invoke(name, *multiline_arguments)
132
+ begin
133
+ # TODO: Very similar to code in Step. Refactor. Get back StepInvocation?
134
+ # Make more similar to JBehave?
135
+ step_definition = @__cucumber_step_mother.step_definition(name)
136
+ matched_args = step_definition.matched_args(name)
137
+ args = (matched_args + multiline_arguments)
138
+ step_definition.execute(name, self, *args)
139
+ rescue Exception => e
140
+ @__cucumber_current_step.exception = e
141
+ raise e
142
+ end
143
+ end
144
+
145
+ def table(text, file=nil, line=0)
146
+ @table_parser ||= Parser::TableParser.new
147
+ @table_parser.parse_or_fail(text.strip, file, line)
148
+ end
149
+
150
+ def pending(message = "TODO")
151
+ if block_given?
152
+ begin
153
+ yield
154
+ rescue Exception => e
155
+ raise Pending.new(message)
156
+ end
157
+ raise Pending.new("Expected pending '#{message}' to fail. No Error was raised. No longer pending?")
158
+ else
159
+ raise Pending.new(message)
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end