Пример #1
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 waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=False):
             CertificateWhitelist.objects.create(
                 user=self.user,
                 course_id=self.course.id
             )
             mock_generate_certificate_apply_async.assert_not_called()
         with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=True):
             CertificateWhitelist.objects.create(
                 user=self.user,
                 course_id=self.course.id
             )
             mock_generate_certificate_apply_async.assert_called_with(
                 countdown=CERTIFICATE_DELAY_SECONDS,
                 kwargs={
                     'student': unicode(self.user.id),
                     'course_key': unicode(self.course.id),
                 }
             )
Пример #2
0
def configure_waffle_namespace(feature_enabled):
    namespace = certs_waffle.waffle()
    auto_certificate_generation_switch = LegacyWaffleSwitch(
        namespace, certs_waffle.AUTO_CERTIFICATE_GENERATION)
    with override_waffle_switch(auto_certificate_generation_switch,
                                active=feature_enabled):
        yield
Пример #3
0
def _listen_for_certificate_whitelist_append(sender, instance, **kwargs):  # pylint: disable=unused-argument
    switches = waffle.waffle()
    # All flags enabled
    if (not switches.is_enabled(waffle.SELF_PACED_ONLY)
            and not switches.is_enabled(waffle.INSTRUCTOR_PACED_ONLY)):
        return

    # Only SELF_PACED_ONLY flag enabled
    if not switches.is_enabled(waffle.INSTRUCTOR_PACED_ONLY):
        if not courses.get_course_by_id(instance.course_id,
                                        depth=0).self_paced:
            return

    # Only INSTRUCTOR_PACED_ONLY flag enabled
    if not switches.is_enabled(waffle.SELF_PACED_ONLY):
        if courses.get_course_by_id(instance.course_id, depth=0).self_paced:
            return

    generate_certificate.apply_async(
        student=instance.user,
        course_key=instance.course_id,
    )
    log.info(
        u'Certificate generation task initiated for {user} : {course} via whitelist'
        .format(user=instance.user.id, course=instance.course_id))
 def test_cert_generation_on_photo_verification_instructor_paced(self):
     with mock.patch(
             'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
             return_value=None) as mock_generate_certificate_apply_async:
         with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION,
                                       active=True):
             mock_generate_certificate_apply_async.assert_not_called()
             attempt = SoftwareSecurePhotoVerification.objects.create(
                 user=self.user_two, status='submitted')
             attempt.approve()
             expected_verification_status = {
                 'status': 'approved',
                 'error': '',
                 'should_display': True,
             }
             mock_generate_certificate_apply_async.assert_called_with(
                 countdown=CERTIFICATE_DELAY_SECONDS,
                 kwargs={
                     'student':
                     unicode(self.user_two.id),
                     'course_key':
                     unicode(self.course_two.id),
                     'expected_verification_status':
                     unicode(expected_verification_status),
                 })
Пример #5
0
def _listen_for_track_change(sender, user, **kwargs):  # pylint: disable=unused-argument
    """
    Catches a track change signal, determines user status,
    calls fire_ungenerated_certificate_task for passing grades
    """
    if (not waffle.waffle().is_enabled(waffle.SELF_PACED_ONLY)
            and not waffle.waffle().is_enabled(waffle.INSTRUCTOR_PACED_ONLY)):
        return
    user_enrollments = CourseEnrollment.enrollments_for_user(user=user)
    grade_factory = CourseGradeFactory()
    for enrollment in user_enrollments:
        if grade_factory.read(user=user, course=enrollment.course).passed:
            if fire_ungenerated_certificate_task(user, enrollment.course.id):
                log.info(
                    u'Certificate generation task initiated for {user} : {course} via track change'
                    .format(user=user.id, course=enrollment.course.id))
Пример #6
0
def configure_waffle_namespace(self_paced_enabled, instructor_paced_enabled):
    namespace = certs_waffle.waffle()

    with namespace.override(certs_waffle.SELF_PACED_ONLY,
                            active=self_paced_enabled):
        with namespace.override(certs_waffle.INSTRUCTOR_PACED_ONLY,
                                active=instructor_paced_enabled):
            yield
