test_services.py 8.07 KB
Newer Older
1
"""
2
Tests of re-verification service.
3
"""
4

5
import ddt
6

7 8
from opaque_keys.edx.keys import CourseKey

9
from course_modes.models import CourseMode
10
from course_modes.tests.factories import CourseModeFactory
11
from student.models import CourseEnrollment
12
from student.tests.factories import UserFactory
13 14
from lms.djangoapps.verify_student.models import VerificationCheckpoint, VerificationStatus, SkippedReverification
from lms.djangoapps.verify_student.services import ReverificationService
15

16 17
from openedx.core.djangoapps.credit.api import get_credit_requirement_status, set_credit_requirements
from openedx.core.djangoapps.credit.models import CreditCourse
18 19
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
20 21 22


@ddt.ddt
23
class TestReverificationService(ModuleStoreTestCase):
24
    """
25
    Tests for the re-verification service.
26 27 28
    """

    def setUp(self):
29
        super(TestReverificationService, self).setUp()
30 31

        self.user = UserFactory.create(username="rusty", password="test")
32 33
        self.course = CourseFactory.create(org='Robot', number='999', display_name='Test Course')
        self.course_id = self.course.id
34
        CourseModeFactory.create(
35
            mode_slug="verified",
36
            course_id=self.course_id,
37 38
            min_price=100,
        )
39 40 41
        self.course_key = CourseKey.from_string(unicode(self.course_id))

        self.item = ItemFactory.create(parent=self.course, category='chapter', display_name='Test Section')
42
        self.final_checkpoint_location = u'i4x://{org}/{course}/edx-reverification-block/final_uuid'.format(
43
            org=self.course_id.org, course=self.course_id.course
44
        )
45

46
        # Enroll in a verified mode
47
        self.enrollment = CourseEnrollment.enroll(self.user, self.course_id, mode=CourseMode.VERIFIED)
48

49
    @ddt.data('final', 'midterm')
50
    def test_start_verification(self, checkpoint_name):
51 52 53 54 55
        """Test the 'start_verification' service method.

        Check that if a reverification checkpoint exists for a specific course
        then 'start_verification' method returns that checkpoint otherwise it
        creates that checkpoint.
56 57
        """
        reverification_service = ReverificationService()
58
        checkpoint_location = u'i4x://{org}/{course}/edx-reverification-block/{checkpoint}'.format(
59
            org=self.course_id.org, course=self.course_id.course, checkpoint=checkpoint_name
60
        )
61 62 63
        expected_url = (
            '/verify_student/reverify'
            '/{course_key}'
64
            '/{checkpoint_location}/'
65
        ).format(course_key=unicode(self.course_id), checkpoint_location=checkpoint_location)
66 67

        self.assertEqual(
68
            reverification_service.start_verification(unicode(self.course_id), checkpoint_location),
69
            expected_url
70 71 72
        )

    def test_get_status(self):
73 74
        """Test the verification statuses of a user for a given 'checkpoint'
        and 'course_id'.
75 76
        """
        reverification_service = ReverificationService()
77
        self.assertIsNone(
78
            reverification_service.get_status(self.user.id, unicode(self.course_id), self.final_checkpoint_location)
79
        )
80

81
        checkpoint_obj = VerificationCheckpoint.objects.create(
82
            course_id=unicode(self.course_id),
83
            checkpoint_location=self.final_checkpoint_location
84 85
        )
        VerificationStatus.objects.create(checkpoint=checkpoint_obj, user=self.user, status='submitted')
86
        self.assertEqual(
87
            reverification_service.get_status(self.user.id, unicode(self.course_id), self.final_checkpoint_location),
88 89
            'submitted'
        )
90

91
        VerificationStatus.objects.create(checkpoint=checkpoint_obj, user=self.user, status='approved')
92
        self.assertEqual(
93
            reverification_service.get_status(self.user.id, unicode(self.course_id), self.final_checkpoint_location),
94
            'approved'
95
        )
96

