cucumber 3.1.2 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +173 -14
  3. data/CONTRIBUTING.md +2 -18
  4. data/README.md +4 -5
  5. data/bin/cucumber +1 -1
  6. data/lib/autotest/cucumber_mixin.rb +34 -39
  7. data/lib/cucumber.rb +1 -1
  8. data/lib/cucumber/cli/configuration.rb +5 -5
  9. data/lib/cucumber/cli/main.rb +12 -12
  10. data/lib/cucumber/cli/options.rb +69 -74
  11. data/lib/cucumber/cli/profile_loader.rb +49 -26
  12. data/lib/cucumber/configuration.rb +31 -23
  13. data/lib/cucumber/constantize.rb +2 -5
  14. data/lib/cucumber/deprecate.rb +31 -7
  15. data/lib/cucumber/errors.rb +5 -7
  16. data/lib/cucumber/events.rb +13 -6
  17. data/lib/cucumber/events/envelope.rb +9 -0
  18. data/lib/cucumber/events/gherkin_source_parsed.rb +11 -0
  19. data/lib/cucumber/events/hook_test_step_created.rb +13 -0
  20. data/lib/cucumber/events/step_activated.rb +2 -1
  21. data/lib/cucumber/events/test_case_created.rb +13 -0
  22. data/lib/cucumber/events/test_case_ready.rb +12 -0
  23. data/lib/cucumber/events/test_step_created.rb +13 -0
  24. data/lib/cucumber/events/undefined_parameter_type.rb +10 -0
  25. data/lib/cucumber/file_specs.rb +6 -6
  26. data/lib/cucumber/filters.rb +1 -0
  27. data/lib/cucumber/filters/activate_steps.rb +5 -3
  28. data/lib/cucumber/filters/broadcast_test_case_ready_event.rb +12 -0
  29. data/lib/cucumber/filters/prepare_world.rb +5 -9
  30. data/lib/cucumber/filters/quit.rb +1 -3
  31. data/lib/cucumber/filters/tag_limits/verifier.rb +2 -4
  32. data/lib/cucumber/formatter/ansicolor.rb +40 -45
  33. data/lib/cucumber/formatter/ast_lookup.rb +165 -0
  34. data/lib/cucumber/formatter/backtrace_filter.rb +9 -8
  35. data/lib/cucumber/formatter/console.rb +58 -66
  36. data/lib/cucumber/formatter/console_counts.rb +4 -9
  37. data/lib/cucumber/formatter/console_issues.rb +6 -3
  38. data/lib/cucumber/formatter/duration.rb +1 -1
  39. data/lib/cucumber/formatter/duration_extractor.rb +3 -1
  40. data/lib/cucumber/formatter/errors.rb +6 -0
  41. data/lib/cucumber/formatter/fanout.rb +2 -0
  42. data/lib/cucumber/formatter/html.rb +11 -598
  43. data/lib/cucumber/formatter/http_io.rb +146 -0
  44. data/lib/cucumber/formatter/ignore_missing_messages.rb +1 -1
  45. data/lib/cucumber/formatter/interceptor.rb +8 -28
  46. data/lib/cucumber/formatter/io.rb +17 -11
  47. data/lib/cucumber/formatter/json.rb +101 -109
  48. data/lib/cucumber/formatter/junit.rb +56 -56
  49. data/lib/cucumber/formatter/message.rb +22 -0
  50. data/lib/cucumber/formatter/message_builder.rb +255 -0
  51. data/lib/cucumber/formatter/pretty.rb +359 -153
  52. data/lib/cucumber/formatter/progress.rb +30 -32
  53. data/lib/cucumber/formatter/query/hook_by_test_step.rb +31 -0
  54. data/lib/cucumber/formatter/query/pickle_by_test.rb +26 -0
  55. data/lib/cucumber/formatter/query/pickle_step_by_test_step.rb +26 -0
  56. data/lib/cucumber/formatter/query/step_definitions_by_test_step.rb +40 -0
  57. data/lib/cucumber/formatter/query/test_case_started_by_test_case.rb +40 -0
  58. data/lib/cucumber/formatter/rerun.rb +22 -4
  59. data/lib/cucumber/formatter/stepdefs.rb +1 -2
  60. data/lib/cucumber/formatter/steps.rb +2 -3
  61. data/lib/cucumber/formatter/summary.rb +16 -8
  62. data/lib/cucumber/formatter/unicode.rb +15 -17
  63. data/lib/cucumber/formatter/usage.rb +11 -10
  64. data/lib/cucumber/gherkin/data_table_parser.rb +17 -6
  65. data/lib/cucumber/gherkin/formatter/ansi_escapes.rb +13 -17
  66. data/lib/cucumber/gherkin/formatter/escaping.rb +2 -2
  67. data/lib/cucumber/gherkin/steps_parser.rb +17 -8
  68. data/lib/cucumber/glue/dsl.rb +1 -1
  69. data/lib/cucumber/glue/hook.rb +34 -11
  70. data/lib/cucumber/glue/invoke_in_world.rb +13 -18
  71. data/lib/cucumber/glue/proto_world.rb +42 -33
  72. data/lib/cucumber/glue/registry_and_more.rb +42 -12
  73. data/lib/cucumber/glue/snippet.rb +23 -22
  74. data/lib/cucumber/glue/step_definition.rb +42 -19
  75. data/lib/cucumber/glue/world_factory.rb +1 -1
  76. data/lib/cucumber/hooks.rb +11 -11
  77. data/lib/cucumber/multiline_argument.rb +4 -6
  78. data/lib/cucumber/multiline_argument/data_table.rb +97 -64
  79. data/lib/cucumber/multiline_argument/data_table/diff_matrices.rb +1 -1
  80. data/lib/cucumber/multiline_argument/doc_string.rb +1 -1
  81. data/lib/cucumber/platform.rb +3 -3
  82. data/lib/cucumber/rake/task.rb +16 -16
  83. data/lib/cucumber/rspec/disable_option_parser.rb +9 -8
  84. data/lib/cucumber/running_test_case.rb +2 -53
  85. data/lib/cucumber/runtime.rb +54 -58
  86. data/lib/cucumber/runtime/after_hooks.rb +8 -4
  87. data/lib/cucumber/runtime/before_hooks.rb +8 -4
  88. data/lib/cucumber/runtime/for_programming_languages.rb +4 -2
  89. data/lib/cucumber/runtime/step_hooks.rb +3 -2
  90. data/lib/cucumber/runtime/support_code.rb +13 -15
  91. data/lib/cucumber/runtime/user_interface.rb +6 -16
  92. data/lib/cucumber/step_definition_light.rb +4 -3
  93. data/lib/cucumber/step_definitions.rb +2 -2
  94. data/lib/cucumber/step_match.rb +12 -11
  95. data/lib/cucumber/step_match_search.rb +2 -1
  96. data/lib/cucumber/term/ansicolor.rb +9 -9
  97. data/lib/cucumber/version +1 -1
  98. metadata +224 -82
  99. data/lib/cucumber/events/gherkin_source_parsed.rb~ +0 -14
  100. data/lib/cucumber/formatter/ast_lookup.rb~ +0 -9
  101. data/lib/cucumber/formatter/cucumber.css +0 -286
  102. data/lib/cucumber/formatter/cucumber.sass +0 -247
  103. data/lib/cucumber/formatter/hook_query_visitor.rb +0 -42
  104. data/lib/cucumber/formatter/html_builder.rb +0 -121
  105. data/lib/cucumber/formatter/inline-js.js +0 -30
  106. data/lib/cucumber/formatter/jquery-min.js +0 -154
  107. data/lib/cucumber/formatter/json_pretty.rb +0 -11
  108. data/lib/cucumber/formatter/legacy_api/adapter.rb +0 -1028
  109. data/lib/cucumber/formatter/legacy_api/ast.rb +0 -394
  110. data/lib/cucumber/formatter/legacy_api/results.rb +0 -50
  111. data/lib/cucumber/formatter/legacy_api/runtime_facade.rb +0 -32
  112. data/lib/cucumber/step_argument.rb +0 -25
