174 lines
6.3 KiB
Python
174 lines
6.3 KiB
Python
"""
|
|
Tests for credit requirement display on the progress page.
|
|
"""
|
|
|
|
|
|
from unittest.mock import patch
|
|
import ddt
|
|
from django.conf import settings
|
|
from django.urls import reverse
|
|
|
|
from common.djangoapps.course_modes.models import CourseMode
|
|
from openedx.core.djangoapps.credit import api as credit_api
|
|
from openedx.core.djangoapps.credit.models import CreditCourse
|
|
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
|
|
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
|
from xmodule.modulestore.tests.factories import CourseFactory
|
|
|
|
|
|
@patch.dict(settings.FEATURES, {"ENABLE_CREDIT_ELIGIBILITY": True})
|
|
@ddt.ddt
|
|
class ProgressPageCreditRequirementsTest(SharedModuleStoreTestCase):
|
|
"""
|
|
Tests for credit requirement display on the progress page.
|
|
"""
|
|
|
|
USERNAME = "bob"
|
|
PASSWORD = "test"
|
|
USER_FULL_NAME = "Bob"
|
|
|
|
MIN_GRADE_REQ_DISPLAY = "Final Grade Credit Requirement"
|
|
VERIFICATION_REQ_DISPLAY = "Midterm Exam Credit Requirement"
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
cls.course = CourseFactory.create()
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
|
|
# Configure course as a credit course
|
|
CreditCourse.objects.create(course_key=self.course.id, enabled=True)
|
|
|
|
# Configure credit requirements (passing grade and in-course reverification)
|
|
credit_api.set_credit_requirements(
|
|
self.course.id,
|
|
[
|
|
{
|
|
"namespace": "grade",
|
|
"name": "grade",
|
|
"display_name": self.MIN_GRADE_REQ_DISPLAY,
|
|
"criteria": {
|
|
"min_grade": 0.8
|
|
}
|
|
},
|
|
{
|
|
"namespace": "reverification",
|
|
"name": "midterm",
|
|
"display_name": self.VERIFICATION_REQ_DISPLAY,
|
|
"criteria": {}
|
|
}
|
|
]
|
|
)
|
|
|
|
# Create a user and log in
|
|
self.user = UserFactory.create(username=self.USERNAME, password=self.PASSWORD)
|
|
self.user.profile.name = self.USER_FULL_NAME
|
|
self.user.profile.save()
|
|
|
|
result = self.client.login(username=self.USERNAME, password=self.PASSWORD)
|
|
assert result, 'Could not log in'
|
|
|
|
# Enroll the user in the course as "verified"
|
|
self.enrollment = CourseEnrollmentFactory(
|
|
user=self.user,
|
|
course_id=self.course.id,
|
|
mode="verified"
|
|
)
|
|
|
|
def test_credit_requirements_maybe_eligible(self):
|
|
# The user hasn't satisfied any of the credit requirements yet, but she
|
|
# also hasn't failed any.
|
|
response = self._get_progress_page()
|
|
|
|
# Expect that the requirements are displayed
|
|
self.assertContains(response, self.MIN_GRADE_REQ_DISPLAY)
|
|
self.assertContains(response, self.VERIFICATION_REQ_DISPLAY)
|
|
self.assertContains(response, "Upcoming")
|
|
self.assertContains(
|
|
response,
|
|
f"{self.USER_FULL_NAME}, you have not yet met the requirements for credit"
|
|
)
|
|
|
|
def test_credit_requirements_eligible(self):
|
|
"""
|
|
Mark the user as eligible for all requirements. Requirements are only displayed
|
|
for credit and verified enrollments.
|
|
"""
|
|
credit_api.set_credit_requirement_status(
|
|
self.user, self.course.id,
|
|
"grade", "grade",
|
|
status="satisfied",
|
|
reason={"final_grade": 0.95}
|
|
)
|
|
|
|
credit_api.set_credit_requirement_status(
|
|
self.user, self.course.id,
|
|
"reverification", "midterm",
|
|
status="satisfied", reason={}
|
|
)
|
|
|
|
# Check the progress page display
|
|
response = self._get_progress_page()
|
|
self.assertContains(response, self.MIN_GRADE_REQ_DISPLAY)
|
|
self.assertContains(response, self.VERIFICATION_REQ_DISPLAY)
|
|
self.assertContains(
|
|
response,
|
|
f"{self.USER_FULL_NAME}, you have met the requirements for credit in this course."
|
|
)
|
|
self.assertContains(response, "Completed by {date}")
|
|
|
|
credit_requirements = credit_api.get_credit_requirement_status(self.course.id, self.user.username)
|
|
for requirement in credit_requirements:
|
|
self.assertContains(response, requirement['status_date'].strftime('%Y-%m-%d %H:%M'))
|
|
self.assertNotContains(response, "95%")
|
|
|
|
def test_credit_requirements_not_eligible(self):
|
|
"""
|
|
Mark the user as having failed both requirements. Requirements are only displayed
|
|
for credit and verified enrollments.
|
|
"""
|
|
credit_api.set_credit_requirement_status(
|
|
self.user, self.course.id,
|
|
"reverification", "midterm",
|
|
status="failed", reason={}
|
|
)
|
|
|
|
# Check the progress page display
|
|
response = self._get_progress_page()
|
|
self.assertContains(response, self.MIN_GRADE_REQ_DISPLAY)
|
|
self.assertContains(response, self.VERIFICATION_REQ_DISPLAY)
|
|
self.assertContains(
|
|
response,
|
|
f"{self.USER_FULL_NAME}, you are no longer eligible for credit in this course."
|
|
)
|
|
self.assertContains(response, "Verification Failed")
|
|
|
|
@ddt.data(
|
|
(CourseMode.VERIFIED, True),
|
|
(CourseMode.CREDIT_MODE, True),
|
|
(CourseMode.HONOR, False),
|
|
(CourseMode.AUDIT, False),
|
|
(CourseMode.PROFESSIONAL, False),
|
|
(CourseMode.NO_ID_PROFESSIONAL_MODE, False)
|
|
)
|
|
@ddt.unpack
|
|
def test_credit_requirements_on_progress_page(self, enrollment_mode, is_requirement_displayed):
|
|
"""Test the progress table is only displayed to the verified and credit students."""
|
|
self.enrollment.mode = enrollment_mode
|
|
self.enrollment.save()
|
|
|
|
response = self._get_progress_page()
|
|
# Verify the requirements are shown only if the user is in a credit-eligible mode.
|
|
classes = ('credit-eligibility', 'eligibility-heading')
|
|
method = self.assertContains if is_requirement_displayed else self.assertNotContains
|
|
|
|
for _class in classes:
|
|
method(response, _class)
|
|
|
|
def _get_progress_page(self):
|
|
"""Load the progress page for the course the user is enrolled in. """
|
|
url = reverse("progress", kwargs={"course_id": str(self.course.id)})
|
|
return self.client.get(url)
|