cucumber 2.99.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (395) hide show
  1. checksums.yaml +4 -4
  2. data/.cucumberproignore +6 -0
  3. data/.gitattributes +32 -0
  4. data/.github/ISSUE_TEMPLATE.md +1 -1
  5. data/.github/PULL_REQUEST_TEMPLATE.md +1 -0
  6. data/.rubocop.yml +13 -0
  7. data/.rubocop_todo.yml +991 -0
  8. data/.travis.yml +56 -10
  9. data/{History.md → CHANGELOG.md} +166 -32
  10. data/CONTRIBUTING.md +21 -1
  11. data/Gemfile +18 -5
  12. data/README.md +13 -4
  13. data/Rakefile +12 -2
  14. data/appveyor.yml +27 -0
  15. data/bin/cucumber +2 -1
  16. data/cucumber.gemspec +15 -10
  17. data/cucumber.yml +10 -11
  18. data/examples/i18n/Rakefile +1 -1
  19. data/examples/i18n/ar/features/step_definitions/calculator_steps.rb +8 -3
  20. data/examples/i18n/ar/lib/calculator.rb +2 -2
  21. data/examples/i18n/bg/features/step_definitions/calculator_steps.rb +6 -6
  22. data/examples/i18n/bg/features/support/env.rb +6 -1
  23. data/examples/i18n/bg/lib/calculator.rb +2 -1
  24. data/examples/i18n/ca/features/step_definitions/calculator_steps.rb +10 -5
  25. data/examples/i18n/ca/lib/calculadora.rb +2 -2
  26. data/examples/i18n/cs/features/step_definitions/calculator_steps.rb +10 -5
  27. data/examples/i18n/cs/lib/calculator.rb +3 -3
  28. data/examples/i18n/da/features/step_definitions/lommeregner_steps.rb +10 -5
  29. data/examples/i18n/da/lib/lommeregner.rb +2 -2
  30. data/examples/i18n/de/features/step_definitions/calculator_steps.rb +10 -5
  31. data/examples/i18n/de/lib/calculator.rb +2 -2
  32. data/examples/i18n/el/features/step_definitions/calculator_steps.rb +10 -5
  33. data/examples/i18n/el/lib/calculator.rb +2 -2
  34. data/examples/i18n/en/features/step_definitions/calculator_steps.rb +9 -4
  35. data/examples/i18n/en/lib/calculator.rb +2 -2
  36. data/examples/i18n/en-lol/features/step_definitions/cucumbrz_steps.rb +4 -4
  37. data/examples/i18n/en-lol/features/support/env.rb +6 -2
  38. data/examples/i18n/en-lol/lib/basket.rb +2 -2
  39. data/examples/i18n/en-lol/lib/belly.rb +2 -2
  40. data/examples/i18n/eo/features/step_definitions/calculator_steps.rb +9 -4
  41. data/examples/i18n/eo/lib/calculator.rb +2 -2
  42. data/examples/i18n/es/features/step_definitions/calculador_steps.rb +10 -5
  43. data/examples/i18n/es/lib/calculador.rb +2 -2
  44. data/examples/i18n/et/features/step_definitions/kalkulaator_steps.rb +10 -5
  45. data/examples/i18n/et/lib/kalkulaator.rb +3 -3
  46. data/examples/i18n/fi/features/step_definitions/laskin_steps.rb +9 -4
  47. data/examples/i18n/fi/lib/laskin.rb +1 -1
  48. data/examples/i18n/fr/features/step_definitions/calculatrice_steps.rb +8 -8
  49. data/examples/i18n/fr/features/support/env.rb +7 -2
  50. data/examples/i18n/fr/lib/calculatrice.rb +2 -2
  51. data/examples/i18n/he/features/step_definitions/calculator_steps.rb +10 -5
  52. data/examples/i18n/he/lib/calculator.rb +1 -1
  53. data/examples/i18n/hi/features/step_definitions/calculator_steps.rb +9 -4
  54. data/examples/i18n/hi/lib/calculator.rb +1 -1
  55. data/examples/i18n/ht/features/step_definitions/kalkilatris_steps.rb +9 -5
  56. data/examples/i18n/ht/lib/kalkilatris.rb +2 -2
  57. data/examples/i18n/hu/features/step_definitions/calculator_steps.rb +10 -5
  58. data/examples/i18n/hu/lib/calculator.rb +1 -1
  59. data/examples/i18n/id/features/step_definitions/calculator_steps.rb +10 -5
  60. data/examples/i18n/id/lib/calculator.rb +2 -2
  61. data/examples/i18n/it/features/step_definitions/calcolatrice_steps.rb +10 -5
  62. data/examples/i18n/it/lib/calcolatrice.rb +3 -3
  63. data/examples/i18n/ja/features/step_definitions/calculator_steps.rb +3 -3
  64. data/examples/i18n/ja/features/support/env.rb +7 -2
  65. data/examples/i18n/ja/lib/calculator.rb +2 -2
  66. data/examples/i18n/ko/features/step_definitions/calculator_steps.rb +10 -5
  67. data/examples/i18n/ko/lib/calculator.rb +2 -2
  68. data/examples/i18n/lt/features/step_definitions/calculator_steps.rb +10 -5
  69. data/examples/i18n/lt/lib/calculator.rb +2 -2
  70. data/examples/i18n/lv/features/step_definitions/calculator_steps.rb +10 -5
  71. data/examples/i18n/lv/lib/calculator.rb +2 -2
  72. data/examples/i18n/no/features/step_definitions/kalkulator_steps.rb +3 -3
  73. data/examples/i18n/no/features/support/env.rb +7 -2
  74. data/examples/i18n/no/lib/kalkulator.rb +2 -2
  75. data/examples/i18n/pl/features/step_definitions/calculator_steps.rb +10 -5
  76. data/examples/i18n/pl/features/support/env.rb +6 -1
  77. data/examples/i18n/pl/lib/calculator.rb +2 -2
  78. data/examples/i18n/pt/features/step_definitions/calculadora_steps.rb +3 -3
  79. data/examples/i18n/pt/features/support/env.rb +7 -2
  80. data/examples/i18n/pt/lib/calculadora.rb +1 -1
  81. data/examples/i18n/ro/features/step_definitions/calculator_steps.rb +11 -6
  82. data/examples/i18n/ro/lib/calculator.rb +1 -1
  83. data/examples/i18n/ru/features/step_definitions/calculator_steps.rb +5 -5
  84. data/examples/i18n/ru/features/support/env.rb +6 -1
  85. data/examples/i18n/ru/lib/calculator.rb +2 -1
  86. data/examples/i18n/sk/features/step_definitions/calculator_steps.rb +10 -5
  87. data/examples/i18n/sk/lib/calculator.rb +2 -2
  88. data/examples/i18n/sr-Cyrl/features/step_definitions/calculator_steps.rb +3 -3
  89. data/examples/i18n/sr-Cyrl/features/support/env.rb +7 -2
  90. data/examples/i18n/sr-Cyrl/lib/calculator.rb +2 -2
  91. data/examples/i18n/sr-Latn/features/step_definitions/calculator_steps.rb +10 -5
  92. data/examples/i18n/sr-Latn/lib/calculator.rb +2 -2
  93. data/examples/i18n/sv/features/step_definitions/kalkulator_steps.rb +9 -4
  94. data/examples/i18n/sv/lib/kalkulator.rb +2 -2
  95. data/examples/i18n/tr/features/step_definitions/hesap_makinesi_adimlari.rb +10 -5
  96. data/examples/i18n/tr/lib/hesap_makinesi.rb +2 -2
  97. data/examples/i18n/uk/features/step_definitions/calculator_steps.rb +4 -4
  98. data/examples/i18n/uk/features/support/env.rb +6 -1
  99. data/examples/i18n/uk/lib/calculator.rb +2 -1
  100. data/examples/i18n/uz/features/step_definitions/calculator_steps.rb +4 -4
  101. data/examples/i18n/uz/features/support/env.rb +6 -1
  102. data/examples/i18n/uz/lib/calculator.rb +2 -1
  103. data/examples/i18n/zh-CN/features/step_definitions/calculator_steps.rb +11 -6
  104. data/examples/i18n/zh-CN/lib/calculator.rb +2 -2
  105. data/examples/i18n/zh-TW/features/step_definitions/calculator_steps.rb +10 -5
  106. data/examples/i18n/zh-TW/lib/calculator.rb +2 -2
  107. data/examples/rspec_doubles/features/step_definitions/calvin_steps.rb +3 -3
  108. data/examples/sinatra/features/step_definitions/add_steps.rb +4 -4
  109. data/examples/sinatra/features/support/env.rb +6 -1
  110. data/examples/tcl/features/step_definitions/fib_steps.rb +2 -2
  111. data/examples/tcl/features/support/env.rb +2 -1
  112. data/examples/test_unit/features/step_definitions/test_unit_steps.rb +4 -4
  113. data/examples/watir/features/step_definitions/search_steps.rb +6 -5
  114. data/examples/watir/features/support/env.rb +5 -1
  115. data/examples/watir/features/support/screenshots.rb +5 -5
  116. data/features/docs/api/list_step_defs_as_json.feature +21 -7
  117. data/features/docs/api/listen_for_events.feature +9 -8
  118. data/features/docs/api/run_cli_main_with_existing_runtime.feature +1 -0
  119. data/features/docs/cli/dry_run.feature +3 -0
  120. data/features/docs/cli/execute_with_tag_filter.feature +8 -6
  121. data/features/docs/cli/fail_fast.feature +2 -0
  122. data/features/docs/cli/help.feature +8 -0
  123. data/features/docs/{gherkin/language_help.feature → cli/i18n.feature} +6 -6
  124. data/features/docs/cli/randomize.feature +2 -2
  125. data/features/docs/cli/retry_failing_tests.feature +75 -15
  126. data/features/docs/cli/run_scenarios_matching_name.feature +1 -0
  127. data/features/docs/cli/specifying_multiple_formatters.feature +3 -0
  128. data/features/docs/cli/strict_mode.feature +6 -0
  129. data/features/docs/defining_steps/ambiguous_steps.feature +89 -0
  130. data/features/docs/defining_steps/nested_steps.feature +5 -1
  131. data/features/docs/defining_steps/nested_steps_i18n.feature +3 -0
  132. data/features/docs/defining_steps/nested_steps_with_second_arg.feature +2 -0
  133. data/features/docs/defining_steps/printing_messages.feature +1 -2
  134. data/features/docs/defining_steps/skip_scenario.feature +1 -34
  135. data/features/docs/defining_steps/snippets.feature +18 -18
  136. data/features/docs/events/gherkin_source_read_event.feature +43 -0
  137. data/features/docs/events/step_activated_event.feature +36 -0
  138. data/features/docs/events/step_definition_registered_event.feature +29 -0
  139. data/features/docs/events/test_case_finished_event.feature +35 -0
  140. data/features/docs/events/test_case_started_event.feature +54 -0
  141. data/features/docs/events/test_run_finished_event.feature +40 -0
  142. data/features/docs/events/test_run_started_event.feature +41 -0
  143. data/features/docs/events/test_step_finished_event.feature +47 -0
  144. data/features/docs/events/test_step_started_event.feature +43 -0
  145. data/features/docs/exception_in_after_hook.feature +3 -2
  146. data/features/docs/exception_in_after_step_hook.feature +2 -0
  147. data/features/docs/exception_in_around_hook.feature +2 -0
  148. data/features/docs/exception_in_before_hook.feature +3 -1
  149. data/features/docs/extending_cucumber/custom_formatter.feature +12 -48
  150. data/features/docs/formatters/json_formatter.feature +4 -4
  151. data/features/docs/formatters/junit_formatter.feature +7 -6
  152. data/features/docs/formatters/pretty_formatter.feature +1 -0
  153. data/features/docs/formatters/progress_formatter.feature +1 -0
  154. data/features/docs/formatters/rerun_formatter.feature +2 -0
  155. data/features/docs/formatters/summary_formatter.feature +35 -0
  156. data/features/docs/formatters/usage_formatter.feature +3 -0
  157. data/features/docs/getting_started.feature +2 -1
  158. data/features/docs/gherkin/background.feature +5 -5
  159. data/features/docs/gherkin/doc_strings.feature +2 -0
  160. data/features/docs/gherkin/expand_option_for_outlines.feature +1 -0
  161. data/features/docs/gherkin/outlines.feature +6 -4
  162. data/features/docs/gherkin/unicode_table.feature +2 -1
  163. data/features/docs/gherkin/using_descriptions.feature +1 -0
  164. data/features/docs/gherkin/using_star_notation.feature +1 -1
  165. data/features/docs/post_configuration_hook.feature +1 -17
  166. data/features/docs/rake_task.feature +5 -0
  167. data/features/docs/raketask.feature +3 -1
  168. data/features/docs/work_in_progress.feature +5 -2
  169. data/features/docs/writing_support_code/after_step_hooks.feature +3 -1
  170. data/features/docs/writing_support_code/around_hooks.feature +6 -0
  171. data/features/docs/writing_support_code/before_hook.feature +1 -0
  172. data/features/docs/writing_support_code/hook_order.feature +3 -1
  173. data/features/docs/writing_support_code/parameter_types.feature +53 -0
  174. data/features/docs/writing_support_code/tagged_hooks.feature +1 -1
  175. data/features/docs/writing_support_code/world.feature +129 -0
  176. data/features/lib/step_definitions/aruba_steps.rb +5 -10
  177. data/features/lib/step_definitions/cli_steps.rb +4 -0
  178. data/features/lib/step_definitions/cucumber_steps.rb +9 -12
  179. data/features/lib/step_definitions/iso-8859-1_steps.rb +9 -5
  180. data/features/lib/step_definitions/json_steps.rb +2 -1
  181. data/features/lib/step_definitions/junit_steps.rb +2 -1
  182. data/features/lib/step_definitions/language_steps.rb +3 -2
  183. data/features/lib/step_definitions/profile_steps.rb +7 -6
  184. data/features/lib/step_definitions/retry_steps.rb +33 -13
  185. data/features/lib/step_definitions/ruby_steps.rb +2 -1
  186. data/features/lib/support/env.rb +3 -2
  187. data/features/lib/support/fake_wire_server.rb +17 -3
  188. data/features/lib/support/feature_factory.rb +2 -1
  189. data/features/lib/support/normalise_output.rb +14 -12
  190. data/features/lib/support/parameter_types.rb +5 -0
  191. data/gem_tasks/contributors.rake +10 -6
  192. data/gem_tasks/cov.rake +1 -0
  193. data/gem_tasks/downloads.rb +1 -0
  194. data/gem_tasks/environment.rake +2 -5
  195. data/gem_tasks/examples.rake +3 -2
  196. data/gem_tasks/fix_cr_lf.rake +19 -7
  197. data/gem_tasks/flog.rake +4 -3
  198. data/gem_tasks/rspec.rake +2 -1
  199. data/gem_tasks/sass.rake +2 -1
  200. data/lib/autotest/cucumber.rb +1 -0
  201. data/lib/autotest/cucumber_mixin.rb +17 -16
  202. data/lib/autotest/cucumber_rails.rb +1 -0
  203. data/lib/autotest/cucumber_rails_rspec.rb +1 -0
  204. data/lib/autotest/cucumber_rails_rspec2.rb +1 -0
  205. data/lib/autotest/cucumber_rspec.rb +1 -0
  206. data/lib/autotest/cucumber_rspec2.rb +1 -0
  207. data/lib/autotest/discover.rb +3 -2
  208. data/lib/cucumber/cli/configuration.rb +12 -21
  209. data/lib/cucumber/cli/main.rb +8 -7
  210. data/lib/cucumber/cli/options.rb +341 -217
  211. data/lib/cucumber/cli/profile_loader.rb +26 -21
  212. data/lib/cucumber/cli/rerun_file.rb +1 -0
  213. data/lib/cucumber/configuration.rb +54 -37
  214. data/lib/cucumber/constantize.rb +2 -1
  215. data/lib/cucumber/core_ext/string.rb +2 -1
  216. data/lib/cucumber/deprecate.rb +4 -3
  217. data/lib/cucumber/encoding.rb +1 -0
  218. data/lib/cucumber/errors.rb +3 -1
  219. data/lib/cucumber/events/gherkin_source_read.rb +17 -0
  220. data/lib/cucumber/events/{step_match.rb → step_activated.rb} +5 -2
  221. data/lib/cucumber/events/step_definition_registered.rb +24 -0
  222. data/lib/cucumber/events/test_case_finished.rb +18 -0
  223. data/lib/cucumber/events/test_case_started.rb +15 -0
  224. data/lib/cucumber/events/test_run_finished.rb +12 -0
  225. data/lib/cucumber/events/test_run_started.rb +16 -0
  226. data/lib/cucumber/events/test_step_finished.rb +20 -0
  227. data/lib/cucumber/events/test_step_started.rb +17 -0
  228. data/lib/cucumber/events.rb +23 -3
  229. data/lib/cucumber/file_specs.rb +1 -0
  230. data/lib/cucumber/filters/activate_steps.rb +8 -3
  231. data/lib/cucumber/filters/apply_after_hooks.rb +1 -0
  232. data/lib/cucumber/filters/apply_after_step_hooks.rb +1 -0
  233. data/lib/cucumber/filters/apply_around_hooks.rb +1 -0
  234. data/lib/cucumber/filters/apply_before_hooks.rb +1 -0
  235. data/lib/cucumber/filters/broadcast_test_run_started_event.rb +27 -0
  236. data/lib/cucumber/filters/gated_receiver.rb +1 -0
  237. data/lib/cucumber/filters/prepare_world.rb +1 -0
  238. data/lib/cucumber/filters/quit.rb +1 -0
  239. data/lib/cucumber/filters/randomizer.rb +1 -0
  240. data/lib/cucumber/filters/retry.rb +4 -4
  241. data/lib/cucumber/filters/tag_limits/test_case_index.rb +1 -0
  242. data/lib/cucumber/filters/tag_limits/verifier.rb +2 -1
  243. data/lib/cucumber/filters/tag_limits.rb +4 -3
  244. data/lib/cucumber/filters.rb +3 -0
  245. data/lib/cucumber/formatter/ansicolor.rb +9 -11
  246. data/lib/cucumber/formatter/backtrace_filter.rb +21 -8
  247. data/lib/cucumber/formatter/console.rb +72 -66
  248. data/lib/cucumber/formatter/console_counts.rb +44 -0
  249. data/lib/cucumber/formatter/console_issues.rb +58 -0
  250. data/lib/cucumber/formatter/duration.rb +2 -1
  251. data/lib/cucumber/formatter/duration_extractor.rb +1 -0
  252. data/lib/cucumber/formatter/fail_fast.rb +4 -2
  253. data/lib/cucumber/formatter/fanout.rb +1 -0
  254. data/lib/cucumber/formatter/hook_query_visitor.rb +1 -0
  255. data/lib/cucumber/formatter/html.rb +175 -249
  256. data/lib/cucumber/formatter/html_builder.rb +120 -0
  257. data/lib/cucumber/formatter/ignore_missing_messages.rb +1 -0
  258. data/lib/cucumber/formatter/inline-js.js +30 -0
  259. data/lib/cucumber/formatter/interceptor.rb +3 -2
  260. data/lib/cucumber/formatter/io.rb +2 -1
  261. data/lib/cucumber/formatter/json.rb +33 -30
  262. data/lib/cucumber/formatter/json_pretty.rb +1 -0
  263. data/lib/cucumber/formatter/junit.rb +26 -24
  264. data/lib/cucumber/formatter/legacy_api/adapter.rb +81 -69
  265. data/lib/cucumber/formatter/legacy_api/ast.rb +27 -22
  266. data/lib/cucumber/formatter/legacy_api/results.rb +7 -8
  267. data/lib/cucumber/formatter/legacy_api/runtime_facade.rb +1 -0
  268. data/lib/cucumber/formatter/pretty.rb +24 -18
  269. data/lib/cucumber/formatter/progress.rb +55 -13
  270. data/lib/cucumber/formatter/rerun.rb +15 -18
  271. data/lib/cucumber/formatter/stepdefs.rb +1 -0
  272. data/lib/cucumber/formatter/steps.rb +2 -1
  273. data/lib/cucumber/formatter/summary.rb +43 -20
  274. data/lib/cucumber/formatter/unicode.rb +2 -1
  275. data/lib/cucumber/formatter/usage.rb +33 -28
  276. data/lib/cucumber/gherkin/data_table_parser.rb +1 -0
  277. data/lib/cucumber/gherkin/formatter/ansi_escapes.rb +2 -1
  278. data/lib/cucumber/gherkin/formatter/escaping.rb +2 -1
  279. data/lib/cucumber/gherkin/i18n.rb +1 -0
  280. data/lib/cucumber/gherkin/steps_parser.rb +1 -0
  281. data/lib/cucumber/{rb_support/rb_dsl.rb → glue/dsl.rb} +41 -30
  282. data/lib/cucumber/glue/hook.rb +43 -0
  283. data/lib/cucumber/glue/invoke_in_world.rb +70 -0
  284. data/lib/cucumber/glue/proto_world.rb +220 -0
  285. data/lib/cucumber/{rb_support/rb_language.rb → glue/registry_and_more.rb} +60 -90
  286. data/lib/cucumber/{rb_support → glue}/snippet.rb +64 -26
  287. data/lib/cucumber/glue/step_definition.rb +143 -0
  288. data/lib/cucumber/glue/world_factory.rb +23 -0
  289. data/lib/cucumber/hooks.rb +9 -8
  290. data/lib/cucumber/load_path.rb +1 -0
  291. data/lib/cucumber/multiline_argument/data_table/diff_matrices.rb +158 -0
  292. data/lib/cucumber/multiline_argument/data_table.rb +47 -181
  293. data/lib/cucumber/multiline_argument/doc_string.rb +1 -0
  294. data/lib/cucumber/multiline_argument.rb +6 -15
  295. data/lib/cucumber/platform.rb +4 -5
  296. data/lib/cucumber/project_initializer.rb +3 -2
  297. data/lib/cucumber/rake/task.rb +19 -14
  298. data/lib/cucumber/rspec/disable_option_parser.rb +2 -1
  299. data/lib/cucumber/rspec/doubles.rb +2 -1
  300. data/lib/cucumber/running_test_case.rb +3 -27
  301. data/lib/cucumber/runtime/after_hooks.rb +2 -1
  302. data/lib/cucumber/runtime/before_hooks.rb +1 -0
  303. data/lib/cucumber/runtime/for_programming_languages.rb +2 -36
  304. data/lib/cucumber/runtime/step_hooks.rb +1 -0
  305. data/lib/cucumber/runtime/support_code.rb +21 -16
  306. data/lib/cucumber/runtime/user_interface.rb +10 -16
  307. data/lib/cucumber/runtime.rb +49 -32
  308. data/lib/cucumber/step_argument.rb +1 -2
  309. data/lib/cucumber/step_definition_light.rb +2 -0
  310. data/lib/cucumber/step_definitions.rb +1 -0
  311. data/lib/cucumber/step_match.rb +30 -15
  312. data/lib/cucumber/step_match_search.rb +3 -3
  313. data/lib/cucumber/term/ansicolor.rb +2 -1
  314. data/lib/cucumber/unit.rb +1 -0
  315. data/lib/cucumber/version +1 -1
  316. data/lib/cucumber.rb +1 -13
  317. data/lib/simplecov_setup.rb +2 -1
  318. data/scripts/invite-collaborator +40 -0
  319. data/scripts/update-changelog +86 -0
  320. data/spec/cucumber/cli/configuration_spec.rb +109 -98
  321. data/spec/cucumber/cli/main_spec.rb +8 -7
  322. data/spec/cucumber/cli/options_spec.rb +114 -79
  323. data/spec/cucumber/cli/profile_loader_spec.rb +25 -5
  324. data/spec/cucumber/cli/rerun_spec.rb +21 -20
  325. data/spec/cucumber/configuration_spec.rb +48 -47
  326. data/spec/cucumber/constantize_spec.rb +3 -2
  327. data/spec/cucumber/events_spec.rb +9 -0
  328. data/spec/cucumber/file_specs_spec.rb +26 -25
  329. data/spec/cucumber/filters/activate_steps_spec.rb +25 -22
  330. data/spec/cucumber/filters/gated_receiver_spec.rb +7 -6
  331. data/spec/cucumber/filters/retry_spec.rb +42 -23
  332. data/spec/cucumber/filters/tag_limits/test_case_index_spec.rb +12 -11
  333. data/spec/cucumber/filters/tag_limits/verifier_spec.rb +15 -14
  334. data/spec/cucumber/filters/tag_limits_spec.rb +9 -8
  335. data/spec/cucumber/formatter/ansicolor_spec.rb +10 -9
  336. data/spec/cucumber/formatter/backtrace_filter_spec.rb +32 -0
  337. data/spec/cucumber/formatter/console_counts_spec.rb +14 -0
  338. data/spec/cucumber/formatter/duration_spec.rb +4 -3
  339. data/spec/cucumber/formatter/fail_fast_spec.rb +27 -27
  340. data/spec/cucumber/formatter/html_spec.rb +65 -60
  341. data/spec/cucumber/formatter/interceptor_spec.rb +1 -0
  342. data/spec/cucumber/formatter/json_spec.rb +71 -97
  343. data/spec/cucumber/formatter/junit_spec.rb +46 -47
  344. data/spec/cucumber/formatter/legacy_api/adapter_spec.rb +134 -141
  345. data/spec/cucumber/formatter/pretty_spec.rb +105 -117
  346. data/spec/cucumber/formatter/progress_spec.rb +22 -21
  347. data/spec/cucumber/formatter/rerun_spec.rb +70 -64
  348. data/spec/cucumber/formatter/spec_helper.rb +14 -12
  349. data/spec/cucumber/{rb_support/rb_world_spec.rb → glue/proto_world_spec.rb} +22 -6
  350. data/spec/cucumber/glue/registry_and_more_spec.rb +213 -0
  351. data/spec/cucumber/{rb_support → glue}/snippet_spec.rb +62 -25
  352. data/spec/cucumber/glue/step_definition_spec.rb +207 -0
  353. data/spec/cucumber/hooks_spec.rb +5 -4
  354. data/spec/cucumber/multiline_argument/data_table_spec.rb +179 -129
  355. data/spec/cucumber/project_initializer_spec.rb +12 -11
  356. data/spec/cucumber/rake/forked_spec.rb +22 -17
  357. data/spec/cucumber/rake/task_spec.rb +21 -20
  358. data/spec/cucumber/running_test_case_spec.rb +36 -35
  359. data/spec/cucumber/runtime/for_programming_languages_spec.rb +2 -30
  360. data/spec/cucumber/runtime/support_code_spec.rb +1 -0
  361. data/spec/cucumber/runtime_spec.rb +3 -2
  362. data/spec/cucumber/step_argument_spec.rb +6 -5
  363. data/spec/cucumber/step_match_search_spec.rb +32 -41
  364. data/spec/cucumber/step_match_spec.rb +34 -33
  365. data/spec/cucumber/world/pending_spec.rb +12 -11
  366. data/spec/spec_helper.rb +1 -0
  367. data/spec/support/standard_step_actions.rb +2 -1
  368. metadata +132 -61
  369. data/features/docs/formatters/debug_formatter.feature +0 -47
  370. data/features/docs/formatters/formatter_step_file_colon_line.feature +0 -44
  371. data/features/docs/writing_support_code/transforms.feature +0 -98
  372. data/features/lib/step_definitions/wire_steps.rb +0 -58
  373. data/gem_tasks/cucumber.rake +0 -25
  374. data/lib/cucumber/ast.rb +0 -13
  375. data/lib/cucumber/core_ext/instance_exec.rb +0 -70
  376. data/lib/cucumber/events/after_test_case.rb +0 -25
  377. data/lib/cucumber/events/after_test_step.rb +0 -30
  378. data/lib/cucumber/events/before_test_case.rb +0 -18
  379. data/lib/cucumber/events/before_test_step.rb +0 -23
  380. data/lib/cucumber/events/bus.rb +0 -86
  381. data/lib/cucumber/events/finished_testing.rb +0 -9
  382. data/lib/cucumber/formatter/debug.rb +0 -35
  383. data/lib/cucumber/formatter/event_bus_report.rb +0 -38
  384. data/lib/cucumber/rb_support/rb_hook.rb +0 -19
  385. data/lib/cucumber/rb_support/rb_step_definition.rb +0 -131
  386. data/lib/cucumber/rb_support/rb_transform.rb +0 -59
  387. data/lib/cucumber/rb_support/rb_world.rb +0 -149
  388. data/spec/cucumber/core_ext/instance_exec_spec.rb +0 -4
  389. data/spec/cucumber/events/bus_spec.rb +0 -94
  390. data/spec/cucumber/formatter/debug_spec.rb +0 -64
  391. data/spec/cucumber/formatter/event_bus_report_spec.rb +0 -88
  392. data/spec/cucumber/rb_support/rb_language_spec.rb +0 -243
  393. data/spec/cucumber/rb_support/rb_step_definition_spec.rb +0 -199
  394. data/spec/cucumber/rb_support/rb_transform_spec.rb +0 -46
  395. data/spec/cucumber_spec.rb +0 -39
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
1
2
  require 'erb'
