Пример #1
0
    def setUp(self):
        super(ProgramPageBase, self).setUp()

        self.set_programs_api_configuration(is_enabled=True)

        self.programs = ProgramFactory.create_batch(3)
        self.username = None
Пример #2
0
    def test_get_many_with_missing(self, mock_cache, mock_warning, mock_info):
        programs = ProgramFactory.create_batch(3)

        all_programs = {
            PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid']): program for program in programs
        }

        partial_programs = {
            PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid']): program for program in programs[:2]
        }

        def fake_get_many(keys):
            if len(keys) == 1:
                return {PROGRAM_CACHE_KEY_TPL.format(uuid=programs[-1]['uuid']): programs[-1]}
            else:
                return partial_programs

        mock_cache.get.return_value = [program['uuid'] for program in programs]
        mock_cache.get_many.side_effect = fake_get_many

        actual_programs = get_programs(self.site)

        # All 3 cached programs should be returned. An info message should be
        # logged about the one that was initially missing, but the code should
        # be able to stitch together all the details.
        self.assertEqual(
            set(program['uuid'] for program in actual_programs),
            set(program['uuid'] for program in all_programs.values())
        )
        self.assertFalse(mock_warning.called)
        mock_info.assert_called_with('Failed to get details for 1 programs. Retrying.')

        for program in actual_programs:
            key = PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid'])
            self.assertEqual(program, all_programs[key])
Пример #3
0
    def setUp(self):
        super(TestCachePrograms, self).setUp()

        httpretty.httpretty.reset()

        self.catalog_integration = self.create_catalog_integration()
        self.site_domain = 'testsite.com'
        self.site = self.set_up_site(
            self.site_domain,
            {
                'COURSE_CATALOG_API_URL': self.catalog_integration.get_internal_api_url().rstrip('/')
            }
        )

        self.list_url = self.catalog_integration.get_internal_api_url().rstrip('/') + '/programs/'
        self.detail_tpl = self.list_url.rstrip('/') + '/{uuid}/'
        self.pathway_url = self.catalog_integration.get_internal_api_url().rstrip('/') + '/pathways/'

        self.programs = ProgramFactory.create_batch(3)
        self.pathways = PathwayFactory.create_batch(3)
        self.child_program = ProgramFactory.create()

        self.programs[0]['curricula'][0]['programs'].append(self.child_program)
        self.programs.append(self.child_program)

        self.programs[0]['authoring_organizations'] = OrganizationFactory.create_batch(2)

        for pathway in self.pathways:
            self.programs += pathway['programs']

        self.uuids = [program['uuid'] for program in self.programs]

        # add some of the previously created programs to some pathways
        self.pathways[0]['programs'].extend([self.programs[0], self.programs[1]])
        self.pathways[1]['programs'].append(self.programs[0])
Пример #4
0
    def test_completed_programs(self, mock_completed_course_runs, mock_get_programs):
        """Verify that completed programs are correctly identified."""
        data = ProgramFactory.create_batch(3)
        mock_get_programs.return_value = data

        program_uuids = []
        course_run_keys = []
        for program in data:
            program_uuids.append(program['uuid'])

            for course in program['courses']:
                for course_run in course['course_runs']:
                    course_run_keys.append(course_run['key'])

        # Verify that no programs are complete.
        meter = ProgramProgressMeter(self.user)
        self.assertEqual(meter.completed_programs, [])

        # Complete all programs.
        self._create_enrollments(*course_run_keys)
        mock_completed_course_runs.return_value = [
            {'course_run_id': course_run_key, 'type': MODES.verified}
            for course_run_key in course_run_keys
        ]

        # Verify that all programs are complete.
        meter = ProgramProgressMeter(self.user)
        self.assertEqual(meter.completed_programs, program_uuids)
