diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/DemoIntegrationTests.LegacyPorted.cs b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/DemoIntegrationTests.LegacyPorted.cs new file mode 100644 index 00000000000..6b0dfc2deb9 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/DemoIntegrationTests.LegacyPorted.cs @@ -0,0 +1,1346 @@ +using HotChocolate.Transport; +using HotChocolate.Transport.Http; + +namespace HotChocolate.Fusion; + +public partial class DemoIntegrationTests +{ + [Fact] + public async Task Authors_And_Reviews_AutoCompose() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2); + + var request = new OperationRequest( + """ + query { + users { + id + } + reviews { + body + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Authors_And_Reviews_And_Products_AutoCompose() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2 | DemoSubgraphs.Products); + + var request = new OperationRequest( + """ + query { + users { + id + } + reviews { + body + } + topProducts(first: 2) { + id + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Authors_And_Reviews_Query_GetUserReviews() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2); + + var request = new OperationRequest( + """ + query GetUser { + users { + name + reviews { + body + author { + name + } + } + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact(Skip = "Cost reporting request options are not wired for this v15 harness yet.")] + public async Task Authors_And_Reviews_Query_GetUserReviews_Report_Cost() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2); + + var request = new OperationRequest( + """ + query GetUser { + users { + name + reviews { + body + author { + name + } + } + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Authors_And_Reviews_Query_GetUserReviews_Skip_Author() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2); + + var request = new OperationRequest( + """ + query GetUser($skip: Boolean!) { + users { + name + reviews { + body + author @skip(if: $skip) { + name + birthdate + } + } + } + } + """, + variables: new Dictionary { ["skip"] = true }); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Authors_And_Reviews_Query_GetUserReviews_Skip_Author_ErrorField() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2); + + var request = new OperationRequest( + """ + query GetUser($skip: Boolean!) { + users { + name + reviews { + body + author { + name + birthdate + errorField @skip(if: $skip) + } + } + } + } + """, + variables: new Dictionary { ["skip"] = true }); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Authors_And_Reviews_Query_GetUserById() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2); + + var request = new OperationRequest( + """ + query GetUser { + userById(id: "VXNlcjox") { + id + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Authors_And_Reviews_Query_GetUserById_With_Invalid_Id_Value() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2); + + var request = new OperationRequest( + """ + query GetUser { + userById(id: 1) { + id + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact(Skip = "Legacy V15 websocket/SSE subscription setup is not ported in this harness.")] + public async Task Authors_And_Reviews_Subscription_OnNewReview() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2); + + var request = new OperationRequest( + """ + subscription OnNewReview { + onNewReview { + body + author { + name + } + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact(Skip = "Legacy V15 websocket/SSE subscription setup is not ported in this harness.")] + public async Task Authors_And_Reviews_Subscription_OnNewReviewError() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2); + + var request = new OperationRequest( + """ + subscription OnNewReview { + onNewReviewError { + body + author { + name + } + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact(Skip = "Legacy V15 websocket/SSE subscription setup is not ported in this harness.")] + public async Task Authors_And_Reviews_Subscription_OnError() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2); + + var request = new OperationRequest( + """ + subscription OnError { + onError { + body + author { + name + } + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact(Skip = "Legacy V15 websocket/SSE subscription setup is not ported in this harness.")] + public async Task Authors_And_Reviews_Subscription_OnError_SSE() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2); + + var request = new OperationRequest( + """ + subscription OnError { + onError { + body + author { + name + } + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact(Skip = "Legacy V15 websocket/SSE subscription setup is not ported in this harness.")] + public async Task Authors_And_Reviews_Subscription_OnNewReview_Two_Graphs() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2); + + var request = new OperationRequest( + """ + subscription OnNewReview { + onNewReview { + body + author { + name + birthdate + } + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Authors_And_Reviews_Query_ReviewsUser() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2); + + var request = new OperationRequest( + """ + query GetUser { + a: reviews { + body + author { + name + } + } + b: reviews { + body + author { + name + } + } + users { + name + reviews { + body + author { + name + } + } + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact(Skip = "Do we want to reformat ids?")] + public async Task Authors_And_Reviews_Query_Reformat_AuthorIds() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2); + + var request = new OperationRequest( + """ + query ReformatIds { + reviews { + author { + id + } + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact(Skip = "this does not work yet")] + public async Task Authors_And_Reviews_Query_Reformat_AuthorIds_ReEncodeAllIds() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2); + + var request = new OperationRequest( + """ + query ReformatIds { + reviews { + author { + id + } + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Authors_And_Reviews_Batch_Requests() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2); + + var request = new OperationRequest( + """ + query GetUser { + reviews { + body + author { + birthdate + } + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Authors_And_Reviews_And_Products_Query_TopProducts() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2 | DemoSubgraphs.Products); + + var request = new OperationRequest( + """ + query TopProducts { + topProducts(first: 2) { + name + reviews { + body + author { + name + } + } + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Authors_And_Reviews_And_Products_Query_TypeName() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2 | DemoSubgraphs.Products); + + var request = new OperationRequest( + """ + query TopProducts { + __typename + topProducts(first: 2) { + __typename + reviews { + __typename + author { + __typename + } + } + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Authors_And_Reviews_And_Products_With_Variables() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2 | DemoSubgraphs.Products); + + var request = new OperationRequest( + """ + query TopProducts($first: Int!) { + topProducts(first: $first) { + id + } + } + """, + variables: new Dictionary { ["first"] = 2 }); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Authors_And_Reviews_And_Products_Introspection() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2 | DemoSubgraphs.Products); + + var request = new OperationRequest( + """ + query Introspect { + __schema { + types { + name + kind + fields { + name + type { + name + kind + } + } + } + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Fetch_User_With_Node_Field() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2 | DemoSubgraphs.Products); + + var request = new OperationRequest( + """ + query FetchNode($id: ID!) { + node(id: $id) { + ... on User { + id + } + } + } + """, + variables: new Dictionary { ["id"] = "VXNlcjox" }); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Fetch_User_With_Invalid_Node_Field() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2 | DemoSubgraphs.Products); + + var request = new OperationRequest( + """ + query FetchNode($id: ID!) { + node(id: $id) { + ... on User { + id + } + } + } + """, + variables: new Dictionary { ["id"] = 1 }); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Fetch_User_With_Node_Field_Pass_In_Review_Id() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2 | DemoSubgraphs.Products); + + var request = new OperationRequest( + """ + query FetchNode($id: ID!) { + node(id: $id) { + ... on User { + id + } + } + } + """, + variables: new Dictionary { ["id"] = "UmV2aWV3OjE=" }); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Fetch_User_With_Node_Field_Pass_In_Unknown_Id() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2 | DemoSubgraphs.Products); + + var request = new OperationRequest( + """ + query FetchNode($id: ID!) { + node(id: $id) { + ... on User { + id + } + } + } + """, + variables: new Dictionary { ["id"] = "VW5rbm93bjox" }); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Fetch_User_With_Node_Field_From_Two_Subgraphs() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2 | DemoSubgraphs.Products); + + var request = new OperationRequest( + """ + query FetchNode($id: ID!) { + node(id: $id) { + ... on User { + birthdate + reviews { + body + } + } + } + } + """, + variables: new Dictionary { ["id"] = "VXNlcjox" }); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact(Skip = "Hot reload via dynamic gateway configuration is not ported in this harness.")] + public async Task Hot_Reload() + { + // arrange + using var gateway = await CreateDemoGatewayAsync(DemoSubgraphs.Accounts); + + var request = new OperationRequest( + """ + { + __type(name: "Query") { + fields { + name + } + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task TypeName_Field_On_QueryRoot() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2 | DemoSubgraphs.Products); + + var request = new OperationRequest( + """ + query Introspect { + __typename + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Forward_Nested_Variables() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2 | DemoSubgraphs.Products); + + var request = new OperationRequest( + """ + query ProductReviews( + $id: ID! + $first: Int! + ) { + productById(id: $id) { + id + repeat(num: $first) + } + } + """, + variables: new Dictionary + { + ["id"] = "UHJvZHVjdDox", + ["first"] = 1 + }); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Forward_Nested_Variables_No_OpName() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2 | DemoSubgraphs.Products); + + var request = new OperationRequest( + """ + query ( + $id: ID! + $first: Int! + ) { + productById(id: $id) { + id + repeat(num: $first) + } + } + """, + variables: new Dictionary + { + ["id"] = "UHJvZHVjdDox", + ["first"] = 1 + }); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Forward_Nested_Variables_No_OpName_Two_RootSelections() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2 | DemoSubgraphs.Products); + + var request = new OperationRequest( + """ + query ( + $id: ID! + $first: Int! + ) { + a: productById(id: $id) { + id + repeat(num: $first) + } + b: productById(id: $id) { + id + repeat(num: $first) + } + } + """, + variables: new Dictionary + { + ["id"] = "UHJvZHVjdDox", + ["first"] = 1 + }); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Forward_Nested_Node_Variables() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2 | DemoSubgraphs.Products); + + var request = new OperationRequest( + """ + query ProductReviews( + $id: ID! + $first: Int! + ) { + node(id: $id) { + ... on Product { + id + repeat(num: $first) + } + } + } + """, + variables: new Dictionary + { + ["id"] = "UHJvZHVjdDox", + ["first"] = 1 + }); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Forward_Nested_Object_Variables() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2 | DemoSubgraphs.Products); + + var request = new OperationRequest( + """ + query ProductReviews( + $id: ID! + $first: Int! + ) { + productById(id: $id) { + id + repeatData(data: { data: { num: $first } }) { + data { + num + } + } + } + } + """, + variables: new Dictionary + { + ["id"] = "UHJvZHVjdDox", + ["first"] = 1 + }); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Require_Data_In_Context() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2 | DemoSubgraphs.Products | DemoSubgraphs.Shipping); + + var request = new OperationRequest( + """ + query Requires { + reviews { + body + author { + name + birthdate + } + product { + name + deliveryEstimate(zip: "12345") { + min + max + } + } + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Require_Data_In_Context_2() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2 | DemoSubgraphs.Products | DemoSubgraphs.Shipping); + + var request = new OperationRequest( + """ + query Requires { + reviews { + body + author { + name + birthdate + } + product { + deliveryEstimate(zip: "12345") { + min + max + } + } + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Require_Data_In_Context_3() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2 | DemoSubgraphs.Products | DemoSubgraphs.Shipping); + + var request = new OperationRequest( + """ + query Large { + users { + id + name + birthdate + reviews { + body + author { + name + birthdate + } + product { + id + name + deliveryEstimate(zip: "abc") { + max + } + } + } + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task GetFirstPage_With_After_Null() + { + // arrange + using var gateway = await CreateDemoGatewayAsync(DemoSubgraphs.Appointment); + + var request = new OperationRequest( + """ + query AfterNull($after: String) { + appointments(after: $after) { + nodes { + id + } + } + } + """, + variables: new Dictionary { ["after"] = null }); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task QueryType_Parallel_Multiple_SubGraphs_WithArguments() + { + // arrange + using var gateway = await CreateDemoGatewayAsync( + DemoSubgraphs.Accounts | DemoSubgraphs.Reviews2 | DemoSubgraphs.Products | DemoSubgraphs.Shipping); + + var request = new OperationRequest( + """ + query TopProducts { + topProducts(first: 5) { + weight + deliveryEstimate(zip: "12345") { + min + max + } + reviews { + body + } + } + } + """); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + [Fact] + public async Task Two_Arguments_Differing_Nullability_Does_Not_Duplicate_Forwarded_Variables() + { + // arrange + using var gateway = await CreateDemoGatewayAsync(DemoSubgraphs.Accounts); + + var request = new OperationRequest( + """ + query Test($number: Int!) { + testWithTwoArgumentsDifferingNullability(first: $number, second: $number) + } + """, + variables: new Dictionary { ["number"] = 1 }); + + // act + using var client = GraphQLHttpClient.Create(gateway.CreateClient()); + using var result = await client.PostAsync(request, _graphQLEndpoint); + + // assert + await MatchSnapshotAsync(gateway, request, result); + } + + private async Task CreateDemoGatewayAsync(DemoSubgraphs subgraphs) + { + var sourceSchemas = new List<(string SchemaName, Microsoft.AspNetCore.TestHost.TestServer Server)>(); + + if (subgraphs.HasFlag(DemoSubgraphs.Accounts)) + { + sourceSchemas.Add(("A", CreateSourceSchema("A", AccountsSchema))); + } + + if (subgraphs.HasFlag(DemoSubgraphs.Reviews2)) + { + sourceSchemas.Add(("B", CreateSourceSchema("B", Reviews2Schema))); + } + + if (subgraphs.HasFlag(DemoSubgraphs.Products)) + { + sourceSchemas.Add(("C", CreateSourceSchema("C", ProductsSchema))); + } + + if (subgraphs.HasFlag(DemoSubgraphs.Shipping)) + { + sourceSchemas.Add(("D", CreateSourceSchema("D", ShippingSchema))); + } + + if (subgraphs.HasFlag(DemoSubgraphs.Appointment)) + { + sourceSchemas.Add(("E", CreateSourceSchema("E", AppointmentSchema))); + } + + if (sourceSchemas.Count is 0) + { + throw new ArgumentException("At least one subgraph must be specified.", nameof(subgraphs)); + } + + return await CreateCompositeSchemaAsync(sourceSchemas.ToArray()); + } + + [Flags] + private enum DemoSubgraphs + { + Accounts = 1, + Reviews2 = 2, + Products = 4, + Shipping = 8, + Appointment = 16 + } + + private static readonly Uri _graphQLEndpoint = new("http://localhost:5000/graphql"); + + private const string AccountsSchema = + """ + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int!, second: Int): String! + } + + interface Node { + id: ID! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + """; + + private const string Reviews2Schema = + """ + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + interface Node { + id: ID! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + """; + + private const string ProductsSchema = + """ + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } + + input RepeatDataDataInput { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + type RepeatDataData { + num: Int! + } + """; + + private const string ShippingSchema = + """ + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + size: Int! @shareable + weight: Int! @shareable + deliveryEstimate( + size: Int + weight: Int + zip: String!): DeliveryEstimate! + } + + type DeliveryEstimate { + min: Int! + max: Int! + } + """; + + private const string AppointmentSchema = + """ + type Query { + appointments(after: String): AppointmentConnection + } + + type AppointmentConnection { + nodes: [Appointment!] + } + + type Appointment { + id: ID! + } + """; +} diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/DemoIntegrationTests.cs b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/DemoIntegrationTests.cs index ad8ca56b6b4..fab4801e7f8 100644 --- a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/DemoIntegrationTests.cs +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/DemoIntegrationTests.cs @@ -4,7 +4,7 @@ namespace HotChocolate.Fusion; -public class DemoIntegrationTests : FusionTestBase +public partial class DemoIntegrationTests : FusionTestBase { [Fact] public async Task Same_Selection_On_Two_Object_Types_That_Require_Data_From_Another_Subgraph() @@ -165,1960 +165,6 @@ type Product implements Node { await MatchSnapshotAsync(gateway, request, result); } - // [Fact] - // public async Task Authors_And_Reviews_AutoCompose() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // }); - - // // assert - // fusionGraph.MatchSnapshot(extension: ".graphql"); - // } - - // [Fact] - // public async Task Authors_And_Reviews_And_Products_AutoCompose() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // demoProject.Products.ToConfiguration(ProductsExtensionSdl), - // }); - - // // assert - // fusionGraph.MatchSnapshot(extension: ".graphql"); - // } - - // [Fact] - // public async Task Authors_And_Reviews_Query_GetUserReviews() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // }); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query GetUser { - // users { - // name - // reviews { - // body - // author { - // name - // } - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Authors_And_Reviews_Query_GetUserReviews_Report_Cost() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(enableCost: true); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory) - // .ComposeAsync( - // [ - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionWithCostSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionWithCostSdl) - // ]); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query GetUser { - // users { - // name - // reviews { - // body - // author { - // name - // } - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .ReportCost() - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Authors_And_Reviews_Query_GetUserReviews_Skip_Author() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // }); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query GetUser($skip: Boolean!) { - // users { - // name - // reviews { - // body - // author @skip(if: $skip) { - // name - // birthdate - // } - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetVariableValues(new Dictionary { { "skip", true } }) - // .SetDocument(request) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Authors_And_Reviews_Query_GetUserReviews_Skip_Author_ErrorField() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // }); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query GetUser($skip: Boolean!) { - // users { - // name - // reviews { - // body - // author { - // name - // birthdate - // errorField @skip(if: $skip) - // } - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetVariableValues(new Dictionary { { "skip", true } }) - // .SetDocument(request) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Authors_And_Reviews_Query_GetUserById() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // }); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query GetUser { - // userById(id: "VXNlcjox") { - // id - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Authors_And_Reviews_Query_GetUserById_With_Invalid_Id_Value() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // }); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query GetUser { - // userById(id: 1) { - // id - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.NotNull(result.ExpectOperationResult().Errors); - // Assert.NotEmpty(result.ExpectOperationResult().Errors!); - // } - - // [Fact] - // public async Task Authors_And_Reviews_Subscription_OnNewReview() - // { - // // arrange - // using var cts = TestEnvironment.CreateCancellationTokenSource(); - // using var demoProject = await DemoProject.CreateAsync(cts.Token); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // [ - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl) - // ], - // null, - // cts.Token); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(cancellationToken: cts.Token); - - // var request = Parse( - // """ - // subscription OnNewReview { - // onNewReview { - // body - // author { - // name - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .Build(), - // cts.Token); - - // // assert - // var snapshot = new Snapshot(); - // await CollectStreamSnapshotData(snapshot, request, result, cts.Token); - // await snapshot.MatchMarkdownAsync(cts.Token); - // } - - // [Fact] - // public async Task Authors_And_Reviews_Subscription_OnNewReviewError() - // { - // // arrange - // using var cts = TestEnvironment.CreateCancellationTokenSource(); - // using var demoProject = await DemoProject.CreateAsync(cts.Token); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // [ - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl) - // ], - // null, - // cts.Token); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(cancellationToken: cts.Token); - - // var request = Parse( - // """ - // subscription OnNewReview { - // onNewReviewError { - // body - // author { - // name - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .Build(), - // cts.Token); - - // // assert - // var snapshot = new Snapshot(); - // await CollectStreamSnapshotData(snapshot, request, result, cts.Token); - // await snapshot.MatchMarkdownAsync(cts.Token); - // } - - // [Fact] - // public async Task Authors_And_Reviews_Subscription_OnError() - // { - // // arrange - // using var cts = TestEnvironment.CreateCancellationTokenSource(); - // using var demoProject = await DemoProject.CreateAsync(cts.Token); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews.ToConfiguration(ReviewsExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // }, - // default, - // cts.Token); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(cancellationToken: cts.Token); - - // var request = Parse( - // """ - // subscription OnError { - // onError { - // body - // author { - // name - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .Build(), - // cts.Token); - - // // assert - // var snapshot = new Snapshot(); - // await CollectStreamSnapshotData(snapshot, request, result, cts.Token); - // await snapshot.MatchMarkdownAsync(cts.Token); - // } - - // [Fact] - // public async Task Authors_And_Reviews_Subscription_OnError_SSE() - // { - // // arrange - // using var cts = TestEnvironment.CreateCancellationTokenSource(); - // using var demoProject = await DemoProject.CreateAsync(cts.Token); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews.ToConfiguration(ReviewsExtensionSdl, onlyHttp: true), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl, onlyHttp: true), - // }, - // default, - // cts.Token); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(cancellationToken: cts.Token); - - // var request = Parse( - // """ - // subscription OnError { - // onError { - // body - // author { - // name - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .Build(), - // cts.Token); - - // // assert - // var snapshot = new Snapshot(); - // await CollectStreamSnapshotData(snapshot, request, result, cts.Token); - // await snapshot.MatchMarkdownAsync(cts.Token); - // } - - // [Fact] - // public async Task Authors_And_Reviews_Subscription_OnNewReview_Two_Graphs() - // { - // // arrange - // using var cts = TestEnvironment.CreateCancellationTokenSource(); - // using var demoProject = await DemoProject.CreateAsync(cts.Token); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // }, - // default, - // cts.Token); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(cancellationToken: cts.Token); - - // var request = Parse( - // """ - // subscription OnNewReview { - // onNewReview { - // body - // author { - // name - // birthdate - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .Build(), - // cts.Token); - - // // assert - // var snapshot = new Snapshot(); - // await CollectStreamSnapshotData(snapshot, request, result, cts.Token); - // await snapshot.MatchMarkdownAsync(cts.Token); - // } - - // [Fact] - // public async Task Authors_And_Reviews_Query_ReviewsUser() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // }); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query GetUser { - // a: reviews { - // body - // author { - // name - // } - // } - // b: reviews { - // body - // author { - // name - // } - // } - // users { - // name - // reviews { - // body - // author { - // name - // } - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact(Skip = "Do we want to reformat ids?")] - // public async Task Authors_And_Reviews_Query_Reformat_AuthorIds() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = - // await new FusionGraphComposer(logFactory: _logFactory) - // .ComposeAsync( - // new[] - // { - // demoProject.Reviews.ToConfiguration(ReviewsExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // }, - // new FusionFeatureCollection(FusionFeatures.NodeField)); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query ReformatIds { - // reviews { - // author { - // id - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact(Skip = "this does not work yet")] - // public async Task Authors_And_Reviews_Query_Reformat_AuthorIds_ReEncodeAllIds() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = - // await new FusionGraphComposer(logFactory: _logFactory) - // .ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // }, - // new FusionFeatureCollection(FusionFeatures.ReEncodeIds)); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query ReformatIds { - // reviews { - // author { - // id - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Authors_And_Reviews_Batch_Requests() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = - // await new FusionGraphComposer(logFactory: _logFactory) - // .ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // }, - // new FusionFeatureCollection(FusionFeatures.NodeField)); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query GetUser { - // reviews { - // body - // author { - // birthdate - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Authors_And_Reviews_And_Products_Query_TopProducts() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // demoProject.Products.ToConfiguration(ProductsExtensionSdl), - // }); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query TopProducts { - // topProducts(first: 2) { - // name - // reviews { - // body - // author { - // name - // } - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Authors_And_Reviews_And_Products_Query_TypeName() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // demoProject.Products.ToConfiguration(ProductsExtensionSdl), - // }); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query TopProducts { - // __typename - // topProducts(first: 2) { - // __typename - // reviews { - // __typename - // author { - // __typename - // } - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Authors_And_Reviews_And_Products_With_Variables() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // demoProject.Products.ToConfiguration(ProductsExtensionSdl), - // }); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query TopProducts($first: Int!) { - // topProducts(first: $first) { - // id - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .SetVariableValues(new Dictionary { { "first", 2 }, }) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Authors_And_Reviews_And_Products_Introspection() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = - // await new FusionGraphComposer(logFactory: _logFactory) - // .ComposeAsync( - // [ - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // demoProject.Products.ToConfiguration(ProductsExtensionSdl) - // ]); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query Introspect { - // __schema { - // types { - // name - // kind - // fields { - // name - // type { - // name - // kind - // } - // } - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Fetch_User_With_Node_Field() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // demoProject.Products.ToConfiguration(ProductsExtensionSdl), - // }, - // new FusionFeatureCollection(FusionFeatures.NodeField)); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query FetchNode($id: ID!) { - // node(id: $id) { - // ... on User { - // id - // } - // } - // } - // """); - - // var id = Convert.ToBase64String("User:1"u8); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .SetVariableValues(new Dictionary { { "id", id }, }) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Fetch_User_With_Invalid_Node_Field() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // demoProject.Products.ToConfiguration(ProductsExtensionSdl), - // }, - // new FusionFeatureCollection(FusionFeatures.NodeField)); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query FetchNode($id: ID!) { - // node(id: $id) { - // ... on User { - // id - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .SetVariableValues(new Dictionary { { "id", 1 }, }) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - // } - - // [Fact] - // public async Task Fetch_User_With_Node_Field_Pass_In_Review_Id() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // demoProject.Products.ToConfiguration(ProductsExtensionSdl), - // }, - // new FusionFeatureCollection(FusionFeatures.NodeField)); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query FetchNode($id: ID!) { - // node(id: $id) { - // ... on User { - // id - // } - // } - // } - // """); - - // var id = Convert.ToBase64String("Review:1"u8); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .SetVariableValues(new Dictionary { { "id", id }, }) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Fetch_User_With_Node_Field_Pass_In_Unknown_Id() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // demoProject.Products.ToConfiguration(ProductsExtensionSdl), - // }, - // new FusionFeatureCollection(FusionFeatures.NodeField)); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query FetchNode($id: ID!) { - // node(id: $id) { - // ... on User { - // id - // } - // } - // } - // """); - - // var id = Convert.ToBase64String("Unknown:1"u8); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .SetVariableValues(new Dictionary { { "id", id }, }) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - // } - - // [Fact] - // public async Task Fetch_User_With_Node_Field_From_Two_Subgraphs() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // demoProject.Products.ToConfiguration(ProductsExtensionSdl), - // }, - // new FusionFeatureCollection(FusionFeatures.NodeField)); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query FetchNode($id: ID!) { - // node(id: $id) { - // ... on User { - // birthdate - // reviews { - // body - // } - // } - // } - // } - // """); - - // var id = Convert.ToBase64String("User:1"u8); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .SetVariableValues(new Dictionary { { "id", id }, }) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Hot_Reload() - // { - // // arrange - // var executorUpdatedResetEvent = new ManualResetEventSlim(false); - // using var demoProject = await DemoProject.CreateAsync(); - - // var fusionGraph = - // await new FusionGraphComposer(logFactory: _logFactory) - // .ComposeAsync( - // new[] { demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), }, - // new FusionFeatureCollection(FusionFeatures.NodeField)); - - // var config = new HotReloadConfiguration( - // new GatewayConfiguration( - // SchemaFormatter.FormatAsDocument(fusionGraph))); - - // var services = new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer(null) - // .RegisterGatewayConfiguration(_ => config) - // .Services - // .BuildServiceProvider(); - - // var request = Parse( - // """ - // { - // __type(name: "Query") { - // fields { - // name - // } - // } - // } - // """); - - // var executorResolver = services.GetRequiredService(); - // var executorProxy = new RequestExecutorProxy(executorResolver, Schema.DefaultName); - // var isFirstUpdate = true; - // executorProxy.ExecutorUpdated += (sender, args) => - // { - // if (isFirstUpdate) - // { - // isFirstUpdate = false; - // } - // else - // { - // executorUpdatedResetEvent.Set(); - // } - // }; - - // var result = await executorProxy.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .Build()); - - // var snapshot = new Snapshot(); - // snapshot.Add(result, "1. Version"); - - // // act - // fusionGraph = - // await new FusionGraphComposer(logFactory: _logFactory) - // .ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(AccountsExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // }, - // new FusionFeatureCollection(FusionFeatures.NodeField)); - // config.SetConfiguration( - // new GatewayConfiguration( - // SchemaFormatter.FormatAsDocument(fusionGraph))); - // using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)); - // executorUpdatedResetEvent.Wait(cts.Token); - - // result = await executorProxy.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .Build()); - - // snapshot.Add(result, "2. Version"); - - // // assert - // await snapshot.MatchMarkdownAsync(); - // } - - // [Fact] - // public async Task TypeName_Field_On_QueryRoot() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // demoProject.Products.ToConfiguration(ProductsExtensionSdl), - // }); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query Introspect { - // __typename - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Forward_Nested_Variables() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // demoProject.Products.ToConfiguration(ProductsExtensionSdl), - // }, - // new FusionFeatureCollection(FusionFeatures.NodeField)); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query ProductReviews( - // $id: ID! - // $first: Int! - // ) { - // productById(id: $id) { - // id - // repeat(num: $first) - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .SetVariableValues(new Dictionary { { "id", "UHJvZHVjdDox" }, { "first", 1 }, }) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Forward_Nested_Variables_No_OpName() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // demoProject.Products.ToConfiguration(ProductsExtensionSdl), - // }, - // new FusionFeatureCollection(FusionFeatures.NodeField)); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query ( - // $id: ID! - // $first: Int! - // ) { - // productById(id: $id) { - // id - // repeat(num: $first) - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .SetVariableValues( - // new Dictionary { { "id", "UHJvZHVjdDox" }, { "first", 1 }, }) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Forward_Nested_Variables_No_OpName_Two_RootSelections() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // demoProject.Products.ToConfiguration(ProductsExtensionSdl), - // }, - // new FusionFeatureCollection(FusionFeatures.NodeField)); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query ( - // $id: ID! - // $first: Int! - // ) { - // a: productById(id: $id) { - // id - // repeat(num: $first) - // } - // b: productById(id: $id) { - // id - // repeat(num: $first) - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .SetVariableValues(new Dictionary { { "id", "UHJvZHVjdDox" }, { "first", 1 }, }) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Forward_Nested_Node_Variables() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // demoProject.Products.ToConfiguration(ProductsExtensionSdl), - // }, - // new FusionFeatureCollection(FusionFeatures.NodeField)); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query ProductReviews( - // $id: ID! - // $first: Int! - // ) { - // node(id: $id) { - // ... on Product { - // id - // repeat(num: $first) - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .SetVariableValues(new Dictionary { { "id", "UHJvZHVjdDox" }, { "first", 1 }, }) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Forward_Nested_Object_Variables() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // demoProject.Products.ToConfiguration(ProductsExtensionSdl), - // }, - // new FusionFeatureCollection(FusionFeatures.NodeField)); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query ProductReviews( - // $id: ID! - // $first: Int! - // ) { - // productById(id: $id) { - // id - // repeatData(data: { data: { num: $first } }) { - // data { - // num - // } - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .SetVariableValues(new Dictionary { { "id", "UHJvZHVjdDox" }, { "first", 1 }, }) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Require_Data_In_Context() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // demoProject.Products.ToConfiguration(ProductsExtensionSdl), - // demoProject.Shipping.ToConfiguration(ShippingExtensionSdl), - // }, - // new FusionFeatureCollection(FusionFeatures.NodeField)); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query Requires { - // reviews { - // body - // author { - // name - // birthdate - // } - // product { - // name - // deliveryEstimate(zip: "12345") { - // min - // max - // } - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .SetVariableValues(new Dictionary { { "id", "UHJvZHVjdDox" }, { "first", 1 }, }) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Require_Data_In_Context_2() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // demoProject.Products.ToConfiguration(ProductsExtensionSdl), - // demoProject.Shipping.ToConfiguration(ShippingExtensionSdl), - // }, - // new FusionFeatureCollection(FusionFeatures.NodeField)); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query Requires { - // reviews { - // body - // author { - // name - // birthdate - // } - // product { - // deliveryEstimate(zip: "12345") { - // min - // max - // } - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .SetVariableValues(new Dictionary { { "id", "UHJvZHVjdDox" }, { "first", 1 }, }) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task Require_Data_In_Context_3() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // demoProject.Products.ToConfiguration(ProductsExtensionSdl), - // demoProject.Shipping.ToConfiguration(ShippingExtensionSdl), - // }, - // new FusionFeatureCollection(FusionFeatures.NodeField)); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query Large { - // users { - // id - // name - // birthdate - // reviews { - // body - // author { - // name - // birthdate - // } - // product { - // id - // name - // deliveryEstimate(zip: "abc") { - // max - // } - // } - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .SetVariableValues(new Dictionary { { "id", "UHJvZHVjdDox" }, { "first", 1 }, }) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task GetFirstPage_With_After_Null() - // { - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] { demoProject.Appointment.ToConfiguration(), }, - // new FusionFeatureCollection(FusionFeatures.NodeField)); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query AfterNull($after: String) { - // appointments(after: $after) { - // nodes { - // id - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .SetVariableValues(new Dictionary { { "after", null }, }) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - - // [Fact] - // public async Task QueryType_Parallel_Multiple_SubGraphs_WithArguments() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] - // { - // demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl), - // demoProject.Accounts.ToConfiguration(AccountsExtensionSdl), - // demoProject.Products.ToConfiguration(ProductsExtensionSdl), - // demoProject.Shipping.ToConfiguration(ShippingExtensionSdl), - // }, - // new FusionFeatureCollection(FusionFeatures.NodeField)); - - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - - // var request = Parse( - // """ - // query TopProducts { - // topProducts(first: 5) { - // weight - // deliveryEstimate(zip: "12345") { - // min - // max - // } - // reviews { - // body - // } - // } - // } - // """); - - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .SetVariableValues(new Dictionary { { "id", "UHJvZHVjdDox" }, { "first", 1 }, }) - // .Build()); - - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - - // Assert.Null(result.ExpectOperationResult().Errors); - // } - [Fact] public async Task BatchExecutionState_With_Multiple_Variable_Values() { @@ -2931,46 +977,6 @@ type SubgraphC { await MatchSnapshotAsync(gateway, request, result); } - // [Fact] - // public async Task Two_Arguments_Differing_Nullability_Does_Not_Duplicate_Forwarded_Variables() - // { - // // arrange - // using var demoProject = await DemoProject.CreateAsync(); - // - // // act - // var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync( - // new[] { demoProject.Accounts.ToConfiguration(AccountsExtensionSdl) }); - // - // var executor = await new ServiceCollection() - // .AddSingleton(demoProject.HttpClientFactory) - // .AddSingleton(demoProject.WebSocketConnectionFactory) - // .AddFusionGatewayServer() - // .ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph)) - // .BuildRequestExecutorAsync(); - // - // var request = Parse( - // """ - // query Test($number: Int!) { - // testWithTwoArgumentsDifferingNullability(first: $number, second: $number) - // } - // """); - // - // // act - // await using var result = await executor.ExecuteAsync( - // OperationRequestBuilder - // .New() - // .SetDocument(request) - // .SetVariableValues(new Dictionary { { "number", 1 } }) - // .Build()); - // - // // assert - // var snapshot = new Snapshot(); - // CollectSnapshotData(snapshot, request, result); - // await snapshot.MatchMarkdownAsync(); - // - // Assert.Null(result.ExpectOperationResult().Errors); - // } - [Fact] public async Task Unresolvable_Subgraph_Is_Not_Chosen_If_Data_Is_Available_In_Resolvable_Subgraph() { diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_AutoCompose.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_AutoCompose.yaml new file mode 100644 index 00000000000..8f6e8aab64c --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_AutoCompose.yaml @@ -0,0 +1,276 @@ +title: Authors_And_Reviews_And_Products_AutoCompose +request: + document: | + { + users { + id + } + reviews { + body + } + topProducts(first: 2) { + id + } + } +response: + body: | + { + "data": { + "users": [ + { + "id": "VXNlcjox" + }, + { + "id": "VXNlcjoy" + }, + { + "id": "VXNlcjoz" + } + ], + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=" + }, + { + "body": "Review: UmV2aWV3OjI=" + }, + { + "body": "Review: UmV2aWV3OjM=" + } + ], + "topProducts": [ + { + "id": "UHJvZHVjdDox" + }, + { + "id": "UHJvZHVjdDoy" + }, + { + "id": "UHJvZHVjdDoz" + } + ] + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + interactions: + - request: + document: | + query Op_5e956cef_2 { + users { + id + } + } + response: + results: + - | + { + "data": { + "users": [ + { + "id": "VXNlcjox" + }, + { + "id": "VXNlcjoy" + }, + { + "id": "VXNlcjoz" + } + ] + } + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + interactions: + - request: + document: | + query Op_5e956cef_1 { + reviews { + body + } + } + response: + results: + - | + { + "data": { + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=" + }, + { + "body": "Review: UmV2aWV3OjI=" + }, + { + "body": "Review: UmV2aWV3OjM=" + } + ] + } + } + - name: C + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + type RepeatDataData { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + input RepeatDataDataInput { + num: Int! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } + interactions: + - request: + document: | + query Op_5e956cef_3 { + topProducts(first: 2) { + id + } + } + response: + results: + - | + { + "data": { + "topProducts": [ + { + "id": "UHJvZHVjdDox" + }, + { + "id": "UHJvZHVjdDoy" + }, + { + "id": "UHJvZHVjdDoz" + } + ] + } + } +operationPlan: + operation: + - document: | + { + users { + id + } + reviews { + body + } + topProducts(first: 2) { + id + } + } + hash: 5e956cefca158ef5509c5abb6ddbd512 + searchSpace: 3 + expandedNodes: 3 + nodes: + - id: 1 + type: Operation + schema: B + operation: | + query Op_5e956cef_1 { + reviews { + body + } + } + - id: 2 + type: Operation + schema: A + operation: | + query Op_5e956cef_2 { + users { + id + } + } + - id: 3 + type: Operation + schema: C + operation: | + query Op_5e956cef_3 { + topProducts(first: 2) { + id + } + } diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Introspection.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Introspection.yaml new file mode 100644 index 00000000000..3caec854aca --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Introspection.yaml @@ -0,0 +1,730 @@ +title: Authors_And_Reviews_And_Products_Introspection +request: + document: | + query Introspect { + __schema { + types { + name + kind + fields { + name + type { + name + kind + } + } + } + } + } +response: + body: | + { + "data": { + "__schema": { + "types": [ + { + "name": "__Schema", + "kind": "OBJECT", + "fields": [ + { + "name": "description", + "type": { + "name": "String", + "kind": "SCALAR" + } + }, + { + "name": "types", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "queryType", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "mutationType", + "type": { + "name": "__Type", + "kind": "OBJECT" + } + }, + { + "name": "subscriptionType", + "type": { + "name": "__Type", + "kind": "OBJECT" + } + }, + { + "name": "directives", + "type": { + "name": null, + "kind": "NON_NULL" + } + } + ] + }, + { + "name": "__Type", + "kind": "OBJECT", + "fields": [ + { + "name": "kind", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "name", + "type": { + "name": "String", + "kind": "SCALAR" + } + }, + { + "name": "description", + "type": { + "name": "String", + "kind": "SCALAR" + } + }, + { + "name": "specifiedByURL", + "type": { + "name": "String", + "kind": "SCALAR" + } + }, + { + "name": "fields", + "type": { + "name": null, + "kind": "LIST" + } + }, + { + "name": "interfaces", + "type": { + "name": null, + "kind": "LIST" + } + }, + { + "name": "possibleTypes", + "type": { + "name": null, + "kind": "LIST" + } + }, + { + "name": "enumValues", + "type": { + "name": null, + "kind": "LIST" + } + }, + { + "name": "inputFields", + "type": { + "name": null, + "kind": "LIST" + } + }, + { + "name": "ofType", + "type": { + "name": "__Type", + "kind": "OBJECT" + } + } + ] + }, + { + "name": "__TypeKind", + "kind": "ENUM", + "fields": null + }, + { + "name": "__Field", + "kind": "OBJECT", + "fields": [ + { + "name": "name", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "description", + "type": { + "name": "String", + "kind": "SCALAR" + } + }, + { + "name": "args", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "type", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "isDeprecated", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "deprecationReason", + "type": { + "name": "String", + "kind": "SCALAR" + } + } + ] + }, + { + "name": "__InputValue", + "kind": "OBJECT", + "fields": [ + { + "name": "name", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "description", + "type": { + "name": "String", + "kind": "SCALAR" + } + }, + { + "name": "type", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "defaultValue", + "type": { + "name": "String", + "kind": "SCALAR" + } + }, + { + "name": "isDeprecated", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "deprecationReason", + "type": { + "name": "String", + "kind": "SCALAR" + } + } + ] + }, + { + "name": "__EnumValue", + "kind": "OBJECT", + "fields": [ + { + "name": "name", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "description", + "type": { + "name": "String", + "kind": "SCALAR" + } + }, + { + "name": "isDeprecated", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "deprecationReason", + "type": { + "name": "String", + "kind": "SCALAR" + } + } + ] + }, + { + "name": "__Directive", + "kind": "OBJECT", + "fields": [ + { + "name": "name", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "description", + "type": { + "name": "String", + "kind": "SCALAR" + } + }, + { + "name": "isRepeatable", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "locations", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "args", + "type": { + "name": null, + "kind": "NON_NULL" + } + } + ] + }, + { + "name": "__DirectiveLocation", + "kind": "ENUM", + "fields": null + }, + { + "name": "Query", + "kind": "OBJECT", + "fields": [ + { + "name": "node", + "type": { + "name": "Node", + "kind": "INTERFACE" + } + }, + { + "name": "productById", + "type": { + "name": "Product", + "kind": "OBJECT" + } + }, + { + "name": "reviews", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "testWithTwoArgumentsDifferingNullability", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "topProducts", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "userById", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "users", + "type": { + "name": null, + "kind": "NON_NULL" + } + } + ] + }, + { + "name": "Product", + "kind": "OBJECT", + "fields": [ + { + "name": "id", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "name", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "repeat", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "repeatData", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "reviewCount", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "reviews", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "size", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "weight", + "type": { + "name": null, + "kind": "NON_NULL" + } + } + ] + }, + { + "name": "RepeatDataData", + "kind": "OBJECT", + "fields": [ + { + "name": "num", + "type": { + "name": null, + "kind": "NON_NULL" + } + } + ] + }, + { + "name": "RepeatDataPayload", + "kind": "OBJECT", + "fields": [ + { + "name": "data", + "type": { + "name": null, + "kind": "NON_NULL" + } + } + ] + }, + { + "name": "Review", + "kind": "OBJECT", + "fields": [ + { + "name": "author", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "body", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "id", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "product", + "type": { + "name": null, + "kind": "NON_NULL" + } + } + ] + }, + { + "name": "User", + "kind": "OBJECT", + "fields": [ + { + "name": "birthdate", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "errorField", + "type": { + "name": "String", + "kind": "SCALAR" + } + }, + { + "name": "id", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "name", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "reviews", + "type": { + "name": null, + "kind": "NON_NULL" + } + }, + { + "name": "username", + "type": { + "name": null, + "kind": "NON_NULL" + } + } + ] + }, + { + "name": "Node", + "kind": "INTERFACE", + "fields": [ + { + "name": "id", + "type": { + "name": null, + "kind": "NON_NULL" + } + } + ] + }, + { + "name": "RepeatDataDataInput", + "kind": "INPUT_OBJECT", + "fields": null + }, + { + "name": "RepeatDataInput", + "kind": "INPUT_OBJECT", + "fields": null + }, + { + "name": "String", + "kind": "SCALAR", + "fields": null + }, + { + "name": "Boolean", + "kind": "SCALAR", + "fields": null + }, + { + "name": "ID", + "kind": "SCALAR", + "fields": null + }, + { + "name": "Int", + "kind": "SCALAR", + "fields": null + } + ] + } + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + - name: C + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + type RepeatDataData { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + input RepeatDataDataInput { + num: Int! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } +operationPlan: + operation: + - document: | + query Introspect { + __schema { + types { + name + kind + fields { + name + type { + name + kind + } + } + } + } + } + name: Introspect + hash: 151c2e2faa405b4b9c65f001decc564e + searchSpace: 1 + expandedNodes: 1 + nodes: + - id: 1 + type: Introspection + selections: + - id: 2 + responseName: __schema + fieldName: __schema diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TopProducts.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TopProducts.yaml new file mode 100644 index 00000000000..da560cb1fc8 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TopProducts.yaml @@ -0,0 +1,545 @@ +title: Authors_And_Reviews_And_Products_Query_TopProducts +request: + document: | + query TopProducts { + topProducts(first: 2) { + name + reviews { + body + author { + name + } + } + } + } +response: + body: | + { + "data": { + "topProducts": [ + { + "name": "Product: UHJvZHVjdDox", + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=", + "author": { + "name": "User: VXNlcjoxNg==" + } + }, + { + "body": "Review: UmV2aWV3OjI=", + "author": { + "name": "User: VXNlcjoxNw==" + } + }, + { + "body": "Review: UmV2aWV3OjM=", + "author": { + "name": "User: VXNlcjoxOA==" + } + } + ] + }, + { + "name": "Product: UHJvZHVjdDoy", + "reviews": [ + { + "body": "Review: UmV2aWV3OjQ=", + "author": { + "name": "User: VXNlcjoxMw==" + } + }, + { + "body": "Review: UmV2aWV3OjU=", + "author": { + "name": "User: VXNlcjoxNA==" + } + }, + { + "body": "Review: UmV2aWV3OjY=", + "author": { + "name": "User: VXNlcjoxNQ==" + } + } + ] + }, + { + "name": "Product: UHJvZHVjdDoz", + "reviews": [ + { + "body": "Review: UmV2aWV3Ojc=", + "author": { + "name": "User: VXNlcjoxMA==" + } + }, + { + "body": "Review: UmV2aWV3Ojg=", + "author": { + "name": "User: VXNlcjoxMQ==" + } + }, + { + "body": "Review: UmV2aWV3Ojk=", + "author": { + "name": "User: VXNlcjoxMg==" + } + } + ] + } + ] + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + interactions: + - request: + document: | + query TopProducts_c6ef3d11_3( + $__fusion_2_id: ID! + ) { + node(id: $__fusion_2_id) { + __typename + ... on User { + name + } + } + } + variables: | + [ + { + "__fusion_2_id": "VXNlcjoxNg==" + }, + { + "__fusion_2_id": "VXNlcjoxNw==" + }, + { + "__fusion_2_id": "VXNlcjoxOA==" + }, + { + "__fusion_2_id": "VXNlcjoxMw==" + }, + { + "__fusion_2_id": "VXNlcjoxNA==" + }, + { + "__fusion_2_id": "VXNlcjoxNQ==" + }, + { + "__fusion_2_id": "VXNlcjoxMA==" + }, + { + "__fusion_2_id": "VXNlcjoxMQ==" + }, + { + "__fusion_2_id": "VXNlcjoxMg==" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxNg==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxNw==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxOA==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMw==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxNA==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxNQ==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMA==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMQ==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMg==" + } + } + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + interactions: + - request: + document: | + query TopProducts_c6ef3d11_2( + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on Product { + reviews { + body + author { + id + } + } + } + } + } + variables: | + [ + { + "__fusion_1_id": "UHJvZHVjdDox" + }, + { + "__fusion_1_id": "UHJvZHVjdDoy" + }, + { + "__fusion_1_id": "UHJvZHVjdDoz" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "Product", + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=", + "author": { + "id": "VXNlcjoxNg==" + } + }, + { + "body": "Review: UmV2aWV3OjI=", + "author": { + "id": "VXNlcjoxNw==" + } + }, + { + "body": "Review: UmV2aWV3OjM=", + "author": { + "id": "VXNlcjoxOA==" + } + } + ] + } + } + } + - | + { + "data": { + "node": { + "__typename": "Product", + "reviews": [ + { + "body": "Review: UmV2aWV3OjQ=", + "author": { + "id": "VXNlcjoxMw==" + } + }, + { + "body": "Review: UmV2aWV3OjU=", + "author": { + "id": "VXNlcjoxNA==" + } + }, + { + "body": "Review: UmV2aWV3OjY=", + "author": { + "id": "VXNlcjoxNQ==" + } + } + ] + } + } + } + - | + { + "data": { + "node": { + "__typename": "Product", + "reviews": [ + { + "body": "Review: UmV2aWV3Ojc=", + "author": { + "id": "VXNlcjoxMA==" + } + }, + { + "body": "Review: UmV2aWV3Ojg=", + "author": { + "id": "VXNlcjoxMQ==" + } + }, + { + "body": "Review: UmV2aWV3Ojk=", + "author": { + "id": "VXNlcjoxMg==" + } + } + ] + } + } + } + - name: C + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + type RepeatDataData { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + input RepeatDataDataInput { + num: Int! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } + interactions: + - request: + document: | + query TopProducts_c6ef3d11_1 { + topProducts(first: 2) { + name + id + } + } + response: + results: + - | + { + "data": { + "topProducts": [ + { + "name": "Product: UHJvZHVjdDox", + "id": "UHJvZHVjdDox" + }, + { + "name": "Product: UHJvZHVjdDoy", + "id": "UHJvZHVjdDoy" + }, + { + "name": "Product: UHJvZHVjdDoz", + "id": "UHJvZHVjdDoz" + } + ] + } + } +operationPlan: + operation: + - document: | + query TopProducts { + topProducts(first: 2) { + name + reviews { + body + author { + name + id @fusion__requirement + } + } + id @fusion__requirement + } + } + name: TopProducts + hash: c6ef3d11d0c88575a305e18635857068 + searchSpace: 1 + expandedNodes: 3 + nodes: + - id: 1 + type: Operation + schema: C + operation: | + query TopProducts_c6ef3d11_1 { + topProducts(first: 2) { + name + id + } + } + - id: 2 + type: Operation + schema: B + operation: | + query TopProducts_c6ef3d11_2( + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on Product { + reviews { + body + author { + id + } + } + } + } + } + source: $.node + target: $.topProducts + requirements: + - name: __fusion_1_id + selectionMap: >- + id + dependencies: + - id: 1 + - id: 3 + type: Operation + schema: A + operation: | + query TopProducts_c6ef3d11_3( + $__fusion_2_id: ID! + ) { + node(id: $__fusion_2_id) { + __typename + ... on User { + name + } + } + } + source: $.node + target: $.topProducts.reviews.author + requirements: + - name: __fusion_2_id + selectionMap: >- + id + dependencies: + - id: 2 diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TypeName.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TypeName.yaml new file mode 100644 index 00000000000..0cc5c1169a1 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TypeName.yaml @@ -0,0 +1,407 @@ +title: Authors_And_Reviews_And_Products_Query_TypeName +request: + document: | + query TopProducts { + __typename + topProducts(first: 2) { + __typename + reviews { + __typename + author { + __typename + } + } + } + } +response: + body: | + { + "data": { + "__typename": "Query", + "topProducts": [ + { + "__typename": "Product", + "reviews": [ + { + "__typename": "Review", + "author": { + "__typename": "User" + } + }, + { + "__typename": "Review", + "author": { + "__typename": "User" + } + }, + { + "__typename": "Review", + "author": { + "__typename": "User" + } + } + ] + }, + { + "__typename": "Product", + "reviews": [ + { + "__typename": "Review", + "author": { + "__typename": "User" + } + }, + { + "__typename": "Review", + "author": { + "__typename": "User" + } + }, + { + "__typename": "Review", + "author": { + "__typename": "User" + } + } + ] + }, + { + "__typename": "Product", + "reviews": [ + { + "__typename": "Review", + "author": { + "__typename": "User" + } + }, + { + "__typename": "Review", + "author": { + "__typename": "User" + } + }, + { + "__typename": "Review", + "author": { + "__typename": "User" + } + } + ] + } + ] + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + interactions: + - request: + document: | + query TopProducts_b7ed3f85_2( + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on Product { + reviews { + __typename + author { + __typename + } + } + } + } + } + variables: | + [ + { + "__fusion_1_id": "UHJvZHVjdDox" + }, + { + "__fusion_1_id": "UHJvZHVjdDoy" + }, + { + "__fusion_1_id": "UHJvZHVjdDoz" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "Product", + "reviews": [ + { + "__typename": "Review", + "author": { + "__typename": "User" + } + }, + { + "__typename": "Review", + "author": { + "__typename": "User" + } + }, + { + "__typename": "Review", + "author": { + "__typename": "User" + } + } + ] + } + } + } + - | + { + "data": { + "node": { + "__typename": "Product", + "reviews": [ + { + "__typename": "Review", + "author": { + "__typename": "User" + } + }, + { + "__typename": "Review", + "author": { + "__typename": "User" + } + }, + { + "__typename": "Review", + "author": { + "__typename": "User" + } + } + ] + } + } + } + - | + { + "data": { + "node": { + "__typename": "Product", + "reviews": [ + { + "__typename": "Review", + "author": { + "__typename": "User" + } + }, + { + "__typename": "Review", + "author": { + "__typename": "User" + } + }, + { + "__typename": "Review", + "author": { + "__typename": "User" + } + } + ] + } + } + } + - name: C + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + type RepeatDataData { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + input RepeatDataDataInput { + num: Int! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } + interactions: + - request: + document: | + query TopProducts_b7ed3f85_1 { + __typename + topProducts(first: 2) { + __typename + id + } + } + response: + results: + - | + { + "data": { + "__typename": "Query", + "topProducts": [ + { + "__typename": "Product", + "id": "UHJvZHVjdDox" + }, + { + "__typename": "Product", + "id": "UHJvZHVjdDoy" + }, + { + "__typename": "Product", + "id": "UHJvZHVjdDoz" + } + ] + } + } +operationPlan: + operation: + - document: | + query TopProducts { + __typename + topProducts(first: 2) { + __typename + reviews { + __typename + author { + __typename + } + } + id @fusion__requirement + } + } + name: TopProducts + hash: b7ed3f85a97fcef1fd08f2541df6814d + searchSpace: 1 + expandedNodes: 2 + nodes: + - id: 1 + type: Operation + schema: C + operation: | + query TopProducts_b7ed3f85_1 { + __typename + topProducts(first: 2) { + __typename + id + } + } + - id: 2 + type: Operation + schema: B + operation: | + query TopProducts_b7ed3f85_2( + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on Product { + reviews { + __typename + author { + __typename + } + } + } + } + } + source: $.node + target: $.topProducts + requirements: + - name: __fusion_1_id + selectionMap: >- + id + dependencies: + - id: 1 + - id: 3 + type: Introspection + selections: + - id: 2 + responseName: __typename + fieldName: __typename diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_With_Variables.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_With_Variables.yaml new file mode 100644 index 00000000000..c75441a598d --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_With_Variables.yaml @@ -0,0 +1,191 @@ +title: Authors_And_Reviews_And_Products_With_Variables +request: + document: | + query TopProducts( + $first: Int! + ) { + topProducts(first: $first) { + id + } + } + variables: | + { + "first": 2 + } +response: + body: | + { + "data": { + "topProducts": [ + { + "id": "UHJvZHVjdDox" + }, + { + "id": "UHJvZHVjdDoy" + }, + { + "id": "UHJvZHVjdDoz" + } + ] + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + - name: C + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + type RepeatDataData { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + input RepeatDataDataInput { + num: Int! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } + interactions: + - request: + document: | + query TopProducts_42998eb3_1( + $first: Int! + ) { + topProducts(first: $first) { + id + } + } + variables: | + { + "first": 2 + } + response: + results: + - | + { + "data": { + "topProducts": [ + { + "id": "UHJvZHVjdDox" + }, + { + "id": "UHJvZHVjdDoy" + }, + { + "id": "UHJvZHVjdDoz" + } + ] + } + } +operationPlan: + operation: + - document: | + query TopProducts( + $first: Int! + ) { + topProducts(first: $first) { + id + } + } + name: TopProducts + hash: 42998eb322dcb3ed03924bcd6d525e0a + searchSpace: 1 + expandedNodes: 1 + nodes: + - id: 1 + type: Operation + schema: C + operation: | + query TopProducts_42998eb3_1( + $first: Int! + ) { + topProducts(first: $first) { + id + } + } + forwardedVariables: + - first diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_AutoCompose.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_AutoCompose.yaml new file mode 100644 index 00000000000..e8d88d7fce0 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_AutoCompose.yaml @@ -0,0 +1,183 @@ +title: Authors_And_Reviews_AutoCompose +request: + document: | + { + users { + id + } + reviews { + body + } + } +response: + body: | + { + "data": { + "users": [ + { + "id": "VXNlcjox" + }, + { + "id": "VXNlcjoy" + }, + { + "id": "VXNlcjoz" + } + ], + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=" + }, + { + "body": "Review: UmV2aWV3OjI=" + }, + { + "body": "Review: UmV2aWV3OjM=" + } + ] + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + interactions: + - request: + document: | + query Op_cd73759d_2 { + users { + id + } + } + response: + results: + - | + { + "data": { + "users": [ + { + "id": "VXNlcjox" + }, + { + "id": "VXNlcjoy" + }, + { + "id": "VXNlcjoz" + } + ] + } + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + interactions: + - request: + document: | + query Op_cd73759d_1 { + reviews { + body + } + } + response: + results: + - | + { + "data": { + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=" + }, + { + "body": "Review: UmV2aWV3OjI=" + }, + { + "body": "Review: UmV2aWV3OjM=" + } + ] + } + } +operationPlan: + operation: + - document: | + { + users { + id + } + reviews { + body + } + } + hash: cd73759d80c767bd54369a8b397afe15 + searchSpace: 2 + expandedNodes: 2 + nodes: + - id: 1 + type: Operation + schema: B + operation: | + query Op_cd73759d_1 { + reviews { + body + } + } + - id: 2 + type: Operation + schema: A + operation: | + query Op_cd73759d_2 { + users { + id + } + } diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.yaml new file mode 100644 index 00000000000..f5f0d41bfa4 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.yaml @@ -0,0 +1,240 @@ +title: Authors_And_Reviews_Batch_Requests +request: + document: | + query GetUser { + reviews { + body + author { + birthdate + } + } + } +response: + body: | + { + "data": { + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=", + "author": { + "birthdate": "User: VXNlcjo0" + } + }, + { + "body": "Review: UmV2aWV3OjI=", + "author": { + "birthdate": "User: VXNlcjo1" + } + }, + { + "body": "Review: UmV2aWV3OjM=", + "author": { + "birthdate": "User: VXNlcjo2" + } + } + ] + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + interactions: + - request: + document: | + query GetUser_bc5cddd0_2( + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on User { + birthdate + } + } + } + variables: | + [ + { + "__fusion_1_id": "VXNlcjo0" + }, + { + "__fusion_1_id": "VXNlcjo1" + }, + { + "__fusion_1_id": "VXNlcjo2" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "User", + "birthdate": "User: VXNlcjo0" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "birthdate": "User: VXNlcjo1" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "birthdate": "User: VXNlcjo2" + } + } + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + interactions: + - request: + document: | + query GetUser_bc5cddd0_1 { + reviews { + body + author { + id + } + } + } + response: + results: + - | + { + "data": { + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=", + "author": { + "id": "VXNlcjo0" + } + }, + { + "body": "Review: UmV2aWV3OjI=", + "author": { + "id": "VXNlcjo1" + } + }, + { + "body": "Review: UmV2aWV3OjM=", + "author": { + "id": "VXNlcjo2" + } + } + ] + } + } +operationPlan: + operation: + - document: | + query GetUser { + reviews { + body + author { + birthdate + id @fusion__requirement + } + } + } + name: GetUser + hash: bc5cddd0c27ee413097062aa33fd6b4b + searchSpace: 1 + expandedNodes: 2 + nodes: + - id: 1 + type: Operation + schema: B + operation: | + query GetUser_bc5cddd0_1 { + reviews { + body + author { + id + } + } + } + - id: 2 + type: Operation + schema: A + operation: | + query GetUser_bc5cddd0_2( + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on User { + birthdate + } + } + } + source: $.node + target: $.reviews.author + requirements: + - name: __fusion_1_id + selectionMap: >- + id + dependencies: + - id: 1 diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById.yaml new file mode 100644 index 00000000000..bb03bc97dd9 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById.yaml @@ -0,0 +1,116 @@ +title: Authors_And_Reviews_Query_GetUserById +request: + document: | + query GetUser { + userById(id: "VXNlcjox") { + id + } + } +response: + body: | + { + "data": { + "userById": { + "id": "VXNlcjox" + } + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + interactions: + - request: + document: | + query GetUser_d81f16d6_1 { + userById(id: "VXNlcjox") { + id + } + } + response: + results: + - | + { + "data": { + "userById": { + "id": "VXNlcjox" + } + } + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } +operationPlan: + operation: + - document: | + query GetUser { + userById(id: "VXNlcjox") { + id + } + } + name: GetUser + hash: d81f16d6452fbd2f140ece4981b94fff + searchSpace: 1 + expandedNodes: 1 + nodes: + - id: 1 + type: Operation + schema: A + operation: | + query GetUser_d81f16d6_1 { + userById(id: "VXNlcjox") { + id + } + } diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById_With_Invalid_Id_Value.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById_With_Invalid_Id_Value.yaml new file mode 100644 index 00000000000..2fb15329d4f --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById_With_Invalid_Id_Value.yaml @@ -0,0 +1,116 @@ +title: Authors_And_Reviews_Query_GetUserById_With_Invalid_Id_Value +request: + document: | + query GetUser { + userById(id: 1) { + id + } + } +response: + body: | + { + "data": { + "userById": { + "id": "1" + } + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + interactions: + - request: + document: | + query GetUser_3fe4ea3e_1 { + userById(id: 1) { + id + } + } + response: + results: + - | + { + "data": { + "userById": { + "id": "1" + } + } + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } +operationPlan: + operation: + - document: | + query GetUser { + userById(id: 1) { + id + } + } + name: GetUser + hash: 3fe4ea3e6b3fadbbd25e5feba7b38e99 + searchSpace: 1 + expandedNodes: 1 + nodes: + - id: 1 + type: Operation + schema: A + operation: | + query GetUser_3fe4ea3e_1 { + userById(id: 1) { + id + } + } diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.yaml new file mode 100644 index 00000000000..440a603b8a6 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.yaml @@ -0,0 +1,503 @@ +title: Authors_And_Reviews_Query_GetUserReviews +request: + document: | + query GetUser { + users { + name + reviews { + body + author { + name + } + } + } + } +response: + body: | + { + "data": { + "users": [ + { + "name": "User: VXNlcjox", + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=", + "author": { + "name": "User: VXNlcjoxNg==" + } + }, + { + "body": "Review: UmV2aWV3OjI=", + "author": { + "name": "User: VXNlcjoxNw==" + } + }, + { + "body": "Review: UmV2aWV3OjM=", + "author": { + "name": "User: VXNlcjoxOA==" + } + } + ] + }, + { + "name": "User: VXNlcjoy", + "reviews": [ + { + "body": "Review: UmV2aWV3OjQ=", + "author": { + "name": "User: VXNlcjoxMw==" + } + }, + { + "body": "Review: UmV2aWV3OjU=", + "author": { + "name": "User: VXNlcjoxNA==" + } + }, + { + "body": "Review: UmV2aWV3OjY=", + "author": { + "name": "User: VXNlcjoxNQ==" + } + } + ] + }, + { + "name": "User: VXNlcjoz", + "reviews": [ + { + "body": "Review: UmV2aWV3Ojc=", + "author": { + "name": "User: VXNlcjoxMA==" + } + }, + { + "body": "Review: UmV2aWV3Ojg=", + "author": { + "name": "User: VXNlcjoxMQ==" + } + }, + { + "body": "Review: UmV2aWV3Ojk=", + "author": { + "name": "User: VXNlcjoxMg==" + } + } + ] + } + ] + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + interactions: + - request: + document: | + query GetUser_6e80578a_1 { + users { + name + id + } + } + response: + results: + - | + { + "data": { + "users": [ + { + "name": "User: VXNlcjox", + "id": "VXNlcjox" + }, + { + "name": "User: VXNlcjoy", + "id": "VXNlcjoy" + }, + { + "name": "User: VXNlcjoz", + "id": "VXNlcjoz" + } + ] + } + } + - request: + document: | + query GetUser_6e80578a_3( + $__fusion_2_id: ID! + ) { + node(id: $__fusion_2_id) { + __typename + ... on User { + name + } + } + } + variables: | + [ + { + "__fusion_2_id": "VXNlcjoxNg==" + }, + { + "__fusion_2_id": "VXNlcjoxNw==" + }, + { + "__fusion_2_id": "VXNlcjoxOA==" + }, + { + "__fusion_2_id": "VXNlcjoxMw==" + }, + { + "__fusion_2_id": "VXNlcjoxNA==" + }, + { + "__fusion_2_id": "VXNlcjoxNQ==" + }, + { + "__fusion_2_id": "VXNlcjoxMA==" + }, + { + "__fusion_2_id": "VXNlcjoxMQ==" + }, + { + "__fusion_2_id": "VXNlcjoxMg==" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxNg==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxNw==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxOA==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMw==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxNA==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxNQ==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMA==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMQ==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMg==" + } + } + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + interactions: + - request: + document: | + query GetUser_6e80578a_2( + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on User { + reviews { + body + author { + id + } + } + } + } + } + variables: | + [ + { + "__fusion_1_id": "VXNlcjox" + }, + { + "__fusion_1_id": "VXNlcjoy" + }, + { + "__fusion_1_id": "VXNlcjoz" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "User", + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=", + "author": { + "id": "VXNlcjoxNg==" + } + }, + { + "body": "Review: UmV2aWV3OjI=", + "author": { + "id": "VXNlcjoxNw==" + } + }, + { + "body": "Review: UmV2aWV3OjM=", + "author": { + "id": "VXNlcjoxOA==" + } + } + ] + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "reviews": [ + { + "body": "Review: UmV2aWV3OjQ=", + "author": { + "id": "VXNlcjoxMw==" + } + }, + { + "body": "Review: UmV2aWV3OjU=", + "author": { + "id": "VXNlcjoxNA==" + } + }, + { + "body": "Review: UmV2aWV3OjY=", + "author": { + "id": "VXNlcjoxNQ==" + } + } + ] + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "reviews": [ + { + "body": "Review: UmV2aWV3Ojc=", + "author": { + "id": "VXNlcjoxMA==" + } + }, + { + "body": "Review: UmV2aWV3Ojg=", + "author": { + "id": "VXNlcjoxMQ==" + } + }, + { + "body": "Review: UmV2aWV3Ojk=", + "author": { + "id": "VXNlcjoxMg==" + } + } + ] + } + } + } +operationPlan: + operation: + - document: | + query GetUser { + users { + name + reviews { + body + author { + name + id @fusion__requirement + } + } + id @fusion__requirement + } + } + name: GetUser + hash: 6e80578a140c2f3d066c653a63ef2977 + searchSpace: 1 + expandedNodes: 3 + nodes: + - id: 1 + type: Operation + schema: A + operation: | + query GetUser_6e80578a_1 { + users { + name + id + } + } + - id: 2 + type: Operation + schema: B + operation: | + query GetUser_6e80578a_2( + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on User { + reviews { + body + author { + id + } + } + } + } + } + source: $.node + target: $.users + requirements: + - name: __fusion_1_id + selectionMap: >- + id + dependencies: + - id: 1 + - id: 3 + type: Operation + schema: A + operation: | + query GetUser_6e80578a_3( + $__fusion_2_id: ID! + ) { + node(id: $__fusion_2_id) { + __typename + ... on User { + name + } + } + } + source: $.node + target: $.users.reviews.author + requirements: + - name: __fusion_2_id + selectionMap: >- + id + dependencies: + - id: 2 diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews_Skip_Author.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews_Skip_Author.yaml new file mode 100644 index 00000000000..548b9a3d8fd --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews_Skip_Author.yaml @@ -0,0 +1,341 @@ +title: Authors_And_Reviews_Query_GetUserReviews_Skip_Author +request: + document: | + query GetUser( + $skip: Boolean! + ) { + users { + name + reviews { + body + author @skip(if: $skip) { + name + birthdate + } + } + } + } + variables: | + { + "skip": true + } +response: + body: | + { + "data": { + "users": [ + { + "name": "User: VXNlcjox", + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=" + }, + { + "body": "Review: UmV2aWV3OjI=" + }, + { + "body": "Review: UmV2aWV3OjM=" + } + ] + }, + { + "name": "User: VXNlcjoy", + "reviews": [ + { + "body": "Review: UmV2aWV3OjQ=" + }, + { + "body": "Review: UmV2aWV3OjU=" + }, + { + "body": "Review: UmV2aWV3OjY=" + } + ] + }, + { + "name": "User: VXNlcjoz", + "reviews": [ + { + "body": "Review: UmV2aWV3Ojc=" + }, + { + "body": "Review: UmV2aWV3Ojg=" + }, + { + "body": "Review: UmV2aWV3Ojk=" + } + ] + } + ] + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + interactions: + - request: + document: | + query GetUser_f346d273_1 { + users { + name + id + } + } + response: + results: + - | + { + "data": { + "users": [ + { + "name": "User: VXNlcjox", + "id": "VXNlcjox" + }, + { + "name": "User: VXNlcjoy", + "id": "VXNlcjoy" + }, + { + "name": "User: VXNlcjoz", + "id": "VXNlcjoz" + } + ] + } + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + interactions: + - request: + document: | + query GetUser_f346d273_2( + $skip: Boolean! + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on User { + reviews { + body + author @skip(if: $skip) { + id + } + } + } + } + } + variables: | + [ + { + "skip": true, + "__fusion_1_id": "VXNlcjox" + }, + { + "skip": true, + "__fusion_1_id": "VXNlcjoy" + }, + { + "skip": true, + "__fusion_1_id": "VXNlcjoz" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "User", + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=" + }, + { + "body": "Review: UmV2aWV3OjI=" + }, + { + "body": "Review: UmV2aWV3OjM=" + } + ] + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "reviews": [ + { + "body": "Review: UmV2aWV3OjQ=" + }, + { + "body": "Review: UmV2aWV3OjU=" + }, + { + "body": "Review: UmV2aWV3OjY=" + } + ] + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "reviews": [ + { + "body": "Review: UmV2aWV3Ojc=" + }, + { + "body": "Review: UmV2aWV3Ojg=" + }, + { + "body": "Review: UmV2aWV3Ojk=" + } + ] + } + } + } +operationPlan: + operation: + - document: | + query GetUser( + $skip: Boolean! + ) { + users { + name + reviews { + body + author @skip(if: $skip) { + name + birthdate + id @fusion__requirement + } + } + id @fusion__requirement + } + } + name: GetUser + hash: f346d273632eda35e187eb747bbc7600 + searchSpace: 1 + expandedNodes: 3 + nodes: + - id: 1 + type: Operation + schema: A + operation: | + query GetUser_f346d273_1 { + users { + name + id + } + } + - id: 2 + type: Operation + schema: B + operation: | + query GetUser_f346d273_2( + $skip: Boolean! + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on User { + reviews { + body + author @skip(if: $skip) { + id + } + } + } + } + } + source: $.node + target: $.users + requirements: + - name: __fusion_1_id + selectionMap: >- + id + forwardedVariables: + - skip + dependencies: + - id: 1 + - id: 3 + type: Operation + schema: A + operation: | + query GetUser_f346d273_3( + $__fusion_2_id: ID! + ) { + node(id: $__fusion_2_id) { + __typename + ... on User { + name + birthdate + } + } + } + source: $.node + target: $.users.reviews.author + requirements: + - name: __fusion_2_id + selectionMap: >- + id + dependencies: + - id: 2 diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews_Skip_Author_ErrorField.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews_Skip_Author_ErrorField.yaml new file mode 100644 index 00000000000..04dcfe45a7a --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews_Skip_Author_ErrorField.yaml @@ -0,0 +1,544 @@ +title: Authors_And_Reviews_Query_GetUserReviews_Skip_Author_ErrorField +request: + document: | + query GetUser( + $skip: Boolean! + ) { + users { + name + reviews { + body + author { + name + birthdate + errorField @skip(if: $skip) + } + } + } + } + variables: | + { + "skip": true + } +response: + body: | + { + "data": { + "users": [ + { + "name": "User: VXNlcjox", + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=", + "author": { + "name": "User: VXNlcjoxNg==", + "birthdate": "User: VXNlcjoxNg==" + } + }, + { + "body": "Review: UmV2aWV3OjI=", + "author": { + "name": "User: VXNlcjoxNw==", + "birthdate": "User: VXNlcjoxNw==" + } + }, + { + "body": "Review: UmV2aWV3OjM=", + "author": { + "name": "User: VXNlcjoxOA==", + "birthdate": "User: VXNlcjoxOA==" + } + } + ] + }, + { + "name": "User: VXNlcjoy", + "reviews": [ + { + "body": "Review: UmV2aWV3OjQ=", + "author": { + "name": "User: VXNlcjoxMw==", + "birthdate": "User: VXNlcjoxMw==" + } + }, + { + "body": "Review: UmV2aWV3OjU=", + "author": { + "name": "User: VXNlcjoxNA==", + "birthdate": "User: VXNlcjoxNA==" + } + }, + { + "body": "Review: UmV2aWV3OjY=", + "author": { + "name": "User: VXNlcjoxNQ==", + "birthdate": "User: VXNlcjoxNQ==" + } + } + ] + }, + { + "name": "User: VXNlcjoz", + "reviews": [ + { + "body": "Review: UmV2aWV3Ojc=", + "author": { + "name": "User: VXNlcjoxMA==", + "birthdate": "User: VXNlcjoxMA==" + } + }, + { + "body": "Review: UmV2aWV3Ojg=", + "author": { + "name": "User: VXNlcjoxMQ==", + "birthdate": "User: VXNlcjoxMQ==" + } + }, + { + "body": "Review: UmV2aWV3Ojk=", + "author": { + "name": "User: VXNlcjoxMg==", + "birthdate": "User: VXNlcjoxMg==" + } + } + ] + } + ] + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + interactions: + - request: + document: | + query GetUser_c6f5d2d4_1 { + users { + name + id + } + } + response: + results: + - | + { + "data": { + "users": [ + { + "name": "User: VXNlcjox", + "id": "VXNlcjox" + }, + { + "name": "User: VXNlcjoy", + "id": "VXNlcjoy" + }, + { + "name": "User: VXNlcjoz", + "id": "VXNlcjoz" + } + ] + } + } + - request: + document: | + query GetUser_c6f5d2d4_3( + $__fusion_2_id: ID! + ) { + node(id: $__fusion_2_id) { + __typename + ... on User { + name + birthdate + } + } + } + variables: | + [ + { + "__fusion_2_id": "VXNlcjoxNg==" + }, + { + "__fusion_2_id": "VXNlcjoxNw==" + }, + { + "__fusion_2_id": "VXNlcjoxOA==" + }, + { + "__fusion_2_id": "VXNlcjoxMw==" + }, + { + "__fusion_2_id": "VXNlcjoxNA==" + }, + { + "__fusion_2_id": "VXNlcjoxNQ==" + }, + { + "__fusion_2_id": "VXNlcjoxMA==" + }, + { + "__fusion_2_id": "VXNlcjoxMQ==" + }, + { + "__fusion_2_id": "VXNlcjoxMg==" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxNg==", + "birthdate": "User: VXNlcjoxNg==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxNw==", + "birthdate": "User: VXNlcjoxNw==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxOA==", + "birthdate": "User: VXNlcjoxOA==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMw==", + "birthdate": "User: VXNlcjoxMw==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxNA==", + "birthdate": "User: VXNlcjoxNA==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxNQ==", + "birthdate": "User: VXNlcjoxNQ==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMA==", + "birthdate": "User: VXNlcjoxMA==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMQ==", + "birthdate": "User: VXNlcjoxMQ==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMg==", + "birthdate": "User: VXNlcjoxMg==" + } + } + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + interactions: + - request: + document: | + query GetUser_c6f5d2d4_2( + $skip: Boolean! + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on User { + reviews { + body + author { + errorField @skip(if: $skip) + id + } + } + } + } + } + variables: | + [ + { + "skip": true, + "__fusion_1_id": "VXNlcjox" + }, + { + "skip": true, + "__fusion_1_id": "VXNlcjoy" + }, + { + "skip": true, + "__fusion_1_id": "VXNlcjoz" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "User", + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=", + "author": { + "id": "VXNlcjoxNg==" + } + }, + { + "body": "Review: UmV2aWV3OjI=", + "author": { + "id": "VXNlcjoxNw==" + } + }, + { + "body": "Review: UmV2aWV3OjM=", + "author": { + "id": "VXNlcjoxOA==" + } + } + ] + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "reviews": [ + { + "body": "Review: UmV2aWV3OjQ=", + "author": { + "id": "VXNlcjoxMw==" + } + }, + { + "body": "Review: UmV2aWV3OjU=", + "author": { + "id": "VXNlcjoxNA==" + } + }, + { + "body": "Review: UmV2aWV3OjY=", + "author": { + "id": "VXNlcjoxNQ==" + } + } + ] + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "reviews": [ + { + "body": "Review: UmV2aWV3Ojc=", + "author": { + "id": "VXNlcjoxMA==" + } + }, + { + "body": "Review: UmV2aWV3Ojg=", + "author": { + "id": "VXNlcjoxMQ==" + } + }, + { + "body": "Review: UmV2aWV3Ojk=", + "author": { + "id": "VXNlcjoxMg==" + } + } + ] + } + } + } +operationPlan: + operation: + - document: | + query GetUser( + $skip: Boolean! + ) { + users { + name + reviews { + body + author { + name + birthdate + id @fusion__requirement + errorField @skip(if: $skip) + } + } + id @fusion__requirement + } + } + name: GetUser + hash: c6f5d2d41d8fb329e843e3fb4d13a435 + searchSpace: 1 + expandedNodes: 3 + nodes: + - id: 1 + type: Operation + schema: A + operation: | + query GetUser_c6f5d2d4_1 { + users { + name + id + } + } + - id: 2 + type: Operation + schema: B + operation: | + query GetUser_c6f5d2d4_2( + $skip: Boolean! + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on User { + reviews { + body + author { + errorField @skip(if: $skip) + id + } + } + } + } + } + source: $.node + target: $.users + requirements: + - name: __fusion_1_id + selectionMap: >- + id + forwardedVariables: + - skip + dependencies: + - id: 1 + - id: 3 + type: Operation + schema: A + operation: | + query GetUser_c6f5d2d4_3( + $__fusion_2_id: ID! + ) { + node(id: $__fusion_2_id) { + __typename + ... on User { + name + birthdate + } + } + } + source: $.node + target: $.users.reviews.author + requirements: + - name: __fusion_2_id + selectionMap: >- + id + dependencies: + - id: 2 diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.yaml new file mode 100644 index 00000000000..999cb58b15c --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.yaml @@ -0,0 +1,765 @@ +title: Authors_And_Reviews_Query_ReviewsUser +request: + document: | + query GetUser { + a: reviews { + body + author { + name + } + } + b: reviews { + body + author { + name + } + } + users { + name + reviews { + body + author { + name + } + } + } + } +response: + body: | + { + "data": { + "a": [ + { + "body": "Review: UmV2aWV3OjE=", + "author": { + "name": "User: VXNlcjoxMA==" + } + }, + { + "body": "Review: UmV2aWV3OjI=", + "author": { + "name": "User: VXNlcjoxMQ==" + } + }, + { + "body": "Review: UmV2aWV3OjM=", + "author": { + "name": "User: VXNlcjoxMg==" + } + } + ], + "b": [ + { + "body": "Review: UmV2aWV3OjQ=", + "author": { + "name": "User: VXNlcjo3" + } + }, + { + "body": "Review: UmV2aWV3OjU=", + "author": { + "name": "User: VXNlcjo4" + } + }, + { + "body": "Review: UmV2aWV3OjY=", + "author": { + "name": "User: VXNlcjo5" + } + } + ], + "users": [ + { + "name": "User: VXNlcjox", + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=", + "author": { + "name": "User: VXNlcjoxNg==" + } + }, + { + "body": "Review: UmV2aWV3OjI=", + "author": { + "name": "User: VXNlcjoxNw==" + } + }, + { + "body": "Review: UmV2aWV3OjM=", + "author": { + "name": "User: VXNlcjoxOA==" + } + } + ] + }, + { + "name": "User: VXNlcjoy", + "reviews": [ + { + "body": "Review: UmV2aWV3OjQ=", + "author": { + "name": "User: VXNlcjoxMw==" + } + }, + { + "body": "Review: UmV2aWV3OjU=", + "author": { + "name": "User: VXNlcjoxNA==" + } + }, + { + "body": "Review: UmV2aWV3OjY=", + "author": { + "name": "User: VXNlcjoxNQ==" + } + } + ] + }, + { + "name": "User: VXNlcjoz", + "reviews": [ + { + "body": "Review: UmV2aWV3Ojc=", + "author": { + "name": "User: VXNlcjoxMA==" + } + }, + { + "body": "Review: UmV2aWV3Ojg=", + "author": { + "name": "User: VXNlcjoxMQ==" + } + }, + { + "body": "Review: UmV2aWV3Ojk=", + "author": { + "name": "User: VXNlcjoxMg==" + } + } + ] + } + ] + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + interactions: + - request: + document: | + query GetUser_c03cccb0_2 { + users { + name + id + } + } + response: + results: + - | + { + "data": { + "users": [ + { + "name": "User: VXNlcjox", + "id": "VXNlcjox" + }, + { + "name": "User: VXNlcjoy", + "id": "VXNlcjoy" + }, + { + "name": "User: VXNlcjoz", + "id": "VXNlcjoz" + } + ] + } + } + - request: + document: | + query GetUser_c03cccb0_4( + $__fusion_2_id: ID! + ) { + node(id: $__fusion_2_id) { + __typename + ... on User { + name + } + } + } + variables: | + [ + { + "__fusion_2_id": "VXNlcjoxNg==" + }, + { + "__fusion_2_id": "VXNlcjoxNw==" + }, + { + "__fusion_2_id": "VXNlcjoxOA==" + }, + { + "__fusion_2_id": "VXNlcjoxMw==" + }, + { + "__fusion_2_id": "VXNlcjoxNA==" + }, + { + "__fusion_2_id": "VXNlcjoxNQ==" + }, + { + "__fusion_2_id": "VXNlcjoxMA==" + }, + { + "__fusion_2_id": "VXNlcjoxMQ==" + }, + { + "__fusion_2_id": "VXNlcjoxMg==" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxNg==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxNw==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxOA==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMw==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxNA==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxNQ==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMA==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMQ==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMg==" + } + } + } + - request: + document: | + query GetUser_c03cccb0_5( + $__fusion_3_id: ID! + ) { + node(id: $__fusion_3_id) { + __typename + ... on User { + name + } + } + } + variables: | + [ + { + "__fusion_3_id": "VXNlcjo3" + }, + { + "__fusion_3_id": "VXNlcjo4" + }, + { + "__fusion_3_id": "VXNlcjo5" + }, + { + "__fusion_3_id": "VXNlcjoxMA==" + }, + { + "__fusion_3_id": "VXNlcjoxMQ==" + }, + { + "__fusion_3_id": "VXNlcjoxMg==" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjo3" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjo4" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjo5" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMA==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMQ==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMg==" + } + } + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + interactions: + - request: + document: | + query GetUser_c03cccb0_1 { + a: reviews { + body + author { + id + } + } + b: reviews { + body + author { + id + } + } + } + response: + results: + - | + { + "data": { + "a": [ + { + "body": "Review: UmV2aWV3OjE=", + "author": { + "id": "VXNlcjoxMA==" + } + }, + { + "body": "Review: UmV2aWV3OjI=", + "author": { + "id": "VXNlcjoxMQ==" + } + }, + { + "body": "Review: UmV2aWV3OjM=", + "author": { + "id": "VXNlcjoxMg==" + } + } + ], + "b": [ + { + "body": "Review: UmV2aWV3OjQ=", + "author": { + "id": "VXNlcjo3" + } + }, + { + "body": "Review: UmV2aWV3OjU=", + "author": { + "id": "VXNlcjo4" + } + }, + { + "body": "Review: UmV2aWV3OjY=", + "author": { + "id": "VXNlcjo5" + } + } + ] + } + } + - request: + document: | + query GetUser_c03cccb0_3( + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on User { + reviews { + body + author { + id + } + } + } + } + } + variables: | + [ + { + "__fusion_1_id": "VXNlcjox" + }, + { + "__fusion_1_id": "VXNlcjoy" + }, + { + "__fusion_1_id": "VXNlcjoz" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "User", + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=", + "author": { + "id": "VXNlcjoxNg==" + } + }, + { + "body": "Review: UmV2aWV3OjI=", + "author": { + "id": "VXNlcjoxNw==" + } + }, + { + "body": "Review: UmV2aWV3OjM=", + "author": { + "id": "VXNlcjoxOA==" + } + } + ] + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "reviews": [ + { + "body": "Review: UmV2aWV3OjQ=", + "author": { + "id": "VXNlcjoxMw==" + } + }, + { + "body": "Review: UmV2aWV3OjU=", + "author": { + "id": "VXNlcjoxNA==" + } + }, + { + "body": "Review: UmV2aWV3OjY=", + "author": { + "id": "VXNlcjoxNQ==" + } + } + ] + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "reviews": [ + { + "body": "Review: UmV2aWV3Ojc=", + "author": { + "id": "VXNlcjoxMA==" + } + }, + { + "body": "Review: UmV2aWV3Ojg=", + "author": { + "id": "VXNlcjoxMQ==" + } + }, + { + "body": "Review: UmV2aWV3Ojk=", + "author": { + "id": "VXNlcjoxMg==" + } + } + ] + } + } + } +operationPlan: + operation: + - document: | + query GetUser { + a: reviews { + body + author { + name + id @fusion__requirement + } + } + b: reviews { + body + author { + name + id @fusion__requirement + } + } + users { + name + reviews { + body + author { + name + id @fusion__requirement + } + } + id @fusion__requirement + } + } + name: GetUser + hash: c03cccb0c97cb564e5173a0bbfa1df1c + searchSpace: 2 + expandedNodes: 5 + nodes: + - id: 1 + type: Operation + schema: B + operation: | + query GetUser_c03cccb0_1 { + a: reviews { + body + author { + id + } + } + b: reviews { + body + author { + id + } + } + } + - id: 2 + type: Operation + schema: A + operation: | + query GetUser_c03cccb0_2 { + users { + name + id + } + } + - id: 3 + type: Operation + schema: B + operation: | + query GetUser_c03cccb0_3( + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on User { + reviews { + body + author { + id + } + } + } + } + } + source: $.node + target: $.users + requirements: + - name: __fusion_1_id + selectionMap: >- + id + dependencies: + - id: 2 + - id: 4 + type: Operation + schema: A + operation: | + query GetUser_c03cccb0_4( + $__fusion_2_id: ID! + ) { + node(id: $__fusion_2_id) { + __typename + ... on User { + name + } + } + } + source: $.node + target: $.users.reviews.author + requirements: + - name: __fusion_2_id + selectionMap: >- + id + dependencies: + - id: 3 + - id: 5 + type: OperationBatch + schema: A + operation: | + query GetUser_c03cccb0_5( + $__fusion_3_id: ID! + ) { + node(id: $__fusion_3_id) { + __typename + ... on User { + name + } + } + } + source: $.node + targets: + - $.b.author + - $.a.author + batchingGroupId: 1 + requirements: + - name: __fusion_3_id + selectionMap: >- + id + dependencies: + - id: 1 diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Fetch_User_With_Invalid_Node_Field.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Fetch_User_With_Invalid_Node_Field.yaml new file mode 100644 index 00000000000..96bab5f719c --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Fetch_User_With_Invalid_Node_Field.yaml @@ -0,0 +1,181 @@ +title: Fetch_User_With_Invalid_Node_Field +request: + document: | + query FetchNode( + $id: ID! + ) { + node(id: $id) { + ... on User { + id + } + } + } + variables: | + { + "id": 1 + } +response: + body: | + { + "data": { + "node": null + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + - name: C + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + type RepeatDataData { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + input RepeatDataDataInput { + num: Int! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } +operationPlan: + operation: + - document: | + query FetchNode( + $id: ID! + ) { + node(id: $id) { + __typename @fusion__requirement + ... on User { + id + } + } + } + name: FetchNode + hash: 7eae38bd8fde86d9bed495a46e5cc83f + searchSpace: 1 + expandedNodes: 1 + nodes: + - id: 1 + type: Node + idValue: $id + responseName: node + branches: + - User: 3 + fallback: 2 + - id: 2 + type: Operation + operation: | + query FetchNode_7eae38bd_2( + $id: ID! + ) { + node(id: $id) { + __typename + } + } + forwardedVariables: + - id + dependencies: + - id: 1 + - id: 3 + type: Operation + schema: A + operation: | + query FetchNode_7eae38bd_3( + $id: ID! + ) { + node(id: $id) { + __typename + ... on User { + __typename + id + } + } + } + forwardedVariables: + - id + dependencies: + - id: 1 diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field.yaml new file mode 100644 index 00000000000..effab74f01c --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field.yaml @@ -0,0 +1,212 @@ +title: Fetch_User_With_Node_Field +request: + document: | + query FetchNode( + $id: ID! + ) { + node(id: $id) { + ... on User { + id + } + } + } + variables: | + { + "id": "VXNlcjox" + } +response: + body: | + { + "data": { + "node": { + "id": "VXNlcjox" + } + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + interactions: + - request: + document: | + query FetchNode_7eae38bd_3( + $id: ID! + ) { + node(id: $id) { + __typename + ... on User { + __typename + id + } + } + } + variables: | + { + "id": "VXNlcjox" + } + response: + results: + - | + { + "data": { + "node": { + "__typename": "User", + "id": "VXNlcjox" + } + } + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + - name: C + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + type RepeatDataData { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + input RepeatDataDataInput { + num: Int! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } +operationPlan: + operation: + - document: | + query FetchNode( + $id: ID! + ) { + node(id: $id) { + __typename @fusion__requirement + ... on User { + id + } + } + } + name: FetchNode + hash: 7eae38bd8fde86d9bed495a46e5cc83f + searchSpace: 1 + expandedNodes: 1 + nodes: + - id: 1 + type: Node + idValue: $id + responseName: node + branches: + - User: 3 + fallback: 2 + - id: 2 + type: Operation + operation: | + query FetchNode_7eae38bd_2( + $id: ID! + ) { + node(id: $id) { + __typename + } + } + forwardedVariables: + - id + dependencies: + - id: 1 + - id: 3 + type: Operation + schema: A + operation: | + query FetchNode_7eae38bd_3( + $id: ID! + ) { + node(id: $id) { + __typename + ... on User { + __typename + id + } + } + } + forwardedVariables: + - id + dependencies: + - id: 1 diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_From_Two_Subgraphs.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_From_Two_Subgraphs.yaml new file mode 100644 index 00000000000..43d54f1f70e --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_From_Two_Subgraphs.yaml @@ -0,0 +1,297 @@ +title: Fetch_User_With_Node_Field_From_Two_Subgraphs +request: + document: | + query FetchNode( + $id: ID! + ) { + node(id: $id) { + ... on User { + birthdate + reviews { + body + } + } + } + } + variables: | + { + "id": "VXNlcjox" + } +response: + body: | + { + "data": { + "node": { + "birthdate": "User: VXNlcjox", + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=" + }, + { + "body": "Review: UmV2aWV3OjI=" + }, + { + "body": "Review: UmV2aWV3OjM=" + } + ] + } + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + interactions: + - request: + document: | + query FetchNode_47e389d6_4( + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on User { + birthdate + } + } + } + variables: | + { + "__fusion_1_id": "VXNlcjox" + } + response: + results: + - | + { + "data": { + "node": { + "__typename": "User", + "birthdate": "User: VXNlcjox" + } + } + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + interactions: + - request: + document: | + query FetchNode_47e389d6_3( + $id: ID! + ) { + node(id: $id) { + __typename + ... on User { + __typename + reviews { + body + } + id + } + } + } + variables: | + { + "id": "VXNlcjox" + } + response: + results: + - | + { + "data": { + "node": { + "__typename": "User", + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=" + }, + { + "body": "Review: UmV2aWV3OjI=" + }, + { + "body": "Review: UmV2aWV3OjM=" + } + ], + "id": "VXNlcjox" + } + } + } + - name: C + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + type RepeatDataData { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + input RepeatDataDataInput { + num: Int! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } +operationPlan: + operation: + - document: | + query FetchNode( + $id: ID! + ) { + node(id: $id) { + __typename @fusion__requirement + id @fusion__requirement + ... on User { + birthdate + reviews { + body + } + } + } + } + name: FetchNode + hash: 47e389d6e8925aa3aecd4bb054a2ceec + searchSpace: 2 + expandedNodes: 5 + nodes: + - id: 1 + type: Node + idValue: $id + responseName: node + branches: + - User: 3 + fallback: 2 + - id: 2 + type: Operation + operation: | + query FetchNode_47e389d6_2( + $id: ID! + ) { + node(id: $id) { + __typename + } + } + forwardedVariables: + - id + dependencies: + - id: 1 + - id: 3 + type: Operation + schema: B + operation: | + query FetchNode_47e389d6_3( + $id: ID! + ) { + node(id: $id) { + __typename + ... on User { + __typename + reviews { + body + } + id + } + } + } + forwardedVariables: + - id + dependencies: + - id: 1 + - id: 4 + type: Operation + schema: A + operation: | + query FetchNode_47e389d6_4( + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on User { + birthdate + } + } + } + source: $.node + target: $.node + requirements: + - name: __fusion_1_id + selectionMap: >- + id + dependencies: + - id: 3 diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Review_Id.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Review_Id.yaml new file mode 100644 index 00000000000..1a331bfa27c --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Review_Id.yaml @@ -0,0 +1,205 @@ +title: Fetch_User_With_Node_Field_Pass_In_Review_Id +request: + document: | + query FetchNode( + $id: ID! + ) { + node(id: $id) { + ... on User { + id + } + } + } + variables: | + { + "id": "UmV2aWV3OjE=" + } +response: + body: | + { + "data": { + "node": {} + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + interactions: + - request: + document: | + query FetchNode_7eae38bd_2( + $id: ID! + ) { + node(id: $id) { + __typename + } + } + variables: | + { + "id": "UmV2aWV3OjE=" + } + response: + results: + - | + { + "data": { + "node": { + "__typename": "Review" + } + } + } + - name: C + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + type RepeatDataData { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + input RepeatDataDataInput { + num: Int! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } +operationPlan: + operation: + - document: | + query FetchNode( + $id: ID! + ) { + node(id: $id) { + __typename @fusion__requirement + ... on User { + id + } + } + } + name: FetchNode + hash: 7eae38bd8fde86d9bed495a46e5cc83f + searchSpace: 1 + expandedNodes: 1 + nodes: + - id: 1 + type: Node + idValue: $id + responseName: node + branches: + - User: 3 + fallback: 2 + - id: 2 + type: Operation + operation: | + query FetchNode_7eae38bd_2( + $id: ID! + ) { + node(id: $id) { + __typename + } + } + forwardedVariables: + - id + dependencies: + - id: 1 + - id: 3 + type: Operation + schema: A + operation: | + query FetchNode_7eae38bd_3( + $id: ID! + ) { + node(id: $id) { + __typename + ... on User { + __typename + id + } + } + } + forwardedVariables: + - id + dependencies: + - id: 1 diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Unknown_Id.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Unknown_Id.yaml new file mode 100644 index 00000000000..4efe5590dc4 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Unknown_Id.yaml @@ -0,0 +1,192 @@ +title: Fetch_User_With_Node_Field_Pass_In_Unknown_Id +request: + document: | + query FetchNode( + $id: ID! + ) { + node(id: $id) { + ... on User { + id + } + } + } + variables: | + { + "id": "VW5rbm93bjox" + } +response: + body: | + { + "data": { + "node": null + }, + "errors": [ + { + "message": "The node ID string has an invalid format.", + "path": [ + "node" + ], + "extensions": { + "originalValue": "VW5rbm93bjox" + } + } + ] + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + - name: C + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + type RepeatDataData { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + input RepeatDataDataInput { + num: Int! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } +operationPlan: + operation: + - document: | + query FetchNode( + $id: ID! + ) { + node(id: $id) { + __typename @fusion__requirement + ... on User { + id + } + } + } + name: FetchNode + hash: 7eae38bd8fde86d9bed495a46e5cc83f + searchSpace: 1 + expandedNodes: 1 + nodes: + - id: 1 + type: Node + idValue: $id + responseName: node + branches: + - User: 3 + fallback: 2 + - id: 2 + type: Operation + operation: | + query FetchNode_7eae38bd_2( + $id: ID! + ) { + node(id: $id) { + __typename + } + } + forwardedVariables: + - id + dependencies: + - id: 1 + - id: 3 + type: Operation + schema: A + operation: | + query FetchNode_7eae38bd_3( + $id: ID! + ) { + node(id: $id) { + __typename + ... on User { + __typename + id + } + } + } + forwardedVariables: + - id + dependencies: + - id: 1 diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Forward_Nested_Node_Variables.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Forward_Nested_Node_Variables.yaml new file mode 100644 index 00000000000..c1285843699 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Forward_Nested_Node_Variables.yaml @@ -0,0 +1,225 @@ +title: Forward_Nested_Node_Variables +request: + document: | + query ProductReviews( + $id: ID! + $first: Int! + ) { + node(id: $id) { + ... on Product { + id + repeat(num: $first) + } + } + } + variables: | + { + "id": "UHJvZHVjdDox", + "first": 1 + } +response: + body: | + { + "data": { + "node": { + "id": "UHJvZHVjdDox", + "repeat": "Product: UHJvZHVjdDox" + } + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + - name: C + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + type RepeatDataData { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + input RepeatDataDataInput { + num: Int! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } + interactions: + - request: + document: | + query ProductReviews_a31f6868_3( + $id: ID! + $first: Int! + ) { + node(id: $id) { + __typename + ... on Product { + __typename + id + repeat(num: $first) + } + } + } + variables: | + { + "id": "UHJvZHVjdDox", + "first": 1 + } + response: + results: + - | + { + "data": { + "node": { + "__typename": "Product", + "id": "UHJvZHVjdDox", + "repeat": "Product: UHJvZHVjdDox" + } + } + } +operationPlan: + operation: + - document: | + query ProductReviews( + $id: ID! + $first: Int! + ) { + node(id: $id) { + __typename @fusion__requirement + ... on Product { + id + repeat(num: $first) + } + } + } + name: ProductReviews + hash: a31f6868bbb43c4726864f440816041b + searchSpace: 1 + expandedNodes: 1 + nodes: + - id: 1 + type: Node + idValue: $id + responseName: node + branches: + - Product: 3 + fallback: 2 + - id: 2 + type: Operation + operation: | + query ProductReviews_a31f6868_2( + $id: ID! + ) { + node(id: $id) { + __typename + } + } + forwardedVariables: + - id + dependencies: + - id: 1 + - id: 3 + type: Operation + schema: C + operation: | + query ProductReviews_a31f6868_3( + $id: ID! + $first: Int! + ) { + node(id: $id) { + __typename + ... on Product { + __typename + id + repeat(num: $first) + } + } + } + forwardedVariables: + - id + - first + dependencies: + - id: 1 diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Forward_Nested_Object_Variables.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Forward_Nested_Object_Variables.yaml new file mode 100644 index 00000000000..ba0f9595379 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Forward_Nested_Object_Variables.yaml @@ -0,0 +1,212 @@ +title: Forward_Nested_Object_Variables +request: + document: | + query ProductReviews( + $id: ID! + $first: Int! + ) { + productById(id: $id) { + id + repeatData(data: { data: { num: $first } }) { + data { + num + } + } + } + } + variables: | + { + "id": "UHJvZHVjdDox", + "first": 1 + } +response: + body: | + { + "data": { + "productById": { + "id": "UHJvZHVjdDox", + "repeatData": { + "data": { + "num": 123 + } + } + } + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + - name: C + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + type RepeatDataData { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + input RepeatDataDataInput { + num: Int! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } + interactions: + - request: + document: | + query ProductReviews_4a9e0ed8_1( + $id: ID! + $first: Int! + ) { + productById(id: $id) { + id + repeatData(data: { data: { num: $first } }) { + data { + num + } + } + } + } + variables: | + { + "id": "UHJvZHVjdDox", + "first": 1 + } + response: + results: + - | + { + "data": { + "productById": { + "id": "UHJvZHVjdDox", + "repeatData": { + "data": { + "num": 123 + } + } + } + } + } +operationPlan: + operation: + - document: | + query ProductReviews( + $id: ID! + $first: Int! + ) { + productById(id: $id) { + id + repeatData(data: { data: { num: $first } }) { + data { + num + } + } + } + } + name: ProductReviews + hash: 4a9e0ed86f673b2fe29d210703e41470 + searchSpace: 1 + expandedNodes: 1 + nodes: + - id: 1 + type: Operation + schema: C + operation: | + query ProductReviews_4a9e0ed8_1( + $id: ID! + $first: Int! + ) { + productById(id: $id) { + id + repeatData(data: { data: { num: $first } }) { + data { + num + } + } + } + } + forwardedVariables: + - id + - first diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Forward_Nested_Variables.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Forward_Nested_Variables.yaml new file mode 100644 index 00000000000..c60cb70c222 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Forward_Nested_Variables.yaml @@ -0,0 +1,188 @@ +title: Forward_Nested_Variables +request: + document: | + query ProductReviews( + $id: ID! + $first: Int! + ) { + productById(id: $id) { + id + repeat(num: $first) + } + } + variables: | + { + "id": "UHJvZHVjdDox", + "first": 1 + } +response: + body: | + { + "data": { + "productById": { + "id": "UHJvZHVjdDox", + "repeat": "Product: UHJvZHVjdDox" + } + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + - name: C + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + type RepeatDataData { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + input RepeatDataDataInput { + num: Int! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } + interactions: + - request: + document: | + query ProductReviews_f7aec035_1( + $id: ID! + $first: Int! + ) { + productById(id: $id) { + id + repeat(num: $first) + } + } + variables: | + { + "id": "UHJvZHVjdDox", + "first": 1 + } + response: + results: + - | + { + "data": { + "productById": { + "id": "UHJvZHVjdDox", + "repeat": "Product: UHJvZHVjdDox" + } + } + } +operationPlan: + operation: + - document: | + query ProductReviews( + $id: ID! + $first: Int! + ) { + productById(id: $id) { + id + repeat(num: $first) + } + } + name: ProductReviews + hash: f7aec035226d7806637f9ad0495e7170 + searchSpace: 1 + expandedNodes: 1 + nodes: + - id: 1 + type: Operation + schema: C + operation: | + query ProductReviews_f7aec035_1( + $id: ID! + $first: Int! + ) { + productById(id: $id) { + id + repeat(num: $first) + } + } + forwardedVariables: + - id + - first diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Forward_Nested_Variables_No_OpName.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Forward_Nested_Variables_No_OpName.yaml new file mode 100644 index 00000000000..487507bce6e --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Forward_Nested_Variables_No_OpName.yaml @@ -0,0 +1,187 @@ +title: Forward_Nested_Variables_No_OpName +request: + document: | + query( + $id: ID! + $first: Int! + ) { + productById(id: $id) { + id + repeat(num: $first) + } + } + variables: | + { + "id": "UHJvZHVjdDox", + "first": 1 + } +response: + body: | + { + "data": { + "productById": { + "id": "UHJvZHVjdDox", + "repeat": "Product: UHJvZHVjdDox" + } + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + - name: C + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + type RepeatDataData { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + input RepeatDataDataInput { + num: Int! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } + interactions: + - request: + document: | + query Op_4ffcfe3f_1( + $id: ID! + $first: Int! + ) { + productById(id: $id) { + id + repeat(num: $first) + } + } + variables: | + { + "id": "UHJvZHVjdDox", + "first": 1 + } + response: + results: + - | + { + "data": { + "productById": { + "id": "UHJvZHVjdDox", + "repeat": "Product: UHJvZHVjdDox" + } + } + } +operationPlan: + operation: + - document: | + query( + $id: ID! + $first: Int! + ) { + productById(id: $id) { + id + repeat(num: $first) + } + } + hash: 4ffcfe3f81d1721781ad9f6afec98493 + searchSpace: 1 + expandedNodes: 1 + nodes: + - id: 1 + type: Operation + schema: C + operation: | + query Op_4ffcfe3f_1( + $id: ID! + $first: Int! + ) { + productById(id: $id) { + id + repeat(num: $first) + } + } + forwardedVariables: + - id + - first diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Forward_Nested_Variables_No_OpName_Two_RootSelections.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Forward_Nested_Variables_No_OpName_Two_RootSelections.yaml new file mode 100644 index 00000000000..e953c089d13 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Forward_Nested_Variables_No_OpName_Two_RootSelections.yaml @@ -0,0 +1,211 @@ +title: Forward_Nested_Variables_No_OpName_Two_RootSelections +request: + document: | + query( + $id: ID! + $first: Int! + ) { + a: productById(id: $id) { + id + repeat(num: $first) + } + b: productById(id: $id) { + id + repeat(num: $first) + } + } + variables: | + { + "id": "UHJvZHVjdDox", + "first": 1 + } +response: + body: | + { + "data": { + "a": { + "id": "UHJvZHVjdDox", + "repeat": "Product: UHJvZHVjdDox" + }, + "b": { + "id": "UHJvZHVjdDox", + "repeat": "Product: UHJvZHVjdDox" + } + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + - name: C + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + type RepeatDataData { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + input RepeatDataDataInput { + num: Int! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } + interactions: + - request: + document: | + query Op_5090b8e6_1( + $id: ID! + $first: Int! + ) { + a: productById(id: $id) { + id + repeat(num: $first) + } + b: productById(id: $id) { + id + repeat(num: $first) + } + } + variables: | + { + "id": "UHJvZHVjdDox", + "first": 1 + } + response: + results: + - | + { + "data": { + "a": { + "id": "UHJvZHVjdDox", + "repeat": "Product: UHJvZHVjdDox" + }, + "b": { + "id": "UHJvZHVjdDox", + "repeat": "Product: UHJvZHVjdDox" + } + } + } +operationPlan: + operation: + - document: | + query( + $id: ID! + $first: Int! + ) { + a: productById(id: $id) { + id + repeat(num: $first) + } + b: productById(id: $id) { + id + repeat(num: $first) + } + } + hash: 5090b8e67ece2ae849082dd03fb275de + searchSpace: 1 + expandedNodes: 1 + nodes: + - id: 1 + type: Operation + schema: C + operation: | + query Op_5090b8e6_1( + $id: ID! + $first: Int! + ) { + a: productById(id: $id) { + id + repeat(num: $first) + } + b: productById(id: $id) { + id + repeat(num: $first) + } + } + forwardedVariables: + - id + - first diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.GetFirstPage_With_After_Null.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.GetFirstPage_With_After_Null.yaml new file mode 100644 index 00000000000..d0db0a537d0 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.GetFirstPage_With_After_Null.yaml @@ -0,0 +1,121 @@ +title: GetFirstPage_With_After_Null +request: + document: | + query AfterNull( + $after: String + ) { + appointments(after: $after) { + nodes { + id + } + } + } + variables: | + { + "after": null + } +response: + body: | + { + "data": { + "appointments": { + "nodes": [ + { + "id": "QXBwb2ludG1lbnQ6Mg==" + }, + { + "id": "QXBwb2ludG1lbnQ6Mw==" + }, + { + "id": "QXBwb2ludG1lbnQ6NA==" + } + ] + } + } + } +sourceSchemas: + - name: E + schema: | + schema { + query: Query + } + + type Appointment { + id: ID! + } + + type AppointmentConnection { + nodes: [Appointment!] + } + + type Query { + appointments(after: String): AppointmentConnection + } + interactions: + - request: + document: | + query AfterNull_bcc834fd_1( + $after: String + ) { + appointments(after: $after) { + nodes { + id + } + } + } + variables: | + { + "after": null + } + response: + results: + - | + { + "data": { + "appointments": { + "nodes": [ + { + "id": "QXBwb2ludG1lbnQ6Mg==" + }, + { + "id": "QXBwb2ludG1lbnQ6Mw==" + }, + { + "id": "QXBwb2ludG1lbnQ6NA==" + } + ] + } + } + } +operationPlan: + operation: + - document: | + query AfterNull( + $after: String + ) { + appointments(after: $after) { + nodes { + id + } + } + } + name: AfterNull + hash: bcc834fd4621a90c14b517b1ca5aa99d + searchSpace: 1 + expandedNodes: 1 + nodes: + - id: 1 + type: Operation + schema: E + operation: | + query AfterNull_bcc834fd_1( + $after: String + ) { + appointments(after: $after) { + nodes { + id + } + } + } + forwardedVariables: + - after diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.QueryType_Parallel_Multiple_SubGraphs_WithArguments.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.QueryType_Parallel_Multiple_SubGraphs_WithArguments.yaml new file mode 100644 index 00000000000..a9198a16015 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.QueryType_Parallel_Multiple_SubGraphs_WithArguments.yaml @@ -0,0 +1,467 @@ +title: QueryType_Parallel_Multiple_SubGraphs_WithArguments +request: + document: | + query TopProducts { + topProducts(first: 5) { + weight + deliveryEstimate(zip: "12345") { + min + max + } + reviews { + body + } + } + } +response: + body: | + { + "data": { + "topProducts": [ + { + "weight": 123, + "deliveryEstimate": { + "min": 123, + "max": 123 + }, + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=" + }, + { + "body": "Review: UmV2aWV3OjI=" + }, + { + "body": "Review: UmV2aWV3OjM=" + } + ] + }, + { + "weight": 123, + "deliveryEstimate": { + "min": 123, + "max": 123 + }, + "reviews": [ + { + "body": "Review: UmV2aWV3OjQ=" + }, + { + "body": "Review: UmV2aWV3OjU=" + }, + { + "body": "Review: UmV2aWV3OjY=" + } + ] + }, + { + "weight": 123, + "deliveryEstimate": { + "min": 123, + "max": 123 + }, + "reviews": [ + { + "body": "Review: UmV2aWV3Ojc=" + }, + { + "body": "Review: UmV2aWV3Ojg=" + }, + { + "body": "Review: UmV2aWV3Ojk=" + } + ] + } + ] + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + interactions: + - request: + document: | + query TopProducts_ca09eae1_3( + $__fusion_2_id: ID! + ) { + node(id: $__fusion_2_id) { + __typename + ... on Product { + reviews { + body + } + } + } + } + variables: | + [ + { + "__fusion_2_id": "UHJvZHVjdDox" + }, + { + "__fusion_2_id": "UHJvZHVjdDoy" + }, + { + "__fusion_2_id": "UHJvZHVjdDoz" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "Product", + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=" + }, + { + "body": "Review: UmV2aWV3OjI=" + }, + { + "body": "Review: UmV2aWV3OjM=" + } + ] + } + } + } + - | + { + "data": { + "node": { + "__typename": "Product", + "reviews": [ + { + "body": "Review: UmV2aWV3OjQ=" + }, + { + "body": "Review: UmV2aWV3OjU=" + }, + { + "body": "Review: UmV2aWV3OjY=" + } + ] + } + } + } + - | + { + "data": { + "node": { + "__typename": "Product", + "reviews": [ + { + "body": "Review: UmV2aWV3Ojc=" + }, + { + "body": "Review: UmV2aWV3Ojg=" + }, + { + "body": "Review: UmV2aWV3Ojk=" + } + ] + } + } + } + - name: C + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + type RepeatDataData { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + input RepeatDataDataInput { + num: Int! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } + interactions: + - request: + document: | + query TopProducts_ca09eae1_1 { + topProducts(first: 5) { + weight + id + } + } + response: + results: + - | + { + "data": { + "topProducts": [ + { + "weight": 123, + "id": "UHJvZHVjdDox" + }, + { + "weight": 123, + "id": "UHJvZHVjdDoy" + }, + { + "weight": 123, + "id": "UHJvZHVjdDoz" + } + ] + } + } + - name: D + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type DeliveryEstimate { + min: Int! + max: Int! + } + + type Product implements Node { + id: ID! + size: Int! @shareable + weight: Int! @shareable + deliveryEstimate(size: Int weight: Int zip: String!): DeliveryEstimate! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + } + interactions: + - request: + document: | + query TopProducts_ca09eae1_2( + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on Product { + deliveryEstimate(zip: "12345") { + min + max + } + } + } + } + variables: | + [ + { + "__fusion_1_id": "UHJvZHVjdDox" + }, + { + "__fusion_1_id": "UHJvZHVjdDoy" + }, + { + "__fusion_1_id": "UHJvZHVjdDoz" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "Product", + "deliveryEstimate": { + "min": 123, + "max": 123 + } + } + } + } + - | + { + "data": { + "node": { + "__typename": "Product", + "deliveryEstimate": { + "min": 123, + "max": 123 + } + } + } + } + - | + { + "data": { + "node": { + "__typename": "Product", + "deliveryEstimate": { + "min": 123, + "max": 123 + } + } + } + } +operationPlan: + operation: + - document: | + query TopProducts { + topProducts(first: 5) { + weight + deliveryEstimate(zip: "12345") { + min + max + } + reviews { + body + } + id @fusion__requirement + } + } + name: TopProducts + hash: ca09eae12d7fcd12534855b54bb04f05 + searchSpace: 2 + expandedNodes: 5 + nodes: + - id: 1 + type: Operation + schema: C + operation: | + query TopProducts_ca09eae1_1 { + topProducts(first: 5) { + weight + id + } + } + - id: 2 + type: Operation + schema: D + operation: | + query TopProducts_ca09eae1_2( + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on Product { + deliveryEstimate(zip: "12345") { + min + max + } + } + } + } + source: $.node + target: $.topProducts + requirements: + - name: __fusion_1_id + selectionMap: >- + id + dependencies: + - id: 1 + - id: 3 + type: Operation + schema: B + operation: | + query TopProducts_ca09eae1_3( + $__fusion_2_id: ID! + ) { + node(id: $__fusion_2_id) { + __typename + ... on Product { + reviews { + body + } + } + } + } + source: $.node + target: $.topProducts + requirements: + - name: __fusion_2_id + selectionMap: >- + id + dependencies: + - id: 1 diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.yaml new file mode 100644 index 00000000000..7a88328dfa6 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.yaml @@ -0,0 +1,528 @@ +title: Require_Data_In_Context +request: + document: | + query Requires { + reviews { + body + author { + name + birthdate + } + product { + name + deliveryEstimate(zip: "12345") { + min + max + } + } + } + } +response: + body: | + { + "data": { + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=", + "author": { + "name": "User: VXNlcjo0", + "birthdate": "User: VXNlcjo0" + }, + "product": { + "name": "Product: UHJvZHVjdDo1", + "deliveryEstimate": { + "min": 123, + "max": 123 + } + } + }, + { + "body": "Review: UmV2aWV3OjI=", + "author": { + "name": "User: VXNlcjo2", + "birthdate": "User: VXNlcjo2" + }, + "product": { + "name": "Product: UHJvZHVjdDo3", + "deliveryEstimate": { + "min": 123, + "max": 123 + } + } + }, + { + "body": "Review: UmV2aWV3OjM=", + "author": { + "name": "User: VXNlcjo4", + "birthdate": "User: VXNlcjo4" + }, + "product": { + "name": "Product: UHJvZHVjdDo5", + "deliveryEstimate": { + "min": 123, + "max": 123 + } + } + } + ] + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + interactions: + - request: + document: | + query Requires_beac16b7_4( + $__fusion_3_id: ID! + ) { + node(id: $__fusion_3_id) { + __typename + ... on User { + name + birthdate + } + } + } + variables: | + [ + { + "__fusion_3_id": "VXNlcjo0" + }, + { + "__fusion_3_id": "VXNlcjo2" + }, + { + "__fusion_3_id": "VXNlcjo4" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjo0", + "birthdate": "User: VXNlcjo0" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjo2", + "birthdate": "User: VXNlcjo2" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjo4", + "birthdate": "User: VXNlcjo4" + } + } + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + interactions: + - request: + document: | + query Requires_beac16b7_1 { + reviews { + body + author { + id + } + product { + id + } + } + } + response: + results: + - | + { + "data": { + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=", + "author": { + "id": "VXNlcjo0" + }, + "product": { + "id": "UHJvZHVjdDo1" + } + }, + { + "body": "Review: UmV2aWV3OjI=", + "author": { + "id": "VXNlcjo2" + }, + "product": { + "id": "UHJvZHVjdDo3" + } + }, + { + "body": "Review: UmV2aWV3OjM=", + "author": { + "id": "VXNlcjo4" + }, + "product": { + "id": "UHJvZHVjdDo5" + } + } + ] + } + } + - name: C + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + type RepeatDataData { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + input RepeatDataDataInput { + num: Int! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } + interactions: + - request: + document: | + query Requires_beac16b7_3( + $__fusion_2_id: ID! + ) { + productById(id: $__fusion_2_id) { + name + } + } + variables: | + [ + { + "__fusion_2_id": "UHJvZHVjdDo1" + }, + { + "__fusion_2_id": "UHJvZHVjdDo3" + }, + { + "__fusion_2_id": "UHJvZHVjdDo5" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "productById": { + "name": "Product: UHJvZHVjdDo1" + } + } + } + - | + { + "data": { + "productById": { + "name": "Product: UHJvZHVjdDo3" + } + } + } + - | + { + "data": { + "productById": { + "name": "Product: UHJvZHVjdDo5" + } + } + } + - name: D + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type DeliveryEstimate { + min: Int! + max: Int! + } + + type Product implements Node { + id: ID! + size: Int! @shareable + weight: Int! @shareable + deliveryEstimate(size: Int weight: Int zip: String!): DeliveryEstimate! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + } + interactions: + - request: + document: | + query Requires_beac16b7_2( + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on Product { + deliveryEstimate(zip: "12345") { + min + max + } + } + } + } + variables: | + [ + { + "__fusion_1_id": "UHJvZHVjdDo1" + }, + { + "__fusion_1_id": "UHJvZHVjdDo3" + }, + { + "__fusion_1_id": "UHJvZHVjdDo5" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "Product", + "deliveryEstimate": { + "min": 123, + "max": 123 + } + } + } + } + - | + { + "data": { + "node": { + "__typename": "Product", + "deliveryEstimate": { + "min": 123, + "max": 123 + } + } + } + } + - | + { + "data": { + "node": { + "__typename": "Product", + "deliveryEstimate": { + "min": 123, + "max": 123 + } + } + } + } +operationPlan: + operation: + - document: | + query Requires { + reviews { + body + author { + name + birthdate + id @fusion__requirement + } + product { + name + deliveryEstimate(zip: "12345") { + min + max + } + id @fusion__requirement + } + } + } + name: Requires + hash: beac16b73cdc2003ae293980af039c1b + searchSpace: 2 + expandedNodes: 3 + nodes: + - id: 1 + type: Operation + schema: B + operation: | + query Requires_beac16b7_1 { + reviews { + body + author { + id + } + product { + id + } + } + } + - id: 2 + type: Operation + schema: D + operation: | + query Requires_beac16b7_2( + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on Product { + deliveryEstimate(zip: "12345") { + min + max + } + } + } + } + source: $.node + target: $.reviews.product + requirements: + - name: __fusion_1_id + selectionMap: >- + id + dependencies: + - id: 1 + - id: 3 + type: Operation + schema: C + operation: | + query Requires_beac16b7_3( + $__fusion_2_id: ID! + ) { + productById(id: $__fusion_2_id) { + name + } + } + source: $.productById + target: $.reviews.product + requirements: + - name: __fusion_2_id + selectionMap: >- + id + dependencies: + - id: 1 + - id: 4 + type: Operation + schema: A + operation: | + query Requires_beac16b7_4( + $__fusion_3_id: ID! + ) { + node(id: $__fusion_3_id) { + __typename + ... on User { + name + birthdate + } + } + } + source: $.node + target: $.reviews.author + requirements: + - name: __fusion_3_id + selectionMap: >- + id + dependencies: + - id: 1 diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.yaml new file mode 100644 index 00000000000..8188f271467 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.yaml @@ -0,0 +1,455 @@ +title: Require_Data_In_Context_2 +request: + document: | + query Requires { + reviews { + body + author { + name + birthdate + } + product { + deliveryEstimate(zip: "12345") { + min + max + } + } + } + } +response: + body: | + { + "data": { + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=", + "author": { + "name": "User: VXNlcjo0", + "birthdate": "User: VXNlcjo0" + }, + "product": { + "deliveryEstimate": { + "min": 123, + "max": 123 + } + } + }, + { + "body": "Review: UmV2aWV3OjI=", + "author": { + "name": "User: VXNlcjo2", + "birthdate": "User: VXNlcjo2" + }, + "product": { + "deliveryEstimate": { + "min": 123, + "max": 123 + } + } + }, + { + "body": "Review: UmV2aWV3OjM=", + "author": { + "name": "User: VXNlcjo4", + "birthdate": "User: VXNlcjo4" + }, + "product": { + "deliveryEstimate": { + "min": 123, + "max": 123 + } + } + } + ] + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + interactions: + - request: + document: | + query Requires_b3dd796a_3( + $__fusion_2_id: ID! + ) { + node(id: $__fusion_2_id) { + __typename + ... on User { + name + birthdate + } + } + } + variables: | + [ + { + "__fusion_2_id": "VXNlcjo0" + }, + { + "__fusion_2_id": "VXNlcjo2" + }, + { + "__fusion_2_id": "VXNlcjo4" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjo0", + "birthdate": "User: VXNlcjo0" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjo2", + "birthdate": "User: VXNlcjo2" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjo4", + "birthdate": "User: VXNlcjo4" + } + } + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + interactions: + - request: + document: | + query Requires_b3dd796a_1 { + reviews { + body + author { + id + } + product { + id + } + } + } + response: + results: + - | + { + "data": { + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=", + "author": { + "id": "VXNlcjo0" + }, + "product": { + "id": "UHJvZHVjdDo1" + } + }, + { + "body": "Review: UmV2aWV3OjI=", + "author": { + "id": "VXNlcjo2" + }, + "product": { + "id": "UHJvZHVjdDo3" + } + }, + { + "body": "Review: UmV2aWV3OjM=", + "author": { + "id": "VXNlcjo4" + }, + "product": { + "id": "UHJvZHVjdDo5" + } + } + ] + } + } + - name: C + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + type RepeatDataData { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + input RepeatDataDataInput { + num: Int! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } + - name: D + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type DeliveryEstimate { + min: Int! + max: Int! + } + + type Product implements Node { + id: ID! + size: Int! @shareable + weight: Int! @shareable + deliveryEstimate(size: Int weight: Int zip: String!): DeliveryEstimate! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + } + interactions: + - request: + document: | + query Requires_b3dd796a_2( + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on Product { + deliveryEstimate(zip: "12345") { + min + max + } + } + } + } + variables: | + [ + { + "__fusion_1_id": "UHJvZHVjdDo1" + }, + { + "__fusion_1_id": "UHJvZHVjdDo3" + }, + { + "__fusion_1_id": "UHJvZHVjdDo5" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "Product", + "deliveryEstimate": { + "min": 123, + "max": 123 + } + } + } + } + - | + { + "data": { + "node": { + "__typename": "Product", + "deliveryEstimate": { + "min": 123, + "max": 123 + } + } + } + } + - | + { + "data": { + "node": { + "__typename": "Product", + "deliveryEstimate": { + "min": 123, + "max": 123 + } + } + } + } +operationPlan: + operation: + - document: | + query Requires { + reviews { + body + author { + name + birthdate + id @fusion__requirement + } + product { + deliveryEstimate(zip: "12345") { + min + max + } + id @fusion__requirement + } + } + } + name: Requires + hash: b3dd796a6f5e3167e400890922f9923e + searchSpace: 1 + expandedNodes: 2 + nodes: + - id: 1 + type: Operation + schema: B + operation: | + query Requires_b3dd796a_1 { + reviews { + body + author { + id + } + product { + id + } + } + } + - id: 2 + type: Operation + schema: D + operation: | + query Requires_b3dd796a_2( + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on Product { + deliveryEstimate(zip: "12345") { + min + max + } + } + } + } + source: $.node + target: $.reviews.product + requirements: + - name: __fusion_1_id + selectionMap: >- + id + dependencies: + - id: 1 + - id: 3 + type: Operation + schema: A + operation: | + query Requires_b3dd796a_3( + $__fusion_2_id: ID! + ) { + node(id: $__fusion_2_id) { + __typename + ... on User { + name + birthdate + } + } + } + source: $.node + target: $.reviews.author + requirements: + - name: __fusion_2_id + selectionMap: >- + id + dependencies: + - id: 1 diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.yaml new file mode 100644 index 00000000000..83e0f646531 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.yaml @@ -0,0 +1,1023 @@ +title: Require_Data_In_Context_3 +request: + document: | + query Large { + users { + id + name + birthdate + reviews { + body + author { + name + birthdate + } + product { + id + name + deliveryEstimate(zip: "abc") { + max + } + } + } + } + } +response: + body: | + { + "data": { + "users": [ + { + "id": "VXNlcjox", + "name": "User: VXNlcjox", + "birthdate": "User: VXNlcjox", + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=", + "author": { + "name": "User: VXNlcjoyMg==", + "birthdate": "User: VXNlcjoyMg==" + }, + "product": { + "id": "UHJvZHVjdDoyMw==", + "name": "Product: UHJvZHVjdDoyMw==", + "deliveryEstimate": { + "max": 123 + } + } + }, + { + "body": "Review: UmV2aWV3OjI=", + "author": { + "name": "User: VXNlcjoyNA==", + "birthdate": "User: VXNlcjoyNA==" + }, + "product": { + "id": "UHJvZHVjdDoyNQ==", + "name": "Product: UHJvZHVjdDoyNQ==", + "deliveryEstimate": { + "max": 123 + } + } + }, + { + "body": "Review: UmV2aWV3OjM=", + "author": { + "name": "User: VXNlcjoyNg==", + "birthdate": "User: VXNlcjoyNg==" + }, + "product": { + "id": "UHJvZHVjdDoyNw==", + "name": "Product: UHJvZHVjdDoyNw==", + "deliveryEstimate": { + "max": 123 + } + } + } + ] + }, + { + "id": "VXNlcjoy", + "name": "User: VXNlcjoy", + "birthdate": "User: VXNlcjoy", + "reviews": [ + { + "body": "Review: UmV2aWV3OjQ=", + "author": { + "name": "User: VXNlcjoxNg==", + "birthdate": "User: VXNlcjoxNg==" + }, + "product": { + "id": "UHJvZHVjdDoxNw==", + "name": "Product: UHJvZHVjdDoxNw==", + "deliveryEstimate": { + "max": 123 + } + } + }, + { + "body": "Review: UmV2aWV3OjU=", + "author": { + "name": "User: VXNlcjoxOA==", + "birthdate": "User: VXNlcjoxOA==" + }, + "product": { + "id": "UHJvZHVjdDoxOQ==", + "name": "Product: UHJvZHVjdDoxOQ==", + "deliveryEstimate": { + "max": 123 + } + } + }, + { + "body": "Review: UmV2aWV3OjY=", + "author": { + "name": "User: VXNlcjoyMA==", + "birthdate": "User: VXNlcjoyMA==" + }, + "product": { + "id": "UHJvZHVjdDoyMQ==", + "name": "Product: UHJvZHVjdDoyMQ==", + "deliveryEstimate": { + "max": 123 + } + } + } + ] + }, + { + "id": "VXNlcjoz", + "name": "User: VXNlcjoz", + "birthdate": "User: VXNlcjoz", + "reviews": [ + { + "body": "Review: UmV2aWV3Ojc=", + "author": { + "name": "User: VXNlcjoxMA==", + "birthdate": "User: VXNlcjoxMA==" + }, + "product": { + "id": "UHJvZHVjdDoxMQ==", + "name": "Product: UHJvZHVjdDoxMQ==", + "deliveryEstimate": { + "max": 123 + } + } + }, + { + "body": "Review: UmV2aWV3Ojg=", + "author": { + "name": "User: VXNlcjoxMg==", + "birthdate": "User: VXNlcjoxMg==" + }, + "product": { + "id": "UHJvZHVjdDoxMw==", + "name": "Product: UHJvZHVjdDoxMw==", + "deliveryEstimate": { + "max": 123 + } + } + }, + { + "body": "Review: UmV2aWV3Ojk=", + "author": { + "name": "User: VXNlcjoxNA==", + "birthdate": "User: VXNlcjoxNA==" + }, + "product": { + "id": "UHJvZHVjdDoxNQ==", + "name": "Product: UHJvZHVjdDoxNQ==", + "deliveryEstimate": { + "max": 123 + } + } + } + ] + } + ] + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + interactions: + - request: + document: | + query Large_62d57bc0_1 { + users { + id + name + birthdate + } + } + response: + results: + - | + { + "data": { + "users": [ + { + "id": "VXNlcjox", + "name": "User: VXNlcjox", + "birthdate": "User: VXNlcjox" + }, + { + "id": "VXNlcjoy", + "name": "User: VXNlcjoy", + "birthdate": "User: VXNlcjoy" + }, + { + "id": "VXNlcjoz", + "name": "User: VXNlcjoz", + "birthdate": "User: VXNlcjoz" + } + ] + } + } + - request: + document: | + query Large_62d57bc0_5( + $__fusion_4_id: ID! + ) { + node(id: $__fusion_4_id) { + __typename + ... on User { + name + birthdate + } + } + } + variables: | + [ + { + "__fusion_4_id": "VXNlcjoyMg==" + }, + { + "__fusion_4_id": "VXNlcjoyNA==" + }, + { + "__fusion_4_id": "VXNlcjoyNg==" + }, + { + "__fusion_4_id": "VXNlcjoxNg==" + }, + { + "__fusion_4_id": "VXNlcjoxOA==" + }, + { + "__fusion_4_id": "VXNlcjoyMA==" + }, + { + "__fusion_4_id": "VXNlcjoxMA==" + }, + { + "__fusion_4_id": "VXNlcjoxMg==" + }, + { + "__fusion_4_id": "VXNlcjoxNA==" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoyMg==", + "birthdate": "User: VXNlcjoyMg==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoyNA==", + "birthdate": "User: VXNlcjoyNA==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoyNg==", + "birthdate": "User: VXNlcjoyNg==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxNg==", + "birthdate": "User: VXNlcjoxNg==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxOA==", + "birthdate": "User: VXNlcjoxOA==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoyMA==", + "birthdate": "User: VXNlcjoyMA==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMA==", + "birthdate": "User: VXNlcjoxMA==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxMg==", + "birthdate": "User: VXNlcjoxMg==" + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "name": "User: VXNlcjoxNA==", + "birthdate": "User: VXNlcjoxNA==" + } + } + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + interactions: + - request: + document: | + query Large_62d57bc0_2( + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on User { + reviews { + body + author { + id + } + product { + id + } + } + } + } + } + variables: | + [ + { + "__fusion_1_id": "VXNlcjox" + }, + { + "__fusion_1_id": "VXNlcjoy" + }, + { + "__fusion_1_id": "VXNlcjoz" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "User", + "reviews": [ + { + "body": "Review: UmV2aWV3OjE=", + "author": { + "id": "VXNlcjoyMg==" + }, + "product": { + "id": "UHJvZHVjdDoyMw==" + } + }, + { + "body": "Review: UmV2aWV3OjI=", + "author": { + "id": "VXNlcjoyNA==" + }, + "product": { + "id": "UHJvZHVjdDoyNQ==" + } + }, + { + "body": "Review: UmV2aWV3OjM=", + "author": { + "id": "VXNlcjoyNg==" + }, + "product": { + "id": "UHJvZHVjdDoyNw==" + } + } + ] + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "reviews": [ + { + "body": "Review: UmV2aWV3OjQ=", + "author": { + "id": "VXNlcjoxNg==" + }, + "product": { + "id": "UHJvZHVjdDoxNw==" + } + }, + { + "body": "Review: UmV2aWV3OjU=", + "author": { + "id": "VXNlcjoxOA==" + }, + "product": { + "id": "UHJvZHVjdDoxOQ==" + } + }, + { + "body": "Review: UmV2aWV3OjY=", + "author": { + "id": "VXNlcjoyMA==" + }, + "product": { + "id": "UHJvZHVjdDoyMQ==" + } + } + ] + } + } + } + - | + { + "data": { + "node": { + "__typename": "User", + "reviews": [ + { + "body": "Review: UmV2aWV3Ojc=", + "author": { + "id": "VXNlcjoxMA==" + }, + "product": { + "id": "UHJvZHVjdDoxMQ==" + } + }, + { + "body": "Review: UmV2aWV3Ojg=", + "author": { + "id": "VXNlcjoxMg==" + }, + "product": { + "id": "UHJvZHVjdDoxMw==" + } + }, + { + "body": "Review: UmV2aWV3Ojk=", + "author": { + "id": "VXNlcjoxNA==" + }, + "product": { + "id": "UHJvZHVjdDoxNQ==" + } + } + ] + } + } + } + - name: C + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + type RepeatDataData { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + input RepeatDataDataInput { + num: Int! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } + interactions: + - request: + document: | + query Large_62d57bc0_4( + $__fusion_3_id: ID! + ) { + productById(id: $__fusion_3_id) { + name + } + } + variables: | + [ + { + "__fusion_3_id": "UHJvZHVjdDoyMw==" + }, + { + "__fusion_3_id": "UHJvZHVjdDoyNQ==" + }, + { + "__fusion_3_id": "UHJvZHVjdDoyNw==" + }, + { + "__fusion_3_id": "UHJvZHVjdDoxNw==" + }, + { + "__fusion_3_id": "UHJvZHVjdDoxOQ==" + }, + { + "__fusion_3_id": "UHJvZHVjdDoyMQ==" + }, + { + "__fusion_3_id": "UHJvZHVjdDoxMQ==" + }, + { + "__fusion_3_id": "UHJvZHVjdDoxMw==" + }, + { + "__fusion_3_id": "UHJvZHVjdDoxNQ==" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "productById": { + "name": "Product: UHJvZHVjdDoyMw==" + } + } + } + - | + { + "data": { + "productById": { + "name": "Product: UHJvZHVjdDoyNQ==" + } + } + } + - | + { + "data": { + "productById": { + "name": "Product: UHJvZHVjdDoyNw==" + } + } + } + - | + { + "data": { + "productById": { + "name": "Product: UHJvZHVjdDoxNw==" + } + } + } + - | + { + "data": { + "productById": { + "name": "Product: UHJvZHVjdDoxOQ==" + } + } + } + - | + { + "data": { + "productById": { + "name": "Product: UHJvZHVjdDoyMQ==" + } + } + } + - | + { + "data": { + "productById": { + "name": "Product: UHJvZHVjdDoxMQ==" + } + } + } + - | + { + "data": { + "productById": { + "name": "Product: UHJvZHVjdDoxMw==" + } + } + } + - | + { + "data": { + "productById": { + "name": "Product: UHJvZHVjdDoxNQ==" + } + } + } + - name: D + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type DeliveryEstimate { + min: Int! + max: Int! + } + + type Product implements Node { + id: ID! + size: Int! @shareable + weight: Int! @shareable + deliveryEstimate(size: Int weight: Int zip: String!): DeliveryEstimate! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + } + interactions: + - request: + document: | + query Large_62d57bc0_3( + $__fusion_2_id: ID! + ) { + node(id: $__fusion_2_id) { + __typename + ... on Product { + deliveryEstimate(zip: "abc") { + max + } + } + } + } + variables: | + [ + { + "__fusion_2_id": "UHJvZHVjdDoyMw==" + }, + { + "__fusion_2_id": "UHJvZHVjdDoyNQ==" + }, + { + "__fusion_2_id": "UHJvZHVjdDoyNw==" + }, + { + "__fusion_2_id": "UHJvZHVjdDoxNw==" + }, + { + "__fusion_2_id": "UHJvZHVjdDoxOQ==" + }, + { + "__fusion_2_id": "UHJvZHVjdDoyMQ==" + }, + { + "__fusion_2_id": "UHJvZHVjdDoxMQ==" + }, + { + "__fusion_2_id": "UHJvZHVjdDoxMw==" + }, + { + "__fusion_2_id": "UHJvZHVjdDoxNQ==" + } + ] + response: + contentType: application/jsonl; charset=utf-8 + results: + - | + { + "data": { + "node": { + "__typename": "Product", + "deliveryEstimate": { + "max": 123 + } + } + } + } + - | + { + "data": { + "node": { + "__typename": "Product", + "deliveryEstimate": { + "max": 123 + } + } + } + } + - | + { + "data": { + "node": { + "__typename": "Product", + "deliveryEstimate": { + "max": 123 + } + } + } + } + - | + { + "data": { + "node": { + "__typename": "Product", + "deliveryEstimate": { + "max": 123 + } + } + } + } + - | + { + "data": { + "node": { + "__typename": "Product", + "deliveryEstimate": { + "max": 123 + } + } + } + } + - | + { + "data": { + "node": { + "__typename": "Product", + "deliveryEstimate": { + "max": 123 + } + } + } + } + - | + { + "data": { + "node": { + "__typename": "Product", + "deliveryEstimate": { + "max": 123 + } + } + } + } + - | + { + "data": { + "node": { + "__typename": "Product", + "deliveryEstimate": { + "max": 123 + } + } + } + } + - | + { + "data": { + "node": { + "__typename": "Product", + "deliveryEstimate": { + "max": 123 + } + } + } + } +operationPlan: + operation: + - document: | + query Large { + users { + id + id @fusion__requirement + name + birthdate + reviews { + body + author { + name + birthdate + id @fusion__requirement + } + product { + id + id @fusion__requirement + name + deliveryEstimate(zip: "abc") { + max + } + } + } + } + } + name: Large + hash: 62d57bc09d841d72c3b2971bc4f29f40 + searchSpace: 2 + expandedNodes: 4 + nodes: + - id: 1 + type: Operation + schema: A + operation: | + query Large_62d57bc0_1 { + users { + id + name + birthdate + } + } + - id: 2 + type: Operation + schema: B + operation: | + query Large_62d57bc0_2( + $__fusion_1_id: ID! + ) { + node(id: $__fusion_1_id) { + __typename + ... on User { + reviews { + body + author { + id + } + product { + id + } + } + } + } + } + source: $.node + target: $.users + requirements: + - name: __fusion_1_id + selectionMap: >- + id + dependencies: + - id: 1 + - id: 3 + type: Operation + schema: D + operation: | + query Large_62d57bc0_3( + $__fusion_2_id: ID! + ) { + node(id: $__fusion_2_id) { + __typename + ... on Product { + deliveryEstimate(zip: "abc") { + max + } + } + } + } + source: $.node + target: $.users.reviews.product + requirements: + - name: __fusion_2_id + selectionMap: >- + id + dependencies: + - id: 2 + - id: 4 + type: Operation + schema: C + operation: | + query Large_62d57bc0_4( + $__fusion_3_id: ID! + ) { + productById(id: $__fusion_3_id) { + name + } + } + source: $.productById + target: $.users.reviews.product + requirements: + - name: __fusion_3_id + selectionMap: >- + id + dependencies: + - id: 2 + - id: 5 + type: Operation + schema: A + operation: | + query Large_62d57bc0_5( + $__fusion_4_id: ID! + ) { + node(id: $__fusion_4_id) { + __typename + ... on User { + name + birthdate + } + } + } + source: $.node + target: $.users.reviews.author + requirements: + - name: __fusion_4_id + selectionMap: >- + id + dependencies: + - id: 2 diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Two_Arguments_Differing_Nullability_Does_Not_Duplicate_Forwarded_Variables.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Two_Arguments_Differing_Nullability_Does_Not_Duplicate_Forwarded_Variables.yaml new file mode 100644 index 00000000000..5c1d4134719 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.Two_Arguments_Differing_Nullability_Does_Not_Duplicate_Forwarded_Variables.yaml @@ -0,0 +1,88 @@ +title: Two_Arguments_Differing_Nullability_Does_Not_Duplicate_Forwarded_Variables +request: + document: | + query Test( + $number: Int! + ) { + testWithTwoArgumentsDifferingNullability(first: $number, second: $number) + } + variables: | + { + "number": 1 + } +response: + body: | + { + "data": { + "testWithTwoArgumentsDifferingNullability": "Query" + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + interactions: + - request: + document: | + query Test_2ead4419_1( + $number: Int! + ) { + testWithTwoArgumentsDifferingNullability(first: $number, second: $number) + } + variables: | + { + "number": 1 + } + response: + results: + - | + { + "data": { + "testWithTwoArgumentsDifferingNullability": "Query" + } + } +operationPlan: + operation: + - document: | + query Test( + $number: Int! + ) { + testWithTwoArgumentsDifferingNullability(first: $number, second: $number) + } + name: Test + hash: 2ead4419dfb56bb66a60503178451950 + searchSpace: 1 + expandedNodes: 1 + nodes: + - id: 1 + type: Operation + schema: A + operation: | + query Test_2ead4419_1( + $number: Int! + ) { + testWithTwoArgumentsDifferingNullability(first: $number, second: $number) + } + forwardedVariables: + - number diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.TypeName_Field_On_QueryRoot.yaml b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.TypeName_Field_On_QueryRoot.yaml new file mode 100644 index 00000000000..be7ac585e51 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.AspNetCore.Tests/v15/__snapshots__/DemoIntegrationTests.TypeName_Field_On_QueryRoot.yaml @@ -0,0 +1,130 @@ +title: TypeName_Field_On_QueryRoot +request: + document: | + query Introspect { + __typename + } +response: + body: | + { + "data": { + "__typename": "Query" + } + } +sourceSchemas: + - name: A + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + userById(id: ID!): User! + users: [User!]! + testWithTwoArgumentsDifferingNullability(first: Int! second: Int): String! + } + + type User implements Node { + id: ID! + name: String! + username: String! + birthdate: String! + } + - name: B + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + reviews: [Review!]! + reviewCount: Int! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + reviews: [Review!]! + } + + type Review implements Node { + id: ID! + body: String! + author: User! + product: Product! + } + + type User implements Node { + id: ID! + reviews: [Review!]! + errorField: String @error + } + - name: C + schema: | + schema { + query: Query + } + + interface Node { + id: ID! + } + + type Product implements Node { + id: ID! + name: String! + size: Int! @shareable + weight: Int! @shareable + repeat(num: Int!): String! + repeatData(data: RepeatDataInput!): RepeatDataPayload! + } + + type Query { + node(id: ID!): Node @lookup @shareable + nodes(ids: [ID!]!): [Node]! @shareable + productById(id: ID!): Product @lookup @shareable + topProducts(first: Int!): [Product!]! + } + + type RepeatDataData { + num: Int! + } + + type RepeatDataPayload { + data: RepeatDataData! + } + + input RepeatDataDataInput { + num: Int! + } + + input RepeatDataInput { + data: RepeatDataDataInput! + } +operationPlan: + operation: + - document: | + query Introspect { + __typename + } + name: Introspect + hash: e470e03449f5c5ce58bd96634fc2c006 + searchSpace: 1 + expandedNodes: 1 + nodes: + - id: 1 + type: Introspection + selections: + - id: 2 + responseName: __typename + fieldName: __typename