From 9995716899a838e977e88ebb4c83e7a64a3e7feb Mon Sep 17 00:00:00 2001 From: Ibrahim Date: Tue, 6 Jun 2017 18:16:08 +0500 Subject: [PATCH] Exclude hidden programs from white label course and homepage LEARNER-1126, LEARNER-1127 --- common/djangoapps/student/views.py | 2 +- lms/djangoapps/courseware/views/views.py | 2 +- .../djangoapps/catalog/tests/factories.py | 1 + .../djangoapps/catalog/tests/test_utils.py | 60 +++++++++++++++++-- openedx/core/djangoapps/catalog/utils.py | 9 ++- 5 files changed, 66 insertions(+), 8 deletions(-) diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index acd0c016d6..8c8efc5f8e 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -216,7 +216,7 @@ def index(request, extra_context=None, user=AnonymousUser()): # Do not add programs to the context if there are no program types enabled for the site. if program_types: - programs_list = get_programs_with_type(program_types) + programs_list = get_programs_with_type(program_types, include_hidden=False) context["programs_list"] = programs_list diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py index 3db429ad70..b56adf37d2 100644 --- a/lms/djangoapps/courseware/views/views.py +++ b/lms/djangoapps/courseware/views/views.py @@ -167,7 +167,7 @@ def courses(request): # Do not add programs to the context if there are no program types enabled for the site. if program_types: - programs_list = get_programs_with_type(program_types) + programs_list = get_programs_with_type(program_types, include_hidden=False) return render_to_response( "courseware/courses.html", diff --git a/openedx/core/djangoapps/catalog/tests/factories.py b/openedx/core/djangoapps/catalog/tests/factories.py index 5f4dabf9c4..8343b5a15a 100644 --- a/openedx/core/djangoapps/catalog/tests/factories.py +++ b/openedx/core/djangoapps/catalog/tests/factories.py @@ -125,6 +125,7 @@ class ProgramFactory(DictFactoryBase): title = factory.Faker('catch_phrase') type = factory.Faker('word') uuid = factory.Faker('uuid4') + hidden = False class ProgramTypeFactory(DictFactoryBase): diff --git a/openedx/core/djangoapps/catalog/tests/test_utils.py b/openedx/core/djangoapps/catalog/tests/test_utils.py index cc4e798a97..a1864a72db 100644 --- a/openedx/core/djangoapps/catalog/tests/test_utils.py +++ b/openedx/core/djangoapps/catalog/tests/test_utils.py @@ -3,6 +3,7 @@ import copy import uuid +import ddt import mock from django.contrib.auth import get_user_model from django.core.cache import cache @@ -13,15 +14,14 @@ from openedx.core.djangoapps.catalog.models import CatalogIntegration from openedx.core.djangoapps.catalog.tests.factories import CourseRunFactory, ProgramFactory, ProgramTypeFactory from openedx.core.djangoapps.catalog.tests.mixins import CatalogIntegrationMixin from openedx.core.djangoapps.catalog.utils import ( - get_programs, - get_program_types, - get_programs_with_type, get_course_runs, + get_program_types, + get_programs, + get_programs_with_type ) from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_unless_lms from student.tests.factories import UserFactory - UTILS_MODULE = 'openedx.core.djangoapps.catalog.utils' User = get_user_model() # pylint: disable=invalid-name @@ -154,6 +154,58 @@ class TestGetPrograms(CacheIsolationTestCase): @skip_unless_lms +@ddt.ddt +class TestGetProgramsWithType(TestCase): + + @mock.patch(UTILS_MODULE + '.get_programs') + @mock.patch(UTILS_MODULE + '.get_program_types') + 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.assertEqual(actual, programs_with_program_type) + + @ddt.data(False, True) + @mock.patch(UTILS_MODULE + '.get_programs') + @mock.patch(UTILS_MODULE + '.get_program_types') + def test_get_programs_with_type_include_hidden(self, include_hidden, mock_get_program_types, mock_get_programs): + """Verify get_programs_with_type returns the expected list of programs with include_hidden parameter.""" + programs_with_program_type = [] + programs = [ProgramFactory(hidden=False), ProgramFactory(hidden=True)] + program_types = [] + + for program in programs: + if program['hidden'] and not include_hidden: + continue + + 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(include_hidden=include_hidden) + self.assertEqual(actual, programs_with_program_type) + + @mock.patch(UTILS_MODULE + '.get_edx_api_data') class TestGetProgramTypes(CatalogIntegrationMixin, TestCase): """Tests covering retrieval of program types from the catalog service.""" diff --git a/openedx/core/djangoapps/catalog/utils.py b/openedx/core/djangoapps/catalog/utils.py index 7ce02b134b..07d6720f89 100644 --- a/openedx/core/djangoapps/catalog/utils.py +++ b/openedx/core/djangoapps/catalog/utils.py @@ -109,15 +109,17 @@ def get_program_types(name=None): return [] -def get_programs_with_type(types=None): +def get_programs_with_type(types=None, include_hidden=True): """ Return the list of programs. You can filter the types of programs returned using the optional - types parameter. If no filter is provided, all programs of all types will be returned. + types parameter. If no filter is provided, all programs of all types will be returned. In addition, + you can specify whether to include hidden programs using the optional include_hidden parameter. The program dict is updated with the fully serialized program type. Keyword Arguments: types (list): List of program type slugs to filter by. + include_hidden (bool): whether to include hidden programs Return: list of dict, representing the active programs. @@ -136,6 +138,9 @@ def get_programs_with_type(types=None): if types and program['type'] not in types: continue + if program['hidden'] and not include_hidden: + continue + # deepcopy the program dict here so we are not adding # the type to the cached object program_with_type = copy.deepcopy(program)