cucumber 2.99.0 → 3.0.0

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 (395) hide show
  1. checksums.yaml +4 -4
  2. data/.cucumberproignore +6 -0
  3. data/.gitattributes +32 -0
  4. data/.github/ISSUE_TEMPLATE.md +1 -1
  5. data/.github/PULL_REQUEST_TEMPLATE.md +1 -0
  6. data/.rubocop.yml +13 -0
  7. data/.rubocop_todo.yml +991 -0
  8. data/.travis.yml +56 -10
  9. data/{History.md → CHANGELOG.md} +166 -32
  10. data/CONTRIBUTING.md +21 -1
  11. data/Gemfile +18 -5
  12. data/README.md +13 -4
  13. data/Rakefile +12 -2
  14. data/appveyor.yml +27 -0
  15. data/bin/cucumber +2 -1
  16. data/cucumber.gemspec +15 -10
  17. data/cucumber.yml +10 -11
  18. data/examples/i18n/Rakefile +1 -1
  19. data/examples/i18n/ar/features/step_definitions/calculator_steps.rb +8 -3
  20. data/examples/i18n/ar/lib/calculator.rb +2 -2
  21. data/examples/i18n/bg/features/step_definitions/calculator_steps.rb +6 -6
  22. data/examples/i18n/bg/features/support/env.rb +6 -1
  23. data/examples/i18n/bg/lib/calculator.rb +2 -1
  24. data/examples/i18n/ca/features/step_definitions/calculator_steps.rb +10 -5
  25. data/examples/i18n/ca/lib/calculadora.rb +2 -2
  26. data/examples/i18n/cs/features/step_definitions/calculator_steps.rb +10 -5
  27. data/examples/i18n/cs/lib/calculator.rb +3 -3
  28. data/examples/i18n/da/features/step_definitions/lommeregner_steps.rb +10 -5
  29. data/examples/i18n/da/lib/lommeregner.rb +2 -2
  30. data/examples/i18n/de/features/step_definitions/calculator_steps.rb +10 -5
  31. data/examples/i18n/de/lib/calculator.rb +2 -2
  32. data/examples/i18n/el/features/step_definitions/calculator_steps.rb +10 -5
  33. data/examples/i18n/el/lib/calculator.rb +2 -2
  34. data/examples/i18n/en/features/step_definitions/calculator_steps.rb +9 -4
  35. data/examples/i18n/en/lib/calculator.rb +2 -2
  36. data/examples/i18n/en-lol/features/step_definitions/cucumbrz_steps.rb +4 -4
  37. data/examples/i18n/en-lol/features/support/env.rb +6 -2
  38. data/examples/i18n/en-lol/lib/basket.rb +2 -2
  39. data/examples/i18n/en-lol/lib/belly.rb +2 -2
  40. data/examples/i18n/eo/features/step_definitions/calculator_steps.rb +9 -4
  41. data/examples/i18n/eo/lib/calculator.rb +2 -2
  42. data/examples/i18n/es/features/step_definitions/calculador_steps.rb +10 -5
  43. data/examples/i18n/es/lib/calculador.rb +2 -2
  44. data/examples/i18n/et/features/step_definitions/kalkulaator_steps.rb +10 -5
  45. data/examples/i18n/et/lib/kalkulaator.rb +3 -3
  46. data/examples/i18n/fi/features/step_definitions/laskin_steps.rb +9 -4
  47. data/examples/i18n/fi/lib/laskin.rb +1 -1
  48. data/examples/i18n/fr/features/step_definitions/calculatrice_steps.rb +8 -8
  49. data/examples/i18n/fr/features/support/env.rb +7 -2
  50. data/examples/i18n/fr/lib/calculatrice.rb +2 -2
  51. data/examples/i18n/he/features/step_definitions/calculator_steps.rb +10 -5
  52. data/examples/i18n/he/lib/calculator.rb +1 -1
  53. data/examples/i18n/hi/features/step_definitions/calculator_steps.rb +9 -4
  54. data/examples/i18n/hi/lib/calculator.rb +1 -1
  55. data/examples/i18n/ht/features/step_definitions/kalkilatris_steps.rb +9 -5
  56. data/examples/i18n/ht/lib/kalkilatris.rb +2 -2
  57. data/examples/i18n/hu/features/step_definitions/calculator_steps.rb +10 -5
  58. data/examples/i18n/hu/lib/calculator.rb +1 -1
  59. data/examples/i18n/id/features/step_definitions/calculator_steps.rb +10 -5
  60. data/examples/i18n/id/lib/calculator.rb +2 -2
  61. data/examples/i18n/it/features/step_definitions/calcolatrice_steps.rb +10 -5
  62. data/examples/i18n/it/lib/calcolatrice.rb +3 -3
  63. data/examples/i18n/ja/features/step_definitions/calculator_steps.rb +3 -3
  64. data/examples/i18n/ja/features/support/env.rb +7 -2
  65. data/examples/i18n/ja/lib/calculator.rb +2 -2
  66. data/examples/i18n/ko/features/step_definitions/calculator_steps.rb +10 -5
  67. data/examples/i18n/ko/lib/calculator.rb +2 -2
  68. data/examples/i18n/lt/features/step_definitions/calculator_steps.rb +10 -5
  69. data/examples/i18n/lt/lib/calculator.rb +2 -2
  70. data/examples/i18n/lv/features/step_definitions/calculator_steps.rb +10 -5
  71. data/examples/i18n/lv/lib/calculator.rb +2 -2
  72. data/examples/i18n/no/features/step_definitions/kalkulator_steps.rb +3 -3
  73. data/examples/i18n/no/features/support/env.rb +7 -2
  74. data/examples/i18n/no/lib/kalkulator.rb +2 -2
  75. data/examples/i18n/pl/features/step_definitions/calculator_steps.rb +10 -5
  76. data/examples/i18n/pl/features/support/env.rb +6 -1
  77. data/examples/i18n/pl/lib/calculator.rb +2 -2
  78. data/examples/i18n/pt/features/step_definitions/calculadora_steps.rb +3 -3
  79. data/examples/i18n/pt/features/support/env.rb +7 -2
  80. data/examples/i18n/pt/lib/calculadora.rb +1 -1
  81. data/examples/i18n/ro/features/step_definitions/calculator_steps.rb +11 -6
  82. data/examples/i18n/ro/lib/calculator.rb +1 -1
  83. data/examples/i18n/ru/features/step_definitions/calculator_steps.rb +5 -5
  84. data/examples/i18n/ru/features/support/env.rb +6 -1
  85. data/examples/i18n/ru/lib/calculator.rb +2 -1
  86. data/examples/i18n/sk/features/step_definitions/calculator_steps.rb +10 -5
  87. data/examples/i18n/sk/lib/calculator.rb +2 -2
  88. data/examples/i18n/sr-Cyrl/features/step_definitions/calculator_steps.rb +3 -3
  89. data/examples/i18n/sr-Cyrl/features/support/env.rb +7 -2
  90. data/examples/i18n/sr-Cyrl/lib/calculator.rb +2 -2
  91. data/examples/i18n/sr-Latn/features/step_definitions/calculator_steps.rb +10 -5
  92. data/examples/i18n/sr-Latn/lib/calculator.rb +2 -2
  93. data/examples/i18n/sv/features/step_definitions/kalkulator_steps.rb +9 -4
  94. data/examples/i18n/sv/lib/kalkulator.rb +2 -2
  95. data/examples/i18n/tr/features/step_definitions/hesap_makinesi_adimlari.rb +10 -5
  96. data/examples/i18n/tr/lib/hesap_makinesi.rb +2 -2
  97. data/examples/i18n/uk/features/step_definitions/calculator_steps.rb +4 -4
  98. data/examples/i18n/uk/features/support/env.rb +6 -1
  99. data/examples/i18n/uk/lib/calculator.rb +2 -1
  100. data/examples/i18n/uz/features/step_definitions/calculator_steps.rb +4 -4
  101. data/examples/i18n/uz/features/support/env.rb +6 -1
  102. data/examples/i18n/uz/lib/calculator.rb +2 -1
  103. data/examples/i18n/zh-CN/features/step_definitions/calculator_steps.rb +11 -6
  104. data/examples/i18n/zh-CN/lib/calculator.rb +2 -2
  105. data/examples/i18n/zh-TW/features/step_definitions/calculator_steps.rb +10 -5
  106. data/examples/i18n/zh-TW/lib/calculator.rb +2 -2
  107. data/examples/rspec_doubles/features/step_definitions/calvin_steps.rb +3 -3
  108. data/examples/sinatra/features/step_definitions/add_steps.rb +4 -4
  109. data/examples/sinatra/features/support/env.rb +6 -1
  110. data/examples/tcl/features/step_definitions/fib_steps.rb +2 -2
  111. data/examples/tcl/features/support/env.rb +2 -1
  112. data/examples/test_unit/features/step_definitions/test_unit_steps.rb +4 -4
  113. data/examples/watir/features/step_definitions/search_steps.rb +6 -5
  114. data/examples/watir/features/support/env.rb +5 -1
  115. data/examples/watir/features/support/screenshots.rb +5 -5
  116. data/features/docs/api/list_step_defs_as_json.feature +21 -7
  117. data/features/docs/api/listen_for_events.feature +9 -8
  118. data/features/docs/api/run_cli_main_with_existing_runtime.feature +1 -0
  119. data/features/docs/cli/dry_run.feature +3 -0
  120. data/features/docs/cli/execute_with_tag_filter.feature +8 -6
  121. data/features/docs/cli/fail_fast.feature +2 -0
  122. data/features/docs/cli/help.feature +8 -0
  123. data/features/docs/{gherkin/language_help.feature → cli/i18n.feature} +6 -6
  124. data/features/docs/cli/randomize.feature +2 -2
  125. data/features/docs/cli/retry_failing_tests.feature +75 -15
  126. data/features/docs/cli/run_scenarios_matching_name.feature +1 -0
  127. data/features/docs/cli/specifying_multiple_formatters.feature +3 -0
  128. data/features/docs/cli/strict_mode.feature +6 -0
  129. data/features/docs/defining_steps/ambiguous_steps.feature +89 -0
  130. data/features/docs/defining_steps/nested_steps.feature +5 -1
  131. data/features/docs/defining_steps/nested_steps_i18n.feature +3 -0
  132. data/features/docs/defining_steps/nested_steps_with_second_arg.feature +2 -0
  133. data/features/docs/defining_steps/printing_messages.feature +1 -2
  134. data/features/docs/defining_steps/skip_scenario.feature +1 -34
  135. data/features/docs/defining_steps/snippets.feature +18 -18
  136. data/features/docs/events/gherkin_source_read_event.feature +43 -0
  137. data/features/docs/events/step_activated_event.feature +36 -0
  138. data/features/docs/events/step_definition_registered_event.feature +29 -0
  139. data/features/docs/events/test_case_finished_event.feature +35 -0
  140. data/features/docs/events/test_case_started_event.feature +54 -0
  141. data/features/docs/events/test_run_finished_event.feature +40 -0
  142. data/features/docs/events/test_run_started_event.feature +41 -0
  143. data/features/docs/events/test_step_finished_event.feature +47 -0
  144. data/features/docs/events/test_step_started_event.feature +43 -0
  145. data/features/docs/exception_in_after_hook.feature +3 -2
  146. data/features/docs/exception_in_after_step_hook.feature +2 -0
  147. data/features/docs/exception_in_around_hook.feature +2 -0
  148. data/features/docs/exception_in_before_hook.feature +3 -1
  149. data/features/docs/extending_cucumber/custom_formatter.feature +12 -48
  150. data/features/docs/formatters/json_formatter.feature +4 -4
  151. data/features/docs/formatters/junit_formatter.feature +7 -6
  152. data/features/docs/formatters/pretty_formatter.feature +1 -0
  153. data/features/docs/formatters/progress_formatter.feature +1 -0
  154. data/features/docs/formatters/rerun_formatter.feature +2 -0
  155. data/features/docs/formatters/summary_formatter.feature +35 -0
  156. data/features/docs/formatters/usage_formatter.feature +3 -0
  157. data/features/docs/getting_started.feature +2 -1
  158. data/features/docs/gherkin/background.feature +5 -5
  159. data/features/docs/gherkin/doc_strings.feature +2 -0
  160. data/features/docs/gherkin/expand_option_for_outlines.feature +1 -0
  161. data/features/docs/gherkin/outlines.feature +6 -4
  162. data/features/docs/gherkin/unicode_table.feature +2 -1
  163. data/features/docs/gherkin/using_descriptions.feature +1 -0
  164. data/features/docs/gherkin/using_star_notation.feature +1 -1
  165. data/features/docs/post_configuration_hook.feature +1 -17
  166. data/features/docs/rake_task.feature +5 -0
  167. data/features/docs/raketask.feature +3 -1
  168. data/features/docs/work_in_progress.feature +5 -2
  169. data/features/docs/writing_support_code/after_step_hooks.feature +3 -1
  170. data/features/docs/writing_support_code/around_hooks.feature +6 -0
  171. data/features/docs/writing_support_code/before_hook.feature +1 -0
  172. data/features/docs/writing_support_code/hook_order.feature +3 -1
  173. data/features/docs/writing_support_code/parameter_types.feature +53 -0
  174. data/features/docs/writing_support_code/tagged_hooks.feature +1 -1
  175. data/features/docs/writing_support_code/world.feature +129 -0
  176. data/features/lib/step_definitions/aruba_steps.rb +5 -10
  177. data/features/lib/step_definitions/cli_steps.rb +4 -0
  178. data/features/lib/step_definitions/cucumber_steps.rb +9 -12
  179. data/features/lib/step_definitions/iso-8859-1_steps.rb +9 -5
  180. data/features/lib/step_definitions/json_steps.rb +2 -1
  181. data/features/lib/step_definitions/junit_steps.rb +2 -1
  182. data/features/lib/step_definitions/language_steps.rb +3 -2
  183. data/features/lib/step_definitions/profile_steps.rb +7 -6
  184. data/features/lib/step_definitions/retry_steps.rb +33 -13
  185. data/features/lib/step_definitions/ruby_steps.rb +2 -1
  186. data/features/lib/support/env.rb +3 -2
  187. data/features/lib/support/fake_wire_server.rb +17 -3
  188. data/features/lib/support/feature_factory.rb +2 -1
  189. data/features/lib/support/normalise_output.rb +14 -12
  190. data/features/lib/support/parameter_types.rb +5 -0
  191. data/gem_tasks/contributors.rake +10 -6
  192. data/gem_tasks/cov.rake +1 -0
  193. data/gem_tasks/downloads.rb +1 -0
  194. data/gem_tasks/environment.rake +2 -5
  195. data/gem_tasks/examples.rake +3 -2
  196. data/gem_tasks/fix_cr_lf.rake +19 -7
  197. data/gem_tasks/flog.rake +4 -3
  198. data/gem_tasks/rspec.rake +2 -1
  199. data/gem_tasks/sass.rake +2 -1
  200. data/lib/autotest/cucumber.rb +1 -0
  201. data/lib/autotest/cucumber_mixin.rb +17 -16
  202. data/lib/autotest/cucumber_rails.rb +1 -0
  203. data/lib/autotest/cucumber_rails_rspec.rb +1 -0
  204. data/lib/autotest/cucumber_rails_rspec2.rb +1 -0
  205. data/lib/autotest/cucumber_rspec.rb +1 -0
  206. data/lib/autotest/cucumber_rspec2.rb +1 -0
  207. data/lib/autotest/discover.rb +3 -2
  208. data/lib/cucumber/cli/configuration.rb +12 -21
  209. data/lib/cucumber/cli/main.rb +8 -7
  210. data/lib/cucumber/cli/options.rb +341 -217
  211. data/lib/cucumber/cli/profile_loader.rb +26 -21
  212. data/lib/cucumber/cli/rerun_file.rb +1 -0
  213. data/lib/cucumber/configuration.rb +54 -37
  214. data/lib/cucumber/constantize.rb +2 -1
  215. data/lib/cucumber/core_ext/string.rb +2 -1
  216. data/lib/cucumber/deprecate.rb +4 -3
  217. data/lib/cucumber/encoding.rb +1 -0
  218. data/lib/cucumber/errors.rb +3 -1
  219. data/lib/cucumber/events/gherkin_source_read.rb +17 -0
  220. data/lib/cucumber/events/{step_match.rb → step_activated.rb} +5 -2
  221. data/lib/cucumber/events/step_definition_registered.rb +24 -0
  222. data/lib/cucumber/events/test_case_finished.rb +18 -0
  223. data/lib/cucumber/events/test_case_started.rb +15 -0
  224. data/lib/cucumber/events/test_run_finished.rb +12 -0
  225. data/lib/cucumber/events/test_run_started.rb +16 -0
  226. data/lib/cucumber/events/test_step_finished.rb +20 -0
  227. data/lib/cucumber/events/test_step_started.rb +17 -0
  228. data/lib/cucumber/events.rb +23 -3
  229. data/lib/cucumber/file_specs.rb +1 -0
  230. data/lib/cucumber/filters/activate_steps.rb +8 -3
  231. data/lib/cucumber/filters/apply_after_hooks.rb +1 -0
  232. data/lib/cucumber/filters/apply_after_step_hooks.rb +1 -0
  233. data/lib/cucumber/filters/apply_around_hooks.rb +1 -0
  234. data/lib/cucumber/filters/apply_before_hooks.rb +1 -0
  235. data/lib/cucumber/filters/broadcast_test_run_started_event.rb +27 -0
  236. data/lib/cucumber/filters/gated_receiver.rb +1 -0
  237. data/lib/cucumber/filters/prepare_world.rb +1 -0
  238. data/lib/cucumber/filters/quit.rb +1 -0
  239. data/lib/cucumber/filters/randomizer.rb +1 -0
  240. data/lib/cucumber/filters/retry.rb +4 -4
  241. data/lib/cucumber/filters/tag_limits/test_case_index.rb +1 -0
  242. data/lib/cucumber/filters/tag_limits/verifier.rb +2 -1
  243. data/lib/cucumber/filters/tag_limits.rb +4 -3
  244. data/lib/cucumber/filters.rb +3 -0
  245. data/lib/cucumber/formatter/ansicolor.rb +9 -11
  246. data/lib/cucumber/formatter/backtrace_filter.rb +21 -8
  247. data/lib/cucumber/formatter/console.rb +72 -66
  248. data/lib/cucumber/formatter/console_counts.rb +44 -0
  249. data/lib/cucumber/formatter/console_issues.rb +58 -0
  250. data/lib/cucumber/formatter/duration.rb +2 -1
  251. data/lib/cucumber/formatter/duration_extractor.rb +1 -0
  252. data/lib/cucumber/formatter/fail_fast.rb +4 -2
  253. data/lib/cucumber/formatter/fanout.rb +1 -0
  254. data/lib/cucumber/formatter/hook_query_visitor.rb +1 -0
  255. data/lib/cucumber/formatter/html.rb +175 -249
  256. data/lib/cucumber/formatter/html_builder.rb +120 -0
  257. data/lib/cucumber/formatter/ignore_missing_messages.rb +1 -0
  258. data/lib/cucumber/formatter/inline-js.js +30 -0
  259. data/lib/cucumber/formatter/interceptor.rb +3 -2
  260. data/lib/cucumber/formatter/io.rb +2 -1
  261. data/lib/cucumber/formatter/json.rb +33 -30
  262. data/lib/cucumber/formatter/json_pretty.rb +1 -0
  263. data/lib/cucumber/formatter/junit.rb +26 -24
  264. data/lib/cucumber/formatter/legacy_api/adapter.rb +81 -69
  265. data/lib/cucumber/formatter/legacy_api/ast.rb +27 -22
  266. data/lib/cucumber/formatter/legacy_api/results.rb +7 -8
  267. data/lib/cucumber/formatter/legacy_api/runtime_facade.rb +1 -0
  268. data/lib/cucumber/formatter/pretty.rb +24 -18
  269. data/lib/cucumber/formatter/progress.rb +55 -13
  270. data/lib/cucumber/formatter/rerun.rb +15 -18
  271. data/lib/cucumber/formatter/stepdefs.rb +1 -0
  272. data/lib/cucumber/formatter/steps.rb +2 -1
  273. data/lib/cucumber/formatter/summary.rb +43 -20
  274. data/lib/cucumber/formatter/unicode.rb +2 -1
  275. data/lib/cucumber/formatter/usage.rb +33 -28
  276. data/lib/cucumber/gherkin/data_table_parser.rb +1 -0
  277. data/lib/cucumber/gherkin/formatter/ansi_escapes.rb +2 -1
  278. data/lib/cucumber/gherkin/formatter/escaping.rb +2 -1
  279. data/lib/cucumber/gherkin/i18n.rb +1 -0
  280. data/lib/cucumber/gherkin/steps_parser.rb +1 -0
  281. data/lib/cucumber/{rb_support/rb_dsl.rb → glue/dsl.rb} +41 -30
  282. data/lib/cucumber/glue/hook.rb +43 -0
  283. data/lib/cucumber/glue/invoke_in_world.rb +70 -0
  284. data/lib/cucumber/glue/proto_world.rb +220 -0
  285. data/lib/cucumber/{rb_support/rb_language.rb → glue/registry_and_more.rb} +60 -90
  286. data/lib/cucumber/{rb_support → glue}/snippet.rb +64 -26
  287. data/lib/cucumber/glue/step_definition.rb +143 -0
  288. data/lib/cucumber/glue/world_factory.rb +23 -0
  289. data/lib/cucumber/hooks.rb +9 -8
  290. data/lib/cucumber/load_path.rb +1 -0
  291. data/lib/cucumber/multiline_argument/data_table/diff_matrices.rb +158 -0
  292. data/lib/cucumber/multiline_argument/data_table.rb +47 -181
  293. data/lib/cucumber/multiline_argument/doc_string.rb +1 -0
  294. data/lib/cucumber/multiline_argument.rb +6 -15
  295. data/lib/cucumber/platform.rb +4 -5
  296. data/lib/cucumber/project_initializer.rb +3 -2
  297. data/lib/cucumber/rake/task.rb +19 -14
  298. data/lib/cucumber/rspec/disable_option_parser.rb +2 -1
  299. data/lib/cucumber/rspec/doubles.rb +2 -1
  300. data/lib/cucumber/running_test_case.rb +3 -27
  301. data/lib/cucumber/runtime/after_hooks.rb +2 -1
  302. data/lib/cucumber/runtime/before_hooks.rb +1 -0
  303. data/lib/cucumber/runtime/for_programming_languages.rb +2 -36
  304. data/lib/cucumber/runtime/step_hooks.rb +1 -0
  305. data/lib/cucumber/runtime/support_code.rb +21 -16
  306. data/lib/cucumber/runtime/user_interface.rb +10 -16
  307. data/lib/cucumber/runtime.rb +49 -32
  308. data/lib/cucumber/step_argument.rb +1 -2
  309. data/lib/cucumber/step_definition_light.rb +2 -0
  310. data/lib/cucumber/step_definitions.rb +1 -0
  311. data/lib/cucumber/step_match.rb +30 -15
  312. data/lib/cucumber/step_match_search.rb +3 -3
  313. data/lib/cucumber/term/ansicolor.rb +2 -1
  314. data/lib/cucumber/unit.rb +1 -0
  315. data/lib/cucumber/version +1 -1
  316. data/lib/cucumber.rb +1 -13
  317. data/lib/simplecov_setup.rb +2 -1
  318. data/scripts/invite-collaborator +40 -0
  319. data/scripts/update-changelog +86 -0
  320. data/spec/cucumber/cli/configuration_spec.rb +109 -98
  321. data/spec/cucumber/cli/main_spec.rb +8 -7
  322. data/spec/cucumber/cli/options_spec.rb +114 -79
  323. data/spec/cucumber/cli/profile_loader_spec.rb +25 -5
  324. data/spec/cucumber/cli/rerun_spec.rb +21 -20
  325. data/spec/cucumber/configuration_spec.rb +48 -47
  326. data/spec/cucumber/constantize_spec.rb +3 -2
  327. data/spec/cucumber/events_spec.rb +9 -0
  328. data/spec/cucumber/file_specs_spec.rb +26 -25
  329. data/spec/cucumber/filters/activate_steps_spec.rb +25 -22
  330. data/spec/cucumber/filters/gated_receiver_spec.rb +7 -6
  331. data/spec/cucumber/filters/retry_spec.rb +42 -23
  332. data/spec/cucumber/filters/tag_limits/test_case_index_spec.rb +12 -11
  333. data/spec/cucumber/filters/tag_limits/verifier_spec.rb +15 -14
  334. data/spec/cucumber/filters/tag_limits_spec.rb +9 -8
  335. data/spec/cucumber/formatter/ansicolor_spec.rb +10 -9
  336. data/spec/cucumber/formatter/backtrace_filter_spec.rb +32 -0
  337. data/spec/cucumber/formatter/console_counts_spec.rb +14 -0
  338. data/spec/cucumber/formatter/duration_spec.rb +4 -3
  339. data/spec/cucumber/formatter/fail_fast_spec.rb +27 -27
  340. data/spec/cucumber/formatter/html_spec.rb +65 -60
  341. data/spec/cucumber/formatter/interceptor_spec.rb +1 -0
  342. data/spec/cucumber/formatter/json_spec.rb +71 -97
  343. data/spec/cucumber/formatter/junit_spec.rb +46 -47
  344. data/spec/cucumber/formatter/legacy_api/adapter_spec.rb +134 -141
  345. data/spec/cucumber/formatter/pretty_spec.rb +105 -117
  346. data/spec/cucumber/formatter/progress_spec.rb +22 -21
  347. data/spec/cucumber/formatter/rerun_spec.rb +70 -64
  348. data/spec/cucumber/formatter/spec_helper.rb +14 -12
  349. data/spec/cucumber/{rb_support/rb_world_spec.rb → glue/proto_world_spec.rb} +22 -6
  350. data/spec/cucumber/glue/registry_and_more_spec.rb +213 -0
  351. data/spec/cucumber/{rb_support → glue}/snippet_spec.rb +62 -25
  352. data/spec/cucumber/glue/step_definition_spec.rb +207 -0
  353. data/spec/cucumber/hooks_spec.rb +5 -4
  354. data/spec/cucumber/multiline_argument/data_table_spec.rb +179 -129
  355. data/spec/cucumber/project_initializer_spec.rb +12 -11
  356. data/spec/cucumber/rake/forked_spec.rb +22 -17
  357. data/spec/cucumber/rake/task_spec.rb +21 -20
  358. data/spec/cucumber/running_test_case_spec.rb +36 -35
  359. data/spec/cucumber/runtime/for_programming_languages_spec.rb +2 -30
  360. data/spec/cucumber/runtime/support_code_spec.rb +1 -0
  361. data/spec/cucumber/runtime_spec.rb +3 -2
  362. data/spec/cucumber/step_argument_spec.rb +6 -5
  363. data/spec/cucumber/step_match_search_spec.rb +32 -41
  364. data/spec/cucumber/step_match_spec.rb +34 -33
  365. data/spec/cucumber/world/pending_spec.rb +12 -11
  366. data/spec/spec_helper.rb +1 -0
  367. data/spec/support/standard_step_actions.rb +2 -1
  368. metadata +132 -61
  369. data/features/docs/formatters/debug_formatter.feature +0 -47
  370. data/features/docs/formatters/formatter_step_file_colon_line.feature +0 -44
  371. data/features/docs/writing_support_code/transforms.feature +0 -98
  372. data/features/lib/step_definitions/wire_steps.rb +0 -58
  373. data/gem_tasks/cucumber.rake +0 -25
  374. data/lib/cucumber/ast.rb +0 -13
  375. data/lib/cucumber/core_ext/instance_exec.rb +0 -70
  376. data/lib/cucumber/events/after_test_case.rb +0 -25
  377. data/lib/cucumber/events/after_test_step.rb +0 -30
  378. data/lib/cucumber/events/before_test_case.rb +0 -18
  379. data/lib/cucumber/events/before_test_step.rb +0 -23
  380. data/lib/cucumber/events/bus.rb +0 -86
  381. data/lib/cucumber/events/finished_testing.rb +0 -9
  382. data/lib/cucumber/formatter/debug.rb +0 -35
  383. data/lib/cucumber/formatter/event_bus_report.rb +0 -38
  384. data/lib/cucumber/rb_support/rb_hook.rb +0 -19
  385. data/lib/cucumber/rb_support/rb_step_definition.rb +0 -131
  386. data/lib/cucumber/rb_support/rb_transform.rb +0 -59
  387. data/lib/cucumber/rb_support/rb_world.rb +0 -149
  388. data/spec/cucumber/core_ext/instance_exec_spec.rb +0 -4
  389. data/spec/cucumber/events/bus_spec.rb +0 -94
  390. data/spec/cucumber/formatter/debug_spec.rb +0 -64
  391. data/spec/cucumber/formatter/event_bus_report_spec.rb +0 -88
  392. data/spec/cucumber/rb_support/rb_language_spec.rb +0 -243
  393. data/spec/cucumber/rb_support/rb_step_definition_spec.rb +0 -199
  394. data/spec/cucumber/rb_support/rb_transform_spec.rb +0 -46
  395. data/spec/cucumber_spec.rb +0 -39
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Cucumber
2
- module RbSupport
4
+ module Glue
3
5
  module Snippet
