Merge pull request #12575 from edx/renzo/program-detail-data

Include raw program data on the detail page
This commit is contained in:
Renzo Lucioni
2016-05-27 10:01:19 -04:00
4 changed files with 56 additions and 14 deletions

View File

@@ -2,6 +2,7 @@
Unit tests covering the program listing and detail pages.
"""
import datetime
import json
import unittest
from urlparse import urljoin
@@ -16,10 +17,11 @@ from provider.constants import CONFIDENTIAL
from openedx.core.djangoapps.credentials.models import CredentialsApiConfig
from openedx.core.djangoapps.credentials.tests import factories as credentials_factories
from openedx.core.djangoapps.credentials.tests.mixins import CredentialsDataMixin, CredentialsApiConfigMixin
from openedx.core.djangoapps.programs.models import ProgramsApiConfig
from openedx.core.djangoapps.programs.tests import factories
from openedx.core.djangoapps.programs.tests.mixins import (
ProgramsApiConfigMixin,
ProgramsDataMixin)
from openedx.core.djangoapps.programs.models import ProgramsApiConfig
from student.models import CourseEnrollment
from student.tests.factories import UserFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
@@ -226,25 +228,56 @@ class TestProgramListing(
self.assertNotContains(response, certificate['credential_url'])
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@httpretty.activate
@override_settings(MKTG_URLS={'ROOT': 'http://edx.org'})
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
class TestProgramDetails(ProgramsApiConfigMixin, TestCase):
"""
Unit tests for the program details page
"""
program_id = 123
password = 'test'
def setUp(self):
super(TestProgramDetails, self).setUp()
self.user = UserFactory()
self.details_page = reverse('program_details_view', args=['123'])
self.details_page = reverse('program_details_view', args=[self.program_id])
self.client.login(username=self.user.username, password='test')
self.user = UserFactory()
self.client.login(username=self.user.username, password=self.password)
ClientFactory(name=ProgramsApiConfig.OAUTH2_CLIENT_NAME, client_type=CONFIDENTIAL)
self.data = factories.Program(
organizations=[factories.Organization()],
course_codes=[
factories.CourseCode(run_modes=[factories.RunMode()]),
]
)
def _mock_programs_api(self):
"""Helper for mocking out Programs API URLs."""
self.assertTrue(httpretty.is_enabled(), msg='httpretty must be enabled to mock Programs API calls.')
url = '{api_root}/programs/{id}/'.format(
api_root=ProgramsApiConfig.current().internal_api_url.strip('/'),
id=self.program_id
)
body = json.dumps(self.data)
httpretty.register_uri(httpretty.GET, url, body=body, content_type='application/json')
def _assert_program_data_present(self, response):
"""Verify that program data is present."""
self.assertContains(response, 'programData')
self.assertContains(response, self.data['name'])
def test_login_required(self):
"""
Verify that login is required to access the page.
"""
self.create_programs_config()
self._mock_programs_api()
self.client.logout()
@@ -254,10 +287,10 @@ class TestProgramDetails(ProgramsApiConfigMixin, TestCase):
'{}?next={}'.format(reverse('signin_user'), self.details_page)
)
self.client.login(username=self.user.username, password='test')
self.client.login(username=self.user.username, password=self.password)
response = self.client.get(self.details_page)
self.assertEquals(response.status_code, 200)
self._assert_program_data_present(response)
def test_404_if_disabled(self):
"""
@@ -271,12 +304,13 @@ class TestProgramDetails(ProgramsApiConfigMixin, TestCase):
def test_page_routing(self):
"""Verify that the page can be hit with or without a program name in the URL."""
self.create_programs_config()
self._mock_programs_api()
response = self.client.get(self.details_page)
self.assertEquals(response.status_code, 200)
self._assert_program_data_present(response)
response = self.client.get(self.details_page + 'program_name/')
self.assertEquals(response.status_code, 200)
self._assert_program_data_present(response)
response = self.client.get(self.details_page + 'program_name/invalid/')
self.assertEquals(response.status_code, 404)

View File

@@ -9,7 +9,7 @@ from django.http import Http404
from edxmako.shortcuts import render_to_response
from openedx.core.djangoapps.credentials.utils import get_programs_credentials
from openedx.core.djangoapps.programs.models import ProgramsApiConfig
from openedx.core.djangoapps.programs.utils import ProgramProgressMeter, get_display_category
from openedx.core.djangoapps.programs.utils import ProgramProgressMeter, get_programs, get_display_category
from student.views import get_course_enrollments
@@ -50,13 +50,16 @@ def view_programs(request):
@login_required
@require_GET
def program_details(request, program_id): # pylint: disable=unused-argument
def program_details(request, program_id):
"""View details about a specific program."""
show_program_details = ProgramsApiConfig.current().show_program_details
if not show_program_details:
raise Http404
program_data = get_programs(request.user, program_id=program_id)
context = {
'program_data': program_data,
'nav_hidden': True,
'disable_courseware_js': True,
'uses_pattern_library': True

View File

@@ -13,7 +13,9 @@ from openedx.core.djangolib.js_utils import (
<%block name="js_extra">
<%static:require_module module_name="js/learner_dashboard/program_details_factory" class_name="ProgramDetailsFactory">
ProgramDetailsFactory({});
ProgramDetailsFactory({
programData: ${program_data | n, dump_js_escaped_json}
});
</%static:require_module>
</%block>

View File

@@ -10,7 +10,7 @@ from openedx.core.lib.edx_api_utils import get_edx_api_data
log = logging.getLogger(__name__)
def get_programs(user):
def get_programs(user, program_id=None):
"""Given a user, get programs from the Programs service.
Returned value is cached depending on user permissions. Staff users making requests
against Programs will receive unpublished programs, while regular users will only receive
@@ -19,6 +19,9 @@ def get_programs(user):
Arguments:
user (User): The user to authenticate as when requesting programs.
Keyword Arguments:
program_id (int): Identifies a specific program for which to retrieve data.
Returns:
list of dict, representing programs returned by the Programs service.
"""
@@ -27,7 +30,7 @@ def get_programs(user):
# Bypass caching for staff users, who may be creating Programs and want
# to see them displayed immediately.
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', cache_key=cache_key)
return get_edx_api_data(programs_config, user, 'programs', resource_id=program_id, cache_key=cache_key)
def flatten_programs(programs, course_ids):