audio streaming app plyr.fm
38
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 2026.0102.192555 111 lines 4.3 kB view raw
1"""tests for constellation client.""" 2 3from unittest.mock import AsyncMock, MagicMock, patch 4 5import pytest 6 7from backend._internal.constellation import get_like_count, get_like_count_safe 8 9 10@pytest.fixture 11def mock_settings(): 12 """mock settings with like_collection.""" 13 with patch("backend._internal.constellation.settings") as mock: 14 mock.atproto.like_collection = "fm.plyr.dev.like" 15 yield mock 16 17 18class TestGetLikeCount: 19 """tests for get_like_count.""" 20 21 async def test_returns_count_from_response(self, mock_settings): 22 """should return count from constellation response.""" 23 mock_response = MagicMock() 24 mock_response.json.return_value = {"count": 42} 25 mock_response.raise_for_status = MagicMock() 26 27 with patch("backend._internal.constellation.httpx.AsyncClient") as mock_client: 28 mock_client.return_value.__aenter__.return_value.get = AsyncMock( 29 return_value=mock_response 30 ) 31 32 result = await get_like_count("at://did:plc:xxx/fm.plyr.track/abc") 33 34 assert result == 42 35 36 async def test_calls_correct_endpoint(self, mock_settings): 37 """should call constellation with correct params.""" 38 mock_response = MagicMock() 39 mock_response.json.return_value = {"count": 0} 40 mock_response.raise_for_status = MagicMock() 41 42 with patch("backend._internal.constellation.httpx.AsyncClient") as mock_client: 43 mock_get = AsyncMock(return_value=mock_response) 44 mock_client.return_value.__aenter__.return_value.get = mock_get 45 46 await get_like_count("at://did:plc:xxx/fm.plyr.track/abc") 47 48 mock_get.assert_called_once_with( 49 "https://constellation.microcosm.blue/links/count", 50 params={ 51 "target": "at://did:plc:xxx/fm.plyr.track/abc", 52 "collection": "fm.plyr.dev.like", 53 "path": ".subject.uri", 54 }, 55 ) 56 57 async def test_raises_on_http_error(self, mock_settings): 58 """should raise when constellation returns error.""" 59 mock_response = MagicMock() 60 mock_response.raise_for_status.side_effect = Exception("500 error") 61 62 with patch("backend._internal.constellation.httpx.AsyncClient") as mock_client: 63 mock_client.return_value.__aenter__.return_value.get = AsyncMock( 64 return_value=mock_response 65 ) 66 67 with pytest.raises(Exception, match="500 error"): 68 await get_like_count("at://did:plc:xxx/fm.plyr.track/abc") 69 70 71class TestGetLikeCountSafe: 72 """tests for get_like_count_safe.""" 73 74 async def test_returns_count_on_success(self, mock_settings): 75 """should return count when successful.""" 76 mock_response = MagicMock() 77 mock_response.json.return_value = {"count": 10} 78 mock_response.raise_for_status = MagicMock() 79 80 with patch("backend._internal.constellation.httpx.AsyncClient") as mock_client: 81 mock_client.return_value.__aenter__.return_value.get = AsyncMock( 82 return_value=mock_response 83 ) 84 85 result = await get_like_count_safe("at://did:plc:xxx/fm.plyr.track/abc") 86 87 assert result == 10 88 89 async def test_returns_fallback_on_error(self, mock_settings): 90 """should return fallback when constellation fails.""" 91 with patch("backend._internal.constellation.httpx.AsyncClient") as mock_client: 92 mock_client.return_value.__aenter__.return_value.get = AsyncMock( 93 side_effect=Exception("connection failed") 94 ) 95 96 result = await get_like_count_safe( 97 "at://did:plc:xxx/fm.plyr.track/abc", fallback=99 98 ) 99 100 assert result == 99 101 102 async def test_default_fallback_is_zero(self, mock_settings): 103 """should default to 0 fallback.""" 104 with patch("backend._internal.constellation.httpx.AsyncClient") as mock_client: 105 mock_client.return_value.__aenter__.return_value.get = AsyncMock( 106 side_effect=Exception("connection failed") 107 ) 108 109 result = await get_like_count_safe("at://did:plc:xxx/fm.plyr.track/abc") 110 111 assert result == 0