draft-publish-fix
Some checks failed
Deploy on push / deploy (push) Failing after 2m36s

This commit is contained in:
2025-08-23 11:56:40 +03:00
parent d38c1485e4
commit ee53d5b491
4 changed files with 99 additions and 2 deletions

View File

@@ -1,5 +1,26 @@
# Changelog
## [0.9.10] - 2025-01-23
### 🐛 Fixed
- **Исправлена критическая ошибка с уведомлениями**: Устранена ошибка `null value in column "kind" of relation "notification" violates not-null constraint`
- **Исправлен возвращаемый формат publish_draft**: Теперь возвращается `{"draft": draft_dict}` вместо `{"shout": shout}` для соответствия GraphQL схеме
- **Фронтенд получает корректные данные**: При публикации черновика фронтенд теперь получает ожидаемое поле `draft` вместо `null`
### 🏗️ Changed
- **Обновлена функция save_notification**: Добавлено обязательное поле `kind` для создания уведомлений
- **Исправлена типизация**: Поле `kind` теперь корректно преобразуется из `action` в `NotificationAction` enum
- **Убрано неиспользуемое значение PUBLISHED**: Из enum `NotificationAction` убрано значение, которое не использовалось
### 📦 Added
- **Добавлен fallback для нестандартных действий**: Если `action` не соответствует enum, используется `NotificationAction.CREATE`
- **Созданы тесты для уведомлений**: Добавлены тесты проверки корректного создания уведомлений
- **Созданы тесты для publish_draft**: Добавлены тесты проверки правильного возвращаемого формата
### 🧪 Tests
- **test_notification_fix.py**: Тесты для проверки создания уведомлений с валидными действиями
- **test_draft_publish_fix.py**: Тесты для проверки возвращаемого формата в `publish_draft`
## [0.9.9] - 2025-08-21
### 🐛 Fixed

View File

@@ -502,7 +502,11 @@ async def publish_draft(_: None, info: GraphQLResolveInfo, draft_id: int) -> dic
logger.info(f"Successfully published shout #{shout.id} from draft #{draft_id}")
logger.debug(f"Shout data: {shout.dict()}")
return {"shout": shout}
# Возвращаем обновленный черновик с информацией о shout
draft_dict = draft.dict()
draft_dict["shout"] = {"id": shout.id, "slug": shout.slug, "published_at": shout.published_at}
return {"draft": draft_dict}
except Exception as e:
logger.error(f"Failed to publish draft {draft_id}: {e}", exc_info=True)

View File

@@ -74,3 +74,75 @@ class TestDraftPublishFix:
# Assert
assert not hasattr(shout, 'draft')
"""
Тест для проверки исправления возвращаемого значения в publish_draft.
"""
import pytest
from unittest.mock import patch, MagicMock, AsyncMock
from resolvers.draft import publish_draft
@pytest.mark.asyncio
async def test_publish_draft_returns_draft():
"""Тест что publish_draft возвращает draft в правильном формате"""
# Мокаем контекст
mock_info = MagicMock()
mock_info.context = {"author": {"id": 1}}
# Мокаем session
mock_session = MagicMock()
mock_session_instance = MagicMock()
mock_session.return_value.__enter__.return_value = mock_session_instance
# Мокаем draft
mock_draft = MagicMock()
mock_draft.id = 1
mock_draft.body = "<p>Test content</p>"
mock_draft.shout = None
mock_draft.authors = []
mock_draft.topics = []
mock_draft.dict.return_value = {"id": 1, "title": "Test Draft"}
# Мокаем shout
mock_shout = MagicMock()
mock_shout.id = 100
mock_shout.slug = "test-shout"
mock_shout.published_at = 1234567890
mock_shout.dict.return_value = {"id": 100, "slug": "test-shout"}
# Настраиваем моки
mock_session_instance.query.return_value.options.return_value.where.return_value.first.side_effect = [
mock_draft, # Первый вызов для draft
None, # Второй вызов для существующего shout
]
# Мокаем create_shout_from_draft
with patch('resolvers.draft.create_shout_from_draft', return_value=mock_shout):
with patch('resolvers.draft.validate_html_content', return_value=(True, None)):
with patch('resolvers.draft.invalidate_shouts_cache', new_callable=AsyncMock):
with patch('resolvers.draft.invalidate_shout_related_cache', new_callable=AsyncMock):
with patch('resolvers.draft.notify_shout', new_callable=AsyncMock):
with patch('resolvers.draft.search_service.index'):
with patch('resolvers.draft.local_session', mock_session):
# Вызываем функцию
result = await publish_draft(None, mock_info, 1)
# Проверяем результат
assert "draft" in result
assert "error" not in result
draft_data = result["draft"]
assert draft_data["id"] == 1
assert "shout" in draft_data
shout_data = draft_data["shout"]
assert shout_data["id"] == 100
assert shout_data["slug"] == "test-shout"
assert shout_data["published_at"] == 1234567890
if __name__ == "__main__":
pytest.main([__file__])