cucumber 3.1.2 → 8.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 (125) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1880 -1146
  3. data/CONTRIBUTING.md +220 -61
  4. data/README.md +143 -22
  5. data/bin/cucumber +1 -1
  6. data/lib/autotest/cucumber_mixin.rb +49 -53
  7. data/lib/autotest/discover.rb +3 -2
  8. data/lib/cucumber/cli/configuration.rb +32 -7
  9. data/lib/cucumber/cli/main.rb +16 -15
  10. data/lib/cucumber/cli/options.rb +111 -79
  11. data/lib/cucumber/cli/profile_loader.rb +45 -26
  12. data/lib/cucumber/cli/rerun_file.rb +1 -1
  13. data/lib/cucumber/configuration.rb +47 -31
  14. data/lib/cucumber/constantize.rb +3 -6
  15. data/lib/cucumber/deprecate.rb +32 -7
  16. data/lib/cucumber/errors.rb +5 -7
  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 +12 -0
  20. data/lib/cucumber/events/step_activated.rb +0 -5
  21. data/lib/cucumber/events/step_definition_registered.rb +0 -5
  22. data/lib/cucumber/events/test_case_created.rb +12 -0
  23. data/lib/cucumber/events/test_case_ready.rb +12 -0
  24. data/lib/cucumber/events/test_run_finished.rb +2 -1
  25. data/lib/cucumber/events/test_step_created.rb +12 -0
  26. data/lib/cucumber/events/undefined_parameter_type.rb +9 -0
  27. data/lib/cucumber/events.rb +15 -8
  28. data/lib/cucumber/file_specs.rb +8 -7
  29. data/lib/cucumber/filters/activate_steps.rb +6 -3
  30. data/lib/cucumber/filters/broadcast_test_case_ready_event.rb +12 -0
  31. data/lib/cucumber/filters/prepare_world.rb +5 -9
  32. data/lib/cucumber/filters/quit.rb +1 -3
  33. data/lib/cucumber/filters/tag_limits/verifier.rb +3 -7
  34. data/lib/cucumber/filters/tag_limits.rb +1 -3
  35. data/lib/cucumber/filters.rb +1 -0
  36. data/lib/cucumber/formatter/ansicolor.rb +74 -86
  37. data/lib/cucumber/formatter/ast_lookup.rb +163 -0
  38. data/lib/cucumber/formatter/backtrace_filter.rb +10 -7
  39. data/lib/cucumber/formatter/console.rb +76 -68
  40. data/lib/cucumber/formatter/console_counts.rb +4 -9
  41. data/lib/cucumber/formatter/console_issues.rb +12 -4
  42. data/lib/cucumber/formatter/duration.rb +1 -1
  43. data/lib/cucumber/formatter/duration_extractor.rb +4 -1
  44. data/lib/cucumber/formatter/errors.rb +7 -0
  45. data/lib/cucumber/formatter/fanout.rb +3 -1
  46. data/lib/cucumber/formatter/html.rb +11 -598
  47. data/lib/cucumber/formatter/http_io.rb +152 -0
  48. data/lib/cucumber/formatter/ignore_missing_messages.rb +2 -2
  49. data/lib/cucumber/formatter/interceptor.rb +11 -30
  50. data/lib/cucumber/formatter/io.rb +57 -13
  51. data/lib/cucumber/formatter/json.rb +119 -124
  52. data/lib/cucumber/formatter/junit.rb +75 -55
  53. data/lib/cucumber/formatter/message.rb +23 -0
  54. data/lib/cucumber/formatter/message_builder.rb +256 -0
  55. data/lib/cucumber/formatter/pretty.rb +370 -153
  56. data/lib/cucumber/formatter/progress.rb +31 -32
  57. data/lib/cucumber/formatter/publish_banner_printer.rb +77 -0
  58. data/lib/cucumber/formatter/query/hook_by_test_step.rb +32 -0
  59. data/lib/cucumber/formatter/query/pickle_by_test.rb +26 -0
  60. data/lib/cucumber/formatter/query/pickle_step_by_test_step.rb +26 -0
  61. data/lib/cucumber/formatter/query/step_definitions_by_test_step.rb +40 -0
  62. data/lib/cucumber/formatter/query/test_case_started_by_test_case.rb +42 -0
  63. data/lib/cucumber/formatter/rerun.rb +24 -4
  64. data/lib/cucumber/formatter/stepdefs.rb +1 -2
  65. data/lib/cucumber/formatter/steps.rb +8 -6
  66. data/lib/cucumber/formatter/summary.rb +17 -8
  67. data/lib/cucumber/formatter/unicode.rb +18 -20
  68. data/lib/cucumber/formatter/url_reporter.rb +17 -0
  69. data/lib/cucumber/formatter/usage.rb +18 -15
  70. data/lib/cucumber/gherkin/data_table_parser.rb +18 -6
  71. data/lib/cucumber/gherkin/formatter/ansi_escapes.rb +14 -18
  72. data/lib/cucumber/gherkin/formatter/escaping.rb +2 -2
  73. data/lib/cucumber/gherkin/steps_parser.rb +17 -8
  74. data/lib/cucumber/glue/dsl.rb +29 -15
  75. data/lib/cucumber/glue/hook.rb +37 -11
  76. data/lib/cucumber/glue/invoke_in_world.rb +17 -22
  77. data/lib/cucumber/glue/proto_world.rb +47 -53
  78. data/lib/cucumber/glue/registry_and_more.rb +62 -17
  79. data/lib/cucumber/glue/registry_wrapper.rb +31 -0
  80. data/lib/cucumber/glue/snippet.rb +23 -22
  81. data/lib/cucumber/glue/step_definition.rb +48 -23
  82. data/lib/cucumber/glue/world_factory.rb +1 -1
  83. data/lib/cucumber/hooks.rb +12 -11
  84. data/lib/cucumber/multiline_argument/data_table/diff_matrices.rb +4 -3
  85. data/lib/cucumber/multiline_argument/data_table.rb +143 -123
  86. data/lib/cucumber/multiline_argument/doc_string.rb +1 -1
  87. data/lib/cucumber/multiline_argument.rb +4 -6
  88. data/lib/cucumber/platform.rb +5 -5
  89. data/lib/cucumber/rake/task.rb +34 -25
  90. data/lib/cucumber/rspec/disable_option_parser.rb +15 -11
  91. data/lib/cucumber/rspec/doubles.rb +3 -5
  92. data/lib/cucumber/running_test_case.rb +3 -53
  93. data/lib/cucumber/runtime/after_hooks.rb +8 -4
  94. data/lib/cucumber/runtime/before_hooks.rb +8 -4
  95. data/lib/cucumber/runtime/for_programming_languages.rb +4 -2
  96. data/lib/cucumber/runtime/meta_message_builder.rb +106 -0
  97. data/lib/cucumber/runtime/step_hooks.rb +6 -2
  98. data/lib/cucumber/runtime/support_code.rb +16 -15
  99. data/lib/cucumber/runtime/user_interface.rb +10 -19
  100. data/lib/cucumber/runtime.rb +78 -76
  101. data/lib/cucumber/step_definition_light.rb +4 -3
  102. data/lib/cucumber/step_definitions.rb +2 -2
  103. data/lib/cucumber/step_match.rb +17 -20
  104. data/lib/cucumber/step_match_search.rb +5 -3
  105. data/lib/cucumber/term/ansicolor.rb +72 -48
  106. data/lib/cucumber/term/banner.rb +57 -0
  107. data/lib/cucumber/version +1 -1
  108. data/lib/cucumber.rb +3 -2
  109. data/lib/simplecov_setup.rb +1 -1
  110. metadata +279 -81
  111. data/lib/cucumber/core_ext/string.rb +0 -11
  112. data/lib/cucumber/events/gherkin_source_parsed.rb~ +0 -14
  113. data/lib/cucumber/formatter/ast_lookup.rb~ +0 -9
  114. data/lib/cucumber/formatter/cucumber.css +0 -286
  115. data/lib/cucumber/formatter/cucumber.sass +0 -247
  116. data/lib/cucumber/formatter/hook_query_visitor.rb +0 -42
  117. data/lib/cucumber/formatter/html_builder.rb +0 -121
  118. data/lib/cucumber/formatter/inline-js.js +0 -30
  119. data/lib/cucumber/formatter/jquery-min.js +0 -154
  120. data/lib/cucumber/formatter/json_pretty.rb +0 -11
  121. data/lib/cucumber/formatter/legacy_api/adapter.rb +0 -1028
  122. data/lib/cucumber/formatter/legacy_api/ast.rb +0 -394
  123. data/lib/cucumber/formatter/legacy_api/results.rb +0 -50
  124. data/lib/cucumber/formatter/legacy_api/runtime_facade.rb +0 -32
  125. data/lib/cucumber/step_argument.rb +0 -25
