"""Unit tests for API-first catalog hub.""" from unittest.mock import AsyncMock, patch import pytest from app.services.catalog_hub import ( CatalogSnapshot, build_catalog_snapshot, discover_platform_hit, isbn_retailer_urls, normalize_source_platform, ) from app.services.isbn_catalog import classify_retailer_url, sanitize_platform_url class TestNormalizeSourcePlatform: def test_google_play_maps_to_google_books(self): assert normalize_source_platform("google_play") == "google_books" def test_amazon_unchanged(self): assert normalize_source_platform("amazon") == "amazon" class TestDiscoverPlatformHit: def _snap(self, **kwargs) -> CatalogSnapshot: return CatalogSnapshot(**kwargs) def test_source_amazon_verified(self): hit = discover_platform_hit( "amazon", self._snap(asin="B0DHWS3P6T"), source_platform="amazon", buy_url="https://www.amazon.com/dp/B0DHWS3P6T", ) assert hit.confidence == 1.0 assert hit.listing_url == "https://www.amazon.com/dp/B0DHWS3P6T" def test_google_books_api_verified(self): snap = self._snap(gb_volume_id="abc123", gb_confidence=0.92) hit = discover_platform_hit("google_books", snap) assert hit.listing_url == "https://books.google.com/books?id=abc123" assert hit.confidence >= 0.85 def test_open_library_verified(self): snap = self._snap(isbn13="9780593128251", ol_confidence=0.90, ol_key="/works/OL123W") hit = discover_platform_hit("open_library", snap) assert hit.listing_url == "https://openlibrary.org/isbn/9780593128251" def test_goodreads_product_link(self): snap = self._snap( retailer_links={ "thriftbooks": "https://www.thriftbooks.com/w/lethal-lines/123/", }, ) hit = discover_platform_hit("thriftbooks", snap) assert hit.confidence == 0.95 assert "thriftbooks.com/w/" in hit.listing_url def test_isbn_search_url_not_present(self): snap = self._snap(isbn13="9780593128251") hit = discover_platform_hit("kobo", snap) assert hit.listing_url is None assert hit.confidence == 0.0 def test_search_link_not_verified_product(self): url = "https://www.barnesandnoble.com/s/Lethal+Lines" assert classify_retailer_url(url, "barnes_noble") == "search" class TestIsbnRetailerUrls: def test_builds_isbn_targets(self): urls = isbn_retailer_urls("9780593128251") assert "abebooks.com" in urls["abebooks"] assert "9780593128251" in urls["kobo"] @pytest.mark.asyncio async def test_build_catalog_snapshot_parallel(): """Catalog snapshot merges Google Books + Open Library + Apple.""" mock_client = AsyncMock() with patch( "app.services.catalog_hub._resolve_google", new=AsyncMock(return_value={ "confidence": 0.92, "volume_id": "vol123", "isbn13": "9780593128251", "isbn10": "0593128257", "title": "Regime Change", "author": "Patrick Deneen", "isbn_match": True, }), ), patch( "app.services.catalog_hub.lookup_open_library", new=AsyncMock(return_value={ "isbn13": "9780593128251", "work_key": "/works/OL27445227W", "confidence": 0.90, "author": "Patrick Deneen", }), ), patch( "app.services.catalog_hub._resolve_apple", new=AsyncMock(return_value={"confidence": 0.88, "url": "https://books.apple.com/us/book/id123"}), ): snap = await build_catalog_snapshot( mock_client, title="Regime Change", author="Patrick Deneen", isbn="9780593128251", ) assert snap.gb_volume_id == "vol123" assert snap.isbn13 == "9780593128251" assert snap.apple_url is not None class TestSanitizePlatformUrl: def test_amazon_affiliate_to_dp(self): url = sanitize_platform_url( "http://www.amazon.com/gp/product/B0DHWS3P6T/ref=affiliate", "amazon", ) assert url == "https://www.amazon.com/dp/B0DHWS3P6T"