@@ -8,9 +8,7 @@ module Cucumber
8
8
  end
9
9
 
10
10
  def test_case(test_case)
11
- unless Cucumber.wants_to_quit
12
- test_case.describe_to @receiver
13
- end
11
+ test_case.describe_to @receiver unless Cucumber.wants_to_quit
14
12
  self
15
13
  end
16
14
 
@@ -17,10 +17,8 @@ module Cucumber
17
17
 
18
18
  def collect_breaches(test_case_index)
19
19
  tag_limits.reduce([]) do |breaches, (tag_name, limit)|
20
- breaches.tap do |breaches|
21
- if test_case_index.count_by_tag_name(tag_name) > limit
22
- breaches << Breach.new(tag_name, limit, test_case_index.locations_of_tag_name(tag_name))
23
- end
20
+ breaches.tap do |breach|
21
+ breach << Breach.new(tag_name, limit, test_case_index.locations_of_tag_name(tag_name)) if test_case_index.count_by_tag_name(tag_name) > limit
24
22
  end
25
23
  end
26
24
  end
@@ -55,20 +55,18 @@ module Cucumber
55
55
  include Cucumber::Term::ANSIColor
56
56
 
57
57
  ALIASES = Hash.new do |h, k|
58
- if k.to_s =~ /(.*)_param/
59
- h[$1] + ',bold'
60
- end
61
- end.merge({
62
- 'undefined' => 'yellow',
63
- 'pending' => 'yellow',
64
- 'flaky' => 'yellow',
65
- 'failed' => 'red',
66
- 'passed' => 'green',
67
- 'outline' => 'cyan',
68
- 'skipped' => 'cyan',
69
- 'comment' => 'grey',
70
- 'tag' => 'cyan'
71
- })
58
+ h[Regexp.last_match(1)] + ',bold' if k.to_s =~ /(.*)_param/
59
+ end.merge(
60
+ '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'
69
+ )
72
70
 
