Skip to content

Commit ed2b260

Browse files
committed
Validation: Remove internal functions for error messages (#2159)
Makes it easier to review changes in error messages and in general validation tests more readable. Also makes it easier to maintain Flow typings after TS conversion.
1 parent 34d1c69 commit ed2b260

File tree

99 files changed

+1925
-1578
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+1925
-1578
lines changed

src/validation/__tests__/ExecutableDefinitions-test.js

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22

33
import { describe, it } from 'mocha';
44

5-
import {
6-
ExecutableDefinitions,
7-
nonExecutableDefinitionMessage,
8-
} from '../rules/ExecutableDefinitions';
5+
import { ExecutableDefinitions } from '../rules/ExecutableDefinitions';
96

107
import { expectValidationErrors } from './harness';
118

@@ -17,13 +14,6 @@ function expectValid(queryStr) {
1714
expectErrors(queryStr).to.deep.equal([]);
1815
}
1916

20-
function nonExecutableDefinition(defName, line, column) {
21-
return {
22-
message: nonExecutableDefinitionMessage(defName),
23-
locations: [{ line, column }],
24-
};
25-
}
26-
2717
describe('Validate: Executable definitions', () => {
2818
it('with only operation', () => {
2919
expectValid(`
@@ -66,8 +56,14 @@ describe('Validate: Executable definitions', () => {
6656
color: String
6757
}
6858
`).to.deep.equal([
69-
nonExecutableDefinition('Cow', 8, 7),
70-
nonExecutableDefinition('Dog', 12, 7),
59+
{
60+
message: 'The Cow definition is not executable.',
61+
locations: [{ line: 8, column: 7 }],
62+
},
63+
{
64+
message: 'The Dog definition is not executable.',
65+
locations: [{ line: 12, column: 7 }],
66+
},
7167
]);
7268
});
7369

@@ -83,9 +79,18 @@ describe('Validate: Executable definitions', () => {
8379
8480
extend schema @directive
8581
`).to.deep.equal([
86-
nonExecutableDefinition('schema', 2, 7),
87-
nonExecutableDefinition('Query', 6, 7),
88-
nonExecutableDefinition('schema', 10, 7),
82+
{
83+
message: 'The schema definition is not executable.',
84+
locations: [{ line: 2, column: 7 }],
85+
},
86+
{
87+
message: 'The Query definition is not executable.',
88+
locations: [{ line: 6, column: 7 }],
89+
},
90+
{
91+
message: 'The schema definition is not executable.',
92+
locations: [{ line: 10, column: 7 }],
93+
},
8994
]);
9095
});
9196
});

src/validation/__tests__/FieldsOnCorrectType-test.js

Lines changed: 146 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
import { expect } from 'chai';
44
import { describe, it } from 'mocha';
55

6-
import {
7-
FieldsOnCorrectType,
8-
undefinedFieldMessage,
9-
} from '../rules/FieldsOnCorrectType';
6+
import { parse } from '../../language/parser';
7+
8+
import { buildSchema } from '../../utilities/buildASTSchema';
9+
10+
import { validate } from '../validate';
11+
import { FieldsOnCorrectType } from '../rules/FieldsOnCorrectType';
1012

1113
import { expectValidationErrors } from './harness';
1214

@@ -18,25 +20,6 @@ function expectValid(queryStr) {
1820
expectErrors(queryStr).to.deep.equal([]);
1921
}
2022

21-
function undefinedField(
22-
field,
23-
type,
24-
suggestedTypes,
25-
suggestedFields,
26-
line,
27-
column,
28-
) {
29-
return {
30-
message: undefinedFieldMessage(
31-
field,
32-
type,
33-
suggestedTypes,
34-
suggestedFields,
35-
),
36-
locations: [{ line, column }],
37-
};
38-
}
39-
4023
describe('Validate: Fields on correct type', () => {
4124
it('Object field selection', () => {
4225
expectValid(`
@@ -99,8 +82,14 @@ describe('Validate: Fields on correct type', () => {
9982
}
10083
}
10184
`).to.deep.equal([
102-
undefinedField('unknown_pet_field', 'Pet', [], [], 3, 9),
103-
undefinedField('unknown_cat_field', 'Cat', [], [], 5, 13),
85+
{
86+
message: 'Cannot query field "unknown_pet_field" on type "Pet".',
87+
locations: [{ line: 3, column: 9 }],
88+
},
89+
{
90+
message: 'Cannot query field "unknown_cat_field" on type "Cat".',
91+
locations: [{ line: 5, column: 13 }],
92+
},
10493
]);
10594
});
10695

@@ -110,7 +99,11 @@ describe('Validate: Fields on correct type', () => {
11099
meowVolume
111100
}
112101
`).to.deep.equal([
113-
undefinedField('meowVolume', 'Dog', [], ['barkVolume'], 3, 9),
102+
{
103+
message:
104+
'Cannot query field "meowVolume" on type "Dog". Did you mean "barkVolume"?',
105+
locations: [{ line: 3, column: 9 }],
106+
},
114107
]);
115108
});
116109

@@ -121,7 +114,12 @@ describe('Validate: Fields on correct type', () => {
121114
deeper_unknown_field
122115
}
123116
}
124-
`).to.deep.equal([undefinedField('unknown_field', 'Dog', [], [], 3, 9)]);
117+
`).to.deep.equal([
118+
{
119+
message: 'Cannot query field "unknown_field" on type "Dog".',
120+
locations: [{ line: 3, column: 9 }],
121+
},
122+
]);
125123
});
126124

