def test_course_details_with_enabled_setting(self):
        """
        Test that credit eligibility requirements are present in
        response if the feature flag 'ENABLE_CREDIT_ELIGIBILITY' is enabled.
        """
        # verify that credit eligibility requirements block don't show if the
        # course is not set as credit course
        response = self.client.get_html(self.course_details_url)
        self.assertEqual(response.status_code, 200)
        self.assertNotContains(response, "Course Credit Requirements")
        self.assertNotContains(response, "Steps required to earn course credit")

        # verify that credit eligibility requirements block shows if the
        # course is set as credit course and it has eligibility requirements
        credit_course = CreditCourse(course_key=unicode(self.course.id), enabled=True)
        credit_course.save()
        self.assertEqual(len(get_credit_requirements(self.course.id)), 0)
        # test that after publishing course, minimum grade requirement is added
        on_course_publish(self.course.id)
        self.assertEqual(len(get_credit_requirements(self.course.id)), 1)

        response = self.client.get_html(self.course_details_url)
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "Course Credit Requirements")
        self.assertContains(response, "Steps required to earn course credit")
Exemplo n.º 2
0
    def test_disable_credit_requirements(self):
        self.add_credit_course()
        requirements = [{
            "namespace": "grade",
            "name": "grade",
            "criteria": {
                "min_grade": 0.8
            }
        }, {
            "namespace": "grade",
            "name": "grade",
            "criteria": {
                "min_grade": 0.8
            }
        }]
        set_credit_requirements(self.course_key, requirements)
        self.assertEqual(len(get_credit_requirements(self.course_key)), 1)

        requirements = [{
            "namespace": "reverification",
            "name": "midterm",
            "criteria": {}
        }]
        set_credit_requirements(self.course_key, requirements)
        self.assertEqual(len(get_credit_requirements(self.course_key)), 1)
        grade_req = CreditRequirement.objects.filter(namespace="grade",
                                                     name="grade")
        self.assertEqual(len(grade_req), 1)
        self.assertEqual(grade_req[0].active, False)
Exemplo n.º 3
0
    def test_proctored_exam_requirements(self):
        """
        Make sure that proctored exams are being registered as requirements
        """

        self.add_credit_course(self.course.id)
        create_exam(
            course_id=unicode(self.course.id),
            content_id='foo',
            exam_name='A Proctored Exam',
            time_limit_mins=10,
            is_proctored=True,
            is_active=True
        )

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)
        on_course_publish(self.course.id)

        # just inspect the proctored exam requirement
        requirements = [
            requirement
            for requirement in get_credit_requirements(self.course.id)
            if requirement['namespace'] == 'proctored_exam'
        ]

        self.assertEqual(len(requirements), 1)
        self.assertEqual(requirements[0]['namespace'], 'proctored_exam')
        self.assertEqual(requirements[0]['name'], 'proctored_exam_id:1')
        self.assertEqual(requirements[0]['display_name'], 'A Proctored Exam')
        self.assertEqual(requirements[0]['criteria'], {})
Exemplo n.º 4
0
    def test_disable_credit_requirements(self):
        self.add_credit_course()
        requirements = [{
            "namespace": "grade",
            "name": "grade",
            "display_name": "Grade",
            "criteria": {
                "min_grade": 0.8
            },
        }]
        api.set_credit_requirements(self.course_key, requirements)
        self.assertEqual(len(api.get_credit_requirements(self.course_key)), 1)

        requirements = [{
            "namespace": "reverification",
            "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
            "display_name": "Assessment 1",
            "criteria": {},
        }]
        api.set_credit_requirements(self.course_key, requirements)
        self.assertEqual(len(api.get_credit_requirements(self.course_key)), 1)

        grade_req = CreditRequirement.objects.filter(namespace="grade",
                                                     name="grade")
        self.assertEqual(len(grade_req), 1)
        self.assertEqual(grade_req[0].active, False)
Exemplo n.º 5
0
    def test_set_get_credit_requirements(self):
        """Test that if same requirement is added multiple times
        then it is added only one time and update for next all iterations.
        """
        self.add_credit_course()
        requirements = [
            {
                "namespace": "grade",
                "name": "grade",
                "display_name": "Grade",
                "criteria": {
                    "min_grade": 0.8
                }
            },
            {
                "namespace": "grade",
                "name": "grade",
                "display_name": "Grade",
                "criteria": {
                    "min_grade": 0.9
                }
            }
        ]
        set_credit_requirements(self.course_key, requirements)
        self.assertEqual(len(get_credit_requirements(self.course_key)), 1)

        # now verify that the saved requirement has values of last requirement
        # from all same requirements
        self.assertEqual(get_credit_requirements(self.course_key)[0], requirements[1])
Exemplo n.º 6
0
    def test_disable_credit_requirements(self):
        self.add_credit_course()
        requirements = [
            {
                "namespace": "grade",
                "name": "grade",
                "display_name": "Grade",
                "criteria": {
                    "min_grade": 0.8
                }
            }
        ]
        set_credit_requirements(self.course_key, requirements)
        self.assertEqual(len(get_credit_requirements(self.course_key)), 1)

        requirements = [
            {
                "namespace": "reverification",
                "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
                "display_name": "Assessment 1",
                "criteria": {}
            }
        ]
        set_credit_requirements(self.course_key, requirements)
        self.assertEqual(len(get_credit_requirements(self.course_key)), 1)

        grade_req = CreditRequirement.objects.filter(namespace="grade", name="grade")
        self.assertEqual(len(grade_req), 1)
        self.assertEqual(grade_req[0].active, False)
Exemplo n.º 7
0
    def test_disable_credit_requirements(self):
        self.add_credit_course()
        requirements = [
            {
                "namespace": "grade",
                "name": "grade",
                "criteria": {
                    "min_grade": 0.8
                }
            },
            {
                "namespace": "grade",
                "name": "grade",
                "criteria": {
                    "min_grade": 0.8
                }
            }
        ]
        set_credit_requirements(self.course_key, requirements)
        self.assertEqual(len(get_credit_requirements(self.course_key)), 1)

        requirements = [
            {
                "namespace": "reverification",
                "name": "midterm",
                "criteria": {}
            }
        ]
        set_credit_requirements(self.course_key, requirements)
        self.assertEqual(len(get_credit_requirements(self.course_key)), 1)
        grade_req = CreditRequirement.objects.filter(namespace="grade", name="grade")
        self.assertEqual(len(grade_req), 1)
        self.assertEqual(grade_req[0].active, False)