4
6
 
5
7
  ARGUMENT_PATTERNS = ['"([^"]*)"', '(\d+)']
@@ -9,22 +11,27 @@ module Cucumber
9
11
  configuration.snippet_generators << new
10
12
  end
11
13
 
12
- def call(code_keyword, step_name, multiline_arg, snippet_type = :regexp)
14
+ def initialize(cucumber_expression_generator)
15
+ @cucumber_expression_generator = cucumber_expression_generator
16
+ end
17
+
18
+ def call(code_keyword, step_name, multiline_arg, snippet_type)
13
19
  snippet_class = typed_snippet_class(snippet_type)
14
- snippet_class.new(code_keyword, step_name, multiline_arg).to_s
20
+ snippet_class.new(@cucumber_expression_generator, code_keyword, step_name, multiline_arg).to_s
15
21
  end
16
22
 
17
23
  def typed_snippet_class(type)
18
- SNIPPET_TYPES.fetch(type || :regexp)
24
+ SNIPPET_TYPES.fetch(type || :cucumber_expression)
19
25
  end
20
26
  end
21
27
 
22
28
  class BaseSnippet
23
29
 
24
- def initialize(code_keyword, pattern, multiline_argument)
30
+ def initialize(cucumber_expression_generator, code_keyword, step_name, multiline_argument)
25
31
  @number_of_arguments = 0
