This commit is contained in:
4
main.py
4
main.py
@@ -216,7 +216,9 @@ async def lifespan(app: Starlette):
|
|||||||
try:
|
try:
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
result = subprocess.run(["alembic", "upgrade", "head"], check=False, capture_output=True, text=True, cwd="/app")
|
result = subprocess.run(
|
||||||
|
["alembic", "upgrade", "head"], check=False, capture_output=True, text=True, cwd="/app"
|
||||||
|
)
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
print("[lifespan] Database migrations completed successfully")
|
print("[lifespan] Database migrations completed successfully")
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -494,7 +494,7 @@ async def publish_draft(_: None, info: GraphQLResolveInfo, draft_id: int) -> dic
|
|||||||
await invalidate_shout_related_cache(shout, author_id)
|
await invalidate_shout_related_cache(shout, author_id)
|
||||||
|
|
||||||
# Уведомляем о публикации
|
# Уведомляем о публикации
|
||||||
await notify_shout(shout.dict(), "published")
|
await notify_shout(shout.dict(), "create")
|
||||||
|
|
||||||
# Обновляем поисковый индекс
|
# Обновляем поисковый индекс
|
||||||
search_service.index(shout)
|
search_service.index(shout)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from typing import Any
|
|||||||
|
|
||||||
import orjson
|
import orjson
|
||||||
|
|
||||||
from orm.notification import Notification
|
from orm.notification import Notification, NotificationAction
|
||||||
from orm.reaction import Reaction
|
from orm.reaction import Reaction
|
||||||
from orm.shout import Shout
|
from orm.shout import Shout
|
||||||
from storage.db import local_session
|
from storage.db import local_session
|
||||||
@@ -21,7 +21,15 @@ def save_notification(action: str, entity: str, payload: dict[Any, Any] | str |
|
|||||||
payload = {"id": payload.id}
|
payload = {"id": payload.id}
|
||||||
|
|
||||||
with local_session() as session:
|
with local_session() as session:
|
||||||
n = Notification(action=action, entity=entity, payload=payload)
|
# Преобразуем action в NotificationAction enum для поля kind
|
||||||
|
try:
|
||||||
|
kind = NotificationAction.from_string(action)
|
||||||
|
except ValueError:
|
||||||
|
# Fallback: создаем NotificationAction с пользовательским значением
|
||||||
|
# TODO: базовое значение для нестандартных действий
|
||||||
|
kind = NotificationAction.CREATE
|
||||||
|
|
||||||
|
n = Notification(action=action, entity=entity, payload=payload, kind=kind)
|
||||||
session.add(n)
|
session.add(n)
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
|
|||||||
78
tests/test_notification_fix.py
Normal file
78
tests/test_notification_fix.py
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
"""
|
||||||
|
Тест для проверки исправления проблемы с полем kind в уведомлениях.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from unittest.mock import patch, MagicMock
|
||||||
|
|
||||||
|
from services.notify import save_notification
|
||||||
|
from orm.notification import NotificationAction
|
||||||
|
|
||||||
|
|
||||||
|
def test_save_notification_with_create_action():
|
||||||
|
"""Тест создания уведомления с действием create для shout"""
|
||||||
|
with patch('services.notify.local_session') as mock_session:
|
||||||
|
mock_session_instance = MagicMock()
|
||||||
|
mock_session.return_value.__enter__.return_value = mock_session_instance
|
||||||
|
|
||||||
|
# Тестируем с действием create для shout
|
||||||
|
save_notification("create", "shout", {"id": 1})
|
||||||
|
|
||||||
|
# Проверяем, что уведомление создано с правильным kind
|
||||||
|
mock_session_instance.add.assert_called_once()
|
||||||
|
notification = mock_session_instance.add.call_args[0][0]
|
||||||
|
assert notification.kind == NotificationAction.CREATE
|
||||||
|
assert notification.action == "create"
|
||||||
|
assert notification.entity == "shout"
|
||||||
|
|
||||||
|
|
||||||
|
def test_save_notification_with_update_action():
|
||||||
|
"""Тест создания уведомления с действием update"""
|
||||||
|
with patch('services.notify.local_session') as mock_session:
|
||||||
|
mock_session_instance = MagicMock()
|
||||||
|
mock_session.return_value.__enter__.return_value = mock_session_instance
|
||||||
|
|
||||||
|
# Тестируем с действием update
|
||||||
|
save_notification("update", "shout", {"id": 1})
|
||||||
|
|
||||||
|
# Проверяем, что уведомление создано с правильным kind
|
||||||
|
mock_session_instance.add.assert_called_once()
|
||||||
|
notification = mock_session_instance.add.call_args[0][0]
|
||||||
|
assert notification.kind == NotificationAction.UPDATE
|
||||||
|
assert notification.action == "update"
|
||||||
|
assert notification.entity == "shout"
|
||||||
|
|
||||||
|
|
||||||
|
def test_save_notification_with_invalid_action():
|
||||||
|
"""Тест создания уведомления с невалидным действием (fallback)"""
|
||||||
|
with patch('services.notify.local_session') as mock_session:
|
||||||
|
mock_session_instance = MagicMock()
|
||||||
|
mock_session.return_value.__enter__.return_value = mock_session_instance
|
||||||
|
|
||||||
|
# Тестируем с невалидным действием
|
||||||
|
save_notification("invalid_action", "shout", {"id": 1})
|
||||||
|
|
||||||
|
# Проверяем, что уведомление создано с fallback значением
|
||||||
|
mock_session_instance.add.assert_called_once()
|
||||||
|
notification = mock_session_instance.add.call_args[0][0]
|
||||||
|
assert notification.kind == "invalid_action" # fallback
|
||||||
|
assert notification.action == "invalid_action"
|
||||||
|
assert notification.entity == "shout"
|
||||||
|
|
||||||
|
|
||||||
|
def test_save_notification_with_none_payload():
|
||||||
|
"""Тест создания уведомления с None payload (должно вернуться без создания)"""
|
||||||
|
with patch('services.notify.local_session') as mock_session:
|
||||||
|
mock_session_instance = MagicMock()
|
||||||
|
mock_session.return_value.__enter__.return_value = mock_session_instance
|
||||||
|
|
||||||
|
# Тестируем с None payload
|
||||||
|
save_notification("create", "shout", None)
|
||||||
|
|
||||||
|
# Проверяем, что уведомление не создавалось
|
||||||
|
mock_session_instance.add.assert_not_called()
|
||||||
|
mock_session_instance.commit.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
pytest.main([__file__])
|
||||||
Reference in New Issue
Block a user