feat(fc3c): PatreonResolver — vanity → campaign_id via requests
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from backend.app.services.patreon_resolver import resolve_campaign_id
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_resolves_on_happy_path():
|
||||
fake_response = MagicMock()
|
||||
fake_response.status_code = 200
|
||||
fake_response.json.return_value = {"data": [{"id": "12345678", "type": "campaign"}]}
|
||||
with patch("backend.app.services.patreon_resolver.requests.get", return_value=fake_response):
|
||||
result = await resolve_campaign_id("alice", cookies_path=None)
|
||||
assert result == "12345678"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_returns_none_on_401():
|
||||
fake_response = MagicMock()
|
||||
fake_response.status_code = 401
|
||||
fake_response.json.return_value = {}
|
||||
with patch("backend.app.services.patreon_resolver.requests.get", return_value=fake_response):
|
||||
result = await resolve_campaign_id("alice", cookies_path=None)
|
||||
assert result is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_returns_none_on_network_error():
|
||||
import requests
|
||||
with patch(
|
||||
"backend.app.services.patreon_resolver.requests.get",
|
||||
side_effect=requests.ConnectionError("nope"),
|
||||
):
|
||||
result = await resolve_campaign_id("alice", cookies_path=None)
|
||||
assert result is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_returns_none_on_empty_data():
|
||||
fake_response = MagicMock()
|
||||
fake_response.status_code = 200
|
||||
fake_response.json.return_value = {"data": []}
|
||||
with patch("backend.app.services.patreon_resolver.requests.get", return_value=fake_response):
|
||||
result = await resolve_campaign_id("alice", cookies_path=None)
|
||||
assert result is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_returns_none_on_malformed_json():
|
||||
fake_response = MagicMock()
|
||||
fake_response.status_code = 200
|
||||
fake_response.json.side_effect = ValueError("not json")
|
||||
with patch("backend.app.services.patreon_resolver.requests.get", return_value=fake_response):
|
||||
result = await resolve_campaign_id("alice", cookies_path=None)
|
||||
assert result is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_missing_cookies_file_does_not_raise(tmp_path):
|
||||
fake_response = MagicMock()
|
||||
fake_response.status_code = 200
|
||||
fake_response.json.return_value = {"data": [{"id": "1", "type": "campaign"}]}
|
||||
with patch("backend.app.services.patreon_resolver.requests.get", return_value=fake_response):
|
||||
result = await resolve_campaign_id(
|
||||
"alice", cookies_path=str(tmp_path / "does-not-exist.txt")
|
||||
)
|
||||
assert result == "1"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_loads_cookies_file_when_present(tmp_path):
|
||||
cookies = tmp_path / "cookies.txt"
|
||||
cookies.write_text(
|
||||
"# Netscape HTTP Cookie File\n"
|
||||
".patreon.com\tTRUE\t/\tTRUE\t1700000000\tsession_id\tabc\n"
|
||||
)
|
||||
fake_response = MagicMock()
|
||||
fake_response.status_code = 200
|
||||
fake_response.json.return_value = {"data": [{"id": "9", "type": "campaign"}]}
|
||||
with patch(
|
||||
"backend.app.services.patreon_resolver.requests.get",
|
||||
return_value=fake_response,
|
||||
) as mock_get:
|
||||
result = await resolve_campaign_id("alice", cookies_path=str(cookies))
|
||||
assert result == "9"
|
||||
_, kwargs = mock_get.call_args
|
||||
assert kwargs.get("cookies") is not None
|
||||
Reference in New Issue
Block a user