26
32
  @code_keyword = code_keyword
27
- @pattern = replace_and_count_capturing_groups(pattern)
33
+ @pattern = replace_and_count_capturing_groups(step_name)
34
+ @generated_expressions = cucumber_expression_generator.generate_expressions(step_name)
28
35
  @multiline_argument = MultilineArgumentSnippet.new(multiline_argument)
29
36
  end
30
37
 
@@ -36,13 +43,13 @@ module Cucumber
36
43
  "#{code_keyword}#{typed_pattern}"
37
44
  end
38
45
 
39
- def self.cli_option_string(type)
40
- "%-7s: %-28s e.g. %s" % [type, description, example]
46
+ def self.cli_option_string(type, cucumber_expression_generator)
47
+ format('%-7s: %-28s e.g. %s', type, description, example(cucumber_expression_generator))
41
48
  end
42
49
 
43
50
  private
44
51
 
45
- attr_reader :code_keyword, :pattern, :multiline_argument, :number_of_arguments
52
+ attr_reader :code_keyword, :pattern, :generated_expressions, :multiline_argument, :number_of_arguments
46
53
 
47
54
  def replace_and_count_capturing_groups(pattern)
48
55
  modified_pattern = ::Regexp.escape(pattern).gsub('\ ', ' ').gsub('/', '\/')