2
- require 'builder'
3
3
  require 'cucumber/formatter/duration'
4
4
  require 'cucumber/formatter/io'
5
+ require 'cucumber/formatter/html_builder'
5
6
  require 'pathname'
6
7
 
7
8
  module Cucumber
@@ -13,174 +14,141 @@ module Cucumber
13
14
  Cucumber::Core::Ast::Scenario => 'scenario',
14
15
  Cucumber::Core::Ast::ScenarioOutline => 'scenario outline'
15
16
  }
17
+
16
18
  AST_DATA_TABLE = LegacyApi::Ast::MultilineArg::DataTable
17
19
 
18
20
  include ERB::Util # for the #h method
19
21
  include Duration
20
22
  include Io
21
23
 
24
+ attr_reader :builder
25
+ private :builder
26
+
22
27
  def initialize(runtime, path_or_io, options)
23
28
  @io = ensure_io(path_or_io)
24
29
  @runtime = runtime
25
30
  @options = options
26
31
  @buffer = {}
27
- @builder = create_builder(@io)
32
+ @builder = HtmlBuilder.new(target: @io, indent: 0)
28
33
  @feature_number = 0
29
34
  @scenario_number = 0
30
35
  @step_number = 0
31
36
  @header_red = nil
32
37
  @delayed_messages = []
