Skip to content

Commit a6df773

Browse files
committed
Merge pull request #187 from abevoelker/keywordargs_unexpected_keys
Make KeywordArgs fail if unexpected keys are passed in
2 parents fc98f41 + 1960743 commit a6df773

File tree

4 files changed

+26
-3
lines changed

4 files changed

+26
-3
lines changed

lib/contracts/builtin_contracts.rb

+1
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ def initialize(options)
385385
end
386386

387387
def valid?(hash)
388+
return false unless hash.keys - options.keys == []
388389
options.all? do |key, contract|
389390
Optional._valid?(hash, key, contract)
390391
end

spec/builtin_contracts_spec.rb

+18
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,24 @@
332332
end
333333
end
334334

335+
describe "KeywordArgs:" do
336+
it "should pass for exact correct input" do
337+
expect { @o.person_keywordargs(:name => "calvin", :age => 10) }.to_not raise_error
338+
end
339+
340+
it "should fail if some keys don't have contracts" do
341+
expect { @o.person_keywordargs(:name => "calvin", :age => 10, :foo => "bar") }.to raise_error(ContractError)
342+
end
343+
344+
it "should fail if a key with a contract on it isn't provided" do
345+
expect { @o.person_keywordargs(:name => "calvin") }.to raise_error(ContractError)
346+
end
347+
348+
it "should fail for incorrect input" do
349+
expect { @o.person_keywordargs(:name => 50, :age => 10) }.to raise_error(ContractError)
350+
end
351+
end
352+
335353
describe "Optional:" do
336354
it "can't be used outside of KeywordArgs" do
337355
expect do

spec/fixtures/fixtures.rb

+4
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ def hash_complex_contracts(data)
113113
def nested_hash_complex_contracts(data)
114114
end
115115

116+
Contract KeywordArgs[:name => String, :age => Fixnum] => nil
117+
def person_keywordargs(data)
118+
end
119+
116120
Contract [Or[TrueClass, FalseClass]] => nil
117121
def array_complex_contracts(data)
118122
end

spec/ruby_version_specific/contracts_spec_2.1.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
class GenericExample
2-
Contract String, Bool, Args[Symbol], Float, KeywordArgs[e: Range, f: Optional[Num]], Proc =>
2+
Contract String, Bool, Args[Symbol], Float, KeywordArgs[e: Range, f: Optional[Num], g: Symbol], Proc =>
33
[Proc, Hash, Maybe[Num], Range, Float, ArrayOf[Symbol], Bool, String]
44
def complicated(a, b = true, *c, d, e:, f:2, **g, &h)
55
h.call [h, g, f, e, d, c, b, a]
@@ -15,7 +15,7 @@ def complicated(a, b = true, *c, d, e:, f:2, **g, &h)
1515
describe "really complicated method signature" do
1616
it "should work with default named args used" do
1717
expect do
18-
@o.complicated("a", false, :b, 2.0, e: (1..5)) { |x| x }
18+
@o.complicated("a", false, :b, 2.0, e: (1..5), g: :d) { |x| x }
1919
end.to_not raise_error
2020
end
2121

@@ -56,7 +56,7 @@ def complicated(a, b = true, *c, d, e:, f:2, **g, &h)
5656
@o.complicated("a", true, :b, :c, 2.0, e: (1..5), f: nil, g: :d) do |x|
5757
x
5858
end
59-
end.to raise_error(ContractError, /Expected: \(KeywordArgs\[{:e=>Range, :f=>Optional\[Num\]}\]\)/)
59+
end.to raise_error(ContractError, /Expected: \(KeywordArgs\[{:e=>Range, :f=>Optional\[Num\], :g=>Symbol}\]\)/)
6060
end
6161
end
6262
end

0 commit comments

Comments
 (0)