diff --git a/src/type/__tests__/enumType-test.js b/src/type/__tests__/enumType-test.js index 80b1f2a17f..37993a673a 100644 --- a/src/type/__tests__/enumType-test.js +++ b/src/type/__tests__/enumType-test.js @@ -224,7 +224,8 @@ describe('Type System: Enum Values', () => { expect(result).to.deep.equal({ errors: [ { - message: 'Expected value of type "Int", found GREEN.', + message: + 'Expected value of type "Int", found GREEN; Int cannot represent non-integer value: GREEN', locations: [{ line: 1, column: 22 }], }, ], diff --git a/src/type/__tests__/scalars-test.js b/src/type/__tests__/scalars-test.js index d9493a5bed..3ad38fa15c 100644 --- a/src/type/__tests__/scalars-test.js +++ b/src/type/__tests__/scalars-test.js @@ -75,18 +75,40 @@ describe('Type System: Specified scalar types', () => { expect(parseLiteral('0')).to.equal(0); expect(parseLiteral('-1')).to.equal(-1); - expect(parseLiteral('9876504321')).to.equal(undefined); - expect(parseLiteral('-9876504321')).to.equal(undefined); - - expect(parseLiteral('1.0')).to.equal(undefined); - expect(parseLiteral('null')).to.equal(undefined); - expect(parseLiteral('""')).to.equal(undefined); - expect(parseLiteral('"123"')).to.equal(undefined); - expect(parseLiteral('false')).to.equal(undefined); - expect(parseLiteral('[1]')).to.equal(undefined); - expect(parseLiteral('{ value: 1 }')).to.equal(undefined); - expect(parseLiteral('ENUM_VALUE')).to.equal(undefined); - expect(parseLiteral('$var')).to.equal(undefined); + expect(() => parseLiteral('9876504321')).to.throw( + 'Int cannot represent non 32-bit signed integer value: 9876504321', + ); + expect(() => parseLiteral('-9876504321')).to.throw( + 'Int cannot represent non 32-bit signed integer value: -9876504321', + ); + + expect(() => parseLiteral('1.0')).to.throw( + 'Int cannot represent non-integer value: 1.0', + ); + expect(() => parseLiteral('null')).to.throw( + 'Int cannot represent non-integer value: null', + ); + expect(() => parseLiteral('""')).to.throw( + 'Int cannot represent non-integer value: ""', + ); + expect(() => parseLiteral('"123"')).to.throw( + 'Int cannot represent non-integer value: "123"', + ); + expect(() => parseLiteral('false')).to.throw( + 'Int cannot represent non-integer value: false', + ); + expect(() => parseLiteral('[1]')).to.throw( + 'Int cannot represent non-integer value: [1]', + ); + expect(() => parseLiteral('{ value: 1 }')).to.throw( + 'Int cannot represent non-integer value: {value: 1}', + ); + expect(() => parseLiteral('ENUM_VALUE')).to.throw( + 'Int cannot represent non-integer value: ENUM_VALUE', + ); + expect(() => parseLiteral('$var')).to.throw( + 'Int cannot represent non-integer value: $var', + ); }); }); @@ -149,15 +171,33 @@ describe('Type System: Specified scalar types', () => { expect(parseLiteral('0.1')).to.equal(0.1); expect(parseLiteral(Math.PI.toString())).to.equal(Math.PI); - expect(parseLiteral('null')).to.equal(undefined); - expect(parseLiteral('""')).to.equal(undefined); - expect(parseLiteral('"123"')).to.equal(undefined); - expect(parseLiteral('"123.5"')).to.equal(undefined); - expect(parseLiteral('false')).to.equal(undefined); - expect(parseLiteral('[0.1]')).to.equal(undefined); - expect(parseLiteral('{ value: 0.1 }')).to.equal(undefined); - expect(parseLiteral('ENUM_VALUE')).to.equal(undefined); - expect(parseLiteral('$var')).to.equal(undefined); + expect(() => parseLiteral('null')).to.throw( + 'Float cannot represent non numeric value: null', + ); + expect(() => parseLiteral('""')).to.throw( + 'Float cannot represent non numeric value: ""', + ); + expect(() => parseLiteral('"123"')).to.throw( + 'Float cannot represent non numeric value: "123"', + ); + expect(() => parseLiteral('"123.5"')).to.throw( + 'Float cannot represent non numeric value: "123.5"', + ); + expect(() => parseLiteral('false')).to.throw( + 'Float cannot represent non numeric value: false', + ); + expect(() => parseLiteral('[0.1]')).to.throw( + 'Float cannot represent non numeric value: [0.1]', + ); + expect(() => parseLiteral('{ value: 0.1 }')).to.throw( + 'Float cannot represent non numeric value: {value: 0.1}', + ); + expect(() => parseLiteral('ENUM_VALUE')).to.throw( + 'Float cannot represent non numeric value: ENUM_VALUE', + ); + expect(() => parseLiteral('$var')).to.throw( + 'Float cannot represent non numeric value: $var', + ); }); }); @@ -200,14 +240,30 @@ describe('Type System: Specified scalar types', () => { expect(parseLiteral('"foo"')).to.equal('foo'); expect(parseLiteral('"""bar"""')).to.equal('bar'); - expect(parseLiteral('null')).to.equal(undefined); - expect(parseLiteral('1')).to.equal(undefined); - expect(parseLiteral('0.1')).to.equal(undefined); - expect(parseLiteral('false')).to.equal(undefined); - expect(parseLiteral('["foo"]')).to.equal(undefined); - expect(parseLiteral('{ value: "foo" }')).to.equal(undefined); - expect(parseLiteral('ENUM_VALUE')).to.equal(undefined); - expect(parseLiteral('$var')).to.equal(undefined); + expect(() => parseLiteral('null')).to.throw( + 'String cannot represent a non string value: null', + ); + expect(() => parseLiteral('1')).to.throw( + 'String cannot represent a non string value: 1', + ); + expect(() => parseLiteral('0.1')).to.throw( + 'String cannot represent a non string value: 0.1', + ); + expect(() => parseLiteral('false')).to.throw( + 'String cannot represent a non string value: false', + ); + expect(() => parseLiteral('["foo"]')).to.throw( + 'String cannot represent a non string value: ["foo"]', + ); + expect(() => parseLiteral('{ value: "foo" }')).to.throw( + 'String cannot represent a non string value: {value: "foo"}', + ); + expect(() => parseLiteral('ENUM_VALUE')).to.throw( + 'String cannot represent a non string value: ENUM_VALUE', + ); + expect(() => parseLiteral('$var')).to.throw( + 'String cannot represent a non string value: $var', + ); }); }); @@ -257,16 +313,36 @@ describe('Type System: Specified scalar types', () => { expect(parseLiteral('true')).to.equal(true); expect(parseLiteral('false')).to.equal(false); - expect(parseLiteral('null')).to.equal(undefined); - expect(parseLiteral('0')).to.equal(undefined); - expect(parseLiteral('1')).to.equal(undefined); - expect(parseLiteral('0.1')).to.equal(undefined); - expect(parseLiteral('""')).to.equal(undefined); - expect(parseLiteral('"false"')).to.equal(undefined); - expect(parseLiteral('[false]')).to.equal(undefined); - expect(parseLiteral('{ value: false }')).to.equal(undefined); - expect(parseLiteral('ENUM_VALUE')).to.equal(undefined); - expect(parseLiteral('$var')).to.equal(undefined); + expect(() => parseLiteral('null')).to.throw( + 'Boolean cannot represent a non boolean value: null', + ); + expect(() => parseLiteral('0')).to.throw( + 'Boolean cannot represent a non boolean value: 0', + ); + expect(() => parseLiteral('1')).to.throw( + 'Boolean cannot represent a non boolean value: 1', + ); + expect(() => parseLiteral('0.1')).to.throw( + 'Boolean cannot represent a non boolean value: 0.1', + ); + expect(() => parseLiteral('""')).to.throw( + 'Boolean cannot represent a non boolean value: ""', + ); + expect(() => parseLiteral('"false"')).to.throw( + 'Boolean cannot represent a non boolean value: "false"', + ); + expect(() => parseLiteral('[false]')).to.throw( + 'Boolean cannot represent a non boolean value: [false]', + ); + expect(() => parseLiteral('{ value: false }')).to.throw( + 'Boolean cannot represent a non boolean value: {value: false}', + ); + expect(() => parseLiteral('ENUM_VALUE')).to.throw( + 'Boolean cannot represent a non boolean value: ENUM_VALUE', + ); + expect(() => parseLiteral('$var')).to.throw( + 'Boolean cannot represent a non boolean value: $var', + ); }); }); @@ -326,13 +402,27 @@ describe('Type System: Specified scalar types', () => { expect(parseLiteral('90071992547409910')).to.equal('90071992547409910'); expect(parseLiteral('-90071992547409910')).to.equal('-90071992547409910'); - expect(parseLiteral('null')).to.equal(undefined); - expect(parseLiteral('0.1')).to.equal(undefined); - expect(parseLiteral('false')).to.equal(undefined); - expect(parseLiteral('["1"]')).to.equal(undefined); - expect(parseLiteral('{ value: "1" }')).to.equal(undefined); - expect(parseLiteral('ENUM_VALUE')).to.equal(undefined); - expect(parseLiteral('$var')).to.equal(undefined); + expect(() => parseLiteral('null')).to.throw( + 'ID cannot represent a non-string and non-integer value: null', + ); + expect(() => parseLiteral('0.1')).to.throw( + 'ID cannot represent a non-string and non-integer value: 0.1', + ); + expect(() => parseLiteral('false')).to.throw( + 'ID cannot represent a non-string and non-integer value: false', + ); + expect(() => parseLiteral('["1"]')).to.throw( + 'ID cannot represent a non-string and non-integer value: ["1"]', + ); + expect(() => parseLiteral('{ value: "1" }')).to.throw( + 'ID cannot represent a non-string and non-integer value: {value: "1"}', + ); + expect(() => parseLiteral('ENUM_VALUE')).to.throw( + 'ID cannot represent a non-string and non-integer value: ENUM_VALUE', + ); + expect(() => parseLiteral('$var')).to.throw( + 'ID cannot represent a non-string and non-integer value: $var', + ); }); }); }); diff --git a/src/type/__tests__/serialization-test.js b/src/type/__tests__/serialization-test.js index a8b636ea55..2dcbd8696a 100644 --- a/src/type/__tests__/serialization-test.js +++ b/src/type/__tests__/serialization-test.js @@ -133,6 +133,11 @@ describe('Type System: Scalar coercion', () => { expect(() => GraphQLString.serialize(badObjValue)).to.throw( 'String cannot represent value: {}', ); + + const badValueOfObjValue = { valueOf: 'valueOf string' }; + expect(() => GraphQLString.serialize(badValueOfObjValue)).to.throw( + 'String cannot represent value: { valueOf: "valueOf string" }', + ); }); it('serializes output as Boolean', () => { diff --git a/src/type/scalars.js b/src/type/scalars.js index bea0c17964..b60c43d390 100644 --- a/src/type/scalars.js +++ b/src/type/scalars.js @@ -7,6 +7,7 @@ import inspect from '../jsutils/inspect'; import isObjectLike from '../jsutils/isObjectLike'; import { Kind } from '../language/kinds'; +import { print } from '../language/printer'; import { GraphQLScalarType, isScalarType } from './definition'; @@ -62,13 +63,18 @@ export const GraphQLInt = new GraphQLScalarType({ serialize: serializeInt, parseValue: coerceInt, parseLiteral(ast) { - if (ast.kind === Kind.INT) { - const num = parseInt(ast.value, 10); - if (num <= MAX_INT && num >= MIN_INT) { - return num; - } + if (ast.kind !== Kind.INT) { + throw new TypeError( + 'Int cannot represent non-integer value: ' + print(ast), + ); + } + const num = parseInt(ast.value, 10); + if (num > MAX_INT || num < MIN_INT) { + throw new TypeError( + 'Int cannot represent non 32-bit signed integer value: ' + ast.value, + ); } - return undefined; + return num; }, }); @@ -105,9 +111,12 @@ export const GraphQLFloat = new GraphQLScalarType({ serialize: serializeFloat, parseValue: coerceFloat, parseLiteral(ast) { - return ast.kind === Kind.FLOAT || ast.kind === Kind.INT - ? parseFloat(ast.value) - : undefined; + if (ast.kind !== Kind.FLOAT && ast.kind !== Kind.INT) { + throw new TypeError( + 'Float cannot represent non numeric value: ' + print(ast), + ); + } + return parseFloat(ast.value); }, }); @@ -163,7 +172,12 @@ export const GraphQLString = new GraphQLScalarType({ serialize: serializeString, parseValue: coerceString, parseLiteral(ast) { - return ast.kind === Kind.STRING ? ast.value : undefined; + if (ast.kind !== Kind.STRING) { + throw new TypeError( + 'String cannot represent a non string value: ' + print(ast), + ); + } + return ast.value; }, }); @@ -194,7 +208,12 @@ export const GraphQLBoolean = new GraphQLScalarType({ serialize: serializeBoolean, parseValue: coerceBoolean, parseLiteral(ast) { - return ast.kind === Kind.BOOLEAN ? ast.value : undefined; + if (ast.kind !== Kind.BOOLEAN) { + throw new TypeError( + 'Boolean cannot represent a non boolean value: ' + print(ast), + ); + } + return ast.value; }, }); @@ -227,9 +246,12 @@ export const GraphQLID = new GraphQLScalarType({ serialize: serializeID, parseValue: coerceID, parseLiteral(ast) { - return ast.kind === Kind.STRING || ast.kind === Kind.INT - ? ast.value - : undefined; + if (ast.kind !== Kind.STRING && ast.kind !== Kind.INT) { + throw new TypeError( + 'ID cannot represent a non-string and non-integer value: ' + print(ast), + ); + } + return ast.value; }, }); diff --git a/src/validation/__tests__/ValuesOfCorrectType-test.js b/src/validation/__tests__/ValuesOfCorrectType-test.js index 2e2acf1033..ec0b752305 100644 --- a/src/validation/__tests__/ValuesOfCorrectType-test.js +++ b/src/validation/__tests__/ValuesOfCorrectType-test.js @@ -165,7 +165,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "String", found 1.', + message: + 'Expected value of type "String", found 1; String cannot represent a non string value: 1', locations: [{ line: 4, column: 39 }], }, ]); @@ -180,7 +181,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "String", found 1.0.', + message: + 'Expected value of type "String", found 1.0; String cannot represent a non string value: 1.0', locations: [{ line: 4, column: 39 }], }, ]); @@ -195,7 +197,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "String", found true.', + message: + 'Expected value of type "String", found true; String cannot represent a non string value: true', locations: [{ line: 4, column: 39 }], }, ]); @@ -210,7 +213,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "String", found BAR.', + message: + 'Expected value of type "String", found BAR; String cannot represent a non string value: BAR', locations: [{ line: 4, column: 39 }], }, ]); @@ -227,7 +231,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "Int", found "3".', + message: + 'Expected value of type "Int", found "3"; Int cannot represent non-integer value: "3"', locations: [{ line: 4, column: 33 }], }, ]); @@ -243,7 +248,7 @@ describe('Validate: Values of correct type', () => { `).to.deep.equal([ { message: - 'Expected value of type "Int", found 829384293849283498239482938.', + 'Expected value of type "Int", found 829384293849283498239482938; Int cannot represent non 32-bit signed integer value: 829384293849283498239482938', locations: [{ line: 4, column: 33 }], }, ]); @@ -258,7 +263,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "Int", found FOO.', + message: + 'Expected value of type "Int", found FOO; Int cannot represent non-integer value: FOO', locations: [{ line: 4, column: 33 }], }, ]); @@ -273,7 +279,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "Int", found 3.0.', + message: + 'Expected value of type "Int", found 3.0; Int cannot represent non-integer value: 3.0', locations: [{ line: 4, column: 33 }], }, ]); @@ -288,7 +295,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "Int", found 3.333.', + message: + 'Expected value of type "Int", found 3.333; Int cannot represent non-integer value: 3.333', locations: [{ line: 4, column: 33 }], }, ]); @@ -305,7 +313,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "Float", found "3.333".', + message: + 'Expected value of type "Float", found "3.333"; Float cannot represent non numeric value: "3.333"', locations: [{ line: 4, column: 37 }], }, ]); @@ -320,7 +329,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "Float", found true.', + message: + 'Expected value of type "Float", found true; Float cannot represent non numeric value: true', locations: [{ line: 4, column: 37 }], }, ]); @@ -335,7 +345,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "Float", found FOO.', + message: + 'Expected value of type "Float", found FOO; Float cannot represent non numeric value: FOO', locations: [{ line: 4, column: 37 }], }, ]); @@ -352,7 +363,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "Boolean", found 2.', + message: + 'Expected value of type "Boolean", found 2; Boolean cannot represent a non boolean value: 2', locations: [{ line: 4, column: 41 }], }, ]); @@ -367,7 +379,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "Boolean", found 1.0.', + message: + 'Expected value of type "Boolean", found 1.0; Boolean cannot represent a non boolean value: 1.0', locations: [{ line: 4, column: 41 }], }, ]); @@ -382,7 +395,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "Boolean", found "true".', + message: + 'Expected value of type "Boolean", found "true"; Boolean cannot represent a non boolean value: "true"', locations: [{ line: 4, column: 41 }], }, ]); @@ -397,7 +411,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "Boolean", found TRUE.', + message: + 'Expected value of type "Boolean", found TRUE; Boolean cannot represent a non boolean value: TRUE', locations: [{ line: 4, column: 41 }], }, ]); @@ -414,7 +429,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "ID", found 1.0.', + message: + 'Expected value of type "ID", found 1.0; ID cannot represent a non-string and non-integer value: 1.0', locations: [{ line: 4, column: 31 }], }, ]); @@ -429,7 +445,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "ID", found true.', + message: + 'Expected value of type "ID", found true; ID cannot represent a non-string and non-integer value: true', locations: [{ line: 4, column: 31 }], }, ]); @@ -444,7 +461,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "ID", found SOMETHING.', + message: + 'Expected value of type "ID", found SOMETHING; ID cannot represent a non-string and non-integer value: SOMETHING', locations: [{ line: 4, column: 31 }], }, ]); @@ -597,7 +615,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "String", found 2.', + message: + 'Expected value of type "String", found 2; String cannot represent a non string value: 2', locations: [{ line: 4, column: 55 }], }, ]); @@ -612,7 +631,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "[String]", found 1.', + message: + 'Expected value of type "[String]", found 1; String cannot represent a non string value: 1', locations: [{ line: 4, column: 47 }], }, ]); @@ -731,11 +751,13 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "Int!", found "two".', + message: + 'Expected value of type "Int!", found "two"; Int cannot represent non-integer value: "two"', locations: [{ line: 4, column: 32 }], }, { - message: 'Expected value of type "Int!", found "one".', + message: + 'Expected value of type "Int!", found "one"; Int cannot represent non-integer value: "one"', locations: [{ line: 4, column: 45 }], }, ]); @@ -750,7 +772,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "Int!", found "one".', + message: + 'Expected value of type "Int!", found "one"; Int cannot represent non-integer value: "one"', locations: [{ line: 4, column: 32 }], }, ]); @@ -875,7 +898,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "String", found 2.', + message: + 'Expected value of type "String", found 2; String cannot represent a non string value: 2', locations: [{ line: 5, column: 40 }], }, ]); @@ -974,11 +998,13 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "Boolean!", found "yes".', + message: + 'Expected value of type "Boolean!", found "yes"; Boolean cannot represent a non boolean value: "yes"', locations: [{ line: 3, column: 28 }], }, { - message: 'Expected value of type "Boolean!", found ENUM.', + message: + 'Expected value of type "Boolean!", found ENUM; Boolean cannot represent a non boolean value: ENUM', locations: [{ line: 4, column: 28 }], }, ]); @@ -1047,11 +1073,13 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "Int", found "one".', + message: + 'Expected value of type "Int", found "one"; Int cannot represent non-integer value: "one"', locations: [{ line: 3, column: 21 }], }, { - message: 'Expected value of type "String", found 4.', + message: + 'Expected value of type "String", found 4; String cannot represent a non string value: 4', locations: [{ line: 4, column: 24 }], }, { @@ -1071,11 +1099,13 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "Boolean!", found 123.', + message: + 'Expected value of type "Boolean!", found 123; Boolean cannot represent a non boolean value: 123', locations: [{ line: 3, column: 47 }], }, { - message: 'Expected value of type "Int", found "abc".', + message: + 'Expected value of type "Int", found "abc"; Int cannot represent non-integer value: "abc"', locations: [{ line: 3, column: 62 }], }, ]); @@ -1102,7 +1132,8 @@ describe('Validate: Values of correct type', () => { } `).to.deep.equal([ { - message: 'Expected value of type "String", found 2.', + message: + 'Expected value of type "String", found 2; String cannot represent a non string value: 2', locations: [{ line: 2, column: 50 }], }, ]);