示例#1
0
 def test_can_generate_auto_disabled(self):
     """
     Test handling when automatic generation is disabled
     """
     with override_waffle_switch(AUTO_GENERATION_SWITCH, active=False):
         assert not _can_generate_allowlist_certificate(
             self.user, self.course_run_key)
示例#2
0
 def test_uncached_with_storage(self):
     with override_waffle_switch(waffle_switch(STORAGE_BACKING_FOR_CACHE),
                                 active=True):
         self.store.add(self.block_structure)
         self.mock_cache.map.clear()
         stored_value = self.store.get(
             self.block_structure.root_block_usage_key)
         self.assert_block_structure(stored_value, self.children_map)
示例#3
0
    def test_override(self):
        switch = WaffleSwitch("test_namespace.test_switch",
                              module_name="testmodule")

        self.assertFalse(switch.is_enabled())
        with override_waffle_switch(switch, active=True):
            self.assertTrue(switch.is_enabled())
        self.assertFalse(switch.is_enabled())
示例#4
0
 def test_read_zero(self, assume_zero_enabled, create_if_needed):
     with override_waffle_switch(waffle_switch(ASSUME_ZERO_GRADE_IF_ABSENT), active=assume_zero_enabled):
         grade_factory = CourseGradeFactory()
         course_grade = grade_factory.read(self.request.user, self.course, create_if_needed=create_if_needed)
         if create_if_needed or assume_zero_enabled:
             self._assert_zero_grade(course_grade, ZeroCourseGrade if assume_zero_enabled else CourseGrade)
         else:
             assert course_grade is None
示例#5
0
def configure_waffle_namespace(feature_enabled):
    """
    Context manager to configure the certs flags
    """
    namespace = certs_waffle.waffle()
    auto_certificate_generation_switch = LegacyWaffleSwitch(namespace, certs_waffle.AUTO_CERTIFICATE_GENERATION)  # pylint: disable=toggle-missing-annotation
    with override_waffle_switch(auto_certificate_generation_switch, active=feature_enabled):
        yield
示例#6
0
    def test_cache_invalidation(self, invalidate_cache_enabled, mock_bs_manager_clear):
        test_display_name = "Jedi 101"

        with override_waffle_switch(INVALIDATE_CACHE_ON_PUBLISH, active=invalidate_cache_enabled):
            self.course.display_name = test_display_name
            self.store.update_item(self.course, self.user.id)

        self.assertEqual(mock_bs_manager_clear.called, invalidate_cache_enabled)
示例#7
0
 def test_view_enabled(self, method, url):
     """
     Ensure CourseEnrollmentAdmin views can be enabled with the waffle switch.
     """
     with override_waffle_switch(COURSE_ENROLLMENT_ADMIN_SWITCH,
                                 active=True):
         response = getattr(self.client, method)(url)
     self.assertEqual(response.status_code, 200)
示例#8
0
 def test_add_and_get(self, with_storage_backing):
     with override_waffle_switch(STORAGE_BACKING_FOR_CACHE,
                                 active=with_storage_backing):
         self.store.add(self.block_structure)
         stored_value = self.store.get(
             self.block_structure.root_block_usage_key)
         assert stored_value is not None
         self.assert_block_structure(stored_value, self.children_map)
示例#9
0
 def test_query_counts_cached(self, store_type, with_storage_backing):
     with override_waffle_switch(waffle_switch(STORAGE_BACKING_FOR_CACHE), active=with_storage_backing):
         course = self._create_course(store_type)
         self._get_blocks(
             course,
             expected_mongo_queries=0,
             expected_sql_queries=11 if with_storage_backing else 10,
         )
示例#10
0
    def test_ungating_when_fulfilled(self, earned, max_possible, result):
        self.assert_user_has_prereq_milestone(self.non_staff_user, expected_has_milestone=False)
        self.assert_access_to_gated_content(self.non_staff_user)
        with override_waffle_switch(ENABLE_COMPLETION_TRACKING_SWITCH, True):
            answer_problem(self.course, self.request, self.gating_prob1, earned, max_possible)

            self.assert_user_has_prereq_milestone(self.non_staff_user, expected_has_milestone=result)
            self.assert_access_to_gated_content(self.non_staff_user)