73
71
  if ENV['CUCUMBER_COLORS'] # Example: export CUCUMBER_COLORS="passed=red:failed=yellow"
74
72
  ENV['CUCUMBER_COLORS'].split(':').each do |pair|
@@ -89,45 +87,42 @@ module Cucumber
89
87
  # red(bold(string, &proc)) + red
90
88
  # end
91
89
  ALIASES.each_key do |method_name|
92
- unless method_name =~ /.*_param/
93
- code = <<-EOF
90
+ next if method_name =~ /.*_param/
91
+ code = <<-COLOR
94
92
  def #{method_name}(string=nil, &proc)
95
- #{ALIASES[method_name].split(",").join("(") + "(string, &proc" + ")" * ALIASES[method_name].split(",").length}
93
+ #{ALIASES[method_name].split(',').join('(') + '(string, &proc' + ')' * ALIASES[method_name].split(',').length}
96
94
  end
97
95
  # This resets the colour to the non-param colour
98
96
  def #{method_name}_param(string=nil, &proc)
99
- #{ALIASES[method_name + '_param'].split(",").join("(") + "(string, &proc" + ")" * ALIASES[method_name + '_param'].split(",").length} + #{ALIASES[method_name].split(",").join(' + ')}
97
+ #{ALIASES[method_name + '_param'].split(',').join('(') + '(string, &proc' + ')' * ALIASES[method_name + '_param'].split(',').length} + #{ALIASES[method_name].split(',').join(' + ')}
100
98
  end
101
- EOF
102
- eval(code)
103
- end
99
+ COLOR
100
+ eval(code) # rubocop:disable Security/Eval
104
101
  end
105
102
 
106
103
  def self.define_grey #:nodoc:
107
- begin
108
- gem 'genki-ruby-terminfo'
109
- require 'terminfo'
110
- case TermInfo.default_object.tigetnum('colors')
111
- when 0
112
- raise "Your terminal doesn't support colours."
113
- when 1
114
- ::Cucumber::Term::ANSIColor.coloring = false
115
- alias grey white
116
- when 2..8
117
- alias grey white
118
- else
119
- define_real_grey
120
- end
121
- rescue Exception => e
122
- if e.class.name == 'TermInfo::TermInfoError'
123
- STDERR.puts '*** WARNING ***'
124
- STDERR.puts "You have the genki-ruby-terminfo gem installed, but you haven't set your TERM variable."
125
- STDERR.puts 'Try setting it to TERM=xterm-256color to get grey colour in output.'
126
- STDERR.puts "\n"
127
- alias grey white
128
- else
129
- define_real_grey
130
- end
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
131
126
  end
