Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2026-01-06 12:52:49 UTC using RuboCop version 1.81.7.
# on 2026-04-06 21:27:57 UTC using RuboCop version 1.81.7.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.

# TODO: [LH] v14 Pre-release iteration -> 58 files inspected, 392 offenses detected, 100 offenses auto-correctable
# TODO: [LH] v14 Pre-release iteration 2 (Rubocop upgrade) -> 60 files inspected, 324 offenses detected, 86 offenses autocorrectable
# TODO: [LH] v14 Pre-release iteration 3 (Rubocop additional upgrade) -> 60 files inspected, 267 offenses detected, 26 offenses autocorrectable
# TODO: [LH] v15 Release incoming (Minimum ruby bump) -> 60 files inspected, 234 offenses detected, 12 offenses autocorrectable
# TODO: [LH] v15.1 (Minor fixes) -> 60 files inspected, 239 offenses detected, 15 offenses autocorrectable
# TODO: [LH] v16 (Gherkin/Message bump) -> 61 files inspected, 272 offenses detected, 60 offenses autocorrectable
# TODO: [LH] v16.2 (Generic refactors / new events) -> 79 files inspected, 222 offenses detected, 10 offenses autocorrectable

# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
Expand Down
6 changes: 3 additions & 3 deletions lib/cucumber/core/compiler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class Compiler
attr_reader :receiver, :gherkin_query, :id_generator
private :receiver, :gherkin_query, :id_generator

def initialize(receiver, gherkin_query, event_bus = nil)
def initialize(receiver, gherkin_query, event_bus)
@receiver = receiver
@id_generator = Cucumber::Messages::Helpers::IdGenerator::UUID.new
@gherkin_query = gherkin_query
Expand All @@ -42,15 +42,15 @@ def create_test_case(pickle)
parent_locations = parent_locations_from_pickle(pickle)
tags = tags_from_pickle(pickle, uri)
Test::Case.new(id_generator.new_id, pickle.name, test_steps, location, parent_locations, tags, pickle.language).tap do |test_case|
@event_bus&.test_case_created(test_case, pickle)
@event_bus.test_case_created(test_case, pickle)
end
end

def create_test_step(pickle_step, uri)
location = location_from_pickle_step(pickle_step, uri)
multiline_arg = create_multiline_arg(pickle_step, uri)
Test::Step.new(id_generator.new_id, pickle_step.text, location, multiline_arg).tap do |test_step|
@event_bus&.test_step_created(test_step, pickle_step)
@event_bus.test_step_created(test_step, pickle_step)
end
end

Expand Down
8 changes: 4 additions & 4 deletions lib/cucumber/core/gherkin/document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ module Gherkin
class Document
attr_reader :uri, :body, :language

def initialize(uri, body, language = nil)
@uri = uri
@body = body
@language = language || 'en'
def initialize(uri, body, language = 'en')
@uri = uri
@body = body
@language = language
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing the signature to language = 'en' subtly changes behavior when callers pass nil explicitly: it will now set @language to nil instead of defaulting to 'en'. If the intention is to keep the previous behavior, coerce nil to 'en' (e.g. @language = language || 'en').

Suggested change
@language = language
@language = language || 'en'

Copilot uses AI. Check for mistakes.
end

def to_s
Expand Down
14 changes: 5 additions & 9 deletions lib/cucumber/core/gherkin/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,11 @@ def update_gherkin_query(message)
end

def type(message)
if !message.gherkin_document.nil?
:gherkin_document
elsif !message.pickle.nil?
:pickle
elsif message.parse_error
:parse_error
else
:unknown
end
return :gherkin_document if message.gherkin_document
return :pickle if message.pickle
return :parse_error if message.parse_error

:unknown
end
end
end
Expand Down
17 changes: 0 additions & 17 deletions lib/cucumber/core/platform.rb

This file was deleted.

12 changes: 6 additions & 6 deletions lib/cucumber/core/test/action.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# frozen_string_literal: true

require 'cucumber/core/test/location'
require 'cucumber/core/test/result'
require 'cucumber/core/test/timer'
require_relative 'location'
require_relative 'result'
require_relative 'timer'

require 'cucumber/core/test/action/defined'
require 'cucumber/core/test/action/undefined'
require 'cucumber/core/test/action/unskippable'
require_relative 'action/defined'
require_relative 'action/undefined'
require_relative 'action/unskippable'
8 changes: 4 additions & 4 deletions lib/cucumber/core/test/around_hook.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ def describe_to(visitor, *, &)
visitor.around_hook(self, *, &)
end

def hook?
true
end

def execute(*_args, &continue)
@timer.start
@block.call(continue)
Expand All @@ -27,6 +23,10 @@ def execute(*_args, &continue)
failed(e)
end

def hook?
true
end

private

def failed(exception)
Expand Down
53 changes: 27 additions & 26 deletions lib/cucumber/core/test/case.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# frozen_string_literal: true

require 'cucumber/core/test/result'
require 'cucumber/tag_expressions'

require_relative 'result'