33
- @img_id = 0
34
- @text_id = 0
35
- @inside_outline = false
38
+ @inside_outline = false
36
39
  @previous_step_keyword = nil
37
40
  end
38
41
 
39
42
  def embed(src, mime_type, label)
40
- case(mime_type)
41
- when /^image\/(png|gif|jpg|jpeg)/
42
- unless File.file?(src) or src =~ /^data:image\/(png|gif|jpg|jpeg);base64,/
43
- type = mime_type =~ /;base[0-9]+$/ ? mime_type : mime_type + ";base64"
44
- src = "data:" + type + "," + src
45
- end
46
- embed_image(src, label)
47
- when /^text\/plain/
48
- embed_text(src, label)
43
+ if image?(mime_type)
44
+ src = src_is_file_or_data?(src) ? src : "data:#{standardize_mime_type(mime_type)},#{src}"
45
+ builder.embed(type: :image, src: set_path(src), label: label, id: next_id(:img))
46
+ else
47
+ builder.embed(type: :text, src: src, label: label, id: next_id(:text))
49
48
  end
50
49
  end
51
50
 
52
- def embed_image(src, label)
53
- id = "img_#{@img_id}"
54
- @img_id += 1
55
- if @io.respond_to?(:path) and File.file?(src)
51
+ def set_path(src)
52
+ if @io.respond_to?(:path) && File.file?(src)
56
53
  out_dir = Pathname.new(File.dirname(File.absolute_path(@io.path)))
