UTAsutin is an example partner who would use mixed casing on their external_user_key references for program enrollment upload and matriculation. Update the system to be case insensitive on external_user_key Co-authored-by: Simon Chen <schen@edX-C02FW0GUML85.local>
151 lines
6.6 KiB
Python
151 lines
6.6 KiB
Python
"""
|
|
Unit tests for program_course_enrollments tasks
|
|
"""
|
|
|
|
|
|
from datetime import timedelta
|
|
|
|
import pytest
|
|
from django.db.models.base import ObjectDoesNotExist
|
|
from django.test import TestCase
|
|
from django.utils import timezone
|
|
from freezegun import freeze_time
|
|
from opaque_keys.edx.keys import CourseKey
|
|
from testfixtures import LogCapture
|
|
|
|
from common.djangoapps.course_modes.models import CourseMode
|
|
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
|
|
from lms.djangoapps.program_enrollments.models import ProgramCourseEnrollment, ProgramEnrollment
|
|
from lms.djangoapps.program_enrollments.tasks import expire_waiting_enrollments, log
|
|
from lms.djangoapps.program_enrollments.tests.factories import ProgramCourseEnrollmentFactory, ProgramEnrollmentFactory
|
|
from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
|
|
|
|
|
|
class ExpireWaitingEnrollmentsTest(TestCase):
|
|
""" Test expire_waiting_enrollments task """
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super(cls, ExpireWaitingEnrollmentsTest).setUpClass()
|
|
cls.timed_course_key = CourseKey.from_string('course-v1:edX+TestExpire+Timed')
|
|
cls.fresh_course_key = CourseKey.from_string('course-v1:edX+TestExpire+Fresh')
|
|
CourseOverviewFactory(id=cls.timed_course_key)
|
|
CourseOverviewFactory(id=cls.fresh_course_key)
|
|
|
|
def _set_up_course_enrollment(self, user, program_enrollment, course_key):
|
|
""" helper function to set up a program course enrollment """
|
|
if user:
|
|
ProgramCourseEnrollmentFactory(
|
|
program_enrollment=program_enrollment,
|
|
course_enrollment=CourseEnrollmentFactory(
|
|
course_id=course_key, user=user, mode=CourseMode.MASTERS
|
|
)
|
|
)
|
|
else:
|
|
ProgramCourseEnrollmentFactory(
|
|
program_enrollment=program_enrollment,
|
|
course_key=course_key,
|
|
)
|
|
|
|
def _set_up_enrollments(self, external_user_key, user, created_date):
|
|
""" helper function to setup enrollments """
|
|
with freeze_time(created_date):
|
|
program_enrollment = ProgramEnrollmentFactory(
|
|
user=user,
|
|
external_user_key=external_user_key,
|
|
)
|
|
self._set_up_course_enrollment(
|
|
user, program_enrollment, self.timed_course_key
|
|
)
|
|
# additional course enrollment that is always fresh
|
|
self._set_up_course_enrollment(
|
|
user, program_enrollment, self.fresh_course_key
|
|
)
|
|
|
|
def test_expire(self):
|
|
self._set_up_enrollments('student_expired_waiting', None, timezone.now() - timedelta(60))
|
|
self._set_up_enrollments('student_waiting', None, timezone.now() - timedelta(59))
|
|
self._set_up_enrollments('student_actualized', UserFactory(), timezone.now() - timedelta(90))
|
|
|
|
expired_program_enrollment = ProgramEnrollment.objects.get(
|
|
external_user_key='student_expired_waiting'
|
|
)
|
|
expired_course_enrollments = list(ProgramCourseEnrollment.objects.filter(
|
|
program_enrollment=expired_program_enrollment
|
|
))
|
|
|
|
# assert deleted enrollments are logged (without pii)
|
|
with LogCapture(log.name) as log_capture:
|
|
expire_waiting_enrollments(60)
|
|
|
|
program_enrollment_message_tmpl = 'Found expired program_enrollment (id={}) for program_uuid={}'
|
|
course_enrollment_message_tmpl = (
|
|
'Found expired program_course_enrollment (id={}) for program_uuid={}, course_key={}'
|
|
)
|
|
|
|
log_capture.check_present(
|
|
(
|
|
log.name,
|
|
'INFO',
|
|
program_enrollment_message_tmpl.format(
|
|
expired_program_enrollment.id,
|
|
expired_program_enrollment.program_uuid,
|
|
)
|
|
),
|
|
(
|
|
log.name,
|
|
'INFO',
|
|
course_enrollment_message_tmpl.format(
|
|
expired_course_enrollments[0].id,
|
|
expired_program_enrollment.program_uuid,
|
|
expired_course_enrollments[0].course_key,
|
|
)
|
|
),
|
|
(
|
|
log.name,
|
|
'INFO',
|
|
course_enrollment_message_tmpl.format(
|
|
expired_course_enrollments[1].id,
|
|
expired_program_enrollment.program_uuid,
|
|
expired_course_enrollments[1].course_key,
|
|
)
|
|
),
|
|
)
|
|
|
|
assert 'Removed 3 expired records:' in log_capture.records[3].getMessage()
|
|
assert "program_enrollments.ProgramCourseEnrollment': 2" in log_capture.records[3].getMessage()
|
|
assert "program_enrollments.ProgramEnrollment': 1" in log_capture.records[3].getMessage()
|
|
|
|
program_enrollments = ProgramEnrollment.objects.all()
|
|
program_course_enrollments = ProgramCourseEnrollment.objects.all()
|
|
historical_program_enrollments = ProgramEnrollment.historical_records.all() # pylint: disable=no-member
|
|
historical_program_course_enrollments = ProgramCourseEnrollment.historical_records.all() # pylint: disable=no-member
|
|
|
|
# assert expired records no longer exist
|
|
with pytest.raises(ProgramEnrollment.DoesNotExist):
|
|
program_enrollments.get(external_user_key='student_expired_waiting')
|
|
assert len(program_course_enrollments) == 4
|
|
|
|
# assert fresh waiting records are not affected
|
|
waiting_enrollment = program_enrollments.get(external_user_key='student_waiting')
|
|
assert len(waiting_enrollment.program_course_enrollments.all()) == 2
|
|
|
|
# assert actualized enrollments are not affected
|
|
actualized_enrollment = program_enrollments.get(external_user_key='student_actualized')
|
|
assert len(actualized_enrollment.program_course_enrollments.all()) == 2
|
|
|
|
# assert expired historical records are also removed
|
|
with pytest.raises(ObjectDoesNotExist):
|
|
historical_program_enrollments.get(external_user_key='student_expired_waiting')
|
|
assert len(historical_program_course_enrollments
|
|
.filter(program_enrollment_id=expired_program_enrollment.id)) == 0
|
|
|
|
# assert other historical records are not affected
|
|
assert len(historical_program_enrollments) == 2
|
|
assert len(historical_program_course_enrollments) == 4
|
|
|
|
def test_expire_none(self):
|
|
""" Asserts no exceptions are thrown if no enrollments are found """
|
|
expire_waiting_enrollments(60)
|
|
assert len(ProgramEnrollment.objects.all()) == 0
|