@@ -4,6 +4,7 @@ require 'cucumber/cucumber_expressions/parameter_type_registry'
4
4
  require 'cucumber/cucumber_expressions/cucumber_expression'
5
5
  require 'cucumber/cucumber_expressions/regular_expression'
6
6
  require 'cucumber/cucumber_expressions/cucumber_expression_generator'
7
+ require 'cucumber/deprecate'
7
8
  require 'cucumber/glue/dsl'
8
9
  require 'cucumber/glue/snippet'
9
10
  require 'cucumber/glue/hook'
@@ -28,7 +29,7 @@ module Cucumber
28
29
  # Raised if there are 2 or more World blocks.
29
30
  class MultipleWorld < StandardError
30
31
  def initialize(first_proc, second_proc)
31
- message = String.new
32
+ message = String.new # rubocop:disable Style/EmptyLiteral
32
33
  message << "You can only pass a proc to #World once, but it's happening\n"
33
34
  message << "in 2 places:\n\n"
34
35
  message << Glue.backtrace_line(first_proc, 'World') << "\n"
@@ -53,7 +54,8 @@ module Cucumber
53
54
  end
54
55
 
55
56
  def initialize(runtime, configuration)
56
- @runtime, @configuration = runtime, configuration
57
+ @runtime = runtime
58
+ @configuration = configuration
57
59
  @step_definitions = []
