Example #1
0
    def test_get_studentview_submitted_status_with_duedate(self):
        """
        Test for get_student_view proctored exam which has been submitted
        And due date has passed
        """
        proctored_exam = ProctoredExam.objects.create(
            course_id='a/b/c',
            content_id='test_content',
            exam_name='Test Exam',
            external_id='123aXqe3',
            time_limit_mins=30,
            is_proctored=True,
            is_active=True,
            due_date=datetime.now(pytz.UTC) + timedelta(minutes=40)
        )

        exam_attempt = ProctoredExamStudentAttempt.objects.create(
            proctored_exam=proctored_exam,
            user=self.user,
            allowed_time_limit_mins=30,
            taking_as_proctored=True,
            external_id=proctored_exam.external_id,
            status=ProctoredExamStudentAttemptStatus.submitted,
        )

        # due date is after 10 minutes
        reset_time = datetime.now(pytz.UTC) + timedelta(minutes=20)
        with freeze_time(reset_time):
            rendered_response = get_student_view(
                user_id=self.user.id,
                course_id='a/b/c',
                content_id='test_content',
                context={
                    'is_proctored': True,
                    'display_name': 'Test Exam',
                    'default_time_limit_mins': 30
                }
            )
            self.assertIn(self.proctored_exam_submitted_msg, rendered_response)
            exam_attempt.is_status_acknowledged = True
            exam_attempt.save()

            rendered_response = get_student_view(
                user_id=self.user.id,
                course_id='a/b/c',
                content_id='test_content',
                context={
                    'is_proctored': True,
                    'display_name': 'Test Exam',
                    'default_time_limit_mins': 30
                }
            )
            self.assertIsNotNone(rendered_response)
Example #2
0
 def _render_exam(self, content_id, context_overrides=None):
     """
     Renders a test exam.
     """
     exam = get_exam_by_id(content_id)
     context = {
         'is_proctored': True,
         'allow_proctoring_opt_out': True,
         'display_name': self.exam_name,
         'default_time_limit_mins': 90,
         'is_practice_exam': False,
         'credit_state': {
             'enrollment_mode': 'verified',
             'credit_requirement_status': [],
         },
         'verification_status': 'approved',
         'verification_url': '/reverify',
     }
     if context_overrides:
         context.update(context_overrides)
     return get_student_view(
         user_id=self.user_id,
         course_id=exam['course_id'],
         content_id=exam['content_id'],
         context=context,
     )
    def test_get_studentview_submitted_timed_exam_with_past_due_date(
            self, due_date, hide_after_due):
        """
        Test for get_student_view timed exam with the due date.
        """

        # exam is created with due datetime which has already passed
        exam_id = self._create_exam_with_due_time(is_proctored=False,
                                                  due_date=due_date)
        if hide_after_due:
            update_exam(exam_id, hide_after_due=hide_after_due)

        # now create the timed_exam attempt in the submitted state
        self._create_exam_attempt(exam_id, status='submitted')

        rendered_response = get_student_view(
            user_id=self.user_id,
            course_id=self.course_id,
            content_id=self.content_id_for_exam_with_due_date,
            context={
                'is_proctored': False,
                'display_name': self.exam_name,
                'default_time_limit_mins': 10,
                'due_date': due_date,
            })
        if datetime.now(pytz.UTC) < due_date:
            self.assertIn(self.timed_exam_submitted, rendered_response)
            self.assertIn(self.submitted_timed_exam_msg_with_due_date,
                          rendered_response)
        elif hide_after_due:
            self.assertIn(self.timed_exam_submitted, rendered_response)
            self.assertNotIn(self.submitted_timed_exam_msg_with_due_date,
                             rendered_response)
        else:
            self.assertIsNone(rendered_response)
 def _render_exam(self, content_id, context_overrides=None):
     """
     Renders a test exam.
     """
     exam = get_exam_by_id(content_id)
     context = {
         'is_proctored': True,
         'allow_proctoring_opt_out': True,
         'display_name': self.exam_name,
         'default_time_limit_mins': 90,
         'is_practice_exam': False,
         'credit_state': {
             'enrollment_mode': 'verified',
             'credit_requirement_status': [],
         },
         'verification_status': 'approved',
         'verification_url': '/reverify',
     }
     if context_overrides:
         context.update(context_overrides)
     return get_student_view(
         user_id=self.user_id,
         course_id=exam['course_id'],
         content_id=exam['content_id'],
         context=context,
     )
    def test_get_studentview_unstarted_timed_exam_with_allowance(self):
        """
        Test for get_student_view Timed exam which is not proctored and has not started yet.
        But user has an allowance
        """

        allowed_extra_time = 10
        add_allowance_for_user(
            self.timed_exam_id, self.user.username,
            ProctoredExamStudentAllowance.ADDITIONAL_TIME_GRANTED,
            six.text_type(allowed_extra_time))

        rendered_response = get_student_view(user_id=self.user_id,
                                             course_id=self.course_id,
                                             content_id=self.content_id_timed,
                                             context={})
        self.assertNotIn(
            'data-exam-id="{proctored_exam_id}"'.format(
                proctored_exam_id=self.proctored_exam_id), rendered_response)
        self.assertIn(self.timed_exam_msg.format(exam_name=self.exam_name),
                      rendered_response)
        self.assertIn('31 minutes', rendered_response)
        self.assertNotIn(
            self.start_an_exam_msg.format(exam_name=self.exam_name),
            rendered_response)
