Example #1
0
    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('/') + '/credit_pathways/'

        self.programs = ProgramFactory.create_batch(3)
        self.pathways = CreditPathwayFactory.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])
Example #2
0
    def test_pathways_multiple_pages(self):
        """
        Verify that the command properly caches credit pathways when multiple pages are returned from its endpoint
        """
        UserFactory(username=self.catalog_integration.service_username)
        new_pathways = CreditPathwayFactory.create_batch(40)
        for new_pathway in new_pathways:
            new_pathway['programs'] = []
        pathways = self.pathways + new_pathways

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

        self.mock_list()
        for uuid in self.uuids:
            program = programs[PROGRAM_CACHE_KEY_TPL.format(uuid=uuid)]
            self.mock_detail(uuid, program)

        # mock 3 pages of credit pathways, starting at the last
        self.mock_pathways(pathways[40:], page_number=3, final=True)
        self.mock_pathways(pathways[20:40], page_number=2, final=False)
        self.mock_pathways(pathways[:20], page_number=1, final=False)

        call_command('cache_programs')

        pathways_dict = {
            CREDIT_PATHWAY_CACHE_KEY_TPL.format(id=pathway['id']): pathway
            for pathway in pathways
        }
        pathway_keys = pathways_dict.keys()

        cached_pathway_keys = cache.get(
            SITE_CREDIT_PATHWAY_IDS_CACHE_KEY_TPL.format(
                domain=self.site_domain))
        self.assertEqual(set(cached_pathway_keys), set(pathway_keys))

        cached_pathways = cache.get_many(pathway_keys)
        self.assertEqual(set(cached_pathways), set(pathways_dict))

        # We can't use a set comparison here because these values are dictionaries
        # and aren't hashable. We've already verified that all pathways came out
        # of the cache above, so all we need to do here is verify the accuracy of
        # the data itself.
        for key, pathway in cached_pathways.items():
            # cached pathways store just program uuids instead of the full programs, transform before comparing
            pathways_dict[key]['program_uuids'] = [
                program['uuid'] for program in pathways_dict[key]['programs']
            ]
            del pathways_dict[key]['programs']

            self.assertEqual(pathway, pathways_dict[key])
Example #3
0
    def setUpClass(cls):
        super(TestProgramDetails, cls).setUpClass()

        modulestore_course = ModuleStoreCourseFactory()
        course_run = CourseRunFactory(key=unicode(modulestore_course.id))  # pylint: disable=no-member
        course = CourseFactory(course_runs=[course_run])

        cls.program_data = ProgramFactory(uuid=cls.program_uuid, courses=[course])
        cls.pathway_data = CreditPathwayFactory()
        cls.program_data['pathway_ids'] = [cls.pathway_data['id']]
        cls.pathway_data['program_uuids'] = [cls.program_data['uuid']]
        del cls.pathway_data['programs']
Example #4
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
Example #5
0
    def test_get_one(self, mock_warning, _mock_info):
        expected_pathway = CreditPathwayFactory()
        expected_id = expected_pathway['id']

        self.assertEqual(
            get_credit_pathways(self.site, pathway_id=expected_id), None)
        mock_warning.assert_called_once_with(
            'Failed to get details for credit pathway {id} from the cache.'.
            format(id=expected_id))
        mock_warning.reset_mock()

        cache.set(CREDIT_PATHWAY_CACHE_KEY_TPL.format(id=expected_id),
                  expected_pathway, None)

        actual_pathway = get_credit_pathways(self.site, pathway_id=expected_id)
        self.assertEqual(actual_pathway, expected_pathway)
        self.assertFalse(mock_warning.called)
Example #6
0
    def test_get_many_with_missing(self, mock_cache, mock_warning, mock_info):
        pathways = CreditPathwayFactory.create_batch(3)

        all_pathways = {
            CREDIT_PATHWAY_CACHE_KEY_TPL.format(id=pathway['id']): pathway
            for pathway in pathways
        }

        partial_pathways = {
            CREDIT_PATHWAY_CACHE_KEY_TPL.format(id=pathway['id']): pathway
            for pathway in pathways[:2]
        }

        def fake_get_many(keys):
            if len(keys) == 1:
                return {
                    CREDIT_PATHWAY_CACHE_KEY_TPL.format(id=pathways[-1]['id']):
                    pathways[-1]
                }
            else:
                return partial_pathways

        mock_cache.get.return_value = [pathway['id'] for pathway in pathways]
        mock_cache.get_many.side_effect = fake_get_many

        actual_pathways = get_credit_pathways(self.site)

        # All 3 cached pathways 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(pathway['id'] for pathway in actual_pathways),
            set(pathway['id'] for pathway in all_pathways.values()))
        self.assertFalse(mock_warning.called)
        mock_info.assert_called_with(
            'Failed to get details for 1 pathways. Retrying.')

        for pathway in actual_pathways:
            key = CREDIT_PATHWAY_CACHE_KEY_TPL.format(id=pathway['id'])
            self.assertEqual(pathway, all_pathways[key])
Example #7
0
    def test_get_many(self, mock_warning, mock_info):
        pathways = CreditPathwayFactory.create_batch(3)

        # Cache details for 2 of 3 programs.
        partial_pathways = {
            CREDIT_PATHWAY_CACHE_KEY_TPL.format(id=pathway['id']): pathway
            for pathway in pathways[:2]
        }
        cache.set_many(partial_pathways, None)

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

        # Cache all 3 pathways
        cache.set(
            SITE_CREDIT_PATHWAY_IDS_CACHE_KEY_TPL.format(
                domain=self.site.domain),
            [pathway['id'] for pathway in pathways], None)

        actual_pathways = get_credit_pathways(self.site)

        # The 2 cached pathways should be returned while info and warning
        # messages should be logged for the missing one.
        self.assertEqual(
            set(pathway['id'] for pathway in actual_pathways),
            set(pathway['id'] for pathway in partial_pathways.values()))
        mock_info.assert_called_with(
            'Failed to get details for 1 pathways. Retrying.')
        mock_warning.assert_called_with(
            'Failed to get details for credit pathway {id} from the cache.'.
            format(id=pathways[2]['id']))
        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 pathways came out
        # of the cache above, so all we need to do here is verify the accuracy of
        # the data itself.
        for pathway in actual_pathways:
            key = CREDIT_PATHWAY_CACHE_KEY_TPL.format(id=pathway['id'])
            self.assertEqual(pathway, partial_pathways[key])

        # Cache details for all 3 pathways.
        all_pathways = {
            CREDIT_PATHWAY_CACHE_KEY_TPL.format(id=pathway['id']): pathway
            for pathway in pathways
        }
        cache.set_many(all_pathways, None)

        actual_pathways = get_credit_pathways(self.site)

        # All 3 pathways should be returned.
        self.assertEqual(
            set(pathway['id'] for pathway in actual_pathways),
            set(pathway['id'] for pathway in all_pathways.values()))
        self.assertFalse(mock_warning.called)

        for pathway in actual_pathways:
            key = CREDIT_PATHWAY_CACHE_KEY_TPL.format(id=pathway['id'])
            self.assertEqual(pathway, all_pathways[key])