Arag / tests /unit /test_platform_api_registry.py
AuthorBot
Add SuperAdmin retailer API keys with priority over env and free scraping.
ad1b7c6
Raw
History Blame Contribute Delete
4.68 kB
"""Unit tests for platform API credential registry and providers."""
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from app.core.crypto.credential_crypto import decrypt_secret, encrypt_secret, mask_secret
from app.services.platform_api_registry import (
EffectiveCredential,
build_credential_views,
fetch_price_via_credential,
resolve_platform_credential,
)
class TestCredentialCrypto:
def test_encrypt_decrypt_roundtrip(self):
raw = "sk-test-api-key-12345"
token = encrypt_secret(raw)
assert decrypt_secret(token) == raw
assert raw not in token
def test_mask_secret(self):
assert mask_secret("abcd") == "••••"
assert mask_secret("my-long-api-key-9xyz") == "••••9xyz"
class TestBuildCredentialViews:
def test_no_row_no_env_shows_none_source(self):
views = build_credential_views([])
amazon = next(v for v in views if v.platform_id == "amazon")
assert amazon.source == "none"
assert amazon.api_key_hint is None
assert "rainforest" in amazon.available_providers
def test_env_credential_shows_environment_source(self):
with patch("app.services.platform_api_registry.get_settings") as gs:
gs.return_value = MagicMock(RAINFOREST_API_KEY="rf-env-key-9999")
views = build_credential_views([])
amazon = next(v for v in views if v.platform_id == "amazon")
assert amazon.source == "environment"
assert amazon.api_key_hint == "••••9999"
assert amazon.is_enabled is True
@pytest.mark.asyncio
class TestResolvePlatformCredential:
async def test_superadmin_db_takes_priority_over_env(self):
row = MagicMock()
row.platform_id = "amazon"
row.provider = "rainforest"
row.api_key_encrypted = encrypt_secret("db-key-wins")
row.api_secret_encrypted = None
row.is_enabled = True
db = AsyncMock()
repo = MagicMock()
repo.get_enabled = AsyncMock(return_value=row)
with patch(
"app.services.platform_api_registry.PlatformApiCredentialRepository",
return_value=repo,
), patch("app.services.platform_api_registry._env_credential") as env:
env.return_value = EffectiveCredential(
platform_id="amazon",
provider="rainforest",
api_key="env-key",
api_secret=None,
source="environment",
)
cred = await resolve_platform_credential("amazon", db=db, redis=None)
assert cred is not None
assert cred.source == "superadmin"
assert cred.api_key == "db-key-wins"
async def test_falls_back_to_environment(self):
db = AsyncMock()
repo = MagicMock()
repo.get_enabled = AsyncMock(return_value=None)
with patch(
"app.services.platform_api_registry.PlatformApiCredentialRepository",
return_value=repo,
), patch("app.services.platform_api_registry._env_credential") as env:
env.return_value = EffectiveCredential(
platform_id="google_books",
provider="google_books",
api_key="gbooks-env",
api_secret=None,
source="environment",
)
cred = await resolve_platform_credential("google_books", db=db, redis=None)
assert cred is not None
assert cred.source == "environment"
@pytest.mark.asyncio
class TestFetchPriceViaCredential:
async def test_rainforest_parses_buybox_price(self):
client = AsyncMock()
response = MagicMock(status_code=200)
response.json.return_value = {
"product": {
"buybox_winner": {
"price": {"value": 15.99, "currency": "USD"},
},
},
}
client.get.return_value = response
cred = EffectiveCredential(
platform_id="amazon",
provider="rainforest",
api_key="rf-key",
api_secret=None,
source="superadmin",
)
hit = await fetch_price_via_credential(
client,
cred,
"amazon",
"https://www.amazon.com/dp/B012345678",
)
assert hit is not None
assert hit.formatted == "$15.99"
assert hit.source == "api:rainforest"
async def test_scrapingbee_delegates_to_html_parser(self):
client = AsyncMock()
response = MagicMock(
status_code=200,
text=('{"price": "12.50", "title": "Test Book"}' + " " * 600),
)
client.get.return_value = response
cred = EffectiveCredential(
platform_id="barnes_noble",
provider="scrapingbee",
api_key="sb-key",
api_secret=None,
source="superadmin",
)
hit = await fetch_price_via_credential(
client,
cred,
"barnes_noble",
"https://www.barnesandnoble.com/w/book",
)
assert hit is not None
assert hit.formatted == "$12.50"
assert hit.source == "api:scrapingbee"