test_tabs.py 9.67 KB
Newer Older
1 2
"""
Test cases for tabs.
3
Note: Tests covering workflows in the actual tabs.py file begin after line 100
4
"""
5
from django.conf import settings
6 7
from django.core.urlresolvers import reverse
from django.http import Http404
8
from mock import MagicMock, Mock, patch
9
from opaque_keys.edx.locations import SlashSeparatedCourseKey
10

11
from courseware.courses import get_course_by_id
12
from courseware.tests.helpers import get_request_for_user, LoginEnrollmentTestCase
13
from xmodule import tabs
14 15 16
from xmodule.modulestore.tests.django_utils import (
    TEST_DATA_MIXED_TOY_MODULESTORE, TEST_DATA_MIXED_CLOSED_MODULESTORE
)
17
from courseware.views import get_static_tab_contents, static_tab
18
from student.tests.factories import UserFactory
19
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
20
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
21

22 23 24 25 26
if settings.FEATURES.get('MILESTONES_APP', False):
    from courseware.tabs import get_course_tab_list
    from milestones import api as milestones_api
    from milestones.models import MilestoneRelationshipType

27

28
class StaticTabDateTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
29 30
    """Test cases for Static Tab Dates."""

31 32
    MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE

33
    def setUp(self):
34
        super(StaticTabDateTestCase, self).setUp()
35 36 37 38 39
        self.course = CourseFactory.create()
        self.page = ItemFactory.create(
            category="static_tab", parent_location=self.course.location,
            data="OOGIE BLOOGIE", display_name="new_tab"
        )
40
        self.toy_course_key = SlashSeparatedCourseKey('edX', 'toy', '2012_Fall')
41 42 43

    def test_logged_in(self):
        self.setup_user()
44
        url = reverse('static_tab', args=[self.course.id.to_deprecated_string(), 'new_tab'])
45 46 47 48 49
        resp = self.client.get(url)
        self.assertEqual(resp.status_code, 200)
        self.assertIn("OOGIE BLOOGIE", resp.content)

    def test_anonymous_user(self):
50
        url = reverse('static_tab', args=[self.course.id.to_deprecated_string(), 'new_tab'])
51 52 53 54
        resp = self.client.get(url)
        self.assertEqual(resp.status_code, 200)
        self.assertIn("OOGIE BLOOGIE", resp.content)

55 56 57
    def test_invalid_course_key(self):
        request = get_request_for_user(UserFactory.create())
        with self.assertRaises(Http404):
58
            static_tab(request, course_id='edX/toy', tab_slug='new_tab')
59

60
    def test_get_static_tab_contents(self):
61
        course = get_course_by_id(self.toy_course_key)
62
        request = get_request_for_user(UserFactory.create())
63
        tab = tabs.CourseTabList.get_tab_by_slug(course.tabs, 'resources')
64 65 66

        # Test render works okay
        tab_content = get_static_tab_contents(request, course, tab)
67
        self.assertIn(self.toy_course_key.to_deprecated_string(), tab_content)
68 69 70 71 72 73 74 75 76 77
        self.assertIn('static_tab', tab_content)

        # Test when render raises an exception
        with patch('courseware.views.get_module') as mock_module_render:
            mock_module_render.return_value = MagicMock(
                render=Mock(side_effect=Exception('Render failed!'))
            )
            static_tab = get_static_tab_contents(request, course, tab)
            self.assertIn("this module is temporarily unavailable", static_tab)

Adam Palay committed
78 79

class StaticTabDateTestCaseXML(LoginEnrollmentTestCase, ModuleStoreTestCase):
80 81 82
    """
    Tests for the static tab dates of an XML course
    """
83 84 85

    MODULESTORE = TEST_DATA_MIXED_CLOSED_MODULESTORE

Adam Palay committed
86 87 88
    # The following XML test course (which lives at common/test/data/2014)
    # is closed; we're testing that tabs still appear when
    # the course is already closed
89
    xml_course_key = SlashSeparatedCourseKey('edX', 'detached_pages', '2014')
Adam Palay committed
90 91 92 93 94 95

    # this text appears in the test course's tab
    # common/test/data/2014/tabs/8e4cce2b4aaf4ba28b1220804619e41f.html
    xml_data = "static 463139"
    xml_url = "8e4cce2b4aaf4ba28b1220804619e41f"

96 97 98
    @patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False})
    def test_logged_in_xml(self):
        self.setup_user()
99
        url = reverse('static_tab', args=[self.xml_course_key.to_deprecated_string(), self.xml_url])
100 101 102 103 104 105
        resp = self.client.get(url)
        self.assertEqual(resp.status_code, 200)
        self.assertIn(self.xml_data, resp.content)

    @patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False})
    def test_anonymous_user_xml(self):
106
        url = reverse('static_tab', args=[self.xml_course_key.to_deprecated_string(), self.xml_url])
107 108 109
        resp = self.client.get(url)
        self.assertEqual(resp.status_code, 200)
        self.assertIn(self.xml_data, resp.content)