Пример #7
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
Пример #8
0
 def test_cert_generation_on_whitelist_append_instructor_paced(self):
     """
     Verify that signal is sent, received, and fires task
     based on 'INSTRUCTOR_PACED_ONLY' flag
     """
     with mock.patch(
             'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
             return_value=None) as mock_generate_certificate_apply_async:
         with waffle.waffle().override(waffle.INSTRUCTOR_PACED_ONLY,
                                       active=False):
             CertificateWhitelist.objects.create(
                 user=self.user, course_id=self.ip_course.id)
             mock_generate_certificate_apply_async.assert_not_called()
         with waffle.waffle().override(waffle.INSTRUCTOR_PACED_ONLY,
                                       active=True):
             CertificateWhitelist.objects.create(
                 user=self.user, course_id=self.ip_course.id)
             mock_generate_certificate_apply_async.assert_called_with(
                 student=self.user, course_key=self.ip_course.id)
Пример #9
0
def _listen_for_passing_grade(sender, user, course_id, **kwargs):  # pylint: disable=unused-argument
    """
    Listen for a learner passing a course, send cert generation task,
    downstream signal from COURSE_GRADE_CHANGED
    """
    # No flags enabled
    if (not waffle.waffle().is_enabled(waffle.SELF_PACED_ONLY)
            and not waffle.waffle().is_enabled(waffle.INSTRUCTOR_PACED_ONLY)):
        return

    if courses.get_course_by_id(course_id, depth=0).self_paced:
        if not waffle.waffle().is_enabled(waffle.SELF_PACED_ONLY):
            return
    else:
        if not waffle.waffle().is_enabled(waffle.INSTRUCTOR_PACED_ONLY):
            return

    if fire_ungenerated_certificate_task(user, course_id):
        log.info(
            u'Certificate generation task initiated for {user} : {course} via passing grade'
            .format(user=user.id, course=course_id))
Пример #10
0
 def test_cert_generation_on_passing_self_paced(self):
     with mock.patch(
             'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
             return_value=None) as mock_generate_certificate_apply_async:
         with waffle.waffle().override(waffle.SELF_PACED_ONLY, active=True):
             grade_factory = CourseGradeFactory()
             # Not passing
             grade_factory.update(self.user, self.course)
             mock_generate_certificate_apply_async.assert_not_called()
             # Certs fired after passing
             with mock_passing_grade():
                 grade_factory.update(self.user, self.course)
                 mock_generate_certificate_apply_async.assert_called_with(
                     student=self.user, course_key=self.course.id)
Пример #11
0
 def test_cert_generation_on_photo_verification_self_paced(self):
     with mock.patch(
             'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
             return_value=None) as mock_generate_certificate_apply_async:
         with waffle.waffle().override(waffle.SELF_PACED_ONLY, active=True):
             mock_generate_certificate_apply_async.assert_not_called()
             attempt = SoftwareSecurePhotoVerification.objects.create(
                 user=self.user_one, status='submitted')
             attempt.approve()
             mock_generate_certificate_apply_async.assert_called_with(
                 kwargs={
                     'student': unicode(self.user_one.id),
                     'course_key': unicode(self.course_one.id),
                 })
Пример #12
0
    def test_cert_generation_on_photo_verification_instructor_paced(self):
        with mock.patch(
                'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
                return_value=None) as mock_generate_certificate_apply_async:
            with mock_passing_grade():
                grade_factory = CourseGradeFactory()
                grade_factory.update(self.user_two, self.course_two)

            with waffle.waffle().override(waffle.INSTRUCTOR_PACED_ONLY,
                                          active=True):
                mock_generate_certificate_apply_async.assert_not_called()
                attempt = SoftwareSecurePhotoVerification.objects.create(
                    user=self.user_two, status='submitted')
                attempt.approve()
                mock_generate_certificate_apply_async.assert_called_with(
                    student=self.user_two, course_key=self.course_two.id)
Пример #13
0
def _listen_for_certificate_whitelist_append(sender, instance, **kwargs):  # pylint: disable=unused-argument
    switches = waffle.waffle()
    # No flags enabled
    if (not switches.is_enabled(waffle.SELF_PACED_ONLY)
            and not switches.is_enabled(waffle.INSTRUCTOR_PACED_ONLY)):
        return

    if courses.get_course_by_id(instance.course_id, depth=0).self_paced:
        if not switches.is_enabled(waffle.SELF_PACED_ONLY):
            return
    else:
        if not switches.is_enabled(waffle.INSTRUCTOR_PACED_ONLY):
            return

    fire_ungenerated_certificate_task(instance.user, instance.course_id)
    log.info(
        u'Certificate generation task initiated for {user} : {course} via whitelist'
        .format(user=instance.user.id, course=instance.course_id))
