cucumber 3.1.2 → 7.1.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 (118) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1780 -1146
  3. data/CONTRIBUTING.md +224 -61
  4. data/README.md +144 -22
  5. data/bin/cucumber +1 -1
  6. data/lib/autotest/cucumber_mixin.rb +46 -53
  7. data/lib/cucumber/cli/configuration.rb +28 -6
  8. data/lib/cucumber/cli/main.rb +12 -12
  9. data/lib/cucumber/cli/options.rb +103 -77
  10. data/lib/cucumber/cli/profile_loader.rb +49 -26
  11. data/lib/cucumber/configuration.rb +44 -29
  12. data/lib/cucumber/constantize.rb +2 -5
  13. data/lib/cucumber/deprecate.rb +31 -7
  14. data/lib/cucumber/errors.rb +5 -7
  15. data/lib/cucumber/events/envelope.rb +9 -0
  16. data/lib/cucumber/events/gherkin_source_parsed.rb +11 -0
  17. data/lib/cucumber/events/hook_test_step_created.rb +13 -0
  18. data/lib/cucumber/events/step_activated.rb +2 -1
  19. data/lib/cucumber/events/test_case_created.rb +13 -0
  20. data/lib/cucumber/events/test_case_ready.rb +12 -0
  21. data/lib/cucumber/events/test_step_created.rb +13 -0
  22. data/lib/cucumber/events/undefined_parameter_type.rb +10 -0
  23. data/lib/cucumber/events.rb +14 -7
  24. data/lib/cucumber/file_specs.rb +6 -6
  25. data/lib/cucumber/filters/activate_steps.rb +5 -3
  26. data/lib/cucumber/filters/broadcast_test_case_ready_event.rb +12 -0
  27. data/lib/cucumber/filters/prepare_world.rb +5 -9
  28. data/lib/cucumber/filters/quit.rb +1 -3
  29. data/lib/cucumber/filters/tag_limits/verifier.rb +2 -4
  30. data/lib/cucumber/filters.rb +1 -0
  31. data/lib/cucumber/formatter/ansicolor.rb +40 -52
  32. data/lib/cucumber/formatter/ast_lookup.rb +163 -0
  33. data/lib/cucumber/formatter/backtrace_filter.rb +10 -8
  34. data/lib/cucumber/formatter/console.rb +69 -69
  35. data/lib/cucumber/formatter/console_counts.rb +4 -9
  36. data/lib/cucumber/formatter/console_issues.rb +6 -3
  37. data/lib/cucumber/formatter/duration.rb +1 -1
  38. data/lib/cucumber/formatter/duration_extractor.rb +3 -1
  39. data/lib/cucumber/formatter/errors.rb +6 -0
  40. data/lib/cucumber/formatter/fanout.rb +2 -0
  41. data/lib/cucumber/formatter/html.rb +11 -598
  42. data/lib/cucumber/formatter/http_io.rb +147 -0
  43. data/lib/cucumber/formatter/ignore_missing_messages.rb +1 -1
  44. data/lib/cucumber/formatter/interceptor.rb +11 -30
  45. data/lib/cucumber/formatter/io.rb +55 -13
  46. data/lib/cucumber/formatter/json.rb +115 -122
  47. data/lib/cucumber/formatter/junit.rb +72 -55
  48. data/lib/cucumber/formatter/message.rb +23 -0
  49. data/lib/cucumber/formatter/message_builder.rb +255 -0
  50. data/lib/cucumber/formatter/pretty.rb +360 -153
  51. data/lib/cucumber/formatter/progress.rb +30 -32
  52. data/lib/cucumber/formatter/publish_banner_printer.rb +77 -0
  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 +8 -6
  61. data/lib/cucumber/formatter/summary.rb +16 -8
  62. data/lib/cucumber/formatter/unicode.rb +15 -17
  63. data/lib/cucumber/formatter/url_reporter.rb +17 -0
  64. data/lib/cucumber/formatter/usage.rb +17 -14
  65. data/lib/cucumber/gherkin/data_table_parser.rb +17 -6
  66. data/lib/cucumber/gherkin/formatter/ansi_escapes.rb +13 -17
  67. data/lib/cucumber/gherkin/formatter/escaping.rb +2 -2
  68. data/lib/cucumber/gherkin/steps_parser.rb +17 -8
  69. data/lib/cucumber/glue/dsl.rb +19 -0
  70. data/lib/cucumber/glue/hook.rb +34 -11
  71. data/lib/cucumber/glue/invoke_in_world.rb +13 -18
  72. data/lib/cucumber/glue/proto_world.rb +37 -44
  73. data/lib/cucumber/glue/registry_and_more.rb +71 -12
  74. data/lib/cucumber/glue/registry_wrapper.rb +31 -0
  75. data/lib/cucumber/glue/snippet.rb +23 -22
  76. data/lib/cucumber/glue/step_definition.rb +42 -20
  77. data/lib/cucumber/glue/world_factory.rb +1 -1
  78. data/lib/cucumber/hooks.rb +11 -11
  79. data/lib/cucumber/multiline_argument/data_table/diff_matrices.rb +2 -2
  80. data/lib/cucumber/multiline_argument/data_table.rb +97 -64
  81. data/lib/cucumber/multiline_argument/doc_string.rb +1 -1
  82. data/lib/cucumber/multiline_argument.rb +4 -6
  83. data/lib/cucumber/platform.rb +3 -3
  84. data/lib/cucumber/rake/task.rb +16 -18
  85. data/lib/cucumber/rspec/disable_option_parser.rb +9 -8
  86. data/lib/cucumber/rspec/doubles.rb +3 -5
  87. data/lib/cucumber/running_test_case.rb +2 -53
  88. data/lib/cucumber/runtime/after_hooks.rb +8 -4
  89. data/lib/cucumber/runtime/before_hooks.rb +8 -4
  90. data/lib/cucumber/runtime/for_programming_languages.rb +4 -2
  91. data/lib/cucumber/runtime/step_hooks.rb +6 -2
  92. data/lib/cucumber/runtime/support_code.rb +13 -15
  93. data/lib/cucumber/runtime/user_interface.rb +6 -16
  94. data/lib/cucumber/runtime.rb +77 -59
  95. data/lib/cucumber/step_definition_light.rb +4 -3
  96. data/lib/cucumber/step_definitions.rb +2 -2
  97. data/lib/cucumber/step_match.rb +12 -17
  98. data/lib/cucumber/step_match_search.rb +2 -1
  99. data/lib/cucumber/term/ansicolor.rb +9 -9
  100. data/lib/cucumber/term/banner.rb +56 -0
  101. data/lib/cucumber/version +1 -1
  102. data/lib/cucumber.rb +1 -1
  103. metadata +272 -81
  104. data/lib/cucumber/core_ext/string.rb +0 -11
  105. data/lib/cucumber/events/gherkin_source_parsed.rb~ +0 -14
  106. data/lib/cucumber/formatter/ast_lookup.rb~ +0 -9
  107. data/lib/cucumber/formatter/cucumber.css +0 -286
  108. data/lib/cucumber/formatter/cucumber.sass +0 -247
  109. data/lib/cucumber/formatter/hook_query_visitor.rb +0 -42
  110. data/lib/cucumber/formatter/html_builder.rb +0 -121
  111. data/lib/cucumber/formatter/inline-js.js +0 -30
  112. data/lib/cucumber/formatter/jquery-min.js +0 -154
  113. data/lib/cucumber/formatter/json_pretty.rb +0 -11
  114. data/lib/cucumber/formatter/legacy_api/adapter.rb +0 -1028
  115. data/lib/cucumber/formatter/legacy_api/ast.rb +0 -394
  116. data/lib/cucumber/formatter/legacy_api/results.rb +0 -50
  117. data/lib/cucumber/formatter/legacy_api/runtime_facade.rb +0 -32
  118. 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,27 +65,36 @@ 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
