import { describe, it } from 'node:test';
import { expect } from 'chai';
import { invariant } from '../../jsutils/invariant.ts';
import type { ReadOnlyObjMap } from '../../jsutils/ObjMap.ts';
import { Parser, parseValue } from '../../language/parser.ts';
import { TokenKind } from '../../language/tokenKind.ts';
import type { GraphQLInputType } from '../../type/definition.ts';
import {
GraphQLEnumType,
GraphQLInputObjectType,
GraphQLList,
GraphQLNonNull,
GraphQLScalarType,
} from '../../type/definition.ts';
import { GraphQLInt } from '../../type/scalars.ts';
import { GraphQLSchema } from '../../type/schema.ts';
import type { VariableValues } from '../../execution/values.ts';
import { getVariableValues } from '../../execution/values.ts';
import {
validateInputLiteral,
validateInputValue,
} from '../validateInputValue.ts';
describe('validateInputValue', () => {
function test(
inputValue: unknown,
type: GraphQLInputType,
expected: unknown,
hideSuggestions = false,
) {
const errors: any = [];
validateInputValue(
inputValue,
type,
(error, path) => {
errors.push({ error: error.message, path });
},
hideSuggestions,
);
expect(errors).to.deep.equal(expected);
}
describe('for GraphQLNonNull', () => {
const TestNonNull = new GraphQLNonNull(GraphQLInt);
it('returns no error for non-null value', () => {
test(1, TestNonNull, []);
});
it('returns an error for undefined value', () => {
test(undefined, TestNonNull, [
{
error: 'Expected a value of non-null type "Int!" to be provided.',
path: [],
},
]);
});
it('returns an error for null value', () => {
test(null, TestNonNull, [
{
error: 'Expected value of non-null type "Int!" not to be null.',
path: [],
},
]);
});
});
describe('for GraphQLScalar', () => {
const TestScalar = new GraphQLScalarType({
name: 'TestScalar',
parseValue(input: any) {
invariant(typeof input === 'object' && input !== null);
if (input.error != null) {
throw new Error(input.error);
}
return input.value;
},
});
it('returns no error for valid input', () => {
test({ value: 1 }, TestScalar, []);
});
it('returns no error for null result', () => {
test({ value: null }, TestScalar, []);
});
it('returns no error for NaN result', () => {
test({ value: NaN }, TestScalar, []);
});
it('returns an error for undefined result', () => {
test({ value: undefined }, TestScalar, [
{
error:
'Expected value of type "TestScalar", found: { value: undefined }.',
path: [],
},
]);
});
it('returns an error for undefined result', () => {
const inputValue = { error: 'Some error message.' };
test(inputValue, TestScalar, [
{
error:
'Expected value of type "TestScalar", but encountered error "Some error message."; found: { error: "Some error message." }.',
path: [],
},
]);
});
});
describe('for GraphQLEnum', () => {
const TestEnum = new GraphQLEnumType({
name: 'TestEnum',
values: {
FOO: { value: 'InternalFoo' },
BAR: { value: 123456789 },
},
});
it('returns no error for a known enum name', () => {
test('FOO', TestEnum, []);
test('BAR', TestEnum, []);
});
it('returns an error for unknown enum value', () => {
test('UNKNOWN', TestEnum, [
{
error: 'Value "UNKNOWN" does not exist in "TestEnum" enum.',
path: [],
},
]);
});
it('returns an error for misspelled enum value', () => {
test('foo', TestEnum, [
{
error:
'Value "foo" does not exist in "TestEnum" enum. Did you mean the enum value "FOO"?',
path: [],
},
]);
});
it('returns an error for misspelled enum value (no suggestions)', () => {
test(
'foo',
TestEnum,
[
{
error: 'Value "foo" does not exist in "TestEnum" enum.',
path: [],
},
],
true,
);
});
it('returns an error for incorrect value type', () => {
class Foo {
toJSON() {
return 'FOO';
}
}
test(new Foo(), TestEnum, [
{
error:
'Enum "TestEnum" cannot represent non-string value: FOO. Did you mean the enum value "FOO"?',
path: [],
},
]);
test(
new Foo(),
TestEnum,
[
{
error: 'Enum "TestEnum" cannot represent non-string value: FOO.',
path: [],
},
],
true,
);
test(123, TestEnum, [
{
error: 'Enum "TestEnum" cannot represent non-string value: 123.',
path: [],
},
]);
test({ field: 'value' }, TestEnum, [
{
error:
'Enum "TestEnum" cannot represent non-string value: { field: "value" }.',
path: [],
},
]);
});
it('reports thrown non-error', () => {
const TestThrowScalar = new GraphQLScalarType({
name: 'TestScalar',
parseValue() {
throw 'Not an error object.';
},
});
test({}, TestThrowScalar, [
{
error:
'Expected value of type "TestScalar", but encountered error "Not an error object."; found: {}.',
path: [],
},
]);
});
});
describe('for GraphQLInputObject', () => {
const TestInputObject: GraphQLInputObjectType = new GraphQLInputObjectType({
name: 'TestInputObject',
fields: () => ({
foo: { type: new GraphQLNonNull(GraphQLInt) },
bar: { type: GraphQLInt },
nested: { type: TestInputObject },
}),
});
it('returns no error for a valid input', () => {
test({ foo: 123 }, TestInputObject, []);
});
it('returns an error for a non-object type', () => {
test(123, TestInputObject, [
{
error:
'Expected value of type "TestInputObject" to be an object, found: 123.',
path: [],
},
]);
});
it('returns an error for an invalid field', () => {
test({ foo: NaN }, TestInputObject, [
{
error: 'Int cannot represent non-integer value: NaN',
path: ['foo'],
},
]);
});
it('returns multiple errors for multiple invalid fields', () => {
test({ foo: 'abc', bar: 'def' }, TestInputObject, [
{
error: 'Int cannot represent non-integer value: "abc"',
path: ['foo'],
},
{
error: 'Int cannot represent non-integer value: "def"',
path: ['bar'],
},
]);
});
it('returns error for a missing required field', () => {
test({ bar: 123 }, TestInputObject, [
{
error:
'Expected value of type "TestInputObject" to include required field "foo", found: { bar: 123 }.',
path: [],
},
]);
});
it('returns error for an unknown field', () => {
test({ foo: 123, unknownField: 123 }, TestInputObject, [
{
error:
'Expected value of type "TestInputObject" not to include unknown field "unknownField", found: { foo: 123, unknownField: 123 }.',
path: [],
},
]);
});
it('ignores unknown fields with undefined values', () => {
test({ foo: 123, unknownField: undefined }, TestInputObject, []);
});
it('returns error when supplied with an array', () => {
test([{ foo: 123 }, { bar: 456 }], TestInputObject, [
{
error:
'Expected value of type "TestInputObject" to be an object, found: [{ foo: 123 }, { bar: 456 }].',
path: [],
},
]);
});
it('returns error when a nested input object is supplied with an array', () => {
test(
{ foo: 123, nested: [{ foo: 123 }, { bar: 456 }] },
TestInputObject,
[
{
error:
'Expected value of type "TestInputObject" to be an object, found: [{ foo: 123 }, { bar: 456 }].',
path: ['nested'],
},
],
);
});
it('returns error for a misspelled field', () => {
test({ foo: 123, bart: 123 }, TestInputObject, [
{
error:
'Expected value of type "TestInputObject" not to include unknown field "bart". Did you mean "bar"? Found: { foo: 123, bart: 123 }.',
path: [],
},
]);
});
it('returns error for a misspelled field (no suggestions)', () => {
test(
{ foo: 123, bart: 123 },
TestInputObject,
[
{
error:
'Expected value of type "TestInputObject" not to include unknown field "bart", found: { foo: 123, bart: 123 }.',
path: [],
},
],
true,
);
});
});
describe('for GraphQLInputObject with default value', () => {
function makeTestInputObject(defaultValue: unknown) {
return new GraphQLInputObjectType({
name: 'TestInputObject',
fields: {
foo: {
type: new GraphQLScalarType({ name: 'TestScalar' }),
default: { value: defaultValue },
},
},
});
}
it('no error for no errors for valid input value', () => {
test({ foo: 5 }, makeTestInputObject(7), []);
});
it('no error for object with default value', () => {
test({}, makeTestInputObject(7), []);
});
it('no error for null as value', () => {
test({}, makeTestInputObject(null), []);
});
it('no error for NaN as value', () => {
test({}, makeTestInputObject(NaN), []);
});
});
describe('for GraphQLInputObject that isOneOf', () => {
const TestInputObject = new GraphQLInputObjectType({
name: 'TestInputObject',
fields: {
foo: { type: GraphQLInt },
bar: { type: GraphQLInt },
},
isOneOf: true,
});
it('no error for a valid input', () => {
test({ foo: 123 }, TestInputObject, []);
});
it('returns error if more than one field is specified', () => {
test({ foo: 123, bar: null }, TestInputObject, [
{
error:
'Within OneOf Input Object type "TestInputObject", exactly one field must be specified, and the value for that field must be non-null.',
path: [],
},
]);
});
it('does not count undefined keys as provided', () => {
test({ foo: 123, bar: undefined }, TestInputObject, []);
});
it('returns error if the one field is null', () => {
test({ bar: null }, TestInputObject, [
{
error:
'Within OneOf Input Object type "TestInputObject", exactly one field must be specified, and the value for that field must be non-null.',
path: ['bar'],
},
]);
});
it('returns error for an invalid field', () => {
test({ foo: NaN }, TestInputObject, [
{
error: 'Int cannot represent non-integer value: NaN',
path: ['foo'],
},
]);
});
it('returns multiple errors for multiple invalid fields', () => {
test({ foo: 'abc', bar: 'def' }, TestInputObject, [
{
error: 'Int cannot represent non-integer value: "abc"',
path: ['foo'],
},
{
error: 'Int cannot represent non-integer value: "def"',
path: ['bar'],
},
{
error:
'Within OneOf Input Object type "TestInputObject", exactly one field must be specified, and the value for that field must be non-null.',
path: [],
},
]);
});
it('returns error for an unknown field', () => {
test({ foo: 123, unknownField: 123 }, TestInputObject, [
{
error:
'Expected value of type "TestInputObject" not to include unknown field "unknownField", found: { foo: 123, unknownField: 123 }.',
path: [],
},
]);
});
it('returns error for a misspelled field', () => {
test({ bart: 123 }, TestInputObject, [
{
error:
'Expected value of type "TestInputObject" not to include unknown field "bart". Did you mean "bar"? Found: { bart: 123 }.',
path: [],
},
{
error:
'Within OneOf Input Object type "TestInputObject", exactly one field must be specified, and the value for that field must be non-null.',
path: [],
},
]);
});
it('returns error for a misspelled field (no suggestions)', () => {
test(
{ bart: 123 },
TestInputObject,
[
{
error:
'Expected value of type "TestInputObject" not to include unknown field "bart", found: { bart: 123 }.',
path: [],
},
{
error:
'Within OneOf Input Object type "TestInputObject", exactly one field must be specified, and the value for that field must be non-null.',
path: [],
},
],
true,
);
});
});
describe('for GraphQLList', () => {
const TestList = new GraphQLList(GraphQLInt);
it('returns no error for a valid input', () => {
test([1, 2, 3], TestList, []);
});
it('returns no error for a valid iterable input', () => {
function* listGenerator() {
yield 1;
yield 2;
yield 3;
}
test(listGenerator(), TestList, []);
});
it('returns an error for an invalid input', () => {
test([1, 'b', true, 4], TestList, [
{
error: 'Int cannot represent non-integer value: "b"',
path: [1],
},
{
error: 'Int cannot represent non-integer value: true',
path: [2],
},
]);
});
it('no error for a list for a non-list value', () => {
test(42, TestList, []);
});
it('returns an error for a non-list invalid value', () => {
test('INVALID', TestList, [
{
error: 'Int cannot represent non-integer value: "INVALID"',
path: [],
},
]);
});
it('no error for null for a null value', () => {
test(null, TestList, []);
});
});
describe('for nested GraphQLList', () => {
const TestNestedList = new GraphQLList(new GraphQLList(GraphQLInt));
it('no error for a valid input', () => {
test([[1], [2, 3]], TestNestedList, []);
});
it('no error for a list for a non-list value', () => {
test(42, TestNestedList, []);
});
it('no error for null for a null value', () => {
test(null, TestNestedList, []);
});
it('no error for nested lists for nested non-list values', () => {
test([1, 2, 3], TestNestedList, []);
});
it('no error for nested null for nested null values', () => {
test([42, [null], null], TestNestedList, []);
});
});
});
describe('validateInputLiteral', () => {
function test(
inputValue: string,
type: GraphQLInputType,
expected: unknown,
variableValues?: VariableValues,
hideSuggestions = false,
) {
const errors: any = [];
validateInputLiteral(
parseValue(inputValue),
type,
(error, path) => {
errors.push({ error: error.message, path });
},
variableValues,
undefined,
hideSuggestions,
);
expect(errors).to.deep.equal(expected);
}
function testWithVariables(
variableDefs: string,
values: ReadOnlyObjMap<unknown>,
inputValue: string,
type: GraphQLInputType,
expected: unknown,
) {
const parser = new Parser(variableDefs);
parser.expectToken(TokenKind.SOF);
const variableValuesOrErrors = getVariableValues(
new GraphQLSchema({ types: [GraphQLInt] }),
parser.parseVariableDefinitions() ?? [],
values,
);
invariant(variableValuesOrErrors.variableValues != null);
test(inputValue, type, expected, variableValuesOrErrors.variableValues);
}
it('ignores variables statically', () => {
const TestNonNull = new GraphQLNonNull(GraphQLInt);
test('$var', TestNonNull, []);
});
it('returns an error for null variables for non-nullable types', () => {
const TestNonNull = new GraphQLNonNull(GraphQLInt);
testWithVariables('($var: Int)', { var: null }, '$var', TestNonNull, [
{
error:
'Expected variable "$var" provided to non-null type "Int!" not to be null.',
path: [],
},
]);
});
describe('for GraphQLNonNull', () => {
const TestNonNull = new GraphQLNonNull(GraphQLInt);
it('returns no error for non-null value', () => {
test('1', TestNonNull, []);
});
it('returns an error for null value', () => {
test('null', TestNonNull, [
{
error: 'Expected value of non-null type "Int!" not to be null.',
path: [],
},
]);
});
});
describe('for GraphQLScalar', () => {
const TestScalar = new GraphQLScalarType({
name: 'TestScalar',
parseValue(input: any) {
invariant(typeof input === 'object' && input !== null);
if (input.error != null) {
throw new Error(input.error);
}
return input.value;
},
});
it('returns no error for valid input', () => {
test('{ value: 1 }', TestScalar, []);
});
it('returns no error for null result', () => {
test('{ value: null }', TestScalar, []);
});
it('returns no error for NaN result', () => {
test('{ value: NaN }', TestScalar, []);
});
it('returns an error for undefined result', () => {
test('{}', TestScalar, [
{
error: 'Expected value of type "TestScalar", found: { }.',
path: [],
},
]);
});
it('returns an error for undefined result', () => {
const inputValue = '{ error: "Some error message." }';
test(inputValue, TestScalar, [
{
error:
'Expected value of type "TestScalar", but encountered error "Some error message."; found: { error: "Some error message." }.',
path: [],
},
]);
});
it('reports thrown non-error', () => {
const TestThrowScalar = new GraphQLScalarType({
name: 'TestScalar',
parseValue() {
throw 'Not an error object.';
},
});
test('{}', TestThrowScalar, [
{
error:
'Expected value of type "TestScalar", but encountered error "Not an error object."; found: { }.',
path: [],
},
]);
});
});
describe('for GraphQLEnum', () => {
const TestEnum = new GraphQLEnumType({
name: 'TestEnum',
values: {
FOO: { value: 'InternalFoo' },
BAR: { value: 123456789 },
},
});
it('returns no error for a known enum name', () => {
test('FOO', TestEnum, []);
test('BAR', TestEnum, []);
});
it('returns an error for unknown enum value', () => {
test('UNKNOWN', TestEnum, [
{
error: 'Value "UNKNOWN" does not exist in "TestEnum" enum.',
path: [],
},
]);
});
it('returns an error for misspelled enum value', () => {
test('foo', TestEnum, [
{
error:
'Value "foo" does not exist in "TestEnum" enum. Did you mean the enum value "FOO"?',
path: [],
},
]);
});
it('returns an error for misspelled enum value (no suggestions)', () => {
test(
'foo',
TestEnum,
[
{
error: 'Value "foo" does not exist in "TestEnum" enum.',
path: [],
},
],
undefined,
true,
);
});
it('returns an error for incorrect value type', () => {
test('"FOO"', TestEnum, [
{
error:
'Enum "TestEnum" cannot represent non-enum value: "FOO". Did you mean the enum value "FOO"?',
path: [],
},
]);
test(
'"FOO"',
TestEnum,
[
{
error: 'Enum "TestEnum" cannot represent non-enum value: "FOO".',
path: [],
},
],
undefined,
true,
);
test('"UNKNOWN"', TestEnum, [
{
error: 'Enum "TestEnum" cannot represent non-enum value: "UNKNOWN".',
path: [],
},
]);
test('123', TestEnum, [
{
error: 'Enum "TestEnum" cannot represent non-enum value: 123.',
path: [],
},
]);
test('{ field: "value" }', TestEnum, [
{
error:
'Enum "TestEnum" cannot represent non-enum value: { field: "value" }.',
path: [],
},
]);
});
});
describe('for GraphQLInputObject', () => {
const TestInputObject = new GraphQLInputObjectType({
name: 'TestInputObject',
fields: {
foo: { type: new GraphQLNonNull(GraphQLInt) },
bar: { type: GraphQLInt },
optional: {
type: new GraphQLNonNull(GraphQLInt),
default: { value: 42 },
},
},
});
it('returns no error for a valid input', () => {
test('{ foo: 123 }', TestInputObject, []);
});
it('returns an error for a non-object type', () => {
test('123', TestInputObject, [
{
error:
'Expected value of type "TestInputObject" to be an object, found: 123.',
path: [],
},
]);
});
it('returns an error for an invalid field', () => {
test('{ foo: 1.5 }', TestInputObject, [
{
error: 'Int cannot represent non-integer value: 1.5',
path: ['foo'],
},
]);
});
it('returns multiple errors for multiple invalid fields', () => {
test('{ foo: "abc", bar: "def" }', TestInputObject, [
{
error: 'Int cannot represent non-integer value: "abc"',
path: ['foo'],
},
{
error: 'Int cannot represent non-integer value: "def"',
path: ['bar'],
},
]);
});
it('returns error for a missing required field', () => {
test('{ bar: 123 }', TestInputObject, [
{
error:
'Expected value of type "TestInputObject" to include required field "foo", found: { bar: 123 }.',
path: [],
},
]);
});
it('returns error for an unknown field', () => {
test('{ foo: 123, unknownField: 123 }', TestInputObject, [
{
error:
'Expected value of type "TestInputObject" not to include unknown field "unknownField", found: { foo: 123, unknownField: 123 }.',
path: [],
},
]);
});
it('returns error for a misspelled field', () => {
test('{ foo: 123, bart: 123 }', TestInputObject, [
{
error:
'Expected value of type "TestInputObject" not to include unknown field "bart". Did you mean "bar"? Found: { foo: 123, bart: 123 }.',
path: [],
},
]);
});
it('allows variables in an object, statically', () => {
test('{ foo: $var }', TestInputObject, []);
});
it('allows correct use of variables', () => {
testWithVariables(
'($var: Int)',
{ var: 123 },
'{ foo: $var }',
TestInputObject,
[],
);
});
it('allows missing variables in an nullable field', () => {
testWithVariables('', {}, '{ foo: 123, bar: $var }', TestInputObject, []);
testWithVariables(
'($var: Int)',
{},
'{ foo: 123, bar: $var }',
TestInputObject,
[],
);
});
it('allows missing variables in an optional field', () => {
testWithVariables(
'($var: Int)',
{},
'{ foo: 123, optional: $var }',
TestInputObject,
[],
);
});
it('errors on missing variable in an required field', () => {
testWithVariables('($var: Int)', {}, '{ foo: $var }', TestInputObject, [
{
error:
'Expected variable "$var" provided to type "Int!" to provide a runtime value.',
path: ['foo'],
},
]);
});
it('errors on null variable in an non-null field', () => {
testWithVariables(
'($var: Int)',
{ var: null },
'{ foo: 123, optional: $var }',
TestInputObject,
[
{
error:
'Expected variable "$var" provided to non-null type "Int!" not to be null.',
path: ['optional'],
},
],
);
});
});
describe('for GraphQLInputObject with default value', () => {
function makeTestInputObject(defaultValue: unknown) {
return new GraphQLInputObjectType({
name: 'TestInputObject',
fields: {
foo: {
type: new GraphQLScalarType({ name: 'TestScalar' }),
default: { value: defaultValue },
},
},
});
}
it('no error for no errors for valid input value', () => {
test('{ foo: 5 }', makeTestInputObject(7), []);
});
it('no error for object with default value', () => {
test('{}', makeTestInputObject(7), []);
});
it('no error for null as value', () => {
test('{}', makeTestInputObject(null), []);
});
it('no error for NaN as value', () => {
test('{}', makeTestInputObject(NaN), []);
});
});
describe('for GraphQLInputObject that isOneOf', () => {
const TestInputObject = new GraphQLInputObjectType({
name: 'TestInputObject',
fields: {
foo: { type: GraphQLInt },
bar: { type: GraphQLInt },
},
isOneOf: true,
});
it('returns no error for a valid input', () => {
test('{ foo: 123 }', TestInputObject, []);
});
it('returns an error if more than one field is specified', () => {
test('{ foo: 123, bar: null }', TestInputObject, [
{
error:
'Within OneOf Input Object type "TestInputObject", exactly one field must be specified, and the value for that field must be non-null.',
path: [],
},
]);
});
it('returns an error if the one field is null', () => {
test('{ bar: null }', TestInputObject, [
{
error:
'Within OneOf Input Object type "TestInputObject", exactly one field must be specified, and the value for that field must be non-null.',
path: ['bar'],
},
]);
});
it('returns an error for a non-object type', () => {
test('123', TestInputObject, [
{
error:
'Expected value of type "TestInputObject" to be an object, found: 123.',
path: [],
},
]);
});
it('returns an error for an invalid field', () => {
test('{ foo: 1.5 }', TestInputObject, [
{
error: 'Int cannot represent non-integer value: 1.5',
path: ['foo'],
},
]);
});
it('returns error for an unknown field', () => {
test('{ foo: 123, unknownField: 123 }', TestInputObject, [
{
error:
'Expected value of type "TestInputObject" not to include unknown field "unknownField", found: { foo: 123, unknownField: 123 }.',
path: [],
},
]);
});
it('returns error for a misspelled field', () => {
test('{ foo: 123, bart: 123 }', TestInputObject, [
{
error:
'Expected value of type "TestInputObject" not to include unknown field "bart". Did you mean "bar"? Found: { foo: 123, bart: 123 }.',
path: [],
},
]);
});
it('allows variables in an object, statically', () => {
test('{ foo: $var }', TestInputObject, []);
});
it('allows correct use of variables', () => {
testWithVariables(
'($var: Int)',
{ var: 123 },
'{ foo: $var }',
TestInputObject,
[],
);
});
it('returns error with variable provided a value of null', () => {
testWithVariables(
'($var: Int)',
{ var: null },
'{ foo: $var }',
TestInputObject,
[
{
error:
'Expected variable "$var" provided to field "foo" for OneOf Input Object type "TestInputObject" not to be null.',
path: [],
},
],
);
});
it('errors with missing variables as the additional field', () => {
testWithVariables('', {}, '{ foo: 123, bar: $var }', TestInputObject, [
{
error:
'Expected variable "$var" provided to field "bar" for OneOf Input Object type "TestInputObject" to provide a runtime value.',
path: [],
},
{
error:
'Within OneOf Input Object type "TestInputObject", exactly one field must be specified, and the value for that field must be non-null.',
path: [],
},
]);
testWithVariables(
'($var: Int)',
{},
'{ foo: 123, bar: $var }',
TestInputObject,
[
{
error:
'Expected variable "$var" provided to field "bar" for OneOf Input Object type "TestInputObject" to provide a runtime value.',
path: [],
},
{
error:
'Within OneOf Input Object type "TestInputObject", exactly one field must be specified, and the value for that field must be non-null.',
path: [],
},
],
);
});
it('errors with multiple variables when one is missing', () => {
testWithVariables(
'($foo: Int, $bar: Int)',
{ foo: 123 },
'{ foo: $foo, bar: $bar }',
TestInputObject,
[
{
error:
'Expected variable "$bar" provided to field "bar" for OneOf Input Object type "TestInputObject" to provide a runtime value.',
path: [],
},
{
error:
'Within OneOf Input Object type "TestInputObject", exactly one field must be specified, and the value for that field must be non-null.',
path: [],
},
],
);
});
});
describe('for GraphQLList', () => {
const TestList = new GraphQLList(GraphQLInt);
it('returns no error for a valid input', () => {
test('[1, 2, 3]', TestList, []);
});
it('returns an error for an invalid input', () => {
test('[1, "b", true, 4]', TestList, [
{
error: 'Int cannot represent non-integer value: "b"',
path: [1],
},
{
error: 'Int cannot represent non-integer value: true',
path: [2],
},
]);
});
it('no error for a list for a non-list value', () => {
test('42', TestList, []);
});
it('returns an error for a non-list invalid value', () => {
test('"INVALID"', TestList, [
{
error: 'Int cannot represent non-integer value: "INVALID"',
path: [],
},
]);
});
it('no error for null for a null value', () => {
test('null', TestList, []);
});
it('allows variables in a list, statically', () => {
test('[1, $var, 3]', TestList, []);
});
it('allows missing variables in a list (which coerce to null)', () => {
testWithVariables('($var: Int)', {}, '[1, $var, 3]', TestList, []);
});
it('errors on missing variables in a list of non-null', () => {
const TestListNonNull = new GraphQLList(new GraphQLNonNull(GraphQLInt));
testWithVariables('($var: Int)', {}, '[1, $var, 3]', TestListNonNull, [
{
error:
'Expected variable "$var" provided to type "Int!" to provide a runtime value.',
path: [1],
},
]);
});
it('errors on null variables in a list of non-null', () => {
const TestListNonNull = new GraphQLList(new GraphQLNonNull(GraphQLInt));
testWithVariables(
'($var: Int)',
{ var: null },
'[1, $var, 3]',
TestListNonNull,
[
{
error:
'Expected variable "$var" provided to non-null type "Int!" not to be null.',
path: [1],
},
],
);
});
});
describe('for nested GraphQLList', () => {
const TestNestedList = new GraphQLList(new GraphQLList(GraphQLInt));
it('no error for a valid input', () => {
test('[[1], [2, 3]]', TestNestedList, []);
});
it('no error for a list for a non-list value', () => {
test('42', TestNestedList, []);
});
it('no error for null for a null value', () => {
test('null', TestNestedList, []);
});
it('no error for nested lists for nested non-list values', () => {
test('[1, 2, 3]', TestNestedList, []);
});
it('no error for nested null for nested null values', () => {
test('[42, [null], null]', TestNestedList, []);
});
});
});