mobiusloop 0.1.2

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 (516) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.rspec +1 -0
  4. data/.ruby-gemset +1 -0
  5. data/.travis.yml +22 -0
  6. data/.yardopts +1 -0
  7. data/CONTRIBUTING.md +68 -0
  8. data/Gemfile +5 -0
  9. data/History.md +2280 -0
  10. data/LICENSE +22 -0
  11. data/README.md +373 -0
  12. data/Rakefile +22 -0
  13. data/bin/mobiusloop +8 -0
  14. data/cucumber.gemspec +47 -0
  15. data/cucumber.yml +20 -0
  16. data/examples/i18n/README.textile +3 -0
  17. data/examples/i18n/Rakefile +33 -0
  18. data/examples/i18n/ar/Rakefile +6 -0
  19. data/examples/i18n/ar/features/addition.feature +17 -0
  20. data/examples/i18n/ar/features/step_definitions/calculator_steps.rb +24 -0
  21. data/examples/i18n/ar/lib/calculator.rb +11 -0
  22. data/examples/i18n/bg/Rakefile +6 -0
  23. data/examples/i18n/bg/features/addition.feature +12 -0
  24. data/examples/i18n/bg/features/consecutive_calculations.feature +19 -0
  25. data/examples/i18n/bg/features/division.feature +17 -0
  26. data/examples/i18n/bg/features/step_definitions/calculator_steps.rb +24 -0
  27. data/examples/i18n/bg/features/support/env.rb +5 -0
  28. data/examples/i18n/bg/features/support/world.rb +8 -0
  29. data/examples/i18n/bg/lib/calculator.rb +24 -0
  30. data/examples/i18n/ca/Rakefile +6 -0
  31. data/examples/i18n/ca/features/step_definitions/calculator_steps.rb +21 -0
  32. data/examples/i18n/ca/features/suma.feature +17 -0
  33. data/examples/i18n/ca/lib/calculadora.rb +16 -0
  34. data/examples/i18n/cs/Rakefile +6 -0
  35. data/examples/i18n/cs/features/addition.feature +17 -0
  36. data/examples/i18n/cs/features/division.feature +11 -0
  37. data/examples/i18n/cs/features/step_definitions/calculator_steps.rb +24 -0
  38. data/examples/i18n/cs/lib/calculator.rb +14 -0
  39. data/examples/i18n/da/Rakefile +6 -0
  40. data/examples/i18n/da/features/sammenlaegning.feature +18 -0
  41. data/examples/i18n/da/features/step_definitions/lommeregner_steps.rb +24 -0
  42. data/examples/i18n/da/lib/lommeregner.rb +11 -0
  43. data/examples/i18n/de/Rakefile +6 -0
  44. data/examples/i18n/de/features/addition.feature +17 -0
  45. data/examples/i18n/de/features/division.feature +10 -0
  46. data/examples/i18n/de/features/step_definitions/calculator_steps.rb +24 -0
  47. data/examples/i18n/de/lib/calculator.rb +14 -0
  48. data/examples/i18n/el/Rakefile +6 -0
  49. data/examples/i18n/el/features/addition.feature +17 -0
  50. data/examples/i18n/el/features/division.feature +10 -0
  51. data/examples/i18n/el/features/step_definitions/calculator_steps.rb +24 -0
  52. data/examples/i18n/el/lib/calculator.rb +14 -0
  53. data/examples/i18n/en-lol/Rakefile +4 -0
  54. data/examples/i18n/en-lol/features/step_definitions/cucumbrz_steps.rb +16 -0
  55. data/examples/i18n/en-lol/features/stuffing.feature +8 -0
  56. data/examples/i18n/en-lol/features/support/env.rb +7 -0
  57. data/examples/i18n/en-lol/lib/basket.rb +12 -0
  58. data/examples/i18n/en-lol/lib/belly.rb +11 -0
  59. data/examples/i18n/en/Rakefile +6 -0
  60. data/examples/i18n/en/features/addition.feature +17 -0
  61. data/examples/i18n/en/features/division.feature +10 -0
  62. data/examples/i18n/en/features/step_definitions/calculator_steps.rb +24 -0
  63. data/examples/i18n/en/lib/calculator.rb +14 -0
  64. data/examples/i18n/eo/Rakefile +6 -0
  65. data/examples/i18n/eo/features/adicio.feature +17 -0
  66. data/examples/i18n/eo/features/divido.feature +10 -0
  67. data/examples/i18n/eo/features/step_definitions/calculator_steps.rb +24 -0
  68. data/examples/i18n/eo/lib/calculator.rb +14 -0
  69. data/examples/i18n/es/Rakefile +6 -0
  70. data/examples/i18n/es/features/adicion.feature +17 -0
  71. data/examples/i18n/es/features/step_definitions/calculador_steps.rb +21 -0
  72. data/examples/i18n/es/lib/calculador.rb +14 -0
  73. data/examples/i18n/et/Rakefile +6 -0
  74. data/examples/i18n/et/features/jagamine.feature +10 -0
  75. data/examples/i18n/et/features/liitmine.feature +17 -0
  76. data/examples/i18n/et/features/step_definitions/kalkulaator_steps.rb +24 -0
  77. data/examples/i18n/et/lib/kalkulaator.rb +14 -0
  78. data/examples/i18n/fi/Rakefile +6 -0
  79. data/examples/i18n/fi/features/jakolasku.feature +10 -0
  80. data/examples/i18n/fi/features/step_definitions/laskin_steps.rb +24 -0
  81. data/examples/i18n/fi/features/yhteenlasku.feature +17 -0
  82. data/examples/i18n/fi/lib/laskin.rb +14 -0
  83. data/examples/i18n/fr/Rakefile +8 -0
  84. data/examples/i18n/fr/features/addition.feature +18 -0
  85. data/examples/i18n/fr/features/addition2.feature +17 -0
  86. data/examples/i18n/fr/features/step_definitions/calculatrice_steps.rb +32 -0
  87. data/examples/i18n/fr/features/support/env.rb +5 -0
  88. data/examples/i18n/fr/lib/calculatrice.rb +10 -0
  89. data/examples/i18n/he/Rakefile +6 -0
  90. data/examples/i18n/he/features/addition.feature +17 -0
  91. data/examples/i18n/he/features/division.feature +10 -0
  92. data/examples/i18n/he/features/step_definitions/calculator_steps.rb +24 -0
  93. data/examples/i18n/he/lib/calculator.rb +15 -0
  94. data/examples/i18n/hi/Rakefile +6 -0
  95. data/examples/i18n/hi/features/addition.feature +16 -0
  96. data/examples/i18n/hi/features/division.feature +10 -0
  97. data/examples/i18n/hi/features/step_definitions/calculator_steps.rb +24 -0
  98. data/examples/i18n/hi/lib/calculator.rb +15 -0
  99. data/examples/i18n/ht/Rakefile +6 -0
  100. data/examples/i18n/ht/features/adisyon.feature +17 -0
  101. data/examples/i18n/ht/features/divizyon.feature +10 -0
  102. data/examples/i18n/ht/features/step_definitions/kalkilatris_steps.rb +25 -0
  103. data/examples/i18n/ht/lib/kalkilatris.rb +14 -0
  104. data/examples/i18n/hu/Rakefile +6 -0
  105. data/examples/i18n/hu/features/osszeadas.feature +17 -0
  106. data/examples/i18n/hu/features/osztas.feature +10 -0
  107. data/examples/i18n/hu/features/step_definitions/calculator_steps.rb +25 -0
  108. data/examples/i18n/hu/lib/calculator.rb +14 -0
  109. data/examples/i18n/id/Rakefile +6 -0
  110. data/examples/i18n/id/features/addition.feature +17 -0
  111. data/examples/i18n/id/features/division.feature +10 -0
  112. data/examples/i18n/id/features/step_definitions/calculator_steps.rb +24 -0
  113. data/examples/i18n/id/lib/calculator.rb +14 -0
  114. data/examples/i18n/it/Rakefile +6 -0
  115. data/examples/i18n/it/features/somma.feature +11 -0
  116. data/examples/i18n/it/features/step_definitions/calcolatrice_steps.rb +24 -0
  117. data/examples/i18n/it/lib/calcolatrice.rb +11 -0
  118. data/examples/i18n/ja/Rakefile +6 -0
  119. data/examples/i18n/ja/features/addition.feature +17 -0
  120. data/examples/i18n/ja/features/division.feature +10 -0
  121. data/examples/i18n/ja/features/step_definitions/calculator_steps.rb +19 -0
  122. data/examples/i18n/ja/features/support/env.rb +5 -0
  123. data/examples/i18n/ja/lib/calculator.rb +14 -0
  124. data/examples/i18n/ko/Rakefile +6 -0
  125. data/examples/i18n/ko/features/addition.feature +17 -0
  126. data/examples/i18n/ko/features/division.feature +11 -0
  127. data/examples/i18n/ko/features/step_definitions/calculator_steps.rb +24 -0
  128. data/examples/i18n/ko/lib/calculator.rb +14 -0
  129. data/examples/i18n/lt/Rakefile +6 -0
  130. data/examples/i18n/lt/features/addition.feature +17 -0
  131. data/examples/i18n/lt/features/division.feature +10 -0
  132. data/examples/i18n/lt/features/step_definitions/calculator_steps.rb +24 -0
  133. data/examples/i18n/lt/lib/calculator.rb +14 -0
  134. data/examples/i18n/lv/Rakefile +6 -0
  135. data/examples/i18n/lv/features/addition.feature +17 -0
  136. data/examples/i18n/lv/features/division.feature +10 -0
  137. data/examples/i18n/lv/features/step_definitions/calculator_steps.rb +24 -0
  138. data/examples/i18n/lv/lib/calculator.rb +14 -0
  139. data/examples/i18n/no/Rakefile +6 -0
  140. data/examples/i18n/no/features/step_definitions/kalkulator_steps.rb +17 -0
  141. data/examples/i18n/no/features/summering.feature +19 -0
  142. data/examples/i18n/no/features/support/env.rb +6 -0
  143. data/examples/i18n/no/lib/kalkulator.rb +11 -0
  144. data/examples/i18n/pl/Rakefile +6 -0
  145. data/examples/i18n/pl/features/addition.feature +17 -0
  146. data/examples/i18n/pl/features/division.feature +10 -0
  147. data/examples/i18n/pl/features/step_definitions/calculator_steps.rb +24 -0
  148. data/examples/i18n/pl/features/support/env.rb +5 -0
  149. data/examples/i18n/pl/lib/calculator.rb +14 -0
  150. data/examples/i18n/pt/Rakefile +6 -0
  151. data/examples/i18n/pt/features/adicao.feature +11 -0
  152. data/examples/i18n/pt/features/step_definitions/calculadora_steps.rb +20 -0
  153. data/examples/i18n/pt/features/support/env.rb +5 -0
  154. data/examples/i18n/pt/lib/calculadora.rb +10 -0
  155. data/examples/i18n/ro/Rakefile +6 -0
  156. data/examples/i18n/ro/features/adunare.feature +12 -0
  157. data/examples/i18n/ro/features/step_definitions/calculator_steps.rb +21 -0
  158. data/examples/i18n/ro/lib/calculator.rb +11 -0
  159. data/examples/i18n/ru/Rakefile +6 -0
  160. data/examples/i18n/ru/features/addition.feature +11 -0
  161. data/examples/i18n/ru/features/consecutive_calculations.feature +17 -0
  162. data/examples/i18n/ru/features/division.feature +16 -0
  163. data/examples/i18n/ru/features/step_definitions/calculator_steps.rb +19 -0
  164. data/examples/i18n/ru/features/support/env.rb +5 -0
  165. data/examples/i18n/ru/features/support/world.rb +8 -0
  166. data/examples/i18n/ru/lib/calculator.rb +24 -0
  167. data/examples/i18n/sk/Rakefile +6 -0
  168. data/examples/i18n/sk/features/addition.feature +17 -0
  169. data/examples/i18n/sk/features/division.feature +10 -0
  170. data/examples/i18n/sk/features/step_definitions/calculator_steps.rb +24 -0
  171. data/examples/i18n/sk/lib/calculator.rb +14 -0
  172. data/examples/i18n/sr-Cyrl/Rakefile +6 -0
  173. data/examples/i18n/sr-Cyrl/features/sabiranje.feature +18 -0
  174. data/examples/i18n/sr-Cyrl/features/step_definitions/calculator_steps.rb +20 -0
  175. data/examples/i18n/sr-Cyrl/features/support/env.rb +5 -0
  176. data/examples/i18n/sr-Cyrl/lib/calculator.rb +12 -0
  177. data/examples/i18n/sr-Latn/Rakefile +6 -0
  178. data/examples/i18n/sr-Latn/features/sabiranje.feature +18 -0
  179. data/examples/i18n/sr-Latn/features/step_definitions/calculator_steps.rb +24 -0
  180. data/examples/i18n/sr-Latn/lib/calculator.rb +12 -0
  181. data/examples/i18n/sv/Rakefile +6 -0
  182. data/examples/i18n/sv/features/step_definitions/kalkulator_steps.rb +24 -0
  183. data/examples/i18n/sv/features/summering.feature +18 -0
  184. data/examples/i18n/sv/lib/kalkulator.rb +11 -0
  185. data/examples/i18n/tr/Rakefile +6 -0
  186. data/examples/i18n/tr/features/bolme.feature +10 -0
  187. data/examples/i18n/tr/features/step_definitions/hesap_makinesi_adimlari.rb +24 -0
  188. data/examples/i18n/tr/features/toplama.feature +18 -0
  189. data/examples/i18n/tr/lib/hesap_makinesi.rb +15 -0
  190. data/examples/i18n/uk/Rakefile +6 -0
  191. data/examples/i18n/uk/features/addition.feature +11 -0
  192. data/examples/i18n/uk/features/consecutive_calculations.feature +17 -0
  193. data/examples/i18n/uk/features/division.feature +16 -0
  194. data/examples/i18n/uk/features/step_definitions/calculator_steps.rb +19 -0
  195. data/examples/i18n/uk/features/support/env.rb +5 -0
  196. data/examples/i18n/uk/features/support/world.rb +8 -0
  197. data/examples/i18n/uk/lib/calculator.rb +24 -0
  198. data/examples/i18n/uz/Rakefile +6 -0
  199. data/examples/i18n/uz/features/addition.feature +10 -0
  200. data/examples/i18n/uz/features/consecutive_calculations.feature +17 -0
  201. data/examples/i18n/uz/features/division.feature +17 -0
  202. data/examples/i18n/uz/features/step_definitions/calculator_steps.rb +19 -0
  203. data/examples/i18n/uz/features/support/env.rb +5 -0
  204. data/examples/i18n/uz/features/support/world.rb +8 -0
  205. data/examples/i18n/uz/lib/calculator.rb +24 -0
  206. data/examples/i18n/zh-CN/Rakefile +4 -0
  207. data/examples/i18n/zh-CN/features/addition.feature +18 -0
  208. data/examples/i18n/zh-CN/features/step_definitions/calculator_steps.rb +26 -0
  209. data/examples/i18n/zh-CN/lib/calculator.rb +10 -0
  210. data/examples/i18n/zh-TW/Rakefile +4 -0
  211. data/examples/i18n/zh-TW/features/addition.feature +17 -0
  212. data/examples/i18n/zh-TW/features/division.feature +11 -0
  213. data/examples/i18n/zh-TW/features/step_definitions/calculator_steps.rb +24 -0
  214. data/examples/i18n/zh-TW/lib/calculator.rb +14 -0
  215. data/examples/mobiusloop/increase_readers.goal +13 -0
  216. data/examples/mobiusloop/scale_page_response.rb +20 -0
  217. data/examples/mobiusloop/total_articles_scale.rb +10 -0
  218. data/examples/mobiusloop/total_readers_scale.rb +10 -0
  219. data/examples/rspec_doubles/Rakefile +4 -0
  220. data/examples/rspec_doubles/features/mocking.feature +9 -0
  221. data/examples/rspec_doubles/features/step_definitions/calvin_steps.rb +19 -0
  222. data/examples/rspec_doubles/features/support/env.rb +12 -0
  223. data/examples/sinatra/README.textile +13 -0
  224. data/examples/sinatra/Rakefile +6 -0
  225. data/examples/sinatra/app.rb +14 -0
  226. data/examples/sinatra/features/add.feature +11 -0
  227. data/examples/sinatra/features/step_definitions/add_steps.rb +15 -0
  228. data/examples/sinatra/features/support/env.rb +10 -0
  229. data/examples/sinatra/views/add.erb +7 -0
  230. data/examples/sinatra/views/layout.erb +8 -0
  231. data/examples/tcl/README.textile +11 -0
  232. data/examples/tcl/Rakefile +6 -0
  233. data/examples/tcl/features/fibonnacci.feature +17 -0
  234. data/examples/tcl/features/step_definitions/fib_steps.rb +7 -0
  235. data/examples/tcl/features/support/env.rb +6 -0
  236. data/examples/tcl/src/fib.tcl +3 -0
  237. data/examples/test_unit/Gemfile +4 -0
  238. data/examples/test_unit/Rakefile +6 -0
  239. data/examples/test_unit/features/step_definitions/test_unit_steps.rb +20 -0
  240. data/examples/test_unit/features/test_unit.feature +9 -0
  241. data/examples/watir/README.textile +16 -0
  242. data/examples/watir/Rakefile +12 -0
  243. data/examples/watir/cucumber.yml +1 -0
  244. data/examples/watir/features/search.feature +12 -0
  245. data/examples/watir/features/step_definitions/search_steps.rb +26 -0
  246. data/examples/watir/features/support/env.rb +35 -0
  247. data/examples/watir/features/support/screenshots.rb +47 -0
  248. data/features/docs/api/list_step_defs_as_json.feature +50 -0
  249. data/features/docs/api/listen_for_events.feature +58 -0
  250. data/features/docs/api/run_cli_main_with_existing_runtime.feature +26 -0
  251. data/features/docs/cli/backtraces.feature +36 -0
  252. data/features/docs/cli/dry_run.feature +70 -0
  253. data/features/docs/cli/exclude_files.feature +18 -0
  254. data/features/docs/cli/execute_with_tag_filter.feature +117 -0
  255. data/features/docs/cli/fail_fast.feature +46 -0
  256. data/features/docs/cli/finding_steps.feature +28 -0
  257. data/features/docs/cli/randomize.feature +140 -0
  258. data/features/docs/cli/require.feature +27 -0
  259. data/features/docs/cli/retry_failing_tests.feature +32 -0
  260. data/features/docs/cli/run_scenarios_matching_name.feature +104 -0
  261. data/features/docs/cli/run_specific_scenarios.feature +77 -0
  262. data/features/docs/cli/showing_differences.feature +43 -0
  263. data/features/docs/cli/specifying_multiple_formatters.feature +65 -0
  264. data/features/docs/cli/strict_mode.feature +64 -0
  265. data/features/docs/defining_steps/nested_steps.feature +177 -0
  266. data/features/docs/defining_steps/nested_steps_i18n.feature +34 -0
  267. data/features/docs/defining_steps/nested_steps_with_second_arg.feature +54 -0
  268. data/features/docs/defining_steps/one_line_step_definitions.feature +65 -0
  269. data/features/docs/defining_steps/printing_messages.feature +148 -0
  270. data/features/docs/defining_steps/skip_scenario.feature +64 -0
  271. data/features/docs/defining_steps/snippets.feature +56 -0
  272. data/features/docs/defining_steps/table_diffing.feature +50 -0
  273. data/features/docs/exception_in_after_hook.feature +126 -0
  274. data/features/docs/exception_in_after_step_hook.feature +102 -0
  275. data/features/docs/exception_in_around_hook.feature +78 -0
  276. data/features/docs/exception_in_before_hook.feature +96 -0
  277. data/features/docs/extending_cucumber/custom_filter.feature +29 -0
  278. data/features/docs/extending_cucumber/custom_formatter.feature +130 -0
  279. data/features/docs/formatters/api_methods.feature +37 -0
  280. data/features/docs/formatters/debug_formatter.feature +47 -0
  281. data/features/docs/formatters/formatter_step_file_colon_line.feature +44 -0
  282. data/features/docs/formatters/html_formatter.feature +91 -0
  283. data/features/docs/formatters/json_formatter.feature +767 -0
  284. data/features/docs/formatters/junit_formatter.feature +454 -0
  285. data/features/docs/formatters/pretty_formatter.feature +73 -0
  286. data/features/docs/formatters/progress_formatter.feature +31 -0
  287. data/features/docs/formatters/rerun_formatter.feature +188 -0
  288. data/features/docs/formatters/usage_formatter.feature +98 -0
  289. data/features/docs/getting_started.feature +27 -0
  290. data/features/docs/gherkin/background.feature +548 -0
  291. data/features/docs/gherkin/doc_strings.feature +74 -0
  292. data/features/docs/gherkin/expand_option_for_outlines.feature +46 -0
  293. data/features/docs/gherkin/language_from_header.feature +32 -0
  294. data/features/docs/gherkin/language_help.feature +42 -0
  295. data/features/docs/gherkin/outlines.feature +156 -0
  296. data/features/docs/gherkin/unicode_table.feature +32 -0
  297. data/features/docs/gherkin/using_descriptions.feature +82 -0
  298. data/features/docs/gherkin/using_star_notation.feature +37 -0
  299. data/features/docs/iso-8859-1.feature +6 -0
  300. data/features/docs/post_configuration_hook.feature +49 -0
  301. data/features/docs/profiles.feature +120 -0
  302. data/features/docs/rake_task.feature +141 -0
  303. data/features/docs/raketask.feature +44 -0
  304. data/features/docs/work_in_progress.feature +154 -0
  305. data/features/docs/writing_support_code/after_hooks.feature +102 -0
  306. data/features/docs/writing_support_code/after_step_hooks.feature +53 -0
  307. data/features/docs/writing_support_code/around_hooks.feature +260 -0
  308. data/features/docs/writing_support_code/before_hook.feature +65 -0
  309. data/features/docs/writing_support_code/hook_order.feature +61 -0
  310. data/features/docs/writing_support_code/load_path.feature +17 -0
  311. data/features/docs/writing_support_code/state.feature +32 -0
  312. data/features/docs/writing_support_code/tagged_hooks.feature +95 -0
  313. data/features/docs/writing_support_code/transforms.feature +98 -0
  314. data/features/lib/step_definitions/aruba_steps.rb +26 -0
  315. data/features/lib/step_definitions/cucumber_steps.rb +78 -0
  316. data/features/lib/step_definitions/iso-8859-1_steps.rb +12 -0
  317. data/features/lib/step_definitions/json_steps.rb +7 -0
  318. data/features/lib/step_definitions/junit_steps.rb +13 -0
  319. data/features/lib/step_definitions/language_steps.rb +8 -0
  320. data/features/lib/step_definitions/profile_steps.rb +15 -0
  321. data/features/lib/step_definitions/retry_steps.rb +35 -0
  322. data/features/lib/step_definitions/ruby_steps.rb +3 -0
  323. data/features/lib/step_definitions/wire_steps.rb +58 -0
  324. data/features/lib/support/env.rb +21 -0
  325. data/features/lib/support/fake_wire_server.rb +80 -0
  326. data/features/lib/support/feature_factory.rb +67 -0
  327. data/features/lib/support/normalise_output.rb +50 -0
  328. data/gem_tasks/contributors.rake +15 -0
  329. data/gem_tasks/cov.rake +5 -0
  330. data/gem_tasks/cucumber.rake +25 -0
  331. data/gem_tasks/downloads.rb +7 -0
  332. data/gem_tasks/environment.rake +7 -0
  333. data/gem_tasks/examples.rake +11 -0
  334. data/gem_tasks/fix_cr_lf.rake +10 -0
  335. data/gem_tasks/flog.rake +4 -0
  336. data/gem_tasks/rspec.rake +6 -0
  337. data/gem_tasks/sass.rake +4 -0
  338. data/gem_tasks/stats +16 -0
  339. data/gem_tasks/versions.txt +74 -0
  340. data/gherkin-languages.json +2972 -0
  341. data/lib/autotest/cucumber.rb +6 -0
  342. data/lib/autotest/cucumber_mixin.rb +135 -0
  343. data/lib/autotest/cucumber_rails.rb +6 -0
  344. data/lib/autotest/cucumber_rails_rspec.rb +6 -0
  345. data/lib/autotest/cucumber_rails_rspec2.rb +6 -0
  346. data/lib/autotest/cucumber_rspec.rb +6 -0
  347. data/lib/autotest/cucumber_rspec2.rb +6 -0
  348. data/lib/autotest/discover.rb +11 -0
  349. data/lib/cucumber.rb +37 -0
  350. data/lib/cucumber/ast.rb +13 -0
  351. data/lib/cucumber/cli/configuration.rb +146 -0
  352. data/lib/cucumber/cli/main.rb +99 -0
  353. data/lib/cucumber/cli/options.rb +465 -0
  354. data/lib/cucumber/cli/profile_loader.rb +91 -0
  355. data/lib/cucumber/cli/rerun_file.rb +29 -0
  356. data/lib/cucumber/configuration.rb +268 -0
  357. data/lib/cucumber/constantize.rb +45 -0
  358. data/lib/cucumber/core_ext/instance_exec.rb +70 -0
  359. data/lib/cucumber/core_ext/string.rb +9 -0
  360. data/lib/cucumber/deprecate.rb +29 -0
  361. data/lib/cucumber/encoding.rb +5 -0
  362. data/lib/cucumber/errors.rb +51 -0
  363. data/lib/cucumber/events.rb +20 -0
  364. data/lib/cucumber/events/after_test_case.rb +25 -0
  365. data/lib/cucumber/events/after_test_step.rb +30 -0
  366. data/lib/cucumber/events/before_test_case.rb +18 -0
  367. data/lib/cucumber/events/before_test_step.rb +23 -0
  368. data/lib/cucumber/events/bus.rb +86 -0
  369. data/lib/cucumber/events/finished_testing.rb +9 -0
  370. data/lib/cucumber/events/step_match.rb +23 -0
  371. data/lib/cucumber/file_specs.rb +37 -0
  372. data/lib/cucumber/filters.rb +9 -0
  373. data/lib/cucumber/filters/activate_steps.rb +67 -0
  374. data/lib/cucumber/filters/apply_after_hooks.rb +9 -0
  375. data/lib/cucumber/filters/apply_after_step_hooks.rb +12 -0
  376. data/lib/cucumber/filters/apply_around_hooks.rb +12 -0
  377. data/lib/cucumber/filters/apply_before_hooks.rb +9 -0
  378. data/lib/cucumber/filters/gated_receiver.rb +25 -0
  379. data/lib/cucumber/filters/prepare_world.rb +45 -0
  380. data/lib/cucumber/filters/quit.rb +28 -0
  381. data/lib/cucumber/filters/randomizer.rb +45 -0
  382. data/lib/cucumber/filters/retry.rb +32 -0
  383. data/lib/cucumber/filters/tag_limits.rb +45 -0
  384. data/lib/cucumber/filters/tag_limits/test_case_index.rb +31 -0
  385. data/lib/cucumber/filters/tag_limits/verifier.rb +59 -0
  386. data/lib/cucumber/formatter/ansicolor.rb +160 -0
  387. data/lib/cucumber/formatter/backtrace_filter.rb +41 -0
  388. data/lib/cucumber/formatter/console.rb +252 -0
  389. data/lib/cucumber/formatter/cucumber.css +286 -0
  390. data/lib/cucumber/formatter/cucumber.sass +247 -0
  391. data/lib/cucumber/formatter/debug.rb +35 -0
  392. data/lib/cucumber/formatter/duration.rb +13 -0
  393. data/lib/cucumber/formatter/duration_extractor.rb +28 -0
  394. data/lib/cucumber/formatter/event_bus_report.rb +38 -0
  395. data/lib/cucumber/formatter/fail_fast.rb +18 -0
  396. data/lib/cucumber/formatter/fanout.rb +27 -0
  397. data/lib/cucumber/formatter/hook_query_visitor.rb +40 -0
  398. data/lib/cucumber/formatter/html.rb +689 -0
  399. data/lib/cucumber/formatter/ignore_missing_messages.rb +20 -0
  400. data/lib/cucumber/formatter/interceptor.rb +80 -0
  401. data/lib/cucumber/formatter/io.rb +34 -0
  402. data/lib/cucumber/formatter/jquery-min.js +154 -0
  403. data/lib/cucumber/formatter/json.rb +334 -0
  404. data/lib/cucumber/formatter/json_pretty.rb +10 -0
  405. data/lib/cucumber/formatter/junit.rb +238 -0
  406. data/lib/cucumber/formatter/legacy_api/adapter.rb +1016 -0
  407. data/lib/cucumber/formatter/legacy_api/ast.rb +389 -0
  408. data/lib/cucumber/formatter/legacy_api/results.rb +51 -0
  409. data/lib/cucumber/formatter/legacy_api/runtime_facade.rb +31 -0
  410. data/lib/cucumber/formatter/pretty.rb +247 -0
  411. data/lib/cucumber/formatter/progress.rb +73 -0
  412. data/lib/cucumber/formatter/rerun.rb +35 -0
  413. data/lib/cucumber/formatter/stepdefs.rb +14 -0
  414. data/lib/cucumber/formatter/steps.rb +49 -0
  415. data/lib/cucumber/formatter/summary.rb +35 -0
  416. data/lib/cucumber/formatter/unicode.rb +53 -0
  417. data/lib/cucumber/formatter/usage.rb +136 -0
  418. data/lib/cucumber/gherkin/data_table_parser.rb +31 -0
  419. data/lib/cucumber/gherkin/formatter/ansi_escapes.rb +99 -0
  420. data/lib/cucumber/gherkin/formatter/escaping.rb +17 -0
  421. data/lib/cucumber/gherkin/i18n.rb +15 -0
  422. data/lib/cucumber/gherkin/steps_parser.rb +31 -0
  423. data/lib/cucumber/hooks.rb +99 -0
  424. data/lib/cucumber/load_path.rb +13 -0
  425. data/lib/cucumber/multiline_argument.rb +71 -0
  426. data/lib/cucumber/multiline_argument/data_table.rb +744 -0
  427. data/lib/cucumber/multiline_argument/doc_string.rb +9 -0
  428. data/lib/cucumber/platform.rb +27 -0
  429. data/lib/cucumber/project_initializer.rb +82 -0
  430. data/lib/cucumber/rake/task.rb +168 -0
  431. data/lib/cucumber/rb_support/rb_dsl.rb +119 -0
  432. data/lib/cucumber/rb_support/rb_hook.rb +19 -0
  433. data/lib/cucumber/rb_support/rb_language.rb +216 -0
  434. data/lib/cucumber/rb_support/rb_step_definition.rb +131 -0
  435. data/lib/cucumber/rb_support/rb_transform.rb +59 -0
  436. data/lib/cucumber/rb_support/rb_world.rb +149 -0
  437. data/lib/cucumber/rb_support/snippet.rb +170 -0
  438. data/lib/cucumber/rspec/disable_option_parser.rb +23 -0
  439. data/lib/cucumber/rspec/doubles.rb +19 -0
  440. data/lib/cucumber/running_test_case.rb +134 -0
  441. data/lib/cucumber/runtime.rb +266 -0
  442. data/lib/cucumber/runtime/after_hooks.rb +25 -0
  443. data/lib/cucumber/runtime/before_hooks.rb +27 -0
  444. data/lib/cucumber/runtime/for_programming_languages.rb +66 -0
  445. data/lib/cucumber/runtime/step_hooks.rb +23 -0
  446. data/lib/cucumber/runtime/support_code.rb +151 -0
  447. data/lib/cucumber/runtime/user_interface.rb +85 -0
  448. data/lib/cucumber/step_argument.rb +25 -0
  449. data/lib/cucumber/step_definition_light.rb +20 -0
  450. data/lib/cucumber/step_definitions.rb +13 -0
  451. data/lib/cucumber/step_match.rb +141 -0
  452. data/lib/cucumber/step_match_search.rb +67 -0
  453. data/lib/cucumber/term/ansicolor.rb +110 -0
  454. data/lib/cucumber/unit.rb +11 -0
  455. data/lib/cucumber/version +1 -0
  456. data/lib/mobiusloop/measure.rb +19 -0
  457. data/lib/mobiusloop/mobius_steps.rb +36 -0
  458. data/lib/mobiusloop/objective.rb +10 -0
  459. data/lib/mobiusloop/outcome.rb +99 -0
  460. data/lib/mobiusloop/scale.rb +32 -0
  461. data/lib/simplecov_setup.rb +18 -0
  462. data/major_changes_to_cucumber.md +45 -0
  463. data/mobiusloop.gemspec +47 -0
  464. data/spec/cucumber/cli/configuration_spec.rb +435 -0
  465. data/spec/cucumber/cli/main_spec.rb +83 -0
  466. data/spec/cucumber/cli/options_spec.rb +410 -0
  467. data/spec/cucumber/cli/profile_loader_spec.rb +46 -0
  468. data/spec/cucumber/cli/rerun_spec.rb +85 -0
  469. data/spec/cucumber/configuration_spec.rb +147 -0
  470. data/spec/cucumber/constantize_spec.rb +19 -0
  471. data/spec/cucumber/core_ext/instance_exec_spec.rb +4 -0
  472. data/spec/cucumber/events/bus_spec.rb +94 -0
  473. data/spec/cucumber/file_specs_spec.rb +60 -0
  474. data/spec/cucumber/filters/activate_steps_spec.rb +149 -0
  475. data/spec/cucumber/filters/gated_receiver_spec.rb +47 -0
  476. data/spec/cucumber/filters/retry_spec.rb +79 -0
  477. data/spec/cucumber/filters/tag_limits/test_case_index_spec.rb +38 -0
  478. data/spec/cucumber/filters/tag_limits/verifier_spec.rb +57 -0
  479. data/spec/cucumber/filters/tag_limits_spec.rb +59 -0
  480. data/spec/cucumber/formatter/ansicolor_spec.rb +32 -0
  481. data/spec/cucumber/formatter/debug_spec.rb +64 -0
  482. data/spec/cucumber/formatter/duration_spec.rb +22 -0
  483. data/spec/cucumber/formatter/event_bus_report_spec.rb +88 -0
  484. data/spec/cucumber/formatter/fail_fast_spec.rb +88 -0
  485. data/spec/cucumber/formatter/html_spec.rb +538 -0
  486. data/spec/cucumber/formatter/interceptor_spec.rb +136 -0
  487. data/spec/cucumber/formatter/json_spec.rb +841 -0
  488. data/spec/cucumber/formatter/junit_spec.rb +252 -0
  489. data/spec/cucumber/formatter/legacy_api/adapter_spec.rb +2182 -0
  490. data/spec/cucumber/formatter/pretty_spec.rb +919 -0
  491. data/spec/cucumber/formatter/progress_spec.rb +169 -0
  492. data/spec/cucumber/formatter/rerun_spec.rb +91 -0
  493. data/spec/cucumber/formatter/spec_helper.rb +82 -0
  494. data/spec/cucumber/hooks_spec.rb +30 -0
  495. data/spec/cucumber/multiline_argument/data_table_spec.rb +603 -0
  496. data/spec/cucumber/project_initializer_spec.rb +87 -0
  497. data/spec/cucumber/rake/forked_spec.rb +53 -0
  498. data/spec/cucumber/rake/task_spec.rb +85 -0
  499. data/spec/cucumber/rb_support/rb_language_spec.rb +243 -0
  500. data/spec/cucumber/rb_support/rb_step_definition_spec.rb +199 -0
  501. data/spec/cucumber/rb_support/rb_transform_spec.rb +46 -0
  502. data/spec/cucumber/rb_support/rb_world_spec.rb +47 -0
  503. data/spec/cucumber/rb_support/snippet_spec.rb +137 -0
  504. data/spec/cucumber/running_test_case_spec.rb +139 -0
  505. data/spec/cucumber/runtime/for_programming_languages_spec.rb +36 -0
  506. data/spec/cucumber/runtime/support_code_spec.rb +16 -0
  507. data/spec/cucumber/runtime_spec.rb +20 -0
  508. data/spec/cucumber/sell_cucumbers.feature +19 -0
  509. data/spec/cucumber/step_argument_spec.rb +18 -0
  510. data/spec/cucumber/step_match_search_spec.rb +122 -0
  511. data/spec/cucumber/step_match_spec.rb +85 -0
  512. data/spec/cucumber/world/pending_spec.rb +47 -0
  513. data/spec/cucumber_spec.rb +39 -0
  514. data/spec/spec_helper.rb +29 -0
  515. data/spec/support/standard_step_actions.rb +18 -0
  516. metadata +1007 -0