Example #6
0
    def test_get_studentview_submitted_timed_exam_with_past_due_date(self, due_date, hide_after_due):
        """
        Test for get_student_view timed exam with the due date.
        """

        # exam is created with due datetime which has already passed
        exam_id = self._create_exam_with_due_time(is_proctored=False, due_date=due_date)
        if hide_after_due:
            update_exam(exam_id, hide_after_due=hide_after_due)

        # now create the timed_exam attempt in the submitted state
        self._create_exam_attempt(exam_id, status='submitted')

        rendered_response = get_student_view(
            user_id=self.user_id,
            course_id=self.course_id,
            content_id=self.content_id_for_exam_with_due_date,
            context={
                'is_proctored': False,
                'display_name': self.exam_name,
                'default_time_limit_mins': 10,
                'due_date': due_date,
            }
        )
        if datetime.now(pytz.UTC) < due_date:
            self.assertIn(self.timed_exam_submitted, rendered_response)
            self.assertIn(self.submitted_timed_exam_msg_with_due_date, rendered_response)
        elif hide_after_due:
            self.assertIn(self.timed_exam_submitted, rendered_response)
            self.assertNotIn(self.submitted_timed_exam_msg_with_due_date, rendered_response)
        else:
            self.assertIsNone(rendered_response)
Example #7
0
    def test_get_studentview_unstarted_timed_exam_with_allowance(self):
        """
        Test for get_student_view Timed exam which is not proctored and has not started yet.
        But user has an allowance
        """

        allowed_extra_time = 10
        add_allowance_for_user(
            self.timed_exam_id,
            self.user.username,
            ProctoredExamStudentAllowance.ADDITIONAL_TIME_GRANTED,
            six.text_type(allowed_extra_time)
        )

        rendered_response = get_student_view(
            user_id=self.user_id,
            course_id=self.course_id,
            content_id=self.content_id_timed,
            context={}
        )
        self.assertNotIn(
            'data-exam-id="{proctored_exam_id}"'.format(proctored_exam_id=self.proctored_exam_id),
            rendered_response
        )
        self.assertIn(self.timed_exam_msg.format(exam_name=self.exam_name), rendered_response)
        self.assertIn('31 minutes', rendered_response)
        self.assertNotIn(self.start_an_exam_msg.format(exam_name=self.exam_name), rendered_response)
