Skip to content

Commit ec05b54

Browse files
committed
Factor out suggestion quoting utility
1 parent 92923be commit ec05b54

File tree

7 files changed

+79
-35
lines changed

7 files changed

+79
-35
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* Copyright (c) 2015, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
import { expect } from 'chai';
11+
import { describe, it } from 'mocha';
12+
import quotedOrList from '../quotedOrList';
13+
14+
describe('quotedOrList', () => {
15+
16+
it('Does not accept an empty list', () => {
17+
expect(() => quotedOrList([])).to.throw(TypeError);
18+
});
19+
20+
it('Returns single quoted item', () => {
21+
expect(quotedOrList([ 'A' ])).to.equal('"A"');
22+
});
23+
24+
it('Returns two item list', () => {
25+
expect(quotedOrList([ 'A', 'B' ])).to.equal('"A" or "B"');
26+
});
27+
28+
it('Returns comma separated many item list', () => {
29+
expect(quotedOrList([ 'A', 'B', 'C' ])).to.equal('"A", "B", or "C"');
30+
});
31+
32+
it('Limits to five items', () => {
33+
expect(
34+
quotedOrList([ 'A', 'B', 'C', 'D', 'E', 'F' ])
35+
).to.equal(
36+
'"A", "B", "C", "D", or "E"'
37+
);
38+
});
39+
40+
});

src/jsutils/__tests__/suggestionList-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
import { expect } from 'chai';
1111
import { describe, it } from 'mocha';
12-
import { suggestionList } from '../suggestionList';
12+
import suggestionList from '../suggestionList';
1313

1414
describe('suggestionList', () => {
1515

src/jsutils/quotedOrList.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/* @flow */
2+
/**
3+
* Copyright (c) 2015, Facebook, Inc.
4+
* All rights reserved.
5+
*
6+
* This source code is licensed under the BSD-style license found in the
7+
* LICENSE file in the root directory of this source tree. An additional grant
8+
* of patent rights can be found in the PATENTS file in the same directory.
9+
*/
10+
11+
const MAX_LENGTH = 5;
12+
13+
/**
14+
* Given [ A, B, C ] return '"A", "B", or "C"'.
15+
*/
16+
export default function quotedOrList(items: Array<string>): string {
17+
const selected = items.slice(0, MAX_LENGTH);
18+
return selected
19+
.map(item => `"${item}"`)
20+
.reduce((list, quoted, index) =>
21+
list +
22+
(selected.length > 2 ? ', ' : ' ') +
23+
(index === selected.length - 1 ? 'or ' : '') +
24+
quoted
25+
);
26+
}

src/jsutils/suggestionList.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* Given an invalid input string and a list of valid options, returns a filtered
1313
* list of valid options sorted based on their similarity with the input.
1414
*/
15-
export function suggestionList(
15+
export default function suggestionList(
1616
input: string,
1717
options: Array<string>
1818
): Array<string> {

src/validation/rules/FieldsOnCorrectType.js

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010

1111
import type { ValidationContext } from '../index';
1212
import { GraphQLError } from '../../error';
13-
import { suggestionList } from '../../jsutils/suggestionList';
13+
import suggestionList from '../../jsutils/suggestionList';
14+
import quotedOrList from '../../jsutils/quotedOrList';
1415
import type { Field } from '../../language/ast';
1516
import type { GraphQLSchema } from '../../type/schema';
1617
import type { GraphQLOutputType } from '../../type/definition';
@@ -28,13 +29,11 @@ export function undefinedFieldMessage(
2829
suggestedFieldNames: Array<string>
2930
): string {
3031
let message = `Cannot query field "${fieldName}" on type "${type}".`;
31-
const MAX_LENGTH = 5;
3232
if (suggestedTypeNames.length !== 0) {
33-
const suggestions = quotedOrList(suggestedTypeNames.slice(0, MAX_LENGTH));
33+
const suggestions = quotedOrList(suggestedTypeNames);
3434
message += ` Did you mean to use an inline fragment on ${suggestions}?`;
3535
} else if (suggestedFieldNames.length !== 0) {
36-
const suggestions = quotedOrList(suggestedFieldNames.slice(0, MAX_LENGTH));
37-
message += ` Did you mean ${suggestions}?`;
36+
message += ` Did you mean ${quotedOrList(suggestedFieldNames)}?`;
3837
}
3938
return message;
4039
}
@@ -139,15 +138,3 @@ function getSuggestedFieldNames(
139138
// Otherwise, must be a Union type, which does not define fields.
140139
return [];
141140
}
142-
143-
/**
144-
* Given [ A, B, C ] return '"A", "B", or "C"'.
145-
*/
146-
function quotedOrList(items: Array<string>): string {
147-
return items.map(item => `"${item}"`).reduce((list, quoted, index) =>
148-
list +
149-
(items.length > 2 ? ', ' : ' ') +
150-
(index === items.length - 1 ? 'or ' : '') +
151-
quoted
152-
);
153-
}

src/validation/rules/KnownArgumentNames.js

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import type { ValidationContext } from '../index';
1212
import { GraphQLError } from '../../error';
1313
import find from '../../jsutils/find';
1414
import invariant from '../../jsutils/invariant';
15-
import { suggestionList } from '../../jsutils/suggestionList';
15+
import suggestionList from '../../jsutils/suggestionList';
16+
import quotedOrList from '../../jsutils/quotedOrList';
1617
import {
1718
FIELD,
1819
DIRECTIVE
@@ -29,10 +30,7 @@ export function unknownArgMessage(
2930
let message = `Unknown argument "${argName}" on field "${fieldName}" of ` +
3031
`type "${type}".`;
3132
if (suggestedArgs.length) {
32-
const suggestions = suggestedArgs
33-
.map(t => `"${t}"`)
34-
.join(', ');
35-
message += ` Perhaps you meant ${suggestions}?`;
33+
message += ` Did you mean ${quotedOrList(suggestedArgs)}?`;
3634
}
3735
return message;
3836
}
@@ -45,10 +43,7 @@ export function unknownDirectiveArgMessage(
4543
let message =
4644
`Unknown argument "${argName}" on directive "@${directiveName}".`;
4745
if (suggestedArgs.length) {
48-
const suggestions = suggestedArgs
49-
.map(t => `"${t}"`)
50-
.join(', ');
51-
message += ` Perhaps you meant ${suggestions}?`;
46+
message += ` Did you mean ${quotedOrList(suggestedArgs)}?`;
5247
}
5348
return message;
5449
}

src/validation/rules/KnownTypeNames.js

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010

1111
import type { ValidationContext } from '../index';
1212
import { GraphQLError } from '../../error';
13-
import { suggestionList } from '../../jsutils/suggestionList';
13+
import suggestionList from '../../jsutils/suggestionList';
14+
import quotedOrList from '../../jsutils/quotedOrList';
1415
import type { GraphQLType } from '../../type/definition';
1516

1617

@@ -19,13 +20,8 @@ export function unknownTypeMessage(
1920
suggestedTypes: Array<string>
2021
): string {
2122
let message = `Unknown type "${type}".`;
22-
const MAX_LENGTH = 5;
2323
if (suggestedTypes.length) {
24-
const suggestions = suggestedTypes
25-
.slice(0, MAX_LENGTH)
26-
.map(t => `"${t}"`)
27-
.join(', ');
28-
message += ` Perhaps you meant one of the following: ${suggestions}.`;
24+
message += ` Did you mean ${quotedOrList(suggestedTypes)}?`;
2925
}
3026
return message;
3127
}

0 commit comments

Comments
 (0)