/
navydragon
/
tutorCompetitionApi
Обзор
Документация
Войти
/
navydragon
/
tutorCompetitionApi
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
learning/tests.py
634 строки
26 KB
navydragon
learning
03 авг 2026, 15:06
03 авг 2026, 15:06
ad4803a
Код
Авторство
О чём код?
import base64 from django.core import mail from django.test import override_settings from django.urls import reverse from rest_framework import status from rest_framework.test import APITestCase from accounts.models import CustomUser from core.models import Setting from learning.models import LearningApplication TEST_STORAGES = { "default": { "BACKEND": "django.core.files.storage.InMemoryStorage", }, "staticfiles": { "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage", }, } class LearningApplicationAPITests(APITestCase): def setUp(self): self.password = "strong_password_123" self.user = CustomUser.objects.create_user( username="listener1", email="listener1@example.com", password=self.password, first_name="Иван", last_name="Иванов", middle_name="Иванович", phone_number="+79001234567", educational_organization="РУт МИИТ", main_position="Преподаватель", timezone="Europe/Moscow", ) self.my_url = reverse("my_learning_application") self.submit_url = reverse("submit_learning_application") self.documents_url = reverse("upload_learning_document") self.confirm_url = reverse("confirm_learning_section") self.list_url = reverse("learning_applications_list") def mark_all_sections_confirmed(self, application): application.info_confirmed = True application.consent_confirmed = True application.snils_confirmed = True application.diploma_confirmed = True application.personal_data_consent = True application.save( update_fields=[ "info_confirmed", "consent_confirmed", "snils_confirmed", "diploma_confirmed", "personal_data_consent", ] ) def authenticate(self): resp = self.client.post( reverse("user_login"), {"username": self.user.username, "password": self.password}, format="json", ) self.assertEqual(resp.status_code, status.HTTP_200_OK) self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {resp.data['access']}") def test_get_creates_empty_application(self): self.authenticate() self.assertEqual(LearningApplication.objects.count(), 0) resp = self.client.get(self.my_url) self.assertEqual(resp.status_code, status.HTTP_200_OK) self.assertEqual(LearningApplication.objects.count(), 1) application = LearningApplication.objects.get(user=self.user) self.assertEqual(application.status, LearningApplication.STATUS_FILLING) self.assertEqual(resp.data["status"], "filling") self.assertEqual(resp.data["lastName"], "Иванов") self.assertEqual(resp.data["firstName"], "Иван") self.assertEqual(resp.data["email"], "listener1@example.com") self.assertEqual(resp.data["workplace"], "РУт МИИТ") self.assertEqual(resp.data["educationLevelId"], 0) self.assertEqual(resp.data["birthDate"], {"day": "", "month": "", "year": ""}) self.assertEqual(resp.data["snilsFileName"], "") def test_get_does_not_create_duplicate(self): self.authenticate() self.client.get(self.my_url) self.client.get(self.my_url) self.assertEqual(LearningApplication.objects.count(), 1) def test_patch_updates_application_and_syncs_user(self): self.authenticate() self.client.get(self.my_url) payload = { "lastName": "Петров", "firstName": "Пётр", "middleName": "Петрович", "email": "petrov@example.com", "phone": "+79007654321", "workplace": "Новый вуз", "position": "Доцент", "birthDate": {"day": "15", "month": "03", "year": "1990"}, "gender": "male", "educationLevelId": 2, "graduationYear": "2012", "institutionName": "МГУ", "actualAddress": "Москва, ул. Примерная, 1", "addressSameAsActual": True, "registrationAddress": "Москва, ул. Регистрации, 2", "passportSeries": "1234", "passportNumber": "567890", "passportIssueDate": {"day": "01", "month": "02", "year": "2010"}, "passportIssuedBy": "ОВД", "personalDataConsent": True, "snils": "123-456-789 00", } resp = self.client.patch(self.my_url, payload, format="json") self.assertEqual(resp.status_code, status.HTTP_200_OK) application = LearningApplication.objects.get(user=self.user) self.assertEqual(application.gender, "male") self.assertEqual(application.education_level, 2) self.assertEqual(application.graduation_year, 2012) self.assertEqual(application.study_address, "Москва, ул. Примерная, 1") self.assertEqual(str(application.birth_date), "1990-03-15") self.assertTrue(application.personal_data_consent) self.user.refresh_from_db() self.assertEqual(self.user.last_name, "Петров") self.assertEqual(self.user.first_name, "Пётр") self.assertEqual(self.user.email, "petrov@example.com") self.assertEqual(self.user.phone_number, "+79007654321") self.assertEqual(self.user.educational_organization, "Новый вуз") self.assertEqual(self.user.main_position, "Доцент") self.assertEqual(resp.data["lastName"], "Петров") self.assertEqual(resp.data["studyAddress"], "Москва, ул. Примерная, 1") self.assertEqual( resp.data["birthDate"], {"day": "15", "month": "03", "year": "1990"} ) def test_patch_forbidden_when_submitted(self): self.authenticate() self.client.get(self.my_url) application = LearningApplication.objects.get(user=self.user) application.status = LearningApplication.STATUS_SUBMITTED application.save(update_fields=["status"]) resp = self.client.patch( self.my_url, {"snils": "111-111-111 11"}, format="json" ) self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN) def test_submit_requires_password_and_consent(self): self.authenticate() self.client.get(self.my_url) resp = self.client.post(self.submit_url, {"password": self.password}, format="json") self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST) application = LearningApplication.objects.get(user=self.user) application.personal_data_consent = True application.save(update_fields=["personal_data_consent"]) resp = self.client.post( self.submit_url, {"password": "wrong_password"}, format="json" ) self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST) self.mark_all_sections_confirmed(application) resp = self.client.post( self.submit_url, {"password": self.password}, format="json" ) self.assertEqual(resp.status_code, status.HTTP_200_OK) application.refresh_from_db() self.assertEqual(application.status, LearningApplication.STATUS_SUBMITTED) def test_submit_requires_all_sections_confirmed(self): self.authenticate() self.client.get(self.my_url) application = LearningApplication.objects.get(user=self.user) application.personal_data_consent = True application.save(update_fields=["personal_data_consent"]) resp = self.client.post( self.submit_url, {"password": self.password}, format="json" ) self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST) self.assertIn("раздел", resp.data["error"].lower()) @override_settings( EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend", FRONTEND_URL="http://localhost:5173", ) def test_submit_sends_email_to_admins(self): Setting.objects.update_or_create( key="request_admins", defaults={"value": "ief07@bk.ru, navydragon@inbox.ru"}, ) self.authenticate() self.client.get(self.my_url) application = LearningApplication.objects.get(user=self.user) self.mark_all_sections_confirmed(application) resp = self.client.post( self.submit_url, {"password": self.password}, format="json" ) self.assertEqual(resp.status_code, status.HTTP_200_OK) self.assertEqual(len(mail.outbox), 1) self.assertEqual( sorted(mail.outbox[0].to), sorted(["ief07@bk.ru", "navydragon@inbox.ru"]), ) self.assertIn("/staff/learning-applications", mail.outbox[0].alternatives[0][0]) @override_settings( EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend", ) def test_status_change_to_submitted_sends_email(self): Setting.objects.update_or_create( key="request_admins", defaults={"value": "admin@example.com"}, ) self.authenticate() self.client.get(self.my_url) application = LearningApplication.objects.get(user=self.user) application.status = LearningApplication.STATUS_FILLING application.save(update_fields=["status"]) mail.outbox.clear() application.status = LearningApplication.STATUS_SUBMITTED application.save(update_fields=["status"]) self.assertEqual(len(mail.outbox), 1) self.assertEqual(mail.outbox[0].to, ["admin@example.com"]) @override_settings( EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend", ) def test_resubmit_does_not_send_duplicate_email(self): Setting.objects.update_or_create( key="request_admins", defaults={"value": "admin@example.com"}, ) self.authenticate() self.client.get(self.my_url) application = LearningApplication.objects.get(user=self.user) application.status = LearningApplication.STATUS_SUBMITTED application.save(update_fields=["status"]) mail.outbox.clear() application.save() self.assertEqual(len(mail.outbox), 0) def test_submit_from_correction_required(self): self.authenticate() self.client.get(self.my_url) application = LearningApplication.objects.get(user=self.user) application.status = LearningApplication.STATUS_CORRECTION_REQUIRED self.mark_all_sections_confirmed(application) resp = self.client.post( self.submit_url, {"password": self.password}, format="json" ) self.assertEqual(resp.status_code, status.HTTP_200_OK) application.refresh_from_db() self.assertEqual(application.status, LearningApplication.STATUS_SUBMITTED) @override_settings(STORAGES=TEST_STORAGES) def test_upload_document(self): self.authenticate() self.client.get(self.my_url) content = base64.b64encode(b"%PDF-1.4 test").decode("ascii") payload = { "document_type": "snils", "filename": "snils.pdf", "file_data": f"data:application/pdf;base64,{content}", } resp = self.client.post(self.documents_url, payload, format="json") self.assertEqual(resp.status_code, status.HTTP_200_OK) self.assertEqual(resp.data["snilsFileName"], "snils.pdf") application = LearningApplication.objects.get(user=self.user) self.assertTrue(bool(application.snils_file)) self.assertIn("snils.pdf", application.snils_file.name) def test_upload_forbidden_when_submitted(self): self.authenticate() self.client.get(self.my_url) application = LearningApplication.objects.get(user=self.user) application.status = LearningApplication.STATUS_SUBMITTED application.save(update_fields=["status"]) content = base64.b64encode(b"file").decode("ascii") resp = self.client.post( self.documents_url, { "document_type": "diploma", "filename": "diploma.pdf", "file_data": f"data:application/pdf;base64,{content}", }, format="json", ) self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN) def test_confirm_section_sets_flag(self): self.authenticate() self.client.get(self.my_url) resp = self.client.post( self.confirm_url, {"section": "info", "password": self.password, "agreed": True}, format="json", ) self.assertEqual(resp.status_code, status.HTTP_200_OK) self.assertTrue(resp.data["infoConfirmed"]) application = LearningApplication.objects.get(user=self.user) self.assertTrue(application.info_confirmed) def test_confirm_consent_sets_personal_data_consent(self): self.authenticate() self.client.get(self.my_url) resp = self.client.post( self.confirm_url, {"section": "consent", "password": self.password, "agreed": True}, format="json", ) self.assertEqual(resp.status_code, status.HTTP_200_OK) self.assertTrue(resp.data["consentConfirmed"]) self.assertTrue(resp.data["personalDataConsent"]) def test_confirm_section_requires_valid_password(self): self.authenticate() self.client.get(self.my_url) resp = self.client.post( self.confirm_url, {"section": "info", "password": "wrong", "agreed": True}, format="json", ) self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST) def test_patch_resets_confirmed_flag(self): self.authenticate() self.client.get(self.my_url) application = LearningApplication.objects.get(user=self.user) application.info_confirmed = True application.snils_confirmed = True application.save(update_fields=["info_confirmed", "snils_confirmed"]) resp = self.client.patch( self.my_url, {"snils": "111-222-333 44"}, format="json" ) self.assertEqual(resp.status_code, status.HTTP_200_OK) self.assertFalse(resp.data["snilsConfirmed"]) self.assertTrue(resp.data["infoConfirmed"]) resp = self.client.patch(self.my_url, {"gender": "female"}, format="json") self.assertEqual(resp.status_code, status.HTTP_200_OK) self.assertFalse(resp.data["infoConfirmed"]) def test_patch_same_values_do_not_reset_confirmed_flags(self): self.authenticate() get_resp = self.client.get(self.my_url) self.assertEqual(get_resp.status_code, status.HTTP_200_OK) application = LearningApplication.objects.get(user=self.user) application.info_confirmed = True application.consent_confirmed = True application.save(update_fields=["info_confirmed", "consent_confirmed"]) payload = { "lastName": get_resp.data["lastName"], "firstName": get_resp.data["firstName"], "middleName": get_resp.data["middleName"], "email": get_resp.data["email"], "phone": get_resp.data["phone"], "registrationAddress": get_resp.data["registrationAddress"], "passportSeries": get_resp.data["passportSeries"], "passportNumber": get_resp.data["passportNumber"], "passportIssueDate": get_resp.data["passportIssueDate"], "passportIssuedBy": get_resp.data["passportIssuedBy"], "personalDataConsent": get_resp.data["personalDataConsent"], } resp = self.client.patch(self.my_url, payload, format="json") self.assertEqual(resp.status_code, status.HTTP_200_OK) self.assertTrue(resp.data["infoConfirmed"]) self.assertTrue(resp.data["consentConfirmed"]) class LearningApplicationListAPITests(APITestCase): def setUp(self): self.password = "strong_password_123" self.user = CustomUser.objects.create_user( username="listener2", email="listener2@example.com", password=self.password, first_name="Пётр", last_name="Петров", middle_name="Петрович", phone_number="+79001234568", educational_organization="РУт МИИТ", main_position="Преподаватель", timezone="Europe/Moscow", ) self.staff_user = CustomUser.objects.create_user( username="staff1", email="staff1@example.com", password=self.password, first_name="Стафф", last_name="Админов", middle_name="", phone_number="+79001234569", educational_organization="РУт МИИТ", main_position="Админ", timezone="Europe/Moscow", is_staff=True, ) self.list_url = reverse("learning_applications_list") LearningApplication.objects.create( user=self.user, status=LearningApplication.STATUS_SUBMITTED, ) def authenticate(self, user): resp = self.client.post( reverse("user_login"), {"username": user.username, "password": self.password}, format="json", ) self.assertEqual(resp.status_code, status.HTTP_200_OK) self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {resp.data['access']}") def test_list_forbidden_for_non_staff(self): self.authenticate(self.user) resp = self.client.get(self.list_url) self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN) def test_list_allowed_for_staff(self): self.authenticate(self.staff_user) resp = self.client.get(self.list_url) self.assertEqual(resp.status_code, status.HTTP_200_OK) self.assertEqual(resp.data["count"], 1) self.assertEqual(resp.data["results"][0]["lastName"], "Петров") def test_list_search_by_last_name(self): self.authenticate(self.staff_user) resp = self.client.get(self.list_url, {"search": "Петров"}) self.assertEqual(resp.status_code, status.HTTP_200_OK) self.assertEqual(resp.data["count"], 1) resp = self.client.get(self.list_url, {"search": "Сидоров"}) self.assertEqual(resp.status_code, status.HTTP_200_OK) self.assertEqual(resp.data["count"], 0) class LearningApplicationStaffActionsAPITests(APITestCase): def setUp(self): self.password = "strong_password_123" self.user = CustomUser.objects.create_user( username="listener_review", email="listener_review@example.com", password=self.password, first_name="Анна", last_name="Тестова", middle_name="Ивановна", phone_number="+79001234570", educational_organization="РУТ МИИТ", main_position="Преподаватель", timezone="Europe/Moscow", ) self.staff_user = CustomUser.objects.create_user( username="staff_review", email="staff_review@example.com", password=self.password, first_name="Стафф", last_name="Ревизор", middle_name="", phone_number="+79001234571", educational_organization="РУТ МИИТ", main_position="Админ", timezone="Europe/Moscow", is_staff=True, ) self.application = LearningApplication.objects.create( user=self.user, status=LearningApplication.STATUS_SUBMITTED, info_confirmed=True, consent_confirmed=True, snils_confirmed=True, diploma_confirmed=True, ) self.detail_url = reverse( "learning_application_detail", kwargs={"application_id": self.application.id}, ) self.approve_url = reverse( "learning_application_approve", kwargs={"application_id": self.application.id}, ) self.correction_url = reverse( "learning_application_request_correction", kwargs={"application_id": self.application.id}, ) self.reject_url = reverse( "learning_application_reject", kwargs={"application_id": self.application.id}, ) def authenticate(self, user): resp = self.client.post( reverse("user_login"), {"username": user.username, "password": self.password}, format="json", ) self.assertEqual(resp.status_code, status.HTTP_200_OK) self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {resp.data['access']}") def test_detail_forbidden_for_non_staff(self): self.authenticate(self.user) resp = self.client.get(self.detail_url) self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN) def test_detail_allowed_for_staff(self): self.authenticate(self.staff_user) resp = self.client.get(self.detail_url) self.assertEqual(resp.status_code, status.HTTP_200_OK) self.assertEqual(resp.data["id"], self.application.id) self.assertEqual(resp.data["lastName"], "Тестова") self.assertIn("snilsFileUrl", resp.data) self.assertIn("organizerComment", resp.data) @override_settings(EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend") def test_approve_sends_email(self): self.authenticate(self.staff_user) resp = self.client.post(self.approve_url, {}, format="json") self.assertEqual(resp.status_code, status.HTTP_200_OK) self.application.refresh_from_db() self.assertEqual(self.application.status, LearningApplication.STATUS_APPROVED) self.assertEqual(len(mail.outbox), 1) self.assertEqual(mail.outbox[0].to, ["listener_review@example.com"]) self.assertIn("одобрена", mail.outbox[0].subject.lower()) @override_settings(EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend") def test_request_correction_unconfirms_sections_and_sends_email(self): self.authenticate(self.staff_user) resp = self.client.post( self.correction_url, { "comment": "Исправьте СНИЛС и диплом", "sectionsToRevise": ["snils", "diploma"], }, format="json", ) self.assertEqual(resp.status_code, status.HTTP_200_OK) self.application.refresh_from_db() self.assertEqual( self.application.status, LearningApplication.STATUS_CORRECTION_REQUIRED ) self.assertEqual(self.application.organizer_comment, "Исправьте СНИЛС и диплом") self.assertTrue(self.application.info_confirmed) self.assertTrue(self.application.consent_confirmed) self.assertFalse(self.application.snils_confirmed) self.assertFalse(self.application.diploma_confirmed) self.assertEqual(len(mail.outbox), 1) self.assertIn("СНИЛС", mail.outbox[0].body) self.assertIn("Диплом", mail.outbox[0].body) self.assertIn("Исправьте СНИЛС и диплом", mail.outbox[0].body) self.assertIn("/person/learning/listener", mail.outbox[0].body) def test_request_correction_requires_comment_and_sections(self): self.authenticate(self.staff_user) resp = self.client.post( self.correction_url, {"comment": "", "sectionsToRevise": ["snils"]}, format="json", ) self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST) resp = self.client.post( self.correction_url, {"comment": "Нужны правки", "sectionsToRevise": []}, format="json", ) self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST) @override_settings(EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend") def test_reject_sends_email(self): self.authenticate(self.staff_user) resp = self.client.post( self.reject_url, {"comment": "Документы не соответствуют требованиям"}, format="json", ) self.assertEqual(resp.status_code, status.HTTP_200_OK) self.application.refresh_from_db() self.assertEqual(self.application.status, LearningApplication.STATUS_REJECTED) self.assertEqual( self.application.organizer_comment, "Документы не соответствуют требованиям", ) self.assertEqual(len(mail.outbox), 1) self.assertIn("отклонена", mail.outbox[0].subject.lower()) self.assertIn("Документы не соответствуют требованиям", mail.outbox[0].body) def test_actions_forbidden_when_not_submitted(self): self.application.status = LearningApplication.STATUS_APPROVED self.application.save(update_fields=["status"]) self.authenticate(self.staff_user) resp = self.client.post(self.approve_url, {}, format="json") self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST) resp = self.client.post( self.correction_url, {"comment": "Правки", "sectionsToRevise": ["info"]}, format="json", ) self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST) resp = self.client.post( self.reject_url, {"comment": "Отклонено"}, format="json" ) self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)