diff --git a/lms/djangoapps/courseware/tests/test_course_info.py b/lms/djangoapps/courseware/tests/test_course_info.py index ccef2c7a1e..bab762367e 100644 --- a/lms/djangoapps/courseware/tests/test_course_info.py +++ b/lms/djangoapps/courseware/tests/test_course_info.py @@ -1,14 +1,15 @@ +# coding=utf-8 """ Test the course_info xblock """ import mock from nose.plugins.attrib import attr from pyquery import PyQuery as pq -from urllib import urlencode from ccx_keys.locator import CCXLocator from django.conf import settings from django.core.urlresolvers import reverse +from django.http import QueryDict from django.test.utils import override_settings from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration @@ -89,7 +90,34 @@ class CourseInfoTestCase(LoginEnrollmentTestCase, SharedModuleStoreTestCase): url = reverse('info', args=[unicode(self.course.id)]) response = self.client.get(url) start_date = strftime_localized(self.course.start, 'SHORT_DATE') - self.assertRedirects(response, '{0}?{1}'.format(reverse('dashboard'), urlencode({'notlive': start_date}))) + expected_params = QueryDict(mutable=True) + expected_params['notlive'] = start_date + expected_url = '{url}?{params}'.format( + url=reverse('dashboard'), + params=expected_params.urlencode() + ) + self.assertRedirects(response, expected_url) + + @mock.patch.dict(settings.FEATURES, {'DISABLE_START_DATES': False}) + @mock.patch("courseware.views.views.strftime_localized") + def test_non_live_course_other_language(self, mock_strftime_localized): + """Ensure that a user accessing a non-live course sees a redirect to + the student dashboard, not a 404, even if the localized date is unicode + """ + self.setup_user() + self.enroll(self.course) + fake_unicode_start_time = u"üñîçø∂é_ßtå®t_tîµé" + mock_strftime_localized.return_value = fake_unicode_start_time + + url = reverse('info', args=[unicode(self.course.id)]) + response = self.client.get(url) + expected_params = QueryDict(mutable=True) + expected_params['notlive'] = fake_unicode_start_time + expected_url = u'{url}?{params}'.format( + url=reverse('dashboard'), + params=expected_params.urlencode() + ) + self.assertRedirects(response, expected_url) def test_nonexistent_course(self): self.setup_user() diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py index 662020978b..7d2c8a0723 100644 --- a/lms/djangoapps/courseware/views/views.py +++ b/lms/djangoapps/courseware/views/views.py @@ -17,7 +17,7 @@ from django.core.urlresolvers import reverse from django.core.context_processors import csrf from django.db import transaction from django.db.models import Q -from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponseForbidden +from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, QueryDict from django.shortcuts import redirect from django.utils.decorators import method_decorator from django.utils.timezone import UTC @@ -271,7 +271,7 @@ def course_info(request, course_id): Assumes the course_id is in a valid format. """ - course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id) + course_key = CourseKey.from_string(course_id) with modulestore().bulk_operations(course_key): course = get_course_by_id(course_key, depth=2) access_response = has_access(request.user, 'load', course, course_key) @@ -283,8 +283,12 @@ def course_info(request, course_id): # redirect to the dashboard page. if isinstance(access_response, StartDateError): start_date = strftime_localized(course.start, 'SHORT_DATE') - params = urllib.urlencode({'notlive': start_date}) - return redirect('{0}?{1}'.format(reverse('dashboard'), params)) + params = QueryDict(mutable=True) + params['notlive'] = start_date + return redirect('{dashboard_url}?{params}'.format( + dashboard_url=reverse('dashboard'), + params=params.urlencode() + )) # Otherwise, give a 404 to avoid leaking info about access # control. raise Http404("Course not found.")