Skip to content

Commit 98364f6

Browse files
committed
Improve error messages further
1 parent 2ada5c6 commit 98364f6

File tree

7 files changed

+93
-51
lines changed

7 files changed

+93
-51
lines changed

src/execution/__tests__/variables.js

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,9 @@ describe('Execute: Handles inputs', () => {
248248
expect(caughtError).to.containSubset({
249249
locations: [ { line: 2, column: 17 } ],
250250
message:
251-
'Variable "$input" expected value of type "TestInputObject" but ' +
252-
'got: {"a":"foo","b":"bar","c":null}. ' +
253-
'In field c: Expected non-null value.'
251+
'Variable "$input" got invalid value ' +
252+
'{"a":"foo","b":"bar","c":null}.' +
253+
'\nIn field "c": Expected "String!", found null.'
254254
});
255255
});
256256

@@ -267,8 +267,8 @@ describe('Execute: Handles inputs', () => {
267267
expect(caughtError).to.containSubset({
268268
locations: [ { line: 2, column: 17 } ],
269269
message:
270-
'Variable "$input" expected value of type "TestInputObject" but ' +
271-
'got: "foo bar". Not an object.'
270+
'Variable "$input" got invalid value "foo bar".' +
271+
'\nExpected "TestInputObject", found not an object.'
272272
});
273273
});
274274

@@ -285,8 +285,8 @@ describe('Execute: Handles inputs', () => {
285285
expect(caughtError).to.containSubset({
286286
locations: [ { line: 2, column: 17 } ],
287287
message:
288-
'Variable "$input" expected value of type "TestInputObject" but ' +
289-
'got: {"a":"foo","b":"bar"}. In field c: Expected non-null value.'
288+
'Variable "$input" got invalid value {"a":"foo","b":"bar"}.' +
289+
'\nIn field "c": Expected "String!", found null.'
290290
});
291291
});
292292

@@ -309,10 +309,9 @@ describe('Execute: Handles inputs', () => {
309309
expect(caughtError).to.containSubset({
310310
locations: [ { line: 2, column: 19 } ],
311311
message:
312-
'Variable "$input" expected value of type "TestNestedInputObject" but ' +
313-
'got: {"na":{"a":"foo"}}.' +
314-
' In field na: In field c: Expected non-null value.' +
315-
' In field nb: Expected non-null value.'
312+
'Variable "$input" got invalid value {"na":{"a":"foo"}}.' +
313+
'\nIn field "na": In field "c": Expected "String!", found null.' +
314+
'\nIn field "nb": Expected "String!", found null.'
316315
});
317316

318317
});
@@ -330,8 +329,10 @@ describe('Execute: Handles inputs', () => {
330329
expect(caughtError).to.containSubset({
331330
locations: [ { line: 2, column: 17 } ],
332331
message:
333-
'Variable "$input" expected value of type "TestInputObject" but ' +
334-
'got: {"a":"foo","b":"bar","c":"baz","d":"dog"}.'
332+
'Variable "$input" got invalid value ' +
333+
'{"a":"foo","b":"bar","c":"baz","d":"dog"}.' +
334+
'\nIn field "d": Expected type "ComplexScalar", found "dog".'
335+
335336
});
336337
});
337338

@@ -687,8 +688,8 @@ describe('Execute: Handles inputs', () => {
687688
expect(caughtError).to.containSubset({
688689
locations: [ { line: 2, column: 17 } ],
689690
message:
690-
'Variable "$input" expected value of type "[String!]" but got: ' +
691-
'["A",null,"B"]. In element #1: Expected non-null value.'
691+
'Variable "$input" got invalid value ["A",null,"B"].' +
692+
'\nIn element #1: Expected "String!", found null.'
692693
});
693694
});
694695

