Skip to content

Commit 4b42ace

Browse files
committed
fix(OneOf): fail coercion when the single OneOf field is invalidly provided by a default
Also provides the previously omitted undefined key in the execution test for accepting a good variable with an undefined key. Replicates graphql/graphql-js@5042e18
1 parent bd4f4f5 commit 4b42ace

3 files changed

Lines changed: 33 additions & 8 deletions

File tree

src/graphql/utilities/coerce_input_value.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,13 @@ def coerce_input_value(input_value: Any, type_: GraphQLInputType) -> Any:
7272

7373
coerced_dict: dict[str, Any] = {}
7474
fields = type_.fields
75-
if any(
76-
field_value is not Undefined and field_name not in fields
77-
for field_name, field_value in input_value.items()
78-
):
79-
return Undefined # Invalid: intentionally return no value.
75+
defined_field_count = 0
76+
for field_name, field_value in input_value.items():
77+
if field_value is Undefined:
78+
continue
79+
defined_field_count += 1
80+
if field_name not in fields:
81+
return Undefined # Invalid: intentionally return no value.
8082
for field_name, field in fields.items():
8183
field_value = input_value.get(field_name, Undefined)
8284
if field_value is Undefined:
@@ -94,8 +96,8 @@ def coerce_input_value(input_value: Any, type_: GraphQLInputType) -> Any:
9496

9597
if type_.is_one_of:
9698
keys = list(coerced_dict)
97-
if len(keys) != 1:
98-
# Invalid: not exactly one key, intentionally return no value.
99+
if defined_field_count != 1 or len(keys) != 1:
100+
# Invalid: intentionally return no value.
99101
return Undefined
100102
if coerced_dict[keys[0]] is None:
101103
# Invalid: value not non-null, intentionally return no value.

tests/execution/test_oneof.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from graphql.execution import ExecutionResult, execute
66
from graphql.language import parse
7+
from graphql.pyutils import Undefined
78
from graphql.utilities import build_schema
89

910
if TYPE_CHECKING:
@@ -97,7 +98,9 @@ def accepts_a_good_variable_with_an_undefined_key():
9798
}
9899
}
99100
"""
100-
result = execute_query(query, root_value, {"input": {"a": "abc"}})
101+
result = execute_query(
102+
query, root_value, {"input": {"a": "abc", "b": Undefined}}
103+
)
101104

102105
assert result == ({"test": {"a": "abc", "b": None}}, None)
103106

tests/utilities/test_coerce_input_value.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,16 @@ def describe_for_graphql_input_object_that_is_one_of():
194194
is_one_of=True,
195195
)
196196

197+
TestInvalidOneOfInputObjectWithDefault = GraphQLInputObjectType(
198+
"TestInvalidOneOfInputObjectWithDefault",
199+
{
200+
"foo": GraphQLInputField(
201+
GraphQLInt, default=GraphQLDefaultInput(value=123)
202+
),
203+
},
204+
is_one_of=True,
205+
)
206+
197207
def returns_for_valid_input():
198208
_test({"foo": 123}, TestInputObject, {"foo": 123})
199209

@@ -203,6 +213,16 @@ def invalid_if_more_than_one_field_is_specified():
203213
def invalid_if_the_one_field_is_null():
204214
_test({"bar": None}, TestInputObject, Undefined)
205215

216+
def invalid_if_an_omitted_field_would_be_filled_by_a_default():
217+
_test({}, TestInvalidOneOfInputObjectWithDefault, Undefined)
218+
219+
def invalid_if_an_undefined_field_would_be_filled_by_a_default():
220+
_test(
221+
{"foo": Undefined},
222+
TestInvalidOneOfInputObjectWithDefault,
223+
Undefined,
224+
)
225+
206226
def invalid_for_an_invalid_field():
207227
_test({"foo": nan}, TestInputObject, Undefined)
208228

0 commit comments

Comments
 (0)