57
54
  src = Pathname.new(File.absolute_path(src)).relative_path_from(out_dir)
58
- end
59
- @builder.span(:class => 'embed') do |pre|
60
- pre << %{<a href="" onclick="img=document.getElementById('#{id}'); img.style.display = (img.style.display == 'none' ? 'block' : 'none');return false">#{label}</a><br>&nbsp;
61
- <img id="#{id}" style="display: none" src="#{src}"/>}
62
55
  end
56
+
57
+ src
63
58
  end
64
59
 
65
- def embed_text(src, label)
66
- id = "text_#{@text_id}"
67
- @text_id += 1
68
- @builder.span(:class => 'embed') do |pre|
69
- pre << %{<a id="#{id}" href="#{src}" title="#{label}">#{label}</a>}
70
- end
60
+ def standardize_mime_type(mime_type)
61
+ mime_type =~ /;base[0-9]+$/ ? mime_type : mime_type + ';base64'
71
62
  end
72
63
 
64
+ def src_is_file_or_data?(src)
65
+ File.file?(src) || src =~ /^data:image\/(png|gif|jpg|jpeg);base64,/
66
+ end
67
+
68
+ def image?(mime_type)
69
+ mime_type =~ /^image\/(png|gif|jpg|jpeg)/
70
+ end
73
71
 
74
72
  def before_features(features)
75
73
  @step_count = features && features.step_count || 0 #TODO: Make this work with core!
76
74
 
77
- # <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
78
- @builder.declare!(
79
- :DOCTYPE,
80
- :html,
81
- :PUBLIC,
82
- '-//W3C//DTD XHTML 1.0 Strict//EN',
83
- 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'
84
- )
85
-
86
- @builder << '<html xmlns ="http://www.w3.org/1999/xhtml">'
87
- @builder.head do
88
- @builder.meta('http-equiv' => 'Content-Type', :content => 'text/html;charset=utf-8')
89
- @builder.title 'Cucumber'
90
- inline_css
91
- inline_js
92
- end
93
- @builder << '<body>'
94
- @builder << "<!-- Step count #{@step_count}-->"
95
- @builder << '<div class="cucumber">'
96
- @builder.div(:id => 'cucumber-header') do
97
- @builder.div(:id => 'label') do
98
- @builder.h1('Cucumber Features')
99
- end
100
- @builder.div(:id => 'summary') do
101
- @builder.p('',:id => 'totals')
102
- @builder.p('',:id => 'duration')
103
- @builder.div(:id => 'expand-collapse') do
104
- @builder.p('Expand All', :id => 'expander')
105
- @builder.p('Collapse All', :id => 'collapser')
106
- end
107
- end
108
- end
75
+ builder.build_document!
76
+ builder.format_features! features
109
77
  end
110
78
 
111
79
  def after_features(features)
112
80
  print_stats(features)
113
- @builder << '</div>'
114
- @builder << '</body>'
115
- @builder << '</html>'
81
+ builder << '</div>'
82
+ builder << '</body>'
83
+ builder << '</html>'
116
84
  end
117
85
 
118
- def before_feature(feature)
86
+ def before_feature(_feature)
119
87
  @exceptions = []
120
- @builder << '<div class="feature">'
88
+ builder << '<div class="feature">'
121
89
  end
122
90
 
123
- def after_feature(feature)
124
- @builder << '</div>'
91
+ def after_feature(_feature)
92
+ builder << '</div>'
125
93
  end
126
94
 
127
- def before_comment(comment)
128
- @builder << '<pre class="comment">'
95
+ def before_comment(_comment)
96
+ builder << '<pre class="comment">'
129
97
  end
130
98
 
131
- def after_comment(comment)
132
- @builder << '</pre>'
99
+ def after_comment(_comment)
100
+ builder << '</pre>'
133
101
  end
134
102
 
135
103
  def comment_line(comment_line)
136
- @builder.text!(comment_line)
137
- @builder.br
104
+ builder.text!(comment_line)
105
+ builder.br
138
106
  end
139
107
 
140
- def after_tags(tags)
108
+ def after_tags(_tags)
141
109
  @tag_spacer = nil
142
110
  end
143
111
 
144
112
  def tag_name(tag_name)
145
- @builder.text!(@tag_spacer) if @tag_spacer
113
+ builder.text!(@tag_spacer) if @tag_spacer
146
114
  @tag_spacer = ' '
147
- @builder.span(tag_name, :class => 'tag')
115
+ builder.span(tag_name, :class => 'tag')
148
116
  end
149
117
 
150
118
  def feature_name(keyword, name)
151
119
  lines = name.split(/\r?\n/)
152
120
  return if lines.empty?
153
- @builder.h2 do |h2|
154
- @builder.span(keyword + ': ' + lines[0], :class => 'val')
121
+ builder.h2 do |h2|
122
+ builder.span(keyword + ': ' + lines[0], :class => 'val')
155
123
  end
156
- @builder.p(:class => 'narrative') do
124
+ builder.p(:class => 'narrative') do
157
125
  lines[1..-1].each do |line|
158
- @builder.text!(line.strip)
159
- @builder.br
126
+ builder.text!(line.strip)
127
+ builder.br
160
128
  end
161
129
  end
162
130
  end
163
131
 
164
- def before_test_case(test_case)
132
+ def before_test_case(_test_case)
165
133
  @previous_step_keyword = nil
166
134
  end
167
135
 
168
- def before_background(background)
136
+ def before_background(_background)
169
137
  @in_background = true
170
- @builder << '<div class="background">'
138
+ builder << '<div class="background">'
171
139
  end
172
140
 
173
- def after_background(background)
141
+ def after_background(_background)
174
142
  @in_background = nil
175
- @builder << '</div>'
143
+ builder << '</div>'
176
144
  end
177
145
 
178
- def background_name(keyword, name, file_colon_line, source_indent)
146
+ def background_name(keyword, name, _file_colon_line, _source_indent)
179
147
  @listing_background = true
180
- @builder.h3(:id => "background_#{@scenario_number}") do |h3|
181
- @builder.span(keyword, :class => 'keyword')
182
- @builder.text!(' ')
183
- @builder.span(name, :class => 'val')
148
+ builder.h3(:id => "background_#{@scenario_number}") do |h3|
149
+ builder.span(keyword, :class => 'keyword')
150
+ builder.text!(' ')
151
+ builder.span(name, :class => 'val')
184
152
  end
185
153
  end
186
154
 
@@ -188,22 +156,22 @@ module Cucumber
188
156
  @scenario_number+=1
189
157
  @scenario_red = false
190
158
  css_class = AST_CLASSES[feature_element.class]
191
- @builder << "<div class='#{css_class}'>"
159
+ builder << "<div class='#{css_class}'>"
192
160
  @in_scenario_outline = feature_element.class == Cucumber::Core::Ast::ScenarioOutline
193
161
  end
194
162
 
195
- def after_feature_element(feature_element)
163
+ def after_feature_element(_feature_element)
196
164
  unless @in_scenario_outline
197
165
  print_messages
198
- @builder << '</ol>'
166
+ builder << '</ol>'
199
167
  end
200
- @builder << '</div>'
168
+ builder << '</div>'
201
169
  @in_scenario_outline = nil
202
170
  end
203
171
 
204
- def scenario_name(keyword, name, file_colon_line, source_indent)
205
- @builder.span(:class => 'scenario_file') do
206
- @builder << file_colon_line
172
+ def scenario_name(keyword, name, file_colon_line, _source_indent)
173
+ builder.span(:class => 'scenario_file') do
174
+ builder << file_colon_line
207
175
  end
208
176
  @listing_background = false
209
177
  scenario_id = "scenario_#{@scenario_number}"
@@ -212,48 +180,48 @@ module Cucumber
212
180
  scenario_id += "_#{@outline_row}"
213
181
  @scenario_red = false
214
182
  end
215
- @builder.h3(:id => scenario_id) do
216
- @builder.span(keyword + ':', :class => 'keyword')
217
- @builder.text!(' ')
218
- @builder.span(name, :class => 'val')
183
+ builder.h3(:id => scenario_id) do
184
+ builder.span(keyword + ':', :class => 'keyword')
185
+ builder.text!(' ')
186
+ builder.span(name, :class => 'val')
219
187
  end
220
188
  end
221
189
 
222
- def before_outline_table(outline_table)
190
+ def before_outline_table(_outline_table)
223
191
  @inside_outline = true
224
192
  @outline_row = 0
225
- @builder << '<table>'
193
+ builder << '<table>'
226
194
  end
227
195
 
228
- def after_outline_table(outline_table)
229
- @builder << '</table>'
196
+ def after_outline_table(_outline_table)
197
+ builder << '</table>'
230
198
  @outline_row = nil
231
199
  @inside_outline = false
232
200
  end
233
201
 
234
- def before_examples(examples)
235
- @builder << '<div class="examples">'
202
+ def before_examples(_examples)
203
+ builder << '<div class="examples">'
236
204
  end
237
205
 
238
- def after_examples(examples)
239
- @builder << '</div>'
206
+ def after_examples(_examples)
207
+ builder << '</div>'
240
208
  end
241
209
 
242
210
  def examples_name(keyword, name)
243
- @builder.h4 do
244
- @builder.span(keyword, :class => 'keyword')
245
- @builder.text!(' ')
246
- @builder.span(name, :class => 'val')
211
+ builder.h4 do
212
+ builder.span(keyword, :class => 'keyword')
213
+ builder.text!(' ')
214
+ builder.span(name, :class => 'val')
247
215
  end
248
216
  end
249
217
 
250
- def before_steps(steps)
251
- @builder << '<ol>'
218
+ def before_steps(_steps)
219
+ builder << '<ol>'
252
220
  end
253
221
 
254
- def after_steps(steps)
222
+ def after_steps(_steps)
255
223
  print_messages
256
- @builder << '</ol>' if @in_background or @in_scenario_outline
224
+ builder << '</ol>' if @in_background || @in_scenario_outline
257
225
  end
258
226
 
259
227
  def before_step(step)
@@ -263,11 +231,11 @@ module Cucumber
263
231
  @step = step
264
232
  end
265
233
 
266
- def after_step(step)
234
+ def after_step(_step)
267
235
  move_progress
268
236
  end
269
237
 
270
- def before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line)
238
+ def before_step_result(_keyword, step_match, _multiline_arg, status, exception, _source_indent, background, _file_colon_line)
271
239
  @step_match = step_match