Exemplo n.º 8
0
    def test_course_details_with_enabled_setting(self):
        """
        Test that credit eligibility requirements are present in
        response if the feature flag 'ENABLE_CREDIT_ELIGIBILITY' is enabled.
        """
        # verify that credit eligibility requirements block don't show if the
        # course is not set as credit course
        response = self.client.get_html(self.course_details_url)
        self.assertEqual(response.status_code, 200)
        self.assertNotContains(response, "Course Credit Requirements")
        self.assertNotContains(response,
                               "Steps required to earn course credit")

        # verify that credit eligibility requirements block shows if the
        # course is set as credit course and it has eligibility requirements
        credit_course = CreditCourse(course_key=six.text_type(self.course.id),
                                     enabled=True)
        credit_course.save()
        self.assertEqual(len(get_credit_requirements(self.course.id)), 0)
        # test that after publishing course, minimum grade requirement is added
        on_course_publish(self.course.id)
        self.assertEqual(len(get_credit_requirements(self.course.id)), 1)

        response = self.client.get_html(self.course_details_url)
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "Course Credit Requirements")
        self.assertContains(response, "Steps required to earn course credit")
Exemplo n.º 9
0
    def test_proctored_exam_requirements(self):
        """
        Make sure that proctored exams are being registered as requirements
        """

        self.add_credit_course(self.course.id)

        create_exam(
            course_id=str(self.course.id),
            content_id=str(self.subsection.location),
            exam_name='A Proctored Exam',
            time_limit_mins=10,
            is_proctored=True,
            is_active=True
        )

        requirements = get_credit_requirements(self.course.id)
        assert len(requirements) == 0

        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        assert len(requirements) == 2
        assert requirements[1]['namespace'] == 'proctored_exam'
        assert requirements[1]['name'] == str(self.subsection.location)
        assert requirements[1]['display_name'] == 'A Proctored Exam'
        assert requirements[1]['criteria'] == {}
Exemplo n.º 10
0
    def test_proctored_exam_requirements(self):
        """
        Make sure that proctored exams are being registered as requirements
        """

        self.add_credit_course(self.course.id)

        create_exam(
            course_id=six.text_type(self.course.id),
            content_id=six.text_type(self.subsection.location),
            exam_name='A Proctored Exam',
            time_limit_mins=10,
            is_proctored=True,
            is_active=True
        )

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)

        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 2)
        self.assertEqual(requirements[1]['namespace'], 'proctored_exam')
        self.assertEqual(requirements[1]['name'], six.text_type(self.subsection.location))
        self.assertEqual(requirements[1]['display_name'], 'A Proctored Exam')
        self.assertEqual(requirements[1]['criteria'], {})
Exemplo n.º 11
0
    def test_proctored_exam_requirements(self):
        """
        Make sure that proctored exams are being registered as requirements
        """

        self.add_credit_course(self.course.id)

        create_exam(course_id=six.text_type(self.course.id),
                    content_id=six.text_type(self.subsection.location),
                    exam_name='A Proctored Exam',
                    time_limit_mins=10,
                    is_proctored=True,
                    is_active=True)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)

        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 2)
        self.assertEqual(requirements[1]['namespace'], 'proctored_exam')
        self.assertEqual(requirements[1]['name'],
                         six.text_type(self.subsection.location))
        self.assertEqual(requirements[1]['display_name'], 'A Proctored Exam')
        self.assertEqual(requirements[1]['criteria'], {})
Exemplo n.º 12
0
    def test_proctored_exam_requirements(self):
        """
        Make sure that proctored exams are being registered as requirements
        """

        self.add_credit_course(self.course.id)
        create_exam(course_id=unicode(self.course.id),
                    content_id='foo',
                    exam_name='A Proctored Exam',
                    time_limit_mins=10,
                    is_proctored=True,
                    is_active=True)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)
        on_course_publish(self.course.id)

        # just inspect the proctored exam requirement
        requirements = [
            requirement
            for requirement in get_credit_requirements(self.course.id)
            if requirement['namespace'] == 'proctored_exam'
        ]

        self.assertEqual(len(requirements), 1)
        self.assertEqual(requirements[0]['namespace'], 'proctored_exam')
        self.assertEqual(requirements[0]['name'], 'proctored_exam_id:1')
        self.assertEqual(requirements[0]['display_name'], 'A Proctored Exam')
        self.assertEqual(requirements[0]['criteria'], {})
Exemplo n.º 13
0
    def test_task_adding_requirements_invalid_course(self):
        """
        Test that credit requirements cannot be added for non credit course.
        """
        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)
        listen_for_course_publish(self, self.course.id)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)
Exemplo n.º 14
0
    def test_task_adding_requirements_invalid_course(self):
        """
        Test that credit requirements cannot be added for non credit course.
        """
        requirements = get_credit_requirements(self.course.id)
        assert len(requirements) == 0
        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        assert len(requirements) == 0
Exemplo n.º 15
0
    def test_task_adding_requirements_invalid_course(self):
        """
        Test that credit requirements cannot be added for non credit course.
        """
        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)
        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)
Exemplo n.º 16
0
    def test_task_adding_requirements_invalid_course(self):
        """
        Make sure that the receiver correctly fires off the task when
        invoked by signal
        """
        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)
        listen_for_course_publish(self, self.course.id)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)
Exemplo n.º 17
0
    def test_task_adding_icrv_requirements(self):
        """Make sure that the receiver correctly fires off the task when
        invoked by signal.
        """
        self.add_credit_course(self.course.id)
        self.add_icrv_xblock()
        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)
        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 2)
Exemplo n.º 18
0
    def test_task_adding_icrv_requirements(self):
        """Make sure that the receiver correctly fires off the task when
        invoked by signal.
        """
        self.add_credit_course(self.course.id)
        self.add_icrv_xblock()
        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)
        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 2)
Exemplo n.º 19
0
    def test_task_adding_requirements(self):
        """Test that credit requirements are added properly for credit course.

        Make sure that the receiver correctly fires off the task when
        invoked by signal.
        """
        self.add_credit_course(self.course.id)
        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)
        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 1)
Exemplo n.º 20
0
    def test_task_adding_requirements(self):
        """Test that credit requirements are added properly for credit course.

        Make sure that the receiver correctly fires off the task when
        invoked by signal.
        """
        self.add_credit_course(self.course.id)
        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)
        listen_for_course_publish(self, self.course.id)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 1)
