aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/Jellyfin.Providers.Tests/Books/ComicBookInfoProviderTests.cs143
1 files changed, 143 insertions, 0 deletions
diff --git a/tests/Jellyfin.Providers.Tests/Books/ComicBookInfoProviderTests.cs b/tests/Jellyfin.Providers.Tests/Books/ComicBookInfoProviderTests.cs
new file mode 100644
index 0000000000..f7f29d9768
--- /dev/null
+++ b/tests/Jellyfin.Providers.Tests/Books/ComicBookInfoProviderTests.cs
@@ -0,0 +1,143 @@
+using System;
+using System.IO;
+using System.IO.Compression;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Providers.Books.ComicBookInfo;
+using Microsoft.Extensions.Logging;
+using Moq;
+using Xunit;
+
+namespace Jellyfin.Providers.Tests.Books;
+
+public sealed class ComicBookInfoProviderTests : IDisposable
+{
+ private const string ValidComment = """
+ {"appID":"test","ComicBookInfo/1.0":{"series":"Jungle Juice","title":"Episode 36","issue":175}}
+ """;
+
+ private readonly string _directory;
+
+ public ComicBookInfoProviderTests()
+ {
+ _directory = Path.Combine(Path.GetTempPath(), "jf-cbz-" + Guid.NewGuid().ToString("N"));
+ Directory.CreateDirectory(_directory);
+ }
+
+ public void Dispose()
+ {
+ Directory.Delete(_directory, true);
+ }
+
+ [Theory]
+ [InlineData(null)] // archive written without ever touching Comment
+ [InlineData("")]
+ [InlineData(" ")]
+ public async Task ReadMetadata_EmptyArchiveComment_SkipsWithoutDeserializing(string? comment)
+ {
+ var logger = new Mock<ILogger<ComicBookInfoProvider>>();
+ var path = CreateArchive(comment);
+ var provider = new ComicBookInfoProvider(CreateFileSystem(path), logger.Object);
+
+ var result = await provider.ReadMetadata(new ItemInfo(new Book { Path = path }), Mock.Of<IDirectoryService>(), CancellationToken.None);
+
+ Assert.False(result.HasMetadata);
+ VerifyLogged(logger, LogLevel.Debug, "missing ComicBookInfo in archive comment");
+ VerifyNothingLoggedAbove(logger, LogLevel.Debug);
+ }
+
+ [Fact]
+ public async Task ReadMetadata_ArchiveCommentIsNotComicBookInfo_SkipsWithoutError()
+ {
+ var logger = new Mock<ILogger<ComicBookInfoProvider>>();
+ var path = CreateArchive("Created by some packer");
+ var provider = new ComicBookInfoProvider(CreateFileSystem(path), logger.Object);
+
+ var result = await provider.ReadMetadata(new ItemInfo(new Book { Path = path }), Mock.Of<IDirectoryService>(), CancellationToken.None);
+
+ Assert.False(result.HasMetadata);
+ VerifyLogged(logger, LogLevel.Debug, "archive comment is not valid ComicBookInfo metadata");
+ VerifyNothingLoggedAbove(logger, LogLevel.Debug);
+ }
+
+ [Fact]
+ public async Task ReadMetadata_ValidComicBookInfoComment_ReturnsMetadata()
+ {
+ var logger = new Mock<ILogger<ComicBookInfoProvider>>();
+ var path = CreateArchive(ValidComment);
+ var provider = new ComicBookInfoProvider(CreateFileSystem(path), logger.Object);
+
+ var result = await provider.ReadMetadata(new ItemInfo(new Book { Path = path }), Mock.Of<IDirectoryService>(), CancellationToken.None);
+
+ Assert.True(result.HasMetadata);
+ Assert.NotNull(result.Item);
+ Assert.Equal("Episode 36", result.Item.Name);
+ Assert.Equal("Jungle Juice", result.Item.SeriesName);
+ Assert.Equal(175, result.Item.IndexNumber);
+ VerifyNothingLoggedAbove(logger, LogLevel.Debug);
+ }
+
+ private static void VerifyLogged(Mock<ILogger<ComicBookInfoProvider>> logger, LogLevel level, string message)
+ {
+ logger.Verify(
+ x => x.Log(
+ level,
+ It.IsAny<EventId>(),
+ It.Is<It.IsAnyType>((state, _) => state.ToString()!.Contains(message, StringComparison.Ordinal)),
+ It.IsAny<Exception>(),
+ It.IsAny<Func<It.IsAnyType, Exception?, string>>()),
+ Times.Once);
+ }
+
+ private static void VerifyNothingLoggedAbove(Mock<ILogger<ComicBookInfoProvider>> logger, LogLevel level)
+ {
+ // a comment that holds no ComicBookInfo is normal, so it must not reach the log of a default install
+ logger.Verify(
+ x => x.Log(
+ It.Is<LogLevel>(actual => actual > level),
+ It.IsAny<EventId>(),
+ It.IsAny<It.IsAnyType>(),
+ It.IsAny<Exception>(),
+ It.IsAny<Func<It.IsAnyType, Exception?, string>>()),
+ Times.Never);
+ }
+
+ private static IFileSystem CreateFileSystem(string path)
+ {
+ var fileSystem = new Mock<IFileSystem>();
+ fileSystem.Setup(x => x.GetFileSystemInfo(path))
+ .Returns(new FileSystemMetadata
+ {
+ Exists = true,
+ FullName = path,
+ Name = Path.GetFileName(path),
+ Extension = ".cbz",
+ IsDirectory = false
+ });
+
+ return fileSystem.Object;
+ }
+
+ private string CreateArchive(string? comment)
+ {
+ var path = Path.Combine(_directory, Guid.NewGuid().ToString("N") + ".cbz");
+
+ using (var stream = File.Create(path))
+ using (var archive = new ZipArchive(stream, ZipArchiveMode.Create))
+ {
+ if (comment is not null)
+ {
+ archive.Comment = comment;
+ }
+
+ var entry = archive.CreateEntry("ComicInfo.xml");
+ using var writer = new StreamWriter(entry.Open());
+ writer.Write("<ComicInfo />");
+ }
+
+ return path;
+ }
+}