Testing blitz!

This commit is contained in:
Jack Kingsman
2026-02-10 16:47:46 -08:00
parent cf6df506d1
commit 875f197812
9 changed files with 1181 additions and 7 deletions
+194
View File
@@ -0,0 +1,194 @@
"""Tests for settings router endpoints and validation behavior."""
from unittest.mock import AsyncMock, patch
import pytest
from fastapi import HTTPException
from app.models import AppSettings, BotConfig, Favorite
from app.routers.settings import (
AppSettingsUpdate,
FavoriteRequest,
MigratePreferencesRequest,
migrate_preferences,
toggle_favorite,
update_settings,
)
def _settings(
*,
favorites: list[Favorite] | None = None,
migrated: bool = False,
max_radio_contacts: int = 200,
) -> AppSettings:
return AppSettings(
max_radio_contacts=max_radio_contacts,
favorites=favorites or [],
auto_decrypt_dm_on_advert=False,
sidebar_sort_order="recent",
last_message_times={},
preferences_migrated=migrated,
advert_interval=0,
last_advert_time=0,
bots=[],
)
class TestUpdateSettings:
@pytest.mark.asyncio
async def test_forwards_only_provided_fields(self):
updated = _settings(max_radio_contacts=321)
with patch(
"app.routers.settings.AppSettingsRepository.update",
new_callable=AsyncMock,
return_value=updated,
) as mock_update:
result = await update_settings(
AppSettingsUpdate(max_radio_contacts=321, advert_interval=3600)
)
assert result.max_radio_contacts == 321
assert mock_update.call_count == 1
assert mock_update.call_args.kwargs == {
"max_radio_contacts": 321,
"advert_interval": 3600,
}
@pytest.mark.asyncio
async def test_empty_patch_returns_current_settings(self):
current = _settings()
with (
patch(
"app.routers.settings.AppSettingsRepository.get",
new_callable=AsyncMock,
return_value=current,
) as mock_get,
patch(
"app.routers.settings.AppSettingsRepository.update",
new_callable=AsyncMock,
) as mock_update,
):
result = await update_settings(AppSettingsUpdate())
assert result == current
mock_get.assert_awaited_once()
mock_update.assert_not_awaited()
@pytest.mark.asyncio
async def test_invalid_bot_syntax_returns_400(self):
bad_bot = BotConfig(
id="bot-1",
name="BadBot",
enabled=True,
code="def bot(:\n return 'x'\n",
)
with pytest.raises(HTTPException) as exc:
await update_settings(AppSettingsUpdate(bots=[bad_bot]))
assert exc.value.status_code == 400
assert "syntax error" in exc.value.detail.lower()
class TestToggleFavorite:
@pytest.mark.asyncio
async def test_adds_when_not_favorited(self):
initial = _settings(favorites=[])
updated = _settings(favorites=[Favorite(type="contact", id="aa" * 32)])
request = FavoriteRequest(type="contact", id="aa" * 32)
with (
patch(
"app.routers.settings.AppSettingsRepository.get",
new_callable=AsyncMock,
return_value=initial,
),
patch(
"app.routers.settings.AppSettingsRepository.add_favorite",
new_callable=AsyncMock,
return_value=updated,
) as mock_add,
patch(
"app.routers.settings.AppSettingsRepository.remove_favorite",
new_callable=AsyncMock,
) as mock_remove,
):
result = await toggle_favorite(request)
assert result.favorites == updated.favorites
mock_add.assert_awaited_once_with("contact", "aa" * 32)
mock_remove.assert_not_awaited()
@pytest.mark.asyncio
async def test_removes_when_already_favorited(self):
initial = _settings(favorites=[Favorite(type="channel", id="ABCD")])
updated = _settings(favorites=[])
request = FavoriteRequest(type="channel", id="ABCD")
with (
patch(
"app.routers.settings.AppSettingsRepository.get",
new_callable=AsyncMock,
return_value=initial,
),
patch(
"app.routers.settings.AppSettingsRepository.remove_favorite",
new_callable=AsyncMock,
return_value=updated,
) as mock_remove,
patch(
"app.routers.settings.AppSettingsRepository.add_favorite",
new_callable=AsyncMock,
) as mock_add,
):
result = await toggle_favorite(request)
assert result.favorites == []
mock_remove.assert_awaited_once_with("channel", "ABCD")
mock_add.assert_not_awaited()
class TestMigratePreferences:
@pytest.mark.asyncio
async def test_maps_frontend_payload_and_returns_migrated_true(self):
request = MigratePreferencesRequest(
favorites=[FavoriteRequest(type="contact", id="aa" * 32)],
sort_order="alpha",
last_message_times={"contact-aaaaaaaaaaaa": 123},
)
settings = _settings(favorites=[Favorite(type="contact", id="aa" * 32)], migrated=True)
with patch(
"app.routers.settings.AppSettingsRepository.migrate_preferences_from_frontend",
new_callable=AsyncMock,
return_value=(settings, True),
) as mock_migrate:
response = await migrate_preferences(request)
assert response.migrated is True
assert response.settings == settings
assert mock_migrate.call_args.kwargs == {
"favorites": [{"type": "contact", "id": "aa" * 32}],
"sort_order": "alpha",
"last_message_times": {"contact-aaaaaaaaaaaa": 123},
}
@pytest.mark.asyncio
async def test_returns_migrated_false_when_already_done(self):
request = MigratePreferencesRequest(
favorites=[],
sort_order="recent",
last_message_times={},
)
settings = _settings(migrated=True)
with patch(
"app.routers.settings.AppSettingsRepository.migrate_preferences_from_frontend",
new_callable=AsyncMock,
return_value=(settings, False),
):
response = await migrate_preferences(request)
assert response.migrated is False
assert response.settings.preferences_migrated is True