Пример #1
0
    def test_handle(self, commit, mock_task, mock_get_programs):
        """
        Verify that relevant tasks are only enqueued when the commit option is passed.
        """
        data = [
            factories.Program(courses=[
                factories.Course(course_runs=[
                    factories.CourseRun(key=self.course_run_key),
                ]),
            ]),
        ]
        mock_get_programs.return_value = data

        GeneratedCertificateFactory(
            user=self.alice,
            course_id=self.course_run_key,
            mode=MODES.verified,
            status=CertificateStatuses.downloadable,
        )

        GeneratedCertificateFactory(
            user=self.bob,
            course_id=self.alternate_course_run_key,
            mode=MODES.verified,
            status=CertificateStatuses.downloadable,
        )

        call_command('backpopulate_program_credentials', commit=commit)

        if commit:
            mock_task.assert_called_once_with(self.alice.username)
        else:
            mock_task.assert_not_called()
Пример #2
0
    def test_get_programs_data(self, _mock_cache, mock_get_catalog_data):   # pylint: disable=unused-argument
        programs = []
        program_types = []
        programs_data = []

        for index in range(3):
            # Creating the Programs and their corresponding program types.
            type_name = "type_name_{postfix}".format(postfix=index)
            program = factories.Program(type=type_name)
            program_type = factories.ProgramType(name=type_name)

            # Maintaining the programs, program types and program data(program+logo_image) lists.
            programs.append(program)
            program_types.append(program_type)
            programs_data.append(copy.deepcopy(program))

            # Adding the logo image in program data.
            programs_data[-1]['logo_image'] = program_type["logo_image"]

        with mock.patch("openedx.core.djangoapps.catalog.utils.get_programs") as patched_get_programs:
            with mock.patch("openedx.core.djangoapps.catalog.utils.get_program_types") as patched_get_program_types:
                # Mocked the "get_programs" and "get_program_types"
                patched_get_programs.return_value = programs
                patched_get_program_types.return_value = program_types

                programs_data = utils.get_programs_data()
                self.assertEqual(programs_data, programs)
Пример #3
0
    def test_handle_mode_slugs(self, mock_task, mock_get_programs):
        """
        Verify that course run types are taken into account when identifying
        qualifying course run certificates.
        """
        data = [
            factories.Program(courses=[
                factories.Course(course_runs=[
                    factories.CourseRun(key=self.course_run_key, type='honor'),
                ]),
            ]),
        ]
        mock_get_programs.return_value = data

        GeneratedCertificateFactory(
            user=self.alice,
            course_id=self.course_run_key,
            mode=MODES.honor,
            status=CertificateStatuses.downloadable,
        )

        GeneratedCertificateFactory(
            user=self.bob,
            course_id=self.course_run_key,
            mode=MODES.verified,
            status=CertificateStatuses.downloadable,
        )

        call_command('backpopulate_program_credentials', commit=True)

        mock_task.assert_called_once_with(self.alice.username)
Пример #4
0
    def test_handle_username_dedup(self, mock_task, mock_get_programs):
        """
        Verify that only one task is enqueued for a user with multiple eligible
        course run certificates.
        """
        data = [
            factories.Program(courses=[
                factories.Course(course_runs=[
                    factories.CourseRun(key=self.course_run_key),
                    factories.CourseRun(key=self.alternate_course_run_key),
                ]),
            ]),
        ]
        mock_get_programs.return_value = data

        GeneratedCertificateFactory(
            user=self.alice,
            course_id=self.course_run_key,
            mode=MODES.verified,
            status=CertificateStatuses.downloadable,
        )

        GeneratedCertificateFactory(
            user=self.alice,
            course_id=self.alternate_course_run_key,
            mode=MODES.verified,
            status=CertificateStatuses.downloadable,
        )

        call_command('backpopulate_program_credentials', commit=True)

        mock_task.assert_called_once_with(self.alice.username)
