Skip to content

Commit

Permalink
Merge branch 'master' into code-cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
rose-a authored Apr 21, 2020
2 parents cc131e2 + aadf594 commit 51f313d
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 17 deletions.
6 changes: 2 additions & 4 deletions GraphQL.Client.sln
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GraphQL.Server.Test", "test
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{05CAF9B2-981E-40C0-AE31-5FA56E351F12}"
ProjectSection(SolutionItems) = preProject
.github\workflows\branches-ubuntu.yml = .github\workflows\branches-ubuntu.yml
.github\workflows\branches-windows.yml = .github\workflows\branches-windows.yml
.github\workflows\main-ubuntu.yml = .github\workflows\main-ubuntu.yml
.github\workflows\main-windows.yml = .github\workflows\main-windows.yml
.github\workflows\branches.yml = .github\workflows\branches.yml
.github\workflows\master.yml = .github\workflows\master.yml
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GraphQL.Primitives", "src\GraphQL.Primitives\GraphQL.Primitives.csproj", "{87FC440E-6A4D-47D8-9EB2-416FC31CC4A6}"
Expand Down
7 changes: 4 additions & 3 deletions src/GraphQL.Client.Serializer.Newtonsoft/MapConverter.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

Expand All @@ -22,11 +23,11 @@ public override Map ReadJson(JsonReader reader, Type objectType, Map existingVal
throw new ArgumentException("This converter can only parse when the root element is a JSON Object.");
}

private object ReadToken(JToken? token) =>
private object? ReadToken(JToken? token) =>
token switch
{
JObject jObject => ReadDictionary(jObject, new Dictionary<string, object>()),
JArray jArray => ReadArray(jArray),
JArray jArray => ReadArray(jArray).ToList(),
JValue jValue => jValue.Value,
JConstructor _ => throw new ArgumentOutOfRangeException(nameof(token.Type),
"cannot deserialize a JSON constructor"),
Expand All @@ -48,7 +49,7 @@ private Dictionary<string, object> ReadDictionary(JToken element, Dictionary<str
return to;
}

private IEnumerable<object> ReadArray(JArray element)
private IEnumerable<object?> ReadArray(JArray element)
{
foreach (var item in element)
{
Expand Down
12 changes: 6 additions & 6 deletions src/GraphQL.Client.Serializer.SystemTextJson/MapConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ private TDictionary ReadDictionary<TDictionary>(JsonElement element) where TDict
return result;
}

private IEnumerable<object> ReadArray(JsonElement value)
private IEnumerable<object?> ReadArray(JsonElement value)
{
foreach (var item in value.EnumerateArray())
{
yield return ReadValue(item);
}
}

private object ReadValue(JsonElement value)
private object? ReadValue(JsonElement value)
=> value.ValueKind switch
{
JsonValueKind.Array => ReadArray(value).ToList(),
Expand All @@ -65,15 +65,15 @@ private object ReadValue(JsonElement value)

private object ReadNumber(JsonElement value)
{
if (value.TryGetInt32(out var i))
if (value.TryGetInt32(out int i))
return i;
else if (value.TryGetInt64(out var l))
else if (value.TryGetInt64(out long l))
return l;
else if (BigInteger.TryParse(value.GetRawText(), out var bi))
return bi;
else if (value.TryGetDouble(out var d))
else if (value.TryGetDouble(out double d))
return d;
else if (value.TryGetDecimal(out var dd))
else if (value.TryGetDecimal(out decimal dd))
return dd;

throw new NotImplementedException($"Unexpected Number value. Raw text was: {value.GetRawText()}");
Expand Down
6 changes: 6 additions & 0 deletions src/GraphQL.Client/GraphQLHttpClientOptions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.WebSockets;
using System.Threading.Tasks;

namespace GraphQL.Client.Http
Expand Down Expand Up @@ -50,5 +51,10 @@ public class GraphQLHttpClientOptions
/// This callback is called after successfully establishing a websocket connection but before any regular request is made.
/// </summary>
public Func<GraphQLHttpClient, Task> OnWebsocketConnected { get; set; } = client => Task.CompletedTask;

/// <summary>
/// Configure additional websocket options (i.e. headers). This will not be invoked on Windows 7 when targeting .NET Framework 4.x.
/// </summary>
public Action<ClientWebSocketOptions> ConfigureWebsocketOptions { get; set; } = options => { };
}
}
8 changes: 5 additions & 3 deletions src/GraphQL.Client/Websocket/GraphQLHttpWebSocket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -396,12 +396,13 @@ public Task InitializeWebSocket()
nativeWebSocket.Options.AddSubProtocol("graphql-ws");
nativeWebSocket.Options.ClientCertificates = ((HttpClientHandler)Options.HttpMessageHandler).ClientCertificates;
nativeWebSocket.Options.UseDefaultCredentials = ((HttpClientHandler)Options.HttpMessageHandler).UseDefaultCredentials;
break;
Options.ConfigureWebsocketOptions(nativeWebSocket.Options);
break;
case System.Net.WebSockets.Managed.ClientWebSocket managedWebSocket:
managedWebSocket.Options.AddSubProtocol("graphql-ws");
managedWebSocket.Options.ClientCertificates = ((HttpClientHandler)Options.HttpMessageHandler).ClientCertificates;
managedWebSocket.Options.UseDefaultCredentials = ((HttpClientHandler)Options.HttpMessageHandler).UseDefaultCredentials;
break;
break;
default:
throw new NotSupportedException($"unknown websocket type {_clientWebSocket.GetType().Name}");
}
Expand All @@ -410,6 +411,7 @@ public Task InitializeWebSocket()
_clientWebSocket.Options.AddSubProtocol("graphql-ws");
_clientWebSocket.Options.ClientCertificates = ((HttpClientHandler)Options.HttpMessageHandler).ClientCertificates;
_clientWebSocket.Options.UseDefaultCredentials = ((HttpClientHandler)Options.HttpMessageHandler).UseDefaultCredentials;
Options.ConfigureWebsocketOptions(_clientWebSocket.Options);
#endif
return _initializeWebSocketTask = ConnectAsync(_internalCancellationToken);
}
Expand Down Expand Up @@ -607,7 +609,7 @@ public void Complete()
/// Task to await the completion (a.k.a. disposal) of this websocket.
/// </summary>
/// Async disposal as recommended by Stephen Cleary (https://blog.stephencleary.com/2013/03/async-oop-6-disposal.html)
public Task Completion { get; private set; }
public Task? Completion { get; private set; }

