tests.py 8.88 KB
Newer Older
Ned Batchelder committed
1
"""
2
Test the lms/staticbook views.
Ned Batchelder committed
3 4
"""

5 6 7 8 9
import textwrap

import mock
import requests

Ned Batchelder committed
10
from django.test.utils import override_settings
11
from django.core.urlresolvers import reverse, NoReverseMatch
Ned Batchelder committed
12

13
from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE
Ned Batchelder committed
14
from student.tests.factories import UserFactory, CourseEnrollmentFactory
Ned Batchelder committed
15
from xmodule.modulestore.tests.factories import CourseFactory
Ned Batchelder committed
16 17 18
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase


19 20
IMAGE_BOOK = ("An Image Textbook", "http://example.com/the_book/")

Ned Batchelder committed
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
PDF_BOOK = {
    "tab_title": "Textbook",
    "title": "A PDF Textbook",
    "chapters": [
        { "title": "Chapter 1 for PDF", "url": "https://somehost.com/the_book/chap1.pdf" },
        { "title": "Chapter 2 for PDF", "url": "https://somehost.com/the_book/chap2.pdf" },
    ],
}

HTML_BOOK = {
    "tab_title": "Textbook",
    "title": "An HTML Textbook",
    "chapters": [
        { "title": "Chapter 1 for HTML", "url": "https://somehost.com/the_book/chap1.html" },
        { "title": "Chapter 2 for HTML", "url": "https://somehost.com/the_book/chap2.html" },
    ],
}

Will Daly committed
39

40
@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE)
Ned Batchelder committed
41 42 43 44 45
class StaticBookTest(ModuleStoreTestCase):
    """
    Helpers for the static book tests.
    """

46 47 48 49
    def __init__(self, *args, **kwargs):
        super(StaticBookTest, self).__init__(*args, **kwargs)
        self.course = None

Ned Batchelder committed
50 51 52 53
    def make_course(self, **kwargs):
        """
        Make a course with an enrolled logged-in student.
        """
54
        self.course = CourseFactory.create(**kwargs)
Ned Batchelder committed
55
        user = UserFactory.create()
56
        CourseEnrollmentFactory.create(user=user, course_id=self.course.id)
Ned Batchelder committed
57
        self.client.login(username=user.username, password='test')
58 59 60 61 62 63 64 65 66 67 68

    def make_url(self, url_name, **kwargs):
        """
        Make a URL for a `url_name` using keyword args for url slots.

        Automatically provides the course id.

        """
        kwargs['course_id'] = self.course.id
        url = reverse(url_name, kwargs=kwargs)
        return url
Ned Batchelder committed
69 70


71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
class StaticImageBookTest(StaticBookTest):
    """
    Test the image-based static book view.
    """

    def test_book(self):
        # We can access a book.
        with mock.patch.object(requests, 'get') as mock_get:
            mock_get.return_value.text = textwrap.dedent('''\
                <?xml version="1.0"?>
                <table_of_contents>
                <entry page="9" page_label="ix" name="Contents!?"/>
                <entry page="1" page_label="i" name="Preamble">
                    <entry page="4" page_label="iv" name="About the Elephants"/>
                </entry>
                </table_of_contents>
                ''')

            self.make_course(textbooks=[IMAGE_BOOK])
            url = self.make_url('book', book_index=0)
            response = self.client.get(url)

        self.assertContains(response, "Contents!?")
        self.assertContains(response, "About the Elephants")

    def test_bad_book_id(self):
        # A bad book id will be a 404.
        self.make_course(textbooks=[IMAGE_BOOK])
        with self.assertRaises(NoReverseMatch):
            self.make_url('book', book_index='fooey')

    def test_out_of_range_book_id(self):
        self.make_course()
        url = self.make_url('book', book_index=0)
        response = self.client.get(url)
        self.assertEqual(response.status_code, 404)

108 109
    def test_bad_page_id(self):
        # A bad page id will cause a 404.        
110 111 112 113
        self.make_course(textbooks=[IMAGE_BOOK])
        with self.assertRaises(NoReverseMatch):
            self.make_url('book', book_index=0, page='xyzzy')

114

Ned Batchelder committed
115 116 117 118 119 120 121
class StaticPdfBookTest(StaticBookTest):
    """
    Test the PDF static book view.
    """

    def test_book(self):
        # We can access a book.
122 123
        self.make_course(pdf_textbooks=[PDF_BOOK])
        url = self.make_url('pdf_book', book_index=0)
Ned Batchelder committed
124 125 126 127 128 129 130
        response = self.client.get(url)
        self.assertContains(response, "Chapter 1 for PDF")
        self.assertNotContains(response, "options.chapterNum =")
        self.assertNotContains(response, "options.pageNum =")

    def test_book_chapter(self):
        # We can access a book at a particular chapter.
131 132
        self.make_course(pdf_textbooks=[PDF_BOOK])
        url = self.make_url('pdf_book', book_index=0, chapter=2)
Ned Batchelder committed
133 134 135 136 137 138 139
        response = self.client.get(url)
        self.assertContains(response, "Chapter 2 for PDF")
        self.assertContains(response, "options.chapterNum = 2;")
        self.assertNotContains(response, "options.pageNum =")

    def test_book_page(self):
        # We can access a book at a particular page.
