Skip to content

Commit 443c150

Browse files
committed
Test suite
1 parent 55f8d21 commit 443c150

2 files changed

Lines changed: 189 additions & 19 deletions

File tree

src/type/__tests__/validation-test.js

Lines changed: 186 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import type {
2020
GraphQLEnumValueConfigMap,
2121
} from '../definition';
2222
import { GraphQLSchema } from '../schema';
23-
import { GraphQLString } from '../scalars';
23+
import { GraphQLString, GraphQLInt } from '../scalars';
2424
import { validateSchema, assertValidSchema } from '../validate';
2525
import { GraphQLDirective, assertDirective } from '../directives';
2626
import {
@@ -871,7 +871,7 @@ describe('Type System: Input Objects must have fields', () => {
871871
it('accepts Input Objects with default values without circular references (SDL)', () => {
872872
const validSchema = buildSchema(`
873873
type Query {
874-
field(arg1: A, arg2: B, arg3: C): String
874+
field(arg1: A, arg2: B): String
875875
}
876876
877877
input A {
@@ -882,6 +882,8 @@ describe('Type System: Input Objects must have fields', () => {
882882
883883
input B {
884884
x: B2 = {}
885+
y: String = "abc"
886+
z: Custom = {}
885887
}
886888
887889
input B2 {
@@ -892,11 +894,6 @@ describe('Type System: Input Objects must have fields', () => {
892894
x: B = { x: { x: null } }
893895
}
894896
895-
input C {
896-
x: String = "123"
897-
y: Custom = {}
898-
}
899-
900897
scalar Custom
901898
`);
902899

@@ -917,6 +914,8 @@ describe('Type System: Input Objects must have fields', () => {
917914
name: 'B',
918915
fields: () => ({
919916
x: { type: B2Type, defaultValue: {} },
917+
y: { type: GraphQLString, defaultValue: 'abc' },
918+
z: { type: CustomType, defaultValue: {} },
920919
}),
921920
});
922921

@@ -936,14 +935,6 @@ describe('Type System: Input Objects must have fields', () => {
936935

937936
const CustomType = new GraphQLScalarType({ name: 'Custom' });
938937

939-
const CType = new GraphQLInputObjectType({
940-
name: 'C',
941-
fields: () => ({
942-
x: { type: GraphQLString, defaultValue: '123' },
943-
y: { type: CustomType, defaultValue: {} },
944-
}),
945-
});
946-
947938
const validSchema = new GraphQLSchema({
948939
query: new GraphQLObjectType({
949940
name: 'Query',
@@ -953,7 +944,6 @@ describe('Type System: Input Objects must have fields', () => {
953944
args: {
954945
arg1: { type: AType },
955946
arg2: { type: BType },
956-
arg3: { type: CType },
957947
},
958948
},
959949
},
@@ -1160,7 +1150,7 @@ describe('Type System: Input Objects must have fields', () => {
11601150
]);
11611151
});
11621152

1163-
it('rejects an Input Object type with required argument that is deprecated', () => {
1153+
it('rejects an Input Object type with required field that is deprecated', () => {
11641154
const schema = buildSchema(`
11651155
type Query {
11661156
field(arg: SomeInputObject): String
@@ -1857,6 +1847,130 @@ describe('Type System: Arguments must have input types', () => {
18571847
});
18581848
});
18591849

1850+
describe('Type System: Argument default values must be valid', () => {
1851+
it('rejects an argument with invalid default values (SDL)', () => {
1852+
const schema = buildSchema(`
1853+
type Query {
1854+
field(arg: Int = 3.14): Int
1855+
}
1856+
1857+
directive @bad(arg: Int = 2.718) on FIELD
1858+
`);
1859+
1860+
expect(validateSchema(schema)).to.deep.equal([
1861+
{
1862+
message:
1863+
'@bad(arg:) has invalid default value: Int cannot represent non-integer value: 2.718',
1864+
locations: [{ line: 6, column: 33 }],
1865+
},
1866+
{
1867+
message:
1868+
'Query.field(arg:) has invalid default value: Int cannot represent non-integer value: 3.14',
1869+
locations: [{ line: 3, column: 26 }],
1870+
},
1871+
]);
1872+
});
1873+
1874+
it('rejects an argument with invalid default values (programmatic)', () => {
1875+
const schema = new GraphQLSchema({
1876+
query: new GraphQLObjectType({
1877+
name: 'Query',
1878+
fields: {
1879+
field: {
1880+
type: GraphQLInt,
1881+
args: {
1882+
arg: { type: GraphQLInt, defaultValue: 3.14 },
1883+
},
1884+
},
1885+
},
1886+
}),
1887+
directives: [
1888+
new GraphQLDirective({
1889+
name: 'bad',
1890+
args: {
1891+
arg: { type: GraphQLInt, defaultValue: 2.718 },
1892+
},
1893+
locations: ['FIELD'],
1894+
}),
1895+
],
1896+
});
1897+
1898+
expect(validateSchema(schema)).to.deep.equal([
1899+
{
1900+
message:
1901+
'@bad(arg:) has invalid default value: Int cannot represent non-integer value: 2.718',
1902+
},
1903+
{
1904+
message:
1905+
'Query.field(arg:) has invalid default value: Int cannot represent non-integer value: 3.14',
1906+
},
1907+
]);
1908+
});
1909+
1910+
it('Attempts to offer a suggested fix if possible', () => {
1911+
const testEnum = new GraphQLEnumType({
1912+
name: 'TestEnum',
1913+
values: {
1914+
ONE: { value: 1 },
1915+
TWO: { value: 2 },
1916+
},
1917+
});
1918+
1919+
const testInput = new GraphQLInputObjectType({
1920+
name: 'TestInput',
1921+
fields: () => ({
1922+
self: { type: testInput },
1923+
string: { type: new GraphQLNonNull(new GraphQLList(GraphQLString)) },
1924+
enum: { type: new GraphQLList(testEnum) },
1925+
}),
1926+
});
1927+
1928+
const schema = new GraphQLSchema({
1929+
query: new GraphQLObjectType({
1930+
name: 'Query',
1931+
fields: {
1932+
field: {
1933+
type: GraphQLInt,
1934+
args: {
1935+
argWithPossibleFix: {
1936+
type: testInput,
1937+
defaultValue: { self: null, string: [1], enum: 2 },
1938+
},
1939+
argWithInvalidPossibleFix: {
1940+
type: testInput,
1941+
defaultValue: { string: null },
1942+
},
1943+
argWithoutPossibleFix: {
1944+
type: testInput,
1945+
defaultValue: { enum: 3 },
1946+
},
1947+
},
1948+
},
1949+
},
1950+
}),
1951+
});
1952+
1953+
expect(validateSchema(schema)).to.deep.equal([
1954+
{
1955+
message:
1956+
'Query.field(argWithPossibleFix:) has invalid default value: { self: null, string: [1], enum: 2 }. Did you mean: { self: null, string: ["1"], enum: "TWO" }?',
1957+
},
1958+
{
1959+
message:
1960+
'Query.field(argWithInvalidPossibleFix:) has invalid default value at .string: Expected value of non-null type "[String]!" not to be null.',
1961+
},
1962+
{
1963+
message:
1964+
'Query.field(argWithoutPossibleFix:) has invalid default value: Expected value of type "TestInput" to include required field "string", found { enum: 3 }',
1965+
},
1966+
{
1967+
message:
1968+
'Query.field(argWithoutPossibleFix:) has invalid default value at .enum: Enum "TestEnum" cannot represent non-string value: 3.',
1969+
},
1970+
]);
1971+
});
1972+
});
1973+
18601974
describe('Type System: Input Object fields must have input types', () => {
18611975
function schemaWithInputField(
18621976
inputFieldConfig: GraphQLInputFieldConfig,
@@ -1953,6 +2067,61 @@ describe('Type System: Input Object fields must have input types', () => {
19532067
});
19542068
});
19552069

2070+
describe('Type System: Input Object field default values must be valid', () => {
2071+
it('rejects an Input Object field with invalid default values (SDL)', () => {
2072+
const schema = buildSchema(`
2073+
type Query {
2074+
field(arg: SomeInputObject): Int
2075+
}
2076+
2077+
input SomeInputObject {
2078+
field: Int = 3.14
2079+
}
2080+
`);
2081+
2082+
expect(validateSchema(schema)).to.deep.equal([
2083+
{
2084+
message:
2085+
'SomeInputObject.field has invalid default value: Int cannot represent non-integer value: 3.14',
2086+
locations: [{ line: 7, column: 20 }],
2087+
},
2088+
]);
2089+
});
2090+
2091+
it('rejects an Input Object field with invalid default values (programmatic)', () => {
2092+
const someInputObject = new GraphQLInputObjectType({
2093+
name: 'SomeInputObject',
2094+
fields: {
2095+
field: {
2096+
type: GraphQLInt,
2097+
defaultValue: 3.14,
2098+
},
2099+
},
2100+
});
2101+
2102+
const schema = new GraphQLSchema({
2103+
query: new GraphQLObjectType({
2104+
name: 'Query',
2105+
fields: {
2106+
field: {
2107+
type: GraphQLInt,
2108+
args: {
2109+
arg: { type: someInputObject },
2110+
},
2111+
},
2112+
},
2113+
}),
2114+
});
2115+
2116+
expect(validateSchema(schema)).to.deep.equal([
2117+
{
2118+
message:
2119+
'SomeInputObject.field has invalid default value: Int cannot represent non-integer value: 3.14',
2120+
},
2121+
]);
2122+
});
2123+
});
2124+
19562125
describe('Objects must adhere to Interface they implement', () => {
19572126
it('accepts an Object which implements an Interface', () => {
19582127
const schema = buildSchema(`

src/type/validate.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,9 +257,9 @@ function validateDefaultValue(
257257
});
258258
if (uncoercedErrors.length === 0) {
259259
context.reportError(
260-
`${coordinate} has an already coerced default value: ${inspect(
260+
`${coordinate} has invalid default value: ${inspect(
261261
defaultValue.value,
262-
)}. Provide it as a pre-coerced value: ${inspect(uncoercedValue)}.`,
262+
)}. Did you mean: ${inspect(uncoercedValue)}?`,
263263
defaultValueNode,
264264
);
265265
errors = [];
@@ -316,6 +316,7 @@ function uncoerceDefaultValue(value: mixed, type: GraphQLInputType): mixed {
316316
});
317317
}
318318

319+
// istanbul ignore else (See: 'https://github.com/graphql/graphql-js/issues/2618')
319320
if (isLeafType(type)) {
320321
// For most leaf types (Scalars, Enums), result coercion ("serialize") is
321322
// the inverse of input coercion ("parseValue") and will produce an

0 commit comments

Comments
 (0)