58
60
  Glue::Dsl.rb_language = self
59
61
  @world_proc = @world_modules = nil
@@ -63,32 +65,42 @@ module Cucumber
63
65
  end
64
66
 
65
67
  def step_matches(name_to_match)
66
- @step_definitions.reduce([]) do |result, step_definition|
68
+ @step_definitions.each_with_object([]) do |step_definition, result|
67
69
  if (arguments = step_definition.arguments_from(name_to_match))
68
70
  result << StepMatch.new(step_definition, name_to_match, arguments)
69
71
  end
70
- result
71
72
  end
72
73
  end
73
74
 
74
- def register_rb_hook(phase, tag_expressions, proc)
75
- add_hook(phase, Hook.new(self, tag_expressions, proc))
75
+ def register_rb_hook(phase, tag_expressions, proc, name: nil)
76
+ hook = add_hook(phase, Hook.new(@configuration.id_generator.new_id, self, tag_expressions, proc, name: name))
77
+ @configuration.notify :envelope, hook.to_envelope
78
+ hook
76
79
  end
77
80
 
78
81
  def define_parameter_type(parameter_type)
82
+ @configuration.notify :envelope, parameter_type_envelope(parameter_type)
83
+
79
84
  @parameter_type_registry.define_parameter_type(parameter_type)
80
85
  end
81
86
 
82
87
  def register_rb_step_definition(string_or_regexp, proc_or_sym, options)
83
- step_definition = StepDefinition.new(self, string_or_regexp, proc_or_sym, options)
88
+ step_definition = StepDefinition.new(@configuration.id_generator.new_id, self, string_or_regexp, proc_or_sym, options)
84
89
  @step_definitions << step_definition
85
90
  @configuration.notify :step_definition_registered, step_definition
91
+ @configuration.notify :envelope, step_definition.to_envelope
86
92
  step_definition
