cucumber 4.1.0 → 9.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +134 -21
  3. data/VERSION +1 -0
  4. data/lib/cucumber/cli/configuration.rb +27 -2
  5. data/lib/cucumber/cli/main.rb +5 -4
  6. data/lib/cucumber/cli/options.rb +102 -65
  7. data/lib/cucumber/cli/profile_loader.rb +6 -10
  8. data/lib/cucumber/cli/rerun_file.rb +1 -1
  9. data/lib/cucumber/configuration.rb +26 -13
  10. data/lib/cucumber/constantize.rb +1 -1
  11. data/lib/cucumber/deprecate.rb +6 -46
  12. data/lib/cucumber/errors.rb +4 -3
  13. data/lib/cucumber/events/envelope.rb +2 -0
  14. data/lib/cucumber/events/gherkin_source_parsed.rb +2 -0
  15. data/lib/cucumber/events/gherkin_source_read.rb +2 -0
  16. data/lib/cucumber/events/hook_test_step_created.rb +1 -2
  17. data/lib/cucumber/events/step_activated.rb +0 -6
  18. data/lib/cucumber/events/step_definition_registered.rb +0 -5
  19. data/lib/cucumber/events/test_case_created.rb +1 -2
  20. data/lib/cucumber/events/test_case_finished.rb +2 -0
  21. data/lib/cucumber/events/test_case_started.rb +2 -0
  22. data/lib/cucumber/events/test_run_finished.rb +2 -1
  23. data/lib/cucumber/events/test_step_created.rb +1 -2
  24. data/lib/cucumber/events/test_step_finished.rb +2 -0
  25. data/lib/cucumber/events/test_step_started.rb +2 -0
  26. data/lib/cucumber/events/undefined_parameter_type.rb +3 -2
  27. data/lib/cucumber/events.rb +2 -2
  28. data/lib/cucumber/file_specs.rb +2 -1
  29. data/lib/cucumber/filters/activate_steps.rb +1 -0
  30. data/lib/cucumber/filters/retry.rb +20 -1
  31. data/lib/cucumber/filters/tag_limits/verifier.rb +1 -3
  32. data/lib/cucumber/filters/tag_limits.rb +1 -3
  33. data/lib/cucumber/formatter/ansicolor.rb +70 -85
  34. data/lib/cucumber/formatter/ast_lookup.rb +16 -10
  35. data/lib/cucumber/formatter/backtrace_filter.rb +3 -1
  36. data/lib/cucumber/formatter/console.rb +34 -16
  37. data/lib/cucumber/formatter/console_counts.rb +3 -1
  38. data/lib/cucumber/formatter/console_issues.rb +10 -3
  39. data/lib/cucumber/formatter/curl_option_parser.rb +49 -0
  40. data/lib/cucumber/formatter/duration_extractor.rb +1 -0
  41. data/lib/cucumber/formatter/errors.rb +3 -0
  42. data/lib/cucumber/formatter/fail_fast.rb +1 -1
  43. data/lib/cucumber/formatter/fanout.rb +1 -1
  44. data/lib/cucumber/formatter/html.rb +3 -1
  45. data/lib/cucumber/formatter/http_io.rb +10 -136
  46. data/lib/cucumber/formatter/ignore_missing_messages.rb +1 -1
  47. data/lib/cucumber/formatter/interceptor.rb +4 -3
  48. data/lib/cucumber/formatter/io.rb +50 -12
  49. data/lib/cucumber/formatter/io_http_buffer.rb +88 -0
  50. data/lib/cucumber/formatter/json.rb +36 -37
  51. data/lib/cucumber/formatter/junit.rb +29 -9
  52. data/lib/cucumber/formatter/message.rb +3 -2
  53. data/lib/cucumber/formatter/message_builder.rb +32 -16
  54. data/lib/cucumber/formatter/pretty.rb +44 -29
  55. data/lib/cucumber/formatter/progress.rb +2 -1
  56. data/lib/cucumber/formatter/publish_banner_printer.rb +75 -0
  57. data/lib/cucumber/formatter/query/hook_by_test_step.rb +3 -0
  58. data/lib/cucumber/formatter/query/pickle_by_test.rb +2 -0
  59. data/lib/cucumber/formatter/query/pickle_step_by_test_step.rb +2 -0
  60. data/lib/cucumber/formatter/query/step_definitions_by_test_step.rb +2 -0
  61. data/lib/cucumber/formatter/query/test_case_started_by_test_case.rb +4 -0
  62. data/lib/cucumber/formatter/rerun.rb +7 -5
  63. data/lib/cucumber/formatter/steps.rb +6 -3
  64. data/lib/cucumber/formatter/summary.rb +2 -1
  65. data/lib/cucumber/formatter/unicode.rb +7 -7
  66. data/lib/cucumber/formatter/url_reporter.rb +19 -0
  67. data/lib/cucumber/formatter/usage.rb +9 -7
  68. data/lib/cucumber/gherkin/data_table_parser.rb +2 -1
  69. data/lib/cucumber/gherkin/formatter/ansi_escapes.rb +25 -27
  70. data/lib/cucumber/gherkin/steps_parser.rb +1 -1
  71. data/lib/cucumber/glue/dsl.rb +30 -16
  72. data/lib/cucumber/glue/hook.rb +6 -3
  73. data/lib/cucumber/glue/invoke_in_world.rb +5 -5
  74. data/lib/cucumber/glue/proto_world.rb +37 -57
  75. data/lib/cucumber/glue/registry_and_more.rb +31 -12
  76. data/lib/cucumber/glue/registry_wrapper.rb +31 -0
  77. data/lib/cucumber/glue/snippet.rb +4 -2
  78. data/lib/cucumber/glue/step_definition.rb +9 -7
  79. data/lib/cucumber/glue/world_factory.rb +2 -0
  80. data/lib/cucumber/hooks.rb +1 -0
  81. data/lib/cucumber/multiline_argument/data_table/diff_matrices.rb +5 -2
  82. data/lib/cucumber/multiline_argument/data_table.rb +65 -79
  83. data/lib/cucumber/platform.rb +11 -16
  84. data/lib/cucumber/rake/task.rb +22 -17
  85. data/lib/cucumber/rspec/disable_option_parser.rb +6 -3
  86. data/lib/cucumber/rspec/doubles.rb +3 -5
  87. data/lib/cucumber/running_test_case.rb +2 -1
  88. data/lib/cucumber/runtime/for_programming_languages.rb +1 -2
  89. data/lib/cucumber/runtime/meta_message_builder.rb +108 -0
  90. data/lib/cucumber/runtime/support_code.rb +3 -0
  91. data/lib/cucumber/runtime/user_interface.rb +7 -6
  92. data/lib/cucumber/runtime.rb +50 -24
  93. data/lib/cucumber/step_match.rb +7 -11
  94. data/lib/cucumber/step_match_search.rb +3 -2
  95. data/lib/cucumber/term/ansicolor.rb +74 -50
  96. data/lib/cucumber/term/banner.rb +59 -0
  97. data/lib/cucumber.rb +2 -1
  98. data/lib/simplecov_setup.rb +1 -1
  99. metadata +103 -229
  100. data/CHANGELOG.md +0 -2682
  101. data/CONTRIBUTING.md +0 -71
  102. data/lib/autotest/cucumber.rb +0 -8
  103. data/lib/autotest/cucumber_mixin.rb +0 -132
  104. data/lib/autotest/cucumber_rails.rb +0 -8
  105. data/lib/autotest/cucumber_rails_rspec.rb +0 -8
  106. data/lib/autotest/cucumber_rails_rspec2.rb +0 -8
  107. data/lib/autotest/cucumber_rspec.rb +0 -8
  108. data/lib/autotest/cucumber_rspec2.rb +0 -8
  109. data/lib/autotest/discover.rb +0 -13
  110. data/lib/cucumber/core_ext/string.rb +0 -11
  111. data/lib/cucumber/version +0 -1