Exemplo n.º 21
0
    def test_retry(self):
        """Test that adding credit requirements is retried when
        'InvalidCreditRequirements' exception is raised.

        Make sure that the receiver correctly fires off the task when
        invoked by signal
        """
        self.add_credit_course(self.course.id)
        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)
        listen_for_course_publish(self, self.course.id)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)
Exemplo n.º 22
0
    def test_proctored_exam_filtering(self):
        """
        Make sure that timed or inactive exams do not end up in the requirements table
        """

        self.add_credit_course(self.course.id)
        create_exam(
            course_id=unicode(self.course.id),
            content_id='foo',
            exam_name='A Proctored Exam',
            time_limit_mins=10,
            is_proctored=False,
            is_active=True
        )

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)

        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 1)

        # make sure we don't have a proctoring requirement
        self.assertFalse([
            requirement
            for requirement in requirements
            if requirement['namespace'] == 'proctored_exam'
        ])

        create_exam(
            course_id=unicode(self.course.id),
            content_id='foo2',
            exam_name='A Proctored Exam',
            time_limit_mins=10,
            is_proctored=True,
            is_active=False
        )

        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 1)

        # make sure we don't have a proctoring requirement
        self.assertFalse([
            requirement
            for requirement in requirements
            if requirement['namespace'] == 'proctored_exam'
        ])
Exemplo n.º 23
0
    def test_retry(self):
        """Test that adding credit requirements is retried when
        'InvalidCreditRequirements' exception is raised.

        Make sure that the receiver correctly fires off the task when
        invoked by signal
        """
        self.add_credit_course(self.course.id)
        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)
        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)
Exemplo n.º 24
0
    def test_remove_credit_requirement_status(self):
        self.add_credit_course()
        requirements = [
            {"namespace": "grade", "name": "grade", "display_name": "Grade", "criteria": {"min_grade": 0.8}},
            {
                "namespace": "reverification",
                "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
                "display_name": "Assessment 1",
                "criteria": {},
            },
        ]

        api.set_credit_requirements(self.course_key, requirements)
        course_requirements = api.get_credit_requirements(self.course_key)
        self.assertEqual(len(course_requirements), 2)

        # before setting credit_requirement_status
        api.remove_credit_requirement_status("staff", self.course_key, "grade", "grade")
        req_status = api.get_credit_requirement_status(self.course_key, "staff", namespace="grade", name="grade")
        self.assertIsNone(req_status[0]["status"])
        self.assertIsNone(req_status[0]["status_date"])
        self.assertIsNone(req_status[0]["reason"])

        # Set the requirement to "satisfied" and check that it's actually set
        api.set_credit_requirement_status("staff", self.course_key, "grade", "grade")
        req_status = api.get_credit_requirement_status(self.course_key, "staff", namespace="grade", name="grade")
        self.assertEqual(len(req_status), 1)
        self.assertEqual(req_status[0]["status"], "satisfied")

        # remove the credit requirement status and check that it's actually removed
        api.remove_credit_requirement_status("staff", self.course_key, "grade", "grade")
        req_status = api.get_credit_requirement_status(self.course_key, "staff", namespace="grade", name="grade")
        self.assertIsNone(req_status[0]["status"])
        self.assertIsNone(req_status[0]["status_date"])
        self.assertIsNone(req_status[0]["reason"])
Exemplo n.º 25
0
    def test_disable_existing_requirement(self):
        self.add_credit_course()

        # Set initial requirements
        requirements = [{
            "namespace": "reverification",
            "name": "midterm",
            "display_name": "Midterm",
            "criteria": {},
        }, {
            "namespace": "grade",
            "name": "grade",
            "display_name": "Grade",
            "criteria": {
                "min_grade": 0.8
            },
        }]
        api.set_credit_requirements(self.course_key, requirements)

        # Update the requirements, removing an existing requirement
        api.set_credit_requirements(self.course_key, requirements[1:])

        # Expect that now only the grade requirement is returned
        visible_reqs = api.get_credit_requirements(self.course_key)
        self.assertEqual(len(visible_reqs), 1)
        self.assertEqual(visible_reqs[0]["namespace"], "grade")
Exemplo n.º 26
0
    def test_disable_existing_requirement(self):
        self.add_credit_course()

        # Set initial requirements
        requirements = [
            {
                "namespace": "reverification",
                "name": "midterm",
                "display_name": "Midterm",
                "criteria": {},
            },
            {
                "namespace": "grade",
                "name": "grade",
                "display_name": "Grade",
                "criteria": {
                    "min_grade": 0.8
                },
            }
        ]
        api.set_credit_requirements(self.course_key, requirements)

        # Update the requirements, removing an existing requirement
        api.set_credit_requirements(self.course_key, requirements[1:])

        # Expect that now only the grade requirement is returned
        visible_reqs = api.get_credit_requirements(self.course_key)
        self.assertEqual(len(visible_reqs), 1)
        self.assertEqual(visible_reqs[0]["namespace"], "grade")
Exemplo n.º 27
0
    def test_set_credit_requirement_status(self):
        self.add_credit_course()
        requirements = [
            {"namespace": "grade", "name": "grade", "display_name": "Grade", "criteria": {"min_grade": 0.8}},
            {
                "namespace": "reverification",
                "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
                "display_name": "Assessment 1",
                "criteria": {},
            },
        ]

        api.set_credit_requirements(self.course_key, requirements)
        course_requirements = api.get_credit_requirements(self.course_key)
        self.assertEqual(len(course_requirements), 2)

        # Initially, the status should be None
        req_status = api.get_credit_requirement_status(self.course_key, "staff", namespace="grade", name="grade")
        self.assertEqual(req_status[0]["status"], None)

        # Set the requirement to "satisfied" and check that it's actually set
        api.set_credit_requirement_status("staff", self.course_key, "grade", "grade")
        req_status = api.get_credit_requirement_status(self.course_key, "staff", namespace="grade", name="grade")
        self.assertEqual(req_status[0]["status"], "satisfied")

        # Set the requirement to "failed" and check that it's actually set
        api.set_credit_requirement_status("staff", self.course_key, "grade", "grade", status="failed")
        req_status = api.get_credit_requirement_status(self.course_key, "staff", namespace="grade", name="grade")
        self.assertEqual(req_status[0]["status"], "failed")
