test_navigation.py 10.2 KB
Newer Older
1 2 3 4 5
"""
This test file will run through some LMS test scenarios regarding access and navigation of the LMS
"""
import time

6
from django.conf import settings
7 8 9
from django.core.urlresolvers import reverse
from django.test.utils import override_settings

10
from courseware.tests.helpers import LoginEnrollmentTestCase
11
from courseware.tests.factories import GlobalStaffFactory
12 13
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
14 15


16 17 18 19
class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase):
    """
    Check that navigation state is saved properly.
    """
20

21 22
    STUDENT_INFO = [('view@test.com', 'foo'), ('view2@test.com', 'foo')]

23
    def setUp(self):
Don Mitchell committed
24 25 26
        super(TestNavigation, self).setUp()
        self.test_course = CourseFactory.create()
        self.course = CourseFactory.create()
27
        self.chapter0 = ItemFactory.create(parent=self.course,
28
                                           display_name='Overview')
29
        self.chapter9 = ItemFactory.create(parent=self.course,
30
                                           display_name='factory_chapter')
31
        self.section0 = ItemFactory.create(parent=self.chapter0,
32
                                           display_name='Welcome')
33
        self.section9 = ItemFactory.create(parent=self.chapter9,
34
                                           display_name='factory_section')
35
        self.unit0 = ItemFactory.create(parent=self.section0,
36
                                        display_name='New Unit')
37

38 39 40 41 42 43 44 45 46 47 48
        self.chapterchrome = ItemFactory.create(parent=self.course,
                                                display_name='Chrome')
        self.chromelesssection = ItemFactory.create(parent=self.chapterchrome,
                                                    display_name='chromeless',
                                                    chrome='none')
        self.accordionsection = ItemFactory.create(parent=self.chapterchrome,
                                                   display_name='accordion',
                                                   chrome='accordion')
        self.tabssection = ItemFactory.create(parent=self.chapterchrome,
                                              display_name='tabs',
                                              chrome='tabs')
49 50 51 52
        self.defaultchromesection = ItemFactory.create(
            parent=self.chapterchrome,
            display_name='defaultchrome',
        )
53 54 55 56 57
        self.fullchromesection = ItemFactory.create(parent=self.chapterchrome,
                                                    display_name='fullchrome',
                                                    chrome='accordion,tabs')
        self.tabtest = ItemFactory.create(parent=self.chapterchrome,
                                          display_name='progress_tab',
Don Mitchell committed
58
                                          default_tab='progress')
59

60 61
        # Create student accounts and activate them.
        for i in range(len(self.STUDENT_INFO)):
62 63 64 65
            email, password = self.STUDENT_INFO[i]
            username = 'u{0}'.format(i)
            self.create_account(username, email, password)
            self.activate_user(email)
66

67 68
        self.staff_user = GlobalStaffFactory()

Piotr Mitros committed
69
    def assertTabActive(self, tabname, response):
70
        ''' Check if the progress tab is active in the tab set '''
Piotr Mitros committed
71 72 73
        for line in response.content.split('\n'):
            if tabname in line and 'active' in line:
                return
Don Mitchell committed
74
        raise AssertionError("assertTabActive failed: {} not active".format(tabname))
Piotr Mitros committed
75 76

    def assertTabInactive(self, tabname, response):
77
        ''' Check if the progress tab is active in the tab set '''
Piotr Mitros committed
78 79
        for line in response.content.split('\n'):
            if tabname in line and 'active' in line:
80
                raise AssertionError("assertTabInactive failed: " + tabname + " active")
Piotr Mitros committed
81 82
        return

83 84
    def test_chrome_settings(self):
        '''
85
        Test settings for disabling and modifying navigation chrome in the courseware:
86 87 88 89 90 91 92 93 94 95 96 97
        - Accordion enabled, or disabled
        - Navigation tabs enabled, disabled, or redirected
        '''
        email, password = self.STUDENT_INFO[0]
        self.login(email, password)
        self.enroll(self.course, True)

        test_data = (
            ('tabs', False, True),
            ('none', False, False),
            ('fullchrome', True, True),
            ('accordion', True, False),
Piotr Mitros committed
98
            ('fullchrome', True, True)
Don Mitchell committed
99
        )
100 101
        for (displayname, accordion, tabs) in test_data:
            response = self.client.get(reverse('courseware_section', kwargs={
Piotr Mitros committed
102 103 104 105
                'course_id': self.course.id.to_deprecated_string(),
                'chapter': 'Chrome',
                'section': displayname,
            }))
106 107
            self.assertEquals('open_close_accordion' in response.content, accordion)
            self.assertEquals('course-tabs' in response.content, tabs)
108

Piotr Mitros committed
109 110
        self.assertTabInactive('progress', response)
        self.assertTabActive('courseware', response)
111 112

        response = self.client.get(reverse('courseware_section', kwargs={
Piotr Mitros committed
113 114 115 116
            'course_id': self.course.id.to_deprecated_string(),
            'chapter': 'Chrome',
            'section': 'progress_tab',
        }))