127125
it('Sub-field not defined', () => {
@@ -131,7 +129,12 @@ describe('Validate: Fields on correct type', () => {
131129
unknown_field
132130
}
133131
}
134-
`).to.deep.equal([undefinedField('unknown_field', 'Pet', [], [], 4, 11)]);
132+
`).to.deep.equal([
133+
{
134+
message: 'Cannot query field "unknown_field" on type "Pet".',
135+
locations: [{ line: 4, column: 11 }],
136+
},
137+
]);
135138
});
136139

137140
it('Field not defined on inline fragment', () => {
@@ -142,7 +145,11 @@ describe('Validate: Fields on correct type', () => {
142145
}
143146
}
144147
`).to.deep.equal([
145-
undefinedField('meowVolume', 'Dog', [], ['barkVolume'], 4, 11),
148+
{
149+
message:
150+
'Cannot query field "meowVolume" on type "Dog". Did you mean "barkVolume"?',
151+
locations: [{ line: 4, column: 11 }],
152+
},
146153
]);
147154
});
148155

@@ -152,7 +159,11 @@ describe('Validate: Fields on correct type', () => {
152159
volume : mooVolume
153160
}
154161
`).to.deep.equal([
155-
undefinedField('mooVolume', 'Dog', [], ['barkVolume'], 3, 9),
162+
{
163+
message:
164+
'Cannot query field "mooVolume" on type "Dog". Did you mean "barkVolume"?',
165+
locations: [{ line: 3, column: 9 }],
166+
},
156167
]);
157168
});
158169

@@ -162,7 +173,11 @@ describe('Validate: Fields on correct type', () => {
162173
barkVolume : kawVolume
163174
}
164175
`).to.deep.equal([
165-
undefinedField('kawVolume', 'Dog', [], ['barkVolume'], 3, 9),
176+
{
177+
message:
178+
'Cannot query field "kawVolume" on type "Dog". Did you mean "barkVolume"?',
179+
locations: [{ line: 3, column: 9 }],
180+
},
166181
]);
167182
});
168183

@@ -171,7 +186,12 @@ describe('Validate: Fields on correct type', () => {
171186
fragment notDefinedOnInterface on Pet {
172187
tailLength
173188
}
174-
`).to.deep.equal([undefinedField('tailLength', 'Pet', [], [], 3, 9)]);
189+
`).to.deep.equal([
190+
{
191+
message: 'Cannot query field "tailLength" on type "Pet".',
192+
locations: [{ line: 3, column: 9 }],
193+
},
194+
]);
175195
});
176196

177197
it('Defined on implementors but not on interface', () => {
@@ -180,7 +200,11 @@ describe('Validate: Fields on correct type', () => {
180200
nickname
181201
}
182202
`).to.deep.equal([
183-
undefinedField('nickname', 'Pet', ['Dog', 'Cat'], ['name'], 3, 9),
203+
{
204+
message:
205+
'Cannot query field "nickname" on type "Pet". Did you mean to use an inline fragment on "Dog" or "Cat"?',
206+
locations: [{ line: 3, column: 9 }],
207+
},
184208
]);
185209
});
186210

@@ -197,7 +221,12 @@ describe('Validate: Fields on correct type', () => {
197221
fragment directFieldSelectionOnUnion on CatOrDog {
198222
directField
199223
}
200-
`).to.deep.equal([undefinedField('directField', 'CatOrDog', [], [], 3, 9)]);
224+
`).to.deep.equal([
225+
{
226+
message: 'Cannot query field "directField" on type "CatOrDog".',
227+
locations: [{ line: 3, column: 9 }],
228+
},
229+
]);
201230
});
202231

