diff --git a/src/HotChocolate/Fusion/src/Core/Metadata/ResolverDefinition.FetchRewriterContext.cs b/src/HotChocolate/Fusion/src/Core/Metadata/ResolverDefinition.FetchRewriterContext.cs index 4fa26741f36..62cf40a5ded 100644 --- a/src/HotChocolate/Fusion/src/Core/Metadata/ResolverDefinition.FetchRewriterContext.cs +++ b/src/HotChocolate/Fusion/src/Core/Metadata/ResolverDefinition.FetchRewriterContext.cs @@ -9,7 +9,8 @@ private sealed class FetchRewriterContext( IReadOnlyDictionary variables, SelectionSetNode? selectionSet, string? responseName, - IReadOnlyList? unspecifiedArguments) + IReadOnlyList? unspecifiedArguments, + IReadOnlyList? directives) { public string? ResponseName { get; } = responseName; @@ -26,6 +27,8 @@ private sealed class FetchRewriterContext( /// public IReadOnlyList? UnspecifiedArguments { get; } = unspecifiedArguments; + public IReadOnlyList? Directives { get; } = directives; + public SelectionSetNode? SelectionSet { get; } = selectionSet; public IReadOnlyList SelectionPath { get; set; } = Array.Empty(); diff --git a/src/HotChocolate/Fusion/src/Core/Metadata/ResolverDefinition.ResolverRewriter.cs b/src/HotChocolate/Fusion/src/Core/Metadata/ResolverDefinition.ResolverRewriter.cs index 66c484c9f8c..6c5014e2146 100644 --- a/src/HotChocolate/Fusion/src/Core/Metadata/ResolverDefinition.ResolverRewriter.cs +++ b/src/HotChocolate/Fusion/src/Core/Metadata/ResolverDefinition.ResolverRewriter.cs @@ -17,6 +17,11 @@ private class ResolverRewriter : SyntaxRewriter return null; } + if (context.Directives?.Count > 0) + { + result = result.WithDirectives(context.Directives); + } + if (context.UnspecifiedArguments?.Count > 0) { var explicitlyDefinedArguments = result.Arguments diff --git a/src/HotChocolate/Fusion/src/Core/Metadata/ResolverDefinition.cs b/src/HotChocolate/Fusion/src/Core/Metadata/ResolverDefinition.cs index e14c50059e6..adec2845af9 100644 --- a/src/HotChocolate/Fusion/src/Core/Metadata/ResolverDefinition.cs +++ b/src/HotChocolate/Fusion/src/Core/Metadata/ResolverDefinition.cs @@ -1,3 +1,4 @@ +using HotChocolate.Execution.Processing; using HotChocolate.Language; using static HotChocolate.Fusion.FusionResources; @@ -48,15 +49,17 @@ public ResolverDefinition( /// /// Gets the argument target types of this resolver. /// - public IReadOnlyDictionary ArgumentTypes { get; } + public IReadOnlyDictionary ArgumentTypes { get; } public (ISelectionNode selectionNode, IReadOnlyList Path) CreateSelection( IReadOnlyDictionary variables, SelectionSetNode? selectionSet, string? responseName, - IReadOnlyList? unspecifiedArguments) + IReadOnlyList? unspecifiedArguments, + IReadOnlyList? directives) { - var context = new FetchRewriterContext(Placeholder, variables, selectionSet, responseName, unspecifiedArguments); + var context = new FetchRewriterContext(Placeholder, variables, selectionSet, responseName, unspecifiedArguments, + directives); var selection = _rewriter.Rewrite(_field ?? (ISyntaxNode)Select, context); if (Placeholder is null && selectionSet is not null) diff --git a/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/NodeRequestDocumentFormatter.cs b/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/NodeRequestDocumentFormatter.cs index 9f9792f65f9..63ad94a0760 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/NodeRequestDocumentFormatter.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/NodeRequestDocumentFormatter.cs @@ -91,7 +91,8 @@ private SelectionSetNode CreateRootSelectionSetNode( context.VariableValues, selectionSetNode, nodeSelection.Selection.ResponseName, - null); + null, + nodeSelection.Selection.SyntaxNode.Directives); if (selectionNode is FieldNode fieldNode && !nodeSelection.Selection.ResponseName.EqualsOrdinal(fieldNode.Name.Value)) diff --git a/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs b/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs index 9186e10821c..399fae4691a 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs @@ -51,7 +51,8 @@ internal RequestDocument CreateRequestDocument( context.VariableValues, rootSelectionSetNode, null, - unspecifiedArguments); + unspecifiedArguments, + null); rootSelectionSetNode = new SelectionSetNode(new[] { rootResolver, }); path = p; @@ -62,6 +63,7 @@ internal RequestDocument CreateRequestDocument( executionStep.ParentSelectionPath is not null) { rootSelectionSetNode = CreateRootLevelQuery( + context, executionStep.ParentSelectionPath, rootSelectionSetNode); } @@ -83,6 +85,7 @@ internal RequestDocument CreateRequestDocument( } private SelectionSetNode CreateRootLevelQuery( + QueryPlanContext context, SelectionPath path, SelectionSetNode selectionSet) { @@ -90,8 +93,29 @@ private SelectionSetNode CreateRootLevelQuery( while (current is not null) { - selectionSet = new SelectionSetNode( - new[] { current.Selection.SyntaxNode.WithSelectionSet(selectionSet), }); + var selectionNode = current.Selection.SyntaxNode.WithSelectionSet(selectionSet); + + // TODO: this is not good but will fix the include issue ... + // we need to rework the operation compiler for a proper fix. + if (selectionNode.Directives.Count > 0) + { + foreach (var directive in selectionNode.Directives) + { + foreach (var argument in directive.Arguments) + { + if (argument.Value is not VariableNode variable) + { + continue; + } + + var originalVarDef = context.Operation.Definition.VariableDefinitions + .First(t => t.Variable.Equals(variable, SyntaxComparison.Syntax)); + context.ForwardedVariables.Add(originalVarDef); + } + } + } + + selectionSet = new SelectionSetNode(new[] { selectionNode, }); current = current.Parent; } @@ -164,7 +188,8 @@ protected virtual SelectionSetNode CreateRootSelectionSetNode( context.VariableValues, selectionSetNode, rootSelection.Selection.ResponseName, - unspecifiedArguments); + unspecifiedArguments, + rootSelection.Selection.SyntaxNode.Directives); selectionNode = s; } @@ -175,6 +200,26 @@ protected virtual SelectionSetNode CreateRootSelectionSetNode( new NameNode(rootSelection.Selection.ResponseName)); } + // TODO: this is not good but will fix the include issue ... + // we need to rework the operation compiler for a proper fix. + if (selectionNode.Directives.Count > 0) + { + foreach (var directive in selectionNode.Directives) + { + foreach (var argument in directive.Arguments) + { + if (argument.Value is not VariableNode variable) + { + continue; + } + + var originalVarDef = context.Operation.Definition.VariableDefinitions + .First(t => t.Variable.Equals(variable, SyntaxComparison.Syntax)); + context.ForwardedVariables.Add(originalVarDef); + } + } + } + selectionNodes.Add(selectionNode); } diff --git a/src/HotChocolate/Fusion/test/Core.Tests/SkipTests.cs b/src/HotChocolate/Fusion/test/Core.Tests/SkipTests.cs new file mode 100644 index 00000000000..5e4526ba4bf --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/SkipTests.cs @@ -0,0 +1,2610 @@ +using HotChocolate.Execution; +using HotChocolate.Fusion.Shared; +using Xunit.Abstractions; +using static HotChocolate.Fusion.TestHelper; + +namespace HotChocolate.Fusion; + +public class SkipTests(ITestOutputHelper output) +{ + #region EntityResolver + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task EntityResolver_Skip_On_EntityResolver(bool skip) + { + // arrange + var subgraph = await TestSubgraph.CreateAsync( + """ + type Query { + productById(id: ID!): Product + } + + type Product implements Node { + id: ID! + name: String! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraph]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + productById(id: "1") @skip(if: $skip) { + id + name + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + if (skip) + { + Assert.False(subgraph.HasReceivedRequest); + } + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task EntityResolver_Skip_On_EntityResolver_Other_RootField_Selected(bool skip) + { + // arrange + var subgraph = await TestSubgraph.CreateAsync( + """ + type Query { + productById(id: ID!): Product + other: String + } + + type Product implements Node { + id: ID! + name: String! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraph]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + productById(id: "1") @skip(if: $skip) { + id + name + } + other + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task EntityResolver_Skip_On_EntityResolver_Fragment(bool skip) + { + // arrange + var subgraph = await TestSubgraph.CreateAsync( + """ + type Query { + productById(id: ID!): Product + } + + type Product implements Node { + id: ID! + name: String! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraph]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + ...Test @skip(if: $skip) + } + + fragment Test on Query { + productById(id: "1") { + id + name + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + if (skip) + { + Assert.False(subgraph.HasReceivedRequest); + } + } + + [Theory] + [InlineData(true, Skip = "@skip isn't forwarded correctly")] + [InlineData(false)] + public async Task EntityResolver_Skip_On_EntityResolver_Fragment_Other_RootField_Selected(bool skip) + { + // arrange + var subgraph = await TestSubgraph.CreateAsync( + """ + type Query { + productById(id: ID!): Product + other: String + } + + type Product implements Node { + id: ID! + name: String! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraph]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + ...Test @skip(if: $skip) + other + } + + fragment Test on Query { + productById(id: "1") { + id + name + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task EntityResolver_Skip_On_EntityResolver_Fragment_EntityResolver_Selected_Separately(bool skip) + { + // arrange + var subgraph = await TestSubgraph.CreateAsync( + """ + type Query { + productById(id: ID!): Product + } + + type Product implements Node { + id: ID! + name: String! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraph]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + ...Test @skip(if: $skip) + productById(id: "1") { + id + name + } + } + + fragment Test on Query { + productById(id: "1") { + id + name + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task EntityResolver_Skip_On_SubField(bool skip) + { + // arrange + var subgraph = await TestSubgraph.CreateAsync( + """ + type Query { + productById(id: ID!): Product + } + + type Product implements Node { + id: ID! + name: String! + price: Float! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraph]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + productById(id: "1") { + name @skip(if: $skip) + price + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + } + + [Theory] + [InlineData(true, Skip = "@skip isn't forwarded correctly")] + [InlineData(false)] + public async Task EntityResolver_Skip_On_SubField_Fragment(bool skip) + { + // arrange + var subgraph = await TestSubgraph.CreateAsync( + """ + type Query { + productById(id: ID!): Product + } + + type Product implements Node { + id: ID! + name: String! + price: Float! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraph]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + productById(id: "1") { + ...Test @skip(if: $skip) + price + } + } + + fragment Test on Product { + name + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task EntityResolver_Skip_On_SubField_Fragment_SubField_Selected_Separately(bool skip) + { + // arrange + var subgraph = await TestSubgraph.CreateAsync( + """ + type Query { + productById(id: ID!): Product + } + + type Product implements Node { + id: ID! + name: String! + price: Float! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraph]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + productById(id: "1") { + ...Test @skip(if: $skip) + name + price + } + } + + fragment Test on Product { + name + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result); + } + + #endregion + + #region Parallel Resolve + + [Theory] + [InlineData(true, Skip = "Subgraph unnecessarily called")] + [InlineData(false)] + public async Task Parallel_Resolve_Skip_On_EntryField(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + other: Other! + } + + type Other { + userId: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + viewer { + name + } + other @skip(if: $skip) { + userId + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + if (skip) + { + Assert.False(subgraphB.HasReceivedRequest); + } + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task Parallel_Resolve_Skip_On_EntryField_Other_RootField_Selected(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + other: Other! + another: String + } + + type Other { + userId: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + viewer { + name + } + other @skip(if: $skip) { + userId + } + another + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + } + + [Theory] + [InlineData(true, Skip = "Subgraph unnecessarily called")] + [InlineData(false)] + public async Task Parallel_Resolve_Skip_On_EntryField_Fragment(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + other: Other! + } + + type Other { + userId: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + viewer { + name + } + ...Test @skip(if: $skip) + } + + fragment Test on Query { + other { + userId + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + if (skip) + { + Assert.False(subgraphB.HasReceivedRequest); + } + } + + [Theory] + [InlineData(true, Skip = "@skip isn't forwarded correctly")] + [InlineData(false)] + public async Task Parallel_Resolve_Skip_On_EntryField_Fragment_Other_RootField_Selected(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + other: Other! + another: String + } + + type Other { + userId: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + viewer { + name + } + ...Test @skip(if: $skip) + another + } + + fragment Test on Query { + other { + userId + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task Parallel_Resolve_Skip_On_EntryField_Fragment_EntryField_Selected_Separately(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + other: Other! + } + + type Other { + userId: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + viewer { + name + } + other { + userId + } + ...Test @skip(if: $skip) + } + + fragment Test on Query { + other { + userId + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task Parallel_Resolve_Skip_On_SubField(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + other: Other! + } + + type Other { + userId: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + viewer { + name + } + other { + userId @skip(if: $skip) + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + } + + [Theory] + [InlineData(true, Skip = "@skip isn't forwarded correctly")] + [InlineData(false)] + public async Task Parallel_Resolve_Skip_On_SubField_Fragment(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + other: Other! + } + + type Other { + userId: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + viewer { + name + } + other { + ...Test @skip(if: $skip) + } + } + + fragment Test on Other { + userId + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task Parallel_Resolve_Skip_On_SubField_Fragment_SubField_Selected_Separately(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + other: Other! + } + + type Other { + userId: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + viewer { + name + } + other { + userId + ...Test @skip(if: $skip) + } + } + + fragment Test on Other { + userId + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result); + } + + #endregion + + #region Parallel Resolve - Shared Entry Field + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task Parallel_Resolve_SharedEntryField_Skip_On_EntryField(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + userId: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + viewer @skip(if: $skip) { + userId + name + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + if (skip) + { + Assert.False(subgraphA.HasReceivedRequest); + Assert.False(subgraphB.HasReceivedRequest); + } + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Other_RootField_Selected(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + other: String + } + + type Viewer { + userId: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + viewer @skip(if: $skip) { + userId + name + } + other + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + if (skip) + { + Assert.False(subgraphA.HasReceivedRequest); + } + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + userId: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + ...Test @skip(if: $skip) + } + + fragment Test on Query { + viewer { + userId + name + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + if (skip) + { + Assert.False(subgraphA.HasReceivedRequest); + Assert.False(subgraphB.HasReceivedRequest); + } + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_Other_RootField_Selected(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + other: String + } + + type Viewer { + userId: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + ...Test @skip(if: $skip) + other + } + + fragment Test on Query { + viewer { + userId + name + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + if (skip) + { + Assert.False(subgraphA.HasReceivedRequest); + } + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task + Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_EntryField_Selected_Separately(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + userId: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + ...Test @skip(if: $skip) + viewer { + userId + name + } + } + + fragment Test on Query { + viewer { + userId + name + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result); + } + + [Theory] + [InlineData(true, Skip = "Not sure what correct behavior would be")] + [InlineData(false)] + public async Task + Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_EntryField_Partially_Selected_Separately( + bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + userId: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + ...Test @skip(if: $skip) + viewer { + name + } + } + + fragment Test on Query { + viewer { + userId + name + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + if (skip) + { + Assert.False(subgraphB.HasReceivedRequest); + } + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task Parallel_Resolve_SharedEntryField_Skip_On_SubField(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + userId: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + viewer { + userId @skip(if: $skip) + name + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + } + + [Theory] + [InlineData(true, Skip = "Not sure what correct behavior would be")] + [InlineData(false)] + public async Task Parallel_Resolve_SharedEntryField_Skip_On_SubField_Fragment(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + userId: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + viewer { + ...Test @skip(if: $skip) + name + } + } + + fragment Test on Viewer { + userId + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + if (skip) + { + Assert.False(subgraphB.HasReceivedRequest); + } + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task Parallel_Resolve_SharedEntryField_Skip_On_SubField_Fragment_SubField_Selected_Separately( + bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + viewer: Viewer! + } + + type Viewer { + userId: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + viewer { + ...Test @skip(if: $skip) + userId + name + } + } + + fragment Test on Viewer { + userId + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result); + } + + #endregion + + #region Resolve Sequence + + [Theory] + [InlineData(true, Skip = "Subgraph unnecessarily called")] + [InlineData(false)] + public async Task Resolve_Sequence_Skip_On_RootField(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + product: Product + } + + type Product { + id: ID! + brand: Brand! + } + + type Brand { + id: ID! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + brandById(id: ID!): Brand + } + + type Brand implements Node { + id: ID! + name: String! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + product @skip(if: $skip) { + id + brand { + id + name + } + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + if (skip) + { + Assert.False(subgraphA.HasReceivedRequest); + Assert.False(subgraphB.HasReceivedRequest); + } + } + + [Theory] + [InlineData(true, Skip = "Subgraph unnecessarily called")] + [InlineData(false)] + public async Task Resolve_Sequence_Skip_On_RootField_Fragment(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + product: Product + } + + type Product { + id: ID! + brand: Brand! + } + + type Brand { + id: ID! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + brandById(id: ID!): Brand + } + + type Brand implements Node { + id: ID! + name: String! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + ...Test @skip(if: $skip) + } + + fragment Test on Query { + product { + id + brand { + id + name + } + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + if (skip) + { + Assert.False(subgraphA.HasReceivedRequest); + Assert.False(subgraphB.HasReceivedRequest); + } + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task Resolve_Sequence_Skip_On_RootField_Other_RootField_Selected(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + product: Product + other: String + } + + type Product { + id: ID! + brand: Brand! + } + + type Brand { + id: ID! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + brandById(id: ID!): Brand + } + + type Brand implements Node { + id: ID! + name: String! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + product @skip(if: $skip) { + id + brand { + id + name + } + } + other + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + if (skip) + { + Assert.False(subgraphB.HasReceivedRequest); + } + } + + [Theory] + [InlineData(true, Skip = "@skip isn't forwarded correctly")] + [InlineData(false)] + public async Task Resolve_Sequence_Skip_On_RootField_Fragment_Other_RootField_Selected(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + product: Product + other: String + } + + type Product { + id: ID! + brand: Brand! + } + + type Brand { + id: ID! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + brandById(id: ID!): Brand + } + + type Brand implements Node { + id: ID! + name: String! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + ...Test @skip(if: $skip) + other + } + + fragment Test on Query { + product { + id + brand { + id + name + } + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + if (skip) + { + Assert.False(subgraphB.HasReceivedRequest); + } + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task Resolve_Sequence_Skip_On_EntryField(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + product: Product + } + + type Product { + id: ID! + brand: Brand! + } + + type Brand { + id: ID! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + brandById(id: ID!): Brand + } + + type Brand implements Node { + id: ID! + name: String! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + product { + id + brand @skip(if: $skip) { + id + name + } + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + if (skip) + { + Assert.False(subgraphB.HasReceivedRequest); + } + } + + [Theory] + [InlineData(true, Skip = "@skip isn't forwarded correctly")] + [InlineData(false)] + public async Task Resolve_Sequence_Skip_On_EntryField_Fragment(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + product: Product + } + + type Product { + id: ID! + brand: Brand! + } + + type Brand { + id: ID! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + brandById(id: ID!): Brand + } + + type Brand implements Node { + id: ID! + name: String! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + product { + id + ...Test @skip(if: $skip) + } + } + + fragment Test on Product { + brand { + id + name + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + if (skip) + { + Assert.False(subgraphB.HasReceivedRequest); + } + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task Resolve_Sequence_Skip_On_EntryField_Other_Field_Selected(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + product: Product + } + + type Product { + id: ID! + brand: Brand! + } + + type Brand { + id: ID! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + brandById(id: ID!): Bran + productById(id: ID!): Product + } + + type Product implements Node { + id: ID! + other: String! + } + + type Brand implements Node { + id: ID! + name: String! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + product { + id + brand @skip(if: $skip) { + id + name + } + other + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + } + + [Theory] + [InlineData(true, Skip = "@skip isn't forwarded correctly")] + [InlineData(false)] + public async Task Resolve_Sequence_Skip_On_EntryField_Fragment_Other_Field_Selected(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + product: Product + } + + type Product { + id: ID! + brand: Brand! + } + + type Brand { + id: ID! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + brandById(id: ID!): Brand + productById(id: ID!): Product + } + + type Product implements Node { + id: ID! + other: String! + } + + type Brand implements Node { + id: ID! + name: String! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + product { + id + ...Test @skip(if: $skip) + other + } + } + + fragment Test on Product { + brand { + id + name + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task Resolve_Sequence_Skip_On_EntryField_Fragment_EntryField_Selected_Separately(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + product: Product + } + + type Product { + id: ID! + brand: Brand! + } + + type Brand { + id: ID! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + brandById(id: ID!): Brand + } + + type Brand implements Node { + id: ID! + name: String! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + product { + id + ...Test @skip(if: $skip) + brand { + id + name + } + } + } + + fragment Test on Product { + brand { + id + name + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result); + } + + [Theory] + [InlineData(true, Skip = "Subgraph unnecessarily called")] + [InlineData(false)] + public async Task Resolve_Sequence_Skip_On_SubField(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + product: Product + } + + type Product { + id: ID! + brand: Brand! + } + + type Brand { + id: ID! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + brandById(id: ID!): Brand + } + + type Brand implements Node { + id: ID! + name: String! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + product { + id + brand { + id + name @skip(if: $skip) + } + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + if (skip) + { + Assert.False(subgraphB.HasReceivedRequest); + } + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task Resolve_Sequence_Skip_On_SubField_Other_Field_Selected(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + product: Product + } + + type Product { + id: ID! + brand: Brand! + } + + type Brand { + id: ID! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + brandById(id: ID!): Brand + } + + type Brand implements Node { + id: ID! + name: String! + other: String! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + product { + id + brand { + id + name @skip(if: $skip) + other + } + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + } + + [Theory] + [InlineData(true, Skip = "Subgraph unnecessarily called")] + [InlineData(false)] + public async Task Resolve_Sequence_Skip_On_SubField_Fragment(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + product: Product + } + + type Product { + id: ID! + brand: Brand! + } + + type Brand { + id: ID! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + brandById(id: ID!): Brand + } + + type Brand implements Node { + id: ID! + name: String! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + product { + id + brand { + id + ...Test @skip(if: $skip) + } + } + } + + fragment Test on Brand { + name + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + if (skip) + { + Assert.False(subgraphB.HasReceivedRequest); + } + } + + [Theory] + [InlineData(true, Skip = "@skip isn't forwarded correctly")] + [InlineData(false)] + public async Task Resolve_Sequence_Skip_On_SubField_Fragment_Other_Field_Selected(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + product: Product + } + + type Product { + id: ID! + brand: Brand! + } + + type Brand { + id: ID! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + brandById(id: ID!): Brand + } + + type Brand implements Node { + id: ID! + name: String! + other: String! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + product { + id + brand { + id + ...Test @skip(if: $skip) + other + } + } + } + + fragment Test on Brand { + name + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task Resolve_Sequence_Skip_On_SubField_Fragment_SubField_Selected_Separately(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + product: Product + } + + type Product { + id: ID! + brand: Brand! + } + + type Brand { + id: ID! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + brandById(id: ID!): Brand + } + + type Brand implements Node { + id: ID! + name: String! + } + + interface Node { + id: ID! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + product { + id + brand { + id + ...Test @skip(if: $skip) + name + } + } + } + + fragment Test on Brand { + name + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result); + } + + #endregion + + #region ResolveByKey + + [Theory] + [InlineData(true, Skip = "Subgraph unnecessarily called")] + [InlineData(false)] + public async Task ResolveByKey_Skip_On_SubField(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + products: [Product!] + } + + type Product { + id: ID! + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + productsById(ids: [ID!]!): [Product] + } + + type Product { + id: ID! + price: Int! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + products { + id + name + price @skip(if: $skip) + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + if (skip) + { + Assert.False(subgraphB.HasReceivedRequest); + } + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task ResolveByKey_Skip_On_SubField_Other_Field_Selected(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + products: [Product!] + } + + type Product { + id: ID! + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + productsById(ids: [ID!]!): [Product] + } + + type Product { + id: ID! + price: Int! + other: String! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + products { + id + name + price @skip(if: $skip) + other + } + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + } + + [Theory] + [InlineData(true, Skip = "Subgraph unnecessarily called")] + [InlineData(false)] + public async Task ResolveByKey_Skip_On_SubField_Fragment(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + products: [Product!] + } + + type Product { + id: ID! + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + productsById(ids: [ID!]!): [Product] + } + + type Product { + id: ID! + price: Int! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + products { + id + name + ...Test @skip(if: $skip) + } + } + + fragment Test on Product { + price + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + if (skip) + { + Assert.False(subgraphB.HasReceivedRequest); + } + } + + [Theory] + [InlineData(true, Skip = "@skip isn't forwarded correctly")] + [InlineData(false)] + public async Task ResolveByKey_Skip_On_SubField_Fragment_Other_Field_Selected(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + products: [Product!] + } + + type Product { + id: ID! + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + productsById(ids: [ID!]!): [Product] + } + + type Product { + id: ID! + price: Int! + other: String! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + products { + id + name + ...Test @skip(if: $skip) + other + } + } + + fragment Test on Product { + price + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result, postFix: skip); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task ResolveByKey_Skip_On_SubField_Fragment_SubField_Selected_Separately(bool skip) + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + products: [Product!] + } + + type Product { + id: ID! + name: String! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + productsById(ids: [ID!]!): [Product] + } + + type Product { + id: ID! + price: Int! + } + """); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = OperationRequestBuilder.New() + .SetDocument(""" + query Test($skip: Boolean!) { + products { + id + name + ...Test @skip(if: $skip) + price + } + } + + fragment Test on Product { + price + } + """) + .SetVariableValues(new Dictionary { ["skip"] = skip }) + .Build(); + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result); + } + + #endregion +} diff --git a/src/HotChocolate/Fusion/test/Core.Tests/TestHelper.cs b/src/HotChocolate/Fusion/test/Core.Tests/TestHelper.cs index da341026675..1d6d7304243 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/TestHelper.cs +++ b/src/HotChocolate/Fusion/test/Core.Tests/TestHelper.cs @@ -11,23 +11,21 @@ namespace HotChocolate.Fusion; internal static class TestHelper { - // TODO: Temporary - public static async Task ProduceProperError(string schemaText, string request) - { - var subgraph = await TestSubgraph.CreateAsync(schemaText); - var executor = await subgraph.TestServer.Services.GetRequestExecutorAsync(); - - return await executor.ExecuteAsync(request); - } + public static void MatchMarkdownSnapshot( + IOperationRequest request, + IExecutionResult result, + object? postFix = null) + => MatchMarkdownSnapshot(request.Document?.ToString() ?? string.Empty, result, postFix); public static void MatchMarkdownSnapshot( string requestText, - IExecutionResult result) + IExecutionResult result, + object? postFix = null) { - var snapshot = new Snapshot(); - var request = Utf8GraphQLParser.Parse(requestText); + var snapshot = new Snapshot(postFix?.ToString()); + var requestDocument = Utf8GraphQLParser.Parse(requestText); - CollectSnapshotData(snapshot, request, result); + CollectSnapshotData(snapshot, requestDocument, result); snapshot.MatchMarkdownSnapshot(); } diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_False.md new file mode 100644 index 00000000000..eb17df3cef8 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_False.md @@ -0,0 +1,63 @@ +# EntityResolver_Skip_On_EntityResolver + +## Result + +```json +{ + "data": { + "productById": { + "id": "1", + "name": "string" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + productById(id: "1") @skip(if: $skip) { + id + name + } +} +``` + +## QueryPlan Hash + +```text +349C194994A0E867AC52596C3042DCA90B529A8B +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { productById(id: \u00221\u0022) @skip(if: $skip) { id name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1($skip: Boolean!) { productById(id: \u00221\u0022) @skip(if: $skip) { id name } }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Fragment_EntityResolver_Selected_Separately.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Fragment_EntityResolver_Selected_Separately.md new file mode 100644 index 00000000000..fbcf1a71234 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Fragment_EntityResolver_Selected_Separately.md @@ -0,0 +1,66 @@ +# EntityResolver_Skip_On_EntityResolver_Fragment_EntityResolver_Selected_Separately + +## Result + +```json +{ + "data": { + "productById": { + "id": "1", + "name": "string" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + ... Test @skip(if: $skip) + productById(id: "1") { + id + name + } +} + +fragment Test on Query { + productById(id: "1") { + id + name + } +} +``` + +## QueryPlan Hash + +```text +FD8123BBA58871A09E0E6F6C118EE453FBD7046F +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { ... Test @skip(if: $skip) productById(id: \u00221\u0022) { id name } } fragment Test on Query { productById(id: \u00221\u0022) { id name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { productById(id: \u00221\u0022) { id name } }", + "selectionSetId": 0 + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Fragment_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Fragment_False.md new file mode 100644 index 00000000000..426abdde91d --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Fragment_False.md @@ -0,0 +1,62 @@ +# EntityResolver_Skip_On_EntityResolver_Fragment + +## Result + +```json +{ + "data": { + "productById": { + "id": "1", + "name": "string" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + ... Test @skip(if: $skip) +} + +fragment Test on Query { + productById(id: "1") { + id + name + } +} +``` + +## QueryPlan Hash + +```text +299C3A16E021343840D26468051FDFFA6D9D7878 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { ... Test @skip(if: $skip) } fragment Test on Query { productById(id: \u00221\u0022) { id name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { productById(id: \u00221\u0022) { id name } }", + "selectionSetId": 0 + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Fragment_Other_RootField_Selected_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Fragment_Other_RootField_Selected_False.md new file mode 100644 index 00000000000..c373bcc5506 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Fragment_Other_RootField_Selected_False.md @@ -0,0 +1,64 @@ +# EntityResolver_Skip_On_EntityResolver_Fragment_Other_RootField_Selected + +## Result + +```json +{ + "data": { + "productById": { + "id": "1", + "name": "string" + }, + "other": "string" + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + ... Test @skip(if: $skip) + other +} + +fragment Test on Query { + productById(id: "1") { + id + name + } +} +``` + +## QueryPlan Hash + +```text +82F401D4DDCF4CA99A4426A0DBAB4D69CD3F13A2 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { ... Test @skip(if: $skip) other } fragment Test on Query { productById(id: \u00221\u0022) { id name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { productById(id: \u00221\u0022) { id name } other }", + "selectionSetId": 0 + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Fragment_Other_RootField_Selected_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Fragment_Other_RootField_Selected_True.md new file mode 100644 index 00000000000..d3c06815e24 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Fragment_Other_RootField_Selected_True.md @@ -0,0 +1,60 @@ +# EntityResolver_Skip_On_EntityResolver_Fragment_Other_RootField_Selected + +## Result + +```json +{ + "data": { + "other": "string" + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + ... Test @skip(if: $skip) + other +} + +fragment Test on Query { + productById(id: "1") { + id + name + } +} +``` + +## QueryPlan Hash + +```text +82F401D4DDCF4CA99A4426A0DBAB4D69CD3F13A2 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { ... Test @skip(if: $skip) other } fragment Test on Query { productById(id: \u00221\u0022) { id name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { productById(id: \u00221\u0022) { id name } other }", + "selectionSetId": 0 + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Fragment_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Fragment_True.md new file mode 100644 index 00000000000..d217612a9e6 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Fragment_True.md @@ -0,0 +1,57 @@ +# EntityResolver_Skip_On_EntityResolver_Fragment + +## Result + +```json +{ + "data": {} +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + ... Test @skip(if: $skip) +} + +fragment Test on Query { + productById(id: "1") { + id + name + } +} +``` + +## QueryPlan Hash + +```text +299C3A16E021343840D26468051FDFFA6D9D7878 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { ... Test @skip(if: $skip) } fragment Test on Query { productById(id: \u00221\u0022) { id name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { productById(id: \u00221\u0022) { id name } }", + "selectionSetId": 0 + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Other_RootField_Selected_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Other_RootField_Selected_False.md new file mode 100644 index 00000000000..fee47c255cf --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Other_RootField_Selected_False.md @@ -0,0 +1,65 @@ +# EntityResolver_Skip_On_EntityResolver_Other_RootField_Selected + +## Result + +```json +{ + "data": { + "productById": { + "id": "1", + "name": "string" + }, + "other": "string" + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + productById(id: "1") @skip(if: $skip) { + id + name + } + other +} +``` + +## QueryPlan Hash + +```text +9C12237B1A40129B239D76EA6B2F29D0D1305240 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { productById(id: \u00221\u0022) @skip(if: $skip) { id name } other }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1($skip: Boolean!) { productById(id: \u00221\u0022) @skip(if: $skip) { id name } other }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Other_RootField_Selected_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Other_RootField_Selected_True.md new file mode 100644 index 00000000000..dc704aad9bc --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_Other_RootField_Selected_True.md @@ -0,0 +1,61 @@ +# EntityResolver_Skip_On_EntityResolver_Other_RootField_Selected + +## Result + +```json +{ + "data": { + "other": "string" + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + productById(id: "1") @skip(if: $skip) { + id + name + } + other +} +``` + +## QueryPlan Hash + +```text +9C12237B1A40129B239D76EA6B2F29D0D1305240 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { productById(id: \u00221\u0022) @skip(if: $skip) { id name } other }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1($skip: Boolean!) { productById(id: \u00221\u0022) @skip(if: $skip) { id name } other }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_True.md new file mode 100644 index 00000000000..f447cd3925f --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_EntityResolver_True.md @@ -0,0 +1,58 @@ +# EntityResolver_Skip_On_EntityResolver + +## Result + +```json +{ + "data": {} +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + productById(id: "1") @skip(if: $skip) { + id + name + } +} +``` + +## QueryPlan Hash + +```text +349C194994A0E867AC52596C3042DCA90B529A8B +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { productById(id: \u00221\u0022) @skip(if: $skip) { id name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1($skip: Boolean!) { productById(id: \u00221\u0022) @skip(if: $skip) { id name } }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_SubField_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_SubField_False.md new file mode 100644 index 00000000000..1489d739c35 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_SubField_False.md @@ -0,0 +1,63 @@ +# EntityResolver_Skip_On_SubField + +## Result + +```json +{ + "data": { + "productById": { + "name": "string", + "price": 123.456 + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + productById(id: "1") { + name @skip(if: $skip) + price + } +} +``` + +## QueryPlan Hash + +```text +38DB93D5058D1661AB219912CD754C469DB36C49 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { productById(id: \u00221\u0022) { name @skip(if: $skip) price } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1($skip: Boolean!) { productById(id: \u00221\u0022) { name @skip(if: $skip) price } }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_SubField_Fragment_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_SubField_Fragment_False.md new file mode 100644 index 00000000000..c96457a25c2 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_SubField_Fragment_False.md @@ -0,0 +1,62 @@ +# EntityResolver_Skip_On_SubField_Fragment + +## Result + +```json +{ + "data": { + "productById": { + "name": "string", + "price": 123.456 + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + productById(id: "1") { + ... Test @skip(if: $skip) + price + } +} + +fragment Test on Product { + name +} +``` + +## QueryPlan Hash + +```text +F70E2C57BE7C90427FF9E449DE7F1251066313CE +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { productById(id: \u00221\u0022) { ... Test @skip(if: $skip) price } } fragment Test on Product { name }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { productById(id: \u00221\u0022) { name price } }", + "selectionSetId": 0 + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_SubField_Fragment_SubField_Selected_Separately.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_SubField_Fragment_SubField_Selected_Separately.md new file mode 100644 index 00000000000..736c4042309 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_SubField_Fragment_SubField_Selected_Separately.md @@ -0,0 +1,63 @@ +# EntityResolver_Skip_On_SubField_Fragment_SubField_Selected_Separately + +## Result + +```json +{ + "data": { + "productById": { + "name": "string", + "price": 123.456 + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + productById(id: "1") { + ... Test @skip(if: $skip) + name + price + } +} + +fragment Test on Product { + name +} +``` + +## QueryPlan Hash + +```text +CE8F8A324258B4FB0800D2D67B1B7582688DA221 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { productById(id: \u00221\u0022) { ... Test @skip(if: $skip) name price } } fragment Test on Product { name }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { productById(id: \u00221\u0022) { name price } }", + "selectionSetId": 0 + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_SubField_Fragment_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_SubField_Fragment_True.md new file mode 100644 index 00000000000..b1d9e9ab07e --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_SubField_Fragment_True.md @@ -0,0 +1,61 @@ +# EntityResolver_Skip_On_SubField_Fragment + +## Result + +```json +{ + "data": { + "productById": { + "price": 123.456 + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + productById(id: "1") { + ... Test @skip(if: $skip) + price + } +} + +fragment Test on Product { + name +} +``` + +## QueryPlan Hash + +```text +F70E2C57BE7C90427FF9E449DE7F1251066313CE +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { productById(id: \u00221\u0022) { ... Test @skip(if: $skip) price } } fragment Test on Product { name }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { productById(id: \u00221\u0022) { name price } }", + "selectionSetId": 0 + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_SubField_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_SubField_True.md new file mode 100644 index 00000000000..589b6813f78 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.EntityResolver_Skip_On_SubField_True.md @@ -0,0 +1,62 @@ +# EntityResolver_Skip_On_SubField + +## Result + +```json +{ + "data": { + "productById": { + "price": 123.456 + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + productById(id: "1") { + name @skip(if: $skip) + price + } +} +``` + +## QueryPlan Hash + +```text +38DB93D5058D1661AB219912CD754C469DB36C49 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { productById(id: \u00221\u0022) { name @skip(if: $skip) price } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1($skip: Boolean!) { productById(id: \u00221\u0022) { name @skip(if: $skip) price } }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_False.md new file mode 100644 index 00000000000..13e5dbaf404 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_False.md @@ -0,0 +1,79 @@ +# Parallel_Resolve_SharedEntryField_Skip_On_EntryField + +## Result + +```json +{ + "data": { + "viewer": { + "userId": "1", + "name": "string" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer @skip(if: $skip) { + userId + name + } +} +``` + +## QueryPlan Hash + +```text +9B94B894786FE90D76FAB8290F12CD0CBE51C564 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer @skip(if: $skip) { userId name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1($skip: Boolean!) { viewer @skip(if: $skip) { name } }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($skip: Boolean!) { viewer @skip(if: $skip) { userId } }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_EntryField_Partially_Selected_Separately_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_EntryField_Partially_Selected_Separately_False.md new file mode 100644 index 00000000000..68f8da0df1b --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_EntryField_Partially_Selected_Separately_False.md @@ -0,0 +1,76 @@ +# Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_EntryField_Partially_Selected_Separately + +## Result + +```json +{ + "data": { + "viewer": { + "userId": "1", + "name": "string" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + ... Test @skip(if: $skip) + viewer { + name + } +} + +fragment Test on Query { + viewer { + userId + name + } +} +``` + +## QueryPlan Hash + +```text +DE7FCDAA96445C4383E2C3A94814FD94461B9E3E +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { ... Test @skip(if: $skip) viewer { name } } fragment Test on Query { viewer { userId name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2 { viewer { userId } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_EntryField_Partially_Selected_Separately_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_EntryField_Partially_Selected_Separately_True.md new file mode 100644 index 00000000000..4e6598a235b --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_EntryField_Partially_Selected_Separately_True.md @@ -0,0 +1,75 @@ +# Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_EntryField_Partially_Selected_Separately + +## Result + +```json +{ + "data": { + "viewer": { + "name": "string" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + ... Test @skip(if: $skip) + viewer { + name + } +} + +fragment Test on Query { + viewer { + userId + name + } +} +``` + +## QueryPlan Hash + +```text +DE7FCDAA96445C4383E2C3A94814FD94461B9E3E +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { ... Test @skip(if: $skip) viewer { name } } fragment Test on Query { viewer { userId name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2 { viewer { userId } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_EntryField_Selected_Separately.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_EntryField_Selected_Separately.md new file mode 100644 index 00000000000..1863358fdd0 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_EntryField_Selected_Separately.md @@ -0,0 +1,77 @@ +# Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_EntryField_Selected_Separately + +## Result + +```json +{ + "data": { + "viewer": { + "userId": "1", + "name": "string" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + ... Test @skip(if: $skip) + viewer { + userId + name + } +} + +fragment Test on Query { + viewer { + userId + name + } +} +``` + +## QueryPlan Hash + +```text +EC537BBD29F26377D1FE5B7E20A94C4A1038A483 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { ... Test @skip(if: $skip) viewer { userId name } } fragment Test on Query { viewer { userId name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2 { viewer { userId } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_False.md new file mode 100644 index 00000000000..d9f9b1840cb --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_False.md @@ -0,0 +1,73 @@ +# Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment + +## Result + +```json +{ + "data": { + "viewer": { + "userId": "1", + "name": "string" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + ... Test @skip(if: $skip) +} + +fragment Test on Query { + viewer { + userId + name + } +} +``` + +## QueryPlan Hash + +```text +A8CB83116739564244E01F56F4419A743BABD3B4 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { ... Test @skip(if: $skip) } fragment Test on Query { viewer { userId name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2 { viewer { userId } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_Other_RootField_Selected_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_Other_RootField_Selected_False.md new file mode 100644 index 00000000000..b66b7d2517b --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_Other_RootField_Selected_False.md @@ -0,0 +1,75 @@ +# Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_Other_RootField_Selected + +## Result + +```json +{ + "data": { + "viewer": { + "userId": "1", + "name": "string" + }, + "other": "string" + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + ... Test @skip(if: $skip) + other +} + +fragment Test on Query { + viewer { + userId + name + } +} +``` + +## QueryPlan Hash + +```text +52DDC1FC3CEEDF059D4A4A9B40B5682AD44360F4 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { ... Test @skip(if: $skip) other } fragment Test on Query { viewer { userId name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_1 { viewer { userId } other }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_2 { viewer { name } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_Other_RootField_Selected_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_Other_RootField_Selected_True.md new file mode 100644 index 00000000000..2a7f6385fbc --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_Other_RootField_Selected_True.md @@ -0,0 +1,71 @@ +# Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_Other_RootField_Selected + +## Result + +```json +{ + "data": { + "other": "string" + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + ... Test @skip(if: $skip) + other +} + +fragment Test on Query { + viewer { + userId + name + } +} +``` + +## QueryPlan Hash + +```text +52DDC1FC3CEEDF059D4A4A9B40B5682AD44360F4 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { ... Test @skip(if: $skip) other } fragment Test on Query { viewer { userId name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_1 { viewer { userId } other }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_2 { viewer { name } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_True.md new file mode 100644 index 00000000000..b6e446957a8 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment_True.md @@ -0,0 +1,68 @@ +# Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Fragment + +## Result + +```json +{ + "data": {} +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + ... Test @skip(if: $skip) +} + +fragment Test on Query { + viewer { + userId + name + } +} +``` + +## QueryPlan Hash + +```text +A8CB83116739564244E01F56F4419A743BABD3B4 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { ... Test @skip(if: $skip) } fragment Test on Query { viewer { userId name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2 { viewer { userId } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Other_RootField_Selected_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Other_RootField_Selected_False.md new file mode 100644 index 00000000000..f5afa04361c --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Other_RootField_Selected_False.md @@ -0,0 +1,81 @@ +# Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Other_RootField_Selected + +## Result + +```json +{ + "data": { + "viewer": { + "userId": "1", + "name": "string" + }, + "other": "string" + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer @skip(if: $skip) { + userId + name + } + other +} +``` + +## QueryPlan Hash + +```text +16940BE29715988F4EFF523764D3BB5B7EFD976E +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer @skip(if: $skip) { userId name } other }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_1($skip: Boolean!) { viewer @skip(if: $skip) { userId } other }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_2($skip: Boolean!) { viewer @skip(if: $skip) { name } }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Other_RootField_Selected_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Other_RootField_Selected_True.md new file mode 100644 index 00000000000..08f4890d9d2 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Other_RootField_Selected_True.md @@ -0,0 +1,77 @@ +# Parallel_Resolve_SharedEntryField_Skip_On_EntryField_Other_RootField_Selected + +## Result + +```json +{ + "data": { + "other": "string" + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer @skip(if: $skip) { + userId + name + } + other +} +``` + +## QueryPlan Hash + +```text +16940BE29715988F4EFF523764D3BB5B7EFD976E +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer @skip(if: $skip) { userId name } other }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_1($skip: Boolean!) { viewer @skip(if: $skip) { userId } other }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_2($skip: Boolean!) { viewer @skip(if: $skip) { name } }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_True.md new file mode 100644 index 00000000000..9c33fb5b49e --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_EntryField_True.md @@ -0,0 +1,74 @@ +# Parallel_Resolve_SharedEntryField_Skip_On_EntryField + +## Result + +```json +{ + "data": {} +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer @skip(if: $skip) { + userId + name + } +} +``` + +## QueryPlan Hash + +```text +9B94B894786FE90D76FAB8290F12CD0CBE51C564 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer @skip(if: $skip) { userId name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1($skip: Boolean!) { viewer @skip(if: $skip) { name } }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($skip: Boolean!) { viewer @skip(if: $skip) { userId } }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_SubField_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_SubField_False.md new file mode 100644 index 00000000000..b5ac7cc661f --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_SubField_False.md @@ -0,0 +1,74 @@ +# Parallel_Resolve_SharedEntryField_Skip_On_SubField + +## Result + +```json +{ + "data": { + "viewer": { + "userId": "1", + "name": "string" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer { + userId @skip(if: $skip) + name + } +} +``` + +## QueryPlan Hash + +```text +359E27BB01CBCC1B008A003A40263BBE81CA5A5B +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer { userId @skip(if: $skip) name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($skip: Boolean!) { viewer { userId @skip(if: $skip) } }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_SubField_Fragment_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_SubField_Fragment_False.md new file mode 100644 index 00000000000..6a4d78926d3 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_SubField_Fragment_False.md @@ -0,0 +1,73 @@ +# Parallel_Resolve_SharedEntryField_Skip_On_SubField_Fragment + +## Result + +```json +{ + "data": { + "viewer": { + "userId": "1", + "name": "string" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer { + ... Test @skip(if: $skip) + name + } +} + +fragment Test on Viewer { + userId +} +``` + +## QueryPlan Hash + +```text +D71B896CB16891D2B0CA1F6F79ECA60E41F2A41F +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer { ... Test @skip(if: $skip) name } } fragment Test on Viewer { userId }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2 { viewer { userId } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_SubField_Fragment_SubField_Selected_Separately.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_SubField_Fragment_SubField_Selected_Separately.md new file mode 100644 index 00000000000..9723aeec7da --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_SubField_Fragment_SubField_Selected_Separately.md @@ -0,0 +1,74 @@ +# Parallel_Resolve_SharedEntryField_Skip_On_SubField_Fragment_SubField_Selected_Separately + +## Result + +```json +{ + "data": { + "viewer": { + "userId": "1", + "name": "string" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer { + ... Test @skip(if: $skip) + userId + name + } +} + +fragment Test on Viewer { + userId +} +``` + +## QueryPlan Hash + +```text +653A2F97D20C9C6C47695F68306379FB45775C7F +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer { ... Test @skip(if: $skip) userId name } } fragment Test on Viewer { userId }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2 { viewer { userId } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_SubField_Fragment_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_SubField_Fragment_True.md new file mode 100644 index 00000000000..2e7f1811a43 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_SubField_Fragment_True.md @@ -0,0 +1,72 @@ +# Parallel_Resolve_SharedEntryField_Skip_On_SubField_Fragment + +## Result + +```json +{ + "data": { + "viewer": { + "name": "string" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer { + ... Test @skip(if: $skip) + name + } +} + +fragment Test on Viewer { + userId +} +``` + +## QueryPlan Hash + +```text +D71B896CB16891D2B0CA1F6F79ECA60E41F2A41F +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer { ... Test @skip(if: $skip) name } } fragment Test on Viewer { userId }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2 { viewer { userId } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_SubField_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_SubField_True.md new file mode 100644 index 00000000000..9fa2fc98a7c --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_SharedEntryField_Skip_On_SubField_True.md @@ -0,0 +1,73 @@ +# Parallel_Resolve_SharedEntryField_Skip_On_SubField + +## Result + +```json +{ + "data": { + "viewer": { + "name": "string" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer { + userId @skip(if: $skip) + name + } +} +``` + +## QueryPlan Hash + +```text +359E27BB01CBCC1B008A003A40263BBE81CA5A5B +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer { userId @skip(if: $skip) name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($skip: Boolean!) { viewer { userId @skip(if: $skip) } }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_False.md new file mode 100644 index 00000000000..904224ebfe5 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_False.md @@ -0,0 +1,78 @@ +# Parallel_Resolve_Skip_On_EntryField + +## Result + +```json +{ + "data": { + "viewer": { + "name": "string" + }, + "other": { + "userId": "1" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer { + name + } + other @skip(if: $skip) { + userId + } +} +``` + +## QueryPlan Hash + +```text +EBF12464BEA547C7E5B76B77619C730E63F9BB78 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer { name } other @skip(if: $skip) { userId } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($skip: Boolean!) { other @skip(if: $skip) { userId } }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Fragment_EntryField_Selected_Separately_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Fragment_EntryField_Selected_Separately_False.md new file mode 100644 index 00000000000..27d04854e8a --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Fragment_EntryField_Selected_Separately_False.md @@ -0,0 +1,80 @@ +# Parallel_Resolve_Skip_On_EntryField_Fragment_EntryField_Selected_Separately + +## Result + +```json +{ + "data": { + "viewer": { + "name": "string" + }, + "other": { + "userId": "1" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer { + name + } + other { + userId + } + ... Test @skip(if: $skip) +} + +fragment Test on Query { + other { + userId + } +} +``` + +## QueryPlan Hash + +```text +011B48529F192BCF168898CCD7B79A8D06AC0006 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer { name } other { userId } ... Test @skip(if: $skip) } fragment Test on Query { other { userId } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2 { other { userId } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Fragment_EntryField_Selected_Separately_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Fragment_EntryField_Selected_Separately_True.md new file mode 100644 index 00000000000..27d04854e8a --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Fragment_EntryField_Selected_Separately_True.md @@ -0,0 +1,80 @@ +# Parallel_Resolve_Skip_On_EntryField_Fragment_EntryField_Selected_Separately + +## Result + +```json +{ + "data": { + "viewer": { + "name": "string" + }, + "other": { + "userId": "1" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer { + name + } + other { + userId + } + ... Test @skip(if: $skip) +} + +fragment Test on Query { + other { + userId + } +} +``` + +## QueryPlan Hash + +```text +011B48529F192BCF168898CCD7B79A8D06AC0006 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer { name } other { userId } ... Test @skip(if: $skip) } fragment Test on Query { other { userId } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2 { other { userId } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Fragment_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Fragment_False.md new file mode 100644 index 00000000000..bf4aa6e9256 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Fragment_False.md @@ -0,0 +1,77 @@ +# Parallel_Resolve_Skip_On_EntryField_Fragment + +## Result + +```json +{ + "data": { + "viewer": { + "name": "string" + }, + "other": { + "userId": "1" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer { + name + } + ... Test @skip(if: $skip) +} + +fragment Test on Query { + other { + userId + } +} +``` + +## QueryPlan Hash + +```text +9C2E1B5B1976B055D0F3E9380B846B70B9831BC3 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer { name } ... Test @skip(if: $skip) } fragment Test on Query { other { userId } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2 { other { userId } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Fragment_Other_RootField_Selected_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Fragment_Other_RootField_Selected_False.md new file mode 100644 index 00000000000..f96654bb090 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Fragment_Other_RootField_Selected_False.md @@ -0,0 +1,79 @@ +# Parallel_Resolve_Skip_On_EntryField_Fragment_Other_RootField_Selected + +## Result + +```json +{ + "data": { + "viewer": { + "name": "string" + }, + "other": { + "userId": "1" + }, + "another": "string" + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer { + name + } + ... Test @skip(if: $skip) + another +} + +fragment Test on Query { + other { + userId + } +} +``` + +## QueryPlan Hash + +```text +28FA0CC34DE3FA1E5BEC2B3AA2B722B768B80609 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer { name } ... Test @skip(if: $skip) another } fragment Test on Query { other { userId } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_1 { other { userId } another }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_2 { viewer { name } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Fragment_Other_RootField_Selected_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Fragment_Other_RootField_Selected_True.md new file mode 100644 index 00000000000..e535194f017 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Fragment_Other_RootField_Selected_True.md @@ -0,0 +1,76 @@ +# Parallel_Resolve_Skip_On_EntryField_Fragment_Other_RootField_Selected + +## Result + +```json +{ + "data": { + "viewer": { + "name": "string" + }, + "another": "string" + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer { + name + } + ... Test @skip(if: $skip) + another +} + +fragment Test on Query { + other { + userId + } +} +``` + +## QueryPlan Hash + +```text +28FA0CC34DE3FA1E5BEC2B3AA2B722B768B80609 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer { name } ... Test @skip(if: $skip) another } fragment Test on Query { other { userId } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_1 { other { userId } another }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_2 { viewer { name } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Fragment_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Fragment_True.md new file mode 100644 index 00000000000..36613055a25 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Fragment_True.md @@ -0,0 +1,74 @@ +# Parallel_Resolve_Skip_On_EntryField_Fragment + +## Result + +```json +{ + "data": { + "viewer": { + "name": "string" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer { + name + } + ... Test @skip(if: $skip) +} + +fragment Test on Query { + other { + userId + } +} +``` + +## QueryPlan Hash + +```text +9C2E1B5B1976B055D0F3E9380B846B70B9831BC3 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer { name } ... Test @skip(if: $skip) } fragment Test on Query { other { userId } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2 { other { userId } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Other_RootField_Selected_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Other_RootField_Selected_False.md new file mode 100644 index 00000000000..5021eb241ee --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Other_RootField_Selected_False.md @@ -0,0 +1,80 @@ +# Parallel_Resolve_Skip_On_EntryField_Other_RootField_Selected + +## Result + +```json +{ + "data": { + "viewer": { + "name": "string" + }, + "other": { + "userId": "1" + }, + "another": "string" + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer { + name + } + other @skip(if: $skip) { + userId + } + another +} +``` + +## QueryPlan Hash + +```text +A1607582FDA8ACE7201DD6EECD6EF8922C8D9043 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer { name } other @skip(if: $skip) { userId } another }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_1($skip: Boolean!) { other @skip(if: $skip) { userId } another }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_2 { viewer { name } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Other_RootField_Selected_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Other_RootField_Selected_True.md new file mode 100644 index 00000000000..ffc53bc29e6 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_Other_RootField_Selected_True.md @@ -0,0 +1,77 @@ +# Parallel_Resolve_Skip_On_EntryField_Other_RootField_Selected + +## Result + +```json +{ + "data": { + "viewer": { + "name": "string" + }, + "another": "string" + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer { + name + } + other @skip(if: $skip) { + userId + } + another +} +``` + +## QueryPlan Hash + +```text +A1607582FDA8ACE7201DD6EECD6EF8922C8D9043 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer { name } other @skip(if: $skip) { userId } another }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_1($skip: Boolean!) { other @skip(if: $skip) { userId } another }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_2 { viewer { name } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_True.md new file mode 100644 index 00000000000..4a3194e747c --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_EntryField_True.md @@ -0,0 +1,75 @@ +# Parallel_Resolve_Skip_On_EntryField + +## Result + +```json +{ + "data": { + "viewer": { + "name": "string" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer { + name + } + other @skip(if: $skip) { + userId + } +} +``` + +## QueryPlan Hash + +```text +EBF12464BEA547C7E5B76B77619C730E63F9BB78 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer { name } other @skip(if: $skip) { userId } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($skip: Boolean!) { other @skip(if: $skip) { userId } }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_SubField_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_SubField_False.md new file mode 100644 index 00000000000..3b79482603b --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_SubField_False.md @@ -0,0 +1,78 @@ +# Parallel_Resolve_Skip_On_SubField + +## Result + +```json +{ + "data": { + "viewer": { + "name": "string" + }, + "other": { + "userId": "1" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer { + name + } + other { + userId @skip(if: $skip) + } +} +``` + +## QueryPlan Hash + +```text +424991873692932F36F2ED2FCF024547AD0AD47A +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer { name } other { userId @skip(if: $skip) } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($skip: Boolean!) { other { userId @skip(if: $skip) } }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_SubField_Fragment_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_SubField_Fragment_False.md new file mode 100644 index 00000000000..6f726f473df --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_SubField_Fragment_False.md @@ -0,0 +1,77 @@ +# Parallel_Resolve_Skip_On_SubField_Fragment + +## Result + +```json +{ + "data": { + "viewer": { + "name": "string" + }, + "other": { + "userId": "1" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer { + name + } + other { + ... Test @skip(if: $skip) + } +} + +fragment Test on Other { + userId +} +``` + +## QueryPlan Hash + +```text +673C1AC76B07700826D5C27DD146138C765DA6CB +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer { name } other { ... Test @skip(if: $skip) } } fragment Test on Other { userId }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2 { other { userId } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_SubField_Fragment_SubField_Selected_Separately.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_SubField_Fragment_SubField_Selected_Separately.md new file mode 100644 index 00000000000..a9e1813cebb --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_SubField_Fragment_SubField_Selected_Separately.md @@ -0,0 +1,78 @@ +# Parallel_Resolve_Skip_On_SubField_Fragment_SubField_Selected_Separately + +## Result + +```json +{ + "data": { + "viewer": { + "name": "string" + }, + "other": { + "userId": "1" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer { + name + } + other { + userId + ... Test @skip(if: $skip) + } +} + +fragment Test on Other { + userId +} +``` + +## QueryPlan Hash + +```text +B9AFD14189FE2CF8604139F95A0501C33D60BB82 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer { name } other { userId ... Test @skip(if: $skip) } } fragment Test on Other { userId }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2 { other { userId } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_SubField_Fragment_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_SubField_Fragment_True.md new file mode 100644 index 00000000000..7915253d970 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_SubField_Fragment_True.md @@ -0,0 +1,75 @@ +# Parallel_Resolve_Skip_On_SubField_Fragment + +## Result + +```json +{ + "data": { + "viewer": { + "name": "string" + }, + "other": {} + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer { + name + } + other { + ... Test @skip(if: $skip) + } +} + +fragment Test on Other { + userId +} +``` + +## QueryPlan Hash + +```text +673C1AC76B07700826D5C27DD146138C765DA6CB +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer { name } other { ... Test @skip(if: $skip) } } fragment Test on Other { userId }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2 { other { userId } }", + "selectionSetId": 0 + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_SubField_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_SubField_True.md new file mode 100644 index 00000000000..41c4482820a --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Parallel_Resolve_Skip_On_SubField_True.md @@ -0,0 +1,76 @@ +# Parallel_Resolve_Skip_On_SubField + +## Result + +```json +{ + "data": { + "viewer": { + "name": "string" + }, + "other": {} + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + viewer { + name + } + other { + userId @skip(if: $skip) + } +} +``` + +## QueryPlan Hash + +```text +424991873692932F36F2ED2FCF024547AD0AD47A +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { viewer { name } other { userId @skip(if: $skip) } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { viewer { name } }", + "selectionSetId": 0 + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($skip: Boolean!) { other { userId @skip(if: $skip) } }", + "selectionSetId": 0, + "forwardedVariables": [ + { + "variable": "skip" + } + ] + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_False.md new file mode 100644 index 00000000000..f5426c32e1b --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_False.md @@ -0,0 +1,105 @@ +# ResolveByKey_Skip_On_SubField + +## Result + +```json +{ + "data": { + "products": [ + { + "id": "1", + "name": "string", + "price": 123 + }, + { + "id": "2", + "name": "string", + "price": 123 + }, + { + "id": "3", + "name": "string", + "price": 123 + } + ] + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + products { + id + name + price @skip(if: $skip) + } +} +``` + +## QueryPlan Hash + +```text +49DCEC3B3A87A360729B0D001F5A6913DC573FD6 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { products { id name price @skip(if: $skip) } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { products { id name __fusion_exports__1: id } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "ResolveByKeyBatch", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: [ID!]!, $skip: Boolean!) { productsById(ids: $__fusion_exports__1) { price @skip(if: $skip) __fusion_exports__1: id } }", + "selectionSetId": 1, + "path": [ + "productsById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ], + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 1 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Product_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Fragment_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Fragment_False.md new file mode 100644 index 00000000000..4d480171310 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Fragment_False.md @@ -0,0 +1,104 @@ +# ResolveByKey_Skip_On_SubField_Fragment + +## Result + +```json +{ + "data": { + "products": [ + { + "id": "1", + "name": "string", + "price": 123 + }, + { + "id": "2", + "name": "string", + "price": 123 + }, + { + "id": "3", + "name": "string", + "price": 123 + } + ] + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + products { + id + name + ... Test @skip(if: $skip) + } +} + +fragment Test on Product { + price +} +``` + +## QueryPlan Hash + +```text +89B962E6D6970E4B6797A38CC1AE85501E7486CF +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { products { id name ... Test @skip(if: $skip) } } fragment Test on Product { price }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { products { id name __fusion_exports__1: id } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "ResolveByKeyBatch", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: [ID!]!) { productsById(ids: $__fusion_exports__1) { price __fusion_exports__1: id } }", + "selectionSetId": 1, + "path": [ + "productsById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 1 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Product_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Fragment_Other_Field_Selected_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Fragment_Other_Field_Selected_False.md new file mode 100644 index 00000000000..569483256c0 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Fragment_Other_Field_Selected_False.md @@ -0,0 +1,108 @@ +# ResolveByKey_Skip_On_SubField_Fragment_Other_Field_Selected + +## Result + +```json +{ + "data": { + "products": [ + { + "id": "1", + "name": "string", + "price": 123, + "other": "string" + }, + { + "id": "2", + "name": "string", + "price": 123, + "other": "string" + }, + { + "id": "3", + "name": "string", + "price": 123, + "other": "string" + } + ] + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + products { + id + name + ... Test @skip(if: $skip) + other + } +} + +fragment Test on Product { + price +} +``` + +## QueryPlan Hash + +```text +935028235BB705504E70B07C6D0118B5505183CA +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { products { id name ... Test @skip(if: $skip) other } } fragment Test on Product { price }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { products { id name __fusion_exports__1: id } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "ResolveByKeyBatch", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: [ID!]!) { productsById(ids: $__fusion_exports__1) { price other __fusion_exports__1: id } }", + "selectionSetId": 1, + "path": [ + "productsById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 1 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Product_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Fragment_Other_Field_Selected_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Fragment_Other_Field_Selected_True.md new file mode 100644 index 00000000000..2e1c62663ae --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Fragment_Other_Field_Selected_True.md @@ -0,0 +1,105 @@ +# ResolveByKey_Skip_On_SubField_Fragment_Other_Field_Selected + +## Result + +```json +{ + "data": { + "products": [ + { + "id": "1", + "name": "string", + "other": "string" + }, + { + "id": "2", + "name": "string", + "other": "string" + }, + { + "id": "3", + "name": "string", + "other": "string" + } + ] + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + products { + id + name + ... Test @skip(if: $skip) + other + } +} + +fragment Test on Product { + price +} +``` + +## QueryPlan Hash + +```text +935028235BB705504E70B07C6D0118B5505183CA +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { products { id name ... Test @skip(if: $skip) other } } fragment Test on Product { price }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { products { id name __fusion_exports__1: id } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "ResolveByKeyBatch", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: [ID!]!) { productsById(ids: $__fusion_exports__1) { price other __fusion_exports__1: id } }", + "selectionSetId": 1, + "path": [ + "productsById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 1 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Product_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Fragment_SubField_Selected_Separately.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Fragment_SubField_Selected_Separately.md new file mode 100644 index 00000000000..d5ccd87dcaa --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Fragment_SubField_Selected_Separately.md @@ -0,0 +1,105 @@ +# ResolveByKey_Skip_On_SubField_Fragment_SubField_Selected_Separately + +## Result + +```json +{ + "data": { + "products": [ + { + "id": "1", + "name": "string", + "price": 123 + }, + { + "id": "2", + "name": "string", + "price": 123 + }, + { + "id": "3", + "name": "string", + "price": 123 + } + ] + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + products { + id + name + ... Test @skip(if: $skip) + price + } +} + +fragment Test on Product { + price +} +``` + +## QueryPlan Hash + +```text +EAB85F949C3500001321C9AEBD67AE3760355E3D +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { products { id name ... Test @skip(if: $skip) price } } fragment Test on Product { price }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { products { id name __fusion_exports__1: id } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "ResolveByKeyBatch", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: [ID!]!) { productsById(ids: $__fusion_exports__1) { price __fusion_exports__1: id } }", + "selectionSetId": 1, + "path": [ + "productsById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 1 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Product_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Fragment_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Fragment_True.md new file mode 100644 index 00000000000..ac8e1851ab0 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Fragment_True.md @@ -0,0 +1,101 @@ +# ResolveByKey_Skip_On_SubField_Fragment + +## Result + +```json +{ + "data": { + "products": [ + { + "id": "1", + "name": "string" + }, + { + "id": "2", + "name": "string" + }, + { + "id": "3", + "name": "string" + } + ] + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + products { + id + name + ... Test @skip(if: $skip) + } +} + +fragment Test on Product { + price +} +``` + +## QueryPlan Hash + +```text +89B962E6D6970E4B6797A38CC1AE85501E7486CF +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { products { id name ... Test @skip(if: $skip) } } fragment Test on Product { price }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { products { id name __fusion_exports__1: id } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "ResolveByKeyBatch", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: [ID!]!) { productsById(ids: $__fusion_exports__1) { price __fusion_exports__1: id } }", + "selectionSetId": 1, + "path": [ + "productsById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 1 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Product_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Other_Field_Selected_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Other_Field_Selected_False.md new file mode 100644 index 00000000000..8f61678f4d9 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Other_Field_Selected_False.md @@ -0,0 +1,109 @@ +# ResolveByKey_Skip_On_SubField_Other_Field_Selected + +## Result + +```json +{ + "data": { + "products": [ + { + "id": "1", + "name": "string", + "price": 123, + "other": "string" + }, + { + "id": "2", + "name": "string", + "price": 123, + "other": "string" + }, + { + "id": "3", + "name": "string", + "price": 123, + "other": "string" + } + ] + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + products { + id + name + price @skip(if: $skip) + other + } +} +``` + +## QueryPlan Hash + +```text +4ADF4130AAF9816DC72A9671227E2151B3E05554 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { products { id name price @skip(if: $skip) other } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { products { id name __fusion_exports__1: id } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "ResolveByKeyBatch", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: [ID!]!, $skip: Boolean!) { productsById(ids: $__fusion_exports__1) { price @skip(if: $skip) other __fusion_exports__1: id } }", + "selectionSetId": 1, + "path": [ + "productsById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ], + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 1 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Product_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Other_Field_Selected_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Other_Field_Selected_True.md new file mode 100644 index 00000000000..88b29c5306b --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_Other_Field_Selected_True.md @@ -0,0 +1,106 @@ +# ResolveByKey_Skip_On_SubField_Other_Field_Selected + +## Result + +```json +{ + "data": { + "products": [ + { + "id": "1", + "name": "string", + "other": "string" + }, + { + "id": "2", + "name": "string", + "other": "string" + }, + { + "id": "3", + "name": "string", + "other": "string" + } + ] + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + products { + id + name + price @skip(if: $skip) + other + } +} +``` + +## QueryPlan Hash + +```text +4ADF4130AAF9816DC72A9671227E2151B3E05554 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { products { id name price @skip(if: $skip) other } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { products { id name __fusion_exports__1: id } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "ResolveByKeyBatch", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: [ID!]!, $skip: Boolean!) { productsById(ids: $__fusion_exports__1) { price @skip(if: $skip) other __fusion_exports__1: id } }", + "selectionSetId": 1, + "path": [ + "productsById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ], + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 1 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Product_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_True.md new file mode 100644 index 00000000000..bc12cf4be3b --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.ResolveByKey_Skip_On_SubField_True.md @@ -0,0 +1,102 @@ +# ResolveByKey_Skip_On_SubField + +## Result + +```json +{ + "data": { + "products": [ + { + "id": "1", + "name": "string" + }, + { + "id": "2", + "name": "string" + }, + { + "id": "3", + "name": "string" + } + ] + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + products { + id + name + price @skip(if: $skip) + } +} +``` + +## QueryPlan Hash + +```text +49DCEC3B3A87A360729B0D001F5A6913DC573FD6 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { products { id name price @skip(if: $skip) } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { products { id name __fusion_exports__1: id } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "ResolveByKeyBatch", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: [ID!]!, $skip: Boolean!) { productsById(ids: $__fusion_exports__1) { price @skip(if: $skip) __fusion_exports__1: id } }", + "selectionSetId": 1, + "path": [ + "productsById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ], + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 1 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Product_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_False.md new file mode 100644 index 00000000000..a870f2c0e6e --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_False.md @@ -0,0 +1,97 @@ +# Resolve_Sequence_Skip_On_EntryField + +## Result + +```json +{ + "data": { + "product": { + "id": "1", + "brand": { + "id": "1", + "name": "string" + } + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product { + id + brand @skip(if: $skip) { + id + name + } + } +} +``` + +## QueryPlan Hash + +```text +766DA2342654C1585E6163852A6CEA388399CB8F +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product { id brand @skip(if: $skip) { id name } } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1($skip: Boolean!) { product { id brand @skip(if: $skip) { id __fusion_exports__1: id } } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ], + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Fragment_EntryField_Selected_Separately.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Fragment_EntryField_Selected_Separately.md new file mode 100644 index 00000000000..dad3e26b060 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Fragment_EntryField_Selected_Separately.md @@ -0,0 +1,100 @@ +# Resolve_Sequence_Skip_On_EntryField_Fragment_EntryField_Selected_Separately + +## Result + +```json +{ + "data": { + "product": { + "id": "1", + "brand": { + "id": "1", + "name": "string" + } + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product { + id + ... Test @skip(if: $skip) + brand { + id + name + } + } +} + +fragment Test on Product { + brand { + id + name + } +} +``` + +## QueryPlan Hash + +```text +E29BD8AE1B9E6A7AC6032E10211DAA4AD174FC05 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product { id ... Test @skip(if: $skip) brand { id name } } } fragment Test on Product { brand { id name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { product { id brand { id __fusion_exports__1: id } } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Fragment_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Fragment_False.md new file mode 100644 index 00000000000..2b7ba7d9219 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Fragment_False.md @@ -0,0 +1,96 @@ +# Resolve_Sequence_Skip_On_EntryField_Fragment + +## Result + +```json +{ + "data": { + "product": { + "id": "1", + "brand": { + "id": "1", + "name": "string" + } + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product { + id + ... Test @skip(if: $skip) + } +} + +fragment Test on Product { + brand { + id + name + } +} +``` + +## QueryPlan Hash + +```text +E44128C141B47EF61E050F0DD1FEE670AADE3125 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product { id ... Test @skip(if: $skip) } } fragment Test on Product { brand { id name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { product { id brand { id __fusion_exports__1: id } } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Fragment_Other_Field_Selected_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Fragment_Other_Field_Selected_False.md new file mode 100644 index 00000000000..e7a8c628f70 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Fragment_Other_Field_Selected_False.md @@ -0,0 +1,122 @@ +# Resolve_Sequence_Skip_On_EntryField_Fragment_Other_Field_Selected + +## Result + +```json +{ + "data": { + "product": { + "id": "1", + "brand": { + "id": "1", + "name": "string" + }, + "other": "string" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product { + id + ... Test @skip(if: $skip) + other + } +} + +fragment Test on Product { + brand { + id + name + } +} +``` + +## QueryPlan Hash + +```text +D46EDD9E2C2343DBA4034F26AF6A89C30A23A2BE +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product { id ... Test @skip(if: $skip) other } } fragment Test on Product { brand { id name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { product { id brand { id __fusion_exports__1: id } __fusion_exports__2: id } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + }, + { + "variable": "__fusion_exports__2" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_3($__fusion_exports__2: ID!) { productById(id: $__fusion_exports__2) { other } }", + "selectionSetId": 1, + "path": [ + "productById" + ], + "requires": [ + { + "variable": "__fusion_exports__2" + } + ] + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 1, + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id", + "__fusion_exports__2": "Product_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Fragment_Other_Field_Selected_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Fragment_Other_Field_Selected_True.md new file mode 100644 index 00000000000..b2609bf1624 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Fragment_Other_Field_Selected_True.md @@ -0,0 +1,118 @@ +# Resolve_Sequence_Skip_On_EntryField_Fragment_Other_Field_Selected + +## Result + +```json +{ + "data": { + "product": { + "id": "1", + "other": "string" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product { + id + ... Test @skip(if: $skip) + other + } +} + +fragment Test on Product { + brand { + id + name + } +} +``` + +## QueryPlan Hash + +```text +D46EDD9E2C2343DBA4034F26AF6A89C30A23A2BE +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product { id ... Test @skip(if: $skip) other } } fragment Test on Product { brand { id name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { product { id brand { id __fusion_exports__1: id } __fusion_exports__2: id } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + }, + { + "variable": "__fusion_exports__2" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_3($__fusion_exports__2: ID!) { productById(id: $__fusion_exports__2) { other } }", + "selectionSetId": 1, + "path": [ + "productById" + ], + "requires": [ + { + "variable": "__fusion_exports__2" + } + ] + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 1, + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id", + "__fusion_exports__2": "Product_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Fragment_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Fragment_True.md new file mode 100644 index 00000000000..92275c8ecd6 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Fragment_True.md @@ -0,0 +1,92 @@ +# Resolve_Sequence_Skip_On_EntryField_Fragment + +## Result + +```json +{ + "data": { + "product": { + "id": "1" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product { + id + ... Test @skip(if: $skip) + } +} + +fragment Test on Product { + brand { + id + name + } +} +``` + +## QueryPlan Hash + +```text +E44128C141B47EF61E050F0DD1FEE670AADE3125 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product { id ... Test @skip(if: $skip) } } fragment Test on Product { brand { id name } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { product { id brand { id __fusion_exports__1: id } } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Other_Field_Selected_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Other_Field_Selected_False.md new file mode 100644 index 00000000000..59342fe350c --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Other_Field_Selected_False.md @@ -0,0 +1,123 @@ +# Resolve_Sequence_Skip_On_EntryField_Other_Field_Selected + +## Result + +```json +{ + "data": { + "product": { + "id": "1", + "brand": { + "id": "1", + "name": "string" + }, + "other": "string" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product { + id + brand @skip(if: $skip) { + id + name + } + other + } +} +``` + +## QueryPlan Hash + +```text +187D3C73D0E5FFA7512DC6F8A2FFBC03E623CF85 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product { id brand @skip(if: $skip) { id name } other } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1($skip: Boolean!) { product { id brand @skip(if: $skip) { id __fusion_exports__1: id } __fusion_exports__2: id } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + }, + { + "variable": "__fusion_exports__2" + } + ], + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_3($__fusion_exports__2: ID!) { productById(id: $__fusion_exports__2) { other } }", + "selectionSetId": 1, + "path": [ + "productById" + ], + "requires": [ + { + "variable": "__fusion_exports__2" + } + ] + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 1, + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id", + "__fusion_exports__2": "Product_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Other_Field_Selected_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Other_Field_Selected_True.md new file mode 100644 index 00000000000..83d93654090 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_Other_Field_Selected_True.md @@ -0,0 +1,119 @@ +# Resolve_Sequence_Skip_On_EntryField_Other_Field_Selected + +## Result + +```json +{ + "data": { + "product": { + "id": "1", + "other": "string" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product { + id + brand @skip(if: $skip) { + id + name + } + other + } +} +``` + +## QueryPlan Hash + +```text +187D3C73D0E5FFA7512DC6F8A2FFBC03E623CF85 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product { id brand @skip(if: $skip) { id name } other } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1($skip: Boolean!) { product { id brand @skip(if: $skip) { id __fusion_exports__1: id } __fusion_exports__2: id } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + }, + { + "variable": "__fusion_exports__2" + } + ], + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Parallel", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_3($__fusion_exports__2: ID!) { productById(id: $__fusion_exports__2) { other } }", + "selectionSetId": 1, + "path": [ + "productById" + ], + "requires": [ + { + "variable": "__fusion_exports__2" + } + ] + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 1, + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id", + "__fusion_exports__2": "Product_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_True.md new file mode 100644 index 00000000000..7756e29aad1 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_EntryField_True.md @@ -0,0 +1,93 @@ +# Resolve_Sequence_Skip_On_EntryField + +## Result + +```json +{ + "data": { + "product": { + "id": "1" + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product { + id + brand @skip(if: $skip) { + id + name + } + } +} +``` + +## QueryPlan Hash + +```text +766DA2342654C1585E6163852A6CEA388399CB8F +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product { id brand @skip(if: $skip) { id name } } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1($skip: Boolean!) { product { id brand @skip(if: $skip) { id __fusion_exports__1: id } } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ], + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_False.md new file mode 100644 index 00000000000..59c6fc0d72a --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_False.md @@ -0,0 +1,97 @@ +# Resolve_Sequence_Skip_On_RootField + +## Result + +```json +{ + "data": { + "product": { + "id": "1", + "brand": { + "id": "1", + "name": "string" + } + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product @skip(if: $skip) { + id + brand { + id + name + } + } +} +``` + +## QueryPlan Hash + +```text +BC8B783BA7D23AED2207786ABCBE977B2138450C +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product @skip(if: $skip) { id brand { id name } } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1($skip: Boolean!) { product @skip(if: $skip) { id brand { id __fusion_exports__1: id } } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ], + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_Fragment_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_Fragment_False.md new file mode 100644 index 00000000000..aa0c42c676c --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_Fragment_False.md @@ -0,0 +1,96 @@ +# Resolve_Sequence_Skip_On_RootField_Fragment + +## Result + +```json +{ + "data": { + "product": { + "id": "1", + "brand": { + "id": "1", + "name": "string" + } + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + ... Test @skip(if: $skip) +} + +fragment Test on Query { + product { + id + brand { + id + name + } + } +} +``` + +## QueryPlan Hash + +```text +A6EBFB1FAE1EEF9C6E715C47035579475761DC8C +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { ... Test @skip(if: $skip) } fragment Test on Query { product { id brand { id name } } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { product { id brand { id __fusion_exports__1: id } } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_Fragment_Other_RootField_Selected_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_Fragment_Other_RootField_Selected_False.md new file mode 100644 index 00000000000..b7d5aba46f0 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_Fragment_Other_RootField_Selected_False.md @@ -0,0 +1,98 @@ +# Resolve_Sequence_Skip_On_RootField_Fragment_Other_RootField_Selected + +## Result + +```json +{ + "data": { + "product": { + "id": "1", + "brand": { + "id": "1", + "name": "string" + } + }, + "other": "string" + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + ... Test @skip(if: $skip) + other +} + +fragment Test on Query { + product { + id + brand { + id + name + } + } +} +``` + +## QueryPlan Hash + +```text +6E1700DC6EE5369F86BDD345970684098CE4EFA2 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { ... Test @skip(if: $skip) other } fragment Test on Query { product { id brand { id name } } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { product { id brand { id __fusion_exports__1: id } } other }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_Fragment_Other_RootField_Selected_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_Fragment_Other_RootField_Selected_True.md new file mode 100644 index 00000000000..332fcd7eea8 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_Fragment_Other_RootField_Selected_True.md @@ -0,0 +1,91 @@ +# Resolve_Sequence_Skip_On_RootField_Fragment_Other_RootField_Selected + +## Result + +```json +{ + "data": { + "other": "string" + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + ... Test @skip(if: $skip) + other +} + +fragment Test on Query { + product { + id + brand { + id + name + } + } +} +``` + +## QueryPlan Hash + +```text +6E1700DC6EE5369F86BDD345970684098CE4EFA2 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { ... Test @skip(if: $skip) other } fragment Test on Query { product { id brand { id name } } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { product { id brand { id __fusion_exports__1: id } } other }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_Fragment_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_Fragment_True.md new file mode 100644 index 00000000000..073b09d5391 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_Fragment_True.md @@ -0,0 +1,88 @@ +# Resolve_Sequence_Skip_On_RootField_Fragment + +## Result + +```json +{ + "data": {} +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + ... Test @skip(if: $skip) +} + +fragment Test on Query { + product { + id + brand { + id + name + } + } +} +``` + +## QueryPlan Hash + +```text +A6EBFB1FAE1EEF9C6E715C47035579475761DC8C +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { ... Test @skip(if: $skip) } fragment Test on Query { product { id brand { id name } } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { product { id brand { id __fusion_exports__1: id } } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_Other_RootField_Selected_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_Other_RootField_Selected_False.md new file mode 100644 index 00000000000..431149bad3a --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_Other_RootField_Selected_False.md @@ -0,0 +1,99 @@ +# Resolve_Sequence_Skip_On_RootField_Other_RootField_Selected + +## Result + +```json +{ + "data": { + "product": { + "id": "1", + "brand": { + "id": "1", + "name": "string" + } + }, + "other": "string" + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product @skip(if: $skip) { + id + brand { + id + name + } + } + other +} +``` + +## QueryPlan Hash + +```text +12CBB47F127A11FEA0B752CFECDF5D239AEDBA24 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product @skip(if: $skip) { id brand { id name } } other }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1($skip: Boolean!) { product @skip(if: $skip) { id brand { id __fusion_exports__1: id } } other }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ], + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_Other_RootField_Selected_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_Other_RootField_Selected_True.md new file mode 100644 index 00000000000..8ef6989f968 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_Other_RootField_Selected_True.md @@ -0,0 +1,92 @@ +# Resolve_Sequence_Skip_On_RootField_Other_RootField_Selected + +## Result + +```json +{ + "data": { + "other": "string" + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product @skip(if: $skip) { + id + brand { + id + name + } + } + other +} +``` + +## QueryPlan Hash + +```text +12CBB47F127A11FEA0B752CFECDF5D239AEDBA24 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product @skip(if: $skip) { id brand { id name } } other }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1($skip: Boolean!) { product @skip(if: $skip) { id brand { id __fusion_exports__1: id } } other }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ], + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_True.md new file mode 100644 index 00000000000..34b581f1b58 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_RootField_True.md @@ -0,0 +1,89 @@ +# Resolve_Sequence_Skip_On_RootField + +## Result + +```json +{ + "data": {} +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product @skip(if: $skip) { + id + brand { + id + name + } + } +} +``` + +## QueryPlan Hash + +```text +BC8B783BA7D23AED2207786ABCBE977B2138450C +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product @skip(if: $skip) { id brand { id name } } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1($skip: Boolean!) { product @skip(if: $skip) { id brand { id __fusion_exports__1: id } } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ], + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_False.md new file mode 100644 index 00000000000..807675840eb --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_False.md @@ -0,0 +1,97 @@ +# Resolve_Sequence_Skip_On_SubField + +## Result + +```json +{ + "data": { + "product": { + "id": "1", + "brand": { + "id": "1", + "name": "string" + } + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product { + id + brand { + id + name @skip(if: $skip) + } + } +} +``` + +## QueryPlan Hash + +```text +3606D677DEA5F72F4BCFFF22476A493A194AF5F9 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product { id brand { id name @skip(if: $skip) } } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { product { id brand { id __fusion_exports__1: id } } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!, $skip: Boolean!) { brandById(id: $__fusion_exports__1) { name @skip(if: $skip) } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ], + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Fragment_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Fragment_False.md new file mode 100644 index 00000000000..246ed7a3ac1 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Fragment_False.md @@ -0,0 +1,96 @@ +# Resolve_Sequence_Skip_On_SubField_Fragment + +## Result + +```json +{ + "data": { + "product": { + "id": "1", + "brand": { + "id": "1", + "name": "string" + } + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product { + id + brand { + id + ... Test @skip(if: $skip) + } + } +} + +fragment Test on Brand { + name +} +``` + +## QueryPlan Hash + +```text +9334F2320F732410E6A92FA83B655CA678BD80E8 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product { id brand { id ... Test @skip(if: $skip) } } } fragment Test on Brand { name }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { product { id brand { id __fusion_exports__1: id } } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Fragment_Other_Field_Selected_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Fragment_Other_Field_Selected_False.md new file mode 100644 index 00000000000..e0269b4c432 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Fragment_Other_Field_Selected_False.md @@ -0,0 +1,98 @@ +# Resolve_Sequence_Skip_On_SubField_Fragment_Other_Field_Selected + +## Result + +```json +{ + "data": { + "product": { + "id": "1", + "brand": { + "id": "1", + "name": "string", + "other": "string" + } + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product { + id + brand { + id + ... Test @skip(if: $skip) + other + } + } +} + +fragment Test on Brand { + name +} +``` + +## QueryPlan Hash + +```text +8D098A71B600717F663C5F09256662A3EF6B7501 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product { id brand { id ... Test @skip(if: $skip) other } } } fragment Test on Brand { name }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { product { id brand { id __fusion_exports__1: id } } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name other } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Fragment_Other_Field_Selected_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Fragment_Other_Field_Selected_True.md new file mode 100644 index 00000000000..825d28980fb --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Fragment_Other_Field_Selected_True.md @@ -0,0 +1,97 @@ +# Resolve_Sequence_Skip_On_SubField_Fragment_Other_Field_Selected + +## Result + +```json +{ + "data": { + "product": { + "id": "1", + "brand": { + "id": "1", + "other": "string" + } + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product { + id + brand { + id + ... Test @skip(if: $skip) + other + } + } +} + +fragment Test on Brand { + name +} +``` + +## QueryPlan Hash + +```text +8D098A71B600717F663C5F09256662A3EF6B7501 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product { id brand { id ... Test @skip(if: $skip) other } } } fragment Test on Brand { name }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { product { id brand { id __fusion_exports__1: id } } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name other } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Fragment_SubField_Selected_Separately.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Fragment_SubField_Selected_Separately.md new file mode 100644 index 00000000000..57bdc2d984f --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Fragment_SubField_Selected_Separately.md @@ -0,0 +1,97 @@ +# Resolve_Sequence_Skip_On_SubField_Fragment_SubField_Selected_Separately + +## Result + +```json +{ + "data": { + "product": { + "id": "1", + "brand": { + "id": "1", + "name": "string" + } + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product { + id + brand { + id + ... Test @skip(if: $skip) + name + } + } +} + +fragment Test on Brand { + name +} +``` + +## QueryPlan Hash + +```text +DC36350D9F22A68467B13E2E20BF6A02FCFF791C +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product { id brand { id ... Test @skip(if: $skip) name } } } fragment Test on Brand { name }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { product { id brand { id __fusion_exports__1: id } } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Fragment_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Fragment_True.md new file mode 100644 index 00000000000..338023b24a6 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Fragment_True.md @@ -0,0 +1,95 @@ +# Resolve_Sequence_Skip_On_SubField_Fragment + +## Result + +```json +{ + "data": { + "product": { + "id": "1", + "brand": { + "id": "1" + } + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product { + id + brand { + id + ... Test @skip(if: $skip) + } + } +} + +fragment Test on Brand { + name +} +``` + +## QueryPlan Hash + +```text +9334F2320F732410E6A92FA83B655CA678BD80E8 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product { id brand { id ... Test @skip(if: $skip) } } } fragment Test on Brand { name }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { product { id brand { id __fusion_exports__1: id } } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Other_Field_Selected_False.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Other_Field_Selected_False.md new file mode 100644 index 00000000000..d63f4d334c4 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Other_Field_Selected_False.md @@ -0,0 +1,99 @@ +# Resolve_Sequence_Skip_On_SubField_Other_Field_Selected + +## Result + +```json +{ + "data": { + "product": { + "id": "1", + "brand": { + "id": "1", + "name": "string", + "other": "string" + } + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product { + id + brand { + id + name @skip(if: $skip) + other + } + } +} +``` + +## QueryPlan Hash + +```text +06ADDD5F781B1908E4503D6617A487BE592DB04D +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product { id brand { id name @skip(if: $skip) other } } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { product { id brand { id __fusion_exports__1: id } } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!, $skip: Boolean!) { brandById(id: $__fusion_exports__1) { name @skip(if: $skip) other } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ], + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Other_Field_Selected_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Other_Field_Selected_True.md new file mode 100644 index 00000000000..eb405b3b327 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_Other_Field_Selected_True.md @@ -0,0 +1,98 @@ +# Resolve_Sequence_Skip_On_SubField_Other_Field_Selected + +## Result + +```json +{ + "data": { + "product": { + "id": "1", + "brand": { + "id": "1", + "other": "string" + } + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product { + id + brand { + id + name @skip(if: $skip) + other + } + } +} +``` + +## QueryPlan Hash + +```text +06ADDD5F781B1908E4503D6617A487BE592DB04D +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product { id brand { id name @skip(if: $skip) other } } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { product { id brand { id __fusion_exports__1: id } } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!, $skip: Boolean!) { brandById(id: $__fusion_exports__1) { name @skip(if: $skip) other } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ], + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_True.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_True.md new file mode 100644 index 00000000000..c06e5f3fecb --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/SkipTests.Resolve_Sequence_Skip_On_SubField_True.md @@ -0,0 +1,96 @@ +# Resolve_Sequence_Skip_On_SubField + +## Result + +```json +{ + "data": { + "product": { + "id": "1", + "brand": { + "id": "1" + } + } + } +} +``` + +## Request + +```graphql +query Test($skip: Boolean!) { + product { + id + brand { + id + name @skip(if: $skip) + } + } +} +``` + +## QueryPlan Hash + +```text +3606D677DEA5F72F4BCFFF22476A493A194AF5F9 +``` + +## QueryPlan + +```json +{ + "document": "query Test($skip: Boolean!) { product { id brand { id name @skip(if: $skip) } } }", + "operation": "Test", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query Test_1 { product { id brand { id __fusion_exports__1: id } } }", + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + }, + { + "type": "Resolve", + "subgraph": "Subgraph_2", + "document": "query Test_2($__fusion_exports__1: ID!, $skip: Boolean!) { brandById(id: $__fusion_exports__1) { name @skip(if: $skip) } }", + "selectionSetId": 2, + "path": [ + "brandById" + ], + "requires": [ + { + "variable": "__fusion_exports__1" + } + ], + "forwardedVariables": [ + { + "variable": "skip" + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 2 + ] + } + ] + }, + "state": { + "__fusion_exports__1": "Brand_id" + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Shared/TestSubgraph.cs b/src/HotChocolate/Fusion/test/Shared/TestSubgraph.cs index cd2d57c76a4..0d697df1de1 100644 --- a/src/HotChocolate/Fusion/test/Shared/TestSubgraph.cs +++ b/src/HotChocolate/Fusion/test/Shared/TestSubgraph.cs @@ -7,33 +7,22 @@ namespace HotChocolate.Fusion.Shared; -public record TestSubgraph(TestServer TestServer, ISchema Schema, string SchemaExtensions = "", bool IsOffline = false) +public record TestSubgraph( + TestServer TestServer, + ISchema Schema, + SubgraphTestContext Context, + string SchemaExtensions = "", + bool IsOffline = false) { - public static async Task CreateAsync( + public static Task CreateAsync( string schemaText, bool isOffline = false) - { - var testServerFactory = new TestServerFactory(); - - var testServer = testServerFactory.Create( - services => - { - services - .AddRouting() - .AddGraphQLServer() - .AddDocumentFromString(schemaText) - .AddResolverMocking() - .AddTestDirectives(); - }, - app => - { - app.UseRouting().UseEndpoints(endpoints => endpoints.MapGraphQL()); - }); - - var schema = await testServer.Services.GetSchemaAsync(); - - return new TestSubgraph(testServer, schema, IsOffline: isOffline); - } + => CreateAsync( + configureBuilder: builder => builder + .AddDocumentFromString(schemaText) + .AddResolverMocking() + .AddTestDirectives(), + isOffline: isOffline); public static async Task CreateAsync( Action configureBuilder, @@ -41,6 +30,7 @@ public static async Task CreateAsync( bool isOffline = false) { var testServerFactory = new TestServerFactory(); + var testContext = new SubgraphTestContext(); var testServer = testServerFactory.Create( services => @@ -53,11 +43,24 @@ public static async Task CreateAsync( }, app => { + app.Use(next => context => + { + testContext.HasReceivedRequest = true; + return next(context); + }); + app.UseRouting().UseEndpoints(endpoints => endpoints.MapGraphQL()); }); var schema = await testServer.Services.GetSchemaAsync(); - return new TestSubgraph(testServer, schema, extensions, isOffline); + return new TestSubgraph(testServer, schema, testContext, extensions, isOffline); } + + public bool HasReceivedRequest => Context.HasReceivedRequest; +} + +public class SubgraphTestContext +{ + public bool HasReceivedRequest { get; set; } }