@@ -750,8 +751,8 @@ describe('Execute: Handles inputs', () => {
750751
expect(caughtError).to.containSubset({
751752
locations: [ { line: 2, column: 17 } ],
752753
message:
753-
'Variable "$input" expected value of type "[String!]!" but got: ' +
754-
'["A",null,"B"]. In element #1: Expected non-null value.'
754+
'Variable "$input" got invalid value ["A",null,"B"].' +
755+
'\nIn element #1: Expected "String!", found null.'
755756
});
756757
});
757758

src/execution/values.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,8 @@ function getVariableValue(
113113
}
114114
var message = errors ? '\n' + errors.join('\n') : '';
115115
throw new GraphQLError(
116-
`Variable "$${variable.name.value}" expected value of type ` +
117-
`"${print(definitionAST.type)}" but got: ${JSON.stringify(input)}.` +
118-
`${message}`,
116+
`Variable "$${variable.name.value}" got invalid value ` +
117+
`${JSON.stringify(input)}.${message}`,
119118
[ definitionAST ]
120119
);
121120
}

src/type/__tests__/enumType.js

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,10 @@ describe('Type System: Enum Values', () => {
107107
await graphql(schema, '{ colorEnum(fromEnum: "GREEN") }')
108108
).to.deep.equal({
109109
errors: [
110-
{ message:
111-
'Argument "fromEnum" expected type "Color" but got: "GREEN".' }
110+
{
111+
message: 'Argument "fromEnum" has invalid value "GREEN".' +
112+
'\nExpected type \"Color\", found "GREEN".'
113+
}
112114
]
113115
});
114116
});
@@ -128,7 +130,8 @@ describe('Type System: Enum Values', () => {
128130
await graphql(schema, '{ colorEnum(fromEnum: 1) }')
129131
).to.deep.equal({
130132
errors: [
131-
{ message: 'Argument "fromEnum" expected type "Color" but got: 1.' }
133+
{ message: 'Argument "fromEnum" has invalid value 1.' +
134+
'\nExpected type "Color", found 1.' }
132135
]
133136
});
134137
});
@@ -138,7 +141,8 @@ describe('Type System: Enum Values', () => {
138141
await graphql(schema, '{ colorEnum(fromInt: GREEN) }')
139142
).to.deep.equal({
140143
errors: [
141-
{ message: 'Argument "fromInt" expected type "Int" but got: GREEN.' }
144+
{ message: 'Argument "fromInt" has invalid value GREEN.' +
145+
'\nExpected type "Int", found GREEN.' }
142146
]
143147
});
144148
});
@@ -183,8 +187,11 @@ describe('Type System: Enum Values', () => {
183187
)
184188
).to.deep.equal({
185189
errors: [
186-
{ message:
187-
'Variable "$color" expected value of type "Color!" but got: 2.' }
190+
{
191+
message:
192+
'Variable "\$color" got invalid value 2.' +
193+
'\nExpected type "Color", found 2.'
194+
}
188195
]
189196
});
190197
});

