Skip to content

Commit

Permalink
Migrate ArrayTypeConverter and ObjectTypeConverter to `System.Tex…
Browse files Browse the repository at this point in the history
…t.Json`
  • Loading branch information
y0ung3r committed Jul 10, 2024
2 parents 49480c3 + 88624ff commit cb77c2e
Show file tree
Hide file tree
Showing 19 changed files with 293 additions and 27 deletions.
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.3.0]

### Added

- New interfaces to represent weakly-typed arrays and objects - `IObjectType` and `IArrayType` with corresponding JSON converters

### Fixed

- Fix code generation problem with `object` and `array` type definitions without properties (#7)

## [1.2.3]

### Fixed
Expand Down Expand Up @@ -52,7 +62,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Initial release

[Unreleased]: https://github.com/seclerp/dotnet-chrome-protocol/compare/1.2.3...HEAD
[Unreleased]: https://github.com/seclerp/dotnet-chrome-protocol/compare/1.3.0...HEAD
[1.3.0]: https://github.com/seclerp/dotnet-chrome-protocol/compare/1.2.3...1.3.0
[1.2.3]: https://github.com/seclerp/dotnet-chrome-protocol/compare/1.2.2...1.2.3
[1.2.2]: https://github.com/seclerp/dotnet-chrome-protocol/compare/1.2.1...1.2.2
[1.2.1]: https://github.com/seclerp/dotnet-chrome-protocol/compare/1.2.0...1.2.1
Expand Down
44 changes: 44 additions & 0 deletions src/ChromeProtocol.Core.Tests/ArrayTypeConverterTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using Xunit;

namespace ChromeProtocol.Core.Tests;

[JsonConverter(typeof(ArrayTypeConverter))]
public record TestableArrayType(IReadOnlyCollection<JsonNode> Items) : IArrayType;

public sealed class ArrayTypeConverterTests
{
[Fact]
public void Should_deserialize_using_attribute_properly()
{
// Arrange & Act
var actual = JsonSerializer.Deserialize<TestableArrayType>("[1,2,3]") ?? new TestableArrayType(Array.Empty<JsonNode>());

// Assert
Assert.Collection(
actual.Items,
jsonNode => Assert.Equal(expected: 1, jsonNode.GetValue<int>()),
jsonNode => Assert.Equal(expected: 2, jsonNode.GetValue<int>()),
jsonNode => Assert.Equal(expected: 3, jsonNode.GetValue<int>()));
}

[Fact]
public void Should_serialize_using_attribute_properly()
{
// Arrange
var expected = new TestableArrayType(new JsonNode[]
{
JsonValue.Create(1),
JsonValue.Create(2),
JsonValue.Create(3),
});

// Act
var actual = JsonSerializer.Serialize(expected);

// Assert
Assert.Equal("[1,2,3]", actual);
}
}
34 changes: 34 additions & 0 deletions src/ChromeProtocol.Core.Tests/ChromeProtocol.Core.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>

<RootNamespace>ChromeProtocol.Core.Tests</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="System.Text.Json" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\ChromeProtocol.Tests.Extensions\ChromeProtocol.Tests.Extensions.csproj" />
<ProjectReference Include="..\ChromeProtocol.Core\ChromeProtocol.Core.csproj" />
</ItemGroup>

</Project>
50 changes: 50 additions & 0 deletions src/ChromeProtocol.Core.Tests/ObjectTypeConverterTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using Xunit;

namespace ChromeProtocol.Core.Tests;

[JsonConverter(typeof(ObjectTypeConverter))]
public record TestableObjectType(IReadOnlyDictionary<string, JsonNode?> Properties) : IObjectType;

public sealed class ObjectTypeConverterTests
{
[Fact]
public void Should_deserialize_using_attribute_properly()
{
// Arrange
var expectedJson = "{ \"foo\": 1, \"bar\": 2 }";

// Act
var actual = JsonSerializer.Deserialize<TestableObjectType>(expectedJson) ?? new TestableObjectType(new Dictionary<string, JsonNode?>());

// Assert
Assert.Collection(
actual.Properties,
pair =>
{
Assert.Equal("foo", pair.Key);
Assert.Equal(expected: 1, pair.Value?.GetValue<int>());
},
pair =>
{
Assert.Equal("bar", pair.Key);
Assert.Equal(expected: 2, pair.Value?.GetValue<int>());
});
}

[Fact]
public void Should_serialize_using_attribute_properly()
{
var expected = new TestableObjectType(new Dictionary<string, JsonNode?>
{
{ "foo", JsonValue.Create(1) },
{ "bar", JsonValue.Create(2) }
});

var actual = JsonSerializer.Serialize(expected);

Assert.Equal("{\"foo\":1,\"bar\":2}", actual);
}
}
28 changes: 28 additions & 0 deletions src/ChromeProtocol.Core/ArrayTypeConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;

namespace ChromeProtocol.Core;

public class ArrayTypeConverter : JsonConverter<IArrayType?>
{
public override bool CanConvert(Type objectType)
{
return typeof(IArrayType).IsAssignableFrom(objectType);
}

/// <inheritdoc />
public override void Write(Utf8JsonWriter writer, IArrayType? value, JsonSerializerOptions options)
{
var jsonArray = new JsonArray(value?.Items.ToArray() ?? Array.Empty<JsonNode>());

jsonArray.WriteTo(writer);
}

/// <inheritdoc />
public override IArrayType? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var jsonNode = JsonNode.Parse(ref reader);
return Activator.CreateInstance(typeToConvert, jsonNode.Deserialize<IReadOnlyCollection<JsonNode>>()) as IArrayType;
}
}
8 changes: 8 additions & 0 deletions src/ChromeProtocol.Core/IArrayType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Text.Json.Nodes;

