diff --git a/CHANGELOG.md b/CHANGELOG.md index e25481094..97cb2de57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ refactored to use newer, less procedural ruby_) - Fixed an issue where a change to one example in compatibility testing wasn't fully adhered to ([luke-hill](https://github.com/luke-hill)) - Fixed Ruby 3.4+ issue where error backtraces weren't being formatted. ([#1771](https://github.com/cucumber/cucumber-ruby/pull/1771) [orien](https://github.com/orien)) - Fix some problematic specs that were leaking state and showcasing an issue on JRuby ([#1783](https://github.com/cucumber/cucumber-ruby/pull/1783) [luke-hill](https://github.com/luke-hill)) +- Fixed an issue where NoMethodError could be raised when declaring a parameter-type that used bound methods ([#1789](https://github.com/cucumber/cucumber-ruby/pull/1789)) ### Removed - `StepDefinitionLight` associated methods. The class itself is present but deprecated diff --git a/lib/cucumber/glue/registry_and_more.rb b/lib/cucumber/glue/registry_and_more.rb index 349977a59..eed3b0da8 100644 --- a/lib/cucumber/glue/registry_and_more.rb +++ b/lib/cucumber/glue/registry_and_more.rb @@ -198,14 +198,22 @@ def parameter_type_envelope(parameter_type) regular_expressions: parameter_type.regexps.map(&:to_s), prefer_for_regular_expression_match: parameter_type.prefer_for_regexp_match, use_for_snippets: parameter_type.use_for_snippets, - source_reference: Cucumber::Messages::SourceReference.new( - uri: parameter_type.transformer.source_location[0], - location: Cucumber::Messages::Location.new(line: parameter_type.transformer.source_location[1]) - ) + source_reference: source_reference_for(parameter_type.transformer) ) ) end + def source_reference_for(transformer) + # #source_location may return nil if no definition was found + # This is the case for transformers created using method(sym) or similar + return nil if transformer.source_location.nil? + + Cucumber::Messages::SourceReference.new( + uri: transformer.source_location[0], + location: Cucumber::Messages::Location.new(line: transformer.source_location[1]) + ) + end + def hooks @hooks ||= Hash.new { |h, k| h[k] = [] } end diff --git a/spec/cucumber/glue/registry_and_more_spec.rb b/spec/cucumber/glue/registry_and_more_spec.rb index a7e6c60e3..3afa21f30 100644 --- a/spec/cucumber/glue/registry_and_more_spec.rb +++ b/spec/cucumber/glue/registry_and_more_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' require 'cucumber/glue/registry_and_more' +require 'cucumber/cucumber_expressions/parameter_type' require 'support/fake_objects' module Cucumber @@ -221,5 +222,60 @@ class << registry.current_world end end end + + describe RegistryAndMore do + let(:registry) { described_class.new(double, configuration) } + let(:configuration) { Configuration.new({}) } + + describe '#parameter_type_envelope' do + subject(:envelope) { registry.send(:parameter_type_envelope, parameter_type) } + + let(:parameter_type) { CucumberExpressions::ParameterType.new(name, regexp, type, transformer, use_for_snippets, prefer_for_regexp_match) } + let(:id) { '279e0f28-c91b-4de2-89c0-e7fbc2a15406' } + let(:name) { 'person' } + let(:regexp) { /"[^"]+"/ } + let(:type) { String } + let(:transformer) { ->(s) { s } } + let(:use_for_snippets) { false } + let(:prefer_for_regexp_match) { true } + + before do + allow(configuration).to receive_message_chain(:id_generator, :new_id).and_return(id) # rubocop:disable RSpec/MessageChain + end + + it 'produces an envelope with the expected contents' do + expect(envelope).to be_a Cucumber::Messages::Envelope + expect(envelope.parameter_type).to be_a Cucumber::Messages::ParameterType + expect(envelope.parameter_type).to have_attributes( + id: '279e0f28-c91b-4de2-89c0-e7fbc2a15406', + name: 'person', + regular_expressions: [%("[^"]+")], + prefer_for_regular_expression_match: true, + use_for_snippets: false, + source_reference: anything # tested in later cases + ) + end + + context 'when provided a ParameterType with transformer being a lambda' do + let(:transformer) { ->(s) { s } } + + it 'includes the lambda source-location in the envelope' do + expect(envelope.parameter_type.source_reference).to be_a Cucumber::Messages::SourceReference + expect(envelope.parameter_type.source_reference).to have_attributes( + uri: transformer.source_location[0], + location: have_attributes(line: transformer.source_location[1]) + ) + end + end + + context 'when provided a ParameterType with transformer being a bound method, which has no source location' do + let(:transformer) { String.method(:new) } + + it 'does not include the source-location in the envelope' do + expect(envelope.parameter_type.source_reference).to be_nil + end + end + end + end end end