75
  def register_rb_hook(phase, tag_expressions, proc)
75
- add_hook(phase, Hook.new(self, tag_expressions, proc))
76
+ hook = add_hook(phase, Hook.new(@configuration.id_generator.new_id, self, tag_expressions, proc))
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)
@@ -96,15 +107,20 @@ module Cucumber
96
107
 
97
108
  @namespaced_world_modules ||= Hash.new { |h, k| h[k] = [] }
98
109
  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
110
+ @namespaced_world_modules[namespace] << world_module unless @namespaced_world_modules[namespace].include?(world_module)
102
111
  end
103
112
  end
104
113
 
105
114
  def load_code_file(code_file)
106
115
  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
116
+
117
+ # This will cause self.add_step_definition, self.add_hook, and self.define_parameter_type to be called from Glue::Dsl
118
+
119
+ if Cucumber.use_legacy_autoloader
120
+ load File.expand_path(code_file)
121
+ else
122
+ require File.expand_path(code_file)
123
+ end
108
124
  end
109
125
 
110
126
  def begin_scenario(test_case)
@@ -120,11 +136,31 @@ module Cucumber
120
136
  end
121
137
 
122
138
  def after_configuration(configuration)
139
+ deprecate_after_configuration_hook if hooks[:after_configuration].any?
140
+
123
141
  hooks[:after_configuration].each do |hook|