Пример #5
0
    def setUp(self):
        super(ProgramPageBase, self).setUp()

        self.set_programs_api_configuration(is_enabled=True)

        self.programs = ProgramFactory.create_batch(3)
        self.username = None
    def setUp(self):
        super(TestCachePrograms, self).setUp()

        httpretty.httpretty.reset()

        self.catalog_integration = self.create_catalog_integration()
        self.site_domain = 'testsite.com'
        self.set_up_site(
            self.site_domain,
            {
                'COURSE_CATALOG_API_URL': self.catalog_integration.get_internal_api_url().rstrip('/')
            }
        )

        self.list_url = self.catalog_integration.get_internal_api_url().rstrip('/') + '/programs/'
        self.detail_tpl = self.list_url.rstrip('/') + '/{uuid}/'
        self.pathway_url = self.catalog_integration.get_internal_api_url().rstrip('/') + '/pathways/'

        self.programs = ProgramFactory.create_batch(3)
        self.pathways = PathwayFactory.create_batch(3)

        for pathway in self.pathways:
            self.programs += pathway['programs']

        self.uuids = [program['uuid'] for program in self.programs]

        # add some of the previously created programs to some pathways
        self.pathways[0]['programs'].extend([self.programs[0], self.programs[1]])
        self.pathways[1]['programs'].append(self.programs[0])
Пример #7
0
    def test_get_many_with_missing(self, mock_cache, mock_warning, mock_info):
        programs = ProgramFactory.create_batch(3)

        all_programs = {
            PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid']): program for program in programs
        }

        partial_programs = {
            PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid']): program for program in programs[:2]
        }

        def fake_get_many(keys):
            if len(keys) == 1:
                return {PROGRAM_CACHE_KEY_TPL.format(uuid=programs[-1]['uuid']): programs[-1]}
            else:
                return partial_programs

        mock_cache.get.return_value = [program['uuid'] for program in programs]
        mock_cache.get_many.side_effect = fake_get_many

        with with_site_configuration_context(domain=self.site.name, configuration={'COURSE_CATALOG_API_URL': 'foo'}):
            actual_programs = get_programs(site=self.site)

        # All 3 cached programs should be returned. An info message should be
        # logged about the one that was initially missing, but the code should
        # be able to stitch together all the details.
            assert {program['uuid'] for program in actual_programs} ==\
                   {program['uuid'] for program in all_programs.values()}
            assert not mock_warning.called
            mock_info.assert_called_with('Failed to get details for 1 programs. Retrying.')

            for program in actual_programs:
                key = PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid'])
                assert program == all_programs[key]
Пример #8
0
    def test_get_many_with_missing(self, mock_cache, mock_warning, mock_info):
        programs = ProgramFactory.create_batch(3)

        all_programs = {
            PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid']): program for program in programs
        }

        partial_programs = {
            PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid']): program for program in programs[:2]
        }

        def fake_get_many(keys):
            if len(keys) == 1:
                return {PROGRAM_CACHE_KEY_TPL.format(uuid=programs[-1]['uuid']): programs[-1]}
            else:
                return partial_programs

        mock_cache.get.return_value = [program['uuid'] for program in programs]
        mock_cache.get_many.side_effect = fake_get_many

        actual_programs = get_programs(self.site)

        # All 3 cached programs should be returned. An info message should be
        # logged about the one that was initially missing, but the code should
        # be able to stitch together all the details.
        self.assertEqual(
            set(program['uuid'] for program in actual_programs),
            set(program['uuid'] for program in all_programs.values())
        )
        self.assertFalse(mock_warning.called)
        mock_info.assert_called_with('Failed to get details for 1 programs. Retrying.')

        for program in actual_programs:
            key = PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid'])
            self.assertEqual(program, all_programs[key])
Пример #9
0
    def test_completed_programs(self, mock_completed_course_runs, mock_get_programs):
        """Verify that completed programs are correctly identified."""
        data = ProgramFactory.create_batch(3)
        mock_get_programs.return_value = data

        program_uuids = []
        course_run_keys = []
        for program in data:
            program_uuids.append(program['uuid'])

            for course in program['courses']:
                for course_run in course['course_runs']:
                    course_run_keys.append(course_run['key'])

        # Verify that no programs are complete.
        meter = ProgramProgressMeter(self.site, self.user)
        self.assertEqual(meter.completed_programs, [])

        # Complete all programs.
        self._create_enrollments(*course_run_keys)
        mock_completed_course_runs.return_value = [
            {'course_run_id': course_run_key, 'type': MODES.verified}
            for course_run_key in course_run_keys
        ]

        # Verify that all programs are complete.
        meter = ProgramProgressMeter(self.site, self.user)
        self.assertEqual(meter.completed_programs, program_uuids)
