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
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,9 @@ private void ValidateField(
FieldNode field,
IType parentType)
{
if (parentType is not IComplexTypeDefinition complex
var namedParentType = parentType.NamedType();

if (namedParentType is not IComplexTypeDefinition complex
|| !complex.Fields.TryGetField(field.Name.Value, out var fieldDef))
{
// handled by other rules like KnownFieldNames
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Xunit.Sdk;

Expand All @@ -36,7 +37,8 @@ protected async Task<Gateway> CreateCompositeSchemaAsync(
Action<IServiceCollection>? configureServices = null,
Action<IApplicationBuilder>? configureApplication = null,
Action<IFusionGatewayBuilder>? configureGatewayBuilder = null,
[StringSyntax("json")] string? gatewaySettings = null)
[StringSyntax("json")] string? gatewaySettings = null,
string? environmentName = "Development")
{
var sourceSchemas = new List<SourceSchemaText>();
var gatewayServices = new ServiceCollection();
Expand Down Expand Up @@ -181,7 +183,8 @@ protected async Task<Gateway> CreateCompositeSchemaAsync(

configureServices?.Invoke(services);
},
configureApplication);
configureApplication,
environmentName);

return new Gateway(gatewayTestServer, sourceSchemas, interactions);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,76 @@ public async Task Typename_On_Introspection_Types()
await MatchSnapshotAsync(gateway, request, result);
}

[Fact]
public async Task Introspection_OfType_Without_SelectionSet()
{
// arrange
using var server1 = CreateSourceSchema(
"A",
TestSchema);

using var gateway = await CreateCompositeSchemaAsync(
[
("A", server1)
]);

// act
using var client = GraphQLHttpClient.Create(gateway.CreateClient());

var request = new OperationRequest(
"""
{
__schema {
types {
ofType
}
}
}
""");

using var result = await client.PostAsync(
request,
new Uri("http://localhost:5000/graphql"));

// assert
await MatchSnapshotAsync(gateway, request, result);
}

[Fact]
public async Task Introspection_Field_Type_Without_SelectionSet()
{
// arrange
using var server1 = CreateSourceSchema(
"A",
TestSchema);

using var gateway = await CreateCompositeSchemaAsync(
[
("A", server1)
]);

// act
using var client = GraphQLHttpClient.Create(gateway.CreateClient());

var request = new OperationRequest(
"""
{
__type(name: "Query") {
fields {
type
}
}
}
""");

using var result = await client.PostAsync(
request,
new Uri("http://localhost:5000/graphql"));

// assert
await MatchSnapshotAsync(gateway, request, result);
}

