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
@@ -6,51 +6,33 @@ module Cucumber
6
6
  include Console
7
7
 
8
8
  def initialize(config)
9
- @test_case_summary = Core::Test::Result::Summary.new
10
- @test_step_summary = Core::Test::Result::Summary.new
11
-
12
- config.on_event :test_case_finished do |event|
13
- event.result.describe_to @test_case_summary
14
- end
15
-
16
- config.on_event :test_step_finished do |event|
17
- event.result.describe_to @test_step_summary if from_gherkin?(event.test_step)
18
- end
9
+ @summary = Core::Report::Summary.new(config.event_bus)
19
10
  end
20
11
 
21
12
  def to_s
22
13
  [
23
- [scenario_count, status_counts(@test_case_summary)].compact.join(" "),
24
- [step_count, status_counts(@test_step_summary)].compact.join(" ")
14
+ [scenario_count, status_counts(@summary.test_cases)].compact.join(' '),
15
+ [step_count, status_counts(@summary.test_steps)].compact.join(' ')
25
16
  ].join("\n")
26
17
  end
27
18
 
28
19
  private
29
20
 
30
- def from_gherkin?(test_step)
31
- test_step.source.last.location.file.match(/\.feature$/)
32
- end
33
-
34
21
  def scenario_count
35
- count = @test_case_summary.total
36
- "#{count} scenario" + (count == 1 ? "" : "s")
22
+ count = @summary.test_cases.total
23
+ "#{count} scenario" + (count == 1 ? '' : 's')
37
24
  end
38
25
 
39
26
  def step_count
40
- count = @test_step_summary.total
41
- "#{count} step" + (count == 1 ? "" : "s")
27
+ count = @summary.test_steps.total
28
+ "#{count} step" + (count == 1 ? '' : 's')
42
29
  end
43
30
 
44
31
  def status_counts(summary)
45
- counts = [:failed, :skipped, :undefined, :pending, :passed].map { |status|
46
- count = summary.total(status)
47
- [status, count]
48
- }.select { |status, count|
49
- count > 0
50
- }.map { |status, count|
51
- format_string("#{count} #{status}", status)
52
- }
53
- "(#{counts.join(", ")})" if counts.any?
32
+ counts = Core::Test::Result::TYPES.map { |status| [status, summary.total(status)] }
33
+ counts = counts.select { |_status, count| count > 0 }
34
+ counts = counts.map { |status, count| format_string("#{count} #{status}", status) }
35
+ "(#{counts.join(', ')})" if counts.any?
54
36
  end
55
37
  end
56
38
  end
@@ -5,29 +5,53 @@ module Cucumber
5
5
  class ConsoleIssues
6
6
  include Console
7
7
 
8
- def initialize(config)
9
- @failures = []
8
+ def initialize(config, ast_lookup = AstLookup.new(config))
9
+ @previous_test_case = nil
10
+ @issues = Hash.new { |h, k| h[k] = [] }
10
11
  @config = config
11
12
  @config.on_event(:test_case_finished) do |event|
12
- @failures << event.test_case if event.result.failed?
13
+ if event.test_case != @previous_test_case
14
+ @previous_test_case = event.test_case
15
+ @issues[event.result.to_sym] << event.test_case unless event.result.ok?(@config.strict)
16
+ elsif event.result.passed?
17
+ @issues[:flaky] << event.test_case unless Core::Test::Result::Flaky.ok?(@config.strict.strict?(:flaky))
18
+ @issues[:failed].delete(event.test_case)
19
+ end
13
20
  end
21
+ @ast_lookup = ast_lookup
14
22
  end
15
23
 
16
24
  def to_s
17
- return if @failures.empty?
18
- result = [ format_string("Failing Scenarios:", :failed) ] + @failures.map { |failure|
19
- source = @config.source? ? format_string(" # #{failure.keyword}: #{failure.name}", :comment) : ''
20
- format_string("cucumber #{profiles_string}" + failure.location, :failed) + source
21
- }
22
- result.join("\n")
25
+ return if @issues.empty?
26
+ result = Core::Test::Result::TYPES.map { |type| scenario_listing(type, @issues[type]) }
27
+ result.flatten.join("\n")
23
28
  end
24
29
 
25
30
  def any?
