kosmas58-cucumber 0.1.16.6 → 0.1.99.21

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 (248) hide show
  1. data/History.txt +126 -2
  2. data/License.txt +1 -1
  3. data/Manifest.txt +0 -270
  4. data/Rakefile +1 -1
  5. data/bin/cucumber +2 -2
  6. data/config/hoe.rb +7 -2
  7. data/examples/cs/features/step_definitons/calculator_steps.rb +1 -1
  8. data/examples/i18n/README.textile +1 -1
  9. data/examples/i18n/Rakefile +3 -3
  10. data/examples/i18n/ar/features/step_definitons/calculator_steps.rb +1 -6
  11. data/examples/i18n/da/features/step_definitons/kalkulator_steps.rb +1 -1
  12. data/examples/i18n/de/features/addition.feature +6 -6
  13. data/examples/i18n/de/features/step_definitons/calculator_steps.rb +2 -2
  14. data/examples/i18n/en/features/addition.feature +6 -6
  15. data/examples/i18n/en/features/step_definitons/calculator_steps.rb +2 -2
  16. data/examples/i18n/es/features/adicion.feature +11 -12
  17. data/examples/i18n/es/features/step_definitons/calculador_steps.rb +7 -10
  18. data/examples/i18n/es/lib/calculador.rb +4 -1
  19. data/examples/i18n/et/features/liitmine.feature +7 -6
  20. data/examples/i18n/et/features/step_definitions/kalkulaator_steps.rb +1 -1
  21. data/examples/i18n/fi/features/step_definitons/laskin_steps.rb +1 -1
  22. data/examples/i18n/fi/features/yhteenlasku.feature +2 -2
  23. data/examples/i18n/fr/features/addition.feature +2 -2
  24. data/examples/i18n/fr/features/step_definitions/calculatrice_steps.rb +1 -1
  25. data/examples/i18n/id/features/addition.feature +6 -6
  26. data/examples/i18n/id/features/step_definitons/calculator_steps.rb +2 -2
  27. data/examples/i18n/it/features/step_definitons/calcolatrice_steps.rb +1 -1
  28. data/examples/i18n/ja/features/step_definitons/calculator_steps.rb +2 -3
  29. data/examples/i18n/ko/features/step_definitons/calculator_steps.rb +1 -1
  30. data/examples/i18n/lt/features/addition.feature +7 -6
  31. data/examples/i18n/lt/features/step_definitons/calculator_steps.rb +2 -2
  32. data/examples/i18n/no/features/step_definitons/kalkulator_steps.rb +7 -7
  33. data/examples/i18n/no/features/summering.feature +1 -0
  34. data/examples/i18n/pt/features/step_definitions/calculadora_steps.rb +1 -1
  35. data/examples/i18n/ro/features/step_definitons/calculator_steps.rb +1 -1
  36. data/examples/i18n/se/features/step_definitons/kalkulator_steps.rb +1 -1
  37. data/examples/i18n/zh-CN/features/step_definitons/calculator_steps.rb +2 -2
  38. data/examples/java/src/cucumber/demo/Hello.java +16 -0
  39. data/examples/jbehave/README.textile +17 -0
  40. data/examples/jbehave/features/support/env.rb +7 -0
  41. data/examples/jbehave/features/trading.feature +24 -0
  42. data/examples/jbehave/pom.xml +48 -0
  43. data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/converters/TraderConverter.java +32 -0
  44. data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/model/Stock.java +42 -0
  45. data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/model/Trader.java +29 -0
  46. data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/persistence/TraderPersister.java +22 -0
  47. data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/scenarios/TraderSteps.java +65 -0
  48. data/examples/self_test/README.textile +4 -1
  49. data/examples/{calculator_ruby_features → self_test}/Rakefile +3 -3
  50. data/examples/self_test/features/background/failing_background.feature +10 -0
  51. data/examples/self_test/features/background/failing_background_after_success.feature +11 -0
  52. data/examples/self_test/features/background/multiline_args_background.feature +32 -0
  53. data/examples/self_test/features/background/passing_background.feature +10 -0
  54. data/examples/self_test/features/background/pending_background.feature +10 -0
  55. data/examples/self_test/features/background/scenario_outline_failing_background.feature +16 -0
  56. data/examples/self_test/features/background/scenario_outline_passing_background.feature +16 -0
  57. data/examples/self_test/features/call_undefined_step_from_step_def.feature +7 -0
  58. data/examples/self_test/features/lots_of_undefined.feature +8 -0
  59. data/examples/self_test/features/outline_sample.feature +11 -5
  60. data/examples/self_test/features/sample.feature +8 -3
  61. data/examples/self_test/features/step_definitions/sample_steps.rb +53 -4
  62. data/examples/self_test/features/support/env.rb +1 -0
  63. data/examples/self_test/features/support/tag_count_formatter.rb +25 -0
  64. data/examples/tickets/features/172.feature +28 -0
  65. data/examples/tickets/features/177/1.feature +29 -0
  66. data/examples/tickets/features/177/2.feature +21 -0
  67. data/examples/tickets/features/177/3.feature +18 -0
  68. data/examples/tickets/features/180.feature +7 -0
  69. data/examples/tickets/features/scenario_outline.feature +6 -1
  70. data/examples/tickets/features/step_definitons/tickets_steps.rb +27 -3
  71. data/examples/tickets/features/tickets.feature +4 -0
  72. data/features/background.feature +223 -0
  73. data/features/cucumber_cli.feature +218 -98
  74. data/features/cucumber_cli_outlines.feature +54 -37
  75. data/features/custom_formatter.feature +11 -0
  76. data/features/report_called_undefined_steps.feature +32 -0
  77. data/features/step_definitions/cucumber_steps.rb +7 -3
  78. data/features/step_definitions/extra_steps.rb +1 -1
  79. data/features/support/env.rb +2 -1
  80. data/gem_tasks/flog.rake +1 -1
  81. data/gem_tasks/gemspec.rake +2 -2
  82. data/gem_tasks/jar.rake +67 -0
  83. data/lib/autotest/cucumber_mixin.rb +17 -23
  84. data/lib/cucumber.rb +63 -11
  85. data/lib/cucumber/ast.rb +29 -0
  86. data/lib/cucumber/ast/background.rb +88 -0
  87. data/lib/cucumber/ast/comment.rb +26 -0
  88. data/lib/cucumber/ast/examples.rb +26 -0
  89. data/lib/cucumber/ast/feature.rb +66 -0
  90. data/lib/cucumber/ast/features.rb +39 -0
  91. data/lib/cucumber/ast/filter.rb +22 -0
  92. data/lib/cucumber/ast/outline_table.rb +49 -0
  93. data/lib/cucumber/ast/py_string.rb +52 -0
  94. data/lib/cucumber/ast/scenario.rb +103 -0
  95. data/lib/cucumber/ast/scenario_outline.rb +92 -0
  96. data/lib/cucumber/ast/step.rb +161 -0
  97. data/lib/cucumber/ast/steps.rb +13 -0
  98. data/lib/cucumber/ast/table.rb +218 -0
  99. data/lib/cucumber/ast/tags.rb +40 -0
  100. data/lib/cucumber/ast/visitor.rb +109 -0
  101. data/lib/cucumber/broadcaster.rb +1 -6
  102. data/lib/cucumber/cli/configuration.rb +339 -0
  103. data/lib/cucumber/cli/language_help_formatter.rb +59 -0
  104. data/lib/cucumber/cli/main.rb +100 -0
  105. data/lib/cucumber/core_ext/exception.rb +41 -8
  106. data/lib/cucumber/core_ext/instance_exec.rb +54 -0
  107. data/lib/cucumber/core_ext/proc.rb +29 -65
  108. data/lib/cucumber/core_ext/string.rb +19 -0
  109. data/lib/cucumber/formatter.rb +1 -0
  110. data/lib/cucumber/{formatters → formatter}/ansicolor.rb +14 -16
  111. data/lib/cucumber/formatter/color_io.rb +17 -0
  112. data/lib/cucumber/formatter/console.rb +119 -0
  113. data/lib/cucumber/formatter/cucumber.css +55 -0
  114. data/lib/cucumber/formatter/cucumber.sass +49 -0
  115. data/lib/cucumber/formatter/html.rb +121 -0
  116. data/lib/cucumber/formatter/pretty.rb +167 -0
  117. data/lib/cucumber/formatter/profile.rb +77 -0
  118. data/lib/cucumber/formatter/progress.rb +68 -0
  119. data/lib/cucumber/formatter/rerun.rb +35 -0
  120. data/lib/cucumber/formatter/unicode.rb +35 -0
  121. data/lib/cucumber/formatters/unicode.rb +2 -35
  122. data/lib/cucumber/jbehave.rb +102 -0
  123. data/lib/cucumber/languages.yml +128 -75
  124. data/lib/cucumber/parser.rb +43 -0
  125. data/lib/cucumber/parser/basic.rb +0 -0
  126. data/lib/cucumber/parser/feature.rb +1490 -0
  127. data/lib/cucumber/parser/feature.tt +188 -0
  128. data/lib/cucumber/parser/i18n.tt +31 -0
  129. data/lib/cucumber/parser/table.rb +402 -0
  130. data/lib/cucumber/parser/table.tt +59 -0
  131. data/lib/cucumber/parser/treetop_ext.rb +75 -0
  132. data/lib/cucumber/platform.rb +3 -17
  133. data/lib/cucumber/rails/rspec.rb +5 -2
  134. data/lib/cucumber/step_definition.rb +87 -0
  135. data/lib/cucumber/step_mother.rb +151 -66
  136. data/lib/cucumber/version.rb +2 -2
  137. data/rails_generators/cucumber/USAGE +3 -2
  138. data/rails_generators/cucumber/cucumber_generator.rb +33 -23
  139. data/rails_generators/cucumber/templates/cucumber +2 -1
  140. data/rails_generators/cucumber/templates/cucumber.rake +6 -1
  141. data/rails_generators/cucumber/templates/env.rb +1 -1
  142. data/rails_generators/feature/USAGE +3 -0
  143. data/rails_generators/feature/feature_generator.rb +30 -6
  144. data/spec/cucumber/ast/background_spec.rb +58 -0
  145. data/spec/cucumber/ast/feature_factory.rb +54 -0
  146. data/spec/cucumber/ast/feature_spec.rb +60 -0
  147. data/spec/cucumber/ast/py_string_spec.rb +40 -0
  148. data/spec/cucumber/ast/scenario_outline_spec.rb +64 -0
  149. data/spec/cucumber/ast/scenario_spec.rb +82 -0
  150. data/spec/cucumber/ast/step_spec.rb +45 -0
  151. data/spec/cucumber/ast/table_spec.rb +81 -0
  152. data/spec/cucumber/ast/tags_spec.rb +23 -0
  153. data/spec/cucumber/broadcaster_spec.rb +4 -17
  154. data/spec/cucumber/cli/configuration_spec.rb +239 -0
  155. data/spec/cucumber/cli/main_spec.rb +164 -0
  156. data/spec/cucumber/core_ext/proc_spec.rb +27 -35
  157. data/spec/cucumber/core_ext/string_spec.rb +8 -0
  158. data/spec/cucumber/{formatters → formatter}/ansicolor_spec.rb +2 -2
  159. data/spec/cucumber/formatter/html/cucumber.css +37 -0
  160. data/spec/cucumber/formatter/html/cucumber.js +13 -0
  161. data/spec/cucumber/formatter/html/index.html +45 -0
  162. data/spec/cucumber/formatter/html/jquery-1.3.min.js +19 -0
  163. data/spec/cucumber/formatter/html/jquery.uitableedit.js +100 -0
  164. data/spec/cucumber/formatters/profile_formatter_spec.rb +17 -16
  165. data/spec/cucumber/parser/feature_parser_spec.rb +281 -0
  166. data/spec/cucumber/parser/table_parser_spec.rb +48 -0
  167. data/spec/cucumber/step_definition_spec.rb +62 -0
  168. data/spec/cucumber/step_mother_spec.rb +50 -51
  169. data/spec/cucumber/treetop_parser/empty_feature.feature +1 -1
  170. data/spec/cucumber/treetop_parser/scenario_outline.feature +1 -1
  171. data/spec/cucumber/treetop_parser/spaces.feature +3 -1
  172. data/spec/cucumber/treetop_parser/with_comments.feature +1 -1
  173. data/spec/cucumber/treetop_parser/with_tags.feature +18 -0
  174. data/spec/cucumber/world/pending_spec.rb +13 -12
  175. data/spec/spec_helper.rb +1 -1
  176. metadata +107 -79
  177. data/examples/calculator_ruby_features/features/addition.rb +0 -39
  178. data/examples/calculator_ruby_features/features/step_definitons/calculator_steps.rb +0 -43
  179. data/gem_tasks/treetop.rake +0 -41
  180. data/lib/cucumber/cli.rb +0 -355
  181. data/lib/cucumber/executor.rb +0 -205
  182. data/lib/cucumber/formatters.rb +0 -1
  183. data/lib/cucumber/formatters/autotest_formatter.rb +0 -23
  184. data/lib/cucumber/formatters/cucumber.css +0 -132
  185. data/lib/cucumber/formatters/cucumber.js +0 -11
  186. data/lib/cucumber/formatters/html_formatter.rb +0 -152
  187. data/lib/cucumber/formatters/jquery.js +0 -32
  188. data/lib/cucumber/formatters/pretty_formatter.rb +0 -285
  189. data/lib/cucumber/formatters/profile_formatter.rb +0 -92
  190. data/lib/cucumber/formatters/progress_formatter.rb +0 -61
  191. data/lib/cucumber/model.rb +0 -1
  192. data/lib/cucumber/model/table.rb +0 -32
  193. data/lib/cucumber/step_methods.rb +0 -49
  194. data/lib/cucumber/tree.rb +0 -16
  195. data/lib/cucumber/tree/feature.rb +0 -105
  196. data/lib/cucumber/tree/features.rb +0 -21
  197. data/lib/cucumber/tree/given_scenario.rb +0 -13
  198. data/lib/cucumber/tree/scenario.rb +0 -240
  199. data/lib/cucumber/tree/step.rb +0 -173
  200. data/lib/cucumber/tree/table.rb +0 -26
  201. data/lib/cucumber/tree/top_down_visitor.rb +0 -23
  202. data/lib/cucumber/treetop_parser/feature.treetop.erb +0 -254
  203. data/lib/cucumber/treetop_parser/feature_ar.rb +0 -1951
  204. data/lib/cucumber/treetop_parser/feature_cy.rb +0 -1951
  205. data/lib/cucumber/treetop_parser/feature_da.rb +0 -1951
  206. data/lib/cucumber/treetop_parser/feature_de.rb +0 -1951
  207. data/lib/cucumber/treetop_parser/feature_en-lol.rb +0 -1951
  208. data/lib/cucumber/treetop_parser/feature_en-tx.rb +0 -1951
  209. data/lib/cucumber/treetop_parser/feature_en.rb +0 -1951
  210. data/lib/cucumber/treetop_parser/feature_es.rb +0 -1951
  211. data/lib/cucumber/treetop_parser/feature_et.rb +0 -1951
  212. data/lib/cucumber/treetop_parser/feature_fi.rb +0 -1951
  213. data/lib/cucumber/treetop_parser/feature_fr.rb +0 -1951
  214. data/lib/cucumber/treetop_parser/feature_id.rb +0 -1951
  215. data/lib/cucumber/treetop_parser/feature_it.rb +0 -1951
  216. data/lib/cucumber/treetop_parser/feature_ja.rb +0 -1951
  217. data/lib/cucumber/treetop_parser/feature_ko.rb +0 -1951
  218. data/lib/cucumber/treetop_parser/feature_lt.rb +0 -1951
  219. data/lib/cucumber/treetop_parser/feature_nl.rb +0 -1951
  220. data/lib/cucumber/treetop_parser/feature_no.rb +0 -1951
  221. data/lib/cucumber/treetop_parser/feature_parser.rb +0 -36
  222. data/lib/cucumber/treetop_parser/feature_pl.rb +0 -1951
  223. data/lib/cucumber/treetop_parser/feature_pt.rb +0 -1951
  224. data/lib/cucumber/treetop_parser/feature_ro.rb +0 -1951
  225. data/lib/cucumber/treetop_parser/feature_ro2.rb +0 -1951
  226. data/lib/cucumber/treetop_parser/feature_ru.rb +0 -1951
  227. data/lib/cucumber/treetop_parser/feature_se.rb +0 -1951
  228. data/lib/cucumber/treetop_parser/feature_zh-CN.rb +0 -1951
  229. data/lib/cucumber/world.rb +0 -1
  230. data/lib/cucumber/world/pending.rb +0 -22
  231. data/setup.rb +0 -1585
  232. data/spec/cucumber/cli_spec.rb +0 -521
  233. data/spec/cucumber/executor_spec.rb +0 -382
  234. data/spec/cucumber/formatters/autotest_formatter_spec.rb +0 -26
  235. data/spec/cucumber/formatters/features.html +0 -269
  236. data/spec/cucumber/formatters/html_formatter_spec.rb +0 -110
  237. data/spec/cucumber/formatters/pretty_formatter_spec.rb +0 -410
  238. data/spec/cucumber/formatters/progress_formatter_spec.rb +0 -81
  239. data/spec/cucumber/model/table_spec.rb +0 -32
  240. data/spec/cucumber/tree/feature_spec.rb +0 -122
  241. data/spec/cucumber/tree/row_scenario_outline_spec.rb +0 -73
  242. data/spec/cucumber/tree/row_scenario_spec.rb +0 -55
  243. data/spec/cucumber/tree/row_step_outline_spec.rb +0 -38
  244. data/spec/cucumber/tree/scenario_outline_spec.rb +0 -50
  245. data/spec/cucumber/tree/scenario_spec.rb +0 -134
  246. data/spec/cucumber/tree/step_outline_spec.rb +0 -17
  247. data/spec/cucumber/tree/step_spec.rb +0 -59
  248. data/spec/cucumber/treetop_parser/feature_parser_spec.rb +0 -120
