kosmas58-cucumber 0.1.16.6 → 0.1.99.21

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 (248) hide show
  1. data/History.txt +126 -2
  2. data/License.txt +1 -1
  3. data/Manifest.txt +0 -270
  4. data/Rakefile +1 -1
  5. data/bin/cucumber +2 -2
  6. data/config/hoe.rb +7 -2
  7. data/examples/cs/features/step_definitons/calculator_steps.rb +1 -1
  8. data/examples/i18n/README.textile +1 -1
  9. data/examples/i18n/Rakefile +3 -3
  10. data/examples/i18n/ar/features/step_definitons/calculator_steps.rb +1 -6
  11. data/examples/i18n/da/features/step_definitons/kalkulator_steps.rb +1 -1
  12. data/examples/i18n/de/features/addition.feature +6 -6
  13. data/examples/i18n/de/features/step_definitons/calculator_steps.rb +2 -2
  14. data/examples/i18n/en/features/addition.feature +6 -6
  15. data/examples/i18n/en/features/step_definitons/calculator_steps.rb +2 -2
  16. data/examples/i18n/es/features/adicion.feature +11 -12
  17. data/examples/i18n/es/features/step_definitons/calculador_steps.rb +7 -10
  18. data/examples/i18n/es/lib/calculador.rb +4 -1
  19. data/examples/i18n/et/features/liitmine.feature +7 -6
  20. data/examples/i18n/et/features/step_definitions/kalkulaator_steps.rb +1 -1
  21. data/examples/i18n/fi/features/step_definitons/laskin_steps.rb +1 -1
  22. data/examples/i18n/fi/features/yhteenlasku.feature +2 -2
  23. data/examples/i18n/fr/features/addition.feature +2 -2
  24. data/examples/i18n/fr/features/step_definitions/calculatrice_steps.rb +1 -1
  25. data/examples/i18n/id/features/addition.feature +6 -6
  26. data/examples/i18n/id/features/step_definitons/calculator_steps.rb +2 -2
  27. data/examples/i18n/it/features/step_definitons/calcolatrice_steps.rb +1 -1
  28. data/examples/i18n/ja/features/step_definitons/calculator_steps.rb +2 -3
  29. data/examples/i18n/ko/features/step_definitons/calculator_steps.rb +1 -1
  30. data/examples/i18n/lt/features/addition.feature +7 -6
  31. data/examples/i18n/lt/features/step_definitons/calculator_steps.rb +2 -2
  32. data/examples/i18n/no/features/step_definitons/kalkulator_steps.rb +7 -7
  33. data/examples/i18n/no/features/summering.feature +1 -0
  34. data/examples/i18n/pt/features/step_definitions/calculadora_steps.rb +1 -1
  35. data/examples/i18n/ro/features/step_definitons/calculator_steps.rb +1 -1
  36. data/examples/i18n/se/features/step_definitons/kalkulator_steps.rb +1 -1
  37. data/examples/i18n/zh-CN/features/step_definitons/calculator_steps.rb +2 -2
  38. data/examples/java/src/cucumber/demo/Hello.java +16 -0
  39. data/examples/jbehave/README.textile +17 -0
  40. data/examples/jbehave/features/support/env.rb +7 -0
  41. data/examples/jbehave/features/trading.feature +24 -0
  42. data/examples/jbehave/pom.xml +48 -0
  43. data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/converters/TraderConverter.java +32 -0
  44. data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/model/Stock.java +42 -0
  45. data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/model/Trader.java +29 -0
  46. data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/persistence/TraderPersister.java +22 -0
  47. data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/scenarios/TraderSteps.java +65 -0
  48. data/examples/self_test/README.textile +4 -1
  49. data/examples/{calculator_ruby_features → self_test}/Rakefile +3 -3
  50. data/examples/self_test/features/background/failing_background.feature +10 -0
  51. data/examples/self_test/features/background/failing_background_after_success.feature +11 -0
  52. data/examples/self_test/features/background/multiline_args_background.feature +32 -0
  53. data/examples/self_test/features/background/passing_background.feature +10 -0
  54. data/examples/self_test/features/background/pending_background.feature +10 -0
  55. data/examples/self_test/features/background/scenario_outline_failing_background.feature +16 -0
  56. data/examples/self_test/features/background/scenario_outline_passing_background.feature +16 -0
  57. data/examples/self_test/features/call_undefined_step_from_step_def.feature +7 -0
  58. data/examples/self_test/features/lots_of_undefined.feature +8 -0
  59. data/examples/self_test/features/outline_sample.feature +11 -5
  60. data/examples/self_test/features/sample.feature +8 -3
  61. data/examples/self_test/features/step_definitions/sample_steps.rb +53 -4
  62. data/examples/self_test/features/support/env.rb +1 -0
  63. data/examples/self_test/features/support/tag_count_formatter.rb +25 -0
  64. data/examples/tickets/features/172.feature +28 -0
  65. data/examples/tickets/features/177/1.feature +29 -0
  66. data/examples/tickets/features/177/2.feature +21 -0
  67. data/examples/tickets/features/177/3.feature +18 -0
  68. data/examples/tickets/features/180.feature +7 -0
  69. data/examples/tickets/features/scenario_outline.feature +6 -1
  70. data/examples/tickets/features/step_definitons/tickets_steps.rb +27 -3
  71. data/examples/tickets/features/tickets.feature +4 -0
  72. data/features/background.feature +223 -0
  73. data/features/cucumber_cli.feature +218 -98
  74. data/features/cucumber_cli_outlines.feature +54 -37
  75. data/features/custom_formatter.feature +11 -0
  76. data/features/report_called_undefined_steps.feature +32 -0
  77. data/features/step_definitions/cucumber_steps.rb +7 -3
  78. data/features/step_definitions/extra_steps.rb +1 -1
  79. data/features/support/env.rb +2 -1
  80. data/gem_tasks/flog.rake +1 -1
  81. data/gem_tasks/gemspec.rake +2 -2
  82. data/gem_tasks/jar.rake +67 -0
  83. data/lib/autotest/cucumber_mixin.rb +17 -23
  84. data/lib/cucumber.rb +63 -11
  85. data/lib/cucumber/ast.rb +29 -0
  86. data/lib/cucumber/ast/background.rb +88 -0
  87. data/lib/cucumber/ast/comment.rb +26 -0
  88. data/lib/cucumber/ast/examples.rb +26 -0
  89. data/lib/cucumber/ast/feature.rb +66 -0
  90. data/lib/cucumber/ast/features.rb +39 -0
  91. data/lib/cucumber/ast/filter.rb +22 -0
  92. data/lib/cucumber/ast/outline_table.rb +49 -0
  93. data/lib/cucumber/ast/py_string.rb +52 -0
  94. data/lib/cucumber/ast/scenario.rb +103 -0
  95. data/lib/cucumber/ast/scenario_outline.rb +92 -0
  96. data/lib/cucumber/ast/step.rb +161 -0
  97. data/lib/cucumber/ast/steps.rb +13 -0
  98. data/lib/cucumber/ast/table.rb +218 -0
  99. data/lib/cucumber/ast/tags.rb +40 -0
  100. data/lib/cucumber/ast/visitor.rb +109 -0
  101. data/lib/cucumber/broadcaster.rb +1 -6
  102. data/lib/cucumber/cli/configuration.rb +339 -0
  103. data/lib/cucumber/cli/language_help_formatter.rb +59 -0
  104. data/lib/cucumber/cli/main.rb +100 -0
  105. data/lib/cucumber/core_ext/exception.rb +41 -8
  106. data/lib/cucumber/core_ext/instance_exec.rb +54 -0
  107. data/lib/cucumber/core_ext/proc.rb +29 -65
  108. data/lib/cucumber/core_ext/string.rb +19 -0
  109. data/lib/cucumber/formatter.rb +1 -0
  110. data/lib/cucumber/{formatters → formatter}/ansicolor.rb +14 -16
  111. data/lib/cucumber/formatter/color_io.rb +17 -0
  112. data/lib/cucumber/formatter/console.rb +119 -0
  113. data/lib/cucumber/formatter/cucumber.css +55 -0
  114. data/lib/cucumber/formatter/cucumber.sass +49 -0
  115. data/lib/cucumber/formatter/html.rb +121 -0
  116. data/lib/cucumber/formatter/pretty.rb +167 -0
  117. data/lib/cucumber/formatter/profile.rb +77 -0
  118. data/lib/cucumber/formatter/progress.rb +68 -0
  119. data/lib/cucumber/formatter/rerun.rb +35 -0
  120. data/lib/cucumber/formatter/unicode.rb +35 -0
  121. data/lib/cucumber/formatters/unicode.rb +2 -35
  122. data/lib/cucumber/jbehave.rb +102 -0
  123. data/lib/cucumber/languages.yml +128 -75
  124. data/lib/cucumber/parser.rb +43 -0
  125. data/lib/cucumber/parser/basic.rb +0 -0
  126. data/lib/cucumber/parser/feature.rb +1490 -0
  127. data/lib/cucumber/parser/feature.tt +188 -0
  128. data/lib/cucumber/parser/i18n.tt +31 -0
  129. data/lib/cucumber/parser/table.rb +402 -0
  130. data/lib/cucumber/parser/table.tt +59 -0
  131. data/lib/cucumber/parser/treetop_ext.rb +75 -0
  132. data/lib/cucumber/platform.rb +3 -17
  133. data/lib/cucumber/rails/rspec.rb +5 -2
  134. data/lib/cucumber/step_definition.rb +87 -0
  135. data/lib/cucumber/step_mother.rb +151 -66
  136. data/lib/cucumber/version.rb +2 -2
  137. data/rails_generators/cucumber/USAGE +3 -2
  138. data/rails_generators/cucumber/cucumber_generator.rb +33 -23
  139. data/rails_generators/cucumber/templates/cucumber +2 -1
  140. data/rails_generators/cucumber/templates/cucumber.rake +6 -1
  141. data/rails_generators/cucumber/templates/env.rb +1 -1
  142. data/rails_generators/feature/USAGE +3 -0
  143. data/rails_generators/feature/feature_generator.rb +30 -6
  144. data/spec/cucumber/ast/background_spec.rb +58 -0
  145. data/spec/cucumber/ast/feature_factory.rb +54 -0
  146. data/spec/cucumber/ast/feature_spec.rb +60 -0
  147. data/spec/cucumber/ast/py_string_spec.rb +40 -0
  148. data/spec/cucumber/ast/scenario_outline_spec.rb +64 -0
  149. data/spec/cucumber/ast/scenario_spec.rb +82 -0
  150. data/spec/cucumber/ast/step_spec.rb +45 -0
  151. data/spec/cucumber/ast/table_spec.rb +81 -0
  152. data/spec/cucumber/ast/tags_spec.rb +23 -0
  153. data/spec/cucumber/broadcaster_spec.rb +4 -17
  154. data/spec/cucumber/cli/configuration_spec.rb +239 -0
  155. data/spec/cucumber/cli/main_spec.rb +164 -0
  156. data/spec/cucumber/core_ext/proc_spec.rb +27 -35
  157. data/spec/cucumber/core_ext/string_spec.rb +8 -0
  158. data/spec/cucumber/{formatters → formatter}/ansicolor_spec.rb +2 -2
  159. data/spec/cucumber/formatter/html/cucumber.css +37 -0
  160. data/spec/cucumber/formatter/html/cucumber.js +13 -0
  161. data/spec/cucumber/formatter/html/index.html +45 -0
  162. data/spec/cucumber/formatter/html/jquery-1.3.min.js +19 -0
  163. data/spec/cucumber/formatter/html/jquery.uitableedit.js +100 -0
  164. data/spec/cucumber/formatters/profile_formatter_spec.rb +17 -16
  165. data/spec/cucumber/parser/feature_parser_spec.rb +281 -0
  166. data/spec/cucumber/parser/table_parser_spec.rb +48 -0
  167. data/spec/cucumber/step_definition_spec.rb +62 -0
  168. data/spec/cucumber/step_mother_spec.rb +50 -51
  169. data/spec/cucumber/treetop_parser/empty_feature.feature +1 -1
  170. data/spec/cucumber/treetop_parser/scenario_outline.feature +1 -1
  171. data/spec/cucumber/treetop_parser/spaces.feature +3 -1
  172. data/spec/cucumber/treetop_parser/with_comments.feature +1 -1
  173. data/spec/cucumber/treetop_parser/with_tags.feature +18 -0
  174. data/spec/cucumber/world/pending_spec.rb +13 -12
  175. data/spec/spec_helper.rb +1 -1
  176. metadata +107 -79
  177. data/examples/calculator_ruby_features/features/addition.rb +0 -39
  178. data/examples/calculator_ruby_features/features/step_definitons/calculator_steps.rb +0 -43
  179. data/gem_tasks/treetop.rake +0 -41
  180. data/lib/cucumber/cli.rb +0 -355
  181. data/lib/cucumber/executor.rb +0 -205
  182. data/lib/cucumber/formatters.rb +0 -1
  183. data/lib/cucumber/formatters/autotest_formatter.rb +0 -23
  184. data/lib/cucumber/formatters/cucumber.css +0 -132
  185. data/lib/cucumber/formatters/cucumber.js +0 -11
  186. data/lib/cucumber/formatters/html_formatter.rb +0 -152
  187. data/lib/cucumber/formatters/jquery.js +0 -32
  188. data/lib/cucumber/formatters/pretty_formatter.rb +0 -285
  189. data/lib/cucumber/formatters/profile_formatter.rb +0 -92
  190. data/lib/cucumber/formatters/progress_formatter.rb +0 -61
  191. data/lib/cucumber/model.rb +0 -1
  192. data/lib/cucumber/model/table.rb +0 -32
  193. data/lib/cucumber/step_methods.rb +0 -49
  194. data/lib/cucumber/tree.rb +0 -16
  195. data/lib/cucumber/tree/feature.rb +0 -105
  196. data/lib/cucumber/tree/features.rb +0 -21
  197. data/lib/cucumber/tree/given_scenario.rb +0 -13
  198. data/lib/cucumber/tree/scenario.rb +0 -240
  199. data/lib/cucumber/tree/step.rb +0 -173
  200. data/lib/cucumber/tree/table.rb +0 -26
  201. data/lib/cucumber/tree/top_down_visitor.rb +0 -23
  202. data/lib/cucumber/treetop_parser/feature.treetop.erb +0 -254
  203. data/lib/cucumber/treetop_parser/feature_ar.rb +0 -1951
  204. data/lib/cucumber/treetop_parser/feature_cy.rb +0 -1951
  205. data/lib/cucumber/treetop_parser/feature_da.rb +0 -1951
  206. data/lib/cucumber/treetop_parser/feature_de.rb +0 -1951
  207. data/lib/cucumber/treetop_parser/feature_en-lol.rb +0 -1951
  208. data/lib/cucumber/treetop_parser/feature_en-tx.rb +0 -1951
  209. data/lib/cucumber/treetop_parser/feature_en.rb +0 -1951
  210. data/lib/cucumber/treetop_parser/feature_es.rb +0 -1951
  211. data/lib/cucumber/treetop_parser/feature_et.rb +0 -1951
  212. data/lib/cucumber/treetop_parser/feature_fi.rb +0 -1951
  213. data/lib/cucumber/treetop_parser/feature_fr.rb +0 -1951
  214. data/lib/cucumber/treetop_parser/feature_id.rb +0 -1951
  215. data/lib/cucumber/treetop_parser/feature_it.rb +0 -1951
  216. data/lib/cucumber/treetop_parser/feature_ja.rb +0 -1951
  217. data/lib/cucumber/treetop_parser/feature_ko.rb +0 -1951
  218. data/lib/cucumber/treetop_parser/feature_lt.rb +0 -1951
  219. data/lib/cucumber/treetop_parser/feature_nl.rb +0 -1951
  220. data/lib/cucumber/treetop_parser/feature_no.rb +0 -1951
  221. data/lib/cucumber/treetop_parser/feature_parser.rb +0 -36
  222. data/lib/cucumber/treetop_parser/feature_pl.rb +0 -1951
  223. data/lib/cucumber/treetop_parser/feature_pt.rb +0 -1951
  224. data/lib/cucumber/treetop_parser/feature_ro.rb +0 -1951
  225. data/lib/cucumber/treetop_parser/feature_ro2.rb +0 -1951
  226. data/lib/cucumber/treetop_parser/feature_ru.rb +0 -1951
  227. data/lib/cucumber/treetop_parser/feature_se.rb +0 -1951
  228. data/lib/cucumber/treetop_parser/feature_zh-CN.rb +0 -1951
  229. data/lib/cucumber/world.rb +0 -1
  230. data/lib/cucumber/world/pending.rb +0 -22
  231. data/setup.rb +0 -1585
  232. data/spec/cucumber/cli_spec.rb +0 -521
  233. data/spec/cucumber/executor_spec.rb +0 -382
  234. data/spec/cucumber/formatters/autotest_formatter_spec.rb +0 -26
  235. data/spec/cucumber/formatters/features.html +0 -269
  236. data/spec/cucumber/formatters/html_formatter_spec.rb +0 -110
  237. data/spec/cucumber/formatters/pretty_formatter_spec.rb +0 -410
  238. data/spec/cucumber/formatters/progress_formatter_spec.rb +0 -81
  239. data/spec/cucumber/model/table_spec.rb +0 -32
  240. data/spec/cucumber/tree/feature_spec.rb +0 -122
  241. data/spec/cucumber/tree/row_scenario_outline_spec.rb +0 -73
  242. data/spec/cucumber/tree/row_scenario_spec.rb +0 -55
  243. data/spec/cucumber/tree/row_step_outline_spec.rb +0 -38
  244. data/spec/cucumber/tree/scenario_outline_spec.rb +0 -50
  245. data/spec/cucumber/tree/scenario_spec.rb +0 -134
  246. data/spec/cucumber/tree/step_outline_spec.rb +0 -17
  247. data/spec/cucumber/tree/step_spec.rb +0 -59
  248. data/spec/cucumber/treetop_parser/feature_parser_spec.rb +0 -120
