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.
 
 
 
 

174 lines
6.7 KiB

from io import StringIO
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.management import call_command
from django.test import TestCase
from apps.account.models import ProfessorUser
from apps.course.models.course import Course, CourseCategory
from apps.course.models.lesson import CourseChapter, CourseLesson, Lesson
class LessonsCountSyncTests(TestCase):
def setUp(self):
self.professor = ProfessorUser.objects.create(
email='prof-sync@example.com',
fullname='Professor Sync',
experience_years=5,
)
self.category = CourseCategory.objects.create(
name='Sync Category',
slug='sync-category',
)
def _create_course(self, slug, title, lessons_count=0):
thumbnail = SimpleUploadedFile(f'{slug}.jpg', b'filecontent', content_type='image/jpeg')
return Course.objects.create(
title=title,
slug=slug,
category=self.category,
professor=self.professor,
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=lessons_count,
description='Description',
short_description='Short description',
status=Course.StatusChoices.ONGOING,
is_free=True,
)
def _create_chapter(self, course, title='Chapter', priority=1):
return CourseChapter.objects.create(
course=course,
title=title,
priority=priority,
is_active=True,
)
def _create_course_lesson(self, course, chapter=None, title='Lesson', is_active=True, priority=1):
if chapter is None:
chapter = self._create_chapter(course, title=f'{course.title} Chapter', priority=priority)
lesson = Lesson.objects.create(
title=title,
content_type=Lesson.ContentTypeChoices.VIDEO_FILE,
duration=5,
)
return CourseLesson.objects.create(
course=course,
chapter=chapter,
lesson=lesson,
priority=priority,
is_active=is_active,
)
def test_creating_active_course_lesson_updates_lessons_count(self):
course = self._create_course('create-active-course', 'Create Active Course')
self._create_course_lesson(course, title='Lesson 1')
course.refresh_from_db()
self.assertEqual(course.lessons_count, 1)
def test_deleting_active_course_lesson_updates_lessons_count(self):
course = self._create_course('delete-active-course', 'Delete Active Course')
course_lesson = self._create_course_lesson(course, title='Lesson 1')
course.refresh_from_db()
self.assertEqual(course.lessons_count, 1)
course_lesson.delete()
course.refresh_from_db()
self.assertEqual(course.lessons_count, 0)
def test_toggling_is_active_updates_lessons_count(self):
course = self._create_course('toggle-active-course', 'Toggle Active Course')
course_lesson = self._create_course_lesson(course, title='Lesson 1', is_active=False)
course.refresh_from_db()
self.assertEqual(course.lessons_count, 0)
course_lesson.is_active = True
course_lesson.save()
course.refresh_from_db()
self.assertEqual(course.lessons_count, 1)
course_lesson.is_active = False
course_lesson.save()
course.refresh_from_db()
self.assertEqual(course.lessons_count, 0)
def test_moving_course_lesson_updates_old_and_new_course_counts(self):
old_course = self._create_course('old-course', 'Old Course')
new_course = self._create_course('new-course', 'New Course')
old_chapter = self._create_chapter(old_course, title='Old Chapter', priority=1)
new_chapter = self._create_chapter(new_course, title='New Chapter', priority=1)
course_lesson = self._create_course_lesson(
old_course,
chapter=old_chapter,
title='Lesson 1',
is_active=True,
priority=1,
)
old_course.refresh_from_db()
new_course.refresh_from_db()
self.assertEqual(old_course.lessons_count, 1)
self.assertEqual(new_course.lessons_count, 0)
course_lesson.chapter = new_chapter
course_lesson.save()
old_course.refresh_from_db()
new_course.refresh_from_db()
self.assertEqual(old_course.lessons_count, 0)
self.assertEqual(new_course.lessons_count, 1)
def test_inactive_lessons_are_not_counted(self):
course = self._create_course('inactive-course', 'Inactive Course')
self._create_course_lesson(course, title='Lesson 1', is_active=False)
self._create_course_lesson(course, title='Lesson 2', is_active=True, priority=2)
course.refresh_from_db()
self.assertEqual(course.lessons_count, 1)
def test_sync_course_lessons_count_command_updates_mismatched_courses(self):
first_course = self._create_course('sync-first-course', 'Sync First Course', lessons_count=99)
second_course = self._create_course('sync-second-course', 'Sync Second Course', lessons_count=7)
self._create_course_lesson(first_course, title='Lesson 1', is_active=True)
self._create_course_lesson(first_course, title='Lesson 2', is_active=False, priority=2)
self._create_course_lesson(second_course, title='Lesson 3', is_active=True)
self._create_course_lesson(second_course, title='Lesson 4', is_active=True, priority=2)
Course.objects.filter(pk=first_course.pk).update(lessons_count=99)
Course.objects.filter(pk=second_course.pk).update(lessons_count=7)
stdout = StringIO()
call_command('sync_course_lessons_count', stdout=stdout)
first_course.refresh_from_db()
second_course.refresh_from_db()
self.assertEqual(first_course.lessons_count, 1)
self.assertEqual(second_course.lessons_count, 2)
self.assertIn('Sync complete. 2 course(s) updated.', stdout.getvalue())
def test_sync_course_lessons_count_command_dry_run_does_not_persist_changes(self):
course = self._create_course('sync-dry-course', 'Sync Dry Course', lessons_count=5)
self._create_course_lesson(course, title='Lesson 1', is_active=True)
Course.objects.filter(pk=course.pk).update(lessons_count=5)
stdout = StringIO()
call_command('sync_course_lessons_count', '--dry-run', stdout=stdout)
course.refresh_from_db()
self.assertEqual(course.lessons_count, 5)
self.assertIn('Dry run complete. 1 course(s) would be updated.', stdout.getvalue())