namespace ChromeProtocol.Core;

public interface IArrayType
{
public IReadOnlyCollection<JsonNode?> Items { get; }
}
8 changes: 8 additions & 0 deletions src/ChromeProtocol.Core/IObjectType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Text.Json.Nodes;

namespace ChromeProtocol.Core;

public interface IObjectType
{
public IReadOnlyDictionary<string, JsonNode?> Properties { get; }
}
2 changes: 0 additions & 2 deletions src/ChromeProtocol.Core/IType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,3 @@
public interface IType
{
}

public record ExampleValue(string Value) : PrimitiveType<string>(Value);
28 changes: 28 additions & 0 deletions src/ChromeProtocol.Core/ObjectTypeConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;

namespace ChromeProtocol.Core;

public class ObjectTypeConverter : JsonConverter<IObjectType?>
{
public override bool CanConvert(Type objectType)
{
return typeof(IObjectType).IsAssignableFrom(objectType);
}

/// <inheritdoc />
public override void Write(Utf8JsonWriter writer, IObjectType? value, JsonSerializerOptions options)
{
var jsonObject = new JsonObject(value?.Properties ?? Enumerable.Empty<KeyValuePair<string, JsonNode?>>());

jsonObject.WriteTo(writer);
}

/// <inheritdoc />
public override IObjectType? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var jsonNode = JsonNode.Parse(ref reader);
return Activator.CreateInstance(typeToConvert, jsonNode.Deserialize<IReadOnlyDictionary<string, JsonNode?>>()) as IObjectType;
}
}
5 changes: 4 additions & 1 deletion src/ChromeProtocol.Domains/Generated/DOM.cs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,10 @@ public record RGBAType(
{
}
/// <summary>An array of quad vertices, x immediately followed by y for each point, points clock-wise.</summary>
public record QuadType() : ChromeProtocol.Core.IType
[System.Text.Json.Serialization.JsonConverter(typeof(ChromeProtocol.Core.ArrayTypeConverter))]
public record QuadType(
System.Collections.Generic.IReadOnlyCollection<System.Text.Json.Nodes.JsonNode> Items
) : ChromeProtocol.Core.IArrayType
{
}
/// <summary>Box model.</summary>
Expand Down
10 changes: 8 additions & 2 deletions src/ChromeProtocol.Domains/Generated/DOMSnapshot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,10 @@ int Value
{
}
/// <summary>Index of the string in the strings table.</summary>
public record ArrayOfStringsType() : ChromeProtocol.Core.IType
[System.Text.Json.Serialization.JsonConverter(typeof(ChromeProtocol.Core.ArrayTypeConverter))]
public record ArrayOfStringsType(
System.Collections.Generic.IReadOnlyCollection<System.Text.Json.Nodes.JsonNode> Items
) : ChromeProtocol.Core.IArrayType
{
}
/// <summary>Data that is only present on rare nodes.</summary>
Expand All @@ -216,7 +219,10 @@ System.Collections.Generic.IReadOnlyList<int> Value
) : ChromeProtocol.Core.IType
{
}
public record RectangleType() : ChromeProtocol.Core.IType
[System.Text.Json.Serialization.JsonConverter(typeof(ChromeProtocol.Core.ArrayTypeConverter))]
public record RectangleType(
System.Collections.Generic.IReadOnlyCollection<System.Text.Json.Nodes.JsonNode> Items
) : ChromeProtocol.Core.IArrayType
{
}
/// <summary>Document snapshot.</summary>
Expand Down
5 changes: 4 additions & 1 deletion src/ChromeProtocol.Domains/Generated/DOMStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ public record StorageIdType(
{
}
/// <summary>DOM Storage item.</summary>
public record ItemType() : ChromeProtocol.Core.IType
[System.Text.Json.Serialization.JsonConverter(typeof(ChromeProtocol.Core.ArrayTypeConverter))]
public record ItemType(
System.Collections.Generic.IReadOnlyCollection<System.Text.Json.Nodes.JsonNode> Items
) : ChromeProtocol.Core.IArrayType
{
}
[ChromeProtocol.Core.MethodName("DOMStorage.domStorageItemAdded")]
Expand Down
5 changes: 4 additions & 1 deletion src/ChromeProtocol.Domains/Generated/LayerTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,10 @@ public record LayerType(
{
}
/// <summary>Array of timings, one per paint step.</summary>
public record PaintProfileType() : ChromeProtocol.Core.IType
[System.Text.Json.Serialization.JsonConverter(typeof(ChromeProtocol.Core.ArrayTypeConverter))]
public record PaintProfileType(
System.Collections.Generic.IReadOnlyCollection<System.Text.Json.Nodes.JsonNode> Items
) : ChromeProtocol.Core.IArrayType
{
}
/// <param name="LayerId">The id of the painted layer.</param>
Expand Down
5 changes: 4 additions & 1 deletion src/ChromeProtocol.Domains/Generated/Network.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ double Value
{
}
/// <summary>Request / response headers as keys / values of JSON object.</summary>
public record HeadersType() : ChromeProtocol.Core.IType
[System.Text.Json.Serialization.JsonConverter(typeof(ChromeProtocol.Core.ObjectTypeConverter))]
public record HeadersType(
System.Collections.Generic.IReadOnlyDictionary<System.String, System.Text.Json.Nodes.JsonNode?> Properties
) : ChromeProtocol.Core.IObjectType
{
}
/// <summary>The underlying connection technology that the browser is supposedly using.</summary>
Expand Down
5 changes: 4 additions & 1 deletion src/ChromeProtocol.Domains/Generated/Target.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,10 @@ public record FilterEntryType(
/// [{type: &quot;browser&quot;, exclude: true}, {type: &quot;tab&quot;, exclude: true}, {}]<br/>
/// (i.e. include everything but `browser` and `tab`).<br/>
/// </summary>
public record TargetFilterType() : ChromeProtocol.Core.IType
[System.Text.Json.Serialization.JsonConverter(typeof(ChromeProtocol.Core.ArrayTypeConverter))]
public record TargetFilterType(
System.Collections.Generic.IReadOnlyCollection<System.Text.Json.Nodes.JsonNode> Items
) : ChromeProtocol.Core.IArrayType
{
}
public record RemoteLocationType(
Expand Down
5 changes: 4 additions & 1 deletion src/ChromeProtocol.Domains/Generated/Tracing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ namespace ChromeProtocol.Domains
public static partial class Tracing
{
/// <summary>Configuration for memory dump. Used only when &quot;memory-infra&quot; category is enabled.</summary>
public record MemoryDumpConfigType() : ChromeProtocol.Core.IType
[System.Text.Json.Serialization.JsonConverter(typeof(ChromeProtocol.Core.ObjectTypeConverter))]
public record MemoryDumpConfigType(
System.Collections.Generic.IReadOnlyDictionary<System.String, System.Text.Json.Nodes.JsonNode?> Properties
) : ChromeProtocol.Core.IObjectType
{
}
/// <param name="RecordMode">Controls how the trace buffer stores data.</param>
Expand Down
Loading

0 comments on commit cb77c2e

Please sign in to comment.