diff options
| author | Marc Brooks <IDisposable@gmail.com> | 2025-02-03 19:48:59 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-03 19:48:59 -0600 |
| commit | e8cbcde02ebd930a5eeb6c95e0875a9e30acb3e8 (patch) | |
| tree | 2ecd43f232012c8f037f4cd6fee4168e46d01aa3 /tests | |
| parent | 6dc61a430ba3a8480399309f277e5debfd6403ba (diff) | |
| parent | d376b5fbc7cf3ae7440a606a9e885d70605956bd (diff) | |
Merge branch 'master' into sort-nfo-data
Diffstat (limited to 'tests')
38 files changed, 188 insertions, 242 deletions
diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props index bec3481cb..6b851021f 100644 --- a/tests/Directory.Build.props +++ b/tests/Directory.Build.props @@ -4,9 +4,8 @@ <Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" /> <PropertyGroup> - <TargetFramework>net8.0</TargetFramework> + <TargetFramework>net9.0</TargetFramework> <IsPackable>false</IsPackable> - <CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)/jellyfin-tests.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <!-- Code Analyzers --> diff --git a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonBoolNumberTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonBoolNumberTests.cs index 125229ff9..d58a62cc8 100644 --- a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonBoolNumberTests.cs +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonBoolNumberTests.cs @@ -1,5 +1,6 @@ using System.Text.Json; using FsCheck; +using FsCheck.Fluent; using FsCheck.Xunit; using Jellyfin.Extensions.Json.Converters; using Xunit; diff --git a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs index 61105b42b..d247b8cb1 100644 --- a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs @@ -41,7 +41,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters { var desiredValue = new GenericBodyArrayModel<string> { - Value = new[] { "a", "b", "c" } + Value = ["a", "b", "c"] }; var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": ""a,b,c"" }", _jsonOptions); @@ -53,7 +53,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters { var desiredValue = new GenericBodyArrayModel<string> { - Value = new[] { "a", "b", "c" } + Value = ["a", "b", "c"] }; var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": ""a, b, c"" }", _jsonOptions); @@ -65,7 +65,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters { var desiredValue = new GenericBodyArrayModel<GeneralCommandType> { - Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } + Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown] }; var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,MoveDown"" }", _jsonOptions); @@ -77,7 +77,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters { var desiredValue = new GenericBodyArrayModel<GeneralCommandType> { - Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } + Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown] }; var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,,MoveDown"" }", _jsonOptions); @@ -89,10 +89,10 @@ namespace Jellyfin.Extensions.Tests.Json.Converters { var desiredValue = new GenericBodyArrayModel<GeneralCommandType> { - Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } + Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown] }; - var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,TotallyNotAVallidCommand,MoveDown"" }", _jsonOptions); + var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,TotallyNotAValidCommand,MoveDown"" }", _jsonOptions); Assert.Equal(desiredValue.Value, value?.Value); } @@ -101,7 +101,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters { var desiredValue = new GenericBodyArrayModel<GeneralCommandType> { - Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } + Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown] }; var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp, MoveDown"" }", _jsonOptions); @@ -113,7 +113,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters { var desiredValue = new GenericBodyArrayModel<string> { - Value = new[] { "a", "b", "c" } + Value = ["a", "b", "c"] }; var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": [""a"",""b"",""c""] }", _jsonOptions); @@ -125,7 +125,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters { var desiredValue = new GenericBodyArrayModel<GeneralCommandType> { - Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } + Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown] }; var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": [""MoveUp"", ""MoveDown""] }", _jsonOptions); diff --git a/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyArrayModel.cs b/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyArrayModel.cs index ef135278f..76669ea19 100644 --- a/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyArrayModel.cs +++ b/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyArrayModel.cs @@ -8,7 +8,7 @@ namespace Jellyfin.Extensions.Tests.Json.Models /// The generic body model. /// </summary> /// <typeparam name="T">The value type.</typeparam> - public class GenericBodyArrayModel<T> + public sealed class GenericBodyArrayModel<T> { /// <summary> /// Gets or sets the value. diff --git a/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyIReadOnlyListModel.cs b/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyIReadOnlyListModel.cs index 8e7b5a35b..7e6b97afe 100644 --- a/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyIReadOnlyListModel.cs +++ b/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyIReadOnlyListModel.cs @@ -8,7 +8,7 @@ namespace Jellyfin.Extensions.Tests.Json.Models /// The generic body <c>IReadOnlyList</c> model. /// </summary> /// <typeparam name="T">The value type.</typeparam> - public class GenericBodyIReadOnlyListModel<T> + public sealed class GenericBodyIReadOnlyListModel<T> { /// <summary> /// Gets or sets the value. diff --git a/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs b/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs index 69d20bd3f..028f12afa 100644 --- a/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs +++ b/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs @@ -6,8 +6,8 @@ namespace Jellyfin.Extensions.Tests public class StringExtensionsTests { [Theory] - [InlineData("", "")] // Identity edge-case (no diactritics) - [InlineData("Indiana Jones", "Indiana Jones")] // Identity (no diactritics) + [InlineData("", "")] // Identity edge-case (no diacritics) + [InlineData("Indiana Jones", "Indiana Jones")] // Identity (no diacritics) [InlineData("a\ud800b", "ab")] // Invalid UTF-16 char stripping [InlineData("åäö", "aao")] // Issue #7484 [InlineData("Jön", "Jon")] // Issue #7484 @@ -25,8 +25,8 @@ namespace Jellyfin.Extensions.Tests } [Theory] - [InlineData("", false)] // Identity edge-case (no diactritics) - [InlineData("Indiana Jones", false)] // Identity (no diactritics) + [InlineData("", false)] // Identity edge-case (no diacritics) + [InlineData("Indiana Jones", false)] // Identity (no diacritics) [InlineData("a\ud800b", true)] // Invalid UTF-16 char stripping [InlineData("åäö", true)] // Issue #7484 [InlineData("Jön", true)] // Issue #7484 diff --git a/tests/Jellyfin.LiveTv.Tests/Jellyfin.LiveTv.Tests.csproj b/tests/Jellyfin.LiveTv.Tests/Jellyfin.LiveTv.Tests.csproj index cf967b84c..fdcf7d61e 100644 --- a/tests/Jellyfin.LiveTv.Tests/Jellyfin.LiveTv.Tests.csproj +++ b/tests/Jellyfin.LiveTv.Tests/Jellyfin.LiveTv.Tests.csproj @@ -1,6 +1,6 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>net8.0</TargetFramework> + <TargetFramework>net9.0</TargetFramework> </PropertyGroup> <ItemGroup> @@ -22,7 +22,7 @@ <PackageReference Include="Xunit.SkippableFact" /> <PackageReference Include="coverlet.collector" /> </ItemGroup> - + <ItemGroup> <ProjectReference Include="..\..\src\Jellyfin.LiveTv\Jellyfin.LiveTv.csproj" /> </ItemGroup> diff --git a/tests/Jellyfin.LiveTv.Tests/Listings/ListingsManagerTests.cs b/tests/Jellyfin.LiveTv.Tests/Listings/ListingsManagerTests.cs new file mode 100644 index 000000000..40934d9c6 --- /dev/null +++ b/tests/Jellyfin.LiveTv.Tests/Listings/ListingsManagerTests.cs @@ -0,0 +1,50 @@ +using System; +using Jellyfin.LiveTv.Configuration; +using Jellyfin.LiveTv.Listings; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Model.LiveTv; +using MediaBrowser.Model.Tasks; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Jellyfin.LiveTv.Tests.Listings; + +public class ListingsManagerTests +{ + private readonly IConfigurationManager _config; + private readonly IListingsProvider[] _listingsProviders; + private readonly ILogger<ListingsManager> _logger; + private readonly ITaskManager _taskManager; + private readonly ITunerHostManager _tunerHostManager; + + public ListingsManagerTests() + { + _logger = Mock.Of<ILogger<ListingsManager>>(); + _config = Mock.Of<IConfigurationManager>(); + _taskManager = Mock.Of<ITaskManager>(); + _tunerHostManager = Mock.Of<ITunerHostManager>(); + _listingsProviders = new[] { Mock.Of<IListingsProvider>() }; + } + + [Fact] + public void DeleteListingsProvider_DeletesProvider() + { + // Arrange + var id = "MockId"; + var manager = new ListingsManager(_logger, _config, _taskManager, _tunerHostManager, _listingsProviders); + + Mock.Get(_config) + .Setup(x => x.GetConfiguration(It.IsAny<string>())) + .Returns(new LiveTvOptions { ListingProviders = [new ListingsProviderInfo { Id = id }] }); + + // Act + manager.DeleteListingsProvider(id); + + // Assert + Assert.DoesNotContain( + _config.GetLiveTvConfiguration().ListingProviders, + p => p.Id.Equals(id, StringComparison.Ordinal)); + } +} diff --git a/tests/Jellyfin.LiveTv.Tests/SchedulesDirect/SchedulesDirectDeserializeTests.cs b/tests/Jellyfin.LiveTv.Tests/SchedulesDirect/SchedulesDirectDeserializeTests.cs index 6975d56d9..59cd42c05 100644 --- a/tests/Jellyfin.LiveTv.Tests/SchedulesDirect/SchedulesDirectDeserializeTests.cs +++ b/tests/Jellyfin.LiveTv.Tests/SchedulesDirect/SchedulesDirectDeserializeTests.cs @@ -232,7 +232,7 @@ namespace Jellyfin.LiveTv.Tests.SchedulesDirect Assert.Equal(2, channelDto!.Map.Count); Assert.Equal("24326", channelDto.Map[0].StationId); Assert.Equal("001", channelDto.Map[0].Channel); - Assert.Equal("BBC ONE South", channelDto.Map[0].ProvderCallsign); + Assert.Equal("BBC ONE South", channelDto.Map[0].ProviderCallsign); Assert.Equal("1", channelDto.Map[0].LogicalChannelNumber); Assert.Equal("providerCallsign", channelDto.Map[0].MatchType); } diff --git a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs index df51d39cb..61282785f 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs @@ -65,7 +65,7 @@ namespace Jellyfin.MediaEncoding.Tests.Probing Assert.True(res.VideoStream.IsDefault); Assert.False(res.VideoStream.IsExternal); Assert.False(res.VideoStream.IsForced); - Assert.False(res.VideoStream.IsHearingImpaired); + Assert.False(res.VideoStream.IsHearingImpaired.GetValueOrDefault()); Assert.False(res.VideoStream.IsInterlaced); Assert.False(res.VideoStream.IsTextSubtitleStream); Assert.Equal(13d, res.VideoStream.Level); @@ -152,19 +152,19 @@ namespace Jellyfin.MediaEncoding.Tests.Probing Assert.Equal(MediaStreamType.Subtitle, res.MediaStreams[3].Type); Assert.Equal("DVDSUB", res.MediaStreams[3].Codec); Assert.Null(res.MediaStreams[3].Title); - Assert.False(res.MediaStreams[3].IsHearingImpaired); + Assert.False(res.MediaStreams[3].IsHearingImpaired.GetValueOrDefault()); Assert.Equal("eng", res.MediaStreams[4].Language); Assert.Equal(MediaStreamType.Subtitle, res.MediaStreams[4].Type); Assert.Equal("mov_text", res.MediaStreams[4].Codec); Assert.Null(res.MediaStreams[4].Title); - Assert.True(res.MediaStreams[4].IsHearingImpaired); + Assert.True(res.MediaStreams[4].IsHearingImpaired.GetValueOrDefault()); Assert.Equal("eng", res.MediaStreams[5].Language); Assert.Equal(MediaStreamType.Subtitle, res.MediaStreams[5].Type); Assert.Equal("mov_text", res.MediaStreams[5].Codec); Assert.Equal("Commentary", res.MediaStreams[5].Title); - Assert.False(res.MediaStreams[5].IsHearingImpaired); + Assert.False(res.MediaStreams[5].IsHearingImpaired.GetValueOrDefault()); } [Fact] diff --git a/tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs b/tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs index 0a4e060df..c710df082 100644 --- a/tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs +++ b/tests/Jellyfin.Model.Tests/Extensions/StringHelperTests.cs @@ -1,5 +1,6 @@ using System; using FsCheck; +using FsCheck.Fluent; using FsCheck.Xunit; using MediaBrowser.Model.Extensions; using Xunit; diff --git a/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs b/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs index 406381f14..7bfab570b 100644 --- a/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs +++ b/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs @@ -77,6 +77,8 @@ namespace Jellyfin.Naming.Tests.TV [InlineData("Season 3/The Series S3 E9 - The title.avi", 9)] [InlineData("Season 3/S003 E009.avi", 9)] [InlineData("Season 3/Season 3 Episode 9.avi", 9)] + [InlineData("[VCB-Studio] Re Zero kara Hajimeru Isekai Seikatsu [21][Ma10p_1080p][x265_flac].mkv", 21)] + [InlineData("[CASO&Sumisora][Oda_Nobuna_no_Yabou][04][BDRIP][1920x1080][x264_AAC][7620E503].mp4", 4)] // [InlineData("Case Closed (1996-2007)/Case Closed - 317.mkv", 317)] // triple digit episode number // TODO: [InlineData("Season 2/16 12 Some Title.avi", 16)] diff --git a/tests/Jellyfin.Naming.Tests/TV/TvParserHelpersTest.cs b/tests/Jellyfin.Naming.Tests/TV/TvParserHelpersTest.cs index 2d4b5b730..5dd004408 100644 --- a/tests/Jellyfin.Naming.Tests/TV/TvParserHelpersTest.cs +++ b/tests/Jellyfin.Naming.Tests/TV/TvParserHelpersTest.cs @@ -15,17 +15,17 @@ public class TvParserHelpersTest [InlineData("Unreleased", SeriesStatus.Unreleased)] public void SeriesStatusParserTest_Valid(string statusString, SeriesStatus? status) { - var successful = TvParserHelpers.TryParseSeriesStatus(statusString, out var parsered); + var successful = TvParserHelpers.TryParseSeriesStatus(statusString, out var parsed); Assert.True(successful); - Assert.Equal(status, parsered); + Assert.Equal(status, parsed); } [Theory] [InlineData("XXX")] public void SeriesStatusParserTest_InValid(string statusString) { - var successful = TvParserHelpers.TryParseSeriesStatus(statusString, out var parsered); + var successful = TvParserHelpers.TryParseSeriesStatus(statusString, out var parsed); Assert.False(successful); - Assert.Null(parsered); + Assert.Null(parsed); } } diff --git a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs index 3005a4416..6b1398695 100644 --- a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs @@ -25,8 +25,8 @@ namespace Jellyfin.Naming.Tests.Video files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); - Assert.Single(result.Where(v => v.ExtraType is null)); - Assert.Single(result.Where(v => v.ExtraType is not null)); + Assert.Single(result, v => v.ExtraType is null); + Assert.Single(result, v => v.ExtraType is not null); } [Fact] @@ -44,8 +44,8 @@ namespace Jellyfin.Naming.Tests.Video files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); - Assert.Single(result.Where(v => v.ExtraType is null)); - Assert.Single(result.Where(v => v.ExtraType is not null)); + Assert.Single(result, v => v.ExtraType is null); + Assert.Single(result, v => v.ExtraType is not null); Assert.Equal(2, result[0].AlternateVersions.Count); } diff --git a/tests/Jellyfin.Networking.Tests/NetworkExtensionsTests.cs b/tests/Jellyfin.Networking.Tests/NetworkExtensionsTests.cs index 01546aa2b..4ebd54786 100644 --- a/tests/Jellyfin.Networking.Tests/NetworkExtensionsTests.cs +++ b/tests/Jellyfin.Networking.Tests/NetworkExtensionsTests.cs @@ -1,4 +1,5 @@ using FsCheck; +using FsCheck.Fluent; using FsCheck.Xunit; using MediaBrowser.Common.Net; using Xunit; diff --git a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs index 3b7c43100..4144300da 100644 --- a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs +++ b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs @@ -238,7 +238,7 @@ namespace Jellyfin.Networking.Tests // User on external network, internal binding only - so assumption is a proxy forward, return external override. [InlineData("jellyfin.org", "192.168.1.0/24", "eth16", false, "external=http://helloworld.com", "http://helloworld.com")] - // User on external network, no binding - so result is the 1st external which is overriden. + // User on external network, no binding - so result is the 1st external which is overridden. [InlineData("jellyfin.org", "192.168.1.0/24", "", false, "external=http://helloworld.com", "http://helloworld.com")] // User assumed to be internal, no binding - so result is the 1st matching interface. diff --git a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs index 0c7d2487c..1ec859223 100644 --- a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs +++ b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs @@ -5,6 +5,7 @@ using System.IO; using System.Linq; using System.Net; using System.Net.Http; +using System.Net.Mime; using System.Text; using System.Text.RegularExpressions; using System.Threading; @@ -292,6 +293,9 @@ namespace Jellyfin.Providers.Tests.Manager providerManager.Setup(pm => pm.SaveImage(item, It.IsAny<Stream>(), It.IsAny<string>(), imageType, null, It.IsAny<CancellationToken>())) .Callback<BaseItem, Stream, string, ImageType, int?, CancellationToken>((callbackItem, _, _, callbackType, _, _) => callbackItem.SetImagePath(callbackType, 0, new FileSystemMetadata())) .Returns(Task.CompletedTask); + providerManager.Setup(pm => pm.SaveImage(item, It.IsAny<string>(), It.IsAny<string>(), imageType, null, null, It.IsAny<CancellationToken>())) + .Callback<BaseItem, string, string, ImageType, int?, bool?, CancellationToken>((callbackItem, _, _, callbackType, _, _, _) => callbackItem.SetImagePath(callbackType, 0, new FileSystemMetadata())) + .Returns(Task.CompletedTask); var itemImageProvider = GetItemImageProvider(providerManager.Object, null); var result = await itemImageProvider.RefreshImages(item, libraryOptions, new List<IImageProvider> { dynamicProvider.Object }, refreshOptions, CancellationToken.None); @@ -388,7 +392,7 @@ namespace Jellyfin.Providers.Tests.Manager { ReasonPhrase = url, StatusCode = HttpStatusCode.OK, - Content = new StringContent(Content, Encoding.UTF8, "image/jpeg") + Content = new StringContent(Content, Encoding.UTF8, MediaTypeNames.Image.Jpeg) }); var refreshOptions = fullRefresh diff --git a/tests/Jellyfin.Providers.Tests/Manager/MetadataServiceTests.cs b/tests/Jellyfin.Providers.Tests/Manager/MetadataServiceTests.cs index cedcaf9c0..b32ecf6ec 100644 --- a/tests/Jellyfin.Providers.Tests/Manager/MetadataServiceTests.cs +++ b/tests/Jellyfin.Providers.Tests/Manager/MetadataServiceTests.cs @@ -330,7 +330,7 @@ namespace Jellyfin.Providers.Tests.Manager MetadataService<Movie, MovieInfo>.MergeBaseItemData(source, target, lockedFields, replaceData, false); actualValue = target.People; - return newValue?.Equals(actualValue) ?? actualValue is null; + return newValue?.SequenceEqual((IEnumerable<PersonInfo>)actualValue!) ?? actualValue is null; } /// <summary> diff --git a/tests/Jellyfin.Providers.Tests/Omdb/JsonOmdbConverterTests.cs b/tests/Jellyfin.Providers.Tests/Omdb/JsonOmdbConverterTests.cs index eed9eedc7..3062cb7b4 100644 --- a/tests/Jellyfin.Providers.Tests/Omdb/JsonOmdbConverterTests.cs +++ b/tests/Jellyfin.Providers.Tests/Omdb/JsonOmdbConverterTests.cs @@ -31,7 +31,7 @@ namespace Jellyfin.Providers.Tests.Omdb [Theory] [InlineData("\"N/A\"")] [InlineData("null")] - public void Deserialization_To_Nullable_Int_Shoud_Be_Null(string input) + public void Deserialization_To_Nullable_Int_Should_Be_Null(string input) { var result = JsonSerializer.Deserialize<int?>(input, _options); Assert.Null(result); @@ -49,7 +49,7 @@ namespace Jellyfin.Providers.Tests.Omdb [Theory] [InlineData("\"N/A\"")] [InlineData("null")] - public void Deserialization_To_Nullable_String_Shoud_Be_Null(string input) + public void Deserialization_To_Nullable_String_Should_Be_Null(string input) { var result = JsonSerializer.Deserialize<string?>(input, _options); Assert.Null(result); diff --git a/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs index 0d2b488bc..105f5d7af 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs @@ -3,8 +3,10 @@ using System.Collections.Generic; using AutoFixture; using AutoFixture.AutoMoq; using Emby.Server.Implementations.Data; +using Jellyfin.Server.Implementations.Item; using MediaBrowser.Controller; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Entities; using Microsoft.Extensions.Configuration; using Moq; @@ -18,7 +20,7 @@ namespace Jellyfin.Server.Implementations.Tests.Data public const string MetaDataPath = "/meta/data/path"; private readonly IFixture _fixture; - private readonly SqliteItemRepository _sqliteItemRepository; + private readonly BaseItemRepository _sqliteItemRepository; public SqliteItemRepositoryTests() { @@ -40,7 +42,7 @@ namespace Jellyfin.Server.Implementations.Tests.Data _fixture = new Fixture().Customize(new AutoMoqCustomization { ConfigureMembers = true }); _fixture.Inject(appHost); _fixture.Inject(config); - _sqliteItemRepository = _fixture.Create<SqliteItemRepository>(); + _sqliteItemRepository = _fixture.Create<BaseItemRepository>(); } public static TheoryData<string, ItemImageInfo> ItemImageInfoFromValueString_Valid_TestData() @@ -97,31 +99,6 @@ namespace Jellyfin.Server.Implementations.Tests.Data return data; } - [Theory] - [MemberData(nameof(ItemImageInfoFromValueString_Valid_TestData))] - public void ItemImageInfoFromValueString_Valid_Success(string value, ItemImageInfo expected) - { - var result = _sqliteItemRepository.ItemImageInfoFromValueString(value); - Assert.Equal(expected.Path, result.Path); - Assert.Equal(expected.Type, result.Type); - Assert.Equal(expected.DateModified, result.DateModified); - Assert.Equal(expected.Width, result.Width); - Assert.Equal(expected.Height, result.Height); - Assert.Equal(expected.BlurHash, result.BlurHash); - } - - [Theory] - [InlineData("")] - [InlineData("*")] - [InlineData("https://image.tmdb.org/t/p/original/zhB5CHEgqqh4wnEqDNJLfWXJlcL.jpg*0")] - [InlineData("/mnt/series/Family Guy/Season 1/Family Guy - S01E01-thumb.jpg*6374520964785129080*WjQbtJtSO8nhNZ%L_Io#R/oaS<o}-;adXAoIn7j[%hW9s:WGw[nN")] // Invalid modified date - [InlineData("/mnt/series/Family Guy/Season 1/Family Guy - S01E01-thumb.jpg*-637452096478512963*WjQbtJtSO8nhNZ%L_Io#R/oaS<o}-;adXAoIn7j[%hW9s:WGw[nN")] // Negative modified date - [InlineData("/mnt/series/Family Guy/Season 1/Family Guy - S01E01-thumb.jpg*637452096478512963*Invalid*1920*1080*WjQbtJtSO8nhNZ%L_Io#R/oaS6o}-;adXAoIn7j[%hW9s:WGw[nN")] // Invalid type - public void ItemImageInfoFromValueString_Invalid_Null(string value) - { - Assert.Null(_sqliteItemRepository.ItemImageInfoFromValueString(value)); - } - public static TheoryData<string, ItemImageInfo[]> DeserializeImages_Valid_TestData() { var data = new TheoryData<string, ItemImageInfo[]>(); @@ -202,97 +179,6 @@ namespace Jellyfin.Server.Implementations.Tests.Data return data; } - [Theory] - [MemberData(nameof(DeserializeImages_Valid_TestData))] - public void DeserializeImages_Valid_Success(string value, ItemImageInfo[] expected) - { - var result = _sqliteItemRepository.DeserializeImages(value); - Assert.Equal(expected.Length, result.Length); - for (int i = 0; i < expected.Length; i++) - { - Assert.Equal(expected[i].Path, result[i].Path); - Assert.Equal(expected[i].Type, result[i].Type); - Assert.Equal(expected[i].DateModified, result[i].DateModified); - Assert.Equal(expected[i].Width, result[i].Width); - Assert.Equal(expected[i].Height, result[i].Height); - Assert.Equal(expected[i].BlurHash, result[i].BlurHash); - } - } - - [Theory] - [MemberData(nameof(DeserializeImages_ValidAndInvalid_TestData))] - public void DeserializeImages_ValidAndInvalid_Success(string value, ItemImageInfo[] expected) - { - var result = _sqliteItemRepository.DeserializeImages(value); - Assert.Equal(expected.Length, result.Length); - for (int i = 0; i < expected.Length; i++) - { - Assert.Equal(expected[i].Path, result[i].Path); - Assert.Equal(expected[i].Type, result[i].Type); - Assert.Equal(expected[i].DateModified, result[i].DateModified); - Assert.Equal(expected[i].Width, result[i].Width); - Assert.Equal(expected[i].Height, result[i].Height); - Assert.Equal(expected[i].BlurHash, result[i].BlurHash); - } - } - - [Theory] - [MemberData(nameof(DeserializeImages_Valid_TestData))] - public void SerializeImages_Valid_Success(string expected, ItemImageInfo[] value) - { - Assert.Equal(expected, _sqliteItemRepository.SerializeImages(value)); - } - - public static TheoryData<string, Dictionary<string, string>> DeserializeProviderIds_Valid_TestData() - { - var data = new TheoryData<string, Dictionary<string, string>>(); - - data.Add( - "Imdb=tt0119567", - new Dictionary<string, string>() - { - { "Imdb", "tt0119567" }, - }); - - data.Add( - "Imdb=tt0119567|Tmdb=330|TmdbCollection=328", - new Dictionary<string, string>() - { - { "Imdb", "tt0119567" }, - { "Tmdb", "330" }, - { "TmdbCollection", "328" }, - }); - - data.Add( - "MusicBrainzAlbum=9d363e43-f24f-4b39-bc5a-7ef305c677c7|MusicBrainzReleaseGroup=63eba062-847c-3b73-8b0f-6baf27bba6fa|AudioDbArtist=111352|AudioDbAlbum=2116560|MusicBrainzAlbumArtist=20244d07-534f-4eff-b4d4-930878889970", - new Dictionary<string, string>() - { - { "MusicBrainzAlbum", "9d363e43-f24f-4b39-bc5a-7ef305c677c7" }, - { "MusicBrainzReleaseGroup", "63eba062-847c-3b73-8b0f-6baf27bba6fa" }, - { "AudioDbArtist", "111352" }, - { "AudioDbAlbum", "2116560" }, - { "MusicBrainzAlbumArtist", "20244d07-534f-4eff-b4d4-930878889970" }, - }); - - return data; - } - - [Theory] - [MemberData(nameof(DeserializeProviderIds_Valid_TestData))] - public void DeserializeProviderIds_Valid_Success(string value, Dictionary<string, string> expected) - { - var result = new ProviderIdsExtensionsTestsObject(); - SqliteItemRepository.DeserializeProviderIds(value, result); - Assert.Equal(expected, result.ProviderIds); - } - - [Theory] - [MemberData(nameof(DeserializeProviderIds_Valid_TestData))] - public void SerializeProviderIds_Valid_Success(string expected, Dictionary<string, string> values) - { - Assert.Equal(expected, SqliteItemRepository.SerializeProviderIds(values)); - } - private sealed class ProviderIdsExtensionsTestsObject : IHasProviderIds { public Dictionary<string, string> ProviderIds { get; set; } = new Dictionary<string, string>(); diff --git a/tests/Jellyfin.Server.Implementations.Tests/EfMigrations/EfMigrationTests.cs b/tests/Jellyfin.Server.Implementations.Tests/EfMigrations/EfMigrationTests.cs new file mode 100644 index 000000000..e6ccae183 --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/EfMigrations/EfMigrationTests.cs @@ -0,0 +1,18 @@ +using System; +using System.Threading.Tasks; +using Jellyfin.Server.Implementations.Migrations; +using Microsoft.EntityFrameworkCore; +using Xunit; + +namespace Jellyfin.Server.Implementations.Tests.EfMigrations; + +public class EfMigrationTests +{ + [Fact] + public void CheckForUnappliedMigrations() + { + var dbDesignContext = new DesignTimeJellyfinDbFactory(); + var context = dbDesignContext.CreateDbContext([]); + Assert.False(context.Database.HasPendingModelChanges(), "There are unapplied changes to the EfCore model. Please create a Migration."); + } +} diff --git a/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs index 0afbf7e63..65f018ee3 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs @@ -84,7 +84,7 @@ namespace Jellyfin.Server.Implementations.Tests.Localization await localizationManager.LoadAll(); var ratings = localizationManager.GetParentalRatings().ToList(); - Assert.Equal(54, ratings.Count); + Assert.Equal(56, ratings.Count); var tvma = ratings.FirstOrDefault(x => x.Name.Equals("TV-MA", StringComparison.Ordinal)); Assert.NotNull(tvma); diff --git a/tests/Jellyfin.Server.Implementations.Tests/Test Data/Updates/manifest.json b/tests/Jellyfin.Server.Implementations.Tests/Test Data/Updates/manifest.json index 57367ce88..6aa40c1dd 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Test Data/Updates/manifest.json +++ b/tests/Jellyfin.Server.Implementations.Tests/Test Data/Updates/manifest.json @@ -540,7 +540,7 @@ { "guid": "022a3003-993f-45f1-8565-87d12af2e12a", "name": "InfuseSync", - "description": "This plugin will track all media changes while any Infuse clients are offline to decrease sync times when logging back in to your server.", + "description": "This plugin will track all media changes while any Infuse clients are offline to decrease sync times when logging back into your server.", "overview": "Blazing fast indexing for Infuse", "owner": "Firecore LLC", "category": "General", diff --git a/tests/Jellyfin.Server.Implementations.Tests/TypedBaseItem/BaseItemKindTests.cs b/tests/Jellyfin.Server.Implementations.Tests/TypedBaseItem/BaseItemKindTests.cs index 1bd51b246..9a4389e7a 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/TypedBaseItem/BaseItemKindTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/TypedBaseItem/BaseItemKindTests.cs @@ -35,7 +35,7 @@ namespace Jellyfin.Server.Implementations.Tests.TypedBaseItem public void EnumParse_GivenValidBaseItemType_ReturnsEnumValue(Type baseItemDescendantType) { var enumValue = Enum.Parse<BaseItemKind>(baseItemDescendantType.Name); - Assert.True(Enum.IsDefined(typeof(BaseItemKind), enumValue)); + Assert.True(Enum.IsDefined(enumValue)); } [Theory] diff --git a/tests/Jellyfin.Server.Implementations.Tests/Users/UserManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Users/UserManagerTests.cs index 295f558fa..665afe111 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Users/UserManagerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Users/UserManagerTests.cs @@ -10,6 +10,9 @@ namespace Jellyfin.Server.Implementations.Tests.Users [InlineData("this_is_valid")] [InlineData("this is also valid")] [InlineData("0@_-' .")] + [InlineData("Aa0@_-' .+")] + [InlineData("thisisa+testemail@test.foo")] + [InlineData("------@@@--+++----@@--abcdefghijklmn---------@----_-_-___-_ .9foo+")] public void ThrowIfInvalidUsername_WhenValidUsername_DoesNotThrowArgumentException(string username) { var ex = Record.Exception(() => UserManager.ThrowIfInvalidUsername(username)); diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs index 39d449e27..d92dbbd73 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs @@ -14,7 +14,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers public sealed class DashboardControllerTests : IClassFixture<JellyfinApplicationFactory> { private readonly JellyfinApplicationFactory _factory; - private readonly JsonSerializerOptions _jsonOpions = JsonDefaults.Options; + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; private static string? _accessToken; public DashboardControllerTests(JellyfinApplicationFactory factory) @@ -65,7 +65,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Assert.Equal(HttpStatusCode.OK, response.StatusCode); - _ = await response.Content.ReadFromJsonAsync<ConfigurationPageInfo[]>(_jsonOpions); + _ = await response.Content.ReadFromJsonAsync<ConfigurationPageInfo[]>(_jsonOptions); // TODO: check content } @@ -81,7 +81,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet); - var data = await response.Content.ReadFromJsonAsync<ConfigurationPageInfo[]>(_jsonOpions); + var data = await response.Content.ReadFromJsonAsync<ConfigurationPageInfo[]>(_jsonOptions); Assert.NotNull(data); Assert.Empty(data); } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/ItemsControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/ItemsControllerTests.cs index 23de2489e..64b9bd8e1 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/ItemsControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/ItemsControllerTests.cs @@ -35,7 +35,7 @@ public sealed class ItemsControllerTests : IClassFixture<JellyfinApplicationFact [Theory] [InlineData("Users/{0}/Items")] [InlineData("Users/{0}/Items/Resume")] - public async Task GetUserItems_NonExistentUserId_NotFound(string format) + public async Task GetUserItems_NonexistentUserId_NotFound(string format) { var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryControllerTests.cs index 06abae14c..6881a9210 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryControllerTests.cs @@ -29,7 +29,7 @@ public sealed class LibraryControllerTests : IClassFixture<JellyfinApplicationFa [InlineData("Shows/{0}/Similar")] [InlineData("Movies/{0}/Similar")] [InlineData("Trailers/{0}/Similar")] - public async Task Get_NonExistentItemId_NotFound(string format) + public async Task Get_NonexistentItemId_NotFound(string format) { var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); @@ -41,7 +41,7 @@ public sealed class LibraryControllerTests : IClassFixture<JellyfinApplicationFa [Theory] [InlineData("Items/{0}")] [InlineData("Items?ids={0}")] - public async Task Delete_NonExistentItemId_Unauthorised(string format) + public async Task Delete_NonexistentItemId_Unauthorised(string format) { var client = _factory.CreateClient(); @@ -52,7 +52,7 @@ public sealed class LibraryControllerTests : IClassFixture<JellyfinApplicationFa [Theory] [InlineData("Items/{0}")] [InlineData("Items?ids={0}")] - public async Task Delete_NonExistentItemId_NotFound(string format) + public async Task Delete_NonexistentItemId_NotFound(string format) { var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs index bf3bfdad4..e7166d424 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs @@ -45,7 +45,7 @@ public sealed class LibraryStructureControllerTests : IClassFixture<JellyfinAppl } [Fact] - [Priority(0)] + [Priority(-2)] public async Task UpdateLibraryOptions_Invalid_NotFound() { var client = _factory.CreateClient(); @@ -62,12 +62,23 @@ public sealed class LibraryStructureControllerTests : IClassFixture<JellyfinAppl } [Fact] - [Priority(0)] + [Priority(-2)] public async Task UpdateLibraryOptions_Valid_Success() { var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); + var createBody = new AddVirtualFolderDto() + { + LibraryOptions = new LibraryOptions() + { + Enabled = false + } + }; + + using var createResponse = await client.PostAsJsonAsync("Library/VirtualFolders?name=test&refreshLibrary=true", createBody, _jsonOptions); + Assert.Equal(HttpStatusCode.NoContent, createResponse.StatusCode); + using var response = await client.GetAsync("Library/VirtualFolders"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/PlaystateControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/PlaystateControllerTests.cs index c02eedb20..3b9ed1778 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/PlaystateControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/PlaystateControllerTests.cs @@ -16,7 +16,7 @@ public class PlaystateControllerTests : IClassFixture<JellyfinApplicationFactory } [Fact] - public async Task DeleteMarkUnplayedItem_NonExistentUserId_NotFound() + public async Task DeleteMarkUnplayedItem_NonexistentUserId_NotFound() { var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); @@ -26,7 +26,7 @@ public class PlaystateControllerTests : IClassFixture<JellyfinApplicationFactory } [Fact] - public async Task PostMarkPlayedItem_NonExistentUserId_NotFound() + public async Task PostMarkPlayedItem_NonexistentUserId_NotFound() { var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); @@ -36,7 +36,7 @@ public class PlaystateControllerTests : IClassFixture<JellyfinApplicationFactory } [Fact] - public async Task DeleteMarkUnplayedItem_NonExistentItemId_NotFound() + public async Task DeleteMarkUnplayedItem_NonexistentItemId_NotFound() { var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); @@ -48,7 +48,7 @@ public class PlaystateControllerTests : IClassFixture<JellyfinApplicationFactory } [Fact] - public async Task PostMarkPlayedItem_NonExistentItemId_NotFound() + public async Task PostMarkPlayedItem_NonexistentItemId_NotFound() { var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/SessionControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/SessionControllerTests.cs deleted file mode 100644 index c267d3dd3..000000000 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/SessionControllerTests.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Net; -using System.Threading.Tasks; -using Xunit; - -namespace Jellyfin.Server.Integration.Tests.Controllers; - -public class SessionControllerTests : IClassFixture<JellyfinApplicationFactory> -{ - private readonly JellyfinApplicationFactory _factory; - private static string? _accessToken; - - public SessionControllerTests(JellyfinApplicationFactory factory) - { - _factory = factory; - } - - [Fact] - public async Task GetSessions_NonExistentUserId_NotFound() - { - var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - - using var response = await client.GetAsync($"Sessions?controllableByUserId={Guid.NewGuid()}"); - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); - } -} diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs index 4fcacd2ca..16c63ed49 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs @@ -20,7 +20,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers private const string TestUsername = "testUser01"; private readonly JellyfinApplicationFactory _factory; - private readonly JsonSerializerOptions _jsonOpions = JsonDefaults.Options; + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; private static string? _accessToken; private static Guid _testUserId = Guid.Empty; @@ -30,10 +30,10 @@ namespace Jellyfin.Server.Integration.Tests.Controllers } private Task<HttpResponseMessage> CreateUserByName(HttpClient httpClient, CreateUserByName request) - => httpClient.PostAsJsonAsync("Users/New", request, _jsonOpions); + => httpClient.PostAsJsonAsync("Users/New", request, _jsonOptions); private Task<HttpResponseMessage> UpdateUserPassword(HttpClient httpClient, Guid userId, UpdateUserPassword request) - => httpClient.PostAsJsonAsync("Users/" + userId.ToString("N", CultureInfo.InvariantCulture) + "/Password", request, _jsonOpions); + => httpClient.PostAsJsonAsync("Users/" + userId.ToString("N", CultureInfo.InvariantCulture) + "/Password", request, _jsonOptions); [Fact] [Priority(-1)] @@ -43,7 +43,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers using var response = await client.GetAsync("Users/Public"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var users = await response.Content.ReadFromJsonAsync<UserDto[]>(_jsonOpions); + var users = await response.Content.ReadFromJsonAsync<UserDto[]>(_jsonOptions); // User are hidden by default Assert.NotNull(users); Assert.Empty(users); @@ -58,7 +58,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers using var response = await client.GetAsync("Users"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var users = await response.Content.ReadFromJsonAsync<UserDto[]>(_jsonOpions); + var users = await response.Content.ReadFromJsonAsync<UserDto[]>(_jsonOptions); Assert.NotNull(users); Assert.Single(users); Assert.False(users![0].HasConfiguredPassword); @@ -90,7 +90,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers using var response = await CreateUserByName(client, createRequest); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var user = await response.Content.ReadFromJsonAsync<UserDto>(_jsonOpions); + var user = await response.Content.ReadFromJsonAsync<UserDto>(_jsonOptions); Assert.Equal(TestUsername, user!.Name); Assert.False(user.HasPassword); Assert.False(user.HasConfiguredPassword); @@ -151,7 +151,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); var users = await JsonSerializer.DeserializeAsync<UserDto[]>( - await client.GetStreamAsync("Users"), _jsonOpions); + await client.GetStreamAsync("Users"), _jsonOptions); var user = users!.First(x => x.Id.Equals(_testUserId)); Assert.True(user.HasPassword); Assert.True(user.HasConfiguredPassword); @@ -174,7 +174,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); var users = await JsonSerializer.DeserializeAsync<UserDto[]>( - await client.GetStreamAsync("Users"), _jsonOpions); + await client.GetStreamAsync("Users"), _jsonOptions); var user = users!.First(x => x.Id.Equals(_testUserId)); Assert.False(user.HasPassword); Assert.False(user.HasConfiguredPassword); diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserLibraryControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserLibraryControllerTests.cs index 130281c6d..8df86111e 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserLibraryControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserLibraryControllerTests.cs @@ -23,7 +23,7 @@ public sealed class UserLibraryControllerTests : IClassFixture<JellyfinApplicati } [Fact] - public async Task GetRootFolder_NonExistenUserId_NotFound() + public async Task GetRootFolder_NonexistentUserId_NotFound() { var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); @@ -47,7 +47,7 @@ public sealed class UserLibraryControllerTests : IClassFixture<JellyfinApplicati [InlineData("Users/{0}/Items/{1}/LocalTrailers")] [InlineData("Users/{0}/Items/{1}/SpecialFeatures")] [InlineData("Users/{0}/Items/{1}/Lyrics")] - public async Task GetItem_NonExistenUserId_NotFound(string format) + public async Task GetItem_NonexistentUserId_NotFound(string format) { var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); @@ -64,7 +64,7 @@ public sealed class UserLibraryControllerTests : IClassFixture<JellyfinApplicati [InlineData("Users/{0}/Items/{1}/LocalTrailers")] [InlineData("Users/{0}/Items/{1}/SpecialFeatures")] [InlineData("Users/{0}/Items/{1}/Lyrics")] - public async Task GetItem_NonExistentItemId_NotFound(string format) + public async Task GetItem_NonexistentItemId_NotFound(string format) { var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/VideosControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/VideosControllerTests.cs index 47bec5d79..1916ced12 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/VideosControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/VideosControllerTests.cs @@ -16,7 +16,7 @@ public sealed class VideosControllerTests : IClassFixture<JellyfinApplicationFac } [Fact] - public async Task DeleteAlternateSources_NonExistentItemId_NotFound() + public async Task DeleteAlternateSources_NonexistentItemId_NotFound() { var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs index 3721d1f7a..f9126ce9b 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs @@ -85,7 +85,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers Assert.Contains("Bryan Fuller", writers.Select(x => x.Name)); Assert.Contains("Michael Green", writers.Select(x => x.Name)); - // Direcotrs + // Directors var directors = result.People.Where(x => x.Type == PersonKind.Director).ToArray(); Assert.Single(directors); Assert.Contains("David Slade", directors.Select(x => x.Name)); @@ -157,7 +157,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers _parser.Fetch(result, "Test Data/Sonarr-Thumb.nfo", CancellationToken.None); - Assert.Single(result.RemoteImages.Where(x => x.Type == ImageType.Primary)); + Assert.Single(result.RemoteImages, x => x.Type == ImageType.Primary); Assert.Equal("https://artworks.thetvdb.com/banners/episodes/359095/7081317.jpg", result.RemoteImages.First(x => x.Type == ImageType.Primary).Url); } diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs index 5bc4abd06..9c2655154 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs @@ -149,7 +149,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers Assert.Equal(new DateTime(2019, 8, 6, 9, 1, 18), item.DateCreated); // userData - var userData = _userDataManager.GetUserData(_testUser, item); + var userData = _userDataManager.GetUserData(_testUser, item)!; Assert.Equal(2, userData.PlayCount); Assert.True(userData.Played); Assert.Equal(new DateTime(2021, 02, 11, 07, 47, 23), userData.LastPlayedDate); @@ -220,7 +220,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers _parser.Fetch(result, "Test Data/Fanart.nfo", CancellationToken.None); - Assert.Single(result.RemoteImages.Where(x => x.Type == ImageType.Backdrop)); + Assert.Single(result.RemoteImages, x => x.Type == ImageType.Backdrop); Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/moviebackground/justice-league-5a5332c7b5e77.jpg", result.RemoteImages.First(x => x.Type == ImageType.Backdrop).Url); } @@ -257,5 +257,23 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers Assert.Throws<ArgumentException>(() => _parser.Fetch(result, string.Empty, CancellationToken.None)); } + + [Fact] + public void Parsing_Fields_With_Escaped_Xml_Special_Characters_Success() + { + var result = new MetadataResult<Video>() + { + Item = new Movie() + }; + + _parser.Fetch(result, "Test Data/Lilo & Stitch.nfo", CancellationToken.None); + var item = (Movie)result.Item; + + Assert.Equal("Lilo & Stitch", item.Name); + Assert.Equal("Lilo & Stitch", item.OriginalTitle); + Assert.Equal("Lilo & Stitch Collection", item.CollectionName); + Assert.StartsWith(">>", item.Overview, StringComparison.InvariantCulture); + Assert.EndsWith("<<", item.Overview, StringComparison.InvariantCulture); + } } } diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Test Data/Lilo & Stitch.nfo b/tests/Jellyfin.XbmcMetadata.Tests/Test Data/Lilo & Stitch.nfo new file mode 100644 index 000000000..1eab687a2 --- /dev/null +++ b/tests/Jellyfin.XbmcMetadata.Tests/Test Data/Lilo & Stitch.nfo @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<movie> + <title>Lilo & Stitch</title> + <originaltitle>Lilo & Stitch</originaltitle> + <set>Lilo & Stitch Collection</set> + <plot>>>As Stitch, a runaway genetic experiment from a faraway planet, wreaks havoc on the Hawaiian Islands, he becomes the mischievous adopted alien "puppy" of an independent little girl named Lilo and learns about loyalty, friendship, and ʻohana, the Hawaiian tradition of family.<<</plot> +</movie> diff --git a/tests/jellyfin-tests.ruleset b/tests/jellyfin-tests.ruleset deleted file mode 100644 index 9d133da56..000000000 --- a/tests/jellyfin-tests.ruleset +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<RuleSet Name="Rules for Jellyfin.Api.Tests" Description="Code analysis rules for Jellyfin.Api.Tests.csproj" ToolsVersion="14.0"> - - <!-- Include the solution default RuleSet. The rules in this file will override the defaults. --> - <Include Path="../jellyfin.ruleset" Action="Default" /> - - <!-- StyleCop Analyzer Rules --> - <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers"> - <!-- SA0001: XML comment analysis is disabled due to project configuration --> - <Rule Id="SA0001" Action="None" /> - </Rules> - - <!-- FxCop Analyzer Rules --> - <Rules AnalyzerId="Microsoft.CodeAnalysis.FxCopAnalyzers" RuleNamespace="Microsoft.Design"> - <!-- CA1707: Identifiers should not contain underscores --> - <Rule Id="CA1707" Action="None" /> - <!-- CA2007: Consider calling ConfigureAwait on the awaited task --> - <Rule Id="CA2007" Action="None" /> - <!-- CA2234: Pass system uri objects instead of strings --> - <Rule Id="CA2234" Action="Info" /> - </Rules> - - <!-- xUnit --> - <Rules AnalyzerId="xUnit" RuleNamespace="xUnit"> - <!-- Test methods must have a supported return type. --> - <Rule Id="xUnit1028" Action="None" /> - </Rules> -</RuleSet> |
