Programs list conditionally added to the context of index and courses page.
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('catalog', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='catalogintegration',
|
||||
name='service_username',
|
||||
field=models.CharField(default=b'lms_catalog_service_user', help_text='Username created for Course Catalog Integration, e.g. lms_catalog_service_user.', max_length=100),
|
||||
),
|
||||
]
|
||||
@@ -25,6 +25,16 @@ class CatalogIntegration(ConfigurationModel):
|
||||
)
|
||||
)
|
||||
|
||||
service_username = models.CharField(
|
||||
max_length=100,
|
||||
default="lms_catalog_service_user",
|
||||
null=False,
|
||||
blank=False,
|
||||
help_text=_(
|
||||
'Username created for Course Catalog Integration, e.g. lms_catalog_service_user.'
|
||||
)
|
||||
)
|
||||
|
||||
@property
|
||||
def is_cache_enabled(self):
|
||||
"""Whether responses from the catalog API will be cached."""
|
||||
|
||||
@@ -70,3 +70,14 @@ class Program(factory.Factory):
|
||||
banner_image = {
|
||||
size: BannerImage() for size in ['large', 'medium', 'small', 'x-small']
|
||||
}
|
||||
|
||||
|
||||
class ProgramType(factory.Factory):
|
||||
"""
|
||||
Factory for stubbing ProgramType resources from the catalog API.
|
||||
"""
|
||||
class Meta(object):
|
||||
model = dict
|
||||
|
||||
name = FuzzyText()
|
||||
logo_image = FuzzyText(prefix='https://example.com/program/logo')
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
Tests covering utilities for integrating with the catalog service.
|
||||
"""
|
||||
import uuid
|
||||
import copy
|
||||
|
||||
from django.core.cache import cache
|
||||
from django.test import TestCase
|
||||
@@ -12,9 +13,8 @@ from opaque_keys.edx.keys import CourseKey
|
||||
from openedx.core.djangoapps.catalog import utils
|
||||
from openedx.core.djangoapps.catalog.models import CatalogIntegration
|
||||
from openedx.core.djangoapps.catalog.tests import factories, mixins
|
||||
from student.tests.factories import UserFactory, AnonymousUserFactory
|
||||
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
|
||||
from student.tests.factories import UserFactory
|
||||
|
||||
|
||||
UTILS_MODULE = 'openedx.core.djangoapps.catalog.utils'
|
||||
|
||||
@@ -76,6 +76,73 @@ class TestGetPrograms(mixins.CatalogIntegrationMixin, TestCase):
|
||||
self.assert_contract(mock_get_catalog_data.call_args)
|
||||
self.assertEqual(data, programs)
|
||||
|
||||
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='lms_catalog_service_user')
|
||||
# After creating the service user above,
|
||||
data = utils.get_programs(anonymous_user)
|
||||
# the programs should be returned successfully.
|
||||
self.assertEqual(data, programs)
|
||||
|
||||
def test_get_program_types(self, _mock_cache, mock_get_catalog_data):
|
||||
program_types = [factories.ProgramType() for __ in range(3)]
|
||||
mock_get_catalog_data.return_value = program_types
|
||||
|
||||
# Creating Anonymous user but the Catalog Service User has not been created yet.
|
||||
anonymous_user = AnonymousUserFactory()
|
||||
data = utils.get_program_types(anonymous_user)
|
||||
# This should not return programs.
|
||||
self.assertEqual(data, [])
|
||||
|
||||
# Creating Catalog Service User user
|
||||
UserFactory(username='lms_catalog_service_user')
|
||||
data = utils.get_program_types(anonymous_user)
|
||||
# the programs should be returned successfully.
|
||||
self.assertEqual(data, program_types)
|
||||
|
||||
# Catalog integration is disabled now.
|
||||
self.catalog_integration = self.create_catalog_integration(enabled=False)
|
||||
data = utils.get_program_types(anonymous_user)
|
||||
# This should not return programs.
|
||||
self.assertEqual(data, [])
|
||||
|
||||
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)
|
||||
|
||||
def test_get_one_program(self, _mock_cache, mock_get_catalog_data):
|
||||
program = factories.Program()
|
||||
mock_get_catalog_data.return_value = program
|
||||
|
||||
@@ -4,6 +4,7 @@ import logging
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from django.contrib.auth.models import User
|
||||
from edx_rest_api_client.client import EdxRestApiClient
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
|
||||
@@ -24,7 +25,20 @@ def create_catalog_api_client(user, catalog_integration):
|
||||
return EdxRestApiClient(catalog_integration.internal_api_url, jwt=jwt)
|
||||
|
||||
|
||||
def get_programs(user, uuid=None, type=None): # pylint: disable=redefined-builtin
|
||||
def _get_service_user(user, service_username):
|
||||
"""
|
||||
Retrieve and return the Catalog Integration Service User Object
|
||||
if the passed user is None or anonymous
|
||||
"""
|
||||
if not user or user.is_anonymous():
|
||||
try:
|
||||
user = User.objects.get(username=service_username)
|
||||
except User.DoesNotExist:
|
||||
user = None
|
||||
return user
|
||||
|
||||
|
||||
def get_programs(user=None, uuid=None, type=None): # pylint: disable=redefined-builtin
|
||||
"""Retrieve marketable programs from the catalog service.
|
||||
|
||||
Keyword Arguments:
|
||||
@@ -36,8 +50,11 @@ def get_programs(user, uuid=None, type=None): # pylint: disable=redefined-built
|
||||
dict, if a specific program is requested.
|
||||
"""
|
||||
catalog_integration = CatalogIntegration.current()
|
||||
|
||||
if catalog_integration.enabled:
|
||||
user = _get_service_user(user, catalog_integration.service_username)
|
||||
if not user:
|
||||
return []
|
||||
|
||||
api = create_catalog_api_client(user, catalog_integration)
|
||||
|
||||
cache_key = '{base}.programs{type}'.format(
|
||||
@@ -66,6 +83,46 @@ def get_programs(user, uuid=None, type=None): # pylint: disable=redefined-built
|
||||
return []
|
||||
|
||||
|
||||
def get_program_types(user=None): # pylint: disable=redefined-builtin
|
||||
"""Retrieve all program types from the catalog service.
|
||||
|
||||
Returns:
|
||||
list of dict, representing program types.
|
||||
"""
|
||||
catalog_integration = CatalogIntegration.current()
|
||||
if catalog_integration.enabled:
|
||||
user = _get_service_user(user, catalog_integration.service_username)
|
||||
if not user:
|
||||
return []
|
||||
|
||||
api = create_catalog_api_client(user, catalog_integration)
|
||||
cache_key = '{base}.program_types'.format(base=catalog_integration.CACHE_KEY)
|
||||
|
||||
return get_edx_api_data(
|
||||
catalog_integration,
|
||||
user,
|
||||
'program_types',
|
||||
cache_key=cache_key if catalog_integration.is_cache_enabled else None,
|
||||
api=api
|
||||
)
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
def get_programs_data(user=None):
|
||||
"""Return the list of Programs after adding the ProgramType Logo Image"""
|
||||
|
||||
programs_list = get_programs(user)
|
||||
program_types = get_program_types(user)
|
||||
|
||||
program_types_lookup_dict = {program_type["name"]: program_type for program_type in program_types}
|
||||
|
||||
for program in programs_list:
|
||||
program["logo_image"] = program_types_lookup_dict[program["type"]]["logo_image"]
|
||||
|
||||
return programs_list
|
||||
|
||||
|
||||
def munge_catalog_program(catalog_program):
|
||||
"""Make a program from the catalog service look like it came from the programs service.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user