[Theory]
[InlineData("SchemaCapabilitiesQuery")]
[InlineData("InputValueCapabilitiesQuery")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,19 @@

public TestServer CreateServer(
Action<IServiceCollection> configureServices,
Action<IApplicationBuilder> configureApplication)
Action<IApplicationBuilder> configureApplication,
string? environmentName = null)
{
var builder = new WebHostBuilder()

Check warning on line 19 in src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/TestServerSession.cs

View workflow job for this annotation

GitHub Actions / Run HotChocolate.Fusion.Caching.Tests

'WebHostBuilder' is obsolete: 'WebHostBuilder is deprecated in favor of HostBuilder and WebApplicationBuilder. For more information, visit https://aka.ms/aspnet/deprecate/004.' (https://aka.ms/aspnet/deprecate/004)

Check warning on line 19 in src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/TestServerSession.cs

View workflow job for this annotation

GitHub Actions / Run HotChocolate.Fusion.Caching.Tests

'WebHostBuilder' is obsolete: 'WebHostBuilder is deprecated in favor of HostBuilder and WebApplicationBuilder. For more information, visit https://aka.ms/aspnet/deprecate/004.' (https://aka.ms/aspnet/deprecate/004)

Check warning on line 19 in src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/TestServerSession.cs

View workflow job for this annotation

GitHub Actions / Run HotChocolate.Fusion.Diagnostics.Tests

'WebHostBuilder' is obsolete: 'WebHostBuilder is deprecated in favor of HostBuilder and WebApplicationBuilder. For more information, visit https://aka.ms/aspnet/deprecate/004.' (https://aka.ms/aspnet/deprecate/004)

Check warning on line 19 in src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/TestServerSession.cs

View workflow job for this annotation

GitHub Actions / Run HotChocolate.Fusion.Diagnostics.Tests

'WebHostBuilder' is obsolete: 'WebHostBuilder is deprecated in favor of HostBuilder and WebApplicationBuilder. For more information, visit https://aka.ms/aspnet/deprecate/004.' (https://aka.ms/aspnet/deprecate/004)

Check warning on line 19 in src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/TestServerSession.cs

View workflow job for this annotation

GitHub Actions / Run HotChocolate.Fusion.AspNetCore.Tests

'WebHostBuilder' is obsolete: 'WebHostBuilder is deprecated in favor of HostBuilder and WebApplicationBuilder. For more information, visit https://aka.ms/aspnet/deprecate/004.' (https://aka.ms/aspnet/deprecate/004)

Check warning on line 19 in src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/TestServerSession.cs

View workflow job for this annotation

GitHub Actions / Run HotChocolate.Fusion.AspNetCore.Tests

'WebHostBuilder' is obsolete: 'WebHostBuilder is deprecated in favor of HostBuilder and WebApplicationBuilder. For more information, visit https://aka.ms/aspnet/deprecate/004.' (https://aka.ms/aspnet/deprecate/004)
.Configure(configureApplication)
.ConfigureServices(configureServices);

if (environmentName is not null)
{
builder.UseEnvironment(environmentName);
}

var server = new TestServer(builder);

Check warning on line 28 in src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/TestServerSession.cs

View workflow job for this annotation

GitHub Actions / Run HotChocolate.Fusion.Caching.Tests

'TestServer.TestServer(IWebHostBuilder)' is obsolete: 'IWebHost, which this method uses, is obsolete. Use one of the ctors that takes an IServiceProvider instead. For more information, visit https://aka.ms/aspnet/deprecate/008.' (https://aka.ms/aspnet/deprecate/008)

Check warning on line 28 in src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/TestServerSession.cs

View workflow job for this annotation

GitHub Actions / Run HotChocolate.Fusion.Caching.Tests

'TestServer.TestServer(IWebHostBuilder)' is obsolete: 'IWebHost, which this method uses, is obsolete. Use one of the ctors that takes an IServiceProvider instead. For more information, visit https://aka.ms/aspnet/deprecate/008.' (https://aka.ms/aspnet/deprecate/008)

Check warning on line 28 in src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/TestServerSession.cs

View workflow job for this annotation

GitHub Actions / Run HotChocolate.Fusion.Diagnostics.Tests

'TestServer.TestServer(IWebHostBuilder)' is obsolete: 'IWebHost, which this method uses, is obsolete. Use one of the ctors that takes an IServiceProvider instead. For more information, visit https://aka.ms/aspnet/deprecate/008.' (https://aka.ms/aspnet/deprecate/008)

Check warning on line 28 in src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/TestServerSession.cs

View workflow job for this annotation

GitHub Actions / Run HotChocolate.Fusion.Diagnostics.Tests

'TestServer.TestServer(IWebHostBuilder)' is obsolete: 'IWebHost, which this method uses, is obsolete. Use one of the ctors that takes an IServiceProvider instead. For more information, visit https://aka.ms/aspnet/deprecate/008.' (https://aka.ms/aspnet/deprecate/008)

Check warning on line 28 in src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/TestServerSession.cs

View workflow job for this annotation

GitHub Actions / Run HotChocolate.Fusion.AspNetCore.Tests

'TestServer.TestServer(IWebHostBuilder)' is obsolete: 'IWebHost, which this method uses, is obsolete. Use one of the ctors that takes an IServiceProvider instead. For more information, visit https://aka.ms/aspnet/deprecate/008.' (https://aka.ms/aspnet/deprecate/008)

Check warning on line 28 in src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/TestServerSession.cs

View workflow job for this annotation

GitHub Actions / Run HotChocolate.Fusion.AspNetCore.Tests

'TestServer.TestServer(IWebHostBuilder)' is obsolete: 'IWebHost, which this method uses, is obsolete. Use one of the ctors that takes an IServiceProvider instead. For more information, visit https://aka.ms/aspnet/deprecate/008.' (https://aka.ms/aspnet/deprecate/008)

if (!_cleanupPipeline.Writer.TryWrite(server))
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
title: Introspection_Field_Type_Without_SelectionSet
request:
document: |
{
__type(name: "Query") {
fields {
type
}
}
}
response:
body: |
{
"errors": [
{
"message": "Field \u0022type\u0022 of type \u0022__Type!\u0022 must have a selection of subfields. Did you mean \u0022type { ... }\u0022?",
"locations": [
{
"line": 4,
"column": 7
}
],
"extensions": {
"declaringType": "__Field",
"field": "type",
"type": "__Type!",
"responseName": "type",
"specifiedBy": "https://spec.graphql.org/September2025/#sec-Field-Selections"
}
}
]
}
sourceSchemas:
- name: A
schema: |
"Schema description"
schema @test(arg: "value") {
query: Query
mutation: Mutation
subscription: Subscription
}

interface Node @test(arg: "value") {
id: ID!
}

"Interface description"
interface Votable implements Node {
"Interface field description"
id: ID!
}

type Mutation @test(arg: "value") {
postReview(input: PostReviewInput): Review @test(arg: "value")
}

type Post implements Votable & Node @key(fields: "id") {
id: ID!
postKind: PostKind @shareable
location: String @inaccessible
}

"Object type description"
type Query @test(arg: "value") {
"Object field description"
posts(
"Argument description"
filter: PostsFilter
first: Int! = 5 @test(arg: "value")
hidden: Boolean @deprecated(reason: "No longer supported")
): [Post]
userCreation: UserCreation
votables: [Votable]! @deprecated(reason: "No longer supported")
postById(postId: ID! @is(field: "id")): Post @lookup
node(id: ID!): Node @lookup
}

type Review implements Votable & Node @test(arg: "value") {
id: ID!
}

type Subscription @test(arg: "value") {
onNewReview: Review
}

"Union description"
union UserCreation @test(arg: "value") = Post | Review

input PostReviewInput @oneOf {
scalar: String @deprecated(reason: "No longer supported")
pros: [PostReviewPro]
}

input PostReviewPro {
scalar: Int!
}

"Input object type description"
input PostsFilter @test(arg: "value") {
"Input field description"
scalar: String = "test" @test(arg: "value")
}

"Enum description"
enum PostKind @test(arg: "value") {
"Enum value description"
STORY @test(arg: "value")
PHOTO @deprecated(reason: "No longer supported")
}

"The `@oneOf` directive is used within the type system definition language to indicate that an Input Object is a OneOf Input Object."
directive @oneOf on INPUT_OBJECT

"Directive description"
directive @test("Directive argument description" arg: String! = "default") repeatable on QUERY | MUTATION | SUBSCRIPTION | FIELD | FRAGMENT_DEFINITION | FRAGMENT_SPREAD | INLINE_FRAGMENT | VARIABLE_DEFINITION | SCHEMA | SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
title: Introspection_OfType_Without_SelectionSet
request:
document: |
{
__schema {
types {
ofType
}
}
}
response:
body: |
{
"errors": [
{
"message": "Field \u0022ofType\u0022 of type \u0022__Type\u0022 must have a selection of subfields. Did you mean \u0022ofType { ... }\u0022?",
"locations": [
{
"line": 4,
"column": 7
}
],
"extensions": {
"declaringType": "__Type",
"field": "ofType",
"type": "__Type",
"responseName": "ofType",
"specifiedBy": "https://spec.graphql.org/September2025/#sec-Field-Selections"
}
}
]
}
sourceSchemas:
- name: A
schema: |
"Schema description"
schema @test(arg: "value") {
query: Query
mutation: Mutation
subscription: Subscription
}

interface Node @test(arg: "value") {
id: ID!
}

"Interface description"
interface Votable implements Node {
"Interface field description"
id: ID!
}

type Mutation @test(arg: "value") {
postReview(input: PostReviewInput): Review @test(arg: "value")
}

type Post implements Votable & Node @key(fields: "id") {
id: ID!
postKind: PostKind @shareable
location: String @inaccessible
}

"Object type description"
type Query @test(arg: "value") {
"Object field description"
posts(
"Argument description"
filter: PostsFilter
first: Int! = 5 @test(arg: "value")
hidden: Boolean @deprecated(reason: "No longer supported")
): [Post]
userCreation: UserCreation
votables: [Votable]! @deprecated(reason: "No longer supported")
postById(postId: ID! @is(field: "id")): Post @lookup
node(id: ID!): Node @lookup
}

type Review implements Votable & Node @test(arg: "value") {
id: ID!
}

type Subscription @test(arg: "value") {
onNewReview: Review
}

"Union description"
union UserCreation @test(arg: "value") = Post | Review

input PostReviewInput @oneOf {
scalar: String @deprecated(reason: "No longer supported")
pros: [PostReviewPro]
}

input PostReviewPro {
scalar: Int!
}

"Input object type description"
input PostsFilter @test(arg: "value") {
"Input field description"
scalar: String = "test" @test(arg: "value")
}

"Enum description"
enum PostKind @test(arg: "value") {
"Enum value description"
STORY @test(arg: "value")
PHOTO @deprecated(reason: "No longer supported")
}

"The `@oneOf` directive is used within the type system definition language to indicate that an Input Object is a OneOf Input Object."
directive @oneOf on INPUT_OBJECT

"Directive description"
directive @test("Directive argument description" arg: String! = "default") repeatable on QUERY | MUTATION | SUBSCRIPTION | FIELD | FRAGMENT_DEFINITION | FRAGMENT_SPREAD | INLINE_FRAGMENT | VARIABLE_DEFINITION | SCHEMA | SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
Loading