@@ -56,33 +63,63 @@ module Cucumber
56
63
  end
57
64
 
58
65
  def do_block
59
- do_block = ""
60
- do_block << "do#{arguments}\n"
66
+ do_block = String.new
67
+ do_block << "do#{parameters}\n"
61
68
  multiline_argument.append_comment_to(do_block)
62
69
  do_block << " pending # Write code here that turns the phrase above into concrete actions\n"
63
- do_block << "end"
70
+ do_block << 'end'
64
71
  do_block
65
72
  end
66
73
 
67
- def arguments
74
+ def parameters
68
75
  block_args = (0...number_of_arguments).map { |n| "arg#{n+1}" }
69
- multiline_argument.append_block_argument_to(block_args)
70
- block_args.empty? ? "" : " |#{block_args.join(", ")}|"
76
+ multiline_argument.append_block_parameter_to(block_args)
77
+ block_args.empty? ? '' : " |#{block_args.join(", ")}|"
71
78
  end
72
79
 
73
- def self.example
74
- new("Given", "missing step", MultilineArgument::None.new).step
80
+ def self.example(cucumber_expression_generator)
81
+ new(cucumber_expression_generator, 'Given', 'I have 2 cukes', MultilineArgument::None.new).step
75
82
  end
76
83
 
77
84
  end