272
240
  @hide_this_step = false
273
241
  if exception
@@ -284,10 +252,10 @@ module Cucumber
284
252
  @status = status
285
253
  return if @hide_this_step
286
254
  set_scenario_color(status)
287
- @builder << "<li id='#{@step_id}' class='step #{status}'>"
255
+ builder << "<li id='#{@step_id}' class='step #{status}'>"
288
256
  end
289
257
 
290
- def after_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line)
258
+ def after_step_result(keyword, step_match, _multiline_arg, status, _exception, _source_indent, _background, _file_colon_line)
291
259
  return if @hide_this_step
292
260
  # print snippet for undefined steps
293
261
  unless outline_step?(@step)
@@ -295,17 +263,17 @@ module Cucumber
295
263
  @previous_step_keyword = keyword
296
264
  end
297
265
  if status == :undefined
298
- @builder.pre do |pre|
299
- # TODO: snippet text should be an event sent to the formatter so we don't
266
+ builder.pre do |pre|
267
+ # TODO: snippet text should be an event sent to the formatter so we don't
300
268
  # have this couping to the runtime.
301
- pre << @runtime.snippet_text(keyword,step_match.instance_variable_get("@name") || '', @step.multiline_arg)
269
+ pre << @runtime.snippet_text(keyword,step_match.instance_variable_get('@name') || '', @step.multiline_arg)
302
270
  end