@@ -5,14 +5,9 @@ module Cucumber
5
5
  @receivers = receivers
6
6
  end
7
7
 
8
- def register(receiver)
9
- @receivers << receiver
10
- end
11
-
12
8
  def method_missing(method_name, *args)
13
9
  @receivers.each do |receiver|
14
- r = (receiver == STDOUT) ? Kernel : receiver # Needed to make colors work on Windows
15
- r.__send__(method_name, *args) if receiver.respond_to?(method_name)
10
+ receiver.__send__(method_name, *args)
16
11
  end
17
12
  end
18
13
 
@@ -0,0 +1,339 @@
1
+ module Cucumber
2
+ module Cli
3
+ class YmlLoadError < StandardError; end
4
+
5
+ class Configuration
6
+ FORMATS = %w{pretty profile progress rerun}
7
+ DEFAULT_FORMAT = 'pretty'
8
+
9
+ attr_reader :paths
10
+ attr_reader :options
11
+
12
+ def initialize(out_stream = STDOUT, error_stream = STDERR)
13
+ @out_stream = out_stream
14
+ @error_stream = error_stream
15
+
16
+ @paths = []
17
+ @options = default_options
18
+ @active_format = DEFAULT_FORMAT
19
+ end
20
+
21
+ def parse!(args)
22
+ @args = args
23
+ return parse_args_from_profile('default') if @args.empty?
24
+ @args.extend(::OptionParser::Arguable)
25
+
26
+ @args.options do |opts|
27
+ opts.banner = ["Usage: cucumber [options] [ [FILE|DIR|URL][:LINE[:LINE]*] ]+", "",
28
+ "Examples:",
29
+ "cucumber examples/i18n/en/features",
30
+ "cucumber --language it examples/i18n/it/features/somma.feature:6:98:113",
31
+ "cucumber -n -i http://rubyurl.com/eeCl", "", "",
32
+ ].join("\n")
33
+ opts.on("-r LIBRARY|DIR", "--require LIBRARY|DIR",
34
+ "Require files before executing the features. If this",
35
+ "option is not specified, all *.rb files that are",
36
+ "siblings or below the features will be loaded auto-",
37
+ "matically. Automatic loading is disabled when this",
38
+ "option is specified, and all loading becomes explicit.",
39
+ "Files under directories named \"support\" are always",
40
+ "loaded first.",
41
+ "This option can be specified multiple times.") do |v|
42
+ @options[:require] ||= []
43
+ @options[:require] << v
44
+ end
45
+ opts.on("-l LANG", "--language LANG",
46
+ "Specify language for features (Default: #{@options[:lang]})",
47
+ %{Run with "--language help" to see all languages},
48
+ %{Run with "--language LANG help" to list keywords for LANG}) do |v|
49
+ if v == 'help'
50
+ list_languages
51
+ elsif args==['help']
52
+ list_keywords(v)
53
+ else
54
+ @options[:lang] = v
55
+ end
56
+ end
57
+ opts.on("-f FORMAT", "--format FORMAT",
58
+ "How to format features (Default: #{DEFAULT_FORMAT})",
59
+ "Available formats: #{FORMATS.join(", ")}",
60
+ "You can also provide your own formatter classes as long",
61
+ "as they have been previously required using --require or",
62
+ "if they are in the folder structure such that cucumber",
63
+ "will require them automatically.",
64
+ "This option can be specified multiple times.") do |v|
65
+ @options[:formats][v] = @out_stream
66
+ @active_format = v
67
+ end
68
+ opts.on("-o", "--out FILE",
69
+ "Write output to a file instead of STDOUT. This option",
70
+ "applies to the previously specified --format, or the",
71
+ "default format if no format is specified.") do |v|
72
+ @options[:formats][@active_format] = v
73
+ end
74
+ opts.on("-t TAGS", "--tags TAGS",
75
+ "Only execute the features or scenarios with the specified tags.",
76
+ "TAGS must be comma-separated without spaces. Prefix tags with ! to",
77
+ "exclude features or scenarios having that tag. tags can be specified",
78
+ "with or without the @ prefix.") do |v|
79
+ @options[:tags] = v.split(",")
80
+ end
81
+ opts.on("-s SCENARIO", "--scenario SCENARIO",
82
+ "Only execute the scenario with the given name. If this option",
83
+ "is given more than once, run all the specified scenarios.") do |v|
84
+ @options[:scenario_names] << v
85
+ end
86
+ opts.on("-e", "--exclude PATTERN", "Don't run feature files matching PATTERN") do |v|
87
+ @options[:excludes] << v
88
+ end
89
+ opts.on("-p", "--profile PROFILE", "Pull commandline arguments from cucumber.yml.") do |v|
90
+ parse_args_from_profile(v)
91
+ end
92
+ opts.on("-c", "--[no-]color",
93
+ "Whether or not to use ANSI color in the output. Cucumber decides",
94
+ "based on your platform and the output destination if not specified.") do |v|
95
+ Term::ANSIColor.coloring = v
96
+ end
97
+ opts.on("-d", "--dry-run", "Invokes formatters without executing the steps.",
98
+ "Implies --quiet.") do
99
+ @options[:dry_run] = true
100
+ @quiet = true
101
+ end
102
+ opts.on("-a", "--autoformat DIRECTORY",
103
+ "Reformats (pretty prints) feature files and write them to DIRECTORY.",
104
+ "Be careful if you choose to overwrite the originals.",
105
+ "Implies --dry-run --formatter pretty.") do |directory|
106
+ @options[:autoformat] = directory
107
+ Term::ANSIColor.coloring = false
108
+ @options[:dry_run] = true
109
+ @quiet = true
110
+ end
111
+ opts.on("-m", "--no-multiline",
112
+ "Don't print multiline strings and tables under steps.") do
113
+ @options[:no_multiline] = true
114
+ end
115
+ opts.on("-n", "--no-source",
116
+ "Don't print the file and line of the step definition with the steps.") do
117
+ @options[:source] = false
118
+ end
119
+ opts.on("-i", "--no-snippets", "Don't print snippets for pending steps.") do
120
+ @options[:snippets] = false
121
+ end
122
+ opts.on("-q", "--quiet", "Alias for --no-snippets --no-source.") do
123
+ @quiet = true
124
+ end
125
+ opts.on("-b", "--backtrace", "Show full backtrace for all errors.") do
126
+ Exception.cucumber_full_backtrace = true
127
+ end
128
+ opts.on("--strict", "Fail if there are any undefined steps.") do
129
+ @options[:strict] = true
130
+ end
131
+ opts.on("-v", "--verbose", "Show the files and features loaded.") do
132
+ @options[:verbose] = true
133
+ end
134
+ opts.on("-g", "--guess", "Guess best match for Ambiguous steps.") do
135
+ @options[:guess] = true
136
+ end
137
+ opts.on_tail("--version", "Show version.") do
138
+ @out_stream.puts VERSION::STRING
139
+ Kernel.exit
140
+ end
141
+ opts.on_tail("--help", "You're looking at it.") do
142
+ @out_stream.puts opts.help
143
+ Kernel.exit
144
+ end
145
+ end.parse!
146
+
147
+ @options[:formats]['pretty'] = @out_stream if @options[:formats].empty?
148
+
149
+ @options[:snippets] = true if !@quiet && @options[:snippets].nil?
150
+ @options[:source] = true if !@quiet && @options[:source].nil?
151
+
152
+ # Whatever is left after option parsing is the FILE arguments
153
+ @paths += args
154
+ end
155
+
156
+ def ast_filter
157
+ Ast::Filter.new(@options)
158
+ end
159
+
160
+ def verbose?
161
+ @options[:verbose]
162
+ end
163
+
164
+ def strict?
165
+ @options[:strict]
166
+ end
167
+
168
+ def guess?
169
+ !!@options[:guess]
170
+ end
171
+
172
+ def load_language
173
+ Cucumber.load_language(@options[:lang])
174
+
175
+ if Cucumber.language_incomplete?
176
+ list_keywords(Cucumber.lang)
177
+ end
178
+ end
179
+
180
+ def build_formatter_broadcaster(step_mother)
181
+ return Formatter::Pretty.new(step_mother, nil, @options) if @options[:autoformat]
182
+ formatters = @options[:formats].map do |format, out|
183
+ if String === out # file name
184
+ out = File.open(out, Cucumber.file_mode('w'))
185
+ at_exit do
186
+ out.flush
187
+ out.close
188
+ end
189
+ end
190
+
191
+ begin
192
+ formatter_class = formatter_class(format)
193
+ formatter_class.new(step_mother, out, @options)
194
+ rescue Exception => e
195
+ exit_with_error("Error creating formatter: #{format}", e)
196
+ end
197
+ end
198
+
199
+ broadcaster = Broadcaster.new(formatters)
200
+ broadcaster.options = @options
201
+ return broadcaster
202
+ end
203
+
204
+ def formatter_class(format)
205
+ case format
206
+ when 'pretty' then Formatter::Pretty
207
+ when 'progress' then Formatter::Progress
208
+ when 'profile' then Formatter::Profile
209
+ when 'rerun' then Formatter::Rerun
210
+ when 'html' then Formatter::Html
211
+ else
212
+ constantize(format)
213
+ end
214
+ end
215
+
216
+ def files_to_require
217
+ requires = @options[:require] || feature_dirs
218
+ files = requires.map do |path|
219
+ path = path.gsub(/\\/, '/') # In case we're on windows. Globs don't work with backslashes.
220
+ File.directory?(path) ? Dir["#{path}/**/*.rb"] : path
221
+ end.flatten.uniq
222
+ files.sort { |a,b| (b =~ %r{/support/} || -1) <=> (a =~ %r{/support/} || -1) }.reject{|f| f =~ /^http/}
223
+ end
224
+
225
+ def feature_files
226
+ potential_feature_files = @paths.map do |path|
227
+ path = path.gsub(/\\/, '/') # In case we're on windows. Globs don't work with backslashes.
228
+ path = path.chomp('/')
229
+ File.directory?(path) ? Dir["#{path}/**/*.feature"] : path
230
+ end.flatten.uniq
231
+
232
+ @options[:excludes].each do |exclude|
233
+ potential_feature_files.reject! do |path|
234
+ path =~ /#{Regexp.escape(exclude)}/
235
+ end
236
+ end
237
+
238
+ potential_feature_files
239
+ end
240
+
241
+ protected
242
+
243
+ def feature_dirs
244
+ feature_files.map { |f| File.directory?(f) ? f : File.dirname(f) }.uniq
245
+ end
246
+
247
+ def constantize(camel_cased_word)
248
+ names = camel_cased_word.split('::')
249
+ names.shift if names.empty? || names.first.empty?
250
+
251
+ constant = Object
252
+ names.each do |name|
253
+ constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
254
+ end
255
+ constant
256
+ end
257
+
258
+ def parse_args_from_profile(profile)
259
+ unless cucumber_yml.has_key?(profile)
260
+ return(exit_with_error <<-END_OF_ERROR)
261
+ Could not find profile: '#{profile}'
262
+
263
+ Defined profiles in cucumber.yml:
264
+ * #{cucumber_yml.keys.join("\n * ")}
265
+ END_OF_ERROR
266
+ end
267
+
268
+ args_from_yml = cucumber_yml[profile] || ''
269
+
270
+ if !args_from_yml.is_a?(String)
271
+ exit_with_error "Profiles must be defined as a String. The '#{profile}' profile was #{args_from_yml.inspect} (#{args_from_yml.class}).\n"
272
+ elsif args_from_yml =~ /^\s*$/
273
+ exit_with_error "The 'foo' profile in cucumber.yml was blank. Please define the command line arguments for the 'foo' profile in cucumber.yml.\n"
274
+ else
275
+ parse!(args_from_yml.split(' '))
276
+ end
277
+
278
+ rescue YmlLoadError => e
279
+ exit_with_error(e.message)
280
+ end
281
+
282
+ def cucumber_yml
283
+ return @cucumber_yml if @cucumber_yml
284
+ unless File.exist?('cucumber.yml')
285
+ raise(YmlLoadError,"cucumber.yml was not found. Please refer to cucumber's documentaion on defining profiles in cucumber.yml. You must define a 'default' profile to use the cucumber command without any arguments.\nType 'cucumber --help' for usage.\n")
286
+ end
287
+
288
+ require 'yaml'
289
+ begin
290
+ @cucumber_yml = YAML::load(IO.read('cucumber.yml'))
291
+ rescue Exception => e
292
+ raise(YmlLoadError,"cucumber.yml was found, but could not be parsed. Please refer to cucumber's documentaion on correct profile usage.\n")
293
+ end
294
+
295
+ if @cucumber_yml.nil? || !@cucumber_yml.is_a?(Hash)
296
+ raise(YmlLoadError,"cucumber.yml was found, but was blank or malformed. Please refer to cucumber's documentaion on correct profile usage.\n")
297
+ end
298
+
299
+ return @cucumber_yml
300
+ end
301
+
302
+ def list_keywords(lang)
303
+ unless Cucumber::LANGUAGES[lang]
304
+ exit_with_error("No language with key #{lang}")
305
+ end
306
+ LanguageHelpFormatter.list_keywords(@out_stream, lang)
307
+ Kernel.exit
308
+ end
309
+
310
+ def list_languages
311
+ LanguageHelpFormatter.list_languages(@out_stream)
312
+ Kernel.exit
313
+ end
314
+
315
+ def default_options
316
+ {
317
+ :strict => false,
318
+ :require => nil,
319
+ :lang => 'en',
320
+ :dry_run => false,
321
+ :formats => {},
322
+ :excludes => [],
323
+ :tags => [],
324
+ :scenario_names => []
325
+ }
326
+ end
327
+
328
+ def exit_with_error(error_message, e=nil)
329
+ @error_stream.puts(error_message)
330
+ if e
331
+ @error_stream.puts("#{e.message} (#{e.class})")
332
+ @error_stream.puts(e.backtrace.join("\n"))
333
+ end
334
+ Kernel.exit 1
335
+ end
336
+ end
337
+
338
+ end
339
+ end
@@ -0,0 +1,59 @@
1
+ require 'cucumber/formatter/pretty'
2
+
3
+ module Cucumber
4
+ module Cli
5
+ class LanguageHelpFormatter < Formatter::Pretty
6
+ INCOMPLETE = %{
7
+ The Cucumber grammar has evolved since this translation was written.
8
+ Please help us complete the translation by translating the missing words in
9
+
10
+ #{Cucumber::LANGUAGE_FILE}
11
+
12
+ Then contribute back to the Cucumber project. Details here:
13
+ http://wiki.github.com/aslakhellesoy/cucumber/spoken-languages
14
+ }
15
+
16
+ def self.list_languages(io)
17
+ raw = Cucumber::LANGUAGES.keys.sort.map do |lang|
18
+ [lang, Cucumber::LANGUAGES[lang]['name'], Cucumber::LANGUAGES[lang]['native']]
19
+ end
20
+ table = Ast::Table.new(raw)
21
+ new(nil, io, {:check_lang=>true}, '').visit_multiline_arg(table, :passed)
22
+ end
23
+
24
+ def self.list_keywords(io, lang)
25
+ raw = Cucumber::KEYWORD_KEYS.map do |key|
26
+ [key, Cucumber::LANGUAGES[lang][key]]
27
+ end
28
+ table = Ast::Table.new(raw)
29
+ new(nil, io, {:incomplete => Cucumber.language_incomplete?(lang)}, '').visit_multiline_arg(table, :passed)
30
+ end
31
+
32
+ def visit_multiline_arg(table, status)
33
+ if @options[:incomplete]
34
+ @io.puts(format_string(INCOMPLETE, :failed))
35
+ end
36
+ super
37
+ end
38
+
39
+ def visit_table_row(table_row, status)
40
+ @col = 1
41
+ super
42
+ end
43
+
44
+ def visit_table_cell_value(value, width, status)
45
+ if @col == 1
46
+ if(@options[:check_lang])
47
+ @incomplete = Cucumber.language_incomplete?(value)
48
+ end
49
+ status = :comment
50
+ elsif @incomplete
51
+ status = :failed
52
+ end
53
+
54
+ @col += 1
55
+ super(value, width, status)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,100 @@
1
+ require 'optparse'
2
+ require 'cucumber'
3
+ require 'ostruct'
4
+ require 'cucumber/parser'
5
+ require 'cucumber/formatter'
6
+ require 'cucumber/cli/language_help_formatter'
7
+ require 'cucumber/cli/configuration'
8
+
9
+ module Cucumber
10
+ module Cli
11
+ class Main
12
+ class << self
13
+ def step_mother=(step_mother)
14
+ @step_mother = step_mother
15
+ @step_mother.extend(StepMother)
16
+ @step_mother.snippet_generator = StepDefinition
17
+ end
18
+
19
+ def execute(args)
20
+ new(args).execute!(@step_mother)
21
+ end
22
+ end
23
+
24
+ def initialize(args, out_stream = STDOUT, error_stream = STDERR)
25
+ @args = args
26
+ @out_stream = out_stream == STDOUT ? Formatter::ColorIO.new : out_stream
27
+ @error_stream = error_stream
28
+ end
29
+
30
+ def execute!(step_mother)
31
+ configuration.load_language
32
+ step_mother.options = configuration.options
33
+
34
+ require_files
35
+ enable_diffing
36
+
37
+ features = load_plain_text_features
38
+
39
+ visitor = configuration.build_formatter_broadcaster(step_mother)
40
+ visitor.visit_features(features)
41
+
42
+ failure = features.steps[:failed].any? || (configuration.strict? && features.steps[:undefined].length)
43
+ Kernel.exit(failure ? 1 : 0)
44
+ end
45
+
46
+ private
47
+
48
+ def configuration
49
+ return @configuration if @configuration
50
+
51
+ @configuration = Configuration.new(@out_stream, @error_stream)
52
+ @configuration.parse!(@args)
53
+ @configuration
54
+ end
55
+
56
+ def require_files
57
+ verbose_log("Ruby files required:")
58
+ configuration.files_to_require.each do |lib|
59
+ begin
60
+ require lib
61
+ verbose_log(" * #{lib}")
62
+ rescue LoadError => e
63
+ e.message << "\nFailed to load #{lib}"
64
+ raise e
65
+ end
66
+ end
67
+ verbose_log("\n")
68
+ end
69
+
70
+ def load_plain_text_features
71
+ filter = configuration.ast_filter
72
+ features = Ast::Features.new(filter)
73
+ parser = Parser::FeatureParser.new
74
+
75
+ verbose_log("Features:")
76
+ configuration.feature_files.each do |f|
77
+ features.add_feature(parser.parse_file(f))
78
+ verbose_log(" * #{f}")
79
+ end
80
+ verbose_log("\n"*2)
81
+ features
82
+ end
83
+
84
+ def verbose_log(string)
85
+ @out_stream.puts(string) if configuration.verbose?
86
+ end
87
+
88
+ def enable_diffing
89
+ if defined?(::Spec)
90
+ require 'spec/expectations/differs/default'
91
+ options = OpenStruct.new(:diff_format => :unified, :context_lines => 3)
92
+ ::Spec::Expectations.differ = ::Spec::Expectations::Differs::Default.new(options)
93
+ end
94
+ end
95
+
96
+ end
97
+ end
98
+ end
99
+
100
+ Cucumber::Cli::Main.step_mother = self