diff --git a/lms/djangoapps/django_comment_client/base/tests.py b/lms/djangoapps/django_comment_client/base/tests.py index e1c6d7ba12..37bc7f7892 100644 --- a/lms/djangoapps/django_comment_client/base/tests.py +++ b/lms/djangoapps/django_comment_client/base/tests.py @@ -1,14 +1,18 @@ import logging +import json from django.test.utils import override_settings -from django.test.client import Client +from django.test.client import Client, RequestFactory from django.contrib.auth.models import User -from student.tests.factories import CourseEnrollmentFactory +from student.tests.factories import CourseEnrollmentFactory, UserFactory from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from django.core.urlresolvers import reverse from django.core.management import call_command from util.testing import UrlResetMixin +from django_comment_common.utils import seed_permissions_roles +from django_comment_client.base import views +from django_comment_client.tests.unicode import UnicodeTestMixin from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE from nose.tools import assert_true, assert_equal # pylint: disable=E0611 @@ -334,3 +338,121 @@ class ViewsTestCase(UrlResetMixin, ModuleStoreTestCase): assert_equal(call_list, mock_request.call_args_list) assert_equal(response.status_code, 200) + + +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) +class CreateThreadUnicodeTestCase(ModuleStoreTestCase, UnicodeTestMixin): + def setUp(self): + self.course = CourseFactory.create() + seed_permissions_roles(self.course.id) + self.student = UserFactory.create() + CourseEnrollmentFactory(user=self.student, course_id=self.course.id) + + @patch('lms.lib.comment_client.utils.requests.request') + def _test_unicode_data(self, text, mock_request): + mock_request.return_value.text = "{}" + request = RequestFactory().post("dummy_url", {"body": text, "title": text}) + request.user = self.student + request.view_name = "create_thread" + response = views.create_thread(request, course_id=self.course.id, commentable_id="test_commentable") + + self.assertEqual(response.status_code, 200) + self.assertTrue(mock_request.called) + self.assertEqual(mock_request.call_args[1]["data"]["body"], text) + self.assertEqual(mock_request.call_args[1]["data"]["title"], text) + + +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) +class UpdateThreadUnicodeTestCase(ModuleStoreTestCase, UnicodeTestMixin): + def setUp(self): + self.course = CourseFactory.create() + seed_permissions_roles(self.course.id) + self.student = UserFactory.create() + CourseEnrollmentFactory(user=self.student, course_id=self.course.id) + + @patch('lms.lib.comment_client.utils.requests.request') + def _test_unicode_data(self, text, mock_request): + mock_request.return_value.text = json.dumps({ + "user_id": str(self.student.id), + "closed": False, + }) + request = RequestFactory().post("dummy_url", {"body": text, "title": text}) + request.user = self.student + request.view_name = "update_thread" + response = views.update_thread(request, course_id=self.course.id, thread_id="dummy_thread_id") + + self.assertEqual(response.status_code, 200) + self.assertTrue(mock_request.called) + self.assertEqual(mock_request.call_args[1]["data"]["body"], text) + self.assertEqual(mock_request.call_args[1]["data"]["title"], text) + + +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) +class CreateCommentUnicodeTestCase(ModuleStoreTestCase, UnicodeTestMixin): + def setUp(self): + self.course = CourseFactory.create() + seed_permissions_roles(self.course.id) + self.student = UserFactory.create() + CourseEnrollmentFactory(user=self.student, course_id=self.course.id) + + @patch('lms.lib.comment_client.utils.requests.request') + def _test_unicode_data(self, text, mock_request): + mock_request.return_value.text = json.dumps({ + "closed": False, + }) + request = RequestFactory().post("dummy_url", {"body": text}) + request.user = self.student + request.view_name = "create_comment" + response = views.create_comment(request, course_id=self.course.id, thread_id="dummy_thread_id") + + self.assertEqual(response.status_code, 200) + self.assertTrue(mock_request.called) + self.assertEqual(mock_request.call_args[1]["data"]["body"], text) + + +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) +class UpdateCommentUnicodeTestCase(ModuleStoreTestCase, UnicodeTestMixin): + def setUp(self): + self.course = CourseFactory.create() + seed_permissions_roles(self.course.id) + self.student = UserFactory.create() + CourseEnrollmentFactory(user=self.student, course_id=self.course.id) + + @patch('lms.lib.comment_client.utils.requests.request') + def _test_unicode_data(self, text, mock_request): + mock_request.return_value.text = json.dumps({ + "user_id": str(self.student.id), + "closed": False, + }) + request = RequestFactory().post("dummy_url", {"body": text}) + request.user = self.student + request.view_name = "update_comment" + response = views.update_comment(request, course_id=self.course.id, comment_id="dummy_comment_id") + + self.assertEqual(response.status_code, 200) + self.assertTrue(mock_request.called) + self.assertEqual(mock_request.call_args[1]["data"]["body"], text) + + +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) +class CreateSubCommentUnicodeTestCase(ModuleStoreTestCase, UnicodeTestMixin): + def setUp(self): + self.course = CourseFactory.create() + seed_permissions_roles(self.course.id) + self.student = UserFactory.create() + CourseEnrollmentFactory(user=self.student, course_id=self.course.id) + + @patch('lms.lib.comment_client.utils.requests.request') + def _test_unicode_data(self, text, mock_request): + mock_request.return_value.text = json.dumps({ + "closed": False, + "depth": 1, + }) + request = RequestFactory().post("dummy_url", {"body": text}) + request.user = self.student + request.view_name = "create_sub_comment" + response = views.create_sub_comment(request, course_id=self.course.id, comment_id="dummy_comment_id") + + self.assertEqual(response.status_code, 200) + self.assertTrue(mock_request.called) + self.assertEqual(mock_request.call_args[1]["data"]["body"], text) diff --git a/lms/djangoapps/django_comment_client/forum/tests.py b/lms/djangoapps/django_comment_client/forum/tests.py index e8ebdb3e00..fa3d9c96b3 100644 --- a/lms/djangoapps/django_comment_client/forum/tests.py +++ b/lms/djangoapps/django_comment_client/forum/tests.py @@ -1,10 +1,13 @@ +import json from django.test.utils import override_settings -from django.test.client import Client +from django.test.client import Client, RequestFactory from xmodule.modulestore.tests.factories import CourseFactory from student.tests.factories import UserFactory, CourseEnrollmentFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from django.core.urlresolvers import reverse from util.testing import UrlResetMixin +from django_comment_client.tests.unicode import UnicodeTestMixin +from django_comment_client.forum import views from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE from nose.tools import assert_true # pylint: disable=E0611 @@ -80,3 +83,152 @@ class ViewsExceptionTestCase(UrlResetMixin, ModuleStoreTestCase): kwargs={'course_id': self.course.id, 'user_id': '12345'}) # There is no user 12345 self.response = self.client.get(url) self.assertEqual(self.response.status_code, 404) + + +def make_mock_request_impl(text, thread_id=None): + def mock_request_impl(*args, **kwargs): + url = args[1] + if url.endswith("threads"): + return Mock( + status_code=200, + text=json.dumps({ + "collection": [{ + "id": "dummy_thread_id", + "type": "thread", + "commentable_id": "dummy_commentable_id", + "title": text, + "body": text, + }] + }) + ) + elif thread_id and url.endswith(thread_id): + return Mock( + status_code=200, + text=json.dumps({ + "id": thread_id, + "type": "thread", + "title": text, + "body": text, + "commentable_id": "dummy_commentable_id", + "children": [{ + "id": "dummy_comment_id", + "type": "comment", + "body": text, + }], + }) + ) + else: # user query + return Mock( + status_code=200, + text=json.dumps({ + "upvoted_ids": [], + "downvoted_ids": [], + "subscribed_thread_ids": [], + }) + ) + return mock_request_impl + + +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) +class InlineDiscussionUnicodeTestCase(ModuleStoreTestCase, UnicodeTestMixin): + def setUp(self): + self.course = CourseFactory.create() + self.student = UserFactory.create() + CourseEnrollmentFactory(user=self.student, course_id=self.course.id) + + @patch('lms.lib.comment_client.utils.requests.request') + def _test_unicode_data(self, text, mock_request): + mock_request.side_effect = make_mock_request_impl(text) + request = RequestFactory().get("dummy_url") + request.user = self.student + + response = views.inline_discussion(request, self.course.id, "dummy_discussion_id") + self.assertEqual(response.status_code, 200) + response_data = json.loads(response.content) + self.assertEqual(response_data["discussion_data"][0]["title"], text) + self.assertEqual(response_data["discussion_data"][0]["body"], text) + + +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) +class ForumFormDiscussionUnicodeTestCase(ModuleStoreTestCase, UnicodeTestMixin): + def setUp(self): + self.course = CourseFactory.create() + self.student = UserFactory.create() + CourseEnrollmentFactory(user=self.student, course_id=self.course.id) + + @patch('lms.lib.comment_client.utils.requests.request') + def _test_unicode_data(self, text, mock_request): + mock_request.side_effect = make_mock_request_impl(text) + request = RequestFactory().get("dummy_url") + request.user = self.student + request.META["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" # so request.is_ajax() == True + + response = views.forum_form_discussion(request, self.course.id) + self.assertEqual(response.status_code, 200) + response_data = json.loads(response.content) + self.assertEqual(response_data["discussion_data"][0]["title"], text) + self.assertEqual(response_data["discussion_data"][0]["body"], text) + + +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) +class SingleThreadUnicodeTestCase(ModuleStoreTestCase, UnicodeTestMixin): + def setUp(self): + self.course = CourseFactory.create() + self.student = UserFactory.create() + CourseEnrollmentFactory(user=self.student, course_id=self.course.id) + + @patch('lms.lib.comment_client.utils.requests.request') + def _test_unicode_data(self, text, mock_request): + thread_id = "test_thread_id" + mock_request.side_effect = make_mock_request_impl(text, thread_id) + request = RequestFactory().get("dummy_url") + request.user = self.student + request.META["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" # so request.is_ajax() == True + + response = views.single_thread(request, self.course.id, "dummy_discussion_id", thread_id) + self.assertEqual(response.status_code, 200) + response_data = json.loads(response.content) + self.assertEqual(response_data["content"]["title"], text) + self.assertEqual(response_data["content"]["body"], text) + + +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) +class UserProfileUnicodeTestCase(ModuleStoreTestCase, UnicodeTestMixin): + def setUp(self): + self.course = CourseFactory.create() + self.student = UserFactory.create() + CourseEnrollmentFactory(user=self.student, course_id=self.course.id) + + @patch('lms.lib.comment_client.utils.requests.request') + def _test_unicode_data(self, text, mock_request): + mock_request.side_effect = make_mock_request_impl(text) + request = RequestFactory().get("dummy_url") + request.user = self.student + request.META["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" # so request.is_ajax() == True + + response = views.user_profile(request, self.course.id, str(self.student.id)) + self.assertEqual(response.status_code, 200) + response_data = json.loads(response.content) + self.assertEqual(response_data["discussion_data"][0]["title"], text) + self.assertEqual(response_data["discussion_data"][0]["body"], text) + + +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) +class FollowedThreadsUnicodeTestCase(ModuleStoreTestCase, UnicodeTestMixin): + def setUp(self): + self.course = CourseFactory.create() + self.student = UserFactory.create() + CourseEnrollmentFactory(user=self.student, course_id=self.course.id) + + @patch('lms.lib.comment_client.utils.requests.request') + def _test_unicode_data(self, text, mock_request): + mock_request.side_effect = make_mock_request_impl(text) + request = RequestFactory().get("dummy_url") + request.user = self.student + request.META["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" # so request.is_ajax() == True + + response = views.followed_threads(request, self.course.id, str(self.student.id)) + self.assertEqual(response.status_code, 200) + response_data = json.loads(response.content) + self.assertEqual(response_data["discussion_data"][0]["title"], text) + self.assertEqual(response_data["discussion_data"][0]["body"], text) diff --git a/lms/djangoapps/django_comment_client/tests/test_utils.py b/lms/djangoapps/django_comment_client/tests/test_utils.py index d0f6996a4b..8acb5a057e 100644 --- a/lms/djangoapps/django_comment_client/tests/test_utils.py +++ b/lms/djangoapps/django_comment_client/tests/test_utils.py @@ -1,3 +1,4 @@ +import json from datetime import datetime from pytz import UTC from django.core.urlresolvers import reverse @@ -5,6 +6,7 @@ from django.test import TestCase from django.test.utils import override_settings from student.tests.factories import UserFactory, CourseEnrollmentFactory from django_comment_client.tests.factories import RoleFactory +from django_comment_client.tests.unicode import UnicodeTestMixin import django_comment_client.utils as utils from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase @@ -496,3 +498,10 @@ class CategoryMapTestCase(ModuleStoreTestCase): "children": ["Chapter A", "Chapter B", "Chapter C"] } ) + + +class JsonResponseTestCase(TestCase, UnicodeTestMixin): + def _test_unicode_data(self, text): + response = utils.JsonResponse(text) + reparsed = json.loads(response.content) + self.assertEqual(reparsed, text) diff --git a/lms/djangoapps/django_comment_client/tests/unicode.py b/lms/djangoapps/django_comment_client/tests/unicode.py new file mode 100644 index 0000000000..4240d2636e --- /dev/null +++ b/lms/djangoapps/django_comment_client/tests/unicode.py @@ -0,0 +1,20 @@ +# coding=utf-8 + +class UnicodeTestMixin(object): + def test_ascii(self): + self._test_unicode_data(u"This post contains ASCII.") + + def test_latin_1(self): + self._test_unicode_data(u"Thís pøst çòñtáins Lätin-1 tæxt") + + def test_CJK(self): + self._test_unicode_data(u"イんノ丂 アo丂イ co刀イムノ刀丂 cフズ") + + def test_non_BMP(self): + self._test_unicode_data(u"𝕋𝕙𝕚𝕤 𝕡𝕠𝕤𝕥 𝕔𝕠𝕟𝕥𝕒𝕚𝕟𝕤 𝕔𝕙𝕒𝕣𝕒𝕔𝕥𝕖𝕣𝕤 𝕠𝕦𝕥𝕤𝕚𝕕𝕖 𝕥𝕙𝕖 𝔹𝕄ℙ") + + def test_special_chars(self): + self._test_unicode_data(u"\" This , post > contains < delimiter ] and [ other } special { characters ; that & may ' break things") + + def test_string_interp(self): + self._test_unicode_data(u"This post contains %s string interpolation #{syntax}")