Commit a7d036f9 by AlasdairSwan

Merge pull request #12613 from edx/release

Release 1st June 2016
parents 16bf044e 81d2c75d
...@@ -267,7 +267,7 @@ EMAIL_HOST_USER = AUTH_TOKENS.get('EMAIL_HOST_USER', EMAIL_HOST_USER) ...@@ -267,7 +267,7 @@ EMAIL_HOST_USER = AUTH_TOKENS.get('EMAIL_HOST_USER', EMAIL_HOST_USER)
EMAIL_HOST_PASSWORD = AUTH_TOKENS.get('EMAIL_HOST_PASSWORD', EMAIL_HOST_PASSWORD) EMAIL_HOST_PASSWORD = AUTH_TOKENS.get('EMAIL_HOST_PASSWORD', EMAIL_HOST_PASSWORD)
AWS_SES_REGION_NAME = ENV_TOKENS.get('AWS_SES_REGION_NAME', 'us-east-1') AWS_SES_REGION_NAME = ENV_TOKENS.get('AWS_SES_REGION_NAME', 'us-east-1')
AWS_SES_REGION_ENDPOINT = ENV_TOKENS.get('AWS_SES_REGION_ENDPOINT', 'email-smtp.us-east-1.amazonaws.com') AWS_SES_REGION_ENDPOINT = ENV_TOKENS.get('AWS_SES_REGION_ENDPOINT', 'email.us-east-1.amazonaws.com')
# Note that this is the Studio key for Segment. There is a separate key for the LMS. # Note that this is the Studio key for Segment. There is a separate key for the LMS.
CMS_SEGMENT_KEY = AUTH_TOKENS.get('SEGMENT_KEY') CMS_SEGMENT_KEY = AUTH_TOKENS.get('SEGMENT_KEY')
......
...@@ -20,6 +20,7 @@ from edxmako.tests import mako_middleware_process_request ...@@ -20,6 +20,7 @@ from edxmako.tests import mako_middleware_process_request
from external_auth.models import ExternalAuthMap from external_auth.models import ExternalAuthMap
import student import student
from student.models import UserAttribute from student.models import UserAttribute
from student.views import REGISTRATION_AFFILIATE_ID
TEST_CS_URL = 'https://comments.service.test:123/' TEST_CS_URL = 'https://comments.service.test:123/'
...@@ -288,14 +289,14 @@ class TestCreateAccount(TestCase): ...@@ -288,14 +289,14 @@ class TestCreateAccount(TestCase):
affiliate_id = 'test-partner' affiliate_id = 'test-partner'
self.client.cookies[settings.AFFILIATE_COOKIE_NAME] = affiliate_id self.client.cookies[settings.AFFILIATE_COOKIE_NAME] = affiliate_id
user = self.create_account_and_fetch_profile().user user = self.create_account_and_fetch_profile().user
self.assertEqual(UserAttribute.get_user_attribute(user, settings.AFFILIATE_COOKIE_NAME), affiliate_id) self.assertEqual(UserAttribute.get_user_attribute(user, REGISTRATION_AFFILIATE_ID), affiliate_id)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
def test_no_referral(self): def test_no_referral(self):
"""Verify that no referral is recorded when a cookie is not present.""" """Verify that no referral is recorded when a cookie is not present."""
self.assertIsNone(self.client.cookies.get(settings.AFFILIATE_COOKIE_NAME)) # pylint: disable=no-member self.assertIsNone(self.client.cookies.get(settings.AFFILIATE_COOKIE_NAME)) # pylint: disable=no-member
user = self.create_account_and_fetch_profile().user user = self.create_account_and_fetch_profile().user
self.assertIsNone(UserAttribute.get_user_attribute(user, settings.AFFILIATE_COOKIE_NAME)) self.assertIsNone(UserAttribute.get_user_attribute(user, REGISTRATION_AFFILIATE_ID))
@ddt.ddt @ddt.ddt
......
...@@ -133,6 +133,8 @@ log = logging.getLogger("edx.student") ...@@ -133,6 +133,8 @@ log = logging.getLogger("edx.student")
AUDIT_LOG = logging.getLogger("audit") AUDIT_LOG = logging.getLogger("audit")
ReverifyInfo = namedtuple('ReverifyInfo', 'course_id course_name course_number date status display') # pylint: disable=invalid-name ReverifyInfo = namedtuple('ReverifyInfo', 'course_id course_name course_number date status display') # pylint: disable=invalid-name
SETTING_CHANGE_INITIATED = 'edx.user.settings.change_initiated' SETTING_CHANGE_INITIATED = 'edx.user.settings.change_initiated'
# Used as the name of the user attribute for tracking affiliate registrations
REGISTRATION_AFFILIATE_ID = 'registration_affiliate_id'
# Disable this warning because it doesn't make sense to completely refactor tests to appease Pylint # Disable this warning because it doesn't make sense to completely refactor tests to appease Pylint
# pylint: disable=logging-format-interpolation # pylint: disable=logging-format-interpolation
...@@ -1861,7 +1863,7 @@ def _record_registration_attribution(request, user): ...@@ -1861,7 +1863,7 @@ def _record_registration_attribution(request, user):
""" """
affiliate_id = request.COOKIES.get(settings.AFFILIATE_COOKIE_NAME) affiliate_id = request.COOKIES.get(settings.AFFILIATE_COOKIE_NAME)
if user is not None and affiliate_id is not None: if user is not None and affiliate_id is not None:
UserAttribute.set_user_attribute(user, settings.AFFILIATE_COOKIE_NAME, affiliate_id) UserAttribute.set_user_attribute(user, REGISTRATION_AFFILIATE_ID, affiliate_id)
@csrf_exempt @csrf_exempt
......
...@@ -535,8 +535,6 @@ ...@@ -535,8 +535,6 @@
.speed-option, .speed-option,
.control-lang { .control-lang {
@include border-left($baseline/10 solid rgb(14, 166, 236));
font-weight: $font-bold;
color: rgb(14, 166, 236); // UXPL primary accent color: rgb(14, 166, 236); // UXPL primary accent
} }
} }
......
...@@ -266,7 +266,6 @@ ...@@ -266,7 +266,6 @@
expect($('.closed-captions')).toHaveAttrs({ expect($('.closed-captions')).toHaveAttrs({
'lang': 'de' 'lang': 'de'
}); });
expect(link).toHaveAttr('aria-pressed', 'true');
}); });
it('when clicking on link with current language', function () { it('when clicking on link with current language', function () {
...@@ -285,7 +284,6 @@ ...@@ -285,7 +284,6 @@
expect(state.storage.setItem) expect(state.storage.setItem)
.not.toHaveBeenCalledWith('language', 'en'); .not.toHaveBeenCalledWith('language', 'en');
expect($('.langs-list li.is-active').length).toBe(1); expect($('.langs-list li.is-active').length).toBe(1);
expect(link).toHaveAttr('aria-pressed', 'true');
}); });
it('open the language toggle on hover', function () { it('open the language toggle on hover', function () {
......
...@@ -203,18 +203,16 @@ ...@@ -203,18 +203,16 @@
describe('onSpeedChange', function () { describe('onSpeedChange', function () {
beforeEach(function () { beforeEach(function () {
state = jasmine.initializePlayer(); state = jasmine.initializePlayer();
$('li[data-speed="1.0"]').addClass('is-active').attr('aria-pressed', 'true'); $('li[data-speed="1.0"]').addClass('is-active');
state.videoSpeedControl.setSpeed(0.75); state.videoSpeedControl.setSpeed(0.75);
}); });
it('set the new speed as active', function () { it('set the new speed as active', function () {
expect($('li[data-speed="1.0"]')).not.toHaveClass('is-active'); expect($('.video-speeds li[data-speed="1.0"]'))
expect($('li[data-speed="1.0"] .speed-option').attr('aria-pressed')).not.toEqual('true'); .not.toHaveClass('is-active');
expect($('.video-speeds li[data-speed="0.75"]'))
expect($('li[data-speed="0.75"]')).toHaveClass('is-active'); .toHaveClass('is-active');
expect($('li[data-speed="0.75"] .speed-option').attr('aria-pressed')).toEqual('true'); expect($('.speeds .value')).toHaveHtml('0.75x');
expect($('.speeds .speed-button .value')).toHaveHtml('0.75x');
}); });
}); });
......
...@@ -95,15 +95,14 @@ function (Iterator) { ...@@ -95,15 +95,14 @@ function (Iterator) {
* Creates any necessary DOM elements, attach them, and set their, * Creates any necessary DOM elements, attach them, and set their,
* initial configuration. * initial configuration.
* @param {array} speeds List of speeds available for the player. * @param {array} speeds List of speeds available for the player.
* @param {string} currentSpeed The current speed set to the player.
*/ */
render: function (speeds, currentSpeed) { render: function (speeds) {
var speedsContainer = this.speedsContainer, var speedsContainer = this.speedsContainer,
reversedSpeeds = speeds.concat().reverse(), reversedSpeeds = speeds.concat().reverse(),
speedsList = $.map(reversedSpeeds, function (speed) { speedsList = $.map(reversedSpeeds, function (speed) {
return [ return [
'<li data-speed="', speed, '">', '<li data-speed="', speed, '">',
'<button class="control speed-option" tabindex="-1" aria-pressed="false">', '<button class="control speed-option" tabindex="-1">',
speed, 'x', speed, 'x',
'</button>', '</button>',
'</li>' '</li>'
...@@ -113,7 +112,6 @@ function (Iterator) { ...@@ -113,7 +112,6 @@ function (Iterator) {
speedsContainer.html(speedsList.join('')); speedsContainer.html(speedsList.join(''));
this.speedLinks = new Iterator(speedsContainer.find('.speed-option')); this.speedLinks = new Iterator(speedsContainer.find('.speed-option'));
this.state.el.find('.secondary-controls').prepend(this.el); this.state.el.find('.secondary-controls').prepend(this.el);
this.setActiveSpeed(currentSpeed);
}, },
/** /**
...@@ -218,38 +216,17 @@ function (Iterator) { ...@@ -218,38 +216,17 @@ function (Iterator) {
if (speed !== this.currentSpeed || forceUpdate) { if (speed !== this.currentSpeed || forceUpdate) {
this.speedsContainer this.speedsContainer
.find('li') .find('li')
.siblings("li[data-speed='" + speed + "']"); .removeClass('is-active')
.siblings("li[data-speed='" + speed + "']")
.addClass('is-active');
this.speedButton.find('.value').text(speed + 'x'); this.speedButton.find('.value').html(speed + 'x');
this.currentSpeed = speed; this.currentSpeed = speed;
if (!silent) { if (!silent) {
this.el.trigger('speedchange', [speed, this.state.speed]); this.el.trigger('speedchange', [speed, this.state.speed]);
} }
} }
this.resetActiveSpeed();
this.setActiveSpeed(speed);
},
resetActiveSpeed: function() {
var speedOptions = this.speedsContainer.find('li');
$(speedOptions).each(function(index, el) {
$(el).removeClass('is-active')
.find('.speed-option')
.attr('aria-pressed', 'false');
});
},
setActiveSpeed: function(speed) {
var speedOption = this.speedsContainer.find('li[data-speed="' + speed + '"]');
speedOption.addClass('is-active')
.find('.speed-option')
.attr('aria-pressed', 'true');
this.speedButton.attr('title', gettext('Video speed: ') + speed + 'x');
}, },
/** /**
...@@ -267,13 +244,10 @@ function (Iterator) { ...@@ -267,13 +244,10 @@ function (Iterator) {
* @param {jquery Event} event * @param {jquery Event} event
*/ */
clickLinkHandler: function (event) { clickLinkHandler: function (event) {
var el = $(event.currentTarget).parent(), var speed = $(event.currentTarget).parent().data('speed');
speed = $(el).data('speed');
this.closeMenu();
this.resetActiveSpeed();
this.setActiveSpeed(speed);
this.state.videoCommands.execute('speed', speed); this.state.videoCommands.execute('speed', speed);
this.closeMenu(true);
return false; return false;
}, },
......
...@@ -662,11 +662,10 @@ ...@@ -662,11 +662,10 @@
$.each(languages, function(code, label) { $.each(languages, function(code, label) {
var li = $('<li data-lang-code="' + code + '" />'), var li = $('<li data-lang-code="' + code + '" />'),
link = $('<button class="control control-lang" aria-pressed="false">' + label + '</button>'); link = $('<button class="control control-lang">' + label + '</button>');
if (currentLang === code) { if (currentLang === code) {
li.addClass('is-active'); li.addClass('is-active');
link.attr('aria-pressed', 'true');
} }
li.append(link); li.append(link);
...@@ -684,11 +683,7 @@ ...@@ -684,11 +683,7 @@
state.lang = langCode; state.lang = langCode;
el .addClass('is-active') el .addClass('is-active')
.siblings('li') .siblings('li')
.removeClass('is-active') .removeClass('is-active');
.find('.control-lang')
.attr('aria-pressed', 'false');
$(e.currentTarget).attr('aria-pressed', 'true');
state.el.trigger('language_menu:change', [langCode]); state.el.trigger('language_menu:change', [langCode]);
self.fetchCaption(); self.fetchCaption();
...@@ -698,7 +693,6 @@ ...@@ -698,7 +693,6 @@
// update the transcript lang attribute // update the transcript lang attribute
self.subtitlesMenuEl.attr('lang', langCode); self.subtitlesMenuEl.attr('lang', langCode);
self.closeLanguageMenu(e);
} }
}); });
}, },
...@@ -721,7 +715,7 @@ ...@@ -721,7 +715,7 @@
'data-index': index, 'data-index': index,
'data-start': start[index], 'data-start': start[index],
'tabindex': 0 'tabindex': 0
}).text(text); }).html(text);
return liEl[0]; return liEl[0];
}; };
......
...@@ -174,12 +174,6 @@ class DashboardPage(PageObject): ...@@ -174,12 +174,6 @@ class DashboardPage(PageObject):
""" """
self.q(css='.dropdown').first.click() self.q(css='.dropdown').first.click()
def click_username(self):
"""
Click username.
"""
self.q(css='.label-username').first.click()
@property @property
def username_dropdown_link_text(self): def username_dropdown_link_text(self):
""" """
......
...@@ -266,17 +266,21 @@ class OwnLearnerProfilePageTest(LearnerProfileTestMixin, WebAppTest): ...@@ -266,17 +266,21 @@ class OwnLearnerProfilePageTest(LearnerProfileTestMixin, WebAppTest):
def test_dashboard_learner_profile_link(self): def test_dashboard_learner_profile_link(self):
""" """
Scenario: Verify that when user click on username it will leads to profile page. Scenario: Verify that my profile link is present on dashboard page and we can navigate to correct page.
Given that I am a registered user. Given that I am a registered user.
When I go to Dashboard page. When I go to Dashboard page.
And I click on username. And I click on username dropdown.
Then I see Profile link in the dropdown menu.
When I click on Profile link.
Then I will be navigated to Profile page. Then I will be navigated to Profile page.
""" """
username, user_id = self.log_in_as_unique_user() username, user_id = self.log_in_as_unique_user()
dashboard_page = DashboardPage(self.browser) dashboard_page = DashboardPage(self.browser)
dashboard_page.visit() dashboard_page.visit()
dashboard_page.click_username() dashboard_page.click_username_dropdown()
self.assertIn('Profile', dashboard_page.username_dropdown_link_text)
dashboard_page.click_my_profile_link()
my_profile_page = LearnerProfilePage(self.browser, username) my_profile_page = LearnerProfilePage(self.browser, username)
my_profile_page.wait_for_page() my_profile_page.wait_for_page()
......
...@@ -450,7 +450,7 @@ class ViewsTestCase(ModuleStoreTestCase): ...@@ -450,7 +450,7 @@ class ViewsTestCase(ModuleStoreTestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertIn(in_cart_span, response.content) self.assertIn(in_cart_span, response.content)
def assert_enrollment_link_present(self, is_anonymous, _id=False): def assert_enrollment_link_present(self, is_anonymous):
""" """
Prepare ecommerce checkout data and assert if the ecommerce link is contained in the response. Prepare ecommerce checkout data and assert if the ecommerce link is contained in the response.
...@@ -474,17 +474,13 @@ class ViewsTestCase(ModuleStoreTestCase): ...@@ -474,17 +474,13 @@ class ViewsTestCase(ModuleStoreTestCase):
# Set up the edxmako middleware for this request to create the RequestContext # Set up the edxmako middleware for this request to create the RequestContext
mako_middleware_process_request(request) mako_middleware_process_request(request)
# Construct the link for each of the four possibilities: # Generate the course about page content
# (1) shopping cart is disabled and the user is not logged in
# (2) shopping cart is disabled and the user is logged in
# (3) shopping cart is enabled and the user is not logged in
# (4) shopping cart is enabled and the user is logged in
href = '<a href="{}?{}" class="add-to-cart"{}'.format(
checkout_page,
'sku=TEST123',
' id="">' if _id else ">"
)
response = views.course_about(request, unicode(course.id)) response = views.course_about(request, unicode(course.id))
# Construct the link according the following scenarios and verify its presence in the response:
# (1) shopping cart is enabled and the user is not logged in
# (2) shopping cart is enabled and the user is logged in
href = '<a href="{uri_stem}?sku={sku}" class="add-to-cart">'.format(uri_stem=checkout_page, sku=sku)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertIn(href, response.content) self.assertIn(href, response.content)
...@@ -500,8 +496,13 @@ class ViewsTestCase(ModuleStoreTestCase): ...@@ -500,8 +496,13 @@ class ViewsTestCase(ModuleStoreTestCase):
@unittest.skipUnless(settings.FEATURES.get('ENABLE_SHOPPING_CART'), 'Shopping Cart not enabled in settings') @unittest.skipUnless(settings.FEATURES.get('ENABLE_SHOPPING_CART'), 'Shopping Cart not enabled in settings')
@patch.dict(settings.FEATURES, {'ENABLE_PAID_COURSE_REGISTRATION': True}) @patch.dict(settings.FEATURES, {'ENABLE_PAID_COURSE_REGISTRATION': True})
def test_ecommerce_checkout_shopping_cart_enabled(self, is_anonymous): def test_ecommerce_checkout_shopping_cart_enabled(self, is_anonymous):
"""
Two scenarios are being validated here -- authenticated/known user and unauthenticated/anonymous user
For a known user we expect the checkout link to point to Otto in a scenario where the CommerceConfiguration
is active and the course mode is PROFESSIONAL.
"""
if not is_anonymous: if not is_anonymous:
self.assert_enrollment_link_present(is_anonymous=is_anonymous, _id=True) self.assert_enrollment_link_present(is_anonymous=is_anonymous)
else: else:
request = self.request_factory.get("foo") request = self.request_factory.get("foo")
self.assertEqual(EcommerceService().is_enabled(AnonymousUser()), False) self.assertEqual(EcommerceService().is_enabled(AnonymousUser()), False)
......
...@@ -575,15 +575,17 @@ def course_about(request, course_id): ...@@ -575,15 +575,17 @@ def course_about(request, course_id):
# If the ecommerce checkout flow is enabled and the mode of the course is # If the ecommerce checkout flow is enabled and the mode of the course is
# professional or no id professional, we construct links for the enrollment # professional or no id professional, we construct links for the enrollment
# button to add the course to the ecommerce basket. # button to add the course to the ecommerce basket.
ecomm_service = EcommerceService()
ecommerce_checkout = ecomm_service.is_enabled(request.user)
ecommerce_checkout_link = '' ecommerce_checkout_link = ''
ecommerce_bulk_checkout_link = '' ecommerce_bulk_checkout_link = ''
professional_mode = None professional_mode = None
ecomm_service = EcommerceService()
is_professional_mode = CourseMode.PROFESSIONAL in modes or CourseMode.NO_ID_PROFESSIONAL_MODE in modes is_professional_mode = CourseMode.PROFESSIONAL in modes or CourseMode.NO_ID_PROFESSIONAL_MODE in modes
if ecomm_service.is_enabled(request.user) and (is_professional_mode): if ecommerce_checkout and is_professional_mode:
professional_mode = modes.get(CourseMode.PROFESSIONAL, '') or \ professional_mode = modes.get(CourseMode.PROFESSIONAL, '') or \
modes.get(CourseMode.NO_ID_PROFESSIONAL_MODE, '') modes.get(CourseMode.NO_ID_PROFESSIONAL_MODE, '')
ecommerce_checkout_link = ecomm_service.checkout_page_url(professional_mode.sku) if professional_mode.sku:
ecommerce_checkout_link = ecomm_service.checkout_page_url(professional_mode.sku)
if professional_mode.bulk_sku: if professional_mode.bulk_sku:
ecommerce_bulk_checkout_link = ecomm_service.checkout_page_url(professional_mode.bulk_sku) ecommerce_bulk_checkout_link = ecomm_service.checkout_page_url(professional_mode.bulk_sku)
...@@ -593,7 +595,9 @@ def course_about(request, course_id): ...@@ -593,7 +595,9 @@ def course_about(request, course_id):
settings.PAID_COURSE_REGISTRATION_CURRENCY[0] settings.PAID_COURSE_REGISTRATION_CURRENCY[0]
) )
course_price = get_cosmetic_display_price(course, registration_price) course_price = get_cosmetic_display_price(course, registration_price)
can_add_course_to_cart = _is_shopping_cart_enabled and registration_price
# Determine which checkout workflow to use -- LMS shoppingcart or Otto basket
can_add_course_to_cart = _is_shopping_cart_enabled and registration_price and not ecommerce_checkout_link
# Used to provide context to message to student if enrollment not allowed # Used to provide context to message to student if enrollment not allowed
can_enroll = bool(has_access(request.user, 'enroll', course)) can_enroll = bool(has_access(request.user, 'enroll', course))
...@@ -624,7 +628,7 @@ def course_about(request, course_id): ...@@ -624,7 +628,7 @@ def course_about(request, course_id):
'is_cosmetic_price_enabled': settings.FEATURES.get('ENABLE_COSMETIC_DISPLAY_PRICE'), 'is_cosmetic_price_enabled': settings.FEATURES.get('ENABLE_COSMETIC_DISPLAY_PRICE'),
'course_price': course_price, 'course_price': course_price,
'in_cart': in_cart, 'in_cart': in_cart,
'ecommerce_checkout': ecomm_service.is_enabled(request.user), 'ecommerce_checkout': ecommerce_checkout,
'ecommerce_checkout_link': ecommerce_checkout_link, 'ecommerce_checkout_link': ecommerce_checkout_link,
'ecommerce_bulk_checkout_link': ecommerce_bulk_checkout_link, 'ecommerce_bulk_checkout_link': ecommerce_bulk_checkout_link,
'professional_mode': professional_mode, 'professional_mode': professional_mode,
......
...@@ -19,7 +19,6 @@ from django.test.utils import override_settings ...@@ -19,7 +19,6 @@ from django.test.utils import override_settings
from django.http import HttpRequest from django.http import HttpRequest
from course_modes.models import CourseMode from course_modes.models import CourseMode
from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin
from openedx.core.djangoapps.user_api.accounts.api import activate_account, create_account from openedx.core.djangoapps.user_api.accounts.api import activate_account, create_account
from openedx.core.djangoapps.user_api.accounts import EMAIL_MAX_LENGTH from openedx.core.djangoapps.user_api.accounts import EMAIL_MAX_LENGTH
from openedx.core.djangolib.js_utils import dump_js_escaped_json from openedx.core.djangolib.js_utils import dump_js_escaped_json
...@@ -443,7 +442,7 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi ...@@ -443,7 +442,7 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
}) })
class AccountSettingsViewTest(ThirdPartyAuthTestMixin, TestCase, ProgramsApiConfigMixin): class AccountSettingsViewTest(ThirdPartyAuthTestMixin, TestCase):
""" Tests for the account settings view. """ """ Tests for the account settings view. """
USERNAME = 'student' USERNAME = 'student'
...@@ -457,7 +456,6 @@ class AccountSettingsViewTest(ThirdPartyAuthTestMixin, TestCase, ProgramsApiConf ...@@ -457,7 +456,6 @@ class AccountSettingsViewTest(ThirdPartyAuthTestMixin, TestCase, ProgramsApiConf
'year_of_birth', 'year_of_birth',
'preferred_language', 'preferred_language',
] ]
view_path = reverse('account_settings')
@mock.patch("django.conf.settings.MESSAGE_STORAGE", 'django.contrib.messages.storage.cookie.CookieStorage') @mock.patch("django.conf.settings.MESSAGE_STORAGE", 'django.contrib.messages.storage.cookie.CookieStorage')
def setUp(self): def setUp(self):
...@@ -504,29 +502,12 @@ class AccountSettingsViewTest(ThirdPartyAuthTestMixin, TestCase, ProgramsApiConf ...@@ -504,29 +502,12 @@ class AccountSettingsViewTest(ThirdPartyAuthTestMixin, TestCase, ProgramsApiConf
def test_view(self): def test_view(self):
response = self.client.get(path=self.view_path) view_path = reverse('account_settings')
response = self.client.get(path=view_path)
for attribute in self.FIELDS: for attribute in self.FIELDS:
self.assertIn(attribute, response.content) self.assertIn(attribute, response.content)
def test_header_with_programs_listing_enabled(self):
"""
Verify that tabs header will be shown while program listing is enabled.
"""
self.create_programs_config(program_listing_enabled=True)
response = self.client.get(path=self.view_path)
self.assertContains(response, '<li class="tab-nav-item">')
def test_header_with_programs_listing_disabled(self):
"""
Verify that nav header will be shown while program listing is disabled.
"""
self.create_programs_config(program_listing_enabled=False)
response = self.client.get(path=self.view_path)
self.assertContains(response, '<li class="item nav-global-01">')
@override_settings(SITE_NAME=settings.MICROSITE_LOGISTRATION_HOSTNAME) @override_settings(SITE_NAME=settings.MICROSITE_LOGISTRATION_HOSTNAME)
class MicrositeLogistrationTests(TestCase): class MicrositeLogistrationTests(TestCase):
......
...@@ -36,7 +36,6 @@ from third_party_auth import pipeline ...@@ -36,7 +36,6 @@ from third_party_auth import pipeline
from third_party_auth.decorators import xframe_allow_whitelisted from third_party_auth.decorators import xframe_allow_whitelisted
from util.bad_request_rate_limiter import BadRequestRateLimiter from util.bad_request_rate_limiter import BadRequestRateLimiter
from openedx.core.djangoapps.programs.models import ProgramsApiConfig
from openedx.core.djangoapps.theming.helpers import is_request_in_themed_site, get_value as get_themed_value from openedx.core.djangoapps.theming.helpers import is_request_in_themed_site, get_value as get_themed_value
from openedx.core.djangoapps.user_api.accounts.api import request_password_change from openedx.core.djangoapps.user_api.accounts.api import request_password_change
from openedx.core.djangoapps.user_api.errors import UserNotFound from openedx.core.djangoapps.user_api.errors import UserNotFound
...@@ -395,7 +394,6 @@ def account_settings_context(request): ...@@ -395,7 +394,6 @@ def account_settings_context(request):
'user_accounts_api_url': reverse("accounts_api", kwargs={'username': user.username}), 'user_accounts_api_url': reverse("accounts_api", kwargs={'username': user.username}),
'user_preferences_api_url': reverse('preferences_api', kwargs={'username': user.username}), 'user_preferences_api_url': reverse('preferences_api', kwargs={'username': user.username}),
'disable_courseware_js': True, 'disable_courseware_js': True,
'show_program_listing': ProgramsApiConfig.current().show_program_listing,
} }
if third_party_auth.is_enabled(): if third_party_auth.is_enabled():
......
...@@ -6,13 +6,13 @@ from django.core.urlresolvers import reverse ...@@ -6,13 +6,13 @@ from django.core.urlresolvers import reverse
from django.test import TestCase from django.test import TestCase
from django.test.client import RequestFactory from django.test.client import RequestFactory
from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin from util.testing import UrlResetMixin
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from student_profile.views import learner_profile_context from student_profile.views import learner_profile_context
from util.testing import UrlResetMixin
class LearnerProfileViewTest(UrlResetMixin, TestCase, ProgramsApiConfigMixin): class LearnerProfileViewTest(UrlResetMixin, TestCase):
""" Tests for the student profile view. """ """ Tests for the student profile view. """
USERNAME = "username" USERNAME = "username"
...@@ -101,23 +101,3 @@ class LearnerProfileViewTest(UrlResetMixin, TestCase, ProgramsApiConfigMixin): ...@@ -101,23 +101,3 @@ class LearnerProfileViewTest(UrlResetMixin, TestCase, ProgramsApiConfigMixin):
profile_path = reverse('learner_profile', kwargs={'username': "no_such_user"}) profile_path = reverse('learner_profile', kwargs={'username': "no_such_user"})
response = self.client.get(path=profile_path) response = self.client.get(path=profile_path)
self.assertEqual(404, response.status_code) self.assertEqual(404, response.status_code)
def test_header_with_programs_listing_enabled(self):
"""
Verify that tabs header will be shown while program listing is enabled.
"""
self.create_programs_config(program_listing_enabled=True)
profile_path = reverse('learner_profile', kwargs={'username': self.USERNAME})
response = self.client.get(path=profile_path)
self.assertContains(response, '<li class="tab-nav-item">')
def test_header_with_programs_listing_disabled(self):
"""
Verify that nav header will be shown while program listing is disabled.
"""
self.create_programs_config(program_listing_enabled=False)
profile_path = reverse('learner_profile', kwargs={'username': self.USERNAME})
response = self.client.get(path=profile_path)
self.assertContains(response, '<li class="item nav-global-01">')
...@@ -12,7 +12,6 @@ from django.contrib.staticfiles.storage import staticfiles_storage ...@@ -12,7 +12,6 @@ from django.contrib.staticfiles.storage import staticfiles_storage
from badges.utils import badges_enabled from badges.utils import badges_enabled
from edxmako.shortcuts import render_to_response, marketing_link from edxmako.shortcuts import render_to_response, marketing_link
from microsite_configuration import microsite from microsite_configuration import microsite
from openedx.core.djangoapps.programs.models import ProgramsApiConfig
from openedx.core.djangoapps.user_api.accounts.api import get_account_settings from openedx.core.djangoapps.user_api.accounts.api import get_account_settings
from openedx.core.djangoapps.user_api.errors import UserNotFound, UserNotAuthorized from openedx.core.djangoapps.user_api.errors import UserNotFound, UserNotAuthorized
from openedx.core.djangoapps.user_api.preferences.api import get_user_preferences from openedx.core.djangoapps.user_api.preferences.api import get_user_preferences
...@@ -96,7 +95,6 @@ def learner_profile_context(request, profile_username, user_is_staff): ...@@ -96,7 +95,6 @@ def learner_profile_context(request, profile_username, user_is_staff):
'platform_name': microsite.get_value('platform_name', settings.PLATFORM_NAME), 'platform_name': microsite.get_value('platform_name', settings.PLATFORM_NAME),
}, },
'disable_courseware_js': True, 'disable_courseware_js': True,
'show_program_listing': ProgramsApiConfig.current().show_program_listing,
} }
if badges_enabled(): if badges_enabled():
......
...@@ -50,21 +50,13 @@ site_status_msg = get_site_status_msg(course_id) ...@@ -50,21 +50,13 @@ site_status_msg = get_site_status_msg(course_id)
</%block> </%block>
<header id="global-navigation" class="header-global ${"slim" if course else ""}" > <header id="global-navigation" class="header-global ${"slim" if course else ""}" >
<nav class="wrapper-header" aria-label="${_('Global')}"> <nav class="wrapper-header" aria-label="${_('Global')}">
<h1 class="logo"> <h1 class="logo">
<a href="${marketing_link('ROOT')}">
<%block name="navigation_logo"> <%block name="navigation_logo">
% if user.is_authenticated(): <img src="${static.url(branding_api.get_logo_url())}" alt="${_("{platform_name} Home Page").format(platform_name=static.get_platform_name())}"/>
<a href="${reverse('dashboard')}"> </%block>
<img src="${static.url(branding_api.get_logo_url())}" alt=${_("Your Dashboard")}/> </a>
</a> </h1>
% else:
<a href="${marketing_link('ROOT')}">
<img src="${static.url(branding_api.get_logo_url())}"
alt="${_("{platform_name} Home Page").format(platform_name=static.get_platform_name())}"/>
</a>
% endif
</%block>
</h1>
% if course: % if course:
<h2 class="course-header"><span class="provider">${course.display_org_with_default}:</span> <h2 class="course-header"><span class="provider">${course.display_org_with_default}:</span>
......
...@@ -28,6 +28,8 @@ from openedx.core.djangoapps.user_api.accounts.image_helpers import get_profile_ ...@@ -28,6 +28,8 @@ from openedx.core.djangoapps.user_api.accounts.image_helpers import get_profile_
</button> </button>
<ul class="dropdown-menu list-divided is-hidden" id="${_("Usermenu")}" tabindex="-1"> <ul class="dropdown-menu list-divided is-hidden" id="${_("Usermenu")}" tabindex="-1">
<%block name="navigation_dropdown_menu_links" > <%block name="navigation_dropdown_menu_links" >
<li class="dropdown-item item has-block-link"><a href="${reverse('dashboard')}" class="action">${_("Dashboard")}</a></li>
<li class="dropdown-item item has-block-link"><a href="${reverse('learner_profile', kwargs={'username': user.username})}" class="action">${_("Profile")}</a></li>
<li class="dropdown-item item has-block-link"><a href="${reverse('account_settings')}" class="action">${_("Account")}</a></li> <li class="dropdown-item item has-block-link"><a href="${reverse('account_settings')}" class="action">${_("Account")}</a></li>
</%block> </%block>
<li class="dropdown-item item has-block-link"><a href="${reverse('logout')}" role="menuitem" class="action">${_("Sign Out")}</a></li> <li class="dropdown-item item has-block-link"><a href="${reverse('logout')}" role="menuitem" class="action">${_("Sign Out")}</a></li>
...@@ -36,19 +38,19 @@ from openedx.core.djangoapps.user_api.accounts.image_helpers import get_profile_ ...@@ -36,19 +38,19 @@ from openedx.core.djangoapps.user_api.accounts.image_helpers import get_profile_
% else: % else:
<ol class="user"> <ol class="user">
<li class="primary"> <li class="primary">
<a href="${reverse('learner_profile', kwargs={'username': user.username})}" class="user-link"> <a href="${reverse('dashboard')}" class="user-link">
<span class="sr">${_("Profile for:")}</span> <span class="sr">${_("Dashboard for:")}</span>
<% <%
username = user.username username = user.username
profile_image_url = get_profile_image_urls_for_user(user)['medium'] profile_image_url = get_profile_image_urls_for_user(user)['medium']
%> %>
<img class="user-image-frame" src="${profile_image_url}" alt=""> <img class="user-image-frame" src="${profile_image_url}" alt="${_('Profile image for {username}').format(username=username)}">
<div class="label-username">${username}</div> <div class="label-username">${username}</div>
</a> </a>
</li> </li>
<li class="primary"> <li class="primary">
<button class="dropdown" aria-haspopup="true" aria-expanded="false" title=${_("Account settings menu")}><span class="fa fa-sort-desc" aria-hidden="true"></span></button> <button class="dropdown" aria-haspopup="true" aria-expanded="false"><span class="sr">${_("More options dropdown")}</span><span class="fa fa-sort-desc" aria-hidden="true"></span></button>
<ul class="dropdown-menu" aria-label=${_("Account settings")} role="menu"> <ul class="dropdown-menu" aria-label="More Options" role="menu">
${navigation_dropdown_menu_links()} ${navigation_dropdown_menu_links()}
<li class="item"><a href="${reverse('logout')}" role="menuitem">${_("Sign Out")}</a></li> <li class="item"><a href="${reverse('logout')}" role="menuitem">${_("Sign Out")}</a></li>
</ul> </ul>
......
...@@ -51,18 +51,11 @@ site_status_msg = get_site_status_msg(course_id) ...@@ -51,18 +51,11 @@ site_status_msg = get_site_status_msg(course_id)
% endif % endif
<div class="${"rwd" if responsive else ""} wrapper-header nav-container"> <div class="${"rwd" if responsive else ""} wrapper-header nav-container">
<h1 class="logo" itemscope="" itemtype="http://schema.org/Organization"> <h1 class="logo" itemscope="" itemtype="http://schema.org/Organization">
<%block name="navigation_logo"> <a href="${marketing_link('ROOT')}" itemprop="url">
% if user.is_authenticated(): <%block name="navigation_logo">
<a href="${reverse('dashboard')}"> <img src="${static.url("images/logo.png")}" alt="${_("{platform_name} Home Page").format(platform_name=static.get_platform_name())}" itemprop="logo" />
<img src="${static.url("images/logo.png")}" alt=${_("Your Dashboard")}/> </%block>
</a> </a>
% else:
<a href="${marketing_link('ROOT')}" itemprop="url">
<img src="${static.url("images/logo.png")}" itemprop="logo"
alt="${_("{platform_name} Home Page").format(platform_name=static.get_platform_name())}"/>
</a>
% endif
</%block>
</h1> </h1>
% if course and not disable_courseware_header: % if course and not disable_courseware_header:
...@@ -76,20 +69,10 @@ site_status_msg = get_site_status_msg(course_id) ...@@ -76,20 +69,10 @@ site_status_msg = get_site_status_msg(course_id)
% if user.is_authenticated(): % if user.is_authenticated():
% if not course or disable_courseware_header: % if not course or disable_courseware_header:
% if not nav_hidden or show_program_listing:
<nav aria-label="Main" class="nav-main"> <nav aria-label="Main" class="nav-main">
<ul class="left list-inline nav-global authenticated"> <ul class="left list-inline nav-global authenticated">
% if show_program_listing: % if not nav_hidden:
<li class="tab-nav-item">
<a class="${'active ' if reverse('dashboard') == request.path else ''}tab-nav-link" href="${reverse('dashboard')}">
${_("Courses")}
</a>
</li>
<li class="tab-nav-item">
<a class="${'active ' if reverse('program_listing_view') in request.path else ''}tab-nav-link" href="${reverse('program_listing_view')}">
${_("Programs")}
</a>
</li>
% elif not nav_hidden:
<%block name="navigation_global_links_authenticated"> <%block name="navigation_global_links_authenticated">
<li class="item nav-global-01"> <li class="item nav-global-01">
<a href="${marketing_link('HOW_IT_WORKS')}">${_("How it Works")}</a> <a href="${marketing_link('HOW_IT_WORKS')}">${_("How it Works")}</a>
...@@ -102,8 +85,21 @@ site_status_msg = get_site_status_msg(course_id) ...@@ -102,8 +85,21 @@ site_status_msg = get_site_status_msg(course_id)
</li> </li>
</%block> </%block>
% endif % endif
% if show_program_listing:
<li class="tab-nav-item">
<a class="${'active ' if reverse('dashboard') == request.path else ''}tab-nav-link" href="${reverse('dashboard')}">
${_("Courses")}
</a>
</li>
<li class="tab-nav-item">
<a class="${'active ' if reverse('program_listing_view') in request.path else ''}tab-nav-link" href="${reverse('program_listing_view')}">
${_("Programs")}
</a>
</li>
% endif
</ul> </ul>
</nav> </nav>
% endif
% endif % endif
<%include file="user_dropdown.html"/> <%include file="user_dropdown.html"/>
......
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