Пример #14
0
 def test_cert_generation_on_passing_instructor_paced(self):
     with mock.patch(
             'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
             return_value=None) as mock_generate_certificate_apply_async:
         with waffle.waffle().override(waffle.INSTRUCTOR_PACED_ONLY,
                                       active=True):
             grade_factory = CourseGradeFactory()
             # Not passing
             grade_factory.update(self.user, self.ip_course)
             mock_generate_certificate_apply_async.assert_not_called()
             # Certs fired after passing
             with mock_passing_grade():
                 grade_factory.update(self.user, self.ip_course)
                 mock_generate_certificate_apply_async.assert_called_with(
                     kwargs={
                         'student': unicode(self.user.id),
                         'course_key': unicode(self.ip_course.id),
                     })
Пример #15
0
 def test_fire_ungenerated_certificate_task_allowed_modes(
         self, enrollment_mode, should_create):
     """
     Test that certificate generation task is fired for only modes that are
     allowed to generate certificates automatically.
     """
     self.user = UserFactory.create()
     self.enrollment = CourseEnrollmentFactory(user=self.user,
                                               course_id=self.course.id,
                                               is_active=True,
                                               mode=enrollment_mode)
     with mock.patch(
             'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
             return_value=None) as mock_generate_certificate_apply_async:
         with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION,
                                       active=True):
             fire_ungenerated_certificate_task(self.user, self.course.id)
             task_created = mock_generate_certificate_apply_async.called
             self.assertEqual(task_created, should_create)
Пример #16
0
 def test_cert_generation_on_passing_instructor_paced(self):
     with mock.patch(
             'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
             return_value=None) as mock_generate_certificate_apply_async:
         with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION,
                                       active=True):
             grade_factory = CourseGradeFactory()
             # Not passing
             grade_factory.update(self.user, self.ip_course)
             mock_generate_certificate_apply_async.assert_not_called()
             # Certs fired after passing
             with mock_passing_grade():
                 grade_factory.update(self.user, self.ip_course)
                 mock_generate_certificate_apply_async.assert_called_with(
                     countdown=CERTIFICATE_DELAY_SECONDS,
                     kwargs={
                         'student': unicode(self.user.id),
                         'course_key': unicode(self.ip_course.id),
                     })
Пример #17
0
 def test_cert_generation_on_photo_verification_instructor_paced(self):
     with mock.patch(
         'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
         return_value=None
     ) as mock_generate_certificate_apply_async:
         with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=True):
             mock_generate_certificate_apply_async.assert_not_called()
             attempt = SoftwareSecurePhotoVerification.objects.create(
                 user=self.user_two,
                 status='submitted'
             )
             attempt.approve()
             mock_generate_certificate_apply_async.assert_called_with(
                 countdown=CERTIFICATE_DELAY_SECONDS,
                 kwargs={
                     'student': unicode(self.user_two.id),
                     'course_key': unicode(self.course_two.id),
                     'expected_verification_status': IDVerificationAttempt.STATUS.approved,
                 }
             )
 def test_cert_generation_on_photo_verification_self_paced(self):
     with mock.patch(
             'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
             return_value=None) as mock_generate_certificate_apply_async:
         with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION,
                                       active=True):
             mock_generate_certificate_apply_async.assert_not_called()
             attempt = SoftwareSecurePhotoVerification.objects.create(
                 user=self.user_one, status='submitted')
             attempt.approve()
             mock_generate_certificate_apply_async.assert_called_with(
                 countdown=CERTIFICATE_DELAY_SECONDS,
                 kwargs={
                     'student':
                     six.text_type(self.user_one.id),
                     'course_key':
                     six.text_type(self.course_one.id),
                     'expected_verification_status':
                     IDVerificationAttempt.STATUS.approved,
                 })
Пример #19
0
 def test_fire_ungenerated_certificate_task_allowed_modes(self, enrollment_mode, should_create):
     """
     Test that certificate generation task is fired for only modes that are
     allowed to generate certificates automatically.
     """
     self.user = UserFactory.create()
     self.enrollment = CourseEnrollmentFactory(
         user=self.user,
         course_id=self.course.id,
         is_active=True,
         mode=enrollment_mode
     )
     with mock.patch(
         'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
         return_value=None
     ) as mock_generate_certificate_apply_async:
         with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=True):
             fire_ungenerated_certificate_task(self.user, self.course.id)
             task_created = mock_generate_certificate_apply_async.called
             self.assertEqual(task_created, should_create)
