| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 | using System;using System.Collections.Generic;using System.Globalization;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;namespace Jellyfin.Api.Tests.ModelBinders{    public sealed class CommaDelimitedArrayModelBinderTests    {        [Fact]        public async Task BindModelAsync_CorrectlyBindsValidCommaDelimitedStringArrayQuery()        {            var queryParamName = "test";            IReadOnlyList<string> queryParamValues = new[] { "lol", "xd" };            var queryParamString = "lol,xd";            var queryParamType = typeof(string[]);            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) } }),                    CultureInfo.InvariantCulture);            var bindingContextMock = new Mock<ModelBindingContext>();            bindingContextMock.Setup(b => b.ValueProvider).Returns(valueProvider);            bindingContextMock.Setup(b => b.ModelName).Returns(queryParamName);            bindingContextMock.Setup(b => b.ModelType).Returns(queryParamType);            bindingContextMock.SetupProperty(b => b.Result);            await modelBinder.BindModelAsync(bindingContextMock.Object);            Assert.True(bindingContextMock.Object.Result.IsModelSet);            Assert.Equal((IReadOnlyList<string>?)bindingContextMock.Object?.Result.Model, queryParamValues);        }        [Fact]        public async Task BindModelAsync_CorrectlyBindsValidCommaDelimitedIntArrayQuery()        {            var queryParamName = "test";            IReadOnlyList<int> queryParamValues = new[] { 42, 0 };            var queryParamString = "42,0";            var queryParamType = typeof(int[]);            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) } }),                    CultureInfo.InvariantCulture);            var bindingContextMock = new Mock<ModelBindingContext>();            bindingContextMock.Setup(b => b.ValueProvider).Returns(valueProvider);            bindingContextMock.Setup(b => b.ModelName).Returns(queryParamName);            bindingContextMock.Setup(b => b.ModelType).Returns(queryParamType);            bindingContextMock.SetupProperty(b => b.Result);            await modelBinder.BindModelAsync(bindingContextMock.Object);            Assert.True(bindingContextMock.Object.Result.IsModelSet);            Assert.Equal((IReadOnlyList<int>?)bindingContextMock.Object.Result.Model, queryParamValues);        }        [Fact]        public async Task BindModelAsync_CorrectlyBindsValidCommaDelimitedEnumArrayQuery()        {            var queryParamName = "test";            IReadOnlyList<TestType> queryParamValues = new[] { TestType.How, TestType.Much };            var queryParamString = "How,Much";            var queryParamType = typeof(TestType[]);            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) } }),                    CultureInfo.InvariantCulture);            var bindingContextMock = new Mock<ModelBindingContext>();            bindingContextMock.Setup(b => b.ValueProvider).Returns(valueProvider);            bindingContextMock.Setup(b => b.ModelName).Returns(queryParamName);            bindingContextMock.Setup(b => b.ModelType).Returns(queryParamType);            bindingContextMock.SetupProperty(b => b.Result);            await modelBinder.BindModelAsync(bindingContextMock.Object);            Assert.True(bindingContextMock.Object.Result.IsModelSet);            Assert.Equal((IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model, queryParamValues);        }        [Fact]        public async Task BindModelAsync_CorrectlyBindsValidCommaDelimitedEnumArrayQueryWithDoubleCommas()        {            var queryParamName = "test";            IReadOnlyList<TestType> queryParamValues = new[] { TestType.How, TestType.Much };            var queryParamString = "How,,Much";            var queryParamType = typeof(TestType[]);            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) } }),                    CultureInfo.InvariantCulture);            var bindingContextMock = new Mock<ModelBindingContext>();            bindingContextMock.Setup(b => b.ValueProvider).Returns(valueProvider);            bindingContextMock.Setup(b => b.ModelName).Returns(queryParamName);            bindingContextMock.Setup(b => b.ModelType).Returns(queryParamType);            bindingContextMock.SetupProperty(b => b.Result);            await modelBinder.BindModelAsync(bindingContextMock.Object);            Assert.True(bindingContextMock.Object.Result.IsModelSet);            Assert.Equal((IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model, queryParamValues);        }        [Fact]        public async Task BindModelAsync_CorrectlyBindsValidEnumArrayQuery()        {            var queryParamName = "test";            IReadOnlyList<TestType> queryParamValues = new[] { TestType.How, TestType.Much };            var queryParamString1 = "How";            var queryParamString2 = "Much";            var queryParamType = typeof(TestType[]);            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(new[] { queryParamString1, queryParamString2 }) },                    }),                    CultureInfo.InvariantCulture);            var bindingContextMock = new Mock<ModelBindingContext>();            bindingContextMock.Setup(b => b.ValueProvider).Returns(valueProvider);            bindingContextMock.Setup(b => b.ModelName).Returns(queryParamName);            bindingContextMock.Setup(b => b.ModelType).Returns(queryParamType);            bindingContextMock.SetupProperty(b => b.Result);            await modelBinder.BindModelAsync(bindingContextMock.Object);            Assert.True(bindingContextMock.Object.Result.IsModelSet);            Assert.Equal((IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model, queryParamValues);        }        [Fact]        public async Task BindModelAsync_CorrectlyBindsEmptyEnumArrayQuery()        {            var queryParamName = "test";            IReadOnlyList<TestType> queryParamValues = Array.Empty<TestType>();            var queryParamType = typeof(TestType[]);            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(value: null) },                    }),                    CultureInfo.InvariantCulture);            var bindingContextMock = new Mock<ModelBindingContext>();            bindingContextMock.Setup(b => b.ValueProvider).Returns(valueProvider);            bindingContextMock.Setup(b => b.ModelName).Returns(queryParamName);            bindingContextMock.Setup(b => b.ModelType).Returns(queryParamType);            bindingContextMock.SetupProperty(b => b.Result);            await modelBinder.BindModelAsync(bindingContextMock.Object);            Assert.True(bindingContextMock.Object.Result.IsModelSet);            Assert.Equal((IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model, queryParamValues);        }        [Fact]        public async Task BindModelAsync_EnumArrayQuery_BindValidOnly()        {            var queryParamName = "test";            var queryParamString = "🔥,😢";            var queryParamType = typeof(IReadOnlyList<TestType>);            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) } }),                    CultureInfo.InvariantCulture);            var bindingContextMock = new Mock<ModelBindingContext>();            bindingContextMock.Setup(b => b.ValueProvider).Returns(valueProvider);            bindingContextMock.Setup(b => b.ModelName).Returns(queryParamName);            bindingContextMock.Setup(b => b.ModelType).Returns(queryParamType);            bindingContextMock.SetupProperty(b => b.Result);            await modelBinder.BindModelAsync(bindingContextMock.Object);            Assert.True(bindingContextMock.Object.Result.IsModelSet);            var listResult = (IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model;            Assert.NotNull(listResult);            Assert.Empty(listResult);        }        [Fact]        public async Task BindModelAsync_EnumArrayQuery_BindValidOnly_2()        {            var queryParamName = "test";            var queryParamString1 = "How";            var queryParamString2 = "😱";            var queryParamType = typeof(IReadOnlyList<TestType>);            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(new[] { queryParamString1, queryParamString2 }) },                    }),                    CultureInfo.InvariantCulture);            var bindingContextMock = new Mock<ModelBindingContext>();            bindingContextMock.Setup(b => b.ValueProvider).Returns(valueProvider);            bindingContextMock.Setup(b => b.ModelName).Returns(queryParamName);            bindingContextMock.Setup(b => b.ModelType).Returns(queryParamType);            bindingContextMock.SetupProperty(b => b.Result);            await modelBinder.BindModelAsync(bindingContextMock.Object);            Assert.True(bindingContextMock.Object.Result.IsModelSet);            var listResult = (IReadOnlyList<TestType>?)bindingContextMock.Object.Result.Model;            Assert.NotNull(listResult);            Assert.Single(listResult);        }    }}
 |