"""Unit tests for the Patreon campaign-ID resolver.""" import asyncio import aiohttp from aioresponses import aioresponses from app.services.patreon_resolver import resolve_campaign_id CAMPAIGNS_URL = "https://www.patreon.com/api/campaigns?filter%5Bvanity%5D=mstsu&fields%5Bcampaign%5D=name" async def test_happy_path_returns_campaign_id(): with aioresponses() as mock: mock.get( CAMPAIGNS_URL, payload={"data": [{"id": "12345", "type": "campaign", "attributes": {"name": "MSTSU"}}]}, ) result = await resolve_campaign_id("mstsu", cookies_path=None) assert result == "12345" async def test_empty_data_returns_none(): with aioresponses() as mock: mock.get(CAMPAIGNS_URL, payload={"data": []}) result = await resolve_campaign_id("mstsu", cookies_path=None) assert result is None async def test_missing_data_key_returns_none(): with aioresponses() as mock: mock.get(CAMPAIGNS_URL, payload={"errors": [{"code": 1}]}) result = await resolve_campaign_id("mstsu", cookies_path=None) assert result is None async def test_missing_id_field_returns_none(): with aioresponses() as mock: mock.get(CAMPAIGNS_URL, payload={"data": [{"type": "campaign"}]}) result = await resolve_campaign_id("mstsu", cookies_path=None) assert result is None async def test_http_401_returns_none(): with aioresponses() as mock: mock.get(CAMPAIGNS_URL, status=401, body="Unauthorized") result = await resolve_campaign_id("mstsu", cookies_path=None) assert result is None async def test_network_error_returns_none(): with aioresponses() as mock: mock.get(CAMPAIGNS_URL, exception=aiohttp.ClientConnectionError("boom")) result = await resolve_campaign_id("mstsu", cookies_path=None) assert result is None async def test_timeout_returns_none(): with aioresponses() as mock: mock.get(CAMPAIGNS_URL, exception=asyncio.TimeoutError()) result = await resolve_campaign_id("mstsu", cookies_path=None) assert result is None async def test_invalid_json_returns_none(): with aioresponses() as mock: mock.get(CAMPAIGNS_URL, body="not json", content_type="text/html") result = await resolve_campaign_id("mstsu", cookies_path=None) assert result is None async def test_missing_cookies_path_proceeds_without_jar(tmp_path): """When cookies_path is None, the request still goes out (cookies are optional).""" with aioresponses() as mock: mock.get(CAMPAIGNS_URL, payload={"data": [{"id": "99", "type": "campaign"}]}) result = await resolve_campaign_id("mstsu", cookies_path=None) assert result == "99" async def test_nonexistent_cookies_path_proceeds_without_jar(tmp_path): """When cookies_path points to a missing file, don't crash — just skip the jar.""" ghost = tmp_path / "does-not-exist.txt" with aioresponses() as mock: mock.get(CAMPAIGNS_URL, payload={"data": [{"id": "99"}]}) result = await resolve_campaign_id("mstsu", cookies_path=str(ghost)) assert result == "99"