test_forms.py 6.55 KB
Newer Older
1 2 3
"""
Tests for Discussion API forms
"""
4
import itertools
5
from unittest import TestCase
6 7
from urllib import urlencode

8 9
import ddt

10
from django.http import QueryDict
11 12 13

from opaque_keys.edx.locator import CourseLocator

14
from discussion_api.forms import CommentListGetForm, ThreadListGetForm
15 16


17 18
class FormTestMixin(object):
    """A mixin for testing forms"""
19 20 21 22 23
    def get_form(self, expected_valid):
        """
        Return a form bound to self.form_data, asserting its validity (or lack
        thereof) according to expected_valid
        """
24
        form = self.FORM_CLASS(self.form_data)
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
        self.assertEqual(form.is_valid(), expected_valid)
        return form

    def assert_error(self, expected_field, expected_message):
        """
        Create a form bound to self.form_data, assert its invalidity, and assert
        that its error dictionary contains one entry with the expected field and
        message
        """
        form = self.get_form(expected_valid=False)
        self.assertEqual(form.errors, {expected_field: [expected_message]})

    def assert_field_value(self, field, expected_value):
        """
        Create a form bound to self.form_data, assert its validity, and assert
        that the given field in the cleaned data has the expected value
        """
        form = self.get_form(expected_valid=True)
        self.assertEqual(form.cleaned_data[field], expected_value)

45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68

class PaginationTestMixin(object):
    """A mixin for testing forms with pagination fields"""
    def test_missing_page(self):
        self.form_data.pop("page")
        self.assert_field_value("page", 1)

    def test_invalid_page(self):
        self.form_data["page"] = "0"
        self.assert_error("page", "Ensure this value is greater than or equal to 1.")

    def test_missing_page_size(self):
        self.form_data.pop("page_size")
        self.assert_field_value("page_size", 10)

    def test_zero_page_size(self):
        self.form_data["page_size"] = "0"
        self.assert_error("page_size", "Ensure this value is greater than or equal to 1.")

    def test_excessive_page_size(self):
        self.form_data["page_size"] = "101"
        self.assert_field_value("page_size", 100)


69
@ddt.ddt
70 71 72 73 74 75
class ThreadListGetFormTest(FormTestMixin, PaginationTestMixin, TestCase):
    """Tests for ThreadListGetForm"""
    FORM_CLASS = ThreadListGetForm

    def setUp(self):
        super(ThreadListGetFormTest, self).setUp()
76 77 78 79 80 81 82 83 84 85
        self.form_data = QueryDict(
            urlencode(
                {
                    "course_id": "Foo/Bar/Baz",
                    "page": "2",
                    "page_size": "13",
                }
            ),
            mutable=True
        )
86

87 88 89 90 91 92 93 94
    def test_basic(self):
        form = self.get_form(expected_valid=True)
        self.assertEqual(
            form.cleaned_data,
            {
                "course_id": CourseLocator.from_string("Foo/Bar/Baz"),
                "page": 2,
                "page_size": 13,
95 96
                "topic_id": [],
                "text_search": "",
97
                "following": None,
98 99 100
                "view": "",
                "order_by": "last_activity_at",
                "order_direction": "desc",
101 102 103
            }
        )

104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
    def test_topic_id(self):
        self.form_data.setlist("topic_id", ["example topic_id", "example 2nd topic_id"])
        form = self.get_form(expected_valid=True)
        self.assertEqual(
            form.cleaned_data["topic_id"],
            ["example topic_id", "example 2nd topic_id"],
        )

    def test_text_search(self):
        self.form_data["text_search"] = "test search string"
        form = self.get_form(expected_valid=True)
        self.assertEqual(
            form.cleaned_data["text_search"],
            "test search string",
        )

120 121 122 123 124 125 126 127
    def test_missing_course_id(self):
        self.form_data.pop("course_id")
        self.assert_error("course_id", "This field is required.")

    def test_invalid_course_id(self):
        self.form_data["course_id"] = "invalid course id"
        self.assert_error("course_id", "'invalid course id' is not a valid course id")

128 129 130 131
    def test_empty_topic_id(self):
        self.form_data.setlist("topic_id", ["", "not empty"])
        self.assert_error("topic_id", "This field cannot be empty.")

132 133 134 135 136 137 138 139 140
    def test_following_true(self):
        self.form_data["following"] = "True"
        self.assert_field_value("following", True)

    def test_following_false(self):
        self.form_data["following"] = "False"
        self.assert_error("following", "The value of the 'following' parameter must be true.")

    @ddt.data(*itertools.combinations(["topic_id", "text_search", "following"], 2))
141
    def test_mutually_exclusive(self, params):
142
        self.form_data.update({param: "True" for param in params})
143 144
        self.assert_error(
            "__all__",
145
            "The following query parameters are mutually exclusive: topic_id, text_search, following"
146 147
        )

148 149 150 151
    def test_invalid_view_choice(self):
        self.form_data["view"] = "not_a_valid_choice"
        self.assert_error("view", "Select a valid choice. not_a_valid_choice is not one of the available choices.")

152 153 154 155 156 157 158 159 160 161 162 163 164 165
    def test_invalid_sort_by_choice(self):
        self.form_data["order_by"] = "not_a_valid_choice"
        self.assert_error(
            "order_by",
            "Select a valid choice. not_a_valid_choice is not one of the available choices."
        )

    def test_invalid_sort_direction_choice(self):
        self.form_data["order_direction"] = "not_a_valid_choice"
        self.assert_error(
            "order_direction",
            "Select a valid choice. not_a_valid_choice is not one of the available choices."
        )

166

167 168 169
class CommentListGetFormTest(FormTestMixin, PaginationTestMixin, TestCase):
    """Tests for CommentListGetForm"""
    FORM_CLASS = CommentListGetForm
170

171 172 173 174 175 176 177 178
    def setUp(self):
        super(CommentListGetFormTest, self).setUp()
        self.form_data = {
            "thread_id": "deadbeef",
            "endorsed": "False",
            "page": "2",
            "page_size": "13",
        }
179

180 181 182 183 184 185 186 187 188
    def test_basic(self):
        form = self.get_form(expected_valid=True)
        self.assertEqual(
            form.cleaned_data,
            {
                "thread_id": "deadbeef",
                "endorsed": False,
                "page": 2,
                "page_size": 13,
189
                "mark_as_read": False
190 191
            }
        )
192

193 194 195 196 197 198 199
    def test_missing_thread_id(self):
        self.form_data.pop("thread_id")
        self.assert_error("thread_id", "This field is required.")

    def test_missing_endorsed(self):
        self.form_data.pop("endorsed")
        self.assert_field_value("endorsed", None)