93
+ rescue Cucumber::CucumberExpressions::UndefinedParameterTypeError => e
94
+ # TODO: add a way to extract the parameter type directly from the error.
95
+ type_name = e.message.match(/^Undefined parameter type ['|{](.*)['|}].?$/)[1]
96
+
97
+ @configuration.notify :undefined_parameter_type, type_name, string_or_regexp
87
98
  end
88
99
 
89
100
  def build_rb_world_factory(world_modules, namespaced_world_modules, proc)
90
101
  if proc
91
102
  raise MultipleWorld.new(@world_proc, proc) if @world_proc
103
+
92
104
  @world_proc = proc
93
105
  end
94
106
  @world_modules ||= []
@@ -96,15 +108,20 @@ module Cucumber
96
108
 
97
109
  @namespaced_world_modules ||= Hash.new { |h, k| h[k] = [] }
98
110
  namespaced_world_modules.each do |namespace, world_module|
99
- unless @namespaced_world_modules[namespace].include?(world_module)
100
- @namespaced_world_modules[namespace] << world_module
101
- end
111
+ @namespaced_world_modules[namespace] << world_module unless @namespaced_world_modules[namespace].include?(world_module)
102
112
  end
103
113
  end
104
114
 
105
115
  def load_code_file(code_file)
106
116
  return unless File.extname(code_file) == '.rb'
107
- load File.expand_path(code_file) # This will cause self.add_step_definition, self.add_hook, and self.define_parameter_type to be called from Glue::Dsl
117
+
118
+ # This will cause self.add_step_definition, self.add_hook, and self.define_parameter_type to be called from Glue::Dsl
119
+
120
+ if Cucumber.use_legacy_autoloader
121
+ load File.expand_path(code_file)
122
+ else
123
+ require File.expand_path(code_file)
124
+ end
108
125
  end
109
126
 
110
127
  def begin_scenario(test_case)
@@ -119,9 +136,21 @@ module Cucumber
119
136
  @current_world = nil
120
137
  end
121
138
 
122
- def after_configuration(configuration)
123
- hooks[:after_configuration].each do |hook|
124
- hook.invoke('AfterConfiguration', configuration)
139
+ def install_plugin(configuration, registry)
140
+ hooks[:install_plugin].each do |hook|
141
+ hook.invoke('InstallPlugin', [configuration, registry])
142
+ end
143
+ end
144
+
145
+ def before_all
146
+ hooks[:before_all].each do |hook|
147
+ hook.invoke('BeforeAll', [])
148
+ end
149
+ end
150
+
151
+ def after_all
152
+ hooks[:after_all].each do |hook|
153
+ hook.invoke('AfterAll', [])
125
154
  end
126
155
  end
127
156
 
@@ -134,7 +163,7 @@ module Cucumber
134
163
  @hooks = nil
135
164
  end
136
165
 
137
- def hooks_for(phase, scenario) #:nodoc:
166
+ def hooks_for(phase, scenario) # :nodoc:
138
167
  hooks[phase.to_sym].select { |hook| scenario.accept_hook?(hook) }
139
168
  end
140
169
 
@@ -153,7 +182,8 @@ module Cucumber
153
182
  def create_expression(string_or_regexp)
154
183
  return CucumberExpressions::CucumberExpression.new(string_or_regexp, @parameter_type_registry) if string_or_regexp.is_a?(String)
155
184
  return CucumberExpressions::RegularExpression.new(string_or_regexp, @parameter_type_registry) if string_or_regexp.is_a?(Regexp)
156
- raise ArgumentError.new('Expression must be a String or Regexp')
185
+
186
+ raise ArgumentError, 'Expression must be a String or Regexp'
157
187
  end
158
188
 
159
189
  def self.cli_snippet_type_options
@@ -166,6 +196,21 @@ module Cucumber
166
196
 
167
197
  private
168
198
 