97 98
    def test_skip_verification(self):
        """
99
        Test adding skip attempt of a user for a reverification checkpoint.
100 101
        """
        reverification_service = ReverificationService()
102
        VerificationCheckpoint.objects.create(
103
            course_id=unicode(self.course_id),
104
            checkpoint_location=self.final_checkpoint_location
105 106
        )

107
        reverification_service.skip_verification(self.user.id, unicode(self.course_id), self.final_checkpoint_location)
108
        self.assertEqual(
109
            SkippedReverification.objects.filter(user=self.user, course_id=self.course_id).count(),
110 111
            1
        )
112

113 114
        # now test that a user can have only one entry for a skipped
        # reverification for a course
115
        reverification_service.skip_verification(self.user.id, unicode(self.course_id), self.final_checkpoint_location)
116
        self.assertEqual(
117
            SkippedReverification.objects.filter(user=self.user, course_id=self.course_id).count(),
118 119
            1
        )
120

121 122
        # testing service for skipped attempt.
        self.assertEqual(
123
            reverification_service.get_status(self.user.id, unicode(self.course_id), self.final_checkpoint_location),
124 125 126
            'skipped'
        )

127 128 129 130
    @ddt.data(
        *CourseMode.CREDIT_ELIGIBLE_MODES
    )
    def test_declined_verification_on_skip(self, mode):
131 132 133 134 135 136 137 138 139 140
        """Test that status with value 'declined' is added in credit
        requirement status model when a user skip's an ICRV.
        """
        reverification_service = ReverificationService()
        checkpoint = VerificationCheckpoint.objects.create(
            course_id=unicode(self.course_id),
            checkpoint_location=self.final_checkpoint_location
        )
        # Create credit course and set credit requirements.
        CreditCourse.objects.create(course_key=self.course_key, enabled=True)
141 142
        self.enrollment.update_enrollment(mode=mode)

143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
        set_credit_requirements(
            self.course_key,
            [
                {
                    "namespace": "reverification",
                    "name": checkpoint.checkpoint_location,
                    "display_name": "Assessment 1",
                    "criteria": {},
                }
            ]
        )

        reverification_service.skip_verification(self.user.id, unicode(self.course_id), self.final_checkpoint_location)
        requirement_status = get_credit_requirement_status(
            self.course_key, self.user.username, 'reverification', checkpoint.checkpoint_location
        )
        self.assertEqual(SkippedReverification.objects.filter(user=self.user, course_id=self.course_id).count(), 1)
        self.assertEqual(len(requirement_status), 1)
        self.assertEqual(requirement_status[0].get('name'), checkpoint.checkpoint_location)
        self.assertEqual(requirement_status[0].get('status'), 'declined')

164
    def test_get_attempts(self):
165
        """Check verification attempts count against a user for a given
166 167 168
        'checkpoint' and 'course_id'.
        """
        reverification_service = ReverificationService()
169
        course_id = unicode(self.course_id)
170
        self.assertEqual(
171
            reverification_service.get_attempts(self.user.id, course_id, self.final_checkpoint_location),
172 173
            0
        )
174

175
        # now create a checkpoint and add user's entry against it then test
176 177 178 179 180
        # that the 'get_attempts' service method returns correct count
        checkpoint_obj = VerificationCheckpoint.objects.create(
            course_id=course_id,
            checkpoint_location=self.final_checkpoint_location
        )
181 182
        VerificationStatus.objects.create(checkpoint=checkpoint_obj, user=self.user, status='submitted')
        self.assertEqual(
183
            reverification_service.get_attempts(self.user.id, course_id, self.final_checkpoint_location),
184 185
            1
        )
186 187 188 189 190 191 192

    def test_not_in_verified_track(self):
        # No longer enrolled in a verified track
        self.enrollment.update_enrollment(mode=CourseMode.HONOR)

        # Should be marked as "skipped" (opted out)
        service = ReverificationService()
193
        status = service.get_status(self.user.id, unicode(self.course_id), self.final_checkpoint_location)
194
        self.assertEqual(status, service.NON_VERIFIED_TRACK)