26
- @failures.any?
31
+ @issues.any?
27
32
  end
28
33
 
29
34
  private
30
35
 
36
+ def scenario_listing(type, test_cases)
37
+ return [] if test_cases.empty?
38
+ [format_string("#{type_heading(type)} Scenarios:", type)] + test_cases.map do |test_case|
39
+ scenario_source = @ast_lookup.scenario_source(test_case)
40
+ keyword = scenario_source.type == :Scenario ? scenario_source.scenario.keyword : scenario_source.scenario_outline.keyword
41
+ source = @config.source? ? format_string(" # #{keyword}: #{test_case.name}", :comment) : ''
42
+ format_string("cucumber #{profiles_string}#{test_case.location.file}:#{test_case.location.lines.max}", type) + source
43
+ end
44
+ end
45
+
46
+ def type_heading(type)
47
+ case type
48
+ when :failed
49
+ 'Failing'
50
+ else
51
+ type.to_s.slice(0, 1).capitalize + type.to_s.slice(1..-1)
52
+ end
53
+ end
54
+
31
55
  def profiles_string
32
56
  return if @config.custom_profiles.empty?
33
57
  @config.custom_profiles.map { |profile| "-p #{profile}" }.join(' ') + ' '
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Cucumber
3
4
  module Formatter
4
5
  module Duration
@@ -7,7 +8,7 @@ module Cucumber
7
8
  # <tt>time</tt> format.
8
9
  def format_duration(seconds)
9
10
  m, s = seconds.divmod(60)
10
- "#{m}m#{'%.3f' % s}s"
11
+ "#{m}m#{format('%<seconds>.3f', seconds: s)}s"
11
12
  end
12
13
  end
13
14
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Cucumber
3
4
  module Formatter
4
-
5
5
  class DurationExtractor
6
6
  attr_reader :result_duration
7
7
  def initialize(result)
@@ -22,8 +22,10 @@ module Cucumber
22
22
  def exception(*) end
23
23
 
24
24
  def duration(duration, *)
25
- duration.tap { |duration| @result_duration = duration.nanoseconds / 10**9.0 }
25
+ duration.tap { |dur| @result_duration = dur.nanoseconds / 10**9.0 }
26
26
  end
27
+
28
+ def attach(*) end
27
29
  end
28
30
  end
29
31
  end
@@ -0,0 +1,6 @@
1
+ module Cucumber
2
+ module Formatter
3
+ class TestCaseUnknownError < StandardError; end
4
+ class TestStepUnknownError < StandardError; end
5
+ end
6
+ end
@@ -1,20 +1,23 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'cucumber/formatter/io'
3
4
  require 'cucumber/formatter/console'
4
5
 
5
6
  module Cucumber
6
7
  module Formatter
7
-
8
8
  class FailFast
9
-
10
9
  def initialize(configuration)
10
+ @previous_test_case = nil
11
11
  configuration.on_event :test_case_finished do |event|
12
12
  test_case, result = *event.attributes
13
- Cucumber.wants_to_quit = true unless result.ok?(configuration.strict?)
13
+ if test_case != @previous_test_case
14
+ @previous_test_case = event.test_case
15
+ Cucumber.wants_to_quit = true unless result.ok?(configuration.strict)
16
+ elsif result.passed?
17
+ Cucumber.wants_to_quit = false
18
+ end
14
19
  end
15
20
  end
16
-
17
21
  end
18
-
19
22
  end
20
23
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Cucumber
3
4
  module Formatter
4
-
5
5
  # Forwards any messages sent to this object to all recipients
6
6
  # that respond to that message.
7
7
  class Fanout < BasicObject
@@ -13,6 +13,8 @@ module Cucumber
13
13
  end
14
14
 
15
15
  def method_missing(message, *args)
16
+ super unless recipients
17
+
16
18
  recipients.each do |recipient|
17
19
  recipient.send(message, *args) if recipient.respond_to?(message)
18
20
  end
@@ -21,8 +23,6 @@ module Cucumber
21
23
  def respond_to_missing?(name, include_private = false)
22
24
  recipients.any? { |recipient| recipient.respond_to?(name, include_private) }
23
25
  end
24
-
25
26
  end
26
-
27
27
  end
28
28
  end