示例#11
0
    def test_override(self):
        switch = WaffleSwitch(  # lint-amnesty, pylint: disable=toggle-missing-annotation
            "test_namespace.test_switch", module_name="testmodule"
        )

        self.assertFalse(switch.is_enabled())
        with override_waffle_switch(switch, active=True):
            self.assertTrue(switch.is_enabled())
        self.assertFalse(switch.is_enabled())
    def test_display_maintenance_warning_switch(self, display_warning):
        """
        Tests the `DISPLAY_MAINTENANCE_WARNING` switch is working as expected.

        Checks if the decorated request from `get_decorated_request` has a warning or not.
        """
        with override_waffle_switch(DISPLAY_MAINTENANCE_WARNING, active=display_warning):
            banner_added, _ = self.add_maintenance_banner()

            assert display_warning == banner_added
示例#13
0
 def test_without_cert(self):
     with override_waffle_switch(AUTO_CERTIFICATE_GENERATION, active=True):
         with mock.patch(
                 'lms.djangoapps.certificates.signals.generate_certificate_task',
                 return_value=None) as mock_cert_task:
             grade_factory = CourseGradeFactory()
             with mock_passing_grade():
                 grade_factory.update(self.user, self.course)
                 mock_cert_task.assert_called_with(self.user,
                                                   self.course_key)
示例#14
0
 def override_waffle_switch(self, override):
     """
     Override the setting of the ENABLE_COMPLETION_TRACKING waffle switch
     for the course of the test.
     Parameters:
         override (bool): True if tracking should be enabled.
     """
     _waffle_overrider = override_waffle_switch(
         waffle.ENABLE_COMPLETION_TRACKING_SWITCH, override)
     _waffle_overrider.__enter__()
     self.addCleanup(_waffle_overrider.__exit__, None, None, None)
示例#15
0
    def test_admin_login_redirect(self):
        with override_waffle_switch(ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY,
                                    True):
            response = self.client.get(reverse('admin:login'))
            assert response.url == '/login?next=/admin'
            assert response.status_code == 302

        with override_waffle_flag(ADMIN_AUTH_REDIRECT_TO_LMS, True):
            response = self.client.get(reverse('admin:login'))
            assert response.url == '/login?next=/admin'
            assert response.status_code == 302

        with override_waffle_switch(ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY,
                                    False):
            response = self.client.get(reverse('admin:login'))
            assert response.template_name == ['admin/login.html']

        with override_waffle_flag(ADMIN_AUTH_REDIRECT_TO_LMS, False):
            response = self.client.get(reverse('admin:login'))
            assert response.template_name == ['admin/login.html']
示例#16
0
 def test_cert_generation_on_photo_verification(self):
     with mock.patch(
             'lms.djangoapps.certificates.signals.generate_certificate_task',
             return_value=None) as mock_cert_task:
         with override_waffle_switch(AUTO_CERTIFICATE_GENERATION,
                                     active=True):
             attempt = SoftwareSecurePhotoVerification.objects.create(
                 user=self.user_two, status='submitted')
             attempt.approve()
             mock_cert_task.assert_called_with(self.user_two,
                                               self.course_two.id)
 def test_enable_completion_tracking(self):
     """
     Test response when the waffle switch is disabled (default).
     """
     with override_waffle_switch(ENABLE_COMPLETION_TRACKING_SWITCH, False):
         response = self.client.post(self.url, {'username': self.ENROLLED_USERNAME}, format='json')
     assert response.data == \
            {
                'detail': 'BlockCompletion.objects.submit_batch_completion'
                          ' should not be called when the feature is disabled.'
            }
     assert response.status_code == 400
示例#18
0
 def test_fire_task_allowlist_auto_disabled(self):
     """
     Test that the allowlist generation is not invoked if automatic generation is disabled
     """
     with mock.patch(
             'lms.djangoapps.certificates.signals.generate_allowlist_certificate_task',
             return_value=None) as mock_generate_allowlist_task:
         with override_waffle_switch(AUTO_CERTIFICATE_GENERATION,
                                     active=False):
             CertificateAllowlistFactory(user=self.user,
                                         course_id=self.ip_course.id)
             mock_generate_allowlist_task.assert_not_called()
示例#19
0
    def test_query_counts_uncached(self, store_type, expected_mongo_queries,
                                   with_storage_backing, num_sql_queries):
        with override_waffle_switch(STORAGE_BACKING_FOR_CACHE,
                                    active=with_storage_backing):
            course = self._create_course(store_type)
            clear_course_from_cache(course.id)

            self._get_blocks(
                course,
                expected_mongo_queries,
                expected_sql_queries=num_sql_queries,
            )
