Added support for bittorrent
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
using FluentAssertions;
|
||||
using PageManager.Api.Services;
|
||||
using PageManager.Api.Tests.Helpers;
|
||||
|
||||
namespace PageManager.Api.Tests.Unit.Services;
|
||||
|
||||
public class FileOrganizerServiceTests
|
||||
{
|
||||
// ── SanitizePathComponent ─────────────────────────────────────────────────
|
||||
|
||||
[Theory]
|
||||
[InlineData("Andy Weir", "Andy Weir")]
|
||||
[InlineData("Brandon Sanderson", "Brandon Sanderson")]
|
||||
[InlineData("Hello: World", "Hello_ World")] // colon is invalid
|
||||
[InlineData("Title/Sub", "Title_Sub")] // slash is invalid
|
||||
[InlineData("Name.", "Name")] // trailing dot stripped
|
||||
[InlineData(" Name ", "Name")] // whitespace trimmed
|
||||
public void SanitizePathComponent_ReturnsExpected(string input, string expected)
|
||||
{
|
||||
FileOrganizerService.SanitizePathComponent(input).Should().Be(expected);
|
||||
}
|
||||
|
||||
// ── ComputeCanonicalRelativePath — ebooks ─────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void Ebook_WithYear_ProducesAuthorTitleYearFolder()
|
||||
{
|
||||
var book = BookFactory.Create(title: "The Martian", year: 2011)
|
||||
.WithAuthors((1, "Andy Weir"));
|
||||
|
||||
var result = FileOrganizerService.ComputeCanonicalRelativePath(book, ".epub", isAudio: false);
|
||||
|
||||
result.Should().Be(Path.Combine("Andy Weir", "The Martian (2011)", "The Martian.epub"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Ebook_WithoutYear_OmitsYearFromFolder()
|
||||
{
|
||||
var book = BookFactory.Create(title: "Dune", year: null)
|
||||
.WithAuthors((1, "Frank Herbert"));
|
||||
|
||||
var result = FileOrganizerService.ComputeCanonicalRelativePath(book, ".epub", isAudio: false);
|
||||
|
||||
result.Should().Be(Path.Combine("Frank Herbert", "Dune", "Dune.epub"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Ebook_SeriesIgnored_SeriesNotInEbookPath()
|
||||
{
|
||||
var book = BookFactory.Create(title: "The Way of Kings", year: 2010)
|
||||
.WithAuthors((1, "Brandon Sanderson"))
|
||||
.WithSeries(seriesName: "The Stormlight Archive");
|
||||
|
||||
var result = FileOrganizerService.ComputeCanonicalRelativePath(book, ".epub", isAudio: false);
|
||||
|
||||
// Series folder should NOT appear for ebooks
|
||||
result.Should().Be(Path.Combine("Brandon Sanderson", "The Way of Kings (2010)", "The Way of Kings.epub"));
|
||||
}
|
||||
|
||||
// ── ComputeCanonicalRelativePath — audiobooks ─────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void Audiobook_WithoutSeries_ProducesAuthorTitleTitle()
|
||||
{
|
||||
var book = BookFactory.Create(title: "Project Hail Mary", year: 2021)
|
||||
.WithAuthors((1, "Andy Weir"));
|
||||
|
||||
var result = FileOrganizerService.ComputeCanonicalRelativePath(book, ".m4b", isAudio: true);
|
||||
|
||||
result.Should().Be(Path.Combine("Andy Weir", "Project Hail Mary", "Project Hail Mary.m4b"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Audiobook_WithSeries_InsertSeriesFolderBetweenAuthorAndTitle()
|
||||
{
|
||||
var book = BookFactory.Create(title: "The Way of Kings", year: 2010)
|
||||
.WithAuthors((1, "Brandon Sanderson"))
|
||||
.WithSeries(seriesName: "The Stormlight Archive");
|
||||
|
||||
var result = FileOrganizerService.ComputeCanonicalRelativePath(book, ".m4b", isAudio: true);
|
||||
|
||||
result.Should().Be(Path.Combine("Brandon Sanderson", "The Stormlight Archive", "The Way of Kings", "The Way of Kings.m4b"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Audiobook_Mp3Extension_PreservedInFilename()
|
||||
{
|
||||
var book = BookFactory.Create(title: "Dune", year: 1965)
|
||||
.WithAuthors((1, "Frank Herbert"));
|
||||
|
||||
var result = FileOrganizerService.ComputeCanonicalRelativePath(book, ".mp3", isAudio: true);
|
||||
|
||||
result.Should().Be(Path.Combine("Frank Herbert", "Dune", "Dune.mp3"));
|
||||
}
|
||||
|
||||
// ── Multiple authors ──────────────────────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void MultipleAuthors_UsesPrimaryAuthorForPath()
|
||||
{
|
||||
var book = BookFactory.Create(title: "Good Omens", year: 1990)
|
||||
.WithAuthors((1, "Terry Pratchett"), (2, "Neil Gaiman"));
|
||||
|
||||
var result = FileOrganizerService.ComputeCanonicalRelativePath(book, ".epub", isAudio: false);
|
||||
|
||||
result.Should().StartWith("Terry Pratchett");
|
||||
result.Should().NotContain("Neil Gaiman");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NoAuthors_UsesUnknownFolder()
|
||||
{
|
||||
var book = BookFactory.Create(title: "Anonymous Work", year: 2000);
|
||||
// No authors added
|
||||
|
||||
var result = FileOrganizerService.ComputeCanonicalRelativePath(book, ".epub", isAudio: false);
|
||||
|
||||
result.Should().StartWith("Unknown");
|
||||
}
|
||||
|
||||
// ── Sanitization edge cases ───────────────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void TitleWithInvalidChars_Sanitized()
|
||||
{
|
||||
var book = BookFactory.Create(title: "Title: A Story", year: 2020)
|
||||
.WithAuthors((1, "Author Name"));
|
||||
|
||||
var result = FileOrganizerService.ComputeCanonicalRelativePath(book, ".epub", isAudio: false);
|
||||
|
||||
result.Should().Be(Path.Combine("Author Name", "Title_ A Story (2020)", "Title_ A Story.epub"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user