124
142
  hook.invoke('AfterConfiguration', configuration)
125
143
  end
126
144
  end
127
145
 
146
+ def install_plugin(configuration, registry)
147
+ hooks[:install_plugin].each do |hook|
148
+ hook.invoke('InstallPlugin', [configuration, registry])
149
+ end
150
+ end
151
+
152
+ def before_all
153
+ hooks[:before_all].each do |hook|
154
+ hook.invoke('BeforeAll', [])
155
+ end
156
+ end
157
+
158
+ def after_all
159
+ hooks[:after_all].each do |hook|
160
+ hook.invoke('AfterAll', [])
161
+ end
162
+ end
163
+
128
164
  def add_hook(phase, hook)
129
165
  hooks[phase.to_sym] << hook
130
166
  hook
@@ -153,7 +189,7 @@ module Cucumber
153
189
  def create_expression(string_or_regexp)
154
190
  return CucumberExpressions::CucumberExpression.new(string_or_regexp, @parameter_type_registry) if string_or_regexp.is_a?(String)
155
191
  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')
192
+ raise ArgumentError, 'Expression must be a String or Regexp'
157
193
  end
158
194
 
159
195
  def self.cli_snippet_type_options
@@ -166,6 +202,21 @@ module Cucumber
166
202
 
167
203
  private
168
204
 
205
+ def parameter_type_envelope(parameter_type)
206
+ # TODO: should me moved to Cucumber::Expression::ParameterType#to_envelope ?
207
+ # Note: that would mean that cucumber-expression would depend on cucumber-messages
208
+
209
+ Cucumber::Messages::Envelope.new(
210
+ parameter_type: Cucumber::Messages::ParameterType.new(
211
+ id: @configuration.id_generator.new_id,
212
+ name: parameter_type.name,
213
+ regular_expressions: parameter_type.regexps.map(&:to_s),
214
+ prefer_for_regular_expression_match: parameter_type.prefer_for_regexp_match?,
215
+ use_for_snippets: parameter_type.use_for_snippets?
216
+ )
217
+ )
218
+ end
219
+
169
220
  def available_step_definition_hash
170
221
  @available_step_definition_hash ||= {}
171
222
  end
@@ -177,10 +228,18 @@ module Cucumber
177
228
  def hooks
178
229
  @hooks ||= Hash.new { |h, k| h[k] = [] }
179
230
  end
231
+
232
+ def deprecate_after_configuration_hook
233
+ Cucumber.deprecate(
234
+ 'See https://github.com/cucumber/cucumber-ruby/blob/main/UPGRADING.md#upgrading-to-710 for more info',
235
+ ' AfterConfiguration hook',
236
+ '8.0.0'
237
+ )
238
+ end
180
239
  end
181
240
 
182
241
  def self.backtrace_line(proc, name)
183
- location = Cucumber::Core::Ast::Location.from_source_location(*proc.source_location)
242
+ location = Cucumber::Core::Test::Location.from_source_location(*proc.source_location)
184
243
  "#{location}:in `#{name}'"
185
244
  end
186
245
  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,9 @@ 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
+ super id, registry, registry.create_expression(string_or_regexp), create_proc(proc_or_sym, options)
31
29
  end
32
30
 
33
31
  private
@@ -44,33 +42,59 @@ module Cucumber
44
42
  end
45
43
 
46
44
  def patch_location_onto(block)
47
- location = Core::Ast::Location.of_caller(5)
45
+ location = Core::Test::Location.of_caller(5)
48
46
  block.define_singleton_method(:source_location) { [location.file, location.line] }
49
47
  block
50
48
  end
51
49
 
52
50
  def parse_target_proc_from(options)
53
- return lambda { self } unless options.key?(:on)
51
+ return -> { self } unless options.key?(:on)
54
52
  target = options[:on]
55
53
  case target