78
85
 
86
+ class CucumberExpression < BaseSnippet
87
+ def typed_pattern
88
+ "(\"#{generated_expressions[0].source}\")"
89
+ end
90
+
91
+ def to_s
92
+ header = generated_expressions.each_with_index.map do |expr, i|
93
+ prefix = i == 0 ? '' : '# '
94
+ "#{prefix}#{code_keyword}(\"#{expr.source}\") do#{parameters(expr)}"
95
+ end.join("\n")
96
+
97
+ body = String.new
98
+ multiline_argument.append_comment_to(body)
99
+ body << " pending # Write code here that turns the phrase above into concrete actions\n"
100
+ body << 'end'
101
+
102
+ "#{header}\n#{body}"
103
+ end
104
+
105
+ def parameters(expr)
106
+ parameter_names = expr.parameter_names
107
+ multiline_argument.append_block_parameter_to(parameter_names)
108
+ parameter_names.empty? ? '' : " |#{parameter_names.join(", ")}|"
109
+ end
110
+
111
+ def self.description
112
+ 'Cucumber Expressions'
113
+ end
114
+ end
115
+
79
116
  class Regexp < BaseSnippet
80
117
  def typed_pattern
81
118
  "(/^#{pattern}$/)"
82
119
  end
83
120
 
