Spaces:
Running
Running
| """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"] | |
| 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" | |