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
}
}