Skip to content

Commit 8dcc5b0

Browse files
authored
Merge pull request #561 from graphql/format-path
Add path to formatError
2 parents 95c1bc2 + 3e069f5 commit 8dcc5b0

29 files changed

+211
-86
lines changed

src/error/__tests__/GraphQLError-test.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import { expect } from 'chai';
1111
import { describe, it } from 'mocha';
1212

13-
import { parse, Source, GraphQLError } from '../../';
13+
import { parse, Source, GraphQLError, formatError } from '../../';
1414

1515

1616
describe('GraphQLError', () => {
@@ -123,4 +123,20 @@ describe('GraphQLError', () => {
123123
);
124124
});
125125

126+
it('default error formatter includes path', () => {
127+
const e = new GraphQLError(
128+
'msg',
129+
null,
130+
null,
131+
null,
132+
[ 'path', 3, 'to', 'field' ]
133+
);
134+
135+
expect(formatError(e)).to.deep.equal({
136+
message: 'msg',
137+
locations: undefined,
138+
path: [ 'path', 3, 'to', 'field' ]
139+
});
140+
});
141+
126142
});

src/error/formatError.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@ export function formatError(error: GraphQLError): GraphQLFormattedError {
2020
invariant(error, 'Received null or undefined error.');
2121
return {
2222
message: error.message,
23-
locations: error.locations
23+
locations: error.locations,
24+
path: error.path
2425
};
2526
}
2627

2728
export type GraphQLFormattedError = {
2829
message: string,
29-
locations: ?Array<GraphQLErrorLocation>
30+
locations: ?Array<GraphQLErrorLocation>,
31+
path: ?Array<string | number>
3032
};
3133

3234
export type GraphQLErrorLocation = {

src/execution/__tests__/executor-test.js

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -403,27 +403,38 @@ describe('Execute: Handles basic execution tasks', () => {
403403

404404
expect(result.errors && result.errors.map(formatError)).to.deep.equal([
405405
{ message: 'Error getting syncError',
406-
locations: [ { line: 3, column: 7 } ] },
406+
locations: [ { line: 3, column: 7 } ],
407+
path: [ 'syncError' ] },
407408
{ message: 'Error getting syncRawError',
408-
locations: [ { line: 4, column: 7 } ] },
409+
locations: [ { line: 4, column: 7 } ],
410+
path: [ 'syncRawError' ] },
409411
{ message: 'Error getting syncReturnError',
410-
locations: [ { line: 5, column: 7 } ] },
412+
locations: [ { line: 5, column: 7 } ],
413+
path: [ 'syncReturnError' ] },
411414
{ message: 'Error getting syncReturnErrorList1',
412-
locations: [ { line: 6, column: 7 } ] },
415+
locations: [ { line: 6, column: 7 } ],
416+
path: [ 'syncReturnErrorList', 1 ] },
413417
{ message: 'Error getting syncReturnErrorList3',
414-
locations: [ { line: 6, column: 7 } ] },
418+
locations: [ { line: 6, column: 7 } ],
419+
path: [ 'syncReturnErrorList', 3 ] },
415420
{ message: 'Error getting asyncReject',
416-
locations: [ { line: 8, column: 7 } ] },
421+
locations: [ { line: 8, column: 7 } ],
422+
path: [ 'asyncReject' ] },
417423
{ message: 'Error getting asyncRawReject',
418-
locations: [ { line: 9, column: 7 } ] },
424+
locations: [ { line: 9, column: 7 } ],
425+
path: [ 'asyncRawReject' ] },
419426
{ message: 'An unknown error occurred.',
420-
locations: [ { line: 10, column: 7 } ] },
427+
locations: [ { line: 10, column: 7 } ],
428+
path: [ 'asyncEmptyReject' ] },
421429
{ message: 'Error getting asyncError',
422-
locations: [ { line: 11, column: 7 } ] },
430+
locations: [ { line: 11, column: 7 } ],
431+
path: [ 'asyncError' ] },
423432
{ message: 'Error getting asyncRawError',
424-
locations: [ { line: 12, column: 7 } ] },
433+
locations: [ { line: 12, column: 7 } ],
434+
path: [ 'asyncRawError' ] },
425435
{ message: 'Error getting asyncReturnError',
426-
locations: [ { line: 13, column: 7 } ] },
436+
locations: [ { line: 13, column: 7 } ],
437+
path: [ 'asyncReturnError' ] },
427438
]);
428439
});
429440

