diff --git a/src/validation/__tests__/ScalarLeafsRule-test.ts b/src/validation/__tests__/ScalarLeafsRule-test.ts index fd000b92..33f091e6 100644 --- a/src/validation/__tests__/ScalarLeafsRule-test.ts +++ b/src/validation/__tests__/ScalarLeafsRule-test.ts @@ -1,8 +1,15 @@ import { describe, it } from 'mocha'; +import { expectJSON } from '../../__testUtils__/expectJSON.js'; + +import type { DocumentNode } from '../../language/ast.js'; +import { OperationTypeNode } from '../../language/ast.js'; +import { Kind } from '../../language/kinds.js'; + import { ScalarLeafsRule } from '../rules/ScalarLeafsRule.js'; +import { validate } from '../validate.js'; -import { expectValidationErrors } from './harness.js'; +import { expectValidationErrors, testSchema } from './harness.js'; function expectErrors(queryStr: string) { return expectValidationErrors(ScalarLeafsRule, queryStr); @@ -35,6 +42,39 @@ describe('Validate: Scalar leafs', () => { ]); }); + it('object type having only one selection', () => { + const doc: DocumentNode = { + kind: Kind.DOCUMENT, + definitions: [ + { + kind: Kind.OPERATION_DEFINITION, + operation: OperationTypeNode.QUERY, + selectionSet: { + kind: Kind.SELECTION_SET, + selections: [ + { + kind: Kind.FIELD, + name: { kind: Kind.NAME, value: 'human' }, + selectionSet: { kind: Kind.SELECTION_SET, selections: [] }, + }, + ], + }, + }, + ], + }; + + // We can't leverage expectErrors since it doesn't support passing in the + // documentNode directly. We have to do this because this is technically + // an invalid document. + const errors = validate(testSchema, doc, [ScalarLeafsRule]); + expectJSON(errors).toDeepEqual([ + { + message: + 'Field "human" of type "Human" must have at least one field selected.', + }, + ]); + }); + it('interface type missing selection', () => { expectErrors(` { diff --git a/src/validation/rules/ScalarLeafsRule.ts b/src/validation/rules/ScalarLeafsRule.ts index 7e901493..f1c365b3 100644 --- a/src/validation/rules/ScalarLeafsRule.ts +++ b/src/validation/rules/ScalarLeafsRule.ts @@ -41,6 +41,15 @@ export function ScalarLeafsRule(context: ValidationContext): ASTVisitor { { nodes: node }, ), ); + } else if (selectionSet.selections.length === 0) { + const fieldName = node.name.value; + const typeStr = inspect(type); + context.reportError( + new GraphQLError( + `Field "${fieldName}" of type "${typeStr}" must have at least one field selected.`, + { nodes: node }, + ), + ); } } },