Пример #20
0
 def test_cert_generation_on_passing_instructor_paced(self):
     with mock.patch(
         'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
         return_value=None
     ) as mock_generate_certificate_apply_async:
         with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=True):
             grade_factory = CourseGradeFactory()
             # Not passing
             grade_factory.update(self.user, self.ip_course)
             mock_generate_certificate_apply_async.assert_not_called()
             # Certs fired after passing
             with mock_passing_grade():
                 grade_factory.update(self.user, self.ip_course)
                 mock_generate_certificate_apply_async.assert_called_with(
                     countdown=CERTIFICATE_DELAY_SECONDS,
                     kwargs={
                         'student': unicode(self.user.id),
                         'course_key': unicode(self.ip_course.id),
                     }
                 )
Пример #21
0
from lms.djangoapps.certificates.generation_handler import CERTIFICATES_USE_UPDATED
from lms.djangoapps.certificates.models import (
    CertificateGenerationConfiguration, CertificateStatuses,
    GeneratedCertificate)
from lms.djangoapps.certificates.signals import _fire_ungenerated_certificate_task
from lms.djangoapps.certificates.tasks import CERTIFICATE_DELAY_SECONDS
from lms.djangoapps.certificates.tests.factories import CertificateAllowlistFactory, GeneratedCertificateFactory
from lms.djangoapps.grades.course_grade_factory import CourseGradeFactory
from lms.djangoapps.grades.tests.utils import mock_passing_grade
from lms.djangoapps.verify_student.models import IDVerificationAttempt, SoftwareSecurePhotoVerification
from openedx.core.djangoapps.certificates.config import waffle
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory

AUTO_CERTIFICATE_GENERATION_SWITCH = LegacyWaffleSwitch(
    waffle.waffle(), waffle.AUTO_CERTIFICATE_GENERATION)  # lint-amnesty, pylint: disable=toggle-missing-annotation


class SelfGeneratedCertsSignalTest(ModuleStoreTestCase):
    """
    Tests for enabling/disabling self-generated certificates according to course-pacing.
    """
    ENABLED_SIGNALS = ['course_published']

    def setUp(self):
        super().setUp()
        CertificateGenerationConfiguration.objects.create(enabled=True)

    def test_cert_generation_flag_on_pacing_toggle(self):
        """
        Verify that signal enables or disables self-generated certificates
Пример #22
0
def configure_waffle_namespace(feature_enabled):
    namespace = certs_waffle.waffle()

    with namespace.override(certs_waffle.AUTO_CERTIFICATE_GENERATION, active=feature_enabled):
        yield
Пример #23
0
"""
The public API for certificates.
"""
from datetime import datetime
from pytz import UTC
from openedx.core.djangoapps.certificates.config import waffle


SWITCHES = waffle.waffle()


def auto_certificate_generation_enabled():
    return SWITCHES.is_enabled(waffle.AUTO_CERTIFICATE_GENERATION)


def _enabled_and_instructor_paced(course):
    if auto_certificate_generation_enabled():
        return not course.self_paced
    return False


def can_show_certificate_available_date_field(course):
    return _enabled_and_instructor_paced(course)


def display_date_for_certificate(course, certificate):
    if (
        auto_certificate_generation_enabled() and
        not course.self_paced and
        course.certificate_available_date and
        course.certificate_available_date < datetime.now(UTC)
Пример #24
0
def configure_waffle_namespace(feature_enabled):
    namespace = certs_waffle.waffle()

    with namespace.override(certs_waffle.AUTO_CERTIFICATE_GENERATION, active=feature_enabled):
        yield
Пример #25
0
 def is_enabled(self):
     return (
         self.date is not None and datetime.datetime.now(utc) <= self.date and not self.course.self_paced and
         waffle.waffle().is_enabled(waffle.INSTRUCTOR_PACED_ONLY)
     )
Пример #26
0
from lms.djangoapps.certificates import api as certs_api
from lms.djangoapps.certificates.generation_handler import CERTIFICATES_USE_ALLOWLIST
from lms.djangoapps.certificates.models import (
    CertificateGenerationConfiguration, CertificateStatuses,
    GeneratedCertificate)
from lms.djangoapps.certificates.signals import fire_ungenerated_certificate_task
from lms.djangoapps.certificates.tasks import CERTIFICATE_DELAY_SECONDS
from lms.djangoapps.certificates.tests.factories import CertificateWhitelistFactory
from lms.djangoapps.certificates.tests.factories import GeneratedCertificateFactory
from lms.djangoapps.grades.course_grade_factory import CourseGradeFactory
from lms.djangoapps.grades.tests.utils import mock_passing_grade
from lms.djangoapps.verify_student.models import IDVerificationAttempt, SoftwareSecurePhotoVerification
from openedx.core.djangoapps.certificates.config import waffle

AUTO_CERTIFICATE_GENERATION_SWITCH = LegacyWaffleSwitch(
    waffle.waffle(), waffle.AUTO_CERTIFICATE_GENERATION)


class SelfGeneratedCertsSignalTest(ModuleStoreTestCase):
    """
    Tests for enabling/disabling self-generated certificates according to course-pacing.
    """
    ENABLED_SIGNALS = ['course_published']

    def setUp(self):
        super(SelfGeneratedCertsSignalTest, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
        CertificateGenerationConfiguration.objects.create(enabled=True)

    def test_cert_generation_flag_on_pacing_toggle(self):
        """
        Verify that signal enables or disables self-generated certificates
