Skip to content

Commit

Permalink
test: [AXM-1512] write unit-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
kyrylo-kh committed Feb 25, 2025
1 parent 2bee3ea commit 4ca9de9
Show file tree
Hide file tree
Showing 2 changed files with 207 additions and 0 deletions.
50 changes: 50 additions & 0 deletions lms/djangoapps/mobile_api/tests/test_course_dates_serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from django.db.models import F, Value
from django.utils import timezone
from edx_when.models import ContentDate, DatePolicy

from lms.djangoapps.mobile_api.course_dates.serializers import ContentDateSerializer
from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.utils import MixedSplitTestCase


class TestContentDateSerializer(MixedSplitTestCase):
def setUp(self):
super().setUp()

self.course = CourseFactory.create(modulestore=self.store)
self.course_overview = CourseOverviewFactory.create(id=self.course.id, display_name="Test Display Name")
self.chapter = self.make_block("chapter", self.course)
self.sequential = self.make_block("sequential", self.chapter)

self.date_policy = DatePolicy.objects.create(
abs_date=timezone.now(),
)
self.content_date = ContentDate.objects.create(
course_id=self.course.id,
location=self.sequential.location,
active=True,
block_type="sequential",
field="due",
policy=self.date_policy,
)

def test_content_date_serializer(self):
"""
Test the serializer for ContentDate model.
"""
queryset = ContentDate.objects.annotate(
due_date=F("policy__abs_date"),
course_name=Value("Test Display Name"),
).first()
serializer = ContentDateSerializer(queryset)
expected_data = {
"course_id": str(self.course.id),
"assignment_block_id": str(self.sequential.location),
"due_date": str(self.date_policy.abs_date),
"assignment_title": self.sequential.display_name,
"learner_has_access": True,
"course_name": "Test Display Name",
}

self.assertEqual(serializer.data, expected_data)
157 changes: 157 additions & 0 deletions lms/djangoapps/mobile_api/tests/test_course_dates_views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
"""
Tests for course_info
"""

from datetime import timedelta

from django.contrib.auth import get_user_model
from django.utils import timezone
from edx_when.models import ContentDate, DatePolicy
from milestones.tests.utils import MilestonesTestCaseMixin
from rest_framework.test import APIRequestFactory

from common.djangoapps.student.tests.factories import CourseEnrollmentFactory
from lms.djangoapps.mobile_api.course_dates.views import AllCourseDatesViewSet
from lms.djangoapps.mobile_api.testutils import MobileAPITestCase
from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.utils import MixedSplitTestCase

User = get_user_model()


class TestCourseEnrollmentDetailsView(
MobileAPITestCase, MixedSplitTestCase, MilestonesTestCaseMixin
): # lint-amnesty, pylint: disable=test-inherits-tests
def setUp(self):
super().setUp()

self.course_1 = CourseFactory.create(modulestore=self.store)
self.course_without_enrollment = CourseFactory.create(modulestore=self.store)

self.course_overview_1 = CourseOverviewFactory.create(id=self.course_1.id, display_name="Test Course 1")
self.course_overview_without_enrollment = CourseOverviewFactory.create(
id=self.course_without_enrollment.id, display_name="Test Course Without Enrollment"
)

self.chapter_1 = self.make_block("chapter", self.course_1)
self.sequential_1 = self.make_block("sequential", self.chapter_1)

self.chapter_without_enrollment = self.make_block("chapter", self.course_without_enrollment)
self.sequential_without_enrollment = self.make_block("sequential", self.chapter_without_enrollment)

self.enrollment_1 = CourseEnrollmentFactory(user=self.user, course_id=self.course_1.id, is_active=True)

self.date_policy_1 = DatePolicy.objects.create(abs_date=timezone.now() + timedelta(days=1))

self.content_date_1 = ContentDate.objects.create(
course_id=self.course_1.id,
location=self.sequential_1.location,
active=True,
block_type="sequential",
field="due",
policy=self.date_policy_1,
)
self.content_date_without_enrollment = ContentDate.objects.create(
course_id=self.course_without_enrollment.id,
location=self.sequential_without_enrollment.location,
active=True,
block_type="sequential",
field="due",
policy=self.date_policy_1,
)

def _get_view_with_request(self):
request = APIRequestFactory().get(f"/api/mobile/v1/course_dates/{self.user.username}/")
view = AllCourseDatesViewSet()
view.request = request
view.kwargs = {"username": self.user.username}
return view

def test_get_queryset(self):
"""
Simple test to check if the queryset is returning the correct course dates.
Dates from not enrolled courses should not be returned.
"""
view = self._get_view_with_request()

queryset = view.get_queryset()
self.assertEqual(queryset.count(), 1)
self.assertEqual(queryset.first(), self.content_date_1)

def test_get_queryset_with_relative_date(self):
"""
Test to check if the queryset is returning the correct course dates with relative date.
Due date should be calculated based on the enrollment date plus the relative date interval.
"""
date_policy_with_relative_date = DatePolicy.objects.create(rel_date=timedelta(weeks=2))

chapter_2 = self.make_block("chapter", self.course_1)
sequential_2 = self.make_block("sequential", chapter_2)

content_date_with_relative_date = ContentDate.objects.create(
course_id=self.course_1.id,
location=sequential_2.location,
active=True,
block_type="sequential",
field="due",
policy=date_policy_with_relative_date,
)

view = self._get_view_with_request()
queryset = view.get_queryset()
self.assertEqual(queryset.count(), 2)
self.assertIn(self.content_date_1, queryset)
self.assertIn(content_date_with_relative_date, queryset)

content_date = queryset.filter(location=sequential_2.location).first()
self.assertEqual(content_date.due_date, self.enrollment_1.created + date_policy_with_relative_date.rel_date)

def test_get_queryset_with_past_due_date_not_self_paced_course(self):
"""
Test to check if not self paced courses with past due dates are not returned.
"""
date_policy_past_due_date = DatePolicy.objects.create(abs_date=timezone.now() - timedelta(days=1))

chapter_2 = self.make_block("chapter", self.course_1)
sequential_2 = self.make_block("sequential", chapter_2)

ContentDate.objects.create(
course_id=self.course_1.id,
location=sequential_2.location,
active=True,
block_type="sequential",
field="due",
policy=date_policy_past_due_date,
)

view = self._get_view_with_request()
queryset = view.get_queryset()
self.assertEqual(queryset.count(), 1)
self.assertEqual(queryset.first(), self.content_date_1)

def test_get_queryset_with_past_due_date_self_paced_course_with_relative_date(self):
"""
Test to check if self paced courses with past due dates are returned.
"""
self_paced_course = CourseFactory.create(modulestore=self.store)
CourseOverviewFactory.create(id=self_paced_course.id, display_name="Self-paced Course", self_paced=True)
CourseEnrollmentFactory(user=self.user, course_id=self_paced_course.id, is_active=True)
chapter_2 = self.make_block("chapter", self_paced_course)
sequential_2 = self.make_block("sequential", chapter_2)

date_policy_past_due_date = DatePolicy.objects.create(rel_date=timedelta(weeks=-2))
content_date_past_due_date = ContentDate.objects.create(
course_id=self_paced_course.id,
location=sequential_2.location,
active=True,
block_type="sequential",
field="due",
policy=date_policy_past_due_date,
)

view = self._get_view_with_request()
queryset = view.get_queryset()
self.assertEqual(queryset.count(), 2)
self.assertIn(self.content_date_1, queryset)
self.assertIn(content_date_past_due_date, queryset)

0 comments on commit 4ca9de9

Please sign in to comment.