diff options
Diffstat (limited to 'tests/Jellyfin.Server.Implementations.Tests/Library')
5 files changed, 155 insertions, 7 deletions
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/AudioResolverTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/AudioResolverTests.cs new file mode 100644 index 000000000..d136c1bc6 --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/AudioResolverTests.cs @@ -0,0 +1,76 @@ +using System.Linq; +using Emby.Naming.Common; +using Emby.Server.Implementations.Library.Resolvers.Audio; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.IO; +using Moq; +using Xunit; + +namespace Jellyfin.Server.Implementations.Tests.Library; + +public class AudioResolverTests +{ + private static readonly NamingOptions _namingOptions = new(); + + [Theory] + [InlineData("words.mp3")] // single non-tagged file + [InlineData("chapter 01.mp3")] + [InlineData("part 1.mp3")] + [InlineData("chapter 01.mp3", "non-media.txt")] + [InlineData("title.mp3", "title.epub")] + [InlineData("01.mp3", "subdirectory/")] // single media file with sub-directory - note that this will hide any contents in the subdirectory + public void Resolve_AudiobookDirectory_SingleResult(params string[] children) + { + var resolved = TestResolveChildren("/parent/title", children); + Assert.NotNull(resolved); + } + + [Theory] + /* Results that can't be displayed as an audio book. */ + [InlineData] // no contents + [InlineData("subdirectory/")] + [InlineData("non-media.txt")] + /* Names don't indicate parts of a single book. */ + [InlineData("Name.mp3", "Another Name.mp3")] + /* Results that are an audio book but not currently navigable as such (multiple chapters and/or parts). */ + [InlineData("01.mp3", "02.mp3")] + [InlineData("chapter 01.mp3", "chapter 02.mp3")] + [InlineData("part 1.mp3", "part 2.mp3")] + [InlineData("chapter 01 part 01.mp3", "chapter 01 part 02.mp3")] + /* Mismatched chapters, parts, and named files. */ + [InlineData("chapter 01.mp3", "part 2.mp3")] + [InlineData("book title.mp3", "chapter name.mp3")] // "book title" resolves as alternate version of book based on directory name + [InlineData("01 Content.mp3", "01 Credits.mp3")] // resolves as alternate versions of chapter 1 + [InlineData("Chapter Name.mp3", "Part 1.mp3")] + public void Resolve_AudiobookDirectory_NoResult(params string[] children) + { + var resolved = TestResolveChildren("/parent/book title", children); + Assert.Null(resolved); + } + + private Audio? TestResolveChildren(string parent, string[] children) + { + var childrenMetadata = children.Select(name => new FileSystemMetadata + { + FullName = parent + "/" + name, + IsDirectory = name.EndsWith('/') + }).ToArray(); + + var resolver = new AudioResolver(_namingOptions); + var itemResolveArgs = new ItemResolveArgs( + null, + Mock.Of<ILibraryManager>()) + { + CollectionType = "books", + FileInfo = new FileSystemMetadata + { + FullName = parent, + IsDirectory = true + }, + FileSystemChildren = childrenMetadata + }; + + return resolver.Resolve(itemResolveArgs); + } +} diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs index 286ba0405..6d0ed7bbb 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs @@ -22,10 +22,10 @@ namespace Jellyfin.Server.Implementations.Tests.Library { var parent = new Folder { Name = "extras" }; - var episodeResolver = new EpisodeResolver(Mock.Of<ILogger<EpisodeResolver>>(), _namingOptions); + var episodeResolver = new EpisodeResolver(Mock.Of<ILogger<EpisodeResolver>>(), _namingOptions, Mock.Of<IDirectoryService>()); var itemResolveArgs = new ItemResolveArgs( Mock.Of<IServerApplicationPaths>(), - Mock.Of<IDirectoryService>()) + null) { Parent = parent, CollectionType = CollectionType.TvShows, @@ -45,10 +45,10 @@ namespace Jellyfin.Server.Implementations.Tests.Library // Have to create a mock because of moq proxies not being castable to a concrete implementation // https://github.com/jellyfin/jellyfin/blob/ab0cff8556403e123642dc9717ba778329554634/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs#L48 - var episodeResolver = new EpisodeResolverMock(Mock.Of<ILogger<EpisodeResolver>>(), _namingOptions); + var episodeResolver = new EpisodeResolverMock(Mock.Of<ILogger<EpisodeResolver>>(), _namingOptions, Mock.Of<IDirectoryService>()); var itemResolveArgs = new ItemResolveArgs( Mock.Of<IServerApplicationPaths>(), - Mock.Of<IDirectoryService>()) + null) { Parent = series, CollectionType = CollectionType.TvShows, @@ -62,7 +62,7 @@ namespace Jellyfin.Server.Implementations.Tests.Library private sealed class EpisodeResolverMock : EpisodeResolver { - public EpisodeResolverMock(ILogger<EpisodeResolver> logger, NamingOptions namingOptions) : base(logger, namingOptions) + public EpisodeResolverMock(ILogger<EpisodeResolver> logger, NamingOptions namingOptions, IDirectoryService directoryService) : base(logger, namingOptions, directoryService) { } diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs index 599599071..562711337 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs @@ -80,6 +80,35 @@ public class FindExtrasTests } [Fact] + public void FindExtras_SeparateMovieFolder_CleanExtraNames() + { + var owner = new Movie { Name = "Up", Path = "/movies/Up/Up.mkv" }; + var paths = new List<string> + { + "/movies/Up/Up.mkv", + "/movies/Up/Recording the audio[Bluray]-behindthescenes.mkv", + "/movies/Up/Interview with the dog-interview.mkv", + "/movies/Up/shorts/Balloons[1080p].mkv" + }; + + var files = paths.Select(p => new FileSystemMetadata + { + FullName = p, + IsDirectory = false + }).ToList(); + + var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.ExtraType).ToList(); + + Assert.Equal(3, extras.Count); + Assert.Equal(ExtraType.BehindTheScenes, extras[0].ExtraType); + Assert.Equal("Recording the audio", extras[0].Name); + Assert.Equal(ExtraType.Interview, extras[1].ExtraType); + Assert.Equal("Interview with the dog", extras[1].Name); + Assert.Equal(ExtraType.Short, extras[2].ExtraType); + Assert.Equal("Balloons", extras[2].Name); + } + + [Fact] public void FindExtras_SeparateMovieFolderWithMixedExtras_FindsCorrectExtras() { var owner = new Movie { Name = "Up", Path = "/movies/Up/Up.mkv" }; diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/MovieResolverTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/MovieResolverTests.cs index efc3ac0c2..aed584355 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/MovieResolverTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/MovieResolverTests.cs @@ -18,10 +18,10 @@ public class MovieResolverTests [Fact] public void Resolve_GivenLocalAlternateVersion_ResolvesToVideo() { - var movieResolver = new MovieResolver(Mock.Of<IImageProcessor>(), Mock.Of<ILogger<MovieResolver>>(), _namingOptions); + var movieResolver = new MovieResolver(Mock.Of<IImageProcessor>(), Mock.Of<ILogger<MovieResolver>>(), _namingOptions, Mock.Of<IDirectoryService>()); var itemResolveArgs = new ItemResolveArgs( Mock.Of<IServerApplicationPaths>(), - Mock.Of<IDirectoryService>()) + null) { Parent = null, FileInfo = new FileSystemMetadata diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs index be2dfe0a8..c33a957e6 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using Emby.Server.Implementations.Library; using Xunit; @@ -73,5 +74,47 @@ namespace Jellyfin.Server.Implementations.Tests.Library Assert.False(PathExtensions.TryReplaceSubPath(path, subPath, newSubPath, out var result)); Assert.Null(result); } + + [Theory] + [InlineData(null, '/', null)] + [InlineData(null, '\\', null)] + [InlineData("/home/jeff/myfile.mkv", '\\', "\\home\\jeff\\myfile.mkv")] + [InlineData("C:\\Users\\Jeff\\myfile.mkv", '/', "C:/Users/Jeff/myfile.mkv")] + [InlineData("\\home/jeff\\myfile.mkv", '\\', "\\home\\jeff\\myfile.mkv")] + [InlineData("\\home/jeff\\myfile.mkv", '/', "/home/jeff/myfile.mkv")] + [InlineData("", '/', "")] + public void NormalizePath_SpecifyingSeparator_Normalizes(string path, char separator, string expectedPath) + { + Assert.Equal(expectedPath, path.NormalizePath(separator)); + } + + [Theory] + [InlineData("/home/jeff/myfile.mkv")] + [InlineData("C:\\Users\\Jeff\\myfile.mkv")] + [InlineData("\\home/jeff\\myfile.mkv")] + public void NormalizePath_NoArgs_UsesDirectorySeparatorChar(string path) + { + var separator = Path.DirectorySeparatorChar; + + Assert.Equal(path.Replace('\\', separator).Replace('/', separator), path.NormalizePath()); + } + + [Theory] + [InlineData("/home/jeff/myfile.mkv", '/')] + [InlineData("C:\\Users\\Jeff\\myfile.mkv", '\\')] + [InlineData("\\home/jeff\\myfile.mkv", '/')] + public void NormalizePath_OutVar_Correct(string path, char expectedSeparator) + { + var result = path.NormalizePath(out var separator); + + Assert.Equal(expectedSeparator, separator); + Assert.Equal(path.Replace('\\', separator).Replace('/', separator), result); + } + + [Fact] + public void NormalizePath_SpecifyInvalidSeparator_ThrowsException() + { + Assert.Throws<ArgumentException>(() => string.Empty.NormalizePath('a')); + } } } |
