diff --git a/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/InlineFragmentOperationRewriter.cs b/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/InlineFragmentOperationRewriter.cs index ad8bfd8656e..f7ac20e75e8 100644 --- a/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/InlineFragmentOperationRewriter.cs +++ b/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/InlineFragmentOperationRewriter.cs @@ -135,7 +135,7 @@ private void InlineFragmentDefinition( { var fragmentContext = context.Branch(typeCondition); - RewriteFields(fragmentDefinition.SelectionSet, context); + RewriteFields(fragmentDefinition.SelectionSet, fragmentContext); var selectionSet = new SelectionSetNode( null, diff --git a/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/Nodes/SelectionPlanNode.cs b/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/Nodes/SelectionPlanNode.cs index ce8cfc9fe12..1837460805d 100644 --- a/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/Nodes/SelectionPlanNode.cs +++ b/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/Nodes/SelectionPlanNode.cs @@ -152,7 +152,7 @@ public bool RemoveDirective(CompositeDirective directive) private void InitializeConditions() { - if(_isConditional.HasValue) + if (_isConditional.HasValue) { return; } @@ -170,7 +170,7 @@ private void InitializeConditions() continue; } - if (directive.Name.Value.Equals("skip")) + if (directive.Name.Value.Equals("include")) { _includeVariable = GetVariableName(directive); } diff --git a/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/OperationPlanner.cs b/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/OperationPlanner.cs index ebcd5dda618..f0adf7d5a56 100644 --- a/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/OperationPlanner.cs +++ b/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/OperationPlanner.cs @@ -31,7 +31,7 @@ public RootPlanNode CreatePlan(DocumentNode document, string? operationName) var context = new PlaningContext(operation, operation, ImmutableStack.Empty); if (TryPlanSelectionSet(context)) { - PlanConditionNode(operation, operation.Selections); + TryMakeOperationConditional(operation, operation.Selections); operationPlan.AddOperation(operation); } } @@ -275,7 +275,7 @@ private bool TryHandleUnresolvedSelections( } schemasInContext.Add(schemaName, lookupOperation); - PlanConditionNode(lookupOperation, lookupField.Selections); + TryMakeOperationConditional(lookupOperation, lookupField.Selections); // we add the lookup operation to all the schemas that we have requirements with. foreach (var requiredSchema in fieldSchemaDependencies.Values.Distinct()) @@ -607,7 +607,7 @@ private static FieldNode CreateFieldNodeFromPath(FieldPath path) return current!; } - private void PlanConditionNode( + private void TryMakeOperationConditional( OperationPlanNode operation, IReadOnlyList selections) { @@ -655,9 +655,8 @@ private void PlanConditionNode( } } - private bool IsSelectionAlwaysSkipped(ISelectionNode selectionNode) + private static bool IsSelectionAlwaysSkipped(ISelectionNode selectionNode) { - var selectionIsSkipped = false; foreach (var directive in selectionNode.Directives) { var isSkipDirective = directive.Name.Value == "skip"; @@ -673,26 +672,19 @@ private bool IsSelectionAlwaysSkipped(ISelectionNode selectionNode) { if (booleanValueNode.Value && isSkipDirective) { - selectionIsSkipped = true; + return true; } - else if (!booleanValueNode.Value && isIncludedDirective) - { - selectionIsSkipped = true; - } - else + + if (!booleanValueNode.Value && isIncludedDirective) { - selectionIsSkipped = false; + return true; } } - else - { - selectionIsSkipped = false; - } } } } - return selectionIsSkipped; + return false; } private string GetNextRequirementName() diff --git a/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/OperationVariableBinder.cs b/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/OperationVariableBinder.cs index 488c4fafd59..ecea116fab9 100644 --- a/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/OperationVariableBinder.cs +++ b/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/OperationVariableBinder.cs @@ -9,7 +9,7 @@ public static void BindOperationVariables( OperationDefinitionNode operationDefinition, RootPlanNode operationPlan) { - var operationBacklog = new Stack(operationPlan.Operations.OfType()); + var operationBacklog = new Stack(operationPlan.Operations); var selectionBacklog = new Stack(); var variableDefinitions = operationDefinition.VariableDefinitions.ToDictionary(t => t.Variable.Name.Value); var usedVariables = new HashSet(); @@ -18,7 +18,7 @@ public static void BindOperationVariables( { CollectAndBindUsedVariables(operation, variableDefinitions, usedVariables, selectionBacklog); - foreach (var child in operation.Dependants.OfType()) + foreach (var child in operation.Dependants) { operationBacklog.Push(child); } diff --git a/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/PlanNodeJsonFormatter.cs b/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/PlanNodeJsonFormatter.cs index 33e1c110675..bc018a872ac 100644 --- a/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/PlanNodeJsonFormatter.cs +++ b/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/PlanNodeJsonFormatter.cs @@ -7,6 +7,13 @@ namespace HotChocolate.Fusion.Planning; public static class PlanNodeJsonFormatter { + public static void FormatToJson(this RootPlanNode root, IBufferWriter writer) + { + var jsonWriter = new Utf8JsonWriter(writer, new JsonWriterOptions { Indented = true }); + jsonWriter.Write(root); + jsonWriter.Flush(); + } + public static string ToJson(this RootPlanNode root) { var buffer = new ArrayBufferWriter(); @@ -16,7 +23,7 @@ public static string ToJson(this RootPlanNode root) return Encoding.UTF8.GetString(buffer.WrittenSpan); } - public static void Write(this Utf8JsonWriter writer, RootPlanNode root) + private static void Write(this Utf8JsonWriter writer, RootPlanNode root) { var nodeIdLookup = CollectNodeIds(root); diff --git a/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/PlanNodeYamlFormatter.cs b/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/PlanNodeYamlFormatter.cs index 282a08e0349..9734e5196af 100644 --- a/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/PlanNodeYamlFormatter.cs +++ b/src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/PlanNodeYamlFormatter.cs @@ -1,4 +1,5 @@ using System.Buffers; +using System.Buffers.Text; using System.Text; using System.Text.Json; using HotChocolate.Fusion.Planning.Nodes; @@ -7,6 +8,14 @@ namespace HotChocolate.Fusion.Planning; public static class PlanNodeYamlFormatter { + public static void FormatToYaml(this RootPlanNode root, IBufferWriter writer) + { + var yaml = root.ToYaml(); + + // Performance go brrr + writer.Write(Encoding.UTF8.GetBytes(yaml)); + } + public static string ToYaml(this RootPlanNode root) { var sb = new StringBuilder(); @@ -16,7 +25,7 @@ public static string ToYaml(this RootPlanNode root) return sb.ToString(); } - public static void Write(this StringWriter writer, RootPlanNode root) + private static void Write(this StringWriter writer, RootPlanNode root) { var nodeIdLookup = CollectNodeIds(root); @@ -57,7 +66,7 @@ private static void WriteOperationNode( if (operation.IncludeVariable is not null) { - writer.WriteLine(" includeIf: \"{0}\"", operation.SkipVariable); + writer.WriteLine(" includeIf: \"{0}\"", operation.IncludeVariable); } if (operation.Requirements.Count > 0) diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests.cs b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests.cs deleted file mode 100644 index 70579d76eb0..00000000000 --- a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests.cs +++ /dev/null @@ -1,829 +0,0 @@ -using HotChocolate.Fusion.Planning; - -namespace HotChocolate.Fusion; - -public class ConditionTests : FusionTestBase -{ - [Test] - public void Skip_On_SubField() - { - // arrange - var compositeSchema = CreateCompositeSchema(); - - // act - var plan = PlanOperationAsync( - compositeSchema, - """ - query GetProduct($id: ID!, $skip: Boolean!) { - productById(id: $id) { - name @skip(if: $skip) - description - } - } - """); - - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - query($id: ID!, $skip: Boolean!) { - productById(id: $id) { - name @skip(if: $skip) - description - } - } - - """); - } - - [Test] - public void Skip_On_SubField_If_False() - { - // arrange - var compositeSchema = CreateCompositeSchema(); - - // act - var plan = PlanOperationAsync( - compositeSchema, - """ - query GetProduct($id: ID!) { - productById(id: $id) { - name @skip(if: false) - description - } - } - """); - - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - query($id: ID!) { - productById(id: $id) { - name - description - } - } - - """); - } - - [Test] - public void Skip_On_SubField_If_True() - { - // arrange - var compositeSchema = CreateCompositeSchema(); - - // act - var plan = PlanOperationAsync( - compositeSchema, - """ - query GetProduct($id: ID!) { - productById(id: $id) { - name @skip(if: true) - description - } - } - """); - - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - query($id: ID!) { - productById(id: $id) { - description - } - } - - """); - } - - [Test] - public void Skip_On_SubField_Only_Skipped_Field_Selected() - { - // arrange - var compositeSchema = CreateCompositeSchema(); - - // act - var plan = PlanOperationAsync( - compositeSchema, - """ - query GetProduct($id: ID!, $skip: Boolean!) { - productById(id: $id) { - name @skip(if: $skip) - } - } - """); - - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - query($id: ID!, $skip: Boolean!) { - productById(id: $id) { - name @skip(if: $skip) - } - } - - """); - } - - [Test] - public void Skip_On_SubField_Only_Skipped_Field_Selected_If_False() - { - // arrange - var compositeSchema = CreateCompositeSchema(); - - // act - var plan = PlanOperationAsync( - compositeSchema, - """ - query GetProduct($id: ID!) { - productById(id: $id) { - name @skip(if: false) - } - } - """); - - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - query($id: ID!) { - productById(id: $id) { - name - } - } - - """); - } - - [Test] - public void Skip_On_SubField_Only_Skipped_Field_Selected_If_True() - { - // arrange - var compositeSchema = CreateCompositeSchema(); - - // act - var plan = PlanOperationAsync( - compositeSchema, - """ - query GetProduct($id: ID!) { - productById(id: $id) { - name @skip(if: true) - } - } - """); - - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - query($id: ID!) { - productById(id: $id) { - __typename - } - } - - """); - } - - [Test] - public void Skip_On_SubField_Resolved_From_Other_Source() - { - // arrange - var compositeSchema = CreateCompositeSchema(); - - // act - var plan = PlanOperationAsync( - compositeSchema, - """ - query GetProduct($id: ID!, $skip: Boolean!) { - productById(id: $id) { - name - averageRating - reviews(first: 10) @skip(if: $skip) { - nodes { - body - } - } - } - } - """); - - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - query($id: ID!) { - productById(id: $id) { - name - id - } - } - - id: 2 - schema: "REVIEWS" - operation: >- - query($__fusion_requirement_1: ID!, $skip: Boolean!) { - productById(id: $__fusion_requirement_1) { - averageRating - reviews(first: 10) @skip(if: $skip) { - nodes { - body - } - } - } - } - requirements: - - name: "__fusion_requirement_1" - dependsOn: "1" - selectionSet: "productById" - field: "id" - type: "ID!" - - """); - } - - [Test] - public void Skip_On_SubField_Resolved_From_Other_Source_If_False() - { - // arrange - var compositeSchema = CreateCompositeSchema(); - - // act - var plan = PlanOperationAsync( - compositeSchema, - """ - query GetProduct($id: ID!) { - productById(id: $id) { - name - averageRating - reviews(first: 10) @skip(if: false) { - nodes { - body - } - } - } - } - """); - - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - query($id: ID!) { - productById(id: $id) { - name - id - } - } - - id: 2 - schema: "REVIEWS" - operation: >- - query($__fusion_requirement_1: ID!) { - productById(id: $__fusion_requirement_1) { - averageRating - reviews(first: 10) { - nodes { - body - } - } - } - } - requirements: - - name: "__fusion_requirement_1" - dependsOn: "1" - selectionSet: "productById" - field: "id" - type: "ID!" - - """); - } - - [Test] - public void Skip_On_SubField_Resolved_From_Other_Source_If_True() - { - // arrange - var compositeSchema = CreateCompositeSchema(); - - // act - var plan = PlanOperationAsync( - compositeSchema, - """ - query GetProduct($id: ID!) { - productById(id: $id) { - name - averageRating - reviews(first: 10) @skip(if: true) { - nodes { - body - } - } - } - } - """); - - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - query($id: ID!) { - productById(id: $id) { - name - id - } - } - - id: 2 - schema: "REVIEWS" - operation: >- - query($__fusion_requirement_1: ID!) { - productById(id: $__fusion_requirement_1) { - averageRating - } - } - requirements: - - name: "__fusion_requirement_1" - dependsOn: "1" - selectionSet: "productById" - field: "id" - type: "ID!" - - """); - } - - [Test] - public void Skip_On_SubField_Resolved_From_Other_Source_Only_Skipped_Field_Selected() - { - // arrange - var compositeSchema = CreateCompositeSchema(); - - // act - var plan = PlanOperationAsync( - compositeSchema, - """ - query GetProduct($id: ID!, $skip: Boolean!) { - productById(id: $id) { - name - reviews(first: 10) @skip(if: $skip) { - nodes { - body - } - } - } - } - """); - - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - query($id: ID!) { - productById(id: $id) { - name - id - } - } - - id: 2 - schema: "REVIEWS" - operation: >- - query($__fusion_requirement_1: ID!) { - productById(id: $__fusion_requirement_1) { - reviews(first: 10) { - nodes { - body - } - } - } - } - skipIf: "skip" - requirements: - - name: "__fusion_requirement_1" - dependsOn: "1" - selectionSet: "productById" - field: "id" - type: "ID!" - - """); - } - - [Test] - public void Skip_On_SubField_Resolved_From_Other_Source_Only_Skipped_Field_Selected_If_False() - { - // arrange - var compositeSchema = CreateCompositeSchema(); - - // act - var plan = PlanOperationAsync( - compositeSchema, - """ - query GetProduct($id: ID!) { - productById(id: $id) { - name - reviews(first: 10) @skip(if: false) { - nodes { - body - } - } - } - } - """); - - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - query($id: ID!) { - productById(id: $id) { - name - id - } - } - - id: 2 - schema: "REVIEWS" - operation: >- - query($__fusion_requirement_1: ID!) { - productById(id: $__fusion_requirement_1) { - reviews(first: 10) { - nodes { - body - } - } - } - } - requirements: - - name: "__fusion_requirement_1" - dependsOn: "1" - selectionSet: "productById" - field: "id" - type: "ID!" - - """); - } - - [Test] - public void Skip_On_SubField_Resolved_From_Other_Source_Only_Skipped_Field_Selected_If_True() - { - // arrange - var compositeSchema = CreateCompositeSchema(); - - // act - var plan = PlanOperationAsync( - compositeSchema, - """ - query GetProduct($id: ID!) { - productById(id: $id) { - name - reviews(first: 10) @skip(if: true) { - nodes { - body - } - } - } - } - """); - - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - query($id: ID!) { - productById(id: $id) { - name - } - } - - """); - } - - [Test] - public void Skip_On_RootField() - { - // arrange - var compositeSchema = CreateCompositeSchema(); - - // act - var plan = PlanOperationAsync( - compositeSchema, - """ - query GetProduct($id: ID!, $skip: Boolean!) { - productById(id: $id) @skip(if: $skip) { - name - } - products { - nodes { - name - } - } - } - """); - - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - query($id: ID!, $skip: Boolean!) { - productById(id: $id) @skip(if: $skip) { - name - } - products { - nodes { - name - } - } - } - - """); - } - - [Test] - public void Skip_On_RootField_If_False() - { - // arrange - var compositeSchema = CreateCompositeSchema(); - - // act - var plan = PlanOperationAsync( - compositeSchema, - """ - query GetProduct($id: ID!) { - productById(id: $id) @skip(if: false) { - name - } - products { - nodes { - name - } - } - } - """); - - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - query($id: ID!) { - productById(id: $id) { - name - } - products { - nodes { - name - } - } - } - - """); - } - - [Test] - public void Skip_On_RootField_If_True() - { - // arrange - var compositeSchema = CreateCompositeSchema(); - - // act - var plan = PlanOperationAsync( - compositeSchema, - """ - query GetProduct($id: ID!) { - productById(id: $id) @skip(if: true) { - name - } - products { - nodes { - name - } - } - } - """); - - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - { - products { - nodes { - name - } - } - } - - """); - } - - [Test] - public void Skip_On_RootField_Only_Skipped_Field_Selected() - { - // arrange - var compositeSchema = CreateCompositeSchema(); - - // act - var plan = PlanOperationAsync( - compositeSchema, - """ - query GetProduct($id: ID!, $skip: Boolean!) { - productById(id: $id) @skip(if: $skip) { - name - } - } - """); - - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - query($id: ID!) { - productById(id: $id) { - name - } - } - skipIf: "skip" - - """); - } - - [Test] - public void Skip_On_RootField_Only_Skipped_Field_Selected_If_False() - { - // arrange - var compositeSchema = CreateCompositeSchema(); - - // act - var plan = PlanOperationAsync( - compositeSchema, - """ - query GetProduct($id: ID!) { - productById(id: $id) @skip(if: false) { - name - } - } - """); - - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - query($id: ID!) { - productById(id: $id) { - name - } - } - - """); - } - - [Test] - public void Skip_On_RootField_Only_Skipped_Field_Selected_If_True() - { - // arrange - var compositeSchema = CreateCompositeSchema(); - - // act - var plan = PlanOperationAsync( - compositeSchema, - """ - query GetProduct($id: ID!) { - productById(id: $id) @skip(if: true) { - name - } - } - """); - - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - """); - } - - [Test] - public void Skip_And_Include_On_RootField_Only_Skipped_Field_Selected() - { - // arrange - var compositeSchema = CreateCompositeSchema(); - - // act - var plan = PlanOperationAsync( - compositeSchema, - """ - query GetProduct($id: ID!, $skip: Boolean!, $include: Boolean!) { - productById(id: $id) @skip(if: $skip) @include(if: $include) { - name - } - } - """); - - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - query($id: ID!) { - productById(id: $id) { - name - } - } - skipIf: "skip" - - """); - } - - [Test] - public void Skip_And_Include_On_RootField() - { - // arrange - var compositeSchema = CreateCompositeSchema(); - - // act - var plan = PlanOperationAsync( - compositeSchema, - """ - query GetProduct($id: ID!, $skip: Boolean!, $include: Boolean!) { - productById(id: $id) @skip(if: $skip) @include(if: $include) { - name - } - products { - nodes { - name - } - } - } - """); - - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - query($id: ID!, $include: Boolean!, $skip: Boolean!) { - productById(id: $id) @skip(if: $skip) @include(if: $include) { - name - } - products { - nodes { - name - } - } - } - - """); - } -} diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/SkipAndIncludeTests.cs b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/SkipAndIncludeTests.cs new file mode 100644 index 00000000000..faa3c9f7c5a --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/SkipAndIncludeTests.cs @@ -0,0 +1,758 @@ +using static HotChocolate.Language.Utf8GraphQLParser; + +namespace HotChocolate.Fusion; + +public class SkipAndIncludeTests : FusionTestBase +{ + [Test] + public async Task Skip_And_Include_On_RootField() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!, $skip: Boolean!, $include: Boolean!) { + productBySlug(slug: $slug) @skip(if: $skip) @include(if: $include) { + name + } + products { + nodes { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_RootField_With_Same_Variable() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!, $skipOrInclude: Boolean!) { + productBySlug(slug: $slug) @skip(if: $skipOrInclude) @include(if: $skipOrInclude) { + name + } + products { + nodes { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_RootField_Skip_False() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!, $include: Boolean!) { + productBySlug(slug: $slug) @include(if: $include) @skip(if: false) { + name + } + products { + nodes { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_RootField_Skip_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!, $include: Boolean!) { + productBySlug(slug: $slug) @include(if: $include) @skip(if: true) { + name + } + products { + nodes { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_RootField_Skip_True_Include_False() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!) { + productBySlug(slug: $slug) @skip(if: true) @include(if: false) { + name + } + products { + nodes { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_RootField_Skip_False_Include_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!) { + productBySlug(slug: $slug) @skip(if: false) @include(if: true) { + name + } + products { + nodes { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_RootField_Skip_True_Include_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!) { + productBySlug(slug: $slug) @skip(if: true) @include(if: true) { + name + } + products { + nodes { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_RootField_Skip_False_Include_False() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!) { + productBySlug(slug: $slug) @skip(if: false) @include(if: false) { + name + } + products { + nodes { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_RootField_Only_Skipped_Field_Selected() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!, $skip: Boolean!, $include: Boolean!) { + productBySlug(slug: $slug) @skip(if: $skip) @include(if: $include) { + name + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_With_Same_Variable() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!, $skipOrInclude: Boolean!) { + productBySlug(slug: $slug) @skip(if: $skipOrInclude) @include(if: $skipOrInclude) { + name + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_False() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!, $include: Boolean!) { + productBySlug(slug: $slug) @include(if: $include) @skip(if: false) { + name + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!, $include: Boolean!) { + productBySlug(slug: $slug) @include(if: $include) @skip(if: true) { + name + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_True_Include_False() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!) { + productBySlug(slug: $slug) @skip(if: true) @include(if: false) { + name + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_False_Include_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!) { + productBySlug(slug: $slug) @skip(if: false) @include(if: true) { + name + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_True_Include_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!) { + productBySlug(slug: $slug) @skip(if: true) @include(if: true) { + name + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_False_Include_False() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!) { + productBySlug(slug: $slug) @skip(if: false) @include(if: false) { + name + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_SubField() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!, $skip: Boolean!, $include: Boolean!) { + productBySlug(slug: $slug) { + name @skip(if: $skip) @include(if: $include) + description + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_SubField_With_Same_Variable() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!, $skipOrInclude: Boolean!) { + productBySlug(slug: $slug) { + name @skip(if: $skipOrInclude) @include(if: $skipOrInclude) + description + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_SubField_Skip_False() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!, $include: Boolean!) { + productBySlug(slug: $slug) { + name @include(if: $include) @skip(if: false) + description + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_SubField_Skip_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!, $include: Boolean!) { + productBySlug(slug: $slug) { + name @include(if: $include) @skip(if: true) + description + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_SubField_Skip_True_Include_False() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: true) @include(if: false) + description + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_SubField_Skip_False_Include_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: false) @include(if: true) + description + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_SubField_Skip_True_Include_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: true) @include(if: true) + description + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_SubField_Skip_False_Include_False() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: false) @include(if: false) + description + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_SubField_Only_Skipped_Field_Selected() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!, $skip: Boolean!, $include: Boolean!) { + productBySlug(slug: $slug) { + name @skip(if: $skip) @include(if: $include) + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_False() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!, $include: Boolean!) { + productBySlug(slug: $slug) { + name @include(if: $include) @skip(if: false) + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!, $include: Boolean!) { + productBySlug(slug: $slug) { + name @include(if: $include) @skip(if: true) + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_With_Same_Variable() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!, $skipOrInclude: Boolean!) { + productBySlug(slug: $slug) { + name @skip(if: $skipOrInclude) @include(if: $skipOrInclude) + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_True_Include_False() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: true) @include(if: false) + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_False_Include_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: false) @include(if: true) + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_True_Include_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: true) @include(if: true) + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_False_Include_False() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query GetProduct($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: false) @include(if: false) + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } +} diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/SkipTests.cs b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/SkipTests.cs new file mode 100644 index 00000000000..388b1bc3f8e --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/SkipTests.cs @@ -0,0 +1,644 @@ +using static HotChocolate.Language.Utf8GraphQLParser; + +namespace HotChocolate.Fusion; + +public class SkipTests : FusionTestBase +{ + [Test] + public async Task Skipped_Root_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!, $skip: Boolean!) { + productBySlug(slug: $slug) @skip(if: $skip) { + name + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skipped_Root_Selection_If_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) @skip(if: true) { + name + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skipped_Root_Selections_From_Same_Subgraph() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!, $skip1: Boolean!, $skip2: Boolean!) { + productBySlug(slug: $slug) @skip(if: $skip1) { + name + } + products @skip(if: $skip2) { + nodes { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skipped_Root_Selections_From_Same_Subgraph_Same_Variable() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!, $skip: Boolean!) { + productBySlug(slug: $slug) @skip(if: $skip) { + name + } + products @skip(if: $skip) { + nodes { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + [Skip("Not yet supported by the planner")] + public async Task Skipped_Root_Selections_From_Different_Subgraphs() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!, $skip1: Boolean!, $skip2: Boolean!) { + productBySlug(slug: $slug) @skip(if: $skip1) { + name + } + viewer @skip(if: $skip2) { + displayName + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + [Skip("Not yet supported by the planner")] + public async Task Skipped_Root_Selections_From_Different_Subgraphs_Same_Variable() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!, $skip: Boolean!) { + productBySlug(slug: $slug) @skip(if: $skip) { + name + } + viewer @skip(if: $skip) { + displayName + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + [Skip("Not yet supported by the planner")] + public async Task Skipped_Shared_Viewer_Root_Selection_With_Sub_Selections_From_Different_Subgraphs() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($skip: Boolean!) { + viewer @skip(if: $skip) { + displayName + reviews(first: 3) { + nodes { + body + } + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + [Skip("Not yet supported by the planner")] + public async Task Skipped_Shared_byId_Root_Selection_With_Sub_Selections_From_Different_Subgraphs() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($id: ID!) { + productById(id: $id) @skip(if: $skip) { + name + averageRating + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skipped_Root_Selection_Other_Not_Skipped_Root_Selection_From_Same_Subgraph() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!, $skip: Boolean!) { + productBySlug(slug: $slug) @skip(if: $skip) { + name + } + products { + nodes { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skipped_Root_Selection_Other_Not_Skipped_Root_Selection_From_Same_Subgraph_If_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) @skip(if: true) { + name + } + products { + nodes { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + [Skip("Not yet supported by the planner")] + public async Task Skipped_Root_Selection_Other_Not_Skipped_Root_Selection_From_Different_Subgraph() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!, $skip: Boolean!) { + productBySlug(slug: $slug) @skip(if: $skip) { + name + } + viewer { + displayName + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + [Skip("Not yet supported by the planner")] + public async Task Skipped_Root_Selection_Other_Not_Skipped_Root_Selection_From_Different_Subgraph_If_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) @skip(if: true) { + name + } + viewer { + displayName + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skipped_Sub_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!, $skip: Boolean!) { + productBySlug(slug: $slug) { + name @skip(if: $skip) + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skipped_Sub_Selection_If_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: true) + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skipped_Sub_Selection_Other_Not_Skipped_Sub_Selection_From_Same_Subgraph() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!, $skip: Boolean!) { + productBySlug(slug: $slug) { + name @skip(if: $skip) + description + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skipped_Sub_Selection_Other_Not_Skipped_Sub_Selection_From_Same_Subgraph_If_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: true) + description + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skipped_Sub_Selection_Other_Not_Skipped_Sub_Selection_From_Different_Subgraph() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!, $skip: Boolean!) { + productBySlug(slug: $slug) { + name @skip(if: $skip) + averageRating + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skipped_Sub_Selection_Other_Not_Skipped_Sub_Selection_From_Different_Subgraph_If_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: true) + averageRating + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skipped_Sub_Selection_From_Different_Subgraph() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!, $skip: Boolean!) { + productBySlug(slug: $slug) { + averageRating @skip(if: $skip) + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skipped_Sub_Selection_From_Different_Subgraph_If_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + averageRating @skip(if: true) + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skipped_Sub_Selection_From_Different_Subgraph_Other_Not_Skipped_Sub_Selection_From_First_Subgraph() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!, $skip: Boolean!) { + productBySlug(slug: $slug) { + name + averageRating @skip(if: $skip) + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skipped_Sub_Selection_From_Different_Subgraph_Other_Not_Skipped_Sub_Selection_From_First_Subgraph_If_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + name + averageRating @skip(if: true) + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skipped_Sub_Selection_From_Different_Subgraph_Other_Not_Skipped_Sub_Selection_From_Same_Subgraph() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!, $skip: Boolean!) { + productBySlug(slug: $slug) { + averageRating @skip(if: $skip) + reviews(first: 10) { + nodes { + body + } + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skipped_Sub_Selection_From_Different_Subgraph_Other_Not_Skipped_Sub_Selection_From_Same_Subgraph_If_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + averageRating @skip(if: true) + reviews(first: 10) { + nodes { + body + } + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skipped_Sub_Selection_That_Provides_Data_For_Lookup_On_Different_Subgraph() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($id: ID!, $skip: Boolean!) { + reviewById(id: $id) { + body + author @skip(if: $skip) { + displayName + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Skipped_Sub_Selection_That_Provides_Data_For_Lookup_On_Different_Subgraph_If_True() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($id: ID!) { + reviewById(id: $id) { + body + author @skip(if: true) { + displayName + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } +} diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField.md new file mode 100644 index 00000000000..52fa269d7e2 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField.md @@ -0,0 +1,37 @@ +# Skip_And_Include_On_RootField + +## Request + +```graphql +query GetProduct($slug: String!, $skip: Boolean!, $include: Boolean!) { + productBySlug(slug: $slug) @skip(if: $skip) @include(if: $include) { + name + } + products { + nodes { + name + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($include: Boolean!, $skip: Boolean!, $slug: String!) { + productBySlug(slug: $slug) @skip(if: $skip) @include(if: $include) { + name + } + products { + nodes { + name + } + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected.md new file mode 100644 index 00000000000..605931ef791 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected.md @@ -0,0 +1,29 @@ +# Skip_And_Include_On_RootField_Only_Skipped_Field_Selected + +## Request + +```graphql +query GetProduct($slug: String!, $skip: Boolean!, $include: Boolean!) { + productBySlug(slug: $slug) @skip(if: $skip) @include(if: $include) { + name + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + } + skipIf: "skip" + includeIf: "include" + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_False.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_False.md new file mode 100644 index 00000000000..7369445dd6d --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_False.md @@ -0,0 +1,28 @@ +# Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_False + +## Request + +```graphql +query GetProduct($slug: String!, $include: Boolean!) { + productBySlug(slug: $slug) @include(if: $include) @skip(if: false) { + name + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + } + includeIf: "include" + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_False_Include_False.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_False_Include_False.md new file mode 100644 index 00000000000..96b4871092b --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_False_Include_False.md @@ -0,0 +1,19 @@ +# Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_False_Include_False + +## Request + +```graphql +query GetProduct($slug: String!) { + productBySlug(slug: $slug) @skip(if: false) @include(if: false) { + name + } +} +``` + +## Plan + +```yaml +nodes: + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_False_Include_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_False_Include_True.md new file mode 100644 index 00000000000..5013c356859 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_False_Include_True.md @@ -0,0 +1,27 @@ +# Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_False_Include_True + +## Request + +```graphql +query GetProduct($slug: String!) { + productBySlug(slug: $slug) @skip(if: false) @include(if: true) { + name + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_True.md new file mode 100644 index 00000000000..4b790daa492 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_True.md @@ -0,0 +1,19 @@ +# Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_True + +## Request + +```graphql +query GetProduct($slug: String!, $include: Boolean!) { + productBySlug(slug: $slug) @include(if: $include) @skip(if: true) { + name + } +} +``` + +## Plan + +```yaml +nodes: + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_True_Include_False.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_True_Include_False.md new file mode 100644 index 00000000000..2a36a3e4cc0 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_True_Include_False.md @@ -0,0 +1,19 @@ +# Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_True_Include_False + +## Request + +```graphql +query GetProduct($slug: String!) { + productBySlug(slug: $slug) @skip(if: true) @include(if: false) { + name + } +} +``` + +## Plan + +```yaml +nodes: + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_True_Include_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_True_Include_True.md new file mode 100644 index 00000000000..ba590d0ddcb --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_True_Include_True.md @@ -0,0 +1,19 @@ +# Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_Skip_True_Include_True + +## Request + +```graphql +query GetProduct($slug: String!) { + productBySlug(slug: $slug) @skip(if: true) @include(if: true) { + name + } +} +``` + +## Plan + +```yaml +nodes: + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_With_Same_Variable.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_With_Same_Variable.md new file mode 100644 index 00000000000..2d04961d212 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_With_Same_Variable.md @@ -0,0 +1,29 @@ +# Skip_And_Include_On_RootField_Only_Skipped_Field_Selected_With_Same_Variable + +## Request + +```graphql +query GetProduct($slug: String!, $skipOrInclude: Boolean!) { + productBySlug(slug: $slug) @skip(if: $skipOrInclude) @include(if: $skipOrInclude) { + name + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + } + skipIf: "skipOrInclude" + includeIf: "skipOrInclude" + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Skip_False.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Skip_False.md new file mode 100644 index 00000000000..3808fb26180 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Skip_False.md @@ -0,0 +1,37 @@ +# Skip_And_Include_On_RootField_Skip_False + +## Request + +```graphql +query GetProduct($slug: String!, $include: Boolean!) { + productBySlug(slug: $slug) @include(if: $include) @skip(if: false) { + name + } + products { + nodes { + name + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($include: Boolean!, $slug: String!) { + productBySlug(slug: $slug) @include(if: $include) { + name + } + products { + nodes { + name + } + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Skip_False_Include_False.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Skip_False_Include_False.md new file mode 100644 index 00000000000..dd036fb39f8 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Skip_False_Include_False.md @@ -0,0 +1,34 @@ +# Skip_And_Include_On_RootField_Skip_False_Include_False + +## Request + +```graphql +query GetProduct($slug: String!) { + productBySlug(slug: $slug) @skip(if: false) @include(if: false) { + name + } + products { + nodes { + name + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + { + products { + nodes { + name + } + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Skip_False_Include_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Skip_False_Include_True.md new file mode 100644 index 00000000000..a114c252797 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Skip_False_Include_True.md @@ -0,0 +1,37 @@ +# Skip_And_Include_On_RootField_Skip_False_Include_True + +## Request + +```graphql +query GetProduct($slug: String!) { + productBySlug(slug: $slug) @skip(if: false) @include(if: true) { + name + } + products { + nodes { + name + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + products { + nodes { + name + } + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Skip_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Skip_True.md new file mode 100644 index 00000000000..197b7c0fd3e --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Skip_True.md @@ -0,0 +1,34 @@ +# Skip_And_Include_On_RootField_Skip_True + +## Request + +```graphql +query GetProduct($slug: String!, $include: Boolean!) { + productBySlug(slug: $slug) @include(if: $include) @skip(if: true) { + name + } + products { + nodes { + name + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + { + products { + nodes { + name + } + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Skip_True_Include_False.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Skip_True_Include_False.md new file mode 100644 index 00000000000..7a5731ef79f --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Skip_True_Include_False.md @@ -0,0 +1,34 @@ +# Skip_And_Include_On_RootField_Skip_True_Include_False + +## Request + +```graphql +query GetProduct($slug: String!) { + productBySlug(slug: $slug) @skip(if: true) @include(if: false) { + name + } + products { + nodes { + name + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + { + products { + nodes { + name + } + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Skip_True_Include_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Skip_True_Include_True.md new file mode 100644 index 00000000000..8eff4294f3d --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_Skip_True_Include_True.md @@ -0,0 +1,34 @@ +# Skip_And_Include_On_RootField_Skip_True_Include_True + +## Request + +```graphql +query GetProduct($slug: String!) { + productBySlug(slug: $slug) @skip(if: true) @include(if: true) { + name + } + products { + nodes { + name + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + { + products { + nodes { + name + } + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_With_Same_Variable.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_With_Same_Variable.md new file mode 100644 index 00000000000..26a7760fc37 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_RootField_With_Same_Variable.md @@ -0,0 +1,37 @@ +# Skip_And_Include_On_RootField_With_Same_Variable + +## Request + +```graphql +query GetProduct($slug: String!, $skipOrInclude: Boolean!) { + productBySlug(slug: $slug) @skip(if: $skipOrInclude) @include(if: $skipOrInclude) { + name + } + products { + nodes { + name + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($skipOrInclude: Boolean!, $slug: String!) { + productBySlug(slug: $slug) @skip(if: $skipOrInclude) @include(if: $skipOrInclude) { + name + } + products { + nodes { + name + } + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField.md new file mode 100644 index 00000000000..97fbdd9d84d --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField.md @@ -0,0 +1,29 @@ +# Skip_And_Include_On_SubField + +## Request + +```graphql +query GetProduct($slug: String!, $skip: Boolean!, $include: Boolean!) { + productBySlug(slug: $slug) { + name @skip(if: $skip) @include(if: $include) + description + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($include: Boolean!, $skip: Boolean!, $slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: $skip) @include(if: $include) + description + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected.md new file mode 100644 index 00000000000..373b828ebb1 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected.md @@ -0,0 +1,27 @@ +# Skip_And_Include_On_SubField_Only_Skipped_Field_Selected + +## Request + +```graphql +query GetProduct($slug: String!, $skip: Boolean!, $include: Boolean!) { + productBySlug(slug: $slug) { + name @skip(if: $skip) @include(if: $include) + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($include: Boolean!, $skip: Boolean!, $slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: $skip) @include(if: $include) + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_False.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_False.md new file mode 100644 index 00000000000..77537355e03 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_False.md @@ -0,0 +1,27 @@ +# Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_False + +## Request + +```graphql +query GetProduct($slug: String!, $include: Boolean!) { + productBySlug(slug: $slug) { + name @include(if: $include) @skip(if: false) + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($include: Boolean!, $slug: String!) { + productBySlug(slug: $slug) { + name @include(if: $include) + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_False_Include_False.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_False_Include_False.md new file mode 100644 index 00000000000..201f59618b7 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_False_Include_False.md @@ -0,0 +1,27 @@ +# Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_False_Include_False + +## Request + +```graphql +query GetProduct($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: false) @include(if: false) + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + __typename + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_False_Include_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_False_Include_True.md new file mode 100644 index 00000000000..7facc426143 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_False_Include_True.md @@ -0,0 +1,27 @@ +# Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_False_Include_True + +## Request + +```graphql +query GetProduct($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: false) @include(if: true) + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_True.md new file mode 100644 index 00000000000..79a8a841d14 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_True.md @@ -0,0 +1,27 @@ +# Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_True + +## Request + +```graphql +query GetProduct($slug: String!, $include: Boolean!) { + productBySlug(slug: $slug) { + name @include(if: $include) @skip(if: true) + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + __typename + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_True_Include_False.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_True_Include_False.md new file mode 100644 index 00000000000..b93c3f4ae5f --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_True_Include_False.md @@ -0,0 +1,27 @@ +# Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_True_Include_False + +## Request + +```graphql +query GetProduct($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: true) @include(if: false) + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + __typename + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_True_Include_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_True_Include_True.md new file mode 100644 index 00000000000..ee54f506afd --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_True_Include_True.md @@ -0,0 +1,27 @@ +# Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_Skip_True_Include_True + +## Request + +```graphql +query GetProduct($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: true) @include(if: true) + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + __typename + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_With_Same_Variable.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_With_Same_Variable.md new file mode 100644 index 00000000000..7c531b14d5f --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_With_Same_Variable.md @@ -0,0 +1,27 @@ +# Skip_And_Include_On_SubField_Only_Skipped_Field_Selected_With_Same_Variable + +## Request + +```graphql +query GetProduct($slug: String!, $skipOrInclude: Boolean!) { + productBySlug(slug: $slug) { + name @skip(if: $skipOrInclude) @include(if: $skipOrInclude) + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($skipOrInclude: Boolean!, $slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: $skipOrInclude) @include(if: $skipOrInclude) + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Skip_False.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Skip_False.md new file mode 100644 index 00000000000..7cd38a5d69d --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Skip_False.md @@ -0,0 +1,29 @@ +# Skip_And_Include_On_SubField_Skip_False + +## Request + +```graphql +query GetProduct($slug: String!, $include: Boolean!) { + productBySlug(slug: $slug) { + name @include(if: $include) @skip(if: false) + description + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($include: Boolean!, $slug: String!) { + productBySlug(slug: $slug) { + name @include(if: $include) + description + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Skip_False_Include_False.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Skip_False_Include_False.md new file mode 100644 index 00000000000..9517e286090 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Skip_False_Include_False.md @@ -0,0 +1,28 @@ +# Skip_And_Include_On_SubField_Skip_False_Include_False + +## Request + +```graphql +query GetProduct($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: false) @include(if: false) + description + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + description + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Skip_False_Include_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Skip_False_Include_True.md new file mode 100644 index 00000000000..82cfe97329d --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Skip_False_Include_True.md @@ -0,0 +1,29 @@ +# Skip_And_Include_On_SubField_Skip_False_Include_True + +## Request + +```graphql +query GetProduct($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: false) @include(if: true) + description + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + description + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Skip_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Skip_True.md new file mode 100644 index 00000000000..3050446b018 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Skip_True.md @@ -0,0 +1,28 @@ +# Skip_And_Include_On_SubField_Skip_True + +## Request + +```graphql +query GetProduct($slug: String!, $include: Boolean!) { + productBySlug(slug: $slug) { + name @include(if: $include) @skip(if: true) + description + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + description + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Skip_True_Include_False.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Skip_True_Include_False.md new file mode 100644 index 00000000000..3fcbf964339 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Skip_True_Include_False.md @@ -0,0 +1,28 @@ +# Skip_And_Include_On_SubField_Skip_True_Include_False + +## Request + +```graphql +query GetProduct($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: true) @include(if: false) + description + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + description + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Skip_True_Include_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Skip_True_Include_True.md new file mode 100644 index 00000000000..7c62d8479f6 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_Skip_True_Include_True.md @@ -0,0 +1,28 @@ +# Skip_And_Include_On_SubField_Skip_True_Include_True + +## Request + +```graphql +query GetProduct($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: true) @include(if: true) + description + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + description + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_With_Same_Variable.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_With_Same_Variable.md new file mode 100644 index 00000000000..c14b4fbb90b --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipAndIncludeTests.Skip_And_Include_On_SubField_With_Same_Variable.md @@ -0,0 +1,29 @@ +# Skip_And_Include_On_SubField_With_Same_Variable + +## Request + +```graphql +query GetProduct($slug: String!, $skipOrInclude: Boolean!) { + productBySlug(slug: $slug) { + name @skip(if: $skipOrInclude) @include(if: $skipOrInclude) + description + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($skipOrInclude: Boolean!, $slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: $skipOrInclude) @include(if: $skipOrInclude) + description + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Root_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Root_Selection.md new file mode 100644 index 00000000000..f2d983b0d4e --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Root_Selection.md @@ -0,0 +1,28 @@ +# Skipped_Root_Selection + +## Request + +```graphql +query($slug: String!, $skip: Boolean!) { + productBySlug(slug: $slug) @skip(if: $skip) { + name + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + } + skipIf: "skip" + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Root_Selection_If_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Root_Selection_If_True.md new file mode 100644 index 00000000000..aad60ae4a96 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Root_Selection_If_True.md @@ -0,0 +1,19 @@ +# Skipped_Root_Selection_If_True + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) @skip(if: true) { + name + } +} +``` + +## Plan + +```yaml +nodes: + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Root_Selection_Other_Not_Skipped_Root_Selection_From_Same_Subgraph.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Root_Selection_Other_Not_Skipped_Root_Selection_From_Same_Subgraph.md new file mode 100644 index 00000000000..befb1c096bc --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Root_Selection_Other_Not_Skipped_Root_Selection_From_Same_Subgraph.md @@ -0,0 +1,37 @@ +# Skipped_Root_Selection_Other_Not_Skipped_Root_Selection_From_Same_Subgraph + +## Request + +```graphql +query($slug: String!, $skip: Boolean!) { + productBySlug(slug: $slug) @skip(if: $skip) { + name + } + products { + nodes { + name + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($skip: Boolean!, $slug: String!) { + productBySlug(slug: $slug) @skip(if: $skip) { + name + } + products { + nodes { + name + } + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Root_Selection_Other_Not_Skipped_Root_Selection_From_Same_Subgraph_If_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Root_Selection_Other_Not_Skipped_Root_Selection_From_Same_Subgraph_If_True.md new file mode 100644 index 00000000000..b356f79dadf --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Root_Selection_Other_Not_Skipped_Root_Selection_From_Same_Subgraph_If_True.md @@ -0,0 +1,34 @@ +# Skipped_Root_Selection_Other_Not_Skipped_Root_Selection_From_Same_Subgraph_If_True + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) @skip(if: true) { + name + } + products { + nodes { + name + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + { + products { + nodes { + name + } + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Root_Selections_From_Same_Subgraph.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Root_Selections_From_Same_Subgraph.md new file mode 100644 index 00000000000..9b6de5baa6e --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Root_Selections_From_Same_Subgraph.md @@ -0,0 +1,37 @@ +# Skipped_Root_Selections_From_Same_Subgraph + +## Request + +```graphql +query($slug: String!, $skip1: Boolean!, $skip2: Boolean!) { + productBySlug(slug: $slug) @skip(if: $skip1) { + name + } + products @skip(if: $skip2) { + nodes { + name + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($skip1: Boolean!, $skip2: Boolean!, $slug: String!) { + productBySlug(slug: $slug) @skip(if: $skip1) { + name + } + products @skip(if: $skip2) { + nodes { + name + } + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Root_Selections_From_Same_Subgraph_Same_Variable.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Root_Selections_From_Same_Subgraph_Same_Variable.md new file mode 100644 index 00000000000..548cddba739 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Root_Selections_From_Same_Subgraph_Same_Variable.md @@ -0,0 +1,38 @@ +# Skipped_Root_Selections_From_Same_Subgraph_Same_Variable + +## Request + +```graphql +query($slug: String!, $skip: Boolean!) { + productBySlug(slug: $slug) @skip(if: $skip) { + name + } + products @skip(if: $skip) { + nodes { + name + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + products { + nodes { + name + } + } + } + skipIf: "skip" + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection.md new file mode 100644 index 00000000000..12eaccbf72f --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection.md @@ -0,0 +1,27 @@ +# Skipped_Sub_Selection + +## Request + +```graphql +query($slug: String!, $skip: Boolean!) { + productBySlug(slug: $slug) { + name @skip(if: $skip) + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($skip: Boolean!, $slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: $skip) + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_From_Different_Subgraph.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_From_Different_Subgraph.md new file mode 100644 index 00000000000..30e26914c57 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_From_Different_Subgraph.md @@ -0,0 +1,42 @@ +# Skipped_Sub_Selection_From_Different_Subgraph + +## Request + +```graphql +query($slug: String!, $skip: Boolean!) { + productBySlug(slug: $slug) { + averageRating @skip(if: $skip) + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + id + } + } + - id: 2 + schema: "REVIEWS" + operation: >- + query($__fusion_requirement_1: ID!) { + productById(id: $__fusion_requirement_1) { + averageRating + } + } + skipIf: "skip" + requirements: + - name: "__fusion_requirement_1" + dependsOn: "1" + selectionSet: "productBySlug" + field: "id" + type: "ID!" + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_From_Different_Subgraph_If_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_From_Different_Subgraph_If_True.md new file mode 100644 index 00000000000..f69225072c6 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_From_Different_Subgraph_If_True.md @@ -0,0 +1,27 @@ +# Skipped_Sub_Selection_From_Different_Subgraph_If_True + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + averageRating @skip(if: true) + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + __typename + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_From_Different_Subgraph_Other_Not_Skipped_Sub_Selection_From_First_Subgraph.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_From_Different_Subgraph_Other_Not_Skipped_Sub_Selection_From_First_Subgraph.md new file mode 100644 index 00000000000..c66440da3c0 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_From_Different_Subgraph_Other_Not_Skipped_Sub_Selection_From_First_Subgraph.md @@ -0,0 +1,44 @@ +# Skipped_Sub_Selection_From_Different_Subgraph_Other_Not_Skipped_Sub_Selection_From_First_Subgraph + +## Request + +```graphql +query($slug: String!, $skip: Boolean!) { + productBySlug(slug: $slug) { + name + averageRating @skip(if: $skip) + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + id + } + } + - id: 2 + schema: "REVIEWS" + operation: >- + query($__fusion_requirement_1: ID!) { + productById(id: $__fusion_requirement_1) { + averageRating + } + } + skipIf: "skip" + requirements: + - name: "__fusion_requirement_1" + dependsOn: "1" + selectionSet: "productBySlug" + field: "id" + type: "ID!" + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_From_Different_Subgraph_Other_Not_Skipped_Sub_Selection_From_First_Subgraph_If_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_From_Different_Subgraph_Other_Not_Skipped_Sub_Selection_From_First_Subgraph_If_True.md new file mode 100644 index 00000000000..b93a1efeb5d --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_From_Different_Subgraph_Other_Not_Skipped_Sub_Selection_From_First_Subgraph_If_True.md @@ -0,0 +1,28 @@ +# Skipped_Sub_Selection_From_Different_Subgraph_Other_Not_Skipped_Sub_Selection_From_First_Subgraph_If_True + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + name + averageRating @skip(if: true) + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_From_Different_Subgraph_Other_Not_Skipped_Sub_Selection_From_Same_Subgraph.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_From_Different_Subgraph_Other_Not_Skipped_Sub_Selection_From_Same_Subgraph.md new file mode 100644 index 00000000000..cf3bd20f850 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_From_Different_Subgraph_Other_Not_Skipped_Sub_Selection_From_Same_Subgraph.md @@ -0,0 +1,51 @@ +# Skipped_Sub_Selection_From_Different_Subgraph_Other_Not_Skipped_Sub_Selection_From_Same_Subgraph + +## Request + +```graphql +query($slug: String!, $skip: Boolean!) { + productBySlug(slug: $slug) { + averageRating @skip(if: $skip) + reviews(first: 10) { + nodes { + body + } + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + id + } + } + - id: 2 + schema: "REVIEWS" + operation: >- + query($__fusion_requirement_1: ID!, $skip: Boolean!) { + productById(id: $__fusion_requirement_1) { + averageRating @skip(if: $skip) + reviews(first: 10) { + nodes { + body + } + } + } + } + requirements: + - name: "__fusion_requirement_1" + dependsOn: "1" + selectionSet: "productBySlug" + field: "id" + type: "ID!" + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_From_Different_Subgraph_Other_Not_Skipped_Sub_Selection_From_Same_Subgraph_If_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_From_Different_Subgraph_Other_Not_Skipped_Sub_Selection_From_Same_Subgraph_If_True.md new file mode 100644 index 00000000000..0f53eafdbfe --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_From_Different_Subgraph_Other_Not_Skipped_Sub_Selection_From_Same_Subgraph_If_True.md @@ -0,0 +1,51 @@ +# Skipped_Sub_Selection_From_Different_Subgraph_Other_Not_Skipped_Sub_Selection_From_Same_Subgraph_If_True + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + averageRating @skip(if: true) + reviews(first: 10) { + nodes { + body + } + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + __typename + id + } + } + - id: 2 + schema: "REVIEWS" + operation: >- + query($__fusion_requirement_1: ID!) { + productById(id: $__fusion_requirement_1) { + reviews(first: 10) { + nodes { + body + } + } + } + } + requirements: + - name: "__fusion_requirement_1" + dependsOn: "1" + selectionSet: "productBySlug" + field: "id" + type: "ID!" + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_If_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_If_True.md new file mode 100644 index 00000000000..8a08337bf08 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_If_True.md @@ -0,0 +1,27 @@ +# Skipped_Sub_Selection_If_True + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: true) + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + __typename + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_Other_Not_Skipped_Sub_Selection_From_Different_Subgraph.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_Other_Not_Skipped_Sub_Selection_From_Different_Subgraph.md new file mode 100644 index 00000000000..d32ebea01ab --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_Other_Not_Skipped_Sub_Selection_From_Different_Subgraph.md @@ -0,0 +1,43 @@ +# Skipped_Sub_Selection_Other_Not_Skipped_Sub_Selection_From_Different_Subgraph + +## Request + +```graphql +query($slug: String!, $skip: Boolean!) { + productBySlug(slug: $slug) { + name @skip(if: $skip) + averageRating + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($skip: Boolean!, $slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: $skip) + id + } + } + - id: 2 + schema: "REVIEWS" + operation: >- + query($__fusion_requirement_1: ID!) { + productById(id: $__fusion_requirement_1) { + averageRating + } + } + requirements: + - name: "__fusion_requirement_1" + dependsOn: "1" + selectionSet: "productBySlug" + field: "id" + type: "ID!" + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_Other_Not_Skipped_Sub_Selection_From_Different_Subgraph_If_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_Other_Not_Skipped_Sub_Selection_From_Different_Subgraph_If_True.md new file mode 100644 index 00000000000..0901eab35e2 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_Other_Not_Skipped_Sub_Selection_From_Different_Subgraph_If_True.md @@ -0,0 +1,43 @@ +# Skipped_Sub_Selection_Other_Not_Skipped_Sub_Selection_From_Different_Subgraph_If_True + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: true) + averageRating + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + __typename + id + } + } + - id: 2 + schema: "REVIEWS" + operation: >- + query($__fusion_requirement_1: ID!) { + productById(id: $__fusion_requirement_1) { + averageRating + } + } + requirements: + - name: "__fusion_requirement_1" + dependsOn: "1" + selectionSet: "productBySlug" + field: "id" + type: "ID!" + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_Other_Not_Skipped_Sub_Selection_From_Same_Subgraph.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_Other_Not_Skipped_Sub_Selection_From_Same_Subgraph.md new file mode 100644 index 00000000000..7f7b367f898 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_Other_Not_Skipped_Sub_Selection_From_Same_Subgraph.md @@ -0,0 +1,29 @@ +# Skipped_Sub_Selection_Other_Not_Skipped_Sub_Selection_From_Same_Subgraph + +## Request + +```graphql +query($slug: String!, $skip: Boolean!) { + productBySlug(slug: $slug) { + name @skip(if: $skip) + description + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($skip: Boolean!, $slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: $skip) + description + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_Other_Not_Skipped_Sub_Selection_From_Same_Subgraph_If_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_Other_Not_Skipped_Sub_Selection_From_Same_Subgraph_If_True.md new file mode 100644 index 00000000000..ae23a5c19d6 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_Other_Not_Skipped_Sub_Selection_From_Same_Subgraph_If_True.md @@ -0,0 +1,28 @@ +# Skipped_Sub_Selection_Other_Not_Skipped_Sub_Selection_From_Same_Subgraph_If_True + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + name @skip(if: true) + description + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + description + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_That_Provides_Data_For_Lookup_On_Different_Subgraph.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_That_Provides_Data_For_Lookup_On_Different_Subgraph.md new file mode 100644 index 00000000000..567551ebde8 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_That_Provides_Data_For_Lookup_On_Different_Subgraph.md @@ -0,0 +1,47 @@ +# Skipped_Sub_Selection_That_Provides_Data_For_Lookup_On_Different_Subgraph + +## Request + +```graphql +query($id: ID!, $skip: Boolean!) { + reviewById(id: $id) { + body + author @skip(if: $skip) { + displayName + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "REVIEWS" + operation: >- + query($id: ID!, $skip: Boolean!) { + reviewById(id: $id) { + body + author @skip(if: $skip) { + id + } + } + } + - id: 2 + schema: "ACCOUNTS" + operation: >- + query($__fusion_requirement_1: ID!) { + userById(id: $__fusion_requirement_1) { + displayName + } + } + requirements: + - name: "__fusion_requirement_1" + dependsOn: "1" + selectionSet: "reviewById.author" + field: "id" + type: "ID!" + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_That_Provides_Data_For_Lookup_On_Different_Subgraph_If_True.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_That_Provides_Data_For_Lookup_On_Different_Subgraph_If_True.md new file mode 100644 index 00000000000..e296b961874 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ConditionTests/__snapshots__/SkipTests.Skipped_Sub_Selection_That_Provides_Data_For_Lookup_On_Different_Subgraph_If_True.md @@ -0,0 +1,30 @@ +# Skipped_Sub_Selection_That_Provides_Data_For_Lookup_On_Different_Subgraph_If_True + +## Request + +```graphql +query($id: ID!) { + reviewById(id: $id) { + body + author @skip(if: true) { + displayName + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "REVIEWS" + operation: >- + query($id: ID!) { + reviewById(id: $id) { + body + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/FragmentTests.cs b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/FragmentTests.cs new file mode 100644 index 00000000000..e7b03fa735e --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/FragmentTests.cs @@ -0,0 +1,453 @@ +using static HotChocolate.Language.Utf8GraphQLParser; + +namespace HotChocolate.Fusion; + +public class FragmentTests : FusionTestBase +{ + [Test] + public async Task Fragment_On_Root() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + ...QueryFragment + } + + fragment QueryFragment on Query { + productBySlug(slug: $slug) { + name + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Fragment_On_Root_Next_To_Same_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + ...QueryFragment + } + + fragment QueryFragment on Query { + productBySlug(slug: $slug) { + name + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Fragment_On_Root_Next_To_Same_Selection_With_Different_Sub_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + description + } + ...QueryFragment + } + + fragment QueryFragment on Query { + productBySlug(slug: $slug) { + name + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Fragment_On_Root_Next_To_Different_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + products { + nodes { + description + } + } + ...QueryFragment + } + + fragment QueryFragment on Query { + productBySlug(slug: $slug) { + name + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + [Skip("Not yet supported by the planner")] + public async Task Fragment_On_Root_Next_To_Different_Selection_From_Different_Subgraph() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + viewer { + displayName + } + ...QueryFragment + } + + fragment QueryFragment on Query { + productBySlug(slug: $slug) { + name + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Two_Fragments_On_Root_With_Same_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + ...QueryFragment1 + ...QueryFragment2 + } + + fragment QueryFragment1 on Query { + productBySlug(slug: $slug) { + name + } + } + + fragment QueryFragment2 on Query { + productBySlug(slug: $slug) { + name + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Two_Fragments_On_Root_With_Different_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + ...QueryFragment1 + ...QueryFragment2 + } + + fragment QueryFragment1 on Query { + productBySlug(slug: $slug) { + name + } + } + + fragment QueryFragment2 on Query { + products { + nodes { + description + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + [Skip("Not yet supported by the planner")] + public async Task Two_Fragments_On_Root_With_Different_Selection_From_Different_Subgraph() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + ...QueryFragment1 + ...QueryFragment2 + } + + fragment QueryFragment1 on Query { + productBySlug(slug: $slug) { + name + } + } + + fragment QueryFragment2 on Query { + viewer { + displayName + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Fragment_On_Sub_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + ...ProductFragment + } + } + + fragment ProductFragment on Product { + name + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Fragment_On_Sub_Selection_Next_To_Same_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + name + ...ProductFragment + } + } + + fragment ProductFragment on Product { + name + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Fragment_On_Sub_Selection_Next_To_Different_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + name + ...ProductFragment + } + } + + fragment ProductFragment on Product { + description + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Fragment_On_Sub_Selection_Next_To_Different_Selection_From_Different_Subgraph() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + name + ...ProductFragment + } + } + + fragment ProductFragment on Product { + averageRating + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Two_Fragments_On_Sub_Selection_With_Same_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + ...ProductFragment1 + ...ProductFragment2 + } + } + + fragment ProductFragment1 on Product { + name + } + + fragment ProductFragment2 on Product { + name + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Two_Fragments_On_Sub_Selection_With_Different_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + ...ProductFragment1 + ...ProductFragment2 + } + } + + fragment ProductFragment1 on Product { + name + } + + fragment ProductFragment2 on Product { + description + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Two_Fragments_On_Sub_Selection_With_Different_Selection_From_Different_Subgraph() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + ...ProductFragment1 + ...ProductFragment2 + } + } + + fragment ProductFragment1 on Product { + name + } + + fragment ProductFragment2 on Product { + averageRating + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } +} diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/FusionTestBase.cs b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/FusionTestBase.cs index 028b82a5936..8956a63b06b 100644 --- a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/FusionTestBase.cs +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/FusionTestBase.cs @@ -14,14 +14,21 @@ protected static CompositeSchema CreateCompositeSchema() return CompositeSchemaBuilder.Create(compositeSchemaDoc); } - protected static RootPlanNode PlanOperationAsync(CompositeSchema compositeSchema, string operation) + protected static RootPlanNode PlanOperation(DocumentNode request, CompositeSchema compositeSchema) { - var doc = Utf8GraphQLParser.Parse(operation); - var rewriter = new InlineFragmentOperationRewriter(compositeSchema); - var rewritten = rewriter.RewriteDocument(doc, null); + var rewritten = rewriter.RewriteDocument(request, null); var planner = new OperationPlanner(compositeSchema); return planner.CreatePlan(rewritten, null); } + + protected static async Task MatchSnapshotAsync(DocumentNode request,RootPlanNode plan) + { + var snapshot = new Snapshot(); + snapshot.Add(request, "Request"); + snapshot.Add(plan, "Plan"); + + await snapshot.MatchMarkdownAsync(); + } } diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/InlineFragmentTests.cs b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/InlineFragmentTests.cs new file mode 100644 index 00000000000..70b0aa3a1ce --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/InlineFragmentTests.cs @@ -0,0 +1,411 @@ +using HotChocolate.Language; + +namespace HotChocolate.Fusion; + +public class InlineFragmentTests : FusionTestBase +{ + [Test] + public async Task InlineFragment_On_Root() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Utf8GraphQLParser.Parse( + """ + query($slug: String!) { + ... { + productBySlug(slug: $slug) { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task InlineFragment_On_Root_Next_To_Same_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Utf8GraphQLParser.Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + ... { + productBySlug(slug: $slug) { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task InlineFragment_On_Root_Next_To_Same_Selection_With_Different_Sub_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Utf8GraphQLParser.Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + description + } + ... { + productBySlug(slug: $slug) { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task InlineFragment_On_Root_Next_To_Different_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Utf8GraphQLParser.Parse( + """ + query($slug: String!) { + products { + nodes { + description + } + } + ... { + productBySlug(slug: $slug) { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + [Skip("Not yet supported by the planner")] + public async Task InlineFragment_On_Root_Next_To_Different_Selection_From_Different_Subgraph() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Utf8GraphQLParser.Parse( + """ + query($slug: String!) { + viewer { + displayName + } + ... { + productBySlug(slug: $slug) { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Two_InlineFragments_On_Root_With_Same_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Utf8GraphQLParser.Parse( + """ + query($slug: String!) { + ... { + productBySlug(slug: $slug) { + name + } + } + ... { + productBySlug(slug: $slug) { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Two_InlineFragments_On_Root_With_Different_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Utf8GraphQLParser.Parse( + """ + query($slug: String!) { + ... { + productBySlug(slug: $slug) { + name + } + } + ... { + products { + nodes { + description + } + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + [Skip("Not yet supported by the planner")] + public async Task Two_InlineFragments_On_Root_With_Different_Selection_From_Different_Subgraph() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Utf8GraphQLParser.Parse( + """ + query($slug: String!) { + ... { + productBySlug(slug: $slug) { + name + } + } + ... { + viewer { + displayName + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task InlineFragment_On_Sub_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Utf8GraphQLParser.Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + ... { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task InlineFragment_On_Sub_Selection_Next_To_Same_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Utf8GraphQLParser.Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + name + ... { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task InlineFragment_On_Sub_Selection_Next_To_Different_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Utf8GraphQLParser.Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + name + ... { + description + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task InlineFragment_On_Sub_Selection_Next_To_Different_Selection_From_Different_Subgraph() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Utf8GraphQLParser.Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + name + ... { + averageRating + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Two_Fragments_On_Sub_Selection_With_Same_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Utf8GraphQLParser.Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + ... { + name + } + ... { + name + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Two_Fragments_On_Sub_Selection_With_Different_Selection() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Utf8GraphQLParser.Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + ... { + name + } + ... { + description + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } + + [Test] + public async Task Two_Fragments_On_Sub_Selection_With_Different_Selection_From_Different_Subgraph() + { + // arrange + var compositeSchema = CreateCompositeSchema(); + + var request = Utf8GraphQLParser.Parse( + """ + query($slug: String!) { + productBySlug(slug: $slug) { + ... { + name + } + ... { + averageRating + } + } + } + """); + + // act + var plan = PlanOperation(request, compositeSchema); + + // assert + await MatchSnapshotAsync(request, plan); + } +} diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ModuleInitializer.cs b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ModuleInitializer.cs index d50f67d0c56..a86ea7dd0f4 100644 --- a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ModuleInitializer.cs +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/ModuleInitializer.cs @@ -1,4 +1,10 @@ +using System.Buffers; using System.Runtime.CompilerServices; +using CookieCrumble.Formatters; +using HotChocolate.Fusion.Planning; +using HotChocolate.Fusion.Planning.Nodes; +using HotChocolate.Language; +using HotChocolate.Language.Utilities; namespace HotChocolate.Fusion; @@ -8,5 +14,48 @@ internal static class ModuleInitializer public static void Initialize() { CookieCrumbleTUnit.Initialize(); + Snapshot.TryRegisterFormatter(new RootPlanNodeSnapshotValueFormatter()); + Snapshot.TryRegisterFormatter(new SyntaxNodeSnapshotValueFormatter()); + } + + private sealed class RootPlanNodeSnapshotValueFormatter() : SnapshotValueFormatter("yaml") + { + protected override void Format(IBufferWriter snapshot, RootPlanNode value) + => value.FormatToYaml(snapshot); + } + + // Taken from CookieCrumble.HotChocolate + private sealed class SyntaxNodeSnapshotValueFormatter : SnapshotValueFormatter + { + protected override void Format(IBufferWriter snapshot, ISyntaxNode value) + { + var serialized = value.Print().AsSpan(); + var buffer = ArrayPool.Shared.Rent(serialized.Length); + var span = buffer.AsSpan()[..serialized.Length]; + var written = 0; + + for (var i = 0; i < serialized.Length; i++) + { + if (serialized[i] is not '\r') + { + span[written++] = serialized[i]; + } + } + + span = span[..written]; + snapshot.Append(span); + + ArrayPool.Shared.Return(buffer); + } + + protected override void FormatMarkdown(IBufferWriter snapshot, ISyntaxNode value) + { + snapshot.Append("```graphql"); + snapshot.AppendLine(); + Format(snapshot, value); + snapshot.AppendLine(); + snapshot.Append("```"); + snapshot.AppendLine(); + } } } diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/OperationPlannerTests.cs b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/OperationPlannerTests.cs index b4c1e9fc0aa..46af14273e6 100644 --- a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/OperationPlannerTests.cs +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/OperationPlannerTests.cs @@ -1,23 +1,22 @@ using HotChocolate.Fusion.Planning; using HotChocolate.Fusion.Types.Completion; using HotChocolate.Language; +using static HotChocolate.Language.Utf8GraphQLParser; namespace HotChocolate.Fusion; public class OperationPlannerTests : FusionTestBase { [Test] - public void Plan_Simple_Operation_1_Source_Schema() + public async Task Plan_Simple_Operation_1_Source_Schema() { // arrange var compositeSchema = CreateCompositeSchema(); - // act - var plan = PlanOperationAsync( - compositeSchema, + var request = Parse( """ { - productById(id: 1) { + productBySlug(slug: "1") { ... Product } } @@ -28,35 +27,23 @@ fragment Product on Product { } """); - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - { - productById(id: 1) { - id - name - } - } + // act + var plan = PlanOperation(request, compositeSchema); - """); + // assert + await MatchSnapshotAsync(request, plan); } [Test] - public void Plan_Simple_Operation_2_Source_Schema() + public async Task Plan_Simple_Operation_2_Source_Schema() { // arrange var compositeSchema = CreateCompositeSchema(); - // act - var plan = PlanOperationAsync( - compositeSchema, + var request = Parse( """ { - productById(id: 1) { + productBySlug(slug: "1") { ... Product } } @@ -68,50 +55,23 @@ fragment Product on Product { } """); - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - { - productById(id: 1) { - id - name - id - } - } - - id: 2 - schema: "SHIPPING" - operation: >- - query($__fusion_requirement_1: ID!) { - productById(id: $__fusion_requirement_1) { - estimatedDelivery(postCode: "12345") - } - } - requirements: - - name: "__fusion_requirement_1" - dependsOn: "1" - selectionSet: "productById" - field: "id" - type: "ID!" + // act + var plan = PlanOperation(request, compositeSchema); - """); + // assert + await MatchSnapshotAsync(request, plan); } [Test] - public void Plan_Simple_Operation_3_Source_Schema() + public async Task Plan_Simple_Operation_3_Source_Schema() { // arrange var compositeSchema = CreateCompositeSchema(); - // act - var plan = PlanOperationAsync( - compositeSchema, + var request = Parse( """ { - productById(id: 1) { + productBySlug(slug: "1") { ... ProductCard } } @@ -138,71 +98,23 @@ fragment AuthorCard on UserProfile { } """); - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - { - productById(id: 1) { - name - id - } - } - - id: 2 - schema: "REVIEWS" - operation: >- - query($__fusion_requirement_2: ID!) { - productById(id: $__fusion_requirement_2) { - reviews(first: 10) { - nodes { - body - stars - author { - id - } - } - } - } - } - requirements: - - name: "__fusion_requirement_2" - dependsOn: "1" - selectionSet: "productById" - field: "id" - type: "ID!" - - id: 3 - schema: "ACCOUNTS" - operation: >- - query($__fusion_requirement_1: ID!) { - userById(id: $__fusion_requirement_1) { - displayName - } - } - requirements: - - name: "__fusion_requirement_1" - dependsOn: "2" - selectionSet: "productById.reviews.nodes.author" - field: "id" - type: "ID!" + // act + var plan = PlanOperation(request, compositeSchema); - """); + // assert + await MatchSnapshotAsync(request, plan); } [Test] - public void Plan_Simple_Operation_3_Source_Schema_And_Single_Variable() + public async Task Plan_Simple_Operation_3_Source_Schema_And_Single_Variable() { // arrange var compositeSchema = CreateCompositeSchema(); - // act - var plan = PlanOperationAsync( - compositeSchema, + var request = Parse( """ - query GetProduct($id: ID!, $first: Int! = 10) { - productById(id: $id) { + query GetProduct($slug: String! $first: Int! = 10) { + productBySlug(slug: $slug) { ... ProductCard } } @@ -229,66 +141,20 @@ fragment AuthorCard on UserProfile { } """); - // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - query($id: ID!) { - productById(id: $id) { - name - id - } - } - - id: 2 - schema: "REVIEWS" - operation: >- - query($__fusion_requirement_2: ID!, $first: Int! = 10) { - productById(id: $__fusion_requirement_2) { - reviews(first: $first) { - nodes { - body - stars - author { - id - } - } - } - } - } - requirements: - - name: "__fusion_requirement_2" - dependsOn: "1" - selectionSet: "productById" - field: "id" - type: "ID!" - - id: 3 - schema: "ACCOUNTS" - operation: >- - query($__fusion_requirement_1: ID!) { - userById(id: $__fusion_requirement_1) { - displayName - } - } - requirements: - - name: "__fusion_requirement_1" - dependsOn: "2" - selectionSet: "productById.reviews.nodes.author" - field: "id" - type: "ID!" + // act + var plan = PlanOperation(request, compositeSchema); - """); + // assert + await MatchSnapshotAsync(request, plan); } [Test] - public void Plan_With_Conditional_InlineFragment() + public async Task Plan_With_Conditional_InlineFragment() { - var compositeSchemaDoc = Utf8GraphQLParser.Parse(FileResource.Open("fusion1.graphql")); - var compositeSchema = CompositeSchemaBuilder.Create(compositeSchemaDoc); + // arrange + var compositeSchema = CreateCompositeSchema(); - var doc = Utf8GraphQLParser.Parse( + var request = Parse( """ { productById(id: 1) { @@ -305,27 +171,10 @@ ... @include(if: true) { } """); - var rewriter = new InlineFragmentOperationRewriter(compositeSchema); - var rewritten = rewriter.RewriteDocument(doc, null); - // act - var planner = new OperationPlanner(compositeSchema); - var plan = planner.CreatePlan(rewritten, null); + var plan = PlanOperation(request, compositeSchema); // assert - plan.ToYaml().MatchInlineSnapshot( - """ - nodes: - - id: 1 - schema: "PRODUCTS" - operation: >- - { - productById(id: 1) { - id - name - } - } - - """); + await MatchSnapshotAsync(request, plan); } } diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__resources__/fusion1.graphql b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__resources__/fusion1.graphql index 81047170eb2..bbd7495d614 100644 --- a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__resources__/fusion1.graphql +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__resources__/fusion1.graphql @@ -1,12 +1,28 @@ type Query @fusion__type(schema: ACCOUNTS) + @fusion__type(schema: REVIEWS) @fusion__type(schema: PRODUCTS) { - viewer: UserProfile + viewer: Viewer @fusion__field(schema: ACCOUNTS) + @fusion__field(schema: REVIEWS) productById(id: ID!): Product @fusion__field(schema: PRODUCTS) + @fusion__field(schema: REVIEWS) products(first: Int, after: String, last: Int, before: String): ProductConnection @fusion__field(schema: PRODUCTS) + productBySlug(slug: String!): Product + @fusion__field(schema: PRODUCTS) + reviewById(id: ID!): Review + @fusion__field(schema: REVIEWS) +} + +type Viewer + @fusion__type(schema: ACCOUNTS) + @fusion__type(schema: REVIEWS) { + displayName: String! + @fusion__field(schema: ACCOUNTS) + reviews(first: Int, after: String, last: Int, before: String): ProductReviewConnection + @fusion__field(schema: REVIEWS) } type Product diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Root.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Root.md new file mode 100644 index 00000000000..c8410272053 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Root.md @@ -0,0 +1,31 @@ +# Fragment_On_Root + +## Request + +```graphql +query($slug: String!) { + ... QueryFragment +} + +fragment QueryFragment on Query { + productBySlug(slug: $slug) { + name + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Root_Next_To_Different_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Root_Next_To_Different_Selection.md new file mode 100644 index 00000000000..a5b302580ac --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Root_Next_To_Different_Selection.md @@ -0,0 +1,41 @@ +# Fragment_On_Root_Next_To_Different_Selection + +## Request + +```graphql +query($slug: String!) { + products { + nodes { + description + } + } + ... QueryFragment +} + +fragment QueryFragment on Query { + productBySlug(slug: $slug) { + name + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + products { + nodes { + description + } + } + productBySlug(slug: $slug) { + name + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Root_Next_To_Same_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Root_Next_To_Same_Selection.md new file mode 100644 index 00000000000..1b6533ae00a --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Root_Next_To_Same_Selection.md @@ -0,0 +1,34 @@ +# Fragment_On_Root_Next_To_Same_Selection + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + name + } + ... QueryFragment +} + +fragment QueryFragment on Query { + productBySlug(slug: $slug) { + name + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Root_Next_To_Same_Selection_With_Different_Sub_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Root_Next_To_Same_Selection_With_Different_Sub_Selection.md new file mode 100644 index 00000000000..b3ad05cc23a --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Root_Next_To_Same_Selection_With_Different_Sub_Selection.md @@ -0,0 +1,37 @@ +# Fragment_On_Root_Next_To_Same_Selection_With_Different_Sub_Selection + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + description + } + ... QueryFragment +} + +fragment QueryFragment on Query { + productBySlug(slug: $slug) { + name + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + description + } + productBySlug(slug: $slug) { + name + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Sub_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Sub_Selection.md new file mode 100644 index 00000000000..940124adf0a --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Sub_Selection.md @@ -0,0 +1,31 @@ +# Fragment_On_Sub_Selection + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + ... ProductFragment + } +} + +fragment ProductFragment on Product { + name +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Sub_Selection_Next_To_Different_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Sub_Selection_Next_To_Different_Selection.md new file mode 100644 index 00000000000..5bac05a5202 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Sub_Selection_Next_To_Different_Selection.md @@ -0,0 +1,33 @@ +# Fragment_On_Sub_Selection_Next_To_Different_Selection + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + name + ... ProductFragment + } +} + +fragment ProductFragment on Product { + description +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + description + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Sub_Selection_Next_To_Different_Selection_From_Different_Subgraph.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Sub_Selection_Next_To_Different_Selection_From_Different_Subgraph.md new file mode 100644 index 00000000000..2cf688b02b7 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Sub_Selection_Next_To_Different_Selection_From_Different_Subgraph.md @@ -0,0 +1,47 @@ +# Fragment_On_Sub_Selection_Next_To_Different_Selection_From_Different_Subgraph + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + name + ... ProductFragment + } +} + +fragment ProductFragment on Product { + averageRating +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + id + } + } + - id: 2 + schema: "REVIEWS" + operation: >- + query($__fusion_requirement_1: ID!) { + productById(id: $__fusion_requirement_1) { + averageRating + } + } + requirements: + - name: "__fusion_requirement_1" + dependsOn: "1" + selectionSet: "productBySlug" + field: "id" + type: "ID!" + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Sub_Selection_Next_To_Same_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Sub_Selection_Next_To_Same_Selection.md new file mode 100644 index 00000000000..95886ff4c60 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Fragment_On_Sub_Selection_Next_To_Same_Selection.md @@ -0,0 +1,32 @@ +# Fragment_On_Sub_Selection_Next_To_Same_Selection + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + name + ... ProductFragment + } +} + +fragment ProductFragment on Product { + name +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Two_Fragments_On_Root_With_Different_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Two_Fragments_On_Root_With_Different_Selection.md new file mode 100644 index 00000000000..d64c1d35c2b --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Two_Fragments_On_Root_With_Different_Selection.md @@ -0,0 +1,45 @@ +# Two_Fragments_On_Root_With_Different_Selection + +## Request + +```graphql +query($slug: String!) { + ... QueryFragment1 + ... QueryFragment2 +} + +fragment QueryFragment1 on Query { + productBySlug(slug: $slug) { + name + } +} + +fragment QueryFragment2 on Query { + products { + nodes { + description + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + products { + nodes { + description + } + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Two_Fragments_On_Root_With_Same_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Two_Fragments_On_Root_With_Same_Selection.md new file mode 100644 index 00000000000..53d14a6d90f --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Two_Fragments_On_Root_With_Same_Selection.md @@ -0,0 +1,38 @@ +# Two_Fragments_On_Root_With_Same_Selection + +## Request + +```graphql +query($slug: String!) { + ... QueryFragment1 + ... QueryFragment2 +} + +fragment QueryFragment1 on Query { + productBySlug(slug: $slug) { + name + } +} + +fragment QueryFragment2 on Query { + productBySlug(slug: $slug) { + name + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Two_Fragments_On_Sub_Selection_With_Different_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Two_Fragments_On_Sub_Selection_With_Different_Selection.md new file mode 100644 index 00000000000..6a095bf0709 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Two_Fragments_On_Sub_Selection_With_Different_Selection.md @@ -0,0 +1,37 @@ +# Two_Fragments_On_Sub_Selection_With_Different_Selection + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + ... ProductFragment1 + ... ProductFragment2 + } +} + +fragment ProductFragment1 on Product { + name +} + +fragment ProductFragment2 on Product { + description +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + description + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Two_Fragments_On_Sub_Selection_With_Different_Selection_From_Different_Subgraph.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Two_Fragments_On_Sub_Selection_With_Different_Selection_From_Different_Subgraph.md new file mode 100644 index 00000000000..b8f116c9b38 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Two_Fragments_On_Sub_Selection_With_Different_Selection_From_Different_Subgraph.md @@ -0,0 +1,51 @@ +# Two_Fragments_On_Sub_Selection_With_Different_Selection_From_Different_Subgraph + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + ... ProductFragment1 + ... ProductFragment2 + } +} + +fragment ProductFragment1 on Product { + name +} + +fragment ProductFragment2 on Product { + averageRating +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + id + } + } + - id: 2 + schema: "REVIEWS" + operation: >- + query($__fusion_requirement_1: ID!) { + productById(id: $__fusion_requirement_1) { + averageRating + } + } + requirements: + - name: "__fusion_requirement_1" + dependsOn: "1" + selectionSet: "productBySlug" + field: "id" + type: "ID!" + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Two_Fragments_On_Sub_Selection_With_Same_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Two_Fragments_On_Sub_Selection_With_Same_Selection.md new file mode 100644 index 00000000000..ed72a66a162 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/FragmentTests.Two_Fragments_On_Sub_Selection_With_Same_Selection.md @@ -0,0 +1,36 @@ +# Two_Fragments_On_Sub_Selection_With_Same_Selection + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + ... ProductFragment1 + ... ProductFragment2 + } +} + +fragment ProductFragment1 on Product { + name +} + +fragment ProductFragment2 on Product { + name +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Root.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Root.md new file mode 100644 index 00000000000..f8e3966f84c --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Root.md @@ -0,0 +1,29 @@ +# InlineFragment_On_Root + +## Request + +```graphql +query($slug: String!) { + ... { + productBySlug(slug: $slug) { + name + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Root_Next_To_Different_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Root_Next_To_Different_Selection.md new file mode 100644 index 00000000000..5cdecc13a08 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Root_Next_To_Different_Selection.md @@ -0,0 +1,39 @@ +# InlineFragment_On_Root_Next_To_Different_Selection + +## Request + +```graphql +query($slug: String!) { + products { + nodes { + description + } + } + ... { + productBySlug(slug: $slug) { + name + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + products { + nodes { + description + } + } + productBySlug(slug: $slug) { + name + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Root_Next_To_Same_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Root_Next_To_Same_Selection.md new file mode 100644 index 00000000000..5ffecebdad0 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Root_Next_To_Same_Selection.md @@ -0,0 +1,32 @@ +# InlineFragment_On_Root_Next_To_Same_Selection + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + name + } + ... { + productBySlug(slug: $slug) { + name + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Root_Next_To_Same_Selection_With_Different_Sub_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Root_Next_To_Same_Selection_With_Different_Sub_Selection.md new file mode 100644 index 00000000000..a11b589951f --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Root_Next_To_Same_Selection_With_Different_Sub_Selection.md @@ -0,0 +1,35 @@ +# InlineFragment_On_Root_Next_To_Same_Selection_With_Different_Sub_Selection + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + description + } + ... { + productBySlug(slug: $slug) { + name + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + description + } + productBySlug(slug: $slug) { + name + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Sub_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Sub_Selection.md new file mode 100644 index 00000000000..06eb40743d1 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Sub_Selection.md @@ -0,0 +1,29 @@ +# InlineFragment_On_Sub_Selection + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + ... { + name + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Sub_Selection_Next_To_Different_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Sub_Selection_Next_To_Different_Selection.md new file mode 100644 index 00000000000..7e669c297b4 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Sub_Selection_Next_To_Different_Selection.md @@ -0,0 +1,31 @@ +# InlineFragment_On_Sub_Selection_Next_To_Different_Selection + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + name + ... { + description + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + description + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Sub_Selection_Next_To_Different_Selection_From_Different_Subgraph.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Sub_Selection_Next_To_Different_Selection_From_Different_Subgraph.md new file mode 100644 index 00000000000..c864ae87c06 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Sub_Selection_Next_To_Different_Selection_From_Different_Subgraph.md @@ -0,0 +1,45 @@ +# InlineFragment_On_Sub_Selection_Next_To_Different_Selection_From_Different_Subgraph + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + name + ... { + averageRating + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + id + } + } + - id: 2 + schema: "REVIEWS" + operation: >- + query($__fusion_requirement_1: ID!) { + productById(id: $__fusion_requirement_1) { + averageRating + } + } + requirements: + - name: "__fusion_requirement_1" + dependsOn: "1" + selectionSet: "productBySlug" + field: "id" + type: "ID!" + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Sub_Selection_Next_To_Same_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Sub_Selection_Next_To_Same_Selection.md new file mode 100644 index 00000000000..734f137c6b8 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.InlineFragment_On_Sub_Selection_Next_To_Same_Selection.md @@ -0,0 +1,30 @@ +# InlineFragment_On_Sub_Selection_Next_To_Same_Selection + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + name + ... { + name + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.Two_Fragments_On_Sub_Selection_With_Different_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.Two_Fragments_On_Sub_Selection_With_Different_Selection.md new file mode 100644 index 00000000000..54c13923c79 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.Two_Fragments_On_Sub_Selection_With_Different_Selection.md @@ -0,0 +1,33 @@ +# Two_Fragments_On_Sub_Selection_With_Different_Selection + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + ... { + name + } + ... { + description + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + description + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.Two_Fragments_On_Sub_Selection_With_Different_Selection_From_Different_Subgraph.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.Two_Fragments_On_Sub_Selection_With_Different_Selection_From_Different_Subgraph.md new file mode 100644 index 00000000000..4c44c121cfc --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.Two_Fragments_On_Sub_Selection_With_Different_Selection_From_Different_Subgraph.md @@ -0,0 +1,47 @@ +# Two_Fragments_On_Sub_Selection_With_Different_Selection_From_Different_Subgraph + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + ... { + name + } + ... { + averageRating + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + id + } + } + - id: 2 + schema: "REVIEWS" + operation: >- + query($__fusion_requirement_1: ID!) { + productById(id: $__fusion_requirement_1) { + averageRating + } + } + requirements: + - name: "__fusion_requirement_1" + dependsOn: "1" + selectionSet: "productBySlug" + field: "id" + type: "ID!" + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.Two_Fragments_On_Sub_Selection_With_Same_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.Two_Fragments_On_Sub_Selection_With_Same_Selection.md new file mode 100644 index 00000000000..9e12bffd9f1 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.Two_Fragments_On_Sub_Selection_With_Same_Selection.md @@ -0,0 +1,32 @@ +# Two_Fragments_On_Sub_Selection_With_Same_Selection + +## Request + +```graphql +query($slug: String!) { + productBySlug(slug: $slug) { + ... { + name + } + ... { + name + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.Two_InlineFragments_On_Root_With_Different_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.Two_InlineFragments_On_Root_With_Different_Selection.md new file mode 100644 index 00000000000..30b196d4f4c --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.Two_InlineFragments_On_Root_With_Different_Selection.md @@ -0,0 +1,41 @@ +# Two_InlineFragments_On_Root_With_Different_Selection + +## Request + +```graphql +query($slug: String!) { + ... { + productBySlug(slug: $slug) { + name + } + } + ... { + products { + nodes { + description + } + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + products { + nodes { + description + } + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.Two_InlineFragments_On_Root_With_Same_Selection.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.Two_InlineFragments_On_Root_With_Same_Selection.md new file mode 100644 index 00000000000..7943f615ef8 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/InlineFragmentTests.Two_InlineFragments_On_Root_With_Same_Selection.md @@ -0,0 +1,34 @@ +# Two_InlineFragments_On_Root_With_Same_Selection + +## Request + +```graphql +query($slug: String!) { + ... { + productBySlug(slug: $slug) { + name + } + } + ... { + productBySlug(slug: $slug) { + name + } + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/OperationPlannerTests.Plan_Simple_Operation_1_Source_Schema.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/OperationPlannerTests.Plan_Simple_Operation_1_Source_Schema.md new file mode 100644 index 00000000000..1694f9037a8 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/OperationPlannerTests.Plan_Simple_Operation_1_Source_Schema.md @@ -0,0 +1,33 @@ +# Plan_Simple_Operation_1_Source_Schema + +## Request + +```graphql +{ + productBySlug(slug: "1") { + ... Product + } +} + +fragment Product on Product { + id + name +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + { + productBySlug(slug: "1") { + id + name + } + } + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/OperationPlannerTests.Plan_Simple_Operation_2_Source_Schema.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/OperationPlannerTests.Plan_Simple_Operation_2_Source_Schema.md new file mode 100644 index 00000000000..ff9e302fe4f --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/OperationPlannerTests.Plan_Simple_Operation_2_Source_Schema.md @@ -0,0 +1,49 @@ +# Plan_Simple_Operation_2_Source_Schema + +## Request + +```graphql +{ + productBySlug(slug: "1") { + ... Product + } +} + +fragment Product on Product { + id + name + estimatedDelivery(postCode: "12345") +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + { + productBySlug(slug: "1") { + id + name + id + } + } + - id: 2 + schema: "SHIPPING" + operation: >- + query($__fusion_requirement_1: ID!) { + productById(id: $__fusion_requirement_1) { + estimatedDelivery(postCode: "12345") + } + } + requirements: + - name: "__fusion_requirement_1" + dependsOn: "1" + selectionSet: "productBySlug" + field: "id" + type: "ID!" + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/OperationPlannerTests.Plan_Simple_Operation_3_Source_Schema.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/OperationPlannerTests.Plan_Simple_Operation_3_Source_Schema.md new file mode 100644 index 00000000000..0cf242a5d5a --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/OperationPlannerTests.Plan_Simple_Operation_3_Source_Schema.md @@ -0,0 +1,85 @@ +# Plan_Simple_Operation_3_Source_Schema + +## Request + +```graphql +{ + productBySlug(slug: "1") { + ... ProductCard + } +} + +fragment ProductCard on Product { + name + reviews(first: 10) { + nodes { + ... ReviewCard + } + } +} + +fragment ReviewCard on Review { + body + stars + author { + ... AuthorCard + } +} + +fragment AuthorCard on UserProfile { + displayName +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + { + productBySlug(slug: "1") { + name + id + } + } + - id: 2 + schema: "REVIEWS" + operation: >- + query($__fusion_requirement_2: ID!) { + productById(id: $__fusion_requirement_2) { + reviews(first: 10) { + nodes { + body + stars + author { + id + } + } + } + } + } + requirements: + - name: "__fusion_requirement_2" + dependsOn: "1" + selectionSet: "productBySlug" + field: "id" + type: "ID!" + - id: 3 + schema: "ACCOUNTS" + operation: >- + query($__fusion_requirement_1: ID!) { + userById(id: $__fusion_requirement_1) { + displayName + } + } + requirements: + - name: "__fusion_requirement_1" + dependsOn: "2" + selectionSet: "productBySlug.reviews.nodes.author" + field: "id" + type: "ID!" + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/OperationPlannerTests.Plan_Simple_Operation_3_Source_Schema_And_Single_Variable.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/OperationPlannerTests.Plan_Simple_Operation_3_Source_Schema_And_Single_Variable.md new file mode 100644 index 00000000000..bacc62262d8 --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/OperationPlannerTests.Plan_Simple_Operation_3_Source_Schema_And_Single_Variable.md @@ -0,0 +1,85 @@ +# Plan_Simple_Operation_3_Source_Schema_And_Single_Variable + +## Request + +```graphql +query GetProduct($slug: String!, $first: Int! = 10) { + productBySlug(slug: $slug) { + ... ProductCard + } +} + +fragment ProductCard on Product { + name + reviews(first: $first) { + nodes { + ... ReviewCard + } + } +} + +fragment ReviewCard on Review { + body + stars + author { + ... AuthorCard + } +} + +fragment AuthorCard on UserProfile { + displayName +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + query($slug: String!) { + productBySlug(slug: $slug) { + name + id + } + } + - id: 2 + schema: "REVIEWS" + operation: >- + query($__fusion_requirement_2: ID!, $first: Int! = 10) { + productById(id: $__fusion_requirement_2) { + reviews(first: $first) { + nodes { + body + stars + author { + id + } + } + } + } + } + requirements: + - name: "__fusion_requirement_2" + dependsOn: "1" + selectionSet: "productBySlug" + field: "id" + type: "ID!" + - id: 3 + schema: "ACCOUNTS" + operation: >- + query($__fusion_requirement_1: ID!) { + userById(id: $__fusion_requirement_1) { + displayName + } + } + requirements: + - name: "__fusion_requirement_1" + dependsOn: "2" + selectionSet: "productBySlug.reviews.nodes.author" + field: "id" + type: "ID!" + +``` + diff --git a/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/OperationPlannerTests.Plan_With_Conditional_InlineFragment.md b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/OperationPlannerTests.Plan_With_Conditional_InlineFragment.md new file mode 100644 index 00000000000..692d88b0aab --- /dev/null +++ b/src/HotChocolate/Fusion-vnext/test/Fusion.Execution.Tests/__snapshots__/OperationPlannerTests.Plan_With_Conditional_InlineFragment.md @@ -0,0 +1,36 @@ +# Plan_With_Conditional_InlineFragment + +## Request + +```graphql +{ + productById(id: 1) { + ... Product + } +} + +fragment Product on Product { + id + name + ... @include(if: true) { + estimatedDelivery(postCode: "12345") + } +} +``` + +## Plan + +```yaml +nodes: + - id: 1 + schema: "PRODUCTS" + operation: >- + { + productById(id: 1) { + id + name + } + } + +``` +