140 141
        self.make_course(pdf_textbooks=[PDF_BOOK])
        url = self.make_url('pdf_book', book_index=0, page=17)
Ned Batchelder committed
142 143 144 145 146 147 148
        response = self.client.get(url)
        self.assertContains(response, "Chapter 1 for PDF")
        self.assertNotContains(response, "options.chapterNum =")
        self.assertContains(response, "options.pageNum = 17;")

    def test_book_chapter_page(self):
        # We can access a book at a particular chapter and page.
149 150
        self.make_course(pdf_textbooks=[PDF_BOOK])
        url = self.make_url('pdf_book', book_index=0, chapter=2, page=17)
Ned Batchelder committed
151 152 153 154 155 156
        response = self.client.get(url)
        self.assertContains(response, "Chapter 2 for PDF")
        self.assertContains(response, "options.chapterNum = 2;")
        self.assertContains(response, "options.pageNum = 17;")

    def test_bad_book_id(self):
157 158 159 160 161 162
        # If the book id isn't an int, we'll get a 404.
        self.make_course(pdf_textbooks=[PDF_BOOK])
        with self.assertRaises(NoReverseMatch):
            self.make_url('pdf_book', book_index='fooey', chapter=1)

    def test_out_of_range_book_id(self):
Ned Batchelder committed
163
        # If we have one book, asking for the second book will fail with a 404.
164 165
        self.make_course(pdf_textbooks=[PDF_BOOK])
        url = self.make_url('pdf_book', book_index=1, chapter=1)
Ned Batchelder committed
166 167 168 169 170
        response = self.client.get(url)
        self.assertEqual(response.status_code, 404)

    def test_no_book(self):
        # If we have no books, asking for the first book will fail with a 404.
171 172
        self.make_course()
        url = self.make_url('pdf_book', book_index=0, chapter=1)
Ned Batchelder committed
173 174 175
        response = self.client.get(url)
        self.assertEqual(response.status_code, 404)

176 177
    def test_chapter_xss(self):
        # The chapter in the URL used to go right on the page.
178
        self.make_course(pdf_textbooks=[PDF_BOOK])
179 180
        # It's no longer possible to use a non-integer chapter.
        with self.assertRaises(NoReverseMatch):
181
            self.make_url('pdf_book', book_index=0, chapter='xyzzy')
182 183 184

    def test_page_xss(self):
        # The page in the URL used to go right on the page.
185
        self.make_course(pdf_textbooks=[PDF_BOOK])
186 187
        # It's no longer possible to use a non-integer page.
        with self.assertRaises(NoReverseMatch):
188
            self.make_url('pdf_book', book_index=0, page='xyzzy')
189

190 191 192 193 194 195 196
    def test_chapter_page_xss(self):
        # The page in the URL used to go right on the page.
        self.make_course(pdf_textbooks=[PDF_BOOK])
        # It's no longer possible to use a non-integer page and a non-integer chapter.
        with self.assertRaises(NoReverseMatch):
            self.make_url('pdf_book', book_index=0, chapter='fooey', page='xyzzy')

Ned Batchelder committed
197 198 199 200 201 202 203 204

class StaticHtmlBookTest(StaticBookTest):
    """
    Test the HTML static book view.
    """

    def test_book(self):
        # We can access a book.
205 206
        self.make_course(html_textbooks=[HTML_BOOK])
        url = self.make_url('html_book', book_index=0)
Ned Batchelder committed
207 208 209 210 211 212
        response = self.client.get(url)
        self.assertContains(response, "Chapter 1 for HTML")
        self.assertNotContains(response, "options.chapterNum =")

    def test_book_chapter(self):
        # We can access a book at a particular chapter.
213 214
        self.make_course(html_textbooks=[HTML_BOOK])
        url = self.make_url('html_book', book_index=0, chapter=2)
Ned Batchelder committed
215 216 217 218 219 220
        response = self.client.get(url)
        self.assertContains(response, "Chapter 2 for HTML")
        self.assertContains(response, "options.chapterNum = 2;")

    def test_bad_book_id(self):
        # If we have one book, asking for the second book will fail with a 404.
221 222
        self.make_course(html_textbooks=[HTML_BOOK])
        url = self.make_url('html_book', book_index=1, chapter=1)
Ned Batchelder committed
223 224 225 226 227
        response = self.client.get(url)
        self.assertEqual(response.status_code, 404)

    def test_no_book(self):
        # If we have no books, asking for the first book will fail with a 404.
228 229
        self.make_course()
        url = self.make_url('html_book', book_index=0, chapter=1)
Ned Batchelder committed
230 231
        response = self.client.get(url)
        self.assertEqual(response.status_code, 404)
232 233 234

    def test_chapter_xss(self):
        # The chapter in the URL used to go right on the page.
235
        self.make_course(pdf_textbooks=[HTML_BOOK])
236 237
        # It's no longer possible to use a non-integer chapter.
        with self.assertRaises(NoReverseMatch):
238
            self.make_url('html_book', book_index=0, chapter='xyzzy')