Пример #10
0
    def test_get_programs_by_types(self, mock_get_edx_api_data):
        programs = ProgramFactory.create_batch(2)
        mock_get_edx_api_data.return_value = programs

        data = get_programs(types=self.types)

        self.assert_contract(mock_get_edx_api_data.call_args, types=self.types)
        self.assertEqual(data, programs)
Пример #11
0
    def test_get_programs_by_types(self, mock_get_edx_api_data):
        programs = ProgramFactory.create_batch(2)
        mock_get_edx_api_data.return_value = programs

        data = get_programs(types=self.types)

        self.assert_contract(mock_get_edx_api_data.call_args, types=self.types)
        self.assertEqual(data, programs)
Пример #12
0
    def test_get_many(self, mock_warning):
        programs = ProgramFactory.create_batch(3)

        # Cache details for 2 of 3 programs.
        partial_programs = {
            PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid']): program
            for program in programs[:2]
        }
        cache.set_many(partial_programs, None)

        # When called before UUIDs are cached, the function should return an empty
        # list and log a warning.
        self.assertEqual(get_programs(), [])
        mock_warning.assert_called_once_with('Program UUIDs are not cached.')
        mock_warning.reset_mock()

        # Cache UUIDs for all 3 programs.
        cache.set(PROGRAM_UUIDS_CACHE_KEY,
                  [program['uuid'] for program in programs], None)

        actual_programs = get_programs()

        # The 2 cached programs should be returned while a warning should be logged
        # for the missing one.
        self.assertEqual(
            set(program['uuid'] for program in actual_programs),
            set(program['uuid'] for program in partial_programs.values()))
        mock_warning.assert_called_with(
            'Details for program {uuid} are not cached.'.format(
                uuid=programs[2]['uuid']))
        mock_warning.reset_mock()

        # We can't use a set comparison here because these values are dictionaries
        # and aren't hashable. We've already verified that all programs came out
        # of the cache above, so all we need to do here is verify the accuracy of
        # the data itself.
        for program in actual_programs:
            key = PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid'])
            self.assertEqual(program, partial_programs[key])

        # Cache details for all 3 programs.
        all_programs = {
            PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid']): program
            for program in programs
        }
        cache.set_many(all_programs, None)

        actual_programs = get_programs()

        # All 3 programs should be returned.
        self.assertEqual(
            set(program['uuid'] for program in actual_programs),
            set(program['uuid'] for program in all_programs.values()))
        self.assertFalse(mock_warning.called)

        for program in actual_programs:
            key = PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid'])
            self.assertEqual(program, all_programs[key])
Пример #13
0
    def setUp(self):
        super(TestCachePrograms, self).setUp()

        self.catalog_integration = self.create_catalog_integration()

        self.list_url = self.catalog_integration.get_internal_api_url().rstrip('/') + '/programs/'
        self.detail_tpl = self.list_url.rstrip('/') + '/{uuid}/'

        self.programs = ProgramFactory.create_batch(3)
        self.uuids = [program['uuid'] for program in self.programs]
Пример #14
0
    def test_get_programs_with_status_filtering(self, mock_get_edx_api_data):
        """ The function should request active and retired programs when the Waffle switch is enabled. """
        programs = ProgramFactory.create_batch(3)
        mock_get_edx_api_data.return_value = programs

        Switch.objects.get_or_create(name='display_retired_programs_on_learner_dashboard', defaults={'active': True})
        data = get_programs()

        expected_querystring = {
            'exclude_utm': 1,
            'status': ('active', 'retired',)
        }
        self.assert_contract(mock_get_edx_api_data.call_args, expected_querystring=expected_querystring)
        self.assertEqual(data, programs)
Пример #15
0
    def setUp(self):
        super(ProgramPageBase, self).setUp()

        self.set_programs_api_configuration(is_enabled=True)

        self.programs = ProgramFactory.create_batch(3)
        self.pathways = PathwayFactory.create_batch(3)
        for pathway in self.pathways:
            self.programs += pathway['programs']

        # add some of the previously created programs to some pathways
        self.pathways[0]['programs'].extend([self.programs[0], self.programs[1]])
        self.pathways[1]['programs'].append(self.programs[0])

        self.username = None