199
+ def parameter_type_envelope(parameter_type)
200
+ # TODO: should me moved to Cucumber::Expression::ParameterType#to_envelope ?
201
+ # Note: that would mean that cucumber-expression would depend on cucumber-messages
202
+
203
+ Cucumber::Messages::Envelope.new(
204
+ parameter_type: Cucumber::Messages::ParameterType.new(
205
+ id: @configuration.id_generator.new_id,
206
+ name: parameter_type.name,
207
+ regular_expressions: parameter_type.regexps.map(&:to_s),
208
+ prefer_for_regular_expression_match: parameter_type.prefer_for_regexp_match?,
209
+ use_for_snippets: parameter_type.use_for_snippets?
210
+ )
211
+ )
212
+ end
213
+
169
214
  def available_step_definition_hash
170
215
  @available_step_definition_hash ||= {}
171
216
  end
@@ -180,7 +225,7 @@ module Cucumber
180
225
  end
181
226
 
182
227
  def self.backtrace_line(proc, name)
183
- location = Cucumber::Core::Ast::Location.from_source_location(*proc.source_location)
228
+ location = Cucumber::Core::Test::Location.from_source_location(*proc.source_location)
184
229
  "#{location}:in `#{name}'"
185
230
  end
186
231
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cucumber
4
+ module Glue
5
+ ##
6
+ # This class wraps some internals methods to expose them to external plugins.
7
+ class RegistryWrapper
8
+ def initialize(registry)
9
+ @registry = registry
10
+ end
11
+
12
+ ##
13
+ # Creates a new CucumberExpression from the given +string_or_regexp+.
14
+ #
15
+ # If +string_or_regexp+ is a string, it will return a new CucumberExpression::CucumberExpression
16
+ #
17
+ # If +string_or_regexp+ is a regexp, it will return a new CucumberExpressions::RegularExpression
18
+ #
19
+ # An ArgumentError is raised if +string_or_regexp+ is not a string or a regexp
20
+ def create_expression(string_or_regexp)
21
+ @registry.create_expression(string_or_regexp)
22
+ end
23
+
24
+ ##
25
+ # Return the current execution environment - AKA an isntance of World
26
+ def current_world
27
+ @registry.current_world
28
+ end
29
+ end
30
+ end
31
+ end
@@ -3,7 +3,7 @@
3
3
  module Cucumber
4
4
  module Glue
5
5
  module Snippet
6
- ARGUMENT_PATTERNS = ['"([^"]*)"', '(\d+)']
6
+ ARGUMENT_PATTERNS = ['"([^"]*)"', '(\d+)'].freeze
7
7
 
8
8
  class Generator
9
9
  def self.register_on(configuration)
@@ -42,7 +42,7 @@ module Cucumber
42
42
  end
43
43
 
44
44
  def self.cli_option_string(type, cucumber_expression_generator)
45
- format('%-7s: %-28s e.g. %s', type, description, example(cucumber_expression_generator))
45
+ format('%<type>-7s: %<description>-28s e.g. %<example>s', type: type, description: description, example: example(cucumber_expression_generator))
46
46
  end
47
47
 
48
48
  private
@@ -61,7 +61,7 @@ module Cucumber
61
61
  end
62
62
 
63
63
  def do_block
64
- do_block = String.new
64
+ do_block = String.new # rubocop:disable Style/EmptyLiteral
65
65
  do_block << "do#{parameters}\n"
66
66
  multiline_argument.append_comment_to(do_block)
67
67
  do_block << " pending # Write code here that turns the phrase above into concrete actions\n"
@@ -72,11 +72,15 @@ module Cucumber
72
72
  def parameters
73
73
  block_args = (0...number_of_arguments).map { |n| "arg#{n + 1}" }
74
74
  multiline_argument.append_block_parameter_to(block_args)
75
- block_args.empty? ? '' : " |#{block_args.join(", ")}|"
75
+ block_args.empty? ? '' : " |#{block_args.join(', ')}|"
76
76
  end
77
77
 
78
- def self.example(cucumber_expression_generator)
79
- new(cucumber_expression_generator, 'Given', 'I have 2 cukes', MultilineArgument::None.new).step
78
+ class << self
79
+ private
80
+
81
+ def example(cucumber_expression_generator)
82
+ new(cucumber_expression_generator, 'Given', 'I have 2 cukes', MultilineArgument::None.new).step
83
+ end
80
84
  end
81
85
  end
