Commit bc5daffc by AlasdairSwan

ECOM-4215 adding setup for new program details page

parent 91d04979
......@@ -20,3 +20,11 @@ class ProgramListingPage(PageObject):
def is_sidebar_present(self):
"""Check whether sidebar is present."""
return self.q(css='.sidebar').present
class ProgramDetailsPage(PageObject):
"""Program details page."""
url = BASE_URL + '/dashboard/programs/123'
def is_browser_on_page(self):
return self.q(css='.js-program-details-wrapper').present
......@@ -5,16 +5,15 @@ from ...fixtures.programs import FakeProgram, ProgramsFixture, ProgramsConfigMix
from ...fixtures.course import CourseFixture
from ..helpers import UniqueCourseTest
from ...pages.lms.auto_auth import AutoAuthPage
from ...pages.lms.programs import ProgramListingPage
from ...pages.lms.programs import ProgramListingPage, ProgramDetailsPage
class ProgramListingPageBase(ProgramsConfigMixin, UniqueCourseTest):
class ProgramPageBase(ProgramsConfigMixin, UniqueCourseTest):
"""Base class used for program listing page tests."""
def setUp(self):
super(ProgramListingPageBase, self).setUp()
super(ProgramPageBase, self).setUp()
self.set_programs_api_configuration(is_enabled=True)
self.listing_page = ProgramListingPage(self.browser)
def stub_api(self, course_id=None):
"""Stub out the programs API with fake data."""
......@@ -35,8 +34,13 @@ class ProgramListingPageBase(ProgramsConfigMixin, UniqueCourseTest):
AutoAuthPage(self.browser, course_id=course_id).visit()
class ProgramListingPageTest(ProgramListingPageBase):
class ProgramListingPageTest(ProgramPageBase):
"""Verify user-facing behavior of the program listing page."""
def setUp(self):
super(ProgramListingPageTest, self).setUp()
self.listing_page = ProgramListingPage(self.browser)
def test_no_enrollments(self):
"""Verify that no cards appear when the user has no enrollments."""
self.stub_api()
......@@ -76,8 +80,12 @@ class ProgramListingPageTest(ProgramListingPageBase):
@attr('a11y')
class ProgramListingPageA11yTest(ProgramListingPageBase):
class ProgramListingPageA11yTest(ProgramPageBase):
"""Test program listing page accessibility."""
def setUp(self):
super(ProgramListingPageA11yTest, self).setUp()
self.listing_page = ProgramListingPage(self.browser)
def test_empty_a11y(self):
"""Test a11y of the page's empty state."""
......@@ -100,3 +108,19 @@ class ProgramListingPageA11yTest(ProgramListingPageBase):
self.assertTrue(self.listing_page.are_cards_present)
self.listing_page.a11y_audit.check_for_accessibility_errors()
@attr('a11y')
class ProgramDetailsPageA11yTest(ProgramPageBase):
"""Test program details page accessibility."""
def setUp(self):
super(ProgramDetailsPageA11yTest, self).setUp()
self.details_page = ProgramDetailsPage(self.browser)
def test_a11y(self):
"""Test a11y of the page's state."""
self.auth(enroll=False)
self.details_page.visit()
self.details_page.a11y_audit.check_for_accessibility_errors()
......@@ -8,7 +8,7 @@ from urlparse import urljoin
from django.conf import settings
from django.core.urlresolvers import reverse
from django.test import override_settings
from django.test import override_settings, TestCase
from edx_oauth2_provider.tests.factories import ClientFactory
from opaque_keys.edx import locator
from provider.constants import CONFIDENTIAL
......@@ -205,3 +205,39 @@ class TestProgramListing(
for certificate in self._expected_credentials_data():
self.assertNotContains(response, certificate['display_name'])
self.assertNotContains(response, certificate['credential_url'])
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@override_settings(MKTG_URLS={'ROOT': 'http://edx.org'})
class TestProgramDetails(ProgramsApiConfigMixin, TestCase):
"""
Unit tests for the program details page
"""
def setUp(self):
super(TestProgramDetails, self).setUp()
self.user = UserFactory()
self.details_page = reverse('program_details_view', args=['123'])
def test_login_required(self):
"""
Verify that login is required to access the page.
"""
self.create_programs_config()
response = self.client.get(self.details_page)
self.assertRedirects(
response,
'{}?next={}'.format(reverse('signin_user'), self.details_page)
)
self.client.login(username=self.user.username, password='test')
response = self.client.get(self.details_page)
self.assertEquals(response.status_code, 200)
def test_404_if_disabled(self):
"""
Verify that the page 404s if disabled.
"""
self.create_programs_config(program_details_enabled=False)
self.client.login(username=self.user.username, password='test')
response = self.client.get(self.details_page)
self.assertEquals(response.status_code, 404)
......@@ -6,5 +6,6 @@ from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^programs/(?P<program_uuid>[0-9a-f-]+)/$', views.program_details, name='program_details_view'),
url(r'^programs/$', views.view_programs, name='program_listing_view'),
]
......@@ -45,3 +45,20 @@ def view_programs(request):
}
return render_to_response('learner_dashboard/programs.html', context)
@login_required
@require_GET
def program_details(request, program_uuid): # pylint: disable=unused-argument
"""View programs in which the user is engaged."""
show_program_details = ProgramsApiConfig.current().show_program_details
if not show_program_details:
raise Http404
context = {
'nav_hidden': True,
'disable_courseware_js': True,
'uses_pattern_library': True
}
return render_to_response('learner_dashboard/program_details.html', context)
;(function (define) {
'use strict';
define([
'js/learner_dashboard/views/program_details_view'
],
function(ProgramDetailsView) {
return function (options) {
var ProgramDetails = new ProgramDetailsView(options);
return ProgramDetails;
};
});
}).call(this, define || RequireJS.define);
;(function (define) {
'use strict';
define(['backbone',
'jquery',
'underscore',
'gettext',
'text!../../../templates/learner_dashboard/program_details_view.underscore'
],
function(
Backbone,
$,
_,
gettext,
pageTpl
) {
return Backbone.View.extend({
el: '.js-program-details-wrapper',
tpl: _.template(pageTpl),
initialize: function(data) {
this.context = data.context;
this.render();
},
render: function() {
this.$el.html(this.tpl(this.context));
this.postRender();
},
postRender: function() {
// Add subviews
}
});
}
);
}).call(this, define || RequireJS.define);
......@@ -35,6 +35,7 @@
'support/js/certificates_factory',
'support/js/enrollment_factory',
'js/bookmarks/bookmarks_factory',
'js/learner_dashboard/program_details_factory',
'js/learner_dashboard/program_list_factory',
'js/api_admin/catalog_preview_factory'
]),
......
## Override the default styles_version to the Pattern Library version (version 2)
<%! main_css = "style-learner-dashboard" %>
<%page expression_filter="h"/>
<%inherit file="../main.html" />
<%namespace name='static' file='../static_content.html'/>
<%!
from django.utils.translation import ugettext as _
from openedx.core.djangolib.js_utils import (
dump_js_escaped_json, js_escaped_string
)
%>
<%block name="js_extra">
<%static:require_module module_name="js/learner_dashboard/program_details_factory" class_name="ProgramDetailsFactory">
ProgramDetailsFactory({});
</%static:require_module>
</%block>
<%block name="pagetitle">${_("Program Details")}</%block>
<main id="main" aria-label="Content" tabindex="-1">
<div class="js-program-details-wrapper grid-container"></div>
</main>
<header class="program-header">
<div>
<h2 class="hd-2">Program Title</h2>
<p>Program Subtitle</p>
</div>
</header>
<div class="js-program-progress-view"></div>
<div class="js-course-list"></div>
<aside class="js-course-sidebar"></aside>
......@@ -85,7 +85,7 @@ site_status_msg = get_site_status_msg(course_id)
</a>
</li>
<li class="tab-nav-item">
<a class="${'active ' if reverse('program_listing_view') == request.path else ''}tab-nav-link" href="${reverse('program_listing_view')}">
<a class="${'active ' if reverse('program_listing_view') in request.path else ''}tab-nav-link" href="${reverse('program_listing_view')}">
${_("Programs")}
</a>
</li>
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('programs', '0007_programsapiconfig_program_listing_enabled'),
]
operations = [
migrations.AddField(
model_name='programsapiconfig',
name='program_details_enabled',
field=models.BooleanField(default=False, verbose_name='Do we want to show program details pages'),
),
]
......@@ -84,6 +84,11 @@ class ProgramsApiConfig(ConfigurationModel):
default=False
)
program_details_enabled = models.BooleanField(
verbose_name=_("Do we want to show program details pages"),
default=False
)
@property
def internal_api_url(self):
"""
......@@ -156,3 +161,10 @@ class ProgramsApiConfig(ConfigurationModel):
Indicates whether we want to show program listing page
"""
return self.enabled and self.program_listing_enabled
@property
def show_program_details(self):
"""
Indicates whether we want to show program details pages
"""
return self.enabled and self.program_details_enabled
......@@ -22,6 +22,7 @@ class ProgramsApiConfigMixin(object):
'enable_studio_tab': True,
'enable_certification': True,
'xseries_ad_enabled': True,
'program_details_enabled': True,
}
def create_programs_config(self, **kwargs):
......
......@@ -92,7 +92,7 @@ site_status_msg = get_site_status_msg(course_id)
</a>
</li>
<li class="tab-nav-item">
<a class="${'active ' if reverse('program_listing_view') == request.path else ''}tab-nav-link" href="${reverse('program_listing_view')}">
<a class="${'active ' if reverse('program_listing_view') in request.path else ''}tab-nav-link" href="${reverse('program_listing_view')}">
${_("Programs")}
</a>
</li>
......
......@@ -81,7 +81,7 @@ site_status_msg = get_site_status_msg(course_id)
</a>
</li>
<li class="tab-nav-item">
<a class="${'active ' if reverse('program_listing_view') == request.path else ''}tab-nav-link" href="${reverse('program_listing_view')}">
<a class="${'active ' if reverse('program_listing_view') in request.path else ''}tab-nav-link" href="${reverse('program_listing_view')}">
${_("Programs")}
</a>
</li>
......
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