cucumber 3.0.0.pre.1 → 4.0.0.rc.4

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 (533) hide show
  1. checksums.yaml +5 -5
  2. data/{History.md → CHANGELOG.md} +339 -37
  3. data/CONTRIBUTING.md +11 -21
  4. data/README.md +20 -12
  5. data/bin/cucumber +2 -1
  6. data/lib/autotest/cucumber.rb +1 -0
  7. data/lib/autotest/cucumber_mixin.rb +44 -48
  8. data/lib/autotest/cucumber_rails.rb +1 -0
  9. data/lib/autotest/cucumber_rails_rspec.rb +1 -0
  10. data/lib/autotest/cucumber_rails_rspec2.rb +1 -0
  11. data/lib/autotest/cucumber_rspec.rb +1 -0
  12. data/lib/autotest/cucumber_rspec2.rb +1 -0
  13. data/lib/autotest/discover.rb +3 -2
  14. data/lib/cucumber.rb +2 -1
  15. data/lib/cucumber/cli/configuration.rb +15 -20
  16. data/lib/cucumber/cli/main.rb +15 -15
  17. data/lib/cucumber/cli/options.rb +249 -197
  18. data/lib/cucumber/cli/profile_loader.rb +63 -38
  19. data/lib/cucumber/cli/rerun_file.rb +1 -0
  20. data/lib/cucumber/configuration.rb +49 -44
  21. data/lib/cucumber/constantize.rb +8 -10
  22. data/lib/cucumber/core_ext/string.rb +2 -1
  23. data/lib/cucumber/deprecate.rb +34 -10
  24. data/lib/cucumber/encoding.rb +2 -1
  25. data/lib/cucumber/errors.rb +10 -8
  26. data/lib/cucumber/events.rb +18 -3
  27. data/lib/cucumber/events/envelope.rb +9 -0
  28. data/lib/cucumber/events/gherkin_source_parsed.rb +11 -0
  29. data/lib/cucumber/events/gherkin_source_read.rb +14 -0
  30. data/lib/cucumber/events/hook_test_step_created.rb +13 -0
  31. data/lib/cucumber/events/{step_match.rb → step_activated.rb} +8 -8
  32. data/lib/cucumber/events/step_definition_registered.rb +5 -9
  33. data/lib/cucumber/events/test_case_created.rb +13 -0
  34. data/lib/cucumber/events/test_case_finished.rb +14 -0
  35. data/lib/cucumber/events/test_case_ready.rb +12 -0
  36. data/lib/cucumber/events/test_case_started.rb +11 -0
  37. data/lib/cucumber/events/test_run_finished.rb +2 -3
  38. data/lib/cucumber/events/test_run_started.rb +14 -0
  39. data/lib/cucumber/events/test_step_created.rb +13 -0
  40. data/lib/cucumber/events/test_step_finished.rb +14 -0
  41. data/lib/cucumber/events/test_step_started.rb +11 -0
  42. data/lib/cucumber/file_specs.rb +7 -6
  43. data/lib/cucumber/filters.rb +3 -0
  44. data/lib/cucumber/filters/activate_steps.rb +12 -6
  45. data/lib/cucumber/filters/apply_after_hooks.rb +1 -0
  46. data/lib/cucumber/filters/apply_after_step_hooks.rb +1 -0
  47. data/lib/cucumber/filters/apply_around_hooks.rb +1 -0
  48. data/lib/cucumber/filters/apply_before_hooks.rb +1 -0
  49. data/lib/cucumber/filters/broadcast_test_case_ready_event.rb +12 -0
  50. data/lib/cucumber/filters/broadcast_test_run_started_event.rb +28 -0
  51. data/lib/cucumber/filters/gated_receiver.rb +1 -2
  52. data/lib/cucumber/filters/prepare_world.rb +6 -13
  53. data/lib/cucumber/filters/quit.rb +3 -7
  54. data/lib/cucumber/filters/randomizer.rb +6 -7
  55. data/lib/cucumber/filters/retry.rb +3 -3
  56. data/lib/cucumber/filters/tag_limits.rb +5 -5
  57. data/lib/cucumber/filters/tag_limits/test_case_index.rb +1 -2
  58. data/lib/cucumber/filters/tag_limits/verifier.rb +4 -7
  59. data/lib/cucumber/formatter/ansicolor.rb +38 -45
  60. data/lib/cucumber/formatter/ast_lookup.rb +165 -0
  61. data/lib/cucumber/formatter/backtrace_filter.rb +24 -12
  62. data/lib/cucumber/formatter/console.rb +48 -88
  63. data/lib/cucumber/formatter/console_counts.rb +11 -29
  64. data/lib/cucumber/formatter/console_issues.rb +34 -10
  65. data/lib/cucumber/formatter/duration.rb +2 -1
  66. data/lib/cucumber/formatter/duration_extractor.rb +4 -2
  67. data/lib/cucumber/formatter/errors.rb +6 -0
  68. data/lib/cucumber/formatter/fail_fast.rb +8 -5
  69. data/lib/cucumber/formatter/fanout.rb +3 -3
  70. data/lib/cucumber/formatter/ignore_missing_messages.rb +2 -4
  71. data/lib/cucumber/formatter/interceptor.rb +12 -14
  72. data/lib/cucumber/formatter/io.rb +5 -4
  73. data/lib/cucumber/formatter/json.rb +109 -115
  74. data/lib/cucumber/formatter/junit.rb +85 -80
  75. data/lib/cucumber/formatter/message.rb +246 -0
  76. data/lib/cucumber/formatter/pretty.rb +353 -153
  77. data/lib/cucumber/formatter/progress.rb +34 -38
  78. data/lib/cucumber/formatter/query/hook_by_test_step.rb +31 -0
  79. data/lib/cucumber/formatter/query/pickle_by_test.rb +26 -0
  80. data/lib/cucumber/formatter/query/pickle_step_by_test_step.rb +26 -0
  81. data/lib/cucumber/formatter/query/step_definitions_by_test_step.rb +40 -0
  82. data/lib/cucumber/formatter/query/test_case_started_by_test_case.rb +40 -0
  83. data/lib/cucumber/formatter/rerun.rb +24 -5
  84. data/lib/cucumber/formatter/stepdefs.rb +2 -2
  85. data/lib/cucumber/formatter/steps.rb +5 -6
  86. data/lib/cucumber/formatter/summary.rb +18 -11
  87. data/lib/cucumber/formatter/unicode.rb +16 -18
  88. data/lib/cucumber/formatter/usage.rb +37 -33
  89. data/lib/cucumber/gherkin/data_table_parser.rb +18 -6
  90. data/lib/cucumber/gherkin/formatter/ansi_escapes.rb +83 -86
  91. data/lib/cucumber/gherkin/formatter/escaping.rb +13 -12
  92. data/lib/cucumber/gherkin/i18n.rb +1 -0
  93. data/lib/cucumber/gherkin/steps_parser.rb +18 -8
  94. data/lib/cucumber/{rb_support/rb_dsl.rb → glue/dsl.rb} +37 -23
  95. data/lib/cucumber/glue/hook.rb +67 -0
  96. data/lib/cucumber/glue/invoke_in_world.rb +65 -0
  97. data/lib/cucumber/glue/proto_world.rb +231 -0
  98. data/lib/cucumber/glue/registry_and_more.rb +221 -0
  99. data/lib/cucumber/glue/snippet.rb +205 -0
  100. data/lib/cucumber/glue/step_definition.rb +166 -0
  101. data/lib/cucumber/glue/world_factory.rb +21 -0
  102. data/lib/cucumber/hooks.rb +30 -20
  103. data/lib/cucumber/load_path.rb +1 -0
  104. data/lib/cucumber/multiline_argument.rb +9 -19
  105. data/lib/cucumber/multiline_argument/data_table.rb +143 -250
  106. data/lib/cucumber/multiline_argument/data_table/diff_matrices.rb +154 -0
  107. data/lib/cucumber/multiline_argument/doc_string.rb +2 -1
  108. data/lib/cucumber/platform.rb +5 -6
  109. data/lib/cucumber/project_initializer.rb +2 -2
  110. data/lib/cucumber/rake/task.rb +34 -27
  111. data/lib/cucumber/rspec/disable_option_parser.rb +10 -8
  112. data/lib/cucumber/rspec/doubles.rb +2 -1
  113. data/lib/cucumber/running_test_case.rb +4 -54
  114. data/lib/cucumber/runtime.rb +54 -72
  115. data/lib/cucumber/runtime/after_hooks.rb +10 -5
  116. data/lib/cucumber/runtime/before_hooks.rb +9 -4
  117. data/lib/cucumber/runtime/for_programming_languages.rb +12 -44
  118. data/lib/cucumber/runtime/step_hooks.rb +5 -2
  119. data/lib/cucumber/runtime/support_code.rb +30 -32
  120. data/lib/cucumber/runtime/user_interface.rb +16 -34
  121. data/lib/cucumber/step_definition_light.rb +7 -4
  122. data/lib/cucumber/step_definitions.rb +3 -2
  123. data/lib/cucumber/step_match.rb +42 -26
  124. data/lib/cucumber/step_match_search.rb +11 -12
  125. data/lib/cucumber/term/ansicolor.rb +39 -39
  126. data/lib/cucumber/unit.rb +1 -0
  127. data/lib/cucumber/version +1 -1
  128. data/lib/simplecov_setup.rb +2 -1
  129. metadata +238 -623
  130. data/.coveralls.yml +0 -1
  131. data/.github/ISSUE_TEMPLATE.md +0 -48
  132. data/.github/PULL_REQUEST_TEMPLATE.md +0 -39
  133. data/.rspec +0 -1
  134. data/.ruby-gemset +0 -1
  135. data/.travis.yml +0 -35
  136. data/.yardopts +0 -1
  137. data/Gemfile +0 -22
  138. data/Rakefile +0 -22
  139. data/cucumber.gemspec +0 -47
  140. data/cucumber.yml +0 -20
  141. data/examples/i18n/README.textile +0 -3
  142. data/examples/i18n/Rakefile +0 -33
  143. data/examples/i18n/ar/Rakefile +0 -6
  144. data/examples/i18n/ar/features/addition.feature +0 -17
  145. data/examples/i18n/ar/features/step_definitions/calculator_steps.rb +0 -24
  146. data/examples/i18n/ar/lib/calculator.rb +0 -11
  147. data/examples/i18n/bg/Rakefile +0 -6
  148. data/examples/i18n/bg/features/addition.feature +0 -12
  149. data/examples/i18n/bg/features/consecutive_calculations.feature +0 -19
  150. data/examples/i18n/bg/features/division.feature +0 -17
  151. data/examples/i18n/bg/features/step_definitions/calculator_steps.rb +0 -24
  152. data/examples/i18n/bg/features/support/env.rb +0 -5
  153. data/examples/i18n/bg/features/support/world.rb +0 -8
  154. data/examples/i18n/bg/lib/calculator.rb +0 -24
  155. data/examples/i18n/ca/Rakefile +0 -6
  156. data/examples/i18n/ca/features/step_definitions/calculator_steps.rb +0 -21
  157. data/examples/i18n/ca/features/suma.feature +0 -17
  158. data/examples/i18n/ca/lib/calculadora.rb +0 -16
  159. data/examples/i18n/cs/Rakefile +0 -6
  160. data/examples/i18n/cs/features/addition.feature +0 -17
  161. data/examples/i18n/cs/features/division.feature +0 -11
  162. data/examples/i18n/cs/features/step_definitions/calculator_steps.rb +0 -24
  163. data/examples/i18n/cs/lib/calculator.rb +0 -14
  164. data/examples/i18n/da/Rakefile +0 -6
  165. data/examples/i18n/da/features/sammenlaegning.feature +0 -18
  166. data/examples/i18n/da/features/step_definitions/lommeregner_steps.rb +0 -24
  167. data/examples/i18n/da/lib/lommeregner.rb +0 -11
  168. data/examples/i18n/de/Rakefile +0 -6
  169. data/examples/i18n/de/features/addition.feature +0 -17
  170. data/examples/i18n/de/features/division.feature +0 -10
  171. data/examples/i18n/de/features/step_definitions/calculator_steps.rb +0 -24
  172. data/examples/i18n/de/lib/calculator.rb +0 -14
  173. data/examples/i18n/el/Rakefile +0 -6
  174. data/examples/i18n/el/features/addition.feature +0 -17
  175. data/examples/i18n/el/features/division.feature +0 -10
  176. data/examples/i18n/el/features/step_definitions/calculator_steps.rb +0 -24
  177. data/examples/i18n/el/lib/calculator.rb +0 -14
  178. data/examples/i18n/en-lol/Rakefile +0 -4
  179. data/examples/i18n/en-lol/features/step_definitions/cucumbrz_steps.rb +0 -16
  180. data/examples/i18n/en-lol/features/stuffing.feature +0 -8
  181. data/examples/i18n/en-lol/features/support/env.rb +0 -7
  182. data/examples/i18n/en-lol/lib/basket.rb +0 -12
  183. data/examples/i18n/en-lol/lib/belly.rb +0 -11
  184. data/examples/i18n/en/Rakefile +0 -6
  185. data/examples/i18n/en/features/addition.feature +0 -17
  186. data/examples/i18n/en/features/division.feature +0 -10
  187. data/examples/i18n/en/features/step_definitions/calculator_steps.rb +0 -24
  188. data/examples/i18n/en/lib/calculator.rb +0 -14
  189. data/examples/i18n/eo/Rakefile +0 -6
  190. data/examples/i18n/eo/features/adicio.feature +0 -17
  191. data/examples/i18n/eo/features/divido.feature +0 -10
  192. data/examples/i18n/eo/features/step_definitions/calculator_steps.rb +0 -24
  193. data/examples/i18n/eo/lib/calculator.rb +0 -14
  194. data/examples/i18n/es/Rakefile +0 -6
  195. data/examples/i18n/es/features/adicion.feature +0 -17
  196. data/examples/i18n/es/features/step_definitions/calculador_steps.rb +0 -21
  197. data/examples/i18n/es/lib/calculador.rb +0 -14
  198. data/examples/i18n/et/Rakefile +0 -6
  199. data/examples/i18n/et/features/jagamine.feature +0 -10
  200. data/examples/i18n/et/features/liitmine.feature +0 -17
  201. data/examples/i18n/et/features/step_definitions/kalkulaator_steps.rb +0 -24
  202. data/examples/i18n/et/lib/kalkulaator.rb +0 -14
  203. data/examples/i18n/fi/Rakefile +0 -6
  204. data/examples/i18n/fi/features/jakolasku.feature +0 -10
  205. data/examples/i18n/fi/features/step_definitions/laskin_steps.rb +0 -24
  206. data/examples/i18n/fi/features/yhteenlasku.feature +0 -17
  207. data/examples/i18n/fi/lib/laskin.rb +0 -14
  208. data/examples/i18n/fr/Rakefile +0 -8
  209. data/examples/i18n/fr/features/addition.feature +0 -18
  210. data/examples/i18n/fr/features/addition2.feature +0 -17
  211. data/examples/i18n/fr/features/step_definitions/calculatrice_steps.rb +0 -32
  212. data/examples/i18n/fr/features/support/env.rb +0 -5
  213. data/examples/i18n/fr/lib/calculatrice.rb +0 -10
  214. data/examples/i18n/he/Rakefile +0 -6
  215. data/examples/i18n/he/features/addition.feature +0 -17
  216. data/examples/i18n/he/features/division.feature +0 -10
  217. data/examples/i18n/he/features/step_definitions/calculator_steps.rb +0 -24
  218. data/examples/i18n/he/lib/calculator.rb +0 -15
  219. data/examples/i18n/hi/Rakefile +0 -6
  220. data/examples/i18n/hi/features/addition.feature +0 -16
  221. data/examples/i18n/hi/features/division.feature +0 -10
  222. data/examples/i18n/hi/features/step_definitions/calculator_steps.rb +0 -24
  223. data/examples/i18n/hi/lib/calculator.rb +0 -15
  224. data/examples/i18n/ht/Rakefile +0 -6
  225. data/examples/i18n/ht/features/adisyon.feature +0 -17
  226. data/examples/i18n/ht/features/divizyon.feature +0 -10
  227. data/examples/i18n/ht/features/step_definitions/kalkilatris_steps.rb +0 -25
  228. data/examples/i18n/ht/lib/kalkilatris.rb +0 -14
  229. data/examples/i18n/hu/Rakefile +0 -6
  230. data/examples/i18n/hu/features/osszeadas.feature +0 -17
  231. data/examples/i18n/hu/features/osztas.feature +0 -10
  232. data/examples/i18n/hu/features/step_definitions/calculator_steps.rb +0 -25
  233. data/examples/i18n/hu/lib/calculator.rb +0 -14
  234. data/examples/i18n/id/Rakefile +0 -6
  235. data/examples/i18n/id/features/addition.feature +0 -17
  236. data/examples/i18n/id/features/division.feature +0 -10
  237. data/examples/i18n/id/features/step_definitions/calculator_steps.rb +0 -24
  238. data/examples/i18n/id/lib/calculator.rb +0 -14
  239. data/examples/i18n/it/Rakefile +0 -6
  240. data/examples/i18n/it/features/somma.feature +0 -11
  241. data/examples/i18n/it/features/step_definitions/calcolatrice_steps.rb +0 -24
  242. data/examples/i18n/it/lib/calcolatrice.rb +0 -11
  243. data/examples/i18n/ja/Rakefile +0 -6
  244. data/examples/i18n/ja/features/addition.feature +0 -17
  245. data/examples/i18n/ja/features/division.feature +0 -10
  246. data/examples/i18n/ja/features/step_definitions/calculator_steps.rb +0 -19
  247. data/examples/i18n/ja/features/support/env.rb +0 -5
  248. data/examples/i18n/ja/lib/calculator.rb +0 -14
  249. data/examples/i18n/ko/Rakefile +0 -6
  250. data/examples/i18n/ko/features/addition.feature +0 -17
  251. data/examples/i18n/ko/features/division.feature +0 -11
  252. data/examples/i18n/ko/features/step_definitions/calculator_steps.rb +0 -24
  253. data/examples/i18n/ko/lib/calculator.rb +0 -14
  254. data/examples/i18n/lt/Rakefile +0 -6
  255. data/examples/i18n/lt/features/addition.feature +0 -17
  256. data/examples/i18n/lt/features/division.feature +0 -10
  257. data/examples/i18n/lt/features/step_definitions/calculator_steps.rb +0 -24
  258. data/examples/i18n/lt/lib/calculator.rb +0 -14
  259. data/examples/i18n/lv/Rakefile +0 -6
  260. data/examples/i18n/lv/features/addition.feature +0 -17
  261. data/examples/i18n/lv/features/division.feature +0 -10
  262. data/examples/i18n/lv/features/step_definitions/calculator_steps.rb +0 -24
  263. data/examples/i18n/lv/lib/calculator.rb +0 -14
  264. data/examples/i18n/no/Rakefile +0 -6
  265. data/examples/i18n/no/features/step_definitions/kalkulator_steps.rb +0 -17
  266. data/examples/i18n/no/features/summering.feature +0 -19
  267. data/examples/i18n/no/features/support/env.rb +0 -6
  268. data/examples/i18n/no/lib/kalkulator.rb +0 -11
  269. data/examples/i18n/pl/Rakefile +0 -6
  270. data/examples/i18n/pl/features/addition.feature +0 -17
  271. data/examples/i18n/pl/features/division.feature +0 -10
  272. data/examples/i18n/pl/features/step_definitions/calculator_steps.rb +0 -24
  273. data/examples/i18n/pl/features/support/env.rb +0 -5
  274. data/examples/i18n/pl/lib/calculator.rb +0 -14
  275. data/examples/i18n/pt/Rakefile +0 -6
  276. data/examples/i18n/pt/features/adicao.feature +0 -11
  277. data/examples/i18n/pt/features/step_definitions/calculadora_steps.rb +0 -20
  278. data/examples/i18n/pt/features/support/env.rb +0 -5
  279. data/examples/i18n/pt/lib/calculadora.rb +0 -10
  280. data/examples/i18n/ro/Rakefile +0 -6
  281. data/examples/i18n/ro/features/adunare.feature +0 -12
  282. data/examples/i18n/ro/features/step_definitions/calculator_steps.rb +0 -21
  283. data/examples/i18n/ro/lib/calculator.rb +0 -11
  284. data/examples/i18n/ru/Rakefile +0 -6
  285. data/examples/i18n/ru/features/addition.feature +0 -11
  286. data/examples/i18n/ru/features/consecutive_calculations.feature +0 -17
  287. data/examples/i18n/ru/features/division.feature +0 -16
  288. data/examples/i18n/ru/features/step_definitions/calculator_steps.rb +0 -19
  289. data/examples/i18n/ru/features/support/env.rb +0 -5
  290. data/examples/i18n/ru/features/support/world.rb +0 -8
  291. data/examples/i18n/ru/lib/calculator.rb +0 -24
  292. data/examples/i18n/sk/Rakefile +0 -6
  293. data/examples/i18n/sk/features/addition.feature +0 -17
  294. data/examples/i18n/sk/features/division.feature +0 -10
  295. data/examples/i18n/sk/features/step_definitions/calculator_steps.rb +0 -24
  296. data/examples/i18n/sk/lib/calculator.rb +0 -14
  297. data/examples/i18n/sr-Cyrl/Rakefile +0 -6
  298. data/examples/i18n/sr-Cyrl/features/sabiranje.feature +0 -18
  299. data/examples/i18n/sr-Cyrl/features/step_definitions/calculator_steps.rb +0 -20
  300. data/examples/i18n/sr-Cyrl/features/support/env.rb +0 -5
  301. data/examples/i18n/sr-Cyrl/lib/calculator.rb +0 -12
  302. data/examples/i18n/sr-Latn/Rakefile +0 -6
  303. data/examples/i18n/sr-Latn/features/sabiranje.feature +0 -18
  304. data/examples/i18n/sr-Latn/features/step_definitions/calculator_steps.rb +0 -24
  305. data/examples/i18n/sr-Latn/lib/calculator.rb +0 -12
  306. data/examples/i18n/sv/Rakefile +0 -6
  307. data/examples/i18n/sv/features/step_definitions/kalkulator_steps.rb +0 -24
  308. data/examples/i18n/sv/features/summering.feature +0 -18
  309. data/examples/i18n/sv/lib/kalkulator.rb +0 -11
  310. data/examples/i18n/tr/Rakefile +0 -6
  311. data/examples/i18n/tr/features/bolme.feature +0 -10
  312. data/examples/i18n/tr/features/step_definitions/hesap_makinesi_adimlari.rb +0 -24
  313. data/examples/i18n/tr/features/toplama.feature +0 -18
  314. data/examples/i18n/tr/lib/hesap_makinesi.rb +0 -15
  315. data/examples/i18n/uk/Rakefile +0 -6
  316. data/examples/i18n/uk/features/addition.feature +0 -11
  317. data/examples/i18n/uk/features/consecutive_calculations.feature +0 -17
  318. data/examples/i18n/uk/features/division.feature +0 -16
  319. data/examples/i18n/uk/features/step_definitions/calculator_steps.rb +0 -19
  320. data/examples/i18n/uk/features/support/env.rb +0 -5
  321. data/examples/i18n/uk/features/support/world.rb +0 -8
  322. data/examples/i18n/uk/lib/calculator.rb +0 -24
  323. data/examples/i18n/uz/Rakefile +0 -6
  324. data/examples/i18n/uz/features/addition.feature +0 -10
  325. data/examples/i18n/uz/features/consecutive_calculations.feature +0 -17
  326. data/examples/i18n/uz/features/division.feature +0 -17
  327. data/examples/i18n/uz/features/step_definitions/calculator_steps.rb +0 -19
  328. data/examples/i18n/uz/features/support/env.rb +0 -5
  329. data/examples/i18n/uz/features/support/world.rb +0 -8
  330. data/examples/i18n/uz/lib/calculator.rb +0 -24
  331. data/examples/i18n/zh-CN/Rakefile +0 -4
  332. data/examples/i18n/zh-CN/features/addition.feature +0 -18
  333. data/examples/i18n/zh-CN/features/step_definitions/calculator_steps.rb +0 -26
  334. data/examples/i18n/zh-CN/lib/calculator.rb +0 -10
  335. data/examples/i18n/zh-TW/Rakefile +0 -4
  336. data/examples/i18n/zh-TW/features/addition.feature +0 -17
  337. data/examples/i18n/zh-TW/features/division.feature +0 -11
  338. data/examples/i18n/zh-TW/features/step_definitions/calculator_steps.rb +0 -24
  339. data/examples/i18n/zh-TW/lib/calculator.rb +0 -14
  340. data/examples/rspec_doubles/Rakefile +0 -4
  341. data/examples/rspec_doubles/features/mocking.feature +0 -9
  342. data/examples/rspec_doubles/features/step_definitions/calvin_steps.rb +0 -19
  343. data/examples/rspec_doubles/features/support/env.rb +0 -12
  344. data/examples/sinatra/README.textile +0 -13
  345. data/examples/sinatra/Rakefile +0 -6
  346. data/examples/sinatra/app.rb +0 -14
  347. data/examples/sinatra/features/add.feature +0 -11
  348. data/examples/sinatra/features/step_definitions/add_steps.rb +0 -15
  349. data/examples/sinatra/features/support/env.rb +0 -10
  350. data/examples/sinatra/views/add.erb +0 -7
  351. data/examples/sinatra/views/layout.erb +0 -8
  352. data/examples/tcl/README.textile +0 -11
  353. data/examples/tcl/Rakefile +0 -6
  354. data/examples/tcl/features/fibonnacci.feature +0 -17
  355. data/examples/tcl/features/step_definitions/fib_steps.rb +0 -7
  356. data/examples/tcl/features/support/env.rb +0 -6
  357. data/examples/tcl/src/fib.tcl +0 -3
  358. data/examples/test_unit/Gemfile +0 -4
  359. data/examples/test_unit/Rakefile +0 -6
  360. data/examples/test_unit/features/step_definitions/test_unit_steps.rb +0 -20
  361. data/examples/test_unit/features/test_unit.feature +0 -9
  362. data/examples/watir/README.textile +0 -16
  363. data/examples/watir/Rakefile +0 -12
  364. data/examples/watir/cucumber.yml +0 -1
  365. data/examples/watir/features/search.feature +0 -12
  366. data/examples/watir/features/step_definitions/search_steps.rb +0 -26
  367. data/examples/watir/features/support/env.rb +0 -35
  368. data/examples/watir/features/support/screenshots.rb +0 -47
  369. data/features/docs/api/list_step_defs_as_json.feature +0 -50
  370. data/features/docs/api/listen_for_events.feature +0 -59
  371. data/features/docs/api/run_cli_main_with_existing_runtime.feature +0 -26
  372. data/features/docs/cli/backtraces.feature +0 -36
  373. data/features/docs/cli/dry_run.feature +0 -70
  374. data/features/docs/cli/exclude_files.feature +0 -18
  375. data/features/docs/cli/execute_with_tag_filter.feature +0 -117
  376. data/features/docs/cli/fail_fast.feature +0 -46
  377. data/features/docs/cli/finding_steps.feature +0 -28
  378. data/features/docs/cli/help.feature +0 -8
  379. data/features/docs/cli/randomize.feature +0 -140
  380. data/features/docs/cli/require.feature +0 -27
  381. data/features/docs/cli/retry_failing_tests.feature +0 -67
  382. data/features/docs/cli/run_scenarios_matching_name.feature +0 -104
  383. data/features/docs/cli/run_specific_scenarios.feature +0 -77
  384. data/features/docs/cli/showing_differences.feature +0 -43
  385. data/features/docs/cli/specifying_multiple_formatters.feature +0 -65
  386. data/features/docs/cli/strict_mode.feature +0 -64
  387. data/features/docs/defining_steps/nested_steps.feature +0 -177
  388. data/features/docs/defining_steps/nested_steps_i18n.feature +0 -36
  389. data/features/docs/defining_steps/nested_steps_with_second_arg.feature +0 -54
  390. data/features/docs/defining_steps/one_line_step_definitions.feature +0 -65
  391. data/features/docs/defining_steps/printing_messages.feature +0 -147
  392. data/features/docs/defining_steps/skip_scenario.feature +0 -30
  393. data/features/docs/defining_steps/snippets.feature +0 -56
  394. data/features/docs/defining_steps/table_diffing.feature +0 -50
  395. data/features/docs/exception_in_after_hook.feature +0 -126
  396. data/features/docs/exception_in_after_step_hook.feature +0 -102
  397. data/features/docs/exception_in_around_hook.feature +0 -78
  398. data/features/docs/exception_in_before_hook.feature +0 -96
  399. data/features/docs/extending_cucumber/custom_filter.feature +0 -29
  400. data/features/docs/extending_cucumber/custom_formatter.feature +0 -102
  401. data/features/docs/formatters/api_methods.feature +0 -37
  402. data/features/docs/formatters/debug_formatter.feature +0 -47
  403. data/features/docs/formatters/formatter_step_file_colon_line.feature +0 -44
  404. data/features/docs/formatters/html_formatter.feature +0 -91
  405. data/features/docs/formatters/json_formatter.feature +0 -767
  406. data/features/docs/formatters/junit_formatter.feature +0 -454
  407. data/features/docs/formatters/pretty_formatter.feature +0 -73
  408. data/features/docs/formatters/progress_formatter.feature +0 -31
  409. data/features/docs/formatters/rerun_formatter.feature +0 -188
  410. data/features/docs/formatters/summary_formatter.feature +0 -34
  411. data/features/docs/formatters/usage_formatter.feature +0 -98
  412. data/features/docs/getting_started.feature +0 -27
  413. data/features/docs/gherkin/background.feature +0 -548
  414. data/features/docs/gherkin/doc_strings.feature +0 -74
  415. data/features/docs/gherkin/expand_option_for_outlines.feature +0 -46
  416. data/features/docs/gherkin/language_from_header.feature +0 -32
  417. data/features/docs/gherkin/language_help.feature +0 -42
  418. data/features/docs/gherkin/outlines.feature +0 -156
  419. data/features/docs/gherkin/unicode_table.feature +0 -32
  420. data/features/docs/gherkin/using_descriptions.feature +0 -82
  421. data/features/docs/gherkin/using_star_notation.feature +0 -37
  422. data/features/docs/iso-8859-1.feature +0 -6
  423. data/features/docs/post_configuration_hook.feature +0 -33
  424. data/features/docs/profiles.feature +0 -120
  425. data/features/docs/rake_task.feature +0 -141
  426. data/features/docs/raketask.feature +0 -44
  427. data/features/docs/work_in_progress.feature +0 -154
  428. data/features/docs/writing_support_code/after_hooks.feature +0 -102
  429. data/features/docs/writing_support_code/after_step_hooks.feature +0 -53
  430. data/features/docs/writing_support_code/around_hooks.feature +0 -260
  431. data/features/docs/writing_support_code/before_hook.feature +0 -65
  432. data/features/docs/writing_support_code/hook_order.feature +0 -61
  433. data/features/docs/writing_support_code/load_path.feature +0 -17
  434. data/features/docs/writing_support_code/state.feature +0 -32
  435. data/features/docs/writing_support_code/tagged_hooks.feature +0 -95
  436. data/features/docs/writing_support_code/transforms.feature +0 -98
  437. data/features/docs/writing_support_code/world.feature +0 -129
  438. data/features/lib/step_definitions/aruba_steps.rb +0 -27
  439. data/features/lib/step_definitions/cli_steps.rb +0 -4
  440. data/features/lib/step_definitions/cucumber_steps.rb +0 -79
  441. data/features/lib/step_definitions/iso-8859-1_steps.rb +0 -13
  442. data/features/lib/step_definitions/json_steps.rb +0 -8
  443. data/features/lib/step_definitions/junit_steps.rb +0 -14
  444. data/features/lib/step_definitions/language_steps.rb +0 -9
  445. data/features/lib/step_definitions/profile_steps.rb +0 -16
  446. data/features/lib/step_definitions/retry_steps.rb +0 -55
  447. data/features/lib/step_definitions/ruby_steps.rb +0 -4
  448. data/features/lib/step_definitions/wire_steps.rb +0 -59
  449. data/features/lib/support/env.rb +0 -22
  450. data/features/lib/support/fake_wire_server.rb +0 -81
  451. data/features/lib/support/feature_factory.rb +0 -68
  452. data/features/lib/support/normalise_output.rb +0 -51
  453. data/gem_tasks/contributors.rake +0 -16
  454. data/gem_tasks/cov.rake +0 -6
  455. data/gem_tasks/cucumber.rake +0 -26
  456. data/gem_tasks/downloads.rb +0 -8
  457. data/gem_tasks/environment.rake +0 -8
  458. data/gem_tasks/examples.rake +0 -12
  459. data/gem_tasks/fix_cr_lf.rake +0 -11
  460. data/gem_tasks/flog.rake +0 -5
  461. data/gem_tasks/rspec.rake +0 -7
  462. data/gem_tasks/sass.rake +0 -5
  463. data/gem_tasks/stats +0 -16
  464. data/gem_tasks/versions.txt +0 -74
  465. data/lib/cucumber/core_ext/instance_exec.rb +0 -71
  466. data/lib/cucumber/formatter/cucumber.css +0 -286
  467. data/lib/cucumber/formatter/cucumber.sass +0 -247
  468. data/lib/cucumber/formatter/debug.rb +0 -36
  469. data/lib/cucumber/formatter/hook_query_visitor.rb +0 -41
  470. data/lib/cucumber/formatter/html.rb +0 -690
  471. data/lib/cucumber/formatter/jquery-min.js +0 -154
  472. data/lib/cucumber/formatter/json_pretty.rb +0 -11
  473. data/lib/cucumber/formatter/legacy_api/adapter.rb +0 -1012
  474. data/lib/cucumber/formatter/legacy_api/ast.rb +0 -390
  475. data/lib/cucumber/formatter/legacy_api/results.rb +0 -52
  476. data/lib/cucumber/formatter/legacy_api/runtime_facade.rb +0 -32
  477. data/lib/cucumber/rb_support/rb_hook.rb +0 -20
  478. data/lib/cucumber/rb_support/rb_language.rb +0 -227
  479. data/lib/cucumber/rb_support/rb_step_definition.rb +0 -132
  480. data/lib/cucumber/rb_support/rb_transform.rb +0 -60
  481. data/lib/cucumber/rb_support/rb_world.rb +0 -171
  482. data/lib/cucumber/rb_support/snippet.rb +0 -171
  483. data/lib/cucumber/step_argument.rb +0 -26
  484. data/spec/cucumber/cli/configuration_spec.rb +0 -436
  485. data/spec/cucumber/cli/main_spec.rb +0 -84
  486. data/spec/cucumber/cli/options_spec.rb +0 -411
  487. data/spec/cucumber/cli/profile_loader_spec.rb +0 -47
  488. data/spec/cucumber/cli/rerun_spec.rb +0 -86
  489. data/spec/cucumber/configuration_spec.rb +0 -148
  490. data/spec/cucumber/constantize_spec.rb +0 -20
  491. data/spec/cucumber/core_ext/instance_exec_spec.rb +0 -5
  492. data/spec/cucumber/file_specs_spec.rb +0 -61
  493. data/spec/cucumber/filters/activate_steps_spec.rb +0 -152
  494. data/spec/cucumber/filters/gated_receiver_spec.rb +0 -48
  495. data/spec/cucumber/filters/retry_spec.rb +0 -85
  496. data/spec/cucumber/filters/tag_limits/test_case_index_spec.rb +0 -39
  497. data/spec/cucumber/filters/tag_limits/verifier_spec.rb +0 -58
  498. data/spec/cucumber/filters/tag_limits_spec.rb +0 -60
  499. data/spec/cucumber/formatter/ansicolor_spec.rb +0 -33
  500. data/spec/cucumber/formatter/console_counts_spec.rb +0 -14
  501. data/spec/cucumber/formatter/debug_spec.rb +0 -65
  502. data/spec/cucumber/formatter/duration_spec.rb +0 -23
  503. data/spec/cucumber/formatter/fail_fast_spec.rb +0 -88
  504. data/spec/cucumber/formatter/html_spec.rb +0 -543
  505. data/spec/cucumber/formatter/interceptor_spec.rb +0 -137
  506. data/spec/cucumber/formatter/json_spec.rb +0 -842
  507. data/spec/cucumber/formatter/junit_spec.rb +0 -253
  508. data/spec/cucumber/formatter/legacy_api/adapter_spec.rb +0 -2187
  509. data/spec/cucumber/formatter/pretty_spec.rb +0 -920
  510. data/spec/cucumber/formatter/progress_spec.rb +0 -170
  511. data/spec/cucumber/formatter/rerun_spec.rb +0 -97
  512. data/spec/cucumber/formatter/spec_helper.rb +0 -83
  513. data/spec/cucumber/hooks_spec.rb +0 -31
  514. data/spec/cucumber/multiline_argument/data_table_spec.rb +0 -604
  515. data/spec/cucumber/project_initializer_spec.rb +0 -88
  516. data/spec/cucumber/rake/forked_spec.rb +0 -54
  517. data/spec/cucumber/rake/task_spec.rb +0 -86
  518. data/spec/cucumber/rb_support/rb_language_spec.rb +0 -321
  519. data/spec/cucumber/rb_support/rb_step_definition_spec.rb +0 -200
  520. data/spec/cucumber/rb_support/rb_transform_spec.rb +0 -47
  521. data/spec/cucumber/rb_support/rb_world_spec.rb +0 -48
  522. data/spec/cucumber/rb_support/snippet_spec.rb +0 -138
  523. data/spec/cucumber/running_test_case_spec.rb +0 -140
  524. data/spec/cucumber/runtime/for_programming_languages_spec.rb +0 -37
  525. data/spec/cucumber/runtime/support_code_spec.rb +0 -17
  526. data/spec/cucumber/runtime_spec.rb +0 -21
  527. data/spec/cucumber/sell_cucumbers.feature +0 -19
  528. data/spec/cucumber/step_argument_spec.rb +0 -19
  529. data/spec/cucumber/step_match_search_spec.rb +0 -123
  530. data/spec/cucumber/step_match_spec.rb +0 -86
  531. data/spec/cucumber/world/pending_spec.rb +0 -48
  532. data/spec/spec_helper.rb +0 -30
  533. data/spec/support/standard_step_actions.rb +0 -19