203232
it('Defined on implementors queried on union', () => {
@@ -206,14 +235,11 @@ describe('Validate: Fields on correct type', () => {
206235
name
207236
}
208237
`).to.deep.equal([
209-
undefinedField(
210-
'name',
211-
'CatOrDog',
212-
['Being', 'Pet', 'Canine', 'Dog', 'Cat'],
213-
[],
214-
3,
215-
9,
216-
),
238+
{
239+
message:
240+
'Cannot query field "name" on type "CatOrDog". Did you mean to use an inline fragment on "Being", "Pet", "Canine", "Dog", or "Cat"?',
241+
locations: [{ line: 3, column: 9 }],
242+
},
217243
]);
218244
});
219245

@@ -231,42 +257,110 @@ describe('Validate: Fields on correct type', () => {
231257
});
232258

233259
describe('Fields on correct type error message', () => {
260+
function expectErrorMessage(schema, queryStr) {
261+
const errors = validate(schema, parse(queryStr), [FieldsOnCorrectType]);
262+
expect(errors.length).to.equal(1);
263+
return expect(errors[0].message);
264+
}
265+
234266
it('Works with no suggestions', () => {
235-
expect(undefinedFieldMessage('f', 'T', [], [])).to.equal(
267+
const schema = buildSchema(`
268+
type T {
269+
fieldWithVeryLongNameThatWillNeverBeSuggested: String
270+
}
271+
type Query { t: T }
272+
`);
273+
274+
expectErrorMessage(schema, '{ t { f } }').to.equal(
236275
'Cannot query field "f" on type "T".',
237276
);
238277
});
239278

240279
it('Works with no small numbers of type suggestions', () => {
241-
expect(undefinedFieldMessage('f', 'T', ['A', 'B'], [])).to.equal(
280+
const schema = buildSchema(`
281+
union T = A | B
282+
type Query { t: T }
283+
284+
type A { f: String }
285+
type B { f: String }
286+
`);
287+
288+
expectErrorMessage(schema, '{ t { f } }').to.equal(
242289
'Cannot query field "f" on type "T". Did you mean to use an inline fragment on "A" or "B"?',
243290
);
244291
});
245292

246293
it('Works with no small numbers of field suggestions', () => {
247-
expect(undefinedFieldMessage('f', 'T', [], ['z', 'y'])).to.equal(
294+
const schema = buildSchema(`
295+
type T {
296+
z: String
297+
y: String
298+
}
299+
type Query { t: T }
300+
`);
301+
302+
expectErrorMessage(schema, '{ t { f } }').to.equal(
248303
'Cannot query field "f" on type "T". Did you mean "z" or "y"?',
249304
);
250305
});
251306

252307
it('Only shows one set of suggestions at a time, preferring types', () => {
253-
expect(undefinedFieldMessage('f', 'T', ['A', 'B'], ['z', 'y'])).to.equal(
308+
const schema = buildSchema(`
309+
interface T {
310+
z: String
311+
y: String
312+
}
313+
type Query { t: T }
314+
315+
type A implements T {
316+
f: String
317+
z: String
318+
y: String
319+
}
320+
type B implements T {
321+
f: String
322+
z: String
323+
y: String
324+
}
325+
`);
326+
327+
expectErrorMessage(schema, '{ t { f } }').to.equal(
254328
'Cannot query field "f" on type "T". Did you mean to use an inline fragment on "A" or "B"?',
255329
);
256330
});
257331

258332
it('Limits lots of type suggestions', () => {
259-
expect(
260-
undefinedFieldMessage('f', 'T', ['A', 'B', 'C', 'D', 'E', 'F'], []),
261-
).to.equal(
333+
const schema = buildSchema(`
334+
union T = A | B | C | D | E | F
335+
type Query { t: T }
336+
337+
type A { f: String }
338+
type B { f: String }
339+
type C { f: String }
340+
type D { f: String }
341+
type E { f: String }
342+
type F { f: String }
343+
`);
344+
345+
expectErrorMessage(schema, '{ t { f } }').to.equal(
262346
'Cannot query field "f" on type "T". Did you mean to use an inline fragment on "A", "B", "C", "D", or "E"?',
263347
);
264348
});
265349

266350
it('Limits lots of field suggestions', () => {
267-
expect(
268-
undefinedFieldMessage('f', 'T', [], ['z', 'y', 'x', 'w', 'v', 'u']),
269-
).to.equal(
351+
const schema = buildSchema(`
352+
type T {
353+
z: String
354+
y: String
355+
x: String
356+
w: String
357+
v: String
358+
u: String
359+
}
360+
type Query { t: T }
361+
`);
362+
363+
expectErrorMessage(schema, '{ t { f } }').to.equal(
270364
'Cannot query field "f" on type "T". Did you mean "z", "y", "x", "w", or "v"?',
271365
);
272366
});

0 commit comments

Comments
 (0)