84
121
  def self.description
85
- "Snippets with parentheses"
122
+ 'Snippets with parentheses'
86
123
  end
87
124
  end
88
125
 
@@ -92,7 +129,7 @@ module Cucumber
92
129
  end
93
130
 
94
131
  def self.description
95
- "Snippets without parentheses. Note that these cause a warning from modern versions of Ruby."
132
+ 'Snippets without parentheses. Note that these cause a warning from modern versions of Ruby.'
96
133
  end
97
134
  end
98
135
 
@@ -102,11 +139,12 @@ module Cucumber
102
139
  end
103
140
 
104
141
  def self.description
105
- "Snippets with percent regexp"
142
+ 'Snippets with percent regexp'
106
143
  end
107
144
  end
108
145
 
109
146
  SNIPPET_TYPES = {
147
+ :cucumber_expression => CucumberExpression,
110
148
  :regexp => Regexp,
111
149
  :classic => Classic,
112
150
  :percent => Percent
@@ -121,11 +159,11 @@ module Cucumber
121
159
  end
122
160
 
123
161
  class Builder
124
- def doc_string(*args)
162
+ def doc_string(*_args)
125
163
  @result = DocString.new
126
164
  end
127
165
 
128
- def data_table(table, *args)
166
+ def data_table(table, *_args)
129
167
  @result = DataTable.new(table)
130
168
  end
131
169
 
@@ -135,7 +173,7 @@ module Cucumber
135
173
  end
136
174
 
137
175
  class DocString
138
- def append_block_argument_to(array)
176
+ def append_block_parameter_to(array)
139
177
  array << 'string'
140
178
  end
141
179
 
@@ -148,17 +186,17 @@ module Cucumber
148
186
  @table = table
149
187
  end
150
188
 
151
- def append_block_argument_to(array)
189
+ def append_block_parameter_to(array)
152
190
  array << 'table'
153
191
  end
154
192
 
155
193
  def append_comment_to(string)
156
- string << " # table is a #{Cucumber::MultilineArgument::DataTable.to_s}\n"
194
+ string << " # table is a #{Cucumber::MultilineArgument::DataTable}\n"
157
195
  end
158
196
  end
159
197
 
160
198
  class None
161
- def append_block_argument_to(array)
199
+ def append_block_parameter_to(array)
162
200
  end
163
201
 
164
202
  def append_comment_to(string)
@@ -0,0 +1,143 @@
1
+ # frozen_string_literal: true
2
+ require 'cucumber/step_match'
3
+ require 'cucumber/step_argument'
4
+ require 'cucumber/core_ext/string'
5
+ require 'cucumber/glue/invoke_in_world'
6
+
7
+ module Cucumber
8
+ module Glue
9
+ # A Step Definition holds a Regexp pattern and a Proc, and is
10
+ # typically created by calling {Dsl#register_rb_step_definition Given, When or Then}
11
+ # in the step_definitions Ruby files.
12
+ #
13
+ # Example:
14
+ #
15
+ # Given /I have (\d+) cucumbers in my belly/ do
16
+ # # some code here
17
+ # end
18
+ #
19
+ class StepDefinition
20
+
21
+ class MissingProc < StandardError
22
+ def message
23
+ 'Step definitions must always have a proc or symbol'
24
+ end
25
+ end
26
+
27
+ class << self
28
+ def new(registry, string_or_regexp, proc_or_sym, options)
29
+ raise MissingProc if proc_or_sym.nil?
30
+ super registry, registry.create_expression(string_or_regexp), create_proc(proc_or_sym, options)
31
+ end
32
+
33
+ private
34
+
35
+ def create_proc(proc_or_sym, options)
36
+ return proc_or_sym if proc_or_sym.is_a?(Proc)
37
+ raise ArgumentError unless proc_or_sym.is_a?(Symbol)
38
+ message = proc_or_sym
39
+ target_proc = parse_target_proc_from(options)
40
+ patch_location_onto lambda { |*args|
41
+ target = instance_exec(&target_proc)
42
+ target.send(message, *args)
43
+ }
44
+ end
45
+
46
+ def patch_location_onto(block)
47
+ location = Core::Ast::Location.of_caller(5)
48
+ block.define_singleton_method(:source_location) { [location.file, location.line] }
49
+ block
50
+ end
51
+
52
+ def parse_target_proc_from(options)
53
+ return lambda { self } unless options.key?(:on)
54
+ target = options[:on]
55
+ case target
56
+ when Proc
57
+ target
58
+ when Symbol
59
+ lambda { self.send(target) }
60
+ else
61
+ lambda { raise ArgumentError, 'Target must be a symbol or a proc' }
62
+ end
63
+ end
64
+ end
65
+
66
+ attr_reader :expression
67
+
68
+ def initialize(registry, expression, proc)
69
+ raise 'No regexp' if expression.is_a?(Regexp)
70
+ @registry, @expression, @proc = registry, expression, proc
71
+ # @registry.available_step_definition(regexp_source, location)
72
+ end
73
+
74
+ # @api private
75
+ def to_hash
76
+ type = expression.is_a?(CucumberExpressions::RegularExpression) ? 'regular expression' : 'cucumber expression'
77
+ regexp = expression.regexp
78
+ flags = ''
79
+ flags += 'm' if (regexp.options & Regexp::MULTILINE) != 0
80
+ flags += 'i' if (regexp.options & Regexp::IGNORECASE) != 0
81
+ flags += 'x' if (regexp.options & Regexp::EXTENDED) != 0
82
+ {
83
+ source: {
84
+ type: type,
85
+ expression: expression.source
86
+ },
87
+ regexp: {
88
+ source: regexp.source,
89
+ flags: flags
90
+ }
91
+ }
92
+ end
93
+
94
+ # @api private
95
+ def ==(step_definition)
96
+ expression.source == step_definition.expression.source
97
+ end
98
+
99
+ # @api private
100
+ def arguments_from(step_name)
101
+ args = @expression.match(step_name)
102
+ # @registry.invoked_step_definition(regexp_source, location) if args
103
+ args
104
+ end
105
+
106
+ # @api private
107
+ # TODO: inline this and step definition just be a value object
108
+ def invoke(args)
109
+ begin
110
+ InvokeInWorld.cucumber_instance_exec_in(@registry.current_world, true, @expression.to_s, *args, &@proc)
111
+ rescue ArityMismatchError => e
112
+ e.backtrace.unshift(self.backtrace_line)
113
+ raise e
114
+ end
115
+ end
116
+
117
+ # @api private
118
+ def backtrace_line
119
+ "#{location}:in `#{@expression}'"
120
+ end
121
+
122
+ # @api private
123
+ def file_colon_line
124
+ case @proc
125
+ when Proc
126
+ location.to_s
127
+ when Symbol
128
+ ":#{@proc}"
129
+ end
130
+ end
131
+
132
+ # The source location where the step defintion can be found
133
+ def location
134
+ @location ||= Cucumber::Core::Ast::Location.from_source_location(*@proc.source_location)
135
+ end
136
+
137
+ # @api private
138
+ def file
139
+ @file ||= location.file
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,23 @@
1
+ module Cucumber
2
+ module Glue
3
+
4
+ class WorldFactory
5
+ def initialize(proc)
6
+ @proc = proc || -> { Object.new }
7
+ end
8
+
9
+ def create_world
10
+ @proc.call || raise_nil_world
11
+ end
12
+
13
+ def raise_nil_world
14
+ raise NilWorld.new
15
+ rescue NilWorld => e
16
+ e.backtrace.clear
17
+ e.backtrace.push(Glue.backtrace_line(@proc, 'World'))
18
+ raise e
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'pathname'
2
3
  require 'cucumber/core/ast/location'
3
4
  require 'cucumber/core/test/around_hook'
@@ -18,11 +19,11 @@ module Cucumber
18
19
  end
19
20
 
20
21
  def after_step_hook(source, location, &block)
21
- raise ArgumentError unless source.last.kind_of?(Core::Ast::Step)
22
+ raise ArgumentError unless source.last.is_a?(Core::Ast::Step)
22
23
  build_hook_step(source, location, block, AfterStepHook, Core::Test::Action)
23
24
  end
24
25
 
25
- def around_hook(source, &block)
26
+ def around_hook(_source, &block)
26
27
  Core::Test::AroundHook.new(&block)
27
28
  end
28
29
 
@@ -42,8 +43,8 @@ module Cucumber
42
43
  @location = location
43
44
  end
44
45
 
45
- def name
46
- "After hook"
46
+ def text
47
+ 'After hook'
47
48
  end
48
49
 
49
50
  def match_locations?(queried_locations)
@@ -62,8 +63,8 @@ module Cucumber
62
63
  @location = location
63
64
  end
64
65
 
65
- def name
66
- "Before hook"
66
+ def text
67
+ 'Before hook'
67
68
  end
68
69
 
69
70
  def match_locations?(queried_locations)
@@ -82,8 +83,8 @@ module Cucumber
82
83
  @location = location
83
84
  end
84
85
 
85
- def name
86
- "AfterStep hook"
86
+ def text
87
+ 'AfterStep hook'
87
88
  end
88
89
 
89
90
  def match_locations?(queried_locations)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Cucumber
2
3
  module LoadPath
3
4
  def add_dirs(*dirs)
@@ -0,0 +1,158 @@
1
+ module Cucumber
2
+ module MultilineArgument
3
+ class DataTable
4
+ class DiffMatrices #:nodoc:
5
+ attr_accessor :cell_matrix, :other_table_cell_matrix, :options
6
+
7
+ def initialize(cell_matrix, other_table_cell_matrix, options)
8
+ @cell_matrix = cell_matrix
9
+ @other_table_cell_matrix = other_table_cell_matrix
10
+ @options = options
11
+ end
12
+
13
+ def call
14
+ prepare_diff
15
+ perform_diff
16
+ fill_in_missing_values
17
+ raise_error if should_raise?
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :row_indices, :original_width, :original_header, :padded_width, :missing_row_pos, :insert_row_pos
23
+
24
+ def prepare_diff
25
+ @original_width = cell_matrix[0].length
26
+ @original_header = other_table_cell_matrix[0]
27
+ pad_and_match
28
+ @padded_width = cell_matrix[0].length
29
+ @row_indices = Array.new(other_table_cell_matrix.length) {|n| n}
30
+ end
31
+
32
+ # Pads two cell matrices to same column width and matches columns according to header value.
33
+ def pad_and_match
34
+ cols = cell_matrix.transpose
35
+ unmatched_cols = other_table_cell_matrix.transpose
36
+
37
+ header_values = cols.map(&:first)
38
+ matched_cols = []
39
+
40
+ header_values.each_with_index do |v, i|
41
+ mapped_index = unmatched_cols.index{|unmapped_col| unmapped_col.first == v}
42
+ if mapped_index
43
+ matched_cols << unmatched_cols.delete_at(mapped_index)
44
+ else
45
+ mark_as_missing(cols[i])
46
+ empty_col = ensure_2d(other_table_cell_matrix).collect {SurplusCell.new(nil, self, -1)}
47
+ empty_col.first.value = v
48
+ matched_cols << empty_col
49
+ end
50
+ end
51
+
52
+ unmatched_cols.each do
53
+ empty_col = cell_matrix.collect {SurplusCell.new(nil, self, -1)}
54
+ cols << empty_col
55
+ end
56
+
57
+ self.cell_matrix = ensure_2d(cols.transpose)
58
+ self.other_table_cell_matrix = ensure_2d((matched_cols + unmatched_cols).transpose)
59
+ end
60
+
61
+ def mark_as_missing(col)
62
+ col.each do |cell|
63
+ cell.status = :undefined
64
+ end
65
+ end
66
+
67
+ def ensure_2d(array)
68
+ array[0].is_a?(Array) ? array : [array]
69
+ end
70
+
71
+
72
+ def perform_diff
73
+ inserted = 0
74
+ missing = 0
75
+ last_change = nil
76
+
77
+ changes.each do |change|
78
+ if change.action == '-'
79
+ @missing_row_pos = change.position + inserted
80
+ cell_matrix[missing_row_pos].each{|cell| cell.status = :undefined}
81
+ row_indices.insert(missing_row_pos, nil)
82
+ missing += 1
83
+ else # '+'
84
+ @insert_row_pos = change.position + missing
85
+ inserted_row = change.element
86
+ inserted_row.each{|cell| cell.status = :comment}
87
+ cell_matrix.insert(insert_row_pos, inserted_row)
88
+ row_indices[insert_row_pos] = nil
89
+ inspect_rows(cell_matrix[missing_row_pos], inserted_row) if last_change == '-'
90
+ inserted += 1
91
+ end
92
+ last_change = change.action
93
+ end
94
+ end
95
+
96
+ def changes
97
+ require 'diff/lcs'
98
+ diffable_cell_matrix = cell_matrix.dup.extend(::Diff::LCS)
99
+ diffable_cell_matrix.diff(other_table_cell_matrix).flatten
100
+ end
101
+
102
+ def inspect_rows(missing_row, inserted_row)
103
+ missing_row.each_with_index do |missing_cell, col|
104
+ inserted_cell = inserted_row[col]
105
+ if missing_cell.value != inserted_cell.value && missing_cell.value.to_s == inserted_cell.value.to_s
106
+ missing_cell.inspect!
107
+ inserted_cell.inspect!
108
+ end
109
+ end
110
+ end
111
+
112
+
113
+ def fill_in_missing_values
114
+ other_table_cell_matrix.each_with_index do |other_row, i|
115
+ row_index = row_indices.index(i)
116
+ row = cell_matrix[row_index] if row_index
117
+ next unless row
118
+ (original_width..padded_width).each do |col_index|
119
+ surplus_cell = other_row[col_index]
120
+ row[col_index].value = surplus_cell.value if row[col_index]
121
+ end
122
+ end
123
+ end
124
+
125
+ def missing_col
126
+ cell_matrix[0].find{|cell| cell.status == :undefined}
127
+ end
128
+
129
+ def surplus_col
130
+ padded_width > original_width
131
+ end
132
+
133
+ def misplaced_col
134
+ cell_matrix[0] != original_header
135
+ end
136
+
137
+
138
+ def raise_error
139
+ table = DataTable.from([[]])
140
+ table.instance_variable_set :@cell_matrix, cell_matrix
141
+ raise Different.new(table) if should_raise?
142
+ end
143
+
144
+ def should_raise?
145
+ [
146
+ missing_row_pos && options.fetch(:missing_row, true),
147
+ insert_row_pos && options.fetch(:surplus_row, true),
148
+ missing_col && options.fetch(:missing_col, true),
149
+ surplus_col && options.fetch(:surplus_col, false),
150
+ misplaced_col && options.fetch(:misplaced_col, false)
151
+ ].any?
152
+ end
153
+ end
154
+ private_constant :DiffMatrices
155
+ end
156
+ end
157
+ end
158
+