diff --git a/src/utilities/__tests__/coerceInputValue-test.ts b/src/utilities/__tests__/coerceInputValue-test.ts index f8910bd5ba..22006dfc2c 100644 --- a/src/utilities/__tests__/coerceInputValue-test.ts +++ b/src/utilities/__tests__/coerceInputValue-test.ts @@ -190,6 +190,13 @@ describe('coerceInputValue', () => { }, isOneOf: true, }); + const TestInvalidOneOfInputObjectWithDefault = new GraphQLInputObjectType({ + name: 'TestInvalidOneOfInputObjectWithDefault', + fields: { + foo: { type: GraphQLInt, default: { value: 123 } }, + }, + isOneOf: true, + }); it('returns for valid input', () => { test({ foo: 123 }, TestInputObject, { foo: 123 }); @@ -203,6 +210,18 @@ describe('coerceInputValue', () => { test({ bar: null }, TestInputObject, undefined); }); + it('invalid if an omitted field would be filled by a default', () => { + test({}, TestInvalidOneOfInputObjectWithDefault, undefined); + }); + + it('invalid if an undefined field would be filled by a default', () => { + test( + { foo: undefined }, + TestInvalidOneOfInputObjectWithDefault, + undefined, + ); + }); + it('invalid for an invalid field', () => { test({ foo: NaN }, TestInputObject, undefined); }); diff --git a/src/utilities/coerceInputValue.ts b/src/utilities/coerceInputValue.ts index 1ba8a18af0..8937fd9a92 100644 --- a/src/utilities/coerceInputValue.ts +++ b/src/utilities/coerceInputValue.ts @@ -73,12 +73,15 @@ export function coerceInputValue( const coercedValue: ObjMap = Object.create(null); const fieldDefs = type.getFields(); - const hasUndefinedField = Object.keys(inputValue).some( - (name) => - inputValue[name] !== undefined && !Object.hasOwn(fieldDefs, name), - ); - if (hasUndefinedField) { - return; // Invalid: intentionally return no value. + let definedFieldCount = 0; + for (const fieldName of Object.keys(inputValue)) { + if (inputValue[fieldName] === undefined) { + continue; + } + definedFieldCount++; + if (!Object.hasOwn(fieldDefs, fieldName)) { + return; // Invalid: intentionally return no value. + } } for (const field of Object.values(fieldDefs)) { const fieldValue = inputValue[field.name]; @@ -101,7 +104,7 @@ export function coerceInputValue( if (type.isOneOf) { const keys = Object.keys(coercedValue); - if (keys.length !== 1) { + if (definedFieldCount !== 1 || keys.length !== 1) { return; // Invalid: intentionally return no value. }