diff --git a/lib/rspec/core/shared_example_group.rb b/lib/rspec/core/shared_example_group.rb index b6ced2cc1f..6e21e6dfc6 100644 --- a/lib/rspec/core/shared_example_group.rb +++ b/lib/rspec/core/shared_example_group.rb @@ -33,10 +33,31 @@ def include_in(klass, inclusion_line, args, customization_block) klass.update_inherited_metadata(@metadata) unless @metadata.empty? SharedExampleGroupInclusionStackFrame.with_frame(@description, inclusion_line) do - klass.class_exec(*args, &@definition) + klass_exec(klass, *args, &@definition) klass.class_exec(&customization_block) if customization_block end end + + private + + if RSpec::Support::RubyFeatures.kw_args_supported? + # Remove this in RSpec 4 in favour of explictly passed in kwargs down the entire + # stack, e.g. rspec/rspec-core#2711 + binding.eval(<<-CODE, __FILE__, __LINE__) + def klass_exec(klass, *args, &definition) + if RSpec::Support::MethodSignature.new(definition).has_kw_args_in?(args) + kwargs = args.pop + klass.class_exec(*args, **kwargs, &definition) + else + klass.class_exec(*args, &definition) + end + end + CODE + else + def klass_exec(klass, *args, &definition) + klass.class_exec(*args, &definition) + end + end end # Shared example groups let you define common context and/or common diff --git a/spec/rspec/core/shared_example_group_spec.rb b/spec/rspec/core/shared_example_group_spec.rb index 6b897c395e..0a14b538e8 100644 --- a/spec/rspec/core/shared_example_group_spec.rb +++ b/spec/rspec/core/shared_example_group_spec.rb @@ -543,6 +543,20 @@ def self.bar; 'bar'; end expect(group).to have_example_descriptions("a different spec") end end + + if RSpec::Support::RubyFeatures.required_kw_args_supported? + binding.eval(<<-CODE, __FILE__, __LINE__) + context "supporting kwargs" do + __send__ shared_method_name, "shared context" do |foo:| + it "has an expected value" do + expect(foo).to eq("bar") + end + end + + it_behaves_like "shared context", foo: "bar" + end + CODE + end end end end