Files
chitai/backend/tests/unit/test_metadata_extractor.py
T
patrick f6bb06ac6e fix: merge identifiers across a book's formats
Identifiers are a collection, but the whole dict was replaced per format, so
the last file to report won outright — an EPUB declaring an ASIN, a Google id
and a Calibre id kept none of them once a PDF contributed one ISBN. Accumulate
instead, letting a declared identifier outrank one scraped off a page.
2026-08-15 21:57:01 -04:00

77 lines
2.9 KiB
Python

import pytest
from pathlib import Path
from datetime import date
from chitai.services.metadata_extractor import EpubExtractor, Extractor, PdfExtractor
@pytest.mark.asyncio()
class TestEpubExtractor:
async def test_extraction_by_path(self):
path = Path("tests/data_files/Moby Dick; Or, The Whale - Herman Melville.epub")
metadata = await EpubExtractor.extract_metadata(path)
assert metadata["title"] == "Moby Dick; Or, The Whale"
assert metadata["authors"] == ["Herman Melville"]
assert metadata["published_date"] == date(year=2001, month=7, day=1)
EPUB = Path("tests/data_files/Metamorphosis - Franz Kafka.epub")
PDF = Path("tests/data_files/Calculus Made Easy - Silvanus Thompson.pdf")
@pytest.mark.asyncio()
class TestIdentifierMerging:
"""A book's formats each contribute identifiers; none of them replaces the rest."""
async def test_every_format_contributes(self, monkeypatch: pytest.MonkeyPatch) -> None:
"""
Identifiers are a collection, not a single value.
Merging the whole dict meant the last format to report won outright: an EPUB
declaring an ASIN, a Google volume id and a Calibre id kept none of them once
a PDF contributed one ISBN.
"""
async def epub(_file):
return {
"title": "How Linux Works",
"identifiers": {"isbn-13": "9781718500419", "asin": "1718500408"},
}
async def pdf(_file):
return {"identifiers": {"isbn-13": "9781718500402", "isbn-10": "1593270356"}}
monkeypatch.setattr(EpubExtractor, "extract_metadata", epub)
monkeypatch.setattr(PdfExtractor, "extract_metadata", pdf)
metadata = await Extractor.extract_metadata(
[Path("How Linux Works.epub"), Path("How Linux Works.pdf")]
)
assert metadata["identifiers"] == {
# Declared by the publisher's toolchain, so it outranks the PDF's, which
# was scraped off a copyright page that also prints the print edition's.
"isbn-13": "9781718500419",
"asin": "1718500408",
"isbn-10": "1593270356",
}
async def test_a_second_format_that_finds_nothing_erases_nothing(self) -> None:
"""The PDF fixture carries no ISBN, so it must leave the EPUB's alone."""
metadata = await Extractor.extract_metadata([EPUB, PDF])
assert metadata["identifiers"] == {"id": "http://www.gutenberg.org/5200"}
async def test_one_format_on_its_own_is_unaffected(self) -> None:
metadata = await Extractor.extract_metadata([EPUB])
assert metadata["identifiers"] == {"id": "http://www.gutenberg.org/5200"}
async def test_no_identifiers_anywhere_leaves_the_field_absent(self) -> None:
"""An empty dict would count as extracted metadata and overwrite nothing."""
metadata = await Extractor.extract_metadata([PDF])
assert "identifiers" not in metadata