@@ -3,28 +3,48 @@
3
3
  require 'cucumber/platform'
4
4
  require 'cucumber/term/ansicolor'
5
5
 
6
- if Cucumber::WINDOWS_MRI
7
- unless ENV['ANSICON']
8
- STDERR.puts %{*** WARNING: You must use ANSICON 1.31 or higher (https://github.com/adoxa/ansicon/) to get coloured output on Windows}
9
- Cucumber::Term::ANSIColor.coloring = false
10
- end
11
- end
12
-
13
- Cucumber::Term::ANSIColor.coloring = false if !STDOUT.tty? && !ENV.key?('AUTOTEST')
6
+ Cucumber::Term::ANSIColor.coloring = false unless $stdout.tty?
14
7
 
15
8
  module Cucumber
16
9
  module Formatter
17
- # Defines aliases for coloured output. You don't invoke any methods from this
18
- # module directly, but you can change the output colours by defining
19
- # a <tt>CUCUMBER_COLORS</tt> variable in your shell, very much like how you can
20
- # tweak the familiar POSIX command <tt>ls</tt> with
21
- # <a href="http://mipsisrisc.com/rambling/2008/06/27/lscolorsls_colors-now-with-linux-support/">$LSCOLORS/$LS_COLORS</a>
10
+ # This module allows to format cucumber related outputs using ANSI escape sequences.
11
+ #
12
+ # For example, it provides a `passed` method which returns the string with
13
+ # the ANSI escape sequence to format it green per default.
14
+ #
15
+ # To use this, include or extend it in your class.
16
+ #
17
+ # Example:
18
+ #
19
+ # require 'cucumber/formatter/ansicolor'
20
+ #
21
+ # class MyFormatter
22
+ # extend Cucumber::Term::ANSIColor
23
+ #
24
+ # def on_test_step_finished(event)
25
+ # $stdout.puts undefined(event.test_step) if event.result.undefined?
26
+ # $stdout.puts passed(event.test_step) if event.result.passed?
27
+ # end
28
+ # end
29
+ #
30
+ # This module also allows the user to customize the format of cucumber outputs
31
+ # using environment variables.
32
+ #
33
+ # For instance, if your shell has a black background and a green font (like the
34
+ # "Homebrew" settings for OS X' Terminal.app), you may want to override passed
35
+ # steps to be white instead of green.
36
+ #
37
+ # Example:
38
+ #
39
+ # export CUCUMBER_COLORS="passed=white,bold:passed_param=white,bold,underline"
22
40
  #
23
41
  # The colours that you can change are:
24
42
  #
25
43
  # * <tt>undefined</tt> - defaults to <tt>yellow</tt>
26
44
  # * <tt>pending</tt> - defaults to <tt>yellow</tt>
27
45
  # * <tt>pending_param</tt> - defaults to <tt>yellow,bold</tt>
46
+ # * <tt>flaky</tt> - defaults to <tt>yellow</tt>
47
+ # * <tt>flaky_param</tt> - defaults to <tt>yellow,bold</tt>
28
48
  # * <tt>failed</tt> - defaults to <tt>red</tt>
29
49
  # * <tt>failed_param</tt> - defaults to <tt>red,bold</tt>
30
50
  # * <tt>passed</tt> - defaults to <tt>green</tt>
@@ -36,46 +56,39 @@ module Cucumber
36
56
  # * <tt>comment</tt> - defaults to <tt>grey</tt>
37
57
  # * <tt>tag</tt> - defaults to <tt>cyan</tt>
38
58
  #
39
- # For instance, if your shell has a black background and a green font (like the
40
- # "Homebrew" settings for OS X' Terminal.app), you may want to override passed
41
- # steps to be white instead of green.
42
- #
43
- # Although not listed, you can also use <tt>grey</tt>.
44
- #
45
- # Examples: (On Windows, use SET instead of export.)
46
- #
47
- # export CUCUMBER_COLORS="passed=white"
48
- # export CUCUMBER_COLORS="passed=white,bold:passed_param=white,bold,underline"
49
- #
50
59
  # To see what colours and effects are available, just run this in your shell:
51
60
  #
52
- # ruby -e "require 'rubygems'; require 'term/ansicolor'; puts Cucumber::Term::ANSIColor.attributes"
61
+ # ruby -e "require 'rubygems'; require 'cucumber/term/ansicolor'; puts Cucumber::Term::ANSIColor.attributes"
53
62
  #
54
63
  module ANSIColor
55
64
  include Cucumber::Term::ANSIColor
56
65
 
57
66
  ALIASES = Hash.new do |h, k|
58
- h[Regexp.last_match(1)] + ',bold' if k.to_s =~ /(.*)_param/
67
+ next unless k.to_s =~ /(.*)_param/
68
+
69
+ "#{h[Regexp.last_match(1)]},bold"
59
70
  end.merge(
60
71
  'undefined' => 'yellow',
61
- 'pending' => 'yellow',
62
- 'flaky' => 'yellow',
63
- 'failed' => 'red',
64
- 'passed' => 'green',
65
- 'outline' => 'cyan',
66
- 'skipped' => 'cyan',
67
- 'comment' => 'grey',
68
- 'tag' => 'cyan'
72
+ 'pending' => 'yellow',
73
+ 'flaky' => 'yellow',
74
+ 'failed' => 'red',
75
+ 'passed' => 'green',
76
+ 'outline' => 'cyan',
77
+ 'skipped' => 'cyan',
78
+ 'comment' => 'grey',
79
+ 'tag' => 'cyan'
69
80
  )
70
81
 
71
- if ENV['CUCUMBER_COLORS'] # Example: export CUCUMBER_COLORS="passed=red:failed=yellow"
72
- ENV['CUCUMBER_COLORS'].split(':').each do |pair|
82
+ # Apply the custom color scheme -> i.e. apply_custom_colors('passed=white')
83
+ def self.apply_custom_colors(colors)
84
+ colors.split(':').each do |pair|
73
85
  a = pair.split('=')
74
86
  ALIASES[a[0]] = a[1]
75
87
  end
76
88
  end
89
+ apply_custom_colors(ENV['CUCUMBER_COLORS']) if ENV['CUCUMBER_COLORS']
77
90
 
78
- # Eval to define the color-named methods required by Term::ANSIColor.
91
+ # Define the color-named methods required by Term::ANSIColor.
79
92
  #
80
93
  # Examples:
81
94
  #
@@ -87,67 +100,39 @@ module Cucumber
87
100
  # red(bold(string, &proc)) + red
88
101
  # end
89
102
  ALIASES.each_key do |method_name|
90
- next if method_name =~ /.*_param/
91
- code = <<-COLOR
92
- def #{method_name}(string=nil, &proc)
93
- #{ALIASES[method_name].split(',').join('(') + '(string, &proc' + ')' * ALIASES[method_name].split(',').length}
94
- end
95
- # This resets the colour to the non-param colour
96
- def #{method_name}_param(string=nil, &proc)
97
- #{ALIASES[method_name + '_param'].split(',').join('(') + '(string, &proc' + ')' * ALIASES[method_name + '_param'].split(',').length} + #{ALIASES[method_name].split(',').join(' + ')}
98
- end
99
- COLOR
100
- eval(code) # rubocop:disable Security/Eval
101
- end
103
+ next if method_name.end_with?('_param')
102
104
 
103
- def self.define_grey #:nodoc:
104
- gem 'genki-ruby-terminfo'
105
- require 'terminfo'
106
- case TermInfo.default_object.tigetnum('colors')
107
- when 0
108
- raise "Your terminal doesn't support colours."
109
- when 1
110
- ::Cucumber::Term::ANSIColor.coloring = false
111
- alias_method :grey, :white
112
- when 2..8
113
- alias_method :grey, :white # rubocop:disable Lint/DuplicateMethods
114
- else
115
- define_real_grey
116
- end
117
- rescue Exception => e # rubocop:disable Lint/RescueException
118
- if e.class.name == 'TermInfo::TermInfoError'
119
- STDERR.puts '*** WARNING ***'
120
- STDERR.puts "You have the genki-ruby-terminfo gem installed, but you haven't set your TERM variable."
121
- STDERR.puts 'Try setting it to TERM=xterm-256color to get grey colour in output.'
122
- STDERR.puts "\n"
123
- alias_method :grey, :white
124
- else
125
- define_real_grey
105
+ define_method(method_name) do |text = nil, &proc|
106
+ apply_styles(ALIASES[method_name], text, &proc)
126
107
  end
127
- end
128
108
 
129
- def self.define_real_grey #:nodoc:
130
- define_method :grey do |string|
131
- ::Cucumber::Term::ANSIColor.coloring? ? "\e[90m#{string}\e[0m" : string
109
+ define_method("#{method_name}_param") do |text = nil, &proc|
110
+ apply_styles(ALIASES["#{method_name}_param"], text, &proc) + apply_styles(ALIASES[method_name])
132
111
  end
133
112
  end
134
113
 
135
- define_grey
114
+ def cukes(amount)
115
+ ('(::) ' * amount).strip
116
+ end
136
117
 
137
- def cukes(n)
138
- ('(::) ' * n).strip
118
+ def green_cukes(amount)
119
+ blink(green(cukes(amount)))
139
120
  end
140
121
 
141
- def green_cukes(n)
142
- blink(green(cukes(n)))
122
+ def red_cukes(amount)
123
+ blink(red(cukes(amount)))
143
124
  end
144
125
 
145
- def red_cukes(n)
146
- blink(red(cukes(n)))
126
+ def yellow_cukes(amount)
127
+ blink(yellow(cukes(amount)))
147
128
  end
148
129
 
149
- def yellow_cukes(n)
150
- blink(yellow(cukes(n)))
130
+ private
131
+
132
+ def apply_styles(styles, text = nil, &proc)
133
+ styles.split(',').reverse.reduce(text) do |result, method_name|
134
+ send(method_name, result, &proc)
135
+ end
151
136
  end
152
137
  end
153
138
  end
@@ -45,11 +45,11 @@ module Cucumber
45
45
  break
46
46
  end
47
47
  break if node.previous_node.nil?
48
+
48
49
  node = node.previous_node
49
50
  end
50
51
  keyword = dialect.given_keywords.reject { |kw| kw == '* ' }[0] if keyword.nil?
51
- keyword = Cucumber::Gherkin::I18n.code_keyword_for(keyword)
52
- keyword
52
+ Cucumber::Gherkin::I18n.code_keyword_for(keyword)
53
53
  end
54
54
 
55
55
  ScenarioSource = Struct.new(:type, :scenario)
@@ -112,16 +112,24 @@ module Cucumber
112
112
  if child.respond_to?(:rule) && child.rule
113
113
  process_scenario_container(child.rule)
114
114
  elsif child.respond_to?(:scenario) && child.scenario
115
- child.scenario.steps.each do |step|
116
- @lookup_hash[step.location.line] = StepSource.new(:Step, step)
117
- end
115
+ store_scenario_source_steps(child.scenario)
118
116
  elsif !child.background.nil?
119
- child.background.steps.each do |step|
120
- @lookup_hash[step.location.line] = StepSource.new(:Step, step)
121
- end
117
+ store_background_source_steps(child.background)
122
118
  end
123
119
  end
124
120
  end
121
+
122
+ def store_scenario_source_steps(scenario)
123
+ scenario.steps.each do |step|
124
+ @lookup_hash[step.location.line] = StepSource.new(:Step, step)
125
+ end
126
+ end
127
+
128
+ def store_background_source_steps(background)
129
+ background.steps.each do |step|
130
+ @lookup_hash[step.location.line] = StepSource.new(:Step, step)
131
+ end
132
+ end
125
133
  end
126
134
 
127
135
  KeywordSearchNode = Struct.new(:keyword, :previous_node)
@@ -136,7 +144,6 @@ module Cucumber
136
144
 
137
145
  private
138
146
 
139
- # rubocop:disable Metrics/PerceivedComplexity
140
147
  def process_scenario_container(container, original_previous_node)
141
148
  container.children.each do |child|
142
149
  previous_node = original_previous_node
@@ -158,7 +165,6 @@ module Cucumber
158
165
  end
159
166
  end
160
167
  end
161
- # rubocop:enable Metrics/PerceivedComplexity
162
168
  end
163
169
  end
164
170
  end
@@ -15,12 +15,14 @@ module Cucumber
15
15
  test/unit
16
16
  .gem/ruby
17
17
  bin/bundle
18
+ rdebug-ide
18
19
  ]
19
20
 
20
21
  @backtrace_filters << RbConfig::CONFIG['rubyarchdir'] if RbConfig::CONFIG['rubyarchdir']
21
22
  @backtrace_filters << RbConfig::CONFIG['rubylibdir'] if RbConfig::CONFIG['rubylibdir']
22
23
 
23
24
  @backtrace_filters << 'org/jruby/' if ::Cucumber::JRUBY
25
+ @backtrace_filters << '<internal:' if RUBY_ENGINE == 'truffleruby'
24
26
 
25
27
  BACKTRACE_FILTER_PATTERNS = Regexp.new(@backtrace_filters.join('|'))
26
28
 
@@ -32,7 +34,7 @@ module Cucumber
32
34
  def exception
33
35
  return @exception if ::Cucumber.use_full_backtrace
34
36
 
35
- pwd_pattern = /#{::Regexp.escape(::Dir.pwd)}\//m # rubocop:disable Style/RegexpLiteral
37
+ pwd_pattern = /#{::Regexp.escape(::Dir.pwd)}\//m
36
38
  backtrace = @exception.backtrace.map { |line| line.gsub(pwd_pattern, './') }
37
39
 
38
40
  filtered = (backtrace || []).reject do |line|
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # rubocop:disable Metrics/ModuleLength
4
-
5
3
  require 'cucumber/formatter/ansicolor'
6
4
  require 'cucumber/formatter/duration'
7
5
  require 'cucumber/gherkin/i18n'
@@ -34,7 +32,7 @@ module Cucumber
34
32
 
35
33
  def format_step(keyword, step_match, status, source_indent)
36
34
  comment = if source_indent
37
- c = ('# ' + step_match.location.to_s).indent(source_indent)
35
+ c = indent("# #{step_match.location}", source_indent)
38
36
  format_string(c, :comment)
39
37
  else
40
38
  ''
@@ -45,10 +43,10 @@ module Cucumber
45
43
  format_string(line, status)
46
44
  end
47
45
 
48
- def format_string(o, status)
46
+ def format_string(input, status)
49
47
  fmt = format_for(status)
50
- o.to_s.split("\n").map do |line|
51
- if Proc == fmt.class
48
+ input.to_s.split("\n").map do |line|
49
+ if fmt.instance_of?(Proc)
52
50
  fmt.call(line)
53
51
  else
54
52
  fmt % line
@@ -94,22 +92,25 @@ module Cucumber
94
92
  @io.flush
95
93
  end
96
94
 
97
- def print_exception(e, status, indent)
98
- string = exception_message_string(e, indent)
95
+ def print_exception(exception, status, indent)
96
+ string = exception_message_string(exception, indent)
99
97
  @io.puts(format_string(string, status))
100
98
  end
101
99
 
102
- def exception_message_string(e, indent)
103
- message = "#{e.message} (#{e.class})".dup.force_encoding('UTF-8')
100
+ def exception_message_string(exception, indent_amount)
101
+ message = "#{exception.message} (#{exception.class})".dup.force_encoding('UTF-8')
104
102
  message = linebreaks(message, ENV['CUCUMBER_TRUNCATE_OUTPUT'].to_i)
105
103
 
106
- "#{message}\n#{e.backtrace.join("\n")}".indent(indent)
104
+ indent("#{message}\n#{exception.backtrace.join("\n")}", indent_amount)
107
105
  end
108
106
 
109
107
  # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/10655
110
108
  def linebreaks(msg, max)
111
- return msg unless max && max > 0
112
- msg.gsub(/.{1,#{max}}(?:\s|\Z)/) { ($& + 5.chr).gsub(/\n\005/, "\n").gsub(/\005/, "\n") }.rstrip
109
+ return msg unless max.positive?
110
+
111
+ msg.gsub(/.{1,#{max}}(?:\s|\Z)/) do
112
+ (Regexp.last_match(0) + 5.chr).gsub(/\n\005/, "\n").gsub(/\005/, "\n")
113
+ end.rstrip
113
114
  end
114
115
 
115
116
  def collect_snippet_data(test_step, ast_lookup)
@@ -150,6 +151,7 @@ module Cucumber
150
151
 
151
152
  def print_passing_wip(config, passed_test_cases, ast_lookup)
152
153
  return unless config.wip?
154
+
153
155
  messages = passed_test_cases.map do |test_case|
154
156
  scenario_source = ast_lookup.scenario_source(test_case)
155
157
  keyword = scenario_source.type == :Scenario ? scenario_source.scenario.keyword : scenario_source.scenario_outline.keyword
@@ -167,16 +169,23 @@ module Cucumber
167
169
  end
168
170
  end
169
171
 
170
- def attach(src, media_type)
172
+ def attach(src, media_type, filename)
171
173
  return unless media_type == 'text/x.cucumber.log+plain'
172
174
  return unless @io
175
+
173
176
  @io.puts
174
- @io.puts(format_string(src, :tag))
177
+ if filename
178
+ @io.puts("#{filename}: #{format_string(src, :tag)}")
179
+ else
180
+ @io.puts(format_string(src, :tag))
181
+ end
182
+
175
183
  @io.flush
176
184
  end
177
185
 
178
186
  def print_profile_information
179
187
  return if @options[:skip_profile_information] || @options[:profiles].nil? || @options[:profiles].empty?
188
+
180
189
  do_print_profile_information(@options[:profiles])
181
190
  end
182
191
 
@@ -208,6 +217,14 @@ module Cucumber
208
217
  ].join("\n")
209
218
  end
210
219
 
220
+ def indent(string, padding)
221
+ if padding >= 0
222
+ string.gsub(/^/, ' ' * padding)
223
+ else
224
+ string.gsub(/^ {0,#{-padding}}/, '')
225
+ end
226
+ end
227
+
211
228
  private
212
229
 
213
230
  FORMATS = Hash.new { |hash, format| hash[format] = method(format).to_proc }
@@ -216,6 +233,7 @@ module Cucumber
216
233
  key = keys.join('_').to_sym
217
234
  fmt = FORMATS[key]
218
235
  raise "No format for #{key.inspect}: #{FORMATS.inspect}" if fmt.nil?
236
+
219
237
  fmt
220
238
  end
221
239
 
@@ -238,6 +256,7 @@ module Cucumber
238
256
 
239
257
  class SnippetData
240
258
  attr_reader :actual_keyword, :step
259
+
241
260
  def initialize(actual_keyword, step)
242
261
  @actual_keyword = actual_keyword
243
262
  @step = step
@@ -246,4 +265,3 @@ module Cucumber
246
265
  end
247
266
  end
248
267
  end
249
- # rubocop:enable Metrics/ModuleLength
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'cucumber/formatter/console'
2
4
 
3
5
  module Cucumber
@@ -30,7 +32,7 @@ module Cucumber
30
32
 
31
33
  def status_counts(summary)
32
34
  counts = Core::Test::Result::TYPES.map { |status| [status, summary.total(status)] }
33
- counts = counts.select { |_status, count| count > 0 }
35
+ counts = counts.select { |_status, count| count.positive? }
34
36
  counts = counts.map { |status, count| format_string("#{count} #{status}", status) }
35
37
  "(#{counts.join(', ')})" if counts.any?
36
38
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'cucumber/formatter/console'
2
4
 
3
5
  module Cucumber
@@ -12,9 +14,9 @@ module Cucumber
12
14
  @config.on_event(:test_case_finished) do |event|
13
15
  if event.test_case != @previous_test_case
14
16
  @previous_test_case = event.test_case
15
- @issues[event.result.to_sym] << event.test_case unless event.result.ok?(@config.strict)
17
+ @issues[event.result.to_sym] << event.test_case unless event.result.ok?(strict: @config.strict)
16
18
  elsif event.result.passed?
17
- @issues[:flaky] << event.test_case unless Core::Test::Result::Flaky.ok?(@config.strict.strict?(:flaky))
19
+ @issues[:flaky] << event.test_case unless Core::Test::Result::Flaky.ok?(strict: @config.strict.strict?(:flaky))
18
20
  @issues[:failed].delete(event.test_case)
19
21
  end
20
22
  end
@@ -23,6 +25,7 @@ module Cucumber
23
25
 
24
26
  def to_s
25
27
  return if @issues.empty?
28
+
26
29
  result = Core::Test::Result::TYPES.map { |type| scenario_listing(type, @issues[type]) }
27
30
  result.flatten.join("\n")
28
31
  end
@@ -35,6 +38,7 @@ module Cucumber
35
38
 
36
39
  def scenario_listing(type, test_cases)
37
40
  return [] if test_cases.empty?
41
+
38
42
  [format_string("#{type_heading(type)} Scenarios:", type)] + test_cases.map do |test_case|
39
43
  scenario_source = @ast_lookup.scenario_source(test_case)
40
44
  keyword = scenario_source.type == :Scenario ? scenario_source.scenario.keyword : scenario_source.scenario_outline.keyword
@@ -54,7 +58,10 @@ module Cucumber
54
58
 
55
59
  def profiles_string
56
60
  return if @config.custom_profiles.empty?
57
- @config.custom_profiles.map { |profile| "-p #{profile}" }.join(' ') + ' '
61
+
62
+ profiles = @config.custom_profiles.map { |profile| "-p #{profile}" }.join(' ')
63
+
64
+ "#{profiles} "
58
65
  end
59
66
  end
60
67
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'shellwords'
4
+
5
+ module Cucumber
6
+ module Formatter
7
+ class CurlOptionParser
8
+ def self.parse(options)
9
+ args = Shellwords.split(options)
10
+
11
+ url = nil
12
+ http_method = 'PUT'
13
+ headers = {}
14
+
15
+ until args.empty?
16
+ arg = args.shift
17
+ case arg
18
+ when '-X', '--request'
19
+ http_method = remove_arg_for(args, arg)
20
+ when '-H'
21
+ header_arg = remove_arg_for(args, arg)
22
+ headers = headers.merge(parse_header(header_arg))
23
+ else
24
+ raise StandardError, "#{options} was not a valid curl command. Can't set url to #{arg} it is already set to #{url}" if url
25
+
26
+ url = arg
27
+ end
28
+ end
29
+ raise StandardError, "#{options} was not a valid curl command" unless url
30
+
31
+ [url, http_method, headers]
32
+ end
33
+
34
+ # TODO: [LH] -> Switch below methods to private
35
+ def self.remove_arg_for(args, arg)
36
+ return args.shift unless args.empty?
37
+
38
+ raise StandardError, "Missing argument for #{arg}"
39
+ end
40
+
41
+ def self.parse_header(header_arg)
42
+ parts = header_arg.split(':', 2)
43
+ raise StandardError, "#{header_arg} was not a valid header" unless parts.length == 2
44
+
45
+ { parts[0].strip => parts[1].strip }
46
+ end
47
+ end
48
+ end
49
+ end
@@ -4,6 +4,7 @@ module Cucumber
4
4
  module Formatter
5
5
  class DurationExtractor
6
6
  attr_reader :result_duration
7
+
7
8
  def initialize(result)
8
9
  @result_duration = 0
9
10
  result.describe_to(self)
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Cucumber
2
4
  module Formatter
3
5
  class TestCaseUnknownError < StandardError; end
6
+
4
7
  class TestStepUnknownError < StandardError; end
5
8
  end
6
9
  end
@@ -12,7 +12,7 @@ module Cucumber
12
12
  test_case, result = *event.attributes
13
13
  if test_case != @previous_test_case
14
14
  @previous_test_case = event.test_case
15
- Cucumber.wants_to_quit = true unless result.ok?(configuration.strict)
15
+ Cucumber.wants_to_quit = true unless result.ok?(strict: configuration.strict)
16
16
  elsif result.passed?
17
17
  Cucumber.wants_to_quit = false
18
18
  end
@@ -21,7 +21,7 @@ module Cucumber
21
21
  end
22
22
 
23
23
  def respond_to_missing?(name, include_private = false)
24
- recipients.any? { |recipient| recipient.respond_to?(name, include_private) }
24
+ recipients.any? { |recipient| recipient.respond_to?(name, include_private) } || super(name, include_private)
25
25
  end
26
26
  end
27
27
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'cucumber/formatter/io'
2
4
  require 'cucumber/html_formatter'
3
5
  require 'cucumber/formatter/message_builder'
@@ -8,7 +10,7 @@ module Cucumber
8
10
  include Io
9
11
 
10
12
  def initialize(config)
11
- @io = ensure_io(config.out_stream)
13
+ @io = ensure_io(config.out_stream, config.error_stream)
12
14
  @html_formatter = Cucumber::HTMLFormatter::Formatter.new(@io)
13
15
  @html_formatter.write_pre_message
14
16