Exemplo n.º 28
0
    def test_credit_requirement_blocks_ordering(self):
        """
        Test ordering of the proctoring and ICRV blocks are in proper order.
        """

        self.add_credit_course(self.course.id)
        subsection = ItemFactory.create(parent=self.section,
                                        category='sequential',
                                        display_name='Dummy Subsection')
        create_exam(course_id=unicode(self.course.id),
                    content_id=unicode(subsection.location),
                    exam_name='A Proctored Exam',
                    time_limit_mins=10,
                    is_proctored=True,
                    is_active=True)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)
        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 2)
        self.assertEqual(requirements[1]['namespace'], 'proctored_exam')
        self.assertEqual(requirements[1]['name'], unicode(subsection.location))
        self.assertEqual(requirements[1]['display_name'], 'A Proctored Exam')
        self.assertEqual(requirements[1]['criteria'], {})

        # Create multiple ICRV blocks
        start = datetime.now(UTC)
        self.add_icrv_xblock(related_assessment_name="Midterm A",
                             start_date=start)

        start = start - timedelta(days=1)
        self.add_icrv_xblock(related_assessment_name="Midterm B",
                             start_date=start)

        # Primary sort is based on start date
        on_course_publish(self.course.id)
        requirements = get_credit_requirements(self.course.id)
        # grade requirement is added on publish of the requirements
        self.assertEqual(len(requirements), 4)
        # check requirements are added in the desired order
        # 1st Minimum grade then the blocks with start date than other blocks
        self.assertEqual(requirements[0]["display_name"], "Minimum Grade")
        self.assertEqual(requirements[1]["display_name"], "A Proctored Exam")
        self.assertEqual(requirements[2]["display_name"], "Midterm B")
        self.assertEqual(requirements[3]["display_name"], "Midterm A")
Exemplo n.º 29
0
    def test_icrv_requirement_ordering(self):
        self.add_credit_course(self.course.id)

        # Create multiple ICRV blocks
        start = datetime.now(UTC)
        self.add_icrv_xblock(related_assessment_name="Midterm A",
                             start_date=start)

        start = start - timedelta(days=1)
        self.add_icrv_xblock(related_assessment_name="Midterm B",
                             start_date=start)

        # Primary sort is based on start date
        on_course_publish(self.course.id)
        requirements = get_credit_requirements(self.course.id,
                                               namespace="reverification")
        self.assertEqual(len(requirements), 2)
        self.assertEqual(requirements[0]["display_name"], "Midterm B")
        self.assertEqual(requirements[1]["display_name"], "Midterm A")

        # Add two additional ICRV blocks that have no start date
        # and the same name.
        start = datetime.now(UTC)
        first_block = self.add_icrv_xblock(
            related_assessment_name="Midterm Start Date")

        start = start + timedelta(days=1)
        second_block = self.add_icrv_xblock(
            related_assessment_name="Midterm Start Date")

        on_course_publish(self.course.id)
        requirements = get_credit_requirements(self.course.id,
                                               namespace="reverification")
        self.assertEqual(len(requirements), 4)
        # Since we are now primarily sorting on start_date and display_name if
        # start_date is present otherwise we are just sorting on display_name.
        self.assertEqual(requirements[0]["display_name"], "Midterm B")
        self.assertEqual(requirements[1]["display_name"], "Midterm A")
        self.assertEqual(requirements[2]["display_name"], "Midterm Start Date")
        self.assertEqual(requirements[3]["display_name"], "Midterm Start Date")

        # Since the last two requirements have the same display name,
        # we need to also check that their internal names (locations) are the same.
        self.assertEqual(requirements[2]["name"],
                         first_block.get_credit_requirement_name())
        self.assertEqual(requirements[3]["name"],
                         second_block.get_credit_requirement_name())
Exemplo n.º 30
0
    def test_remove_icrv_requirement(self):
        self.add_credit_course(self.course.id)
        self.add_icrv_xblock()
        on_course_publish(self.course.id)

        # There should be one ICRV requirement
        requirements = get_credit_requirements(self.course.id, namespace="reverification")
        self.assertEqual(len(requirements), 1)

        # Delete the parent section containing the ICRV block
        with self.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, self.course.id):
            self.store.delete_item(self.subsection.location, ModuleStoreEnum.UserID.test)

        # Check that the ICRV block is no longer visible in the requirements
        on_course_publish(self.course.id)
        requirements = get_credit_requirements(self.course.id, namespace="reverification")
        self.assertEqual(len(requirements), 0)
Exemplo n.º 31
0
    def test_remove_icrv_requirement(self):
        self.add_credit_course(self.course.id)
        self.add_icrv_xblock()
        on_course_publish(self.course.id)

        # There should be one ICRV requirement
        requirements = get_credit_requirements(self.course.id, namespace="reverification")
        self.assertEqual(len(requirements), 1)

        # Delete the parent section containing the ICRV block
        with self.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, self.course.id):
            self.store.delete_item(self.subsection.location, ModuleStoreEnum.UserID.test)

        # Check that the ICRV block is no longer visible in the requirements
        on_course_publish(self.course.id)
        requirements = get_credit_requirements(self.course.id, namespace="reverification")
        self.assertEqual(len(requirements), 0)
Exemplo n.º 32
0
    def test_credit_requirement_blocks_ordering(self):
        """
        Test ordering of the proctoring and ICRV blocks are in proper order.
        """

        self.add_credit_course(self.course.id)
        subsection = ItemFactory.create(parent=self.section, category='sequential', display_name='Dummy Subsection')
        create_exam(
            course_id=unicode(self.course.id),
            content_id=unicode(subsection.location),
            exam_name='A Proctored Exam',
            time_limit_mins=10,
            is_proctored=True,
            is_active=True
        )

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)
        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 2)
        self.assertEqual(requirements[1]['namespace'], 'proctored_exam')
        self.assertEqual(requirements[1]['name'], unicode(subsection.location))
        self.assertEqual(requirements[1]['display_name'], 'A Proctored Exam')
        self.assertEqual(requirements[1]['criteria'], {})

        # Create multiple ICRV blocks
        start = datetime.now(UTC)
        self.add_icrv_xblock(related_assessment_name="Midterm A", start_date=start)

        start = start - timedelta(days=1)
        self.add_icrv_xblock(related_assessment_name="Midterm B", start_date=start)

        # Primary sort is based on start date
        on_course_publish(self.course.id)
        requirements = get_credit_requirements(self.course.id)
        # grade requirement is added on publish of the requirements
        self.assertEqual(len(requirements), 4)
        # check requirements are added in the desired order
        # 1st Minimum grade then the blocks with start date than other blocks
        self.assertEqual(requirements[0]["display_name"], "Minimum Grade")
        self.assertEqual(requirements[1]["display_name"], "A Proctored Exam")
        self.assertEqual(requirements[2]["display_name"], "Midterm B")
        self.assertEqual(requirements[3]["display_name"], "Midterm A")