Пример #27
0
from lms.djangoapps.certificates.generation_handler import CERTIFICATES_USE_UPDATED
from lms.djangoapps.certificates.data import CertificateStatuses
from lms.djangoapps.certificates.models import (
    CertificateGenerationConfiguration,
    GeneratedCertificate
)
from lms.djangoapps.certificates.signals import _fire_ungenerated_certificate_task
from lms.djangoapps.certificates.tests.factories import CertificateAllowlistFactory, GeneratedCertificateFactory
from lms.djangoapps.grades.course_grade_factory import CourseGradeFactory
from lms.djangoapps.grades.tests.utils import mock_passing_grade
from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification
from openedx.core.djangoapps.certificates.config import waffle
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory

AUTO_CERTIFICATE_GENERATION_SWITCH = LegacyWaffleSwitch(waffle.waffle(), waffle.AUTO_CERTIFICATE_GENERATION)  # lint-amnesty, pylint: disable=toggle-missing-annotation


class SelfGeneratedCertsSignalTest(ModuleStoreTestCase):
    """
    Tests for enabling/disabling self-generated certificates according to course-pacing.
    """
    ENABLED_SIGNALS = ['course_published']

    def setUp(self):
        super().setUp()
        CertificateGenerationConfiguration.objects.create(enabled=True)

    def test_cert_generation_flag_on_pacing_toggle(self):
        """
        Verify that signal enables or disables self-generated certificates
"""
The public API for certificates.
"""
import logging
from datetime import datetime

from pytz import UTC

from lms.djangoapps.certificates.models import CertificateWhitelist
from openedx.core.djangoapps.certificates.config import waffle
from student.models import CourseEnrollment

log = logging.getLogger(__name__)

SWITCHES = waffle.waffle()


def auto_certificate_generation_enabled():
    return SWITCHES.is_enabled(waffle.AUTO_CERTIFICATE_GENERATION)


def _enabled_and_instructor_paced(course):
    if auto_certificate_generation_enabled():
        return not course.self_paced
    return False


def certificates_viewable_for_course(course):
    """
    Returns True if certificates are viewable for any student enrolled in the course, False otherwise.
    """
Пример #29
0
from lms.djangoapps.certificates.generation_handler import CERTIFICATES_USE_ALLOWLIST
from lms.djangoapps.certificates.models import (
    CertificateGenerationConfiguration,
    CertificateStatuses,
    GeneratedCertificate
)
from lms.djangoapps.certificates.signals import fire_ungenerated_certificate_task
from lms.djangoapps.certificates.tasks import CERTIFICATE_DELAY_SECONDS
from lms.djangoapps.certificates.tests.factories import CertificateWhitelistFactory
from lms.djangoapps.certificates.tests.factories import GeneratedCertificateFactory
from lms.djangoapps.grades.course_grade_factory import CourseGradeFactory
from lms.djangoapps.grades.tests.utils import mock_passing_grade
from lms.djangoapps.verify_student.models import IDVerificationAttempt, SoftwareSecurePhotoVerification
from openedx.core.djangoapps.certificates.config import waffle

AUTO_CERTIFICATE_GENERATION_SWITCH = LegacyWaffleSwitch(waffle.waffle(), waffle.AUTO_CERTIFICATE_GENERATION)


class SelfGeneratedCertsSignalTest(ModuleStoreTestCase):
    """
    Tests for enabling/disabling self-generated certificates according to course-pacing.
    """
    ENABLED_SIGNALS = ['course_published']

    def setUp(self):
        super(SelfGeneratedCertsSignalTest, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
        CertificateGenerationConfiguration.objects.create(enabled=True)

    def test_cert_generation_flag_on_pacing_toggle(self):
        """
        Verify that signal enables or disables self-generated certificates