示例#20
0
    def test_id_verification_allowlist(self):
        # User is not on the allowlist
        with mock.patch(
            'lms.djangoapps.certificates.signals.generate_allowlist_certificate_task',
            return_value=None
        ) as mock_allowlist_task:
            with override_waffle_switch(AUTO_CERTIFICATE_GENERATION, active=True):
                attempt = SoftwareSecurePhotoVerification.objects.create(
                    user=self.user_two,
                    status='submitted'
                )
                attempt.approve()
                mock_allowlist_task.assert_not_called()

        # User is on the allowlist
        with mock.patch(
            'lms.djangoapps.certificates.signals.generate_allowlist_certificate_task',
            return_value=None
        ) as mock_allowlist_task:
            with override_waffle_switch(AUTO_CERTIFICATE_GENERATION, active=True):
                u = UserFactory.create()
                c = CourseFactory()
                course_key = c.id  # pylint: disable=no-member
                CourseEnrollmentFactory(
                    user=u,
                    course_id=course_key,
                    is_active=True,
                    mode='verified'
                )
                CertificateAllowlistFactory(
                    user=u,
                    course_id=course_key
                )
                attempt = SoftwareSecurePhotoVerification.objects.create(
                    user=u,
                    status='submitted'
                )
                attempt.approve()
                mock_allowlist_task.assert_called_with(u, course_key)
示例#21
0
    def test_update_collected_if_needed(self, with_storage_backing):
        with override_waffle_switch(STORAGE_BACKING_FOR_CACHE, active=with_storage_backing):
            with mock_registered_transformers(self.registered_transformers):
                assert TestTransformer1.collect_call_count == 0

                self.bs_manager.update_collected_if_needed()
                assert TestTransformer1.collect_call_count == 1

                self.bs_manager.update_collected_if_needed()
                expected_count = 1 if with_storage_backing else 2
                assert TestTransformer1.collect_call_count == expected_count

                self.collect_and_verify(expect_modulestore_called=False, expect_cache_updated=False)
示例#22
0
 def test_cert_generation_on_whitelist_append_self_paced(self):
     """
     Verify that signal is sent, received, and fires task
     based on 'AUTO_CERTIFICATE_GENERATION' flag
     """
     with mock.patch(
             'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
             return_value=None) as mock_generate_certificate_apply_async:
         with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH,
                                     active=False):
             CertificateWhitelistFactory(user=self.user,
                                         course_id=self.course.id)
             mock_generate_certificate_apply_async.assert_not_called()
         with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH,
                                     active=True):
             CertificateWhitelistFactory(user=self.user,
                                         course_id=self.course.id)
             mock_generate_certificate_apply_async.assert_called_with(
                 countdown=CERTIFICATE_DELAY_SECONDS,
                 kwargs={
                     'student': six.text_type(self.user.id),
                     'course_key': six.text_type(self.course.id),
                 })
示例#23
0
 def test_cert_generation_on_allowlist_append_self_paced_auto_cert_generation_disabled(
         self):
     """
     Verify that signal is sent, received, and fires task
     based on 'AUTO_CERTIFICATE_GENERATION' flag
     """
     with mock.patch(
             'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
             return_value=None) as mock_generate_certificate_apply_async:
         with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH,
                                     active=False):
             CertificateWhitelistFactory(user=self.user,
                                         course_id=self.course.id)
             mock_generate_certificate_apply_async.assert_not_called()
示例#24
0
    def test_cert_already_generated_unverified(self):
        with override_waffle_switch(AUTO_CERTIFICATE_GENERATION, active=True):
            GeneratedCertificateFactory(user=self.user,
                                        course_id=self.course.id,
                                        status=CertificateStatuses.unverified)

            with mock.patch(
                    'lms.djangoapps.certificates.signals.generate_certificate_task',
                    return_value=None) as mock_cert_task:
                grade_factory = CourseGradeFactory()
                with mock_passing_grade():
                    grade_factory.update(self.user, self.course)
                    mock_cert_task.assert_called_with(self.user,
                                                      self.course_key)
示例#25
0
 def test_zero_null_scores(self, assume_zero_enabled):
     """
     Creates a zero course grade and ensures that null scores aren't included in the section problem scores.
     """
     with override_waffle_switch(waffle_switch(ASSUME_ZERO_GRADE_IF_ABSENT),
                                 active=assume_zero_enabled):
         with patch('lms.djangoapps.grades.subsection_grade.get_score',
                    return_value=None):
             course_data = CourseData(self.request.user,
                                      structure=self.course_structure)
             chapter_grades = ZeroCourseGrade(self.request.user,
                                              course_data).chapter_grades
             for chapter in chapter_grades:
                 assert {} != chapter_grades[chapter]['sections']
                 for section in chapter_grades[chapter]['sections']:
                     assert {} == section.problem_scores