src/execution/__tests__/lists-test.js

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ describe('Execute: Accepts any iterable as list value', () => {
104104
{ data: { nest: { test: null } },
105105
errors: [ {
106106
message: 'Expected Iterable, but did not find one for field DataType.test.',
107-
locations: [ { line: 1, column: 10 } ]
107+
locations: [ { line: 1, column: 10 } ],
108+
path: [ 'nest', 'test' ]
108109
} ] }
109110
));
110111

@@ -157,7 +158,8 @@ describe('Execute: Handles list nullability', () => {
157158
{ data: { nest: { test: null } },
158159
errors: [
159160
{ message: 'bad',
160-
locations: [ { line: 1, column: 10 } ] }
161+
locations: [ { line: 1, column: 10 } ],
162+
path: [ 'nest', 'test' ] }
161163
] }
162164
));
163165

@@ -180,7 +182,8 @@ describe('Execute: Handles list nullability', () => {
180182
{ data: { nest: { test: [ 1, null, 2 ] } },
181183
errors: [
182184
{ message: 'bad',
183-
locations: [ { line: 1, column: 10 } ] }
185+
locations: [ { line: 1, column: 10 } ],
186+
path: [ 'nest', 'test', 1 ] }
184187
] }
185188
));
186189

@@ -208,7 +211,8 @@ describe('Execute: Handles list nullability', () => {
208211
{ data: { nest: null },
209212
errors: [
210213
{ message: 'Cannot return null for non-nullable field DataType.test.',
211-
locations: [ { line: 1, column: 10 } ] }
214+
locations: [ { line: 1, column: 10 } ],
215+
path: [ 'nest', 'test' ] }
212216
] }
213217
));
214218

@@ -231,7 +235,8 @@ describe('Execute: Handles list nullability', () => {
231235
{ data: { nest: null },
232236
errors: [
233237
{ message: 'Cannot return null for non-nullable field DataType.test.',
234-
locations: [ { line: 1, column: 10 } ] }
238+
locations: [ { line: 1, column: 10 } ],
239+
path: [ 'nest', 'test' ] }
235240
] }
236241
));
237242

@@ -240,7 +245,8 @@ describe('Execute: Handles list nullability', () => {
240245
{ data: { nest: null },
241246
errors: [
242247
{ message: 'bad',
243-
locations: [ { line: 1, column: 10 } ] }
248+
locations: [ { line: 1, column: 10 } ],
249+
path: [ 'nest', 'test' ] }
244250
] }
245251
));
246252

@@ -263,7 +269,8 @@ describe('Execute: Handles list nullability', () => {
263269
{ data: { nest: { test: [ 1, null, 2 ] } },
264270
errors: [
265271
{ message: 'bad',
266-
locations: [ { line: 1, column: 10 } ] }
272+
locations: [ { line: 1, column: 10 } ],
273+
path: [ 'nest', 'test', 1 ] }
267274
] }
268275
));
269276

@@ -286,7 +293,8 @@ describe('Execute: Handles list nullability', () => {
286293
{ data: { nest: { test: null } },
287294
errors: [
288295
{ message: 'Cannot return null for non-nullable field DataType.test.',
289-
locations: [ { line: 1, column: 10 } ] }
296+
locations: [ { line: 1, column: 10 } ],
297+
path: [ 'nest', 'test', 1 ] }
290298
] }
291299
));
292300