@@ -0,0 +1,10 @@
1
+ require 'cucumber/formatter/json'
2
+
3
+ module Cucumber
4
+ module Formatter
5
+ # The formatter used for <tt>--format json_pretty</tt>
6
+ class JsonPretty < Json
7
+ end
8
+ end
9
+ end
10
+
@@ -0,0 +1,238 @@
1
+ require 'builder'
2
+ require 'cucumber/formatter/backtrace_filter'
3
+ require 'cucumber/formatter/io'
4
+ require 'cucumber/formatter/interceptor'
5
+ require 'fileutils'
6
+
7
+ module Cucumber
8
+ module Formatter
9
+ # The formatter used for <tt>--format junit</tt>
10
+ class Junit
11
+
12
+ include Io
13
+
14
+ class UnNamedFeatureError < StandardError
15
+ def initialize(feature_file)
16
+ super("The feature in '#{feature_file}' does not have a name. The JUnit XML format requires a name for the testsuite element.")
17
+ end
18
+ end
19
+
20
+ def initialize(config)
21
+ config.on_event :before_test_case, &method(:on_before_test_case)
22
+ config.on_event :after_test_case, &method(:on_after_test_case)
23
+ config.on_event :after_test_step, &method(:on_after_test_step)
24
+ config.on_event :finished_testing, &method(:on_finished_testing)
25
+ @reportdir = ensure_dir(config.out_stream, "junit")
26
+ @config = config
27
+ @features_data = Hash.new { |h,k| h[k] = {
28
+ feature: nil,
29
+ failures: 0,
30
+ errors: 0,
31
+ tests: 0,
32
+ skipped: 0,
33
+ time: 0,
34
+ builder: Builder::XmlMarkup.new(:indent => 2)
35
+ }}
36
+ end
37
+
38
+ def on_before_test_case(event)
39
+ test_case = event.test_case
40
+ unless same_feature_as_previous_test_case?(test_case.feature)
41
+ start_feature(test_case.feature)
42
+ end
43
+ @failing_step_source = nil
44
+ # In order to fill out <system-err/> and <system-out/>, we need to
45
+ # intercept the $stderr and $stdout
46
+ @interceptedout = Interceptor::Pipe.wrap(:stdout)
47
+ @interceptederr = Interceptor::Pipe.wrap(:stderr)
48
+ end
49
+
50
+ def on_after_test_step(event)
51
+ return if @failing_step_source
52
+
53
+ @failing_step_source = event.test_step.source.last unless event.result.ok?(@config.strict?)
54
+ end
55
+
56
+ def on_after_test_case(event)
57
+ test_case = event.test_case
58
+ result = event.result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)
59
+ test_case_name = NameBuilder.new(test_case)
60
+ scenario = test_case_name.scenario_name
61
+ scenario_designation = "#{scenario}#{test_case_name.name_suffix}"
62
+ output = create_output_string(test_case, scenario, result, test_case_name.row_name)
63
+ build_testcase(result, scenario_designation, output)
64
+
65
+ Interceptor::Pipe.unwrap! :stdout
66
+ Interceptor::Pipe.unwrap! :stderr
67
+ end
68
+
69
+ def on_finished_testing(event)
70
+ @features_data.each { |file, data| end_feature(data) }
71
+ end
72
+
73
+ private
74
+
75
+ def same_feature_as_previous_test_case?(feature)
76
+ @current_feature_data && @current_feature_data[:feature].file == feature.file && @current_feature_data[:feature].location == feature.location
77
+ end
78
+
79
+ def start_feature(feature)
80
+ raise UnNamedFeatureError.new(feature.file) if feature.name.empty?
81
+ @current_feature_data = @features_data[feature.file]
82
+ @current_feature_data[:feature] = feature unless @current_feature_data[:feature]
83
+ end
84
+
85
+ def end_feature(feature_data)
86
+ @testsuite = Builder::XmlMarkup.new(:indent => 2)
87
+ @testsuite.instruct!
88
+ @testsuite.testsuite(
89
+ :failures => feature_data[:failures],
90
+ :errors => feature_data[:errors],
91
+ :skipped => feature_data[:skipped],
92
+ :tests => feature_data[:tests],
93
+ :time => "%.6f" % feature_data[:time],
94
+ :name => feature_data[:feature].name ) do
95
+ @testsuite << feature_data[:builder].target!
96
+ end
97
+
98
+ write_file(feature_result_filename(feature_data[:feature].file), @testsuite.target!)
99
+ end
100
+
101
+ def create_output_string(test_case, scenario, result, row_name)
102
+ output = "#{test_case.keyword}: #{scenario}\n\n"
103
+ return output if result.ok?(@config.strict?)
104
+ if test_case.keyword == "Scenario"
105
+ output += "#{@failing_step_source.keyword}" unless hook?(@failing_step_source)
106
+ output += "#{@failing_step_source.name}\n"
107
+ else
108
+ output += "Example row: #{row_name}\n"
109
+ end
110
+ output + "\nMessage:\n"
111
+ end
112
+
113
+ def hook?(step)
114
+ ["Before hook", "After hook", "AfterStep hook"].include? step.name
115
+ end
116
+
117
+ def build_testcase(result, scenario_designation, output)
118
+ duration = ResultBuilder.new(result).test_case_duration
119
+ @current_feature_data[:time] += duration
120
+ classname = @current_feature_data[:feature].name
121
+ name = scenario_designation
122
+
123
+ @current_feature_data[:builder].testcase(:classname => classname, :name => name, :time => "%.6f" % duration) do
124
+ if !result.passed? && result.ok?(@config.strict?)
125
+ @current_feature_data[:builder].skipped
126
+ @current_feature_data[:skipped] += 1
127
+ elsif !result.passed?
128
+ status = result.to_sym
129
+ exception = get_backtrace_object(result)
130
+ @current_feature_data[:builder].failure(:message => "#{status} #{name}", :type => status) do
131
+ @current_feature_data[:builder].cdata! output
132
+ @current_feature_data[:builder].cdata!(format_exception(exception)) if exception
133
+ end
134
+ @current_feature_data[:failures] += 1
135
+ end
136
+ @current_feature_data[:builder].tag!('system-out') do
137
+ @current_feature_data[:builder].cdata! strip_control_chars(@interceptedout.buffer.join)
138
+ end
139
+ @current_feature_data[:builder].tag!('system-err') do
140
+ @current_feature_data[:builder].cdata! strip_control_chars(@interceptederr.buffer.join)
141
+ end
142
+ end
143
+ @current_feature_data[:tests] += 1
144
+ end
145
+
146
+ def get_backtrace_object(result)
147
+ if result.failed?
148
+ return result.exception
149
+ elsif result.backtrace
150
+ return result
151
+ else
152
+ return nil
153
+ end
154
+ end
155
+
156
+ def format_exception(exception)
157
+ (["#{exception.message} (#{exception.class})"] + exception.backtrace).join("\n")
158
+ end
159
+
160
+ def feature_result_filename(feature_file)
161
+ File.join(@reportdir, "TEST-#{basename(feature_file)}.xml")
162
+ end
163
+
164
+ def basename(feature_file)
165
+ File.basename(feature_file.gsub(/[\\\/]/, '-'), '.feature')
166
+ end
167
+
168
+ def write_file(feature_filename, data)
169
+ File.open(feature_filename, 'w') { |file| file.write(data) }
170
+ end
171
+
172
+ # strip control chars from cdata, to make it safe for external parsers
173
+ def strip_control_chars(cdata)
174
+ cdata.scan(/[[:print:]\t\n\r]/).join
175
+ end
176
+
177
+ end
178
+
179
+ class NameBuilder
180
+ attr_reader :scenario_name, :name_suffix, :row_name
181
+
182
+ def initialize(test_case)
183
+ @name_suffix = ""
184
+ @row_name = ""
185
+ test_case.describe_source_to self
186
+ end
187
+
188
+ def feature(*)
189
+ self
190
+ end
191
+
192
+ def scenario(scenario)
193
+ @scenario_name = (scenario.name.nil? || scenario.name == "") ? "Unnamed scenario" : scenario.name
194
+ self
195
+ end
196
+
197
+ def scenario_outline(outline)
198
+ @scenario_name = (outline.name.nil? || outline.name == "") ? "Unnamed scenario outline" : outline.name
199
+ self
200
+ end
201
+
202
+ def examples_table(*)
203
+ self
204
+ end
205
+
206
+ def examples_table_row(row)
207
+ @row_name = '| ' + row.values.join(' | ') + ' |'
208
+ @name_suffix = " (outline example : #{@row_name})"
209
+ self
210
+ end
211
+ end
212
+
213
+ class ResultBuilder
214
+ attr_reader :test_case_duration
215
+ def initialize(result)
216
+ @test_case_duration = 0
217
+ result.describe_to(self)
218
+ end
219
+
220
+ def passed(*) end
221
+
222
+ def failed(*) end
223
+
224
+ def undefined(*) end
225
+
226
+ def skipped(*) end
227
+
228
+ def pending(*) end
229
+
230
+ def exception(*) end
231
+
232
+ def duration(duration, *)
233
+ duration.tap { |duration| @test_case_duration = duration.nanoseconds / 10**9.0 }
234
+ end
235
+ end
236
+
237
+ end
238
+ end
@@ -0,0 +1,1016 @@
1
+ require 'forwardable'
2
+ require 'delegate'
3
+ require 'cucumber/errors'
4
+ require 'cucumber/multiline_argument'
5
+ require 'cucumber/formatter/backtrace_filter'
6
+ require 'cucumber/formatter/legacy_api/ast'
7
+
8
+ module Cucumber
9
+ module Formatter
10
+ module LegacyApi
11
+
12
+ Adapter = Struct.new(:formatter, :results, :config) do
13
+ extend Forwardable
14
+
15
+ def initialize(*)
16
+ super
17
+ @matches = collect_matches
18
+ end
19
+
20
+ def_delegators :formatter,
21
+ :ask
22
+
23
+ def_delegators :printer,
24
+ :embed
25
+
26
+ def before_test_case(test_case)
27
+ formatter.before_test_case(test_case)
28
+ printer.before_test_case(test_case)
29
+ end
30
+
31
+ def before_test_step(test_step)
32
+ formatter.before_test_step(test_step)
33
+ printer.before_test_step(test_step)
34
+ end
35
+
36
+ def after_test_step(test_step, result)
37
+ printer.after_test_step(test_step, result)
38
+ formatter.after_test_step(test_step, result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter))
39
+ end
40
+
41
+ def after_test_case(test_case, result)
42
+ record_test_case_result(test_case, result)
43
+ printer.after_test_case(test_case, result)
44
+ formatter.after_test_case(test_case, result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter))
45
+ end
46
+
47
+ def puts(*messages)
48
+ printer.puts(messages)
49
+ end
50
+
51
+ def done
52
+ printer.after
53
+ formatter.done
54
+ end
55
+
56
+ private
57
+
58
+ def printer
59
+ @printer ||= FeaturesPrinter.new(formatter, results, config, @matches).before
60
+ end
61
+
62
+ def record_test_case_result(test_case, result)
63
+ scenario = LegacyResultBuilder.new(result).scenario("#{test_case.keyword}: #{test_case.name}", test_case.location)
64
+ results.scenario_visited(scenario)
65
+ end
66
+
67
+ def collect_matches
68
+ result = {}
69
+ config.on_event(:step_match) do |event|
70
+ result[event.test_step.source.last] = event.step_match
71
+ end
72
+ result
73
+ end
74
+
75
+ require 'cucumber/core/test/timer'
76
+ FeaturesPrinter = Struct.new(:formatter, :results, :config, :matches) do
77
+ extend Forwardable
78
+
79
+ def before
80
+ timer.start
81
+ formatter.before_features(nil)
82
+ self
83
+ end
84
+
85
+ def before_test_case(test_case)
86
+ test_case.describe_source_to(self)
87
+ @child.before_test_case(test_case)
88
+ end
89
+
90
+ def before_test_step(*args)
91
+ @child.before_test_step(*args)
92
+ end
93
+
94
+ def after_test_step(test_step, result)
95
+ @child.after_test_step(test_step, result)
96
+ end
97
+
98
+ def after_test_case(*args)
99
+ @child.after_test_case(*args)
100
+ end
101
+
102
+ def feature(node, *)
103
+ if node != @current_feature
104
+ @child.after if @child
105
+ @child = FeaturePrinter.new(formatter, results, matches, config, node).before
106
+ @current_feature = node
107
+ end
108
+ end
109
+
110
+ def scenario(node, *)
111
+ end
112
+
113
+ def scenario_outline(node, *)
114
+ end
115
+
116
+ def examples_table(node, *)
117
+ end
118
+
119
+ def examples_table_row(node, *)
120
+ end
121
+
122
+ def after
123
+ @child.after if @child
124
+ formatter.after_features Ast::Features.new(timer.sec)
125
+ self
126
+ end
127
+
128
+ def puts(messages)
129
+ @child.puts(messages)
130
+ end
131
+
132
+ def embed(src, mime_type, label)
133
+ @child.embed(src, mime_type, label)
134
+ end
135
+
136
+ private
137
+
138
+ def timer
139
+ @timer ||= Cucumber::Core::Test::Timer.new
140
+ end
141
+
142
+ end
143
+
144
+ module TestCaseSource
145
+ def self.for(test_case, result)
146
+ collector = Collector.new
147
+ test_case.describe_source_to collector, result
148
+ collector.result.freeze
149
+ end
150
+
151
+ class Collector
152
+ attr_reader :result
153
+
154
+ def initialize
155
+ @result = CaseSource.new
156
+ end
157
+
158
+ def method_missing(name, node, test_case_result, *args)
159
+ result.send "#{name}=", node
160
+ end
161
+ end
162
+
163
+ require 'ostruct'
164
+ class CaseSource < OpenStruct
165
+ end
166
+ end
167
+
168
+ module TestStepSource
169
+ def self.for(test_step, result)
170
+ collector = Collector.new
171
+ test_step.describe_source_to collector, result
172
+ collector.result.freeze
173
+ end
174
+
175
+ class Collector
176
+ attr_reader :result
177
+
178
+ def initialize
179
+ @result = StepSource.new
180
+ end
181
+
182
+ def method_missing(name, node, step_result, *args)
183
+ result.send "#{name}=", node
184
+ result.send "#{name}_result=", LegacyResultBuilder.new(step_result)
185
+ end
186
+ end
187
+
188
+ require 'ostruct'
189
+ class StepSource < OpenStruct
190
+ def build_step_invocation(indent, matches, config, messages, embeddings)
191
+ step_result.step_invocation(
192
+ matches.fetch(step) { NoStepMatch.new(step, step.name) },
193
+ step,
194
+ indent,
195
+ background,
196
+ config,
197
+ messages,
198
+ embeddings
199
+ )
200
+ end
201
+ end
202
+
203
+ end
204
+
205
+ Embedding = Struct.new(:src, :mime_type, :label) do
206
+
207
+ def send_to_formatter(formatter)
208
+ formatter.embed(src, mime_type, label)
209
+ end
210
+ end
211
+
212
+ FeaturePrinter = Struct.new(:formatter, :results, :matches, :config, :node) do
213
+
214
+ def before
215
+ formatter.before_feature(node)
216
+ language_comment = node.language.iso_code != 'en' ? ["# language: #{node.language.iso_code}"] : []
217
+ Ast::Comments.new(language_comment + node.comments).accept(formatter)
218
+ Ast::Tags.new(node.tags).accept(formatter)
219
+ formatter.feature_name node.keyword, node.legacy_conflated_name_and_description
220
+ @delayed_messages = []
221
+ @delayed_embeddings = []
222
+ self
223
+ end
224
+
225
+ attr_reader :current_test_step_source
226
+
227
+ def before_test_case(test_case)
228
+ @before_hook_results = Ast::HookResultCollection.new
229
+ @test_step_results = []
230
+ end
231
+
232
+ def before_test_step(test_step)
233
+ end
234
+
235
+ def after_test_step(test_step, result)
236
+ @current_test_step_source = TestStepSource.for(test_step, result)
237
+ # TODO: stop calling self, and describe source to another object
238
+ test_step.describe_source_to(self, result)
239
+ print_step
240
+ @test_step_results << result
241
+ end
242
+
243
+ def after_test_case(test_case, test_case_result)
244
+ if current_test_step_source && current_test_step_source.step_result.nil?
245
+ switch_step_container
246
+ end
247
+
248
+ if test_case_result.failed? && !any_test_steps_failed?
249
+ # around hook must have failed. Print the error.
250
+ switch_step_container(TestCaseSource.for(test_case, test_case_result))
251
+ LegacyResultBuilder.new(test_case_result).describe_exception_to formatter
252
+ end
253
+
254
+ # messages and embedding should already have been handled, but just in case...
255
+ @delayed_messages.each { |message| formatter.puts(message) }
256
+ @delayed_embeddings.each { |embedding| embedding.send_to_formatter(formatter) }
257
+ @delayed_messages = []
258
+ @delayed_embeddings = []
259
+
260
+ @child.after_test_case(test_case, test_case_result) if @child
261
+ @previous_test_case_background = @current_test_case_background
262
+ @previous_test_case_scenario_outline = current_test_step_source && current_test_step_source.scenario_outline
263
+ end
264
+
265
+ def before_hook(location, result)
266
+ @before_hook_results << Ast::HookResult.new(LegacyResultBuilder.new(result), @delayed_messages, @delayed_embeddings)
267
+ @delayed_messages = []
268
+ @delayed_embeddings = []
269
+ end
270
+
271
+ def after_hook(location, result)
272
+ # if the scenario has no steps, we can hit this before we've created the scenario printer
273
+ # ideally we should call switch_step_container in before_step_step
274
+ switch_step_container if !@child
275
+ @child.after_hook Ast::HookResult.new(LegacyResultBuilder.new(result), @delayed_messages, @delayed_embeddings)
276
+ @delayed_messages = []
277
+ @delayed_embeddings = []
278
+ end
279
+
280
+ def after_step_hook(hook, result)
281
+ p current_test_step_source if current_test_step_source.step.nil?
282
+ line = current_test_step_source.step.backtrace_line
283
+ @child.after_step_hook Ast::HookResult.new(LegacyResultBuilder.new(result).
284
+ append_to_exception_backtrace(line), @delayed_messages, @delayed_embeddings)
285
+ @delayed_messages = []
286
+ @delayed_embeddings = []
287
+ end
288
+
289
+ def background(node, *)
290
+ @current_test_case_background = node
291
+ end
292
+
293
+ def puts(messages)
294
+ @delayed_messages.push *messages
295
+ end
296
+
297
+ def embed(src, mime_type, label)
298
+ @delayed_embeddings.push Embedding.new(src, mime_type, label)
299
+ end
300
+
301
+ def step(*);end
302
+ def scenario(*);end
303
+ def scenario_outline(*);end
304
+ def examples_table(*);end
305
+ def examples_table_row(*);end
306
+ def feature(*);end
307
+
308
+ def after
309
+ @child.after if @child
310
+ formatter.after_feature(node)
311
+ self
312
+ end
313
+
314
+ private
315
+
316
+ attr_reader :before_hook_results
317
+ private :before_hook_results
318
+
319
+ def any_test_steps_failed?
320
+ @test_step_results.any? &:failed?
321
+ end
322
+
323
+ def switch_step_container(source = current_test_step_source)
324
+ switch_to_child select_step_container(source), source
325
+ end
326
+
327
+ def select_step_container(source)
328
+ if source.background
329
+ if same_background_as_previous_test_case?(source)
330
+ HiddenBackgroundPrinter.new(formatter, source.background)
331
+ else
332
+ BackgroundPrinter.new(formatter, node, source.background, before_hook_results)
333
+ end
334
+ elsif source.scenario
335
+ ScenarioPrinter.new(formatter, source.scenario, before_hook_results)
336
+ elsif source.scenario_outline
337
+ if same_scenario_outline_as_previous_test_case?(source) and @previous_outline_child
338
+ @previous_outline_child
339
+ else
340
+ ScenarioOutlinePrinter.new(formatter, config, source.scenario_outline)
341
+ end
342
+ else
343
+ raise 'unknown step container'
344
+ end
345
+ end
346
+
347
+ def same_background_as_previous_test_case?(source)
348
+ source.background == @previous_test_case_background
349
+ end
350
+
351
+ def same_scenario_outline_as_previous_test_case?(source)
352
+ source.scenario_outline == @previous_test_case_scenario_outline
353
+ end
354
+
355
+ def print_step
356
+ return unless current_test_step_source.step_result
357
+ switch_step_container
358
+
359
+ if current_test_step_source.scenario_outline
360
+ @child.examples_table(current_test_step_source.examples_table)
361
+ @child.examples_table_row(current_test_step_source.examples_table_row, before_hook_results)
362
+ end
363
+
364
+ if @failed_hidden_background_step
365
+ indent = Indent.new(@child.node)
366
+ step_invocation = @failed_hidden_background_step.build_step_invocation(indent, matches, config, messages = [], embeddings = [])
367
+ @child.step_invocation(step_invocation, @failed_hidden_background_step)
368
+ @failed_hidden_background_step = nil
369
+ end
370
+
371
+ unless @last_step == current_test_step_source.step
372
+ indent ||= Indent.new(@child.node)
373
+ step_invocation = current_test_step_source.build_step_invocation(indent, matches, config, @delayed_messages, @delayed_embeddings)
374
+ results.step_visited step_invocation
375
+ @child.step_invocation(step_invocation, current_test_step_source)
376
+ @last_step = current_test_step_source.step
377
+ end
378
+ @delayed_messages = []
379
+ @delayed_embeddings = []
380
+ end
381
+
382
+ def switch_to_child(child, source)
383
+ return if @child == child
384
+ if @child
385
+ if from_first_background(@child)
386
+ @first_background_failed = @child.failed?
387
+ elsif from_hidden_background(@child)
388
+ if not @first_background_failed
389
+ @failed_hidden_background_step = @child.get_failed_step_source
390
+ end
391
+ if @previous_outline_child
392
+ @previous_outline_child.after unless same_scenario_outline_as_previous_test_case?(source)
393
+ end
394
+ end
395
+ unless from_scenario_outline_to_hidden_backgroud(@child, child)
396
+ @child.after
397
+ @previous_outline_child = nil
398
+ else
399
+ @previous_outline_child = @child
400
+ end
401
+ end
402
+ child.before unless to_scenario_outline(child) and same_scenario_outline_as_previous_test_case?(source)
403
+ @child = child
404
+ end
405
+
406
+ def from_scenario_outline_to_hidden_backgroud(from, to)
407
+ from.class.name == ScenarioOutlinePrinter.name and
408
+ to.class.name == HiddenBackgroundPrinter.name
409
+ end
410
+
411
+ def from_first_background(from)
412
+ from.class.name == BackgroundPrinter.name
413
+ end
414
+
415
+ def from_hidden_background(from)
416
+ from.class.name == HiddenBackgroundPrinter.name
417
+ end
418
+
419
+ def to_scenario_outline(to)
420
+ to.class.name == ScenarioOutlinePrinter.name
421
+ end
422
+
423
+ end
424
+
425
+ module PrintsAfterHooks
426
+ def after_hook_results
427
+ @after_hook_results ||= Ast::HookResultCollection.new
428
+ end
429
+
430
+ def after_hook(result)
431
+ after_hook_results << result
432
+ end
433
+ end
434
+
435
+ # Basic printer used by default
436
+ class AfterHookPrinter
437
+ attr_reader :formatter
438
+
439
+ def initialize(formatter)
440
+ @formatter = formatter
441
+ end
442
+
443
+ include PrintsAfterHooks
444
+
445
+ def after
446
+ after_hook_results.accept(formatter)
447
+ end
448
+ end
449
+
450
+ BackgroundPrinter = Struct.new(:formatter, :feature, :node, :before_hook_results) do
451
+
452
+ def after_test_case(*)
453
+ end
454
+
455
+ def after_hook(*)
456
+ end
457
+
458
+ def before
459
+ formatter.before_background Ast::Background.new(feature, node)
460
+ Ast::Comments.new(node.comments).accept(formatter)
461
+ formatter.background_name node.keyword, node.legacy_conflated_name_and_description, node.location.to_s, indent.of(node)
462
+ before_hook_results.accept(formatter)
463
+ self
464
+ end
465
+
466
+ def after_step_hook(result)
467
+ result.accept formatter
468
+ end
469
+
470
+ def step_invocation(step_invocation, source)
471
+ @child ||= StepsPrinter.new(formatter).before
472
+ @child.step_invocation step_invocation
473
+ if source.step_result.status == :failed
474
+ @failed = true
475
+ end
476
+ end
477
+
478
+ def after
479
+ @child.after if @child
480
+ formatter.after_background(Ast::Background.new(feature, node))
481
+ self
482
+ end
483
+
484
+ def failed?
485
+ @failed
486
+ end
487
+
488
+ private
489
+
490
+ def indent
491
+ @indent ||= Indent.new(node)
492
+ end
493
+ end
494
+
495
+ # Printer to handle background steps for anything but the first scenario in a
496
+ # feature. These steps should not be printed.
497
+ class HiddenBackgroundPrinter < Struct.new(:formatter, :node)
498
+ def get_failed_step_source
499
+ return @source_of_failed_step
500
+ end
501
+
502
+ def step_invocation(step_invocation, source)
503
+ if source.step_result.status == :failed
504
+ @source_of_failed_step = source
505
+ end
506
+ end
507
+
508
+ def before;self;end
509
+ def after;self;end
510
+ def before_hook(*);end
511
+ def after_hook(*);end
512
+ def after_step_hook(*);end
513
+ def examples_table(*);end
514
+ def after_test_case(*);end
515
+ end
516
+
517
+ ScenarioPrinter = Struct.new(:formatter, :node, :before_hook_results) do
518
+ include PrintsAfterHooks
519
+
520
+ def before
521
+ formatter.before_feature_element(node)
522
+ Ast::Comments.new(node.comments).accept(formatter)
523
+ Ast::Tags.new(node.tags).accept(formatter)
524
+ formatter.scenario_name node.keyword, node.legacy_conflated_name_and_description, node.location.to_s, indent.of(node)
525
+ before_hook_results.accept(formatter)
526
+ self
527
+ end
528
+
529
+ def step_invocation(step_invocation, source)
530
+ @child ||= StepsPrinter.new(formatter).before
531
+ @child.step_invocation step_invocation
532
+ end
533
+
534
+ def after_step_hook(result)
535
+ result.accept formatter
536
+ end
537
+
538
+ def after_test_case(test_case, result)
539
+ @test_case_result = result
540
+ after
541
+ end
542
+
543
+ def after
544
+ return if @done
545
+ @child.after if @child
546
+ scenario = LegacyResultBuilder.new(@test_case_result).scenario(node.name, node.location)
547
+ after_hook_results.accept(formatter)
548
+ formatter.after_feature_element(scenario)
549
+ @done = true
550
+ self
551
+ end
552
+
553
+ private
554
+
555
+ def indent
556
+ @indent ||= Indent.new(node)
557
+ end
558
+ end
559
+
560
+ StepsPrinter = Struct.new(:formatter) do
561
+ def before
562
+ formatter.before_steps(nil)
563
+ self
564
+ end
565
+
566
+ def step_invocation(step_invocation)
567
+ steps << step_invocation
568
+ step_invocation.accept(formatter)
569
+ self
570
+ end
571
+
572
+ def after
573
+ formatter.after_steps(steps)
574
+ self
575
+ end
576
+
577
+ private
578
+
579
+ def steps
580
+ @steps ||= Ast::StepInvocations.new
581
+ end
582
+
583
+ end
584
+
585
+ ScenarioOutlinePrinter = Struct.new(:formatter, :configuration, :node) do
586
+ extend Forwardable
587
+ def_delegators :@child, :after_hook, :after_step_hook
588
+
589
+ def before
590
+ formatter.before_feature_element(node)
591
+ Ast::Comments.new(node.comments).accept(formatter)
592
+ Ast::Tags.new(node.tags).accept(formatter)
593
+ formatter.scenario_name node.keyword, node.legacy_conflated_name_and_description, node.location.to_s, indent.of(node)
594
+ OutlineStepsPrinter.new(formatter, configuration, indent).print(node)
595
+ self
596
+ end
597
+
598
+ def step_invocation(step_invocation, source)
599
+ node, result = source.step, source.step_result
600
+ @last_step_result = result
601
+ @child.step_invocation(step_invocation, source)
602
+ end
603
+
604
+ def examples_table(examples_table)
605
+ @child ||= ExamplesArrayPrinter.new(formatter, configuration).before
606
+ @child.examples_table(examples_table)
607
+ end
608
+
609
+ def examples_table_row(node, before_hook_results)
610
+ @child.examples_table_row(node, before_hook_results)
611
+ end
612
+
613
+ def after_test_case(test_case, result)
614
+ @child.after_test_case(test_case, result)
615
+ end
616
+
617
+ def after
618
+ @child.after if @child
619
+ # TODO - the last step result might not accurately reflect the
620
+ # overall scenario result.
621
+ scenario_outline = last_step_result.scenario_outline(node.name, node.location)
622
+ formatter.after_feature_element(scenario_outline)
623
+ self
624
+ end
625
+
626
+ private
627
+
628
+ def last_step_result
629
+ @last_step_result || Core::Test::Result::Unknown.new
630
+ end
631
+
632
+ def indent
633
+ @indent ||= Indent.new(node)
634
+ end
635
+ end
636
+
637
+ OutlineStepsPrinter = Struct.new(:formatter, :configuration, :indent, :outline) do
638
+ def print(node)
639
+ node.describe_to self
640
+ steps_printer.after
641
+ end
642
+
643
+ def scenario_outline(node, &descend)
644
+ descend.call(self)
645
+ end
646
+
647
+ def outline_step(step)
648
+ step_match = NoStepMatch.new(step, step.name)
649
+ step_invocation = LegacyResultBuilder.new(Core::Test::Result::Skipped.new).
650
+ step_invocation(step_match, step, indent, background = nil, configuration, messages = [], embeddings = [])
651
+ steps_printer.step_invocation step_invocation
652
+ end
653
+
654
+ def examples_table(*);end
655
+
656
+ private
657
+
658
+ def steps_printer
659
+ @steps_printer ||= StepsPrinter.new(formatter).before
660
+ end
661
+ end
662
+
663
+ ExamplesArrayPrinter = Struct.new(:formatter, :configuration) do
664
+ extend Forwardable
665
+ def_delegators :@child, :step_invocation, :after_hook, :after_step_hook, :after_test_case, :examples_table_row
666
+
667
+ def before
668
+ formatter.before_examples_array(:examples_array)
669
+ self
670
+ end
671
+
672
+ def examples_table(examples_table)
673
+ return if examples_table == @current
674
+ @child.after if @child
675
+ @child = ExamplesTablePrinter.new(formatter, configuration, examples_table).before
676
+ @current = examples_table
677
+ end
678
+
679
+ def after
680
+ @child.after if @child
681
+ formatter.after_examples_array
682
+ self
683
+ end
684
+ end
685
+
686
+ ExamplesTablePrinter = Struct.new(:formatter, :configuration, :node) do
687
+ extend Forwardable
688
+ def_delegators :@child, :step_invocation, :after_hook, :after_step_hook, :after_test_case
689
+
690
+ def before
691
+ formatter.before_examples(node)
692
+ Ast::Comments.new(node.comments).accept(formatter)
693
+ Ast::Tags.new(node.tags).accept(formatter)
694
+ formatter.examples_name(node.keyword, node.legacy_conflated_name_and_description)
695
+ formatter.before_outline_table(legacy_table)
696
+ if !configuration.expand?
697
+ HeaderTableRowPrinter.new(formatter, ExampleTableRow.new(node.header), Ast::Node.new).before.after
698
+ end
699
+ self
700
+ end
701
+
702
+ def examples_table_row(examples_table_row, before_hook_results)
703
+ return if examples_table_row == @current
704
+ @child.after if @child
705
+ row = ExampleTableRow.new(examples_table_row)
706
+ if !configuration.expand?
707
+ @child = TableRowPrinter.new(formatter, row, before_hook_results).before
708
+ else
709
+ @child = ExpandTableRowPrinter.new(formatter, row, before_hook_results).before
710
+ end
711
+ @current = examples_table_row
712
+ end
713
+
714
+ def after_test_case(*args)
715
+ @child.after_test_case(*args)
716
+ end
717
+
718
+ def after
719
+ @child.after if @child
720
+ formatter.after_outline_table(node)
721
+ formatter.after_examples(node)
722
+ self
723
+ end
724
+
725
+ private
726
+
727
+ def legacy_table
728
+ LegacyTable.new(node)
729
+ end
730
+
731
+ class ExampleTableRow < SimpleDelegator
732
+ def dom_id
733
+ file_colon_line.gsub(/[\/\.:]/, '_')
734
+ end
735
+ end
736
+
737
+ LegacyTable = Struct.new(:node) do
738
+ def col_width(index)
739
+ max_width = FindMaxWidth.new(index)
740
+ node.describe_to max_width
741
+ max_width.result
742
+ end
743
+
744
+ require 'cucumber/gherkin/formatter/escaping'
745
+ FindMaxWidth = Struct.new(:index) do
746
+ include ::Cucumber::Gherkin::Formatter::Escaping
747
+
748
+ def examples_table(table, &descend)
749
+ @result = char_length_of(table.header.values[index])
750
+ descend.call(self)
751
+ end
752
+
753
+ def examples_table_row(row, &descend)
754
+ width = char_length_of(row.values[index])
755
+ @result = width if width > result
756
+ end
757
+
758
+ def result
759
+ @result ||= 0
760
+ end
761
+
762
+ private
763
+ def char_length_of(cell)
764
+ escape_cell(cell).unpack('U*').length
765
+ end
766
+ end
767
+ end
768
+ end
769
+
770
+ class TableRowPrinterBase < Struct.new(:formatter, :node, :before_hook_results)
771
+ include PrintsAfterHooks
772
+
773
+ def after_step_hook(result)
774
+ @after_step_hook_result ||= Ast::HookResultCollection.new
775
+ @after_step_hook_result << result
776
+ end
777
+
778
+ def after_test_case(*args)
779
+ after
780
+ end
781
+
782
+ private
783
+
784
+ def indent
785
+ :not_needed
786
+ end
787
+
788
+ def legacy_table_row
789
+ Ast::ExampleTableRow.new(exception, @status, node.values, node.location, node.language)
790
+ end
791
+
792
+ def exception
793
+ return nil unless @failed_step
794
+ @failed_step.exception
795
+ end
796
+ end
797
+
798
+ class HeaderTableRowPrinter < TableRowPrinterBase
799
+ def legacy_table_row
800
+ Ast::ExampleTableRow.new(exception, @status, node.values, node.location, Ast::NullLanguage.new)
801
+ end
802
+
803
+ def before
804
+ Ast::Comments.new(node.comments).accept(formatter)
805
+ formatter.before_table_row(node)
806
+ self
807
+ end
808
+
809
+ def after
810
+ node.values.each do |value|
811
+ formatter.before_table_cell(value)
812
+ formatter.table_cell_value(value, :skipped_param)
813
+ formatter.after_table_cell(value)
814
+ end
815
+ formatter.after_table_row(legacy_table_row)
816
+ self
817
+ end
818
+ end
819
+
820
+
821
+ class TableRowPrinter < TableRowPrinterBase
822
+ def before
823
+ before_hook_results.accept(formatter)
824
+ Ast::Comments.new(node.comments).accept(formatter)
825
+ formatter.before_table_row(node)
826
+ self
827
+ end
828
+
829
+ def step_invocation(step_invocation, source)
830
+ result = source.step_result
831
+ step_invocation.messages.each { |message| formatter.puts(message) }
832
+ step_invocation.embeddings.each { |embedding| embedding.send_to_formatter(formatter) }
833
+ @failed_step = step_invocation if result.status == :failed
834
+ @status = step_invocation.status unless already_failed?
835
+ end
836
+
837
+ def after
838
+ return if @done
839
+ @child.after if @child
840
+ node.values.each do |value|
841
+ formatter.before_table_cell(value)
842
+ formatter.table_cell_value(value, @status || :skipped)
843
+ formatter.after_table_cell(value)
844
+ end
845
+ @after_step_hook_result.send_output_to(formatter) if @after_step_hook_result
846
+ after_hook_results.send_output_to(formatter)
847
+ formatter.after_table_row(legacy_table_row)
848
+ @after_step_hook_result.describe_exception_to(formatter) if @after_step_hook_result
849
+ after_hook_results.describe_exception_to(formatter)
850
+ @done = true
851
+ self
852
+ end
853
+
854
+ private
855
+
856
+ def already_failed?
857
+ @status == :failed || @status == :undefined || @status == :pending
858
+ end
859
+ end
860
+
861
+ class ExpandTableRowPrinter < TableRowPrinterBase
862
+ def before
863
+ before_hook_results.accept(formatter)
864
+ self
865
+ end
866
+
867
+ def step_invocation(step_invocation, source)
868
+ result = source.step_result
869
+ @table_row ||= legacy_table_row
870
+ step_invocation.indent.record_width_of(@table_row)
871
+ if !@scenario_name_printed
872
+ print_scenario_name(step_invocation, @table_row)
873
+ @scenario_name_printed = true
874
+ end
875
+ step_invocation.accept(formatter)
876
+ @failed_step = step_invocation if result.status == :failed
877
+ @status = step_invocation.status unless @status == :failed
878
+ end
879
+
880
+ def after
881
+ return if @done
882
+ @child.after if @child
883
+ @after_step_hook_result.accept(formatter) if @after_step_hook_result
884
+ after_hook_results.accept(formatter)
885
+ @done = true
886
+ self
887
+ end
888
+
889
+ private
890
+
891
+ def print_scenario_name(step_invocation, table_row)
892
+ formatter.scenario_name table_row.keyword, table_row.name, node.location.to_s, step_invocation.indent.of(table_row)
893
+ end
894
+ end
895
+
896
+ class Indent
897
+ def initialize(node)
898
+ @widths = []
899
+ node.describe_to(self)
900
+ end
901
+
902
+ [:background, :scenario, :scenario_outline].each do |node_name|
903
+ define_method(node_name) do |node, &descend|
904
+ record_width_of node
905
+ descend.call(self)
906
+ end
907
+ end
908
+
909
+ [:step, :outline_step].each do |node_name|
910
+ define_method(node_name) do |node|
911
+ record_width_of node
912
+ end
913
+ end
914
+
915
+ def examples_table(*); end
916
+ def examples_table_row(*); end
917
+
918
+ def of(node)
919
+ # The length of the instantiated steps in --expand mode are currently
920
+ # not included in the calculation of max => make sure to return >= 1
921
+ [1, max - node.name.length - node.keyword.length].max
922
+ end
923
+
924
+ def record_width_of(node)
925
+ @widths << node.keyword.length + node.name.length + 1
926
+ end
927
+
928
+ private
929
+
930
+ def max
931
+ @widths.max
932
+ end
933
+ end
934
+
935
+ class LegacyResultBuilder
936
+ attr_reader :status
937
+ def initialize(result)
938
+ @result = result
939
+ @result.describe_to(self)
940
+ end
941
+
942
+ def passed
943
+ @status = :passed
944
+ end
945
+
946
+ def failed
947
+ @status = :failed
948
+ end
949
+
950
+ def undefined
951
+ @status = :undefined
952
+ end
953
+
954
+ def skipped
955
+ @status = :skipped
956
+ end
957
+
958
+ def pending(exception, *)
959
+ @exception = exception
960
+ @status = :pending
961
+ end
962
+
963
+ def exception(exception, *)
964
+ @exception = exception
965
+ end
966
+
967
+ def append_to_exception_backtrace(line)
968
+ @exception.set_backtrace(@exception.backtrace + [line.to_s]) if @exception
969
+ return self
970
+ end
971
+
972
+ def duration(duration, *)
973
+ @duration = duration
974
+ end
975
+
976
+ def step_invocation(step_match, step, indent, background, configuration, messages, embeddings)
977
+ Ast::StepInvocation.new(step_match, @status, @duration, step_exception(step, configuration), indent, background, step, messages, embeddings)
978
+ end
979
+
980
+ def scenario(name, location)
981
+ Ast::Scenario.new(@status, name, location)
982
+ end
983
+
984
+ def scenario_outline(name, location)
985
+ Ast::ScenarioOutline.new(@status, name, location)
986
+ end
987
+
988
+ def describe_exception_to(formatter)
989
+ formatter.exception(filtered_exception, @status) if @exception
990
+ end
991
+
992
+ private
993
+
994
+ def step_exception(step, configuration)
995
+ return filtered_step_exception(step) if @exception
996
+ return nil unless @status == :undefined && configuration.strict?
997
+ @exception = Cucumber::Undefined.from(@result, step.name)
998
+ @exception.backtrace << step.backtrace_line
999
+ filtered_step_exception(step)
1000
+ end
1001
+
1002
+ def filtered_exception
1003
+ Cucumber::Formatter::BacktraceFilter.new(@exception.dup).exception
1004
+ end
1005
+
1006
+ def filtered_step_exception(step)
1007
+ exception = filtered_exception
1008
+ return Cucumber::Formatter::BacktraceFilter.new(exception).exception
1009
+ end
1010
+ end
1011
+
1012
+ end
1013
+
1014
+ end
1015
+ end
1016
+ end