src/utilities/isValidJSValue.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,14 @@ import type { GraphQLInputType } from '../type/definition';
2828
export function isValidJSValue(value: any, type: GraphQLInputType): [ string ] {
2929
// A value must be provided if the type is non-null.
3030
if (type instanceof GraphQLNonNull) {
31+
var ofType: GraphQLInputType = (type.ofType: any);
3132
if (isNullish(value)) {
32-
return [ 'Expected non-null value.' ];
33+
if (ofType.name) {
34+
return [ `Expected "${ofType.name}!", found null.` ];
35+
}
36+
return [ 'Expected non-null value, found null.' ];
3337
}
34-
var nullableType: GraphQLInputType = (type.ofType: any);
35-
return isValidJSValue(value, nullableType);
38+
return isValidJSValue(value, ofType);
3639
}
3740

3841
if (isNullish(value)) {
@@ -56,7 +59,7 @@ export function isValidJSValue(value: any, type: GraphQLInputType): [ string ] {
5659
// Input objects check each defined field.
5760
if (type instanceof GraphQLInputObjectType) {
5861
if (typeof value !== 'object') {
59-
return [ 'Not an object.' ];
62+
return [ `Expected "${type.name}", found not an object.` ];
6063
}
6164
var fields = type.getFields();
6265

@@ -88,7 +91,9 @@ export function isValidJSValue(value: any, type: GraphQLInputType): [ string ] {
8891
// a non-null value.
8992
var parseResult = type.parseValue(value);
9093
if (isNullish(parseResult)) {
91-
return [ `Expected type "${type.name}", found "{JSON.strigify(value)}".` ];
94+
return [
95+
`Expected type "${type.name}", found ${JSON.stringify(value)}.`
96+
];
9297
}
9398

9499
return [];

src/utilities/isValidLiteralValue.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,13 @@ export function isValidLiteralValue(
4141
): [ string ] {
4242
// A value must be provided if the type is non-null.
4343
if (type instanceof GraphQLNonNull) {
44+
var ofType: GraphQLInputType = (type.ofType: any);
4445
if (!valueAST) {
45-
return [ 'Expected non-null value.' ];
46+
if (ofType.name) {
47+
return [ `Expected "${ofType.name}!", found null.` ];
48+
}
49+
return [ 'Expected non-null value, found null.' ];
4650
}
47-
var ofType: GraphQLInputType = (type.ofType: any);
4851
return isValidLiteralValue(ofType, valueAST);
4952
}
5053

@@ -75,7 +78,7 @@ export function isValidLiteralValue(
7578
// Input objects check each defined field and look for undefined fields.
7679
if (type instanceof GraphQLInputObjectType) {
7780
if (valueAST.kind !== OBJECT) {
78-
return [ 'Not an object.' ];
81+
return [ `Expected "${type.name}", found not an object.` ];
7982
}
8083
var fields = type.getFields();
8184

src/validation/__tests__/ArgumentsOfCorrectType.js

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,21 @@ import {
1616

1717

1818
function badValue(argName, typeName, value, line, column, errors) {
19+
var realErrors;
20+
if (!errors) {
21+
realErrors = [
22+
`Expected type "${typeName}", found ${value}.`
23+
];
24+
} else {
25+
realErrors = errors;
26+
}
1927
return {
20-
message: badValueMessage(argName, typeName, value, errors),
28+
message: badValueMessage(argName, typeName, value, realErrors),
2129
locations: [ { line, column } ],
2230
};
2331
}
2432

33+
2534
describe('Validate: Argument values of correct type', () => {
2635

2736
describe('Valid values', () => {
@@ -484,7 +493,9 @@ describe('Validate: Argument values of correct type', () => {
484493
}
485494
}
486495
`, [
487-
badValue('stringListArg', '[String]', '["one", 2]', 4, 47),
496+
badValue('stringListArg', '[String]', '["one", 2]', 4, 47, [
497+
'In element #1: Expected type "String", found 2.'
498+
]),
488499
]);
489500
});
490501

@@ -496,7 +507,7 @@ describe('Validate: Argument values of correct type', () => {
496507
}
497508
}
498509
`, [
499-
badValue('stringListArg', '[String]', '1', 4, 47),
510+
badValue('stringListArg', 'String', '1', 4, 47),
500511
]);
501512
});
502513

@@ -618,8 +629,8 @@ describe('Validate: Argument values of correct type', () => {
618629
}
619630
}
620631
`, [
621-
badValue('req2', 'Int!', '"two"', 4, 32),
622-
badValue('req1', 'Int!', '"one"', 4, 45),
632+
badValue('req2', 'Int', '"two"', 4, 32),
633+
badValue('req1', 'Int', '"one"', 4, 45),
623634
]);
624635
});
625636

@@ -631,7 +642,7 @@ describe('Validate: Argument values of correct type', () => {
631642
}
632643
}
633644
`, [
634-
badValue('req1', 'Int!', '"one"', 4, 32),
645+
badValue('req1', 'Int', '"one"', 4, 32),
635646
]);
636647
});
637648

@@ -726,7 +737,7 @@ describe('Validate: Argument values of correct type', () => {
726737
}
727738
`, [
728739
badValue('complexArg', 'ComplexInput', '{intField: 4}', 4, 41, [
729-
'In field requiredField: Expected non-null value.'
740+
'In field "requiredField": Expected "Boolean!", found null.'
730741
]),
731742
]);
732743
});
@@ -747,7 +758,9 @@ describe('Validate: Argument values of correct type', () => {
747758
'ComplexInput',
748759
'{stringListField: ["one", 2], requiredField: true}',
749760
4,
750-
41
761+
41,
762+
[ 'In field "stringListField": In element #1: ' +
763+
'Expected type "String", found 2.' ]
751764
),
752765
]);
753766
});
@@ -769,7 +782,7 @@ describe('Validate: Argument values of correct type', () => {
769782
'{requiredField: true, unknownField: "value"}',
770783
4,
771784
41,
772-
[ 'Unknown field unknownField.' ]
785+
[ 'Unknown field "unknownField".' ]
773786
),
774787
]);
775788
});
@@ -799,8 +812,8 @@ describe('Validate: Argument values of correct type', () => {
799812
}
800813
}
801814
`, [
802-
badValue('if', 'Boolean!', '"yes"', 3, 28),
803-
badValue('if', 'Boolean!', 'ENUM', 4, 28),
815+
badValue('if', 'Boolean', '"yes"', 3, 28),
816+
badValue('if', 'Boolean', 'ENUM', 4, 28),
804817
]);
805818
});
806819

src/validation/__tests__/DefaultValuesOfCorrectType.js

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,16 @@ function defaultForNonNullArg(varName, typeName, guessTypeName, line, column) {
2424
}
2525

2626
function badValue(varName, typeName, val, line, column, errors) {
27+
var realErrors;
28+
if (!errors) {
29+
realErrors = [
30+
`Expected type "${typeName}", found ${val}.`
31+
];
32+
} else {
33+
realErrors = errors;
34+
}
2735
return {
28-
message: badValueForDefaultArgMessage(varName, typeName, val, errors),
36+
message: badValueForDefaultArgMessage(varName, typeName, val, realErrors),
2937
locations: [ { line, column } ],
3038
};
3139
}
@@ -81,10 +89,14 @@ describe('Validate: Variable default values of correct type', () => {
8189
dog { name }
8290
}
8391
`, [
84-
badValue('a', 'Int', '"one"', 3, 19),
85-
badValue('b', 'String', '4', 4, 22),
92+
badValue('a', 'Int', '"one"', 3, 19, [
93+
'Expected type "Int", found "one".'
94+
]),
95+
badValue('b', 'String', '4', 4, 22, [
96+
'Expected type "String", found 4.'
97+
]),
8698
badValue('c', 'ComplexInput', '"notverycomplex"', 5, 28, [
87-
'Not an object.'
99+
'Expected "ComplexInput", found not an object.'
88100
])
89101
]);
90102
});
@@ -96,7 +108,7 @@ describe('Validate: Variable default values of correct type', () => {
96108
}
97109
`, [
98110
badValue('a', 'ComplexInput', '{intField: 3}', 2, 53, [
99-
'In field requiredField: Expected non-null value.'
111+
'In field "requiredField": Expected "Boolean!", found null.'
100112
])
101113
]);
102114
});
@@ -107,7 +119,9 @@ describe('Validate: Variable default values of correct type', () => {
107119
dog { name }
108120
}
109121
`, [
110-
badValue('a', '[String]', '["one", 2]', 2, 40)
122+
badValue('a', '[String]', '["one", 2]', 2, 40, [
123+
'In element #1: Expected type "String", found 2.'
124+
])
111125
]);
112126
});
113127

0 commit comments

Comments
 (0)