@@ -1,21 +1,19 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Cucumber
3
4
  module Formatter
4
-
5
5
  class IgnoreMissingMessages < BasicObject
6
6
  def initialize(receiver)
7
7
  @receiver = receiver
8
8
  end
9
9
 
10
10
  def method_missing(message, *args)
11
- @receiver.send(message, *args) if @receiver.respond_to?(message)
11
+ @receiver.respond_to?(message) ? @receiver.send(message, *args) : super
12
12
  end
13
13
 
14
14
  def respond_to_missing?(name, include_private = false)
15
15
  @receiver.respond_to?(name, include_private)
16
16
  end
17
17
  end
18
-
19
18
  end
20
19
  end
21
-
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require 'thread'
3
2
 
4
3
  module Cucumber
5
4
  module Formatter
@@ -8,20 +7,20 @@ module Cucumber
8
7
  attr_reader :pipe
9
8
  def initialize(pipe)
10
9
  @pipe = pipe
11
- @buffer = []
10
+ @buffer = StringIO.new
12
11
  @wrapped = true
13
12
  end
14
13
 
15
14
  def write(str)
16
- lock.synchronize do
15
+ lock.synchronize do
17
16
  @buffer << str if @wrapped
18
17
  return @pipe.write(str)
19
18
  end
20
19
  end
21
20
 
22
- def buffer
21
+ def buffer_string
23
22
  lock.synchronize do
24
- return @buffer.dup
23
+ return @buffer.string.dup
25
24
  end
26
25
  end
27
26
 
@@ -31,17 +30,15 @@ module Cucumber
31
30
  end
32
31
 
33
32
  def method_missing(method, *args, &blk)
34
- @pipe.send(method, *args, &blk)
33
+ @pipe.send(method, *args, &blk) || super
35
34
  end
36
35
 
37
- def respond_to?(method, include_private=false)
36
+ def respond_to_missing?(method, include_private = false)
38
37
  super || @pipe.respond_to?(method, include_private)
39
38
  end
40
39
 
41
40
  def self.validate_pipe(pipe)
42
- unless [:stdout, :stderr].include? pipe
43
- raise ArgumentError, '#wrap only accepts :stderr or :stdout'
44
- end
41
+ raise ArgumentError, '#wrap only accepts :stderr or :stdout' unless %i[stdout stderr].include? pipe
45
42
  end
46
43
 
47
44
  def self.unwrap!(pipe)
@@ -63,17 +60,18 @@ module Cucumber
63
60
 
64
61
  case pipe
65
62
  when :stderr
66
- $stderr = self.new($stderr)
63
+ $stderr = new($stderr)
67
64
  return $stderr
68
65
  when :stdout
69
- $stdout = self.new($stdout)
66
+ $stdout = new($stdout)
70
67
  return $stdout
71
68
  end
72
69
  end
73
70
 
74
- private
71
+ private
72
+
75
73
  def lock
76
- @lock||=Mutex.new
74
+ @lock ||= Mutex.new
77
75
  end
78
76
  end
79
77
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Cucumber
3
4
  module Formatter
4
5
  module Io
@@ -18,17 +19,17 @@ module Cucumber
18
19
  end
19
20
 
20
21
  def ensure_file(path, name)
21
- raise "You *must* specify --out FILE for the #{name} formatter" unless String === path
22
+ raise "You *must* specify --out FILE for the #{name} formatter" unless String == path.class
22
23
  raise "I can't write #{name} to a directory - it has to be a file" if File.directory?(path)
23
- raise "I can't write #{name} to a file in the non-existing directory #{File.dirname(path)}" if !File.directory?(File.dirname(path))
24
+ raise "I can't write #{name} to a file in the non-existing directory #{File.dirname(path)}" unless File.directory?(File.dirname(path))
24
25
  ensure_io(path)
25
26
  end
26
27
 
27
28
  def ensure_dir(path, name)
28
- raise "You *must* specify --out DIR for the #{name} formatter" unless String === path
29
+ raise "You *must* specify --out DIR for the #{name} formatter" unless String == path.class
29
30
  raise "I can't write #{name} reports to a file - it has to be a directory" if File.file?(path)
30
31
  FileUtils.mkdir_p(path) unless File.directory?(path)
