tests.py 6.38 KB
Newer Older
1 2 3
"""
Test for LMS courseware app.
"""
4
from textwrap import dedent
5
from unittest import TestCase
6

7
from django.core.urlresolvers import reverse
8
import mock
9
from nose.plugins.attrib import attr
10
from opaque_keys.edx.locations import SlashSeparatedCourseKey
Victor Shnayder committed
11

12
from courseware.tests.helpers import LoginEnrollmentTestCase
13
from lms.djangoapps.lms_xblock.field_data import LmsFieldData
14 15
from xmodule.error_module import ErrorDescriptor
from xmodule.modulestore.django import modulestore
16
from xmodule.modulestore.tests.django_utils import (
17
    ModuleStoreTestCase, TEST_DATA_MIXED_MODULESTORE
18 19
)
from xmodule.modulestore.tests.factories import ToyCourseFactory
20 21


22
@attr(shard=1)
23 24 25 26 27
class ActivateLoginTest(LoginEnrollmentTestCase):
    """
    Test logging in and logging out.
    """
    def setUp(self):
28
        super(ActivateLoginTest, self).setUp()
29
        self.setup_user()
Victor Shnayder committed
30

31 32 33
    def test_activate_login(self):
        """
        Test login -- the setup function does all the work.
Victor Shnayder committed
34
        """
35 36 37
        pass

    def test_logout(self):
Victor Shnayder committed
38
        """
39
        Test logout -- setup function does login.
Victor Shnayder committed
40
        """
41 42
        self.logout()

43 44 45 46 47 48 49 50
    def test_request_attr_on_logout(self):
        """
        Test request object after logging out to see whether it
        has 'is_from_log_out' attribute set to true.
        """
        response = self.client.get(reverse('logout'))
        self.assertTrue(getattr(response.wsgi_request, 'is_from_logout', False))  # pylint: disable=no-member

51 52 53 54 55

class PageLoaderTestCase(LoginEnrollmentTestCase):
    """
    Base class that adds a function to load all pages in a modulestore.
    """
56

57
    def check_all_pages_load(self, course_key):
58
        """
59 60
        Assert that all pages in the course load correctly.
        `course_id` is the ID of the course to check.
61
        """
62 63 64 65

        store = modulestore()

        # Enroll in the course before trying to access pages
66
        course = store.get_course(course_key)
67 68 69
        self.enroll(course, True)

        # Search for items in the course
70
        items = store.get_items(course_key)
71 72 73 74

        if len(items) < 1:
            self.fail('Could not retrieve any items from course')

75 76
        # Try to load each item in the course
        for descriptor in items:
77

78 79
            if descriptor.location.category == 'about':
                self._assert_loads('about_course',
80
                                   {'course_id': course_key.to_deprecated_string()},
81
                                   descriptor)
82

83
            elif descriptor.location.category == 'static_tab':
84
                kwargs = {'course_id': course_key.to_deprecated_string(),
85 86
                          'tab_slug': descriptor.location.name}
                self._assert_loads('static_tab', kwargs, descriptor)
87

88
            elif descriptor.location.category == 'course_info':
89
                self._assert_loads('info', {'course_id': course_key.to_deprecated_string()},
90
                                   descriptor)
91

92
            else:
93

94
                kwargs = {'course_id': course_key.to_deprecated_string(),
95
                          'location': descriptor.location.to_deprecated_string()}
96

97 98 99
                self._assert_loads('jump_to', kwargs, descriptor,
                                   expect_redirect=True,
                                   check_content=True)
100 101 102 103 104 105 106 107 108

    def _assert_loads(self, django_url, kwargs, descriptor,
                      expect_redirect=False,
                      check_content=False):
        """
        Assert that the url loads correctly.
        If expect_redirect, then also check that we were redirected.
        If check_content, then check that we don't get
        an error message about unavailable modules.
109
        """
Victor Shnayder committed
110

111 112
        url = reverse(django_url, kwargs=kwargs)
        response = self.client.get(url, follow=True)
Will Daly committed
113

114 115
        if response.status_code != 200:
            self.fail('Status %d for page %s' %
116
                      (response.status_code, descriptor.location))
Will Daly committed
117

118 119
        if expect_redirect:
            self.assertEqual(response.redirect_chain[0][1], 302)
Will Daly committed
120

121
        if check_content:
122 123
            self.assertNotContains(response, "this module is temporarily unavailable")
            self.assertNotIsInstance(descriptor, ErrorDescriptor)
124

125

126
@attr(shard=1)
127
class TestMongoCoursesLoad(ModuleStoreTestCase, PageLoaderTestCase):
128 129 130
    """
    Check that all pages in test courses load properly from Mongo.
    """
131
    MODULESTORE = TEST_DATA_MIXED_MODULESTORE
132

133
    def setUp(self):
134
        super(TestMongoCoursesLoad, self).setUp()
135
        self.setup_user()
136
        self.toy_course_key = ToyCourseFactory.create().id
137

lapentab committed
138 139
    @mock.patch('xmodule.course_module.requests.get')
    def test_toy_textbooks_loads(self, mock_get):
lapentab committed
140 141 142 143 144
        mock_get.return_value.text = dedent("""
            <?xml version="1.0"?><table_of_contents>
            <entry page="5" page_label="ii" name="Table of Contents"/>
            </table_of_contents>
        """).strip()
145
        location = self.toy_course_key.make_usage_key('course', '2012_Fall')
146
        course = self.store.get_item(location)
147
        self.assertGreater(len(course.textbooks), 0)
148

lapentab committed
149

150
@attr(shard=1)
Will Daly committed
151
class TestDraftModuleStore(ModuleStoreTestCase):
152 153
    def test_get_items_with_course_items(self):
        store = modulestore()
154

155
        # fix was to allow get_items() to take the course_id parameter
156
        store.get_items(SlashSeparatedCourseKey('abc', 'def', 'ghi'), qualifiers={'category': 'vertical'})
157

158 159 160
        # test success is just getting through the above statement.
        # The bug was that 'course_id' argument was
        # not allowed to be passed in (i.e. was throwing exception)
161 162


163
@attr(shard=1)
164 165 166 167 168 169 170 171 172 173 174 175 176
class TestLmsFieldData(TestCase):
    """
    Tests of the LmsFieldData class
    """
    def test_lms_field_data_wont_nest(self):
        # Verify that if an LmsFieldData is passed into LmsFieldData as the
        # authored_data, that it doesn't produced a nested field data.
        #
        # This fixes a bug where re-use of the same descriptor for many modules
        # would cause more and more nesting, until the recursion depth would be
        # reached on any attribute access

        # pylint: disable=protected-access
177 178
        base_authored = mock.Mock()
        base_student = mock.Mock()
179 180 181 182
        first_level = LmsFieldData(base_authored, base_student)
        second_level = LmsFieldData(first_level, base_student)
        self.assertEquals(second_level._authored_data, first_level._authored_data)
        self.assertNotIsInstance(second_level._authored_data, LmsFieldData)