diff --git a/src/utilities/__tests__/valueFromAST-test.js b/src/utilities/__tests__/valueFromAST-test.js index 56ee07ab65..e1b71ef740 100644 --- a/src/utilities/__tests__/valueFromAST-test.js +++ b/src/utilities/__tests__/valueFromAST-test.js @@ -66,7 +66,13 @@ describe('valueFromAST', () => { const testEnum = new GraphQLEnumType({ name: 'TestColor', - values: { RED: { value: 1 }, GREEN: { value: 2 }, BLUE: { value: 3 } } + values: { + RED: { value: 1 }, + GREEN: { value: 2 }, + BLUE: { value: 3 }, + NULL: { value: null }, + UNDEFINED: { value: undefined } + } }); it('converts enum values according to input coercion rules', () => { @@ -75,6 +81,8 @@ describe('valueFromAST', () => { testCase(testEnum, '3', undefined); testCase(testEnum, '"BLUE"', undefined); testCase(testEnum, 'null', null); + testCase(testEnum, 'NULL', null); + testCase(testEnum, 'UNDEFINED', undefined); }); // Boolean! diff --git a/src/utilities/isValidLiteralValue.js b/src/utilities/isValidLiteralValue.js index 0ace788110..a8be69ff56 100644 --- a/src/utilities/isValidLiteralValue.js +++ b/src/utilities/isValidLiteralValue.js @@ -115,10 +115,11 @@ export function isValidLiteralValue( 'Must be input type' ); - // Scalar/Enum input checks to ensure the type can parse the value to - // a non-null value. + // Scalars must parse to a non-null value, Enums may be null but must + // serialize back to a named value. const parseResult = type.parseLiteral(valueNode); - if (isNullish(parseResult)) { + if (type instanceof GraphQLEnumType ? + !type.serialize(parseResult) : isNullish(parseResult)) { return [ `Expected type "${type.name}", found ${print(valueNode)}.` ]; } diff --git a/src/utilities/valueFromAST.js b/src/utilities/valueFromAST.js index 7524386578..ef999e85d8 100644 --- a/src/utilities/valueFromAST.js +++ b/src/utilities/valueFromAST.js @@ -152,9 +152,11 @@ export function valueFromAST( ); const parsed = type.parseLiteral(valueNode); - if (isNullish(parsed)) { - // null or invalid values represent a failure to parse correctly, - // in which case no value is returned. + if (type instanceof GraphQLEnumType ? + !type.serialize(parsed) : isNullish(parsed)) { + // null or invalid values represent a failure to parse correctly (unless + // we have a legitimately null-valued Enum), in which case no value is + // returned. return; } diff --git a/src/validation/__tests__/ArgumentsOfCorrectType-test.js b/src/validation/__tests__/ArgumentsOfCorrectType-test.js index 18e7086607..8d67c57033 100644 --- a/src/validation/__tests__/ArgumentsOfCorrectType-test.js +++ b/src/validation/__tests__/ArgumentsOfCorrectType-test.js @@ -116,6 +116,26 @@ describe('Validate: Argument values of correct type', () => { `); }); + it('Enum with undefined value', () => { + expectPassesRule(ArgumentsOfCorrectType, ` + { + complicatedArgs { + enumArgField(enumArg: UNKNOWN) + } + } + `); + }); + + it('Enum with null value', () => { + expectPassesRule(ArgumentsOfCorrectType, ` + { + complicatedArgs { + enumArgField(enumArg: NO_FUR) + } + } + `); + }); + it('null into nullable type', () => { expectPassesRule(ArgumentsOfCorrectType, ` { diff --git a/src/validation/__tests__/harness.js b/src/validation/__tests__/harness.js index ab26c915cd..a61d5371bb 100644 --- a/src/validation/__tests__/harness.js +++ b/src/validation/__tests__/harness.js @@ -189,6 +189,8 @@ const FurColor = new GraphQLEnumType({ BLACK: { value: 1 }, TAN: { value: 2 }, SPOTTED: { value: 3 }, + NO_FUR: { value: null }, + UNKNOWN: { value: undefined } }, });