Exemplo n.º 33
0
 def test_set_get_credit_requirements(self):
     # Test that if same requirement is added multiple times
     self.add_credit_course()
     requirements = [
         {"namespace": "grade", "name": "grade", "display_name": "Grade", "criteria": {"min_grade": 0.8}},
         {"namespace": "grade", "name": "grade", "display_name": "Grade", "criteria": {"min_grade": 0.9}},
     ]
     api.set_credit_requirements(self.course_key, requirements)
     self.assertEqual(len(api.get_credit_requirements(self.course_key)), 1)
Exemplo n.º 34
0
    def test_proctored_exam_filtering(self):
        """
        Make sure that timed or inactive exams do not end up in the requirements table
        """

        self.add_credit_course(self.course.id)
        create_exam(course_id=unicode(self.course.id),
                    content_id='foo',
                    exam_name='A Proctored Exam',
                    time_limit_mins=10,
                    is_proctored=False,
                    is_active=True)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)

        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 1)

        # make sure we don't have a proctoring requirement
        self.assertFalse([
            requirement for requirement in requirements
            if requirement['namespace'] == 'proctored_exam'
        ])

        create_exam(course_id=unicode(self.course.id),
                    content_id='foo2',
                    exam_name='A Proctored Exam',
                    time_limit_mins=10,
                    is_proctored=True,
                    is_active=False)

        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 1)

        # make sure we don't have a proctoring requirement
        self.assertFalse([
            requirement for requirement in requirements
            if requirement['namespace'] == 'proctored_exam'
        ])
Exemplo n.º 35
0
    def test_icrv_requirement_ordering(self):
        self.add_credit_course(self.course.id)

        # Create multiple ICRV blocks
        start = datetime.now(UTC)
        self.add_icrv_xblock(related_assessment_name="Midterm A", start_date=start)

        start = start - timedelta(days=1)
        self.add_icrv_xblock(related_assessment_name="Midterm B", start_date=start)

        # Primary sort is based on start date
        on_course_publish(self.course.id)
        requirements = get_credit_requirements(self.course.id, namespace="reverification")
        self.assertEqual(len(requirements), 2)
        self.assertEqual(requirements[0]["display_name"], "Midterm B")
        self.assertEqual(requirements[1]["display_name"], "Midterm A")

        # Add two additional ICRV blocks that have no start date
        # and the same name.
        start = datetime.now(UTC)
        first_block = self.add_icrv_xblock(related_assessment_name="Midterm Start Date")

        start = start + timedelta(days=1)
        second_block = self.add_icrv_xblock(related_assessment_name="Midterm Start Date")

        on_course_publish(self.course.id)
        requirements = get_credit_requirements(self.course.id, namespace="reverification")
        self.assertEqual(len(requirements), 4)
        # Since we are now primarily sorting on start_date and display_name if
        # start_date is present otherwise we are just sorting on display_name.
        self.assertEqual(requirements[0]["display_name"], "Midterm B")
        self.assertEqual(requirements[1]["display_name"], "Midterm A")
        self.assertEqual(requirements[2]["display_name"], "Midterm Start Date")
        self.assertEqual(requirements[3]["display_name"], "Midterm Start Date")

        # Since the last two requirements have the same display name,
        # we need to also check that their internal names (locations) are the same.
        self.assertEqual(requirements[2]["name"], first_block.get_credit_requirement_name())
        self.assertEqual(requirements[3]["name"], second_block.get_credit_requirement_name())
Exemplo n.º 36
0
    def test_remove_credit_requirement_status(self):
        self.add_credit_course()
        requirements = [{
            "namespace": "grade",
            "name": "grade",
            "display_name": "Grade",
            "criteria": {
                "min_grade": 0.8
            },
        }, {
            "namespace": "reverification",
            "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
            "display_name": "Assessment 1",
            "criteria": {},
        }]

        api.set_credit_requirements(self.course_key, requirements)
        course_requirements = api.get_credit_requirements(self.course_key)
        self.assertEqual(len(course_requirements), 2)

        # before setting credit_requirement_status
        api.remove_credit_requirement_status("staff", self.course_key, "grade",
                                             "grade")
        req_status = api.get_credit_requirement_status(self.course_key,
                                                       "staff",
                                                       namespace="grade",
                                                       name="grade")
        self.assertIsNone(req_status[0]["status"])
        self.assertIsNone(req_status[0]["status_date"])
        self.assertIsNone(req_status[0]["reason"])

        # Set the requirement to "satisfied" and check that it's actually set
        api.set_credit_requirement_status("staff", self.course_key, "grade",
                                          "grade")
        req_status = api.get_credit_requirement_status(self.course_key,
                                                       "staff",
                                                       namespace="grade",
                                                       name="grade")
        self.assertEqual(len(req_status), 1)
        self.assertEqual(req_status[0]["status"], "satisfied")

        # remove the credit requirement status and check that it's actually removed
        api.remove_credit_requirement_status("staff", self.course_key, "grade",
                                             "grade")
        req_status = api.get_credit_requirement_status(self.course_key,
                                                       "staff",
                                                       namespace="grade",
                                                       name="grade")
        self.assertIsNone(req_status[0]["status"])
        self.assertIsNone(req_status[0]["status_date"])
        self.assertIsNone(req_status[0]["reason"])
Exemplo n.º 37
0
    def test_credit_requirement_blocks_ordering(self):
        """
        Test ordering of proctoring blocks.
        """

        self.add_credit_course(self.course.id)
        subsection = ItemFactory.create(parent=self.section,
                                        category='sequential',
                                        display_name='Dummy Subsection')
        create_exam(course_id=six.text_type(self.course.id),
                    content_id=six.text_type(subsection.location),
                    exam_name='A Proctored Exam',
                    time_limit_mins=10,
                    is_proctored=True,
                    is_active=True)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)
        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 2)
        self.assertEqual(requirements[1]['namespace'], 'proctored_exam')
        self.assertEqual(requirements[1]['name'],
                         six.text_type(subsection.location))
        self.assertEqual(requirements[1]['display_name'], 'A Proctored Exam')
        self.assertEqual(requirements[1]['criteria'], {})

        # Primary sort is based on start date
        on_course_publish(self.course.id)
        requirements = get_credit_requirements(self.course.id)
        # grade requirement is added on publish of the requirements
        self.assertEqual(len(requirements), 2)
        # check requirements are added in the desired order
        # 1st Minimum grade then the blocks with start date than other blocks
        self.assertEqual(requirements[0]["display_name"], "Minimum Grade")
        self.assertEqual(requirements[1]["display_name"], "A Proctored Exam")
