From 3120dc157e1a9acd6b30963694daff400bc9b2a8 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 28 Feb 2025 14:11:33 +0000 Subject: [PATCH 01/40] Unrestrict runtime deps --- cucumber.gemspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cucumber.gemspec b/cucumber.gemspec index c33d1b856..897c9c657 100644 --- a/cucumber.gemspec +++ b/cucumber.gemspec @@ -26,8 +26,8 @@ Gem::Specification.new do |s| s.add_dependency 'base64', '~> 0.2' s.add_dependency 'builder', '~> 3.2' s.add_dependency 'cucumber-ci-environment', '> 9', '< 11' - s.add_dependency 'cucumber-core', '~> 15.0' - s.add_dependency 'cucumber-cucumber-expressions', '~> 17.0' + s.add_dependency 'cucumber-core', '> 15', '< 17' + s.add_dependency 'cucumber-cucumber-expressions', '> 17', '< 19' s.add_dependency 'cucumber-html-formatter', '> 20.3', '< 22' s.add_dependency 'diff-lcs', '~> 1.5' s.add_dependency 'logger', '~> 1.6' From 0fac6b52139a4a74d05270be8056202d4477128a Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 28 Feb 2025 14:16:02 +0000 Subject: [PATCH 02/40] Remove rubocop-capybara as its no longer needed or suggested and slightly update rubocop gems --- .rubocop.yml | 1 - cucumber.gemspec | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index a1d842ed0..f91dfd78f 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -5,7 +5,6 @@ inherit_mode: - Exclude require: - - rubocop-capybara - rubocop-packaging - rubocop-rake - rubocop-rspec diff --git a/cucumber.gemspec b/cucumber.gemspec index 897c9c657..1cdfb43ce 100644 --- a/cucumber.gemspec +++ b/cucumber.gemspec @@ -40,11 +40,10 @@ Gem::Specification.new do |s| s.add_development_dependency 'nokogiri', '~> 1.15' s.add_development_dependency 'rake', '~> 13.2' s.add_development_dependency 'rspec', '~> 3.13' - s.add_development_dependency 'rubocop', '~> 1.69.2' - s.add_development_dependency 'rubocop-capybara', '~> 2.21.0' + s.add_development_dependency 'rubocop', '~> 1.71.0' s.add_development_dependency 'rubocop-packaging', '~> 0.5.2' s.add_development_dependency 'rubocop-rake', '~> 0.6.0' - s.add_development_dependency 'rubocop-rspec', '~> 3.3.0' + s.add_development_dependency 'rubocop-rspec', '~> 3.4.0' s.add_development_dependency 'simplecov', '~> 0.22.0' s.add_development_dependency 'webrick', '~> 1.8' From b91f20cc4c8f5aaf799189e52a41165762b512fc Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 28 Feb 2025 14:20:39 +0000 Subject: [PATCH 03/40] Slight tidy to interceptor spec --- spec/cucumber/formatter/interceptor_spec.rb | 49 ++++++++------------- 1 file changed, 18 insertions(+), 31 deletions(-) diff --git a/spec/cucumber/formatter/interceptor_spec.rb b/spec/cucumber/formatter/interceptor_spec.rb index f81cee091..c1cf85d6b 100644 --- a/spec/cucumber/formatter/interceptor_spec.rb +++ b/spec/cucumber/formatter/interceptor_spec.rb @@ -14,13 +14,8 @@ module Formatter end context 'when passed :stderr' do - before :each do - @stderr = $stderr - end - - after :each do - $stderr = @stderr - end + before { @stderr = $stderr } + after { $stderr = @stderr } it 'wraps $stderr' do wrapped = described_class.wrap(:stderr) @@ -31,13 +26,8 @@ module Formatter end context 'when passed :stdout' do - before :each do - @stdout = $stdout - end - - after :each do - $stdout = @stdout - end + before { @stdout = $stdout } + after { $stdout = @stdout } it 'wraps $stdout' do wrapped = described_class.wrap(:stdout) @@ -54,10 +44,7 @@ module Formatter $stdout = pipe @wrapped = described_class.wrap(:stdout) end - - after :each do - $stdout = @stdout - end + after { $stdout = @stdout } it "raises an ArgumentError if it wasn't passed :stderr/:stdout" do expect { described_class.unwrap!(:nonsense) }.to raise_error(ArgumentError) @@ -72,18 +59,17 @@ module Formatter it 'noops if $stdout or $stderr has been overwritten' do $stdout = StringIO.new - pipe = described_class.unwrap! :stdout + pipe = described_class.unwrap!(:stdout) expect(pipe).to eq $stdout $stderr = StringIO.new - pipe = described_class.unwrap! :stderr + pipe = described_class.unwrap!(:stderr) expect(pipe).to eq $stderr end it 'disables the pipe bypass' do buffer = '(::)' - described_class.unwrap! :stdout - + described_class.unwrap!(:stdout) @wrapped.write(buffer) expect(@wrapped.buffer_string).not_to end_with(buffer) @@ -95,8 +81,8 @@ module Formatter let(:pi) { described_class.new(pipe) } it 'writes arguments to the original pipe' do - expect(pipe).to receive(:write).with(buffer) { buffer.size } - expect(pi.write(buffer)).to eq buffer.size + expect(pipe).to receive(:write).with(buffer) { buffer.length } + expect(pi.write(buffer)).to eq(buffer.length) end it 'adds the buffer to its stored output' do @@ -105,20 +91,20 @@ module Formatter pi.write(buffer) expect(pi.buffer_string).not_to be_empty - expect(pi.buffer_string).to eq buffer + expect(pi.buffer_string).to eq(buffer) end end describe '#method_missing' do let(:pi) { described_class.new(pipe) } - it 'passes #tty? to the original pipe' do + it 'passes `#tty?` to the original pipe' do expect(pipe).to receive(:tty?).and_return(true) expect(pi.tty?).to be true end end - describe '#respond_to' do + describe '#respond_to?' do let(:pi) { described_class.wrap(:stderr) } it 'responds to all methods $stderr has' do @@ -129,14 +115,15 @@ module Formatter describe 'when calling `methods` on the stream' do it 'does not raise errors' do allow($stderr).to receive(:puts) - described_class.wrap(:stderr) - expect { $stderr.puts('Oh, hi here !') }.not_to raise_exception(NoMethodError) + + expect { $stderr.puts('Oh, hi here !') }.not_to raise_error end - it 'does not shadow errors when method do not exist on the stream' do + it 'does not shadow errors when the method does not exist on the stream' do described_class.wrap(:stderr) - expect { $stderr.not_really_puts('Oh, hi here !') }.to raise_exception(NoMethodError) + + expect { $stderr.not_really_puts('Oh, hi here !') }.to raise_error(NoMethodError) end end end From 4129214c023d0e4dc7674235f4f7487d8289b58f Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 28 Feb 2025 14:26:38 +0000 Subject: [PATCH 04/40] Update CCK testing version --- CHANGELOG.md | 2 +- README.md | 2 +- cucumber.gemspec | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 219c081cd..c182d4e89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,7 +69,7 @@ All logic contained in [compatibility](./compatibility) ([luke-hill](https://git ## [9.1.0] - 2023-11-14 ### Changed -- First couple of passes of tidying up approximately 40% of the manual fix cops +- First iteration to tidy up approximately 40% of the manual fix cops ([#1739](https://github.com/cucumber/cucumber-ruby/pull/1739) [#1740](https://github.com/cucumber/cucumber-ruby/pull/1740) [#1741](https://github.com/cucumber/cucumber-ruby/pull/1741) [#1742](https://github.com/cucumber/cucumber-ruby/pull/1742) [luke-hill](https://github.com/luke-hill)) - Removed a bunch of example files / sample projects from ancient projects no longer viable ([#1740](https://github.com/cucumber/cucumber-ruby/pull/1740) [luke-hill](https://github.com/luke-hill)) diff --git a/README.md b/README.md index 1833af09f..1e8dba583 100644 --- a/README.md +++ b/README.md @@ -45,10 +45,10 @@ Later in this document, bundler is considered being used so all commands are usi ### Supported platforms +- Ruby 3.3 - Ruby 3.2 - Ruby 3.1 - Ruby 3.0 -- Ruby 2.7 - TruffleRuby 22.0.0+ - JRuby 9.4+ (with [some limitations](https://github.com/cucumber/cucumber-ruby/blob/main/docs/jruby-limitations.md)) diff --git a/cucumber.gemspec b/cucumber.gemspec index 1cdfb43ce..5990302ad 100644 --- a/cucumber.gemspec +++ b/cucumber.gemspec @@ -35,7 +35,7 @@ Gem::Specification.new do |s| s.add_dependency 'multi_test', '~> 1.1' s.add_dependency 'sys-uname', '~> 1.3' - s.add_development_dependency 'cucumber-compatibility-kit', '~> 16.2' + s.add_development_dependency 'cucumber-compatibility-kit', '~> 18.0' # Only needed whilst we are testing the formatters. Can be removed once we remove tests for those s.add_development_dependency 'nokogiri', '~> 1.15' s.add_development_dependency 'rake', '~> 13.2' From 583b9ca9ba14cf47ea28e4c90f59d33d14739d84 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 28 Feb 2025 14:28:24 +0000 Subject: [PATCH 05/40] Downgrade CCK to v17 whilst investigating issues --- cucumber.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cucumber.gemspec b/cucumber.gemspec index 5990302ad..f4d6af62b 100644 --- a/cucumber.gemspec +++ b/cucumber.gemspec @@ -35,7 +35,7 @@ Gem::Specification.new do |s| s.add_dependency 'multi_test', '~> 1.1' s.add_dependency 'sys-uname', '~> 1.3' - s.add_development_dependency 'cucumber-compatibility-kit', '~> 18.0' + s.add_development_dependency 'cucumber-compatibility-kit', '~> 17.0' # Only needed whilst we are testing the formatters. Can be removed once we remove tests for those s.add_development_dependency 'nokogiri', '~> 1.15' s.add_development_dependency 'rake', '~> 13.2' From 90c92338a01bdf8df535896d2760bc0beaaac9a2 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 28 Feb 2025 14:51:25 +0000 Subject: [PATCH 06/40] WIP for adding id to test run id --- lib/cucumber/formatter/message_builder.rb | 13 +++++++-- .../formatter/query/test_run_started.rb | 28 +++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 lib/cucumber/formatter/query/test_run_started.rb diff --git a/lib/cucumber/formatter/message_builder.rb b/lib/cucumber/formatter/message_builder.rb index 6f7fb0bc5..d27876a30 100644 --- a/lib/cucumber/formatter/message_builder.rb +++ b/lib/cucumber/formatter/message_builder.rb @@ -21,6 +21,7 @@ def initialize(config) @pickle_step_by_test_step = Query::PickleStepByTestStep.new(config) @step_definitions_by_test_step = Query::StepDefinitionsByTestStep.new(config) @test_case_started_by_test_case = Query::TestCaseStartedByTestCase.new(config) + @test_run_started = Query::TestRunStarted.new(config) config.on_event :envelope, &method(:on_envelope) config.on_event :gherkin_source_read, &method(:on_gherkin_source_read) @@ -34,6 +35,7 @@ def initialize(config) config.on_event :undefined_parameter_type, &method(:on_undefined_parameter_type) @test_case_by_step_id = {} + @current_test_run_started_id = nil @current_test_case_started_id = nil @current_test_step_id = nil end @@ -149,10 +151,13 @@ def parameter_type_name(step_match_argument) step_match_argument.parameter_type&.name if step_match_argument.respond_to?(:parameter_type) end - def on_test_run_started(*) + def on_test_run_started(event) + @current_test_run_started_id = test_case_started_id(event.test_case) + message = Cucumber::Messages::Envelope.new( test_run_started: Cucumber::Messages::TestRunStarted.new( - timestamp: time_to_timestamp(Time.now) + timestamp: time_to_timestamp(Time.now), + id: event.test_cases.first.id ) ) @@ -266,6 +271,10 @@ def on_undefined_parameter_type(event) def test_case_started_id(test_case) @test_case_started_by_test_case.test_case_started_id_by_test_case(test_case) end + + def test_run_started_id(test_case) + @test_run_started.test_run_id(test_case) + end end end end diff --git a/lib/cucumber/formatter/query/test_run_started.rb b/lib/cucumber/formatter/query/test_run_started.rb new file mode 100644 index 000000000..eedb447ff --- /dev/null +++ b/lib/cucumber/formatter/query/test_run_started.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'cucumber/formatter/errors' + +module Cucumber + module Formatter + module Query + class TestRunStarted + def initialize(config) + @test_run_ids = {} + config.on_event :test_run_started, &method(:on_test_run_started) + end + + def test_run_id(test_case) + return @test_run_ids[test_case.id] if @test_run_ids.key?(test_case.id) + + raise TestCaseUnknownError, "No pickle found for #{test_case.id} }. Known: #{@test_run_ids.keys}" + end + + private + + def on_test_run_started(event) + @test_run_ids[event.test_case.id] = event.pickle.id + end + end + end + end +end From 8e89a5614f12d7c76db6d65a3689a34260581f6d Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Tue, 15 Apr 2025 14:21:46 +0100 Subject: [PATCH 07/40] Fix duplicate testing block --- spec/cucumber/formatter/interceptor_spec.rb | 58 ++++----------------- 1 file changed, 10 insertions(+), 48 deletions(-) diff --git a/spec/cucumber/formatter/interceptor_spec.rb b/spec/cucumber/formatter/interceptor_spec.rb index 6994bc274..6d27044ea 100644 --- a/spec/cucumber/formatter/interceptor_spec.rb +++ b/spec/cucumber/formatter/interceptor_spec.rb @@ -41,8 +41,13 @@ @stdout = $stdout $stdout = pipe @wrapped = described_class.wrap(:stdout) + @stderr = $stderr + end + + after :each do + $stdout = @stdout + $stderr = @stderr end - after { $stdout = @stdout } it "raises an ArgumentError if it wasn't passed :stderr/:stdout" do expect { described_class.unwrap!(:nonsense) }.to raise_error(ArgumentError) @@ -57,12 +62,12 @@ it 'noops if $stdout or $stderr has been overwritten' do $stdout = StringIO.new - pipe = described_class.unwrap!(:stdout) - expect(pipe).to eq $stdout + pipe = described_class.unwrap! :stdout + expect(pipe).to eq($stdout) $stderr = StringIO.new - pipe = described_class.unwrap!(:stderr) - expect(pipe).to eq $stderr + pipe = described_class.unwrap! :stderr + expect(pipe).to eq($stderr) end it 'disables the pipe bypass' do @@ -98,49 +103,6 @@ end end - describe '#unwrap!' do - before :each do - @stdout = $stdout - $stdout = pipe - @wrapped = described_class.wrap(:stdout) - @stderr = $stderr - end - - after :each do - $stdout = @stdout - $stderr = @stderr - end - - it "raises an ArgumentError if it wasn't passed :stderr/:stdout" do - expect { described_class.unwrap!(:nonsense) }.to raise_error(ArgumentError) - end - - it 'resets $stdout when #unwrap! is called' do - interceptor = described_class.unwrap! :stdout - - expect(interceptor).to be_instance_of described_class - expect($stdout).not_to be interceptor - end - - it 'noops if $stdout or $stderr has been overwritten' do - $stdout = StringIO.new - pipe = described_class.unwrap! :stdout - expect(pipe).to eq($stdout) - - $stderr = StringIO.new - pipe = described_class.unwrap! :stderr - expect(pipe).to eq($stderr) - end - - it 'disables the pipe bypass' do - buffer = '(::)' - described_class.unwrap! :stdout - @wrapped.write(buffer) - - expect(@wrapped.buffer_string).not_to end_with(buffer) - end - end - describe '#write' do let(:buffer) { 'Some stupid buffer' } let(:pi) { described_class.new(pipe) } From 64798de6751308f862c1899f6181eccfb2bb3dbb Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Tue, 15 Apr 2025 14:25:34 +0100 Subject: [PATCH 08/40] Run release pipeline tests on 3.4 also --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 90f7be8d0..a35137ec3 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -19,7 +19,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] - ruby: ['3.0', '3.1', '3.2', '3.3'] + ruby: ['3.0', '3.1', '3.2', '3.3', '3.4'] include: - os: ubuntu-latest ruby: jruby-9.4 From 244bc1bc08d4746e7cae425eb23448d5dfcb189c Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Tue, 15 Apr 2025 14:30:26 +0100 Subject: [PATCH 09/40] Update docs --- README.md | 6 +++--- RELEASING.md | 10 ---------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 1e8dba583..605ae8d90 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ Later in this document, bundler is considered being used so all commands are usi ### Supported platforms +- Ruby 3.4 - Ruby 3.3 - Ruby 3.2 - Ruby 3.1 @@ -91,12 +92,11 @@ Feature: Rule Sample Given this will fail When I do an action Then some results should be there - ``` ### Automate your specification -And a file named `steps.rb` in `features/step_definitions` with: +And a file named `rule_steps.rb` in `features/step_definitions` with: ```ruby # features/step_definitions/steps.rb @@ -149,4 +149,4 @@ You can also find documentation on the command line possibilities in [features/d ## Copyright -Copyright (c) Cucumber Ltd. and Contributors. See LICENSE for details. +Copyright (c) Cucumber and Contributors. See LICENSE for details. diff --git a/RELEASING.md b/RELEASING.md index 3a1ef9a25..71e0bb877 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,11 +1 @@ See [.github/RELEASING](https://github.com/cucumber/.github/blob/main/RELEASING.md). - -## When done ## - -Update the cucumber-ruby version in the documentation project: - -* https://github.com/cucumber/docs.cucumber.io - -The cucumber-ruby version for the docs is specified in the docs [versions.yaml](https://github.com/cucumber/docs.cucumber.io/blob/master/data/versions.yaml) - -All done! Hurray! From 4258906db7c66389026421f8babef5134f7fd823 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Tue, 15 Apr 2025 14:30:33 +0100 Subject: [PATCH 10/40] Minor simplification to main runtime --- lib/cucumber/cli/main.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/cucumber/cli/main.rb b/lib/cucumber/cli/main.rb index 42ffa6bfb..a550ac984 100644 --- a/lib/cucumber/cli/main.rb +++ b/lib/cucumber/cli/main.rb @@ -93,8 +93,7 @@ def trap_interrupt def runtime(existing_runtime) return Runtime.new(configuration) unless existing_runtime - existing_runtime.configure(configuration) - existing_runtime + existing_runtime.tap { |runtime| runtime.configure(configuration) } end end end From 0857499a034bac5ab6d82ece36db71d3b53becb4 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Tue, 15 Apr 2025 14:32:25 +0100 Subject: [PATCH 11/40] Fix bug with deprecator message --- lib/cucumber/deprecate.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cucumber/deprecate.rb b/lib/cucumber/deprecate.rb index e0bc75177..b8d1217dd 100644 --- a/lib/cucumber/deprecate.rb +++ b/lib/cucumber/deprecate.rb @@ -6,7 +6,7 @@ module Cucumber def self.deprecate(message, method, remove_after_version) $stderr.puts( - "\nWARNING: ##{method} is deprecated" \ + "\nWARNING: #{method} is deprecated" \ " and will be removed after version #{remove_after_version}. #{message}.\n" \ "(Called from #{caller(3..3).first})" ) From 21fea7a0600c59f9f101276d4c250fecf7ef25f6 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Tue, 15 Apr 2025 14:37:13 +0100 Subject: [PATCH 12/40] Fix deprecator spec --- spec/cucumber/deprecate_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/cucumber/deprecate_spec.rb b/spec/cucumber/deprecate_spec.rb index a71600a16..3796c1182 100644 --- a/spec/cucumber/deprecate_spec.rb +++ b/spec/cucumber/deprecate_spec.rb @@ -7,10 +7,10 @@ module Cucumber it 'outputs a message to $stderr' do allow($stderr).to receive(:puts) - Cucumber.deprecate('Use some_method instead', 'someMethod', '1.0.0') + Cucumber.deprecate('Use #some_other_method instead', '#some_method', '1.0.0') expect($stderr).to have_received(:puts).with( a_string_including( - 'WARNING: #someMethod is deprecated and will be removed after version 1.0.0. Use some_method instead.' + 'WARNING: #some_method is deprecated and will be removed after version 1.0.0. Use #some_other_method instead.' ) ) end From bdb9be1772a371e0cc3d343391b6180d89fc1b39 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Thu, 8 May 2025 16:41:22 +0100 Subject: [PATCH 13/40] Minor tidy to backtrace filter --- lib/cucumber/formatter/backtrace_filter.rb | 31 +++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/lib/cucumber/formatter/backtrace_filter.rb b/lib/cucumber/formatter/backtrace_filter.rb index d35d2b014..3558cb050 100644 --- a/lib/cucumber/formatter/backtrace_filter.rb +++ b/lib/cucumber/formatter/backtrace_filter.rb @@ -34,7 +34,6 @@ def initialize(exception) def exception return @exception if ::Cucumber.use_full_backtrace - pwd_pattern = /#{::Regexp.escape(::Dir.pwd)}\//m backtrace = @exception.backtrace.map { |line| line.gsub(pwd_pattern, './') } filtered = (backtrace || []).reject do |line| @@ -42,16 +41,36 @@ def exception end if ::ENV['CUCUMBER_TRUNCATE_OUTPUT'] - # Strip off file locations - regexp = RUBY_VERSION >= '3.4' ? /(.*):in '/ : /(.*):in `/ filtered = filtered.map do |line| - match = regexp.match(line) + # Strip off file locations + match = regexp_filter.match(line) match ? match[1] : line end end - @exception.set_backtrace(filtered) - @exception + @exception.tap { |e| e.set_backtrace(filtered) } + end + + private + + def pwd_pattern + /#{::Regexp.escape(::Dir.pwd)}\//m + end + + def regexp_filter + ruby_greater_than_three_four? ? three_four_filter : three_three_filter + end + + def ruby_greater_than_three_four? + RUBY_VERSION.to_f >= 3.4 + end + + def three_four_filter + /(.*):in '/ + end + + def three_three_filter + /(.*):in `/ end end end From a033db00e1d21b66f1f87c133cd67b0a09f3aa4f Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Thu, 8 May 2025 17:05:15 +0100 Subject: [PATCH 14/40] Change ID generation to be much simpler - Add this to output envelope during the test run started event --- lib/cucumber/formatter/message_builder.rb | 5 +++-- lib/cucumber/formatter/query/test_run_started.rb | 15 +++------------ 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/lib/cucumber/formatter/message_builder.rb b/lib/cucumber/formatter/message_builder.rb index d27876a30..b50a2fe24 100644 --- a/lib/cucumber/formatter/message_builder.rb +++ b/lib/cucumber/formatter/message_builder.rb @@ -7,6 +7,7 @@ require 'cucumber/formatter/query/pickle_step_by_test_step' require 'cucumber/formatter/query/step_definitions_by_test_step' require 'cucumber/formatter/query/test_case_started_by_test_case' +require 'cucumber/formatter/query/test_run_started' module Cucumber module Formatter @@ -152,12 +153,12 @@ def parameter_type_name(step_match_argument) end def on_test_run_started(event) - @current_test_run_started_id = test_case_started_id(event.test_case) + @current_test_run_started_id = @test_run_started.id message = Cucumber::Messages::Envelope.new( test_run_started: Cucumber::Messages::TestRunStarted.new( timestamp: time_to_timestamp(Time.now), - id: event.test_cases.first.id + id: @current_test_run_started_id ) ) diff --git a/lib/cucumber/formatter/query/test_run_started.rb b/lib/cucumber/formatter/query/test_run_started.rb index eedb447ff..6c63dbd39 100644 --- a/lib/cucumber/formatter/query/test_run_started.rb +++ b/lib/cucumber/formatter/query/test_run_started.rb @@ -7,20 +7,11 @@ module Formatter module Query class TestRunStarted def initialize(config) - @test_run_ids = {} - config.on_event :test_run_started, &method(:on_test_run_started) + @config = config end - def test_run_id(test_case) - return @test_run_ids[test_case.id] if @test_run_ids.key?(test_case.id) - - raise TestCaseUnknownError, "No pickle found for #{test_case.id} }. Known: #{@test_run_ids.keys}" - end - - private - - def on_test_run_started(event) - @test_run_ids[event.test_case.id] = event.pickle.id + def id + @id ||= @config.id_generator.new_id end end end From 392292f64077f6b5488b8f9109dfd85e56b5567c Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Thu, 8 May 2025 17:10:32 +0100 Subject: [PATCH 15/40] Remove redundant input event when finding / generating test run id --- lib/cucumber/formatter/message_builder.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/cucumber/formatter/message_builder.rb b/lib/cucumber/formatter/message_builder.rb index b50a2fe24..4915c5c0b 100644 --- a/lib/cucumber/formatter/message_builder.rb +++ b/lib/cucumber/formatter/message_builder.rb @@ -152,7 +152,7 @@ def parameter_type_name(step_match_argument) step_match_argument.parameter_type&.name if step_match_argument.respond_to?(:parameter_type) end - def on_test_run_started(event) + def on_test_run_started(*) @current_test_run_started_id = @test_run_started.id message = Cucumber::Messages::Envelope.new( @@ -272,10 +272,6 @@ def on_undefined_parameter_type(event) def test_case_started_id(test_case) @test_case_started_by_test_case.test_case_started_id_by_test_case(test_case) end - - def test_run_started_id(test_case) - @test_run_started.test_run_id(test_case) - end end end end From 3ecca70106ca96c7044b1a974b69cb38393b596b Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Thu, 8 May 2025 17:23:22 +0100 Subject: [PATCH 16/40] Add Test run ID to test case ready event Change order of broadcast such that test case ready comes after test run started --- lib/cucumber/formatter/message_builder.rb | 3 ++- lib/cucumber/runtime.rb | 4 ++-- spec/cucumber/formatter/spec_helper.rb | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/cucumber/formatter/message_builder.rb b/lib/cucumber/formatter/message_builder.rb index 4915c5c0b..6e9550493 100644 --- a/lib/cucumber/formatter/message_builder.rb +++ b/lib/cucumber/formatter/message_builder.rb @@ -97,7 +97,8 @@ def on_test_case_ready(event) test_case: Cucumber::Messages::TestCase.new( id: event.test_case.id, pickle_id: @pickle_by_test.pickle_id(event.test_case), - test_steps: event.test_case.test_steps.map { |step| test_step_to_message(step) } + test_steps: event.test_case.test_steps.map { |step| test_step_to_message(step) }, + test_run_started_id: @current_test_run_started_id ) ) diff --git a/lib/cucumber/runtime.rb b/lib/cucumber/runtime.rb index 80bd2e956..4ee9c8bc4 100644 --- a/lib/cucumber/runtime.rb +++ b/lib/cucumber/runtime.rb @@ -257,8 +257,6 @@ def filters filters << Filters::ApplyAroundHooks.new(@support_code) end - filters << Filters::BroadcastTestCaseReadyEvent.new(@configuration) - unless configuration.dry_run? filters << Filters::BroadcastTestRunStartedEvent.new(@configuration) filters << Filters::Quit.new @@ -266,6 +264,8 @@ def filters # need to do this last so it becomes the first test step filters << Filters::PrepareWorld.new(self) end + + filters << Filters::BroadcastTestCaseReadyEvent.new(@configuration) end end diff --git a/spec/cucumber/formatter/spec_helper.rb b/spec/cucumber/formatter/spec_helper.rb index 7797fab01..85b7ad34b 100644 --- a/spec/cucumber/formatter/spec_helper.rb +++ b/spec/cucumber/formatter/spec_helper.rb @@ -42,8 +42,8 @@ def filters Filters::ApplyBeforeHooks.new(actual_runtime.support_code), Filters::ApplyAfterHooks.new(actual_runtime.support_code), Filters::ApplyAroundHooks.new(actual_runtime.support_code), - Filters::BroadcastTestCaseReadyEvent.new(actual_runtime.configuration), Filters::BroadcastTestRunStartedEvent.new(actual_runtime.configuration), + Filters::BroadcastTestCaseReadyEvent.new(actual_runtime.configuration), Filters::PrepareWorld.new(actual_runtime) ] end From 6d3851791baf70cb16f1c68b788229fe4eab580a Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Thu, 8 May 2025 17:25:35 +0100 Subject: [PATCH 17/40] Add test run started id to testrunfinished message --- lib/cucumber/formatter/message_builder.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/cucumber/formatter/message_builder.rb b/lib/cucumber/formatter/message_builder.rb index 6e9550493..42caa087f 100644 --- a/lib/cucumber/formatter/message_builder.rb +++ b/lib/cucumber/formatter/message_builder.rb @@ -252,7 +252,8 @@ def on_test_run_finished(event) message = Cucumber::Messages::Envelope.new( test_run_finished: Cucumber::Messages::TestRunFinished.new( timestamp: time_to_timestamp(Time.now), - success: event.success + success: event.success, + test_run_started_id: @current_test_run_started_id ) ) From b783edb6c3d486b1d63230dfcb2cd375c073c277 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Thu, 8 May 2025 17:53:02 +0100 Subject: [PATCH 18/40] Hook refactors Rename phase to type for type of hook Add hook type to envelope creation Ensure enum conversion is adherent to message enum validation (Around hook is the outlier here - InstallPlugin can be converted adherently) --- lib/cucumber/glue/dsl.rb | 4 ++-- lib/cucumber/glue/hook.rb | 17 ++++++++++++++++- lib/cucumber/glue/registry_and_more.rb | 14 +++++++------- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/lib/cucumber/glue/dsl.rb b/lib/cucumber/glue/dsl.rb index 5c6d62063..b713cbd42 100644 --- a/lib/cucumber/glue/dsl.rb +++ b/lib/cucumber/glue/dsl.rb @@ -18,8 +18,8 @@ def build_rb_world_factory(world_modules, namespaced_world_modules, proc) @rb_language.build_rb_world_factory(world_modules, namespaced_world_modules, proc) end - def register_rb_hook(phase, tag_names, proc, name: nil) - @rb_language.register_rb_hook(phase, tag_names, proc, name: name) + def register_rb_hook(type, tag_names, proc, name: nil) + @rb_language.register_rb_hook(type, tag_names, proc, name: name) end def define_parameter_type(parameter_type) diff --git a/lib/cucumber/glue/hook.rb b/lib/cucumber/glue/hook.rb index d1a1694c3..bdbe4114d 100644 --- a/lib/cucumber/glue/hook.rb +++ b/lib/cucumber/glue/hook.rb @@ -28,12 +28,13 @@ def invoke(pseudo_method, arguments, &block) ) end - def to_envelope + def to_envelope(type) Cucumber::Messages::Envelope.new( hook: Cucumber::Messages::Hook.new( id: id, name: name, tag_expression: tag_expressions.empty? ? nil : tag_expressions.join(' '), + type: hook_type_to_enum_value[type.to_sym], source_reference: Cucumber::Messages::SourceReference.new( uri: location.file, location: Cucumber::Messages::Location.new( @@ -43,6 +44,20 @@ def to_envelope ) ) end + + private + + def hook_type_to_enum_value + { + before: 'BEFORE_TEST_CASE', + after: 'AFTER_TEST_CASE', + around: nil, # This needs deleting and removing from cucumber-ruby in v11 + after_step: 'AFTER_TEST_STEP', + install_plugin: 'BEFORE_TEST_RUN', + before_all: 'BEFORE_TEST_RUN', + after_all: 'AFTER_TEST_RUN' + } + end end end end diff --git a/lib/cucumber/glue/registry_and_more.rb b/lib/cucumber/glue/registry_and_more.rb index 5af26d17e..349977a59 100644 --- a/lib/cucumber/glue/registry_and_more.rb +++ b/lib/cucumber/glue/registry_and_more.rb @@ -85,9 +85,9 @@ def step_matches(name_to_match) end end - def register_rb_hook(phase, tag_expressions, proc, name: nil) - hook = add_hook(phase, Hook.new(@configuration.id_generator.new_id, self, tag_expressions, proc, name: name)) - @configuration.notify :envelope, hook.to_envelope + def register_rb_hook(type, tag_expressions, proc, name: nil) + hook = add_hook(type, Hook.new(@configuration.id_generator.new_id, self, tag_expressions, proc, name: name)) + @configuration.notify(:envelope, hook.to_envelope(type)) hook end @@ -166,8 +166,8 @@ def after_all end end - def add_hook(phase, hook) - hooks[phase.to_sym] << hook + def add_hook(type, hook) + hooks[type.to_sym] << hook hook end @@ -175,8 +175,8 @@ def clear_hooks @hooks = nil end - def hooks_for(phase, scenario) # :nodoc: - hooks[phase.to_sym].select { |hook| scenario.accept_hook?(hook) } + def hooks_for(type, scenario) # :nodoc: + hooks[type.to_sym].select { |hook| scenario.accept_hook?(hook) } end def create_expression(string_or_regexp) From 4b6a5b48de6ca490c6b4381821996ba9257a4f97 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 16 May 2025 17:18:35 +0100 Subject: [PATCH 19/40] Downgrade CCK back to 16.2 and hardcode cck tests to just retry --- compatibility/cck_spec.rb | 2 +- cucumber.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compatibility/cck_spec.rb b/compatibility/cck_spec.rb index 0aa162cd6..9df43b18f 100644 --- a/compatibility/cck_spec.rb +++ b/compatibility/cck_spec.rb @@ -8,7 +8,7 @@ describe 'Cucumber Compatibility Kit', type: :feature, cck: true do let(:cucumber_command) { 'bundle exec cucumber --publish-quiet --profile none --format message' } - CCK::Examples.gherkin.each do |example_name| + ['retry'].each do |example_name| describe "'#{example_name}' example" do include_examples 'cucumber compatibility kit' do let(:example) { example_name } diff --git a/cucumber.gemspec b/cucumber.gemspec index f4d6af62b..1cdfb43ce 100644 --- a/cucumber.gemspec +++ b/cucumber.gemspec @@ -35,7 +35,7 @@ Gem::Specification.new do |s| s.add_dependency 'multi_test', '~> 1.1' s.add_dependency 'sys-uname', '~> 1.3' - s.add_development_dependency 'cucumber-compatibility-kit', '~> 17.0' + s.add_development_dependency 'cucumber-compatibility-kit', '~> 16.2' # Only needed whilst we are testing the formatters. Can be removed once we remove tests for those s.add_development_dependency 'nokogiri', '~> 1.15' s.add_development_dependency 'rake', '~> 13.2' From 88ea676d5a78fea6b9879d796388ac7339468a38 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 16 May 2025 17:23:58 +0100 Subject: [PATCH 20/40] Recommit v17 of CCK --- cucumber.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cucumber.gemspec b/cucumber.gemspec index 1cdfb43ce..f4d6af62b 100644 --- a/cucumber.gemspec +++ b/cucumber.gemspec @@ -35,7 +35,7 @@ Gem::Specification.new do |s| s.add_dependency 'multi_test', '~> 1.1' s.add_dependency 'sys-uname', '~> 1.3' - s.add_development_dependency 'cucumber-compatibility-kit', '~> 16.2' + s.add_development_dependency 'cucumber-compatibility-kit', '~> 17.0' # Only needed whilst we are testing the formatters. Can be removed once we remove tests for those s.add_development_dependency 'nokogiri', '~> 1.15' s.add_development_dependency 'rake', '~> 13.2' From 9a2bc8ed6e249346989ec6917b83030a9e6baaaa Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 16 May 2025 17:26:15 +0100 Subject: [PATCH 21/40] Experiment move TestCaseReadyEvent lower down --- lib/cucumber/filters/broadcast_test_case_ready_event.rb | 2 +- lib/cucumber/runtime.rb | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/cucumber/filters/broadcast_test_case_ready_event.rb b/lib/cucumber/filters/broadcast_test_case_ready_event.rb index 15675803a..378a83e5d 100644 --- a/lib/cucumber/filters/broadcast_test_case_ready_event.rb +++ b/lib/cucumber/filters/broadcast_test_case_ready_event.rb @@ -4,7 +4,7 @@ module Cucumber module Filters class BroadcastTestCaseReadyEvent < Core::Filter.new(:config) def test_case(test_case) - config.notify :test_case_ready, test_case + config.notify(:test_case_ready, test_case) test_case.describe_to(receiver) end end diff --git a/lib/cucumber/runtime.rb b/lib/cucumber/runtime.rb index 4ee9c8bc4..4575bae85 100644 --- a/lib/cucumber/runtime.rb +++ b/lib/cucumber/runtime.rb @@ -255,17 +255,17 @@ def filters filters << Filters::ApplyBeforeHooks.new(@support_code) filters << Filters::ApplyAfterHooks.new(@support_code) filters << Filters::ApplyAroundHooks.new(@support_code) + filters << Filters::BroadcastTestRunStartedEvent.new(@configuration) + filters << Filters::Quit.new end + filters << Filters::BroadcastTestCaseReadyEvent.new(@configuration) + unless configuration.dry_run? - filters << Filters::BroadcastTestRunStartedEvent.new(@configuration) - filters << Filters::Quit.new filters << Filters::Retry.new(@configuration) # need to do this last so it becomes the first test step filters << Filters::PrepareWorld.new(self) end - - filters << Filters::BroadcastTestCaseReadyEvent.new(@configuration) end end From cf3d7179106a6401bf85a2ab87ab2ecc45037012 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 16 May 2025 17:28:01 +0100 Subject: [PATCH 22/40] Re-run all CCK tests again; --- compatibility/cck_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compatibility/cck_spec.rb b/compatibility/cck_spec.rb index 9df43b18f..0aa162cd6 100644 --- a/compatibility/cck_spec.rb +++ b/compatibility/cck_spec.rb @@ -8,7 +8,7 @@ describe 'Cucumber Compatibility Kit', type: :feature, cck: true do let(:cucumber_command) { 'bundle exec cucumber --publish-quiet --profile none --format message' } - ['retry'].each do |example_name| + CCK::Examples.gherkin.each do |example_name| describe "'#{example_name}' example" do include_examples 'cucumber compatibility kit' do let(:example) { example_name } From 9f0ba59085f112912a594e888de70c86155b2ab5 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 16 May 2025 19:00:27 +0100 Subject: [PATCH 23/40] Change to CCK steps for v18 conformance --- .../features/attachments/attachments_steps.rb | 8 ------- .../examples-tables-attachment_steps.rb | 13 ++++++++++++ .../hooks-attachment_steps.rb | 17 +++++++++++++++ .../hooks-conditional_steps.rb | 21 +++++++++++++++++++ .../features/hooks-named/hooks-named_steps.rb | 13 ++++++++++++ compatibility/features/hooks/hooks_steps.rb | 16 -------------- 6 files changed, 64 insertions(+), 24 deletions(-) create mode 100644 compatibility/features/examples-tables-attachment/examples-tables-attachment_steps.rb create mode 100644 compatibility/features/hooks-attachment/hooks-attachment_steps.rb create mode 100644 compatibility/features/hooks-conditional/hooks-conditional_steps.rb create mode 100644 compatibility/features/hooks-named/hooks-named_steps.rb diff --git a/compatibility/features/attachments/attachments_steps.rb b/compatibility/features/attachments/attachments_steps.rb index 984b44f2d..e5979326f 100644 --- a/compatibility/features/attachments/attachments_steps.rb +++ b/compatibility/features/attachments/attachments_steps.rb @@ -25,14 +25,6 @@ def cck_asset_path attach(data, media_type) end -When('a JPEG image is attached') do - attach(File.open("#{cck_asset_path}/cucumber.jpeg"), 'image/jpeg') -end - -When('a PNG image is attached') do - attach(File.open("#{cck_asset_path}/cucumber.png"), 'image/png') -end - When('a PDF document is attached and renamed') do attach(File.open("#{cck_asset_path}/document.pdf"), 'document/pdf', 'renamed.pdf') end diff --git a/compatibility/features/examples-tables-attachment/examples-tables-attachment_steps.rb b/compatibility/features/examples-tables-attachment/examples-tables-attachment_steps.rb new file mode 100644 index 000000000..274397a01 --- /dev/null +++ b/compatibility/features/examples-tables-attachment/examples-tables-attachment_steps.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +def cck_asset_path + "#{Gem.loaded_specs['cucumber-compatibility-kit'].full_gem_path}/features/examples-tables-attachment" +end + +When('a JPEG image is attached') do + attach(File.open("#{cck_asset_path}/cucumber.jpeg"), 'image/jpeg') +end + +When('a PNG image is attached') do + attach(File.open("#{cck_asset_path}/cucumber.png"), 'image/png') +end diff --git a/compatibility/features/hooks-attachment/hooks-attachment_steps.rb b/compatibility/features/hooks-attachment/hooks-attachment_steps.rb new file mode 100644 index 000000000..7e5361e0c --- /dev/null +++ b/compatibility/features/hooks-attachment/hooks-attachment_steps.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +def cck_asset_path + "#{Gem.loaded_specs['cucumber-compatibility-kit'].full_gem_path}/features/hooks-attachment" +end + +Before do + attach(File.open("#{cck_asset_path}/cucumber.svg"), 'image/svg+xml') +end + +After do + attach(File.open("#{cck_asset_path}/cucumber.svg"), 'image/svg+xml') +end + +When('a step passes') do + # no-op +end diff --git a/compatibility/features/hooks-conditional/hooks-conditional_steps.rb b/compatibility/features/hooks-conditional/hooks-conditional_steps.rb new file mode 100644 index 000000000..ab1dbf00d --- /dev/null +++ b/compatibility/features/hooks-conditional/hooks-conditional_steps.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +Before('@passing-hook') do + # no-op +end + +Before('@fail-before') do + raise 'Exception in conditional hook' +end + +When('a step passes') do + # no-op +end + +After('@passing-hook') do + # no-op +end + +After('@fail-after') do + raise 'Exception in conditional hook' +end diff --git a/compatibility/features/hooks-named/hooks-named_steps.rb b/compatibility/features/hooks-named/hooks-named_steps.rb new file mode 100644 index 000000000..b5971799c --- /dev/null +++ b/compatibility/features/hooks-named/hooks-named_steps.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +Before(name: 'A named before hook') do + # no-op +end + +When('a step passes') do + # no-op +end + +After(name: 'A named after hook') do + # no-op +end diff --git a/compatibility/features/hooks/hooks_steps.rb b/compatibility/features/hooks/hooks_steps.rb index 2eb59a0ea..fa26531e9 100644 --- a/compatibility/features/hooks/hooks_steps.rb +++ b/compatibility/features/hooks/hooks_steps.rb @@ -4,14 +4,6 @@ # no-op end -Before(name: 'A named hook') do - # no-op -end - -def cck_asset_path - "#{Gem.loaded_specs['cucumber-compatibility-kit'].full_gem_path}/features/hooks" -end - When('a step passes') do # no-op end @@ -23,11 +15,3 @@ def cck_asset_path After do # no-op end - -After('@some-tag or @some-other-tag') do - raise 'Exception in conditional hook' -end - -After('@with-attachment') do - attach(File.open("#{cck_asset_path}/cucumber.svg"), 'image/svg+xml') -end From fc670f9e676ddc6c0de247f4088b2a7f0aa7fbde Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 16 May 2025 19:07:13 +0100 Subject: [PATCH 24/40] Update to v18 of cck --- cucumber.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cucumber.gemspec b/cucumber.gemspec index f4d6af62b..5990302ad 100644 --- a/cucumber.gemspec +++ b/cucumber.gemspec @@ -35,7 +35,7 @@ Gem::Specification.new do |s| s.add_dependency 'multi_test', '~> 1.1' s.add_dependency 'sys-uname', '~> 1.3' - s.add_development_dependency 'cucumber-compatibility-kit', '~> 17.0' + s.add_development_dependency 'cucumber-compatibility-kit', '~> 18.0' # Only needed whilst we are testing the formatters. Can be removed once we remove tests for those s.add_development_dependency 'nokogiri', '~> 1.15' s.add_development_dependency 'rake', '~> 13.2' From ec79d5f74c666d3f825e9718f51574f1bd985aec Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 16 May 2025 19:07:18 +0100 Subject: [PATCH 25/40] Triage one failing test --- compatibility/cck_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compatibility/cck_spec.rb b/compatibility/cck_spec.rb index 0aa162cd6..6242210e5 100644 --- a/compatibility/cck_spec.rb +++ b/compatibility/cck_spec.rb @@ -8,7 +8,7 @@ describe 'Cucumber Compatibility Kit', type: :feature, cck: true do let(:cucumber_command) { 'bundle exec cucumber --publish-quiet --profile none --format message' } - CCK::Examples.gherkin.each do |example_name| + ['attachments'].each do |example_name| describe "'#{example_name}' example" do include_examples 'cucumber compatibility kit' do let(:example) { example_name } From e7ae78af59cc64d7b71b332c23f57a8923394e13 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 16 May 2025 19:07:32 +0100 Subject: [PATCH 26/40] Bugfix wrong media type --- compatibility/features/attachments/attachments_steps.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compatibility/features/attachments/attachments_steps.rb b/compatibility/features/attachments/attachments_steps.rb index e5979326f..b839bbaf0 100644 --- a/compatibility/features/attachments/attachments_steps.rb +++ b/compatibility/features/attachments/attachments_steps.rb @@ -26,7 +26,7 @@ def cck_asset_path end When('a PDF document is attached and renamed') do - attach(File.open("#{cck_asset_path}/document.pdf"), 'document/pdf', 'renamed.pdf') + attach(File.open("#{cck_asset_path}/document.pdf"), 'application/pdf', 'renamed.pdf') end When('a link to {string} is attached') do |link| From deae01814a81faa966bbef41cfa5ca2574de6557 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 16 May 2025 19:18:58 +0100 Subject: [PATCH 27/40] Add in deprecated steps for CCK conformance (currently) --- .../features/attachments/attachments_steps.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/compatibility/features/attachments/attachments_steps.rb b/compatibility/features/attachments/attachments_steps.rb index b839bbaf0..95de903f7 100644 --- a/compatibility/features/attachments/attachments_steps.rb +++ b/compatibility/features/attachments/attachments_steps.rb @@ -25,6 +25,16 @@ def cck_asset_path attach(data, media_type) end +# Deprecated - not used - should be removed +When('a JPEG image is attached') do + attach(File.open("#{cck_asset_path}/cucumber.jpeg"), 'image/jpeg') +end + +# Deprecated - not used - should be removed +When('a PNG image is attached') do + attach(File.open("#{cck_asset_path}/cucumber.png"), 'image/png') +end + When('a PDF document is attached and renamed') do attach(File.open("#{cck_asset_path}/document.pdf"), 'application/pdf', 'renamed.pdf') end From 59d450be4733ec70d03257169eeb8a8735a67346 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 16 May 2025 19:32:49 +0100 Subject: [PATCH 28/40] Add in truffleruby guard for some tests --- spec/cucumber/glue/step_definition_spec.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/spec/cucumber/glue/step_definition_spec.rb b/spec/cucumber/glue/step_definition_spec.rb index ab557763d..3b0b5680e 100644 --- a/spec/cucumber/glue/step_definition_spec.rb +++ b/spec/cucumber/glue/step_definition_spec.rb @@ -57,6 +57,12 @@ def step_match(text) end context 'when mapping to world methods' do + before do + if RUBY_ENGINE.start_with?('truffleruby') + skip('These tests are problematic on truffleruby. See: https://github.com/oracle/truffleruby/issues/3870') + end + end + it 'calls a method on the world when specified with a symbol' do expect(registry.current_world).to receive(:with_symbol) From 8e7f9e82966dd5398a741d1c21080c008ec0bd96 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 16 May 2025 19:33:31 +0100 Subject: [PATCH 29/40] Hard code the truffleruby test to use v24 --- .github/workflows/test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 51c25fd78..f5545bede 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -22,7 +22,7 @@ jobs: - os: ubuntu-latest ruby: jruby-9.4 - os: ubuntu-latest - ruby: truffleruby-head + ruby: truffleruby-24 runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 From 9027061dea69ba3b5f2368ec4a56ec9efed9a0c6 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 16 May 2025 19:34:13 +0100 Subject: [PATCH 30/40] Add truffleruby 24 into release pipeline --- .github/workflows/release.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a35137ec3..2226344d3 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -23,6 +23,8 @@ jobs: include: - os: ubuntu-latest ruby: jruby-9.4 + - os: ubuntu-latest + ruby: truffleruby-24 runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 From cfc7e86b0a2295a14bac79080e5be49688985c9a Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 16 May 2025 19:53:20 +0100 Subject: [PATCH 31/40] Fix rubocop --- spec/cucumber/glue/step_definition_spec.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/spec/cucumber/glue/step_definition_spec.rb b/spec/cucumber/glue/step_definition_spec.rb index 3b0b5680e..e9d26eb77 100644 --- a/spec/cucumber/glue/step_definition_spec.rb +++ b/spec/cucumber/glue/step_definition_spec.rb @@ -58,9 +58,7 @@ def step_match(text) context 'when mapping to world methods' do before do - if RUBY_ENGINE.start_with?('truffleruby') - skip('These tests are problematic on truffleruby. See: https://github.com/oracle/truffleruby/issues/3870') - end + skip('These tests are problematic on truffleruby. See: https://github.com/oracle/truffleruby/issues/3870') if RUBY_ENGINE.start_with?('truffleruby') end it 'calls a method on the world when specified with a symbol' do From b70c54337602bebf33acf3f0c251566de88407db Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 16 May 2025 19:56:06 +0100 Subject: [PATCH 32/40] Compress a few lines down --- spec/cucumber/glue/step_definition_spec.rb | 32 +++++++--------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/spec/cucumber/glue/step_definition_spec.rb b/spec/cucumber/glue/step_definition_spec.rb index e9d26eb77..0a7eb805a 100644 --- a/spec/cucumber/glue/step_definition_spec.rb +++ b/spec/cucumber/glue/step_definition_spec.rb @@ -31,12 +31,8 @@ def step_match(text) end it 'allows calling of other steps' do - dsl.Given(/Outside/) do - step 'Inside' - end - dsl.Given(/Inside/) do - @@inside = true - end + dsl.Given('Outside') { step 'Inside' } + dsl.Given('Inside') { @@inside = true } run_step 'Outside' @@ -44,12 +40,8 @@ def step_match(text) end it 'allows calling of other steps with inline arg' do - dsl.Given(/Outside/) do - step 'Inside', table([['inside']]) - end - dsl.Given(/Inside/) do |t| - @@inside = t.raw[0][0] - end + dsl.Given('Outside') { step 'Inside', table([['inside']]) } + dsl.Given('Inside') { @@inside = t.raw[0][0] } run_step 'Outside' @@ -94,15 +86,14 @@ def step_match(text) end it 'has the correct location' do - dsl.Given(/With symbol/, :with_symbol) - expect(step_match('With symbol').file_colon_line).to eq "spec/cucumber/glue/step_definition_spec.rb:#{__LINE__ - 1}" + dsl.Given('With symbol', :with_symbol) + + expect(step_match('With symbol').file_colon_line).to eq("spec/cucumber/glue/step_definition_spec.rb:#{__LINE__ - 2}") end end it 'raises UndefinedDynamicStep when inside step is not defined' do - dsl.Given(/Outside/) do - step 'Inside' - end + dsl.Given('Outside') { step 'Inside' } expect { run_step 'Outside' }.to raise_error(Cucumber::UndefinedDynamicStep) end @@ -143,16 +134,13 @@ def step_match(text) end it 'allows forced pending' do - dsl.Given(/Outside/) do - pending('Do me!') - end + dsl.Given('Outside') { pending('Do me!') } expect { run_step 'Outside' }.to raise_error(Cucumber::Pending, 'Do me!') end it 'raises ArityMismatchError when the number of capture groups differs from the number of step arguments' do - dsl.Given(/No group: \w+/) do |arg| - end + dsl.Given(/No group: \w+/) { |_arg| } expect { run_step 'No group: arg' }.to raise_error(Cucumber::Glue::ArityMismatchError) end From 62a8fa48ac02df23630bf08edf5474cd5b484a9b Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Wed, 21 May 2025 15:49:03 +0100 Subject: [PATCH 33/40] Re-test the whole of the CCK again --- compatibility/cck_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compatibility/cck_spec.rb b/compatibility/cck_spec.rb index 6242210e5..0aa162cd6 100644 --- a/compatibility/cck_spec.rb +++ b/compatibility/cck_spec.rb @@ -8,7 +8,7 @@ describe 'Cucumber Compatibility Kit', type: :feature, cck: true do let(:cucumber_command) { 'bundle exec cucumber --publish-quiet --profile none --format message' } - ['attachments'].each do |example_name| + CCK::Examples.gherkin.each do |example_name| describe "'#{example_name}' example" do include_examples 'cucumber compatibility kit' do let(:example) { example_name } From a38c2d9f0ba91701040b240e3142adff7cae760e Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Wed, 21 May 2025 15:49:48 +0100 Subject: [PATCH 34/40] Clarify deprecation notice for CCK attachment steps --- compatibility/features/attachments/attachments_steps.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compatibility/features/attachments/attachments_steps.rb b/compatibility/features/attachments/attachments_steps.rb index 95de903f7..b7a8025ed 100644 --- a/compatibility/features/attachments/attachments_steps.rb +++ b/compatibility/features/attachments/attachments_steps.rb @@ -25,12 +25,12 @@ def cck_asset_path attach(data, media_type) end -# Deprecated - not used - should be removed +# To be removed in CCK v19 alongside removing duplicate scenarios: https://github.com/cucumber/compatibility-kit/pull/127 When('a JPEG image is attached') do attach(File.open("#{cck_asset_path}/cucumber.jpeg"), 'image/jpeg') end -# Deprecated - not used - should be removed +# To be removed in CCK v19 alongside removing duplicate scenarios: https://github.com/cucumber/compatibility-kit/pull/127 When('a PNG image is attached') do attach(File.open("#{cck_asset_path}/cucumber.png"), 'image/png') end From 5b56ad6f0554cd8dcab55ecf218a5c80c4d923d4 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Wed, 21 May 2025 15:52:12 +0100 Subject: [PATCH 35/40] Remove redundant require for testrunstarted query --- lib/cucumber/formatter/query/test_run_started.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/cucumber/formatter/query/test_run_started.rb b/lib/cucumber/formatter/query/test_run_started.rb index 6c63dbd39..be3e4c6f0 100644 --- a/lib/cucumber/formatter/query/test_run_started.rb +++ b/lib/cucumber/formatter/query/test_run_started.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require 'cucumber/formatter/errors' - module Cucumber module Formatter module Query From bb99b55c6650b4cc871ac12efe15a5d89a33c407 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Wed, 21 May 2025 15:57:25 +0100 Subject: [PATCH 36/40] Fix missing arg in step --- spec/cucumber/glue/step_definition_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/cucumber/glue/step_definition_spec.rb b/spec/cucumber/glue/step_definition_spec.rb index 0a7eb805a..e5e15394a 100644 --- a/spec/cucumber/glue/step_definition_spec.rb +++ b/spec/cucumber/glue/step_definition_spec.rb @@ -41,7 +41,7 @@ def step_match(text) it 'allows calling of other steps with inline arg' do dsl.Given('Outside') { step 'Inside', table([['inside']]) } - dsl.Given('Inside') { @@inside = t.raw[0][0] } + dsl.Given('Inside') { |t| @@inside = t.raw[0][0] } run_step 'Outside' From 87d439fd112716dab404b12ff69022612e7ea97d Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Wed, 21 May 2025 16:00:25 +0100 Subject: [PATCH 37/40] Tidy up of lines / style --- spec/cucumber/glue/step_definition_spec.rb | 35 +++++++--------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/spec/cucumber/glue/step_definition_spec.rb b/spec/cucumber/glue/step_definition_spec.rb index e5e15394a..81b4385fa 100644 --- a/spec/cucumber/glue/step_definition_spec.rb +++ b/spec/cucumber/glue/step_definition_spec.rb @@ -45,7 +45,7 @@ def step_match(text) run_step 'Outside' - expect(@@inside).to eq 'inside' + expect(@@inside).to eq('inside') end context 'when mapping to world methods' do @@ -169,8 +169,8 @@ def step_match(text) it 'uses the instance created by the ParameterType transformer proc' do dsl.Given 'capture this: {actor}' do |arg| - expect(arg.name).to eq 'Anjie' - expect(arg).to be @actor + expect(arg.name).to eq('Anjie') + expect(arg).to eq(@actor) end run_step 'capture this: Anjie' @@ -183,8 +183,8 @@ def step_match(text) run_step 'capture this: Anjie' step_args = step_match('capture this: Anjie').args - expect(step_args[0].name).not_to eq 'Dave' - expect(step_args[0].name).to eq 'Anjie' + expect(step_args[0].name).not_to eq('Dave') + expect(step_args[0].name).to eq('Anjie') end end @@ -192,18 +192,14 @@ def step_match(text) it 'calls "attach" with the correct media type' do expect(user_interface).to receive(:attach).with('wasup', 'text/x.cucumber.log+plain', nil) - dsl.Given(/Loud/) do - log 'wasup' - end + dsl.Given('Loud') { log 'wasup' } run_step 'Loud' end it 'calls `to_s` if the message is not a String' do expect(user_interface).to receive(:attach).with('["Not", 1, "string"]', 'text/x.cucumber.log+plain', nil) - dsl.Given(/Loud/) do - log ['Not', 1, 'string'] - end + dsl.Given('Loud') { log 'wasup' } run_step 'Loud' end end @@ -217,20 +213,9 @@ def step_match(text) end it 'has a JSON representation of the signature' do - expect(described_class.new( - id, - registry, - /I CAN HAZ (\d+) CUKES/i, - -> {}, - {} - ).to_hash).to eq( - source: { - type: 'regular expression', - expression: 'I CAN HAZ (\\d+) CUKES' - }, - regexp: { - source: 'I CAN HAZ (\\d+) CUKES', flags: 'i' - } + expect(described_class.new(id, registry, /I CAN HAZ (\d+) CUKES/i, -> {}, {}).to_hash).to eq( + source: { type: 'regular expression', expression: 'I CAN HAZ (\\d+) CUKES' }, + regexp: { source: 'I CAN HAZ (\\d+) CUKES', flags: 'i' } ) end end From 30c56c0059bd12cae188eebff3c5ccb8e83e31bd Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Thu, 22 May 2025 16:55:15 +0100 Subject: [PATCH 38/40] Fix up bad copy and paste --- spec/cucumber/glue/step_definition_spec.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/spec/cucumber/glue/step_definition_spec.rb b/spec/cucumber/glue/step_definition_spec.rb index 81b4385fa..927a1da40 100644 --- a/spec/cucumber/glue/step_definition_spec.rb +++ b/spec/cucumber/glue/step_definition_spec.rb @@ -199,15 +199,14 @@ def step_match(text) it 'calls `to_s` if the message is not a String' do expect(user_interface).to receive(:attach).with('["Not", 1, "string"]', 'text/x.cucumber.log+plain', nil) - dsl.Given('Loud') { log 'wasup' } + dsl.Given('Loud') { log ['Not', 1, 'string'] } run_step 'Loud' end end it 'recognizes $arg style captures' do - arg_value = 'up' - dsl.Given 'capture this: {word}' do |arg| - expect(arg).to eq arg_value + dsl.Given('capture this: {word}') do |arg| + expect(arg).to eq('up') end run_step 'capture this: up' end From 49b54ce787f8ef705ebeb06fd204fd1414e841cb Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Thu, 29 May 2025 16:32:57 +0100 Subject: [PATCH 39/40] Add CCK strawman for validating the testRunId consistency --- compatibility/support/shared_examples.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/compatibility/support/shared_examples.rb b/compatibility/support/shared_examples.rb index 7fb6f31b9..21b28c549 100644 --- a/compatibility/support/shared_examples.rb +++ b/compatibility/support/shared_examples.rb @@ -27,4 +27,18 @@ expect(comparator.errors).to be_empty, "There were comparison errors: #{comparator.errors}" end + + it 'ensures a consistent `testRunStartedId` across the entire test run' do + # Step 1) Grab testRunStarted[:id] + test_run_message = parsed_generated.detect { |msg| message_type(msg) == :test_run_started } + id = test_run_message.test_run_started.id + + # Step 2) Validate every testCase has a [:testRunStartedId] equal to the above + # Step 3) Validate the single testRunFinished [:testRunStartedId] equal to the above + messages_types_containing_test_run_started_id = %i[test_case test_run_finished] + messages_containing_test_run_started_id = parsed_generated.select { |msg| messages_types_containing_test_run_started_id.include?(message_type(msg)) } + ids = messages_containing_test_run_started_id.map { |msg| msg.send(message_type(msg)).test_run_started_id } + + expect(ids).to all eq(id) + end end From a0a7d38621f41a95b5a1d1f0f7633c560fe6f65a Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Thu, 29 May 2025 16:39:10 +0100 Subject: [PATCH 40/40] Clean up test for id checking --- compatibility/support/shared_examples.rb | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/compatibility/support/shared_examples.rb b/compatibility/support/shared_examples.rb index 21b28c549..a5dc79b20 100644 --- a/compatibility/support/shared_examples.rb +++ b/compatibility/support/shared_examples.rb @@ -29,16 +29,13 @@ end it 'ensures a consistent `testRunStartedId` across the entire test run' do - # Step 1) Grab testRunStarted[:id] - test_run_message = parsed_generated.detect { |msg| message_type(msg) == :test_run_started } - id = test_run_message.test_run_started.id - - # Step 2) Validate every testCase has a [:testRunStartedId] equal to the above - # Step 3) Validate the single testRunFinished [:testRunStartedId] equal to the above - messages_types_containing_test_run_started_id = %i[test_case test_run_finished] - messages_containing_test_run_started_id = parsed_generated.select { |msg| messages_types_containing_test_run_started_id.include?(message_type(msg)) } + test_run_started_id = parsed_generated.detect { |msg| message_type(msg) == :test_run_started }.test_run_started.id + messages_containing_test_run_started_id = parsed_generated.select do |msg| + # These two types of message are the only ones containing the testRunStartedId attribute + %i[test_case test_run_finished].include?(message_type(msg)) + end ids = messages_containing_test_run_started_id.map { |msg| msg.send(message_type(msg)).test_run_started_id } - expect(ids).to all eq(id) + expect(ids).to all eq(test_run_started_id) end end