mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-06-03 14:28:46 +01:00
Merge branch 'master' into NetworkPR2
This commit is contained in:
@@ -8,6 +8,7 @@ using Jellyfin.Api.Auth;
|
||||
using Jellyfin.Api.Constants;
|
||||
using Jellyfin.Data.Entities;
|
||||
using Jellyfin.Data.Enums;
|
||||
using MediaBrowser.Controller.Authentication;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
@@ -68,19 +69,19 @@ namespace Jellyfin.Api.Tests.Auth
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HandleAuthenticateAsyncShouldFailOnSecurityException()
|
||||
public async Task HandleAuthenticateAsyncShouldFailOnAuthenticationException()
|
||||
{
|
||||
var errorMessage = _fixture.Create<string>();
|
||||
|
||||
_jellyfinAuthServiceMock.Setup(
|
||||
a => a.Authenticate(
|
||||
It.IsAny<HttpRequest>()))
|
||||
.Throws(new SecurityException(errorMessage));
|
||||
.Throws(new AuthenticationException(errorMessage));
|
||||
|
||||
var authenticateResult = await _sut.AuthenticateAsync();
|
||||
|
||||
Assert.False(authenticateResult.Succeeded);
|
||||
Assert.Equal(errorMessage, authenticateResult.Failure.Message);
|
||||
Assert.Equal(errorMessage, authenticateResult.Failure?.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -99,7 +100,7 @@ namespace Jellyfin.Api.Tests.Auth
|
||||
var authorizationInfo = SetupUser();
|
||||
var authenticateResult = await _sut.AuthenticateAsync();
|
||||
|
||||
Assert.True(authenticateResult.Principal.HasClaim(ClaimTypes.Name, authorizationInfo.User.Username));
|
||||
Assert.True(authenticateResult.Principal?.HasClaim(ClaimTypes.Name, authorizationInfo.User.Username));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -111,7 +112,7 @@ namespace Jellyfin.Api.Tests.Auth
|
||||
var authenticateResult = await _sut.AuthenticateAsync();
|
||||
|
||||
var expectedRole = authorizationInfo.User.HasPermission(PermissionKind.IsAdministrator) ? UserRoles.Administrator : UserRoles.User;
|
||||
Assert.True(authenticateResult.Principal.HasClaim(ClaimTypes.Role, expectedRole));
|
||||
Assert.True(authenticateResult.Principal?.HasClaim(ClaimTypes.Role, expectedRole));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -120,7 +121,7 @@ namespace Jellyfin.Api.Tests.Auth
|
||||
SetupUser();
|
||||
var authenticatedResult = await _sut.AuthenticateAsync();
|
||||
|
||||
Assert.Equal(_scheme.Name, authenticatedResult.Ticket.AuthenticationScheme);
|
||||
Assert.Equal(_scheme.Name, authenticatedResult.Ticket?.AuthenticationScheme);
|
||||
}
|
||||
|
||||
private AuthorizationInfo SetupUser(bool isAdmin = false)
|
||||
@@ -128,6 +129,7 @@ namespace Jellyfin.Api.Tests.Auth
|
||||
var authorizationInfo = _fixture.Create<AuthorizationInfo>();
|
||||
authorizationInfo.User = _fixture.Create<User>();
|
||||
authorizationInfo.User.SetPermission(PermissionKind.IsAdministrator, isAdmin);
|
||||
authorizationInfo.IsApiKey = false;
|
||||
|
||||
_jellyfinAuthServiceMock.Setup(
|
||||
a => a.Authenticate(
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Jellyfin.Api.Tests
|
||||
|
||||
// Assert
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal("application/json; charset=utf-8", response.Content.Headers.ContentType.ToString());
|
||||
Assert.Equal("application/json; charset=utf-8", response.Content.Headers.ContentType?.ToString());
|
||||
var responseBody = await response.Content.ReadAsStreamAsync();
|
||||
_ = await JsonSerializer.DeserializeAsync<BrandingOptions>(responseBody);
|
||||
}
|
||||
@@ -43,7 +43,7 @@ namespace Jellyfin.Api.Tests
|
||||
|
||||
// Assert
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal("text/css; charset=utf-8", response.Content.Headers.ContentType.ToString());
|
||||
Assert.Equal("text/css; charset=utf-8", response.Content.Headers.ContentType?.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Nullable>enable</Nullable>
|
||||
@@ -16,9 +16,9 @@
|
||||
<PackageReference Include="AutoFixture" Version="4.14.0" />
|
||||
<PackageReference Include="AutoFixture.AutoMoq" Version="4.14.0" />
|
||||
<PackageReference Include="AutoFixture.Xunit2" Version="4.14.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.9" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="3.1.9" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Threading.Tasks;
|
||||
using Jellyfin.Api.ModelBinders;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
@@ -17,11 +18,11 @@ namespace Jellyfin.Api.Tests.ModelBinders
|
||||
public async Task BindModelAsync_CorrectlyBindsValidCommaDelimitedStringArrayQuery()
|
||||
{
|
||||
var queryParamName = "test";
|
||||
var queryParamValues = new[] { "lol", "xd" };
|
||||
IReadOnlyList<string> queryParamValues = new[] { "lol", "xd" };
|
||||
var queryParamString = "lol,xd";
|
||||
var queryParamType = typeof(string[]);
|
||||
|
||||
var modelBinder = new CommaDelimitedArrayModelBinder();
|
||||
var modelBinder = new CommaDelimitedArrayModelBinder(new NullLogger<CommaDelimitedArrayModelBinder>());
|
||||
var valueProvider = new QueryStringValueProvider(
|
||||
new BindingSource(string.Empty, string.Empty, false, false),
|
||||
new QueryCollection(new Dictionary<string, StringValues> { { queryParamName, new StringValues(queryParamString) } }),
|
||||
@@ -35,18 +36,18 @@ namespace Jellyfin.Api.Tests.ModelBinders
|
||||
await modelBinder.BindModelAsync(bindingContextMock.Object);
|
||||
|
||||
Assert.True(bindingContextMock.Object.Result.IsModelSet);
|
||||
Assert.Equal((string[])bindingContextMock.Object.Result.Model, queryParamValues);
|
||||
Assert.Equal((IReadOnlyList<string>?)bindingContextMock.Object?.Result.Model, queryParamValues);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindModelAsync_CorrectlyBindsValidCommaDelimitedIntArrayQuery()
|
||||
{
|
||||
var queryParamName = "test";
|
||||
var queryParamValues = new[] { 42, 0 };
|
||||
IReadOnlyList<int> queryParamValues = new[] { 42, 0 };
|
||||
var queryParamString = "42,0";
|
||||
var queryParamType = typeof(int[]);
|
||||
|
||||
var modelBinder = new CommaDelimitedArrayModelBinder();
|
||||
var modelBinder = new CommaDelimitedArrayModelBinder(new NullLogger<CommaDelimitedArrayModelBinder>());
|
||||
var valueProvider = new QueryStringValueProvider(
|
||||
new BindingSource(string.Empty, string.Empty, false, false),
|
||||
new QueryCollection(new Dictionary<string, StringValues> { { queryParamName, new StringValues(queryParamString) } }),
|
||||
@@ -60,18 +61,18 @@ namespace Jellyfin.Api.Tests.ModelBinders
|
||||
await modelBinder.BindModelAsync(bindingContextMock.Object);
|
||||
|
||||
Assert.True(bindingContextMock.Object.Result.IsModelSet);
|
||||
Assert.Equal((int[])bindingContextMock.Object.Result.Model, queryParamValues);
|
||||
Assert.Equal((IReadOnlyList<int>?)bindingContextMock.Object.Result.Model, queryParamValues);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindModelAsync_CorrectlyBindsValidCommaDelimitedEnumArrayQuery()
|
||||
{
|
||||
var queryParamName = "test";
|
||||
var queryParamValues = new[] { TestType.How, TestType.Much };
|
||||
IReadOnlyList<TestType> queryParamValues = new[] { TestType.How, TestType.Much };
|
||||
var queryParamString = "How,Much";
|
||||
var queryParamType = typeof(TestType[]);
|
||||
|
||||
var modelBinder = new CommaDelimitedArrayModelBinder();
|
||||
var modelBinder = new CommaDelimitedArrayModelBinder(new NullLogger<CommaDelimitedArrayModelBinder>());
|
||||
var valueProvider = new QueryStringValueProvider(
|
||||
new BindingSource(string.Empty, string.Empty, false, false),
|
||||
new QueryCollection(new Dictionary<string, StringValues> { { queryParamName, new StringValues(queryParamString) } }),
|
||||
@@ -85,18 +86,18 @@ namespace Jellyfin.Api.Tests.ModelBinders
|
||||
await modelBinder.BindModelAsync(bindingContextMock.Object);
|
||||
|
||||
Assert.True(bindingContextMock.Object.Result.IsModelSet);
|
||||
Assert.Equal((TestType[])bindingContextMock.Object.Result.Model, queryParamValues);
|
||||
Assert.Equal((IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model, queryParamValues);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindModelAsync_CorrectlyBindsValidCommaDelimitedEnumArrayQueryWithDoubleCommas()
|
||||
{
|
||||
var queryParamName = "test";
|
||||
var queryParamValues = new[] { TestType.How, TestType.Much };
|
||||
IReadOnlyList<TestType> queryParamValues = new[] { TestType.How, TestType.Much };
|
||||
var queryParamString = "How,,Much";
|
||||
var queryParamType = typeof(TestType[]);
|
||||
|
||||
var modelBinder = new CommaDelimitedArrayModelBinder();
|
||||
var modelBinder = new CommaDelimitedArrayModelBinder(new NullLogger<CommaDelimitedArrayModelBinder>());
|
||||
var valueProvider = new QueryStringValueProvider(
|
||||
new BindingSource(string.Empty, string.Empty, false, false),
|
||||
new QueryCollection(new Dictionary<string, StringValues> { { queryParamName, new StringValues(queryParamString) } }),
|
||||
@@ -110,19 +111,19 @@ namespace Jellyfin.Api.Tests.ModelBinders
|
||||
await modelBinder.BindModelAsync(bindingContextMock.Object);
|
||||
|
||||
Assert.True(bindingContextMock.Object.Result.IsModelSet);
|
||||
Assert.Equal((TestType[])bindingContextMock.Object.Result.Model, queryParamValues);
|
||||
Assert.Equal((IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model, queryParamValues);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindModelAsync_CorrectlyBindsValidEnumArrayQuery()
|
||||
{
|
||||
var queryParamName = "test";
|
||||
var queryParamValues = new[] { TestType.How, TestType.Much };
|
||||
IReadOnlyList<TestType> queryParamValues = new[] { TestType.How, TestType.Much };
|
||||
var queryParamString1 = "How";
|
||||
var queryParamString2 = "Much";
|
||||
var queryParamType = typeof(TestType[]);
|
||||
|
||||
var modelBinder = new CommaDelimitedArrayModelBinder();
|
||||
var modelBinder = new CommaDelimitedArrayModelBinder(new NullLogger<CommaDelimitedArrayModelBinder>());
|
||||
|
||||
var valueProvider = new QueryStringValueProvider(
|
||||
new BindingSource(string.Empty, string.Empty, false, false),
|
||||
@@ -140,17 +141,17 @@ namespace Jellyfin.Api.Tests.ModelBinders
|
||||
await modelBinder.BindModelAsync(bindingContextMock.Object);
|
||||
|
||||
Assert.True(bindingContextMock.Object.Result.IsModelSet);
|
||||
Assert.Equal((TestType[])bindingContextMock.Object.Result.Model, queryParamValues);
|
||||
Assert.Equal((IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model, queryParamValues);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindModelAsync_CorrectlyBindsEmptyEnumArrayQuery()
|
||||
{
|
||||
var queryParamName = "test";
|
||||
var queryParamValues = Array.Empty<TestType>();
|
||||
IReadOnlyList<TestType> queryParamValues = Array.Empty<TestType>();
|
||||
var queryParamType = typeof(TestType[]);
|
||||
|
||||
var modelBinder = new CommaDelimitedArrayModelBinder();
|
||||
var modelBinder = new CommaDelimitedArrayModelBinder(new NullLogger<CommaDelimitedArrayModelBinder>());
|
||||
|
||||
var valueProvider = new QueryStringValueProvider(
|
||||
new BindingSource(string.Empty, string.Empty, false, false),
|
||||
@@ -168,17 +169,17 @@ namespace Jellyfin.Api.Tests.ModelBinders
|
||||
await modelBinder.BindModelAsync(bindingContextMock.Object);
|
||||
|
||||
Assert.True(bindingContextMock.Object.Result.IsModelSet);
|
||||
Assert.Equal((TestType[])bindingContextMock.Object.Result.Model, queryParamValues);
|
||||
Assert.Equal((IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model, queryParamValues);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindModelAsync_ThrowsIfCommaDelimitedEnumArrayQueryIsInvalid()
|
||||
public async Task BindModelAsync_EnumArrayQuery_BindValidOnly()
|
||||
{
|
||||
var queryParamName = "test";
|
||||
var queryParamString = "🔥,😢";
|
||||
var queryParamType = typeof(TestType[]);
|
||||
var queryParamType = typeof(IReadOnlyList<TestType>);
|
||||
|
||||
var modelBinder = new CommaDelimitedArrayModelBinder();
|
||||
var modelBinder = new CommaDelimitedArrayModelBinder(new NullLogger<CommaDelimitedArrayModelBinder>());
|
||||
var valueProvider = new QueryStringValueProvider(
|
||||
new BindingSource(string.Empty, string.Empty, false, false),
|
||||
new QueryCollection(new Dictionary<string, StringValues> { { queryParamName, new StringValues(queryParamString) } }),
|
||||
@@ -189,20 +190,20 @@ namespace Jellyfin.Api.Tests.ModelBinders
|
||||
bindingContextMock.Setup(b => b.ModelType).Returns(queryParamType);
|
||||
bindingContextMock.SetupProperty(b => b.Result);
|
||||
|
||||
Func<Task> act = async () => await modelBinder.BindModelAsync(bindingContextMock.Object);
|
||||
|
||||
await Assert.ThrowsAsync<FormatException>(act);
|
||||
await modelBinder.BindModelAsync(bindingContextMock.Object);
|
||||
Assert.True(bindingContextMock.Object.Result.IsModelSet);
|
||||
Assert.Empty((IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindModelAsync_ThrowsIfCommaDelimitedEnumArrayQueryIsInvalid2()
|
||||
public async Task BindModelAsync_EnumArrayQuery_BindValidOnly_2()
|
||||
{
|
||||
var queryParamName = "test";
|
||||
var queryParamString1 = "How";
|
||||
var queryParamString2 = "😱";
|
||||
var queryParamType = typeof(TestType[]);
|
||||
var queryParamType = typeof(IReadOnlyList<TestType>);
|
||||
|
||||
var modelBinder = new CommaDelimitedArrayModelBinder();
|
||||
var modelBinder = new CommaDelimitedArrayModelBinder(new NullLogger<CommaDelimitedArrayModelBinder>());
|
||||
|
||||
var valueProvider = new QueryStringValueProvider(
|
||||
new BindingSource(string.Empty, string.Empty, false, false),
|
||||
@@ -217,9 +218,9 @@ namespace Jellyfin.Api.Tests.ModelBinders
|
||||
bindingContextMock.Setup(b => b.ModelType).Returns(queryParamType);
|
||||
bindingContextMock.SetupProperty(b => b.Result);
|
||||
|
||||
Func<Task> act = async () => await modelBinder.BindModelAsync(bindingContextMock.Object);
|
||||
|
||||
await Assert.ThrowsAsync<FormatException>(act);
|
||||
await modelBinder.BindModelAsync(bindingContextMock.Object);
|
||||
Assert.True(bindingContextMock.Object.Result.IsModelSet);
|
||||
Assert.Single((IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Jellyfin.Api.Tests
|
||||
|
||||
// Assert
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal("application/json; charset=utf-8", response.Content.Headers.ContentType.ToString());
|
||||
Assert.Equal("application/json; charset=utf-8", response.Content.Headers.ContentType?.ToString());
|
||||
|
||||
// Write out for publishing
|
||||
var responseBody = await response.Content.ReadAsStringAsync();
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Jellyfin.Api.Tests
|
||||
{
|
||||
new Claim(ClaimTypes.Role, role),
|
||||
new Claim(ClaimTypes.Name, "jellyfin"),
|
||||
new Claim(InternalClaimTypes.UserId, Guid.Empty.ToString("N", CultureInfo.InvariantCulture)),
|
||||
new Claim(InternalClaimTypes.UserId, Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture)),
|
||||
new Claim(InternalClaimTypes.DeviceId, Guid.Empty.ToString("N", CultureInfo.InvariantCulture)),
|
||||
new Claim(InternalClaimTypes.Device, "test"),
|
||||
new Claim(InternalClaimTypes.Client, "test"),
|
||||
@@ -60,7 +60,7 @@ namespace Jellyfin.Api.Tests
|
||||
.Returns(user);
|
||||
|
||||
httpContextAccessorMock
|
||||
.Setup(h => h.HttpContext.Connection.RemoteIpAddress)
|
||||
.Setup(h => h.HttpContext!.Connection.RemoteIpAddress)
|
||||
.Returns(new IPAddress(0));
|
||||
|
||||
return new ClaimsPrincipal(identity);
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
||||
|
||||
@@ -11,82 +11,82 @@ namespace Jellyfin.Common.Tests.Json
|
||||
[Fact]
|
||||
public static void Deserialize_String_Valid_Success()
|
||||
{
|
||||
var desiredValue = new GenericBodyModel<string>
|
||||
var desiredValue = new GenericBodyArrayModel<string>
|
||||
{
|
||||
Value = new[] { "a", "b", "c" }
|
||||
};
|
||||
|
||||
var options = new JsonSerializerOptions();
|
||||
var value = JsonSerializer.Deserialize<GenericBodyModel<string>>(@"{ ""Value"": ""a,b,c"" }", options);
|
||||
var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": ""a,b,c"" }", options);
|
||||
Assert.Equal(desiredValue.Value, value?.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void Deserialize_String_Space_Valid_Success()
|
||||
{
|
||||
var desiredValue = new GenericBodyModel<string>
|
||||
var desiredValue = new GenericBodyArrayModel<string>
|
||||
{
|
||||
Value = new[] { "a", "b", "c" }
|
||||
};
|
||||
|
||||
var options = new JsonSerializerOptions();
|
||||
var value = JsonSerializer.Deserialize<GenericBodyModel<string>>(@"{ ""Value"": ""a, b, c"" }", options);
|
||||
var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": ""a, b, c"" }", options);
|
||||
Assert.Equal(desiredValue.Value, value?.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void Deserialize_GenericCommandType_Valid_Success()
|
||||
{
|
||||
var desiredValue = new GenericBodyModel<GeneralCommandType>
|
||||
var desiredValue = new GenericBodyArrayModel<GeneralCommandType>
|
||||
{
|
||||
Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown }
|
||||
};
|
||||
|
||||
var options = new JsonSerializerOptions();
|
||||
options.Converters.Add(new JsonStringEnumConverter());
|
||||
var value = JsonSerializer.Deserialize<GenericBodyModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,MoveDown"" }", options);
|
||||
var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,MoveDown"" }", options);
|
||||
Assert.Equal(desiredValue.Value, value?.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void Deserialize_GenericCommandType_Space_Valid_Success()
|
||||
{
|
||||
var desiredValue = new GenericBodyModel<GeneralCommandType>
|
||||
var desiredValue = new GenericBodyArrayModel<GeneralCommandType>
|
||||
{
|
||||
Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown }
|
||||
};
|
||||
|
||||
var options = new JsonSerializerOptions();
|
||||
options.Converters.Add(new JsonStringEnumConverter());
|
||||
var value = JsonSerializer.Deserialize<GenericBodyModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp, MoveDown"" }", options);
|
||||
var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp, MoveDown"" }", options);
|
||||
Assert.Equal(desiredValue.Value, value?.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void Deserialize_String_Array_Valid_Success()
|
||||
{
|
||||
var desiredValue = new GenericBodyModel<string>
|
||||
var desiredValue = new GenericBodyArrayModel<string>
|
||||
{
|
||||
Value = new[] { "a", "b", "c" }
|
||||
};
|
||||
|
||||
var options = new JsonSerializerOptions();
|
||||
var value = JsonSerializer.Deserialize<GenericBodyModel<string>>(@"{ ""Value"": [""a"",""b"",""c""] }", options);
|
||||
var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": [""a"",""b"",""c""] }", options);
|
||||
Assert.Equal(desiredValue.Value, value?.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void Deserialize_GenericCommandType_Array_Valid_Success()
|
||||
{
|
||||
var desiredValue = new GenericBodyModel<GeneralCommandType>
|
||||
var desiredValue = new GenericBodyArrayModel<GeneralCommandType>
|
||||
{
|
||||
Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown }
|
||||
};
|
||||
|
||||
var options = new JsonSerializerOptions();
|
||||
options.Converters.Add(new JsonStringEnumConverter());
|
||||
var value = JsonSerializer.Deserialize<GenericBodyModel<GeneralCommandType>>(@"{ ""Value"": [""MoveUp"", ""MoveDown""] }", options);
|
||||
var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": [""MoveUp"", ""MoveDown""] }", options);
|
||||
Assert.Equal(desiredValue.Value, value?.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Jellyfin.Common.Tests.Models;
|
||||
using MediaBrowser.Model.Session;
|
||||
using Xunit;
|
||||
|
||||
namespace Jellyfin.Common.Tests.Json
|
||||
{
|
||||
public static class JsonCommaDelimitedIReadOnlyListTests
|
||||
{
|
||||
[Fact]
|
||||
public static void Deserialize_String_Valid_Success()
|
||||
{
|
||||
var desiredValue = new GenericBodyIReadOnlyListModel<string>
|
||||
{
|
||||
Value = new[] { "a", "b", "c" }
|
||||
};
|
||||
|
||||
var options = new JsonSerializerOptions();
|
||||
var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": ""a,b,c"" }", options);
|
||||
Assert.Equal(desiredValue.Value, value?.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void Deserialize_String_Space_Valid_Success()
|
||||
{
|
||||
var desiredValue = new GenericBodyIReadOnlyListModel<string>
|
||||
{
|
||||
Value = new[] { "a", "b", "c" }
|
||||
};
|
||||
|
||||
var options = new JsonSerializerOptions();
|
||||
var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": ""a, b, c"" }", options);
|
||||
Assert.Equal(desiredValue.Value, value?.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void Deserialize_GenericCommandType_Valid_Success()
|
||||
{
|
||||
var desiredValue = new GenericBodyIReadOnlyListModel<GeneralCommandType>
|
||||
{
|
||||
Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown }
|
||||
};
|
||||
|
||||
var options = new JsonSerializerOptions();
|
||||
options.Converters.Add(new JsonStringEnumConverter());
|
||||
var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,MoveDown"" }", options);
|
||||
Assert.Equal(desiredValue.Value, value?.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void Deserialize_GenericCommandType_Space_Valid_Success()
|
||||
{
|
||||
var desiredValue = new GenericBodyIReadOnlyListModel<GeneralCommandType>
|
||||
{
|
||||
Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown }
|
||||
};
|
||||
|
||||
var options = new JsonSerializerOptions();
|
||||
options.Converters.Add(new JsonStringEnumConverter());
|
||||
var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp, MoveDown"" }", options);
|
||||
Assert.Equal(desiredValue.Value, value?.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void Deserialize_String_Array_Valid_Success()
|
||||
{
|
||||
var desiredValue = new GenericBodyIReadOnlyListModel<string>
|
||||
{
|
||||
Value = new[] { "a", "b", "c" }
|
||||
};
|
||||
|
||||
var options = new JsonSerializerOptions();
|
||||
var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<string>>(@"{ ""Value"": [""a"",""b"",""c""] }", options);
|
||||
Assert.Equal(desiredValue.Value, value?.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void Deserialize_GenericCommandType_Array_Valid_Success()
|
||||
{
|
||||
var desiredValue = new GenericBodyIReadOnlyListModel<GeneralCommandType>
|
||||
{
|
||||
Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown }
|
||||
};
|
||||
|
||||
var options = new JsonSerializerOptions();
|
||||
options.Converters.Add(new JsonStringEnumConverter());
|
||||
var value = JsonSerializer.Deserialize<GenericBodyIReadOnlyListModel<GeneralCommandType>>(@"{ ""Value"": [""MoveUp"", ""MoveDown""] }", options);
|
||||
Assert.Equal(desiredValue.Value, value?.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ namespace Jellyfin.Common.Tests.Models
|
||||
/// The generic body model.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The value type.</typeparam>
|
||||
public class GenericBodyModel<T>
|
||||
public class GenericBodyArrayModel<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the value.
|
||||
@@ -17,4 +17,4 @@ namespace Jellyfin.Common.Tests.Models
|
||||
[JsonConverter(typeof(JsonCommaDelimitedArrayConverterFactory))]
|
||||
public T[] Value { get; set; } = default!;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
using MediaBrowser.Common.Json.Converters;
|
||||
|
||||
namespace Jellyfin.Common.Tests.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// The generic body <c>IReadOnlyList</c> model.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The value type.</typeparam>
|
||||
public class GenericBodyIReadOnlyListModel<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the value.
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(JsonCommaDelimitedArrayConverterFactory))]
|
||||
public IReadOnlyList<T> Value { get; set; } = default!;
|
||||
}
|
||||
}
|
||||
@@ -6,14 +6,14 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Nullable>enable</Nullable>
|
||||
@@ -19,7 +19,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Nullable>enable</Nullable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Nullable>enable</Nullable>
|
||||
@@ -16,7 +16,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoFixture" Version="4.14.0" />
|
||||
<PackageReference Include="AutoFixture.AutoMoq" Version="4.14.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
|
||||
<PackageReference Include="Moq" Version="4.14.7" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
|
||||
Reference in New Issue
Block a user