31
- path
32
+ File.absolute_path path
32
33
  end
33
34
  end
34
35
  end
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'multi_json'
3
4
  require 'base64'
4
5
  require 'cucumber/formatter/backtrace_filter'
5
6
  require 'cucumber/formatter/io'
6
- require 'cucumber/formatter/hook_query_visitor'
7
+ require 'cucumber/formatter/ast_lookup'
8
+ require 'cucumber/deprecate'
7
9
 
8
10
  module Cucumber
9
11
  module Formatter
@@ -12,47 +14,59 @@ module Cucumber
12
14
  include Io
13
15
 
14
16
  def initialize(config)
17
+ Cucumber::Deprecate::CliOption.deprecate(
18
+ config.error_stream,
19
+ '--format=json',
20
+ "Please use --format=message and stand-alone json-formatter.\n" \
21
+ 'json-formatter homepage: https://github.com/cucumber/cucumber/tree/master/json-formatter#cucumber-json-formatter',
22
+ '5.0.0'
23
+ )
24
+
15
25
  @io = ensure_io(config.out_stream)
26
+ @ast_lookup = AstLookup.new(config)
16
27
  @feature_hashes = []
17
- config.on_event :test_case_starting, &method(:on_test_case_starting)
28
+ @step_or_hook_hash = {}
29
+ config.on_event :test_case_started, &method(:on_test_case_started)
18
30
  config.on_event :test_case_finished, &method(:on_test_case_finished)
19
- config.on_event :test_step_starting, &method(:on_test_step_starting)
31
+ config.on_event :test_step_started, &method(:on_test_step_started)
20
32
  config.on_event :test_step_finished, &method(:on_test_step_finished)
21
33
  config.on_event :test_run_finished, &method(:on_test_run_finished)
22
34
  end
23
35
 
24
- def on_test_case_starting(event)
36
+ def on_test_case_started(event)
25
37
  test_case = event.test_case
26
- builder = Builder.new(test_case)
27
- unless same_feature_as_previous_test_case?(test_case.feature)
38
+ builder = Builder.new(test_case, @ast_lookup)
39
+ unless same_feature_as_previous_test_case?(test_case)
28
40
  @feature_hash = builder.feature_hash
29
41
  @feature_hashes << @feature_hash
30
42
  end
31
43
  @test_case_hash = builder.test_case_hash
32
44
  if builder.background?
45
+ @in_background = true
33
46
  feature_elements << builder.background_hash
34
47
  @element_hash = builder.background_hash
35
48
  else
49
+ @in_background = false
36
50
  feature_elements << @test_case_hash
37
51
  @element_hash = @test_case_hash
38
52
  end
39
53
  @any_step_failed = false
40
54
  end
41
55
 
42
- def on_test_step_starting(event)
56
+ def on_test_step_started(event)
43
57
  test_step = event.test_step
44
58
  return if internal_hook?(test_step)
45
- hook_query = HookQueryVisitor.new(test_step)
46
- if hook_query.hook?
59
+ if test_step.hook?
47
60
  @step_or_hook_hash = {}
48
- hooks_of_type(hook_query) << @step_or_hook_hash
61
+ hooks_of_type(test_step) << @step_or_hook_hash
49
62
  return
50
63
  end
51
64
  if first_step_after_background?(test_step)
65
+ @in_background = false
52
66
  feature_elements << @test_case_hash
53
67
  @element_hash = @test_case_hash
54
68
  end
55
- @step_or_hook_hash = create_step_hash(test_step.source.last)
69
+ @step_or_hook_hash = create_step_hash(test_step)
56
70
  steps << @step_or_hook_hash
57
71
  @step_hash = @step_or_hook_hash
58
72
  end
@@ -66,50 +80,48 @@ module Cucumber
66
80
  end
67
81
 
68
82
  def on_test_case_finished(event)
69
- test_case, result = *event.attributes
83
+ _test_case, result = *event.attributes
70
84
  result = result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)
71
85
  add_failed_around_hook(result) if result.failed? && !@any_step_failed
72
86
  end
73
87
 
74
- def on_test_run_finished(event)
88
+ def on_test_run_finished(_event)
75
89
  @io.write(MultiJson.dump(@feature_hashes, pretty: true))