Example #8
0
    def test_timed_exam_attempt_with_past_due_datetime(self):
        """
        Test for get_student_view for timed exam with past due datetime
        """

        due_date = datetime.now(pytz.UTC) + timedelta(days=1)

        # exam is created with due datetime which has already passed
        self._create_exam_with_due_time(
            due_date=due_date,
            is_proctored=False
        )

        # due_date is exactly after 24 hours, if student arrives after 2 days
        # then he can not attempt the proctored exam
        reset_time = due_date + timedelta(days=2)
        with freeze_time(reset_time):
            rendered_response = get_student_view(
                user_id=self.user_id,
                course_id=self.course_id,
                content_id=self.content_id_for_exam_with_due_date,
                context={
                    'is_proctored': False,
                    'display_name': self.exam_name,
                    'default_time_limit_mins': self.default_time_limit,
                    'due_date': due_date,
                }
            )
            self.assertIn(self.exam_expired_msg, rendered_response)

            # call the view again, because the first call set the exam attempt to 'expired'
            # this second call will render the view based on the state
            rendered_response = get_student_view(
                user_id=self.user_id,
                course_id=self.course_id,
                content_id=self.content_id_for_exam_with_due_date,
                context={
                    'is_proctored': True,
                    'is_practice_exam': True,
                    'display_name': self.exam_name,
                    'default_time_limit_mins': self.default_time_limit,
                    'due_date': due_date,
                }
            )
            self.assertIn(self.exam_expired_msg, rendered_response)
    def test_expired_exam(self):
        """
        Test that an expired exam shows a difference message when the exam is expired just recently
        """
        # create exam with completed_at equal to current time and started_at equal to allowed_time_limit_mins ago
        attempt = self._create_started_exam_attempt(is_proctored=False)
        attempt.status = "submitted"
        attempt.started_at = attempt.started_at - timedelta(
            minutes=attempt.allowed_time_limit_mins)
        attempt.completed_at = attempt.started_at + timedelta(
            minutes=attempt.allowed_time_limit_mins)
        attempt.save()

        rendered_response = get_student_view(user_id=self.user_id,
                                             course_id=self.course_id,
                                             content_id=self.content_id_timed,
                                             context={
                                                 'display_name':
                                                 self.exam_name,
                                             })

        self.assertIn(self.timed_exam_expired, rendered_response)

        # update start and completed time such that completed_time is allowed_time_limit_mins ago than the current time
        attempt.started_at = attempt.started_at - timedelta(
            minutes=attempt.allowed_time_limit_mins)
        attempt.completed_at = attempt.completed_at - timedelta(
            minutes=attempt.allowed_time_limit_mins)
        attempt.save()

        rendered_response = get_student_view(user_id=self.user_id,
                                             course_id=self.course_id,
                                             content_id=self.content_id_timed,
                                             context={
                                                 'display_name':
                                                 self.exam_name,
                                             })

        self.assertIn(self.timed_exam_submitted, rendered_response)
 def test_get_disabled_student_view(self):
     """
     Assert that a disabled proctored exam will not override the
     student_view
     """
     self.assertIsNone(
         get_student_view(user_id=self.user_id,
                          course_id=self.course_id,
                          content_id=self.disabled_content_id,
                          context={
                              'is_proctored': True,
                              'display_name': self.exam_name,
                              'default_time_limit_mins': 90
                          }))
Example #11
0
    def test_expired_exam(self):
        """
        Test that an expired exam shows a difference message when the exam is expired just recently
        """
        # create exam with completed_at equal to current time and started_at equal to allowed_time_limit_mins ago
        attempt = self._create_started_exam_attempt(is_proctored=False)
        attempt.status = "submitted"
        attempt.started_at = attempt.started_at - timedelta(minutes=attempt.allowed_time_limit_mins)
        attempt.completed_at = attempt.started_at + timedelta(minutes=attempt.allowed_time_limit_mins)
        attempt.save()

        rendered_response = get_student_view(
            user_id=self.user_id,
            course_id=self.course_id,
            content_id=self.content_id_timed,
            context={
                'display_name': self.exam_name,
            }
        )

        self.assertIn(self.timed_exam_expired, rendered_response)

        # update start and completed time such that completed_time is allowed_time_limit_mins ago than the current time
        attempt.started_at = attempt.started_at - timedelta(minutes=attempt.allowed_time_limit_mins)
        attempt.completed_at = attempt.completed_at - timedelta(minutes=attempt.allowed_time_limit_mins)
        attempt.save()

        rendered_response = get_student_view(
            user_id=self.user_id,
            course_id=self.course_id,
            content_id=self.content_id_timed,
            context={
                'display_name': self.exam_name,
            }
        )

        self.assertIn(self.timed_exam_submitted, rendered_response)
    def test_get_studentview_started_timed_exam(self):
        """
        Test for get_student_view timed exam which has started.
        """
        self._create_started_exam_attempt(is_proctored=False)

        rendered_response = get_student_view(user_id=self.user_id,
                                             course_id=self.course_id,
                                             content_id=self.content_id_timed,
                                             context={
                                                 'is_proctored': True,
                                                 'display_name':
                                                 self.exam_name,
                                                 'default_time_limit_mins': 90
                                             })
        self.assertIsNone(rendered_response)
 def test_student_response_without_credit_state(self):
     """
     Test that response is not None for users who are not enrolled.
     """
     set_runtime_service('credit', MockCreditServiceNone())
     rendered_response = get_student_view(user_id=self.user_id,
                                          course_id=self.course_id,
                                          content_id=self.content_id,
                                          context={
                                              'is_proctored': True,
                                              'display_name':
                                              self.exam_name,
                                              'default_time_limit_mins': 90
                                          },
                                          user_role='student')
     self.assertIsNotNone(rendered_response)