82
86
 
@@ -87,11 +91,11 @@ module Cucumber
87
91
 
88
92
  def to_s
89
93
  header = generated_expressions.each_with_index.map do |expr, i|
90
- prefix = i == 0 ? '' : '# '
91
- "#{prefix}#{code_keyword}(\"#{expr.source}\") do#{parameters(expr)}"
94
+ prefix = i.zero? ? '' : '# '
95
+ "#{prefix}#{code_keyword}('#{expr.source}') do#{parameters(expr)}"
92
96
  end.join("\n")
93
97
 
94
- body = String.new
98
+ body = String.new # rubocop:disable Style/EmptyLiteral
95
99
  multiline_argument.append_comment_to(body)
96
100
  body << " pending # Write code here that turns the phrase above into concrete actions\n"
97
101
  body << 'end'
@@ -102,7 +106,7 @@ module Cucumber
102
106
  def parameters(expr)
103
107
  parameter_names = expr.parameter_names
104
108
  multiline_argument.append_block_parameter_to(parameter_names)
105
- parameter_names.empty? ? '' : " |#{parameter_names.join(", ")}|"
109
+ parameter_names.empty? ? '' : " |#{parameter_names.join(', ')}|"
106
110
  end
107
111
 
108
112
  def self.description
@@ -141,11 +145,11 @@ module Cucumber
141
145
  end
142
146
 
143
147
  SNIPPET_TYPES = {
144
- :cucumber_expression => CucumberExpression,
145
- :regexp => Regexp,
146
- :classic => Classic,
147
- :percent => Percent
148
- }
148
+ cucumber_expression: CucumberExpression,
149
+ regexp: Regexp,
150
+ classic: Classic,
151
+ percent: Percent
152
+ }.freeze
149
153
 
150
154
  module MultilineArgumentSnippet
151
155
  def self.new(multiline_argument)
@@ -170,11 +174,10 @@ module Cucumber
170
174
 
171
175
  class DocString
172
176
  def append_block_parameter_to(array)
173
- array << 'string'
177
+ array << 'doc_string'
174
178
  end
175
179
 
176
- def append_comment_to(string)
177
- end
180
+ def append_comment_to(string); end
178
181
  end
179
182
 
180
183
  class DataTable
@@ -192,11 +195,9 @@ module Cucumber
192
195
  end
193
196
 
194
197
  class None
195
- def append_block_parameter_to(array)
196
- end
198
+ def append_block_parameter_to(array); end
197
199
 
198
- def append_comment_to(string)
199
- end
200
+ def append_comment_to(string); end
200
201
  end
201
202
  end
202
203
  end
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'cucumber/step_match'
4
- require 'cucumber/step_argument'
5
- require 'cucumber/core_ext/string'
6
4
  require 'cucumber/glue/invoke_in_world'
7
5
 
8
6
  module Cucumber
@@ -25,9 +23,10 @@ module Cucumber
25
23
  end
26
24
 
27
25
  class << self
28
- def new(registry, string_or_regexp, proc_or_sym, options)
26
+ def new(id, registry, string_or_regexp, proc_or_sym, options)
29
27
  raise MissingProc if proc_or_sym.nil?
30
- super registry, registry.create_expression(string_or_regexp), create_proc(proc_or_sym, options)
28
+
29
+ super id, registry, registry.create_expression(string_or_regexp), create_proc(proc_or_sym, options)
31
30
  end
32
31
 
33
32
  private
@@ -35,6 +34,7 @@ module Cucumber
35
34
  def create_proc(proc_or_sym, options)
36
35
  return proc_or_sym if proc_or_sym.is_a?(Proc)
37
36
  raise ArgumentError unless proc_or_sym.is_a?(Symbol)
37
+
38
38
  message = proc_or_sym
39
39
  target_proc = parse_target_proc_from(options)