Пример #5
0
    def test_get_programs_by_type(self, _mock_cache, mock_get_catalog_data):
        programs = [factories.Program() for __ in range(2)]
        mock_get_catalog_data.return_value = programs

        data = utils.get_programs(self.user, type=self.type)

        self.assert_contract(mock_get_catalog_data.call_args, type=self.type)
        self.assertEqual(data, programs)
Пример #6
0
    def test_get_one_program(self, _mock_cache, mock_get_catalog_data):
        program = factories.Program()
        mock_get_catalog_data.return_value = program

        data = utils.get_programs(self.user, uuid=self.uuid)

        self.assert_contract(mock_get_catalog_data.call_args, program_uuid=self.uuid)
        self.assertEqual(data, program)
Пример #7
0
    def setUp(self):
        super(ProgramPageBase, self).setUp()

        self.set_programs_api_configuration(is_enabled=True)

        self.programs = [catalog_factories.Program() for __ in range(3)]
        self.course_run = catalog_factories.CourseRun(key=self.course_id)
        self.stub_catalog_api()
Пример #8
0
    def test_get_program_for_certificates(self):
        """Verify programs data can be retrieved and parsed correctly for certificates."""
        programs = [
            catalog_factories.Program(uuid=self.primary_uuid),
            catalog_factories.Program(uuid=self.alternate_uuid)
        ]

        program_credentials_data = self._expected_program_credentials_data()
        with mock.patch(
                "openedx.core.djangoapps.credentials.utils.get_programs"
        ) as patched_get_programs:
            patched_get_programs.return_value = programs
            actual = get_programs_for_credentials(self.user,
                                                  program_credentials_data)

            self.assertEqual(len(actual), 2)
            self.assertEqual(actual, programs)
Пример #9
0
    def test_get_programs_credentials(self):
        """ Verify that the program credentials data required for display can
        be retrieved.
        """
        # create credentials and program configuration
        self.create_credentials_config()

        # Mocking the API responses from programs and credentials
        primary_uuid, alternate_uuid = str(uuid.uuid4()), str(uuid.uuid4())
        credentials_api_response = {
            "next":
            None,
            "results": [
                factories.UserCredential(
                    username='******',
                    credential=factories.ProgramCredential(
                        program_uuid=primary_uuid)),
                factories.UserCredential(
                    username='******',
                    credential=factories.ProgramCredential(
                        program_uuid=alternate_uuid))
            ]
        }
        self.mock_credentials_api(self.user,
                                  data=credentials_api_response,
                                  reset_url=False)
        programs = [
            catalog_factories.Program(uuid=primary_uuid),
            catalog_factories.Program(uuid=alternate_uuid)
        ]

        with mock.patch(
                "openedx.core.djangoapps.credentials.utils.get_programs"
        ) as mock_get_programs:
            mock_get_programs.return_value = programs
            actual = get_programs_credentials(self.user)
            expected = self.expected_credentials_display_data(programs)

            # Checking result is as expected
            self.assertEqual(len(actual), 2)
            self.assertEqual(actual, expected)
Пример #10
0
class TestMungeCatalogProgram(TestCase):
    """Tests covering querystring stripping."""
    catalog_program = factories.Program()

    def test_munge_catalog_program(self):
        munged = utils.munge_catalog_program(self.catalog_program)
        expected = {
            'id':
            self.catalog_program['uuid'],
            'name':
            self.catalog_program['title'],
            'subtitle':
            self.catalog_program['subtitle'],
            'category':
            self.catalog_program['type'],
            'marketing_slug':
            self.catalog_program['marketing_slug'],
            'organizations': [{
                'display_name': organization['name'],
                'key': organization['key']
            } for organization in
                              self.catalog_program['authoring_organizations']],
            'course_codes': [{
                'display_name':
                course['title'],
                'key':
                course['key'],
                'organization': {
                    'display_name': course['owners'][0]['name'],
                    'key': course['owners'][0]['key']
                },
                'run_modes': [{
                    'course_key': run['key'],
                    'run_key': CourseKey.from_string(run['key']).run,
                    'mode_slug': 'verified'
                } for run in course['course_runs']],
            } for course in self.catalog_program['courses']],
            'banner_image_urls': {
                'w1440h480':
                self.catalog_program['banner_image']['large']['url'],
                'w726h242':
                self.catalog_program['banner_image']['medium']['url'],
                'w435h145':
                self.catalog_program['banner_image']['small']['url'],
                'w348h116':
                self.catalog_program['banner_image']['x-small']['url'],
            },
        }

        self.assertEqual(munged, expected)
