"""Unit tests for per-platform list price fetching.""" from unittest.mock import AsyncMock, MagicMock import pytest from app.services.platform_pricing import ( PriceContext, extract_price_from_html, fetch_apple_books_price, fetch_google_books_price, fetch_listing_price, format_price, ) class TestFormatPrice: def test_usd(self): assert format_price(14.99, "USD") == "$14.99" def test_gbp(self): assert format_price(9.5, "GBP") == "£9.50" class TestExtractPriceFromHtml: def test_barnes_noble_json_price(self): html = '{"price": "14.99", "title": "Test"}' hit = extract_price_from_html("barnes_noble", html) assert hit is not None assert hit.formatted == "$14.99" def test_abebooks_itemprop(self): html = 'US$ 6.32' hit = extract_price_from_html("abebooks", html) assert hit is not None assert hit.amount == 6.32 def test_amazon_us_offscreen(self): html = '$15.99' hit = extract_price_from_html("amazon", html) assert hit is not None assert hit.formatted == "$15.99" def test_amazon_international_currency(self): html = 'apex-pricetopay-accessibility-label"> PKR 275.24 with 94 percent' hit = extract_price_from_html("amazon", html) assert hit is not None assert "275.24" in hit.formatted def test_goodreads_no_price(self): html = "Goodreads page" assert extract_price_from_html("goodreads", html) is None @pytest.mark.asyncio class TestFetchApiPrices: async def test_google_books_isbn_fallback(self): client = AsyncMock() volume_resp = MagicMock(status_code=200) volume_resp.json.return_value = {"saleInfo": {"saleability": "NOT_FOR_SALE"}} isbn_resp = MagicMock(status_code=200) isbn_resp.json.return_value = { "items": [{"saleInfo": {"listPrice": {"amount": 0.99, "currencyCode": "USD"}}}], } client.get.side_effect = [volume_resp, isbn_resp] hit = await fetch_google_books_price( client, "https://books.google.com/books?id=abc123", PriceContext(isbn13="9781529374551"), ) assert hit is not None assert hit.formatted == "$0.99" async def test_apple_formatted_price(self): client = AsyncMock() response = MagicMock() response.status_code = 200 response.json.return_value = { "results": [{"formattedPrice": "$14.99", "currency": "USD"}], } client.get.return_value = response hit = await fetch_apple_books_price( client, "https://books.apple.com/us/book/x/id6475274221", ) assert hit is not None assert hit.formatted == "$14.99" async def test_open_library_free(self): client = AsyncMock() hit = await fetch_listing_price( client, "open_library", "https://openlibrary.org/isbn/9781529374551", ) assert hit is not None assert hit.formatted == "Free"