cucumber 1.3.20 → 2.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (404) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.rspec +1 -1
  4. data/.travis.yml +1 -2
  5. data/CONTRIBUTING.md +9 -0
  6. data/Gemfile +9 -2
  7. data/History.md +26 -17
  8. data/LICENSE +2 -2
  9. data/README.md +4 -4
  10. data/Rakefile +12 -0
  11. data/bin/cucumber +1 -5
  12. data/bin/cuke +60 -0
  13. data/cucumber.gemspec +10 -15
  14. data/cucumber.yml +14 -26
  15. data/examples/i18n/ar/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  16. data/examples/i18n/bg/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  17. data/examples/i18n/ca/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  18. data/examples/i18n/cs/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  19. data/examples/i18n/da/features/{step_definitons → step_definitions}/lommeregner_steps.rb +0 -0
  20. data/examples/i18n/de/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  21. data/examples/{ramaze → i18n/el}/Rakefile +1 -1
  22. data/examples/i18n/el/features/addition.feature +17 -0
  23. data/examples/i18n/el/features/division.feature +10 -0
  24. data/examples/i18n/el/features/step_definitions/calculator_steps.rb +24 -0
  25. data/examples/i18n/el/lib/calculator.rb +14 -0
  26. data/examples/i18n/en/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  27. data/examples/i18n/eo/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  28. data/examples/i18n/es/features/{step_definitons → step_definitions}/calculador_steps.rb +0 -0
  29. data/examples/i18n/fi/features/{step_definitons → step_definitions}/laskin_steps.rb +0 -0
  30. data/examples/i18n/fr/Rakefile +3 -1
  31. data/examples/i18n/fr/features/step_definitions/calculatrice_steps.rb +2 -2
  32. data/examples/i18n/he/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  33. data/examples/i18n/hi/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  34. data/examples/i18n/hu/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  35. data/examples/i18n/id/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  36. data/examples/i18n/it/features/{step_definitons → step_definitions}/calcolatrice_steps.rb +0 -0
  37. data/examples/i18n/ja/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  38. data/examples/i18n/ko/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  39. data/examples/i18n/lt/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  40. data/examples/i18n/lv/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  41. data/examples/i18n/no/features/{step_definitons → step_definitions}/kalkulator_steps.rb +0 -0
  42. data/examples/i18n/pl/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  43. data/examples/i18n/ro/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  44. data/examples/i18n/ru/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  45. data/examples/i18n/sk/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  46. data/examples/i18n/sr-Cyrl/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  47. data/examples/i18n/sr-Latn/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  48. data/examples/i18n/sv/features/{step_definitons → step_definitions}/kalkulator_steps.rb +0 -0
  49. data/examples/i18n/tr/features/{step_definitons → step_definitions}/hesap_makinesi_adimlari.rb +0 -0
  50. data/examples/i18n/uk/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  51. data/examples/i18n/uz/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  52. data/examples/i18n/zh-CN/features/{step_definitons → step_definitions}/calculator_steps.rb +4 -4
  53. data/examples/i18n/zh-TW/features/{step_definitons → step_definitions}/calculator_steps.rb +0 -0
  54. data/{legacy_features → features/docs}/api/list_step_defs_as_json.feature +14 -14
  55. data/{legacy_features → features/docs}/api/run_cli_main_with_existing_runtime.feature +5 -10
  56. data/features/{backtraces.feature → docs/cli/backtraces.feature} +2 -2
  57. data/features/docs/cli/dry_run.feature +25 -0
  58. data/features/docs/cli/exclude_files.feature +19 -0
  59. data/features/docs/cli/execute_with_tag_filter.feature +117 -0
  60. data/features/docs/cli/randomize.feature +46 -0
  61. data/features/docs/cli/require.feature +27 -0
  62. data/features/docs/cli/run_scenarios_matching_name.feature +104 -0
  63. data/features/docs/cli/run_specific_scenarios.feature +113 -0
  64. data/features/docs/cli/showing_differences.feature +43 -0
  65. data/features/docs/cli/specifying_multiple_formatters.feature +44 -0
  66. data/features/docs/cli/strict_mode.feature +41 -0
  67. data/features/{nested_steps.feature → docs/defining_steps/nested_steps.feature} +3 -5
  68. data/features/{nested_steps_i18n.feature → docs/defining_steps/nested_steps_i18n.feature} +0 -2
  69. data/features/{nested_steps_with_second_arg.feature → docs/defining_steps/nested_steps_with_second_arg.feature} +0 -0
  70. data/features/{step_definitions.feature → docs/defining_steps/one_line_step_definitions.feature} +3 -3
  71. data/features/docs/defining_steps/printing_messages.feature +147 -0
  72. data/features/docs/defining_steps/skip_scenario.feature +33 -0
  73. data/features/docs/defining_steps/snippets.feature +41 -0
  74. data/{legacy_features → features/docs/defining_steps}/table_diffing.feature +15 -15
  75. data/features/{transforms.feature → docs/defining_steps/transforms.feature} +2 -2
  76. data/{legacy_features/exception_in_after_block.feature → features/docs/exception_in_after_hook.feature} +25 -26
  77. data/{legacy_features/exception_in_after_step_block.feature → features/docs/exception_in_after_step_hook.feature} +21 -24
  78. data/{legacy_features/exception_in_before_block.feature → features/docs/exception_in_before_hook.feature} +18 -20
  79. data/features/{custom_formatter.feature → docs/extending_cucumber/custom_formatter.feature} +3 -8
  80. data/features/{formatter_callbacks.feature → docs/extending_cucumber/formatter_callbacks.feature} +185 -4
  81. data/{legacy_features/listener_debugger_formatter.feature → features/docs/formatters/debug_formatter.feature} +13 -15
  82. data/features/{formatter_step_file_colon_line.feature → docs/formatters/formatter_step_file_colon_line.feature} +2 -4
  83. data/features/{html_formatter.feature → docs/formatters/html_formatter.feature} +10 -14
  84. data/features/{json_formatter.feature → docs/formatters/json_formatter.feature} +109 -247
  85. data/features/docs/formatters/junit_formatter.feature +275 -0
  86. data/features/{pretty_formatter.feature → docs/formatters/pretty_formatter.feature} +1 -1
  87. data/features/{progress_formatter.feature → docs/formatters/progress_formatter.feature} +1 -1
  88. data/features/docs/formatters/rerun_formatter.feature +135 -0
  89. data/features/docs/formatters/usage_formatter.feature +102 -0
  90. data/features/docs/getting_started.feature +27 -0
  91. data/features/{background.feature → docs/gherkin/background.feature} +149 -91
  92. data/features/{doc_strings.feature → docs/gherkin/doc_strings.feature} +1 -0
  93. data/features/docs/gherkin/expand_option_for_outlines.feature +46 -0
  94. data/features/docs/gherkin/language_from_header.feature +32 -0
  95. data/features/docs/gherkin/outlines.feature +154 -0
  96. data/features/docs/gherkin/unicode_table.feature +32 -0
  97. data/features/docs/gherkin/using_descriptions.feature +88 -0
  98. data/features/docs/gherkin/using_star_notation.feature +37 -0
  99. data/features/{iso-8859-1.feature → docs/iso-8859-1.feature} +0 -0
  100. data/{legacy_features → features/docs}/post_configuration_hook.feature +17 -18
  101. data/{legacy_features → features/docs}/profiles.feature +30 -36
  102. data/{legacy_features → features/docs}/rake_task.feature +30 -41
  103. data/features/{raketask.feature → docs/raketask.feature} +6 -13
  104. data/features/docs/report_called_undefined_steps.feature +57 -0
  105. data/{legacy_features → features/docs}/wire_protocol.feature +36 -31
  106. data/{legacy_features → features/docs}/wire_protocol_erb.feature +5 -6
  107. data/{legacy_features → features/docs}/wire_protocol_table_diffing.feature +14 -12
  108. data/{legacy_features → features/docs}/wire_protocol_tags.feature +6 -7
  109. data/{legacy_features → features/docs}/wire_protocol_timeouts.feature +6 -6
  110. data/{legacy_features → features/docs}/work_in_progress.feature +52 -54
  111. data/{legacy_features → features/docs/writing_support_code}/around_hooks.feature +25 -28
  112. data/features/docs/writing_support_code/before_hook.feature +61 -0
  113. data/features/docs/writing_support_code/hook_order.feature +61 -0
  114. data/features/{load_path.feature → docs/writing_support_code/load_path.feature} +3 -0
  115. data/features/docs/writing_support_code/state.feature +32 -0
  116. data/features/{tagged_hooks.feature → docs/writing_support_code/tagged_hooks.feature} +11 -13
  117. data/features/lib/step_definitions/aruba_steps.rb +22 -0
  118. data/features/lib/step_definitions/cucumber_steps.rb +50 -0
  119. data/features/{step_definitions → lib/step_definitions}/iso-8859-1_steps.rb +3 -15
  120. data/features/lib/step_definitions/json_steps.rb +7 -0
  121. data/features/lib/step_definitions/junit_steps.rb +13 -0
  122. data/features/lib/step_definitions/language_steps.rb +4 -5
  123. data/features/lib/step_definitions/profile_steps.rb +15 -0
  124. data/features/lib/step_definitions/ruby_steps.rb +3 -0
  125. data/{legacy_features → features/lib}/step_definitions/wire_steps.rb +16 -9
  126. data/features/lib/support/env.rb +21 -0
  127. data/{legacy_features → features/lib}/support/fake_wire_server.rb +0 -0
  128. data/features/{support → lib/support}/feature_factory.rb +1 -1
  129. data/features/lib/support/normalise_output.rb +33 -0
  130. data/gem_tasks/cov.rake +5 -0
  131. data/gem_tasks/cucumber.rake +1 -10
  132. data/gem_tasks/rspec.rake +0 -2
  133. data/gem_tasks/yard.rake +4 -1
  134. data/lib/cucumber.rb +1 -3
  135. data/lib/cucumber/cli/configuration.rb +30 -25
  136. data/lib/cucumber/cli/main.rb +13 -25
  137. data/lib/cucumber/cli/options.rb +15 -57
  138. data/lib/cucumber/configuration.rb +4 -0
  139. data/lib/cucumber/constantize.rb +7 -6
  140. data/lib/cucumber/core_ext/instance_exec.rb +7 -38
  141. data/lib/cucumber/core_ext/proc.rb +1 -1
  142. data/lib/cucumber/errors.rb +3 -1
  143. data/lib/cucumber/file_specs.rb +35 -0
  144. data/lib/cucumber/formatter/console.rb +32 -21
  145. data/lib/cucumber/formatter/debug.rb +5 -0
  146. data/lib/cucumber/formatter/gherkin_formatter_adapter.rb +8 -38
  147. data/lib/cucumber/formatter/html.rb +29 -21
  148. data/lib/cucumber/formatter/junit.rb +10 -7
  149. data/lib/cucumber/formatter/pretty.rb +2 -8
  150. data/lib/cucumber/formatter/rerun.rb +2 -3
  151. data/lib/cucumber/formatter/unicode.rb +8 -21
  152. data/lib/cucumber/formatter/usage.rb +65 -2
  153. data/lib/cucumber/language_support/language_methods.rb +1 -1
  154. data/lib/cucumber/mappings.rb +212 -0
  155. data/lib/cucumber/multiline_argument.rb +115 -0
  156. data/lib/cucumber/platform.rb +21 -22
  157. data/lib/cucumber/rake/task.rb +3 -54
  158. data/lib/cucumber/rb_support/rb_language.rb +2 -5
  159. data/lib/cucumber/rb_support/rb_world.rb +14 -19
  160. data/lib/cucumber/rb_support/snippet.rb +60 -19
  161. data/lib/cucumber/reports/legacy_formatter.rb +1279 -0
  162. data/lib/cucumber/runtime.rb +176 -26
  163. data/lib/cucumber/runtime/for_programming_languages.rb +10 -4
  164. data/lib/cucumber/runtime/gated_receiver.rb +21 -0
  165. data/lib/cucumber/runtime/support_code.rb +9 -7
  166. data/lib/cucumber/runtime/tag_limits.rb +15 -0
  167. data/lib/cucumber/runtime/tag_limits/filter.rb +31 -0
  168. data/lib/cucumber/runtime/tag_limits/test_case_index.rb +29 -0
  169. data/lib/cucumber/runtime/tag_limits/verifier.rb +57 -0
  170. data/lib/cucumber/runtime/user_interface.rb +4 -0
  171. data/lib/cucumber/step_match.rb +3 -3
  172. data/lib/cucumber/term/ansicolor.rb +1 -9
  173. data/lib/cucumber/wire_support/wire_language.rb +23 -9
  174. data/lib/cucumber/wire_support/wire_packet.rb +1 -1
  175. data/lib/cucumber/wire_support/wire_protocol/requests.rb +13 -5
  176. data/lib/cucumber/wire_support/wire_step_definition.rb +1 -8
  177. data/spec/cucumber/cli/configuration_spec.rb +151 -150
  178. data/spec/cucumber/cli/main_spec.rb +36 -99
  179. data/spec/cucumber/cli/options_spec.rb +238 -272
  180. data/spec/cucumber/cli/profile_loader_spec.rb +9 -8
  181. data/spec/cucumber/configuration_spec.rb +3 -3
  182. data/spec/cucumber/constantize_spec.rb +2 -1
  183. data/spec/cucumber/core_ext/proc_spec.rb +32 -43
  184. data/spec/cucumber/file_specs_spec.rb +41 -0
  185. data/spec/cucumber/formatter/ansicolor_spec.rb +11 -10
  186. data/spec/cucumber/formatter/debug_spec.rb +569 -0
  187. data/spec/cucumber/formatter/duration_spec.rb +6 -6
  188. data/spec/cucumber/formatter/html_spec.rb +53 -62
  189. data/spec/cucumber/formatter/interceptor_spec.rb +38 -31
  190. data/spec/cucumber/formatter/junit_spec.rb +34 -28
  191. data/spec/cucumber/formatter/pretty_spec.rb +238 -52
  192. data/spec/cucumber/formatter/progress_spec.rb +2 -2
  193. data/spec/cucumber/formatter/spec_helper.rb +23 -17
  194. data/spec/cucumber/rake/forked_spec.rb +13 -22
  195. data/spec/cucumber/rb_support/rb_language_spec.rb +76 -67
  196. data/spec/cucumber/rb_support/rb_step_definition_spec.rb +63 -42
  197. data/spec/cucumber/rb_support/rb_transform_spec.rb +4 -3
  198. data/spec/cucumber/rb_support/regexp_argument_matcher_spec.rb +6 -4
  199. data/spec/cucumber/rb_support/snippet_spec.rb +42 -33
  200. data/spec/cucumber/reports/legacy_formatter_spec.rb +1750 -0
  201. data/spec/cucumber/runtime/for_programming_languages_spec.rb +11 -10
  202. data/spec/cucumber/runtime/gated_receiver_spec.rb +47 -0
  203. data/spec/cucumber/runtime/results_spec.rb +33 -26
  204. data/spec/cucumber/runtime/support_code_spec.rb +29 -29
  205. data/spec/cucumber/runtime/tag_limits/filter_spec.rb +59 -0
  206. data/spec/cucumber/runtime/tag_limits/test_case_index_spec.rb +38 -0
  207. data/spec/cucumber/runtime/tag_limits/verifier_spec.rb +57 -0
  208. data/spec/cucumber/runtime_spec.rb +39 -34
  209. data/spec/cucumber/step_match_spec.rb +30 -20
  210. data/spec/cucumber/wire_support/configuration_spec.rb +8 -5
  211. data/spec/cucumber/wire_support/connection_spec.rb +12 -8
  212. data/spec/cucumber/wire_support/wire_exception_spec.rb +14 -8
  213. data/spec/cucumber/wire_support/wire_language_spec.rb +8 -9
  214. data/spec/cucumber/wire_support/wire_packet_spec.rb +17 -13
  215. data/spec/cucumber/world/pending_spec.rb +36 -36
  216. data/spec/simplecov_setup.rb +18 -0
  217. data/spec/spec_helper.rb +3 -9
  218. metadata +298 -507
  219. data/.gitattributes +0 -1
  220. data/.ruby-version +0 -1
  221. data/examples/python/README.textile +0 -8
  222. data/examples/python/Rakefile +0 -4
  223. data/examples/python/features/fibonacci.feature +0 -19
  224. data/examples/python/features/step_definitions/fib_steps.py +0 -11
  225. data/examples/python/lib/fib.py +0 -7
  226. data/examples/ramaze/README.textile +0 -7
  227. data/examples/ramaze/app.rb +0 -21
  228. data/examples/ramaze/features/add.feature +0 -11
  229. data/examples/ramaze/features/step_definitions/add_steps.rb +0 -15
  230. data/examples/ramaze/features/support/env.rb +0 -32
  231. data/examples/ramaze/layout/default.html.erb +0 -8
  232. data/examples/ramaze/view/index.html.erb +0 -5
  233. data/examples/ruby2python/README.textile +0 -8
  234. data/examples/ruby2python/Rakefile +0 -4
  235. data/examples/ruby2python/features/fibonacci.feature +0 -19
  236. data/examples/ruby2python/features/step_definitions/fib_steps.rb +0 -7
  237. data/examples/ruby2python/features/support/env.rb +0 -21
  238. data/examples/ruby2python/lib/fib.py +0 -7
  239. data/examples/v8/Rakefile +0 -6
  240. data/examples/v8/features/fibonacci.feature +0 -43
  241. data/examples/v8/features/step_definitions/fib_steps.js +0 -49
  242. data/examples/v8/features/support/env.js +0 -14
  243. data/examples/v8/lib/fibonacci.js +0 -19
  244. data/features/.cucumber/stepdefs.json +0 -722
  245. data/features/assertions.feature +0 -73
  246. data/features/autoformat_profile_output.feature +0 -23
  247. data/features/before_hook.feature +0 -43
  248. data/features/bootstrap.feature +0 -26
  249. data/features/drb_server_integration.feature +0 -63
  250. data/features/execute_with_tag_filter.feature +0 -63
  251. data/features/parsing.feature +0 -18
  252. data/features/rerun_formatter.feature +0 -99
  253. data/features/run_specific_scenarios.feature +0 -47
  254. data/features/stats_formatters.feature +0 -73
  255. data/features/step_definitions/cucumber-features/cucumber_ruby_mappings.rb +0 -197
  256. data/features/step_definitions/cucumber_steps.rb +0 -57
  257. data/features/step_definitions/drb_steps.rb +0 -3
  258. data/features/support/env.rb +0 -57
  259. data/fixtures/json/features/background.feature +0 -7
  260. data/fixtures/json/features/embed.feature +0 -4
  261. data/fixtures/json/features/one_passing_one_failing.feature +0 -11
  262. data/fixtures/json/features/step_definitions/steps.rb +0 -32
  263. data/fixtures/json/features/tables.feature +0 -13
  264. data/fixtures/junit/features/one_passing_one_failing.feature +0 -8
  265. data/fixtures/junit/features/pending.feature +0 -7
  266. data/fixtures/junit/features/scenario_outline.feature +0 -9
  267. data/fixtures/junit/features/some_subdirectory/one_passing_one_failing.feature +0 -8
  268. data/fixtures/junit/features/step_definitions/steps.rb +0 -11
  269. data/fixtures/self_test/README.textile +0 -6
  270. data/fixtures/self_test/Rakefile +0 -6
  271. data/fixtures/self_test/features/call_undefined_step_from_step_def.feature +0 -7
  272. data/fixtures/self_test/features/failing_expectation.feature +0 -4
  273. data/fixtures/self_test/features/lots_of_undefined.feature +0 -8
  274. data/fixtures/self_test/features/multiline_name.feature +0 -27
  275. data/fixtures/self_test/features/outline_sample.feature +0 -15
  276. data/fixtures/self_test/features/sample.feature +0 -21
  277. data/fixtures/self_test/features/search_sample.feature +0 -32
  278. data/fixtures/self_test/features/step_definitions/sample_steps.rb +0 -84
  279. data/fixtures/self_test/features/support/bubble_256x256.png +0 -0
  280. data/fixtures/self_test/features/support/env.rb +0 -26
  281. data/fixtures/self_test/features/tags_sample.feature +0 -17
  282. data/fixtures/self_test/features/tons_of_cukes.feature +0 -52
  283. data/fixtures/self_test/features/undefined_multiline_args.feature +0 -12
  284. data/fixtures/self_test/list-of-features.txt +0 -1
  285. data/fixtures/steps_library/features/step_definitions/steps_lib1.rb +0 -8
  286. data/fixtures/steps_library/features/step_definitions/steps_lib2.rb +0 -8
  287. data/fixtures/tickets/Rakefile +0 -20
  288. data/fixtures/tickets/features.html +0 -138
  289. data/fixtures/tickets/features/172.feature +0 -28
  290. data/fixtures/tickets/features/177/1.feature +0 -28
  291. data/fixtures/tickets/features/177/2.feature +0 -20
  292. data/fixtures/tickets/features/177/3.feature +0 -18
  293. data/fixtures/tickets/features/180.feature +0 -7
  294. data/fixtures/tickets/features/229/tagged_hooks.feature +0 -8
  295. data/fixtures/tickets/features/229/tagged_hooks.rb +0 -14
  296. data/fixtures/tickets/features/236.feature +0 -13
  297. data/fixtures/tickets/features/241.feature +0 -12
  298. data/fixtures/tickets/features/246.feature +0 -4
  299. data/fixtures/tickets/features/248.feature +0 -11
  300. data/fixtures/tickets/features/270/back.feature +0 -14
  301. data/fixtures/tickets/features/270/back.steps.rb +0 -14
  302. data/fixtures/tickets/features/272/hooks.feature +0 -26
  303. data/fixtures/tickets/features/272/hooks_steps.rb +0 -53
  304. data/fixtures/tickets/features/279/py_string_indent.feature +0 -25
  305. data/fixtures/tickets/features/279/py_string_indent.steps.rb +0 -12
  306. data/fixtures/tickets/features/279/wrong.feature_ +0 -11
  307. data/fixtures/tickets/features/301/filter_background_tagged_hooks.feature +0 -6
  308. data/fixtures/tickets/features/301/filter_background_tagged_hooks_steps.rb +0 -12
  309. data/fixtures/tickets/features/306/only_background.feature +0 -4
  310. data/fixtures/tickets/features/around_timeout.feature +0 -6
  311. data/fixtures/tickets/features/gherkin_67.feature +0 -12
  312. data/fixtures/tickets/features/gherkin_68.feature +0 -4
  313. data/fixtures/tickets/features/half_manual.feature +0 -11
  314. data/fixtures/tickets/features/lib/eatting_machine.rb +0 -18
  315. data/fixtures/tickets/features/lib/pantry.rb +0 -20
  316. data/fixtures/tickets/features/scenario_outline.feature +0 -95
  317. data/fixtures/tickets/features/step_definitons/246_steps.rb +0 -3
  318. data/fixtures/tickets/features/step_definitons/248_steps.rb +0 -15
  319. data/fixtures/tickets/features/step_definitons/around_timeout_steps.rb +0 -9
  320. data/fixtures/tickets/features/step_definitons/half_manual_steps.rb +0 -11
  321. data/fixtures/tickets/features/step_definitons/scenario_outline_steps.rb +0 -42
  322. data/fixtures/tickets/features/step_definitons/tickets_steps.rb +0 -88
  323. data/fixtures/tickets/features/table_diffing.feature +0 -13
  324. data/fixtures/tickets/features/tickets.feature +0 -28
  325. data/legacy_features/README.md +0 -14
  326. data/legacy_features/announce.feature +0 -152
  327. data/legacy_features/bug_371.feature +0 -32
  328. data/legacy_features/bug_464.feature +0 -16
  329. data/legacy_features/bug_475.feature +0 -42
  330. data/legacy_features/bug_585_tab_indentation.feature +0 -22
  331. data/legacy_features/bug_600.feature +0 -73
  332. data/legacy_features/cucumber_cli.feature +0 -584
  333. data/legacy_features/cucumber_cli_outlines.feature +0 -117
  334. data/legacy_features/default_snippets.feature +0 -43
  335. data/legacy_features/diffing.feature +0 -25
  336. data/legacy_features/drb_server_integration.feature +0 -174
  337. data/legacy_features/exclude_files.feature +0 -20
  338. data/legacy_features/expand.feature +0 -60
  339. data/legacy_features/junit_formatter.feature +0 -214
  340. data/legacy_features/language_from_header.feature +0 -30
  341. data/legacy_features/multiline_names.feature +0 -44
  342. data/legacy_features/report_called_undefined_steps.feature +0 -35
  343. data/legacy_features/rerun_formatter.feature +0 -52
  344. data/legacy_features/simplest.feature +0 -11
  345. data/legacy_features/snippet.feature +0 -23
  346. data/legacy_features/snippets_when_using_star_keyword.feature +0 -38
  347. data/legacy_features/step_definitions/cucumber_steps.rb +0 -179
  348. data/legacy_features/step_definitions/extra_steps.rb +0 -2
  349. data/legacy_features/step_definitions/simplest_steps.rb +0 -3
  350. data/legacy_features/support/env.rb +0 -161
  351. data/legacy_features/support/env.rb.simplest +0 -7
  352. data/legacy_features/table_mapping.feature +0 -34
  353. data/legacy_features/transform.feature +0 -245
  354. data/legacy_features/unicode_table.feature +0 -35
  355. data/lib/README.rdoc +0 -12
  356. data/lib/cucumber/ast.rb +0 -30
  357. data/lib/cucumber/ast/background.rb +0 -116
  358. data/lib/cucumber/ast/comment.rb +0 -31
  359. data/lib/cucumber/ast/doc_string.rb +0 -61
  360. data/lib/cucumber/ast/empty_background.rb +0 -33
  361. data/lib/cucumber/ast/examples.rb +0 -49
  362. data/lib/cucumber/ast/feature.rb +0 -99
  363. data/lib/cucumber/ast/features.rb +0 -38
  364. data/lib/cucumber/ast/has_steps.rb +0 -74
  365. data/lib/cucumber/ast/location.rb +0 -41
  366. data/lib/cucumber/ast/multiline_argument.rb +0 -30
  367. data/lib/cucumber/ast/names.rb +0 -13
  368. data/lib/cucumber/ast/outline_table.rb +0 -194
  369. data/lib/cucumber/ast/scenario.rb +0 -103
  370. data/lib/cucumber/ast/scenario_outline.rb +0 -146
  371. data/lib/cucumber/ast/step.rb +0 -122
  372. data/lib/cucumber/ast/step_collection.rb +0 -92
  373. data/lib/cucumber/ast/step_invocation.rb +0 -196
  374. data/lib/cucumber/ast/table.rb +0 -738
  375. data/lib/cucumber/ast/tags.rb +0 -28
  376. data/lib/cucumber/ast/tree_walker.rb +0 -191
  377. data/lib/cucumber/ast/visitor.rb +0 -11
  378. data/lib/cucumber/broadcaster.rb +0 -13
  379. data/lib/cucumber/cli/drb_client.rb +0 -43
  380. data/lib/cucumber/feature_file.rb +0 -101
  381. data/lib/cucumber/formatter/ordered_xml_markup.rb +0 -24
  382. data/lib/cucumber/js_support/js_dsl.js +0 -57
  383. data/lib/cucumber/js_support/js_language.rb +0 -185
  384. data/lib/cucumber/js_support/js_snippets.rb +0 -27
  385. data/lib/cucumber/parser.rb +0 -2
  386. data/lib/cucumber/parser/gherkin_builder.rb +0 -284
  387. data/lib/cucumber/py_support/py_dsl.py +0 -10
  388. data/lib/cucumber/py_support/py_language.py +0 -10
  389. data/lib/cucumber/py_support/py_language.rb +0 -80
  390. data/lib/cucumber/step_mother.rb +0 -10
  391. data/spec/cucumber/ast/background_spec.rb +0 -122
  392. data/spec/cucumber/ast/doc_string_spec.rb +0 -40
  393. data/spec/cucumber/ast/feature_factory.rb +0 -72
  394. data/spec/cucumber/ast/feature_spec.rb +0 -63
  395. data/spec/cucumber/ast/features_spec.rb +0 -51
  396. data/spec/cucumber/ast/outline_table_spec.rb +0 -21
  397. data/spec/cucumber/ast/scenario_outline_spec.rb +0 -74
  398. data/spec/cucumber/ast/step_spec.rb +0 -68
  399. data/spec/cucumber/ast/table_spec.rb +0 -594
  400. data/spec/cucumber/ast/tree_walker_spec.rb +0 -19
  401. data/spec/cucumber/broadcaster_spec.rb +0 -15
  402. data/spec/cucumber/cli/drb_client_spec.rb +0 -76
  403. data/spec/cucumber/rake/rcov_spec.rb +0 -71
  404. data/spec/cucumber/wire_support/wire_step_definition_spec.rb +0 -20