Exemplo n.º 38
0
    def test_credit_requirement_blocks_ordering(self):
        """
        Test ordering of proctoring blocks.
        """

        self.add_credit_course(self.course.id)
        subsection = ItemFactory.create(parent=self.section, category='sequential', display_name='Dummy Subsection')
        create_exam(
            course_id=str(self.course.id),
            content_id=str(subsection.location),
            exam_name='A Proctored Exam',
            time_limit_mins=10,
            is_proctored=True,
            is_active=True
        )

        requirements = get_credit_requirements(self.course.id)
        assert len(requirements) == 0
        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        assert len(requirements) == 2
        assert requirements[1]['namespace'] == 'proctored_exam'
        assert requirements[1]['name'] == str(subsection.location)
        assert requirements[1]['display_name'] == 'A Proctored Exam'
        assert requirements[1]['criteria'] == {}

        # Primary sort is based on start date
        on_course_publish(self.course.id)
        requirements = get_credit_requirements(self.course.id)
        # grade requirement is added on publish of the requirements
        assert len(requirements) == 2
        # check requirements are added in the desired order
        # 1st Minimum grade then the blocks with start date than other blocks
        assert requirements[0]['display_name'] == 'Minimum Grade'
        assert requirements[1]['display_name'] == 'A Proctored Exam'
Exemplo n.º 39
0
    def test_credit_requirement_blocks_ordering(self):
        """
        Test ordering of proctoring blocks.
        """

        self.add_credit_course(self.course.id)
        subsection = ItemFactory.create(parent=self.section, category='sequential', display_name='Dummy Subsection')
        create_exam(
            course_id=six.text_type(self.course.id),
            content_id=six.text_type(subsection.location),
            exam_name='A Proctored Exam',
            time_limit_mins=10,
            is_proctored=True,
            is_active=True
        )

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 0)
        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        self.assertEqual(len(requirements), 2)
        self.assertEqual(requirements[1]['namespace'], 'proctored_exam')
        self.assertEqual(requirements[1]['name'], six.text_type(subsection.location))
        self.assertEqual(requirements[1]['display_name'], 'A Proctored Exam')
        self.assertEqual(requirements[1]['criteria'], {})

        # Primary sort is based on start date
        on_course_publish(self.course.id)
        requirements = get_credit_requirements(self.course.id)
        # grade requirement is added on publish of the requirements
        self.assertEqual(len(requirements), 2)
        # check requirements are added in the desired order
        # 1st Minimum grade then the blocks with start date than other blocks
        self.assertEqual(requirements[0]["display_name"], "Minimum Grade")
        self.assertEqual(requirements[1]["display_name"], "A Proctored Exam")
Exemplo n.º 40
0
    def test_set_credit_requirement_status(self):
        self.add_credit_course()
        requirements = [{
            "namespace": "grade",
            "name": "grade",
            "display_name": "Grade",
            "criteria": {
                "min_grade": 0.8
            },
        }, {
            "namespace": "reverification",
            "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
            "display_name": "Assessment 1",
            "criteria": {},
        }]

        api.set_credit_requirements(self.course_key, requirements)
        course_requirements = api.get_credit_requirements(self.course_key)
        self.assertEqual(len(course_requirements), 2)

        # Initially, the status should be None
        req_status = api.get_credit_requirement_status(self.course_key,
                                                       "staff",
                                                       namespace="grade",
                                                       name="grade")
        self.assertEqual(req_status[0]["status"], None)

        # Set the requirement to "satisfied" and check that it's actually set
        api.set_credit_requirement_status("staff", self.course_key, "grade",
                                          "grade")
        req_status = api.get_credit_requirement_status(self.course_key,
                                                       "staff",
                                                       namespace="grade",
                                                       name="grade")
        self.assertEqual(req_status[0]["status"], "satisfied")

        # Set the requirement to "failed" and check that it's actually set
        api.set_credit_requirement_status("staff",
                                          self.course_key,
                                          "grade",
                                          "grade",
                                          status="failed")
        req_status = api.get_credit_requirement_status(self.course_key,
                                                       "staff",
                                                       namespace="grade",
                                                       name="grade")
        self.assertEqual(req_status[0]["status"], "failed")
Exemplo n.º 41
0
 def test_set_get_credit_requirements(self):
     self.add_credit_course()
     requirements = [{
         "namespace": "grade",
         "name": "grade",
         "criteria": {
             "min_grade": 0.8
         }
     }, {
         "namespace": "grade",
         "name": "grade",
         "criteria": {
             "min_grade": 0.8
         }
     }]
     set_credit_requirements(self.course_key, requirements)
     self.assertEqual(len(get_credit_requirements(self.course_key)), 1)
Exemplo n.º 42
0
def listen_for_grade_calculation(sender, username, grade_summary, course_key,
                                 deadline, **kwargs):  # pylint: disable=unused-argument
    """Receive 'MIN_GRADE_REQUIREMENT_STATUS' signal and update minimum grade
    requirement status.

    Args:
        sender: None
        username(string): user name
        grade_summary(dict): Dict containing output from the course grader
        course_key(CourseKey): The key for the course
        deadline(datetime): Course end date or None

    Kwargs:
        kwargs : None

    """
    # This needs to be imported here to avoid a circular dependency
    # that can cause syncdb to fail.
    from openedx.core.djangoapps.credit import api

    course_id = CourseKey.from_string(unicode(course_key))
    is_credit = api.is_credit_course(course_id)
    if is_credit:
        requirements = api.get_credit_requirements(course_id,
                                                   namespace='grade')
        if requirements:
            criteria = requirements[0].get('criteria')
            if criteria:
                min_grade = criteria.get('min_grade')
                if grade_summary['percent'] >= min_grade:
                    reason_dict = {'final_grade': grade_summary['percent']}
                    api.set_credit_requirement_status(username,
                                                      course_id,
                                                      'grade',
                                                      'grade',
                                                      status="satisfied",
                                                      reason=reason_dict)
                elif deadline and deadline < timezone.now():
                    api.set_credit_requirement_status(username,
                                                      course_id,
                                                      'grade',
                                                      'grade',
                                                      status="failed",
                                                      reason={})