132
127
  end
133
128
 
@@ -0,0 +1,165 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cucumber
4
+ module Formatter
5
+ class AstLookup
6
+ def initialize(config)
7
+ @gherkin_documents = {}
8
+ @test_case_lookups = {}
9
+ @test_step_lookups = {}
10
+ @step_keyword_lookups = {}
11
+ config.on_event :gherkin_source_parsed, &method(:on_gherkin_source_parsed)
12
+ end
13
+
14
+ def on_gherkin_source_parsed(event)
15
+ @gherkin_documents[event.gherkin_document.uri] = event.gherkin_document
16
+ end
17
+
18
+ def gherkin_document(uri)
19
+ @gherkin_documents[uri]
20
+ end
21
+
22
+ def scenario_source(test_case)
23
+ uri = test_case.location.file
24
+ @test_case_lookups[uri] ||= TestCaseLookupBuilder.new(gherkin_document(uri)).lookup_hash
25
+ @test_case_lookups[uri][test_case.location.lines.max]
26
+ end
27
+
28
+ def step_source(test_step)
29
+ uri = test_step.location.file
30
+ @test_step_lookups[uri] ||= TestStepLookupBuilder.new(gherkin_document(uri)).lookup_hash
31
+ @test_step_lookups[uri][test_step.location.lines.min]
32
+ end
33
+
34
+ def snippet_step_keyword(test_step)
35
+ uri = test_step.location.file
36
+ document = gherkin_document(uri)
37
+ dialect = ::Gherkin::Dialect.for(document.feature.language)
38
+ given_when_then_keywords = [dialect.given_keywords, dialect.when_keywords, dialect.then_keywords].flatten.uniq.reject { |kw| kw == '* ' }
39
+ keyword_lookup = step_keyword_lookup(uri)
40
+ keyword = nil
41
+ node = keyword_lookup[test_step.location.lines.min]
42
+ while keyword.nil?
43
+ if given_when_then_keywords.include?(node.keyword)
44
+ keyword = node.keyword
45
+ break
46
+ end
47
+ break if node.previous_node.nil?
48
+ node = node.previous_node
49
+ end
50
+ keyword = dialect.given_keywords.reject { |kw| kw == '* ' }[0] if keyword.nil?
51
+ keyword = Cucumber::Gherkin::I18n.code_keyword_for(keyword)
52
+ keyword
53
+ end
54
+
55
+ ScenarioSource = Struct.new(:type, :scenario)
56
+
57
+ ScenarioOutlineSource = Struct.new(:type, :scenario_outline, :examples, :row)
58
+
59
+ StepSource = Struct.new(:type, :step)
60
+
61
+ private
62
+
63
+ def step_keyword_lookup(uri)
64
+ @step_keyword_lookups[uri] ||= KeywordLookupBuilder.new(gherkin_document(uri)).lookup_hash
65
+ end
66
+
67
+ class TestCaseLookupBuilder
68
+ attr_reader :lookup_hash
69
+
70
+ def initialize(gherkin_document)
71
+ @lookup_hash = {}
72
+ process_scenario_container(gherkin_document.feature)
73
+ end
74
+
75
+ private
76
+
77
+ def process_scenario_container(container)
78
+ container.children.each do |child|
79
+ if child.respond_to?(:rule) && child.rule
80
+ process_scenario_container(child.rule)
81
+ elsif child.respond_to?(:scenario) && child.scenario
82
+ process_scenario(child)
83
+ end
84
+ end
85
+ end
86
+
87
+ def process_scenario(child)
88
+ if child.scenario.examples.empty?
89
+ @lookup_hash[child.scenario.location.line] = ScenarioSource.new(:Scenario, child.scenario)
90
+ else
91
+ child.scenario.examples.each do |examples|
92
+ examples.table_body.each do |row|
93
+ @lookup_hash[row.location.line] = ScenarioOutlineSource.new(:ScenarioOutline, child.scenario, examples, row)
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ class TestStepLookupBuilder
101
+ attr_reader :lookup_hash
102
+
103
+ def initialize(gherkin_document)
104
+ @lookup_hash = {}
105
+ process_scenario_container(gherkin_document.feature)
106
+ end
107
+
108
+ private
109
+
110
+ def process_scenario_container(container)
111
+ container.children.each do |child|
112
+ if child.respond_to?(:rule) && child.rule
113
+ process_scenario_container(child.rule)
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
118
+ elsif !child.background.nil?
119
+ child.background.steps.each do |step|
120
+ @lookup_hash[step.location.line] = StepSource.new(:Step, step)
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ KeywordSearchNode = Struct.new(:keyword, :previous_node)
128
+
129
+ class KeywordLookupBuilder
130
+ attr_reader :lookup_hash
131
+
132
+ def initialize(gherkin_document)
133
+ @lookup_hash = {}
134
+ process_scenario_container(gherkin_document.feature, nil)
135
+ end
136
+
137
+ private
138
+
139
+ # rubocop:disable Metrics/PerceivedComplexity
140
+ def process_scenario_container(container, original_previous_node)
141
+ container.children.each do |child|
142
+ previous_node = original_previous_node
143
+ if child.respond_to?(:rule) && child.rule
144
+ process_scenario_container(child.rule, original_previous_node)
145
+ elsif child.respond_to?(:scenario) && child.scenario
146
+ child.scenario.steps.each do |step|
147
+ node = KeywordSearchNode.new(step.keyword, previous_node)
148
+ @lookup_hash[step.location.line] = node
149
+ previous_node = node
150
+ end
151
+ elsif child.respond_to?(:background) && child.background
152
+ child.background.steps.each do |step|
153
+ node = KeywordSearchNode.new(step.keyword, previous_node)
154
+ @lookup_hash[step.location.line] = node
155
+ previous_node = node
156
+ original_previous_node = previous_node
157
+ end
158
+ end
159
+ end
160
+ end
161
+ # rubocop:enable Metrics/PerceivedComplexity
162
+ end
163
+ end
164
+ end
165
+ end
@@ -4,22 +4,23 @@ require 'cucumber/platform'
4
4
 