@@ -1,122 +0,0 @@
1
- require 'cucumber/core_ext/string'
2
- require 'cucumber/step_match'
3
- require 'cucumber/ast/location'
4
-
5
- module Cucumber
6
- module Ast
7
- class Step #:nodoc:
8
- include HasLocation
9
-
10
- attr_reader :keyword, :name, :language
11
- attr_writer :step_collection, :options
12
- attr_accessor :feature_element, :exception, :multiline_arg
13
-
14
- INDENT = 2
15
-
16
- def initialize(language, location, keyword, name, multiline_arg=nil)
17
- @language, @location, @keyword, @name, @multiline_arg = language, location, keyword, name, multiline_arg
18
- @language || raise("Language is required!")
19
- end
20
-
21
- attr_reader :gherkin_statement
22
- def gherkin_statement(statement=nil)
23
- @gherkin_statement ||= statement
24
- end
25
-
26
- def background?
27
- false
28
- end
29
-
30
- def status
31
- # Step always has status skipped, because Step is always in a ScenarioOutline
32
- :skipped
33
- end
34
-
35
- def step_invocation
36
- StepInvocation.new(self, name, @multiline_arg, [])
37
- end
38
-
39
- def step_invocation_from_cells(cells)
40
- matched_cells = matched_cells(cells)
41
-
42
- delimited_arguments = delimit_argument_names(cells.to_hash)
43
- name = replace_name_arguments(delimited_arguments)
44
- multiline_arg = @multiline_arg.nil? ? nil : @multiline_arg.arguments_replaced(delimited_arguments)
45
-
46
- StepInvocation.new(self, name, multiline_arg, matched_cells)
47
- end
48
-
49
- def accept(visitor)
50
- return if Cucumber.wants_to_quit
51
- # The only time a Step is visited is when it is in a ScenarioOutline.
52
- # Otherwise it's always StepInvocation that gets visited instead.
53
- visit_step_result(visitor, first_match(visitor), @multiline_arg, :skipped, nil, nil)
54
- end
55
-
56
- def visit_step_result(visitor, step_match, multiline_arg, status, exception, background)
57
- visitor.visit_step_result(keyword, step_match, @multiline_arg, status, exception, source_indent, background, file_colon_line)
58
- end
59
-
60
- def first_match(visitor)
61
- # feature_element is always a ScenarioOutline in this case
62
- feature_element.each_example_row do |cells|
63
- argument_hash = cells.to_hash
64
- delimited_arguments = delimit_argument_names(argument_hash)
65
- name_to_match = replace_name_arguments(delimited_arguments)
66
- step_match = visitor.runtime.step_match(name_to_match, name) rescue nil
67
- return step_match if step_match
68
- end
69
- NoStepMatch.new(self, name)
70
- end
71
-
72
- def to_sexp
73
- [:step, line, keyword, name, (@multiline_arg.nil? ? nil : @multiline_arg.to_sexp)].compact
74
- end
75
-
76
- def source_indent
77
- feature_element.source_indent(text_length)
78
- end
79
-
80
- def text_length(name=name())
81
- INDENT + INDENT + keyword.unpack('U*').length + name.unpack('U*').length
82
- end
83
-
84
- def backtrace_line
85
- @backtrace_line ||= feature_element.backtrace_line("#{keyword}#{name}", line) unless feature_element.nil?
86
- end
87
-
88
- def dom_id
89
- @dom_id ||= file_colon_line.gsub(/\//, '_').gsub(/\./, '_').gsub(/:/, '_')
90
- end
91
-
92
- private
93
-
94
- def matched_cells(cells)
95
- col_index = 0
96
- cells.select do |cell|
97
- header_cell = cell.table.header_cell(col_index)
98
- col_index += 1
99
- delimited = delimited(header_cell.value)
100
- name.index(delimited) || (@multiline_arg && @multiline_arg.has_text?(delimited))
101
- end
102
- end
103
-
104
- def delimit_argument_names(argument_hash)
105
- argument_hash.inject({}) { |h,(name,value)| h[delimited(name)] = value; h }
106
- end
107
-
108
- def delimited(s)
109
- "<#{s}>"
110
- end
111
-
112
- def replace_name_arguments(argument_hash)
113
- name_with_arguments_replaced = name
114
- argument_hash.each do |key, value|
115
- value ||= ''
116
- name_with_arguments_replaced = name_with_arguments_replaced.gsub(key, value)
117
- end
118
- name_with_arguments_replaced
119
- end
120
- end
121
- end
122
- end
@@ -1,92 +0,0 @@
1
- module Cucumber
2
- module Ast
3
- # Holds an Array of Step or StepDefinition
4
- class StepCollection #:nodoc:
5
- include Enumerable
6
-
7
- def initialize(steps)
8
- @steps = steps
9
- @steps.each{|step| step.step_collection = self}
10
- end
11
-
12
- def inspect
13
- @steps.map { |s| [s.class, s.object_id] }.join(', ')
14
- end
15
-
16
- def accept(visitor)
17
- return if Cucumber.wants_to_quit
18
- @steps.each do |step|
19
- visitor.visit_step(step)
20
- end
21
- end
22
-
23
- def step_invocations(background = false)
24
- StepCollection.new(@steps.map{ |step|
25
- i = step.step_invocation
26
- i.background = background
27
- i
28
- })
29
- end
30
-
31
- def skip_invoke!
32
- @steps.each{|step_invocation| step_invocation.skip_invoke!}
33
- end
34
-
35
- def step_invocations_from_cells(cells)
36
- @steps.map{|step| step.step_invocation_from_cells(cells)}
37
- end
38
-
39
- def +(step_invocations)
40
- dup(step_invocations)
41
- end
42
-
43
- # Duplicates this instance and adds +step_invocations+ to the end
44
- def dup(step_invocations = [])
45
- StepCollection.new(@steps + step_invocations)
46
- end
47
-
48
- def each(&proc)
49
- @steps.each(&proc)
50
- end
51
-
52
- def previous_step(step)
53
- i = @steps.index(step) || -1
54
- @steps[i-1]
55
- end
56
-
57
- def empty?
58
- @steps.empty?
59
- end
60
-
61
- def max_line_length(feature_element)
62
- lengths = (@steps + [feature_element]).map{|e| e.text_length}
63
- lengths.max
64
- end
65
-
66
- def exception
67
- @exception ||= ((failed = @steps.detect {|step| step.exception}) && failed.exception)
68
- end
69
-
70
- def failed?
71
- status == :failed
72
- end
73
-
74
- def passed?
75
- status == :passed
76
- end
77
-
78
- def status
79
- @steps.each{|step_invocation| return step_invocation.status if step_invocation.status != :passed}
80
- :passed
81
- end
82
-
83
- def length
84
- @steps.length
85
- end
86
-
87
- def to_sexp
88
- @steps.map{|step| step.to_sexp}
89
- end
90
- end
91
- end
92
- end
@@ -1,196 +0,0 @@
1
- require 'cucumber/errors'
2
- require 'cucumber/step_match'
3
- require 'cucumber/ast/table'
4
- require 'gherkin/rubify'
5
-
6
- module Cucumber
7
- module Ast
8
- class StepInvocation #:nodoc:
9
- include Gherkin::Rubify
10
-
11
- attr_writer :step_collection, :background
12
- attr_reader :name, :matched_cells, :status, :reported_exception
13
- attr_accessor :exception
14
-
15
- class << self
16
- SEVERITY = [:passed, :undefined, :pending, :skipped, :failed]
17
- def worst_status(statuses)
18
- SEVERITY[statuses.map{|status| SEVERITY.index(status)}.max]
19
- end
20
- end
21
-
22
- def initialize(step, name, multiline_arg, matched_cells)
23
- @step, @name, @multiline_arg, @matched_cells = step, name, multiline_arg, matched_cells
24
- status!(:skipped)
25
- @skip_invoke = @exception = @step_match = @different_table = @reported_exception = @background = nil
26
- end
27
-
28
- def background?
29
- @background
30
- end
31
-
32
- def skip_invoke!
33
- @skip_invoke = true
34
- end
35
-
36
- def accept(visitor)
37
- return if Cucumber.wants_to_quit
38
- invoke(visitor.runtime, visitor.configuration)
39
- visit_step_result(visitor)
40
- end
41
-
42
- def visit_step_result(visitor)
43
- visitor.visit_step_result(
44
- keyword,
45
- @step_match,
46
- (@different_table || @multiline_arg),
47
- @status,
48
- @reported_exception,
49
- source_indent,
50
- @background,
51
- file_colon_line
52
- )
53
- end
54
-
55
- def invoke(runtime, configuration)
56
- find_step_match!(runtime, configuration)
57
- unless @skip_invoke || configuration.dry_run? || @exception || @step_collection.exception
58
- @skip_invoke = true
59
- begin
60
- @step_match.invoke(@multiline_arg)
61
- runtime.after_step
62
- status!(:passed)
63
- rescue Pending => e
64
- failed(configuration, e, false)
65
- status!(:pending)
66
- rescue Undefined => e
67
- failed(configuration, e, false)
68
- status!(:undefined)
69
- rescue Cucumber::Ast::Table::Different => e
70
- @different_table = e.table
71
- failed(configuration, e, false)
72
- status!(:failed)
73
- rescue Exception => e
74
- failed(configuration, e, false)
75
- status!(:failed)
76
- end
77
- end
78
- end
79
-
80
- def find_step_match!(runtime, configuration)
81
- return if @step_match
82
- begin
83
- @step_match = runtime.step_match(@name)
84
- rescue Undefined => e
85
- failed(configuration, e, true)
86
- status!(:undefined)
87
- @step_match = NoStepMatch.new(@step, @name)
88
- rescue Ambiguous => e
89
- failed(configuration, e, false)
90
- status!(:failed)
91
- @step_match = NoStepMatch.new(@step, @name)
92
- end
93
- runtime.step_visited(self)
94
- end
95
-
96
- def failed(configuration, e, clear_backtrace)
97
- e.set_backtrace([]) if e.backtrace.nil? || clear_backtrace
98
- e.backtrace << @step.backtrace_line unless @step.backtrace_line.nil?
99
- e = filter_backtrace(e)
100
- @exception = e
101
- if(configuration.strict? || !(Undefined === e) || e.nested?)
102
- @reported_exception = e
103
- else
104
- @reported_exception = nil
105
- end
106
- end
107
-
108
- # This constant is appended to by Cuke4Duke. Do not change its name
109
- BACKTRACE_FILTER_PATTERNS = [/vendor\/rails|lib\/cucumber|bin\/cucumber:|lib\/rspec|gems\/|minitest|test\/unit|lib\/ruby/]
110
- if(Cucumber::JRUBY)
111
- BACKTRACE_FILTER_PATTERNS << /org\/jruby/
112
- end
113
- PWD_PATTERN = /#{Regexp.escape(Dir.pwd)}\//m
114
-
115
- # This is to work around double ":in " segments in JRuby backtraces. JRuby bug?
116
- def filter_backtrace(e)
117
- return e if Cucumber.use_full_backtrace
118
- e.backtrace.each{|line| line.gsub!(PWD_PATTERN, "./")}
119
-
120
- filtered = (e.backtrace || []).reject do |line|
121
- BACKTRACE_FILTER_PATTERNS.detect { |p| line =~ p }
122
- end
123
-
124
- if ENV['CUCUMBER_TRUNCATE_OUTPUT']
125
- # Strip off file locations
126
- filtered = filtered.map do |line|
127
- line =~ /(.*):in `/ ? $1 : line
128
- end
129
- end
130
-
131
- e.set_backtrace(filtered)
132
- e
133
- end
134
-
135
- def status!(status)
136
- @status = status
137
- @matched_cells.each do |cell|
138
- cell.status = status
139
- end
140
- end
141
-
142
- def previous
143
- @step_collection.previous_step(self)
144
- end
145
-
146
- def actual_keyword
147
- repeat_keywords = rubify([language.keywords('but'), language.keywords('and')]).flatten.uniq.reject{|kw| kw == '* '}
148
- if repeat_keywords.index(@step.keyword) && previous
149
- previous.actual_keyword
150
- else
151
- keyword == '* ' ? language.code_keywords.first : keyword
152
- end
153
- end
154
-
155
- def source_indent
156
- @step.feature_element.source_indent(text_length)
157
- end
158
-
159
- def text_length
160
- @step.text_length(@name)
161
- end
162
-
163
- def keyword
164
- @step.keyword
165
- end
166
-
167
- def multiline_arg
168
- @step.multiline_arg
169
- end
170
-
171
- def file_colon_line
172
- @step.file_colon_line
173
- end
174
-
175
- def dom_id
176
- @step.dom_id
177
- end
178
-
179
- def backtrace_line
180
- @step.backtrace_line
181
- end
182
-
183
- def language
184
- @step.language || raise("Language is required on #{@step}")
185
- end
186
-
187
- def gherkin_statement
188
- @step.gherkin_statement
189
- end
190
-
191
- def to_sexp
192
- [:step_invocation, @step.line, @step.keyword, @name, (@multiline_arg.nil? ? nil : @multiline_arg.to_sexp)].compact
193
- end
194
- end
195
- end
196
- end
@@ -1,738 +0,0 @@
1
- require 'gherkin/rubify'
2
- require 'gherkin/lexer/i18n_lexer'
3
- require 'gherkin/formatter/escaping'
4
-
5
- module Cucumber
6
- module Ast
7
- # Step Definitions that match a plain text Step with a multiline argument table
8
- # will receive it as an instance of Table. A Table object holds the data of a
9
- # table parsed from a feature file and lets you access and manipulate the data
10
- # in different ways.
11
- #
12
- # For example:
13
- #
14
- # Given I have:
15
- # | a | b |
16
- # | c | d |
17
- #
18
- # And a matching StepDefinition:
19
- #
20
- # Given /I have:/ do |table|
21
- # data = table.raw
22
- # end
23
- #
24
- # This will store <tt>[['a', 'b'], ['c', 'd']]</tt> in the <tt>data</tt> variable.
25
- #
26
- class Table
27
- class Different < StandardError
28
- attr_reader :table
29
-
30
- def initialize(table)
31
- super('Tables were not identical')
32
- @table = table
33
- end
34
- end
35
-
36
- class Builder
37
- attr_reader :rows
38
-
39
- def initialize
40
- @rows = []
41
- end
42
-
43
- def row(row, line_number)
44
- @rows << row
45
- end
46
-
47
- def eof
48
- end
49
- end
50
-
51
- include Enumerable
52
- include Gherkin::Rubify
53
-
54
- NULL_CONVERSIONS = Hash.new({ :strict => false, :proc => lambda{ |cell_value| cell_value } }).freeze
55
-
56
- attr_accessor :file
57
-
58
- def self.default_arg_name #:nodoc:
59
- "table"
60
- end
61
-
62
- def self.parse(text, uri, offset)
63
- builder = Builder.new
64
- lexer = Gherkin::Lexer::I18nLexer.new(builder)
65
- lexer.scan(text)
66
- new(builder.rows)
67
- end
68
-
69
- # Creates a new instance. +raw+ should be an Array of Array of String
70
- # or an Array of Hash (similar to what #hashes returns).
71
- # You don't typically create your own Table objects - Cucumber will do
72
- # it internally and pass them to your Step Definitions.
73
- #
74
- def initialize(raw, conversion_procs = NULL_CONVERSIONS.dup, header_mappings = {}, header_conversion_proc = nil)
75
- @cells_class = Cells
76
- @cell_class = Cell
77
- raw = ensure_array_of_array(rubify(raw))
78
- # Verify that it's square
79
- raw.transpose
80
- create_cell_matrix(raw)
81
- @conversion_procs = conversion_procs
82
- @header_mappings = header_mappings
83
- @header_conversion_proc = header_conversion_proc
84
- end
85
-
86
- def to_step_definition_arg
87
- dup
88
- end
89
-
90
- # Creates a copy of this table, inheriting any column and header mappings
91
- # registered with #map_column! and #map_headers!.
92
- #
93
- def dup
94
- self.class.new(raw.dup, @conversion_procs.dup, @header_mappings.dup, @header_conversion_proc)
95
- end
96
-
97
- # Returns a new, transposed table. Example:
98
- #
99
- # | a | 7 | 4 |
100
- # | b | 9 | 2 |
101
- #
102
- # Gets converted into the following:
103
- #
104
- # | a | b |
105
- # | 7 | 9 |
106
- # | 4 | 2 |
107
- #
108
- def transpose
109
- self.class.new(raw.transpose, @conversion_procs.dup, @header_mappings.dup, @header_conversion_proc)
110
- end
111
-
112
- # Converts this table into an Array of Hash where the keys of each
113
- # Hash are the headers in the table. For example, a Table built from
114
- # the following plain text:
115
- #
116
- # | a | b | sum |
117
- # | 2 | 3 | 5 |
118
- # | 7 | 9 | 16 |
119
- #
120
- # Gets converted into the following:
121
- #
122
- # [{'a' => '2', 'b' => '3', 'sum' => '5'}, {'a' => '7', 'b' => '9', 'sum' => '16'}]
123
- #
124
- # Use #map_column! to specify how values in a column are converted.
125
- #
126
- def hashes
127
- @hashes ||= build_hashes
128
- end
129
-
130
- # Converts this table into a Hash where the first column is
131
- # used as keys and the second column is used as values
132
- #
133
- # | a | 2 |
134
- # | b | 3 |
135
- #
136
- # Gets converted into the following:
137
- #
138
- # {'a' => '2', 'b' => '3'}
139
- #
140
- # The table must be exactly two columns wide
141
- #
142
- def rows_hash
143
- return @rows_hash if @rows_hash
144
- verify_table_width(2)
145
- @rows_hash = self.transpose.hashes[0]
146
- end
147
-
148
- # Gets the raw data of this table. For example, a Table built from
149
- # the following plain text:
150
- #
151
- # | a | b |
152
- # | c | d |
153
- #
154
- # gets converted into the following:
155
- #
156
- # [['a', 'b'], ['c', 'd']]
157
- #
158
- def raw
159
- cell_matrix.map do |row|
160
- row.map do |cell|
161
- cell.value
162
- end
163
- end
164
- end
165
-
166
- def column_names #:nodoc:
167
- @col_names ||= cell_matrix[0].map { |cell| cell.value }
168
- end
169
-
170
- def rows
171
- hashes.map do |hash|
172
- hash.values_at *headers
173
- end
174
- end
175
-
176
- def each_cells_row(&proc) #:nodoc:
177
- cells_rows.each(&proc)
178
- end
179
-
180
- def accept(visitor) #:nodoc:
181
- return if Cucumber.wants_to_quit
182
- cells_rows.each do |row|
183
- visitor.visit_table_row(row)
184
- end
185
- nil
186
- end
187
-
188
- # Matches +pattern+ against the header row of the table.
189
- # This is used especially for argument transforms.
190
- #
191
- # Example:
192
- # | column_1_name | column_2_name |
193
- # | x | y |
194
- #
195
- # table.match(/table:column_1_name,column_2_name/) #=> non-nil
196
- #
197
- # Note: must use 'table:' prefix on match
198
- def match(pattern)
199
- header_to_match = "table:#{headers.join(',')}"
200
- pattern.match(header_to_match)
201
- end
202
-
203
- # For testing only
204
- def to_sexp #:nodoc:
205
- [:table, *cells_rows.map{|row| row.to_sexp}]
206
- end
207
-
208
- # Redefines the table headers. This makes it possible to use
209
- # prettier and more flexible header names in the features. The
210
- # keys of +mappings+ are Strings or regular expressions
211
- # (anything that responds to #=== will work) that may match
212
- # column headings in the table. The values of +mappings+ are
213
- # desired names for the columns.
214
- #
215
- # Example:
216
- #
217
- # | Phone Number | Address |
218
- # | 123456 | xyz |
219
- # | 345678 | abc |
220
- #
221
- # A StepDefinition receiving this table can then map the columns
222
- # with both Regexp and String:
223
- #
224
- # table.map_headers!(/phone( number)?/i => :phone, 'Address' => :address)
225
- # table.hashes
226
- # # => [{:phone => '123456', :address => 'xyz'}, {:phone => '345678', :address => 'abc'}]
227
- #
228
- # You may also pass in a block if you wish to convert all of the headers:
229
- #
230
- # table.map_headers! { |header| header.downcase }
231
- # table.hashes.keys
232
- # # => ['phone number', 'address']
233
- #
234
- # When a block is passed in along with a hash then the mappings in the hash take precendence:
235
- #
236
- # table.map_headers!('Address' => 'ADDRESS') { |header| header.downcase }
237
- # table.hashes.keys
238
- # # => ['phone number', 'ADDRESS']
239
- #
240
- def map_headers!(mappings={}, &block)
241
- # TODO: Remove this method for 2.0
242
- clear_cache!
243
- @header_mappings = mappings
244
- @header_conversion_proc = block
245
- end
246
-
247
- # Returns a new Table where the headers are redefined. See #map_headers!
248
- def map_headers(mappings={}, &block)
249
- self.class.new raw.dup, @conversion_procs.dup, mappings, block
250
- end
251
-
252
- # Change how #hashes converts column values. The +column_name+ argument identifies the column
253
- # and +conversion_proc+ performs the conversion for each cell in that column. If +strict+ is
254
- # true, an error will be raised if the column named +column_name+ is not found. If +strict+
255
- # is false, no error will be raised. Example:
256
- #
257
- # Given /^an expense report for (.*) with the following posts:$/ do |table|
258
- # posts_table.map_column!('amount') { |a| a.to_i }
259
- # posts_table.hashes.each do |post|
260
- # # post['amount'] is a Fixnum, rather than a String
261
- # end
262
- # end
263
- #
264
- def map_column!(column_name, strict=true, &conversion_proc)
265
- # TODO: Remove this method for 2.0
266
- @conversion_procs[column_name.to_s] = { :strict => strict, :proc => conversion_proc }
267
- self
268
- end
269
-
270
- # Returns a new Table with an additional column mapping. See #map_column!
271
- def map_column(column_name, strict=true, &conversion_proc)
272
- conversion_procs = @conversion_procs.dup
273
- conversion_procs[column_name.to_s] = { :strict => strict, :proc => conversion_proc }
274
- self.class.new(raw.dup, conversion_procs, @header_mappings.dup, @header_conversion_proc)
275
- end
276
-
277
- # Compares +other_table+ to self. If +other_table+ contains columns
278
- # and/or rows that are not in self, new columns/rows are added at the
279
- # relevant positions, marking the cells in those rows/columns as
280
- # <tt>surplus</tt>. Likewise, if +other_table+ lacks columns and/or
281
- # rows that are present in self, these are marked as <tt>missing</tt>.
282
- #
283
- # <tt>surplus</tt> and <tt>missing</tt> cells are recognised by formatters
284
- # and displayed so that it's easy to read the differences.
285
- #
286
- # Cells that are different, but <em>look</em> identical (for example the
287
- # boolean true and the string "true") are converted to their Object#inspect
288
- # representation and preceded with (i) - to make it easier to identify
289
- # where the difference actually is.
290
- #
291
- # Since all tables that are passed to StepDefinitions always have String
292
- # objects in their cells, you may want to use #map_column! before calling
293
- # #diff!. You can use #map_column! on either of the tables.
294
- #
295
- # A Different error is raised if there are missing rows or columns, or
296
- # surplus rows. An error is <em>not</em> raised for surplus columns. An
297
- # error is <em>not</em> raised for misplaced (out of sequence) columns.
298
- # Whether to raise or not raise can be changed by setting values in
299
- # +options+ to true or false:
300
- #
301
- # * <tt>missing_row</tt> : Raise on missing rows (defaults to true)
302
- # * <tt>surplus_row</tt> : Raise on surplus rows (defaults to true)
303
- # * <tt>missing_col</tt> : Raise on missing columns (defaults to true)
304
- # * <tt>surplus_col</tt> : Raise on surplus columns (defaults to false)
305
- # * <tt>misplaced_col</tt> : Raise on misplaced columns (defaults to false)
306
- #
307
- # The +other_table+ argument can be another Table, an Array of Array or
308
- # an Array of Hash (similar to the structure returned by #hashes).
309
- #
310
- # Calling this method is particularly useful in <tt>Then</tt> steps that take
311
- # a Table argument, if you want to compare that table to some actual values.
312
- #
313
- def diff!(other_table, options={})
314
- options = {
315
- :missing_row => true,
316
- :surplus_row => true,
317
- :missing_col => true,
318
- :surplus_col => false,
319
- :misplaced_col => false
320
- }.merge(options)
321
-
322
- other_table = ensure_table(other_table)
323
- other_table.convert_headers!
324
- other_table.convert_columns!
325
- ensure_green!
326
-
327
- convert_headers!
328
- convert_columns!
329
-
330
- original_width = cell_matrix[0].length
331
- other_table_cell_matrix = pad!(other_table.cell_matrix)
332
- padded_width = cell_matrix[0].length
333
-
334
- missing_col = cell_matrix[0].detect{|cell| cell.status == :undefined}
335
- surplus_col = padded_width > original_width
336
- misplaced_col = cell_matrix[0] != other_table.cell_matrix[0]
337
-
338
- require_diff_lcs
339
- cell_matrix.extend(Diff::LCS)
340
- changes = cell_matrix.diff(other_table_cell_matrix).flatten
341
-
342
- inserted = 0
343
- missing = 0
344
-
345
- row_indices = Array.new(other_table_cell_matrix.length) {|n| n}
346
-
347
- last_change = nil
348
- missing_row_pos = nil
349
- insert_row_pos = nil
350
-
351
- changes.each do |change|
352
- if(change.action == '-')
353
- missing_row_pos = change.position + inserted
354
- cell_matrix[missing_row_pos].each{|cell| cell.status = :undefined}
355
- row_indices.insert(missing_row_pos, nil)
356
- missing += 1
357
- else # '+'
358
- insert_row_pos = change.position + missing
359
- inserted_row = change.element
360
- inserted_row.each{|cell| cell.status = :comment}
361
- cell_matrix.insert(insert_row_pos, inserted_row)
362
- row_indices[insert_row_pos] = nil
363
- inspect_rows(cell_matrix[missing_row_pos], inserted_row) if last_change && last_change.action == '-'
364
- inserted += 1
365
- end
366
- last_change = change
367
- end
368
-
369
- other_table_cell_matrix.each_with_index do |other_row, i|
370
- row_index = row_indices.index(i)
371
- row = cell_matrix[row_index] if row_index
372
- if row
373
- (original_width..padded_width).each do |col_index|
374
- surplus_cell = other_row[col_index]
375
- row[col_index].value = surplus_cell.value if row[col_index]
376
- end
377
- end
378
- end
379
-
380
- clear_cache!
381
- should_raise =
382
- missing_row_pos && options[:missing_row] ||
383
- insert_row_pos && options[:surplus_row] ||
384
- missing_col && options[:missing_col] ||
385
- surplus_col && options[:surplus_col] ||
386
- misplaced_col && options[:misplaced_col]
387
- raise Different.new(self) if should_raise
388
- end
389
-
390
- def to_hash(cells) #:nodoc:
391
- hash = Hash.new do |hash, key|
392
- hash[key.to_s] if key.is_a?(Symbol)
393
- end
394
- column_names.each_with_index do |column_name, column_index|
395
- hash[column_name] = cells.value(column_index)
396
- end
397
- hash
398
- end
399
-
400
- def index(cells) #:nodoc:
401
- cells_rows.index(cells)
402
- end
403
-
404
- def verify_column(column_name) #:nodoc:
405
- raise %{The column named "#{column_name}" does not exist} unless raw[0].include?(column_name)
406
- end
407
-
408
- def verify_table_width(width) #:nodoc:
409
- raise %{The table must have exactly #{width} columns} unless raw[0].size == width
410
- end
411
-
412
- def arguments_replaced(arguments) #:nodoc:
413
- raw_with_replaced_args = raw.map do |row|
414
- row.map do |cell|
415
- cell_with_replaced_args = cell
416
- arguments.each do |name, value|
417
- if cell_with_replaced_args && cell_with_replaced_args.include?(name)
418
- cell_with_replaced_args = value ? cell_with_replaced_args.gsub(name, value) : nil
419
- end
420
- end
421
- cell_with_replaced_args
422
- end
423
- end
424
- Table.new(raw_with_replaced_args)
425
- end
426
-
427
- def has_text?(text) #:nodoc:
428
- raw.flatten.compact.detect{|cell_value| cell_value.index(text)}
429
- end
430
-
431
- def cells_rows #:nodoc:
432
- @rows ||= cell_matrix.map do |cell_row|
433
- @cells_class.new(self, cell_row)
434
- end
435
- end
436
-
437
- def headers #:nodoc:
438
- raw.first
439
- end
440
-
441
- def header_cell(col) #:nodoc:
442
- cells_rows[0][col]
443
- end
444
-
445
- def cell_matrix #:nodoc:
446
- @cell_matrix
447
- end
448
-
449
- def col_width(col) #:nodoc:
450
- columns[col].__send__(:width)
451
- end
452
-
453
- def to_s(options = {}) #:nodoc:
454
- require 'cucumber/formatter/pretty'
455
- options = {:color => true, :indent => 2, :prefixes => TO_S_PREFIXES}.merge(options)
456
- io = StringIO.new
457
-
458
- c = Cucumber::Term::ANSIColor.coloring?
459
- Cucumber::Term::ANSIColor.coloring = options[:color]
460
- formatter = Formatter::Pretty.new(nil, io, options)
461
- formatter.instance_variable_set('@indent', options[:indent])
462
- TreeWalker.new(nil, [formatter]).visit_multiline_arg(self)
463
-
464
- Cucumber::Term::ANSIColor.coloring = c
465
- io.rewind
466
- s = "\n" + io.read + (" " * (options[:indent] - 2))
467
- s
468
- end
469
-
470
- private
471
-
472
- TO_S_PREFIXES = Hash.new(' ')
473
- TO_S_PREFIXES[:comment] = '(+) '
474
- TO_S_PREFIXES[:undefined] = '(-) '
475
-
476
- protected
477
-
478
- def build_hashes
479
- convert_headers!
480
- convert_columns!
481
- cells_rows[1..-1].map do |row|
482
- row.to_hash
483
- end
484
- end
485
-
486
- def inspect_rows(missing_row, inserted_row) #:nodoc:
487
- missing_row.each_with_index do |missing_cell, col|
488
- inserted_cell = inserted_row[col]
489
- if(missing_cell.value != inserted_cell.value && (missing_cell.value.to_s == inserted_cell.value.to_s))
490
- missing_cell.inspect!
491
- inserted_cell.inspect!
492
- end
493
- end
494
- end
495
-
496
- def create_cell_matrix(raw) #:nodoc:
497
- @cell_matrix = raw.map do |raw_row|
498
- line = raw_row.line rescue -1
499
- raw_row.map do |raw_cell|
500
- new_cell(raw_cell, line)
501
- end
502
- end
503
- end
504
-
505
- def convert_columns! #:nodoc:
506
- @conversion_procs.each do |column_name, conversion_proc|
507
- verify_column(column_name) if conversion_proc[:strict]
508
- end
509
-
510
- cell_matrix.transpose.each do |col|
511
- column_name = col[0].value
512
- conversion_proc = @conversion_procs[column_name][:proc]
513
- col[1..-1].each do |cell|
514
- cell.value = conversion_proc.call(cell.value)
515
- end
516
- end
517
- end
518
-
519
- def convert_headers! #:nodoc:
520
- header_cells = cell_matrix[0]
521
-
522
- if @header_conversion_proc
523
- header_values = header_cells.map { |cell| cell.value } - @header_mappings.keys
524
- @header_mappings = @header_mappings.merge(Hash[*header_values.zip(header_values.map(&@header_conversion_proc)).flatten])
525
- end
526
-
527
- @header_mappings.each_pair do |pre, post|
528
- mapped_cells = header_cells.select { |cell| pre === cell.value }
529
- raise "No headers matched #{pre.inspect}" if mapped_cells.empty?
530
- raise "#{mapped_cells.length} headers matched #{pre.inspect}: #{mapped_cells.map { |c| c.value }.inspect}" if mapped_cells.length > 1
531
- mapped_cells[0].value = post
532
- if @conversion_procs.has_key?(pre)
533
- @conversion_procs[post] = @conversion_procs.delete(pre)
534
- end
535
- end
536
- end
537
-
538
- def require_diff_lcs #:nodoc:
539
- begin
540
- require 'diff/lcs'
541
- rescue LoadError => e
542
- e.message << "\n Please gem install diff-lcs\n"
543
- raise e
544
- end
545
- end
546
-
547
- def clear_cache! #:nodoc:
548
- @hashes = @rows_hash = @col_names = @rows = @columns = nil
549
- end
550
-
551
- def columns #:nodoc:
552
- @columns ||= cell_matrix.transpose.map do |cell_row|
553
- @cells_class.new(self, cell_row)
554
- end
555
- end
556
-
557
- def new_cell(raw_cell, line) #:nodoc:
558
- @cell_class.new(raw_cell, self, line)
559
- end
560
-
561
- # Pads our own cell_matrix and returns a cell matrix of same
562
- # column width that can be used for diffing
563
- def pad!(other_cell_matrix) #:nodoc:
564
- clear_cache!
565
- cols = cell_matrix.transpose
566
- unmapped_cols = other_cell_matrix.transpose
567
-
568
- mapped_cols = []
569
-
570
- cols.each_with_index do |col, col_index|
571
- header = col[0]
572
- candidate_cols, unmapped_cols = unmapped_cols.partition do |other_col|
573
- other_col[0] == header
574
- end
575
- raise "More than one column has the header #{header}" if candidate_cols.size > 2
576
-
577
- other_padded_col = if candidate_cols.size == 1
578
- # Found a matching column
579
- candidate_cols[0]
580
- else
581
- mark_as_missing(cols[col_index])
582
- (0...other_cell_matrix.length).map do |row|
583
- val = row == 0 ? header.value : nil
584
- SurplusCell.new(val, self, -1)
585
- end
586
- end
587
- mapped_cols.insert(col_index, other_padded_col)
588
- end
589
-
590
- unmapped_cols.each_with_index do |col, col_index|
591
- empty_col = (0...cell_matrix.length).map do |row|
592
- SurplusCell.new(nil, self, -1)
593
- end
594
- cols << empty_col
595
- end
596
-
597
- @cell_matrix = cols.transpose
598
- (mapped_cols + unmapped_cols).transpose
599
- end
600
-
601
- def ensure_table(table_or_array) #:nodoc:
602
- return table_or_array if Table === table_or_array
603
- Table.new(table_or_array)
604
- end
605
-
606
- def ensure_array_of_array(array)
607
- Hash === array[0] ? hashes_to_array(array) : array
608
- end
609
-
610
- def hashes_to_array(hashes) #:nodoc:
611
- header = hashes[0].keys.sort
612
- [header] + hashes.map{|hash| header.map{|key| hash[key]}}
613
- end
614
-
615
- def ensure_green! #:nodoc:
616
- each_cell{|cell| cell.status = :passed}
617
- end
618
-
619
- def each_cell(&proc) #:nodoc:
620
- cell_matrix.each{|row| row.each(&proc)}
621
- end
622
-
623
- def mark_as_missing(col) #:nodoc:
624
- col.each do |cell|
625
- cell.status = :undefined
626
- end
627
- end
628
-
629
- # Represents a row of cells or columns of cells
630
- class Cells #:nodoc:
631
- include Enumerable
632
- include Gherkin::Formatter::Escaping
633
-
634
- attr_reader :exception
635
-
636
- def initialize(table, cells)
637
- @table, @cells = table, cells
638
- end
639
-
640
- def accept(visitor)
641
- return if Cucumber.wants_to_quit
642
- each do |cell|
643
- visitor.visit_table_cell(cell)
644
- end
645
- nil
646
- end
647
-
648
- # For testing only
649
- def to_sexp #:nodoc:
650
- [:row, line, *@cells.map{|cell| cell.to_sexp}]
651
- end
652
-
653
- def to_hash #:nodoc:
654
- @to_hash ||= @table.to_hash(self)
655
- end
656
-
657
- def value(n) #:nodoc:
658
- self[n].value
659
- end
660
-
661
- def [](n)
662
- @cells[n]
663
- end
664
-
665
- def line
666
- @cells[0].line
667
- end
668
-
669
- def dom_id
670
- "row_#{line}"
671
- end
672
-
673
- private
674
-
675
- def index
676
- @table.index(self)
677
- end
678
-
679
- def width
680
- map{|cell| cell.value ? escape_cell(cell.value.to_s).unpack('U*').length : 0}.max
681
- end
682
-
683
- def each(&proc)
684
- @cells.each(&proc)
685
- end
686
- end
687
-
688
- class Cell #:nodoc:
689
- attr_reader :line, :table
690
- attr_accessor :status, :value
691
-
692
- def initialize(value, table, line)
693
- @value, @table, @line = value, table, line
694
- end
695
-
696
- def accept(visitor)
697
- return if Cucumber.wants_to_quit
698
- visitor.visit_table_cell_value(value, status)
699
- end
700
-
701
- def inspect!
702
- @value = "(i) #{value.inspect}"
703
- end
704
-
705
- def ==(o)
706
- SurplusCell === o || value == o.value
707
- end
708
-
709
- def eql?(o)
710
- self == o
711
- end
712
-
713
- def hash
714
- 0
715
- end
716
-
717
- # For testing only
718
- def to_sexp #:nodoc:
719
- [:cell, @value]
720
- end
721
- end
722
-
723
- class SurplusCell < Cell #:nodoc:
724
- def status
725
- :comment
726
- end
727
-
728
- def ==(o)
729
- true
730
- end
731
-
732
- def hash
733
- 0
734
- end
735
- end
736
- end
737
- end
738
- end