Пример #16
0
    def setUp(self):
        super(ProgramPageBase, self).setUp()

        self.set_programs_api_configuration(is_enabled=True)

        self.programs = ProgramFactory.create_batch(3)
        self.credit_pathways = CreditPathwayFactory.create_batch(3)
        for pathway in self.credit_pathways:
            self.programs += pathway['programs']

        # add some of the previously created programs to some pathways
        self.credit_pathways[0]['programs'].extend([self.programs[0], self.programs[1]])
        self.credit_pathways[1]['programs'].append(self.programs[0])

        self.username = None
Пример #17
0
    def setUp(self):
        super(ProgramPageBase, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments

        self.set_programs_api_configuration(is_enabled=True)

        self.programs = ProgramFactory.create_batch(3)
        self.pathways = PathwayFactory.create_batch(3)
        for pathway in self.pathways:
            self.programs += pathway['programs']

        # add some of the previously created programs to some pathways
        self.pathways[0]['programs'].extend(
            [self.programs[0], self.programs[1]])
        self.pathways[1]['programs'].append(self.programs[0])

        self.username = None
    def setUp(self):
        super(TestCachePrograms, self).setUp()

        self.catalog_integration = self.create_catalog_integration()
        self.site_domain = 'testsite.com'
        self.set_up_site(
            self.site_domain,
            {
                'COURSE_CATALOG_API_URL': self.catalog_integration.get_internal_api_url().rstrip('/')
            }
        )

        self.list_url = self.catalog_integration.get_internal_api_url().rstrip('/') + '/programs/'
        self.detail_tpl = self.list_url.rstrip('/') + '/{uuid}/'

        self.programs = ProgramFactory.create_batch(3)
        self.uuids = [program['uuid'] for program in self.programs]
    def setUp(self):
        super(TestCachePrograms, self).setUp()

        self.catalog_integration = self.create_catalog_integration()
        self.site_domain = 'testsite.com'
        self.set_up_site(
            self.site_domain, {
                'COURSE_CATALOG_API_URL':
                self.catalog_integration.get_internal_api_url().rstrip('/')
            })

        self.list_url = self.catalog_integration.get_internal_api_url().rstrip(
            '/') + '/programs/'
        self.detail_tpl = self.list_url.rstrip('/') + '/{uuid}/'

        self.programs = ProgramFactory.create_batch(3)
        self.uuids = [program['uuid'] for program in self.programs]
Пример #20
0
    def test_get_programs_with_type(self, mock_get_program_types, mock_get_programs):
        """Verify get_programs_with_type returns the expected list of programs."""
        programs_with_program_type = []
        programs = ProgramFactory.create_batch(2)
        program_types = []

        for program in programs:
            program_type = ProgramTypeFactory(name=program['type'])
            program_types.append(program_type)

            program_with_type = copy.deepcopy(program)
            program_with_type['type'] = program_type
            programs_with_program_type.append(program_with_type)

        mock_get_programs.return_value = programs
        mock_get_program_types.return_value = program_types

        actual = get_programs_with_type(self.site)
        self.assertEqual(actual, programs_with_program_type)
Пример #21
0
    def test_get_programs_with_type(self, mock_get_program_types, mock_get_programs):
        """Verify get_programs_with_type returns the expected list of programs."""
        programs_with_program_type = []
        programs = ProgramFactory.create_batch(2)
        program_types = []

        for program in programs:
            program_type = ProgramTypeFactory(name=program['type'])
            program_types.append(program_type)

            program_with_type = copy.deepcopy(program)
            program_with_type['type'] = program_type
            programs_with_program_type.append(program_with_type)

        mock_get_programs.return_value = programs
        mock_get_program_types.return_value = program_types

        actual = get_programs_with_type(self.site)
        self.assertEqual(actual, programs_with_program_type)
Пример #22
0
    def test_get_programs_with_status_filtering(self, mock_get_edx_api_data):
        """ The function should request active and retired programs when the Waffle switch is enabled. """
        programs = ProgramFactory.create_batch(3)
        mock_get_edx_api_data.return_value = programs

        Switch.objects.get_or_create(
            name='display_retired_programs_on_learner_dashboard',
            defaults={'active': True})
        data = get_programs()

        expected_querystring = {
            'exclude_utm': 1,
            'status': (
                'active',
                'retired',
            )
        }
        self.assert_contract(mock_get_edx_api_data.call_args,
                             expected_querystring=expected_querystring)
        self.assertEqual(data, programs)
Пример #23
0
    def test_get_many(self, mock_warning, mock_info):
        programs = ProgramFactory.create_batch(3)

        # Cache details for 2 of 3 programs.
        partial_programs = {
            PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid']): program
            for program in programs[:2]
        }
        cache.set_many(partial_programs, None)

        # When called before UUIDs are cached, the function should return an
        # empty list and log a warning.
        with with_site_configuration_context(
                domain=self.site.name,
                configuration={'COURSE_CATALOG_API_URL': 'foo'}):
            self.assertEqual(get_programs(site=self.site), [])
            mock_warning.assert_called_once_with(
                u'Failed to get program UUIDs from the cache for site {}.'.
                format(self.site.domain))
            mock_warning.reset_mock()

        # Cache UUIDs for all 3 programs.
        cache.set(
            SITE_PROGRAM_UUIDS_CACHE_KEY_TPL.format(domain=self.site.domain),
            [program['uuid'] for program in programs], None)

        actual_programs = get_programs(site=self.site)

        # The 2 cached programs should be returned while info and warning
        # messages should be logged for the missing one.
        self.assertEqual(
            set(program['uuid'] for program in actual_programs),
            set(program['uuid'] for program in partial_programs.values()))
        mock_info.assert_called_with(
            'Failed to get details for 1 programs. Retrying.')
        mock_warning.assert_called_with(
            u'Failed to get details for program {uuid} from the cache.'.format(
                uuid=programs[2]['uuid']))
        mock_warning.reset_mock()

        # We can't use a set comparison here because these values are dictionaries
        # and aren't hashable. We've already verified that all programs came out
        # of the cache above, so all we need to do here is verify the accuracy of
        # the data itself.
        for program in actual_programs:
            key = PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid'])
            self.assertEqual(program, partial_programs[key])

        # Cache details for all 3 programs.
        all_programs = {
            PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid']): program
            for program in programs
        }
        cache.set_many(all_programs, None)

        actual_programs = get_programs(site=self.site)

        # All 3 programs should be returned.
        self.assertEqual(
            set(program['uuid'] for program in actual_programs),
            set(program['uuid'] for program in all_programs.values()))
        self.assertFalse(mock_warning.called)

        for program in actual_programs:
            key = PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid'])
            self.assertEqual(program, all_programs[key])
Пример #24
0
    def test_get_many(self, mock_warning, mock_info):
        programs = ProgramFactory.create_batch(3)

        # Cache details for 2 of 3 programs.
        partial_programs = {
            PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid']): program for program in programs[:2]
        }
        cache.set_many(partial_programs, None)

        # When called before UUIDs are cached, the function should return an
        # empty list and log a warning.
        self.assertEqual(get_programs(self.site), [])
        mock_warning.assert_called_once_with('Failed to get program UUIDs from the cache.')
        mock_warning.reset_mock()

        # Cache UUIDs for all 3 programs.
        cache.set(
            SITE_PROGRAM_UUIDS_CACHE_KEY_TPL.format(domain=self.site.domain),
            [program['uuid'] for program in programs],
            None
        )

        actual_programs = get_programs(self.site)

        # The 2 cached programs should be returned while info and warning
        # messages should be logged for the missing one.
        self.assertEqual(
            set(program['uuid'] for program in actual_programs),
            set(program['uuid'] for program in partial_programs.values())
        )
        mock_info.assert_called_with('Failed to get details for 1 programs. Retrying.')
        mock_warning.assert_called_with(
            'Failed to get details for program {uuid} from the cache.'.format(uuid=programs[2]['uuid'])
        )
        mock_warning.reset_mock()

        # We can't use a set comparison here because these values are dictionaries
        # and aren't hashable. We've already verified that all programs came out
        # of the cache above, so all we need to do here is verify the accuracy of
        # the data itself.
        for program in actual_programs:
            key = PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid'])
            self.assertEqual(program, partial_programs[key])

        # Cache details for all 3 programs.
        all_programs = {
            PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid']): program for program in programs
        }
        cache.set_many(all_programs, None)

        actual_programs = get_programs(self.site)

        # All 3 programs should be returned.
        self.assertEqual(
            set(program['uuid'] for program in actual_programs),
            set(program['uuid'] for program in all_programs.values())
        )
        self.assertFalse(mock_warning.called)

        for program in actual_programs:
            key = PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid'])
            self.assertEqual(program, all_programs[key])