You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

207 lines
8.6 KiB

import datetime
from django.utils import timezone
from django.test import TestCase
from unittest.mock import patch
from django.core.files.uploadedfile import SimpleUploadedFile
from dj_language.models import Language
from apps.account.models import StudentUser, User, Notification
from apps.course.models.course import Course, CourseCategory
from apps.course.models.lesson import CourseChapter, CourseLesson, Lesson, LessonCompletion
from apps.course.models.participant import Participant
from apps.course.models.live_session import CourseLiveSession
from apps.certificate.models import Certificate
from apps.account.tasks import check_live_class_reminders_task, check_new_course_registration_task
class NotificationFlowTests(TestCase):
def setUp(self):
# Create languages
self.lang_fa, _ = Language.objects.update_or_create(
code='fa',
defaults={'name': 'Persian', 'status': True, 'countries': []}
)
self.lang_en, _ = Language.objects.update_or_create(
code='en',
defaults={'name': 'English', 'status': True, 'countries': []}
)
# Create category
self.category = CourseCategory.objects.create(
name=[{"title": "Category", "language_code": "en"}],
slug=[{"title": "category", "language_code": "en"}]
)
# Create student user
self.student = StudentUser.objects.create(
email='student_test@example.com',
username='student_test',
fullname='Test Student',
language=self.lang_fa, # Persian template check
fcm='token_student'
)
# Create English student user for template check
self.student_en = StudentUser.objects.create(
email='student_en@example.com',
username='student_en',
fullname='Test Student EN',
language=self.lang_en,
fcm='token_student_en'
)
def _create_course(self, slug, title_en, title_fa, status='ongoing'):
thumbnail = SimpleUploadedFile('thumb.jpg', b'filecontent', content_type='image/jpeg')
return Course.objects.create(
title=[
{"title": title_en, "language_code": "en"},
{"title": title_fa, "language_code": "fa"}
],
slug=[{"title": slug, "language_code": "en"}],
category=self.category,
thumbnail=thumbnail,
video_type=Course.VedioTypeChoices.YOUTUBE_LINK,
video_link='https://example.com/video',
is_online=False,
level=Course.LevelChoices.BEGINNER,
duration=10,
lessons_count=0,
description='Description',
short_description='Short description',
status=[
{"title": status, "language_code": "en"},
{"title": status, "language_code": "ru"}
],
is_free=True,
)
@patch('apps.account.notification_service.send_notification')
def test_course_access_granted_notification(self, mock_send):
# Event 1: Course Access Granted
course = self._create_course('course-access', 'Course 1', 'دوره ۱')
# Create participant (active=True by default)
Participant.objects.create(student=self.student, course=course)
# Verify notification created in DB (in Persian)
notif_fa = Notification.objects.filter(user=self.student).first()
self.assertIsNotNone(notif_fa)
self.assertEqual(notif_fa.title, "دسترسی به دوره فعال شد")
self.assertIn("دوره ۱", notif_fa.message)
# Create participant for English student
Participant.objects.create(student=self.student_en, course=course)
notif_en = Notification.objects.filter(user=self.student_en).first()
self.assertIsNotNone(notif_en)
self.assertEqual(notif_en.title, "Course Access Granted")
self.assertIn("Course 1", notif_en.message)
# Verify send_notification was called
self.assertTrue(mock_send.called)
@patch('apps.account.notification_service.send_notification')
def test_live_class_reminder_notification(self, mock_send):
# Event 2: LIVE Class Reminder
course = self._create_course('course-live', 'Course 2', 'دوره ۲')
Participant.objects.create(student=self.student, course=course)
# Create a live session starting in 2 hours
session = CourseLiveSession.objects.create(
course=course,
subject='Live Lesson 1',
started_at=timezone.now() + datetime.timedelta(hours=2),
is_cancelled=False,
reminder_sent=False
)
# Run periodic task
check_live_class_reminders_task()
# Verify reminder sent
session.refresh_from_db()
self.assertTrue(session.reminder_sent)
notif = Notification.objects.filter(user=self.student, title="یادآوری کلاس زنده").first()
self.assertIsNotNone(notif)
self.assertIn("دوره ۲", notif.message)
# Test rescheduling resets reminder_sent
session.started_at = timezone.now() + datetime.timedelta(hours=5)
session.save()
session.refresh_from_db()
self.assertFalse(session.reminder_sent)
@patch('apps.account.notification_service.send_notification')
def test_course_completed_notification(self, mock_send):
# Event 3: Course Completed
course = self._create_course('course-complete', 'Course 3', 'دوره ۳')
Participant.objects.create(student=self.student, course=course)
chapter = CourseChapter.objects.create(
course=course,
title='Chapter 1',
priority=1,
is_active=True
)
# Add 2 lessons
l1 = Lesson.objects.create(title='Lesson 1', content_type='video_file', duration=5)
cl1 = CourseLesson.objects.create(course=course, chapter=chapter, lesson=l1, priority=1, is_active=True)
l2 = Lesson.objects.create(title='Lesson 2', content_type='video_file', duration=5)
cl2 = CourseLesson.objects.create(course=course, chapter=chapter, lesson=l2, priority=2, is_active=True)
# Complete first lesson
LessonCompletion.objects.create(student=self.student, course_lesson=cl1)
self.assertFalse(Notification.objects.filter(user=self.student, title="دوره به پایان رسید").exists())
# Complete second (last) lesson
LessonCompletion.objects.create(student=self.student, course_lesson=cl2)
# Verify notification triggered
self.assertTrue(Notification.objects.filter(user=self.student, title="دوره به پایان رسید").exists())
@patch('apps.account.notification_service.send_notification')
def test_certificate_issued_notification(self, mock_send):
# Event 4: Certificate Issued
course = self._create_course('course-cert', 'Course 4', 'دوره ۴')
cert = Certificate.objects.create(
student=self.student,
course=course,
status='pending'
)
# Verify no notification yet
self.assertFalse(Notification.objects.filter(user=self.student, title="گواهی صادر شد").exists())
# Approve certificate
cert.status = 'approved'
cert.save()
# Verify notification triggered
self.assertTrue(Notification.objects.filter(user=self.student, title="گواهی صادر شد").exists())
@patch('apps.account.notification_service.send_notification')
def test_new_course_registration_notification(self, mock_send):
# Event 5: New Course Registration
student_recipient = User.objects.create(
email='student_recipient@example.com',
username='student_recipient',
fullname='Recipient Student',
user_type='student',
is_active=True,
language=self.lang_fa,
fcm='token_recipient'
)
course = self._create_course('course-new', 'New Course A', 'دوره جدید الف', status='registering')
check_new_course_registration_task()
course.refresh_from_db()
self.assertTrue(course.notified_new_registration)
notif = Notification.objects.filter(user=student_recipient, title="ثبت‌نام دوره جدید").first()
self.assertIsNotNone(notif)
self.assertIn("دوره جدید الف", notif.message)