5
5
  module Cucumber
6
6
  module Formatter
7
- @backtrace_filters = %w(
7
+ @backtrace_filters = %w[
8
8
  /vendor/rails
9
9
  lib/cucumber
10
10
  bin/cucumber:
11
11
  lib/rspec
12
12
  gems/
13
+ site_ruby/
13
14
  minitest
14
15
  test/unit
15
16
  .gem/ruby
16
- lib/ruby/
17
17
  bin/bundle
18
- )
18
+ ]
19
19
 
20
- if ::Cucumber::JRUBY
21
- @backtrace_filters << 'org/jruby/'
22
- end
20
+ @backtrace_filters << RbConfig::CONFIG['rubyarchdir'] if RbConfig::CONFIG['rubyarchdir']
21
+ @backtrace_filters << RbConfig::CONFIG['rubylibdir'] if RbConfig::CONFIG['rubylibdir']
22
+
23
+ @backtrace_filters << 'org/jruby/' if ::Cucumber::JRUBY
23
24
 
24
25
  BACKTRACE_FILTER_PATTERNS = Regexp.new(@backtrace_filters.join('|'))
25
26
 
@@ -31,7 +32,7 @@ module Cucumber
31
32
  def exception
32
33
  return @exception if ::Cucumber.use_full_backtrace
33
34
 
34
- pwd_pattern = /#{::Regexp.escape(::Dir.pwd)}\//m
35
+ pwd_pattern = /#{::Regexp.escape(::Dir.pwd)}\//m # rubocop:disable Style/RegexpLiteral
35
36
  backtrace = @exception.backtrace.map { |line| line.gsub(pwd_pattern, './') }
36
37
 
37
38
  filtered = (backtrace || []).reject do |line|
