Allow program listing page to display programs from any category

This work removes most references to XSeries from the LMS in an attempt to be more general. ECOM-5018.
This commit is contained in:
Renzo Lucioni
2016-07-25 15:38:50 -04:00
parent 92f3c7ee60
commit 8196e1a024
35 changed files with 159 additions and 269 deletions

View File

@@ -176,44 +176,9 @@ class TestCredentialsRetrieval(ProgramsApiConfigMixin, CredentialsApiConfigMixin
# Mocking the API responses from programs and credentials
self.mock_programs_api()
self.mock_credentials_api(self.user, reset_url=False)
actual = get_programs_credentials(self.user, category='xseries')
actual = get_programs_credentials(self.user)
expected = self.expected_credentials_display_data()
# Checking result is as expected
self.assertEqual(len(actual), 2)
self.assertEqual(actual, expected)
@httpretty.activate
def test_get_programs_credentials_category(self):
""" Verify behaviour when program category is provided."""
# create credentials and program configuration
self.create_credentials_config()
self.create_programs_config()
# Mocking the API responses from programs and credentials
self.mock_programs_api()
self.mock_credentials_api(self.user, reset_url=False)
actual = get_programs_credentials(self.user, category='dummy_category')
expected = self.expected_credentials_display_data()
self.assertEqual(len(actual), 0)
actual = get_programs_credentials(self.user, category='xseries')
self.assertEqual(len(actual), 2)
self.assertEqual(actual, expected)
@httpretty.activate
def test_get_programs_credentials_no_category(self):
""" Verify behaviour when no program category is provided. """
self.create_credentials_config()
self.create_programs_config()
# Mocking the API responses from programs and credentials
self.mock_programs_api()
self.mock_credentials_api(self.user, reset_url=False)
actual = get_programs_credentials(self.user)
expected = self.expected_credentials_display_data()
self.assertEqual(len(actual), 2)
self.assertEqual(actual, expected)

View File

@@ -66,7 +66,7 @@ def get_user_program_credentials(user):
return programs_credentials_data
def get_programs_credentials(user, category=None):
def get_programs_credentials(user):
"""Return program credentials data required for display.
Given a user, find all programs for which certificates have been earned
@@ -74,7 +74,6 @@ def get_programs_credentials(user, category=None):
Arguments:
user (User): user object for getting programs credentials.
category(str) : program category for getting credentials.
Returns:
list of dict, containing data corresponding to the programs for which
@@ -83,16 +82,14 @@ def get_programs_credentials(user, category=None):
programs_credentials = get_user_program_credentials(user)
credentials_data = []
for program in programs_credentials:
is_included = (category is None) or (program.get('category') == category)
if is_included:
try:
program_data = {
'display_name': program['name'],
'subtitle': program['subtitle'],
'credential_url': program['credential_url'],
}
credentials_data.append(program_data)
except KeyError:
log.warning('Program structure is invalid: %r', program)
try:
program_data = {
'display_name': program['name'],
'subtitle': program['subtitle'],
'credential_url': program['credential_url'],
}
credentials_data.append(program_data)
except KeyError:
log.warning('Program structure is invalid: %r', program)
return credentials_data

View File

@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('programs', '0008_programsapiconfig_program_details_enabled'),
]
operations = [
migrations.AddField(
model_name='programsapiconfig',
name='marketing_path',
field=models.CharField(help_text='Path used to construct URLs to programs marketing pages (e.g., "/foo").', max_length=255, blank=True),
),
]

View File

@@ -21,6 +21,14 @@ class ProgramsApiConfig(ConfigurationModel):
internal_service_url = models.URLField(verbose_name=_("Internal Service URL"))
public_service_url = models.URLField(verbose_name=_("Public Service URL"))
marketing_path = models.CharField(
max_length=255,
blank=True,
help_text=_(
'Path used to construct URLs to programs marketing pages (e.g., "/foo").'
)
)
# TODO: The property below is obsolete. Delete at the earliest safe moment. See ECOM-4995
authoring_app_js_path = models.CharField(
verbose_name=_("Path to authoring app's JS"),
@@ -73,6 +81,7 @@ class ProgramsApiConfig(ConfigurationModel):
)
)
# TODO: Remove unused field.
xseries_ad_enabled = models.BooleanField(
verbose_name=_("Do we want to show xseries program advertising"),
default=False
@@ -131,13 +140,6 @@ class ProgramsApiConfig(ConfigurationModel):
"""
return self.enabled and self.enable_certification
@property
def show_xseries_ad(self):
"""
Indicates whether we should show xseries add
"""
return self.enabled and self.xseries_ad_enabled
@property
def show_program_listing(self):
"""

View File

@@ -13,7 +13,7 @@ class Program(factory.Factory):
id = factory.Sequence(lambda n: n) # pylint: disable=invalid-name
name = FuzzyText(prefix='Program ')
subtitle = FuzzyText(prefix='Subtitle ')
category = 'xseries'
category = 'FooBar'
status = 'unpublished'
marketing_slug = FuzzyText(prefix='slug_')
organizations = []

View File

@@ -19,9 +19,9 @@ class ProgramsApiConfigMixin(object):
'enable_student_dashboard': True,
'enable_studio_tab': True,
'enable_certification': True,
'xseries_ad_enabled': True,
'program_listing_enabled': True,
'program_details_enabled': True,
'marketing_path': 'foo',
}
def create_programs_config(self, **kwargs):

View File

@@ -93,24 +93,6 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential
# Verify the API was actually hit (not the cache).
self.assertEqual(len(httpretty.httpretty.latest_requests), 1)
@ddt.data(True, False)
def test_get_programs_category_casing(self, is_detail):
"""Temporary. Verify that program categories are lowercased."""
self.create_programs_config()
program = factories.Program(category='camelCase')
if is_detail:
program_id = program['id']
self.mock_programs_api(data=program, program_id=program_id)
data = utils.get_programs(self.user, program_id=program_id)
self.assertEqual(data['category'], 'camelcase')
else:
self.mock_programs_api(data={'results': [program]})
data = utils.get_programs(self.user)
self.assertEqual(data[0]['category'], 'camelcase')
def test_get_programs_caching(self):
"""Verify that when enabled, the cache is used for non-staff users."""
self.create_programs_config(cache_ttl=1)
@@ -235,18 +217,6 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential
actual = utils.get_programs_for_credentials(self.user, credential_data)
self.assertEqual(actual, [])
def test_get_display_category_success(self):
self.create_programs_config()
self.mock_programs_api()
actual_programs = utils.get_programs(self.user)
for program in actual_programs:
expected = 'XSeries'
self.assertEqual(expected, utils.get_display_category(program))
def test_get_display_category_none(self):
self.assertEqual('', utils.get_display_category(None))
self.assertEqual('', utils.get_display_category({"id": "test"}))
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
class GetCompletedCoursesTestCase(TestCase):

View File

@@ -49,16 +49,7 @@ def get_programs(user, program_id=None):
# to see them displayed immediately.
cache_key = programs_config.CACHE_KEY if programs_config.is_cache_enabled and not user.is_staff else None
data = get_edx_api_data(programs_config, user, 'programs', resource_id=program_id, cache_key=cache_key)
# TODO: Temporary, to be removed once category names are cased for display. ECOM-5018.
if data and program_id:
data['category'] = data['category'].lower()
else:
for program in data:
program['category'] = program['category'].lower()
return data
return get_edx_api_data(programs_config, user, 'programs', resource_id=program_id, cache_key=cache_key)
def flatten_programs(programs, course_ids):
@@ -151,7 +142,7 @@ def get_program_detail_url(program, marketing_root):
Arguments:
program (dict): Representation of a program.
marketing_root (str): Root URL used to build links to XSeries marketing pages.
marketing_root (str): Root URL used to build links to program marketing pages.
Returns:
str, a link to program details
@@ -166,24 +157,6 @@ def get_program_detail_url(program, marketing_root):
return '{base}/{slug}'.format(base=base, slug=slug)
def get_display_category(program):
""" Given the program, return the category of the program for display
Arguments:
program (Program): The program to get the display category string from
Returns:
string, the category for display to the user.
Empty string if the program has no category or is null.
"""
display_candidate = ''
if program and program.get('category'):
if program.get('category') == 'xseries':
display_candidate = 'XSeries'
else:
display_candidate = program.get('category', '').capitalize()
return display_candidate
def get_completed_courses(student):
"""
Determine which courses have been completed by the user.