303
271
  end
304
- @builder << '</li>'
272
+ builder << '</li>'
305
273
  print_messages
306
274
  end
307
275
 
308
- def step_name(keyword, step_match, status, source_indent, background, file_colon_line)
276
+ def step_name(keyword, step_match, status, _source_indent, background, _file_colon_line)
309
277
  background_in_scenario = background && !@listing_background
310
278
  @skip_step = background_in_scenario
311
279
 
@@ -314,7 +282,7 @@ module Cucumber
314
282
  end
315
283
  end
316
284
 
317
- def exception(exception, status)
285
+ def exception(exception, _status)
318
286
  return if @hide_this_step
319
287
  print_messages
320
288
  build_exception_detail(exception)
@@ -328,21 +296,21 @@ module Cucumber
328
296
  def before_multiline_arg(multiline_arg)
329
297
  return if @hide_this_step || @skip_step
330
298
  if AST_DATA_TABLE === multiline_arg
331
- @builder << '<table>'
299
+ builder << '<table>'
332
300
  end
333
301
  end
334
302
 
335
303
  def after_multiline_arg(multiline_arg)
336
304
  return if @hide_this_step || @skip_step
337
305
  if AST_DATA_TABLE === multiline_arg
338
- @builder << '</table>'
306
+ builder << '</table>'
339
307
  end