private readonly object _completedLocker = new object();
private async Task CompleteAsync()
Expand Down
3 changes: 2 additions & 1 deletion src/GraphQL.Primitives/GraphQLResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@

namespace GraphQL
{
public class GraphQLResponse<T> : IEquatable<GraphQLResponse<T>?>
public class GraphQLResponse<T> : IGraphQLResponse, IEquatable<GraphQLResponse<T>?>
{
[DataMember(Name = "data")]
public T Data { get; set; }
object IGraphQLResponse.Data => Data;

[DataMember(Name = "errors")]
public GraphQLError[]? Errors { get; set; }
Expand Down
11 changes: 11 additions & 0 deletions src/GraphQL.Primitives/IGraphQLResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace GraphQL
{
public interface IGraphQLResponse
{
object Data { get; }

GraphQLError[]? Errors { get; set; }

Map? Extensions { get; set; }
}
}
62 changes: 62 additions & 0 deletions tests/GraphQL.Client.Serializer.Tests/ConsistencyTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System.Collections.Generic;
using FluentAssertions;
using FluentAssertions.Execution;
using GraphQL.Client.Serializer.Newtonsoft;
using GraphQL.Client.Serializer.SystemTextJson;
using Newtonsoft.Json;
using Xunit;

namespace GraphQL.Client.Serializer.Tests
{
public class ConsistencyTests
{
[Fact]
public void MapConvertersShouldBehaveConsistent()
{
const string json = @"{
""array"": [
""some stuff"",
""something else""
],
""string"": ""this is a string"",
""boolean"": true,
""number"": 1234.567,
""nested object"": {
""prop1"": false
},
""arrayOfObjects"": [
{""number"": 1234.567},
{""number"": 567.8}
]
}";

var newtonsoftSerializer = new NewtonsoftJsonSerializer();
var systemTextJsonSerializer = new SystemTextJsonSerializer();

var newtonsoftMap = JsonConvert.DeserializeObject<Map>(json, newtonsoftSerializer.JsonSerializerSettings);
var systemTextJsonMap = System.Text.Json.JsonSerializer.Deserialize<Map>(json, systemTextJsonSerializer.Options);


using(new AssertionScope())
{
CompareMaps(newtonsoftMap, systemTextJsonMap);
}

newtonsoftMap.Should().BeEquivalentTo(systemTextJsonMap, options => options
.RespectingRuntimeTypes());
}

private void CompareMaps(Dictionary<string, object> first, Dictionary<string, object> second)
{
foreach (var keyValuePair in first)
{
second.Should().ContainKey(keyValuePair.Key);
second[keyValuePair.Key].Should().BeOfType(keyValuePair.Value.GetType());
if(keyValuePair.Value is Dictionary<string, object> map)
CompareMaps(map, (Dictionary<string, object>)second[keyValuePair.Key]);
else
keyValuePair.Value.Should().BeEquivalentTo(second[keyValuePair.Key]);
}
}
}
}

0 comments on commit 51f313d

Please sign in to comment.