diff --git a/shelfmark/core/search_plan.py b/shelfmark/core/search_plan.py index 99810b0f..03406906 100644 --- a/shelfmark/core/search_plan.py +++ b/shelfmark/core/search_plan.py @@ -113,17 +113,17 @@ def _normalize_languages(languages: list[str] | None, user_id: int | None) -> li def _pick_search_author(book: BookMetadata) -> str: - if book.search_author: - return book.search_author - - if not book.authors: + author = book.search_author or (book.authors[0] if book.authors else "") + if not author: return "" - first = book.authors[0] - if "," in first: - first = first.split(",")[0].strip() + # `search_author` can arrive as the display string for the whole credit list + # ("Author, Translator, Narrator"), which Anna's Archive answers with nothing at + # all. Trim it to the first name, which is what the authors list already gets. + if "," in author: + author = author.split(",")[0].strip() - return first + return author def _pick_search_title(book: BookMetadata) -> str: diff --git a/tests/core/test_search_plan.py b/tests/core/test_search_plan.py index cdff760a..e565e031 100644 --- a/tests/core/test_search_plan.py +++ b/tests/core/test_search_plan.py @@ -122,3 +122,54 @@ class TestReleaseSearchPlan: plan = build_release_search_plan(book, languages=["fr"], user_id=7) assert plan.languages == ["fr"] + + +class TestSearchAuthorNormalization: + """A credit list must not reach the query, whichever field carries it. + + Anna's Archive answers "Blindness Jose Saramago, Giovanni Pontiero, ..." with + nothing, so a book whose author string lists translators alongside the author + finds no releases at all. + """ + + MULTI = "Jose Saramago, Giovanni Pontiero, Zohreh Eftekhari" + + def test_search_author_is_trimmed_to_the_first_name(self): + book = BookMetadata( + provider="manual", + provider_id="1", + title="Blindness", + authors=[self.MULTI], + search_author=self.MULTI, + ) + + assert build_release_search_plan(book).primary_query == "Blindness Jose Saramago" + + def test_search_author_matches_the_authors_list(self): + """Same credit list, two fields, one query.""" + via_authors = BookMetadata( + provider="manual", provider_id="1", title="Blindness", authors=[self.MULTI] + ) + via_search_author = BookMetadata( + provider="manual", + provider_id="1", + title="Blindness", + authors=[self.MULTI], + search_author=self.MULTI, + ) + + assert ( + build_release_search_plan(via_search_author).primary_query + == build_release_search_plan(via_authors).primary_query + ) + + def test_single_author_is_untouched(self): + book = BookMetadata( + provider="manual", + provider_id="1", + title="Elantris", + authors=["Brandon Sanderson"], + search_author="Brandon Sanderson", + ) + + assert build_release_search_plan(book).primary_query == "Elantris Brandon Sanderson"