using FluentAssertions; using PageManager.Api.Services; using PageManager.Api.Tests.Helpers; namespace PageManager.Api.Tests.Unit.Services; public class MetadataWriterServiceTests { // ── ParseOpfPath ────────────────────────────────────────────────────────── [Fact] public void ParseOpfPath_ReturnsFullPath() { var xml = """ """; MetadataWriterService.ParseOpfPath(xml).Should().Be("OEBPS/content.opf"); } // ── ModifyOpfXml ────────────────────────────────────────────────────────── private const string MinimalOpf = """ Old Title Old Author en """; [Fact] public void ModifyOpfXml_UpdatesTitle() { var book = BookFactory.Create(title: "Dune", year: 1965).WithAuthors((1, "Frank Herbert")); var result = MetadataWriterService.ModifyOpfXml(MinimalOpf, book); result.Should().Contain("Dune"); } [Fact] public void ModifyOpfXml_UpdatesCreator() { var book = BookFactory.Create(title: "Dune").WithAuthors((1, "Frank Herbert")); var result = MetadataWriterService.ModifyOpfXml(MinimalOpf, book); result.Should().Contain("Frank Herbert"); } [Fact] public void ModifyOpfXml_AddsDescription_WhenPresent() { var book = BookFactory.Create(title: "Dune", description: "A sci-fi epic.").WithAuthors((1, "Frank Herbert")); var result = MetadataWriterService.ModifyOpfXml(MinimalOpf, book); result.Should().Contain("A sci-fi epic."); } [Fact] public void ModifyOpfXml_SkipsDescription_WhenNull() { var book = BookFactory.Create(title: "Dune", description: null).WithAuthors((1, "Frank Herbert")); var result = MetadataWriterService.ModifyOpfXml(MinimalOpf, book); result.Should().NotContain("dc:description"); } [Fact] public void ModifyOpfXml_AddsIsbnIdentifier_WhenPresent() { var book = BookFactory.Create(title: "Dune", isbn: "9780441013593").WithAuthors((1, "Frank Herbert")); var result = MetadataWriterService.ModifyOpfXml(MinimalOpf, book); result.Should().Contain("9780441013593"); result.Should().Contain("ISBN"); } [Fact] public void ModifyOpfXml_AddsDate_WhenYearPresent() { var book = BookFactory.Create(title: "Dune", year: 1965).WithAuthors((1, "Frank Herbert")); var result = MetadataWriterService.ModifyOpfXml(MinimalOpf, book); result.Should().Contain("1965"); } [Fact] public void ModifyOpfXml_PreservesExistingXmlStructure() { var book = BookFactory.Create(title: "Dune").WithAuthors((1, "Frank Herbert")); var result = MetadataWriterService.ModifyOpfXml(MinimalOpf, book); // Manifest and spine should still be present result.Should().Contain("manifest"); result.Should().Contain("spine"); result.Should().Contain("dc:language"); } [Fact] public void ModifyOpfXml_WithMultipleAuthors_UsesPrimaryAuthorForCreator() { var book = BookFactory.Create(title: "Good Omens") .WithAuthors((1, "Terry Pratchett"), (2, "Neil Gaiman")); var result = MetadataWriterService.ModifyOpfXml(MinimalOpf, book); result.Should().Contain("Terry Pratchett"); } [Fact] public void ModifyOpfXml_WithNoAuthors_DoesNotAddCreator() { var book = BookFactory.Create(title: "Anonymous"); // No authors added var result = MetadataWriterService.ModifyOpfXml(MinimalOpf, book); // Should not crash and should not add empty creator result.Should().NotContain(""); } [Fact] public void ModifyOpfXml_UpdatesExistingIsbnIdentifier_RatherThanAdding() { var opfWithIsbn = MinimalOpf.Replace( "en", "en\n OLD-ISBN"); var book = BookFactory.Create(title: "Dune", isbn: "9780441013593").WithAuthors((1, "Frank Herbert")); var result = MetadataWriterService.ModifyOpfXml(opfWithIsbn, book); result.Should().Contain("9780441013593"); result.Should().NotContain("OLD-ISBN"); // Should not have two ISBN identifiers result.Split("ISBN").Length.Should().BeLessThanOrEqualTo(3); // "ISBN" appears in scheme + value } }