The existing pattern of using `override_settings(MODULESTORE=...)` prevented
us from having more than one layer of subclassing in modulestore tests.
In a structure like:
@override_settings(MODULESTORE=store_a)
class BaseTestCase(ModuleStoreTestCase):
def setUp(self):
# use store
@override_settings(MODULESTORE=store_b)
class ChildTestCase(BaseTestCase):
def setUp(self):
# use store
In this case, the store actions performed in `BaseTestCase` on behalf of
`ChildTestCase` would still use `store_a`, even though the `ChildTestCase`
had specified to use `store_b`. This is because the `override_settings`
decorator would be the innermost wrapper around the `BaseTestCase.setUp` method,
no matter what `ChildTestCase` does.
To remedy this, we move the call to `override_settings` into the
`ModuleStoreTestCase.setUp` method, and use a cleanup to remove the override.
Subclasses can just defined the `MODULESTORE` class attribute to specify which
modulestore to use _for the entire `setUp` chain_.
[PLAT-419]
243 lines
9.6 KiB
Python
243 lines
9.6 KiB
Python
"""
|
|
Tests for branding page
|
|
"""
|
|
import datetime
|
|
from django.conf import settings
|
|
from django.contrib.auth.models import AnonymousUser
|
|
from django.http import HttpResponseRedirect
|
|
from django.test.utils import override_settings
|
|
from django.test.client import RequestFactory
|
|
from pytz import UTC
|
|
from mock import patch, Mock
|
|
from edxmako.shortcuts import render_to_response
|
|
|
|
from branding.views import index
|
|
from xmodule.modulestore.tests.django_utils import TEST_DATA_MOCK_MODULESTORE
|
|
from edxmako.tests import mako_middleware_process_request
|
|
import student.views
|
|
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
|
from xmodule.modulestore.tests.factories import CourseFactory
|
|
|
|
from django.core.urlresolvers import reverse
|
|
from courseware.tests.helpers import LoginEnrollmentTestCase
|
|
|
|
from util.milestones_helpers import (
|
|
seed_milestone_relationship_types,
|
|
set_prerequisite_courses,
|
|
)
|
|
|
|
FEATURES_WITH_STARTDATE = settings.FEATURES.copy()
|
|
FEATURES_WITH_STARTDATE['DISABLE_START_DATES'] = False
|
|
FEATURES_WO_STARTDATE = settings.FEATURES.copy()
|
|
FEATURES_WO_STARTDATE['DISABLE_START_DATES'] = True
|
|
|
|
|
|
def mock_render_to_response(*args, **kwargs):
|
|
"""
|
|
Mock the render_to_response function
|
|
"""
|
|
return render_to_response(*args, **kwargs)
|
|
|
|
RENDER_MOCK = Mock(side_effect=mock_render_to_response)
|
|
|
|
|
|
class AnonymousIndexPageTest(ModuleStoreTestCase):
|
|
"""
|
|
Tests that anonymous users can access the '/' page, Need courses with start date
|
|
"""
|
|
def setUp(self):
|
|
super(AnonymousIndexPageTest, self).setUp()
|
|
self.factory = RequestFactory()
|
|
self.course = CourseFactory.create(
|
|
days_early_for_beta=5,
|
|
enrollment_start=datetime.datetime.now(UTC) + datetime.timedelta(days=3),
|
|
user_id=self.user.id,
|
|
)
|
|
|
|
@override_settings(FEATURES=FEATURES_WITH_STARTDATE)
|
|
def test_none_user_index_access_with_startdate_fails(self):
|
|
"""
|
|
This is a regression test for a bug where the incoming user is
|
|
anonymous and start dates are being checked. It replaces a previous
|
|
test as it solves the issue in a different way
|
|
"""
|
|
request = self.factory.get('/')
|
|
request.user = AnonymousUser()
|
|
|
|
mako_middleware_process_request(request)
|
|
student.views.index(request)
|
|
|
|
@override_settings(FEATURES=FEATURES_WITH_STARTDATE)
|
|
def test_anon_user_with_startdate_index(self):
|
|
response = self.client.get('/')
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
@override_settings(FEATURES=FEATURES_WO_STARTDATE)
|
|
def test_anon_user_no_startdate_index(self):
|
|
response = self.client.get('/')
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
def test_allow_x_frame_options(self):
|
|
"""
|
|
Check the x-frame-option response header
|
|
"""
|
|
|
|
# check to see that the default setting is to ALLOW iframing
|
|
resp = self.client.get('/')
|
|
self.assertEquals(resp['X-Frame-Options'], 'ALLOW')
|
|
|
|
@override_settings(X_FRAME_OPTIONS='DENY')
|
|
def test_deny_x_frame_options(self):
|
|
"""
|
|
Check the x-frame-option response header
|
|
"""
|
|
|
|
# check to see that the override value is honored
|
|
resp = self.client.get('/')
|
|
self.assertEquals(resp['X-Frame-Options'], 'DENY')
|
|
|
|
def test_edge_redirect_to_login(self):
|
|
"""
|
|
Test edge homepage redirect to lms login.
|
|
"""
|
|
|
|
request = self.factory.get('/')
|
|
request.user = AnonymousUser()
|
|
|
|
# HTTP Host changed to edge.
|
|
request.META["HTTP_HOST"] = "edge.edx.org"
|
|
response = index(request)
|
|
|
|
# Response should be instance of HttpResponseRedirect.
|
|
self.assertIsInstance(response, HttpResponseRedirect)
|
|
# Location should be "/login".
|
|
self.assertEqual(response._headers.get("location")[1], "/login") # pylint: disable=protected-access
|
|
|
|
|
|
class PreRequisiteCourseCatalog(ModuleStoreTestCase, LoginEnrollmentTestCase):
|
|
"""
|
|
Test to simulate and verify fix for disappearing courses in
|
|
course catalog when using pre-requisite courses
|
|
"""
|
|
@patch.dict(settings.FEATURES, {'ENABLE_PREREQUISITE_COURSES': True, 'MILESTONES_APP': True})
|
|
def setUp(self):
|
|
super(PreRequisiteCourseCatalog, self).setUp()
|
|
|
|
seed_milestone_relationship_types()
|
|
|
|
@patch.dict(settings.FEATURES, {'ENABLE_PREREQUISITE_COURSES': True, 'MILESTONES_APP': True})
|
|
def test_course_with_prereq(self):
|
|
"""
|
|
Simulate having a course which has closed enrollments that has
|
|
a pre-req course
|
|
"""
|
|
pre_requisite_course = CourseFactory.create(
|
|
org='edX',
|
|
course='900',
|
|
display_name='pre requisite course',
|
|
)
|
|
|
|
pre_requisite_courses = [unicode(pre_requisite_course.id)]
|
|
|
|
# for this failure to occur, the enrollment window needs to be in the past
|
|
course = CourseFactory.create(
|
|
org='edX',
|
|
course='1000',
|
|
display_name='course that has pre requisite',
|
|
# closed enrollment
|
|
enrollment_start=datetime.datetime(2013, 1, 1),
|
|
enrollment_end=datetime.datetime(2014, 1, 1),
|
|
start=datetime.datetime(2013, 1, 1),
|
|
end=datetime.datetime(2030, 1, 1),
|
|
pre_requisite_courses=pre_requisite_courses,
|
|
)
|
|
set_prerequisite_courses(course.id, pre_requisite_courses)
|
|
|
|
resp = self.client.get('/')
|
|
self.assertEqual(resp.status_code, 200)
|
|
|
|
# make sure both courses are visible in the catalog
|
|
self.assertIn('pre requisite course', resp.content)
|
|
self.assertIn('course that has pre requisite', resp.content)
|
|
|
|
|
|
class IndexPageCourseCardsSortingTests(ModuleStoreTestCase):
|
|
"""
|
|
Test for Index page course cards sorting
|
|
"""
|
|
def setUp(self):
|
|
super(IndexPageCourseCardsSortingTests, self).setUp()
|
|
self.starting_later = CourseFactory.create(
|
|
org='MITx',
|
|
number='1000',
|
|
display_name='Starting later, Announced later',
|
|
metadata={
|
|
'start': datetime.datetime.now(UTC) + datetime.timedelta(days=4),
|
|
'announcement': datetime.datetime.now(UTC) + datetime.timedelta(days=3),
|
|
}
|
|
)
|
|
self.starting_earlier = CourseFactory.create(
|
|
org='MITx',
|
|
number='1001',
|
|
display_name='Starting earlier, Announced earlier',
|
|
metadata={
|
|
'start': datetime.datetime.now(UTC) + datetime.timedelta(days=2),
|
|
'announcement': datetime.datetime.now(UTC) + datetime.timedelta(days=1),
|
|
}
|
|
)
|
|
self.course_with_default_start_date = CourseFactory.create(
|
|
org='MITx',
|
|
number='1002',
|
|
display_name='Tech Beta Course',
|
|
)
|
|
self.factory = RequestFactory()
|
|
|
|
@patch('student.views.render_to_response', RENDER_MOCK)
|
|
@patch('courseware.views.render_to_response', RENDER_MOCK)
|
|
def test_course_cards_sorted_by_default_sorting(self):
|
|
response = self.client.get('/')
|
|
self.assertEqual(response.status_code, 200)
|
|
((template, context), _) = RENDER_MOCK.call_args # pylint: disable=unpacking-non-sequence
|
|
self.assertEqual(template, 'index.html')
|
|
|
|
# Now the courses will be stored in their announcement dates.
|
|
self.assertEqual(context['courses'][0].id, self.starting_later.id)
|
|
self.assertEqual(context['courses'][1].id, self.starting_earlier.id)
|
|
self.assertEqual(context['courses'][2].id, self.course_with_default_start_date.id)
|
|
|
|
# check the /courses view
|
|
response = self.client.get(reverse('branding.views.courses'))
|
|
self.assertEqual(response.status_code, 200)
|
|
((template, context), _) = RENDER_MOCK.call_args # pylint: disable=unpacking-non-sequence
|
|
self.assertEqual(template, 'courseware/courses.html')
|
|
|
|
# Now the courses will be stored in their announcement dates.
|
|
self.assertEqual(context['courses'][0].id, self.starting_later.id)
|
|
self.assertEqual(context['courses'][1].id, self.starting_earlier.id)
|
|
self.assertEqual(context['courses'][2].id, self.course_with_default_start_date.id)
|
|
|
|
@patch('student.views.render_to_response', RENDER_MOCK)
|
|
@patch('courseware.views.render_to_response', RENDER_MOCK)
|
|
@patch.dict('django.conf.settings.FEATURES', {'ENABLE_COURSE_SORTING_BY_START_DATE': True})
|
|
def test_course_cards_sorted_by_start_date_show_earliest_first(self):
|
|
response = self.client.get('/')
|
|
self.assertEqual(response.status_code, 200)
|
|
((template, context), _) = RENDER_MOCK.call_args # pylint: disable=unpacking-non-sequence
|
|
self.assertEqual(template, 'index.html')
|
|
|
|
# now the courses will be sorted by their creation dates, earliest first.
|
|
self.assertEqual(context['courses'][0].id, self.starting_earlier.id)
|
|
self.assertEqual(context['courses'][1].id, self.starting_later.id)
|
|
self.assertEqual(context['courses'][2].id, self.course_with_default_start_date.id)
|
|
|
|
# check the /courses view as well
|
|
response = self.client.get(reverse('branding.views.courses'))
|
|
self.assertEqual(response.status_code, 200)
|
|
((template, context), _) = RENDER_MOCK.call_args # pylint: disable=unpacking-non-sequence
|
|
self.assertEqual(template, 'courseware/courses.html')
|
|
|
|
# now the courses will be sorted by their creation dates, earliest first.
|
|
self.assertEqual(context['courses'][0].id, self.starting_earlier.id)
|
|
self.assertEqual(context['courses'][1].id, self.starting_later.id)
|
|
self.assertEqual(context['courses'][2].id, self.course_with_default_start_date.id)
|