Пример #11
0
    def test_get_programs_anonymous_user(self, _mock_cache, mock_get_catalog_data):
        programs = [factories.Program() for __ in range(3)]
        mock_get_catalog_data.return_value = programs

        anonymous_user = AnonymousUserFactory()

        # The user is an Anonymous user but the Catalog Service User has not been created yet.
        data = utils.get_programs(anonymous_user)
        # This should not return programs.
        self.assertEqual(data, [])

        UserFactory(username='******')
        # After creating the service user above,
        data = utils.get_programs(anonymous_user)
        # the programs should be returned successfully.
        self.assertEqual(data, programs)
Пример #12
0
    def test_handle_enqueue_failure(self, mock_log, mock_task,
                                    mock_get_programs):
        """Verify that failure to enqueue a task doesn't halt execution."""
        def side_effect(username):
            """Simulate failure to enqueue a task."""
            if username == self.alice.username:
                raise Exception

        mock_task.side_effect = side_effect

        data = [
            factories.Program(courses=[
                factories.Course(course_runs=[
                    factories.CourseRun(key=self.course_run_key),
                ]),
            ]),
        ]
        mock_get_programs.return_value = data

        GeneratedCertificateFactory(
            user=self.alice,
            course_id=self.course_run_key,
            mode=MODES.verified,
            status=CertificateStatuses.downloadable,
        )

        GeneratedCertificateFactory(
            user=self.bob,
            course_id=self.course_run_key,
            mode=MODES.verified,
            status=CertificateStatuses.downloadable,
        )

        call_command('backpopulate_program_credentials', commit=True)

        self.assertTrue(mock_log.called)

        calls = [mock.call(self.alice.username), mock.call(self.bob.username)]
        mock_task.assert_has_calls(calls, any_order=True)
Пример #13
0
    def test_get_completed_programs(self, mock_get_completed_courses):
        """
        Verify that completed programs are found, using the cache when possible.
        """
        data = [
            factories.Program(),
        ]
        self._mock_programs_api(data)

        munged_program = munge_catalog_program(data[0])
        course_codes = munged_program['course_codes']

        mock_get_completed_courses.return_value = [{
            'course_id':
            run_mode['course_key'],
            'mode':
            run_mode['mode_slug']
        } for run_mode in course_codes[0]['run_modes']]
        for _ in range(2):
            result = tasks.get_completed_programs(self.user)
            self.assertEqual(result[0], munged_program['id'])

        # Verify that only one request to the catalog was made (i.e., the cache was hit).
        self._assert_num_requests(1)
Пример #14
0
    def test_handle_passing_status(self, mock_task, mock_get_programs):
        """
        Verify that only course run certificates with a passing status are selected.
        """
        data = [
            factories.Program(courses=[
                factories.Course(course_runs=[
                    factories.CourseRun(key=self.course_run_key),
                ]),
            ]),
        ]
        mock_get_programs.return_value = data

        passing_status = CertificateStatuses.downloadable
        failing_status = CertificateStatuses.notpassing

        self.assertIn(passing_status, CertificateStatuses.PASSED_STATUSES)
        self.assertNotIn(failing_status, CertificateStatuses.PASSED_STATUSES)

        GeneratedCertificateFactory(
            user=self.alice,
            course_id=self.course_run_key,
            mode=MODES.verified,
            status=passing_status,
        )

        GeneratedCertificateFactory(
            user=self.bob,
            course_id=self.course_run_key,
            mode=MODES.verified,
            status=failing_status,
        )

        call_command('backpopulate_program_credentials', commit=True)

        mock_task.assert_called_once_with(self.alice.username)