@@ -41,7 +42,7 @@ module Cucumber
41
42
  if ::ENV['CUCUMBER_TRUNCATE_OUTPUT']
42
43
  # Strip off file locations
43
44
  filtered = filtered.map do |line|
44
- line =~ /(.*):in `/ ? $1 : line
45
+ line =~ /(.*):in `/ ? Regexp.last_match(1) : line
45
46
  end
46
47
  end
47
48
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # rubocop:disable Metrics/ModuleLength
4
+
3
5
  require 'cucumber/formatter/ansicolor'
4
6
  require 'cucumber/formatter/duration'
5
7
  require 'cucumber/gherkin/i18n'
@@ -46,7 +48,7 @@ module Cucumber
46
48
  def format_string(o, status)
47
49
  fmt = format_for(status)
48
50
  o.to_s.split("\n").map do |line|
49
- if Proc === fmt
51
+ if Proc == fmt.class
50
52
  fmt.call(line)
51
53
  else
52
54
  fmt % line
@@ -54,10 +56,6 @@ module Cucumber
54
56
  end.join("\n")
55
57
  end
56
58
 
57
- def print_steps(status)
58
- print_elements(runtime.steps(status), status, 'steps')
59
- end
60
-
61
59
  def print_elements(elements, status, kind)
62
60
  return if elements.empty?
63
61
 
@@ -109,28 +107,32 @@ module Cucumber
109
107
  end
110
108
 
111
109
  # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/10655