117

Piotr Mitros committed
118 119
        self.assertTabActive('progress', response)
        self.assertTabInactive('courseware', response)
120

121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
    @override_settings(SESSION_INACTIVITY_TIMEOUT_IN_SECONDS=1)
    def test_inactive_session_timeout(self):
        """
        Verify that an inactive session times out and redirects to the
        login page
        """
        email, password = self.STUDENT_INFO[0]
        self.login(email, password)

        # make sure we can access courseware immediately
        resp = self.client.get(reverse('dashboard'))
        self.assertEquals(resp.status_code, 200)

        # then wait a bit and see if we get timed out
        time.sleep(2)

        resp = self.client.get(reverse('dashboard'))

        # re-request, and we should get a redirect to login page
        self.assertRedirects(resp, settings.LOGIN_REDIRECT_URL + '?next=' + reverse('dashboard'))

142 143 144 145 146
    def test_redirects_first_time(self):
        """
        Verify that the first time we click on the courseware tab we are
        redirected to the 'Welcome' section.
        """
147 148
        email, password = self.STUDENT_INFO[0]
        self.login(email, password)
149
        self.enroll(self.course, True)
150
        self.enroll(self.test_course, True)
151 152

        resp = self.client.get(reverse('courseware',
153
                               kwargs={'course_id': self.course.id.to_deprecated_string()}))
154 155

        self.assertRedirects(resp, reverse(
156
            'courseware_section', kwargs={'course_id': self.course.id.to_deprecated_string(),
157 158 159
                                          'chapter': 'Overview',
                                          'section': 'Welcome'}))

160 161 162 163 164
    def test_redirects_second_time(self):
        """
        Verify the accordion remembers we've already visited the Welcome section
        and redirects correpondingly.
        """
165 166
        email, password = self.STUDENT_INFO[0]
        self.login(email, password)
167
        self.enroll(self.course, True)
168
        self.enroll(self.test_course, True)
169

170 171 172 173 174
        self.client.get(reverse('courseware_section', kwargs={
            'course_id': self.course.id.to_deprecated_string(),
            'chapter': 'Overview',
            'section': 'Welcome',
        }))
175

176
        resp = self.client.get(reverse('courseware',
177
                               kwargs={'course_id': self.course.id.to_deprecated_string()}))
178

179
        redirect_url = reverse(
180 181 182 183 184
            'courseware_chapter',
            kwargs={
                'course_id': self.course.id.to_deprecated_string(),
                'chapter': 'Overview'
            }
185 186
        )
        self.assertRedirects(resp, redirect_url)
187 188 189 190 191

    def test_accordion_state(self):
        """
        Verify the accordion remembers which chapter you were last viewing.
        """
192 193
        email, password = self.STUDENT_INFO[0]
        self.login(email, password)
194
        self.enroll(self.course, True)
195
        self.enroll(self.test_course, True)
196

197
        # Now we directly navigate to a section in a chapter other than 'Overview'.
198
        url = reverse(
199 200 201 202 203 204
            'courseware_section',
            kwargs={
                'course_id': self.course.id.to_deprecated_string(),
                'chapter': 'factory_chapter',
                'section': 'factory_section'
            }
205 206
        )
        self.assert_request_status_code(200, url)
207

208
        # And now hitting the courseware tab should redirect to 'factory_chapter'
209 210 211 212 213
        url = reverse(
            'courseware',
            kwargs={'course_id': self.course.id.to_deprecated_string()}
        )
        resp = self.client.get(url)
214

215 216 217 218 219 220 221 222
        redirect_url = reverse(
            'courseware_chapter',
            kwargs={
                'course_id': self.course.id.to_deprecated_string(),
                'chapter': 'factory_chapter',
            }
        )
        self.assertRedirects(resp, redirect_url)
223 224 225 226 227 228 229 230 231

    def test_incomplete_course(self):
        email = self.staff_user.email
        password = "test"
        self.login(email, password)
        self.enroll(self.test_course, True)

        test_course_id = self.test_course.id.to_deprecated_string()

232 233 234
        url = reverse(
            'courseware',
            kwargs={'course_id': test_course_id}
235
        )
236
        self.assert_request_status_code(200, url)
237 238 239 240 241

        section = ItemFactory.create(
            parent_location=self.test_course.location,
            display_name='New Section'
        )
242 243 244
        url = reverse(
            'courseware',
            kwargs={'course_id': test_course_id}
245
        )
246
        self.assert_request_status_code(200, url)
247 248 249 250 251

        subsection = ItemFactory.create(
            parent_location=section.location,
            display_name='New Subsection'
        )
252 253 254
        url = reverse(
            'courseware',
            kwargs={'course_id': test_course_id}
255
        )
256
        self.assert_request_status_code(200, url)
257 258 259 260 261

        ItemFactory.create(
            parent_location=subsection.location,
            display_name='New Unit'
        )
262 263 264
        url = reverse(
            'courseware',
            kwargs={'course_id': test_course_id}
265
        )
266
        self.assert_request_status_code(302, url)