""" Unit тесты для уведомлений модуля Requests Запуск: pytest backend/requests_app/tests/test_notifications.py -v или python manage.py test requests_app.tests.test_notifications """ from unittest.mock import patch import pytest from django.contrib.auth import get_user_model from django.test import TestCase from communications.comments_helpers import create_comment from employees.models import Department from notifications.models import Notification from requests_app.models import Request from requests_app.notifications.handlers import notify_new_request Employee = get_user_model() @pytest.mark.django_db class TestRequestNotifications(TestCase): """Тесты уведомлений при работе с заявлениями""" def setUp(self): """Подготовка тестовых данных""" # Создаем тестовых пользователей self.author = Employee.objects.create_user( username="test_author", email="author@test.com", phone_number="+79990000001", first_name="Иван", last_name="Автор", email_verified=True, send_activation_email=False, ) self.recipient = Employee.objects.create_user( username="test_recipient", email="recipient@test.com", phone_number="+79990000002", first_name="Петр", last_name="Получатель", email_verified=True, send_activation_email=False, ) self.cc_user = Employee.objects.create_user( username="test_cc", email="cc@test.com", phone_number="+79990000003", first_name="Сидор", last_name="Копия", email_verified=True, send_activation_email=False, ) self.approver = Employee.objects.create_user( username="test_approver", email="approver@test.com", phone_number="+79990000004", first_name="Алексей", last_name="Согласующий", email_verified=True, send_activation_email=False, ) for employee in [ self.author, self.recipient, self.cc_user, self.approver, ]: employee.email_verified = True employee.is_active = True employee.save(update_fields=["email_verified", "is_active"]) # Создаем отдел self.department = Department.objects.create( name="Тестовый отдел", head=self.approver ) def test_new_request_notification_to_recipient(self): """Тест: уведомление получателю при создании заявления""" # Создаем заявление request = Request.objects.create( employee=self.author, type="vacation", comment="Отпуск с 1 по 10 июля", status="pending", department=self.department, ) # Устанавливаем получателя (триггерит сигнал) request.recipients.set([self.recipient]) # Проверяем что уведомление создано notifications = Notification.objects.filter( recipient=self.recipient, verb="request_new" ) self.assertEqual(notifications.count(), 1) notif = notifications.first() # Проверяем содержимое self.assertEqual( notif.data["title"], "Новое заявление", ) self.assertIn( "Иван Автор адресовал вам заявление", notif.description, ) self.assertEqual(notif.data["request_id"], request.id) self.assertEqual(notif.data["is_primary_recipient"], True) self.assertTrue(notif.unread) def test_new_request_notification_to_cc(self): """Тест: уведомление пользователю в копии""" request = Request.objects.create( employee=self.author, type="vacation", comment="Отпуск", status="pending", department=self.department, ) request.recipients.set([self.recipient]) request.cc_users.set([self.cc_user]) Notification.objects.all().delete() notify_new_request(request) # Проверяем уведомление для CC notifications = Notification.objects.filter( recipient=self.cc_user, verb="request_new" ) self.assertEqual(notifications.count(), 1) notif = notifications.first() self.assertEqual(notif.data["is_cc"], True) self.assertEqual( notif.data["title"], "Новое заявление", ) self.assertIn( "Иван Автор поставил вас в копию заявления", notif.description, ) def test_new_request_notification_to_approver(self): """Тест: уведомление согласующему при создании заявления""" request = Request.objects.create( employee=self.author, type="vacation", comment="Отпуск", status="pending", department=self.department, ) request.approver = self.approver Notification.objects.all().delete() notify_new_request(request) notif = Notification.objects.get( recipient=self.approver, verb="request_new", ) self.assertEqual( notif.data["title"], "Новое заявление", ) self.assertIn( "Иван Автор отправил заявление вам на согласование", notif.description, ) self.assertEqual(notif.data["is_approver"], True) def test_new_request_notification_to_department(self): """Тест: уведомление отделу при создании заявления""" request = Request.objects.create( employee=self.author, type="vacation", comment="Отпуск", status="pending", department=self.department, ) Notification.objects.all().delete() notify_new_request(request) notif = Notification.objects.get( recipient=self.approver, verb="request_new", ) self.assertEqual( notif.data["title"], "Новое заявление", ) self.assertIn( "Иван Автор направил заявление в отдел", notif.description, ) self.assertEqual(notif.data["is_approver"], False) def test_request_approval_notification(self): """Тест: уведомление об одобрении заявления""" request = Request.objects.create( employee=self.author, type="vacation", comment="Отпуск", status="pending", department=self.department, approver=self.approver, ) request.recipients.set([self.recipient]) # Очищаем уведомления о создании Notification.objects.all().delete() # Одобряем заявление request.approve(self.approver) # Проверяем уведомление автору notifications = Notification.objects.filter( recipient=self.author, verb="request_approved" ) self.assertEqual(notifications.count(), 1) notif = notifications.first() self.assertIn("одобрено", notif.data["title"]) self.assertEqual(notif.data["new_status"], "approved") self.assertEqual(notif.data["approver_id"], self.approver.id) def test_request_rejection_notification(self): """Тест: уведомление об отклонении заявления""" request = Request.objects.create( employee=self.author, type="vacation", comment="Отпуск", status="pending", department=self.department, approver=self.approver, ) request.recipients.set([self.recipient]) Notification.objects.all().delete() # Отклоняем заявление request.reject(self.approver) notifications = Notification.objects.filter( recipient=self.author, verb="request_rejected" ) self.assertEqual(notifications.count(), 1) notif = notifications.first() self.assertIn("отклонено", notif.data["title"]) self.assertEqual(notif.data["new_status"], "rejected") def test_comment_notification(self): """Тест: уведомление о комментарии к заявлению""" request = Request.objects.create( employee=self.author, type="vacation", comment="Отпуск", status="pending", department=self.department, ) request.recipients.set([self.recipient]) Notification.objects.all().delete() # Добавляем комментарий comment = create_comment( obj=request, author=self.recipient, content="Нужна справка" ) # Проверяем уведомление автору notifications = Notification.objects.filter( recipient=self.author, verb="commented" ) self.assertEqual(notifications.count(), 1) notif = notifications.first() self.assertIn("комментарий", notif.data["title"]) self.assertEqual(notif.data["message_id"], comment.id) self.assertIn("Нужна справка", notif.description) def test_no_notification_to_author_on_own_comment(self): """Тест: автор не получает уведомление о своем комментарии""" request = Request.objects.create( employee=self.author, type="vacation", comment="Отпуск", status="pending", department=self.department, ) request.recipients.set([self.recipient]) Notification.objects.all().delete() # Автор комментирует свое заявление create_comment( obj=request, author=self.author, content="Дополнительная информация" ) # Автор НЕ должен получить уведомление notifications = Notification.objects.filter( recipient=self.author, verb="commented" ) self.assertEqual(notifications.count(), 0) def test_multiple_recipients_notification(self): """Тест: уведомления всем получателям""" request = Request.objects.create( employee=self.author, type="vacation", comment="Отпуск", status="pending", department=self.department, ) # Множественные получатели request.recipients.set([self.recipient, self.cc_user]) # Проверяем что оба получили уведомления notifications = Notification.objects.filter(verb="request_new") recipients = [n.recipient for n in notifications] self.assertIn(self.recipient, recipients) self.assertIn(self.cc_user, recipients) @patch("notifications.channels.route_notification_to_channels") def test_channels_called_on_notification(self, mock_channels): """Тест: channels.py вызывается при создании уведомления""" request = Request.objects.create( employee=self.author, type="vacation", comment="Отпуск", status="pending", department=self.department, ) request.recipients.set([self.recipient]) # Проверяем что channels.py был вызван # (он должен вызываться автоматически через post_save) notification = Notification.objects.filter( recipient=self.recipient, verb="request_new" ).first() # Просто проверяем что уведомление создано # (channels.py запустится автоматически через сигнал) self.assertIsNotNone(notification)