76
90
  end
77
91
 
78
- def puts(message)
79
- test_step_output << message
80
- end
81
-
82
- def embed(src, mime_type, _label)
92
+ def attach(src, mime_type)
93
+ if mime_type == 'text/x.cucumber.log+plain'
94
+ test_step_output << src
95
+ return
96
+ end
83
97
  if File.file?(src)
84
- content = File.open(src, 'rb') { |f| f.read }
98
+ content = File.open(src, 'rb', &:read)
85
99
  data = encode64(content)
100
+ elsif mime_type =~ /;base64$/
101
+ mime_type = mime_type[0..-8]
102
+ data = src
86
103
  else
87
- if mime_type =~ /;base64$/
88
- mime_type = mime_type[0..-8]
89
- data = src
90
- else
91
- data = encode64(src)
92
- end
104
+ data = encode64(src)
93
105
  end
94
106
  test_step_embeddings << { mime_type: mime_type, data: data }
95
107
  end
96
108
 
97
109
  private
98
110
 
99
- def same_feature_as_previous_test_case?(feature)
100
- current_feature[:uri] == feature.file && current_feature[:line] == feature.location.line
111
+ def same_feature_as_previous_test_case?(test_case)
112
+ current_feature[:uri] == test_case.location.file
101
113
  end
102
114
 
103
115
  def first_step_after_background?(test_step)
104
- test_step.source[1].name != @element_hash[:name]
116
+ @in_background && test_step.location.lines.max >= @test_case_hash[:line]
105
117
  end
106
118
 
107
119
  def internal_hook?(test_step)
108
- test_step.source.last.location.file.include?('lib/cucumber/')
120
+ test_step.location.file.include?('lib/cucumber/')
109
121
  end
110
122
 
111
123
  def current_feature
112
- @feature_hash ||= {}
124
+ @feature_hash ||= {} # rubocop:disable Naming/MemoizedInstanceVariableName
113
125
  end
114
126
 
115
127
  def feature_elements
@@ -120,16 +132,16 @@ module Cucumber
120
132
  @element_hash[:steps] ||= []
121
133
  end
122
134
 
123
- def hooks_of_type(hook_query)
124
- case hook_query.type
125
- when :before
126
- return before_hooks
127
- when :after
128
- return after_hooks
129
- when :after_step
130
- return after_step_hooks
135
+ def hooks_of_type(hook_step)
136
+ case hook_step.text
137
+ when 'Before hook'
138
+ before_hooks
139
+ when 'After hook'
140
+ after_hooks
141
+ when 'AfterStep hook'
142
+ after_step_hooks
131
143
  else
132
- fail 'Unkown hook type ' + hook_query.type.to_s
144
+ raise 'Unknown hook type ' + hook_step.to_s
133
145
  end
134
146
  end
135
147
 
@@ -157,20 +169,20 @@ module Cucumber
157
169
  @step_or_hook_hash[:embeddings] ||= []
158
170
  end
159
171
 
160
- def create_step_hash(step_source)
172
+ def create_step_hash(test_step)
173
+ step_source = @ast_lookup.step_source(test_step).step
161
174
  step_hash = {
162
175
  keyword: step_source.keyword,
163
- name: step_source.name,
164
- line: step_source.location.line
176
+ name: test_step.text,
177
+ line: test_step.location.lines.min
165
178
  }
166
- step_hash[:comments] = Formatter.create_comments_array(step_source.comments) unless step_source.comments.empty?
167
- step_hash[:doc_string] = create_doc_string_hash(step_source.multiline_arg) if step_source.multiline_arg.doc_string?
168
- step_hash[:rows] = create_data_table_value(step_source.multiline_arg) if step_source.multiline_arg.data_table?
179
+ step_hash[:doc_string] = create_doc_string_hash(step_source.doc_string) unless step_source.doc_string.nil?
180
+ step_hash[:rows] = create_data_table_value(step_source.data_table) unless step_source.data_table.nil?
169
181
  step_hash
170
182
  end
171
183
 
172
184
  def create_doc_string_hash(doc_string)