Exemplo n.º 43
0
 def test_set_get_credit_requirements(self):
     # Test that if same requirement is added multiple times
     self.add_credit_course()
     requirements = [{
         "namespace": "grade",
         "name": "grade",
         "display_name": "Grade",
         "criteria": {
             "min_grade": 0.8
         },
     }, {
         "namespace": "grade",
         "name": "grade",
         "display_name": "Grade",
         "criteria": {
             "min_grade": 0.9
         },
     }]
     api.set_credit_requirements(self.course_key, requirements)
     self.assertEqual(len(api.get_credit_requirements(self.course_key)), 1)
Exemplo n.º 44
0
 def test_set_get_credit_requirements(self):
     self.add_credit_course()
     requirements = [
         {
             "namespace": "grade",
             "name": "grade",
             "criteria": {
                 "min_grade": 0.8
             }
         },
         {
             "namespace": "grade",
             "name": "grade",
             "criteria": {
                 "min_grade": 0.8
             }
         }
     ]
     set_credit_requirements(self.course_key, requirements)
     self.assertEqual(len(get_credit_requirements(self.course_key)), 1)
Exemplo n.º 45
0
def listen_for_grade_calculation(sender, username, grade_summary, course_key, deadline, **kwargs):  # pylint: disable=unused-argument
    """Receive 'MIN_GRADE_REQUIREMENT_STATUS' signal and update minimum grade
    requirement status.

    Args:
        sender: None
        username(string): user name
        grade_summary(dict): Dict containing output from the course grader
        course_key(CourseKey): The key for the course
        deadline(datetime): Course end date or None

    Kwargs:
        kwargs : None

    """
    # This needs to be imported here to avoid a circular dependency
    # that can cause syncdb to fail.
    from openedx.core.djangoapps.credit import api

    course_id = CourseKey.from_string(unicode(course_key))
    is_credit = api.is_credit_course(course_id)
    if is_credit:
        requirements = api.get_credit_requirements(course_id, namespace='grade')
        if requirements:
            criteria = requirements[0].get('criteria')
            if criteria:
                min_grade = criteria.get('min_grade')
                if grade_summary['percent'] >= min_grade:
                    reason_dict = {'final_grade': grade_summary['percent']}
                    api.set_credit_requirement_status(
                        username, course_id, 'grade', 'grade', status="satisfied", reason=reason_dict
                    )
                elif deadline and deadline < timezone.now():
                    api.set_credit_requirement_status(
                        username, course_id, 'grade', 'grade', status="failed", reason={}
                    )
Exemplo n.º 46
0
def listen_for_grade_calculation(sender, user, course_grade, course_key, deadline, **kwargs):  # pylint: disable=unused-argument
    """Receive 'MIN_GRADE_REQUIREMENT_STATUS' signal and update minimum grade requirement status.

    Args:
        sender: None
        user(User): User Model object
        course_grade(CourseGrade): CourseGrade object
        course_key(CourseKey): The key for the course
        deadline(datetime): Course end date or None

    Kwargs:
        kwargs : None

    """
    # This needs to be imported here to avoid a circular dependency
    # that can cause syncdb to fail.
    from openedx.core.djangoapps.credit import api
    course_id = CourseKey.from_string(unicode(course_key))
    is_credit = api.is_credit_course(course_id)
    if is_credit:
        requirements = api.get_credit_requirements(course_id, namespace='grade')
        if requirements:
            criteria = requirements[0].get('criteria')
            if criteria:
                min_grade = criteria.get('min_grade')
                passing_grade = course_grade.percent >= min_grade
                now = timezone.now()
                status = None
                reason = None

                if (deadline and now < deadline) or not deadline:
                    # Student completed coursework on-time

                    if passing_grade:
                        # Student received a passing grade
                        status = 'satisfied'
                        reason = {'final_grade': course_grade.percent}
                else:
                    # Submission after deadline

                    if passing_grade:
                        # Grade was good, but submission arrived too late
                        status = 'failed'
                        reason = {
                            'current_date': now,
                            'deadline': deadline
                        }
                    else:
                        # Student failed to receive minimum grade
                        status = 'failed'
                        reason = {
                            'final_grade': course_grade.percent,
                            'minimum_grade': min_grade
                        }

                # We do not record a status if the user has not yet earned the minimum grade, but still has
                # time to do so.
                if status and reason:
                    api.set_credit_requirement_status(
                        user, course_id, 'grade', 'grade', status=status, reason=reason
                    )
Exemplo n.º 47
0
    def test_set_credit_requirement_status(self):
        username = "******"
        credit_course = self.add_credit_course()
        requirements = [
            {
                "namespace": "grade",
                "name": "grade",
                "display_name": "Grade",
                "criteria": {
                    "min_grade": 0.8
                },
            },
            {
                "namespace": "reverification",
                "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
                "display_name": "Assessment 1",
                "criteria": {},
            }
        ]

        api.set_credit_requirements(self.course_key, requirements)
        course_requirements = api.get_credit_requirements(self.course_key)
        self.assertEqual(len(course_requirements), 2)

        # Initially, the status should be None
        self.assert_grade_requirement_status(None, 0)

        # Requirement statuses cannot be changed if a CreditRequest exists
        credit_request = CreditRequest.objects.create(
            course=credit_course,
            provider=CreditProvider.objects.first(),
            username=username,
        )
        api.set_credit_requirement_status(username, self.course_key, "grade", "grade")
        self.assert_grade_requirement_status(None, 0)
        credit_request.delete()

        # Set the requirement to "satisfied" and check that it's actually set
        api.set_credit_requirement_status(username, self.course_key, "grade", "grade")
        self.assert_grade_requirement_status('satisfied', 0)

        # Set the requirement to "failed" and check that it's actually set
        api.set_credit_requirement_status(username, self.course_key, "grade", "grade", status="failed")
        self.assert_grade_requirement_status('failed', 0)

        req_status = api.get_credit_requirement_status(self.course_key, "staff")
        self.assertEqual(req_status[0]["status"], "failed")
        self.assertEqual(req_status[0]["order"], 0)

        # make sure the 'order' on the 2nd requirement is set correctly (aka 1)
        self.assertEqual(req_status[1]["status"], None)
        self.assertEqual(req_status[1]["order"], 1)

        # Set the requirement to "declined" and check that it's actually set
        api.set_credit_requirement_status(
            username, self.course_key,
            "reverification",
            "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
            status="declined"
        )
        req_status = api.get_credit_requirement_status(
            self.course_key,
            username,
            namespace="reverification",
            name="i4x://edX/DemoX/edx-reverification-block/assessment_uuid"
        )
        self.assertEqual(req_status[0]["status"], "declined")
