Commit b5409684 by Renzo Lucioni

Updates to facilitate program category casing changes

The LMS continues to expect lowercased category slugs, while the Studio program creator now uses correctly cased slugs. Programs should be updated before this is released. Part of ECOM-5018.
parent 20cbc62c
...@@ -24,7 +24,8 @@ define([ ...@@ -24,7 +24,8 @@ define([
}, },
category: { category: {
required: true, required: true,
oneOf: ['xseries', 'micromasters'] // TODO: Populate with the results of an API call for valid categories.
oneOf: ['XSeries', 'MicroMasters']
}, },
organizations: 'validateOrganizations', organizations: 'validateOrganizations',
marketing_slug: { marketing_slug: {
......
...@@ -77,7 +77,7 @@ define([ ...@@ -77,7 +77,7 @@ define([
spyOn( Router.prototype, 'goHome' ); spyOn( Router.prototype, 'goHome' );
sampleInput = { sampleInput = {
category: 'xseries', category: 'XSeries',
organizations: 'test-org-key', organizations: 'test-org-key',
name: 'Test Course Name', name: 'Test Course Name',
subtitle: 'Test Course Subtitle', subtitle: 'Test Course Subtitle',
...@@ -131,7 +131,7 @@ define([ ...@@ -131,7 +131,7 @@ define([
it( 'should submit the form correctly when creating micromasters program ', function(){ it( 'should submit the form correctly when creating micromasters program ', function(){
var programId = 221; var programId = 221;
sampleInput.category = 'micromasters'; sampleInput.category = 'MicroMasters';
completeForm( sampleInput ); completeForm( sampleInput );
......
...@@ -86,7 +86,7 @@ define([ ...@@ -86,7 +86,7 @@ define([
} }
], ],
programData = { programData = {
category: 'xseries', category: 'XSeries',
course_codes: [{ course_codes: [{
display_name: 'test-course-display_name', display_name: 'test-course-display_name',
key: 'test-course-key', key: 'test-course-key',
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
<label class="field-label" for="program-type"><%- gettext('Program type') %></label> <label class="field-label" for="program-type"><%- gettext('Program type') %></label>
<select id="program-type" class="field-input input-select program-type" name="category"> <select id="program-type" class="field-input input-select program-type" name="category">
<option value=""><%- gettext('Select a type') %></option> <option value=""><%- gettext('Select a type') %></option>
<option value="xseries"><%- gettext('XSeries') %></option> <option value="XSeries"><%- gettext('XSeries') %></option>
<option value="micromasters"><%- gettext('MicroMasters') %></option> <option value="MicroMasters"><%- gettext('MicroMasters') %></option>
</select> </select>
<div class="field-message"> <div class="field-message">
<span class="field-message-content"></span> <span class="field-message-content"></span>
......
...@@ -99,11 +99,13 @@ class ProgramsDataMixin(object): ...@@ -99,11 +99,13 @@ class ProgramsDataMixin(object):
] ]
} }
def mock_programs_api(self, data=None, status_code=200): def mock_programs_api(self, data=None, program_id='', status_code=200):
"""Utility for mocking out Programs API URLs.""" """Utility for mocking out Programs API URLs."""
self.assertTrue(httpretty.is_enabled(), msg='httpretty must be enabled to mock Programs API calls.') self.assertTrue(httpretty.is_enabled(), msg='httpretty must be enabled to mock Programs API calls.')
url = ProgramsApiConfig.current().internal_api_url.strip('/') + '/programs/' url = ProgramsApiConfig.current().internal_api_url.strip('/') + '/programs/'
if program_id:
url += '{}/'.format(str(program_id))
if data is None: if data is None:
data = self.PROGRAMS_API_RESPONSE data = self.PROGRAMS_API_RESPONSE
......
...@@ -40,8 +40,10 @@ ECOMMERCE_URL_ROOT = 'https://example-ecommerce.com' ...@@ -40,8 +40,10 @@ ECOMMERCE_URL_ROOT = 'https://example-ecommerce.com'
MARKETING_URL = 'https://www.example.com/marketing/path' MARKETING_URL = 'https://www.example.com/marketing/path'
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @ddt.ddt
@attr('shard_2') @attr('shard_2')
@httpretty.activate
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, CredentialsDataMixin, class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, CredentialsDataMixin,
CredentialsApiConfigMixin, CacheIsolationTestCase): CredentialsApiConfigMixin, CacheIsolationTestCase):
"""Tests covering the retrieval of programs from the Programs service.""" """Tests covering the retrieval of programs from the Programs service."""
...@@ -77,7 +79,6 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential ...@@ -77,7 +79,6 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential
) )
] ]
@httpretty.activate
def test_get_programs(self): def test_get_programs(self):
"""Verify programs data can be retrieved.""" """Verify programs data can be retrieved."""
self.create_programs_config() self.create_programs_config()
...@@ -92,7 +93,24 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential ...@@ -92,7 +93,24 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential
# Verify the API was actually hit (not the cache). # Verify the API was actually hit (not the cache).
self.assertEqual(len(httpretty.httpretty.latest_requests), 1) self.assertEqual(len(httpretty.httpretty.latest_requests), 1)
@httpretty.activate @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): def test_get_programs_caching(self):
"""Verify that when enabled, the cache is used for non-staff users.""" """Verify that when enabled, the cache is used for non-staff users."""
self.create_programs_config(cache_ttl=1) self.create_programs_config(cache_ttl=1)
...@@ -133,7 +151,6 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential ...@@ -133,7 +151,6 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential
self.assertEqual(actual, []) self.assertEqual(actual, [])
self.assertTrue(mock_init.called) self.assertTrue(mock_init.called)
@httpretty.activate
def test_get_programs_data_retrieval_failure(self): def test_get_programs_data_retrieval_failure(self):
"""Verify behavior when data can't be retrieved from Programs.""" """Verify behavior when data can't be retrieved from Programs."""
self.create_programs_config() self.create_programs_config()
...@@ -142,7 +159,6 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential ...@@ -142,7 +159,6 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential
actual = utils.get_programs(self.user) actual = utils.get_programs(self.user)
self.assertEqual(actual, []) self.assertEqual(actual, [])
@httpretty.activate
def test_get_programs_for_dashboard(self): def test_get_programs_for_dashboard(self):
"""Verify programs data can be retrieved and parsed correctly.""" """Verify programs data can be retrieved and parsed correctly."""
self.create_programs_config() self.create_programs_config()
...@@ -165,7 +181,6 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential ...@@ -165,7 +181,6 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential
actual = utils.get_programs_for_dashboard(self.user, self.COURSE_KEYS) actual = utils.get_programs_for_dashboard(self.user, self.COURSE_KEYS)
self.assertEqual(actual, {}) self.assertEqual(actual, {})
@httpretty.activate
def test_get_programs_for_dashboard_no_data(self): def test_get_programs_for_dashboard_no_data(self):
"""Verify behavior when no programs data is found for the user.""" """Verify behavior when no programs data is found for the user."""
self.create_programs_config() self.create_programs_config()
...@@ -174,17 +189,6 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential ...@@ -174,17 +189,6 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential
actual = utils.get_programs_for_dashboard(self.user, self.COURSE_KEYS) actual = utils.get_programs_for_dashboard(self.user, self.COURSE_KEYS)
self.assertEqual(actual, {}) self.assertEqual(actual, {})
@httpretty.activate
def test_get_programs_for_dashboard_invalid_data(self):
"""Verify behavior when the Programs API returns invalid data and parsing fails."""
self.create_programs_config()
invalid_program = {'invalid_key': 'invalid_data'}
self.mock_programs_api(data={'results': [invalid_program]})
actual = utils.get_programs_for_dashboard(self.user, self.COURSE_KEYS)
self.assertEqual(actual, {})
@httpretty.activate
def test_get_program_for_certificates(self): def test_get_program_for_certificates(self):
"""Verify programs data can be retrieved and parsed correctly for certificates.""" """Verify programs data can be retrieved and parsed correctly for certificates."""
self.create_programs_config() self.create_programs_config()
...@@ -199,7 +203,6 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential ...@@ -199,7 +203,6 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential
self.assertEqual(len(actual), 2) self.assertEqual(len(actual), 2)
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
@httpretty.activate
def test_get_program_for_certificates_no_data(self): def test_get_program_for_certificates_no_data(self):
"""Verify behavior when no programs data is found for the user.""" """Verify behavior when no programs data is found for the user."""
self.create_programs_config() self.create_programs_config()
...@@ -210,7 +213,6 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential ...@@ -210,7 +213,6 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential
actual = utils.get_programs_for_credentials(self.user, program_credentials_data) actual = utils.get_programs_for_credentials(self.user, program_credentials_data)
self.assertEqual(actual, []) self.assertEqual(actual, [])
@httpretty.activate
def test_get_program_for_certificates_id_not_exist(self): def test_get_program_for_certificates_id_not_exist(self):
"""Verify behavior when no program with the given program_id in """Verify behavior when no program with the given program_id in
credentials exists. credentials exists.
...@@ -233,7 +235,6 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential ...@@ -233,7 +235,6 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin, Credential
actual = utils.get_programs_for_credentials(self.user, credential_data) actual = utils.get_programs_for_credentials(self.user, credential_data)
self.assertEqual(actual, []) self.assertEqual(actual, [])
@httpretty.activate
def test_get_display_category_success(self): def test_get_display_category_success(self):
self.create_programs_config() self.create_programs_config()
self.mock_programs_api() self.mock_programs_api()
......
...@@ -48,7 +48,17 @@ def get_programs(user, program_id=None): ...@@ -48,7 +48,17 @@ def get_programs(user, program_id=None):
# Bypass caching for staff users, who may be creating Programs and want # Bypass caching for staff users, who may be creating Programs and want
# to see them displayed immediately. # to see them displayed immediately.
cache_key = programs_config.CACHE_KEY if programs_config.is_cache_enabled and not user.is_staff else None cache_key = programs_config.CACHE_KEY if programs_config.is_cache_enabled and not user.is_staff else None
return get_edx_api_data(programs_config, user, 'programs', resource_id=program_id, cache_key=cache_key)
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
def flatten_programs(programs, course_ids): def flatten_programs(programs, course_ids):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment