Skip to content

Commit

Permalink
Added tests for the new converters etc
Browse files Browse the repository at this point in the history
  • Loading branch information
pingu2k4 committed Nov 27, 2024
1 parent 231485d commit 7f732fb
Show file tree
Hide file tree
Showing 5 changed files with 876 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

namespace PinguApps.Appwrite.Shared.Converters;

public class DocumentGenericConverter<TData> : JsonConverter<Doocument<TData>>
public class DocumentGenericConverter<TData> : JsonConverter<Document<TData>>
where TData : class, new()
{
public override Doocument<TData> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
public override Document<TData> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string? id = null;
string? collectionId = null;
Expand All @@ -37,7 +37,7 @@ public override Doocument<TData> Read(ref Utf8JsonReader reader, Type typeToConv
break;
}

string propertyName = reader.GetString()!;
var propertyName = reader.GetString()!;

reader.Read();

Expand Down Expand Up @@ -102,7 +102,7 @@ public override Doocument<TData> Read(ref Utf8JsonReader reader, Type typeToConv
var dataJson = JsonSerializer.Serialize(dataProperties, options);
data = JsonSerializer.Deserialize<TData>(dataJson, options) ?? new TData();

return new Doocument<TData>(id, collectionId, databaseId, createdAt.Value, updatedAt.Value, permissions, data);
return new Document<TData>(id, collectionId, databaseId, createdAt.Value, updatedAt.Value, permissions, data);
}

Check notice on line 107 in src/PinguApps.Appwrite.Shared/Converters/DocumentGenericConverter.cs

View check run for this annotation

codefactor.io / CodeFactor

src/PinguApps.Appwrite.Shared/Converters/DocumentGenericConverter.cs#L13-L107

Complex Method
internal object? ReadValue(ref Utf8JsonReader reader, JsonSerializerOptions options)
Expand Down Expand Up @@ -184,7 +184,7 @@ public override Doocument<TData> Read(ref Utf8JsonReader reader, Type typeToConv
return dict;
}

public override void Write(Utf8JsonWriter writer, Doocument<TData> value, JsonSerializerOptions options)
public override void Write(Utf8JsonWriter writer, Document<TData> value, JsonSerializerOptions options)
{
writer.WriteStartObject();

Expand All @@ -204,26 +204,72 @@ public override void Write(Utf8JsonWriter writer, Doocument<TData> value, JsonSe
writer.WritePropertyName("$permissions");
JsonSerializer.Serialize(writer, value.Permissions, options);

// Serialize the data object into individual properties.
var dataProperties = JsonSerializer.SerializeToElement(value.Data, options);
foreach (var property in dataProperties.EnumerateObject())
// Serialize the Data property
if (value.Data is not null)
{
writer.WritePropertyName(property.Name);
WriteValue(writer, property, options);
var dataProperties = JsonSerializer.SerializeToElement(value.Data, options);
foreach (var property in dataProperties.EnumerateObject())
{
writer.WritePropertyName(property.Name);
WriteValue(writer, property.Value, options);
}
}

writer.WriteEndObject();
}

private void WriteValue(Utf8JsonWriter writer, JsonProperty property, JsonSerializerOptions options)
internal void WriteValue(Utf8JsonWriter writer, JsonElement element, JsonSerializerOptions options)
{
// Handle null values
if (property.Value.ValueKind is JsonValueKind.Null)
var dateTimeConverter = new MultiFormatDateTimeConverter();

switch (element.ValueKind)
{
writer.WriteNullValue();
return;
case JsonValueKind.String:
var stringValue = element.GetString();
if (DateTime.TryParse(stringValue, out var dateTimeValue))
{
// Write DateTime using the MultiFormatDateTimeConverter
dateTimeConverter.Write(writer, dateTimeValue, options);
}
else
{
writer.WriteStringValue(stringValue);
}
break;
case JsonValueKind.Number:
if (element.TryGetInt32(out var intValue))
writer.WriteNumberValue(intValue);
else if (element.TryGetInt64(out var longValue))
writer.WriteNumberValue(longValue);
else if (element.TryGetDouble(out var doubleValue))
writer.WriteNumberValue(doubleValue);
break;
case JsonValueKind.True:
case JsonValueKind.False:
writer.WriteBooleanValue(element.GetBoolean());
break;
case JsonValueKind.Null:
writer.WriteNullValue();
break;
case JsonValueKind.Array:
writer.WriteStartArray();
foreach (var item in element.EnumerateArray())
{
WriteValue(writer, item, options);
}
writer.WriteEndArray();
break;
case JsonValueKind.Object:
writer.WriteStartObject();
foreach (var property in element.EnumerateObject())
{
writer.WritePropertyName(property.Name);
WriteValue(writer, property.Value, options);
}
writer.WriteEndObject();
break;
case JsonValueKind.Undefined:
throw new JsonException("Cannot serialize undefined JsonElement");
}

// TODO - Complete the implementation using DocumentConverter as a guide
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using PinguApps.Appwrite.Shared.Responses;

namespace PinguApps.Appwrite.Shared.Converters;
public class DocumentGenericConverterFactory : JsonConverterFactory
{
public override bool CanConvert(Type typeToConvert)
{
// Ensure the type is a generic type of Document<>
return typeToConvert.IsGenericType && typeToConvert.GetGenericTypeDefinition() == typeof(Document<>);
}

public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
// Extract the TData type from Doocument<TData>
Type dataType = typeToConvert.GetGenericArguments()[0];

// Create a specific generic converter for Doocument<TData>
var converterType = typeof(DocumentGenericConverter<>).MakeGenericType(dataType);
return (JsonConverter?)Activator.CreateInstance(converterType);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using PinguApps.Appwrite.Shared.Converters;
using PinguApps.Appwrite.Shared.Utils;

namespace PinguApps.Appwrite.Shared.Responses;
Expand All @@ -15,8 +16,8 @@ namespace PinguApps.Appwrite.Shared.Responses;
/// <param name="UpdatedAt">Document update date in ISO 8601 format</param>
/// <param name="Permissions">Document permissions. <see href="https://appwrite.io/docs/permissions">Learn more about permissions</see></param>
/// <param name="Data">Document data</param>
[JsonConverter(typeof(DocumentGenericConverter))]
public record Doocument<TData>(
[JsonConverter(typeof(DocumentGenericConverterFactory))]
public record Document<TData>(
string Id,
string CollectionId,
string DatabaseId,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
using System.Text.Json;
using PinguApps.Appwrite.Shared.Converters;
using PinguApps.Appwrite.Shared.Responses;

namespace PinguApps.Appwrite.Shared.Tests.Converters;
public class DocumentGenericConverterFactoryTests
{
private readonly DocumentGenericConverterFactory _factory;

public DocumentGenericConverterFactoryTests()
{
_factory = new DocumentGenericConverterFactory();
}

public class TestData
{
public string? Field1 { get; set; }
}

[Fact]
public void CanConvert_DocumentGenericType_ReturnsTrue()
{
// Arrange
var typeToConvert = typeof(Document<TestData>);

// Act
var result = _factory.CanConvert(typeToConvert);

// Assert
Assert.True(result);
}

[Fact]
public void CanConvert_NonGenericType_ReturnsFalse()
{
// Arrange
var typeToConvert = typeof(TestData);

// Act
var result = _factory.CanConvert(typeToConvert);

// Assert
Assert.False(result);
}

[Fact]
public void CanConvert_DifferentGenericType_ReturnsFalse()
{
// Arrange
var typeToConvert = typeof(List<TestData>);

// Act
var result = _factory.CanConvert(typeToConvert);

// Assert
Assert.False(result);
}

[Fact]
public void CreateConverter_DocumentGenericType_ReturnsConverter()
{
// Arrange
var typeToConvert = typeof(Document<TestData>);
var options = new JsonSerializerOptions();

// Act
var converter = _factory.CreateConverter(typeToConvert, options);

// Assert
Assert.NotNull(converter);
Assert.IsType<DocumentGenericConverter<TestData>>(converter);
}

[Fact]
public void CreateConverter_NonGenericType_ThrowsException()
{
// Arrange
var typeToConvert = typeof(TestData);
var options = new JsonSerializerOptions();

// Act & Assert
Assert.Throws<IndexOutOfRangeException>(() => _factory.CreateConverter(typeToConvert, options));
}

[Fact]
public void CreateConverter_DifferentGenericType_ReturnsConverterWithFirstGenericArgument()
{
// Arrange
var typeToConvert = typeof(List<TestData>);
var options = new JsonSerializerOptions();

// Act
var converter = _factory.CreateConverter(typeToConvert, options);

// Assert
Assert.NotNull(converter);
Assert.IsType<DocumentGenericConverter<TestData>>(converter);
}
}
Loading

0 comments on commit 7f732fb

Please sign in to comment.