From 91fc947cb802668114aa78fbfd7ccd245a55503b Mon Sep 17 00:00:00 2001 From: Tobias Tengler <45513122+tobias-tengler@users.noreply.github.com> Date: Thu, 22 Aug 2024 23:12:50 +0200 Subject: [PATCH] Associate subgraph transport errors with fields (#7347) --- .../src/Transport.Http/GraphQLHttpResponse.cs | 5 +- .../GraphQLHttpClientTests.cs | 92 +++++++++++ .../Core/Clients/DefaultHttpGraphQLClient.cs | 13 +- .../src/Core/Clients/GraphQLResponse.cs | 30 +--- .../src/Core/Execution/ExecutionUtils.cs | 43 +++++- .../src/Core/Execution/Nodes/Resolve.cs | 12 ++ .../Core/Execution/Nodes/ResolveByKeyBatch.cs | 20 ++- .../Nodes/ResolverNodeBase.Config.cs | 11 ++ .../Core/Execution/Nodes/ResolverNodeBase.cs | 8 + .../ExecutionNodeBuilderMiddleware.cs | 4 + .../test/Core.Tests/TransportErrorTests.cs | 103 +++++++++++++ ...oth_Services_Offline_EntryField_NonNull.md | 10 +- ...th_Services_Offline_EntryField_Nullable.md | 11 +- ...ne_SubFields_NonNull_EntryField_NonNull.md | 10 +- ...e_SubFields_NonNull_EntryField_Nullable.md | 11 +- ..._SubFields_Nullable_EntryField_Nullable.md | 11 +- ...ne_SubFields_NonNull_EntryField_NonNull.md | 10 +- ...e_SubFields_NonNull_EntryField_Nullable.md | 10 +- ..._SubFields_Nullable_EntryField_Nullable.md | 12 +- ...ngle_Service_Offline_EntryField_NonNull.md | 10 +- ...gle_Service_Offline_EntryField_Nullable.md | 11 +- ...fline_SubField_NonNull_ListItem_NonNull.md | 28 +--- ...line_SubField_NonNull_ListItem_Nullable.md | 28 +--- ...econd_Service_Offline_SubField_Nullable.md | 41 ++++- ...ode_Service_Offline_EntryField_Nullable.md | 80 ++++++++++ ...rvices_Offline_SharedEntryField_NonNull.md | 21 +-- ...vices_Offline_SharedEntryField_Nullable.md | 22 ++- ...One_Service_Offline_EntryFields_NonNull.md | 10 +- ...ne_Service_Offline_EntryFields_Nullable.md | 11 +- ...bField_NonNull_SharedEntryField_NonNull.md | 10 +- ...Field_NonNull_SharedEntryField_Nullable.md | 15 +- ...ield_Nullable_SharedEntryField_Nullable.md | 11 +- ...ngle_Service_Offline_EntryField_NonNull.md | 10 +- ...gle_Service_Offline_EntryField_Nullable.md | 11 +- ...irst_Service_Offline_EntryField_NonNull.md | 10 +- ...rst_Service_Offline_EntryField_Nullable.md | 11 +- ...line_SubField_Nullable_Parent_Nullable.md} | 8 +- ...Offline_SubField_NonNull_Parent_NonNull.md | 10 +- ...ffline_SubField_NonNull_Parent_Nullable.md | 10 +- ...fline_SubField_Nullable_Parent_Nullable.md | 13 +- ...oth_Services_Offline_EntryField_NonNull.md | 96 ------------ ...th_Services_Offline_EntryField_Nullable.md | 98 ------------ ...ne_SubFields_NonNull_EntryField_NonNull.md | 14 +- ...e_SubFields_NonNull_EntryField_Nullable.md | 7 +- ...ne_SubFields_NonNull_EntryField_NonNull.md | 97 ------------ ...e_SubFields_NonNull_EntryField_Nullable.md | 99 ------------ ...ngle_Service_Offline_EntryField_NonNull.md | 67 -------- ...gle_Service_Offline_EntryField_Nullable.md | 69 --------- ...fline_SubField_NonNull_ListItem_NonNull.md | 125 --------------- ...line_SubField_NonNull_ListItem_Nullable.md | 131 ---------------- ...econd_Service_Offline_SubField_Nullable.md | 143 ------------------ ...One_Service_Offline_EntryFields_NonNull.md | 79 ---------- ...ne_Service_Offline_EntryFields_Nullable.md | 84 ---------- ...ngle_Service_Offline_EntryField_NonNull.md | 65 -------- ...gle_Service_Offline_EntryField_Nullable.md | 67 -------- ...irst_Service_Offline_EntryField_NonNull.md | 97 ------------ ...rst_Service_Offline_EntryField_Nullable.md | 99 ------------ ...Offline_SubField_NonNull_Parent_NonNull.md | 101 ------------- ...ffline_SubField_NonNull_Parent_Nullable.md | 104 ------------- .../IntrospectionClientTests.cs | 61 ++++++++ 60 files changed, 676 insertions(+), 1834 deletions(-) create mode 100644 src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Node_Service_Offline_EntryField_Nullable.md rename src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/{__EXPECTED__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_Nullable_Parent_Nullable.md => TransportErrorTests.Resolve_Sequence_Node_Second_Service_Offline_SubField_Nullable_Parent_Nullable.md} (88%) delete mode 100644 src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Both_Services_Offline_EntryField_NonNull.md delete mode 100644 src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Both_Services_Offline_EntryField_Nullable.md delete mode 100644 src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Second_Service_Offline_SubFields_NonNull_EntryField_NonNull.md delete mode 100644 src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Second_Service_Offline_SubFields_NonNull_EntryField_Nullable.md delete mode 100644 src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Single_Service_Offline_EntryField_NonNull.md delete mode 100644 src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Single_Service_Offline_EntryField_Nullable.md delete mode 100644 src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_NonNull_ListItem_NonNull.md delete mode 100644 src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_NonNull_ListItem_Nullable.md delete mode 100644 src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_Nullable.md delete mode 100644 src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_EntryFields_NonNull.md delete mode 100644 src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_EntryFields_Nullable.md delete mode 100644 src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Parallel_Single_Service_Offline_EntryField_NonNull.md delete mode 100644 src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Parallel_Single_Service_Offline_EntryField_Nullable.md delete mode 100644 src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Sequence_First_Service_Offline_EntryField_NonNull.md delete mode 100644 src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Sequence_First_Service_Offline_EntryField_Nullable.md delete mode 100644 src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_NonNull_Parent_NonNull.md delete mode 100644 src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_NonNull_Parent_Nullable.md diff --git a/src/HotChocolate/AspNetCore/src/Transport.Http/GraphQLHttpResponse.cs b/src/HotChocolate/AspNetCore/src/Transport.Http/GraphQLHttpResponse.cs index 09b48f1472e..2826a2f6df5 100644 --- a/src/HotChocolate/AspNetCore/src/Transport.Http/GraphQLHttpResponse.cs +++ b/src/HotChocolate/AspNetCore/src/Transport.Http/GraphQLHttpResponse.cs @@ -134,8 +134,9 @@ public ValueTask ReadAsResultAsync(CancellationToken cancellati #endif } - // if the media type is anything else we will return a transport error. - return new ValueTask(_transportError); + _message.EnsureSuccessStatusCode(); + + throw new InvalidOperationException("Received a successful response with an unexpected content type."); } #if NET6_0_OR_GREATER diff --git a/src/HotChocolate/AspNetCore/test/Transport.Http.Tests/GraphQLHttpClientTests.cs b/src/HotChocolate/AspNetCore/test/Transport.Http.Tests/GraphQLHttpClientTests.cs index 747c4390cd9..5b747582819 100644 --- a/src/HotChocolate/AspNetCore/test/Transport.Http.Tests/GraphQLHttpClientTests.cs +++ b/src/HotChocolate/AspNetCore/test/Transport.Http.Tests/GraphQLHttpClientTests.cs @@ -1,3 +1,4 @@ +using System.Net; using System.Text.Json; using CookieCrumble; using HotChocolate.AspNetCore.Tests.Utilities; @@ -14,6 +15,82 @@ public class GraphQLHttpClientTests : ServerTestBase /// public GraphQLHttpClientTests(TestServerFactory serverFactory) : base(serverFactory) { } + [Fact] + public async Task Post_Http_200_Wrong_Content_Type() + { + // arrange + var httpClient = new HttpClient(new CustomHttpClientHandler(HttpStatusCode.OK)); + + var query = + """ + query { + hero(episode: JEDI) { + name + } + } + """; + + var client = new DefaultGraphQLHttpClient(httpClient); + + // act + var response = await client.PostAsync(query, "/graphql"); + + async Task Error() => await response.ReadAsResultAsync(); + + // assert + var exception = await Assert.ThrowsAsync(Error); + Assert.Equal("Received a successful response with an unexpected content type.", exception.Message); + } + + [Fact] + public async Task Post_Http_404_Wrong_Content_Type() + { + var httpClient = new HttpClient(new CustomHttpClientHandler(HttpStatusCode.NotFound)); + + var query = + """ + query { + hero(episode: JEDI) { + name + } + } + """; + + var client = new DefaultGraphQLHttpClient(httpClient); + + // act + var response = await client.PostAsync(query, "/graphql"); + + async Task Error() => await response.ReadAsResultAsync(); + + // assert + await Assert.ThrowsAsync(Error); + } + + [Fact] + public async Task Post_Transport_Error() + { + var httpClient = new HttpClient(new CustomHttpClientHandler()); + + var query = + """ + query { + hero(episode: JEDI) { + name + } + } + """; + + var client = new DefaultGraphQLHttpClient(httpClient); + + // act + async Task Error() => await client.PostAsync(query, "/graphql"); + + // assert + var exception = await Assert.ThrowsAsync(Error); + Assert.Equal("Something went wrong", exception.Message); + } + [Fact] public async Task Post_GraphQL_Query_With_RequestUri() { @@ -778,6 +855,21 @@ public async Task Post_GraphQL_FileUpload_With_ObjectValueNode() """); } + private class CustomHttpClientHandler(HttpStatusCode? httpStatusCode = null) : HttpClientHandler + { + protected override Task SendAsync( + HttpRequestMessage request, + CancellationToken cancellationToken) + { + if (httpStatusCode.HasValue) + { + return Task.FromResult(new HttpResponseMessage(httpStatusCode.Value)); + } + + throw new Exception("Something went wrong"); + } + } + public class ErrorSubscription { public async IAsyncEnumerable CreateStream() diff --git a/src/HotChocolate/Fusion/src/Core/Clients/DefaultHttpGraphQLClient.cs b/src/HotChocolate/Fusion/src/Core/Clients/DefaultHttpGraphQLClient.cs index 0225eb3c35a..ef09f7b5bfa 100644 --- a/src/HotChocolate/Fusion/src/Core/Clients/DefaultHttpGraphQLClient.cs +++ b/src/HotChocolate/Fusion/src/Core/Clients/DefaultHttpGraphQLClient.cs @@ -7,7 +7,6 @@ namespace HotChocolate.Fusion.Clients; internal sealed class DefaultHttpGraphQLClient : IGraphQLClient { - private static readonly GraphQLResponse _transportError = new(CreateTransportError()); private readonly HttpClientConfiguration _config; private readonly DefaultGraphQLHttpClient _client; @@ -51,20 +50,12 @@ private async Task ExecuteInternalAsync(SubgraphGraphQLRequest var result = await response.ReadAsResultAsync(ct).ConfigureAwait(false); return new GraphQLResponse(result); } - catch + catch (Exception exception) { - return _transportError; + return new GraphQLResponse(exception); } } - private static JsonElement CreateTransportError() - { - return JsonDocument.Parse( - """ - [{"message": "Internal Execution Error"}] - """).RootElement; - } - public ValueTask DisposeAsync() { _client.Dispose(); diff --git a/src/HotChocolate/Fusion/src/Core/Clients/GraphQLResponse.cs b/src/HotChocolate/Fusion/src/Core/Clients/GraphQLResponse.cs index 4db04e639a5..00dbb006ba4 100644 --- a/src/HotChocolate/Fusion/src/Core/Clients/GraphQLResponse.cs +++ b/src/HotChocolate/Fusion/src/Core/Clients/GraphQLResponse.cs @@ -7,9 +7,9 @@ public sealed class GraphQLResponse : IDisposable { private readonly IDisposable? _resource; - internal GraphQLResponse(JsonElement errors) + internal GraphQLResponse(Exception transportException) { - Errors = errors; + TransportException = transportException; } internal GraphQLResponse(OperationResult result) @@ -20,32 +20,16 @@ internal GraphQLResponse(OperationResult result) Extensions = result.Extensions; } - public GraphQLResponse(JsonDocument document) - { - _resource = document; - - if (document.RootElement.TryGetProperty(ResponseProperties.Data, out var value)) - { - Data = value; - } - - if (document.RootElement.TryGetProperty(ResponseProperties.Errors, out value)) - { - Errors = value; - } - - if (document.RootElement.TryGetProperty(ResponseProperties.Extensions, out value)) - { - Extensions = value; - } - } - public JsonElement Data { get; } public JsonElement Errors { get; } public JsonElement Extensions { get; } + public Exception? TransportException { get; private set; } + public void Dispose() - => _resource?.Dispose(); + { + _resource?.Dispose(); + } } diff --git a/src/HotChocolate/Fusion/src/Core/Execution/ExecutionUtils.cs b/src/HotChocolate/Fusion/src/Core/Execution/ExecutionUtils.cs index 94f21eb9209..a06bee99d73 100644 --- a/src/HotChocolate/Fusion/src/Core/Execution/ExecutionUtils.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/ExecutionUtils.cs @@ -5,6 +5,7 @@ using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Execution.Nodes; using HotChocolate.Fusion.Metadata; +using HotChocolate.Fusion.Planning; using HotChocolate.Fusion.Utilities; using HotChocolate.Language; using HotChocolate.Language.Visitors; @@ -394,8 +395,8 @@ private static void ExtractSelectionResults( while (Unsafe.IsAddressLessThan(ref selection, ref endSelection)) { - if (data.ValueKind is not JsonValueKind.Null && - data.TryGetProperty(selection.ResponseName, out var value)) + if (data.ValueKind is not JsonValueKind.Null + && data.TryGetProperty(selection.ResponseName, out var value)) { selectionData = selectionData.AddResult(new JsonResult(schemaName, value)); } @@ -417,8 +418,8 @@ private static void ExtractSelectionResults( while (Unsafe.IsAddressLessThan(ref selection, ref endSelection)) { - if (element.ValueKind is not JsonValueKind.Null && - element.TryGetProperty(selection.ResponseName, out var value)) + if (element.ValueKind is not JsonValueKind.Null + && element.TryGetProperty(selection.ResponseName, out var value)) { selectionData = selectionData.AddResult(new JsonResult(schemaName, value)); } @@ -494,6 +495,33 @@ public static void TryInitializeExecutionState(QueryPlan queryPlan, ExecutionSta executionState.IsInitialized = true; } + public static void CreateTransportErrors( + Exception transportException, + ResultBuilder resultBuilder, + IErrorHandler errorHandler, + ObjectResult selectionSetResult, + List rootSelections, + string subgraphName, + bool addDebugInfo) + { + foreach (var rootSelection in rootSelections) + { + var errorBuilder = errorHandler.CreateUnexpectedError(transportException); + + errorBuilder.AddLocation(rootSelection.Selection.SyntaxNode); + errorBuilder.SetPath(PathHelper.CreatePathFromContext(rootSelection.Selection, selectionSetResult, 0)); + + if (addDebugInfo) + { + errorBuilder.SetExtension("subgraphName", subgraphName); + } + + var error = errorHandler.Handle(errorBuilder.Build()); + + resultBuilder.AddError(error); + } + } + public static void ExtractErrors( DocumentNode document, OperationDefinitionNode operation, @@ -509,10 +537,11 @@ public static void ExtractErrors( return; } - var path = PathHelper.CreatePathFromContext(selectionSetResult); + var parentPath = PathHelper.CreatePathFromContext(selectionSetResult); + foreach (var error in errors.EnumerateArray()) { - ExtractError(document, operation, resultBuilder, errorHandler, error, path, pathDepth, addDebugInfo); + ExtractError(document, operation, resultBuilder, errorHandler, error, parentPath, pathDepth, addDebugInfo); } } @@ -724,7 +753,7 @@ private sealed class ErrorPathVisitor : SyntaxWalker Visit(operation, context); - var field = context.Field; + var field = context.Field; context.Reset(); Interlocked.Exchange(ref _errorPathContext, context); diff --git a/src/HotChocolate/Fusion/src/Core/Execution/Nodes/Resolve.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/Resolve.cs index 180c6be4a6b..1247296448f 100644 --- a/src/HotChocolate/Fusion/src/Core/Execution/Nodes/Resolve.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/Resolve.cs @@ -148,6 +148,18 @@ private void ProcessResponses( var exportKeys = state.Requires; var variableValues = state.VariableValues; + if (response.TransportException is not null) + { + CreateTransportErrors( + response.TransportException, + context.Result, + context.ErrorHandler, + selectionSetResult, + RootSelections, + subgraphName, + context.ShowDebugInfo); + } + ExtractErrors( context.Operation.Document, context.Operation.Definition, diff --git a/src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolveByKeyBatch.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolveByKeyBatch.cs index 92402b67dc0..edc4c967b37 100644 --- a/src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolveByKeyBatch.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolveByKeyBatch.cs @@ -90,7 +90,7 @@ protected override async Task OnExecuteAsync( // query plan nodes be interested in it. lock (executionState) { - ProcessResult(context, response, batchExecutionState); + ProcessResult(context, response, batchExecutionState, SubgraphName); } } catch (Exception ex) @@ -142,7 +142,8 @@ private static void InitializeRequests(FusionExecutionContext context, List /// The selection set for which this request provides a patch. /// + /// + /// The root selections of this subgraph request. + /// /// /// The variables that this resolver node will provide. /// @@ -51,6 +55,7 @@ public Config( DocumentNode document, ISelection? parent, ISelectionSet selectionSet, + List rootSelections, IEnumerable provides, IEnumerable requires, IEnumerable forwardedVariables, @@ -63,6 +68,7 @@ public Config( SubgraphName = subgraphName; Document = document.ToString(false); Parent = parent; + RootSelections = rootSelections; SelectionSet = Unsafe.As(selectionSet); Provides = CollectionUtils.CopyToArray(provides, ref buffer, ref usedCapacity); Requires = CollectionUtils.CopyToArray(requires, ref buffer, ref usedCapacity); @@ -94,6 +100,11 @@ public Config( /// public ISelection? Parent { get; } + /// + /// Gets the root selections of this subgraph request. + /// + public List RootSelections { get; } + /// /// Gets the selection set for which this request provides a patch. /// diff --git a/src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolverNodeBase.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolverNodeBase.cs index b1dfb8e6531..97a02c687da 100644 --- a/src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolverNodeBase.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolverNodeBase.cs @@ -4,6 +4,7 @@ using HotChocolate.Execution; using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Clients; +using HotChocolate.Fusion.Planning; using HotChocolate.Language; using static HotChocolate.Fusion.Utilities.Utf8QueryPlanPropertyNames; using ThrowHelper = HotChocolate.Fusion.Utilities.ThrowHelper; @@ -20,6 +21,7 @@ internal abstract partial class ResolverNodeBase : QueryPlanNode private readonly string _document; private readonly ISelection? _parent; private readonly SelectionSet _selectionSet; + private readonly List _rootSelections; private readonly string[] _provides; private readonly string[] _requires; private readonly string[] _forwardedVariables; @@ -44,6 +46,7 @@ protected ResolverNodeBase(int id, Config config) _document = config.Document; _parent = config.Parent; _selectionSet = config.SelectionSet; + _rootSelections = config.RootSelections; _provides = config.Provides; _requires = config.Requires; _forwardedVariables = config.ForwardedVariables; @@ -67,6 +70,11 @@ protected ResolverNodeBase(int id, Config config) /// protected internal SelectionSet SelectionSet => _selectionSet; + /// + /// Gets the root selections of this resolver. + /// + protected internal List RootSelections => _rootSelections; + /// /// Gets the state that is being required by this resolver to be executed. /// diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Pipeline/ExecutionNodeBuilderMiddleware.cs b/src/HotChocolate/Fusion/src/Core/Planning/Pipeline/ExecutionNodeBuilderMiddleware.cs index e9da33a335e..64a09b0d16e 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Pipeline/ExecutionNodeBuilderMiddleware.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Pipeline/ExecutionNodeBuilderMiddleware.cs @@ -138,6 +138,7 @@ private Resolve CreateResolveNode( request.Document, executionStep.ParentSelection, selectionSet, + executionStep.RootSelections, context.Exports.GetExportKeys(executionStep), executionStep.Variables.Values, context.ForwardedVariables.Select(t => t.Variable.Name.Value), @@ -218,6 +219,7 @@ private Resolve CreateResolveNodeNode( requestDocument, executionStep.ParentSelection, selectionSet, + executionStep.SelectEntityStep.RootSelections, context.Exports.GetExportKeys(executionStep), executionStep.SelectEntityStep.Variables.Values, context.ForwardedVariables.Select(t => t.Variable.Name.Value), @@ -261,6 +263,7 @@ private ResolveByKeyBatch CreateResolveByKeyBatchNode( request.Document, executionStep.ParentSelection, selectionSet, + executionStep.RootSelections, context.Exports.GetExportKeys(executionStep), executionStep.Variables.Values, context.ForwardedVariables.Select(t => t.Variable.Name.Value), @@ -288,6 +291,7 @@ private Subscribe CreateSubscribeNode( request.Document, executionStep.ParentSelection, selectionSet, + executionStep.RootSelections, context.Exports.GetExportKeys(executionStep), executionStep.Variables.Values, context.ForwardedVariables.Select(t => t.Variable.Name.Value), diff --git a/src/HotChocolate/Fusion/test/Core.Tests/TransportErrorTests.cs b/src/HotChocolate/Fusion/test/Core.Tests/TransportErrorTests.cs index bb9d0cc06e8..1beca21ec6f 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/TransportErrorTests.cs +++ b/src/HotChocolate/Fusion/test/Core.Tests/TransportErrorTests.cs @@ -7,6 +7,49 @@ namespace HotChocolate.Fusion; public class TransportErrorTests(ITestOutputHelper output) { + #region Resolve (node) + [Fact] + public async Task Resolve_Node_Service_Offline_EntryField_Nullable() + { + // arrange + var subgraph = await TestSubgraph.CreateAsync( + """ + type Query { + node(id: ID!): Node + } + + type Brand implements Node { + id: ID! + name: String + } + + interface Node { + id: ID! + } + """, + isOffline: true); + + using var subgraphs = new TestSubgraphCollection(output, [subgraph]); + var executor = await subgraphs.GetExecutorAsync(); + var request = """ + query { + node(id: "QnJhbmQ6MQ==") { + id + ... on Brand { + name + } + } + } + """; + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result); + } + #endregion + #region Parallel, Shared Entry Field [Fact] @@ -1228,6 +1271,66 @@ type Brand { #endregion + #region Resolve Sequence (node) + [Fact] + public async Task Resolve_Sequence_Node_Second_Service_Offline_SubField_Nullable_Parent_Nullable() + { + // arrange + var subgraphA = await TestSubgraph.CreateAsync( + """ + type Query { + product: Product + } + + type Product { + id: ID! + brand: Brand + } + + type Brand { + id: ID! + } + """); + + var subgraphB = await TestSubgraph.CreateAsync( + """ + type Query { + node(id: ID!): Node + } + + type Brand implements Node { + id: ID! + name: String + } + + interface Node { + id: ID! + } + """, + isOffline: true); + + using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB]); + var executor = await subgraphs.GetExecutorAsync(); + var request = """ + query { + product { + id + brand { + id + name + } + } + } + """; + + // act + var result = await executor.ExecuteAsync(request); + + // assert + MatchMarkdownSnapshot(request, result); + } + #endregion + #region ResolveByKey [Fact] diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Both_Services_Offline_EntryField_NonNull.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Both_Services_Offline_EntryField_NonNull.md index 8468d45e36a..78ee98560a7 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Both_Services_Offline_EntryField_NonNull.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Both_Services_Offline_EntryField_NonNull.md @@ -6,7 +6,7 @@ { "errors": [ { - "message": "Cannot return null for non-nullable field.", + "message": "Unexpected Execution Error", "locations": [ { "line": 2, @@ -15,13 +15,7 @@ ], "path": [ "productById" - ], - "extensions": { - "code": "HC0018" - } - }, - { - "message": "Internal Execution Error" + ] } ], "data": null diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Both_Services_Offline_EntryField_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Both_Services_Offline_EntryField_Nullable.md index a90fdb636ca..a4fbc64904d 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Both_Services_Offline_EntryField_Nullable.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Both_Services_Offline_EntryField_Nullable.md @@ -6,7 +6,16 @@ { "errors": [ { - "message": "Internal Execution Error" + "message": "Unexpected Execution Error", + "locations": [ + { + "line": 2, + "column": 3 + } + ], + "path": [ + "productById" + ] } ], "data": { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_First_Service_Offline_SubFields_NonNull_EntryField_NonNull.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_First_Service_Offline_SubFields_NonNull_EntryField_NonNull.md index a8930f61de3..bf64114ffc8 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_First_Service_Offline_SubFields_NonNull_EntryField_NonNull.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_First_Service_Offline_SubFields_NonNull_EntryField_NonNull.md @@ -6,7 +6,7 @@ { "errors": [ { - "message": "Cannot return null for non-nullable field.", + "message": "Unexpected Execution Error", "locations": [ { "line": 2, @@ -15,13 +15,7 @@ ], "path": [ "productById" - ], - "extensions": { - "code": "HC0018" - } - }, - { - "message": "Internal Execution Error" + ] } ], "data": null diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_First_Service_Offline_SubFields_NonNull_EntryField_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_First_Service_Offline_SubFields_NonNull_EntryField_Nullable.md index db463159f7a..3ec42de33dd 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_First_Service_Offline_SubFields_NonNull_EntryField_Nullable.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_First_Service_Offline_SubFields_NonNull_EntryField_Nullable.md @@ -6,7 +6,16 @@ { "errors": [ { - "message": "Internal Execution Error" + "message": "Unexpected Execution Error", + "locations": [ + { + "line": 2, + "column": 3 + } + ], + "path": [ + "productById" + ] } ], "data": { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_First_Service_Offline_SubFields_Nullable_EntryField_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_First_Service_Offline_SubFields_Nullable_EntryField_Nullable.md index 097510636f5..17fbdeb8007 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_First_Service_Offline_SubFields_Nullable_EntryField_Nullable.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_First_Service_Offline_SubFields_Nullable_EntryField_Nullable.md @@ -6,7 +6,16 @@ { "errors": [ { - "message": "Internal Execution Error" + "message": "Unexpected Execution Error", + "locations": [ + { + "line": 2, + "column": 3 + } + ], + "path": [ + "productById" + ] } ], "data": { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Second_Service_Offline_SubFields_NonNull_EntryField_NonNull.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Second_Service_Offline_SubFields_NonNull_EntryField_NonNull.md index 60e92f8dec0..c1b1c79e725 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Second_Service_Offline_SubFields_NonNull_EntryField_NonNull.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Second_Service_Offline_SubFields_NonNull_EntryField_NonNull.md @@ -6,7 +6,7 @@ { "errors": [ { - "message": "Cannot return null for non-nullable field.", + "message": "Unexpected Execution Error", "locations": [ { "line": 6, @@ -16,13 +16,7 @@ "path": [ "productById", "score" - ], - "extensions": { - "code": "HC0018" - } - }, - { - "message": "Internal Execution Error" + ] } ], "data": null diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Second_Service_Offline_SubFields_NonNull_EntryField_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Second_Service_Offline_SubFields_NonNull_EntryField_Nullable.md index 9d1523d0d4d..62963e34f3d 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Second_Service_Offline_SubFields_NonNull_EntryField_Nullable.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Second_Service_Offline_SubFields_NonNull_EntryField_Nullable.md @@ -6,7 +6,7 @@ { "errors": [ { - "message": "Cannot return null for non-nullable field.", + "message": "Unexpected Execution Error", "locations": [ { "line": 6, @@ -16,13 +16,7 @@ "path": [ "productById", "score" - ], - "extensions": { - "code": "HC0018" - } - }, - { - "message": "Internal Execution Error" + ] } ], "data": { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Second_Service_Offline_SubFields_Nullable_EntryField_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Second_Service_Offline_SubFields_Nullable_EntryField_Nullable.md index 65fa2692606..79c79fc0cd1 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Second_Service_Offline_SubFields_Nullable_EntryField_Nullable.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Second_Service_Offline_SubFields_Nullable_EntryField_Nullable.md @@ -6,7 +6,17 @@ { "errors": [ { - "message": "Internal Execution Error" + "message": "Unexpected Execution Error", + "locations": [ + { + "line": 6, + "column": 5 + } + ], + "path": [ + "productById", + "score" + ] } ], "data": { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Single_Service_Offline_EntryField_NonNull.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Single_Service_Offline_EntryField_NonNull.md index 9fd4ffc2c89..58617313e5d 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Single_Service_Offline_EntryField_NonNull.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Single_Service_Offline_EntryField_NonNull.md @@ -6,7 +6,7 @@ { "errors": [ { - "message": "Cannot return null for non-nullable field.", + "message": "Unexpected Execution Error", "locations": [ { "line": 2, @@ -15,13 +15,7 @@ ], "path": [ "productById" - ], - "extensions": { - "code": "HC0018" - } - }, - { - "message": "Internal Execution Error" + ] } ], "data": null diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Single_Service_Offline_EntryField_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Single_Service_Offline_EntryField_Nullable.md index 3ff8bb6f9a0..30bc07ad689 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Single_Service_Offline_EntryField_Nullable.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Entity_Resolver_Single_Service_Offline_EntryField_Nullable.md @@ -6,7 +6,16 @@ { "errors": [ { - "message": "Internal Execution Error" + "message": "Unexpected Execution Error", + "locations": [ + { + "line": 2, + "column": 3 + } + ], + "path": [ + "productById" + ] } ], "data": { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_NonNull_ListItem_NonNull.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_NonNull_ListItem_NonNull.md index a4a6765bc2e..757ca726d78 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_NonNull_ListItem_NonNull.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_NonNull_ListItem_NonNull.md @@ -6,7 +6,7 @@ { "errors": [ { - "message": "Cannot return null for non-nullable field.", + "message": "Unexpected Execution Error", "locations": [ { "line": 5, @@ -15,15 +15,12 @@ ], "path": [ "products", - 2, + 0, "price" - ], - "extensions": { - "code": "HC0018" - } + ] }, { - "message": "Cannot return null for non-nullable field.", + "message": "Unexpected Execution Error", "locations": [ { "line": 5, @@ -34,13 +31,10 @@ "products", 1, "price" - ], - "extensions": { - "code": "HC0018" - } + ] }, { - "message": "Cannot return null for non-nullable field.", + "message": "Unexpected Execution Error", "locations": [ { "line": 5, @@ -49,15 +43,9 @@ ], "path": [ "products", - 0, + 2, "price" - ], - "extensions": { - "code": "HC0018" - } - }, - { - "message": "Internal Execution Error" + ] } ], "data": null diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_NonNull_ListItem_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_NonNull_ListItem_Nullable.md index 664c73d2750..0ad49befe05 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_NonNull_ListItem_Nullable.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_NonNull_ListItem_Nullable.md @@ -6,7 +6,7 @@ { "errors": [ { - "message": "Cannot return null for non-nullable field.", + "message": "Unexpected Execution Error", "locations": [ { "line": 5, @@ -15,15 +15,12 @@ ], "path": [ "products", - 2, + 0, "price" - ], - "extensions": { - "code": "HC0018" - } + ] }, { - "message": "Cannot return null for non-nullable field.", + "message": "Unexpected Execution Error", "locations": [ { "line": 5, @@ -34,13 +31,10 @@ "products", 1, "price" - ], - "extensions": { - "code": "HC0018" - } + ] }, { - "message": "Cannot return null for non-nullable field.", + "message": "Unexpected Execution Error", "locations": [ { "line": 5, @@ -49,15 +43,9 @@ ], "path": [ "products", - 0, + 2, "price" - ], - "extensions": { - "code": "HC0018" - } - }, - { - "message": "Internal Execution Error" + ] } ], "data": { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_Nullable.md index 20b350084a9..032925931ed 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_Nullable.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_Nullable.md @@ -6,7 +6,46 @@ { "errors": [ { - "message": "Internal Execution Error" + "message": "Unexpected Execution Error", + "locations": [ + { + "line": 5, + "column": 5 + } + ], + "path": [ + "products", + 0, + "price" + ] + }, + { + "message": "Unexpected Execution Error", + "locations": [ + { + "line": 5, + "column": 5 + } + ], + "path": [ + "products", + 1, + "price" + ] + }, + { + "message": "Unexpected Execution Error", + "locations": [ + { + "line": 5, + "column": 5 + } + ], + "path": [ + "products", + 2, + "price" + ] } ], "data": { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Node_Service_Offline_EntryField_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Node_Service_Offline_EntryField_Nullable.md new file mode 100644 index 00000000000..0858279e2d4 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Node_Service_Offline_EntryField_Nullable.md @@ -0,0 +1,80 @@ +# Resolve_Node_Service_Offline_EntryField_Nullable + +## Result + +```json +{ + "errors": [ + { + "message": "Unexpected Execution Error", + "locations": [ + { + "line": 2, + "column": 3 + } + ], + "path": [ + "node" + ] + } + ], + "data": { + "node": null + } +} +``` + +## Request + +```graphql +{ + node(id: "QnJhbmQ6MQ==") { + id + ... on Brand { + name + } + } +} +``` + +## QueryPlan Hash + +```text +32501CA9B2CFE1072BCA51CC37D3C65085CC9CB5 +``` + +## QueryPlan + +```json +{ + "document": "{ node(id: \u0022QnJhbmQ6MQ==\u0022) { id ... on Brand { name } } }", + "rootNode": { + "type": "Sequence", + "nodes": [ + { + "type": "ResolveNode", + "selectionId": 0, + "responseName": "node", + "branches": [ + { + "type": "Brand", + "node": { + "type": "Resolve", + "subgraph": "Subgraph_1", + "document": "query fetch_node_1 { node(id: \u0022QnJhbmQ6MQ==\u0022) { ... on Brand { id name __typename } } }", + "selectionSetId": 0 + } + } + ] + }, + { + "type": "Compose", + "selectionSetIds": [ + 0 + ] + } + ] + } +} +``` + diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_Both_Services_Offline_SharedEntryField_NonNull.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_Both_Services_Offline_SharedEntryField_NonNull.md index cc07832ee3d..cf5d51b86f8 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_Both_Services_Offline_SharedEntryField_NonNull.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_Both_Services_Offline_SharedEntryField_NonNull.md @@ -6,7 +6,7 @@ { "errors": [ { - "message": "Cannot return null for non-nullable field.", + "message": "Unexpected Execution Error", "locations": [ { "line": 2, @@ -15,16 +15,19 @@ ], "path": [ "viewer" - ], - "extensions": { - "code": "HC0018" - } + ] }, { - "message": "Internal Execution Error" - }, - { - "message": "Internal Execution Error" + "message": "Unexpected Execution Error", + "locations": [ + { + "line": 3, + "column": 5 + } + ], + "path": [ + "userId" + ] } ], "data": null diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_Both_Services_Offline_SharedEntryField_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_Both_Services_Offline_SharedEntryField_Nullable.md index 656cf6de082..456bbd50d3c 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_Both_Services_Offline_SharedEntryField_Nullable.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_Both_Services_Offline_SharedEntryField_Nullable.md @@ -6,10 +6,28 @@ { "errors": [ { - "message": "Internal Execution Error" + "message": "Unexpected Execution Error", + "locations": [ + { + "line": 2, + "column": 3 + } + ], + "path": [ + "viewer" + ] }, { - "message": "Internal Execution Error" + "message": "Unexpected Execution Error", + "locations": [ + { + "line": 3, + "column": 5 + } + ], + "path": [ + "userId" + ] } ], "data": { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_EntryFields_NonNull.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_EntryFields_NonNull.md index 2946f88611b..b4b3f5e9a2f 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_EntryFields_NonNull.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_EntryFields_NonNull.md @@ -6,7 +6,7 @@ { "errors": [ { - "message": "Cannot return null for non-nullable field.", + "message": "Unexpected Execution Error", "locations": [ { "line": 2, @@ -15,13 +15,7 @@ ], "path": [ "viewer" - ], - "extensions": { - "code": "HC0018" - } - }, - { - "message": "Internal Execution Error" + ] } ], "data": null diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_EntryFields_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_EntryFields_Nullable.md index 0037513d5d8..0a5d8992d68 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_EntryFields_Nullable.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_EntryFields_Nullable.md @@ -6,7 +6,16 @@ { "errors": [ { - "message": "Internal Execution Error" + "message": "Unexpected Execution Error", + "locations": [ + { + "line": 2, + "column": 3 + } + ], + "path": [ + "viewer" + ] } ], "data": { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_SubField_NonNull_SharedEntryField_NonNull.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_SubField_NonNull_SharedEntryField_NonNull.md index 44dd2662596..e7a844782da 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_SubField_NonNull_SharedEntryField_NonNull.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_SubField_NonNull_SharedEntryField_NonNull.md @@ -6,7 +6,7 @@ { "errors": [ { - "message": "Cannot return null for non-nullable field.", + "message": "Unexpected Execution Error", "locations": [ { "line": 2, @@ -15,10 +15,7 @@ ], "path": [ "viewer" - ], - "extensions": { - "code": "HC0018" - } + ] }, { "message": "Cannot return null for non-nullable field.", @@ -35,9 +32,6 @@ "extensions": { "code": "HC0018" } - }, - { - "message": "Internal Execution Error" } ], "data": null diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_SubField_NonNull_SharedEntryField_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_SubField_NonNull_SharedEntryField_Nullable.md index 1eeca1e0067..88d477455d5 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_SubField_NonNull_SharedEntryField_Nullable.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_SubField_NonNull_SharedEntryField_Nullable.md @@ -5,6 +5,18 @@ ```json { "errors": [ + { + "message": "Unexpected Execution Error", + "locations": [ + { + "line": 2, + "column": 3 + } + ], + "path": [ + "viewer" + ] + }, { "message": "Cannot return null for non-nullable field.", "locations": [ @@ -20,9 +32,6 @@ "extensions": { "code": "HC0018" } - }, - { - "message": "Internal Execution Error" } ], "data": { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_SubField_Nullable_SharedEntryField_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_SubField_Nullable_SharedEntryField_Nullable.md index 6cab0f37ad2..4fd9c78f53e 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_SubField_Nullable_SharedEntryField_Nullable.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_SubField_Nullable_SharedEntryField_Nullable.md @@ -6,7 +6,16 @@ { "errors": [ { - "message": "Internal Execution Error" + "message": "Unexpected Execution Error", + "locations": [ + { + "line": 2, + "column": 3 + } + ], + "path": [ + "viewer" + ] } ], "data": { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_Single_Service_Offline_EntryField_NonNull.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_Single_Service_Offline_EntryField_NonNull.md index 9daaf733bee..ac75f5f061a 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_Single_Service_Offline_EntryField_NonNull.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_Single_Service_Offline_EntryField_NonNull.md @@ -6,7 +6,7 @@ { "errors": [ { - "message": "Cannot return null for non-nullable field.", + "message": "Unexpected Execution Error", "locations": [ { "line": 2, @@ -15,13 +15,7 @@ ], "path": [ "viewer" - ], - "extensions": { - "code": "HC0018" - } - }, - { - "message": "Internal Execution Error" + ] } ], "data": null diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_Single_Service_Offline_EntryField_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_Single_Service_Offline_EntryField_Nullable.md index e604e2fbe7f..e8223929ef3 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_Single_Service_Offline_EntryField_Nullable.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Parallel_Single_Service_Offline_EntryField_Nullable.md @@ -6,7 +6,16 @@ { "errors": [ { - "message": "Internal Execution Error" + "message": "Unexpected Execution Error", + "locations": [ + { + "line": 2, + "column": 3 + } + ], + "path": [ + "viewer" + ] } ], "data": { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_First_Service_Offline_EntryField_NonNull.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_First_Service_Offline_EntryField_NonNull.md index 8f2ce8ff3f1..5200397e3ca 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_First_Service_Offline_EntryField_NonNull.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_First_Service_Offline_EntryField_NonNull.md @@ -6,7 +6,7 @@ { "errors": [ { - "message": "Cannot return null for non-nullable field.", + "message": "Unexpected Execution Error", "locations": [ { "line": 2, @@ -15,13 +15,7 @@ ], "path": [ "product" - ], - "extensions": { - "code": "HC0018" - } - }, - { - "message": "Internal Execution Error" + ] } ], "data": null diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_First_Service_Offline_EntryField_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_First_Service_Offline_EntryField_Nullable.md index 3e7cbc3b4c4..2f0d443696a 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_First_Service_Offline_EntryField_Nullable.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_First_Service_Offline_EntryField_Nullable.md @@ -6,7 +6,16 @@ { "errors": [ { - "message": "Internal Execution Error" + "message": "Unexpected Execution Error", + "locations": [ + { + "line": 2, + "column": 3 + } + ], + "path": [ + "product" + ] } ], "data": { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_Nullable_Parent_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_Node_Second_Service_Offline_SubField_Nullable_Parent_Nullable.md similarity index 88% rename from src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_Nullable_Parent_Nullable.md rename to src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_Node_Second_Service_Offline_SubField_Nullable_Parent_Nullable.md index 5029f85a0de..cb16b1cd5fe 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_Nullable_Parent_Nullable.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_Node_Second_Service_Offline_SubField_Nullable_Parent_Nullable.md @@ -1,4 +1,4 @@ -# Resolve_Sequence_Second_Service_Offline_SubField_Nullable_Parent_Nullable +# Resolve_Sequence_Node_Second_Service_Offline_SubField_Nullable_Parent_Nullable ## Result @@ -49,7 +49,7 @@ ## QueryPlan Hash ```text -10F6CB69F78A0E4FD176C0F4651E2E37CF47C9C5 +D3BBE380CDE08C00EE4F104AAD03C78AC29E4B9C ``` ## QueryPlan @@ -80,10 +80,10 @@ { "type": "Resolve", "subgraph": "Subgraph_2", - "document": "query fetch_product_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", + "document": "query fetch_product_2($__fusion_exports__1: ID!) { node(id: $__fusion_exports__1) { ... on Brand { name } } }", "selectionSetId": 2, "path": [ - "brandById" + "node" ], "requires": [ { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_NonNull_Parent_NonNull.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_NonNull_Parent_NonNull.md index fa2b7c03504..db796bb0563 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_NonNull_Parent_NonNull.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_NonNull_Parent_NonNull.md @@ -6,7 +6,7 @@ { "errors": [ { - "message": "Cannot return null for non-nullable field.", + "message": "Unexpected Execution Error", "locations": [ { "line": 6, @@ -17,13 +17,7 @@ "product", "brand", "name" - ], - "extensions": { - "code": "HC0018" - } - }, - { - "message": "Internal Execution Error" + ] } ], "data": { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_NonNull_Parent_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_NonNull_Parent_Nullable.md index 7488f654f89..76819155651 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_NonNull_Parent_Nullable.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_NonNull_Parent_Nullable.md @@ -6,7 +6,7 @@ { "errors": [ { - "message": "Cannot return null for non-nullable field.", + "message": "Unexpected Execution Error", "locations": [ { "line": 6, @@ -17,13 +17,7 @@ "product", "brand", "name" - ], - "extensions": { - "code": "HC0018" - } - }, - { - "message": "Internal Execution Error" + ] } ], "data": { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_Nullable_Parent_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_Nullable_Parent_Nullable.md index 93409350430..5029f85a0de 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_Nullable_Parent_Nullable.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_Nullable_Parent_Nullable.md @@ -6,7 +6,18 @@ { "errors": [ { - "message": "Internal Execution Error" + "message": "Unexpected Execution Error", + "locations": [ + { + "line": 6, + "column": 7 + } + ], + "path": [ + "product", + "brand", + "name" + ] } ], "data": { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Both_Services_Offline_EntryField_NonNull.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Both_Services_Offline_EntryField_NonNull.md deleted file mode 100644 index 78ee98560a7..00000000000 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Both_Services_Offline_EntryField_NonNull.md +++ /dev/null @@ -1,96 +0,0 @@ -# Entity_Resolver_Both_Services_Offline_EntryField_NonNull - -## Result - -```json -{ - "errors": [ - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 2, - "column": 3 - } - ], - "path": [ - "productById" - ] - } - ], - "data": null -} -``` - -## Request - -```graphql -{ - productById(id: "1") { - id - name - price - score - } -} -``` - -## QueryPlan Hash - -```text -A5FE502D9F6F0548B898BC17A33BC0F2A2A13AE6 -``` - -## QueryPlan - -```json -{ - "document": "{ productById(id: \u00221\u0022) { id name price score } }", - "rootNode": { - "type": "Sequence", - "nodes": [ - { - "type": "Resolve", - "subgraph": "Subgraph_1", - "document": "query fetch_productById_1 { productById(id: \u00221\u0022) { id name price __fusion_exports__1: id } }", - "selectionSetId": 0, - "provides": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 0 - ] - }, - { - "type": "Resolve", - "subgraph": "Subgraph_2", - "document": "query fetch_productById_2($__fusion_exports__1: ID!) { productById(id: $__fusion_exports__1) { score } }", - "selectionSetId": 1, - "path": [ - "productById" - ], - "requires": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 1 - ] - } - ] - }, - "state": { - "__fusion_exports__1": "Product_id" - } -} -``` - diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Both_Services_Offline_EntryField_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Both_Services_Offline_EntryField_Nullable.md deleted file mode 100644 index a4fbc64904d..00000000000 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Both_Services_Offline_EntryField_Nullable.md +++ /dev/null @@ -1,98 +0,0 @@ -# Entity_Resolver_Both_Services_Offline_EntryField_Nullable - -## Result - -```json -{ - "errors": [ - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 2, - "column": 3 - } - ], - "path": [ - "productById" - ] - } - ], - "data": { - "productById": null - } -} -``` - -## Request - -```graphql -{ - productById(id: "1") { - id - name - price - score - } -} -``` - -## QueryPlan Hash - -```text -A5FE502D9F6F0548B898BC17A33BC0F2A2A13AE6 -``` - -## QueryPlan - -```json -{ - "document": "{ productById(id: \u00221\u0022) { id name price score } }", - "rootNode": { - "type": "Sequence", - "nodes": [ - { - "type": "Resolve", - "subgraph": "Subgraph_1", - "document": "query fetch_productById_1 { productById(id: \u00221\u0022) { id name price __fusion_exports__1: id } }", - "selectionSetId": 0, - "provides": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 0 - ] - }, - { - "type": "Resolve", - "subgraph": "Subgraph_2", - "document": "query fetch_productById_2($__fusion_exports__1: ID!) { productById(id: $__fusion_exports__1) { score } }", - "selectionSetId": 1, - "path": [ - "productById" - ], - "requires": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 1 - ] - } - ] - }, - "state": { - "__fusion_exports__1": "Product_id" - } -} -``` - diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_First_Service_Offline_SubFields_NonNull_EntryField_NonNull.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_First_Service_Offline_SubFields_NonNull_EntryField_NonNull.md index fd66d722999..c02366f0044 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_First_Service_Offline_SubFields_NonNull_EntryField_NonNull.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_First_Service_Offline_SubFields_NonNull_EntryField_NonNull.md @@ -6,19 +6,17 @@ { "errors": [ { - "message": "Cannot return null for non-nullable field.", + "message": "Unexpected Execution Error", "locations": [ { - "line": 2, - "column": 3 + "line": 4, + "column": 5 } ], "path": [ - "productById" - ], - "extensions": { - "code": "HC0018" - } + "productById", + "name" + ] } ], "data": null diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_First_Service_Offline_SubFields_NonNull_EntryField_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_First_Service_Offline_SubFields_NonNull_EntryField_Nullable.md index 3ec42de33dd..7b5463e2f27 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_First_Service_Offline_SubFields_NonNull_EntryField_Nullable.md +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_First_Service_Offline_SubFields_NonNull_EntryField_Nullable.md @@ -9,12 +9,13 @@ "message": "Unexpected Execution Error", "locations": [ { - "line": 2, - "column": 3 + "line": 4, + "column": 5 } ], "path": [ - "productById" + "productById", + "name" ] } ], diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Second_Service_Offline_SubFields_NonNull_EntryField_NonNull.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Second_Service_Offline_SubFields_NonNull_EntryField_NonNull.md deleted file mode 100644 index c1b1c79e725..00000000000 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Second_Service_Offline_SubFields_NonNull_EntryField_NonNull.md +++ /dev/null @@ -1,97 +0,0 @@ -# Entity_Resolver_Second_Service_Offline_SubFields_NonNull_EntryField_NonNull - -## Result - -```json -{ - "errors": [ - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 6, - "column": 5 - } - ], - "path": [ - "productById", - "score" - ] - } - ], - "data": null -} -``` - -## Request - -```graphql -{ - productById(id: "1") { - id - name - price - score - } -} -``` - -## QueryPlan Hash - -```text -A5FE502D9F6F0548B898BC17A33BC0F2A2A13AE6 -``` - -## QueryPlan - -```json -{ - "document": "{ productById(id: \u00221\u0022) { id name price score } }", - "rootNode": { - "type": "Sequence", - "nodes": [ - { - "type": "Resolve", - "subgraph": "Subgraph_1", - "document": "query fetch_productById_1 { productById(id: \u00221\u0022) { id name price __fusion_exports__1: id } }", - "selectionSetId": 0, - "provides": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 0 - ] - }, - { - "type": "Resolve", - "subgraph": "Subgraph_2", - "document": "query fetch_productById_2($__fusion_exports__1: ID!) { productById(id: $__fusion_exports__1) { score } }", - "selectionSetId": 1, - "path": [ - "productById" - ], - "requires": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 1 - ] - } - ] - }, - "state": { - "__fusion_exports__1": "Product_id" - } -} -``` - diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Second_Service_Offline_SubFields_NonNull_EntryField_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Second_Service_Offline_SubFields_NonNull_EntryField_Nullable.md deleted file mode 100644 index 62963e34f3d..00000000000 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Second_Service_Offline_SubFields_NonNull_EntryField_Nullable.md +++ /dev/null @@ -1,99 +0,0 @@ -# Entity_Resolver_Second_Service_Offline_SubFields_NonNull_EntryField_Nullable - -## Result - -```json -{ - "errors": [ - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 6, - "column": 5 - } - ], - "path": [ - "productById", - "score" - ] - } - ], - "data": { - "productById": null - } -} -``` - -## Request - -```graphql -{ - productById(id: "1") { - id - name - price - score - } -} -``` - -## QueryPlan Hash - -```text -A5FE502D9F6F0548B898BC17A33BC0F2A2A13AE6 -``` - -## QueryPlan - -```json -{ - "document": "{ productById(id: \u00221\u0022) { id name price score } }", - "rootNode": { - "type": "Sequence", - "nodes": [ - { - "type": "Resolve", - "subgraph": "Subgraph_1", - "document": "query fetch_productById_1 { productById(id: \u00221\u0022) { id name price __fusion_exports__1: id } }", - "selectionSetId": 0, - "provides": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 0 - ] - }, - { - "type": "Resolve", - "subgraph": "Subgraph_2", - "document": "query fetch_productById_2($__fusion_exports__1: ID!) { productById(id: $__fusion_exports__1) { score } }", - "selectionSetId": 1, - "path": [ - "productById" - ], - "requires": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 1 - ] - } - ] - }, - "state": { - "__fusion_exports__1": "Product_id" - } -} -``` - diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Single_Service_Offline_EntryField_NonNull.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Single_Service_Offline_EntryField_NonNull.md deleted file mode 100644 index 58617313e5d..00000000000 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Single_Service_Offline_EntryField_NonNull.md +++ /dev/null @@ -1,67 +0,0 @@ -# Entity_Resolver_Single_Service_Offline_EntryField_NonNull - -## Result - -```json -{ - "errors": [ - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 2, - "column": 3 - } - ], - "path": [ - "productById" - ] - } - ], - "data": null -} -``` - -## Request - -```graphql -{ - productById(id: "1") { - id - name - price - } -} -``` - -## QueryPlan Hash - -```text -3E29A9FA134FCCF20127189A9DE1B4CFB4492EAE -``` - -## QueryPlan - -```json -{ - "document": "{ productById(id: \u00221\u0022) { id name price } }", - "rootNode": { - "type": "Sequence", - "nodes": [ - { - "type": "Resolve", - "subgraph": "Subgraph_1", - "document": "query fetch_productById_1 { productById(id: \u00221\u0022) { id name price } }", - "selectionSetId": 0 - }, - { - "type": "Compose", - "selectionSetIds": [ - 0 - ] - } - ] - } -} -``` - diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Single_Service_Offline_EntryField_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Single_Service_Offline_EntryField_Nullable.md deleted file mode 100644 index 30bc07ad689..00000000000 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Entity_Resolver_Single_Service_Offline_EntryField_Nullable.md +++ /dev/null @@ -1,69 +0,0 @@ -# Entity_Resolver_Single_Service_Offline_EntryField_Nullable - -## Result - -```json -{ - "errors": [ - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 2, - "column": 3 - } - ], - "path": [ - "productById" - ] - } - ], - "data": { - "productById": null - } -} -``` - -## Request - -```graphql -{ - productById(id: "1") { - id - name - price - } -} -``` - -## QueryPlan Hash - -```text -3E29A9FA134FCCF20127189A9DE1B4CFB4492EAE -``` - -## QueryPlan - -```json -{ - "document": "{ productById(id: \u00221\u0022) { id name price } }", - "rootNode": { - "type": "Sequence", - "nodes": [ - { - "type": "Resolve", - "subgraph": "Subgraph_1", - "document": "query fetch_productById_1 { productById(id: \u00221\u0022) { id name price } }", - "selectionSetId": 0 - }, - { - "type": "Compose", - "selectionSetIds": [ - 0 - ] - } - ] - } -} -``` - diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_NonNull_ListItem_NonNull.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_NonNull_ListItem_NonNull.md deleted file mode 100644 index feed57bc8e0..00000000000 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_NonNull_ListItem_NonNull.md +++ /dev/null @@ -1,125 +0,0 @@ -# ResolveByKey_Second_Service_Offline_SubField_NonNull_ListItem_NonNull - -## Result - -```json -{ - "errors": [ - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 5, - "column": 5 - } - ], - "path": [ - "products", - 2, - "price" - ] - }, - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 5, - "column": 5 - } - ], - "path": [ - "products", - 1, - "price" - ] - }, - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 5, - "column": 5 - } - ], - "path": [ - "products", - 0, - "price" - ] - } - ], - "data": null -} -``` - -## Request - -```graphql -{ - products { - id - name - price - } -} -``` - -## QueryPlan Hash - -```text -C991588ECF525B8EF311F2923FD2CEE9D7BE5B3A -``` - -## QueryPlan - -```json -{ - "document": "{ products { id name price } }", - "rootNode": { - "type": "Sequence", - "nodes": [ - { - "type": "Resolve", - "subgraph": "Subgraph_1", - "document": "query fetch_products_1 { products { id name __fusion_exports__1: id } }", - "selectionSetId": 0, - "provides": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 0 - ] - }, - { - "type": "ResolveByKeyBatch", - "subgraph": "Subgraph_2", - "document": "query fetch_products_2($__fusion_exports__1: [ID!]!) { productsById(ids: $__fusion_exports__1) { price __fusion_exports__1: id } }", - "selectionSetId": 1, - "path": [ - "productsById" - ], - "requires": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 1 - ] - } - ] - }, - "state": { - "__fusion_exports__1": "Product_id" - } -} -``` - diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_NonNull_ListItem_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_NonNull_ListItem_Nullable.md deleted file mode 100644 index 87f2a7a4cb0..00000000000 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_NonNull_ListItem_Nullable.md +++ /dev/null @@ -1,131 +0,0 @@ -# ResolveByKey_Second_Service_Offline_SubField_NonNull_ListItem_Nullable - -## Result - -```json -{ - "errors": [ - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 5, - "column": 5 - } - ], - "path": [ - "products", - 2, - "price" - ] - }, - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 5, - "column": 5 - } - ], - "path": [ - "products", - 1, - "price" - ] - }, - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 5, - "column": 5 - } - ], - "path": [ - "products", - 0, - "price" - ] - } - ], - "data": { - "products": [ - null, - null, - null - ] - } -} -``` - -## Request - -```graphql -{ - products { - id - name - price - } -} -``` - -## QueryPlan Hash - -```text -C991588ECF525B8EF311F2923FD2CEE9D7BE5B3A -``` - -## QueryPlan - -```json -{ - "document": "{ products { id name price } }", - "rootNode": { - "type": "Sequence", - "nodes": [ - { - "type": "Resolve", - "subgraph": "Subgraph_1", - "document": "query fetch_products_1 { products { id name __fusion_exports__1: id } }", - "selectionSetId": 0, - "provides": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 0 - ] - }, - { - "type": "ResolveByKeyBatch", - "subgraph": "Subgraph_2", - "document": "query fetch_products_2($__fusion_exports__1: [ID!]!) { productsById(ids: $__fusion_exports__1) { price __fusion_exports__1: id } }", - "selectionSetId": 1, - "path": [ - "productsById" - ], - "requires": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 1 - ] - } - ] - }, - "state": { - "__fusion_exports__1": "Product_id" - } -} -``` - diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_Nullable.md deleted file mode 100644 index a16c0d51e0e..00000000000 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.ResolveByKey_Second_Service_Offline_SubField_Nullable.md +++ /dev/null @@ -1,143 +0,0 @@ -# ResolveByKey_Second_Service_Offline_SubField_Nullable - -## Result - -```json -{ - "errors": [ - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 5, - "column": 5 - } - ], - "path": [ - "products", - 2, - "price" - ] - }, - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 5, - "column": 5 - } - ], - "path": [ - "products", - 1, - "price" - ] - }, - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 5, - "column": 5 - } - ], - "path": [ - "products", - 0, - "price" - ] - } - ], - "data": { - "products": [ - { - "id": "1", - "name": "string", - "price": null - }, - { - "id": "2", - "name": "string", - "price": null - }, - { - "id": "3", - "name": "string", - "price": null - } - ] - } -} -``` - -## Request - -```graphql -{ - products { - id - name - price - } -} -``` - -## QueryPlan Hash - -```text -C991588ECF525B8EF311F2923FD2CEE9D7BE5B3A -``` - -## QueryPlan - -```json -{ - "document": "{ products { id name price } }", - "rootNode": { - "type": "Sequence", - "nodes": [ - { - "type": "Resolve", - "subgraph": "Subgraph_1", - "document": "query fetch_products_1 { products { id name __fusion_exports__1: id } }", - "selectionSetId": 0, - "provides": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 0 - ] - }, - { - "type": "ResolveByKeyBatch", - "subgraph": "Subgraph_2", - "document": "query fetch_products_2($__fusion_exports__1: [ID!]!) { productsById(ids: $__fusion_exports__1) { price __fusion_exports__1: id } }", - "selectionSetId": 1, - "path": [ - "productsById" - ], - "requires": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 1 - ] - } - ] - }, - "state": { - "__fusion_exports__1": "Product_id" - } -} -``` - diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_EntryFields_NonNull.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_EntryFields_NonNull.md deleted file mode 100644 index b4b3f5e9a2f..00000000000 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_EntryFields_NonNull.md +++ /dev/null @@ -1,79 +0,0 @@ -# Resolve_Parallel_One_Service_Offline_EntryFields_NonNull - -## Result - -```json -{ - "errors": [ - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 2, - "column": 3 - } - ], - "path": [ - "viewer" - ] - } - ], - "data": null -} -``` - -## Request - -```graphql -{ - viewer { - name - } - other { - userId - } -} -``` - -## QueryPlan Hash - -```text -1E9F0B5070B0EB2A79CBF03CDCC94C574189F814 -``` - -## QueryPlan - -```json -{ - "document": "{ viewer { name } other { userId } }", - "rootNode": { - "type": "Sequence", - "nodes": [ - { - "type": "Parallel", - "nodes": [ - { - "type": "Resolve", - "subgraph": "Subgraph_1", - "document": "query fetch_viewer_other_1 { viewer { name } }", - "selectionSetId": 0 - }, - { - "type": "Resolve", - "subgraph": "Subgraph_2", - "document": "query fetch_viewer_other_2 { other { userId } }", - "selectionSetId": 0 - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 0 - ] - } - ] - } -} -``` - diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_EntryFields_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_EntryFields_Nullable.md deleted file mode 100644 index 0a5d8992d68..00000000000 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Parallel_One_Service_Offline_EntryFields_Nullable.md +++ /dev/null @@ -1,84 +0,0 @@ -# Resolve_Parallel_One_Service_Offline_EntryFields_Nullable - -## Result - -```json -{ - "errors": [ - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 2, - "column": 3 - } - ], - "path": [ - "viewer" - ] - } - ], - "data": { - "viewer": null, - "other": { - "userId": "1" - } - } -} -``` - -## Request - -```graphql -{ - viewer { - name - } - other { - userId - } -} -``` - -## QueryPlan Hash - -```text -1E9F0B5070B0EB2A79CBF03CDCC94C574189F814 -``` - -## QueryPlan - -```json -{ - "document": "{ viewer { name } other { userId } }", - "rootNode": { - "type": "Sequence", - "nodes": [ - { - "type": "Parallel", - "nodes": [ - { - "type": "Resolve", - "subgraph": "Subgraph_1", - "document": "query fetch_viewer_other_1 { viewer { name } }", - "selectionSetId": 0 - }, - { - "type": "Resolve", - "subgraph": "Subgraph_2", - "document": "query fetch_viewer_other_2 { other { userId } }", - "selectionSetId": 0 - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 0 - ] - } - ] - } -} -``` - diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Parallel_Single_Service_Offline_EntryField_NonNull.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Parallel_Single_Service_Offline_EntryField_NonNull.md deleted file mode 100644 index ac75f5f061a..00000000000 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Parallel_Single_Service_Offline_EntryField_NonNull.md +++ /dev/null @@ -1,65 +0,0 @@ -# Resolve_Parallel_Single_Service_Offline_EntryField_NonNull - -## Result - -```json -{ - "errors": [ - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 2, - "column": 3 - } - ], - "path": [ - "viewer" - ] - } - ], - "data": null -} -``` - -## Request - -```graphql -{ - viewer { - name - } -} -``` - -## QueryPlan Hash - -```text -8B6791F7C91D1B779FF099AD8C7FC0D5980195EF -``` - -## QueryPlan - -```json -{ - "document": "{ viewer { name } }", - "rootNode": { - "type": "Sequence", - "nodes": [ - { - "type": "Resolve", - "subgraph": "Subgraph_1", - "document": "query fetch_viewer_1 { viewer { name } }", - "selectionSetId": 0 - }, - { - "type": "Compose", - "selectionSetIds": [ - 0 - ] - } - ] - } -} -``` - diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Parallel_Single_Service_Offline_EntryField_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Parallel_Single_Service_Offline_EntryField_Nullable.md deleted file mode 100644 index e8223929ef3..00000000000 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Parallel_Single_Service_Offline_EntryField_Nullable.md +++ /dev/null @@ -1,67 +0,0 @@ -# Resolve_Parallel_Single_Service_Offline_EntryField_Nullable - -## Result - -```json -{ - "errors": [ - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 2, - "column": 3 - } - ], - "path": [ - "viewer" - ] - } - ], - "data": { - "viewer": null - } -} -``` - -## Request - -```graphql -{ - viewer { - name - } -} -``` - -## QueryPlan Hash - -```text -8B6791F7C91D1B779FF099AD8C7FC0D5980195EF -``` - -## QueryPlan - -```json -{ - "document": "{ viewer { name } }", - "rootNode": { - "type": "Sequence", - "nodes": [ - { - "type": "Resolve", - "subgraph": "Subgraph_1", - "document": "query fetch_viewer_1 { viewer { name } }", - "selectionSetId": 0 - }, - { - "type": "Compose", - "selectionSetIds": [ - 0 - ] - } - ] - } -} -``` - diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Sequence_First_Service_Offline_EntryField_NonNull.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Sequence_First_Service_Offline_EntryField_NonNull.md deleted file mode 100644 index 5200397e3ca..00000000000 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Sequence_First_Service_Offline_EntryField_NonNull.md +++ /dev/null @@ -1,97 +0,0 @@ -# Resolve_Sequence_First_Service_Offline_EntryField_NonNull - -## Result - -```json -{ - "errors": [ - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 2, - "column": 3 - } - ], - "path": [ - "product" - ] - } - ], - "data": null -} -``` - -## Request - -```graphql -{ - product { - id - brand { - id - name - } - } -} -``` - -## QueryPlan Hash - -```text -10F6CB69F78A0E4FD176C0F4651E2E37CF47C9C5 -``` - -## QueryPlan - -```json -{ - "document": "{ product { id brand { id name } } }", - "rootNode": { - "type": "Sequence", - "nodes": [ - { - "type": "Resolve", - "subgraph": "Subgraph_1", - "document": "query fetch_product_1 { product { id brand { id __fusion_exports__1: id } } }", - "selectionSetId": 0, - "provides": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 0 - ] - }, - { - "type": "Resolve", - "subgraph": "Subgraph_2", - "document": "query fetch_product_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", - "selectionSetId": 2, - "path": [ - "brandById" - ], - "requires": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 2 - ] - } - ] - }, - "state": { - "__fusion_exports__1": "Brand_id" - } -} -``` - diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Sequence_First_Service_Offline_EntryField_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Sequence_First_Service_Offline_EntryField_Nullable.md deleted file mode 100644 index 2f0d443696a..00000000000 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Sequence_First_Service_Offline_EntryField_Nullable.md +++ /dev/null @@ -1,99 +0,0 @@ -# Resolve_Sequence_First_Service_Offline_EntryField_Nullable - -## Result - -```json -{ - "errors": [ - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 2, - "column": 3 - } - ], - "path": [ - "product" - ] - } - ], - "data": { - "product": null - } -} -``` - -## Request - -```graphql -{ - product { - id - brand { - id - name - } - } -} -``` - -## QueryPlan Hash - -```text -10F6CB69F78A0E4FD176C0F4651E2E37CF47C9C5 -``` - -## QueryPlan - -```json -{ - "document": "{ product { id brand { id name } } }", - "rootNode": { - "type": "Sequence", - "nodes": [ - { - "type": "Resolve", - "subgraph": "Subgraph_1", - "document": "query fetch_product_1 { product { id brand { id __fusion_exports__1: id } } }", - "selectionSetId": 0, - "provides": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 0 - ] - }, - { - "type": "Resolve", - "subgraph": "Subgraph_2", - "document": "query fetch_product_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", - "selectionSetId": 2, - "path": [ - "brandById" - ], - "requires": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 2 - ] - } - ] - }, - "state": { - "__fusion_exports__1": "Brand_id" - } -} -``` - diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_NonNull_Parent_NonNull.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_NonNull_Parent_NonNull.md deleted file mode 100644 index db796bb0563..00000000000 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_NonNull_Parent_NonNull.md +++ /dev/null @@ -1,101 +0,0 @@ -# Resolve_Sequence_Second_Service_Offline_SubField_NonNull_Parent_NonNull - -## Result - -```json -{ - "errors": [ - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 6, - "column": 7 - } - ], - "path": [ - "product", - "brand", - "name" - ] - } - ], - "data": { - "product": null - } -} -``` - -## Request - -```graphql -{ - product { - id - brand { - id - name - } - } -} -``` - -## QueryPlan Hash - -```text -10F6CB69F78A0E4FD176C0F4651E2E37CF47C9C5 -``` - -## QueryPlan - -```json -{ - "document": "{ product { id brand { id name } } }", - "rootNode": { - "type": "Sequence", - "nodes": [ - { - "type": "Resolve", - "subgraph": "Subgraph_1", - "document": "query fetch_product_1 { product { id brand { id __fusion_exports__1: id } } }", - "selectionSetId": 0, - "provides": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 0 - ] - }, - { - "type": "Resolve", - "subgraph": "Subgraph_2", - "document": "query fetch_product_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", - "selectionSetId": 2, - "path": [ - "brandById" - ], - "requires": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 2 - ] - } - ] - }, - "state": { - "__fusion_exports__1": "Brand_id" - } -} -``` - diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_NonNull_Parent_Nullable.md b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_NonNull_Parent_Nullable.md deleted file mode 100644 index 76819155651..00000000000 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/__EXPECTED__/TransportErrorTests.Resolve_Sequence_Second_Service_Offline_SubField_NonNull_Parent_Nullable.md +++ /dev/null @@ -1,104 +0,0 @@ -# Resolve_Sequence_Second_Service_Offline_SubField_NonNull_Parent_Nullable - -## Result - -```json -{ - "errors": [ - { - "message": "Unexpected Execution Error", - "locations": [ - { - "line": 6, - "column": 7 - } - ], - "path": [ - "product", - "brand", - "name" - ] - } - ], - "data": { - "product": { - "id": "1", - "brand": null - } - } -} -``` - -## Request - -```graphql -{ - product { - id - brand { - id - name - } - } -} -``` - -## QueryPlan Hash - -```text -10F6CB69F78A0E4FD176C0F4651E2E37CF47C9C5 -``` - -## QueryPlan - -```json -{ - "document": "{ product { id brand { id name } } }", - "rootNode": { - "type": "Sequence", - "nodes": [ - { - "type": "Resolve", - "subgraph": "Subgraph_1", - "document": "query fetch_product_1 { product { id brand { id __fusion_exports__1: id } } }", - "selectionSetId": 0, - "provides": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 0 - ] - }, - { - "type": "Resolve", - "subgraph": "Subgraph_2", - "document": "query fetch_product_2($__fusion_exports__1: ID!) { brandById(id: $__fusion_exports__1) { name } }", - "selectionSetId": 2, - "path": [ - "brandById" - ], - "requires": [ - { - "variable": "__fusion_exports__1" - } - ] - }, - { - "type": "Compose", - "selectionSetIds": [ - 2 - ] - } - ] - }, - "state": { - "__fusion_exports__1": "Brand_id" - } -} -``` - diff --git a/src/HotChocolate/Utilities/test/Utilities.Introspection.Tests/IntrospectionClientTests.cs b/src/HotChocolate/Utilities/test/Utilities.Introspection.Tests/IntrospectionClientTests.cs index f89a83a9401..33cd2da6af6 100644 --- a/src/HotChocolate/Utilities/test/Utilities.Introspection.Tests/IntrospectionClientTests.cs +++ b/src/HotChocolate/Utilities/test/Utilities.Introspection.Tests/IntrospectionClientTests.cs @@ -1,3 +1,4 @@ +using System.Net; using CookieCrumble; using Xunit; using HotChocolate.AspNetCore.Tests.Utilities; @@ -69,4 +70,64 @@ public async Task IntrospectServer_HttpClient_Is_Null() // assert await Assert.ThrowsAsync(Error); } + + [Fact] + public async Task IntrospectServer_Http_200_Wrong_Content_Type() + { + // arrange + var client = new HttpClient(new CustomHttpClientHandler(HttpStatusCode.OK)); + client.BaseAddress = new Uri("http://localhost:5000"); + client.BaseAddress = new Uri("http://localhost:5000"); + + // act + Task Error() => IntrospectionClient.IntrospectServerAsync(client); + + // assert + var exception = await Assert.ThrowsAsync(Error); + Assert.Equal("Received a successful response with an unexpected content type.", exception.Message); + } + + [Fact] + public async Task IntrospectServer_Http_404_Wrong_Content_Type() + { + // arrange + var client = new HttpClient(new CustomHttpClientHandler(HttpStatusCode.NotFound)); + client.BaseAddress = new Uri("http://localhost:5000"); + + // act + Task Error() => IntrospectionClient.IntrospectServerAsync(client); + + // assert + await Assert.ThrowsAsync(Error); + } + + [Fact] + public async Task IntrospectServer_Transport_Error() + { + // arrange + var client = new HttpClient(new CustomHttpClientHandler()); + client.BaseAddress = new Uri("http://localhost:5000"); + + // act + Task Error() => IntrospectionClient.IntrospectServerAsync(client); + + // assert + var exception = await Assert.ThrowsAsync(Error); + Assert.Equal("Something went wrong", exception.Message); + } + + private class CustomHttpClientHandler(HttpStatusCode? httpStatusCode = null) : HttpClientHandler + { + protected override Task SendAsync( + HttpRequestMessage request, + CancellationToken cancellationToken) + { + if (httpStatusCode.HasValue) + { + return Task.FromResult(new HttpResponseMessage(httpStatusCode.Value)); + } + + throw new Exception("Something went wrong"); + } + } }