340
308
  end
341
309
 
342
310
  def doc_string(string)
343
311
  return if @hide_this_step
344
- @builder.pre(:class => 'val') do |pre|
345
- @builder << h(string).gsub("\n", '&#x000A;')
312
+ builder.pre(:class => 'val') do |pre|
313
+ builder << h(string).gsub("\n", '&#x000A;')
346
314
  end
347
315
  end
348
316
 
@@ -350,17 +318,17 @@ module Cucumber
350
318
  @row_id = table_row.dom_id
351
319
  @col_index = 0
352
320
  return if @hide_this_step
353
- @builder << "<tr class='step' id='#{@row_id}'>"
321
+ builder << "<tr class='step' id='#{@row_id}'>"
354
322
  end
355
323
 
356
324
  def after_table_row(table_row)
357
325
  return if @hide_this_step
358
326
  print_table_row_messages
359
- @builder << '</tr>'
327
+ builder << '</tr>'
360
328
  if table_row.exception
361
- @builder.tr do
362
- @builder.td(:colspan => @col_index.to_s, :class => 'failed') do
363
- @builder.pre do |pre|
329
+ builder.tr do
330
+ builder.td(:colspan => @col_index.to_s, :class => 'failed') do
331
+ builder.pre do |pre|
364
332
  pre << h(format_exception(table_row.exception))
365
333
  end
366
334
  end
@@ -391,16 +359,16 @@ module Cucumber
391
359
 
392
360
  def puts(message)
393
361
  @delayed_messages << message
394
- #@builder.pre(message, :class => 'message')
362
+ #builder.pre(message, :class => 'message')
395
363
  end
396
364
 
397
365
  def print_messages
398
366
  return if @delayed_messages.empty?
399
367
 
400
- #@builder.ol do
368
+ #builder.ol do
401
369
  @delayed_messages.each do |ann|
402
- @builder.li(:class => 'step message') do
403
- @builder << ann
370
+ builder.li(:class => 'step message') do
371
+ builder << ann
404
372
  end
405
373
  end
406
374
  #end
@@ -410,8 +378,8 @@ module Cucumber
410
378
  def print_table_row_messages
411
379
  return if @delayed_messages.empty?
412
380
 
413
- @builder.td(:class => 'message') do
414
- @builder << @delayed_messages.join(", ")
381
+ builder.td(:class => 'message') do
382
+ builder << @delayed_messages.join(', ')
415
383
  end
416
384
  empty_messages
417
385
  end
@@ -420,46 +388,56 @@ module Cucumber
420
388
  @delayed_messages = []
421
389
  end
422
390
 
423
- def after_test_case(test_case, result)
424
- if result.failed? and not @scenario_red
391
+ def after_test_case(_test_case, result)
392
+ if result.failed? && !@scenario_red
425
393
  set_scenario_color_failed
426
394
  end
427
395
  end
428
396
 
429
397
  protected
430
398
 
399
+ def next_id(type)
400
+ @indices ||= Hash.new { 0 }
401
+ @indices[type] += 1
402
+ "#{type}_#{@indices[:type]}"
403
+ end
404
+
431
405
  def build_exception_detail(exception)
432
406
  backtrace = Array.new
433
- @builder.div(:class => 'message') do
407
+
408
+ builder.div(:class => 'message') do
434
409
  message = exception.message
410
+
435
411
  if defined?(RAILS_ROOT) && message.include?('Exception caught')