示例#26
0
 def test_zero(self, assume_zero_enabled):
     """
     Creates a ZeroCourseGrade and ensures it's empty.
     """
     with override_waffle_switch(waffle_switch(ASSUME_ZERO_GRADE_IF_ABSENT),
                                 active=assume_zero_enabled):
         course_data = CourseData(self.request.user,
                                  structure=self.course_structure)
         chapter_grades = ZeroCourseGrade(self.request.user,
                                          course_data).chapter_grades
         for chapter in chapter_grades:
             for section in chapter_grades[chapter]['sections']:
                 for score in six.itervalues(section.problem_scores):
                     self.assertEqual(score.earned, 0)
                     self.assertEqual(score.first_attempted, None)
                 self.assertEqual(section.all_total.earned, 0)
示例#27
0
 def test_cert_generation_on_photo_verification_v1(self):
     with mock.patch(
             'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
             return_value=None) as mock_cert_task:
         with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH,
                                     active=True):
             attempt = SoftwareSecurePhotoVerification.objects.create(
                 user=self.user_two, status='submitted')
             attempt.approve()
             mock_cert_task.assert_called_with(
                 countdown=CERTIFICATE_DELAY_SECONDS,
                 kwargs={
                     'student': str(self.user_two.id),
                     'course_key': str(self.course_two.id),
                     'expected_verification_status': 'approved'
                 })
示例#28
0
    def test_save_invalid_course_id(self):
        """
        Send an invalid course ID instead of "org.0/course_0/Run_0" when saving, and verify that it fails.
        """
        data = {
            'user': str(self.course_enrollment.user.id),
            'course': 'invalid-course-id',
            'is_active': 'true',
            'mode': self.course_enrollment.mode,
        }

        with override_waffle_switch(COURSE_ENROLLMENT_ADMIN_SWITCH, active=True):
            with pytest.raises(ValidationError):
                self.client.post(
                    reverse('admin:student_courseenrollment_change', args=(self.course_enrollment.id, )),
                    data=data,
                )
示例#29
0
    def test_gated_content_always_in_grades(self):
        with override_waffle_switch(ENABLE_COMPLETION_TRACKING_SWITCH, True):
            # start with a grade from a non-gated subsection
            answer_problem(self.course, self.request, self.prob3, 10, 10)

            # verify gated status and overall course grade percentage
            self.assert_user_has_prereq_milestone(self.non_staff_user, expected_has_milestone=False)
            self.assert_access_to_gated_content(self.non_staff_user)
            self.assert_course_grade(self.non_staff_user, .33)

            # fulfill the gated requirements
            answer_problem(self.course, self.request, self.gating_prob1, 10, 10)

            # verify gated status and overall course grade percentage
            self.assert_user_has_prereq_milestone(self.non_staff_user, expected_has_milestone=True)
            self.assert_access_to_gated_content(self.non_staff_user)
            self.assert_course_grade(self.non_staff_user, .67)
    def test_complete_student_attempt_split_test(self, mock_submit):
        """
        Asserts complete_student_attempt correctly publishes completion when a split test is involved

        This test case exists because we ran into a bug about the user_service not existing
        when a split_test existed inside of a subsection. Associated with this change was adding
        in the user state into the module before attempting completion and this ensures that is
        working properly.
        """
        partition = UserPartition(
            0,
            'first_partition',
            'First Partition',
            [
                Group(0, 'alpha'),
                Group(1, 'beta')
            ]
        )
        course = CourseFactory.create(user_partitions=[partition])
        section = ItemFactory.create(parent=course, category='chapter')
        subsection = ItemFactory.create(parent=section, category='sequential')

        c0_url = course.id.make_usage_key('vertical', 'split_test_cond0')
        c1_url = course.id.make_usage_key('vertical', 'split_test_cond1')
        split_test = ItemFactory.create(
            parent=subsection,
            category='split_test',
            user_partition_id=0,
            group_id_to_child={'0': c0_url, '1': c1_url},
        )

        cond0vert = ItemFactory.create(parent=split_test, category='vertical', location=c0_url)
        ItemFactory.create(parent=cond0vert, category='video')
        ItemFactory.create(parent=cond0vert, category='problem')

        cond1vert = ItemFactory.create(parent=split_test, category='vertical', location=c1_url)
        ItemFactory.create(parent=cond1vert, category='video')
        ItemFactory.create(parent=cond1vert, category='html')

        with override_waffle_switch(ENABLE_COMPLETION_TRACKING_SWITCH, True):
            self.service.complete_student_attempt(self.student.username, str(subsection.location))

        # Only the group the user was assigned to should have completion published.
        # Either cond0vert's children or cond1vert's children
        assert mock_submit.call_count == 2