56
54
  when Proc
57
55
  target
58
56
  when Symbol
59
- lambda { self.send(target) }
57
+ -> { send(target) }
60
58
  else
61
- lambda { raise ArgumentError, 'Target must be a symbol or a proc' }
59
+ -> { raise ArgumentError, 'Target must be a symbol or a proc' }
62
60
  end
63
61
  end
64
62
  end
65
63
 
66
- attr_reader :expression, :registry
64
+ attr_reader :id, :expression, :registry
67
65
 
68
- def initialize(registry, expression, proc)
66
+ def initialize(id, registry, expression, proc)
69
67
  raise 'No regexp' if expression.is_a?(Regexp)
70
- @registry, @expression, @proc = registry, expression, proc
68
+ @id = id
69
+ @registry = registry
70
+ @expression = expression
71
+ @proc = proc
71
72
  # @registry.available_step_definition(regexp_source, location)
72
73
  end
73
74
 
75
+ def to_envelope
76
+ Cucumber::Messages::Envelope.new(
77
+ step_definition: Cucumber::Messages::StepDefinition.new(
78
+ id: id,
79
+ pattern: Cucumber::Messages::StepDefinitionPattern.new(
80
+ source: expression.source.to_s,
81
+ type: expression_type
82
+ ),
83
+ source_reference: Cucumber::Messages::SourceReference.new(
84
+ uri: location.file,
85
+ location: Cucumber::Messages::Location.new(
86
+ line: location.lines.first
87
+ )
88
+ )
89
+ )
90
+ )
91
+ end
92
+
93
+ def expression_type
94
+ return Cucumber::Messages::StepDefinitionPatternType::CUCUMBER_EXPRESSION if expression.is_a?(CucumberExpressions::CucumberExpression)
95
+ Cucumber::Messages::StepDefinitionPatternType::REGULAR_EXPRESSION
96
+ end
97
+
74
98
  # @api private
75
99
  def to_hash
76
100
  type = expression.is_a?(CucumberExpressions::RegularExpression) ? 'regular expression' : 'cucumber expression'
@@ -92,8 +116,8 @@ module Cucumber
92
116
  end
93
117
 
94
118
  # @api private
95
- def ==(step_definition)
96
- expression.source == step_definition.expression.source
119
+ def ==(other)
120
+ expression.source == other.expression.source
97
121
  end
98
122
 
99
123
  # @api private
@@ -106,12 +130,10 @@ module Cucumber
106
130
  # @api private
107
131
  # TODO: inline this and step definition just be a value object
108
132
  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
133
+ InvokeInWorld.cucumber_instance_exec_in(@registry.current_world, true, @expression.to_s, *args, &@proc)
134
+ rescue ArityMismatchError => e
135
+ e.backtrace.unshift(backtrace_line)
136
+ raise e
115
137
  end
116
138
 
117
139
  # @api private
@@ -131,7 +153,7 @@ module Cucumber
131
153
 
132
154
  # The source location where the step definition can be found
133
155
  def location
134
- @location ||= Cucumber::Core::Ast::Location.from_source_location(*@proc.source_location)
156
+ @location ||= Cucumber::Core::Test::Location.from_source_location(*@proc.source_location)
135
157
  end
136
158
 
137
159
  # @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,29 @@ 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
+ build_hook_step(id, location, block, AfterStepHook, Core::Test::Action)
23
23
  end
24
24
 
25
- def around_hook(_source, &block)
25
+ def around_hook(&block)
26
26
  Core::Test::AroundHook.new(&block)
27
27
  end
28
28
 
29
29
  private
30
30
 
31
- def build_hook_step(source, location, block, hook_type, action_type)
31
+ def build_hook_step(id, location, block, hook_type, action_type)
32
32
  action = action_type.new(location, &block)
33
33
  hook = hook_type.new(action.location)
34
- Core::Test::Step.new(source + [hook], action)
34
+ Core::Test::HookStep.new(id, hook.text, location, action)
35
35
  end
36
36
  end
37
37
 
@@ -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)
@@ -135,7 +135,7 @@ module Cucumber
135
135
  def raise_error
136
136
  table = DataTable.from([[]])
137
137
  table.instance_variable_set :@cell_matrix, cell_matrix
138
- raise Different.new(table) if should_raise?
138
+ raise Different, table if should_raise?
139
139
  end
140
140
 
141
141
  def should_raise?