112
- def linebreaks(s, max)
113
- return s unless max && max > 0
114
- s.gsub(/.{1,#{max}}(?:\s|\Z)/) { ($& + 5.chr).gsub(/\n\005/, "\n").gsub(/\005/, "\n") }.rstrip
110
+ 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
115
113
  end
116
114
 
117
- def collect_snippet_data(test_step, result)
115
+ def collect_snippet_data(test_step, ast_lookup)
118
116
  # collect snippet data for undefined steps
119
- return if hook?(test_step)
120
- keyword = test_step.source.last.actual_keyword(@previous_step_keyword)
121
- @previous_step_keyword = keyword
122
- return unless result.undefined?
123
- @snippets_input << Console::SnippetData.new(keyword, test_step.source.last)
117
+ keyword = ast_lookup.snippet_step_keyword(test_step)
118
+ @snippets_input << Console::SnippetData.new(keyword, test_step)
119
+ end
120
+
121
+ def collect_undefined_parameter_type_names(undefined_parameter_type)
122
+ @undefined_parameter_types << undefined_parameter_type.type_name
124
123
  end
125
124
 
126
125
  def print_snippets(options)
127
126
  return unless options[:snippets]
128
- return if runtime.steps(:undefined).empty?
129
127
 
130
128
  snippet_text_proc = lambda do |step_keyword, step_name, multiline_arg|
131
- runtime.snippet_text(step_keyword, step_name, multiline_arg)
129
+ snippet_text(step_keyword, step_name, multiline_arg)
130
+ end
131
+ do_print_snippets(snippet_text_proc) unless @snippets_input.empty?
132
+
133
+ @undefined_parameter_types.map do |type_name|
134
+ do_print_undefined_parameter_type_snippet(type_name)
132
135
  end
133
- do_print_snippets(snippet_text_proc)
134
136
  end
135
137
 
136
138
  def do_print_snippets(snippet_text_proc)
@@ -146,10 +148,14 @@ module Cucumber
146
148
  @io.flush
147
149
  end
148
150
 
149
- def print_passing_wip(options)
150
- return unless options[:wip]
151
- passed_messages = element_messages(runtime.scenarios(:passed), :passed)
152
- do_print_passing_wip(passed_messages)
151
+ def print_passing_wip(config, passed_test_cases, ast_lookup)
152
+ return unless config.wip?
153
+ messages = passed_test_cases.map do |test_case|
154
+ scenario_source = ast_lookup.scenario_source(test_case)
155
+ keyword = scenario_source.type == :Scenario ? scenario_source.scenario.keyword : scenario_source.scenario_outline.keyword
156
+ linebreaks("#{test_case.location.on_line(test_case.location.lines.max)}:in `#{keyword}: #{test_case.name}'", ENV['CUCUMBER_TRUNCATE_OUTPUT'].to_i)
157
+ end
158
+ do_print_passing_wip(messages)
153
159
  end
154
160
 
155
161
  def do_print_passing_wip(passed_messages)
@@ -161,59 +167,47 @@ module Cucumber
161
167
  end
162
168
  end
163
169
 
164
- def embed(file, mime_type, label)
165
- # no-op
166
- end
167
-
168
- # define @delayed_messages = [] in your Formatter if you want to
169
- # activate this feature
170
- def puts(*messages)
171
- if @delayed_messages
172
- @delayed_messages += messages
173
- else
174
- if @io
175
- @io.puts
176
- messages.each do |message|
177
- @io.puts(format_string(message, :tag))
178
- end
179
- @io.flush
180
- end
181
- end
182
- end
183
-
184
- def print_messages
185
- @delayed_messages.each { |message| print_message(message) }
186
- empty_messages
187
- end
188
-
189
- def print_table_row_messages
190
- return if @delayed_messages.empty?
191
- @io.print(format_string(@delayed_messages.join(', '), :tag).indent(2))
192
- @io.flush
193
- empty_messages
194
- end
195
-
196
- def print_message(message)
197
- @io.puts(format_string(message, :tag).indent(@indent))
170
+ def attach(src, media_type)
171
+ return unless media_type == 'text/x.cucumber.log+plain'
172
+ return unless @io
173
+ @io.puts
174
+ @io.puts(format_string(src, :tag))
198
175
  @io.flush
199
176
  end
200
177
 
201
- def empty_messages
202
- @delayed_messages = []
203
- end
204
-
205
178
  def print_profile_information
206
179
  return if @options[:skip_profile_information] || @options[:profiles].nil? || @options[:profiles].empty?
207
180
  do_print_profile_information(@options[:profiles])
208
181
  end
209
182
 
210
183
  def do_print_profile_information(profiles)
211
- profiles_sentence = profiles.size == 1 ? profiles.first :
212
- "#{profiles[0...-1].join(', ')} and #{profiles.last}"
184
+ profiles_sentence = if profiles.size == 1
185
+ profiles.first
186
+ else
187
+ "#{profiles[0...-1].join(', ')} and #{profiles.last}"
188
+ end
213
189
 
214
190
  @io.puts "Using the #{profiles_sentence} profile#{'s' if profiles.size > 1}..."
215
191
  end
216
192
 
193
+ def do_print_undefined_parameter_type_snippet(type_name)
194
+ camelized = type_name.split(/_|-/).collect(&:capitalize).join
195
+
196
+ @io.puts [
197
+ "The parameter #{type_name} is not defined. You can define a new one with:",
198
+ '',
199
+ 'ParameterType(',
200
+ " name: '#{type_name}',",
201
+ ' regexp: /some regexp here/,',
202
+ " type: #{camelized},",
203
+ ' # The transformer takes as many arguments as there are capture groups in the regexp,',
204
+ ' # or just one if there are none.',
205
+ " transformer: ->(s) { #{camelized}.new(s) }",
206
+ ')',
207
+ ''
208
+ ].join("\n")
209
+ end
210
+
217
211
  private
218
212
 
219
213
  FORMATS = Hash.new { |hash, format| hash[format] = method(format).to_proc }
@@ -225,10 +219,6 @@ module Cucumber
225
219
  fmt
226
220
  end
227
221
 
228
- def hook?(test_step)
229
- not test_step.source.last.respond_to?(:actual_keyword)
230
- end
231
-
232
222
  def element_messages(elements, status)
233
223
  elements.map do |element|
234
224
  if status == :failed
@@ -249,9 +239,11 @@ module Cucumber
249
239
  class SnippetData
250
240
  attr_reader :actual_keyword, :step
251
241
  def initialize(actual_keyword, step)
252
- @actual_keyword, @step = actual_keyword, step
242
+ @actual_keyword = actual_keyword
243
+ @step = step
253
244
  end
254
245
  end
255
246
  end
256
247
  end
257
248
  end
249
+ # rubocop:enable Metrics/ModuleLength