From 1284a2d9a48da4a8b912efb1ec2d362b35b8352b Mon Sep 17 00:00:00 2001 From: Mathieu Le Tiec Date: Thu, 3 Mar 2022 14:10:16 +0100 Subject: [PATCH] Raise an InvalidKeyErrors on substring of valid keys Fixes #705 I'm not completely sure of the fix, but it's probably good enough as a starting point --- .../validation/contract/class_interface.rb | 4 ++- .../contract/class_interface/rule_spec.rb | 34 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/lib/dry/validation/contract/class_interface.rb b/lib/dry/validation/contract/class_interface.rb index b4992e3c..39426031 100644 --- a/lib/dry/validation/contract/class_interface.rb +++ b/lib/dry/validation/contract/class_interface.rb @@ -159,7 +159,9 @@ def ensure_valid_keys(*keys) key_paths = key_paths(keys) invalid_keys = key_paths.map { |(key, path)| - unless valid_paths.any? { |vp| vp.include?(path) || vp.include?("#{path}[]") } + unless valid_paths.any? { |vp| + vp == path || vp.include?("#{path}.") || vp.include?("#{path}[]") + } key end }.compact.uniq diff --git a/spec/integration/contract/class_interface/rule_spec.rb b/spec/integration/contract/class_interface/rule_spec.rb index 4910c204..2d1866db 100644 --- a/spec/integration/contract/class_interface/rule_spec.rb +++ b/spec/integration/contract/class_interface/rule_spec.rb @@ -167,6 +167,40 @@ def self.name end end + context "when keys are substring of valid keys" do + it "raises error with a list of symbol keys" do + expect { contract_class.rule(:details, :addres) } + .to raise_error( + Dry::Validation::InvalidKeysError, + "TestContract.rule specifies keys that are not defined by the schema: [:addres]" + ) + end + + it "raises error with a hash path" do + expect { contract_class.rule(details: :addres) } + .to raise_error( + Dry::Validation::InvalidKeysError, + "TestContract.rule specifies keys that are not defined by the schema: [{:details=>:addres}]" + ) + end + + it "raises error with a dot notation" do + expect { contract_class.rule("details.addres") } + .to raise_error( + Dry::Validation::InvalidKeysError, + 'TestContract.rule specifies keys that are not defined by the schema: ["details.addres"]' + ) + end + + it "raises error with a hash path with multiple nested keys" do + expect { contract_class.rule(details: %i[addres]) } + .to raise_error( + Dry::Validation::InvalidKeysError, + "TestContract.rule specifies keys that are not defined by the schema: [{:details=>[:addres]}]" + ) + end + end + describe "abstract contract" do let(:abstract_contract) do Class.new(Dry::Validation::Contract) do