@@ -0,0 +1,221 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cucumber/cucumber_expressions/parameter_type_registry'
4
+ require 'cucumber/cucumber_expressions/cucumber_expression'
5
+ require 'cucumber/cucumber_expressions/regular_expression'
6
+ require 'cucumber/cucumber_expressions/cucumber_expression_generator'
7
+ require 'cucumber/glue/dsl'
8
+ require 'cucumber/glue/snippet'
9
+ require 'cucumber/glue/hook'
10
+ require 'cucumber/glue/proto_world'
11
+ require 'cucumber/glue/step_definition'
12
+ require 'cucumber/glue/world_factory'
13
+ require 'cucumber/gherkin/i18n'
14
+ require 'multi_test'
15
+ require 'cucumber/step_match'
16
+ require 'cucumber/step_definition_light'
17
+ require 'cucumber/events/step_definition_registered'
18
+
19
+ module Cucumber
20
+ module Glue
21
+ # Raised if a World block returns Nil.
22
+ class NilWorld < StandardError
23
+ def initialize
24
+ super('World procs should never return nil')
25
+ end
26
+ end
27
+
28
+ # Raised if there are 2 or more World blocks.
29
+ class MultipleWorld < StandardError
30
+ def initialize(first_proc, second_proc)
31
+ message = String.new # rubocop:disable Style/EmptyLiteral
32
+ message << "You can only pass a proc to #World once, but it's happening\n"
33
+ message << "in 2 places:\n\n"
34
+ message << Glue.backtrace_line(first_proc, 'World') << "\n"
35
+ message << Glue.backtrace_line(second_proc, 'World') << "\n\n"
36
+ message << "Use Ruby modules instead to extend your worlds. See the Cucumber::Glue::Dsl#World RDoc\n"
37
+ message << "or http://wiki.github.com/cucumber/cucumber/a-whole-new-world.\n\n"
38
+ super(message)
39
+ end
40
+ end
41
+
42
+ # TODO: This class has too many responsibilities, split off
43
+ class RegistryAndMore
44
+ attr_reader :current_world,
45
+ :step_definitions
46
+
47
+ all_keywords = ::Gherkin::DIALECTS.keys.map do |dialect_name|
48
+ dialect = ::Gherkin::Dialect.for(dialect_name)
49
+ dialect.given_keywords + dialect.when_keywords + dialect.then_keywords + dialect.and_keywords + dialect.but_keywords
50
+ end
51
+ Cucumber::Gherkin::I18n.code_keywords_for(all_keywords.flatten.uniq.sort).each do |adverb|
52
+ Glue::Dsl.alias_adverb(adverb.strip)
53
+ end
54
+
55
+ def initialize(runtime, configuration)
56
+ @runtime = runtime
57
+ @configuration = configuration
58
+ @step_definitions = []
59
+ Glue::Dsl.rb_language = self
60
+ @world_proc = @world_modules = nil
61
+ @parameter_type_registry = CucumberExpressions::ParameterTypeRegistry.new
62
+ cucumber_expression_generator = CucumberExpressions::CucumberExpressionGenerator.new(@parameter_type_registry)
63
+ @configuration.register_snippet_generator(Snippet::Generator.new(cucumber_expression_generator))
64
+ end
65
+
66
+ def step_matches(name_to_match)
67
+ @step_definitions.each_with_object([]) do |step_definition, result|
68
+ if (arguments = step_definition.arguments_from(name_to_match))
69
+ result << StepMatch.new(step_definition, name_to_match, arguments)
70
+ end
71
+ end
72
+ end
73
+
74
+ def register_rb_hook(phase, tag_expressions, proc)
75
+ hook = add_hook(phase, Hook.new(@configuration.id_generator.new_id, self, tag_expressions, proc))
76
+ @configuration.notify :envelope, hook.to_envelope
77
+ hook
78
+ end
79
+
80
+ def define_parameter_type(parameter_type)
81
+ @configuration.notify :envelope, parameter_type_envelope(parameter_type)
82
+
83
+ @parameter_type_registry.define_parameter_type(parameter_type)
84
+ end
85
+
86
+ def register_rb_step_definition(string_or_regexp, proc_or_sym, options)
87
+ step_definition = StepDefinition.new(@configuration.id_generator.new_id, self, string_or_regexp, proc_or_sym, options)
88
+ @step_definitions << step_definition
89
+ @configuration.notify :step_definition_registered, step_definition
90
+ @configuration.notify :envelope, step_definition.to_envelope
91
+ step_definition
92
+ rescue Cucumber::CucumberExpressions::UndefinedParameterTypeError => e
93
+ # TODO: add a way to extract the parameter type directly from the error.
94
+ type_name = e.message.match(/^Undefined parameter type \{(.*)\}$/)[1]
95
+
96
+ @configuration.notify :envelope, Cucumber::Messages::Envelope.new(
97
+ undefined_parameter_type: Cucumber::Messages::UndefinedParameterType.new(
98
+ name: type_name,
99
+ expression: string_or_regexp
100
+ )
101
+ )
102
+ end
103
+
104
+ def build_rb_world_factory(world_modules, namespaced_world_modules, proc)
105
+ if proc
106
+ raise MultipleWorld.new(@world_proc, proc) if @world_proc
107
+ @world_proc = proc
108
+ end
109
+ @world_modules ||= []
110
+ @world_modules += world_modules
111
+
112
+ @namespaced_world_modules ||= Hash.new { |h, k| h[k] = [] }
113
+ namespaced_world_modules.each do |namespace, world_module|
114
+ @namespaced_world_modules[namespace] << world_module unless @namespaced_world_modules[namespace].include?(world_module)
115
+ end
116
+ end
117
+
118
+ def load_code_file(code_file)
119
+ return unless File.extname(code_file) == '.rb'
120
+
121
+ # This will cause self.add_step_definition, self.add_hook, and self.define_parameter_type to be called from Glue::Dsl
122
+
123
+ if Cucumber.use_legacy_autoloader
124
+ load File.expand_path(code_file)
125
+ else
126
+ require File.expand_path(code_file)
127
+ end
128
+ end
129
+
130
+ def begin_scenario(test_case)
131
+ @current_world = WorldFactory.new(@world_proc).create_world
132
+ @current_world.extend(ProtoWorld.for(@runtime, test_case.language))
133
+ MultiTest.extend_with_best_assertion_library(@current_world)
134
+ @current_world.add_modules!(@world_modules || [],
135
+ @namespaced_world_modules || {})
136
+ end
137
+
138
+ def end_scenario
139
+ @current_world = nil
140
+ end
141
+
142
+ def after_configuration(configuration)
143
+ hooks[:after_configuration].each do |hook|
144
+ hook.invoke('AfterConfiguration', configuration)
145
+ end
146
+ end
147
+
148
+ def add_hook(phase, hook)
149
+ hooks[phase.to_sym] << hook
150
+ hook
151
+ end
152
+
153
+ def clear_hooks
154
+ @hooks = nil
155
+ end
156
+
157
+ def hooks_for(phase, scenario) #:nodoc:
158
+ hooks[phase.to_sym].select { |hook| scenario.accept_hook?(hook) }
159
+ end
160
+
161
+ def unmatched_step_definitions
162
+ available_step_definition_hash.keys - invoked_step_definition_hash.keys
163
+ end
164
+
165
+ def available_step_definition(regexp_source, file_colon_line)
166
+ available_step_definition_hash[StepDefinitionLight.new(regexp_source, file_colon_line)] = nil
167
+ end
168
+
169
+ def invoked_step_definition(regexp_source, file_colon_line)
170
+ invoked_step_definition_hash[StepDefinitionLight.new(regexp_source, file_colon_line)] = nil
171
+ end
172
+
173
+ def create_expression(string_or_regexp)
174
+ return CucumberExpressions::CucumberExpression.new(string_or_regexp, @parameter_type_registry) if string_or_regexp.is_a?(String)
175
+ return CucumberExpressions::RegularExpression.new(string_or_regexp, @parameter_type_registry) if string_or_regexp.is_a?(Regexp)
176
+ raise ArgumentError, 'Expression must be a String or Regexp'
177
+ end
178
+
179
+ def self.cli_snippet_type_options
180
+ registry = CucumberExpressions::ParameterTypeRegistry.new
181
+ cucumber_expression_generator = CucumberExpressions::CucumberExpressionGenerator.new(registry)
182
+ Snippet::SNIPPET_TYPES.keys.sort_by(&:to_s).map do |type|
183
+ Snippet::SNIPPET_TYPES[type].cli_option_string(type, cucumber_expression_generator)
184
+ end
185
+ end
186
+
187
+ private
188
+
189
+ def parameter_type_envelope(parameter_type)
190
+ # TODO: should me moved to Cucumber::Expression::ParameterType#to_envelope ?
191
+ # Note: that would mean that cucumber-expression would depend on cucumber-messages
192
+
193
+ Cucumber::Messages::Envelope.new(
194
+ parameter_type: Cucumber::Messages::ParameterType.new(
195
+ name: parameter_type.name,
196
+ regular_expressions: parameter_type.regexps.map(&:to_s),
197
+ prefer_for_regular_expression_match: parameter_type.prefer_for_regexp_match?,
198
+ use_for_snippets: parameter_type.use_for_snippets?
199
+ )
200
+ )
201
+ end
202
+
203
+ def available_step_definition_hash
204
+ @available_step_definition_hash ||= {}
205
+ end
206
+
207
+ def invoked_step_definition_hash
208
+ @invoked_step_definition_hash ||= {}
209
+ end
210
+
211
+ def hooks
212
+ @hooks ||= Hash.new { |h, k| h[k] = [] }
213
+ end
214
+ end
215
+
216
+ def self.backtrace_line(proc, name)
217
+ location = Cucumber::Core::Test::Location.from_source_location(*proc.source_location)
218
+ "#{location}:in `#{name}'"
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,205 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cucumber
4
+ module Glue
5
+ module Snippet
6
+ ARGUMENT_PATTERNS = ['"([^"]*)"', '(\d+)'].freeze
7
+
8
+ class Generator
9
+ def self.register_on(configuration)
10
+ configuration.snippet_generators << new
11
+ end
12
+
13
+ def initialize(cucumber_expression_generator)
14
+ @cucumber_expression_generator = cucumber_expression_generator
15
+ end
16
+
17
+ def call(code_keyword, step_name, multiline_arg, snippet_type)
18
+ snippet_class = typed_snippet_class(snippet_type)
19
+ snippet_class.new(@cucumber_expression_generator, code_keyword, step_name, multiline_arg).to_s
20
+ end
21
+
22
+ def typed_snippet_class(type)
23
+ SNIPPET_TYPES.fetch(type || :cucumber_expression)
24
+ end
25
+ end
26
+
27
+ class BaseSnippet
28
+ def initialize(cucumber_expression_generator, code_keyword, step_name, multiline_argument)
29
+ @number_of_arguments = 0
30
+ @code_keyword = code_keyword
31
+ @pattern = replace_and_count_capturing_groups(step_name)
32
+ @generated_expressions = cucumber_expression_generator.generate_expressions(step_name)
33
+ @multiline_argument = MultilineArgumentSnippet.new(multiline_argument)
34
+ end
35
+
36
+ def to_s
37
+ "#{step} #{do_block}"
38
+ end
39
+
40
+ def step
41
+ "#{code_keyword}#{typed_pattern}"
42
+ end
43
+
44
+ def self.cli_option_string(type, cucumber_expression_generator)
45
+ format('%<type>-7s: %<description>-28s e.g. %<example>s', type: type, description: description, example: example(cucumber_expression_generator))
46
+ end
47
+
48
+ private
49
+
50
+ attr_reader :code_keyword, :pattern, :generated_expressions, :multiline_argument, :number_of_arguments
51
+
52
+ def replace_and_count_capturing_groups(pattern)
53
+ modified_pattern = ::Regexp.escape(pattern).gsub('\ ', ' ').gsub('/', '\/')
54
+
55
+ ARGUMENT_PATTERNS.each do |argument_pattern|
56
+ modified_pattern.gsub!(::Regexp.new(argument_pattern), argument_pattern)
57
+ @number_of_arguments += modified_pattern.scan(argument_pattern).length
58
+ end
59
+
60
+ modified_pattern
61
+ end
62
+
63
+ def do_block
64
+ do_block = String.new # rubocop:disable Style/EmptyLiteral
65
+ do_block << "do#{parameters}\n"
66
+ multiline_argument.append_comment_to(do_block)
67
+ do_block << " pending # Write code here that turns the phrase above into concrete actions\n"
68
+ do_block << 'end'
69
+ do_block
70
+ end
71
+
72
+ def parameters
73
+ block_args = (0...number_of_arguments).map { |n| "arg#{n + 1}" }
74
+ multiline_argument.append_block_parameter_to(block_args)
75
+ block_args.empty? ? '' : " |#{block_args.join(', ')}|"
76
+ end
77
+
78
+ class << self
79
+ private
80
+
81
+ def example(cucumber_expression_generator)
82
+ new(cucumber_expression_generator, 'Given', 'I have 2 cukes', MultilineArgument::None.new).step
83
+ end
84
+ end
85
+ end
86
+
87
+ class CucumberExpression < BaseSnippet
88
+ def typed_pattern
89
+ "(\"#{generated_expressions[0].source}\")"
90
+ end
91
+
92
+ def to_s
93
+ header = generated_expressions.each_with_index.map do |expr, i|
94
+ prefix = i.zero? ? '' : '# '
95
+ "#{prefix}#{code_keyword}('#{expr.source}') do#{parameters(expr)}"
96
+ end.join("\n")
97
+
98
+ body = String.new # rubocop:disable Style/EmptyLiteral
99
+ multiline_argument.append_comment_to(body)
100
+ body << " pending # Write code here that turns the phrase above into concrete actions\n"
101
+ body << 'end'
102
+
103
+ "#{header}\n#{body}"
104
+ end
105
+
106
+ def parameters(expr)
107
+ parameter_names = expr.parameter_names
108
+ multiline_argument.append_block_parameter_to(parameter_names)
109
+ parameter_names.empty? ? '' : " |#{parameter_names.join(', ')}|"
110
+ end
111
+
112
+ def self.description
113
+ 'Cucumber Expressions'
114
+ end
115
+ end
116
+
117
+ class Regexp < BaseSnippet
118
+ def typed_pattern
119
+ "(/^#{pattern}$/)"
120
+ end
121
+
122
+ def self.description
123
+ 'Snippets with parentheses'
124
+ end
125
+ end
126
+
127
+ class Classic < BaseSnippet
128
+ def typed_pattern
129
+ " /^#{pattern}$/"
130
+ end
131
+
132
+ def self.description
133
+ 'Snippets without parentheses. Note that these cause a warning from modern versions of Ruby.'
134
+ end
135
+ end
136
+
137
+ class Percent < BaseSnippet
138
+ def typed_pattern
139
+ " %r{^#{pattern}$}"
140
+ end
141
+
142
+ def self.description
143
+ 'Snippets with percent regexp'
144
+ end
145
+ end
146
+
147
+ SNIPPET_TYPES = {
148
+ cucumber_expression: CucumberExpression,
149
+ regexp: Regexp,
150
+ classic: Classic,
151
+ percent: Percent
152
+ }.freeze
153
+
154
+ module MultilineArgumentSnippet
155
+ def self.new(multiline_argument)
156
+ builder = Builder.new
157
+ multiline_argument.describe_to(builder)
158
+ builder.result
159
+ end
160
+
161
+ class Builder
162
+ def doc_string(*_args)
163
+ @result = DocString.new
164
+ end
165
+
166
+ def data_table(table, *_args)
167
+ @result = DataTable.new(table)
168
+ end
169
+
170
+ def result
171
+ @result || None.new
172
+ end
173
+ end
174
+
175
+ class DocString
176
+ def append_block_parameter_to(array)
177
+ array << 'string'
178
+ end
179
+
180
+ def append_comment_to(string); end
181
+ end
182
+
183
+ class DataTable
184
+ def initialize(table)
185
+ @table = table
186
+ end
187
+
188
+ def append_block_parameter_to(array)
189
+ array << 'table'
190
+ end
191
+
192
+ def append_comment_to(string)
193
+ string << " # table is a #{Cucumber::MultilineArgument::DataTable}\n"
194
+ end
195
+ end
196
+
197
+ class None
198
+ def append_block_parameter_to(array); end
199
+
200
+ def append_comment_to(string); end
201
+ end
202
+ end
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cucumber/step_match'
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
+ class MissingProc < StandardError
21
+ def message
22
+ 'Step definitions must always have a proc or symbol'
23
+ end
24
+ end
25
+
26
+ class << self
27
+ def new(id, registry, string_or_regexp, proc_or_sym, options)
28
+ raise MissingProc if proc_or_sym.nil?
29
+ super id, registry, registry.create_expression(string_or_regexp), create_proc(proc_or_sym, options)
30
+ end
31
+
32
+ private
33
+
34
+ def create_proc(proc_or_sym, options)
35
+ return proc_or_sym if proc_or_sym.is_a?(Proc)
36
+ raise ArgumentError unless proc_or_sym.is_a?(Symbol)
37
+ message = proc_or_sym
38
+ target_proc = parse_target_proc_from(options)
39
+ patch_location_onto lambda { |*args|
40
+ target = instance_exec(&target_proc)
41
+ target.send(message, *args)
42
+ }
43
+ end
44
+
45
+ def patch_location_onto(block)
46
+ location = Core::Test::Location.of_caller(5)
47
+ block.define_singleton_method(:source_location) { [location.file, location.line] }
48
+ block
49
+ end
50
+
51
+ def parse_target_proc_from(options)
52
+ return -> { self } unless options.key?(:on)
53
+ target = options[:on]
54
+ case target
55
+ when Proc
56
+ target
57
+ when Symbol
58
+ -> { send(target) }
59
+ else
60
+ -> { raise ArgumentError, 'Target must be a symbol or a proc' }
61
+ end
62
+ end
63
+ end
64
+
65
+ attr_reader :id, :expression, :registry
66
+
67
+ def initialize(id, registry, expression, proc)
68
+ raise 'No regexp' if expression.is_a?(Regexp)
69
+ @id = id
70
+ @registry = registry
71
+ @expression = expression
72
+ @proc = proc
73
+ # @registry.available_step_definition(regexp_source, location)
74
+ end
75
+
76
+ def to_envelope
77
+ Cucumber::Messages::Envelope.new(
78
+ step_definition: Cucumber::Messages::StepDefinition.new(
79
+ id: id,
80
+ pattern: Cucumber::Messages::StepDefinitionPattern.new(
81
+ source: expression.source.to_s,
82
+ type: expression_type
83
+ ),
84
+ source_reference: Cucumber::Messages::SourceReference.new(
85
+ uri: location.file,
86
+ location: Cucumber::Messages::Location.new(
87
+ line: location.lines.first
88
+ )
89
+ )
90
+ )
91
+ )
92
+ end
93
+
94
+ def expression_type
95
+ return Cucumber::Messages::StepDefinitionPatternType::CUCUMBER_EXPRESSION if expression.is_a?(CucumberExpressions::CucumberExpression)
96
+ Cucumber::Messages::StepDefinitionPatternType::REGULAR_EXPRESSION
97
+ end
98
+
99
+ # @api private
100
+ def to_hash
101
+ type = expression.is_a?(CucumberExpressions::RegularExpression) ? 'regular expression' : 'cucumber expression'
102
+ regexp = expression.regexp
103
+ flags = ''
104
+ flags += 'm' if (regexp.options & Regexp::MULTILINE) != 0
105
+ flags += 'i' if (regexp.options & Regexp::IGNORECASE) != 0
106
+ flags += 'x' if (regexp.options & Regexp::EXTENDED) != 0
107
+ {
108
+ source: {
109
+ type: type,
110
+ expression: expression.source
111
+ },
112
+ regexp: {
113
+ source: regexp.source,
114
+ flags: flags
115
+ }
116
+ }
117
+ end
118
+
119
+ # @api private
120
+ def ==(other)
121
+ expression.source == other.expression.source
122
+ end
123
+
124
+ # @api private
125
+ def arguments_from(step_name)
126
+ args = @expression.match(step_name)
127
+ # @registry.invoked_step_definition(regexp_source, location) if args
128
+ args
129
+ end
130
+
131
+ # @api private
132
+ # TODO: inline this and step definition just be a value object
133
+ def invoke(args)
134
+ InvokeInWorld.cucumber_instance_exec_in(@registry.current_world, true, @expression.to_s, *args, &@proc)
135
+ rescue ArityMismatchError => e
136
+ e.backtrace.unshift(backtrace_line)
137
+ raise e
138
+ end
139
+
140
+ # @api private
141
+ def backtrace_line
142
+ "#{location}:in `#{@expression}'"
143
+ end
144
+
145
+ # @api private
146
+ def file_colon_line
147
+ case @proc
148
+ when Proc
149
+ location.to_s
150
+ when Symbol
151
+ ":#{@proc}"
152
+ end
153
+ end
154
+
155
+ # The source location where the step definition can be found
156
+ def location
157
+ @location ||= Cucumber::Core::Test::Location.from_source_location(*@proc.source_location)
158
+ end
159
+
160
+ # @api private
161
+ def file
162
+ @file ||= location.file
163
+ end
164
+ end
165
+ end
166
+ end