173
- content_type = doc_string.content_type ? doc_string.content_type : ""
185
+ content_type = doc_string.media_type || ''
174
186
  {
175
187
  value: doc_string.content,
176
188
  content_type: content_type,
@@ -179,25 +191,26 @@ module Cucumber
179
191
  end
180
192
 
181
193
  def create_data_table_value(data_table)
182
- data_table.raw.map do |row|
183
- { cells: row }
194
+ data_table.rows.map do |row|
195
+ { cells: row.cells.map(&:value) }
184
196
  end
185
197
  end
186
198
 
187
199
  def add_match_and_result(test_step, result)
188
200
  @step_or_hook_hash[:match] = create_match_hash(test_step, result)
189
201
  @step_or_hook_hash[:result] = create_result_hash(result)
202
+ result.embeddings.each { |e| embed(e['src'], e['mime_type'], e['label']) } if result.respond_to?(:embeddings)
190
203
  end
191
204
 
192
205
  def add_failed_around_hook(result)
193
206
  @step_or_hook_hash = {}
194
207
  around_hooks << @step_or_hook_hash
195
- @step_or_hook_hash[:match] = { location: "unknown_hook_location:1" }
208
+ @step_or_hook_hash[:match] = { location: 'unknown_hook_location:1' }
196
209
 
197
210
  @step_or_hook_hash[:result] = create_result_hash(result)
198
211
  end
199
212
 
200
- def create_match_hash(test_step, result)
213
+ def create_match_hash(test_step, _result)
201
214
  { location: test_step.action_location.to_s }
202
215
  end
203
216
 
@@ -218,119 +231,100 @@ module Cucumber
218
231
 
219
232
  def encode64(data)
220
233
  # strip newlines from the encoded data
221
- Base64.encode64(data).gsub(/\n/, '')
234
+ Base64.encode64(data).delete("\n")
222
235
  end
223
236
 
224
237
  class Builder
225
238
  attr_reader :feature_hash, :background_hash, :test_case_hash
226
239
 
227
- def initialize(test_case)
240
+ def initialize(test_case, ast_lookup)
228
241
  @background_hash = nil
229
- test_case.describe_source_to(self)
230
- test_case.feature.background.describe_to(self)
242
+ uri = test_case.location.file
243
+ feature = ast_lookup.gherkin_document(uri).feature
244
+ feature(feature, uri)
245
+ background(feature.children.first.background) unless feature.children.first.background.nil?
246
+ scenario(ast_lookup.scenario_source(test_case), test_case)
231
247
  end
232
248
 
233
249
  def background?
234
250
  @background_hash != nil
235
251
  end
236
252
 
237
- def feature(feature)
253
+ def feature(feature, uri)
238
254
  @feature_hash = {
239
- uri: feature.file,
240
- id: create_id(feature),
255
+ id: create_id(feature.name),
256
+ uri: uri,
241
257
  keyword: feature.keyword,
242
258
  name: feature.name,
243
- description: feature.description,
259
+ description: value_or_empty_string(feature.description),
244
260
  line: feature.location.line
245
261
  }
246
- unless feature.tags.empty?
247
- @feature_hash[:tags] = create_tags_array(feature.tags)
248
- if @test_case_hash[:tags]
249
- @test_case_hash[:tags] = @feature_hash[:tags] + @test_case_hash[:tags]
250
- else
251
- @test_case_hash[:tags] = @feature_hash[:tags]
252
- end
253
- end
254
- @feature_hash[:comments] = Formatter.create_comments_array(feature.comments) unless feature.comments.empty?
255
- @test_case_hash[:id].insert(0, @feature_hash[:id] + ';')
262
+ return if feature.tags.empty?
263
+ @feature_hash[:tags] = create_tags_array_from_hash_array(feature.tags)
256
264
  end
257
265
 
258
266
  def background(background)
259
267
  @background_hash = {
260
268
  keyword: background.keyword,
261
269
  name: background.name,
262
- description: background.description,
270
+ description: value_or_empty_string(background.description),
263
271
  line: background.location.line,
264
272
  type: 'background'
265
273
  }
266
- @background_hash[:comments] = Formatter.create_comments_array(background.comments) unless background.comments.empty?
267
274
  end
268
275
 
269
- def scenario(scenario)
276
+ def scenario(scenario_source, test_case)
277
+ scenario = scenario_source.type == :Scenario ? scenario_source.scenario : scenario_source.scenario_outline
270
278
  @test_case_hash = {
271
- id: create_id(scenario),
279
+ id: "#{@feature_hash[:id]};#{create_id_from_scenario_source(scenario_source)}",
272
280
  keyword: scenario.keyword,
273
- name: scenario.name,
274
- description: scenario.description,
275
- line: scenario.location.line,
281
+ name: test_case.name,
282
+ description: value_or_empty_string(scenario.description),
283
+ line: test_case.location.lines.max,
276
284
  type: 'scenario'
277
285
  }
278
- @test_case_hash[:tags] = create_tags_array(scenario.tags) unless scenario.tags.empty?
279
- @test_case_hash[:comments] = Formatter.create_comments_array(scenario.comments) unless scenario.comments.empty?
286
+ @test_case_hash[:tags] = create_tags_array_from_tags_array(test_case.tags) unless test_case.tags.empty?
280
287
  end
281
288
 
282
- def scenario_outline(scenario)
283
- @test_case_hash = {
284
- id: create_id(scenario) + ';' + @example_id,
285
- keyword: scenario.keyword,
286
- name: scenario.name,
287
- description: scenario.description,
288
- line: @row.location.line,
289
- type: 'scenario'
290
- }
291
- tags = []
292
- tags += create_tags_array(scenario.tags) unless scenario.tags.empty?
293
- tags += @examples_table_tags if @examples_table_tags
294
- @test_case_hash[:tags] = tags unless tags.empty?
295
- comments = []
296
- comments += Formatter.create_comments_array(scenario.comments) unless scenario.comments.empty?
297
- comments += @examples_table_comments if @examples_table_comments
298
- comments += @row_comments if @row_comments
299
- @test_case_hash[:comments] = comments unless comments.empty?
300
- end
289
+ private
301
290
 
302
- def examples_table(examples_table)
303
- # the json file have traditionally used the header row as row 1,
304
- # wheras cucumber-ruby-core used the first example row as row 1.
305
- @example_id = create_id(examples_table) + ";#{@row.number + 1}"
291
+ def value_or_empty_string(value)
292
+ value.nil? ? '' : value
293
+ end
306
294
 
307
- @examples_table_tags = create_tags_array(examples_table.tags) unless examples_table.tags.empty?
308
- @examples_table_comments = Formatter.create_comments_array(examples_table.comments) unless examples_table.comments.empty?
295
+ def create_id(name)
296
+ name.downcase.tr(' ', '-')
309
297
  end
310
298
 
311
- def examples_table_row(row)
312
- @row = row
313
- @row_comments = Formatter.create_comments_array(row.comments) unless row.comments.empty?
299
+ def create_id_from_scenario_source(scenario_source)
300
+ if scenario_source.type == :Scenario
301
+ create_id(scenario_source.scenario.name)
302
+ else
303
+ scenario_outline_name = scenario_source.scenario_outline.name
304
+ examples_name = scenario_source.examples.name
305
+ row_number = calculate_row_number(scenario_source)
306
+ "#{create_id(scenario_outline_name)};#{create_id(examples_name)};#{row_number}"
307
+ end
314
308
  end
315
309
 
316
- private
310
+ def calculate_row_number(scenario_source)
311
+ scenario_source.examples.table_body.each_with_index do |row, index|
312
+ return index + 2 if row == scenario_source.row
313
+ end
314
+ end
317
315
 
318
- def create_id(element)
319
- element.name.downcase.gsub(/ /, '-')
316
+ def create_tags_array_from_hash_array(tags)
317
+ tags_array = []
318
+ tags.each { |tag| tags_array << { name: tag.name, line: tag.location.line } }
319
+ tags_array
320
320
  end
321
321
 
322
- def create_tags_array(tags)
322
+ def create_tags_array_from_tags_array(tags)
323
323
  tags_array = []
324
324
  tags.each { |tag| tags_array << { name: tag.name, line: tag.location.line } }
325
325
  tags_array
326
326
  end
327
327
  end
328
328
  end
329
-
330
- def self.create_comments_array(comments)
331
- comments_array = []
332
- comments.each { |comment| comments_array << { value: comment.to_s.strip, line: comment.location.line } }
333
- comments_array
334
- end
335
329
  end
336
330
  end