diff --git a/CHANGELOG.md b/CHANGELOG.md index b6f504ad..a6f5e4d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Please visit [cucumber/CONTRIBUTING.md](https://github.com/cucumber/cucumber/blo ## [Unreleased] ### Removed - Strict configuration has been removed from all `Result` classes +- Removed the ability to list event attributes (Only the `#to_h` method now remains for this purpose) ### Added - Added `#to_envelope` for `Cucumber::Core::Gherkin::Document` ([#329](https://github.com/cucumber/cucumber-ruby-core/pull/329)) @@ -18,6 +19,8 @@ Please visit [cucumber/CONTRIBUTING.md](https://github.com/cucumber/cucumber/blo ### Changed - Refactored the internal base `Event` class to reduce complexity and make it more flexible for future use (No user facing changes) - Refactored the `Result` classes to be more simplified and one class per file +- Changed the base event inheritance to a new base class structure +- Refactored some internals of the library to be slightly more performant (Including removing redundant nil checks) ## [16.2.0] - 2026-02-06 ### Changed diff --git a/lib/cucumber/core/events/base.rb b/lib/cucumber/core/events/base.rb new file mode 100644 index 00000000..cf2d9f16 --- /dev/null +++ b/lib/cucumber/core/events/base.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module Cucumber + module Core + module Events + # An archetype of what each Cucumber Event defined in cucumber-ruby must adhere to + class Base + # The "key" name of the class to be used as the key in the event registry (Underscored name symbolized) + # @return [Symbol] + def self.event_id + raise 'Must be implemented in subclass' + end + + # The properties of each event. Stored in iVar named format - where the key is the name of the iVar + # @return [Hash] + def to_h + instance_variables.to_h { |variable_name| [variable_name[1..].to_sym, instance_variable_get(variable_name)] } + end + + def event_id + self.class.event_id + end + end + end + end +end diff --git a/lib/cucumber/core/events/envelope.rb b/lib/cucumber/core/events/envelope.rb index 80f0fba5..f944eda8 100644 --- a/lib/cucumber/core/events/envelope.rb +++ b/lib/cucumber/core/events/envelope.rb @@ -1,11 +1,23 @@ # frozen_string_literal: true -require_relative '../event' +require_relative 'base' module Cucumber module Core module Events - class Envelope < Event.new(:envelope) + class Envelope < Base + attr_reader :envelope + + # The underscored name of the class to be used as the key in an event registry + # @return [Symbol] + def self.event_id + :envelope + end + + def initialize(envelope) + @envelope = envelope + super() + end end end end diff --git a/lib/cucumber/core/events/gherkin_source_parsed.rb b/lib/cucumber/core/events/gherkin_source_parsed.rb index 82077302..87860074 100644 --- a/lib/cucumber/core/events/gherkin_source_parsed.rb +++ b/lib/cucumber/core/events/gherkin_source_parsed.rb @@ -1,13 +1,23 @@ # frozen_string_literal: true -require_relative '../event' +require_relative 'base' module Cucumber module Core module Events # Signals that a gherkin source has been parsed - class GherkinSourceParsed < Event.new(:gherkin_document) + class GherkinSourceParsed < Base # @return [GherkinDocument] the GherkinDocument Ast Node that was parsed + attr_reader :gherkin_document + + def self.event_id + :gherkin_source_parsed + end + + def initialize(gherkin_document) + @gherkin_document = gherkin_document + super() + end end end end diff --git a/lib/cucumber/core/events/test_case_created.rb b/lib/cucumber/core/events/test_case_created.rb index fa6d5bf4..1374acf7 100644 --- a/lib/cucumber/core/events/test_case_created.rb +++ b/lib/cucumber/core/events/test_case_created.rb @@ -1,13 +1,23 @@ # frozen_string_literal: true -require_relative '../event' +require_relative 'base' module Cucumber module Core module Events # Signals that a Test::Case was created from a Pickle - class TestCaseCreated < Event.new(:test_case, :pickle) - # The created test step & source pickle + class TestCaseCreated < Base + attr_reader :test_case, :pickle + + def self.event_id + :test_case_created + end + + def initialize(test_case, pickle) + @test_case = test_case + @pickle = pickle + super() + end end end end diff --git a/lib/cucumber/core/events/test_case_finished.rb b/lib/cucumber/core/events/test_case_finished.rb index 7d6b7c96..f86880d7 100644 --- a/lib/cucumber/core/events/test_case_finished.rb +++ b/lib/cucumber/core/events/test_case_finished.rb @@ -6,9 +6,22 @@ module Cucumber module Core module Events # Signals that a {Test::Case} has finished executing - class TestCaseFinished < Event.new(:test_case, :result) + class TestCaseFinished < Base # @return [Test::Case] that was executed + attr_reader :test_case + # @return [Test::Result] the result of running the {Test::Step} + attr_reader :result + + def self.event_id + :test_case_finished + end + + def initialize(test_case, result) + @test_case = test_case + @result = result + super() + end end end end diff --git a/lib/cucumber/core/events/test_case_started.rb b/lib/cucumber/core/events/test_case_started.rb index 0143e1e1..e8c12d7b 100644 --- a/lib/cucumber/core/events/test_case_started.rb +++ b/lib/cucumber/core/events/test_case_started.rb @@ -1,13 +1,23 @@ # frozen_string_literal: true -require_relative '../event' +require_relative 'base' module Cucumber module Core module Events # Signals that a {Test::Case} is about to be executed - class TestCaseStarted < Event.new(:test_case) - # @return [Test::Case] the test case to be executed + class TestCaseStarted < Base + # @return [Cucumber::Core::Test::Case] the test case to be executed + attr_reader :test_case + + def self.event_id + :test_case_started + end + + def initialize(test_case) + @test_case = test_case + super() + end end end end diff --git a/lib/cucumber/core/events/test_step_created.rb b/lib/cucumber/core/events/test_step_created.rb index 507b8c26..044033dc 100644 --- a/lib/cucumber/core/events/test_step_created.rb +++ b/lib/cucumber/core/events/test_step_created.rb @@ -1,13 +1,23 @@ # frozen_string_literal: true -require_relative '../event' +require_relative 'base' module Cucumber module Core module Events # Signals that a Test::Step was created from a PickleStep - class TestStepCreated < Event.new(:test_step, :pickle_step) - # The created test step & source pickle step + class TestStepCreated < Base + attr_reader :test_step, :pickle_step + + def self.event_id + :test_step_created + end + + def initialize(test_step, pickle_step) + @test_step = test_step + @pickle_step = pickle_step + super() + end end end end diff --git a/lib/cucumber/core/events/test_step_finished.rb b/lib/cucumber/core/events/test_step_finished.rb index c2915b00..21849e96 100644 --- a/lib/cucumber/core/events/test_step_finished.rb +++ b/lib/cucumber/core/events/test_step_finished.rb @@ -1,14 +1,27 @@ # frozen_string_literal: true -require_relative '../event' +require_relative 'base' module Cucumber module Core module Events # Signals that a {Test::Step} has finished executing - class TestStepFinished < Event.new(:test_step, :result) - # @return [Test::Step] the test step that was executed - # @return [Test::Result] the result of running the {Test::Step} + class TestStepFinished < Base + # @return [Cucumber::Core::Test::Step] the test step that was executed + attr_reader :test_step + + # @return [Cucumber::Core::Test::Result] the result of running the {Cucumber::Core::Test::Step} + attr_reader :result + + def self.event_id + :test_step_finished + end + + def initialize(test_step, result) + @test_step = test_step + @result = result + super() + end end end end diff --git a/lib/cucumber/core/events/test_step_started.rb b/lib/cucumber/core/events/test_step_started.rb index bb952e33..87c000a9 100644 --- a/lib/cucumber/core/events/test_step_started.rb +++ b/lib/cucumber/core/events/test_step_started.rb @@ -1,13 +1,23 @@ # frozen_string_literal: true -require_relative '../event' +require_relative 'base' module Cucumber module Core module Events # Signals that a {Test::Step} is about to be executed - class TestStepStarted < Event.new(:test_step) - # @return [Test::Step] the test step to be executed + class TestStepStarted < Base + # @return [Cucumber::Core::Test::Step] the test step to be executed + attr_reader :test_step + + def self.event_id + :test_step_started + end + + def initialize(test_step) + @test_step = test_step + super() + end end end end diff --git a/spec/cucumber/core/events/base_spec.rb b/spec/cucumber/core/events/base_spec.rb new file mode 100644 index 00000000..1313df4f --- /dev/null +++ b/spec/cucumber/core/events/base_spec.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +describe Cucumber::Core::Events::Base do + subject(:event) { my_event_type.new(1, 2) } + + let(:my_event_type) do + Class.new(described_class) do + def self.event_id + :my_event_type + end + + def initialize(foo, bar) + @foo = foo + @bar = bar + super() + end + end + end + + describe '.event_id' do + it 'must be generated for subclasses' do + expect { described_class.event_id }.to raise_error(RuntimeError).with_message('Must be implemented in subclass') + end + end + + describe '#to_h' do + it 'can be converted to a hash' do + expect(event.to_h).to eq(foo: 1, bar: 2) + end + end + + describe '#event_id' do + it 'shadows the `.event_id` class method' do + expect(event.event_id).to eq(:my_event_type) + end + end +end