Commit 92f3c7ee by Renzo Lucioni Committed by GitHub

Merge pull request #13112 from edx/release

Release
parents 6e01f532 66d4dc93
...@@ -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