Example #14
0
 def test_get_disabled_student_view(self):
     """
     Assert that a disabled proctored exam will not override the
     student_view
     """
     self.assertIsNone(
         get_student_view(
             user_id=self.user_id,
             course_id=self.course_id,
             content_id=self.disabled_content_id,
             context={
                 'is_proctored': True,
                 'display_name': self.exam_name,
                 'default_time_limit_mins': 90
             }
         )
     )
Example #15
0
    def test_get_studentview_started_timed_exam(self):
        """
        Test for get_student_view timed exam which has started.
        """
        self._create_started_exam_attempt(is_proctored=False)

        rendered_response = get_student_view(
            user_id=self.user_id,
            course_id=self.course_id,
            content_id=self.content_id_timed,
            context={
                'is_proctored': True,
                'display_name': self.exam_name,
                'default_time_limit_mins': 90
            }
        )
        self.assertIsNone(rendered_response)
    def test_student_view_non_student(self):
        """
        Make sure that if we ask for a student view if we are not in a student role,
        then we don't see any proctoring views
        """

        rendered_response = get_student_view(user_id=self.user_id,
                                             course_id=self.course_id,
                                             content_id=self.content_id,
                                             context={
                                                 'is_proctored': True,
                                                 'display_name':
                                                 self.exam_name,
                                                 'default_time_limit_mins': 90
                                             },
                                             user_role='staff')
        self.assertIsNone(rendered_response)
Example #17
0
 def test_student_response_without_credit_state(self):
     """
     Test that response is not None for users who are not enrolled.
     """
     set_runtime_service('credit', MockCreditServiceNone())
     rendered_response = get_student_view(
         user_id=self.user_id,
         course_id=self.course_id,
         content_id=self.content_id,
         context={
             'is_proctored': True,
             'display_name': self.exam_name,
             'default_time_limit_mins': 90
         },
         user_role='student'
     )
     self.assertIsNotNone(rendered_response)
Example #18
0
    def test_student_view_non_student(self):
        """
        Make sure that if we ask for a student view if we are not in a student role,
        then we don't see any proctoring views
        """

        rendered_response = get_student_view(
            user_id=self.user_id,
            course_id=self.course_id,
            content_id=self.content_id,
            context={
                'is_proctored': True,
                'display_name': self.exam_name,
                'default_time_limit_mins': 90
            },
            user_role='staff'
        )
        self.assertIsNone(rendered_response)
    def test_wrong_exam_combo(self):
        """
        Verify that we get a None back when rendering a view
        for a practice, non-proctored exam. This is unsupported.
        """

        rendered_response = get_student_view(user_id=self.user_id,
                                             course_id='foo',
                                             content_id='bar',
                                             context={
                                                 'is_proctored': False,
                                                 'is_practice_exam': True,
                                                 'display_name':
                                                 self.exam_name,
                                                 'default_time_limit_mins': 90,
                                                 'hide_after_due': False,
                                             },
                                             user_role='student')
        self.assertIsNone(rendered_response)
    def test_get_studentview_completed_timed_exam(self, status,
                                                  expected_content):
        """
        Test for get_student_view timed exam which has completed.
        """
        exam_attempt = self._create_started_exam_attempt(is_proctored=False)
        exam_attempt.status = status
        if status == 'submitted':
            exam_attempt.completed_at = datetime.now(pytz.UTC)

        exam_attempt.save()

        rendered_response = get_student_view(user_id=self.user_id,
                                             course_id=self.course_id,
                                             content_id=self.content_id_timed,
                                             context={
                                                 'display_name':
                                                 self.exam_name,
                                             })
        self.assertIn(expected_content, rendered_response)
