test_credit_requirements.py 6.42 KB
Newer Older
1 2 3 4
"""
Tests for credit requirement display on the progress page.
"""

5
import ddt
6 7
from django.conf import settings
from django.core.urlresolvers import reverse
8
from mock import patch
9

10
from course_modes.models import CourseMode
11 12
from openedx.core.djangoapps.credit import api as credit_api
from openedx.core.djangoapps.credit.models import CreditCourse
13 14 15
from student.tests.factories import CourseEnrollmentFactory, UserFactory
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
16 17 18


@patch.dict(settings.FEATURES, {"ENABLE_CREDIT_ELIGIBILITY": True})
19
@ddt.ddt
20
class ProgressPageCreditRequirementsTest(SharedModuleStoreTestCase):
21 22 23 24 25 26 27 28 29 30 31
    """
    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"

32 33 34 35 36
    @classmethod
    def setUpClass(cls):
        super(ProgressPageCreditRequirementsTest, cls).setUpClass()
        cls.course = CourseFactory.create()

37 38 39
    def setUp(self):
        super(ProgressPageCreditRequirementsTest, self).setUp()

40
        # Configure course as a credit course
41
        CreditCourse.objects.create(course_key=self.course.id, enabled=True)
42 43 44

        # Configure credit requirements (passing grade and in-course reverification)
        credit_api.set_credit_requirements(
45
            self.course.id,
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
            [
                {
                    "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)
        self.assertTrue(result, msg="Could not log in")

        # Enroll the user in the course as "verified"
        self.enrollment = CourseEnrollmentFactory(
            user=self.user,
75
            course_id=self.course.id,
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
            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,
            "{}, you have not yet met the requirements for credit".format(self.USER_FULL_NAME)
        )

    def test_credit_requirements_eligible(self):
94 95 96 97
        """
        Mark the user as eligible for all requirements. Requirements are only displayed
        for credit and verified enrollments.
        """
98
        credit_api.set_credit_requirement_status(
99
            self.user, self.course.id,
100 101 102 103 104 105
            "grade", "grade",
            status="satisfied",
            reason={"final_grade": 0.95}
        )

        credit_api.set_credit_requirement_status(
106
            self.user, self.course.id,
107 108 109 110 111 112 113 114 115 116 117 118
            "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,
            "{}, you have met the requirements for credit in this course.".format(self.USER_FULL_NAME)
        )
119
        self.assertContains(response, "Completed by {date}")
120 121 122 123

        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'))
124
        self.assertNotContains(response, "95%")
125 126

    def test_credit_requirements_not_eligible(self):
127 128 129 130
        """
        Mark the user as having failed both requirements. Requirements are only displayed
        for credit and verified enrollments.
        """
131
        credit_api.set_credit_requirement_status(
132
            self.user, self.course.id,
133 134 135 136 137 138 139 140 141 142 143 144 145 146
            "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,
            "{}, you are no longer eligible for credit in this course.".format(self.USER_FULL_NAME)
        )
        self.assertContains(response, "Verification Failed")

147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
    @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()  # pylint: disable=no-member

        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)

169 170 171 172
    def _get_progress_page(self):
        """Load the progress page for the course the user is enrolled in. """
        url = reverse("progress", kwargs={"course_id": unicode(self.course.id)})
        return self.client.get(url)