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,689 @@
1
+ require 'erb'
2
+ require 'builder'
3
+ require 'cucumber/formatter/duration'
4
+ require 'cucumber/formatter/io'
5
+ require 'pathname'
6
+
7
+ module Cucumber
8
+ module Formatter
9
+ class Html
10
+
11
+ # TODO: remove coupling to types
12
+ AST_CLASSES = {
13
+ Cucumber::Core::Ast::Scenario => 'scenario',
14
+ Cucumber::Core::Ast::ScenarioOutline => 'scenario outline'
15
+ }
16
+ AST_DATA_TABLE = LegacyApi::Ast::MultilineArg::DataTable
17
+
18
+ include ERB::Util # for the #h method
19
+ include Duration
20
+ include Io
21
+
22
+ def initialize(runtime, path_or_io, options)
23
+ @io = ensure_io(path_or_io)
24
+ @runtime = runtime
25
+ @options = options
26
+ @buffer = {}
27
+ @builder = create_builder(@io)
28
+ @feature_number = 0
29
+ @scenario_number = 0
30
+ @step_number = 0
31
+ @header_red = nil
32
+ @delayed_messages = []
33
+ @img_id = 0
34
+ @text_id = 0
35
+ @inside_outline = false
36
+ @previous_step_keyword = nil
37
+ end
38
+
39
+ 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)
49
+ end
50
+ end
51
+
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)
56
+ out_dir = Pathname.new(File.dirname(File.absolute_path(@io.path)))
57
+ 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
+ end
63
+ end
64
+
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
71
+ end
72
+
73
+
74
+ def before_features(features)
75
+ @step_count = features && features.step_count || 0 #TODO: Make this work with core!
76
+
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
109
+ end
110
+
111
+ def after_features(features)
112
+ print_stats(features)
113
+ @builder << '</div>'
114
+ @builder << '</body>'
115
+ @builder << '</html>'
116
+ end
117
+
118
+ def before_feature(feature)
119
+ @exceptions = []
120
+ @builder << '<div class="feature">'
121
+ end
122
+
123
+ def after_feature(feature)
124
+ @builder << '</div>'
125
+ end
126
+
127
+ def before_comment(comment)
128
+ @builder << '<pre class="comment">'
129
+ end
130
+
131
+ def after_comment(comment)
132
+ @builder << '</pre>'
133
+ end
134
+
135
+ def comment_line(comment_line)
136
+ @builder.text!(comment_line)
137
+ @builder.br
138
+ end
139
+
140
+ def after_tags(tags)
141
+ @tag_spacer = nil
142
+ end
143
+
144
+ def tag_name(tag_name)
145
+ @builder.text!(@tag_spacer) if @tag_spacer
146
+ @tag_spacer = ' '
147
+ @builder.span(tag_name, :class => 'tag')
148
+ end
149
+
150
+ def feature_name(keyword, name)
151
+ lines = name.split(/\r?\n/)
152
+ return if lines.empty?
153
+ @builder.h2 do |h2|
154
+ @builder.span(keyword + ': ' + lines[0], :class => 'val')
155
+ end
156
+ @builder.p(:class => 'narrative') do
157
+ lines[1..-1].each do |line|
158
+ @builder.text!(line.strip)
159
+ @builder.br
160
+ end
161
+ end
162
+ end
163
+
164
+ def before_test_case(test_case)
165
+ @previous_step_keyword = nil
166
+ end
167
+
168
+ def before_background(background)
169
+ @in_background = true
170
+ @builder << '<div class="background">'
171
+ end
172
+
173
+ def after_background(background)
174
+ @in_background = nil
175
+ @builder << '</div>'
176
+ end
177
+
178
+ def background_name(keyword, name, file_colon_line, source_indent)
179
+ @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')
184
+ end
185
+ end
186
+
187
+ def before_feature_element(feature_element)
188
+ @scenario_number+=1
189
+ @scenario_red = false
190
+ css_class = AST_CLASSES[feature_element.class]
191
+ @builder << "<div class='#{css_class}'>"
192
+ @in_scenario_outline = feature_element.class == Cucumber::Core::Ast::ScenarioOutline
193
+ end
194
+
195
+ def after_feature_element(feature_element)
196
+ unless @in_scenario_outline
197
+ print_messages
198
+ @builder << '</ol>'
199
+ end
200
+ @builder << '</div>'
201
+ @in_scenario_outline = nil
202
+ end
203
+
204
+ def scenario_name(keyword, name, file_colon_line, source_indent)
205
+ @builder.span(:class => 'scenario_file') do
206
+ @builder << file_colon_line
207
+ end
208
+ @listing_background = false
209
+ scenario_id = "scenario_#{@scenario_number}"
210
+ if @inside_outline
211
+ @outline_row += 1
212
+ scenario_id += "_#{@outline_row}"
213
+ @scenario_red = false
214
+ end
215
+ @builder.h3(:id => scenario_id) do
216
+ @builder.span(keyword + ':', :class => 'keyword')
217
+ @builder.text!(' ')
218
+ @builder.span(name, :class => 'val')
219
+ end
220
+ end
221
+
222
+ def before_outline_table(outline_table)
223
+ @inside_outline = true
224
+ @outline_row = 0
225
+ @builder << '<table>'
226
+ end
227
+
228
+ def after_outline_table(outline_table)
229
+ @builder << '</table>'
230
+ @outline_row = nil
231
+ @inside_outline = false
232
+ end
233
+
234
+ def before_examples(examples)
235
+ @builder << '<div class="examples">'
236
+ end
237
+
238
+ def after_examples(examples)
239
+ @builder << '</div>'
240
+ end
241
+
242
+ def examples_name(keyword, name)
243
+ @builder.h4 do
244
+ @builder.span(keyword, :class => 'keyword')
245
+ @builder.text!(' ')
246
+ @builder.span(name, :class => 'val')
247
+ end
248
+ end
249
+
250
+ def before_steps(steps)
251
+ @builder << '<ol>'
252
+ end
253
+
254
+ def after_steps(steps)
255
+ print_messages
256
+ @builder << '</ol>' if @in_background or @in_scenario_outline
257
+ end
258
+
259
+ def before_step(step)
260
+ print_messages
261
+ @step_id = step.dom_id
262
+ @step_number += 1
263
+ @step = step
264
+ end
265
+
266
+ def after_step(step)
267
+ move_progress
268
+ end
269
+
270
+ def before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line)
271
+ @step_match = step_match
272
+ @hide_this_step = false
273
+ if exception
274
+ if @exceptions.include?(exception)
275
+ @hide_this_step = true
276
+ return
277
+ end
278
+ @exceptions << exception
279
+ end
280
+ if status != :failed && @in_background ^ background
281
+ @hide_this_step = true
282
+ return
283
+ end
284
+ @status = status
285
+ return if @hide_this_step
286
+ set_scenario_color(status)
287
+ @builder << "<li id='#{@step_id}' class='step #{status}'>"
288
+ end
289
+
290
+ def after_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line)
291
+ return if @hide_this_step
292
+ # print snippet for undefined steps
293
+ unless outline_step?(@step)
294
+ keyword = @step.actual_keyword(@previous_step_keyword)
295
+ @previous_step_keyword = keyword
296
+ end
297
+ if status == :undefined
298
+ @builder.pre do |pre|
299
+ # TODO: snippet text should be an event sent to the formatter so we don't
300
+ # have this couping to the runtime.
301
+ pre << @runtime.snippet_text(keyword,step_match.instance_variable_get("@name") || '', @step.multiline_arg)
302
+ end
303
+ end
304
+ @builder << '</li>'
305
+ print_messages
306
+ end
307
+
308
+ def step_name(keyword, step_match, status, source_indent, background, file_colon_line)
309
+ background_in_scenario = background && !@listing_background
310
+ @skip_step = background_in_scenario
311
+
312
+ unless @skip_step
313
+ build_step(keyword, step_match, status)
314
+ end
315
+ end
316
+
317
+ def exception(exception, status)
318
+ return if @hide_this_step
319
+ print_messages
320
+ build_exception_detail(exception)
321
+ end
322
+
323
+ def extra_failure_content(file_colon_line)
324
+ @snippet_extractor ||= SnippetExtractor.new
325
+ "<pre class=\"ruby\"><code>#{@snippet_extractor.snippet(file_colon_line)}</code></pre>"
326
+ end
327
+
328
+ def before_multiline_arg(multiline_arg)
329
+ return if @hide_this_step || @skip_step
330
+ if AST_DATA_TABLE === multiline_arg
331
+ @builder << '<table>'
332
+ end
333
+ end
334
+
335
+ def after_multiline_arg(multiline_arg)
336
+ return if @hide_this_step || @skip_step
337
+ if AST_DATA_TABLE === multiline_arg
338
+ @builder << '</table>'
339
+ end
340
+ end
341
+
342
+ def doc_string(string)
343
+ return if @hide_this_step
344
+ @builder.pre(:class => 'val') do |pre|
345
+ @builder << h(string).gsub("\n", '&#x000A;')
346
+ end
347
+ end
348
+
349
+ def before_table_row(table_row)
350
+ @row_id = table_row.dom_id
351
+ @col_index = 0
352
+ return if @hide_this_step
353
+ @builder << "<tr class='step' id='#{@row_id}'>"
354
+ end
355
+
356
+ def after_table_row(table_row)
357
+ return if @hide_this_step
358
+ print_table_row_messages
359
+ @builder << '</tr>'
360
+ if table_row.exception
361
+ @builder.tr do
362
+ @builder.td(:colspan => @col_index.to_s, :class => 'failed') do
363
+ @builder.pre do |pre|
364
+ pre << h(format_exception(table_row.exception))
365
+ end
366
+ end
367
+ end
368
+ if table_row.exception.is_a? ::Cucumber::Pending
369
+ set_scenario_color_pending
370
+ else
371
+ set_scenario_color_failed
372
+ end
373
+ end
374
+ if @outline_row
375
+ @outline_row += 1
376
+ end
377
+ @step_number += 1
378
+ move_progress
379
+ end
380
+
381
+ def table_cell_value(value, status)
382
+ return if @hide_this_step
383
+
384
+ @cell_type = @outline_row == 0 ? :th : :td
385
+ attributes = {:id => "#{@row_id}_#{@col_index}", :class => 'step'}
386
+ attributes[:class] += " #{status}" if status
387
+ build_cell(@cell_type, value, attributes)
388
+ set_scenario_color(status) if @inside_outline
389
+ @col_index += 1
390
+ end
391
+
392
+ def puts(message)
393
+ @delayed_messages << message
394
+ #@builder.pre(message, :class => 'message')
395
+ end
396
+
397
+ def print_messages
398
+ return if @delayed_messages.empty?
399
+
400
+ #@builder.ol do
401
+ @delayed_messages.each do |ann|
402
+ @builder.li(:class => 'step message') do
403
+ @builder << ann
404
+ end
405
+ end
406
+ #end
407
+ empty_messages
408
+ end
409
+
410
+ def print_table_row_messages
411
+ return if @delayed_messages.empty?
412
+
413
+ @builder.td(:class => 'message') do
414
+ @builder << @delayed_messages.join(", ")
415
+ end
416
+ empty_messages
417
+ end
418
+
419
+ def empty_messages
420
+ @delayed_messages = []
421
+ end
422
+
423
+ def after_test_case(test_case, result)
424
+ if result.failed? and not @scenario_red
425
+ set_scenario_color_failed
426
+ end
427
+ end
428
+
429
+ protected
430
+
431
+ def build_exception_detail(exception)
432
+ backtrace = Array.new
433
+ @builder.div(:class => 'message') do
434
+ message = exception.message
435
+ if defined?(RAILS_ROOT) && message.include?('Exception caught')
436
+ matches = message.match(/Showing <i>(.+)<\/i>(?:.+) #(\d+)/)
437
+ backtrace += ["#{RAILS_ROOT}/#{matches[1]}:#{matches[2]}"] if matches
438
+ matches = message.match(/<code>([^(\/)]+)<\//m)
439
+ message = matches ? matches[1] : ""
440
+ end
441
+
442
+ unless exception.instance_of?(RuntimeError)
443
+ message = "#{message} (#{exception.class})"
444
+ end
445
+
446
+ @builder.pre do
447
+ @builder.text!(message)
448
+ end
449
+ end
450
+ @builder.div(:class => 'backtrace') do
451
+ @builder.pre do
452
+ backtrace = exception.backtrace
453
+ backtrace.delete_if { |x| x =~ /\/gems\/(cucumber|rspec)/ }
454
+ @builder << backtrace_line(backtrace.join("\n"))
455
+ end
456
+ end
457
+ extra = extra_failure_content(backtrace)
458
+ @builder << extra unless extra == ""
459
+ end
460
+
461
+ def set_scenario_color(status)
462
+ if status.nil? or status == :undefined or status == :pending
463
+ set_scenario_color_pending
464
+ end
465
+ if status == :failed
466
+ set_scenario_color_failed
467
+ end
468
+ end
469
+
470
+ def set_scenario_color_failed
471
+ @builder.script do
472
+ @builder.text!("makeRed('cucumber-header');") unless @header_red
473
+ @header_red = true
474
+ scenario_or_background = @in_background ? "background" : "scenario"
475
+ @builder.text!("makeRed('#{scenario_or_background}_#{@scenario_number}');") unless @scenario_red
476
+ @scenario_red = true
477
+ if @options[:expand] and @inside_outline
478
+ @builder.text!("makeRed('#{scenario_or_background}_#{@scenario_number}_#{@outline_row}');")
479
+ end
480
+ end
481
+ end
482
+
483
+ 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
488
+ end
489
+ end
490
+
491
+ def build_step(keyword, step_match, status)
492
+ 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|
496
+ name << h(step_name).gsub(/&lt;span class=&quot;(.*?)&quot;&gt;/, '<span class="\1">').gsub(/&lt;\/span&gt;/, '</span>')
497
+ end
498
+ end
499
+
500
+ step_file = step_match.file_colon_line
501
+ step_file.gsub(/^([^:]*\.rb):(\d*)/) do
502
+ if ENV['TM_PROJECT_DIRECTORY']
503
+ step_file = "<a href=\"txmt://open?url=file://#{File.expand_path($1)}&line=#{$2}\">#{$1}:#{$2}</a> "
504
+ end
505
+ end
506
+
507
+ @builder.div(:class => 'step_file') do |div|
508
+ @builder.span do
509
+ @builder << step_file
510
+ end
511
+ end
512
+ end
513
+
514
+ 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')
518
+ end
519
+ end
520
+ end
521
+
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
+ def move_progress
577
+ @builder << " <script type=\"text/javascript\">moveProgressBar('#{percent_done}');</script>"
578
+ end
579
+
580
+ def percent_done
581
+ result = 100.0
582
+ if @step_count != 0
583
+ result = ((@step_number).to_f / @step_count.to_f * 1000).to_i / 10.0
584
+ end
585
+ result
586
+ end
587
+
588
+ def format_exception(exception)
589
+ (["#{exception.message}"] + exception.backtrace).join("\n")
590
+ end
591
+
592
+ def backtrace_line(line)
593
+ line.gsub(/^([^:]*\.(?:rb|feature|haml)):(\d*).*$/) do
594
+ if ENV['TM_PROJECT_DIRECTORY']
595
+ "<a href=\"txmt://open?url=file://#{File.expand_path($1)}&line=#{$2}\">#{$1}:#{$2}</a> "
596
+ else
597
+ line
598
+ end
599
+ end
600
+ end
601
+
602
+ 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>"
605
+ end
606
+
607
+ def print_stat_string(features)
608
+ string = String.new
609
+ string << dump_count(@runtime.scenarios.length, "scenario")
610
+ scenario_count = print_status_counts{|status| @runtime.scenarios(status)}
611
+ string << scenario_count if scenario_count
612
+ string << "<br />"
613
+ string << dump_count(@runtime.steps.length, "step")
614
+ step_count = print_status_counts{|status| @runtime.steps(status)}
615
+ string << step_count if step_count
616
+ end
617
+
618
+ def print_status_counts
619
+ counts = [:failed, :skipped, :undefined, :pending, :passed].map do |status|
620
+ elements = yield status
621
+ elements.any? ? "#{elements.length} #{status.to_s}" : nil
622
+ end.compact
623
+ return " (#{counts.join(', ')})" if counts.any?
624
+ end
625
+
626
+ 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)
632
+ end
633
+
634
+ def outline_step?(step)
635
+ not @step.step.respond_to?(:actual_keyword)
636
+ end
637
+
638
+ 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
641
+
642
+ def snippet(error)
643
+ raw_code, line = snippet_for(error[0])
644
+ highlighted = @@converter.convert(raw_code, false)
645
+ highlighted << "\n<span class=\"comment\"># gem install syntax to get syntax highlighting</span>" if @@converter.is_a?(NullConverter)
646
+ post_process(highlighted, line)
647
+ end
648
+
649
+ def snippet_for(error_line)
650
+ if error_line =~ /(.*):(\d+)/
651
+ file = $1
652
+ line = $2.to_i
653
+ [lines_around(file, line), line]
654
+ else
655
+ ["# Couldn't get snippet for #{error_line}", 1]
656
+ end
657
+ end
658
+
659
+ def lines_around(file, line)
660
+ if File.file?(file)
661
+ begin
662
+ lines = File.open(file).read.split("\n")
663
+ rescue ArgumentError
664
+ return "# Couldn't get snippet for #{file}"
665
+ end
666
+ min = [0, line-3].max
667
+ max = [line+1, lines.length-1].min
668
+ selected_lines = []
669
+ selected_lines.join("\n")
670
+ lines[min..max].join("\n")
671
+ else
672
+ "# Couldn't get snippet for #{file}"
673
+ end
674
+ end
675
+
676
+ def post_process(highlighted, offending_line)
677
+ new_lines = []
678
+ highlighted.split("\n").each_with_index do |line, i|
679
+ new_line = "<span class=\"linenum\">#{offending_line+i-2}</span>#{line}"
680
+ new_line = "<span class=\"offending\">#{new_line}</span>" if i == 2
681
+ new_lines << new_line
682
+ end
683
+ new_lines.join("\n")
684
+ end
685
+
686
+ end
687
+ end
688
+ end
689
+ end