Exemplo n.º 48
0
    def test_proctored_exam_filtering(self):
        """
        Make sure that timed or inactive exams do not end up in the requirements table
        Also practice protored exams are not a requirement
        """

        self.add_credit_course(self.course.id)
        create_exam(
            course_id=str(self.course.id),
            content_id='foo',
            exam_name='A Proctored Exam',
            time_limit_mins=10,
            is_proctored=False,
            is_active=True
        )

        requirements = get_credit_requirements(self.course.id)
        assert len(requirements) == 0

        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        assert len(requirements) == 1

        # make sure we don't have a proctoring requirement
        assert not [requirement for requirement in requirements if requirement['namespace'] == 'proctored_exam']

        create_exam(
            course_id=str(self.course.id),
            content_id='foo2',
            exam_name='A Proctored Exam',
            time_limit_mins=10,
            is_proctored=True,
            is_active=False
        )

        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        assert len(requirements) == 1

        # make sure we don't have a proctoring requirement
        assert not [requirement for requirement in requirements if requirement['namespace'] == 'proctored_exam']

        # practice proctored exams aren't requirements
        create_exam(
            course_id=str(self.course.id),
            content_id='foo3',
            exam_name='A Proctored Exam',
            time_limit_mins=10,
            is_proctored=True,
            is_active=True,
            is_practice_exam=True
        )

        on_course_publish(self.course.id)

        requirements = get_credit_requirements(self.course.id)
        assert len(requirements) == 1

        # make sure we don't have a proctoring requirement
        assert not [requirement for requirement in requirements if requirement['namespace'] == 'proctored_exam']
Exemplo n.º 49
0
    def test_set_credit_requirement_status(self):
        username = "******"
        credit_course = self.add_credit_course()
        requirements = [
            {
                "namespace": "grade",
                "name": "grade",
                "display_name": "Grade",
                "criteria": {
                    "min_grade": 0.8
                },
            },
            {
                "namespace": "reverification",
                "name": "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
                "display_name": "Assessment 1",
                "criteria": {},
            }
        ]

        api.set_credit_requirements(self.course_key, requirements)
        course_requirements = api.get_credit_requirements(self.course_key)
        self.assertEqual(len(course_requirements), 2)

        # Initially, the status should be None
        self.assert_grade_requirement_status(None, 0)

        # Requirement statuses cannot be changed if a CreditRequest exists
        credit_request = CreditRequest.objects.create(
            course=credit_course,
            provider=CreditProvider.objects.first(),
            username=username,
        )
        api.set_credit_requirement_status(username, self.course_key, "grade", "grade")
        self.assert_grade_requirement_status(None, 0)
        credit_request.delete()

        # Set the requirement to "satisfied" and check that it's actually set
        api.set_credit_requirement_status(username, self.course_key, "grade", "grade")
        self.assert_grade_requirement_status('satisfied', 0)

        # Set the requirement to "failed" and check that it's actually set
        api.set_credit_requirement_status(username, self.course_key, "grade", "grade", status="failed")
        self.assert_grade_requirement_status('failed', 0)

        req_status = api.get_credit_requirement_status(self.course_key, "staff")
        self.assertEqual(req_status[0]["status"], "failed")
        self.assertEqual(req_status[0]["order"], 0)

        # make sure the 'order' on the 2nd requirement is set correctly (aka 1)
        self.assertEqual(req_status[1]["status"], None)
        self.assertEqual(req_status[1]["order"], 1)

        # Set the requirement to "declined" and check that it's actually set
        api.set_credit_requirement_status(
            username, self.course_key,
            "reverification",
            "i4x://edX/DemoX/edx-reverification-block/assessment_uuid",
            status="declined"
        )
        req_status = api.get_credit_requirement_status(
            self.course_key,
            username,
            namespace="reverification",
            name="i4x://edX/DemoX/edx-reverification-block/assessment_uuid"
        )
        self.assertEqual(req_status[0]["status"], "declined")
Exemplo n.º 50
0
def listen_for_grade_calculation(sender, user, grade_summary, course_key,
                                 deadline, **kwargs):  # pylint: disable=unused-argument
    """Receive 'MIN_GRADE_REQUIREMENT_STATUS' signal and update minimum grade requirement status.

    Args:
        sender: None
        user(User): User Model object
        grade_summary(dict): Dict containing output from the course grader
        course_key(CourseKey): The key for the course
        deadline(datetime): Course end date or None

    Kwargs:
        kwargs : None

    """
    # This needs to be imported here to avoid a circular dependency
    # that can cause syncdb to fail.
    from openedx.core.djangoapps.credit import api
    course_id = CourseKey.from_string(unicode(course_key))
    is_credit = api.is_credit_course(course_id)
    if is_credit:
        requirements = api.get_credit_requirements(course_id,
                                                   namespace='grade')
        if requirements:
            criteria = requirements[0].get('criteria')
            if criteria:
                min_grade = criteria.get('min_grade')
                passing_grade = grade_summary['percent'] >= min_grade
                now = timezone.now()
                status = None
                reason = None

                if (deadline and now < deadline) or not deadline:
                    # Student completed coursework on-time

                    if passing_grade:
                        # Student received a passing grade
                        status = 'satisfied'
                        reason = {'final_grade': grade_summary['percent']}
                else:
                    # Submission after deadline

                    if passing_grade:
                        # Grade was good, but submission arrived too late
                        status = 'failed'
                        reason = {'current_date': now, 'deadline': deadline}
                    else:
                        # Student failed to receive minimum grade
                        status = 'failed'
                        reason = {
                            'final_grade': grade_summary['percent'],
                            'minimum_grade': min_grade
                        }

                # We do not record a status if the user has not yet earned the minimum grade, but still has
                # time to do so.
                if status and reason:
                    api.set_credit_requirement_status(user,
                                                      course_id,
                                                      'grade',
                                                      'grade',
                                                      status=status,
                                                      reason=reason)