110 111 112 113 114 115


class EntranceExamsTabsTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
    """
    Validate tab behavior when dealing with Entrance Exams
    """
116 117
    MODULESTORE = TEST_DATA_MIXED_CLOSED_MODULESTORE

118 119 120 121 122 123
    if settings.FEATURES.get('ENTRANCE_EXAMS', False):

        def setUp(self):
            """
            Test case scaffolding
            """
124 125
            super(EntranceExamsTabsTestCase, self).setUp()

126 127 128 129 130 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 169 170 171 172 173 174 175 176 177 178
            self.course = CourseFactory.create()
            self.instructor_tab = ItemFactory.create(
                category="instructor", parent_location=self.course.location,
                data="Instructor Tab", display_name="Instructor"
            )
            self.extra_tab_2 = ItemFactory.create(
                category="static_tab", parent_location=self.course.location,
                data="Extra Tab", display_name="Extra Tab 2"
            )
            self.extra_tab_3 = ItemFactory.create(
                category="static_tab", parent_location=self.course.location,
                data="Extra Tab", display_name="Extra Tab 3"
            )
            self.setup_user()
            self.enroll(self.course)
            self.user.is_staff = True
            self.relationship_types = milestones_api.get_milestone_relationship_types()
            MilestoneRelationshipType.objects.create(name='requires')
            MilestoneRelationshipType.objects.create(name='fulfills')

        def test_get_course_tabs_list_entrance_exam_enabled(self):
            """
            Unit Test: test_get_course_tabs_list_entrance_exam_enabled
            """
            entrance_exam = ItemFactory.create(
                category="chapter", parent_location=self.course.location,
                data="Exam Data", display_name="Entrance Exam"
            )
            entrance_exam.is_entrance_exam = True
            milestone = {
                'name': 'Test Milestone',
                'namespace': '{}.entrance_exams'.format(unicode(self.course.id)),
                'description': 'Testing Courseware Tabs'
            }
            self.course.entrance_exam_enabled = True
            self.course.entrance_exam_id = unicode(entrance_exam.location)
            milestone = milestones_api.add_milestone(milestone)
            milestones_api.add_course_milestone(
                unicode(self.course.id),
                self.relationship_types['REQUIRES'],
                milestone
            )
            milestones_api.add_course_content_milestone(
                unicode(self.course.id),
                unicode(entrance_exam.location),
                self.relationship_types['FULFILLS'],
                milestone
            )
            course_tab_list = get_course_tab_list(self.course, self.user)
            self.assertEqual(len(course_tab_list), 2)
            self.assertEqual(course_tab_list[0]['tab_id'], 'courseware')
            self.assertEqual(course_tab_list[0]['name'], 'Entrance Exam')
            self.assertEqual(course_tab_list[1]['tab_id'], 'instructor')
179 180 181 182 183 184


class TextBookTabsTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
    """
    Validate tab behavior when dealing with textbooks.
    """
Jesse Zoldak committed
185
    MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE
186 187

    def setUp(self):
188 189
        super(TextBookTabsTestCase, self).setUp()

190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
        self.course = CourseFactory.create()
        self.set_up_books(2)
        self.course.tabs = [
            tabs.CoursewareTab(),
            tabs.CourseInfoTab(),
            tabs.TextbookTabs(),
            tabs.PDFTextbookTabs(),
            tabs.HtmlTextbookTabs(),
        ]
        self.setup_user()
        self.enroll(self.course)
        self.num_textbook_tabs = sum(1 for tab in self.course.tabs if isinstance(tab, tabs.TextbookTabsBase))
        self.num_textbooks = self.num_textbook_tabs * len(self.books)

    def set_up_books(self, num_books):
        """Initializes the textbooks in the course and adds the given number of books to each textbook"""
        self.books = [MagicMock() for _ in range(num_books)]
        for book_index, book in enumerate(self.books):
            book.title = 'Book{0}'.format(book_index)
        self.course.textbooks = self.books
        self.course.pdf_textbooks = self.books
        self.course.html_textbooks = self.books

    def test_pdf_textbook_tabs(self):
        """
        Test that all textbooks tab links generating correctly.
        """
        type_to_reverse_name = {'textbook': 'book', 'pdftextbook': 'pdf_book', 'htmltextbook': 'html_book'}

        course_tab_list = get_course_tab_list(self.course, self.user)
        num_of_textbooks_found = 0
        for tab in course_tab_list:
            # Verify links of all textbook type tabs.
            if isinstance(tab, tabs.SingleTextbookTab):
                book_type, book_index = tab.tab_id.split("/", 1)
                expected_link = reverse(
                    type_to_reverse_name[book_type],
                    args=[self.course.id.to_deprecated_string(), book_index]
                )
                tab_link = tab.link_func(self.course, reverse)
                self.assertEqual(tab_link, expected_link)
                num_of_textbooks_found += 1
        self.assertEqual(num_of_textbooks_found, self.num_textbooks)