module Cucumber
module Core
module Test
Expand All @@ -22,8 +23,8 @@ def initialize(id, name, test_steps, location, parent_locations, tags, language,
@around_hooks = around_hooks
end

def step_count
test_steps.count
def ==(other)
eql?(other)
end

def describe_to(visitor, *args)
Expand All @@ -37,20 +38,25 @@ def describe_to(visitor, *args)
self
end

def with_steps(test_steps)
self.class.new(id, name, test_steps, location, parent_locations, tags, language, around_hooks)
def eql?(other)
other.hash == hash
end

def with_around_hooks(around_hooks)
self.class.new(id, name, test_steps, location, parent_locations, tags, language, around_hooks)
def hash
location.hash
end

def match_tags?(*expressions)
expressions.flatten.all? { |expression| match_single_tag_expression?(expression) }
def inspect
"#<#{self.class}: #{location}>"
end

def match_name?(name_regexp)
name =~ name_regexp
def matching_locations
[
parent_locations,
location,
tags.map(&:location),
test_steps.map(&:matching_locations)
].flatten
end

def match_locations?(queried_locations)
Expand All @@ -61,29 +67,24 @@ def match_locations?(queried_locations)
end
end

def matching_locations
[
parent_locations,
location,
tags.map(&:location),
test_steps.map(&:matching_locations)
].flatten
def match_name?(name_regexp)
name =~ name_regexp
end

def inspect
"#<#{self.class}: #{location}>"
def match_tags?(*expressions)
expressions.flatten.all? { |expression| match_single_tag_expression?(expression) }
end

def hash
location.hash
def step_count
test_steps.count
end

def eql?(other)
other.hash == hash
def with_around_hooks(around_hooks)
self.class.new(id, name, test_steps, location, parent_locations, tags, language, around_hooks)
end

def ==(other)
eql?(other)
def with_steps(test_steps)
self.class.new(id, name, test_steps, location, parent_locations, tags, language, around_hooks)
end

private
Expand Down
76 changes: 37 additions & 39 deletions lib/cucumber/core/test/data_table.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,60 +16,52 @@ module Test
#
# And a matching StepDefinition:
#
# Given /I have:/ do |table|
# Given('I have:') do |table|
# data = table.raw
# end
#
# This will store <tt>[['a', 'b'], ['c', 'd']]</tt> in the <tt>data</tt> variable.
#
class DataTable
# Creates a new instance. +raw+ should be an Array of Array of String
# or an Array of Hash
attr_reader :raw

# Creates a new instance. +raw+ should be a square (2d), array of strings or an array of hashes
#
# You don't typically create your own DataTable objects - Cucumber will do
# it internally and pass them to your Step Definitions.
#
def initialize(rows)
raw = ensure_array_of_array(rows)
Comment on lines +28 to 33
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The initializer doc comment says +raw+ but the parameter is rows. Update the comment to match the actual argument name (or rename the parameter) to avoid confusing API consumers.

Copilot uses AI. Check for mistakes.
verify_rows_are_same_length(raw)
@raw = raw.freeze
end
attr_reader :raw

def describe_to(visitor, *)
visitor.data_table(self, *)
end

def to_step_definition_arg
dup
def ==(other)
other.class == self.class && raw == other.raw
end

def data_table?
true
end

def describe_to(visitor, *)
visitor.data_table(self, *)
end

def doc_string?
false
end

# Creates a copy of this table
#
def dup
self.class.new(raw.dup)
end

# Returns a new, transposed table. Example:
#
# | a | 7 | 4 |
# | b | 9 | 2 |
#
# Gets converted into the following:
#
# | a | b |
# | 7 | 9 |
# | 4 | 2 |
#
def transpose
self.class.new(raw.transpose)
def inspect
%{#<#{self.class} #{raw.inspect})>}
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inspect returns a string with an extra ) before >, which makes the output malformed (e.g. #<... ...)>). Remove the stray parenthesis so the inspected representation is well-formed.

Suggested change
%{#<#{self.class} #{raw.inspect})>}
%{#<#{self.class} #{raw.inspect}>}

Copilot uses AI. Check for mistakes.
end

def lines_count
raw.count
end

def map(&block)
Expand All @@ -80,26 +72,26 @@ def map(&block)
self.class.new(new_raw)
end

def lines_count
raw.count
end

def ==(other)
other.class == self.class && raw == other.raw
def to_step_definition_arg
dup
end

def inspect
%{#<#{self.class} #{raw.inspect})>}
# Returns a new, transposed table. Example:
#
# | a | 7 | 4 |
# | b | 9 | 2 |
#
# Gets converted into the following:
#
# | a | b |
# | 7 | 9 |
# | 4 | 2 |
def transpose
self.class.new(raw.transpose)
end

private

def verify_rows_are_same_length(raw)
raw.transpose
rescue IndexError
raise ArgumentError, 'Rows must all be the same length'
end

def ensure_array_of_array(array)
array[0].is_a?(Hash) ? hashes_to_array(array) : array
end
Expand All @@ -108,6 +100,12 @@ def hashes_to_array(hashes)
header = hashes[0].keys.sort
[header] + hashes.map { |hash| header.map { |key| hash[key] } }
end

def verify_rows_are_same_length(raw)
raw.transpose
rescue IndexError
raise ArgumentError, 'Rows must all be the same length'
end
end
end
end
Expand Down
Loading