Пример #15
0
class BackpopulateProgramCredentialsTests(CatalogIntegrationMixin,
                                          CredentialsApiConfigMixin, TestCase):
    """Tests for the backpopulate_program_credentials management command."""
    course_run_key, alternate_course_run_key = (
        factories.generate_course_run_key() for __ in range(2))

    def setUp(self):
        super(BackpopulateProgramCredentialsTests, self).setUp()

        self.alice = UserFactory()
        self.bob = UserFactory()

        # Disable certification to prevent the task from being triggered when
        # setting up test data (i.e., certificates with a passing status), thereby
        # skewing mock call counts.
        self.create_credentials_config(enable_learner_issuance=False)

        self.catalog_integration = self.create_catalog_integration()
        self.service_user = UserFactory(
            username=self.catalog_integration.service_username)

    @ddt.data(True, False)
    def test_handle(self, commit, mock_task, mock_get_programs):
        """
        Verify that relevant tasks are only enqueued when the commit option is passed.
        """
        data = [
            factories.Program(courses=[
                factories.Course(course_runs=[
                    factories.CourseRun(key=self.course_run_key),
                ]),
            ]),
        ]
        mock_get_programs.return_value = data

        GeneratedCertificateFactory(
            user=self.alice,
            course_id=self.course_run_key,
            mode=MODES.verified,
            status=CertificateStatuses.downloadable,
        )

        GeneratedCertificateFactory(
            user=self.bob,
            course_id=self.alternate_course_run_key,
            mode=MODES.verified,
            status=CertificateStatuses.downloadable,
        )

        call_command('backpopulate_program_credentials', commit=commit)

        if commit:
            mock_task.assert_called_once_with(self.alice.username)
        else:
            mock_task.assert_not_called()

    @ddt.data(
        [
            factories.Program(courses=[
                factories.Course(course_runs=[
                    factories.CourseRun(key=course_run_key),
                ]),
            ]),
            factories.Program(courses=[
                factories.Course(course_runs=[
                    factories.CourseRun(key=alternate_course_run_key),
                ]),
            ]),
        ],
        [
            factories.Program(courses=[
                factories.Course(course_runs=[
                    factories.CourseRun(key=course_run_key),
                ]),
                factories.Course(course_runs=[
                    factories.CourseRun(key=alternate_course_run_key),
                ]),
            ]),
        ],
        [
            factories.Program(courses=[
                factories.Course(course_runs=[
                    factories.CourseRun(key=course_run_key),
                    factories.CourseRun(key=alternate_course_run_key),
                ]),
            ]),
        ],
    )
    def test_handle_flatten(self, data, mock_task, mock_get_programs):
        """Verify that program structures are flattened correctly."""
        mock_get_programs.return_value = data

        GeneratedCertificateFactory(
            user=self.alice,
            course_id=self.course_run_key,
            mode=MODES.verified,
            status=CertificateStatuses.downloadable,
        )

        GeneratedCertificateFactory(
            user=self.bob,
            course_id=self.alternate_course_run_key,
            mode=MODES.verified,
            status=CertificateStatuses.downloadable,
        )

        call_command('backpopulate_program_credentials', commit=True)

        calls = [mock.call(self.alice.username), mock.call(self.bob.username)]
        mock_task.assert_has_calls(calls, any_order=True)

    def test_handle_username_dedup(self, mock_task, mock_get_programs):
        """
        Verify that only one task is enqueued for a user with multiple eligible
        course run certificates.
        """
        data = [
            factories.Program(courses=[
                factories.Course(course_runs=[
                    factories.CourseRun(key=self.course_run_key),
                    factories.CourseRun(key=self.alternate_course_run_key),
                ]),
            ]),
        ]
        mock_get_programs.return_value = data

        GeneratedCertificateFactory(
            user=self.alice,
            course_id=self.course_run_key,
            mode=MODES.verified,
            status=CertificateStatuses.downloadable,
        )

        GeneratedCertificateFactory(
            user=self.alice,
            course_id=self.alternate_course_run_key,
            mode=MODES.verified,
            status=CertificateStatuses.downloadable,
        )

        call_command('backpopulate_program_credentials', commit=True)

        mock_task.assert_called_once_with(self.alice.username)

    def test_handle_mode_slugs(self, mock_task, mock_get_programs):
        """
        Verify that course run types are taken into account when identifying
        qualifying course run certificates.
        """
        data = [
            factories.Program(courses=[
                factories.Course(course_runs=[
                    factories.CourseRun(key=self.course_run_key, type='honor'),
                ]),
            ]),
        ]
        mock_get_programs.return_value = data

        GeneratedCertificateFactory(
            user=self.alice,
            course_id=self.course_run_key,
            mode=MODES.honor,
            status=CertificateStatuses.downloadable,
        )

        GeneratedCertificateFactory(
            user=self.bob,
            course_id=self.course_run_key,
            mode=MODES.verified,
            status=CertificateStatuses.downloadable,
        )

        call_command('backpopulate_program_credentials', commit=True)

        mock_task.assert_called_once_with(self.alice.username)

    def test_handle_passing_status(self, mock_task, mock_get_programs):
        """
        Verify that only course run certificates with a passing status are selected.
        """
        data = [
            factories.Program(courses=[
                factories.Course(course_runs=[
                    factories.CourseRun(key=self.course_run_key),
                ]),
            ]),
        ]
        mock_get_programs.return_value = data

        passing_status = CertificateStatuses.downloadable
        failing_status = CertificateStatuses.notpassing

        self.assertIn(passing_status, CertificateStatuses.PASSED_STATUSES)
        self.assertNotIn(failing_status, CertificateStatuses.PASSED_STATUSES)

        GeneratedCertificateFactory(
            user=self.alice,
            course_id=self.course_run_key,
            mode=MODES.verified,
            status=passing_status,
        )

        GeneratedCertificateFactory(
            user=self.bob,
            course_id=self.course_run_key,
            mode=MODES.verified,
            status=failing_status,
        )

        call_command('backpopulate_program_credentials', commit=True)

        mock_task.assert_called_once_with(self.alice.username)

    @mock.patch(COMMAND_MODULE + '.logger.exception')
    def test_handle_enqueue_failure(self, mock_log, mock_task,
                                    mock_get_programs):
        """Verify that failure to enqueue a task doesn't halt execution."""
        def side_effect(username):
            """Simulate failure to enqueue a task."""
            if username == self.alice.username:
                raise Exception

        mock_task.side_effect = side_effect

        data = [
            factories.Program(courses=[
                factories.Course(course_runs=[
                    factories.CourseRun(key=self.course_run_key),
                ]),
            ]),
        ]
        mock_get_programs.return_value = data

        GeneratedCertificateFactory(
            user=self.alice,
            course_id=self.course_run_key,
            mode=MODES.verified,
            status=CertificateStatuses.downloadable,
        )

        GeneratedCertificateFactory(
            user=self.bob,
            course_id=self.course_run_key,
            mode=MODES.verified,
            status=CertificateStatuses.downloadable,
        )

        call_command('backpopulate_program_credentials', commit=True)

        self.assertTrue(mock_log.called)

        calls = [mock.call(self.alice.username), mock.call(self.bob.username)]
        mock_task.assert_has_calls(calls, any_order=True)