@@ -0,0 +1,161 @@
1
+ require 'cucumber/step_definition'
2
+ require 'cucumber/core_ext/string'
3
+
4
+ module Cucumber
5
+ module Ast
6
+ class Step
7
+ attr_reader :keyword, :name
8
+ attr_writer :world, :previous, :options
9
+ attr_accessor :status, :scenario, :exception
10
+
11
+ def initialize(line, keyword, name, *multiline_args)
12
+ @line, @keyword, @name, @multiline_args = line, keyword, name, multiline_args
13
+ end
14
+
15
+ def execute_with_arguments(argument_hash, world, previous, visitor, row_line)
16
+ delimited_arguments = delimit_argument_names(argument_hash)
17
+ name = replace_name_arguments(delimited_arguments)
18
+ multiline_args = replace_multiline_args_arguments(delimited_arguments)
19
+
20
+ execute_twin(world, previous, visitor, row_line, name, *multiline_args)
21
+ end
22
+
23
+ def execute_as_new(world, previous, visitor, row_line)
24
+ execute_twin(world, previous, visitor, row_line, @name, *@multiline_args)
25
+ end
26
+
27
+ def accept(visitor)
28
+ execute(visitor)
29
+
30
+ if @status == :outline
31
+ step_definition = find_first_name_and_step_definition_from_examples(visitor)
32
+ else
33
+ step_definition = @step_definition
34
+ end
35
+ visitor.visit_step_name(@keyword, @name, @status, step_definition, source_indent)
36
+ @multiline_args.each do |multiline_arg|
37
+ visitor.visit_multiline_arg(multiline_arg, @status)
38
+ end
39
+ @exception
40
+ end
41
+
42
+ def find_first_name_and_step_definition_from_examples(visitor)
43
+ # @scenario is always a ScenarioOutline in this case
44
+ @scenario.each_example_row do |cells|
45
+ argument_hash = cells.to_hash
46
+ delimited_arguments = delimit_argument_names(argument_hash)
47
+ name = replace_name_arguments(delimited_arguments)
48
+ step_definition = visitor.step_definition(name) rescue nil
49
+ return step_definition if step_definition
50
+ end
51
+ nil
52
+ end
53
+
54
+ def to_sexp
55
+ [:step, @line, @keyword, @name, *@multiline_args.map{|arg| arg.to_sexp}]
56
+ end
57
+
58
+ def at_lines?(lines)
59
+ lines.empty? || lines.index(@line) || @multiline_args.detect{|a| a.at_lines?(lines)}
60
+ end
61
+
62
+ def source_indent
63
+ @scenario.source_indent(text_length)
64
+ end
65
+
66
+ def text_length
67
+ @keyword.jlength + @name.jlength + 2 # Add 2 because steps get indented 2 more than scenarios
68
+ end
69
+
70
+ def backtrace_line
71
+ @backtrace_line ||= @scenario.backtrace_line("#{@keyword} #{@name}", @line) unless @scenario.nil?
72
+ end
73
+
74
+ def file_line
75
+ @file_line ||= @scenario.file_line(@line) unless @scenario.nil?
76
+ end
77
+
78
+ def actual_keyword
79
+ if [Cucumber.keyword_hash['and'], Cucumber.keyword_hash['but']].index(@keyword) && previous_step
80
+ previous_step.actual_keyword
81
+ else
82
+ @keyword
83
+ end
84
+ end
85
+
86
+ protected
87
+
88
+ def previous_step
89
+ @scenario.previous_step(self)
90
+ end
91
+
92
+ private
93
+
94
+ def execute(visitor)
95
+ matched_args = []
96
+ if @status.nil?
97
+ begin
98
+ @step_definition = visitor.step_definition(@name)
99
+ matched_args = @step_definition.matched_args(@name)
100
+ if @previous == :passed && !visitor.options[:dry_run]
101
+ @world.__cucumber_current_step = self
102
+ @step_definition.execute(@name, @world, *(matched_args + @multiline_args))
103
+ @status = :passed
104
+ else
105
+ @status = :skipped
106
+ end
107
+ rescue Undefined => exception
108
+ if visitor.options[:strict]
109
+ exception.set_backtrace([])
110
+ failed(exception)
111
+ else
112
+ @status = :undefined
113
+ end
114
+ rescue Pending => exception
115
+ visitor.options[:strict] ? failed(exception) : @status = :pending
116
+ rescue Exception => exception
117
+ failed(exception)
118
+ end
119
+ @scenario.step_executed(self) if @scenario
120
+ end
121
+ [self, @status, matched_args]
122
+ end
123
+
124
+ def execute_twin(world, previous, visitor, line, name, *multiline_args)
125
+ # We'll create a new step and execute that
126
+ step = Step.new(line, @keyword, name, *multiline_args)
127
+ step.scenario = @scenario
128
+ step.world = world
129
+ step.previous = previous
130
+ step.__send__(:execute, visitor)
131
+ end
132
+
133
+ ARGUMENT_START = '<'
134
+ ARGUMENT_END = '>'
135
+
136
+ def delimit_argument_names(argument_hash)
137
+ argument_hash.inject({}) { |h,(k,v)| h["#{ARGUMENT_START}#{k}#{ARGUMENT_END}"] = v; h }
138
+ end
139
+
140
+ def replace_name_arguments(argument_hash)
141
+ name_with_arguments_replaced = @name
142
+ argument_hash.each do |name, value|
143
+ name_with_arguments_replaced = name_with_arguments_replaced.gsub(name, value) if value
144
+ end
145
+ name_with_arguments_replaced
146
+ end
147
+
148
+ def replace_multiline_args_arguments(arguments)
149
+ @multiline_args.map do |arg|
150
+ arg.arguments_replaced(arguments)
151
+ end
152
+ end
153
+
154
+ def failed(exception)
155
+ @status = :failed
156
+ @exception = exception
157
+ @exception.backtrace << backtrace_line unless backtrace_line.nil?
158
+ end
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,13 @@
1
+ module Cucumber
2
+ module Ast
3
+ class Steps
4
+ def initialize(scenario)
5
+ @scenario = scenario
6
+ end
7
+
8
+ def accept(visitor)
9
+ @scenario.accept_steps(visitor)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,218 @@
1
+ module Cucumber
2
+ module Ast
3
+ # Holds the data of a table parsed from a feature file:
4
+ #
5
+ # | a | b |
6
+ # | c | d |
7
+ #
8
+ # This gets parsed into a Table holding the values <tt>[['a', 'b'], ['c', 'd']]</tt>
9
+ #
10
+ class Table
11
+ attr_accessor :file
12
+
13
+ def initialize(raw)
14
+ # Verify that it's square
15
+ raw.transpose
16
+ @raw = raw
17
+ @cells_class = Cells
18
+ @cell_class = Cell
19
+ end
20
+
21
+ def at_lines?(lines)
22
+ cells_rows.detect { |row| row.at_lines?(lines) }
23
+ end
24
+
25
+ def accept(visitor, status)
26
+ cells_rows.each do |row|
27
+ visitor.visit_table_row(row, status)
28
+ end
29
+ nil
30
+ end
31
+
32
+ # Converts this table into an Array of Hash where the keys of each
33
+ # Hash are the headers in the table. For example, a Table built from
34
+ # the following plain text:
35
+ #
36
+ # | a | b | sum |
37
+ # | 2 | 3 | 5 |
38
+ # | 7 | 9 | 16 |
39
+ #
40
+ # Gets converted into the following:
41
+ #
42
+ # [{'a' => '2', 'b' => '3', 'sum' => '5'}, {'a' => '7', 'b' => '9', 'sum' => '16'}]
43
+ #
44
+ def hashes
45
+ @hashes ||= cells_rows[1..-1].map do |row|
46
+ row.to_hash
47
+ end
48
+ end
49
+
50
+ # Gets the raw data of this table. For example, a Table built from
51
+ # the following plain text:
52
+ #
53
+ # | a | b |
54
+ # | c | d |
55
+ #
56
+ # Get converted into the following:
57
+ #
58
+ # [['a', 'b], ['c', 'd']]
59
+ #
60
+ def raw
61
+ @raw
62
+ end
63
+
64
+ # Same as #raw, but skips the first (header) row
65
+ def rows
66
+ @raw[1..-1]
67
+ end
68
+
69
+ def each_cells_row(&proc)
70
+ cells_rows.each(&proc)
71
+ end
72
+
73
+ # For testing only
74
+ def to_sexp #:nodoc:
75
+ [:table, *cells_rows.map{|row| row.to_sexp}]
76
+ end
77
+
78
+ def to_hash(cells) #:nodoc:
79
+ hash = {}
80
+ @raw[0].each_with_index do |key, n|
81
+ hash[key] = cells.value(n)
82
+ end
83
+ hash
84
+ end
85
+
86
+ def index(cells) #:nodoc:
87
+ cells_rows.index(cells)
88
+ end
89
+
90
+ def arguments_replaced(arguments) #:nodoc:
91
+ raw_with_replaced_args = raw.map do |row|
92
+ row.map do |cell|
93
+ cell_with_replaced_args = cell
94
+ arguments.each do |name, value|
95
+ cell_with_replaced_args = cell_with_replaced_args.gsub(name, value)
96
+ end
97
+ cell_with_replaced_args
98
+ end
99
+ end
100
+
101
+ Table.new(raw_with_replaced_args)
102
+ end
103
+
104
+ def at_lines?(lines)
105
+ cells_rows.detect{|row| row.at_lines?(lines)}
106
+ end
107
+
108
+ private
109
+
110
+ def col_width(col)
111
+ columns[col].__send__(:width)
112
+ end
113
+
114
+ def cells_rows
115
+ @rows ||= cell_matrix.map do |cell_row|
116
+ @cells_class.new(self, cell_row)
117
+ end
118
+ end
119
+
120
+ def columns
121
+ @columns ||= cell_matrix.transpose.map do |cell_row|
122
+ @cells_class.new(self, cell_row)
123
+ end
124
+ end
125
+
126
+ def cell_matrix
127
+ row = -1
128
+ @cell_matrix ||= @raw.map do |raw_row|
129
+ line = raw_row.line rescue -1
130
+ row += 1
131
+ col = -1
132
+ raw_row.map do |raw_cell|
133
+ col += 1
134
+ @cell_class.new(raw_cell, self, row, col, line)
135
+ end
136
+ end
137
+ end
138
+
139
+ # Represents a row of cells or columns of cells
140
+ class Cells
141
+ include Enumerable
142
+
143
+ def initialize(table, cells)
144
+ @table, @cells = table, cells
145
+ end
146
+
147
+ def accept(visitor, status)
148
+ each do |cell|
149
+ visitor.visit_table_cell(cell, status)
150
+ end
151
+ nil
152
+ end
153
+
154
+ # For testing only
155
+ def to_sexp #:nodoc:
156
+ [:row, *@cells.map{|cell| cell.to_sexp}]
157
+ end
158
+
159
+ def to_hash #:nodoc:
160
+ @to_hash ||= @table.to_hash(self)
161
+ end
162
+
163
+ def value(n) #:nodoc:
164
+ self[n].value
165
+ end
166
+
167
+ def [](n)
168
+ @cells[n]
169
+ end
170
+
171
+ def line
172
+ @cells[0].line
173
+ end
174
+
175
+ def at_lines?(lines)
176
+ lines.empty? || lines.index(line)
177
+ end
178
+
179
+ private
180
+
181
+ def index
182
+ @table.index(self)
183
+ end
184
+
185
+ def width
186
+ map{|cell| cell.value ? cell.value.to_s.jlength : 0}.max
187
+ end
188
+
189
+ def each(&proc)
190
+ @cells.each(&proc)
191
+ end
192
+ end
193
+
194
+ class Cell
195
+ attr_reader :value, :line
196
+
197
+ def initialize(value, table, row, col, line)
198
+ @value, @table, @row, @col, @line = value, table, row, col, line
199
+ end
200
+
201
+ def accept(visitor, status)
202
+ visitor.visit_table_cell_value(@value, col_width, status)
203
+ end
204
+
205
+ # For testing only
206
+ def to_sexp #:nodoc:
207
+ [:cell, @value]
208
+ end
209
+
210
+ private
211
+
212
+ def col_width
213
+ @col_width ||= @table.__send__(:col_width, @col)
214
+ end
215
+ end
216
+ end
217
+ end
218
+ end
@@ -0,0 +1,40 @@
1
+ module Cucumber
2
+ module Ast
3
+ # Holds the names of tags parsed from a feature file:
4
+ #
5
+ # @invoice @release_2
6
+ #
7
+ # This gets stored internally as <tt>["invoice", "release_2"]</tt>
8
+ #
9
+ class Tags
10
+ def initialize(line, tag_names)
11
+ @line, @tag_names = line, tag_names
12
+ end
13
+
14
+ def among?(tag_names)
15
+ no_tags, yes_tags = tag_names.partition{|tag| tag =~ /^\!/}
16
+ no_tags = no_tags.map{|tag| tag[1..-1]}
17
+
18
+ # Strip @
19
+ yes_tags = yes_tags.map{|tag| tag =~ /^@(.*)/ ? $1 : tag}
20
+ no_tags = no_tags.map{|tag| tag =~ /^@(.*)/ ? $1 : tag}
21
+
22
+ (@tag_names & yes_tags).any? && (@tag_names & no_tags).empty?
23
+ end
24
+
25
+ def at_lines?(lines)
26
+ lines.empty? || lines.index(@line)
27
+ end
28
+
29
+ def accept(visitor)
30
+ @tag_names.each do |tag_name|
31
+ visitor.visit_tag_name(tag_name)
32
+ end
33
+ end
34
+
35
+ def to_sexp
36
+ @tag_names.map{|tag_name| [:tag, tag_name]}
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,109 @@
1
+ module Cucumber
2
+ module Ast
3
+ # A dumb visitor that implements the whole Visitor API and just walks the tree.
4
+ class Visitor
5
+ attr_accessor :options
6
+
7
+ def initialize(step_mother)
8
+ @step_mother = step_mother
9
+ end
10
+
11
+ def world(scenario, world = nil, &proc)
12
+ @step_mother.world(scenario, world, &proc)
13
+ end
14
+
15
+ def new_world
16
+ @step_mother.new_world
17
+ end
18
+
19
+ def step_definition(step_name)
20
+ @step_mother.step_definition(step_name)
21
+ end
22
+
23
+ def current_feature_lines=(lines)
24
+ @current_feature_lines = lines
25
+ end
26
+
27
+ def current_feature_lines
28
+ @current_feature_lines || []
29
+ end
30
+
31
+ def visit_features(features)
32
+ features.accept(self)
33
+ end
34
+
35
+ def visit_feature(feature)
36
+ feature.accept(self)
37
+ end
38
+
39
+ def visit_comment(comment)
40
+ comment.accept(self)
41
+ end
42
+
43
+ def visit_comment_line(comment_line)
44
+ end
45
+
46
+ def visit_tags(tags)
47
+ tags.accept(self)
48
+ end
49
+
50
+ def visit_tag_name(tag_name)
51
+ end
52
+
53
+ def visit_feature_name(name)
54
+ end
55
+
56
+ # +feature_element+ is either Scenario or ScenarioOutline
57
+ def visit_feature_element(feature_element)
58
+ feature_element.accept(self)
59
+ end
60
+
61
+ def visit_background(background)
62
+ background.accept(self)
63
+ end
64
+
65
+ def visit_examples(examples)
66
+ examples.accept(self)
67
+ end
68
+
69
+ def visit_examples_name(keyword, name)
70
+ end
71
+
72
+ def visit_outline_table(outline_table)
73
+ outline_table.accept(self, nil)
74
+ end
75
+
76
+ def visit_scenario_name(keyword, name, file_line, source_indent)
77
+ end
78
+
79
+ def visit_steps(steps)
80
+ steps.accept(self)
81
+ end
82
+
83
+ def visit_step(step)
84
+ step.accept(self)
85
+ end
86
+
87
+ def visit_step_name(keyword, step_name, status, step_definition, source_indent)
88
+ end
89
+
90
+ def visit_multiline_arg(multiline_arg, status)
91
+ multiline_arg.accept(self, status)
92
+ end
93
+
94
+ def visit_py_string(string, status)
95
+ end
96
+
97
+ def visit_table_row(table_row, status)
98
+ table_row.accept(self, status)
99
+ end
100
+
101
+ def visit_table_cell(table_cell, status)
102
+ table_cell.accept(self, status)
103
+ end
104
+
105
+ def visit_table_cell_value(value, width, status)
106
+ end
107
+ end
108
+ end
109
+ end