@@ -309,7 +317,8 @@ describe('Execute: Handles list nullability', () => {
309317
{ data: { nest: { test: null } },
310318
errors: [
311319
{ message: 'Cannot return null for non-nullable field DataType.test.',
312-
locations: [ { line: 1, column: 10 } ] }
320+
locations: [ { line: 1, column: 10 } ],
321+
path: [ 'nest', 'test', 1 ] }
313322
] }
314323
));
315324

@@ -323,7 +332,8 @@ describe('Execute: Handles list nullability', () => {
323332
{ data: { nest: { test: null } },
324333
errors: [
325334
{ message: 'bad',
326-
locations: [ { line: 1, column: 10 } ] }
335+
locations: [ { line: 1, column: 10 } ],
336+
path: [ 'nest', 'test' ] }
327337
] }
328338
));
329339

@@ -341,7 +351,8 @@ describe('Execute: Handles list nullability', () => {
341351
{ data: { nest: { test: null } },
342352
errors: [
343353
{ message: 'Cannot return null for non-nullable field DataType.test.',
344-
locations: [ { line: 1, column: 10 } ] }
354+
locations: [ { line: 1, column: 10 } ],
355+
path: [ 'nest', 'test', 1 ] }
345356
] }
346357
));
347358

@@ -350,7 +361,8 @@ describe('Execute: Handles list nullability', () => {
350361
{ data: { nest: { test: null } },
351362
errors: [
352363
{ message: 'bad',
353-
locations: [ { line: 1, column: 10 } ] }
364+
locations: [ { line: 1, column: 10 } ],
365+
path: [ 'nest', 'test', 1 ] }
354366
] }
355367
));
356368

@@ -375,7 +387,8 @@ describe('Execute: Handles list nullability', () => {
375387
{ data: { nest: null },
376388
errors: [
377389
{ message: 'Cannot return null for non-nullable field DataType.test.',
378-
locations: [ { line: 1, column: 10 } ] }
390+
locations: [ { line: 1, column: 10 } ],
391+
path: [ 'nest', 'test', 1 ] }
379392
] }
380393
));
381394

@@ -384,7 +397,8 @@ describe('Execute: Handles list nullability', () => {
384397
{ data: { nest: null },
385398
errors: [
386399
{ message: 'Cannot return null for non-nullable field DataType.test.',
387-
locations: [ { line: 1, column: 10 } ] }
400+
locations: [ { line: 1, column: 10 } ],
401+
path: [ 'nest', 'test' ] }
388402
] }
389403
));
390404

@@ -402,7 +416,8 @@ describe('Execute: Handles list nullability', () => {
402416
{ data: { nest: null },
403417
errors: [
404418
{ message: 'Cannot return null for non-nullable field DataType.test.',
405-
locations: [ { line: 1, column: 10 } ] }
419+
locations: [ { line: 1, column: 10 } ],
420+
path: [ 'nest', 'test', 1 ] }
406421
] }
407422
));
408423

@@ -411,7 +426,8 @@ describe('Execute: Handles list nullability', () => {
411426
{ data: { nest: null },
412427
errors: [
413428
{ message: 'Cannot return null for non-nullable field DataType.test.',
414-
locations: [ { line: 1, column: 10 } ] }
429+
locations: [ { line: 1, column: 10 } ],
430+
path: [ 'nest', 'test' ] }
415431
] }
416432
));
417433

@@ -420,7 +436,8 @@ describe('Execute: Handles list nullability', () => {
420436
{ data: { nest: null },
421437
errors: [
422438
{ message: 'bad',
423-
locations: [ { line: 1, column: 10 } ] }
439+
locations: [ { line: 1, column: 10 } ],
440+
path: [ 'nest', 'test' ] }
424441
] }
425442
));
426443

