From f2139bbe2f554a1c03d561797f38a2b466de7299 Mon Sep 17 00:00:00 2001 From: Emma Green Date: Tue, 29 Jan 2019 10:46:35 -0500 Subject: [PATCH] add courses to programs to cache --- .../contentstore/views/tests/test_videos.py | 10 +- common/djangoapps/student/views/dashboard.py | 2 +- common/djangoapps/terrain/stubs/catalog.py | 7 +- common/test/acceptance/fixtures/catalog.py | 26 ++- .../acceptance/tests/lms/test_programs.py | 61 +++++-- .../courseware/tests/test_video_mongo.py | 4 +- lms/djangoapps/courseware/views/views.py | 2 +- openedx/core/djangoapps/catalog/cache.py | 3 + .../management/commands/cache_programs.py | 48 ++++- .../commands/tests/test_cache_programs.py | 165 +++++++++++++++++- .../djangoapps/catalog/tests/factories.py | 20 +++ .../djangoapps/catalog/tests/test_utils.py | 4 +- openedx/core/djangoapps/catalog/utils.py | 31 ++-- openedx/core/djangoapps/programs/utils.py | 2 +- .../commands/migrate_user_profile_langs.py | 6 +- 15 files changed, 345 insertions(+), 46 deletions(-) diff --git a/cms/djangoapps/contentstore/views/tests/test_videos.py b/cms/djangoapps/contentstore/views/tests/test_videos.py index 9f97147021..cb365e8af0 100644 --- a/cms/djangoapps/contentstore/views/tests/test_videos.py +++ b/cms/djangoapps/contentstore/views/tests/test_videos.py @@ -958,7 +958,10 @@ class VideoImageTestCase(VideoUploadTestBase, CourseTestCase): 'width': 16, # 16x9 'height': 9 }, - u'Recommended image resolution is {image_file_max_width}x{image_file_max_height}. The minimum resolution is {image_file_min_width}x{image_file_min_height}.'.format( + ( + u'Recommended image resolution is {image_file_max_width}x{image_file_max_height}. ' + u'The minimum resolution is {image_file_min_width}x{image_file_min_height}.' + ).format( image_file_max_width=settings.VIDEO_IMAGE_MAX_WIDTH, image_file_max_height=settings.VIDEO_IMAGE_MAX_HEIGHT, image_file_min_width=settings.VIDEO_IMAGE_MIN_WIDTH, @@ -970,7 +973,10 @@ class VideoImageTestCase(VideoUploadTestBase, CourseTestCase): 'width': settings.VIDEO_IMAGE_MIN_WIDTH - 10, 'height': settings.VIDEO_IMAGE_MIN_HEIGHT }, - u'Recommended image resolution is {image_file_max_width}x{image_file_max_height}. The minimum resolution is {image_file_min_width}x{image_file_min_height}.'.format( + ( + u'Recommended image resolution is {image_file_max_width}x{image_file_max_height}. ' + u'The minimum resolution is {image_file_min_width}x{image_file_min_height}.' + ).format( image_file_max_width=settings.VIDEO_IMAGE_MAX_WIDTH, image_file_max_height=settings.VIDEO_IMAGE_MAX_HEIGHT, image_file_min_width=settings.VIDEO_IMAGE_MIN_WIDTH, diff --git a/common/djangoapps/student/views/dashboard.py b/common/djangoapps/student/views/dashboard.py index 9a49dec2d5..be52bf8360 100644 --- a/common/djangoapps/student/views/dashboard.py +++ b/common/djangoapps/student/views/dashboard.py @@ -695,7 +695,7 @@ def student_dashboard(request): for program in inverted_programs.values(): try: program_uuid = program[0]['uuid'] - program_data = get_programs(request.site, uuid=program_uuid) + program_data = get_programs(uuid=program_uuid) program_data = ProgramDataExtender(program_data, request.user).extend() skus = program_data.get('skus') checkout_page_url = ecommerce_service.get_checkout_page_url(*skus) diff --git a/common/djangoapps/terrain/stubs/catalog.py b/common/djangoapps/terrain/stubs/catalog.py index f33075a774..04c6a8b24d 100644 --- a/common/djangoapps/terrain/stubs/catalog.py +++ b/common/djangoapps/terrain/stubs/catalog.py @@ -15,7 +15,8 @@ class StubCatalogServiceHandler(StubHttpRequestHandler): r'/api/v1/programs/$': self.program_list, r'/api/v1/programs/([0-9a-f-]+)/$': self.program_detail, r'/api/v1/program_types/$': self.program_types, - r'/api/v1/pathways/$': self.pathways + r'/api/v1/pathways/$': self.pathways, + r'/api/v1/course_runs/$': self.course_runs, } if self.match_pattern(pattern_handlers): @@ -52,6 +53,10 @@ class StubCatalogServiceHandler(StubHttpRequestHandler): pathways = self.server.config.get('catalog.pathways', []) self.send_json_response(pathways) + def course_runs(self): + course_runs = self.server.config.get('catalog.course_runs', {'results': [], 'next': None}) + self.send_json_response(course_runs) + class StubCatalogService(StubHttpService): HANDLER_CLASS = StubCatalogServiceHandler diff --git a/common/test/acceptance/fixtures/catalog.py b/common/test/acceptance/fixtures/catalog.py index 4d1bdea678..ecef37b7fa 100644 --- a/common/test/acceptance/fixtures/catalog.py +++ b/common/test/acceptance/fixtures/catalog.py @@ -13,7 +13,8 @@ class CatalogFixture(object): """ Interface to set up mock responses from the Catalog stub server. """ - def install_programs(self, programs): + @classmethod + def install_programs(cls, programs): """ Stub the discovery service's program list and detail API endpoints. @@ -40,7 +41,8 @@ class CatalogFixture(object): data={key: json.dumps(uuids)}, ) - def install_pathways(self, pathways): + @classmethod + def install_pathways(cls, pathways): """ Stub the discovery service's credit pathways API endpoint @@ -52,7 +54,8 @@ class CatalogFixture(object): data={'catalog.pathways': json.dumps({'results': pathways, 'next': None})} ) - def install_program_types(self, program_types): + @classmethod + def install_program_types(cls, program_types): """ Stub the discovery service's program type list API endpoints. @@ -64,10 +67,25 @@ class CatalogFixture(object): data={'catalog.programs_types': json.dumps(program_types)}, ) + @classmethod + def install_course_runs(cls, course_runs): + """ + Stub the discovery service's course run list API endpoints. + + Arguments: + course_runs (list): A list of course runs. List endpoint will be stubbed using data from this list. + """ + requests.put( + '{}/set_config'.format(CATALOG_STUB_URL), + data={'catalog.course_runs': json.dumps({'results': course_runs, 'next': None})} + ) + class CatalogIntegrationMixin(object): """Mixin providing a method used to configure the catalog integration.""" - def set_catalog_integration(self, is_enabled=False, service_username=None): + + @classmethod + def set_catalog_integration(cls, is_enabled=False, service_username=None): """Use this to change the catalog integration config model during tests.""" ConfigModelFixture('/config/catalog', { 'enabled': is_enabled, diff --git a/common/test/acceptance/tests/lms/test_programs.py b/common/test/acceptance/tests/lms/test_programs.py index 06de2b8a2f..12fa19a06b 100644 --- a/common/test/acceptance/tests/lms/test_programs.py +++ b/common/test/acceptance/tests/lms/test_programs.py @@ -11,7 +11,8 @@ from openedx.core.djangoapps.catalog.tests.factories import ( CourseRunFactory, PathwayFactory, ProgramFactory, - ProgramTypeFactory + ProgramTypeFactory, + ProgramDescriptionFactory, ) @@ -24,6 +25,12 @@ class ProgramPageBase(ProgramsConfigMixin, CatalogIntegrationMixin, UniqueCourse self.programs = ProgramFactory.create_batch(3) self.pathways = PathwayFactory.create_batch(3) + self.course_runs = [ + CourseRunFactory.create(programs=[ProgramDescriptionFactory.from_program(program)], **course_run) + for program in self.programs + for course in program['courses'] + for course_run in course['course_runs'] + ] for pathway in self.pathways: self.programs += pathway['programs'] @@ -51,18 +58,28 @@ class ProgramPageBase(ProgramsConfigMixin, CatalogIntegrationMixin, UniqueCourse program_type = ProgramTypeFactory() return ProgramFactory(courses=[course], type=program_type['name']) - def stub_catalog_api(self, programs, pathways): + def stub_catalog_api(self, programs=None, pathways=None, course_runs=None): """ Stub the discovery service's program list and detail API endpoints, as well as the credit pathway list endpoint. """ self.set_catalog_integration(is_enabled=True, service_username=self.username) - CatalogFixture().install_programs(programs) + + if programs is None: + programs = self.programs + + CatalogFixture.install_programs(programs) program_types = [program['type'] for program in programs] - CatalogFixture().install_program_types(program_types) + CatalogFixture.install_program_types(program_types) - CatalogFixture().install_pathways(pathways) + if pathways is None: + pathways = self.pathways + CatalogFixture.install_pathways(pathways) + + if course_runs is None: + course_runs = self.course_runs + CatalogFixture.install_course_runs(course_runs) def cache_programs(self): """ @@ -84,7 +101,7 @@ class ProgramListingPageTest(ProgramPageBase): def test_no_enrollments(self): """Verify that no cards appear when the user has no enrollments.""" self.auth(enroll=False) - self.stub_catalog_api(self.programs, self.pathways) + self.stub_catalog_api() self.cache_programs() self.listing_page.visit() @@ -98,7 +115,7 @@ class ProgramListingPageTest(ProgramPageBase): but none are included in an active program. """ self.auth() - self.stub_catalog_api(self.programs, self.pathways) + self.stub_catalog_api() self.cache_programs() self.listing_page.visit() @@ -126,7 +143,15 @@ class ProgramListingPageA11yTest(ProgramPageBase): ] }) self.auth(enroll=False) - self.stub_catalog_api(programs=[self.program], pathways=[]) + self.stub_catalog_api( + programs=[self.program], + pathways=[], + course_runs=[ + CourseRunFactory.create(programs=[ProgramDescriptionFactory.from_program(self.program)], **course_run) + for course in self.program['courses'] + for course_run in course['course_runs'] + ] + ) self.cache_programs() self.listing_page.visit() @@ -143,7 +168,15 @@ class ProgramListingPageA11yTest(ProgramPageBase): ] }) self.auth() - self.stub_catalog_api(programs=[self.program], pathways=[]) + self.stub_catalog_api( + programs=[self.program], + pathways=[], + course_runs=[ + CourseRunFactory.create(programs=[ProgramDescriptionFactory.from_program(self.program)], **course_run) + for course in self.program['courses'] + for course_run in course['course_runs'] + ] + ) self.cache_programs() self.listing_page.visit() @@ -173,7 +206,15 @@ class ProgramDetailsPageA11yTest(ProgramPageBase): ] }) self.auth() - self.stub_catalog_api(programs=[self.program], pathways=[]) + self.stub_catalog_api( + programs=[self.program], + pathways=[], + course_runs=[ + CourseRunFactory.create(programs=[ProgramDescriptionFactory.from_program(self.program)], **course_run) + for course in self.program['courses'] + for course_run in course['course_runs'] + ] + ) self.cache_programs() self.details_page.visit() diff --git a/lms/djangoapps/courseware/tests/test_video_mongo.py b/lms/djangoapps/courseware/tests/test_video_mongo.py index 728d1e7da5..c17995ddb9 100644 --- a/lms/djangoapps/courseware/tests/test_video_mongo.py +++ b/lms/djangoapps/courseware/tests/test_video_mongo.py @@ -814,7 +814,7 @@ class TestGetHtmlMethod(BaseTestXmodule): mocked_get_video.side_effect = side_effect - SOURCE_XML = """ + source_xml = """