Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/HotChocolate/Core/src/Validation/ErrorHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ public IError FieldDoesNotExist(FieldNode node, IComplexTypeDefinition outputTyp

public IError LeafFieldsCannotHaveSelections(
FieldNode node,
IComplexTypeDefinition declaringType,
ITypeDefinition declaringType,
IType fieldType)
{
return ErrorBuilder.New()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,22 @@ private void ValidateField(
{
var namedParentType = parentType.NamedType();

// __typename can be selected on unions and interfaces, which don't have this field,
// so we need this special case for it.
if (IntrospectionFieldNames.TypeName.Equals(field.Name.Value, StringComparison.Ordinal))
{
if (field.SelectionSet is not null)
{
context.ReportError(
context.LeafFieldsCannotHaveSelections(
field,
namedParentType,
new NonNullType(context.Schema.Types["String"])));
}

return;
}

if (namedParentType is not IComplexTypeDefinition complex
|| !complex.Fields.TryGetField(field.Name.Value, out var fieldDef))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,48 @@ public void Validate_Should_RejectInvalidSelections_WhenEnabled(
Assert.Equal(expectedMessage, Assert.Single(context.Errors).Message);
}

[Theory]
[InlineData("{ dog { __typename { name } } }")]
[InlineData("{ human { pets { __typename { name } } } }")]
[InlineData("{ catOrDog { __typename { name } } }")]
[InlineData("{ catOrDog { ...f } } fragment f on CatOrDog { __typename { name } }")]
public void Validate_Should_RejectSelectionsOnTypeName_When_ParentIsAnyCompositeType(string sourceText)
{
// arrange
var rule = new LeafFieldSelectionsRule();
var document = Utf8GraphQLParser.Parse(sourceText);
var context = ValidationUtils.CreateContext(document);

// act
rule.Validate(context, document);

// assert
Assert.Equal(
"Field \"__typename\" must not have a selection since type \"String!\" has no subfields.",
Assert.Single(context.Errors).Message);
}

[Fact]
public void TypeNameOnAbstractTypes()
{
ExpectValid(
"""
{
dog {
__typename
}
human {
pets {
__typename
}
}
catOrDog {
__typename
}
}
""");
}

[Fact]
public void ScalarSelection()
{
Expand Down
Loading