From 3120dc157e1a9acd6b30963694daff400bc9b2a8 Mon Sep 17 00:00:00 2001 From: Luke Hill Date: Fri, 28 Feb 2025 14:11:33 +0000 Subject: [PATCH 01/12] 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/12] 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/12] 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/12] 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/12] 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/12] 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/12] 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/12] 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/12] 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/12] 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/12] 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/12] 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