40
40
  patch_location_onto lambda { |*args|
@@ -44,33 +44,62 @@ module Cucumber
44
44
  end
45
45
 
46
46
  def patch_location_onto(block)
47
- location = Core::Ast::Location.of_caller(5)
47
+ location = Core::Test::Location.of_caller(5)
48
48
  block.define_singleton_method(:source_location) { [location.file, location.line] }
49
49
  block
50
50
  end
51
51
 
52
52
  def parse_target_proc_from(options)
53
- return lambda { self } unless options.key?(:on)
53
+ return -> { self } unless options.key?(:on)
54
+
54
55
  target = options[:on]
55
56
  case target
56
57
  when Proc
57
58
  target
58
59
  when Symbol
59
- lambda { self.send(target) }
60
+ -> { send(target) }
60
61
  else
61
- lambda { raise ArgumentError, 'Target must be a symbol or a proc' }
62
+ -> { raise ArgumentError, 'Target must be a symbol or a proc' }
62
63
  end
63
64
  end
64
65
  end
65
66
 
66
- attr_reader :expression, :registry
67
+ attr_reader :id, :expression, :registry
67
68
 
68
- def initialize(registry, expression, proc)
69
+ def initialize(id, registry, expression, proc)
69
70
  raise 'No regexp' if expression.is_a?(Regexp)
70
- @registry, @expression, @proc = registry, expression, proc
71
+
72
+ @id = id
73
+ @registry = registry
74
+ @expression = expression
75
+ @proc = proc
71
76
  # @registry.available_step_definition(regexp_source, location)
72
77
  end
73
78
 
79
+ def to_envelope
80
+ Cucumber::Messages::Envelope.new(
81
+ step_definition: Cucumber::Messages::StepDefinition.new(
82
+ id: id,
83
+ pattern: Cucumber::Messages::StepDefinitionPattern.new(
84
+ source: expression.source.to_s,
85
+ type: expression_type
86
+ ),
87
+ source_reference: Cucumber::Messages::SourceReference.new(
88
+ uri: location.file,
89
+ location: Cucumber::Messages::Location.new(
90
+ line: location.lines.first
91
+ )
92
+ )
93
+ )
94
+ )
95
+ end
96
+
97
+ def expression_type
98
+ return Cucumber::Messages::StepDefinitionPatternType::CUCUMBER_EXPRESSION if expression.is_a?(CucumberExpressions::CucumberExpression)
99
+
100
+ Cucumber::Messages::StepDefinitionPatternType::REGULAR_EXPRESSION
101
+ end
102
+
74
103
  # @api private
75
104
  def to_hash
76
105
  type = expression.is_a?(CucumberExpressions::RegularExpression) ? 'regular expression' : 'cucumber expression'
@@ -92,26 +121,22 @@ module Cucumber
92
121
  end
93
122
 
94
123
  # @api private
95
- def ==(step_definition)
96
- expression.source == step_definition.expression.source
124
+ def ==(other)
125
+ expression.source == other.expression.source
97
126
  end
98
127
 
99
128
  # @api private
100
129
  def arguments_from(step_name)
101
- args = @expression.match(step_name)
102
- # @registry.invoked_step_definition(regexp_source, location) if args
103
- args
130
+ @expression.match(step_name)
104
131
  end
105
132
 
106
133
  # @api private
107
134
  # TODO: inline this and step definition just be a value object
108
135
  def invoke(args)
109
- begin
110
- InvokeInWorld.cucumber_instance_exec_in(@registry.current_world, true, @expression.to_s, *args, &@proc)
111
- rescue ArityMismatchError => e
112
- e.backtrace.unshift(self.backtrace_line)
113
- raise e
114
- end
136
+ InvokeInWorld.cucumber_instance_exec_in(@registry.current_world, true, @expression.to_s, *args, &@proc)
137
+ rescue ArityMismatchError => e
138
+ e.backtrace.unshift(backtrace_line)
139
+ raise e
115
140
  end
116
141
 
117
142
  # @api private
@@ -131,7 +156,7 @@ module Cucumber
131
156
 
132
157
  # The source location where the step definition can be found
133
158
  def location
134
- @location ||= Cucumber::Core::Ast::Location.from_source_location(*@proc.source_location)
159
+ @location ||= Cucumber::Core::Test::Location.from_source_location(*@proc.source_location)
135
160
  end
136
161
 
137
162
  # @api private
@@ -10,7 +10,7 @@ module Cucumber
10
10
  end
11
11
 
12
12
  def raise_nil_world
13
- raise NilWorld.new
13
+ raise NilWorld
14
14
  rescue NilWorld => e
15
15
  e.backtrace.clear
16
16
  e.backtrace.push(Glue.backtrace_line(@proc, 'World'))
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'pathname'
4
- require 'cucumber/core/ast/location'
4
+ require 'cucumber/core/test/location'
5
5
  require 'cucumber/core/test/around_hook'
6
6
 
7
7
  module Cucumber
@@ -9,29 +9,30 @@ module Cucumber
9
9
  # source for test steps
10
10
  module Hooks
11
11
  class << self
12
- def before_hook(source, location, &block)
13
- build_hook_step(source, location, block, BeforeHook, Core::Test::UnskippableAction)
12
+ def before_hook(id, location, &block)
13
+ build_hook_step(id, location, block, BeforeHook, Core::Test::UnskippableAction)
14
14
  end
15
15
 
16
- def after_hook(source, location, &block)
17
- build_hook_step(source, location, block, AfterHook, Core::Test::UnskippableAction)
16
+ def after_hook(id, location, &block)
17
+ build_hook_step(id, location, block, AfterHook, Core::Test::UnskippableAction)
18
18
  end
19
19
 
20
- def after_step_hook(source, location, &block)
21
- raise ArgumentError unless source.last.is_a?(Core::Ast::Step)
22
- build_hook_step(source, location, block, AfterStepHook, Core::Test::Action)
20
+ def after_step_hook(id, test_step, location, &block)
21
+ raise ArgumentError if test_step.hook?
22
+
23
+ build_hook_step(id, location, block, AfterStepHook, Core::Test::Action)
23
24
  end
24
25
 
25
- def around_hook(_source, &block)
26
+ def around_hook(&block)
26
27
  Core::Test::AroundHook.new(&block)
27
28
  end
28
29
 
29
30
  private
30
31
 
31
- def build_hook_step(source, location, block, hook_type, action_type)
32
+ def build_hook_step(id, location, block, hook_type, action_type)
32
33
  action = action_type.new(location, &block)
33
34
  hook = hook_type.new(action.location)
34
- Core::Test::Step.new(source + [hook], action)
35
+ Core::Test::HookStep.new(id, hook.text, location, action)
35
36
  end
36
37
  end
37
38
 
@@ -1,7 +1,7 @@
1
1
  module Cucumber
2
2
  module MultilineArgument
3
3
  class DataTable
4
- class DiffMatrices #:nodoc:
4
+ class DiffMatrices # :nodoc:
5
5
  attr_accessor :cell_matrix, :other_table_cell_matrix, :options
6
6
 
7
7
  def initialize(cell_matrix, other_table_cell_matrix, options)
@@ -95,7 +95,7 @@ module Cucumber
95
95
  def changes
96
96
  require 'diff/lcs'
97
97
  diffable_cell_matrix = cell_matrix.dup.extend(::Diff::LCS)
98
- diffable_cell_matrix.diff(other_table_cell_matrix).flatten
98
+ diffable_cell_matrix.diff(other_table_cell_matrix).flatten(1)
99
99
  end
100
100
 
101
101
  def inspect_rows(missing_row, inserted_row)
@@ -113,6 +113,7 @@ module Cucumber
113
113
  row_index = row_indices.index(i)
114
114
  row = cell_matrix[row_index] if row_index
115
115
  next unless row
116
+
116
117
  (original_width..padded_width).each do |col_index|
117
118
  surplus_cell = other_row[col_index]
118
119
  row[col_index].value = surplus_cell.value if row[col_index]
@@ -135,7 +136,7 @@ module Cucumber
135
136
  def raise_error
136
137
  table = DataTable.from([[]])
137
138
  table.instance_variable_set :@cell_matrix, cell_matrix
138
- raise Different.new(table) if should_raise?
139
+ raise Different, table if should_raise?
139
140
  end
140
141
 
141
142
  def should_raise?