Refactor and modernize JSON converter test code

Refactor test code in Jellyfin.Extensions.Tests for clarity and consistency:
- Use explicit object initializers and collection expressions
- Standardize field naming and use of this.
- Add/improve XML doc comments for test methods
- Use new(...) syntax for Guid/Version instantiation
- Convert file-scoped to block-scoped namespaces in key tests
- Nest test classes and use instance methods in enum tests
- Enable XML docs and suppress select warnings in csproj
- No changes to test or converter logic; style and maintainability only
This commit is contained in:
2026-02-22 10:31:23 -05:00
parent d5522c6fb3
commit dbeec2e9f0
17 changed files with 302 additions and 245 deletions
@@ -2,6 +2,8 @@
<PropertyGroup>
<TargetFramework>net11.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);CS1591;CS1570;CS8600;SA1600;SA1309;SA1200</NoWarn>
</PropertyGroup>
<ItemGroup>
@@ -62,6 +62,8 @@ namespace Jellyfin.Extensions.Tests.Json.Converters
/// <returns>A property test result.</returns>
[Property]
public Property Deserialize_NonZeroInt_True(NonZeroInt input)
=> JsonSerializer.Deserialize<bool>(input.ToString(), this._jsonOptions).ToProperty();
{
return JsonSerializer.Deserialize<bool>(input.ToString(), this._jsonOptions).ToProperty();
}
}
}
@@ -23,7 +23,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters
[InlineData(@"{ ""Value"": ""false"" }", false)]
public void Deserialize_String_Valid_Success(string input, bool output)
{
TestStruct s = JsonSerializer.Deserialize<TestStruct>(input, _jsonOptions);
TestStruct s = JsonSerializer.Deserialize<TestStruct>(input, this._jsonOptions);
Assert.Equal(s.Value, output);
}
@@ -32,7 +32,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters
[InlineData(false, "false")]
public void Serialize_Bool_Success(bool input, string output)
{
string value = JsonSerializer.Serialize(input, _jsonOptions);
string value = JsonSerializer.Serialize(input, this._jsonOptions);
Assert.Equal(value, output);
}
@@ -7,16 +7,18 @@ namespace Jellyfin.Extensions.Tests.Json.Converters
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using Jellyfin.Extensions.Tests.Json.Models;
using MediaBrowser.Model.Session;
using Xunit;
/// <summary>
/// Tests for JSON comma delimited collection converter.
/// </summary>
public class JsonCommaDelimitedCollectionTests
{
private readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions()
private readonly JsonSerializerOptions jsonOptions = new()
{
Converters =
{
@@ -24,203 +26,236 @@ namespace Jellyfin.Extensions.Tests.Json.Converters
},
};
/// <summary>
/// Tests that deserializing null string value succeeds.
/// </summary>
[Fact]
public void Deserialize_String_Null_Success()
{
GenericBodyArrayModel<string value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": null }", _jsonOptions);
GenericBodyArrayModel<string>? value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": null }", this.jsonOptions);
Assert.Null(value?.Value);
}
/// <summary>
/// Tests that deserializing empty string succeeds.
/// </summary>
[Fact]
public void Deserialize_Empty_Success()
{
GenericBodyArrayModel<string>
{ desiredValue = new GenericBodyArrayModel<string>
GenericBodyArrayModel<string> desiredValue = new()
{
Value = Array.Empty<string>(),
Value = [],
};
GenericBodyArrayModel<string value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": """" }", _jsonOptions);
GenericBodyArrayModel<string>? value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": """" }", this.jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
/// <summary>
/// Tests that deserializing empty string to list throws exception.
/// </summary>
[Fact]
public void Deserialize_EmptyList_Success()
{
GenericBodyListModel<string>
{ desiredValue = new GenericBodyListModel<string>
GenericBodyListModel<string> desiredValue = new()
{
Value = [],
};
Assert.Throws<InvalidOperationException>(() => JsonSerializer.Deserialize<GenericBodyListModel<string>>(@"{ ""Value"": """" }", _jsonOptions));
_ = Assert.Throws<InvalidOperationException>(() => JsonSerializer.Deserialize<GenericBodyListModel<string>>(@"{ ""Value"": """" }", this.jsonOptions));
}
/// <summary>
/// Tests that deserializing empty string to IReadOnlyList succeeds.
/// </summary>
[Fact]
public void Deserialize_EmptyIReadOnlyList_Success()
{
GenericBodyIReadOnlyListModel<string>
{ desiredValue = new GenericBodyIReadOnlyListModel<string>
GenericBodyIReadOnlyListModel<string> desiredValue = new()
{
Value = [],
};
GenericBodyIReadOnlyListModel<string value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": """" }", _jsonOptions);
GenericBodyIReadOnlyListModel<string>? value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": """" }", this.jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
/// <summary>
/// Tests that deserializing comma-delimited string succeeds.
/// </summary>
[Fact]
public void Deserialize_String_Valid_Success()
{
GenericBodyArrayModel<string>
{ desiredValue = new GenericBodyArrayModel<string>
GenericBodyArrayModel<string> desiredValue = new()
{
Value = ["a", "b", "c"],
};
GenericBodyArrayModel<string value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": ""a,b,c"" }", _jsonOptions);
GenericBodyArrayModel<string>? value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": ""a,b,c"" }", this.jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
/// <summary>
/// Tests that deserializing comma-delimited string to list throws exception.
/// </summary>
[Fact]
public void Deserialize_StringList_Valid_Success()
{
GenericBodyListModel<string>
{ desiredValue = new GenericBodyListModel<string>
GenericBodyListModel<string> desiredValue = new()
{
Value = ["a", "b", "c"],
};
Assert.Throws<InvalidOperationException>(() => JsonSerializer.Deserialize<GenericBodyListModel<string>>(@"{ ""Value"": ""a,b,c"" }", _jsonOptions));
_ = Assert.Throws<InvalidOperationException>(() => JsonSerializer.Deserialize<GenericBodyListModel<string>>(@"{ ""Value"": ""a,b,c"" }", this.jsonOptions));
}
/// <summary>
/// Tests that deserializing comma-delimited string with spaces succeeds.
/// </summary>
[Fact]
public void Deserialize_String_Space_Valid_Success()
{
GenericBodyArrayModel<string>
{ desiredValue = new GenericBodyArrayModel<string>
GenericBodyArrayModel<string> desiredValue = new()
{
Value = ["a", "b", "c"],
};
GenericBodyArrayModel<string value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": ""a, b, c"" }", _jsonOptions);
GenericBodyArrayModel<string>? value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": ""a, b, c"" }", this.jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
/// <summary>
/// Tests that deserializing comma-delimited enum string succeeds.
/// </summary>
[Fact]
public void Deserialize_GenericCommandType_Valid_Success()
{
GenericBodyArrayModel<GeneralCommandType>
{ desiredValue = new GenericBodyArrayModel<GeneralCommandType>
GenericBodyArrayModel<GeneralCommandType> desiredValue = new()
{
Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown],
};
GenericBodyArrayModel<GeneralCommandType value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,MoveDown"" }", _jsonOptions);
GenericBodyArrayModel<GeneralCommandType>? value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,MoveDown"" }", this.jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
/// <summary>
/// Tests that deserializing comma-delimited enum string with empty entry succeeds.
/// </summary>
[Fact]
public void Deserialize_GenericCommandType_EmptyEntry_Success()
{
GenericBodyArrayModel<GeneralCommandType>
{ desiredValue = new GenericBodyArrayModel<GeneralCommandType>
GenericBodyArrayModel<GeneralCommandType> desiredValue = new()
{
Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown],
};
GenericBodyArrayModel<GeneralCommandType value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,,MoveDown"" }", _jsonOptions);
GenericBodyArrayModel<GeneralCommandType>? value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,,MoveDown"" }", this.jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
/// <summary>
/// Tests that deserializing comma-delimited enum string with invalid value succeeds.
/// </summary>
[Fact]
public void Deserialize_GenericCommandType_Invalid_Success()
{
GenericBodyArrayModel<GeneralCommandType>
{ desiredValue = new GenericBodyArrayModel<GeneralCommandType>
GenericBodyArrayModel<GeneralCommandType> desiredValue = new()
{
Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown],
};
GenericBodyArrayModel<GeneralCommandType value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,TotallyNotAValidCommand,MoveDown"" }", _jsonOptions);
GenericBodyArrayModel<GeneralCommandType>? value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,TotallyNotAValidCommand,MoveDown"" }", this.jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
/// <summary>
/// Tests that deserializing comma-delimited enum string with spaces succeeds.
/// </summary>
[Fact]
public void Deserialize_GenericCommandType_Space_Valid_Success()
{
GenericBodyArrayModel<GeneralCommandType>
{ desiredValue = new GenericBodyArrayModel<GeneralCommandType>
GenericBodyArrayModel<GeneralCommandType> desiredValue = new()
{
Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown],
};
GenericBodyArrayModel<GeneralCommandType value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp, MoveDown"" }", _jsonOptions);
GenericBodyArrayModel<GeneralCommandType>? value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp, MoveDown"" }", this.jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
/// <summary>
/// Tests that deserializing JSON array of strings succeeds.
/// </summary>
[Fact]
public void Deserialize_String_Array_Valid_Success()
{
GenericBodyArrayModel<string>
{ desiredValue = new GenericBodyArrayModel<string>
GenericBodyArrayModel<string> desiredValue = new()
{
Value = ["a", "b", "c"],
};
GenericBodyArrayModel<string value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": [""a"",""b"",""c""] }", _jsonOptions);
GenericBodyArrayModel<string>? value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": [""a"",""b"",""c""] }", this.jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
/// <summary>
/// Tests that deserializing JSON array of enums succeeds.
/// </summary>
[Fact]
public void Deserialize_GenericCommandType_Array_Valid_Success()
{
GenericBodyArrayModel<GeneralCommandType>
{ desiredValue = new GenericBodyArrayModel<GeneralCommandType>
GenericBodyArrayModel<GeneralCommandType> desiredValue = new()
{
Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown],
};
GenericBodyArrayModel<GeneralCommandType value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": [""MoveUp"", ""MoveDown""] }", _jsonOptions);
GenericBodyArrayModel<GeneralCommandType>? value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": [""MoveUp"", ""MoveDown""] }", this.jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
/// <summary>
/// Tests that serializing readonly collection succeeds.
/// </summary>
[Fact]
public void Serialize_GenericCommandType_ReadOnlyArray_Valid_Success()
{
GenericBodyIReadOnlyCollectionModel<GeneralCommandType>
{ valueToSerialize = new GenericBodyIReadOnlyCollectionModel<GeneralCommandType>
GenericBodyIReadOnlyCollectionModel<GeneralCommandType> valueToSerialize = new()
{
Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown }.AsReadOnly(),
};
string value = JsonSerializer.Serialize<GenericBodyIReadOnlyCollectionModel<GeneralCommandType>>(valueToSerialize, _jsonOptions);
string value = JsonSerializer.Serialize<GenericBodyIReadOnlyCollectionModel<GeneralCommandType>>(valueToSerialize, this.jsonOptions);
Assert.Equal(@"{""Value"":[""MoveUp"",""MoveDown""]}", value);
}
/// <summary>
/// Tests that serializing immutable array succeeds.
/// </summary>
[Fact]
public void Serialize_GenericCommandType_ImmutableArrayArray_Valid_Success()
{
GenericBodyIReadOnlyCollectionModel<GeneralCommandType>
{ valueToSerialize = new GenericBodyIReadOnlyCollectionModel<GeneralCommandType>
GenericBodyIReadOnlyCollectionModel<GeneralCommandType> valueToSerialize = new()
{
Value = ImmutableArray.Create(new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown }),
Value = ImmutableArray.Create([GeneralCommandType.MoveUp, GeneralCommandType.MoveDown]),
};
string value = JsonSerializer.Serialize<GenericBodyIReadOnlyCollectionModel<GeneralCommandType>>(valueToSerialize, _jsonOptions);
string value = JsonSerializer.Serialize<GenericBodyIReadOnlyCollectionModel<GeneralCommandType>>(valueToSerialize, this.jsonOptions);
Assert.Equal(@"{""Value"":[""MoveUp"",""MoveDown""]}", value);
}
/// <summary>
/// Tests that serializing list succeeds.
/// </summary>
[Fact]
public void Serialize_GenericCommandType_List_Valid_Success()
{
GenericBodyIReadOnlyListModel<GeneralCommandType>
{ valueToSerialize = new GenericBodyIReadOnlyListModel<GeneralCommandType>
GenericBodyIReadOnlyListModel<GeneralCommandType> valueToSerialize = new()
{
Value = new List<GeneralCommandType> { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown },
Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown],
};
string value = JsonSerializer.Serialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(valueToSerialize, _jsonOptions);
string value = JsonSerializer.Serialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(valueToSerialize, this.jsonOptions);
Assert.Equal(@"{""Value"":[""MoveUp"",""MoveDown""]}", value);
}
}
@@ -4,16 +4,18 @@
namespace Jellyfin.Extensions.Tests.Json.Converters
{
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
using Jellyfin.Extensions.Tests.Json.Models;
using MediaBrowser.Model.Session;
using Xunit;
/// <summary>
/// Tests for JSON comma delimited IReadOnlyList converter.
/// </summary>
public class JsonCommaDelimitedIReadOnlyListTests
{
private readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions()
private readonly JsonSerializerOptions jsonOptions = new()
{
Converters =
{
@@ -21,94 +23,108 @@ namespace Jellyfin.Extensions.Tests.Json.Converters
},
};
/// <summary>
/// Tests that deserializing comma-delimited string succeeds.
/// </summary>
[Fact]
public void Deserialize_String_Valid_Success()
{
GenericBodyIReadOnlyListModel<string>
{ desiredValue = new GenericBodyIReadOnlyListModel<string>
GenericBodyIReadOnlyListModel<string> desiredValue = new()
{
Value = new[] { "a", "b", "c" },
Value = ["a", "b", "c"],
};
GenericBodyIReadOnlyListModel<string value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": ""a,b,c"" }", _jsonOptions);
GenericBodyIReadOnlyListModel<string>? value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": ""a,b,c"" }", this.jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
/// <summary>
/// Tests that deserializing comma-delimited string with spaces succeeds.
/// </summary>
[Fact]
public void Deserialize_String_Space_Valid_Success()
{
GenericBodyIReadOnlyListModel<string>
{ desiredValue = new GenericBodyIReadOnlyListModel<string>
GenericBodyIReadOnlyListModel<string> desiredValue = new()
{
Value = new[] { "a", "b", "c" },
Value = ["a", "b", "c"],
};
GenericBodyIReadOnlyListModel<string value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": ""a, b, c"" }", _jsonOptions);
GenericBodyIReadOnlyListModel<string>? value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": ""a, b, c"" }", this.jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
/// <summary>
/// Tests that deserializing comma-delimited enum string succeeds.
/// </summary>
[Fact]
public void Deserialize_GenericCommandType_Valid_Success()
{
GenericBodyIReadOnlyListModel<GeneralCommandType>
{ desiredValue = new GenericBodyIReadOnlyListModel<GeneralCommandType>
GenericBodyIReadOnlyListModel<GeneralCommandType> desiredValue = new()
{
Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown },
Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown],
};
GenericBodyIReadOnlyListModel<GeneralCommandType value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,MoveDown"" }", _jsonOptions);
GenericBodyIReadOnlyListModel<GeneralCommandType>? value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,MoveDown"" }", this.jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
/// <summary>
/// Tests that deserializing comma-delimited enum string with spaces succeeds.
/// </summary>
[Fact]
public void Deserialize_GenericCommandType_Space_Valid_Success()
{
GenericBodyIReadOnlyListModel<GeneralCommandType>
{ desiredValue = new GenericBodyIReadOnlyListModel<GeneralCommandType>
GenericBodyIReadOnlyListModel<GeneralCommandType> desiredValue = new()
{
Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown },
Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown],
};
GenericBodyIReadOnlyListModel<GeneralCommandType value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp, MoveDown"" }", _jsonOptions);
GenericBodyIReadOnlyListModel<GeneralCommandType>? value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp, MoveDown"" }", this.jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
/// <summary>
/// Tests that deserializing JSON array of strings succeeds.
/// </summary>
[Fact]
public void Deserialize_String_Array_Valid_Success()
{
GenericBodyIReadOnlyListModel<string>
{ desiredValue = new GenericBodyIReadOnlyListModel<string>
GenericBodyIReadOnlyListModel<string> desiredValue = new()
{
Value = new[] { "a", "b", "c" },
Value = ["a", "b", "c"],
};
GenericBodyIReadOnlyListModel<string value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": [""a"",""b"",""c""] }", _jsonOptions);
GenericBodyIReadOnlyListModel<string>? value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": [""a"",""b"",""c""] }", this.jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
/// <summary>
/// Tests that deserializing JSON array of enums succeeds.
/// </summary>
[Fact]
public void Deserialize_GenericCommandType_Array_Valid_Success()
{
GenericBodyIReadOnlyListModel<GeneralCommandType>
{ desiredValue = new GenericBodyIReadOnlyListModel<GeneralCommandType>
GenericBodyIReadOnlyListModel<GeneralCommandType> desiredValue = new()
{
Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown },
Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown],
};
GenericBodyIReadOnlyListModel<GeneralCommandType value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(@"{ ""Value"": [""MoveUp"", ""MoveDown""] }", _jsonOptions);
GenericBodyIReadOnlyListModel<GeneralCommandType>? value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(@"{ ""Value"": [""MoveUp"", ""MoveDown""] }", this.jsonOptions);
Assert.Equal(desiredValue.Value, value?.Value);
}
/// <summary>
/// Tests that serializing IReadOnlyList succeeds.
/// </summary>
[Fact]
public void Serialize_GenericCommandType_IReadOnlyList_Valid_Success()
{
GenericBodyIReadOnlyListModel<GeneralCommandType>
{ valueToSerialize = new GenericBodyIReadOnlyListModel<GeneralCommandType>
GenericBodyIReadOnlyListModel<GeneralCommandType> valueToSerialize = new()
{
Value = new List<GeneralCommandType> { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown },
Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown],
};
string value = JsonSerializer.Serialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(valueToSerialize, _jsonOptions);
string value = JsonSerializer.Serialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(valueToSerialize, this.jsonOptions);
Assert.Equal(@"{""Value"":[""MoveUp"",""MoveDown""]}", value);
}
}
@@ -2,115 +2,116 @@
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace Jellyfin.Extensions.Tests.Json.Converters;
using System.Text.Json;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions.Json.Converters;
using Xunit;
public class JsonDefaultStringEnumConverterTests
namespace Jellyfin.Extensions.Tests.Json.Converters
{
private readonly JsonSerializerOptions _jsonOptions = new() { Converters = { new JsonDefaultStringEnumConverterFactory() } };
using System.Text.Json;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions.Json.Converters;
using Xunit;
/// <summary>
/// Test to ensure that `null` and empty string are deserialized to the default value.
/// </summary>
/// <param name="input">The input string.</param>
/// <param name="output">The expected enum value.</param>
[Theory]
[InlineData("\"\"", MediaStreamProtocol.http)]
[InlineData("\"Http\"", MediaStreamProtocol.http)]
[InlineData("\"Hls\"", MediaStreamProtocol.hls)]
public void Deserialize_Enum_Direct(string input, MediaStreamProtocol output)
public class JsonDefaultStringEnumConverterTests
{
MediaStreamProtocol value = JsonSerializer.Deserialize<MediaStreamProtocol>(input, _jsonOptions);
Assert.Equal(output, value);
}
private readonly JsonSerializerOptions _jsonOptions = new() { Converters = { new JsonDefaultStringEnumConverterFactory() } };
/// <summary>
/// Test to ensure that `null` and empty string are deserialized to the default value.
/// </summary>
/// <param name="input">The input string.</param>
/// <param name="output">The expected enum value.</param>
[Theory]
[InlineData(null, MediaStreamProtocol.http)]
[InlineData("\"\"", MediaStreamProtocol.http)]
[InlineData("\"Http\"", MediaStreamProtocol.http)]
[InlineData("\"Hls\"", MediaStreamProtocol.hls)]
public void Deserialize_Enum(string? input, MediaStreamProtocol output)
{
input ??= "null";
var json = $"{{ \"EnumValue\": {input} }}";
TestClass value = JsonSerializer.Deserialize<TestClass>(json, _jsonOptions);
Assert.NotNull(value);
Assert.Equal(output, value.EnumValue);
}
/// <summary>
/// Test to ensure that `null` and empty string are deserialized to the default value.
/// </summary>
/// <param name="input">The input string.</param>
/// <param name="output">The expected enum value.</param>
[Theory]
[InlineData("\"\"", MediaStreamProtocol.http)]
[InlineData("\"Http\"", MediaStreamProtocol.http)]
[InlineData("\"Hls\"", MediaStreamProtocol.hls)]
public void Deserialize_Enum_Direct(string input, MediaStreamProtocol output)
{
MediaStreamProtocol value = JsonSerializer.Deserialize<MediaStreamProtocol>(input, this._jsonOptions);
Assert.Equal(output, value);
}
/// <summary>
/// Test to ensure that empty string is deserialized to the default value,
/// and `null` is deserialized to `null`.
/// </summary>
/// <param name="input">The input string.</param>
/// <param name="output">The expected enum value.</param>
[Theory]
[InlineData(null, null)]
[InlineData("\"\"", MediaStreamProtocol.http)]
[InlineData("\"Http\"", MediaStreamProtocol.http)]
[InlineData("\"Hls\"", MediaStreamProtocol.hls)]
public void Deserialize_Enum_Nullable(string? input, MediaStreamProtocol? output)
{
input ??= "null";
var json = $"{{ \"EnumValue\": {input} }}";
NullTestClass value = JsonSerializer.Deserialize<NullTestClass>(json, _jsonOptions);
Assert.NotNull(value);
Assert.Equal(output, value.EnumValue);
}
/// <summary>
/// Test to ensure that `null` and empty string are deserialized to the default value.
/// </summary>
/// <param name="input">The input string.</param>
/// <param name="output">The expected enum value.</param>
[Theory]
[InlineData(null, MediaStreamProtocol.http)]
[InlineData("\"\"", MediaStreamProtocol.http)]
[InlineData("\"Http\"", MediaStreamProtocol.http)]
[InlineData("\"Hls\"", MediaStreamProtocol.hls)]
public void Deserialize_Enum(string? input, MediaStreamProtocol output)
{
input ??= "null";
string json = $"{{ \"EnumValue\": {input} }}";
TestClass value = JsonSerializer.Deserialize<TestClass>(json, this._jsonOptions);
Assert.NotNull(value);
Assert.Equal(output, value.EnumValue);
}
/// <summary>
/// Ensures that the roundtrip serialization & deserialization is successful.
/// </summary>
/// <param name="input">Input enum.</param>
/// <param name="output">Output enum.</param>
[Theory]
[InlineData(MediaStreamProtocol.http, MediaStreamProtocol.http)]
[InlineData(MediaStreamProtocol.hls, MediaStreamProtocol.hls)]
public void Enum_RoundTrip(MediaStreamProtocol input, MediaStreamProtocol output)
{
var inputObj = new TestClass { EnumValue = input };
/// <summary>
/// Test to ensure that empty string is deserialized to the default value,
/// and `null` is deserialized to `null`.
/// </summary>
/// <param name="input">The input string.</param>
/// <param name="output">The expected enum value.</param>
[Theory]
[InlineData(null, null)]
[InlineData("\"\"", MediaStreamProtocol.http)]
[InlineData("\"Http\"", MediaStreamProtocol.http)]
[InlineData("\"Hls\"", MediaStreamProtocol.hls)]
public void Deserialize_Enum_Nullable(string? input, MediaStreamProtocol? output)
{
input ??= "null";
string json = $"{{ \"EnumValue\": {input} }}";
NullTestClass value = JsonSerializer.Deserialize<NullTestClass>(json, this._jsonOptions);
Assert.NotNull(value);
Assert.Equal(output, value.EnumValue);
}
var outputObj = JsonSerializer.Deserialize<TestClass>(JsonSerializer.Serialize(inputObj, _jsonOptions), _jsonOptions);
/// <summary>
/// Ensures that the roundtrip serialization &amp; deserialization is successful.
/// </summary>
/// <param name="input">Input enum.</param>
/// <param name="output">Output enum.</param>
[Theory]
[InlineData(MediaStreamProtocol.http, MediaStreamProtocol.http)]
[InlineData(MediaStreamProtocol.hls, MediaStreamProtocol.hls)]
public void Enum_RoundTrip(MediaStreamProtocol input, MediaStreamProtocol output)
{
TestClass inputObj = new() { EnumValue = input };
Assert.NotNull(outputObj);
Assert.Equal(output, outputObj.EnumValue);
}
TestClass? outputObj = JsonSerializer.Deserialize<TestClass>(JsonSerializer.Serialize(inputObj, this._jsonOptions), this._jsonOptions);
/// <summary>
/// Ensures that the roundtrip serialization & deserialization is successful, including null.
/// </summary>
/// <param name="input">Input enum.</param>
/// <param name="output">Output enum.</param>
[Theory]
[InlineData(MediaStreamProtocol.http, MediaStreamProtocol.http)]
[InlineData(MediaStreamProtocol.hls, MediaStreamProtocol.hls)]
[InlineData(null, null)]
public void Enum_RoundTrip_Nullable(MediaStreamProtocol? input, MediaStreamProtocol? output)
{
var inputObj = new NullTestClass { EnumValue = input };
Assert.NotNull(outputObj);
Assert.Equal(output, outputObj.EnumValue);
}
var outputObj = JsonSerializer.Deserialize<NullTestClass>(JsonSerializer.Serialize(inputObj, _jsonOptions), _jsonOptions);
/// <summary>
/// Ensures that the roundtrip serialization &amp; deserialization is successful, including null.
/// </summary>
/// <param name="input">Input enum.</param>
/// <param name="output">Output enum.</param>
[Theory]
[InlineData(MediaStreamProtocol.http, MediaStreamProtocol.http)]
[InlineData(MediaStreamProtocol.hls, MediaStreamProtocol.hls)]
[InlineData(null, null)]
public void Enum_RoundTrip_Nullable(MediaStreamProtocol? input, MediaStreamProtocol? output)
{
NullTestClass inputObj = new() { EnumValue = input };
Assert.NotNull(outputObj);
Assert.Equal(output, outputObj.EnumValue);
}
NullTestClass? outputObj = JsonSerializer.Deserialize<NullTestClass>(JsonSerializer.Serialize(inputObj, this._jsonOptions), this._jsonOptions);
private sealed class TestClass
{
public MediaStreamProtocol EnumValue { get; set; }
}
Assert.NotNull(outputObj);
Assert.Equal(output, outputObj.EnumValue);
}
private sealed class NullTestClass
{
public MediaStreamProtocol? EnumValue { get; set; }
private sealed class TestClass
{
public MediaStreamProtocol EnumValue { get; set; }
}
private sealed class NullTestClass
{
public MediaStreamProtocol? EnumValue { get; set; }
}
}
}
@@ -2,31 +2,32 @@
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace Jellyfin.Extensions.Tests.Json.Converters;
using System.Text.Json;
using Jellyfin.Extensions.Json.Converters;
using MediaBrowser.Model.Session;
using Xunit;
public class JsonFlagEnumTests
namespace Jellyfin.Extensions.Tests.Json.Converters
{
private readonly JsonSerializerOptions _jsonOptions = new()
using System.Text.Json;
using Jellyfin.Extensions.Json.Converters;
using MediaBrowser.Model.Session;
using Xunit;
public class JsonFlagEnumTests
{
Converters =
private readonly JsonSerializerOptions _jsonOptions = new()
{
new JsonFlagEnumConverter<TranscodeReason>(),
},
};
Converters =
{
new JsonFlagEnumConverter<TranscodeReason>(),
},
};
[Theory]
[InlineData(TranscodeReason.AudioIsExternal | TranscodeReason.ContainerNotSupported, "[\"ContainerNotSupported\",\"AudioIsExternal\"]")]
[InlineData(TranscodeReason.AudioIsExternal | TranscodeReason.ContainerNotSupported | TranscodeReason.VideoBitDepthNotSupported, "[\"ContainerNotSupported\",\"AudioIsExternal\",\"VideoBitDepthNotSupported\"]")]
[InlineData((TranscodeReason)0, "[]")]
public void Serialize_Transcode_Reason(TranscodeReason transcodeReason, string output)
{
var result = JsonSerializer.Serialize(transcodeReason, _jsonOptions);
[Theory]
[InlineData(TranscodeReason.AudioIsExternal | TranscodeReason.ContainerNotSupported, "[\"ContainerNotSupported\",\"AudioIsExternal\"]")]
[InlineData(TranscodeReason.AudioIsExternal | TranscodeReason.ContainerNotSupported | TranscodeReason.VideoBitDepthNotSupported, "[\"ContainerNotSupported\",\"AudioIsExternal\",\"VideoBitDepthNotSupported\"]")]
[InlineData((TranscodeReason)0, "[]")]
public void Serialize_Transcode_Reason(TranscodeReason transcodeReason, string output)
{
string result = JsonSerializer.Serialize(transcodeReason, this._jsonOptions);
Assert.Equal(output, result);
Assert.Equal(output, result);
}
}
}
@@ -15,49 +15,49 @@ namespace Jellyfin.Extensions.Tests.Json.Converters
public JsonGuidConverterTests()
{
_options = new JsonSerializerOptions();
_options.Converters.Add(new JsonGuidConverter());
this._options = new JsonSerializerOptions();
this._options.Converters.Add(new JsonGuidConverter());
}
[Fact]
public void Deserialize_Valid_Success()
{
Guid value = JsonSerializer.Deserialize<Guid>(@"""a852a27afe324084ae66db579ee3ee18""", _options);
Assert.Equal(new Guid("a852a27afe324084ae66db579ee3ee18"), value);
Guid value = JsonSerializer.Deserialize<Guid>(@"""a852a27afe324084ae66db579ee3ee18""", this._options);
Assert.Equal(new("a852a27afe324084ae66db579ee3ee18"), value);
}
[Fact]
public void Deserialize_ValidDashed_Success()
{
Guid value = JsonSerializer.Deserialize<Guid>(@"""e9b2dcaa-529c-426e-9433-5e9981f27f2e""", _options);
Assert.Equal(new Guid("e9b2dcaa-529c-426e-9433-5e9981f27f2e"), value);
Guid value = JsonSerializer.Deserialize<Guid>(@"""e9b2dcaa-529c-426e-9433-5e9981f27f2e""", this._options);
Assert.Equal(new("e9b2dcaa-529c-426e-9433-5e9981f27f2e"), value);
}
[Fact]
public void Roundtrip_Valid_Success()
{
Guid guid = new Guid("a852a27afe324084ae66db579ee3ee18");
string value = JsonSerializer.Serialize(guid, _options);
Assert.Equal(guid, JsonSerializer.Deserialize<Guid>(value, _options));
Guid guid = new("a852a27afe324084ae66db579ee3ee18");
string value = JsonSerializer.Serialize(guid, this._options);
Assert.Equal(guid, JsonSerializer.Deserialize<Guid>(value, this._options));
}
[Fact]
public void Deserialize_Null_EmptyGuid()
{
Assert.Equal(Guid.Empty, JsonSerializer.Deserialize<Guid>("null", _options));
Assert.Equal(Guid.Empty, JsonSerializer.Deserialize<Guid>("null", this._options));
}
[Fact]
public void Serialize_EmptyGuid_EmptyGuid()
{
Assert.Equal($"\"{Guid.Empty:N}\"", JsonSerializer.Serialize(Guid.Empty, _options));
Assert.Equal($"\"{Guid.Empty:N}\"", JsonSerializer.Serialize(Guid.Empty, this._options));
}
[Fact]
public void Serialize_Valid_NoDash_Success()
{
var guid = new Guid("531797E9-9457-40E0-88BC-B1D6D38752FA");
var str = JsonSerializer.Serialize(guid, _options);
Guid guid = new("531797E9-9457-40E0-88BC-B1D6D38752FA");
string str = JsonSerializer.Serialize(guid, this._options);
Assert.Equal($"\"{guid:N}\"", str);
}
@@ -65,7 +65,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters
public void Serialize_Nullable_Success()
{
Guid? guid = new Guid("531797E9-9457-40E0-88BC-B1D6D38752FA");
var str = JsonSerializer.Serialize(guid, _options);
string str = JsonSerializer.Serialize(guid, this._options);
Assert.Equal($"\"{guid:N}\"", str);
}
}
@@ -15,69 +15,69 @@ namespace Jellyfin.Extensions.Tests.Json.Converters
public JsonNullableGuidConverterTests()
{
_options = new JsonSerializerOptions();
_options.Converters.Add(new JsonNullableGuidConverter());
this._options = new JsonSerializerOptions();
this._options.Converters.Add(new JsonNullableGuidConverter());
}
[Fact]
public void Deserialize_Valid_Success()
{
Guid? value = JsonSerializer.Deserialize<Guid?>(@"""a852a27afe324084ae66db579ee3ee18""", _options);
Assert.Equal(new Guid("a852a27afe324084ae66db579ee3ee18"), value);
Guid? value = JsonSerializer.Deserialize<Guid?>(@"""a852a27afe324084ae66db579ee3ee18""", this._options);
Assert.Equal(new("a852a27afe324084ae66db579ee3ee18"), value);
}
[Fact]
public void Deserialize_ValidDashed_Success()
{
Guid? value = JsonSerializer.Deserialize<Guid?>(@"""e9b2dcaa-529c-426e-9433-5e9981f27f2e""", _options);
Assert.Equal(new Guid("e9b2dcaa-529c-426e-9433-5e9981f27f2e"), value);
Guid? value = JsonSerializer.Deserialize<Guid?>(@"""e9b2dcaa-529c-426e-9433-5e9981f27f2e""", this._options);
Assert.Equal(new("e9b2dcaa-529c-426e-9433-5e9981f27f2e"), value);
}
[Fact]
public void Roundtrip_Valid_Success()
{
Guid guid = new Guid("a852a27afe324084ae66db579ee3ee18");
string value = JsonSerializer.Serialize(guid, _options);
Assert.Equal(guid, JsonSerializer.Deserialize<Guid?>(value, _options));
Guid guid = new("a852a27afe324084ae66db579ee3ee18");
string value = JsonSerializer.Serialize(guid, this._options);
Assert.Equal(guid, JsonSerializer.Deserialize<Guid?>(value, this._options));
}
[Fact]
public void Deserialize_Null_Null()
{
Assert.Null(JsonSerializer.Deserialize<Guid?>("null", _options));
Assert.Null(JsonSerializer.Deserialize<Guid?>("null", this._options));
}
[Fact]
public void Deserialize_EmptyGuid_EmptyGuid()
{
Assert.Equal(Guid.Empty, JsonSerializer.Deserialize<Guid?>(@"""00000000-0000-0000-0000-000000000000""", _options));
Assert.Equal(Guid.Empty, JsonSerializer.Deserialize<Guid?>(@"""00000000-0000-0000-0000-000000000000""", this._options));
}
[Fact]
public void Serialize_EmptyGuid_Null()
{
Assert.Equal("null", JsonSerializer.Serialize((Guid?)Guid.Empty, _options));
Assert.Equal("null", JsonSerializer.Serialize((Guid?)Guid.Empty, this._options));
}
[Fact]
public void Serialize_Null_Null()
{
Assert.Equal("null", JsonSerializer.Serialize((Guid?)null, _options));
Assert.Equal("null", JsonSerializer.Serialize((Guid?)null, this._options));
}
[Fact]
public void Serialize_Valid_NoDash_Success()
{
var guid = (Guid?)new Guid("531797E9-9457-40E0-88BC-B1D6D38752FA");
var str = JsonSerializer.Serialize(guid, _options);
Guid? guid = new("531797E9-9457-40E0-88BC-B1D6D38752FA");
string str = JsonSerializer.Serialize(guid, this._options);
Assert.Equal($"\"{guid:N}\"", str);
}
[Fact]
public void Serialize_Nullable_Success()
{
Guid? guid = new Guid("531797E9-9457-40E0-88BC-B1D6D38752FA");
var str = JsonSerializer.Serialize(guid, _options);
Guid? guid = new("531797E9-9457-40E0-88BC-B1D6D38752FA");
string str = JsonSerializer.Serialize(guid, this._options);
Assert.Equal($"\"{guid:N}\"", str);
}
}
@@ -26,7 +26,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters
[InlineData("false", "false")]
public void Deserialize_String_Valid_Success(string input, string output)
{
var deserialized = JsonSerializer.Deserialize<string>(input, _jsonSerializerOptions);
string? deserialized = JsonSerializer.Deserialize<string>(input, this._jsonSerializerOptions);
Assert.Equal(deserialized, output);
}
@@ -35,7 +35,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters
{
const string? input = "123";
const int output = 123;
var deserialized = JsonSerializer.Deserialize<int>(input, _jsonSerializerOptions);
int deserialized = JsonSerializer.Deserialize<int>(input, this._jsonSerializerOptions);
Assert.Equal(output, deserialized);
}
}
@@ -15,25 +15,25 @@ namespace Jellyfin.Extensions.Tests.Json.Converters
public JsonVersionConverterTests()
{
_options = new JsonSerializerOptions();
_options.Converters.Add(new JsonVersionConverter());
this._options = new JsonSerializerOptions();
this._options.Converters.Add(new JsonVersionConverter());
}
[Fact]
public void Deserialize_Version_Success()
{
var input = "\"1.025.222\"";
var output = new Version(1, 25, 222);
var deserializedInput = JsonSerializer.Deserialize<Version>(input, _options);
string input = "\"1.025.222\"";
Version output = new(1, 25, 222);
Version? deserializedInput = JsonSerializer.Deserialize<Version>(input, this._options);
Assert.Equal(output, deserializedInput);
}
[Fact]
public void Serialize_Version_Success()
{
var input = new Version(1, 09, 59);
var output = "\"1.9.59\"";
var serializedInput = JsonSerializer.Serialize(input, _options);
Version input = new(1, 09, 59);
string output = "\"1.9.59\"";
string serializedInput = JsonSerializer.Serialize(input, this._options);
Assert.Equal(output, serializedInput);
}
}