Example #21
0
    def test_get_studentview_completed_timed_exam(self, status, expected_content):
        """
        Test for get_student_view timed exam which has completed.
        """
        exam_attempt = self._create_started_exam_attempt(is_proctored=False)
        exam_attempt.status = status
        if status == 'submitted':
            exam_attempt.completed_at = datetime.now(pytz.UTC)

        exam_attempt.save()

        rendered_response = get_student_view(
            user_id=self.user_id,
            course_id=self.course_id,
            content_id=self.content_id_timed,
            context={
                'display_name': self.exam_name,
            }
        )
        self.assertIn(expected_content, rendered_response)
Example #22
0
    def test_wrong_exam_combo(self):
        """
        Verify that we get a None back when rendering a view
        for a practice, non-proctored exam. This is unsupported.
        """

        rendered_response = get_student_view(
            user_id=self.user_id,
            course_id='foo',
            content_id='bar',
            context={
                'is_proctored': False,
                'is_practice_exam': True,
                'display_name': self.exam_name,
                'default_time_limit_mins': 90,
                'hide_after_due': False,
            },
            user_role='student'
        )
        self.assertIsNone(rendered_response)
Example #23
0
 def test_get_studentview_unstarted_timed_exam(self):
     """
     Test for get_student_view Timed exam which is not proctored and has not started yet.
     """
     rendered_response = get_student_view(
         user_id=self.user_id,
         course_id="abc",
         content_id=self.content_id,
         context={
             'is_proctored': False,
             'display_name': self.exam_name,
             'default_time_limit_mins': 90,
             'hide_after_due': False,
         }
     )
     self.assertNotIn(
         'data-exam-id="{proctored_exam_id}"'.format(proctored_exam_id=self.proctored_exam_id),
         rendered_response
     )
     self.assertIn(self.timed_exam_msg.format(exam_name=self.exam_name), rendered_response)
     self.assertIn('1 hour and 30 minutes', rendered_response)
     self.assertNotIn(self.start_an_exam_msg.format(exam_name=self.exam_name), rendered_response)
    def test_practice_exam_passed_end_date(self):
        """
        Verify that we get a None back on a practice exam
        if the course end date is passed
        """

        set_runtime_service('credit', MockCreditServiceWithCourseEndDate())

        rendered_response = get_student_view(user_id=self.user_id,
                                             course_id='foo',
                                             content_id='bar',
                                             context={
                                                 'is_proctored': True,
                                                 'is_practice_exam': True,
                                                 'display_name':
                                                 self.exam_name,
                                                 'default_time_limit_mins': 90,
                                                 'due_date': None,
                                                 'hide_after_due': False,
                                             },
                                             user_role='student')
        self.assertIsNone(rendered_response)
Example #25
0
 def test_get_studentview_long_limit(self, under_exception):
     """
     Test for hide_extra_time_footer on exams with > 20 hours time limit
     """
     exam_id = self._create_exam_with_due_time(is_proctored=False, )
     if under_exception:
         update_exam(exam_id, time_limit_mins=((20 * 60)))  # exactly 20 hours
     else:
         update_exam(exam_id, time_limit_mins=((20 * 60) + 1))  # 1 minute greater than 20 hours
     rendered_response = get_student_view(
         user_id=self.user_id,
         course_id=self.course_id,
         content_id=self.content_id_for_exam_with_due_date,
         context={
             'is_proctored': False,
             'display_name': self.exam_name,
         }
     )
     if under_exception:
         self.assertIn(self.timed_footer_msg, rendered_response)
     else:
         self.assertNotIn(self.timed_footer_msg, rendered_response)
Example #26
0
    def test_practice_exam_passed_end_date(self):
        """
        Verify that we get a None back on a practice exam
        if the course end date is passed
        """
        credit_state = MockCreditServiceWithCourseEndDate().get_credit_state(self.user_id, 'foo', True)

        rendered_response = get_student_view(
            user_id=self.user_id,
            course_id='foo',
            content_id='bar',
            context={
                'is_proctored': True,
                'is_practice_exam': True,
                'display_name': self.exam_name,
                'default_time_limit_mins': 90,
                'due_date': None,
                'hide_after_due': False,
                'credit_state': credit_state,
            },
            user_role='student'
        )
        self.assertIsNone(rendered_response)