@@ -438,7 +455,8 @@ describe('Execute: Handles list nullability', () => {
438455
{ data: { nest: null },
439456
errors: [
440457
{ message: 'Cannot return null for non-nullable field DataType.test.',
441-
locations: [ { line: 1, column: 10 } ] }
458+
locations: [ { line: 1, column: 10 } ],
459+
path: [ 'nest', 'test', 1 ] }
442460
] }
443461
));
444462

@@ -447,7 +465,8 @@ describe('Execute: Handles list nullability', () => {
447465
{ data: { nest: null },
448466
errors: [
449467
{ message: 'bad',
450-
locations: [ { line: 1, column: 10 } ] }
468+
locations: [ { line: 1, column: 10 } ],
469+
path: [ 'nest', 'test', 1 ] }
451470
] }
452471
));
453472

src/validation/__tests__/ArgumentsOfCorrectType-test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ function badValue(argName, typeName, value, line, column, errors) {
2727
return {
2828
message: badValueMessage(argName, typeName, value, realErrors),
2929
locations: [ { line, column } ],
30+
path: undefined,
3031
};
3132
}
3233

src/validation/__tests__/DefaultValuesOfCorrectType-test.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ function defaultForNonNullArg(varName, typeName, guessTypeName, line, column) {
2020
return {
2121
message: defaultForNonNullArgMessage(varName, typeName, guessTypeName),
2222
locations: [ { line, column } ],
23+
path: undefined,
2324
};
2425
}
2526

@@ -35,6 +36,7 @@ function badValue(varName, typeName, val, line, column, errors) {
3536
return {
3637
message: badValueForDefaultArgMessage(varName, typeName, val, realErrors),
3738
locations: [ { line, column } ],
39+
path: undefined,
3840
};
3941
}
4042

src/validation/__tests__/FieldsOnCorrectType-test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ function undefinedField(
3232
suggestedFields
3333
),
3434
locations: [ { line, column } ],
35+
path: undefined,
3536
};
3637
}
3738

src/validation/__tests__/FragmentsOnCompositeTypes-test.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ function error(fragName, typeName, line, column) {
1919
return {
2020
message: fragmentOnNonCompositeErrorMessage(fragName, typeName),
2121
locations: [ { line, column } ],
22+
path: undefined,
2223
};
2324
}
2425

@@ -101,7 +102,8 @@ describe('Validate: Fragments on composite types', () => {
101102
}
102103
`, [
103104
{ message: inlineFragmentOnNonCompositeErrorMessage('String'),
104-
locations: [ { line: 3, column: 16 } ] }
105+
locations: [ { line: 3, column: 16 } ],
106+
path: undefined }
105107
]);
106108
});
107109

src/validation/__tests__/KnownArgumentNames-test.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ function unknownArg(argName, fieldName, typeName, suggestedArgs, line, column) {
2020
return {
2121
message: unknownArgMessage(argName, fieldName, typeName, suggestedArgs),
2222
locations: [ { line, column } ],
23+
path: undefined,
2324
};
2425
}
2526

@@ -33,6 +34,7 @@ function unknownDirectiveArg(
3334
return {
3435
message: unknownDirectiveArgMessage(argName, directiveName, suggestedArgs),
3536
locations: [ { line, column } ],
37+
path: undefined,
3638
};
3739
}
3840

src/validation/__tests__/KnownDirectives-test.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,16 @@ import {
2222
function unknownDirective(directiveName, line, column) {
2323
return {
2424
message: unknownDirectiveMessage(directiveName),
25-
locations: [ { line, column } ]
25+
locations: [ { line, column } ],
26+
path: undefined,
2627
};
2728
}
2829

2930
function misplacedDirective(directiveName, placement, line, column) {
3031
return {
3132
message: misplacedDirectiveMessage(directiveName, placement),
32-
locations: [ { line, column } ]
33+
locations: [ { line, column } ],
34+
path: undefined,
3335
};
3436
}
3537

0 commit comments

Comments
 (0)