test_page.py 11.9 KB
Newer Older
1 2 3
"""
Tests for branding page
"""
Ned Batchelder committed
4

5
import datetime
Ned Batchelder committed
6

7
from django.conf import settings
8
from django.contrib.auth.models import AnonymousUser
9
from django.http import HttpResponseRedirect
10
from django.test.utils import override_settings
11
from django.test.client import RequestFactory
Ned Batchelder committed
12

13
from pytz import UTC
14
from mock import patch, Mock
15
from nose.plugins.attrib import attr
16
from edxmako.shortcuts import render_to_response
17

18
from branding.views import index
19
from edxmako.tests import mako_middleware_process_request
20 21 22
import student.views
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
23

24
from django.core.urlresolvers import reverse
25 26 27 28 29 30
from courseware.tests.helpers import LoginEnrollmentTestCase

from util.milestones_helpers import (
    seed_milestone_relationship_types,
    set_prerequisite_courses,
)
31

32 33 34 35
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
36 37


38 39 40 41 42 43 44 45 46
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)


47
@attr('shard_1')
48 49 50 51 52
class AnonymousIndexPageTest(ModuleStoreTestCase):
    """
    Tests that anonymous users can access the '/' page,  Need courses with start date
    """
    def setUp(self):
53
        super(AnonymousIndexPageTest, self).setUp()
54
        self.factory = RequestFactory()
55 56
        self.course = CourseFactory.create(
            days_early_for_beta=5,
57
            enrollment_start=datetime.datetime.now(UTC) + datetime.timedelta(days=3),
58 59
            user_id=self.user.id,
        )
60

61
    @override_settings(FEATURES=FEATURES_WITH_STARTDATE)
62
    def test_none_user_index_access_with_startdate_fails(self):
63
        """
64 65 66
        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
67
        """
68 69
        request = self.factory.get('/')
        request.user = AnonymousUser()
70 71

        mako_middleware_process_request(request)
72
        student.views.index(request)
73

74
    @override_settings(FEATURES=FEATURES_WITH_STARTDATE)
75 76 77 78
    def test_anon_user_with_startdate_index(self):
        response = self.client.get('/')
        self.assertEqual(response.status_code, 200)

79
    @override_settings(FEATURES=FEATURES_WO_STARTDATE)
80 81 82
    def test_anon_user_no_startdate_index(self):
        response = self.client.get('/')
        self.assertEqual(response.status_code, 200)
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101

    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')
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117

    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".
118
        self.assertEqual(response._headers.get("location")[1], "/login")  # pylint: disable=protected-access
119 120


121
@attr('shard_1')
122 123 124 125 126 127 128
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):
129 130
        super(PreRequisiteCourseCatalog, self).setUp()

131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
        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)


169
@attr('shard_1')
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
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)
202
    @patch('courseware.views.render_to_response', RENDER_MOCK)
203
    @patch.dict('django.conf.settings.FEATURES', {'ENABLE_COURSE_DISCOVERY': False})
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
    def test_course_discovery_off(self):
        """
        Asserts that the Course Discovery UI elements follow the
        feature flag settings
        """
        response = self.client.get('/')
        self.assertEqual(response.status_code, 200)
        # assert that the course discovery UI is not present
        self.assertNotIn('Search for a course', response.content)

        # check the /courses view
        response = self.client.get(reverse('branding.views.courses'))
        self.assertEqual(response.status_code, 200)

        # assert that the course discovery UI is not present
        self.assertNotIn('Search for a course', response.content)
220
        self.assertNotIn('<aside aria-label="Refine Your Search" class="search-facets phone-menu">', response.content)
221 222

        # make sure we have the special css class on the section
Chris Dodge committed
223
        self.assertIn('<div class="courses no-course-discovery"', response.content)
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241

    @patch('student.views.render_to_response', RENDER_MOCK)
    @patch('courseware.views.render_to_response', RENDER_MOCK)
    @patch.dict('django.conf.settings.FEATURES', {'ENABLE_COURSE_DISCOVERY': True})
    def test_course_discovery_on(self):
        """
        Asserts that the Course Discovery UI elements follow the
        feature flag settings
        """
        response = self.client.get('/')
        self.assertEqual(response.status_code, 200)
        # assert that the course discovery UI is not present
        self.assertIn('Search for a course', response.content)

        # check the /courses view
        response = self.client.get(reverse('branding.views.courses'))
        self.assertEqual(response.status_code, 200)

Chris Dodge committed
242
        # assert that the course discovery UI is present
243
        self.assertIn('Search for a course', response.content)
244
        self.assertIn('<aside aria-label="Refine Your Search" class="search-facets phone-menu">', response.content)
Chris Dodge committed
245
        self.assertIn('<div class="courses"', response.content)
246 247 248 249

    @patch('student.views.render_to_response', RENDER_MOCK)
    @patch('courseware.views.render_to_response', RENDER_MOCK)
    @patch.dict('django.conf.settings.FEATURES', {'ENABLE_COURSE_DISCOVERY': False})
250 251 252
    def test_course_cards_sorted_by_default_sorting(self):
        response = self.client.get('/')
        self.assertEqual(response.status_code, 200)
253
        ((template, context), _) = RENDER_MOCK.call_args  # pylint: disable=unpacking-non-sequence
254 255
        self.assertEqual(template, 'index.html')

256 257 258
        # by default 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)
259 260
        self.assertEqual(context['courses'][2].id, self.course_with_default_start_date.id)

261 262 263
        # check the /courses view
        response = self.client.get(reverse('branding.views.courses'))
        self.assertEqual(response.status_code, 200)
264
        ((template, context), _) = RENDER_MOCK.call_args  # pylint: disable=unpacking-non-sequence
265 266
        self.assertEqual(template, 'courseware/courses.html')

267 268 269
        # by default 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)
270 271
        self.assertEqual(context['courses'][2].id, self.course_with_default_start_date.id)

272
    @patch('student.views.render_to_response', RENDER_MOCK)
273
    @patch('courseware.views.render_to_response', RENDER_MOCK)
274
    @patch.dict('django.conf.settings.FEATURES', {'ENABLE_COURSE_SORTING_BY_START_DATE': False})
275
    @patch.dict('django.conf.settings.FEATURES', {'ENABLE_COURSE_DISCOVERY': False})
276
    def test_course_cards_sorted_by_start_date_disabled(self):
277 278
        response = self.client.get('/')
        self.assertEqual(response.status_code, 200)
279
        ((template, context), _) = RENDER_MOCK.call_args  # pylint: disable=unpacking-non-sequence
280 281
        self.assertEqual(template, 'index.html')

282 283 284
        # now the courses will be sorted by their announcement dates.
        self.assertEqual(context['courses'][0].id, self.starting_later.id)
        self.assertEqual(context['courses'][1].id, self.starting_earlier.id)
285
        self.assertEqual(context['courses'][2].id, self.course_with_default_start_date.id)
286 287 288 289

        # check the /courses view as well
        response = self.client.get(reverse('branding.views.courses'))
        self.assertEqual(response.status_code, 200)
290
        ((template, context), _) = RENDER_MOCK.call_args  # pylint: disable=unpacking-non-sequence
291 292
        self.assertEqual(template, 'courseware/courses.html')

293 294 295
        # now the courses will be sorted by their announcement dates.
        self.assertEqual(context['courses'][0].id, self.starting_later.id)
        self.assertEqual(context['courses'][1].id, self.starting_earlier.id)
296
        self.assertEqual(context['courses'][2].id, self.course_with_default_start_date.id)