2 changed files with 177 additions and 17 deletions
@ -0,0 +1,145 @@ |
|||||
|
from django.core.files.uploadedfile import SimpleUploadedFile |
||||
|
from django.core.files.uploadedfile import SimpleUploadedFile |
||||
|
from django.urls import reverse |
||||
|
from rest_framework import status |
||||
|
from rest_framework.test import APITestCase |
||||
|
|
||||
|
from apps.account.models import ProfessorUser, StudentUser |
||||
|
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 |
||||
|
|
||||
|
|
||||
|
class MyCoursesAPITests(APITestCase): |
||||
|
def setUp(self): |
||||
|
self.professor = ProfessorUser.objects.create( |
||||
|
email='prof@example.com', |
||||
|
fullname='Professor Example', |
||||
|
experience_years=5, |
||||
|
) |
||||
|
self.student = StudentUser.objects.create( |
||||
|
email='student@example.com', |
||||
|
fullname='Student Example', |
||||
|
) |
||||
|
self.category = CourseCategory.objects.create( |
||||
|
name='Category', |
||||
|
slug='category', |
||||
|
) |
||||
|
|
||||
|
def _create_course(self, slug, title): |
||||
|
thumbnail = SimpleUploadedFile('thumb.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=0, |
||||
|
description='Description', |
||||
|
short_description='Short description', |
||||
|
status=Course.StatusChoices.ONGOING, |
||||
|
is_free=True, |
||||
|
) |
||||
|
|
||||
|
def _attach_lessons(self, course, lesson_specs): |
||||
|
chapter = CourseChapter.objects.create( |
||||
|
course=course, |
||||
|
title=f'{course.title} Chapter', |
||||
|
priority=1, |
||||
|
is_active=True, |
||||
|
) |
||||
|
|
||||
|
created_lessons = [] |
||||
|
for index, spec in enumerate(lesson_specs, start=1): |
||||
|
lesson = Lesson.objects.create( |
||||
|
title=spec['title'], |
||||
|
content_type=Lesson.ContentTypeChoices.VIDEO_FILE, |
||||
|
duration=5, |
||||
|
) |
||||
|
course_lesson = CourseLesson.objects.create( |
||||
|
course=course, |
||||
|
chapter=chapter, |
||||
|
lesson=lesson, |
||||
|
priority=index, |
||||
|
is_active=spec.get('is_active', True), |
||||
|
) |
||||
|
created_lessons.append(course_lesson) |
||||
|
|
||||
|
return created_lessons |
||||
|
|
||||
|
def test_completed_filter_returns_only_courses_with_all_active_lessons_completed(self): |
||||
|
completed_course = self._create_course('completed-course', 'Completed Course') |
||||
|
partial_course = self._create_course('partial-course', 'Partial Course') |
||||
|
empty_course = self._create_course('empty-course', 'Empty Course') |
||||
|
|
||||
|
completed_lessons = self._attach_lessons( |
||||
|
completed_course, |
||||
|
[ |
||||
|
{'title': 'Completed Lesson 1'}, |
||||
|
{'title': 'Completed Lesson 2'}, |
||||
|
{'title': 'Inactive Lesson', 'is_active': False}, |
||||
|
], |
||||
|
) |
||||
|
partial_lessons = self._attach_lessons( |
||||
|
partial_course, |
||||
|
[ |
||||
|
{'title': 'Partial Lesson 1'}, |
||||
|
{'title': 'Partial Lesson 2'}, |
||||
|
], |
||||
|
) |
||||
|
|
||||
|
Participant.objects.create(student=self.student, course=completed_course) |
||||
|
Participant.objects.create(student=self.student, course=partial_course) |
||||
|
Participant.objects.create(student=self.student, course=empty_course) |
||||
|
|
||||
|
LessonCompletion.objects.create(student=self.student, course_lesson=completed_lessons[0]) |
||||
|
LessonCompletion.objects.create(student=self.student, course_lesson=completed_lessons[1]) |
||||
|
LessonCompletion.objects.create(student=self.student, course_lesson=partial_lessons[0]) |
||||
|
|
||||
|
self.client.force_authenticate(user=self.student) |
||||
|
url = reverse('course-my-courses-list') |
||||
|
response = self.client.get(url, {'completed': 'true'}, format='json') |
||||
|
|
||||
|
self.assertEqual(response.status_code, status.HTTP_200_OK) |
||||
|
self.assertEqual(response.data['count'], 1) |
||||
|
self.assertEqual({item['slug'] for item in response.data['results']}, {completed_course.slug}) |
||||
|
|
||||
|
def test_my_courses_without_completed_filter_returns_completed_and_incomplete_courses(self): |
||||
|
completed_course = self._create_course('all-completed-course', 'All Completed Course') |
||||
|
partial_course = self._create_course('all-partial-course', 'All Partial Course') |
||||
|
|
||||
|
completed_lessons = self._attach_lessons( |
||||
|
completed_course, |
||||
|
[ |
||||
|
{'title': 'Completed Lesson 1'}, |
||||
|
], |
||||
|
) |
||||
|
partial_lessons = self._attach_lessons( |
||||
|
partial_course, |
||||
|
[ |
||||
|
{'title': 'Partial Lesson 1'}, |
||||
|
{'title': 'Partial Lesson 2'}, |
||||
|
], |
||||
|
) |
||||
|
|
||||
|
Participant.objects.create(student=self.student, course=completed_course) |
||||
|
Participant.objects.create(student=self.student, course=partial_course) |
||||
|
|
||||
|
LessonCompletion.objects.create(student=self.student, course_lesson=completed_lessons[0]) |
||||
|
LessonCompletion.objects.create(student=self.student, course_lesson=partial_lessons[0]) |
||||
|
|
||||
|
self.client.force_authenticate(user=self.student) |
||||
|
url = reverse('course-my-courses-list') |
||||
|
response = self.client.get(url, format='json') |
||||
|
|
||||
|
self.assertEqual(response.status_code, status.HTTP_200_OK) |
||||
|
self.assertEqual(response.data['count'], 2) |
||||
|
self.assertEqual( |
||||
|
{item['slug'] for item in response.data['results']}, |
||||
|
{completed_course.slug, partial_course.slug}, |
||||
|
) |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue