Skip to content

Commit

Permalink
Fix #4956
Browse files Browse the repository at this point in the history
  • Loading branch information
anton-gogolev committed Mar 17, 2023
1 parent f4fe3f6 commit 9fcd086
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 1 deletion.
18 changes: 18 additions & 0 deletions src/StrawberryShake/Client/src/Core/Json/JsonExtensionParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.Collections.Generic;
using System.Text.Json;

namespace StrawberryShake.Json;

public static class JsonExtensionParser
{
public static IReadOnlyDictionary<string, object?>? ParseExtensions(JsonElement result)
{
if (result is { ValueKind: JsonValueKind.Object })
{
var extensions = JsonSerializationHelper.ReadValue(result);
return (IReadOnlyDictionary<string, object?>?)extensions;
}

return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public IOperationResult<TResultData> Build(
TResultData? data = null;
IOperationResultDataInfo? dataInfo = null;
IReadOnlyList<IClientError>? errors = null;
IReadOnlyDictionary<string, object?>? extensions = null;

try
{
Expand All @@ -42,6 +43,12 @@ public IOperationResult<TResultData> Build(
{
errors = JsonErrorParser.ParseErrors(errorsProp);
}

if (body.RootElement.TryGetProperty(ResultFields.Extensions, out var extensionsProp) &&
extensionsProp.ValueKind is JsonValueKind.Object)
{
extensions = JsonExtensionParser.ParseExtensions(extensionsProp);
}
}
}
catch (Exception ex)
Expand Down Expand Up @@ -71,7 +78,7 @@ public IOperationResult<TResultData> Build(
dataInfo,
ResultDataFactory,
errors,
response.Extensions,
extensions,
response.ContextData);
}

Expand Down
1 change: 1 addition & 0 deletions src/StrawberryShake/Client/src/Core/ResultFields.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ public static class ResultFields
public const string Path = "path";
public const string Label = "label";
public const string HasNext = "hasNext";
public const string Extensions = "extensions";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Text.Json;

namespace StrawberryShake;

public class OperationResultBuilderTests
{
[Fact]
public void Build_With_Extensions()
{
// arrange
var factory = new DocumentDataFactory();
var builder = new DocumentOperationResultBuilder(factory);

// According to the current design, all implementations of IConnection operate
// on JsonDocuments which are deserialized straight from response streams and
// very few properties in the Response object are in fact ever initialized,
// including Response.Extensions. It is therefore safe to assume that, at
// least for now, OperationResultBuilder is the best place to actually parse
// and extract "extensions".
var body = JsonDocument.Parse(@"{""data"": { }, ""extensions"": { ""a"": 1, ""b"": { ""c"": ""Strawberry"" }, ""d"": 3.14 } }");
var response = new Response<JsonDocument>(body, null);

// act

var result = builder.Build(response);

// assert
Assert.NotEmpty(result.Extensions);
Assert.Equal(1L, result.Extensions["a"]);

var b = (IReadOnlyDictionary<string, object?>?)result.Extensions["b"];

Assert.NotNull(b);
Assert.Equal("Strawberry", b["c"]);

Assert.Equal(3.14, result.Extensions["d"]);
}

internal class Document
{
}

internal class DocumentDataInfo : IOperationResultDataInfo
{
public IReadOnlyCollection<EntityId> EntityIds { get; } = ArraySegment<EntityId>.Empty;

public ulong Version { get; } = 0;

public IOperationResultDataInfo WithVersion(ulong version)
{
throw new NotImplementedException();
}
}

internal class DocumentDataFactory : IOperationResultDataFactory<Document>
{
public Type ResultType { get => typeof(Document); }

public Document Create(IOperationResultDataInfo dataInfo, IEntityStoreSnapshot? snapshot = null)
{
return new Document();
}

object IOperationResultDataFactory.Create(IOperationResultDataInfo dataInfo, IEntityStoreSnapshot? snapshot)
{
return Create(dataInfo, snapshot);
}
}

internal class DocumentOperationResultBuilder : OperationResultBuilder<Document>
{
public DocumentOperationResultBuilder(IOperationResultDataFactory<Document> resultDataFactory)
{
ResultDataFactory = resultDataFactory;
}

protected override IOperationResultDataFactory<Document> ResultDataFactory { get; }

protected override IOperationResultDataInfo BuildData(JsonElement obj)
{
return new DocumentDataInfo();
}
}
}

0 comments on commit 9fcd086

Please sign in to comment.