Merge pull request #10714 from edx/renzo/programs-authoring-page

Add a Studio view and template to host the Programs authoring app
This commit is contained in:
Renzo Lucioni
2015-12-03 12:12:23 -05:00
8 changed files with 140 additions and 17 deletions

View File

@@ -480,6 +480,7 @@ def course_listing(request):
'allow_course_reruns': settings.FEATURES.get('ALLOW_COURSE_RERUNS', True),
'is_programs_enabled': programs_config.is_studio_tab_enabled and request.user.is_staff,
'programs': programs,
'program_authoring_url': reverse('programs'),
})

View File

@@ -0,0 +1,40 @@
"""Programs views for use with Studio."""
from django.contrib.auth.decorators import login_required
from django.core.urlresolvers import reverse
from django.http import Http404
from django.utils.decorators import method_decorator
from django.views.generic import View
from edxmako.shortcuts import render_to_response
from openedx.core.djangoapps.programs.models import ProgramsApiConfig
class ProgramAuthoringView(View):
"""View rendering a template which hosts the Programs authoring app.
The Programs authoring app is a Backbone SPA maintained in a separate repository.
The app handles its own routing and provides a UI which can be used to create and
publish new Programs (e.g, XSeries).
"""
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
"""Relays requests to matching methods.
Decorated to require login before accessing the authoring app.
"""
return super(ProgramAuthoringView, self).dispatch(*args, **kwargs)
def get(self, request, *args, **kwargs):
"""Populate the template context with values required for the authoring app to run."""
programs_config = ProgramsApiConfig.current()
if programs_config.is_studio_tab_enabled and request.user.is_staff:
return render_to_response('program_authoring.html', {
'show_programs_header': programs_config.is_studio_tab_enabled,
'authoring_app_config': programs_config.authoring_app_config,
'programs_api_url': programs_config.public_api_url,
'studio_home_url': reverse('home'),
})
else:
raise Http404

View File

@@ -1,4 +1,5 @@
"""Tests covering the Programs listing on the Studio home."""
from django.conf import settings
from django.core.urlresolvers import reverse
import httpretty
from oauth2_provider.tests.factories import ClientFactory
@@ -17,8 +18,8 @@ class TestProgramListing(ProgramsApiConfigMixin, ProgramsDataMixin, ModuleStoreT
ClientFactory(name=ProgramsApiConfig.OAUTH2_CLIENT_NAME, client_type=CONFIDENTIAL)
self.user = UserFactory(is_staff=True)
self.client.login(username=self.user.username, password='test')
self.staff = UserFactory(is_staff=True)
self.client.login(username=self.staff.username, password='test')
self.studio_home = reverse('home')
@@ -37,9 +38,12 @@ class TestProgramListing(ProgramsApiConfigMixin, ProgramsDataMixin, ModuleStoreT
@httpretty.activate
def test_programs_requires_staff(self):
"""Verify that the programs tab and creation button aren't rendered unless the user has global staff."""
self.user = UserFactory(is_staff=False)
self.client.login(username=self.user.username, password='test')
"""
Verify that the programs tab and creation button aren't rendered unless the user has
global staff permissions.
"""
student = UserFactory(is_staff=False)
self.client.login(username=student.username, password='test')
self.create_config()
self.mock_programs_api()
@@ -64,3 +68,53 @@ class TestProgramListing(ProgramsApiConfigMixin, ProgramsDataMixin, ModuleStoreT
response = self.client.get(self.studio_home)
for program_name in self.PROGRAM_NAMES:
self.assertIn(program_name, response.content)
class TestProgramAuthoringView(ProgramsApiConfigMixin, ModuleStoreTestCase):
"""Verify the behavior of the program authoring app's host view."""
def setUp(self):
super(TestProgramAuthoringView, self).setUp()
self.staff = UserFactory(is_staff=True)
self.programs_path = reverse('programs')
def _assert_status(self, status_code):
"""Verify the status code returned by the Program authoring view."""
response = self.client.get(self.programs_path)
self.assertEquals(response.status_code, status_code)
return response
def test_authoring_login_required(self):
"""Verify that accessing the view requires the user to be authenticated."""
response = self.client.get(self.programs_path)
self.assertRedirects(
response,
'{login_url}?next={programs}'.format(
login_url=settings.LOGIN_URL,
programs=self.programs_path
)
)
def test_authoring_header(self):
"""Verify that the header contains the expected text."""
self.client.login(username=self.staff.username, password='test')
self.create_config()
response = self._assert_status(200)
self.assertIn("Program Administration", response.content)
def test_authoring_access(self):
"""
Verify that a 404 is returned if Programs authoring is disabled, or the user does not have
global staff permissions.
"""
self.client.login(username=self.staff.username, password='test')
self._assert_status(404)
# Enable Programs authoring interface
self.create_config()
student = UserFactory(is_staff=False)
self.client.login(username=student.username, password='test')
self._assert_status(404)