diff --git a/.rubocop.yml b/.rubocop.yml index 4eabc20..e0c9f49 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -10,6 +10,9 @@ AllCops: TargetRubyVersion: 3.1 NewCops: enable +Gemspec/DevelopmentDependencies: + Enabled: false + # Disabled on our repo's to enable polyglot-release Gemspec/RequireMFA: Enabled: false diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 168d6c2..a9fdf2f 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2025-10-07 17:41:43 UTC using RuboCop version 1.81.1. +# on 2025-10-14 17:57:25 UTC using RuboCop version 1.81.1. # 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 @@ -9,21 +9,16 @@ # TODO: Nov '23 -> 25 files inspected, 132 offenses detected, 102 offenses autocorrectable # TODO: Nov '23 -> 25 files inspected, 53 offenses detected, 28 offenses autocorrectable # TODO: Oct '25 -> 25 files inspected, 65 offenses detected, 32 offenses autocorrectable +# TODO: Oct '25 (Take 2) -> 25 files inspected, 36 offenses detected, 18 offenses autocorrectable -# Offense count: 9 -# Configuration parameters: EnforcedStyle, AllowedGems. -# SupportedStyles: Gemfile, gems.rb, gemspec -Gemspec/DevelopmentDependencies: - Exclude: - - 'cucumber-wire.gemspec' - -# Offense count: 4 +# Offense count: 2 # This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, IndentationWidth. -# SupportedStyles: aligned, indented, indented_relative_to_receiver -Layout/MultilineMethodCallIndentation: +# Configuration parameters: EnforcedStyle. +# SupportedStyles: final_newline, final_blank_line +Layout/TrailingEmptyLines: Exclude: - - 'lib/cucumber/wire/request_handler.rb' + - 'Rakefile' + - 'spec/cucumber/wire/connection_spec.rb' # Offense count: 3 # This cop supports unsafe autocorrection (--autocorrect-all). @@ -33,29 +28,18 @@ Lint/AssignmentInCondition: - 'features/step_definitions/wire_steps.rb' - 'features/support/fake_wire_server.rb' -# Offense count: 2 -# Configuration parameters: AllowedMethods. -# AllowedMethods: enums -Lint/ConstantDefinitionInBlock: - Exclude: - - 'spec/cucumber/wire/connection_spec.rb' - # Offense count: 1 Lint/RescueException: Exclude: - 'features/support/fake_wire_server.rb' -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Lint/ToJSON: - Exclude: - - 'lib/cucumber/wire/data_packet.rb' - -# Offense count: 1 +# Offense count: 2 # This cop supports safe autocorrection (--autocorrect). -Lint/UselessAssignment: +# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions. +# NotImplementedExceptions: NotImplementedError +Lint/UnusedMethodArgument: Exclude: - - 'lib/cucumber/wire/connection.rb' + - 'lib/cucumber/wire/protocol/requests.rb' # Offense count: 1 Lint/UselessRescue: @@ -74,22 +58,11 @@ Metrics/MethodLength: # Offense count: 1 # This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: PreferredName. -Naming/RescuedExceptionsVariableName: +# Configuration parameters: EnforcedStyle, BlockForwardingName. +# SupportedStyles: anonymous, explicit +Naming/BlockForwarding: Exclude: - - 'lib/cucumber/wire/connection.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Performance/RegexpMatch: - Exclude: - - 'lib/cucumber/wire/configuration.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Performance/StringIdentifierArgument: - Exclude: - - 'lib/cucumber/wire/data_packet.rb' + - 'lib/cucumber/wire/protocol/requests.rb' # Offense count: 3 # Configuration parameters: CountAsOne. @@ -103,11 +76,6 @@ RSpec/ExampleLength: RSpec/HookArgument: EnforcedStyle: each -# Offense count: 2 -RSpec/LeakyConstantDeclaration: - Exclude: - - 'spec/cucumber/wire/connection_spec.rb' - # Offense count: 3 RSpec/MultipleExpectations: Max: 2 @@ -119,22 +87,6 @@ RSpec/VerifiedDoubles: - 'spec/cucumber/wire/connection_spec.rb' - 'spec/cucumber/wire/connections_spec.rb' -# Offense count: 2 -Rake/Desc: - Exclude: - - 'Rakefile' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods. -# SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces -# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object -# FunctionalMethods: let, let!, subject, watch -# AllowedMethods: lambda, proc, it -Style/BlockDelimiters: - Exclude: - - 'features/step_definitions/wire_steps.rb' - # Offense count: 2 Style/ClassVars: Exclude: @@ -164,27 +116,6 @@ Style/MutableConstant: Exclude: - 'lib/cucumber/wire/configuration.rb' -# Offense count: 3 -# This cop supports safe autocorrection (--autocorrect). -Style/ParallelAssignment: - Exclude: - - 'features/support/fake_wire_server.rb' - - 'lib/cucumber/wire/data_packet.rb' - - 'lib/cucumber/wire/step_argument.rb' - -# Offense count: 2 -# This cop supports safe autocorrection (--autocorrect). -Style/RedundantRegexpArgument: - Exclude: - - 'features/step_definitions/wire_steps.rb' - - 'lib/cucumber/wire/request_handler.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Style/RescueModifier: - Exclude: - - 'lib/cucumber/wire/step_definition.rb' - # Offense count: 1 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. @@ -192,23 +123,3 @@ Style/RescueModifier: Style/RescueStandardError: Exclude: - 'features/support/fake_wire_server.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowAsExpressionSeparator. -Style/Semicolon: - Exclude: - - 'lib/cucumber/wire/connection.rb' - -# Offense count: 1 -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: Mode. -Style/StringConcatenation: - Exclude: - - 'features/support/fake_wire_server.rb' - -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Style/SuperWithArgsParentheses: - Exclude: - - 'lib/cucumber/wire/exception.rb' diff --git a/CHANGELOG.md b/CHANGELOG.md index 35a63c8..56fab14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ Please visit [cucumber/CONTRIBUTING.md](https://github.com/cucumber/cucumber/blo ## [Unreleased] ### Added -- Added some basic rubocop compliance to suite (More fixes to come) ([#69](https://github.com/cucumber/cucumber-ruby-wire/pull/69) [#70](https://github.com/cucumber/cucumber-ruby-wire/pull/70)) +- Added some basic rubocop compliance to suite (More fixes to come) ([#69](https://github.com/cucumber/cucumber-ruby-wire/pull/69) [#70](https://github.com/cucumber/cucumber-ruby-wire/pull/70) [#84](https://github.com/cucumber/cucumber-ruby-wire/pull/84)) ### Changed - Minimum ruby version is now 3.1 ([#82](https://github.com/cucumber/cucumber-ruby-wire/pull/82)) diff --git a/README.md b/README.md index 8e42cda..e55e7db 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ -[![Test cucumber-wire](https://github.com/cucumber/cucumber-ruby-wire/actions/workflows/cucumber-ruby-wire.yml/badge.svg)](https://github.com/cucumber/cucumber-ruby-wire/actions/workflows/cucumber-ruby-wire.yml) +[![Test cucumber-wire](https://github.com/cucumber/cucumber-ruby-wire/actions/workflows/test.yaml/badge.svg)](https://github.com/cucumber/cucumber-ruby-wire/actions/workflows/test.yaml) # cucumber-wire -This gem was extracted from the [cucumber gem](https://github.com/cucumber/cucumber-ruby), and is now an opt-in plugin there +This gem was extracted from the [cucumber gem](https://github.com/cucumber/cucumber-ruby) -Its tests are a bit hairy and prone to the occasional flicker. +This is available as an optional runtime dependency for cucumber-ruby and also as a runtime dependency for cucumber cpp. + +The tests here are a bit hairy and prone to the occasional flicker. ## Configuration diff --git a/Rakefile b/Rakefile index d7f3dec..04b4325 100644 --- a/Rakefile +++ b/Rakefile @@ -2,10 +2,12 @@ task default: %i[unit_tests acceptance_tests] +desc 'Unit tests for Cucumber Ruby Wire' task :unit_tests do sh 'bundle exec rspec' end +desc 'Acceptance tests for Cucumber Ruby Wire' task :acceptance_tests do sh 'bundle exec cucumber' -end +end \ No newline at end of file diff --git a/cucumber-wire.gemspec b/cucumber-wire.gemspec index cb8f03e..929a4a6 100644 --- a/cucumber-wire.gemspec +++ b/cucumber-wire.gemspec @@ -18,8 +18,8 @@ Gem::Specification.new do |s| s.add_dependency 'cucumber-core', '> 11', '< 16' s.add_dependency 'cucumber-cucumber-expressions', '> 14', '< 20' - s.add_development_dependency 'aruba', '~> 2.1' - s.add_development_dependency 'cucumber', '> 7.1', '< 11' + s.add_development_dependency 'aruba', '~> 2.2' + s.add_development_dependency 'cucumber', '> 8', '< 11' s.add_development_dependency 'rake', '~> 13.3' s.add_development_dependency 'rspec', '~> 3.13' s.add_development_dependency 'rubocop', '~> 1.81.0' diff --git a/features/step_definitions/wire_steps.rb b/features/step_definitions/wire_steps.rb index 7118630..34c91f1 100644 --- a/features/step_definitions/wire_steps.rb +++ b/features/step_definitions/wire_steps.rb @@ -2,7 +2,7 @@ Given(/^there is a wire server (running |)on port (\d+) which understands the following protocol:$/) do |running, port, table| protocol = table.hashes.map do |table_hash| - table_hash['response'] = table_hash['response'].gsub(/\n/, '\n') + table_hash['response'] = table_hash['response'].gsub("\n", '\n') table_hash end @@ -29,10 +29,10 @@ module WireHelper def start_wire_server @messages_received = [] reader, writer = IO.pipe - @wire_pid = fork { + @wire_pid = fork do reader.close @server.run(writer) - } + end writer.close Thread.new do while message = reader.gets diff --git a/features/support/fake_wire_server.rb b/features/support/fake_wire_server.rb index bad3dd3..a7a3c49 100644 --- a/features/support/fake_wire_server.rb +++ b/features/support/fake_wire_server.rb @@ -5,7 +5,8 @@ class FakeWireServer def initialize(port, protocol_table) - @port, @protocol_table = port, protocol_table + @port = port + @protocol_table = protocol_table @delays = {} end @@ -69,7 +70,7 @@ def response_to(data) end def send_response(response) - @socket.puts response + "\n" + @socket.puts("#{response}\n") end def delay(data) diff --git a/lib/cucumber/wire/configuration.rb b/lib/cucumber/wire/configuration.rb index 8f08ac5..49ab6b7 100644 --- a/lib/cucumber/wire/configuration.rb +++ b/lib/cucumber/wire/configuration.rb @@ -16,7 +16,7 @@ def self.from_file(wire_file) def initialize(args) @host = args['host'] @port = args['port'] - @unix = args['unix'] if RUBY_PLATFORM !~ /mingw|mswin/ + @unix = args['unix'] unless RUBY_PLATFORM.match?(/mingw|mswin/) @timeouts = DEFAULT_TIMEOUTS.merge(args['timeout'] || {}) end diff --git a/lib/cucumber/wire/connection.rb b/lib/cucumber/wire/connection.rb index af610ff..d08f1f9 100644 --- a/lib/cucumber/wire/connection.rb +++ b/lib/cucumber/wire/connection.rb @@ -60,7 +60,7 @@ def socket else @socket = TCPSocket.new(@config.host, @config.port) end - rescue Errno::ECONNREFUSED => exception + rescue Errno::ECONNREFUSED raise(ConnectionError, "Unable to contact the wire server at #{@config}. Is it up?") end end diff --git a/lib/cucumber/wire/data_packet.rb b/lib/cucumber/wire/data_packet.rb index 6055a49..59365e5 100644 --- a/lib/cucumber/wire/data_packet.rb +++ b/lib/cucumber/wire/data_packet.rb @@ -19,17 +19,18 @@ def parse(raw) attr_reader :message, :params def initialize(message, params = nil) - @message, @params = message, params + @message = message + @params = params end - def to_json + def to_json(*_args) packet = [@message] packet << @params if @params JSON.generate(packet) end def handle_with(handler) - handler.send("handle_#{@message}", @params) + handler.send(:"handle_#{@message}", @params) end end end diff --git a/lib/cucumber/wire/exception.rb b/lib/cucumber/wire/exception.rb index 8a8ec59..7fa7afe 100644 --- a/lib/cucumber/wire/exception.rb +++ b/lib/cucumber/wire/exception.rb @@ -13,7 +13,7 @@ def to_s end def initialize(args, config) - super args['message'] + super(args['message']) if args['exception'] self.class.extend(CanSetName) diff --git a/lib/cucumber/wire/request_handler.rb b/lib/cucumber/wire/request_handler.rb index a38eeb3..4600671 100644 --- a/lib/cucumber/wire/request_handler.rb +++ b/lib/cucumber/wire/request_handler.rb @@ -23,11 +23,13 @@ def handle_success(params); end # Props to Rails def underscore(camel_cased_word) - camel_cased_word.to_s.gsub(/::/, '/') - .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') - .gsub(/([a-z\d])([A-Z])/, '\1_\2') - .tr('-', '_') - .downcase + camel_cased_word + .to_s + .gsub('::', '/') + .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') + .gsub(/([a-z\d])([A-Z])/, '\1_\2') + .tr('-', '_') + .downcase end end end diff --git a/lib/cucumber/wire/step_argument.rb b/lib/cucumber/wire/step_argument.rb index cce7f8d..294119b 100644 --- a/lib/cucumber/wire/step_argument.rb +++ b/lib/cucumber/wire/step_argument.rb @@ -10,7 +10,8 @@ class StepArgument attr_reader :offset def initialize(offset, val) - @offset, @value = offset, val + @offset = offset + @value = val end def value(_current_world) diff --git a/lib/cucumber/wire/step_definition.rb b/lib/cucumber/wire/step_definition.rb index 8581dae..96f89ac 100644 --- a/lib/cucumber/wire/step_definition.rb +++ b/lib/cucumber/wire/step_definition.rb @@ -9,11 +9,15 @@ class StepDefinition def initialize(connection, data, registry) @connection = connection - @registry = registry - @id = data['id'] - @regexp_source = Regexp.new(data['regexp']) rescue data['regexp'] || 'Unknown' - @expression = registry.create_expression(@regexp_source) - @location = Core::Test::Location.from_file_colon_line(data['source'] || 'unknown:0') + @registry = registry + @id = data['id'] + @regexp_source = begin + Regexp.new(data['regexp']) + rescue StandardError + data['regexp'] || 'Unknown' + end + @expression = registry.create_expression(@regexp_source) + @location = Core::Test::Location.from_file_colon_line(data['source'] || 'unknown:0') end def invoke(args) diff --git a/spec/cucumber/wire/connection_spec.rb b/spec/cucumber/wire/connection_spec.rb index 9c84b20..811038c 100644 --- a/spec/cucumber/wire/connection_spec.rb +++ b/spec/cucumber/wire/connection_spec.rb @@ -3,63 +3,62 @@ require 'cucumber/wire/connection' require 'cucumber/wire/configuration' -module Cucumber - module Wire - describe Connection do - class TestConnection < Connection - attr_accessor :socket - end - - class TestConfiguration - attr_reader :custom_timeout +describe Cucumber::Wire::Connection do + subject(:connection) { test_connection.new(config) } - def initialize - @custom_timeout = {} - end - - def timeout(message = nil) - return :default_timeout if message.nil? + let(:test_connection) do + Class.new(described_class) do + attr_accessor :socket + end + end + let(:test_configuration) do + Class.new do + attr_reader :custom_timeout - @custom_timeout[message] || Configuration::DEFAULT_TIMEOUTS.fetch(message) - end + def initialize + @custom_timeout = {} + end - def host - 'localhost' - end + def timeout(message = nil) + return :default_timeout if message.nil? - def port - '3902' - end + @custom_timeout[message] || Cucumber::Wire::Configuration::DEFAULT_TIMEOUTS.fetch(message) end - before(:each) do - @config = TestConfiguration.new - @connection = TestConnection.new(@config) - @connection.socket = @socket = double('socket').as_null_object - @response = '["response"]' + def host + 'localhost' end - it 're-raises a timeout error' do - allow(Timeout).to receive(:timeout).and_raise(Timeout::Error.new('')) - expect { @connection.call_remote(nil, :foo, []) }.to raise_error(Timeout::Error) + def port + '3902' end + end + end + let(:socket) { double('socket').as_null_object } + let(:config) { test_configuration.new } - it 'ignores timeout errors when configured to do so' do - @config.custom_timeout[:foo] = :never + before(:each) { connection.socket = socket } - allow(@socket).to receive(:gets) { @response } + it 're-raises a timeout error' do + allow(Timeout).to receive(:timeout).and_raise(Timeout::Error.new('')) - handler = double(handle_response: :response) + expect { connection.call_remote(nil, :foo, []) }.to raise_error(Timeout::Error) + end - expect(@connection.call_remote(handler, :foo, [])).to eq(:response) - end + it 'ignores timeout errors when configured to do so' do + config.custom_timeout[:foo] = :never - it 'raises an exception on remote connection closed' do - @config.custom_timeout[:foo] = :never + allow(socket).to receive(:gets).and_return('["response"]') - allow(@socket).to receive(:gets) - expect { @connection.call_remote(nil, :foo, []) }.to raise_error(Wire::Exception, 'Remote Socket with localhost:3902 closed.') - end - end + handler = double(handle_response: :response) + + expect(connection.call_remote(handler, :foo, [])).to eq(:response) + end + + it 'raises an exception on remote connection closed' do + config.custom_timeout[:foo] = :never + allow(socket).to receive(:gets) + + expect { connection.call_remote(nil, :foo, []) }.to raise_error(Cucumber::Wire::Exception, 'Remote Socket with localhost:3902 closed.') end -end +end \ No newline at end of file