436
412
  matches = message.match(/Showing <i>(.+)<\/i>(?:.+) #(\d+)/)
437
413
  backtrace += ["#{RAILS_ROOT}/#{matches[1]}:#{matches[2]}"] if matches
438
414
  matches = message.match(/<code>([^(\/)]+)<\//m)
439
- message = matches ? matches[1] : ""
415
+ message = matches ? matches[1] : ''
440
416
  end
441
417
 
442
418
  unless exception.instance_of?(RuntimeError)
443
419
  message = "#{message} (#{exception.class})"
444
420
  end
445
421
 
446
- @builder.pre do
447
- @builder.text!(message)
422
+ builder.pre do
423
+ builder.text!(message)
448
424
  end
449
425
  end
450
- @builder.div(:class => 'backtrace') do
451
- @builder.pre do
426
+
427
+ builder.div(:class => 'backtrace') do
428
+ builder.pre do
452
429
  backtrace = exception.backtrace
453
430
  backtrace.delete_if { |x| x =~ /\/gems\/(cucumber|rspec)/ }
454
- @builder << backtrace_line(backtrace.join("\n"))
431
+ builder << backtrace_line(backtrace.join("\n"))
455
432
  end
456
433
  end
434
+
457
435
  extra = extra_failure_content(backtrace)
458
- @builder << extra unless extra == ""
436
+ builder << extra unless extra == ''
459
437
  end
460
438
 
461
439
  def set_scenario_color(status)
462
- if status.nil? or status == :undefined or status == :pending
440
+ if status.nil? || status == :undefined || status == :pending
463
441
  set_scenario_color_pending
464
442
  end
465
443
  if status == :failed
@@ -468,31 +446,31 @@ module Cucumber
468
446
  end
469
447
 
470
448
  def set_scenario_color_failed
471
- @builder.script do
472
- @builder.text!("makeRed('cucumber-header');") unless @header_red
449
+ builder.script do
450
+ builder.text!("makeRed('cucumber-header');") unless @header_red
473
451
  @header_red = true
474
- scenario_or_background = @in_background ? "background" : "scenario"
475
- @builder.text!("makeRed('#{scenario_or_background}_#{@scenario_number}');") unless @scenario_red
452
+ scenario_or_background = @in_background ? 'background' : 'scenario'
453
+ builder.text!("makeRed('#{scenario_or_background}_#{@scenario_number}');") unless @scenario_red
476
454
  @scenario_red = true
477
- if @options[:expand] and @inside_outline
478
- @builder.text!("makeRed('#{scenario_or_background}_#{@scenario_number}_#{@outline_row}');")
455
+ if @options[:expand] && @inside_outline
456
+ builder.text!("makeRed('#{scenario_or_background}_#{@scenario_number}_#{@outline_row}');")
479
457
  end
480
458
  end
481
459
  end
482
460
 
483
461
  def set_scenario_color_pending
484
- @builder.script do
485
- @builder.text!("makeYellow('cucumber-header');") unless @header_red
486
- scenario_or_background = @in_background ? "background" : "scenario"
487
- @builder.text!("makeYellow('#{scenario_or_background}_#{@scenario_number}');") unless @scenario_red
462
+ builder.script do
463
+ builder.text!("makeYellow('cucumber-header');") unless @header_red
464
+ scenario_or_background = @in_background ? 'background' : 'scenario'
465
+ builder.text!("makeYellow('#{scenario_or_background}_#{@scenario_number}');") unless @scenario_red
488
466
  end
489
467
  end
490
468
 
491
- def build_step(keyword, step_match, status)
469
+ def build_step(keyword, step_match, _status)
492
470
  step_name = step_match.format_args(lambda{|param| %{<span class="param">#{param}</span>}})
493
- @builder.div(:class => 'step_name') do |div|
494
- @builder.span(keyword, :class => 'keyword')
495
- @builder.span(:class => 'step val') do |name|
471
+ builder.div(:class => 'step_name') do |div|
472
+ builder.span(keyword, :class => 'keyword')
473
+ builder.span(:class => 'step val') do |name|
496
474
  name << h(step_name).gsub(/&lt;span class=&quot;(.*?)&quot;&gt;/, '<span class="\1">').gsub(/&lt;\/span&gt;/, '</span>')
497
475
  end
498
476
  end
@@ -504,77 +482,23 @@ module Cucumber
504
482
  end
505
483
  end
506
484
 
507
- @builder.div(:class => 'step_file') do |div|
508
- @builder.span do
509
- @builder << step_file
485
+ builder.div(:class => 'step_file') do |div|
486
+ builder.span do
487
+ builder << step_file
510
488
  end
511
489
  end
512
490
  end
513
491
 
514
492
  def build_cell(cell_type, value, attributes)
515
- @builder.__send__(cell_type, attributes) do
516
- @builder.div do
517
- @builder.span(value,:class => 'step param')
493
+ builder.__send__(cell_type, attributes) do
494
+ builder.div do
495
+ builder.span(value,:class => 'step param')
518
496
  end
519
497
  end
520
498
  end
521
499
 
522
- def inline_css
523
- @builder.style(:type => 'text/css') do
524
- @builder << File.read(File.dirname(__FILE__) + '/cucumber.css')
525
- end
526
- end
527
-
528
- def inline_js
529
- @builder.script(:type => 'text/javascript') do
530
- @builder << inline_jquery
531
- @builder << inline_js_content
532
- end
533
- end
534
-
535
- def inline_jquery
536
- File.read(File.dirname(__FILE__) + '/jquery-min.js')
537
- end
538
-
539
- def inline_js_content
540
- <<-EOF
541
-
542
- SCENARIOS = "h3[id^='scenario_'],h3[id^=background_]";
543
-
544
- $(document).ready(function() {
545
- $(SCENARIOS).css('cursor', 'pointer');
546
- $(SCENARIOS).click(function() {
547
- $(this).siblings().toggle(250);
548
- });
549
-
550
- $("#collapser").css('cursor', 'pointer');
551
- $("#collapser").click(function() {
552
- $(SCENARIOS).siblings().hide();
553
- });
554
-
555
- $("#expander").css('cursor', 'pointer');
556
- $("#expander").click(function() {
557
- $(SCENARIOS).siblings().show();
558
- });
559
- })
560
-
561
- function moveProgressBar(percentDone) {
562
- $("cucumber-header").css('width', percentDone +"%");
563
- }
564
- function makeRed(element_id) {
565
- $('#'+element_id).css('background', '#C40D0D');
566
- $('#'+element_id).css('color', '#FFFFFF');
567
- }
568
- function makeYellow(element_id) {
569
- $('#'+element_id).css('background', '#FAF834');
570
- $('#'+element_id).css('color', '#000000');
571
- }
572
-
573
- EOF
574
- end
575
-
576
500
  def move_progress
577
- @builder << " <script type=\"text/javascript\">moveProgressBar('#{percent_done}');</script>"
501
+ builder << " <script type=\"text/javascript\">moveProgressBar('#{percent_done}');</script>"
578
502
  end
579
503
 
580
504
  def percent_done
@@ -586,31 +510,31 @@ module Cucumber
586
510
  end
587
511
 
588
512
  def format_exception(exception)
589
- (["#{exception.message}"] + exception.backtrace).join("\n")
513
+ ([exception.message.to_s] + exception.backtrace).join("\n")
590
514
  end
591
515
 
592
516
  def backtrace_line(line)
593
- line.gsub(/^([^:]*\.(?:rb|feature|haml)):(\d*).*$/) do
594
- if ENV['TM_PROJECT_DIRECTORY']
517
+ if ENV['TM_PROJECT_DIRECTORY']
518
+ line.gsub(/^([^:]*\.(?:rb|feature|haml)):(\d*).*$/) do
595
519
  "<a href=\"txmt://open?url=file://#{File.expand_path($1)}&line=#{$2}\">#{$1}:#{$2}</a> "
596
- else
597
- line
598
520
  end
521
+ else
522
+ line
599
523
  end
600
524
  end
601
525
 
602
526
  def print_stats(features)
603
- @builder << "<script type=\"text/javascript\">document.getElementById('duration').innerHTML = \"Finished in <strong>#{format_duration(features.duration)} seconds</strong>\";</script>"
604
- @builder << "<script type=\"text/javascript\">document.getElementById('totals').innerHTML = \"#{print_stat_string(features)}\";</script>"
527
+ builder << "<script type=\"text/javascript\">document.getElementById('duration').innerHTML = \"Finished in <strong>#{format_duration(features.duration)} seconds</strong>\";</script>"
528
+ builder << "<script type=\"text/javascript\">document.getElementById('totals').innerHTML = \"#{print_stat_string(features)}\";</script>"
605
529
  end
606
530
 
607
- def print_stat_string(features)
531
+ def print_stat_string(_features)
608
532
  string = String.new
609
- string << dump_count(@runtime.scenarios.length, "scenario")
533
+ string << dump_count(@runtime.scenarios.length, 'scenario')
610
534
  scenario_count = print_status_counts{|status| @runtime.scenarios(status)}
611
535
  string << scenario_count if scenario_count
612
- string << "<br />"
613
- string << dump_count(@runtime.steps.length, "step")
536
+ string << '<br />'
537
+ string << dump_count(@runtime.steps.length, 'step')
614
538
  step_count = print_status_counts{|status| @runtime.steps(status)}
615
539
  string << step_count if step_count
616
540
  end
@@ -618,26 +542,28 @@ module Cucumber
618
542
  def print_status_counts
619
543
  counts = [:failed, :skipped, :undefined, :pending, :passed].map do |status|
620
544
  elements = yield status
621
- elements.any? ? "#{elements.length} #{status.to_s}" : nil
545
+ elements.any? ? "#{elements.length} #{status}" : nil
622
546
  end.compact
623
547
  return " (#{counts.join(', ')})" if counts.any?
624
548
  end
625
549
 
626
550
  def dump_count(count, what, state=nil)
627
- [count, state, "#{what}#{count == 1 ? '' : 's'}"].compact.join(" ")
628
- end
629
-
630
- def create_builder(io)
631
- Builder::XmlMarkup.new(:target => io, :indent => 0)
551
+ [count, state, "#{what}#{count == 1 ? '' : 's'}"].compact.join(' ')
632
552
  end
633
553
 
634
- def outline_step?(step)
554
+ def outline_step?(_step)
635
555
  not @step.step.respond_to?(:actual_keyword)
636
556
  end
637
557
 
638
558
  class SnippetExtractor #:nodoc:
639
- class NullConverter; def convert(code, pre); code; end; end #:nodoc:
640
- begin; require 'syntax/convertors/html'; @@converter = Syntax::Convertors::HTML.for_syntax "ruby"; rescue LoadError => e; @@converter = NullConverter.new; end
559
+ class NullConverter; def convert(code, _pre); code; end; end #:nodoc:
560
+
561
+ begin
562
+ require 'syntax/convertors/html'
563
+ @@converter = Syntax::Convertors::HTML.for_syntax 'ruby'
564
+ rescue LoadError
565
+ @@converter = NullConverter.new
566
+ end
641
567
 
642
568
  def snippet(error)
643
569
  raw_code, line = snippet_for(error[0])