replaced unittest assertions pytest assertions (#26544)

This commit is contained in:
Aarif
2021-02-19 11:59:44 +05:00
committed by GitHub
parent 0112339b20
commit a8b9733654
21 changed files with 1209 additions and 1639 deletions

View File

@@ -45,37 +45,37 @@ class TestStudentModuleHistoryBackends(TestCase):
def test_get_history_true_true(self): def test_get_history_true_true(self):
student_module = StudentModule.objects.all() student_module = StudentModule.objects.all()
history = BaseStudentModuleHistory.get_history(student_module) history = BaseStudentModuleHistory.get_history(student_module)
self.assertEqual(len(history), 6) assert len(history) == 6
self.assertEqual({'type': 'csmhe', 'order': 3}, json.loads(history[0].state)) assert {'type': 'csmhe', 'order': 3} == json.loads(history[0].state)
self.assertEqual({'type': 'csmhe', 'order': 2}, json.loads(history[1].state)) assert {'type': 'csmhe', 'order': 2} == json.loads(history[1].state)
self.assertEqual({'type': 'csmhe', 'order': 1}, json.loads(history[2].state)) assert {'type': 'csmhe', 'order': 1} == json.loads(history[2].state)
self.assertEqual({'type': 'csmh', 'order': 3}, json.loads(history[3].state)) assert {'type': 'csmh', 'order': 3} == json.loads(history[3].state)
self.assertEqual({'type': 'csmh', 'order': 2}, json.loads(history[4].state)) assert {'type': 'csmh', 'order': 2} == json.loads(history[4].state)
self.assertEqual({'type': 'csmh', 'order': 1}, json.loads(history[5].state)) assert {'type': 'csmh', 'order': 1} == json.loads(history[5].state)
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_CSMH_EXTENDED": True}) @patch.dict("django.conf.settings.FEATURES", {"ENABLE_CSMH_EXTENDED": True})
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_READING_FROM_MULTIPLE_HISTORY_TABLES": False}) @patch.dict("django.conf.settings.FEATURES", {"ENABLE_READING_FROM_MULTIPLE_HISTORY_TABLES": False})
def test_get_history_true_false(self): def test_get_history_true_false(self):
student_module = StudentModule.objects.all() student_module = StudentModule.objects.all()
history = BaseStudentModuleHistory.get_history(student_module) history = BaseStudentModuleHistory.get_history(student_module)
self.assertEqual(len(history), 3) assert len(history) == 3
self.assertEqual({'type': 'csmhe', 'order': 3}, json.loads(history[0].state)) assert {'type': 'csmhe', 'order': 3} == json.loads(history[0].state)
self.assertEqual({'type': 'csmhe', 'order': 2}, json.loads(history[1].state)) assert {'type': 'csmhe', 'order': 2} == json.loads(history[1].state)
self.assertEqual({'type': 'csmhe', 'order': 1}, json.loads(history[2].state)) assert {'type': 'csmhe', 'order': 1} == json.loads(history[2].state)
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_CSMH_EXTENDED": False}) @patch.dict("django.conf.settings.FEATURES", {"ENABLE_CSMH_EXTENDED": False})
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_READING_FROM_MULTIPLE_HISTORY_TABLES": True}) @patch.dict("django.conf.settings.FEATURES", {"ENABLE_READING_FROM_MULTIPLE_HISTORY_TABLES": True})
def test_get_history_false_true(self): def test_get_history_false_true(self):
student_module = StudentModule.objects.all() student_module = StudentModule.objects.all()
history = BaseStudentModuleHistory.get_history(student_module) history = BaseStudentModuleHistory.get_history(student_module)
self.assertEqual(len(history), 3) assert len(history) == 3
self.assertEqual({'type': 'csmh', 'order': 3}, json.loads(history[0].state)) assert {'type': 'csmh', 'order': 3} == json.loads(history[0].state)
self.assertEqual({'type': 'csmh', 'order': 2}, json.loads(history[1].state)) assert {'type': 'csmh', 'order': 2} == json.loads(history[1].state)
self.assertEqual({'type': 'csmh', 'order': 1}, json.loads(history[2].state)) assert {'type': 'csmh', 'order': 1} == json.loads(history[2].state)
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_CSMH_EXTENDED": False}) @patch.dict("django.conf.settings.FEATURES", {"ENABLE_CSMH_EXTENDED": False})
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_READING_FROM_MULTIPLE_HISTORY_TABLES": False}) @patch.dict("django.conf.settings.FEATURES", {"ENABLE_READING_FROM_MULTIPLE_HISTORY_TABLES": False})
def test_get_history_false_false(self): def test_get_history_false_false(self):
student_module = StudentModule.objects.all() student_module = StudentModule.objects.all()
history = BaseStudentModuleHistory.get_history(student_module) history = BaseStudentModuleHistory.get_history(student_module)
self.assertEqual(len(history), 0) assert len(history) == 0

View File

@@ -1,8 +1,6 @@
""" """
Provide tests for git_add_course management command. Provide tests for git_add_course management command.
""" """
import logging import logging
import os import os
import shutil import shutil
@@ -10,6 +8,7 @@ import subprocess
import unittest import unittest
from uuid import uuid4 from uuid import uuid4
import pytest
import six import six
from django.conf import settings from django.conf import settings
from django.core.management import call_command from django.core.management import call_command
@@ -31,7 +30,6 @@ from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from xmodule.modulestore.tests.mongo_connection import MONGO_HOST, MONGO_PORT_NUM from xmodule.modulestore.tests.mongo_connection import MONGO_HOST, MONGO_PORT_NUM
TEST_MONGODB_LOG = { TEST_MONGODB_LOG = {
'host': MONGO_HOST, 'host': MONGO_HOST,
'port': MONGO_PORT_NUM, 'port': MONGO_PORT_NUM,
@@ -108,16 +106,16 @@ class TestGitAddCourse(SharedModuleStoreTestCase):
""" """
Various exit path tests for test_add_repo Various exit path tests for test_add_repo
""" """
with self.assertRaises(GitImportErrorNoDir): with pytest.raises(GitImportErrorNoDir):
git_import.add_repo(self.TEST_REPO, None, None) git_import.add_repo(self.TEST_REPO, None, None)
os.mkdir(self.git_repo_dir) os.mkdir(self.git_repo_dir)
self.addCleanup(shutil.rmtree, self.git_repo_dir) self.addCleanup(shutil.rmtree, self.git_repo_dir)
with self.assertRaises(GitImportErrorUrlBad): with pytest.raises(GitImportErrorUrlBad):
git_import.add_repo('foo', None, None) git_import.add_repo('foo', None, None)
with self.assertRaises(GitImportErrorCannotPull): with pytest.raises(GitImportErrorCannotPull):
git_import.add_repo('file:///foobar.git', None, None) git_import.add_repo('file:///foobar.git', None, None)
# Test git repo that exists, but is "broken" # Test git repo that exists, but is "broken"
@@ -127,7 +125,7 @@ class TestGitAddCourse(SharedModuleStoreTestCase):
subprocess.check_output(['git', '--bare', 'init', ], stderr=subprocess.STDOUT, subprocess.check_output(['git', '--bare', 'init', ], stderr=subprocess.STDOUT,
cwd=bare_repo) cwd=bare_repo)
with self.assertRaises(GitImportErrorBadRepo): with pytest.raises(GitImportErrorBadRepo):
git_import.add_repo('file://{0}'.format(bare_repo), None, None) git_import.add_repo('file://{0}'.format(bare_repo), None, None)
def test_detached_repo(self): def test_detached_repo(self):
@@ -145,7 +143,7 @@ class TestGitAddCourse(SharedModuleStoreTestCase):
subprocess.check_output(['git', 'checkout', 'HEAD~2', ], subprocess.check_output(['git', 'checkout', 'HEAD~2', ],
stderr=subprocess.STDOUT, stderr=subprocess.STDOUT,
cwd=repo_dir / 'edx4edx_lite') cwd=repo_dir / 'edx4edx_lite')
with self.assertRaises(GitImportErrorCannotPull): with pytest.raises(GitImportErrorCannotPull):
git_import.add_repo(self.TEST_REPO, repo_dir / 'edx4edx_lite', None) git_import.add_repo(self.TEST_REPO, repo_dir / 'edx4edx_lite', None)
def test_branching(self): def test_branching(self):
@@ -159,7 +157,7 @@ class TestGitAddCourse(SharedModuleStoreTestCase):
self.addCleanup(shutil.rmtree, repo_dir) self.addCleanup(shutil.rmtree, repo_dir)
# Checkout non existent branch # Checkout non existent branch
with self.assertRaises(GitImportErrorRemoteBranchMissing): with pytest.raises(GitImportErrorRemoteBranchMissing):
git_import.add_repo(self.TEST_REPO, repo_dir / 'edx4edx_lite', 'asdfasdfasdf') git_import.add_repo(self.TEST_REPO, repo_dir / 'edx4edx_lite', 'asdfasdfasdf')
# Checkout new branch # Checkout new branch
@@ -168,7 +166,7 @@ class TestGitAddCourse(SharedModuleStoreTestCase):
self.TEST_BRANCH) self.TEST_BRANCH)
def_ms = modulestore() def_ms = modulestore()
# Validate that it is different than master # Validate that it is different than master
self.assertIsNotNone(def_ms.get_course(self.TEST_BRANCH_COURSE)) assert def_ms.get_course(self.TEST_BRANCH_COURSE) is not None
# Attempt to check out the same branch again to validate branch choosing # Attempt to check out the same branch again to validate branch choosing
# works # works
@@ -178,12 +176,12 @@ class TestGitAddCourse(SharedModuleStoreTestCase):
# Delete to test branching back to master # Delete to test branching back to master
def_ms.delete_course(self.TEST_BRANCH_COURSE, ModuleStoreEnum.UserID.test) def_ms.delete_course(self.TEST_BRANCH_COURSE, ModuleStoreEnum.UserID.test)
self.assertIsNone(def_ms.get_course(self.TEST_BRANCH_COURSE)) assert def_ms.get_course(self.TEST_BRANCH_COURSE) is None
git_import.add_repo(self.TEST_REPO, git_import.add_repo(self.TEST_REPO,
repo_dir / 'edx4edx_lite', repo_dir / 'edx4edx_lite',
'master') 'master')
self.assertIsNone(def_ms.get_course(self.TEST_BRANCH_COURSE)) assert def_ms.get_course(self.TEST_BRANCH_COURSE) is None
self.assertIsNotNone(def_ms.get_course(CourseKey.from_string(self.TEST_COURSE))) assert def_ms.get_course(CourseKey.from_string(self.TEST_COURSE)) is not None
def test_branch_exceptions(self): def test_branch_exceptions(self):
""" """
@@ -203,7 +201,7 @@ class TestGitAddCourse(SharedModuleStoreTestCase):
self.addCleanup(shutil.rmtree, repo_dir) self.addCleanup(shutil.rmtree, repo_dir)
rdir = '{0}/bare'.format(repo_dir) rdir = '{0}/bare'.format(repo_dir)
with self.assertRaises(GitImportErrorBadRepo): with pytest.raises(GitImportErrorBadRepo):
git_import.add_repo('file://{0}'.format(bare_repo), None, None) git_import.add_repo('file://{0}'.format(bare_repo), None, None)
# Get logger for checking strings in logs # Get logger for checking strings in logs
@@ -218,7 +216,7 @@ class TestGitAddCourse(SharedModuleStoreTestCase):
try: try:
git_import.switch_branch('master', rdir) git_import.switch_branch('master', rdir)
except GitImportError: except GitImportError:
self.assertIn('Unable to fetch remote', output.getvalue()) assert 'Unable to fetch remote' in output.getvalue()
shutil.move('{0}/not_bare.git'.format(settings.TEST_ROOT), bare_repo) shutil.move('{0}/not_bare.git'.format(settings.TEST_ROOT), bare_repo)
output.truncate(0) output.truncate(0)
@@ -227,6 +225,6 @@ class TestGitAddCourse(SharedModuleStoreTestCase):
['git', 'remote', 'rename', 'origin', 'blah', ], ['git', 'remote', 'rename', 'origin', 'blah', ],
stderr=subprocess.STDOUT, cwd=rdir stderr=subprocess.STDOUT, cwd=rdir
) )
with self.assertRaises(GitImportError): with pytest.raises(GitImportError):
git_import.switch_branch('master', rdir) git_import.switch_branch('master', rdir)
self.assertIn('Getting a list of remote branches failed', output.getvalue()) assert 'Getting a list of remote branches failed' in output.getvalue()

View File

@@ -165,15 +165,15 @@ class TestSysAdminMongoCourseImport(SysadminBaseTestCase):
self._mkdir(settings.GIT_REPO_DIR) self._mkdir(settings.GIT_REPO_DIR)
def_ms = modulestore() def_ms = modulestore()
self.assertNotEqual('xml', def_ms.get_modulestore_type(None)) assert 'xml' != def_ms.get_modulestore_type(None)
self._add_edx4edx() self._add_edx4edx()
course = def_ms.get_course(CourseLocator('MITx', 'edx4edx', 'edx4edx')) course = def_ms.get_course(CourseLocator('MITx', 'edx4edx', 'edx4edx'))
self.assertIsNotNone(course) assert course is not None
self._rm_edx4edx() self._rm_edx4edx()
course = def_ms.get_course(CourseLocator('MITx', 'edx4edx', 'edx4edx')) course = def_ms.get_course(CourseLocator('MITx', 'edx4edx', 'edx4edx'))
self.assertIsNone(course) assert course is None
def test_course_info(self): def test_course_info(self):
""" """
@@ -333,22 +333,22 @@ class TestSysAdminMongoCourseImport(SysadminBaseTestCase):
password='foo') password='foo')
response = self.client.get(reverse('gitlogs')) response = self.client.get(reverse('gitlogs'))
# Make sure our non privileged user doesn't have access to all logs # Make sure our non privileged user doesn't have access to all logs
self.assertEqual(response.status_code, 404) assert response.status_code == 404
# Or specific logs # Or specific logs
response = self.client.get(reverse('gitlogs_detail', kwargs={ response = self.client.get(reverse('gitlogs_detail', kwargs={
'course_id': 'course-v1:MITx+edx4edx+edx4edx' 'course_id': 'course-v1:MITx+edx4edx+edx4edx'
})) }))
self.assertEqual(response.status_code, 404) assert response.status_code == 404
# Add user as staff in course team # Add user as staff in course team
def_ms = modulestore() def_ms = modulestore()
course = def_ms.get_course(CourseLocator('MITx', 'edx4edx', 'edx4edx')) course = def_ms.get_course(CourseLocator('MITx', 'edx4edx', 'edx4edx'))
CourseStaffRole(course.id).add_users(self.user) CourseStaffRole(course.id).add_users(self.user)
self.assertTrue(CourseStaffRole(course.id).has_user(self.user)) assert CourseStaffRole(course.id).has_user(self.user)
logged_in = self.client.login(username=self.user.username, logged_in = self.client.login(username=self.user.username,
password='foo') password='foo')
self.assertTrue(logged_in) assert logged_in
response = self.client.get( response = self.client.get(
reverse('gitlogs_detail', kwargs={ reverse('gitlogs_detail', kwargs={

View File

@@ -1,3 +1,4 @@
import pytest
# pylint: skip-file # pylint: skip-file
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""Tests for django comment client views.""" """Tests for django comment client views."""
@@ -363,11 +364,11 @@ class ViewsTestCaseMixin(object):
}), }),
data={"body": "foo", "title": "foo", "commentable_id": "some_topic"} data={"body": "foo", "title": "foo", "commentable_id": "some_topic"}
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
data = json.loads(response.content.decode('utf-8')) data = json.loads(response.content.decode('utf-8'))
self.assertEqual(data['body'], 'foo') assert data['body'] == 'foo'
self.assertEqual(data['title'], 'foo') assert data['title'] == 'foo'
self.assertEqual(data['commentable_id'], 'some_topic') assert data['commentable_id'] == 'some_topic'
@ddt.ddt @ddt.ddt
@@ -525,7 +526,7 @@ class ViewsTestCase(
kwargs={"course_id": six.text_type(self.course_id), "thread_id": 'i4x-MITx-999-course-Robot_Super_Course'} kwargs={"course_id": six.text_type(self.course_id), "thread_id": 'i4x-MITx-999-course-Robot_Super_Course'}
) )
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
def test_delete_thread(self, mock_request): def test_delete_thread(self, mock_request):
self._set_mock_request_data(mock_request, { self._set_mock_request_data(mock_request, {
@@ -542,8 +543,8 @@ class ViewsTestCase(
course_id=six.text_type(self.course.id), course_id=six.text_type(self.course.id),
thread_id=test_thread_id thread_id=test_thread_id
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertTrue(mock_request.called) assert mock_request.called
def test_delete_comment(self, mock_request): def test_delete_comment(self, mock_request):
self._set_mock_request_data(mock_request, { self._set_mock_request_data(mock_request, {
@@ -560,11 +561,11 @@ class ViewsTestCase(
course_id=six.text_type(self.course.id), course_id=six.text_type(self.course.id),
comment_id=test_comment_id comment_id=test_comment_id
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertTrue(mock_request.called) assert mock_request.called
args = mock_request.call_args[0] args = mock_request.call_args[0]
self.assertEqual(args[0], "delete") assert args[0] == 'delete'
self.assertTrue(args[1].endswith("/{}".format(test_comment_id))) assert args[1].endswith('/{}'.format(test_comment_id))
def _test_request_error(self, view_name, view_kwargs, data, mock_request): def _test_request_error(self, view_name, view_kwargs, data, mock_request):
""" """
@@ -575,9 +576,9 @@ class ViewsTestCase(
self._setup_mock_request(mock_request, include_depth=(view_name == "create_sub_comment")) self._setup_mock_request(mock_request, include_depth=(view_name == "create_sub_comment"))
response = self.client.post(reverse(view_name, kwargs=view_kwargs), data=data) response = self.client.post(reverse(view_name, kwargs=view_kwargs), data=data)
self.assertEqual(response.status_code, 400) assert response.status_code == 400
for call in mock_request.call_args_list: for call in mock_request.call_args_list:
self.assertEqual(call[0][0].lower(), "get") assert call[0][0].lower() == 'get'
def test_create_thread_no_title(self, mock_request): def test_create_thread_no_title(self, mock_request):
self._test_request_error( self._test_request_error(
@@ -669,7 +670,7 @@ class ViewsTestCase(
), ),
data={"body": "body"} data={"body": "body"}
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
def test_create_comment_no_body(self, mock_request): def test_create_comment_no_body(self, mock_request):
self._test_request_error( self._test_request_error(
@@ -731,7 +732,7 @@ class ViewsTestCase(
), ),
data={"body": updated_body} data={"body": updated_body}
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
mock_request.assert_called_with( mock_request.assert_called_with(
"put", "put",
"{prefix}/comments/{comment_id}".format(prefix=CS_PREFIX, comment_id=comment_id), "{prefix}/comments/{comment_id}".format(prefix=CS_PREFIX, comment_id=comment_id),
@@ -1052,7 +1053,7 @@ class ViewsTestCase(
kwargs={item_id: 'dummy', 'course_id': six.text_type(self.course_id)} kwargs={item_id: 'dummy', 'course_id': six.text_type(self.course_id)}
) )
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
def test_endorse_comment(self, mock_request): def test_endorse_comment(self, mock_request):
self._setup_mock_request(mock_request) self._setup_mock_request(mock_request)
@@ -1064,7 +1065,7 @@ class ViewsTestCase(
kwargs={'comment_id': 'dummy', 'course_id': six.text_type(self.course_id)} kwargs={'comment_id': 'dummy', 'course_id': six.text_type(self.course_id)}
) )
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
@patch("openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request", autospec=True) @patch("openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request", autospec=True)
@@ -1102,7 +1103,7 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
response = self.client.post( response = self.client.post(
reverse("pin_thread", kwargs={"course_id": six.text_type(self.course.id), "thread_id": "dummy"}) reverse("pin_thread", kwargs={"course_id": six.text_type(self.course.id), "thread_id": "dummy"})
) )
self.assertEqual(response.status_code, 401) assert response.status_code == 401
def test_pin_thread_as_moderator(self, mock_request): def test_pin_thread_as_moderator(self, mock_request):
self._set_mock_request_data(mock_request, {}) self._set_mock_request_data(mock_request, {})
@@ -1110,7 +1111,7 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
response = self.client.post( response = self.client.post(
reverse("pin_thread", kwargs={"course_id": six.text_type(self.course.id), "thread_id": "dummy"}) reverse("pin_thread", kwargs={"course_id": six.text_type(self.course.id), "thread_id": "dummy"})
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
def test_un_pin_thread_as_student(self, mock_request): def test_un_pin_thread_as_student(self, mock_request):
self._set_mock_request_data(mock_request, {}) self._set_mock_request_data(mock_request, {})
@@ -1118,7 +1119,7 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
response = self.client.post( response = self.client.post(
reverse("un_pin_thread", kwargs={"course_id": six.text_type(self.course.id), "thread_id": "dummy"}) reverse("un_pin_thread", kwargs={"course_id": six.text_type(self.course.id), "thread_id": "dummy"})
) )
self.assertEqual(response.status_code, 401) assert response.status_code == 401
def test_un_pin_thread_as_moderator(self, mock_request): def test_un_pin_thread_as_moderator(self, mock_request):
self._set_mock_request_data(mock_request, {}) self._set_mock_request_data(mock_request, {})
@@ -1126,7 +1127,7 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
response = self.client.post( response = self.client.post(
reverse("un_pin_thread", kwargs={"course_id": six.text_type(self.course.id), "thread_id": "dummy"}) reverse("un_pin_thread", kwargs={"course_id": six.text_type(self.course.id), "thread_id": "dummy"})
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
def _set_mock_request_thread_and_comment(self, mock_request, thread_data, comment_data): def _set_mock_request_thread_and_comment(self, mock_request, thread_data, comment_data):
def handle_request(*args, **kwargs): def handle_request(*args, **kwargs):
@@ -1149,7 +1150,7 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
response = self.client.post( response = self.client.post(
reverse("endorse_comment", kwargs={"course_id": six.text_type(self.course.id), "comment_id": "dummy"}) reverse("endorse_comment", kwargs={"course_id": six.text_type(self.course.id), "comment_id": "dummy"})
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
def test_endorse_response_as_student(self, mock_request): def test_endorse_response_as_student(self, mock_request):
self._set_mock_request_thread_and_comment( self._set_mock_request_thread_and_comment(
@@ -1161,7 +1162,7 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
response = self.client.post( response = self.client.post(
reverse("endorse_comment", kwargs={"course_id": six.text_type(self.course.id), "comment_id": "dummy"}) reverse("endorse_comment", kwargs={"course_id": six.text_type(self.course.id), "comment_id": "dummy"})
) )
self.assertEqual(response.status_code, 401) assert response.status_code == 401
def test_endorse_response_as_student_question_author(self, mock_request): def test_endorse_response_as_student_question_author(self, mock_request):
self._set_mock_request_thread_and_comment( self._set_mock_request_thread_and_comment(
@@ -1173,7 +1174,7 @@ class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStor
response = self.client.post( response = self.client.post(
reverse("endorse_comment", kwargs={"course_id": six.text_type(self.course.id), "comment_id": "dummy"}) reverse("endorse_comment", kwargs={"course_id": six.text_type(self.course.id), "comment_id": "dummy"})
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
class CreateThreadUnicodeTestCase( class CreateThreadUnicodeTestCase(
@@ -1210,10 +1211,10 @@ class CreateThreadUnicodeTestCase(
request, course_id=six.text_type(self.course.id), commentable_id=u"non_tåem_dummy_id" request, course_id=six.text_type(self.course.id), commentable_id=u"non_tåem_dummy_id"
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertTrue(mock_request.called) assert mock_request.called
self.assertEqual(mock_request.call_args[1]["data"]["body"], text) assert mock_request.call_args[1]['data']['body'] == text
self.assertEqual(mock_request.call_args[1]["data"]["title"], text) assert mock_request.call_args[1]['data']['title'] == text
@disable_signal(views, 'thread_edited') @disable_signal(views, 'thread_edited')
@@ -1253,12 +1254,12 @@ class UpdateThreadUnicodeTestCase(
request.view_name = "update_thread" request.view_name = "update_thread"
response = views.update_thread(request, course_id=six.text_type(self.course.id), thread_id="dummy_thread_id") response = views.update_thread(request, course_id=six.text_type(self.course.id), thread_id="dummy_thread_id")
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertTrue(mock_request.called) assert mock_request.called
self.assertEqual(mock_request.call_args[1]["data"]["body"], text) assert mock_request.call_args[1]['data']['body'] == text
self.assertEqual(mock_request.call_args[1]["data"]["title"], text) assert mock_request.call_args[1]['data']['title'] == text
self.assertEqual(mock_request.call_args[1]["data"]["thread_type"], "question") assert mock_request.call_args[1]['data']['thread_type'] == 'question'
self.assertEqual(mock_request.call_args[1]["data"]["commentable_id"], "test_commentable") assert mock_request.call_args[1]['data']['commentable_id'] == 'test_commentable'
@disable_signal(views, 'comment_created') @disable_signal(views, 'comment_created')
@@ -1301,9 +1302,9 @@ class CreateCommentUnicodeTestCase(
request, course_id=six.text_type(self.course.id), thread_id="dummy_thread_id" request, course_id=six.text_type(self.course.id), thread_id="dummy_thread_id"
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertTrue(mock_request.called) assert mock_request.called
self.assertEqual(mock_request.call_args[1]["data"]["body"], text) assert mock_request.call_args[1]['data']['body'] == text
finally: finally:
del Thread.commentable_id del Thread.commentable_id
@@ -1341,9 +1342,9 @@ class UpdateCommentUnicodeTestCase(
request.view_name = "update_comment" request.view_name = "update_comment"
response = views.update_comment(request, course_id=six.text_type(self.course.id), comment_id="dummy_comment_id") response = views.update_comment(request, course_id=six.text_type(self.course.id), comment_id="dummy_comment_id")
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertTrue(mock_request.called) assert mock_request.called
self.assertEqual(mock_request.call_args[1]["data"]["body"], text) assert mock_request.call_args[1]['data']['body'] == text
@disable_signal(views, 'comment_created') @disable_signal(views, 'comment_created')
@@ -1390,9 +1391,9 @@ class CreateSubCommentUnicodeTestCase(
request, course_id=six.text_type(self.course.id), comment_id="dummy_comment_id" request, course_id=six.text_type(self.course.id), comment_id="dummy_comment_id"
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertTrue(mock_request.called) assert mock_request.called
self.assertEqual(mock_request.call_args[1]["data"]["body"], text) assert mock_request.call_args[1]['data']['body'] == text
finally: finally:
del Thread.commentable_id del Thread.commentable_id
@@ -1567,7 +1568,7 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
), ),
data={"body": "foo", "title": "foo", "commentable_id": commentable_id} data={"body": "foo", "title": "foo", "commentable_id": commentable_id}
) )
self.assertEqual(response.status_code, status_code) assert response.status_code == status_code
@ddt.data( @ddt.data(
# Students can delete their own posts # Students can delete their own posts
@@ -1611,7 +1612,7 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
), ),
data={"body": "foo", "title": "foo"} data={"body": "foo", "title": "foo"}
) )
self.assertEqual(response.status_code, status_code) assert response.status_code == status_code
@ddt.data(*ddt_permissions_args) @ddt.data(*ddt_permissions_args)
@ddt.unpack @ddt.unpack
@@ -1632,7 +1633,7 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
), ),
data={"body": "foo", "title": "foo"} data={"body": "foo", "title": "foo"}
) )
self.assertEqual(response.status_code, status_code) assert response.status_code == status_code
@ddt.data(*ddt_permissions_args) @ddt.data(*ddt_permissions_args)
@ddt.unpack @ddt.unpack
@@ -1655,7 +1656,7 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
), ),
data={"body": "foo", "title": "foo"} data={"body": "foo", "title": "foo"}
) )
self.assertEqual(response.status_code, status_code) assert response.status_code == status_code
@ddt.data(*ddt_permissions_args) @ddt.data(*ddt_permissions_args)
@ddt.unpack @ddt.unpack
@@ -1676,7 +1677,7 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
kwargs={"course_id": six.text_type(self.course.id), "comment_id": "dummy_comment"} kwargs={"course_id": six.text_type(self.course.id), "comment_id": "dummy_comment"}
) )
) )
self.assertEqual(response.status_code, status_code) assert response.status_code == status_code
@ddt.data(*ddt_permissions_args) @ddt.data(*ddt_permissions_args)
@ddt.unpack @ddt.unpack
@@ -1698,7 +1699,7 @@ class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleSto
kwargs={"course_id": six.text_type(self.course.id), "thread_id": "dummy_thread"} kwargs={"course_id": six.text_type(self.course.id), "thread_id": "dummy_thread"}
) )
) )
self.assertEqual(response.status_code, status_code) assert response.status_code == status_code
TEAM_COMMENTABLE_ID = 'test-team-discussion' TEAM_COMMENTABLE_ID = 'test-team-discussion'
@@ -1744,13 +1745,13 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
views.create_comment(request, course_id=six.text_type(self.course.id), thread_id='test_thread_id') views.create_comment(request, course_id=six.text_type(self.course.id), thread_id='test_thread_id')
event_name, event = mock_emit.call_args[0] event_name, event = mock_emit.call_args[0]
self.assertEqual(event_name, 'edx.forum.response.created') assert event_name == 'edx.forum.response.created'
self.assertEqual(event['body'], "Test comment") assert event['body'] == 'Test comment'
self.assertEqual(event['commentable_id'], 'test_commentable_id') assert event['commentable_id'] == 'test_commentable_id'
self.assertEqual(event['user_forums_roles'], ['Student']) assert event['user_forums_roles'] == ['Student']
self.assertEqual(event['user_course_roles'], ['Wizard']) assert event['user_course_roles'] == ['Wizard']
self.assertEqual(event['discussion']['id'], 'test_thread_id') assert event['discussion']['id'] == 'test_thread_id'
self.assertEqual(event['options']['followed'], True) assert event['options']['followed'] is True
@patch('eventtracking.tracker.emit') @patch('eventtracking.tracker.emit')
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True) @patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@@ -1771,13 +1772,13 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
views.create_sub_comment(request, course_id=six.text_type(self.course.id), comment_id="dummy_comment_id") views.create_sub_comment(request, course_id=six.text_type(self.course.id), comment_id="dummy_comment_id")
event_name, event = mock_emit.call_args[0] event_name, event = mock_emit.call_args[0]
self.assertEqual(event_name, "edx.forum.comment.created") assert event_name == 'edx.forum.comment.created'
self.assertEqual(event['body'], 'Another comment') assert event['body'] == 'Another comment'
self.assertEqual(event['discussion']['id'], 'test_thread_id') assert event['discussion']['id'] == 'test_thread_id'
self.assertEqual(event['response']['id'], 'test_response_id') assert event['response']['id'] == 'test_response_id'
self.assertEqual(event['user_forums_roles'], ['Student']) assert event['user_forums_roles'] == ['Student']
self.assertEqual(event['user_course_roles'], ['Wizard']) assert event['user_course_roles'] == ['Wizard']
self.assertEqual(event['options']['followed'], False) assert event['options']['followed'] is False
@patch('eventtracking.tracker.emit') @patch('eventtracking.tracker.emit')
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True) @patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@@ -1820,8 +1821,8 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
getattr(views, view_name)(request, course_id=six.text_type(self.course.id), **view_kwargs) getattr(views, view_name)(request, course_id=six.text_type(self.course.id), **view_kwargs)
name, event = mock_emit.call_args[0] name, event = mock_emit.call_args[0]
self.assertEqual(name, event_name) assert name == event_name
self.assertEqual(event['team_id'], team.team_id) assert event['team_id'] == team.team_id
@ddt.data( @ddt.data(
('vote_for_thread', 'thread_id', 'thread'), ('vote_for_thread', 'thread_id', 'thread'),
@@ -1850,12 +1851,12 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
kwargs.update(value='up') kwargs.update(value='up')
view_function(request, **kwargs) view_function(request, **kwargs)
self.assertTrue(mock_emit.called) assert mock_emit.called
event_name, event = mock_emit.call_args[0] event_name, event = mock_emit.call_args[0]
self.assertEqual(event_name, 'edx.forum.{}.voted'.format(obj_type)) assert event_name == 'edx.forum.{}.voted'.format(obj_type)
self.assertEqual(event['target_username'], 'gumprecht') assert event['target_username'] == 'gumprecht'
self.assertEqual(event['undo_vote'], undo) assert event['undo_vote'] == undo
self.assertEqual(event['vote_value'], 'up') assert event['vote_value'] == 'up'
class UsersEndpointTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockRequestSetupMixin): class UsersEndpointTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockRequestSetupMixin):
@@ -1897,55 +1898,52 @@ class UsersEndpointTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockRe
def test_finds_exact_match(self, mock_request): def test_finds_exact_match(self, mock_request):
self.set_post_counts(mock_request) self.set_post_counts(mock_request)
response = self.make_request(username="other") response = self.make_request(username="other")
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertEqual( assert json.loads(response.content.decode('utf-8'))['users'] == [{'id': self.other_user.id, 'username': self.other_user.username}]
json.loads(response.content.decode('utf-8'))["users"],
[{"id": self.other_user.id, "username": self.other_user.username}]
)
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True) @patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
def test_finds_no_match(self, mock_request): def test_finds_no_match(self, mock_request):
self.set_post_counts(mock_request) self.set_post_counts(mock_request)
response = self.make_request(username="othor") response = self.make_request(username="othor")
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertEqual(json.loads(response.content.decode('utf-8'))["users"], []) assert json.loads(response.content.decode('utf-8'))['users'] == []
def test_requires_GET(self): def test_requires_GET(self):
response = self.make_request(method='post', username="other") response = self.make_request(method='post', username="other")
self.assertEqual(response.status_code, 405) assert response.status_code == 405
def test_requires_username_param(self): def test_requires_username_param(self):
response = self.make_request() response = self.make_request()
self.assertEqual(response.status_code, 400) assert response.status_code == 400
content = json.loads(response.content.decode('utf-8')) content = json.loads(response.content.decode('utf-8'))
self.assertIn("errors", content) assert 'errors' in content
self.assertNotIn("users", content) assert 'users' not in content
def test_course_does_not_exist(self): def test_course_does_not_exist(self):
course_id = CourseKey.from_string("does/not/exist") course_id = CourseKey.from_string("does/not/exist")
response = self.make_request(course_id=course_id, username="other") response = self.make_request(course_id=course_id, username="other")
self.assertEqual(response.status_code, 404) assert response.status_code == 404
content = json.loads(response.content.decode('utf-8')) content = json.loads(response.content.decode('utf-8'))
self.assertIn("errors", content) assert 'errors' in content
self.assertNotIn("users", content) assert 'users' not in content
def test_requires_requestor_enrolled_in_course(self): def test_requires_requestor_enrolled_in_course(self):
# unenroll self.student from the course. # unenroll self.student from the course.
self.enrollment.delete() self.enrollment.delete()
response = self.make_request(username="other") response = self.make_request(username="other")
self.assertEqual(response.status_code, 404) assert response.status_code == 404
content = json.loads(response.content.decode('utf-8')) content = json.loads(response.content.decode('utf-8'))
self.assertIn("errors", content) assert 'errors' in content
self.assertNotIn("users", content) assert 'users' not in content
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True) @patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
def test_requires_matched_user_has_forum_content(self, mock_request): def test_requires_matched_user_has_forum_content(self, mock_request):
self.set_post_counts(mock_request, 0, 0) self.set_post_counts(mock_request, 0, 0)
response = self.make_request(username="other") response = self.make_request(username="other")
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertEqual(json.loads(response.content.decode('utf-8'))["users"], []) assert json.loads(response.content.decode('utf-8'))['users'] == []
@ddt.ddt @ddt.ddt
@@ -1966,7 +1964,7 @@ class SegmentIOForumThreadViewedEventTestCase(SegmentIOTrackingTestCaseBase):
middleware.process_request(request) middleware.process_request(request)
try: try:
response = segmentio.segmentio_event(request) response = segmentio.segmentio_event(request)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
finally: finally:
middleware.process_response(request, None) middleware.process_response(request, None)
@@ -1981,8 +1979,8 @@ class SegmentIOForumThreadViewedEventTestCase(SegmentIOTrackingTestCaseBase):
""" """
self._raise_navigation_event('Forum: View Thread', include_name) self._raise_navigation_event('Forum: View Thread', include_name)
event = self.get_event() event = self.get_event()
self.assertEqual(event['name'], 'edx.forum.thread.viewed') assert event['name'] == 'edx.forum.thread.viewed'
self.assertEqual(event['event_type'], event['name']) assert event['event_type'] == event['name']
@ddt.data(True, False) @ddt.data(True, False)
def test_non_thread_viewed(self, include_name): def test_non_thread_viewed(self, include_name):
@@ -2095,7 +2093,7 @@ class ForumThreadViewedEventTransformerTestCase(ForumsEnableMixin, UrlResetMixin
def test_missing_context(self): def test_missing_context(self):
event = _create_event(include_context=False) event = _create_event(include_context=False)
with self.assertRaises(EventEmissionExit): with pytest.raises(EventEmissionExit):
_get_transformed_event(event) _get_transformed_event(event)
def test_no_data(self): def test_no_data(self):
@@ -2107,7 +2105,7 @@ class ForumThreadViewedEventTransformerTestCase(ForumsEnableMixin, UrlResetMixin
def test_inner_context(self): def test_inner_context(self):
_, event_trans = _create_and_transform_event(inner_context={}) _, event_trans = _create_and_transform_event(inner_context={})
self.assertNotIn('context', event_trans['event']) assert 'context' not in event_trans['event']
def test_non_thread_view(self): def test_non_thread_view(self):
event = _create_event( event = _create_event(
@@ -2116,7 +2114,7 @@ class ForumThreadViewedEventTransformerTestCase(ForumsEnableMixin, UrlResetMixin
topic_id=self.DUMMY_CATEGORY_ID, topic_id=self.DUMMY_CATEGORY_ID,
thread_id=self.DUMMY_THREAD_ID, thread_id=self.DUMMY_THREAD_ID,
) )
with self.assertRaises(EventEmissionExit): with pytest.raises(EventEmissionExit):
_get_transformed_event(event) _get_transformed_event(event)
def test_bad_field_types(self): def test_bad_field_types(self):
@@ -2133,19 +2131,19 @@ class ForumThreadViewedEventTransformerTestCase(ForumsEnableMixin, UrlResetMixin
def test_bad_course_id(self): def test_bad_course_id(self):
event, event_trans = _create_and_transform_event(course_id='non-existent-course-id') event, event_trans = _create_and_transform_event(course_id='non-existent-course-id')
event_data = event_trans['event'] event_data = event_trans['event']
self.assertNotIn('category_id', event_data) assert 'category_id' not in event_data
self.assertNotIn('category_name', event_data) assert 'category_name' not in event_data
self.assertNotIn('url', event_data) assert 'url' not in event_data
self.assertNotIn('user_forums_roles', event_data) assert 'user_forums_roles' not in event_data
self.assertNotIn('user_course_roles', event_data) assert 'user_course_roles' not in event_data
def test_bad_username(self): def test_bad_username(self):
event, event_trans = _create_and_transform_event(username='non-existent-username') event, event_trans = _create_and_transform_event(username='non-existent-username')
event_data = event_trans['event'] event_data = event_trans['event']
self.assertNotIn('category_id', event_data) assert 'category_id' not in event_data
self.assertNotIn('category_name', event_data) assert 'category_name' not in event_data
self.assertNotIn('user_forums_roles', event_data) assert 'user_forums_roles' not in event_data
self.assertNotIn('user_course_roles', event_data) assert 'user_course_roles' not in event_data
def test_bad_url(self): def test_bad_url(self):
event, event_trans = _create_and_transform_event( event, event_trans = _create_and_transform_event(
@@ -2153,7 +2151,7 @@ class ForumThreadViewedEventTransformerTestCase(ForumsEnableMixin, UrlResetMixin
topic_id='malformed/commentable/id', topic_id='malformed/commentable/id',
thread_id='malformed/thread/id', thread_id='malformed/thread/id',
) )
self.assertNotIn('url', event_trans['event']) assert 'url' not in event_trans['event']
def test_renamed_fields(self): def test_renamed_fields(self):
AUTHOR = 'joe-the-plumber' AUTHOR = 'joe-the-plumber'
@@ -2163,32 +2161,32 @@ class ForumThreadViewedEventTransformerTestCase(ForumsEnableMixin, UrlResetMixin
thread_id=self.DUMMY_THREAD_ID, thread_id=self.DUMMY_THREAD_ID,
author=AUTHOR, author=AUTHOR,
) )
self.assertEqual(event_trans['event']['commentable_id'], self.DUMMY_CATEGORY_ID) assert event_trans['event']['commentable_id'] == self.DUMMY_CATEGORY_ID
self.assertEqual(event_trans['event']['id'], self.DUMMY_THREAD_ID) assert event_trans['event']['id'] == self.DUMMY_THREAD_ID
self.assertEqual(event_trans['event']['target_username'], AUTHOR) assert event_trans['event']['target_username'] == AUTHOR
def test_titles(self): def test_titles(self):
# No title # No title
_, event_1_trans = _create_and_transform_event() _, event_1_trans = _create_and_transform_event()
self.assertNotIn('title', event_1_trans['event']) assert 'title' not in event_1_trans['event']
self.assertNotIn('title_truncated', event_1_trans['event']) assert 'title_truncated' not in event_1_trans['event']
# Short title # Short title
_, event_2_trans = _create_and_transform_event( _, event_2_trans = _create_and_transform_event(
action='!', action='!',
) )
self.assertIn('title', event_2_trans['event']) assert 'title' in event_2_trans['event']
self.assertIn('title_truncated', event_2_trans['event']) assert 'title_truncated' in event_2_trans['event']
self.assertFalse(event_2_trans['event']['title_truncated']) assert not event_2_trans['event']['title_truncated']
# Long title # Long title
_, event_3_trans = _create_and_transform_event( _, event_3_trans = _create_and_transform_event(
action=('covfefe' * 200), action=('covfefe' * 200),
) )
self.assertIn('title', event_3_trans['event']) assert 'title' in event_3_trans['event']
self.assertIn('title_truncated', event_3_trans['event']) assert 'title_truncated' in event_3_trans['event']
self.assertTrue(event_3_trans['event']['title_truncated']) assert event_3_trans['event']['title_truncated']
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
def test_urls(self, store): def test_urls(self, store):
@@ -2203,7 +2201,7 @@ class ForumThreadViewedEventTransformerTestCase(ForumsEnableMixin, UrlResetMixin
expected_path = '/courses/{0}/discussion/forum/{1}/threads/{2}'.format( expected_path = '/courses/{0}/discussion/forum/{1}/threads/{2}'.format(
course.id, commentable_id, thread_id course.id, commentable_id, thread_id
) )
self.assertTrue(event_trans['event'].get('url').endswith(expected_path)) assert event_trans['event'].get('url').endswith(expected_path)
def test_categories(self): def test_categories(self):
@@ -2213,8 +2211,8 @@ class ForumThreadViewedEventTransformerTestCase(ForumsEnableMixin, UrlResetMixin
course_id=self.course.id, course_id=self.course.id,
topic_id='non-existent-category-id', topic_id='non-existent-category-id',
) )
self.assertNotIn('category_id', event_trans_1['event']) assert 'category_id' not in event_trans_1['event']
self.assertNotIn('category_name', event_trans_1['event']) assert 'category_name' not in event_trans_1['event']
# Good category # Good category
_, event_trans_2 = _create_and_transform_event( _, event_trans_2 = _create_and_transform_event(
@@ -2222,9 +2220,9 @@ class ForumThreadViewedEventTransformerTestCase(ForumsEnableMixin, UrlResetMixin
course_id=self.course.id, course_id=self.course.id,
topic_id=self.category.discussion_id, topic_id=self.category.discussion_id,
) )
self.assertEqual(event_trans_2['event'].get('category_id'), self.category.discussion_id) assert event_trans_2['event'].get('category_id') == self.category.discussion_id
full_category_name = u'{0} / {1}'.format(self.category.discussion_category, self.category.discussion_target) full_category_name = u'{0} / {1}'.format(self.category.discussion_category, self.category.discussion_target)
self.assertEqual(event_trans_2['event'].get('category_name'), full_category_name) assert event_trans_2['event'].get('category_name') == full_category_name
def test_roles(self): def test_roles(self):
@@ -2232,24 +2230,24 @@ class ForumThreadViewedEventTransformerTestCase(ForumsEnableMixin, UrlResetMixin
_, event_trans_1 = _create_and_transform_event( _, event_trans_1 = _create_and_transform_event(
course_id=self.course.id, course_id=self.course.id,
) )
self.assertNotIn('user_forums_roles', event_trans_1['event']) assert 'user_forums_roles' not in event_trans_1['event']
self.assertNotIn('user_course_roles', event_trans_1['event']) assert 'user_course_roles' not in event_trans_1['event']
# Student user # Student user
_, event_trans_2 = _create_and_transform_event( _, event_trans_2 = _create_and_transform_event(
course_id=self.course.id, course_id=self.course.id,
username=self.student.username, username=self.student.username,
) )
self.assertEqual(event_trans_2['event'].get('user_forums_roles'), [FORUM_ROLE_STUDENT]) assert event_trans_2['event'].get('user_forums_roles') == [FORUM_ROLE_STUDENT]
self.assertEqual(event_trans_2['event'].get('user_course_roles'), []) assert event_trans_2['event'].get('user_course_roles') == []
# Course staff user # Course staff user
_, event_trans_3 = _create_and_transform_event( _, event_trans_3 = _create_and_transform_event(
course_id=self.course.id, course_id=self.course.id,
username=self.staff.username, username=self.staff.username,
) )
self.assertEqual(event_trans_3['event'].get('user_forums_roles'), []) assert event_trans_3['event'].get('user_forums_roles') == []
self.assertEqual(event_trans_3['event'].get('user_course_roles'), [CourseStaffRole.ROLE]) assert event_trans_3['event'].get('user_course_roles') == [CourseStaffRole.ROLE]
def test_teams(self): def test_teams(self):
@@ -2257,18 +2255,18 @@ class ForumThreadViewedEventTransformerTestCase(ForumsEnableMixin, UrlResetMixin
_, event_trans_1 = _create_and_transform_event( _, event_trans_1 = _create_and_transform_event(
course_id=self.course.id, course_id=self.course.id,
) )
self.assertNotIn('team_id', event_trans_1) assert 'team_id' not in event_trans_1
# Non-team category # Non-team category
_, event_trans_2 = _create_and_transform_event( _, event_trans_2 = _create_and_transform_event(
course_id=self.course.id, course_id=self.course.id,
topic_id=self.CATEGORY_ID, topic_id=self.CATEGORY_ID,
) )
self.assertNotIn('team_id', event_trans_2) assert 'team_id' not in event_trans_2
# Team category # Team category
_, event_trans_3 = _create_and_transform_event( _, event_trans_3 = _create_and_transform_event(
course_id=self.course.id, course_id=self.course.id,
topic_id=self.TEAM_CATEGORY_ID, topic_id=self.TEAM_CATEGORY_ID,
) )
self.assertEqual(event_trans_3['event'].get('team_id'), self.team.team_id) assert event_trans_3['event'].get('team_id') == self.team.team_id

View File

@@ -23,12 +23,12 @@ class GroupIdAssertionMixin(object):
return call[1]["data"] return call[1]["data"]
def _assert_comments_service_called_with_group_id(self, mock_request, group_id): def _assert_comments_service_called_with_group_id(self, mock_request, group_id):
self.assertTrue(mock_request.called) assert mock_request.called
self.assertEqual(self._data_or_params_cs_request(mock_request)["group_id"], group_id) assert self._data_or_params_cs_request(mock_request)['group_id'] == group_id
def _assert_comments_service_called_without_group_id(self, mock_request): def _assert_comments_service_called_without_group_id(self, mock_request):
self.assertTrue(mock_request.called) assert mock_request.called
self.assertNotIn("group_id", self._data_or_params_cs_request(mock_request)) assert 'group_id' not in self._data_or_params_cs_request(mock_request)
def _assert_html_response_contains_group_info(self, response): def _assert_html_response_contains_group_info(self, response):
group_info = {"group_id": None, "group_name": None} group_info = {"group_id": None, "group_name": None}
@@ -52,8 +52,8 @@ class GroupIdAssertionMixin(object):
self._assert_thread_contains_group_info(thread) self._assert_thread_contains_group_info(thread)
def _assert_thread_contains_group_info(self, thread): def _assert_thread_contains_group_info(self, thread):
self.assertEqual(thread['group_id'], self.student_cohort.id) assert thread['group_id'] == self.student_cohort.id
self.assertEqual(thread['group_name'], self.student_cohort.name) assert thread['group_name'] == self.student_cohort.name
class CohortedTopicGroupIdTestMixin(GroupIdAssertionMixin): class CohortedTopicGroupIdTestMixin(GroupIdAssertionMixin):
@@ -103,7 +103,7 @@ class CohortedTopicGroupIdTestMixin(GroupIdAssertionMixin):
def test_cohorted_topic_moderator_with_invalid_group_id(self, mock_request): def test_cohorted_topic_moderator_with_invalid_group_id(self, mock_request):
invalid_id = self.student_cohort.id + self.moderator_cohort.id invalid_id = self.student_cohort.id + self.moderator_cohort.id
response = self.call_view(mock_request, "cohorted_topic", self.moderator, invalid_id) # lint-amnesty, pylint: disable=assignment-from-no-return response = self.call_view(mock_request, "cohorted_topic", self.moderator, invalid_id) # lint-amnesty, pylint: disable=assignment-from-no-return
self.assertEqual(response.status_code, 500) assert response.status_code == 500
def test_cohorted_topic_enrollment_track_invalid_group_id(self, mock_request): def test_cohorted_topic_enrollment_track_invalid_group_id(self, mock_request):
CourseModeFactory.create(course_id=self.course.id, mode_slug=CourseMode.AUDIT) CourseModeFactory.create(course_id=self.course.id, mode_slug=CourseMode.AUDIT)
@@ -117,7 +117,7 @@ class CohortedTopicGroupIdTestMixin(GroupIdAssertionMixin):
invalid_id = -1000 invalid_id = -1000
response = self.call_view(mock_request, "cohorted_topic", self.moderator, invalid_id) # lint-amnesty, pylint: disable=assignment-from-no-return response = self.call_view(mock_request, "cohorted_topic", self.moderator, invalid_id) # lint-amnesty, pylint: disable=assignment-from-no-return
self.assertEqual(response.status_code, 500) assert response.status_code == 500
class NonCohortedTopicGroupIdTestMixin(GroupIdAssertionMixin): class NonCohortedTopicGroupIdTestMixin(GroupIdAssertionMixin):

View File

@@ -57,4 +57,4 @@ class MockCommentServiceServerTest(unittest.TestCase):
response_dict = json.loads(response.read()) response_dict = json.loads(response.read())
# You should have received the response specified in the setup above # You should have received the response specified in the setup above
self.assertEqual(response_dict, self.expected_response) assert response_dict == self.expected_response

View File

@@ -24,21 +24,15 @@ class AjaxExceptionTestCase(TestCase): # lint-amnesty, pylint: disable=missing-
def test_process_exception(self): def test_process_exception(self):
response1 = self.a.process_exception(self.request1, self.exception1) response1 = self.a.process_exception(self.request1, self.exception1)
self.assertIsInstance(response1, middleware.JsonError) assert isinstance(response1, middleware.JsonError)
self.assertEqual(self.exception1.status_code, response1.status_code) assert self.exception1.status_code == response1.status_code
self.assertEqual( assert {'errors': json.loads(text_type(self.exception1))} == json.loads(response1.content.decode('utf-8'))
{"errors": json.loads(text_type(self.exception1))},
json.loads(response1.content.decode('utf-8'))
)
response2 = self.a.process_exception(self.request1, self.exception2) response2 = self.a.process_exception(self.request1, self.exception2)
self.assertIsInstance(response2, middleware.JsonError) assert isinstance(response2, middleware.JsonError)
self.assertEqual(self.exception2.status_code, response2.status_code) assert self.exception2.status_code == response2.status_code
self.assertEqual( assert {'errors': [text_type(self.exception2)]} == json.loads(response2.content.decode('utf-8'))
{"errors": [text_type(self.exception2)]},
json.loads(response2.content.decode('utf-8'))
)
self.assertIsNone(self.a.process_exception(self.request1, self.exception0)) assert self.a.process_exception(self.request1, self.exception0) is None
self.assertIsNone(self.a.process_exception(self.request0, self.exception1)) assert self.a.process_exception(self.request0, self.exception1) is None
self.assertIsNone(self.a.process_exception(self.request0, self.exception0)) assert self.a.process_exception(self.request0, self.exception0) is None

View File

@@ -40,13 +40,13 @@ class RoleClassTestCase(ModuleStoreTestCase):
# Roles with the same FORUM_ROLE in same class also receives the same # Roles with the same FORUM_ROLE in same class also receives the same
# permission. # permission.
# Is this desirable behavior? # Is this desirable behavior?
self.assertTrue(self.student_role.has_permission("delete_thread")) assert self.student_role.has_permission('delete_thread')
self.assertTrue(self.student_2_role.has_permission("delete_thread")) assert self.student_2_role.has_permission('delete_thread')
self.assertFalse(self.TA_role.has_permission("delete_thread")) assert not self.TA_role.has_permission('delete_thread')
def test_inherit_permission(self): def test_inherit_permission(self):
self.TA_role.inherit_permissions(self.student_role) self.TA_role.inherit_permissions(self.student_role)
self.assertTrue(self.TA_role.has_permission("delete_thread")) assert self.TA_role.has_permission('delete_thread')
# Despite being from 2 different courses, TA_role_2 can still inherit # Despite being from 2 different courses, TA_role_2 can still inherit
# permissions from TA_role without error # permissions from TA_role without error
self.TA_role_2.inherit_permissions(self.TA_role) self.TA_role_2.inherit_permissions(self.TA_role)
@@ -62,4 +62,4 @@ class PermissionClassTestCase(TestCase):
self.permission = models.Permission.objects.get_or_create(name="test")[0] self.permission = models.Permission.objects.get_or_create(name="test")[0]
def test_unicode(self): def test_unicode(self):
self.assertEqual(str(self.permission), "test") assert str(self.permission) == 'test'

View File

@@ -60,17 +60,17 @@ class DictionaryTestCase(TestCase):
d = {'cats': 'meow', 'dogs': 'woof'} d = {'cats': 'meow', 'dogs': 'woof'}
k = ['cats', 'dogs', 'hamsters'] k = ['cats', 'dogs', 'hamsters']
expected = {'cats': 'meow', 'dogs': 'woof', 'hamsters': None} expected = {'cats': 'meow', 'dogs': 'woof', 'hamsters': None}
self.assertEqual(utils.extract(d, k), expected) assert utils.extract(d, k) == expected
def test_strip_none(self): def test_strip_none(self):
d = {'cats': 'meow', 'dogs': 'woof', 'hamsters': None} d = {'cats': 'meow', 'dogs': 'woof', 'hamsters': None}
expected = {'cats': 'meow', 'dogs': 'woof'} expected = {'cats': 'meow', 'dogs': 'woof'}
self.assertEqual(utils.strip_none(d), expected) assert utils.strip_none(d) == expected
def test_strip_blank(self): def test_strip_blank(self):
d = {'cats': 'meow', 'dogs': 'woof', 'hamsters': ' ', 'yetis': ''} d = {'cats': 'meow', 'dogs': 'woof', 'hamsters': ' ', 'yetis': ''}
expected = {'cats': 'meow', 'dogs': 'woof'} expected = {'cats': 'meow', 'dogs': 'woof'}
self.assertEqual(utils.strip_blank(d), expected) assert utils.strip_blank(d) == expected
class AccessUtilsTestCase(ModuleStoreTestCase): class AccessUtilsTestCase(ModuleStoreTestCase):
@@ -106,25 +106,25 @@ class AccessUtilsTestCase(ModuleStoreTestCase):
def test_get_role_ids(self): def test_get_role_ids(self):
ret = utils.get_role_ids(self.course_id) ret = utils.get_role_ids(self.course_id)
expected = {u'Moderator': [3], u'Community TA': [4, 5]} expected = {u'Moderator': [3], u'Community TA': [4, 5]}
self.assertEqual(ret, expected) assert ret == expected
def test_has_discussion_privileges(self): def test_has_discussion_privileges(self):
self.assertFalse(utils.has_discussion_privileges(self.student1, self.course_id)) assert not utils.has_discussion_privileges(self.student1, self.course_id)
self.assertFalse(utils.has_discussion_privileges(self.student2, self.course_id)) assert not utils.has_discussion_privileges(self.student2, self.course_id)
self.assertFalse(utils.has_discussion_privileges(self.course_staff, self.course_id)) assert not utils.has_discussion_privileges(self.course_staff, self.course_id)
self.assertTrue(utils.has_discussion_privileges(self.moderator, self.course_id)) assert utils.has_discussion_privileges(self.moderator, self.course_id)
self.assertTrue(utils.has_discussion_privileges(self.community_ta1, self.course_id)) assert utils.has_discussion_privileges(self.community_ta1, self.course_id)
self.assertTrue(utils.has_discussion_privileges(self.community_ta2, self.course_id)) assert utils.has_discussion_privileges(self.community_ta2, self.course_id)
def test_has_forum_access(self): def test_has_forum_access(self):
ret = utils.has_forum_access('student', self.course_id, 'Student') ret = utils.has_forum_access('student', self.course_id, 'Student')
self.assertTrue(ret) assert ret
ret = utils.has_forum_access('not_a_student', self.course_id, 'Student') ret = utils.has_forum_access('not_a_student', self.course_id, 'Student')
self.assertFalse(ret) assert not ret
ret = utils.has_forum_access('student', self.course_id, 'NotARole') ret = utils.has_forum_access('student', self.course_id, 'NotARole')
self.assertFalse(ret) assert not ret
@ddt.ddt @ddt.ddt
@@ -158,7 +158,7 @@ class CoursewareContextTestCase(ModuleStoreTestCase):
orig = {"commentable_id": "non-inline"} orig = {"commentable_id": "non-inline"}
modified = dict(orig) modified = dict(orig)
utils.add_courseware_context([modified], self.course, self.user) utils.add_courseware_context([modified], self.course, self.user)
self.assertEqual(modified, orig) assert modified == orig
def test_basic(self): def test_basic(self):
threads = [ threads = [
@@ -169,21 +169,9 @@ class CoursewareContextTestCase(ModuleStoreTestCase):
def assertThreadCorrect(thread, discussion, expected_title): # pylint: disable=invalid-name def assertThreadCorrect(thread, discussion, expected_title): # pylint: disable=invalid-name
"""Asserts that the given thread has the expected set of properties""" """Asserts that the given thread has the expected set of properties"""
self.assertEqual( assert set(thread.keys()) == set(['commentable_id', 'courseware_url', 'courseware_title'])
set(thread.keys()), assert thread.get('courseware_url') == reverse('jump_to', kwargs={'course_id': text_type(self.course.id), 'location': text_type(discussion.location)})
set(["commentable_id", "courseware_url", "courseware_title"]) assert thread.get('courseware_title') == expected_title
)
self.assertEqual(
thread.get("courseware_url"),
reverse(
"jump_to",
kwargs={
"course_id": text_type(self.course.id),
"location": text_type(discussion.location)
}
)
)
self.assertEqual(thread.get("courseware_title"), expected_title)
assertThreadCorrect(threads[0], self.discussion1, "Chapter / Discussion 1") assertThreadCorrect(threads[0], self.discussion1, "Chapter / Discussion 1")
assertThreadCorrect(threads[1], self.discussion2, "Subsection / Discussion 2") assertThreadCorrect(threads[1], self.discussion2, "Subsection / Discussion 2")
@@ -202,7 +190,7 @@ class CoursewareContextTestCase(ModuleStoreTestCase):
) )
thread = {"commentable_id": discussion.discussion_id} thread = {"commentable_id": discussion.discussion_id}
utils.add_courseware_context([thread], self.course, self.user) utils.add_courseware_context([thread], self.course, self.user)
self.assertNotIn('/', thread.get("courseware_title")) assert '/' not in thread.get('courseware_title')
@ddt.data((ModuleStoreEnum.Type.mongo, 2), (ModuleStoreEnum.Type.split, 1)) @ddt.data((ModuleStoreEnum.Type.mongo, 2), (ModuleStoreEnum.Type.split, 1))
@ddt.unpack @ddt.unpack
@@ -216,10 +204,10 @@ class CoursewareContextTestCase(ModuleStoreTestCase):
test_discussion = self.store.create_child(self.user.id, course.location, 'discussion', 'test_discussion') test_discussion = self.store.create_child(self.user.id, course.location, 'discussion', 'test_discussion')
# Assert that created discussion xblock is not an orphan. # Assert that created discussion xblock is not an orphan.
self.assertNotIn(test_discussion.location, self.store.get_orphans(course.id)) assert test_discussion.location not in self.store.get_orphans(course.id)
# Assert that there is only one discussion xblock in the course at the moment. # Assert that there is only one discussion xblock in the course at the moment.
self.assertEqual(len(utils.get_accessible_discussion_xblocks(course, self.user)), 1) assert len(utils.get_accessible_discussion_xblocks(course, self.user)) == 1
# The above call is request cached, so we need to clear it for this test. # The above call is request cached, so we need to clear it for this test.
RequestCache.clear_all_namespaces() RequestCache.clear_all_namespaces()
@@ -228,9 +216,9 @@ class CoursewareContextTestCase(ModuleStoreTestCase):
self.store.create_item(self.user.id, orphan.course_key, orphan.block_type, block_id=orphan.block_id) self.store.create_item(self.user.id, orphan.course_key, orphan.block_type, block_id=orphan.block_id)
# Assert that the discussion xblock is an orphan. # Assert that the discussion xblock is an orphan.
self.assertIn(orphan, self.store.get_orphans(course.id)) assert orphan in self.store.get_orphans(course.id)
self.assertEqual(len(utils.get_accessible_discussion_xblocks(course, self.user)), expected_discussion_xblocks) assert len(utils.get_accessible_discussion_xblocks(course, self.user)) == expected_discussion_xblocks
class CachedDiscussionIdMapTestCase(ModuleStoreTestCase): class CachedDiscussionIdMapTestCase(ModuleStoreTestCase):
@@ -276,15 +264,15 @@ class CachedDiscussionIdMapTestCase(ModuleStoreTestCase):
def test_cache_returns_correct_key(self): def test_cache_returns_correct_key(self):
usage_key = utils.get_cached_discussion_key(self.course.id, 'test_discussion_id') usage_key = utils.get_cached_discussion_key(self.course.id, 'test_discussion_id')
self.assertEqual(usage_key, self.discussion.location) assert usage_key == self.discussion.location
def test_cache_returns_none_if_id_is_not_present(self): def test_cache_returns_none_if_id_is_not_present(self):
usage_key = utils.get_cached_discussion_key(self.course.id, 'bogus_id') usage_key = utils.get_cached_discussion_key(self.course.id, 'bogus_id')
self.assertIsNone(usage_key) assert usage_key is None
def test_cache_raises_exception_if_discussion_id_map_not_cached(self): def test_cache_raises_exception_if_discussion_id_map_not_cached(self):
DiscussionsIdMapping.objects.all().delete() DiscussionsIdMapping.objects.all().delete()
with self.assertRaises(utils.DiscussionIdMapIsNotCached): with pytest.raises(utils.DiscussionIdMapIsNotCached):
utils.get_cached_discussion_key(self.course.id, 'test_discussion_id') utils.get_cached_discussion_key(self.course.id, 'test_discussion_id')
def test_cache_raises_exception_if_discussion_id_not_cached(self): def test_cache_raises_exception_if_discussion_id_not_cached(self):
@@ -292,12 +280,12 @@ class CachedDiscussionIdMapTestCase(ModuleStoreTestCase):
cache.mapping = None cache.mapping = None
cache.save() cache.save()
with self.assertRaises(utils.DiscussionIdMapIsNotCached): with pytest.raises(utils.DiscussionIdMapIsNotCached):
utils.get_cached_discussion_key(self.course.id, 'test_discussion_id') utils.get_cached_discussion_key(self.course.id, 'test_discussion_id')
def test_xblock_does_not_have_required_keys(self): def test_xblock_does_not_have_required_keys(self):
self.assertTrue(utils.has_required_keys(self.discussion)) assert utils.has_required_keys(self.discussion)
self.assertFalse(utils.has_required_keys(self.bad_discussion)) assert not utils.has_required_keys(self.bad_discussion)
def verify_discussion_metadata(self): def verify_discussion_metadata(self):
"""Retrieves the metadata for self.discussion and self.discussion2 and verifies that it is correct""" """Retrieves the metadata for self.discussion and self.discussion2 and verifies that it is correct"""
@@ -308,10 +296,10 @@ class CachedDiscussionIdMapTestCase(ModuleStoreTestCase):
) )
discussion1 = metadata[self.discussion.discussion_id] discussion1 = metadata[self.discussion.discussion_id]
discussion2 = metadata[self.discussion2.discussion_id] discussion2 = metadata[self.discussion2.discussion_id]
self.assertEqual(discussion1['location'], self.discussion.location) assert discussion1['location'] == self.discussion.location
self.assertEqual(discussion1['title'], 'Chapter / Discussion 1') assert discussion1['title'] == 'Chapter / Discussion 1'
self.assertEqual(discussion2['location'], self.discussion2.location) assert discussion2['location'] == self.discussion2.location
self.assertEqual(discussion2['title'], 'Chapter 2 / Discussion 2') assert discussion2['title'] == 'Chapter 2 / Discussion 2'
def test_get_discussion_id_map_from_cache(self): def test_get_discussion_id_map_from_cache(self):
self.verify_discussion_metadata() self.verify_discussion_metadata()
@@ -322,34 +310,34 @@ class CachedDiscussionIdMapTestCase(ModuleStoreTestCase):
def test_get_missing_discussion_id_map_from_cache(self): def test_get_missing_discussion_id_map_from_cache(self):
metadata = utils.get_cached_discussion_id_map(self.course, ['bogus_id'], self.user) metadata = utils.get_cached_discussion_id_map(self.course, ['bogus_id'], self.user)
self.assertEqual(metadata, {}) assert metadata == {}
def test_get_discussion_id_map_from_cache_without_access(self): def test_get_discussion_id_map_from_cache_without_access(self):
user = UserFactory.create() user = UserFactory.create()
metadata = utils.get_cached_discussion_id_map(self.course, ['private_discussion_id'], self.user) metadata = utils.get_cached_discussion_id_map(self.course, ['private_discussion_id'], self.user)
self.assertEqual(metadata['private_discussion_id']['title'], 'Chapter 3 / Beta Testing') assert metadata['private_discussion_id']['title'] == 'Chapter 3 / Beta Testing'
metadata = utils.get_cached_discussion_id_map(self.course, ['private_discussion_id'], user) metadata = utils.get_cached_discussion_id_map(self.course, ['private_discussion_id'], user)
self.assertEqual(metadata, {}) assert metadata == {}
def test_get_bad_discussion_id(self): def test_get_bad_discussion_id(self):
metadata = utils.get_cached_discussion_id_map(self.course, ['bad_discussion_id'], self.user) metadata = utils.get_cached_discussion_id_map(self.course, ['bad_discussion_id'], self.user)
self.assertEqual(metadata, {}) assert metadata == {}
def test_discussion_id_accessible(self): def test_discussion_id_accessible(self):
self.assertTrue(utils.discussion_category_id_access(self.course, self.user, 'test_discussion_id')) assert utils.discussion_category_id_access(self.course, self.user, 'test_discussion_id')
def test_bad_discussion_id_not_accessible(self): def test_bad_discussion_id_not_accessible(self):
self.assertFalse(utils.discussion_category_id_access(self.course, self.user, 'bad_discussion_id')) assert not utils.discussion_category_id_access(self.course, self.user, 'bad_discussion_id')
def test_missing_discussion_id_not_accessible(self): def test_missing_discussion_id_not_accessible(self):
self.assertFalse(utils.discussion_category_id_access(self.course, self.user, 'bogus_id')) assert not utils.discussion_category_id_access(self.course, self.user, 'bogus_id')
def test_discussion_id_not_accessible_without_access(self): def test_discussion_id_not_accessible_without_access(self):
user = UserFactory.create() user = UserFactory.create()
self.assertTrue(utils.discussion_category_id_access(self.course, self.user, 'private_discussion_id')) assert utils.discussion_category_id_access(self.course, self.user, 'private_discussion_id')
self.assertFalse(utils.discussion_category_id_access(self.course, user, 'private_discussion_id')) assert not utils.discussion_category_id_access(self.course, user, 'private_discussion_id')
class CategoryMapTestMixin(object): class CategoryMapTestMixin(object):
@@ -364,7 +352,7 @@ class CategoryMapTestMixin(object):
""" """
actual = utils.get_discussion_category_map(self.course, requesting_user or self.user) actual = utils.get_discussion_category_map(self.course, requesting_user or self.user)
actual['subcategories']['Week 1']['children'].sort() actual['subcategories']['Week 1']['children'].sort()
self.assertEqual(actual, expected) assert actual == expected
class CategoryMapTestCase(CategoryMapTestMixin, ModuleStoreTestCase): class CategoryMapTestCase(CategoryMapTestMixin, ModuleStoreTestCase):
@@ -404,12 +392,7 @@ class CategoryMapTestCase(CategoryMapTestMixin, ModuleStoreTestCase):
""" """
Asserts the expected map with the map returned by get_discussion_category_map method. Asserts the expected map with the map returned by get_discussion_category_map method.
""" """
self.assertEqual( assert utils.get_discussion_category_map(self.course, self.instructor, divided_only_if_explicit, exclude_unstarted) == expected
utils.get_discussion_category_map(
self.course, self.instructor, divided_only_if_explicit, exclude_unstarted
),
expected
)
def test_empty(self): def test_empty(self):
self.assert_category_map_equals({"entries": {}, "subcategories": {}, "children": []}) self.assert_category_map_equals({"entries": {}, "subcategories": {}, "children": []})
@@ -680,15 +663,15 @@ class CategoryMapTestCase(CategoryMapTestMixin, ModuleStoreTestCase):
chapter1_discussions = set(["Discussion A", "Discussion B", "Discussion A (1)", "Discussion A (2)"]) chapter1_discussions = set(["Discussion A", "Discussion B", "Discussion A (1)", "Discussion A (2)"])
chapter1_discussions_with_types = set([("Discussion A", TYPE_ENTRY), ("Discussion B", TYPE_ENTRY), chapter1_discussions_with_types = set([("Discussion A", TYPE_ENTRY), ("Discussion B", TYPE_ENTRY),
("Discussion A (1)", TYPE_ENTRY), ("Discussion A (2)", TYPE_ENTRY)]) ("Discussion A (1)", TYPE_ENTRY), ("Discussion A (2)", TYPE_ENTRY)])
self.assertEqual(set(chapter1["children"]), chapter1_discussions_with_types) assert set(chapter1['children']) == chapter1_discussions_with_types
self.assertEqual(set(chapter1["entries"].keys()), chapter1_discussions) assert set(chapter1['entries'].keys()) == chapter1_discussions
chapter2 = category_map["subcategories"]["Chapter 2"] chapter2 = category_map["subcategories"]["Chapter 2"]
subsection1 = chapter2["subcategories"]["Section 1"]["subcategories"]["Subsection 1"] subsection1 = chapter2["subcategories"]["Section 1"]["subcategories"]["Subsection 1"]
subsection1_discussions = set(["Discussion", "Discussion (1)"]) subsection1_discussions = set(["Discussion", "Discussion (1)"])
subsection1_discussions_with_types = set([("Discussion", TYPE_ENTRY), ("Discussion (1)", TYPE_ENTRY)]) subsection1_discussions_with_types = set([("Discussion", TYPE_ENTRY), ("Discussion (1)", TYPE_ENTRY)])
self.assertEqual(set(subsection1["children"]), subsection1_discussions_with_types) assert set(subsection1['children']) == subsection1_discussions_with_types
self.assertEqual(set(subsection1["entries"].keys()), subsection1_discussions) assert set(subsection1['entries'].keys()) == subsection1_discussions
def test_start_date_filter(self): def test_start_date_filter(self):
now = datetime.datetime.now() now = datetime.datetime.now()
@@ -699,7 +682,7 @@ class CategoryMapTestCase(CategoryMapTestMixin, ModuleStoreTestCase):
self.create_discussion("Chapter 2 / Section 1 / Subsection 2", "Discussion", start=self.later) self.create_discussion("Chapter 2 / Section 1 / Subsection 2", "Discussion", start=self.later)
self.create_discussion("Chapter 3 / Section 1", "Discussion", start=self.later) self.create_discussion("Chapter 3 / Section 1", "Discussion", start=self.later)
self.assertFalse(self.course.self_paced) assert not self.course.self_paced
self.assert_category_map_equals( self.assert_category_map_equals(
{ {
"entries": {}, "entries": {},
@@ -742,7 +725,7 @@ class CategoryMapTestCase(CategoryMapTestMixin, ModuleStoreTestCase):
self.create_discussion("Chapter 2 / Section 1 / Subsection 2", "Discussion", start=self.later) self.create_discussion("Chapter 2 / Section 1 / Subsection 2", "Discussion", start=self.later)
self.create_discussion("Chapter 3 / Section 1", "Discussion", start=self.later) self.create_discussion("Chapter 3 / Section 1", "Discussion", start=self.later)
self.assertTrue(self.course.self_paced) assert self.course.self_paced
self.assert_category_map_equals( self.assert_category_map_equals(
{ {
"entries": {}, "entries": {},
@@ -1012,7 +995,7 @@ class CategoryMapTestCase(CategoryMapTestMixin, ModuleStoreTestCase):
) )
def test_ids_empty(self): def test_ids_empty(self):
self.assertEqual(utils.get_discussion_categories_ids(self.course, self.user), []) assert utils.get_discussion_categories_ids(self.course, self.user) == []
def test_ids_configured_topics(self): def test_ids_configured_topics(self):
self.course.discussion_topics = { self.course.discussion_topics = {
@@ -1222,7 +1205,7 @@ class JsonResponseTestCase(TestCase, UnicodeTestMixin):
def _test_unicode_data(self, text): def _test_unicode_data(self, text):
response = utils.JsonResponse(text) response = utils.JsonResponse(text)
reparsed = json.loads(response.content.decode('utf-8')) reparsed = json.loads(response.content.decode('utf-8'))
self.assertEqual(reparsed, text) assert reparsed == text
class DiscussionTabTestCase(ModuleStoreTestCase): class DiscussionTabTestCase(ModuleStoreTestCase):
@@ -1244,18 +1227,18 @@ class DiscussionTabTestCase(ModuleStoreTestCase):
def test_tab_access(self): def test_tab_access(self):
with self.settings(FEATURES={'ENABLE_DISCUSSION_SERVICE': True}): with self.settings(FEATURES={'ENABLE_DISCUSSION_SERVICE': True}):
self.assertTrue(self.discussion_tab_present(self.staff_user)) assert self.discussion_tab_present(self.staff_user)
self.assertTrue(self.discussion_tab_present(self.enrolled_user)) assert self.discussion_tab_present(self.enrolled_user)
self.assertFalse(self.discussion_tab_present(self.unenrolled_user)) assert not self.discussion_tab_present(self.unenrolled_user)
@mock.patch('lms.djangoapps.ccx.overrides.get_current_ccx') @mock.patch('lms.djangoapps.ccx.overrides.get_current_ccx')
def test_tab_settings(self, mock_get_ccx): def test_tab_settings(self, mock_get_ccx):
mock_get_ccx.return_value = True mock_get_ccx.return_value = True
with self.settings(FEATURES={'ENABLE_DISCUSSION_SERVICE': False}): with self.settings(FEATURES={'ENABLE_DISCUSSION_SERVICE': False}):
self.assertFalse(self.discussion_tab_present(self.enrolled_user)) assert not self.discussion_tab_present(self.enrolled_user)
with self.settings(FEATURES={'CUSTOM_COURSES_EDX': True}): with self.settings(FEATURES={'CUSTOM_COURSES_EDX': True}):
self.assertFalse(self.discussion_tab_present(self.enrolled_user)) assert not self.discussion_tab_present(self.enrolled_user)
class IsCommentableDividedTestCase(ModuleStoreTestCase): class IsCommentableDividedTestCase(ModuleStoreTestCase):
@@ -1274,35 +1257,26 @@ class IsCommentableDividedTestCase(ModuleStoreTestCase):
def test_is_commentable_divided(self): def test_is_commentable_divided(self):
course = modulestore().get_course(self.toy_course_key) course = modulestore().get_course(self.toy_course_key)
self.assertFalse(cohorts.is_course_cohorted(course.id)) assert not cohorts.is_course_cohorted(course.id)
def to_id(name): def to_id(name):
"""Helper for topic_name_to_id that uses course.""" """Helper for topic_name_to_id that uses course."""
return topic_name_to_id(course, name) return topic_name_to_id(course, name)
# no topics # no topics
self.assertFalse( assert not utils.is_commentable_divided(course.id, to_id('General')), "Course doesn't even have a 'General' topic"
utils.is_commentable_divided(course.id, to_id("General")),
"Course doesn't even have a 'General' topic"
)
# not cohorted # not cohorted
config_course_cohorts(course, is_cohorted=False) config_course_cohorts(course, is_cohorted=False)
config_course_discussions(course, discussion_topics=["General", "Feedback"]) config_course_discussions(course, discussion_topics=["General", "Feedback"])
self.assertFalse( assert not utils.is_commentable_divided(course.id, to_id('General')), "Course isn't cohorted"
utils.is_commentable_divided(course.id, to_id("General")),
"Course isn't cohorted"
)
# cohorted, but top level topics aren't # cohorted, but top level topics aren't
config_course_cohorts(course, is_cohorted=True) config_course_cohorts(course, is_cohorted=True)
config_course_discussions(course, discussion_topics=["General", "Feedback"]) config_course_discussions(course, discussion_topics=["General", "Feedback"])
self.assertTrue(cohorts.is_course_cohorted(course.id)) assert cohorts.is_course_cohorted(course.id)
self.assertFalse( assert not utils.is_commentable_divided(course.id, to_id('General')), "Course is cohorted, but 'General' isn't."
utils.is_commentable_divided(course.id, to_id("General")),
"Course is cohorted, but 'General' isn't."
)
# cohorted, including "Feedback" top-level topics aren't # cohorted, including "Feedback" top-level topics aren't
config_course_cohorts( config_course_cohorts(
@@ -1311,19 +1285,13 @@ class IsCommentableDividedTestCase(ModuleStoreTestCase):
) )
config_course_discussions(course, discussion_topics=["General", "Feedback"], divided_discussions=["Feedback"]) config_course_discussions(course, discussion_topics=["General", "Feedback"], divided_discussions=["Feedback"])
self.assertTrue(cohorts.is_course_cohorted(course.id)) assert cohorts.is_course_cohorted(course.id)
self.assertFalse( assert not utils.is_commentable_divided(course.id, to_id('General')), "Course is cohorted, but 'General' isn't."
utils.is_commentable_divided(course.id, to_id("General")), assert utils.is_commentable_divided(course.id, to_id('Feedback')), 'Feedback was listed as cohorted. Should be.'
"Course is cohorted, but 'General' isn't."
)
self.assertTrue(
utils.is_commentable_divided(course.id, to_id("Feedback")),
"Feedback was listed as cohorted. Should be."
)
def test_is_commentable_divided_inline_discussion(self): def test_is_commentable_divided_inline_discussion(self):
course = modulestore().get_course(self.toy_course_key) course = modulestore().get_course(self.toy_course_key)
self.assertFalse(cohorts.is_course_cohorted(course.id)) assert not cohorts.is_course_cohorted(course.id)
def to_id(name): def to_id(name):
return topic_name_to_id(course, name) return topic_name_to_id(course, name)
@@ -1338,10 +1306,7 @@ class IsCommentableDividedTestCase(ModuleStoreTestCase):
divided_discussions=["Feedback", "random_inline"] divided_discussions=["Feedback", "random_inline"]
) )
self.assertFalse( assert not utils.is_commentable_divided(course.id, to_id('random')), 'By default, Non-top-level discussions are not cohorted in a cohorted courses.'
utils.is_commentable_divided(course.id, to_id("random")),
"By default, Non-top-level discussions are not cohorted in a cohorted courses."
)
# if always_divide_inline_discussions is set to False, non-top-level discussion are always # if always_divide_inline_discussions is set to False, non-top-level discussion are always
# not divided unless they are explicitly set in divided_discussions # not divided unless they are explicitly set in divided_discussions
@@ -1356,23 +1321,13 @@ class IsCommentableDividedTestCase(ModuleStoreTestCase):
always_divide_inline_discussions=False always_divide_inline_discussions=False
) )
self.assertFalse( assert not utils.is_commentable_divided(course.id, to_id('random')), 'Non-top-level discussion is not cohorted if always_divide_inline_discussions is False.'
utils.is_commentable_divided(course.id, to_id("random")), assert utils.is_commentable_divided(course.id, to_id('random_inline')), 'If always_divide_inline_discussions set to False, Non-top-level discussion is cohorted if explicitly set in cohorted_discussions.'
"Non-top-level discussion is not cohorted if always_divide_inline_discussions is False." assert utils.is_commentable_divided(course.id, to_id('Feedback')), 'If always_divide_inline_discussions set to False, top-level discussion are not affected.'
)
self.assertTrue(
utils.is_commentable_divided(course.id, to_id("random_inline")),
"If always_divide_inline_discussions set to False, Non-top-level discussion is "
"cohorted if explicitly set in cohorted_discussions."
)
self.assertTrue(
utils.is_commentable_divided(course.id, to_id("Feedback")),
"If always_divide_inline_discussions set to False, top-level discussion are not affected."
)
def test_is_commentable_divided_team(self): def test_is_commentable_divided_team(self):
course = modulestore().get_course(self.toy_course_key) course = modulestore().get_course(self.toy_course_key)
self.assertFalse(cohorts.is_course_cohorted(course.id)) assert not cohorts.is_course_cohorted(course.id)
config_course_cohorts(course, is_cohorted=True) config_course_cohorts(course, is_cohorted=True)
config_course_discussions(course, always_divide_inline_discussions=True) config_course_discussions(course, always_divide_inline_discussions=True)
@@ -1381,8 +1336,8 @@ class IsCommentableDividedTestCase(ModuleStoreTestCase):
# Verify that team discussions are not cohorted, but other discussions are # Verify that team discussions are not cohorted, but other discussions are
# if "always cohort inline discussions" is set to true. # if "always cohort inline discussions" is set to true.
self.assertFalse(utils.is_commentable_divided(course.id, team.discussion_topic_id)) assert not utils.is_commentable_divided(course.id, team.discussion_topic_id)
self.assertTrue(utils.is_commentable_divided(course.id, "random")) assert utils.is_commentable_divided(course.id, 'random')
def test_is_commentable_divided_cohorts(self): def test_is_commentable_divided_cohorts(self):
course = modulestore().get_course(self.toy_course_key) course = modulestore().get_course(self.toy_course_key)
@@ -1395,7 +1350,7 @@ class IsCommentableDividedTestCase(ModuleStoreTestCase):
) )
# Although Cohorts are enabled, discussion division is explicitly disabled. # Although Cohorts are enabled, discussion division is explicitly disabled.
self.assertFalse(utils.is_commentable_divided(course.id, "random")) assert not utils.is_commentable_divided(course.id, 'random')
# Now set the discussion division scheme. # Now set the discussion division scheme.
set_discussion_division_settings( set_discussion_division_settings(
@@ -1405,7 +1360,7 @@ class IsCommentableDividedTestCase(ModuleStoreTestCase):
always_divide_inline_discussions=True, always_divide_inline_discussions=True,
division_scheme=CourseDiscussionSettings.COHORT, division_scheme=CourseDiscussionSettings.COHORT,
) )
self.assertTrue(utils.is_commentable_divided(course.id, "random")) assert utils.is_commentable_divided(course.id, 'random')
def test_is_commentable_divided_enrollment_track(self): def test_is_commentable_divided_enrollment_track(self):
course = modulestore().get_course(self.toy_course_key) course = modulestore().get_course(self.toy_course_key)
@@ -1418,12 +1373,12 @@ class IsCommentableDividedTestCase(ModuleStoreTestCase):
# Although division scheme is set to ENROLLMENT_TRACK, divided returns # Although division scheme is set to ENROLLMENT_TRACK, divided returns
# False because there is only a single enrollment mode. # False because there is only a single enrollment mode.
self.assertFalse(utils.is_commentable_divided(course.id, "random")) assert not utils.is_commentable_divided(course.id, 'random')
# Now create 2 explicit course modes. # Now create 2 explicit course modes.
CourseModeFactory.create(course_id=course.id, mode_slug=CourseMode.AUDIT) CourseModeFactory.create(course_id=course.id, mode_slug=CourseMode.AUDIT)
CourseModeFactory.create(course_id=course.id, mode_slug=CourseMode.VERIFIED) CourseModeFactory.create(course_id=course.id, mode_slug=CourseMode.VERIFIED)
self.assertTrue(utils.is_commentable_divided(course.id, "random")) assert utils.is_commentable_divided(course.id, 'random')
class GroupIdForUserTestCase(ModuleStoreTestCase): class GroupIdForUserTestCase(ModuleStoreTestCase):
@@ -1446,30 +1401,24 @@ class GroupIdForUserTestCase(ModuleStoreTestCase):
def test_discussion_division_disabled(self): def test_discussion_division_disabled(self):
course_discussion_settings = get_course_discussion_settings(self.course.id) course_discussion_settings = get_course_discussion_settings(self.course.id)
self.assertEqual(CourseDiscussionSettings.NONE, course_discussion_settings.division_scheme) assert CourseDiscussionSettings.NONE == course_discussion_settings.division_scheme
self.assertIsNone(utils.get_group_id_for_user(self.test_user, course_discussion_settings)) assert utils.get_group_id_for_user(self.test_user, course_discussion_settings) is None
def test_discussion_division_by_cohort(self): def test_discussion_division_by_cohort(self):
set_discussion_division_settings( set_discussion_division_settings(
self.course.id, enable_cohorts=True, division_scheme=CourseDiscussionSettings.COHORT self.course.id, enable_cohorts=True, division_scheme=CourseDiscussionSettings.COHORT
) )
course_discussion_settings = get_course_discussion_settings(self.course.id) course_discussion_settings = get_course_discussion_settings(self.course.id)
self.assertEqual(CourseDiscussionSettings.COHORT, course_discussion_settings.division_scheme) assert CourseDiscussionSettings.COHORT == course_discussion_settings.division_scheme
self.assertEqual( assert self.test_cohort.id == utils.get_group_id_for_user(self.test_user, course_discussion_settings)
self.test_cohort.id,
utils.get_group_id_for_user(self.test_user, course_discussion_settings)
)
def test_discussion_division_by_enrollment_track(self): def test_discussion_division_by_enrollment_track(self):
set_discussion_division_settings( set_discussion_division_settings(
self.course.id, division_scheme=CourseDiscussionSettings.ENROLLMENT_TRACK self.course.id, division_scheme=CourseDiscussionSettings.ENROLLMENT_TRACK
) )
course_discussion_settings = get_course_discussion_settings(self.course.id) course_discussion_settings = get_course_discussion_settings(self.course.id)
self.assertEqual(CourseDiscussionSettings.ENROLLMENT_TRACK, course_discussion_settings.division_scheme) assert CourseDiscussionSettings.ENROLLMENT_TRACK == course_discussion_settings.division_scheme
self.assertEqual( assert (- 2) == utils.get_group_id_for_user(self.test_user, course_discussion_settings)
-2, # Verified has group ID 2, and we negate that value to ensure unique IDs
utils.get_group_id_for_user(self.test_user, course_discussion_settings)
)
class CourseDiscussionDivisionEnabledTestCase(ModuleStoreTestCase): class CourseDiscussionDivisionEnabledTestCase(ModuleStoreTestCase):
@@ -1487,35 +1436,35 @@ class CourseDiscussionDivisionEnabledTestCase(ModuleStoreTestCase):
def test_discussion_division_disabled(self): def test_discussion_division_disabled(self):
course_discussion_settings = get_course_discussion_settings(self.course.id) course_discussion_settings = get_course_discussion_settings(self.course.id)
self.assertFalse(utils.course_discussion_division_enabled(course_discussion_settings)) assert not utils.course_discussion_division_enabled(course_discussion_settings)
self.assertEqual([], utils.available_division_schemes(self.course.id)) assert [] == utils.available_division_schemes(self.course.id)
def test_discussion_division_by_cohort(self): def test_discussion_division_by_cohort(self):
set_discussion_division_settings( set_discussion_division_settings(
self.course.id, enable_cohorts=False, division_scheme=CourseDiscussionSettings.COHORT self.course.id, enable_cohorts=False, division_scheme=CourseDiscussionSettings.COHORT
) )
# Because cohorts are disabled, discussion division is not enabled. # Because cohorts are disabled, discussion division is not enabled.
self.assertFalse(utils.course_discussion_division_enabled(get_course_discussion_settings(self.course.id))) assert not utils.course_discussion_division_enabled(get_course_discussion_settings(self.course.id))
self.assertEqual([], utils.available_division_schemes(self.course.id)) assert [] == utils.available_division_schemes(self.course.id)
# Now enable cohorts, which will cause discussions to be divided. # Now enable cohorts, which will cause discussions to be divided.
set_discussion_division_settings( set_discussion_division_settings(
self.course.id, enable_cohorts=True, division_scheme=CourseDiscussionSettings.COHORT self.course.id, enable_cohorts=True, division_scheme=CourseDiscussionSettings.COHORT
) )
self.assertTrue(utils.course_discussion_division_enabled(get_course_discussion_settings(self.course.id))) assert utils.course_discussion_division_enabled(get_course_discussion_settings(self.course.id))
self.assertEqual([CourseDiscussionSettings.COHORT], utils.available_division_schemes(self.course.id)) assert [CourseDiscussionSettings.COHORT] == utils.available_division_schemes(self.course.id)
def test_discussion_division_by_enrollment_track(self): def test_discussion_division_by_enrollment_track(self):
set_discussion_division_settings( set_discussion_division_settings(
self.course.id, division_scheme=CourseDiscussionSettings.ENROLLMENT_TRACK self.course.id, division_scheme=CourseDiscussionSettings.ENROLLMENT_TRACK
) )
# Only a single enrollment track exists, so discussion division is not enabled. # Only a single enrollment track exists, so discussion division is not enabled.
self.assertFalse(utils.course_discussion_division_enabled(get_course_discussion_settings(self.course.id))) assert not utils.course_discussion_division_enabled(get_course_discussion_settings(self.course.id))
self.assertEqual([], utils.available_division_schemes(self.course.id)) assert [] == utils.available_division_schemes(self.course.id)
# Now create a second CourseMode, which will cause discussions to be divided. # Now create a second CourseMode, which will cause discussions to be divided.
CourseModeFactory.create(course_id=self.course.id, mode_slug=CourseMode.VERIFIED) CourseModeFactory.create(course_id=self.course.id, mode_slug=CourseMode.VERIFIED)
self.assertTrue(utils.course_discussion_division_enabled(get_course_discussion_settings(self.course.id))) assert utils.course_discussion_division_enabled(get_course_discussion_settings(self.course.id))
self.assertEqual([CourseDiscussionSettings.ENROLLMENT_TRACK], utils.available_division_schemes(self.course.id)) assert [CourseDiscussionSettings.ENROLLMENT_TRACK] == utils.available_division_schemes(self.course.id)
class GroupNameTestCase(ModuleStoreTestCase): class GroupNameTestCase(ModuleStoreTestCase):
@@ -1539,51 +1488,29 @@ class GroupNameTestCase(ModuleStoreTestCase):
def test_discussion_division_disabled(self): def test_discussion_division_disabled(self):
course_discussion_settings = get_course_discussion_settings(self.course.id) course_discussion_settings = get_course_discussion_settings(self.course.id)
self.assertEqual({}, utils.get_group_names_by_id(course_discussion_settings)) assert {} == utils.get_group_names_by_id(course_discussion_settings)
self.assertIsNone(utils.get_group_name(-1000, course_discussion_settings)) assert utils.get_group_name((- 1000), course_discussion_settings) is None
def test_discussion_division_by_cohort(self): def test_discussion_division_by_cohort(self):
set_discussion_division_settings( set_discussion_division_settings(
self.course.id, enable_cohorts=True, division_scheme=CourseDiscussionSettings.COHORT self.course.id, enable_cohorts=True, division_scheme=CourseDiscussionSettings.COHORT
) )
course_discussion_settings = get_course_discussion_settings(self.course.id) course_discussion_settings = get_course_discussion_settings(self.course.id)
self.assertEqual( assert {self.test_cohort_1.id: self.test_cohort_1.name, self.test_cohort_2.id: self.test_cohort_2.name} == utils.get_group_names_by_id(course_discussion_settings)
{ assert self.test_cohort_2.name == utils.get_group_name(self.test_cohort_2.id, course_discussion_settings)
self.test_cohort_1.id: self.test_cohort_1.name,
self.test_cohort_2.id: self.test_cohort_2.name
},
utils.get_group_names_by_id(course_discussion_settings)
)
self.assertEqual(
self.test_cohort_2.name,
utils.get_group_name(self.test_cohort_2.id, course_discussion_settings)
)
# Test also with a group_id that doesn't exist. # Test also with a group_id that doesn't exist.
self.assertIsNone( assert utils.get_group_name((- 1000), course_discussion_settings) is None
utils.get_group_name(-1000, course_discussion_settings)
)
def test_discussion_division_by_enrollment_track(self): def test_discussion_division_by_enrollment_track(self):
set_discussion_division_settings( set_discussion_division_settings(
self.course.id, division_scheme=CourseDiscussionSettings.ENROLLMENT_TRACK self.course.id, division_scheme=CourseDiscussionSettings.ENROLLMENT_TRACK
) )
course_discussion_settings = get_course_discussion_settings(self.course.id) course_discussion_settings = get_course_discussion_settings(self.course.id)
self.assertEqual( assert {(- 1): 'audit course', (- 2): 'verified course'} == utils.get_group_names_by_id(course_discussion_settings)
{
-1: "audit course",
-2: "verified course"
},
utils.get_group_names_by_id(course_discussion_settings)
)
self.assertEqual( assert 'verified course' == utils.get_group_name((- 2), course_discussion_settings)
"verified course",
utils.get_group_name(-2, course_discussion_settings)
)
# Test also with a group_id that doesn't exist. # Test also with a group_id that doesn't exist.
self.assertIsNone( assert utils.get_group_name((- 1000), course_discussion_settings) is None
utils.get_group_name(-1000, course_discussion_settings)
)
class PermissionsTestCase(ModuleStoreTestCase): class PermissionsTestCase(ModuleStoreTestCase):
@@ -1601,24 +1528,10 @@ class PermissionsTestCase(ModuleStoreTestCase):
'lms.djangoapps.discussion.django_comment_client.utils.check_permissions_by_view' 'lms.djangoapps.discussion.django_comment_client.utils.check_permissions_by_view'
) as check_perm: ) as check_perm:
check_perm.return_value = True check_perm.return_value = True
self.assertEqual(utils.get_ability(None, content, user), { assert utils.get_ability(None, content, user) == {'editable': True, 'can_reply': True, 'can_delete': True, 'can_openclose': True, 'can_vote': False, 'can_report': False}
'editable': True,
'can_reply': True,
'can_delete': True,
'can_openclose': True,
'can_vote': False,
'can_report': False
})
content['user_id'] = '2' content['user_id'] = '2'
self.assertEqual(utils.get_ability(None, content, user), { assert utils.get_ability(None, content, user) == {'editable': True, 'can_reply': True, 'can_delete': True, 'can_openclose': True, 'can_vote': True, 'can_report': True}
'editable': True,
'can_reply': True,
'can_delete': True,
'can_openclose': True,
'can_vote': True,
'can_report': True
})
def test_get_ability_with_global_staff(self): def test_get_ability_with_global_staff(self):
""" """
@@ -1633,14 +1546,7 @@ class PermissionsTestCase(ModuleStoreTestCase):
# check_permissions_by_view returns false because user is not enrolled in the course. # check_permissions_by_view returns false because user is not enrolled in the course.
check_perm.return_value = False check_perm.return_value = False
global_staff = UserFactory(username='global_staff', email='global_staff@edx.org', is_staff=True) global_staff = UserFactory(username='global_staff', email='global_staff@edx.org', is_staff=True)
self.assertEqual(utils.get_ability(None, content, global_staff), { assert utils.get_ability(None, content, global_staff) == {'editable': False, 'can_reply': False, 'can_delete': False, 'can_openclose': False, 'can_vote': False, 'can_report': True}
'editable': False,
'can_reply': False,
'can_delete': False,
'can_openclose': False,
'can_vote': False,
'can_report': True
})
def test_is_content_authored_by(self): def test_is_content_authored_by(self):
content = {} content = {}
@@ -1649,23 +1555,23 @@ class PermissionsTestCase(ModuleStoreTestCase):
# strict equality checking # strict equality checking
content['user_id'] = 1 content['user_id'] = 1
self.assertTrue(utils.is_content_authored_by(content, user)) assert utils.is_content_authored_by(content, user)
# cast from string to int # cast from string to int
content['user_id'] = '1' content['user_id'] = '1'
self.assertTrue(utils.is_content_authored_by(content, user)) assert utils.is_content_authored_by(content, user)
# strict equality checking, fails # strict equality checking, fails
content['user_id'] = 2 content['user_id'] = 2
self.assertFalse(utils.is_content_authored_by(content, user)) assert not utils.is_content_authored_by(content, user)
# cast from string to int, fails # cast from string to int, fails
content['user_id'] = 'string' content['user_id'] = 'string'
self.assertFalse(utils.is_content_authored_by(content, user)) assert not utils.is_content_authored_by(content, user)
# content has no known author # content has no known author
del content['user_id'] del content['user_id']
self.assertFalse(utils.is_content_authored_by(content, user)) assert not utils.is_content_authored_by(content, user)
class GroupModeratorPermissionsTestCase(ModuleStoreTestCase): class GroupModeratorPermissionsTestCase(ModuleStoreTestCase):
@@ -1733,32 +1639,11 @@ class GroupModeratorPermissionsTestCase(ModuleStoreTestCase):
Group moderator should not have moderator permissions if the discussions are not divided. Group moderator should not have moderator permissions if the discussions are not divided.
""" """
content = {'user_id': self.plain_user.id, 'type': 'thread', 'username': self.plain_user.username} content = {'user_id': self.plain_user.id, 'type': 'thread', 'username': self.plain_user.username}
self.assertEqual(utils.get_ability(self.course.id, content, self.group_moderator), { assert utils.get_ability(self.course.id, content, self.group_moderator) == {'editable': False, 'can_reply': True, 'can_delete': False, 'can_openclose': False, 'can_vote': True, 'can_report': True}
'editable': False,
'can_reply': True,
'can_delete': False,
'can_openclose': False,
'can_vote': True,
'can_report': True
})
content = {'user_id': self.cohorted_user.id, 'type': 'thread'} content = {'user_id': self.cohorted_user.id, 'type': 'thread'}
self.assertEqual(utils.get_ability(self.course.id, content, self.group_moderator), { assert utils.get_ability(self.course.id, content, self.group_moderator) == {'editable': False, 'can_reply': True, 'can_delete': False, 'can_openclose': False, 'can_vote': True, 'can_report': True}
'editable': False,
'can_reply': True,
'can_delete': False,
'can_openclose': False,
'can_vote': True,
'can_report': True
})
content = {'user_id': self.verified_user.id, 'type': 'thread'} content = {'user_id': self.verified_user.id, 'type': 'thread'}
self.assertEqual(utils.get_ability(self.course.id, content, self.group_moderator), { assert utils.get_ability(self.course.id, content, self.group_moderator) == {'editable': False, 'can_reply': True, 'can_delete': False, 'can_openclose': False, 'can_vote': True, 'can_report': True}
'editable': False,
'can_reply': True,
'can_delete': False,
'can_openclose': False,
'can_vote': True,
'can_report': True
})
@mock.patch( @mock.patch(
'lms.djangoapps.discussion.django_comment_client.permissions._check_condition', 'lms.djangoapps.discussion.django_comment_client.permissions._check_condition',
@@ -1771,14 +1656,7 @@ class GroupModeratorPermissionsTestCase(ModuleStoreTestCase):
set_discussion_division_settings(self.course.id, enable_cohorts=True, set_discussion_division_settings(self.course.id, enable_cohorts=True,
division_scheme=CourseDiscussionSettings.COHORT) division_scheme=CourseDiscussionSettings.COHORT)
content = {'user_id': self.cohorted_user.id, 'type': 'thread', 'username': self.cohorted_user.username} content = {'user_id': self.cohorted_user.id, 'type': 'thread', 'username': self.cohorted_user.username}
self.assertEqual(utils.get_ability(self.course.id, content, self.group_moderator), { assert utils.get_ability(self.course.id, content, self.group_moderator) == {'editable': True, 'can_reply': True, 'can_delete': True, 'can_openclose': True, 'can_vote': True, 'can_report': True}
'editable': True,
'can_reply': True,
'can_delete': True,
'can_openclose': True,
'can_vote': True,
'can_report': True
})
@mock.patch( @mock.patch(
'lms.djangoapps.discussion.django_comment_client.permissions._check_condition', 'lms.djangoapps.discussion.django_comment_client.permissions._check_condition',
@@ -1791,14 +1669,7 @@ class GroupModeratorPermissionsTestCase(ModuleStoreTestCase):
content = {'user_id': self.plain_user.id, 'type': 'thread', 'username': self.plain_user.username} content = {'user_id': self.plain_user.id, 'type': 'thread', 'username': self.plain_user.username}
set_discussion_division_settings(self.course.id, division_scheme=CourseDiscussionSettings.NONE) set_discussion_division_settings(self.course.id, division_scheme=CourseDiscussionSettings.NONE)
self.assertEqual(utils.get_ability(self.course.id, content, self.group_moderator), { assert utils.get_ability(self.course.id, content, self.group_moderator) == {'editable': False, 'can_reply': True, 'can_delete': False, 'can_openclose': False, 'can_vote': True, 'can_report': True}
'editable': False,
'can_reply': True,
'can_delete': False,
'can_openclose': False,
'can_vote': True,
'can_report': True
})
class ClientConfigurationTestCase(TestCase): class ClientConfigurationTestCase(TestCase):
@@ -1810,7 +1681,7 @@ class ClientConfigurationTestCase(TestCase):
config.enabled = False config.enabled = False
config.save() config.save()
with self.assertRaises(CommentClientMaintenanceError): with pytest.raises(CommentClientMaintenanceError):
perform_request('GET', 'http://www.google.com') perform_request('GET', 'http://www.google.com')
@patch('requests.request') @patch('requests.request')
@@ -1827,7 +1698,7 @@ class ClientConfigurationTestCase(TestCase):
mock_request.return_value = response mock_request.return_value = response
result = perform_request('GET', 'http://www.google.com') result = perform_request('GET', 'http://www.google.com')
self.assertEqual(result, {}) assert result == {}
def set_discussion_division_settings( def set_discussion_division_settings(
@@ -1865,10 +1736,10 @@ class MiscUtilsTests(TestCase):
thread_data = {'id': content_id, 'course_id': course_id, 'commentable_id': discussion_id, 'type': 'thread'} thread_data = {'id': content_id, 'course_id': course_id, 'commentable_id': discussion_id, 'type': 'thread'}
expected_url = reverse('single_thread', kwargs=url_kwargs) expected_url = reverse('single_thread', kwargs=url_kwargs)
self.assertEqual(utils.permalink(thread_data), expected_url) assert utils.permalink(thread_data) == expected_url
thread_data['course_id'] = CourseKey.from_string(course_id) thread_data['course_id'] = CourseKey.from_string(course_id)
self.assertEqual(utils.permalink(thread_data), expected_url) assert utils.permalink(thread_data) == expected_url
@ddt.data( @ddt.data(
('course-v1:edX+foo101+bar_t2', '99', '99'), ('course-v1:edX+foo101+bar_t2', '99', '99'),
@@ -1887,7 +1758,7 @@ class MiscUtilsTests(TestCase):
} }
expected_url = reverse('single_thread', kwargs=url_kwargs) + '#' + thread_data['id'] expected_url = reverse('single_thread', kwargs=url_kwargs) + '#' + thread_data['id']
self.assertEqual(utils.permalink(thread_data), expected_url) assert utils.permalink(thread_data) == expected_url
thread_data['course_id'] = CourseKey.from_string(course_id) thread_data['course_id'] = CourseKey.from_string(course_id)
self.assertEqual(utils.permalink(thread_data), expected_url) assert utils.permalink(thread_data) == expected_url

View File

@@ -58,17 +58,16 @@ class NotificationPrefViewTest(UrlResetMixin, TestCase): # lint-amnesty, pylint
def assertPrefValid(self, user): def assertPrefValid(self, user):
"""Ensure that the correct preference for the user is persisted""" """Ensure that the correct preference for the user is persisted"""
pref = UserPreference.objects.get(user=user, key=NOTIFICATION_PREF_KEY) pref = UserPreference.objects.get(user=user, key=NOTIFICATION_PREF_KEY)
self.assertTrue(pref) # check exists and only 1 (.get) assert pref
# check exists and only 1 (.get)
# now coerce username to utf-8 encoded str, since we test with non-ascii unicdoe above and # now coerce username to utf-8 encoded str, since we test with non-ascii unicdoe above and
# the unittest framework has hard time coercing to unicode. # the unittest framework has hard time coercing to unicode.
# decrypt also can't take a unicode input, so coerce its input to str # decrypt also can't take a unicode input, so coerce its input to str
self.assertEqual(six.binary_type(user.username.encode('utf-8')), UsernameCipher().decrypt(str(pref.value))) assert six.binary_type(user.username.encode('utf-8')) == UsernameCipher().decrypt(str(pref.value))
def assertNotPrefExists(self, user): def assertNotPrefExists(self, user):
"""Ensure that the user does not have a persisted preference""" """Ensure that the user does not have a persisted preference"""
self.assertFalse( assert not UserPreference.objects.filter(user=user, key=NOTIFICATION_PREF_KEY).exists()
UserPreference.objects.filter(user=user, key=NOTIFICATION_PREF_KEY).exists()
)
# AJAX status view # AJAX status view
@@ -76,22 +75,22 @@ class NotificationPrefViewTest(UrlResetMixin, TestCase): # lint-amnesty, pylint
request = self.request_factory.get("dummy") request = self.request_factory.get("dummy")
request.user = self.user request.user = self.user
response = ajax_status(request) response = ajax_status(request)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertEqual(json.loads(response.content.decode('utf-8')), {"status": 0}) assert json.loads(response.content.decode('utf-8')) == {'status': 0}
def test_ajax_status_get_1(self): def test_ajax_status_get_1(self):
self.create_prefs() self.create_prefs()
request = self.request_factory.get("dummy") request = self.request_factory.get("dummy")
request.user = self.user request.user = self.user
response = ajax_status(request) response = ajax_status(request)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertEqual(json.loads(response.content.decode('utf-8')), {"status": 1}) assert json.loads(response.content.decode('utf-8')) == {'status': 1}
def test_ajax_status_post(self): def test_ajax_status_post(self):
request = self.request_factory.post("dummy") request = self.request_factory.post("dummy")
request.user = self.user request.user = self.user
response = ajax_status(request) response = ajax_status(request)
self.assertEqual(response.status_code, 405) assert response.status_code == 405
def test_ajax_status_anon_user(self): def test_ajax_status_anon_user(self):
request = self.request_factory.get("dummy") request = self.request_factory.get("dummy")
@@ -104,7 +103,7 @@ class NotificationPrefViewTest(UrlResetMixin, TestCase): # lint-amnesty, pylint
request = self.request_factory.get("dummy") request = self.request_factory.get("dummy")
request.user = self.user request.user = self.user
response = ajax_enable(request) response = ajax_enable(request)
self.assertEqual(response.status_code, 405) assert response.status_code == 405
self.assertNotPrefExists(self.user) self.assertNotPrefExists(self.user)
def test_ajax_enable_anon_user(self): def test_ajax_enable_anon_user(self):
@@ -121,7 +120,7 @@ class NotificationPrefViewTest(UrlResetMixin, TestCase): # lint-amnesty, pylint
request = self.request_factory.post("dummy") request = self.request_factory.post("dummy")
request.user = user request.user = user
response = ajax_enable(request) response = ajax_enable(request)
self.assertEqual(response.status_code, 204) assert response.status_code == 204
self.assertPrefValid(user) self.assertPrefValid(user)
for user in self.tokens.keys(): for user in self.tokens.keys():
@@ -132,7 +131,7 @@ class NotificationPrefViewTest(UrlResetMixin, TestCase): # lint-amnesty, pylint
request = self.request_factory.post("dummy") request = self.request_factory.post("dummy")
request.user = self.user request.user = self.user
response = ajax_enable(request) response = ajax_enable(request)
self.assertEqual(response.status_code, 204) assert response.status_code == 204
self.assertPrefValid(self.user) self.assertPrefValid(self.user)
def test_ajax_enable_distinct_values(self): def test_ajax_enable_distinct_values(self):
@@ -142,10 +141,11 @@ class NotificationPrefViewTest(UrlResetMixin, TestCase): # lint-amnesty, pylint
other_user = UserFactory.create() other_user = UserFactory.create()
request.user = other_user request.user = other_user
ajax_enable(request) ajax_enable(request)
self.assertNotEqual( assert UserPreference.objects.get(
UserPreference.objects.get(user=self.user, key=NOTIFICATION_PREF_KEY).value, user=self.user, key=NOTIFICATION_PREF_KEY
UserPreference.objects.get(user=other_user, key=NOTIFICATION_PREF_KEY).value ).value != UserPreference.objects.get(
) user=other_user, key=NOTIFICATION_PREF_KEY
).value
# AJAX disable view # AJAX disable view
@@ -154,7 +154,7 @@ class NotificationPrefViewTest(UrlResetMixin, TestCase): # lint-amnesty, pylint
request = self.request_factory.get("dummy") request = self.request_factory.get("dummy")
request.user = self.user request.user = self.user
response = ajax_disable(request) response = ajax_disable(request)
self.assertEqual(response.status_code, 405) assert response.status_code == 405
self.assertPrefValid(self.user) self.assertPrefValid(self.user)
def test_ajax_disable_anon_user(self): def test_ajax_disable_anon_user(self):
@@ -169,14 +169,14 @@ class NotificationPrefViewTest(UrlResetMixin, TestCase): # lint-amnesty, pylint
request = self.request_factory.post("dummy") request = self.request_factory.post("dummy")
request.user = self.user request.user = self.user
response = ajax_disable(request) response = ajax_disable(request)
self.assertEqual(response.status_code, 204) assert response.status_code == 204
self.assertNotPrefExists(self.user) self.assertNotPrefExists(self.user)
def test_ajax_disable_already_disabled(self): def test_ajax_disable_already_disabled(self):
request = self.request_factory.post("dummy") request = self.request_factory.post("dummy")
request.user = self.user request.user = self.user
response = ajax_disable(request) response = ajax_disable(request)
self.assertEqual(response.status_code, 204) assert response.status_code == 204
self.assertNotPrefExists(self.user) self.assertNotPrefExists(self.user)
# Unsubscribe view # Unsubscribe view
@@ -184,7 +184,7 @@ class NotificationPrefViewTest(UrlResetMixin, TestCase): # lint-amnesty, pylint
def test_unsubscribe_post(self): def test_unsubscribe_post(self):
request = self.request_factory.post("dummy") request = self.request_factory.post("dummy")
response = set_subscription(request, "dummy", subscribe=False) response = set_subscription(request, "dummy", subscribe=False)
self.assertEqual(response.status_code, 405) assert response.status_code == 405
def test_unsubscribe_invalid_token(self): def test_unsubscribe_invalid_token(self):
def test_invalid_token(token, message): def test_invalid_token(token, message):
@@ -225,7 +225,7 @@ class NotificationPrefViewTest(UrlResetMixin, TestCase): # lint-amnesty, pylint
url = reverse('unsubscribe_forum_update', args=[self.tokens[user]]) url = reverse('unsubscribe_forum_update', args=[self.tokens[user]])
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertNotPrefExists(user) self.assertNotPrefExists(user)
for user in self.tokens.keys(): for user in self.tokens.keys():
@@ -237,16 +237,16 @@ class NotificationPrefViewTest(UrlResetMixin, TestCase): # lint-amnesty, pylint
url = reverse('unsubscribe_forum_update', args=[self.tokens[self.user]]) url = reverse('unsubscribe_forum_update', args=[self.tokens[self.user]])
self.client.get(url) self.client.get(url)
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertNotPrefExists(self.user) self.assertNotPrefExists(self.user)
def test_resubscribe_success(self): def test_resubscribe_success(self):
def test_user(user): def test_user(user):
# start without a pref key # start without a pref key
self.assertFalse(UserPreference.objects.filter(user=user, key=NOTIFICATION_PREF_KEY)) assert not UserPreference.objects.filter(user=user, key=NOTIFICATION_PREF_KEY)
url = reverse('resubscribe_forum_update', args=[self.tokens[user]]) url = reverse('resubscribe_forum_update', args=[self.tokens[user]])
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertPrefValid(user) self.assertPrefValid(user)
for user in self.tokens.keys(): for user in self.tokens.keys():

View File

@@ -5,7 +5,7 @@ Tests for Discussion API internal interface
import itertools import itertools
from datetime import datetime, timedelta from datetime import datetime, timedelta
import pytest
import ddt import ddt
import httpretty import httpretty
import mock import mock
@@ -153,32 +153,28 @@ class GetCourseTest(ForumsEnableMixin, UrlResetMixin, SharedModuleStoreTestCase)
self.request.user = self.user self.request.user = self.user
def test_nonexistent_course(self): def test_nonexistent_course(self):
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
get_course(self.request, CourseLocator.from_string("non/existent/course")) get_course(self.request, CourseLocator.from_string("non/existent/course"))
def test_not_enrolled(self): def test_not_enrolled(self):
unenrolled_user = UserFactory.create() unenrolled_user = UserFactory.create()
self.request.user = unenrolled_user self.request.user = unenrolled_user
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
get_course(self.request, self.course.id) get_course(self.request, self.course.id)
def test_discussions_disabled(self): def test_discussions_disabled(self):
with self.assertRaises(DiscussionDisabledError): with pytest.raises(DiscussionDisabledError):
get_course(self.request, _discussion_disabled_course_for(self.user).id) get_course(self.request, _discussion_disabled_course_for(self.user).id)
def test_basic(self): def test_basic(self):
self.assertEqual( assert get_course(self.request, self.course.id) == {
get_course(self.request, self.course.id), 'id': six.text_type(self.course.id),
{ 'blackouts': [],
"id": six.text_type(self.course.id), 'thread_list_url': 'http://testserver/api/discussion/v1/threads/?course_id=x%2Fy%2Fz',
"blackouts": [], 'following_thread_list_url':
"thread_list_url": "http://testserver/api/discussion/v1/threads/?course_id=x%2Fy%2Fz", 'http://testserver/api/discussion/v1/threads/?course_id=x%2Fy%2Fz&following=True',
"following_thread_list_url": ( 'topics_url': 'http://testserver/api/discussion/v1/course_topics/x/y/z'
"http://testserver/api/discussion/v1/threads/?course_id=x%2Fy%2Fz&following=True" }
),
"topics_url": "http://testserver/api/discussion/v1/course_topics/x/y/z",
}
)
@ddt.ddt @ddt.ddt
@@ -205,13 +201,10 @@ class GetCourseTestBlackouts(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCa
] ]
modulestore().update_item(self.course, self.user.id) modulestore().update_item(self.course, self.user.id)
result = get_course(self.request, self.course.id) result = get_course(self.request, self.course.id)
self.assertEqual( assert result['blackouts'] == [
result["blackouts"], {'start': '2015-06-09T00:00:00Z', 'end': '2015-06-10T00:00:00Z'},
[ {'start': '2015-06-11T00:00:00Z', 'end': '2015-06-12T00:00:00Z'}
{"start": "2015-06-09T00:00:00Z", "end": "2015-06-10T00:00:00Z"}, ]
{"start": "2015-06-11T00:00:00Z", "end": "2015-06-12T00:00:00Z"},
]
)
@ddt.data(None, "not a datetime", "2015", []) @ddt.data(None, "not a datetime", "2015", [])
def test_blackout_errors(self, bad_value): def test_blackout_errors(self, bad_value):
@@ -221,7 +214,7 @@ class GetCourseTestBlackouts(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCa
] ]
modulestore().update_item(self.course, self.user.id) modulestore().update_item(self.course, self.user.id)
result = get_course(self.request, self.course.id) result = get_course(self.request, self.course.id)
self.assertEqual(result["blackouts"], []) assert result['blackouts'] == []
@mock.patch.dict("django.conf.settings.FEATURES", {"DISABLE_START_DATES": False}) @mock.patch.dict("django.conf.settings.FEATURES", {"DISABLE_START_DATES": False})
@@ -300,18 +293,18 @@ class GetCourseTopicsTest(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
return node return node
def test_nonexistent_course(self): def test_nonexistent_course(self):
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
get_course_topics(self.request, CourseLocator.from_string("non/existent/course")) get_course_topics(self.request, CourseLocator.from_string("non/existent/course"))
def test_not_enrolled(self): def test_not_enrolled(self):
unenrolled_user = UserFactory.create() unenrolled_user = UserFactory.create()
self.request.user = unenrolled_user self.request.user = unenrolled_user
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
self.get_course_topics() self.get_course_topics()
def test_discussions_disabled(self): def test_discussions_disabled(self):
_remove_discussion_tab(self.course, self.user.id) _remove_discussion_tab(self.course, self.user.id)
with self.assertRaises(DiscussionDisabledError): with pytest.raises(DiscussionDisabledError):
self.get_course_topics() self.get_course_topics()
def test_without_courseware(self): def test_without_courseware(self):
@@ -322,7 +315,7 @@ class GetCourseTopicsTest(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
self.make_expected_tree("non-courseware-topic-id", "Test Topic") self.make_expected_tree("non-courseware-topic-id", "Test Topic")
], ],
} }
self.assertEqual(actual, expected) assert actual == expected
def test_with_courseware(self): def test_with_courseware(self):
self.make_discussion_xblock("courseware-topic-id", "Foo", "Bar") self.make_discussion_xblock("courseware-topic-id", "Foo", "Bar")
@@ -339,7 +332,7 @@ class GetCourseTopicsTest(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
self.make_expected_tree("non-courseware-topic-id", "Test Topic") self.make_expected_tree("non-courseware-topic-id", "Test Topic")
], ],
} }
self.assertEqual(actual, expected) assert actual == expected
def test_many(self): def test_many(self):
with self.store.bulk_operations(self.course.id, emit_signals=False): with self.store.bulk_operations(self.course.id, emit_signals=False):
@@ -383,7 +376,7 @@ class GetCourseTopicsTest(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
self.make_expected_tree("non-courseware-2", "B"), self.make_expected_tree("non-courseware-2", "B"),
], ],
} }
self.assertEqual(actual, expected) assert actual == expected
def test_sort_key(self): def test_sort_key(self):
with self.store.bulk_operations(self.course.id, emit_signals=False): with self.store.bulk_operations(self.course.id, emit_signals=False):
@@ -432,7 +425,7 @@ class GetCourseTopicsTest(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
self.make_expected_tree("non-courseware-1", "W"), self.make_expected_tree("non-courseware-1", "W"),
], ],
} }
self.assertEqual(actual, expected) assert actual == expected
def test_access_control(self): def test_access_control(self):
""" """
@@ -499,7 +492,7 @@ class GetCourseTopicsTest(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
self.make_expected_tree("non-courseware-topic-id", "Test Topic"), self.make_expected_tree("non-courseware-topic-id", "Test Topic"),
], ],
} }
self.assertEqual(student_actual, student_expected) assert student_actual == student_expected
self.request.user = beta_tester self.request.user = beta_tester
beta_actual = self.get_course_topics() beta_actual = self.get_course_topics()
beta_expected = { beta_expected = {
@@ -522,7 +515,7 @@ class GetCourseTopicsTest(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
self.make_expected_tree("non-courseware-topic-id", "Test Topic"), self.make_expected_tree("non-courseware-topic-id", "Test Topic"),
], ],
} }
self.assertEqual(beta_actual, beta_expected) assert beta_actual == beta_expected
self.request.user = staff self.request.user = staff
staff_actual = self.get_course_topics() staff_actual = self.get_course_topics()
@@ -550,7 +543,7 @@ class GetCourseTopicsTest(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
self.make_expected_tree("non-courseware-topic-id", "Test Topic"), self.make_expected_tree("non-courseware-topic-id", "Test Topic"),
], ],
} }
self.assertEqual(staff_actual, staff_expected) assert staff_actual == staff_expected
def test_discussion_topic(self): def test_discussion_topic(self):
""" """
@@ -561,41 +554,35 @@ class GetCourseTopicsTest(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
self.make_discussion_xblock(topic_id_1, "test_category_1", "test_target_1") self.make_discussion_xblock(topic_id_1, "test_category_1", "test_target_1")
self.make_discussion_xblock(topic_id_2, "test_category_2", "test_target_2") self.make_discussion_xblock(topic_id_2, "test_category_2", "test_target_2")
actual = get_course_topics(self.request, self.course.id, {"topic_id_1", "topic_id_2"}) actual = get_course_topics(self.request, self.course.id, {"topic_id_1", "topic_id_2"})
self.assertEqual( assert actual == {
actual, 'non_courseware_topics': [],
{ 'courseware_topics': [
"non_courseware_topics": [], {'children': [
"courseware_topics": [ {'children': [],
{ 'id': 'topic_id_1',
"children": [{ 'thread_list_url':
"children": [], 'http://testserver/api/discussion/v1/threads/?course_id=x%2Fy%2Fz&topic_id=topic_id_1',
"id": "topic_id_1", 'name': 'test_target_1'}
"thread_list_url": "http://testserver/api/discussion/v1/threads/?" ],
"course_id=x%2Fy%2Fz&topic_id=topic_id_1", 'id': None,
"name": "test_target_1" 'thread_list_url':
}], 'http://testserver/api/discussion/v1/threads/?course_id=x%2Fy%2Fz&topic_id=topic_id_1',
"id": None, 'name': 'test_category_1'
"thread_list_url": "http://testserver/api/discussion/v1/threads/?" },
"course_id=x%2Fy%2Fz&topic_id=topic_id_1", {'children': [
"name": "test_category_1" {'children': [],
}, 'id': 'topic_id_2',
{ 'thread_list_url':
"children": 'http://testserver/api/discussion/v1/threads/?course_id=x%2Fy%2Fz&topic_id=topic_id_2',
[{ 'name': 'test_target_2'}
"children": [], ],
"id": "topic_id_2", 'id': None,
"thread_list_url": "http://testserver/api/discussion/v1/threads/?" 'thread_list_url':
"course_id=x%2Fy%2Fz&topic_id=topic_id_2", 'http://testserver/api/discussion/v1/threads/?course_id=x%2Fy%2Fz&topic_id=topic_id_2',
"name": "test_target_2" 'name': 'test_category_2'
}], }
"id": None, ]
"thread_list_url": "http://testserver/api/discussion/v1/threads/?" }
"course_id=x%2Fy%2Fz&topic_id=topic_id_2",
"name": "test_category_2"
}
]
}
)
@ddt.ddt @ddt.ddt
@@ -645,36 +632,35 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
return ret return ret
def test_nonexistent_course(self): def test_nonexistent_course(self):
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
get_thread_list(self.request, CourseLocator.from_string("non/existent/course"), 1, 1) get_thread_list(self.request, CourseLocator.from_string("non/existent/course"), 1, 1)
def test_not_enrolled(self): def test_not_enrolled(self):
self.request.user = UserFactory.create() self.request.user = UserFactory.create()
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
self.get_thread_list([]) self.get_thread_list([])
def test_discussions_disabled(self): def test_discussions_disabled(self):
with self.assertRaises(DiscussionDisabledError): with pytest.raises(DiscussionDisabledError):
self.get_thread_list([], course=_discussion_disabled_course_for(self.user)) self.get_thread_list([], course=_discussion_disabled_course_for(self.user))
def test_empty(self): def test_empty(self):
self.assertEqual( assert self.get_thread_list(
self.get_thread_list([], num_pages=0).data, [], num_pages=0
{ ).data == {
"pagination": { 'pagination': {
"next": None, 'next': None,
"previous": None, 'previous': None,
"num_pages": 0, 'num_pages': 0,
"count": 0 'count': 0
}, },
"results": [], 'results': [],
"text_search_rewrite": None, 'text_search_rewrite': None
} }
)
def test_get_threads_by_topic_id(self): def test_get_threads_by_topic_id(self):
self.get_thread_list([], topic_id_list=["topic_x", "topic_meow"]) self.get_thread_list([], topic_id_list=["topic_x", "topic_meow"])
self.assertEqual(urlparse(httpretty.last_request().path).path, "/api/v1/threads") # lint-amnesty, pylint: disable=no-member assert urlparse(httpretty.last_request().path).path == '/api/v1/threads' # lint-amnesty, pylint: disable=no-member
self.assert_last_query_params({ self.assert_last_query_params({
"user_id": [six.text_type(self.user.id)], "user_id": [six.text_type(self.user.id)],
"course_id": [six.text_type(self.course.id)], "course_id": [six.text_type(self.course.id)],
@@ -774,10 +760,7 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
results=expected_threads, count=2, num_pages=1, next_link=None, previous_link=None results=expected_threads, count=2, num_pages=1, next_link=None, previous_link=None
) )
expected_result.update({"text_search_rewrite": None}) expected_result.update({"text_search_rewrite": None})
self.assertEqual( assert self.get_thread_list(source_threads).data == expected_result
self.get_thread_list(source_threads).data,
expected_result
)
@ddt.data( @ddt.data(
*itertools.product( *itertools.product(
@@ -799,7 +782,7 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
self.get_thread_list([], course=cohort_course) self.get_thread_list([], course=cohort_course)
actual_has_group = "group_id" in httpretty.last_request().querystring # lint-amnesty, pylint: disable=no-member actual_has_group = "group_id" in httpretty.last_request().querystring # lint-amnesty, pylint: disable=no-member
expected_has_group = (course_is_cohorted and role_name == FORUM_ROLE_STUDENT) expected_has_group = (course_is_cohorted and role_name == FORUM_ROLE_STUDENT)
self.assertEqual(actual_has_group, expected_has_group) assert actual_has_group == expected_has_group
def test_pagination(self): def test_pagination(self):
# N.B. Empty thread list is not realistic but convenient for this test # N.B. Empty thread list is not realistic but convenient for this test
@@ -807,10 +790,7 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
results=[], count=0, num_pages=3, next_link="http://testserver/test_path?page=2", previous_link=None results=[], count=0, num_pages=3, next_link="http://testserver/test_path?page=2", previous_link=None
) )
expected_result.update({"text_search_rewrite": None}) expected_result.update({"text_search_rewrite": None})
self.assertEqual( assert self.get_thread_list([], page=1, num_pages=3).data == expected_result
self.get_thread_list([], page=1, num_pages=3).data,
expected_result
)
expected_result = make_paginated_api_response( expected_result = make_paginated_api_response(
results=[], results=[],
@@ -820,23 +800,17 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
previous_link="http://testserver/test_path?page=1" previous_link="http://testserver/test_path?page=1"
) )
expected_result.update({"text_search_rewrite": None}) expected_result.update({"text_search_rewrite": None})
self.assertEqual( assert self.get_thread_list([], page=2, num_pages=3).data == expected_result
self.get_thread_list([], page=2, num_pages=3).data,
expected_result
)
expected_result = make_paginated_api_response( expected_result = make_paginated_api_response(
results=[], count=0, num_pages=3, next_link=None, previous_link="http://testserver/test_path?page=2" results=[], count=0, num_pages=3, next_link=None, previous_link="http://testserver/test_path?page=2"
) )
expected_result.update({"text_search_rewrite": None}) expected_result.update({"text_search_rewrite": None})
self.assertEqual( assert self.get_thread_list([], page=3, num_pages=3).data == expected_result
self.get_thread_list([], page=3, num_pages=3).data,
expected_result
)
# Test page past the last one # Test page past the last one
self.register_get_threads_response([], page=3, num_pages=3) self.register_get_threads_response([], page=3, num_pages=3)
with self.assertRaises(PageNotFoundError): with pytest.raises(PageNotFoundError):
get_thread_list(self.request, self.course.id, page=4, page_size=10) get_thread_list(self.request, self.course.id, page=4, page_size=10)
@ddt.data(None, "rewritten search string") @ddt.data(None, "rewritten search string")
@@ -846,16 +820,13 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
) )
expected_result.update({"text_search_rewrite": text_search_rewrite}) expected_result.update({"text_search_rewrite": text_search_rewrite})
self.register_get_threads_search_response([], text_search_rewrite, num_pages=0) self.register_get_threads_search_response([], text_search_rewrite, num_pages=0)
self.assertEqual( assert get_thread_list(
get_thread_list( self.request,
self.request, self.course.id,
self.course.id, page=1,
page=1, page_size=10,
page_size=10, text_search='test search string'
text_search="test search string" ).data == expected_result
).data,
expected_result
)
self.assert_last_query_params({ self.assert_last_query_params({
"user_id": [six.text_type(self.user.id)], "user_id": [six.text_type(self.user.id)],
"course_id": [six.text_type(self.course.id)], "course_id": [six.text_type(self.course.id)],
@@ -879,14 +850,10 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
results=[], count=0, num_pages=0, next_link=None, previous_link=None results=[], count=0, num_pages=0, next_link=None, previous_link=None
) )
expected_result.update({"text_search_rewrite": None}) expected_result.update({"text_search_rewrite": None})
self.assertEqual( assert result == expected_result
result, assert urlparse(
expected_result httpretty.last_request().path # lint-amnesty, pylint: disable=no-member
) ).path == '/api/v1/users/{}/subscribed_threads'.format(self.user.id)
self.assertEqual(
urlparse(httpretty.last_request().path).path, # lint-amnesty, pylint: disable=no-member
"/api/v1/users/{}/subscribed_threads".format(self.user.id)
)
self.assert_last_query_params({ self.assert_last_query_params({
"user_id": [six.text_type(self.user.id)], "user_id": [six.text_type(self.user.id)],
"course_id": [six.text_type(self.course.id)], "course_id": [six.text_type(self.course.id)],
@@ -910,14 +877,8 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
results=[], count=0, num_pages=0, next_link=None, previous_link=None results=[], count=0, num_pages=0, next_link=None, previous_link=None
) )
expected_result.update({"text_search_rewrite": None}) expected_result.update({"text_search_rewrite": None})
self.assertEqual( assert result == expected_result
result, assert urlparse(httpretty.last_request().path).path == '/api/v1/threads' # lint-amnesty, pylint: disable=no-member
expected_result
)
self.assertEqual(
urlparse(httpretty.last_request().path).path, # lint-amnesty, pylint: disable=no-member
"/api/v1/threads"
)
self.assert_last_query_params({ self.assert_last_query_params({
"user_id": [six.text_type(self.user.id)], "user_id": [six.text_type(self.user.id)],
"course_id": [six.text_type(self.course.id)], "course_id": [six.text_type(self.course.id)],
@@ -954,11 +915,8 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
results=[], count=0, num_pages=0, next_link=None, previous_link=None results=[], count=0, num_pages=0, next_link=None, previous_link=None
) )
expected_result.update({"text_search_rewrite": None}) expected_result.update({"text_search_rewrite": None})
self.assertEqual(result, expected_result) assert result == expected_result
self.assertEqual( assert urlparse(httpretty.last_request().path).path == '/api/v1/threads' # lint-amnesty, pylint: disable=no-member
urlparse(httpretty.last_request().path).path, # lint-amnesty, pylint: disable=no-member
"/api/v1/threads"
)
self.assert_last_query_params({ self.assert_last_query_params({
"user_id": [six.text_type(self.user.id)], "user_id": [six.text_type(self.user.id)],
"course_id": [six.text_type(self.course.id)], "course_id": [six.text_type(self.course.id)],
@@ -985,11 +943,8 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
results=[], count=0, num_pages=0, next_link=None, previous_link=None results=[], count=0, num_pages=0, next_link=None, previous_link=None
) )
expected_result.update({"text_search_rewrite": None}) expected_result.update({"text_search_rewrite": None})
self.assertEqual(result, expected_result) assert result == expected_result
self.assertEqual( assert urlparse(httpretty.last_request().path).path == '/api/v1/threads' # lint-amnesty, pylint: disable=no-member
urlparse(httpretty.last_request().path).path, # lint-amnesty, pylint: disable=no-member
"/api/v1/threads"
)
self.assert_last_query_params({ self.assert_last_query_params({
"user_id": [six.text_type(self.user.id)], "user_id": [six.text_type(self.user.id)],
"course_id": [six.text_type(self.course.id)], "course_id": [six.text_type(self.course.id)],
@@ -1002,7 +957,7 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
""" """
Test with invalid order_direction (e.g. "asc") Test with invalid order_direction (e.g. "asc")
""" """
with self.assertRaises(ValidationError) as assertion: with pytest.raises(ValidationError) as assertion:
self.register_get_threads_response([], page=1, num_pages=0) self.register_get_threads_response([], page=1, num_pages=0)
get_thread_list( # pylint: disable=expression-not-assigned get_thread_list( # pylint: disable=expression-not-assigned
self.request, self.request,
@@ -1011,7 +966,7 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix
page_size=11, page_size=11,
order_direction="asc", order_direction="asc",
).data ).data
self.assertIn("order_direction", assertion.exception.message_dict) assert 'order_direction' in assertion.value.message_dict
@ddt.ddt @ddt.ddt
@@ -1059,21 +1014,21 @@ class GetCommentListTest(ForumsEnableMixin, CommentsServiceMockMixin, SharedModu
def test_nonexistent_thread(self): def test_nonexistent_thread(self):
thread_id = "nonexistent_thread" thread_id = "nonexistent_thread"
self.register_get_thread_error_response(thread_id, 404) self.register_get_thread_error_response(thread_id, 404)
with self.assertRaises(ThreadNotFoundError): with pytest.raises(ThreadNotFoundError):
get_comment_list(self.request, thread_id, endorsed=False, page=1, page_size=1) get_comment_list(self.request, thread_id, endorsed=False, page=1, page_size=1)
def test_nonexistent_course(self): def test_nonexistent_course(self):
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
self.get_comment_list(self.make_minimal_cs_thread({"course_id": "non/existent/course"})) self.get_comment_list(self.make_minimal_cs_thread({"course_id": "non/existent/course"}))
def test_not_enrolled(self): def test_not_enrolled(self):
self.request.user = UserFactory.create() self.request.user = UserFactory.create()
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
self.get_comment_list(self.make_minimal_cs_thread()) self.get_comment_list(self.make_minimal_cs_thread())
def test_discussions_disabled(self): def test_discussions_disabled(self):
disabled_course = _discussion_disabled_course_for(self.user) disabled_course = _discussion_disabled_course_for(self.user)
with self.assertRaises(DiscussionDisabledError): with pytest.raises(DiscussionDisabledError):
self.get_comment_list( self.get_comment_list(
self.make_minimal_cs_thread( self.make_minimal_cs_thread(
overrides={"course_id": six.text_type(disabled_course.id)} overrides={"course_id": six.text_type(disabled_course.id)}
@@ -1128,41 +1083,33 @@ class GetCommentListTest(ForumsEnableMixin, CommentsServiceMockMixin, SharedModu
) )
try: try:
self.get_comment_list(thread) self.get_comment_list(thread)
self.assertFalse(expected_error) assert not expected_error
except ThreadNotFoundError: except ThreadNotFoundError:
self.assertTrue(expected_error) assert expected_error
@ddt.data(True, False) @ddt.data(True, False)
def test_discussion_endorsed(self, endorsed_value): def test_discussion_endorsed(self, endorsed_value):
with self.assertRaises(ValidationError) as assertion: with pytest.raises(ValidationError) as assertion:
self.get_comment_list( self.get_comment_list(
self.make_minimal_cs_thread({"thread_type": "discussion"}), self.make_minimal_cs_thread({"thread_type": "discussion"}),
endorsed=endorsed_value endorsed=endorsed_value
) )
self.assertEqual( assert assertion.value.message_dict == {'endorsed': ['This field may not be specified for discussion threads.']}
assertion.exception.message_dict,
{"endorsed": ["This field may not be specified for discussion threads."]}
)
def test_question_without_endorsed(self): def test_question_without_endorsed(self):
with self.assertRaises(ValidationError) as assertion: with pytest.raises(ValidationError) as assertion:
self.get_comment_list( self.get_comment_list(
self.make_minimal_cs_thread({"thread_type": "question"}), self.make_minimal_cs_thread({"thread_type": "question"}),
endorsed=None endorsed=None
) )
self.assertEqual( assert assertion.value.message_dict == {'endorsed': ['This field is required for question threads.']}
assertion.exception.message_dict,
{"endorsed": ["This field is required for question threads."]}
)
def test_empty(self): def test_empty(self):
discussion_thread = self.make_minimal_cs_thread( discussion_thread = self.make_minimal_cs_thread(
{"thread_type": "discussion", "children": [], "resp_total": 0} {"thread_type": "discussion", "children": [], "resp_total": 0}
) )
self.assertEqual( assert self.get_comment_list(discussion_thread).data == make_paginated_api_response(
self.get_comment_list(discussion_thread).data, results=[], count=0, num_pages=1, next_link=None, previous_link=None)
make_paginated_api_response(results=[], count=0, num_pages=1, next_link=None, previous_link=None)
)
question_thread = self.make_minimal_cs_thread({ question_thread = self.make_minimal_cs_thread({
"thread_type": "question", "thread_type": "question",
@@ -1170,14 +1117,10 @@ class GetCommentListTest(ForumsEnableMixin, CommentsServiceMockMixin, SharedModu
"non_endorsed_responses": [], "non_endorsed_responses": [],
"non_endorsed_resp_total": 0 "non_endorsed_resp_total": 0
}) })
self.assertEqual( assert self.get_comment_list(question_thread, endorsed=False).data == make_paginated_api_response(
self.get_comment_list(question_thread, endorsed=False).data, results=[], count=0, num_pages=1, next_link=None, previous_link=None)
make_paginated_api_response(results=[], count=0, num_pages=1, next_link=None, previous_link=None) assert self.get_comment_list(question_thread, endorsed=True).data == make_paginated_api_response(
) results=[], count=0, num_pages=1, next_link=None, previous_link=None)
self.assertEqual(
self.get_comment_list(question_thread, endorsed=True).data,
make_paginated_api_response(results=[], count=0, num_pages=1, next_link=None, previous_link=None)
)
def test_basic_query_params(self): def test_basic_query_params(self):
self.get_comment_list( self.get_comment_list(
@@ -1284,7 +1227,7 @@ class GetCommentListTest(ForumsEnableMixin, CommentsServiceMockMixin, SharedModu
actual_comments = self.get_comment_list( actual_comments = self.get_comment_list(
self.make_minimal_cs_thread({"children": source_comments}) self.make_minimal_cs_thread({"children": source_comments})
).data["results"] ).data["results"]
self.assertEqual(actual_comments, expected_comments) assert actual_comments == expected_comments
def test_question_content(self): def test_question_content(self):
thread = self.make_minimal_cs_thread({ thread = self.make_minimal_cs_thread({
@@ -1297,10 +1240,10 @@ class GetCommentListTest(ForumsEnableMixin, CommentsServiceMockMixin, SharedModu
}) })
endorsed_actual = self.get_comment_list(thread, endorsed=True).data endorsed_actual = self.get_comment_list(thread, endorsed=True).data
self.assertEqual(endorsed_actual["results"][0]["id"], "endorsed_comment") assert endorsed_actual['results'][0]['id'] == 'endorsed_comment'
non_endorsed_actual = self.get_comment_list(thread, endorsed=False).data non_endorsed_actual = self.get_comment_list(thread, endorsed=False).data
self.assertEqual(non_endorsed_actual["results"][0]["id"], "non_endorsed_comment") assert non_endorsed_actual['results'][0]['id'] == 'non_endorsed_comment'
def test_endorsed_by_anonymity(self): def test_endorsed_by_anonymity(self):
""" """
@@ -1317,7 +1260,7 @@ class GetCommentListTest(ForumsEnableMixin, CommentsServiceMockMixin, SharedModu
] ]
}) })
actual_comments = self.get_comment_list(thread).data["results"] actual_comments = self.get_comment_list(thread).data["results"]
self.assertIsNone(actual_comments[0]["endorsed_by"]) assert actual_comments[0]['endorsed_by'] is None
@ddt.data( @ddt.data(
("discussion", None, "children", "resp_total"), ("discussion", None, "children", "resp_total"),
@@ -1345,23 +1288,23 @@ class GetCommentListTest(ForumsEnableMixin, CommentsServiceMockMixin, SharedModu
# Only page # Only page
actual = self.get_comment_list(thread, endorsed=endorsed_arg, page=1, page_size=5).data actual = self.get_comment_list(thread, endorsed=endorsed_arg, page=1, page_size=5).data
self.assertIsNone(actual["pagination"]["next"]) assert actual['pagination']['next'] is None
self.assertIsNone(actual["pagination"]["previous"]) assert actual['pagination']['previous'] is None
# First page of many # First page of many
actual = self.get_comment_list(thread, endorsed=endorsed_arg, page=1, page_size=2).data actual = self.get_comment_list(thread, endorsed=endorsed_arg, page=1, page_size=2).data
self.assertEqual(actual["pagination"]["next"], "http://testserver/test_path?page=2") assert actual['pagination']['next'] == 'http://testserver/test_path?page=2'
self.assertIsNone(actual["pagination"]["previous"]) assert actual['pagination']['previous'] is None
# Middle page of many # Middle page of many
actual = self.get_comment_list(thread, endorsed=endorsed_arg, page=2, page_size=2).data actual = self.get_comment_list(thread, endorsed=endorsed_arg, page=2, page_size=2).data
self.assertEqual(actual["pagination"]["next"], "http://testserver/test_path?page=3") assert actual['pagination']['next'] == 'http://testserver/test_path?page=3'
self.assertEqual(actual["pagination"]["previous"], "http://testserver/test_path?page=1") assert actual['pagination']['previous'] == 'http://testserver/test_path?page=1'
# Last page of many # Last page of many
actual = self.get_comment_list(thread, endorsed=endorsed_arg, page=3, page_size=2).data actual = self.get_comment_list(thread, endorsed=endorsed_arg, page=3, page_size=2).data
self.assertIsNone(actual["pagination"]["next"]) assert actual['pagination']['next'] is None
self.assertEqual(actual["pagination"]["previous"], "http://testserver/test_path?page=2") assert actual['pagination']['previous'] == 'http://testserver/test_path?page=2'
# Page past the end # Page past the end
thread = self.make_minimal_cs_thread({ thread = self.make_minimal_cs_thread({
@@ -1369,7 +1312,7 @@ class GetCommentListTest(ForumsEnableMixin, CommentsServiceMockMixin, SharedModu
response_field: [], response_field: [],
response_total_field: 5 response_total_field: 5
}) })
with self.assertRaises(PageNotFoundError): with pytest.raises(PageNotFoundError):
self.get_comment_list(thread, endorsed=endorsed_arg, page=2, page_size=5) self.get_comment_list(thread, endorsed=endorsed_arg, page=2, page_size=5)
def test_question_endorsed_pagination(self): def test_question_endorsed_pagination(self):
@@ -1388,17 +1331,12 @@ class GetCommentListTest(ForumsEnableMixin, CommentsServiceMockMixin, SharedModu
""" """
actual = self.get_comment_list(thread, endorsed=True, page=page, page_size=page_size).data actual = self.get_comment_list(thread, endorsed=True, page=page, page_size=page_size).data
result_ids = [result["id"] for result in actual["results"]] result_ids = [result["id"] for result in actual["results"]]
self.assertEqual( assert result_ids == ['comment_{}'.format(i) for i in range(expected_start, expected_stop)]
result_ids, assert actual['pagination']['next'] == (
["comment_{}".format(i) for i in range(expected_start, expected_stop)] 'http://testserver/test_path?page={}'.format(expected_next) if expected_next else None
) )
self.assertEqual( assert actual['pagination']['previous'] == (
actual["pagination"]["next"], 'http://testserver/test_path?page={}'.format(expected_prev) if expected_prev else None
"http://testserver/test_path?page={}".format(expected_next) if expected_next else None
)
self.assertEqual(
actual["pagination"]["previous"],
"http://testserver/test_path?page={}".format(expected_prev) if expected_prev else None
) )
# Only page # Only page
@@ -1442,7 +1380,7 @@ class GetCommentListTest(ForumsEnableMixin, CommentsServiceMockMixin, SharedModu
) )
# Page past the end # Page past the end
with self.assertRaises(PageNotFoundError): with pytest.raises(PageNotFoundError):
self.get_comment_list(thread, endorsed=True, page=2, page_size=10) self.get_comment_list(thread, endorsed=True, page=2, page_size=10)
@@ -1534,39 +1472,33 @@ class CreateThreadTest(
"comment_list_url": "http://testserver/api/discussion/v1/comments/?thread_id=test_id", "comment_list_url": "http://testserver/api/discussion/v1/comments/?thread_id=test_id",
"read": True, "read": True,
}) })
self.assertEqual(actual, expected) assert actual == expected
self.assertEqual( assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member 'course_id': [six.text_type(self.course.id)],
{ 'commentable_id': ['test_topic'],
"course_id": [six.text_type(self.course.id)], 'thread_type': ['discussion'],
"commentable_id": ["test_topic"], 'title': ['Test Title'],
"thread_type": ["discussion"], 'body': ['Test body'],
"title": ["Test Title"], 'user_id': [str(self.user.id)]
"body": ["Test body"], }
"user_id": [str(self.user.id)],
}
)
event_name, event_data = mock_emit.call_args[0] event_name, event_data = mock_emit.call_args[0]
self.assertEqual(event_name, "edx.forum.thread.created") assert event_name == 'edx.forum.thread.created'
self.assertEqual( assert event_data == {
event_data, 'commentable_id': 'test_topic',
{ 'group_id': None,
"commentable_id": "test_topic", 'thread_type': 'discussion',
"group_id": None, 'title': 'Test Title',
"thread_type": "discussion", 'title_truncated': False,
"title": "Test Title", 'anonymous': False,
"title_truncated": False, 'anonymous_to_peers': False,
"anonymous": False, 'options': {'followed': False},
"anonymous_to_peers": False, 'id': 'test_id',
"options": {"followed": False}, 'truncated': False,
"id": "test_id", 'body': 'Test body',
"truncated": False, 'url': '',
"body": "Test body", 'user_forums_roles': [FORUM_ROLE_STUDENT],
"url": "", 'user_course_roles': []
"user_forums_roles": [FORUM_ROLE_STUDENT], }
"user_course_roles": [],
}
)
def test_basic_in_blackout_period(self): def test_basic_in_blackout_period(self):
""" """
@@ -1652,26 +1584,23 @@ class CreateThreadTest(
with self.assert_signal_sent(api, 'thread_created', sender=None, user=self.user, exclude_args=('post',)): with self.assert_signal_sent(api, 'thread_created', sender=None, user=self.user, exclude_args=('post',)):
create_thread(self.request, data) create_thread(self.request, data)
event_name, event_data = mock_emit.call_args[0] event_name, event_data = mock_emit.call_args[0]
self.assertEqual(event_name, "edx.forum.thread.created") assert event_name == 'edx.forum.thread.created'
self.assertEqual( assert event_data == {
event_data, 'commentable_id': 'test_topic',
{ 'group_id': None,
"commentable_id": "test_topic", 'thread_type': 'discussion',
"group_id": None, 'title': self.LONG_TITLE[:1000],
"thread_type": "discussion", 'title_truncated': True,
"title": self.LONG_TITLE[:1000], 'anonymous': False,
"title_truncated": True, 'anonymous_to_peers': False,
"anonymous": False, 'options': {'followed': False},
"anonymous_to_peers": False, 'id': 'test_id',
"options": {"followed": False}, 'truncated': False,
"id": "test_id", 'body': 'Test body',
"truncated": False, 'url': '',
"body": "Test body", 'user_forums_roles': [FORUM_ROLE_STUDENT],
"url": "", 'user_course_roles': []
"user_forums_roles": [FORUM_ROLE_STUDENT], }
"user_course_roles": [],
}
)
@ddt.data( @ddt.data(
*itertools.product( *itertools.product(
@@ -1724,14 +1653,14 @@ class CreateThreadTest(
) )
try: try:
create_thread(self.request, data) create_thread(self.request, data)
self.assertFalse(expected_error) assert not expected_error
actual_post_data = httpretty.last_request().parsed_body # lint-amnesty, pylint: disable=no-member actual_post_data = httpretty.last_request().parsed_body # lint-amnesty, pylint: disable=no-member
if data_group_state == "group_is_set": if data_group_state == "group_is_set":
self.assertEqual(actual_post_data["group_id"], [str(data["group_id"])]) assert actual_post_data['group_id'] == [str(data['group_id'])]
elif data_group_state == "no_group_set" and course_is_cohorted and topic_is_cohorted: elif data_group_state == "no_group_set" and course_is_cohorted and topic_is_cohorted:
self.assertEqual(actual_post_data["group_id"], [str(cohort.id)]) assert actual_post_data['group_id'] == [str(cohort.id)]
else: else:
self.assertNotIn("group_id", actual_post_data) assert 'group_id' not in actual_post_data
except ValidationError as ex: except ValidationError as ex:
if not expected_error: if not expected_error:
self.fail(u"Unexpected validation error: {}".format(ex)) self.fail(u"Unexpected validation error: {}".format(ex))
@@ -1742,17 +1671,11 @@ class CreateThreadTest(
data = self.minimal_data.copy() data = self.minimal_data.copy()
data["following"] = "True" data["following"] = "True"
result = create_thread(self.request, data) result = create_thread(self.request, data)
self.assertEqual(result["following"], True) assert result['following'] is True
cs_request = httpretty.last_request() cs_request = httpretty.last_request()
self.assertEqual( assert urlparse(cs_request.path).path == '/api/v1/users/{}/subscriptions'.format(self.user.id) # lint-amnesty, pylint: disable=no-member
urlparse(cs_request.path).path, # lint-amnesty, pylint: disable=no-member assert cs_request.method == 'POST'
"/api/v1/users/{}/subscriptions".format(self.user.id) assert cs_request.parsed_body == {'source_type': ['thread'], 'source_id': ['test_id']} # lint-amnesty, pylint: disable=no-member
)
self.assertEqual(cs_request.method, "POST")
self.assertEqual(
cs_request.parsed_body, # lint-amnesty, pylint: disable=no-member
{"source_type": ["thread"], "source_id": ["test_id"]}
)
def test_voted(self): def test_voted(self):
self.register_post_thread_response({"id": "test_id", "username": self.user.username}) self.register_post_thread_response({"id": "test_id", "username": self.user.username})
@@ -1761,14 +1684,11 @@ class CreateThreadTest(
data["voted"] = "True" data["voted"] = "True"
with self.assert_signal_sent(api, 'thread_voted', sender=None, user=self.user, exclude_args=('post',)): with self.assert_signal_sent(api, 'thread_voted', sender=None, user=self.user, exclude_args=('post',)):
result = create_thread(self.request, data) result = create_thread(self.request, data)
self.assertEqual(result["voted"], True) assert result['voted'] is True
cs_request = httpretty.last_request() cs_request = httpretty.last_request()
self.assertEqual(urlparse(cs_request.path).path, "/api/v1/threads/test_id/votes") # lint-amnesty, pylint: disable=no-member assert urlparse(cs_request.path).path == '/api/v1/threads/test_id/votes' # lint-amnesty, pylint: disable=no-member
self.assertEqual(cs_request.method, "PUT") assert cs_request.method == 'PUT'
self.assertEqual( assert cs_request.parsed_body == {'user_id': [str(self.user.id)], 'value': ['up']} # lint-amnesty, pylint: disable=no-member
cs_request.parsed_body, # lint-amnesty, pylint: disable=no-member
{"user_id": [str(self.user.id)], "value": ["up"]}
)
def test_abuse_flagged(self): def test_abuse_flagged(self):
self.register_post_thread_response({"id": "test_id", "username": self.user.username}) self.register_post_thread_response({"id": "test_id", "username": self.user.username})
@@ -1776,41 +1696,41 @@ class CreateThreadTest(
data = self.minimal_data.copy() data = self.minimal_data.copy()
data["abuse_flagged"] = "True" data["abuse_flagged"] = "True"
result = create_thread(self.request, data) result = create_thread(self.request, data)
self.assertEqual(result["abuse_flagged"], True) assert result['abuse_flagged'] is True
cs_request = httpretty.last_request() cs_request = httpretty.last_request()
self.assertEqual(urlparse(cs_request.path).path, "/api/v1/threads/test_id/abuse_flag") # lint-amnesty, pylint: disable=no-member assert urlparse(cs_request.path).path == '/api/v1/threads/test_id/abuse_flag' # lint-amnesty, pylint: disable=no-member
self.assertEqual(cs_request.method, "PUT") assert cs_request.method == 'PUT'
self.assertEqual(cs_request.parsed_body, {"user_id": [str(self.user.id)]}) # lint-amnesty, pylint: disable=no-member assert cs_request.parsed_body == {'user_id': [str(self.user.id)]} # lint-amnesty, pylint: disable=no-member
def test_course_id_missing(self): def test_course_id_missing(self):
with self.assertRaises(ValidationError) as assertion: with pytest.raises(ValidationError) as assertion:
create_thread(self.request, {}) create_thread(self.request, {})
self.assertEqual(assertion.exception.message_dict, {"course_id": ["This field is required."]}) assert assertion.value.message_dict == {'course_id': ['This field is required.']}
def test_course_id_invalid(self): def test_course_id_invalid(self):
with self.assertRaises(ValidationError) as assertion: with pytest.raises(ValidationError) as assertion:
create_thread(self.request, {"course_id": "invalid!"}) create_thread(self.request, {"course_id": "invalid!"})
self.assertEqual(assertion.exception.message_dict, {"course_id": ["Invalid value."]}) assert assertion.value.message_dict == {'course_id': ['Invalid value.']}
def test_nonexistent_course(self): def test_nonexistent_course(self):
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
create_thread(self.request, {"course_id": "non/existent/course"}) create_thread(self.request, {"course_id": "non/existent/course"})
def test_not_enrolled(self): def test_not_enrolled(self):
self.request.user = UserFactory.create() self.request.user = UserFactory.create()
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
create_thread(self.request, self.minimal_data) create_thread(self.request, self.minimal_data)
def test_discussions_disabled(self): def test_discussions_disabled(self):
disabled_course = _discussion_disabled_course_for(self.user) disabled_course = _discussion_disabled_course_for(self.user)
self.minimal_data["course_id"] = six.text_type(disabled_course.id) self.minimal_data["course_id"] = six.text_type(disabled_course.id)
with self.assertRaises(DiscussionDisabledError): with pytest.raises(DiscussionDisabledError):
create_thread(self.request, self.minimal_data) create_thread(self.request, self.minimal_data)
def test_invalid_field(self): def test_invalid_field(self):
data = self.minimal_data.copy() data = self.minimal_data.copy()
data["type"] = "invalid_type" data["type"] = "invalid_type"
with self.assertRaises(ValidationError): with pytest.raises(ValidationError):
create_thread(self.request, data) create_thread(self.request, data)
@@ -1893,23 +1813,17 @@ class CreateCommentTest(
"editable_fields": ["abuse_flagged", "raw_body", "voted"], "editable_fields": ["abuse_flagged", "raw_body", "voted"],
"child_count": 0, "child_count": 0,
} }
self.assertEqual(actual, expected) assert actual == expected
expected_url = ( expected_url = (
"/api/v1/comments/{}".format(parent_id) if parent_id else "/api/v1/comments/{}".format(parent_id) if parent_id else
"/api/v1/threads/test_thread/comments" "/api/v1/threads/test_thread/comments"
) )
self.assertEqual( assert urlparse(httpretty.last_request().path).path == expected_url # lint-amnesty, pylint: disable=no-member
urlparse(httpretty.last_request().path).path, # lint-amnesty, pylint: disable=no-member assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
expected_url 'course_id': [six.text_type(self.course.id)],
) 'body': ['Test body'],
self.assertEqual( 'user_id': [str(self.user.id)]
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member }
{
"course_id": [six.text_type(self.course.id)],
"body": ["Test body"],
"user_id": [str(self.user.id)]
}
)
expected_event_name = ( expected_event_name = (
"edx.forum.comment.created" if parent_id else "edx.forum.comment.created" if parent_id else
"edx.forum.response.created" "edx.forum.response.created"
@@ -1928,8 +1842,8 @@ class CreateCommentTest(
if parent_id: if parent_id:
expected_event_data["response"] = {"id": parent_id} expected_event_data["response"] = {"id": parent_id}
actual_event_name, actual_event_data = mock_emit.call_args[0] actual_event_name, actual_event_data = mock_emit.call_args[0]
self.assertEqual(actual_event_name, expected_event_name) assert actual_event_name == expected_event_name
self.assertEqual(actual_event_data, expected_event_data) assert actual_event_data == expected_event_data
@ddt.data(None, "test_parent") @ddt.data(None, "test_parent")
@mock.patch("eventtracking.tracker.emit") @mock.patch("eventtracking.tracker.emit")
@@ -2060,10 +1974,10 @@ class CreateCommentTest(
) )
try: try:
create_comment(self.request, data) create_comment(self.request, data)
self.assertEqual(httpretty.last_request().parsed_body["endorsed"], ["True"]) # lint-amnesty, pylint: disable=no-member assert httpretty.last_request().parsed_body['endorsed'] == ['True'] # lint-amnesty, pylint: disable=no-member
self.assertFalse(expected_error) assert not expected_error
except ValidationError: except ValidationError:
self.assertTrue(expected_error) assert expected_error
def test_voted(self): def test_voted(self):
self.register_post_comment_response({"id": "test_comment", "username": self.user.username}, "test_thread") self.register_post_comment_response({"id": "test_comment", "username": self.user.username}, "test_thread")
@@ -2072,14 +1986,11 @@ class CreateCommentTest(
data["voted"] = "True" data["voted"] = "True"
with self.assert_signal_sent(api, 'comment_voted', sender=None, user=self.user, exclude_args=('post',)): with self.assert_signal_sent(api, 'comment_voted', sender=None, user=self.user, exclude_args=('post',)):
result = create_comment(self.request, data) result = create_comment(self.request, data)
self.assertEqual(result["voted"], True) assert result['voted'] is True
cs_request = httpretty.last_request() cs_request = httpretty.last_request()
self.assertEqual(urlparse(cs_request.path).path, "/api/v1/comments/test_comment/votes") # lint-amnesty, pylint: disable=no-member assert urlparse(cs_request.path).path == '/api/v1/comments/test_comment/votes' # lint-amnesty, pylint: disable=no-member
self.assertEqual(cs_request.method, "PUT") assert cs_request.method == 'PUT'
self.assertEqual( assert cs_request.parsed_body == {'user_id': [str(self.user.id)], 'value': ['up']} # lint-amnesty, pylint: disable=no-member
cs_request.parsed_body, # lint-amnesty, pylint: disable=no-member
{"user_id": [str(self.user.id)], "value": ["up"]}
)
def test_abuse_flagged(self): def test_abuse_flagged(self):
self.register_post_comment_response({"id": "test_comment", "username": self.user.username}, "test_thread") self.register_post_comment_response({"id": "test_comment", "username": self.user.username}, "test_thread")
@@ -2087,32 +1998,32 @@ class CreateCommentTest(
data = self.minimal_data.copy() data = self.minimal_data.copy()
data["abuse_flagged"] = "True" data["abuse_flagged"] = "True"
result = create_comment(self.request, data) result = create_comment(self.request, data)
self.assertEqual(result["abuse_flagged"], True) assert result['abuse_flagged'] is True
cs_request = httpretty.last_request() cs_request = httpretty.last_request()
self.assertEqual(urlparse(cs_request.path).path, "/api/v1/comments/test_comment/abuse_flag") # lint-amnesty, pylint: disable=no-member assert urlparse(cs_request.path).path == '/api/v1/comments/test_comment/abuse_flag' # lint-amnesty, pylint: disable=no-member
self.assertEqual(cs_request.method, "PUT") assert cs_request.method == 'PUT'
self.assertEqual(cs_request.parsed_body, {"user_id": [str(self.user.id)]}) # lint-amnesty, pylint: disable=no-member assert cs_request.parsed_body == {'user_id': [str(self.user.id)]} # lint-amnesty, pylint: disable=no-member
def test_thread_id_missing(self): def test_thread_id_missing(self):
with self.assertRaises(ValidationError) as assertion: with pytest.raises(ValidationError) as assertion:
create_comment(self.request, {}) create_comment(self.request, {})
self.assertEqual(assertion.exception.message_dict, {"thread_id": ["This field is required."]}) assert assertion.value.message_dict == {'thread_id': ['This field is required.']}
def test_thread_id_not_found(self): def test_thread_id_not_found(self):
self.register_get_thread_error_response("test_thread", 404) self.register_get_thread_error_response("test_thread", 404)
with self.assertRaises(ThreadNotFoundError): with pytest.raises(ThreadNotFoundError):
create_comment(self.request, self.minimal_data) create_comment(self.request, self.minimal_data)
def test_nonexistent_course(self): def test_nonexistent_course(self):
self.register_get_thread_response( self.register_get_thread_response(
make_minimal_cs_thread({"id": "test_thread", "course_id": "non/existent/course"}) make_minimal_cs_thread({"id": "test_thread", "course_id": "non/existent/course"})
) )
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
create_comment(self.request, self.minimal_data) create_comment(self.request, self.minimal_data)
def test_not_enrolled(self): def test_not_enrolled(self):
self.request.user = UserFactory.create() self.request.user = UserFactory.create()
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
create_comment(self.request, self.minimal_data) create_comment(self.request, self.minimal_data)
def test_discussions_disabled(self): def test_discussions_disabled(self):
@@ -2124,7 +2035,7 @@ class CreateCommentTest(
"commentable_id": "test_topic", "commentable_id": "test_topic",
}) })
) )
with self.assertRaises(DiscussionDisabledError): with pytest.raises(DiscussionDisabledError):
create_comment(self.request, self.minimal_data) create_comment(self.request, self.minimal_data)
@ddt.data( @ddt.data(
@@ -2161,14 +2072,14 @@ class CreateCommentTest(
) )
try: try:
create_comment(self.request, data) create_comment(self.request, data)
self.assertFalse(expected_error) assert not expected_error
except ThreadNotFoundError: except ThreadNotFoundError:
self.assertTrue(expected_error) assert expected_error
def test_invalid_field(self): def test_invalid_field(self):
data = self.minimal_data.copy() data = self.minimal_data.copy()
del data["raw_body"] del data["raw_body"]
with self.assertRaises(ValidationError): with pytest.raises(ValidationError):
create_comment(self.request, data) create_comment(self.request, data)
@@ -2230,57 +2141,54 @@ class UpdateThreadTest(
self.register_thread() self.register_thread()
update_thread(self.request, "test_thread", {}) update_thread(self.request, "test_thread", {})
for request in httpretty.httpretty.latest_requests: for request in httpretty.httpretty.latest_requests:
self.assertEqual(request.method, "GET") assert request.method == 'GET'
def test_basic(self): def test_basic(self):
self.register_thread() self.register_thread()
with self.assert_signal_sent(api, 'thread_edited', sender=None, user=self.user, exclude_args=('post',)): with self.assert_signal_sent(api, 'thread_edited', sender=None, user=self.user, exclude_args=('post',)):
actual = update_thread(self.request, "test_thread", {"raw_body": "Edited body"}) actual = update_thread(self.request, "test_thread", {"raw_body": "Edited body"})
self.assertEqual(actual, self.expected_thread_data({ assert actual == self.expected_thread_data({
"raw_body": "Edited body", 'raw_body': 'Edited body',
"rendered_body": "<p>Edited body</p>", 'rendered_body': '<p>Edited body</p>',
"topic_id": "original_topic", 'topic_id': 'original_topic',
"read": True, 'read': True,
"title": "Original Title", 'title': 'Original Title'
})) })
self.assertEqual( assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member 'course_id': [six.text_type(self.course.id)],
{ 'commentable_id': ['original_topic'],
"course_id": [six.text_type(self.course.id)], 'thread_type': ['discussion'],
"commentable_id": ["original_topic"], 'title': ['Original Title'],
"thread_type": ["discussion"], 'body': ['Edited body'],
"title": ["Original Title"], 'user_id': [str(self.user.id)],
"body": ["Edited body"], 'anonymous': ['False'],
"user_id": [str(self.user.id)], 'anonymous_to_peers': ['False'],
"anonymous": ["False"], 'closed': ['False'],
"anonymous_to_peers": ["False"], 'pinned': ['False'],
"closed": ["False"], 'read': ['False']
"pinned": ["False"], }
"read": ["False"],
}
)
def test_nonexistent_thread(self): def test_nonexistent_thread(self):
self.register_get_thread_error_response("test_thread", 404) self.register_get_thread_error_response("test_thread", 404)
with self.assertRaises(ThreadNotFoundError): with pytest.raises(ThreadNotFoundError):
update_thread(self.request, "test_thread", {}) update_thread(self.request, "test_thread", {})
def test_nonexistent_course(self): def test_nonexistent_course(self):
self.register_thread({"course_id": "non/existent/course"}) self.register_thread({"course_id": "non/existent/course"})
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
update_thread(self.request, "test_thread", {}) update_thread(self.request, "test_thread", {})
def test_not_enrolled(self): def test_not_enrolled(self):
self.register_thread() self.register_thread()
self.request.user = UserFactory.create() self.request.user = UserFactory.create()
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
update_thread(self.request, "test_thread", {}) update_thread(self.request, "test_thread", {})
def test_discussions_disabled(self): def test_discussions_disabled(self):
disabled_course = _discussion_disabled_course_for(self.user) disabled_course = _discussion_disabled_course_for(self.user)
self.register_thread(overrides={"course_id": six.text_type(disabled_course.id)}) self.register_thread(overrides={"course_id": six.text_type(disabled_course.id)})
with self.assertRaises(DiscussionDisabledError): with pytest.raises(DiscussionDisabledError):
update_thread(self.request, "test_thread", {}) update_thread(self.request, "test_thread", {})
@ddt.data( @ddt.data(
@@ -2313,9 +2221,9 @@ class UpdateThreadTest(
) )
try: try:
update_thread(self.request, "test_thread", {}) update_thread(self.request, "test_thread", {})
self.assertFalse(expected_error) assert not expected_error
except ThreadNotFoundError: except ThreadNotFoundError:
self.assertTrue(expected_error) assert expected_error
@ddt.data( @ddt.data(
FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_ADMINISTRATOR,
@@ -2331,13 +2239,10 @@ class UpdateThreadTest(
expected_error = role_name == FORUM_ROLE_STUDENT expected_error = role_name == FORUM_ROLE_STUDENT
try: try:
update_thread(self.request, "test_thread", data) update_thread(self.request, "test_thread", data)
self.assertFalse(expected_error) assert not expected_error
except ValidationError as err: except ValidationError as err:
self.assertTrue(expected_error) assert expected_error
self.assertEqual( assert err.message_dict == {field: ['This field is not editable.'] for field in data.keys()}
err.message_dict,
{field: ["This field is not editable."] for field in data.keys()}
)
@ddt.data(*itertools.product([True, False], [True, False])) @ddt.data(*itertools.product([True, False], [True, False]))
@ddt.unpack @ddt.unpack
@@ -2357,26 +2262,20 @@ class UpdateThreadTest(
self.register_thread() self.register_thread()
data = {"following": new_following} data = {"following": new_following}
result = update_thread(self.request, "test_thread", data) result = update_thread(self.request, "test_thread", data)
self.assertEqual(result["following"], new_following) assert result['following'] == new_following
last_request_path = urlparse(httpretty.last_request().path).path # lint-amnesty, pylint: disable=no-member last_request_path = urlparse(httpretty.last_request().path).path # lint-amnesty, pylint: disable=no-member
subscription_url = "/api/v1/users/{}/subscriptions".format(self.user.id) subscription_url = "/api/v1/users/{}/subscriptions".format(self.user.id)
if old_following == new_following: if old_following == new_following:
self.assertNotEqual(last_request_path, subscription_url) assert last_request_path != subscription_url
else: else:
self.assertEqual(last_request_path, subscription_url) assert last_request_path == subscription_url
self.assertEqual( assert httpretty.last_request().method == ('POST' if new_following else 'DELETE')
httpretty.last_request().method,
"POST" if new_following else "DELETE"
)
request_data = ( request_data = (
httpretty.last_request().parsed_body if new_following else # lint-amnesty, pylint: disable=no-member httpretty.last_request().parsed_body if new_following else # lint-amnesty, pylint: disable=no-member
parse_qs(urlparse(httpretty.last_request().path).query) # lint-amnesty, pylint: disable=no-member parse_qs(urlparse(httpretty.last_request().path).query) # lint-amnesty, pylint: disable=no-member
) )
request_data.pop("request_id", None) request_data.pop("request_id", None)
self.assertEqual( assert request_data == {'source_type': ['thread'], 'source_id': ['test_thread']}
request_data,
{"source_type": ["thread"], "source_id": ["test_thread"]}
)
@ddt.data(*itertools.product([True, False], [True, False])) @ddt.data(*itertools.product([True, False], [True, False]))
@ddt.unpack @ddt.unpack
@@ -2397,17 +2296,14 @@ class UpdateThreadTest(
self.register_thread() self.register_thread()
data = {"voted": new_vote_status} data = {"voted": new_vote_status}
result = update_thread(self.request, "test_thread", data) result = update_thread(self.request, "test_thread", data)
self.assertEqual(result["voted"], new_vote_status) assert result['voted'] == new_vote_status
last_request_path = urlparse(httpretty.last_request().path).path # lint-amnesty, pylint: disable=no-member last_request_path = urlparse(httpretty.last_request().path).path # lint-amnesty, pylint: disable=no-member
votes_url = "/api/v1/threads/test_thread/votes" votes_url = "/api/v1/threads/test_thread/votes"
if current_vote_status == new_vote_status: if current_vote_status == new_vote_status:
self.assertNotEqual(last_request_path, votes_url) assert last_request_path != votes_url
else: else:
self.assertEqual(last_request_path, votes_url) assert last_request_path == votes_url
self.assertEqual( assert httpretty.last_request().method == ('PUT' if new_vote_status else 'DELETE')
httpretty.last_request().method,
"PUT" if new_vote_status else "DELETE"
)
actual_request_data = ( actual_request_data = (
httpretty.last_request().parsed_body if new_vote_status else # lint-amnesty, pylint: disable=no-member httpretty.last_request().parsed_body if new_vote_status else # lint-amnesty, pylint: disable=no-member
parse_qs(urlparse(httpretty.last_request().path).query) # lint-amnesty, pylint: disable=no-member parse_qs(urlparse(httpretty.last_request().path).query) # lint-amnesty, pylint: disable=no-member
@@ -2416,23 +2312,20 @@ class UpdateThreadTest(
expected_request_data = {"user_id": [str(self.user.id)]} expected_request_data = {"user_id": [str(self.user.id)]}
if new_vote_status: if new_vote_status:
expected_request_data["value"] = ["up"] expected_request_data["value"] = ["up"]
self.assertEqual(actual_request_data, expected_request_data) assert actual_request_data == expected_request_data
event_name, event_data = mock_emit.call_args[0] event_name, event_data = mock_emit.call_args[0]
self.assertEqual(event_name, "edx.forum.thread.voted") assert event_name == 'edx.forum.thread.voted'
self.assertEqual( assert event_data == {
event_data, 'undo_vote': (not new_vote_status),
{ 'url': '',
'undo_vote': not new_vote_status, 'target_username': self.user.username,
'url': '', 'vote_value': 'up',
'target_username': self.user.username, 'user_forums_roles': [FORUM_ROLE_STUDENT],
'vote_value': 'up', 'user_course_roles': [],
'user_forums_roles': [FORUM_ROLE_STUDENT], 'commentable_id': 'original_topic',
'user_course_roles': [], 'id': 'test_thread'
'commentable_id': 'original_topic', }
'id': 'test_thread'
}
)
@ddt.data(*itertools.product([True, False], [True, False], [True, False])) @ddt.data(*itertools.product([True, False], [True, False], [True, False]))
@ddt.unpack @ddt.unpack
@@ -2452,12 +2345,12 @@ class UpdateThreadTest(
data = {"voted": first_vote} data = {"voted": first_vote}
result = update_thread(self.request, "test_thread", data) result = update_thread(self.request, "test_thread", data)
self.register_thread(overrides={"voted": first_vote}) self.register_thread(overrides={"voted": first_vote})
self.assertEqual(result["vote_count"], 1 if first_vote else 0) assert result['vote_count'] == (1 if first_vote else 0)
#second vote #second vote
data = {"voted": second_vote} data = {"voted": second_vote}
result = update_thread(self.request, "test_thread", data) result = update_thread(self.request, "test_thread", data)
self.assertEqual(result["vote_count"], 1 if second_vote else 0) assert result['vote_count'] == (1 if second_vote else 0)
@ddt.data(*itertools.product([True, False], [True, False], [True, False], [True, False])) @ddt.data(*itertools.product([True, False], [True, False], [True, False], [True, False]))
@ddt.unpack @ddt.unpack
@@ -2496,14 +2389,14 @@ class UpdateThreadTest(
data = {"voted": user_vote} data = {"voted": user_vote}
result = update_thread(request, "test_thread", data) result = update_thread(request, "test_thread", data)
if current_vote == user_vote: if current_vote == user_vote:
self.assertEqual(result["vote_count"], vote_count) assert result['vote_count'] == vote_count
elif user_vote: elif user_vote:
vote_count += 1 vote_count += 1
self.assertEqual(result["vote_count"], vote_count) assert result['vote_count'] == vote_count
self.register_get_user_response(self.user, upvoted_ids=["test_thread"]) self.register_get_user_response(self.user, upvoted_ids=["test_thread"])
else: else:
vote_count -= 1 vote_count -= 1
self.assertEqual(result["vote_count"], vote_count) assert result['vote_count'] == vote_count
self.register_get_user_response(self.user, upvoted_ids=[]) self.register_get_user_response(self.user, upvoted_ids=[])
@ddt.data(*itertools.product([True, False], [True, False])) @ddt.data(*itertools.product([True, False], [True, False]))
@@ -2523,32 +2416,23 @@ class UpdateThreadTest(
self.register_thread({"abuse_flaggers": [str(self.user.id)] if old_flagged else []}) self.register_thread({"abuse_flaggers": [str(self.user.id)] if old_flagged else []})
data = {"abuse_flagged": new_flagged} data = {"abuse_flagged": new_flagged}
result = update_thread(self.request, "test_thread", data) result = update_thread(self.request, "test_thread", data)
self.assertEqual(result["abuse_flagged"], new_flagged) assert result['abuse_flagged'] == new_flagged
last_request_path = urlparse(httpretty.last_request().path).path # lint-amnesty, pylint: disable=no-member last_request_path = urlparse(httpretty.last_request().path).path # lint-amnesty, pylint: disable=no-member
flag_url = "/api/v1/threads/test_thread/abuse_flag" flag_url = "/api/v1/threads/test_thread/abuse_flag"
unflag_url = "/api/v1/threads/test_thread/abuse_unflag" unflag_url = "/api/v1/threads/test_thread/abuse_unflag"
if old_flagged == new_flagged: if old_flagged == new_flagged:
self.assertNotEqual(last_request_path, flag_url) assert last_request_path != flag_url
self.assertNotEqual(last_request_path, unflag_url) assert last_request_path != unflag_url
else: else:
self.assertEqual( assert last_request_path == (flag_url if new_flagged else unflag_url)
last_request_path, assert httpretty.last_request().method == 'PUT'
flag_url if new_flagged else unflag_url assert httpretty.last_request().parsed_body == {'user_id': [str(self.user.id)]} # lint-amnesty, pylint: disable=no-member
)
self.assertEqual(httpretty.last_request().method, "PUT")
self.assertEqual(
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member
{"user_id": [str(self.user.id)]}
)
def test_invalid_field(self): def test_invalid_field(self):
self.register_thread() self.register_thread()
with self.assertRaises(ValidationError) as assertion: with pytest.raises(ValidationError) as assertion:
update_thread(self.request, "test_thread", {"raw_body": ""}) update_thread(self.request, "test_thread", {"raw_body": ""})
self.assertEqual( assert assertion.value.message_dict == {'raw_body': ['This field may not be blank.']}
assertion.exception.message_dict,
{"raw_body": ["This field may not be blank."]}
)
@ddt.ddt @ddt.ddt
@@ -2618,7 +2502,7 @@ class UpdateCommentTest(
self.register_comment() self.register_comment()
update_comment(self.request, "test_comment", {}) update_comment(self.request, "test_comment", {})
for request in httpretty.httpretty.latest_requests: for request in httpretty.httpretty.latest_requests:
self.assertEqual(request.method, "GET") assert request.method == 'GET'
@ddt.data(None, "test_parent") @ddt.data(None, "test_parent")
def test_basic(self, parent_id): def test_basic(self, parent_id):
@@ -2646,38 +2530,35 @@ class UpdateCommentTest(
"editable_fields": ["abuse_flagged", "raw_body", "voted"], "editable_fields": ["abuse_flagged", "raw_body", "voted"],
"child_count": 0, "child_count": 0,
} }
self.assertEqual(actual, expected) assert actual == expected
self.assertEqual( assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member 'body': ['Edited body'],
{ 'course_id': [six.text_type(self.course.id)],
"body": ["Edited body"], 'user_id': [str(self.user.id)],
"course_id": [six.text_type(self.course.id)], 'anonymous': ['False'],
"user_id": [str(self.user.id)], 'anonymous_to_peers': ['False'],
"anonymous": ["False"], 'endorsed': ['False']
"anonymous_to_peers": ["False"], }
"endorsed": ["False"],
}
)
def test_nonexistent_comment(self): def test_nonexistent_comment(self):
self.register_get_comment_error_response("test_comment", 404) self.register_get_comment_error_response("test_comment", 404)
with self.assertRaises(CommentNotFoundError): with pytest.raises(CommentNotFoundError):
update_comment(self.request, "test_comment", {}) update_comment(self.request, "test_comment", {})
def test_nonexistent_course(self): def test_nonexistent_course(self):
self.register_comment(thread_overrides={"course_id": "non/existent/course"}) self.register_comment(thread_overrides={"course_id": "non/existent/course"})
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
update_comment(self.request, "test_comment", {}) update_comment(self.request, "test_comment", {})
def test_unenrolled(self): def test_unenrolled(self):
self.register_comment() self.register_comment()
self.request.user = UserFactory.create() self.request.user = UserFactory.create()
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
update_comment(self.request, "test_comment", {}) update_comment(self.request, "test_comment", {})
def test_discussions_disabled(self): def test_discussions_disabled(self):
self.register_comment(course=_discussion_disabled_course_for(self.user)) self.register_comment(course=_discussion_disabled_course_for(self.user))
with self.assertRaises(DiscussionDisabledError): with pytest.raises(DiscussionDisabledError):
update_comment(self.request, "test_comment", {}) update_comment(self.request, "test_comment", {})
@ddt.data( @ddt.data(
@@ -2715,9 +2596,9 @@ class UpdateCommentTest(
) )
try: try:
update_comment(self.request, "test_comment", {}) update_comment(self.request, "test_comment", {})
self.assertFalse(expected_error) assert not expected_error
except ThreadNotFoundError: except ThreadNotFoundError:
self.assertTrue(expected_error) assert expected_error
@ddt.data(*itertools.product( @ddt.data(*itertools.product(
[ [
@@ -2741,13 +2622,10 @@ class UpdateCommentTest(
expected_error = role_name == FORUM_ROLE_STUDENT and not is_comment_author expected_error = role_name == FORUM_ROLE_STUDENT and not is_comment_author
try: try:
update_comment(self.request, "test_comment", {"raw_body": "edited"}) update_comment(self.request, "test_comment", {"raw_body": "edited"})
self.assertFalse(expected_error) assert not expected_error
except ValidationError as err: except ValidationError as err:
self.assertTrue(expected_error) assert expected_error
self.assertEqual( assert err.message_dict == {'raw_body': ['This field is not editable.']}
err.message_dict,
{"raw_body": ["This field is not editable."]}
)
@ddt.data(*itertools.product( @ddt.data(*itertools.product(
[ [
@@ -2776,13 +2654,10 @@ class UpdateCommentTest(
) )
try: try:
update_comment(self.request, "test_comment", {"endorsed": True}) update_comment(self.request, "test_comment", {"endorsed": True})
self.assertFalse(expected_error) assert not expected_error
except ValidationError as err: except ValidationError as err:
self.assertTrue(expected_error) assert expected_error
self.assertEqual( assert err.message_dict == {'endorsed': ['This field is not editable.']}
err.message_dict,
{"endorsed": ["This field is not editable."]}
)
@ddt.data(*itertools.product([True, False], [True, False])) @ddt.data(*itertools.product([True, False], [True, False]))
@ddt.unpack @ddt.unpack
@@ -2805,18 +2680,15 @@ class UpdateCommentTest(
self.register_comment(overrides={"votes": {"up_count": vote_count}}) self.register_comment(overrides={"votes": {"up_count": vote_count}})
data = {"voted": new_vote_status} data = {"voted": new_vote_status}
result = update_comment(self.request, "test_comment", data) result = update_comment(self.request, "test_comment", data)
self.assertEqual(result["vote_count"], 1 if new_vote_status else 0) assert result['vote_count'] == (1 if new_vote_status else 0)
self.assertEqual(result["voted"], new_vote_status) assert result['voted'] == new_vote_status
last_request_path = urlparse(httpretty.last_request().path).path # lint-amnesty, pylint: disable=no-member last_request_path = urlparse(httpretty.last_request().path).path # lint-amnesty, pylint: disable=no-member
votes_url = "/api/v1/comments/test_comment/votes" votes_url = "/api/v1/comments/test_comment/votes"
if current_vote_status == new_vote_status: if current_vote_status == new_vote_status:
self.assertNotEqual(last_request_path, votes_url) assert last_request_path != votes_url
else: else:
self.assertEqual(last_request_path, votes_url) assert last_request_path == votes_url
self.assertEqual( assert httpretty.last_request().method == ('PUT' if new_vote_status else 'DELETE')
httpretty.last_request().method,
"PUT" if new_vote_status else "DELETE"
)
actual_request_data = ( actual_request_data = (
httpretty.last_request().parsed_body if new_vote_status else # lint-amnesty, pylint: disable=no-member httpretty.last_request().parsed_body if new_vote_status else # lint-amnesty, pylint: disable=no-member
parse_qs(urlparse(httpretty.last_request().path).query) # lint-amnesty, pylint: disable=no-member parse_qs(urlparse(httpretty.last_request().path).query) # lint-amnesty, pylint: disable=no-member
@@ -2825,24 +2697,21 @@ class UpdateCommentTest(
expected_request_data = {"user_id": [str(self.user.id)]} expected_request_data = {"user_id": [str(self.user.id)]}
if new_vote_status: if new_vote_status:
expected_request_data["value"] = ["up"] expected_request_data["value"] = ["up"]
self.assertEqual(actual_request_data, expected_request_data) assert actual_request_data == expected_request_data
event_name, event_data = mock_emit.call_args[0] event_name, event_data = mock_emit.call_args[0]
self.assertEqual(event_name, "edx.forum.response.voted") assert event_name == 'edx.forum.response.voted'
self.assertEqual( assert event_data == {
event_data, 'undo_vote': (not new_vote_status),
{ 'url': '',
'undo_vote': not new_vote_status, 'target_username': self.user.username,
'url': '', 'vote_value': 'up',
'target_username': self.user.username, 'user_forums_roles': [FORUM_ROLE_STUDENT],
'vote_value': 'up', 'user_course_roles': [],
'user_forums_roles': [FORUM_ROLE_STUDENT], 'commentable_id': 'dummy',
'user_course_roles': [], 'id': 'test_comment'
'commentable_id': 'dummy', }
'id': 'test_comment'
}
)
@ddt.data(*itertools.product([True, False], [True, False], [True, False])) @ddt.data(*itertools.product([True, False], [True, False], [True, False]))
@ddt.unpack @ddt.unpack
@@ -2862,12 +2731,12 @@ class UpdateCommentTest(
data = {"voted": first_vote} data = {"voted": first_vote}
result = update_comment(self.request, "test_comment", data) result = update_comment(self.request, "test_comment", data)
self.register_comment(overrides={"voted": first_vote}) self.register_comment(overrides={"voted": first_vote})
self.assertEqual(result["vote_count"], 1 if first_vote else 0) assert result['vote_count'] == (1 if first_vote else 0)
#second vote #second vote
data = {"voted": second_vote} data = {"voted": second_vote}
result = update_comment(self.request, "test_comment", data) result = update_comment(self.request, "test_comment", data)
self.assertEqual(result["vote_count"], 1 if second_vote else 0) assert result['vote_count'] == (1 if second_vote else 0)
@ddt.data(*itertools.product([True, False], [True, False], [True, False], [True, False])) @ddt.data(*itertools.product([True, False], [True, False], [True, False], [True, False]))
@ddt.unpack @ddt.unpack
@@ -2905,14 +2774,14 @@ class UpdateCommentTest(
data = {"voted": user_vote} data = {"voted": user_vote}
result = update_comment(request, "test_comment", data) result = update_comment(request, "test_comment", data)
if current_vote == user_vote: if current_vote == user_vote:
self.assertEqual(result["vote_count"], vote_count) assert result['vote_count'] == vote_count
elif user_vote: elif user_vote:
vote_count += 1 vote_count += 1
self.assertEqual(result["vote_count"], vote_count) assert result['vote_count'] == vote_count
self.register_get_user_response(self.user, upvoted_ids=["test_comment"]) self.register_get_user_response(self.user, upvoted_ids=["test_comment"])
else: else:
vote_count -= 1 vote_count -= 1
self.assertEqual(result["vote_count"], vote_count) assert result['vote_count'] == vote_count
self.register_get_user_response(self.user, upvoted_ids=[]) self.register_get_user_response(self.user, upvoted_ids=[])
@ddt.data(*itertools.product([True, False], [True, False])) @ddt.data(*itertools.product([True, False], [True, False]))
@@ -2932,23 +2801,17 @@ class UpdateCommentTest(
self.register_comment({"abuse_flaggers": [str(self.user.id)] if old_flagged else []}) self.register_comment({"abuse_flaggers": [str(self.user.id)] if old_flagged else []})
data = {"abuse_flagged": new_flagged} data = {"abuse_flagged": new_flagged}
result = update_comment(self.request, "test_comment", data) result = update_comment(self.request, "test_comment", data)
self.assertEqual(result["abuse_flagged"], new_flagged) assert result['abuse_flagged'] == new_flagged
last_request_path = urlparse(httpretty.last_request().path).path # lint-amnesty, pylint: disable=no-member last_request_path = urlparse(httpretty.last_request().path).path # lint-amnesty, pylint: disable=no-member
flag_url = "/api/v1/comments/test_comment/abuse_flag" flag_url = "/api/v1/comments/test_comment/abuse_flag"
unflag_url = "/api/v1/comments/test_comment/abuse_unflag" unflag_url = "/api/v1/comments/test_comment/abuse_unflag"
if old_flagged == new_flagged: if old_flagged == new_flagged:
self.assertNotEqual(last_request_path, flag_url) assert last_request_path != flag_url
self.assertNotEqual(last_request_path, unflag_url) assert last_request_path != unflag_url
else: else:
self.assertEqual( assert last_request_path == (flag_url if new_flagged else unflag_url)
last_request_path, assert httpretty.last_request().method == 'PUT'
flag_url if new_flagged else unflag_url assert httpretty.last_request().parsed_body == {'user_id': [str(self.user.id)]} # lint-amnesty, pylint: disable=no-member
)
self.assertEqual(httpretty.last_request().method, "PUT")
self.assertEqual(
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member
{"user_id": [str(self.user.id)]}
)
@ddt.ddt @ddt.ddt
@@ -2999,33 +2862,30 @@ class DeleteThreadTest(
def test_basic(self): def test_basic(self):
self.register_thread() self.register_thread()
with self.assert_signal_sent(api, 'thread_deleted', sender=None, user=self.user, exclude_args=('post',)): with self.assert_signal_sent(api, 'thread_deleted', sender=None, user=self.user, exclude_args=('post',)):
self.assertIsNone(delete_thread(self.request, self.thread_id)) assert delete_thread(self.request, self.thread_id) is None
self.assertEqual( assert urlparse(httpretty.last_request().path).path == '/api/v1/threads/{}'.format(self.thread_id) # lint-amnesty, pylint: disable=no-member
urlparse(httpretty.last_request().path).path, # lint-amnesty, pylint: disable=no-member assert httpretty.last_request().method == 'DELETE'
"/api/v1/threads/{}".format(self.thread_id)
)
self.assertEqual(httpretty.last_request().method, "DELETE")
def test_thread_id_not_found(self): def test_thread_id_not_found(self):
self.register_get_thread_error_response("missing_thread", 404) self.register_get_thread_error_response("missing_thread", 404)
with self.assertRaises(ThreadNotFoundError): with pytest.raises(ThreadNotFoundError):
delete_thread(self.request, "missing_thread") delete_thread(self.request, "missing_thread")
def test_nonexistent_course(self): def test_nonexistent_course(self):
self.register_thread({"course_id": "non/existent/course"}) self.register_thread({"course_id": "non/existent/course"})
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
delete_thread(self.request, self.thread_id) delete_thread(self.request, self.thread_id)
def test_not_enrolled(self): def test_not_enrolled(self):
self.register_thread() self.register_thread()
self.request.user = UserFactory.create() self.request.user = UserFactory.create()
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
delete_thread(self.request, self.thread_id) delete_thread(self.request, self.thread_id)
def test_discussions_disabled(self): def test_discussions_disabled(self):
disabled_course = _discussion_disabled_course_for(self.user) disabled_course = _discussion_disabled_course_for(self.user)
self.register_thread(overrides={"course_id": six.text_type(disabled_course.id)}) self.register_thread(overrides={"course_id": six.text_type(disabled_course.id)})
with self.assertRaises(DiscussionDisabledError): with pytest.raises(DiscussionDisabledError):
delete_thread(self.request, self.thread_id) delete_thread(self.request, self.thread_id)
@ddt.data( @ddt.data(
@@ -3040,9 +2900,9 @@ class DeleteThreadTest(
expected_error = role_name == FORUM_ROLE_STUDENT expected_error = role_name == FORUM_ROLE_STUDENT
try: try:
delete_thread(self.request, self.thread_id) delete_thread(self.request, self.thread_id)
self.assertFalse(expected_error) assert not expected_error
except PermissionDenied: except PermissionDenied:
self.assertTrue(expected_error) assert expected_error
@ddt.data( @ddt.data(
*itertools.product( *itertools.product(
@@ -3082,9 +2942,9 @@ class DeleteThreadTest(
) )
try: try:
delete_thread(self.request, self.thread_id) delete_thread(self.request, self.thread_id)
self.assertFalse(expected_error) assert not expected_error
except ThreadNotFoundError: except ThreadNotFoundError:
self.assertTrue(expected_error) assert expected_error
@ddt.ddt @ddt.ddt
@@ -3144,29 +3004,26 @@ class DeleteCommentTest(
def test_basic(self): def test_basic(self):
self.register_comment_and_thread() self.register_comment_and_thread()
with self.assert_signal_sent(api, 'comment_deleted', sender=None, user=self.user, exclude_args=('post',)): with self.assert_signal_sent(api, 'comment_deleted', sender=None, user=self.user, exclude_args=('post',)):
self.assertIsNone(delete_comment(self.request, self.comment_id)) assert delete_comment(self.request, self.comment_id) is None
self.assertEqual( assert urlparse(httpretty.last_request().path).path == '/api/v1/comments/{}'.format(self.comment_id) # lint-amnesty, pylint: disable=no-member
urlparse(httpretty.last_request().path).path, # lint-amnesty, pylint: disable=no-member assert httpretty.last_request().method == 'DELETE'
"/api/v1/comments/{}".format(self.comment_id)
)
self.assertEqual(httpretty.last_request().method, "DELETE")
def test_comment_id_not_found(self): def test_comment_id_not_found(self):
self.register_get_comment_error_response("missing_comment", 404) self.register_get_comment_error_response("missing_comment", 404)
with self.assertRaises(CommentNotFoundError): with pytest.raises(CommentNotFoundError):
delete_comment(self.request, "missing_comment") delete_comment(self.request, "missing_comment")
def test_nonexistent_course(self): def test_nonexistent_course(self):
self.register_comment_and_thread( self.register_comment_and_thread(
thread_overrides={"course_id": "non/existent/course"} thread_overrides={"course_id": "non/existent/course"}
) )
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
delete_comment(self.request, self.comment_id) delete_comment(self.request, self.comment_id)
def test_not_enrolled(self): def test_not_enrolled(self):
self.register_comment_and_thread() self.register_comment_and_thread()
self.request.user = UserFactory.create() self.request.user = UserFactory.create()
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
delete_comment(self.request, self.comment_id) delete_comment(self.request, self.comment_id)
def test_discussions_disabled(self): def test_discussions_disabled(self):
@@ -3175,7 +3032,7 @@ class DeleteCommentTest(
thread_overrides={"course_id": six.text_type(disabled_course.id)}, thread_overrides={"course_id": six.text_type(disabled_course.id)},
overrides={"course_id": six.text_type(disabled_course.id)} overrides={"course_id": six.text_type(disabled_course.id)}
) )
with self.assertRaises(DiscussionDisabledError): with pytest.raises(DiscussionDisabledError):
delete_comment(self.request, self.comment_id) delete_comment(self.request, self.comment_id)
@ddt.data( @ddt.data(
@@ -3192,9 +3049,9 @@ class DeleteCommentTest(
expected_error = role_name == FORUM_ROLE_STUDENT expected_error = role_name == FORUM_ROLE_STUDENT
try: try:
delete_comment(self.request, self.comment_id) delete_comment(self.request, self.comment_id)
self.assertFalse(expected_error) assert not expected_error
except PermissionDenied: except PermissionDenied:
self.assertTrue(expected_error) assert expected_error
@ddt.data( @ddt.data(
*itertools.product( *itertools.product(
@@ -3237,9 +3094,9 @@ class DeleteCommentTest(
) )
try: try:
delete_comment(self.request, self.comment_id) delete_comment(self.request, self.comment_id)
self.assertFalse(expected_error) assert not expected_error
except ThreadNotFoundError: except ThreadNotFoundError:
self.assertTrue(expected_error) assert expected_error
@ddt.ddt @ddt.ddt
@@ -3292,15 +3149,15 @@ class RetrieveThreadTest(
def test_basic(self): def test_basic(self):
self.register_thread({"resp_total": 2}) self.register_thread({"resp_total": 2})
self.assertEqual(get_thread(self.request, self.thread_id), self.expected_thread_data({ assert get_thread(self.request, self.thread_id) == self.expected_thread_data({
"response_count": 2, 'response_count': 2,
"unread_comment_count": 1, 'unread_comment_count': 1
})) })
self.assertEqual(httpretty.last_request().method, "GET") assert httpretty.last_request().method == 'GET'
def test_thread_id_not_found(self): def test_thread_id_not_found(self):
self.register_get_thread_error_response("missing_thread", 404) self.register_get_thread_error_response("missing_thread", 404)
with self.assertRaises(ThreadNotFoundError): with pytest.raises(ThreadNotFoundError):
get_thread(self.request, "missing_thread") get_thread(self.request, "missing_thread")
def test_nonauthor_enrolled_in_course(self): def test_nonauthor_enrolled_in_course(self):
@@ -3309,16 +3166,16 @@ class RetrieveThreadTest(
CourseEnrollmentFactory.create(user=non_author_user, course_id=self.course.id) CourseEnrollmentFactory.create(user=non_author_user, course_id=self.course.id)
self.register_thread() self.register_thread()
self.request.user = non_author_user self.request.user = non_author_user
self.assertEqual(get_thread(self.request, self.thread_id), self.expected_thread_data({ assert get_thread(self.request, self.thread_id) == self.expected_thread_data({
"editable_fields": ["abuse_flagged", "following", "read", "voted"], 'editable_fields': ['abuse_flagged', 'following', 'read', 'voted'],
"unread_comment_count": 1, 'unread_comment_count': 1
})) })
self.assertEqual(httpretty.last_request().method, "GET") assert httpretty.last_request().method == 'GET'
def test_not_enrolled_in_course(self): def test_not_enrolled_in_course(self):
self.register_thread() self.register_thread()
self.request.user = UserFactory.create() self.request.user = UserFactory.create()
with self.assertRaises(CourseNotFoundError): with pytest.raises(CourseNotFoundError):
get_thread(self.request, self.thread_id) get_thread(self.request, self.thread_id)
@ddt.data( @ddt.data(
@@ -3359,6 +3216,6 @@ class RetrieveThreadTest(
) )
try: try:
get_thread(self.request, self.thread_id) get_thread(self.request, self.thread_id)
self.assertFalse(expected_error) assert not expected_error
except ThreadNotFoundError: except ThreadNotFoundError:
self.assertTrue(expected_error) assert expected_error

View File

@@ -59,37 +59,28 @@ class ThreadListGetFormTest(FormTestMixin, PaginationTestMixin, TestCase):
def test_basic(self): def test_basic(self):
form = self.get_form(expected_valid=True) form = self.get_form(expected_valid=True)
self.assertEqual( assert form.cleaned_data == {
form.cleaned_data, 'course_id': CourseLocator.from_string('Foo/Bar/Baz'),
{ 'page': 2,
"course_id": CourseLocator.from_string("Foo/Bar/Baz"), 'page_size': 13,
"page": 2, 'topic_id': set(),
"page_size": 13, 'text_search': '',
"topic_id": set(), 'following': None,
"text_search": "", 'view': '',
"following": None, 'order_by': 'last_activity_at',
"view": "", 'order_direction': 'desc',
"order_by": "last_activity_at", 'requested_fields': set()
"order_direction": "desc", }
"requested_fields": set(),
}
)
def test_topic_id(self): def test_topic_id(self):
self.form_data.setlist("topic_id", ["example topic_id", "example 2nd topic_id"]) self.form_data.setlist("topic_id", ["example topic_id", "example 2nd topic_id"])
form = self.get_form(expected_valid=True) form = self.get_form(expected_valid=True)
self.assertEqual( assert form.cleaned_data['topic_id'] == {'example topic_id', 'example 2nd topic_id'}
form.cleaned_data["topic_id"],
{"example topic_id", "example 2nd topic_id"},
)
def test_text_search(self): def test_text_search(self):
self.form_data["text_search"] = "test search string" self.form_data["text_search"] = "test search string"
form = self.get_form(expected_valid=True) form = self.get_form(expected_valid=True)
self.assertEqual( assert form.cleaned_data['text_search'] == 'test search string'
form.cleaned_data["text_search"],
"test search string",
)
def test_missing_course_id(self): def test_missing_course_id(self):
self.form_data.pop("course_id") self.form_data.pop("course_id")
@@ -159,10 +150,7 @@ class ThreadListGetFormTest(FormTestMixin, PaginationTestMixin, TestCase):
def test_requested_fields(self): def test_requested_fields(self):
self.form_data["requested_fields"] = "profile_image" self.form_data["requested_fields"] = "profile_image"
form = self.get_form(expected_valid=True) form = self.get_form(expected_valid=True)
self.assertEqual( assert form.cleaned_data['requested_fields'] == {'profile_image'}
form.cleaned_data["requested_fields"],
{"profile_image"},
)
@ddt.ddt @ddt.ddt
@@ -181,16 +169,13 @@ class CommentListGetFormTest(FormTestMixin, PaginationTestMixin, TestCase):
def test_basic(self): def test_basic(self):
form = self.get_form(expected_valid=True) form = self.get_form(expected_valid=True)
self.assertEqual( assert form.cleaned_data == {
form.cleaned_data, 'thread_id': 'deadbeef',
{ 'endorsed': False,
"thread_id": "deadbeef", 'page': 2,
"endorsed": False, 'page_size': 13,
"page": 2, 'requested_fields': set()
"page_size": 13, }
"requested_fields": set(),
}
)
def test_missing_thread_id(self): def test_missing_thread_id(self):
self.form_data.pop("thread_id") self.form_data.pop("thread_id")
@@ -217,7 +202,4 @@ class CommentListGetFormTest(FormTestMixin, PaginationTestMixin, TestCase):
def test_requested_fields(self): def test_requested_fields(self):
self.form_data["requested_fields"] = {"profile_image"} self.form_data["requested_fields"] = {"profile_image"}
form = self.get_form(expected_valid=True) form = self.get_form(expected_valid=True)
self.assertEqual( assert form.cleaned_data['requested_fields'] == {'profile_image'}
form.cleaned_data["requested_fields"],
{"profile_image"},
)

View File

@@ -22,7 +22,7 @@ class PaginationSerializerTest(TestCase):
request = RequestFactory().get("/test") request = RequestFactory().get("/test")
paginator = DiscussionAPIPagination(request, page_num, num_pages) paginator = DiscussionAPIPagination(request, page_num, num_pages)
actual = paginator.get_paginated_response(objects) actual = paginator.get_paginated_response(objects)
self.assertEqual(actual.data, expected) assert actual.data == expected
def test_empty(self): def test_empty(self):
self.do_case( self.do_case(

View File

@@ -48,7 +48,7 @@ class GetInitializableFieldsTest(ModuleStoreTestCase):
} }
if is_privileged and is_cohorted: if is_privileged and is_cohorted:
expected |= {"group_id"} expected |= {"group_id"}
self.assertEqual(actual, expected) assert actual == expected
@ddt.data(*itertools.product([True, False], ["question", "discussion"], [True, False])) @ddt.data(*itertools.product([True, False], ["question", "discussion"], [True, False]))
@ddt.unpack @ddt.unpack
@@ -64,7 +64,7 @@ class GetInitializableFieldsTest(ModuleStoreTestCase):
} }
if (is_thread_author and thread_type == "question") or is_privileged: if (is_thread_author and thread_type == "question") or is_privileged:
expected |= {"endorsed"} expected |= {"endorsed"}
self.assertEqual(actual, expected) assert actual == expected
@ddt.ddt @ddt.ddt
@@ -85,7 +85,7 @@ class GetEditableFieldsTest(ModuleStoreTestCase):
expected |= {"topic_id", "type", "title", "raw_body"} expected |= {"topic_id", "type", "title", "raw_body"}
if is_privileged and is_cohorted: if is_privileged and is_cohorted:
expected |= {"group_id"} expected |= {"group_id"}
self.assertEqual(actual, expected) assert actual == expected
@ddt.data(*itertools.product([True, False], [True, False], ["question", "discussion"], [True, False])) @ddt.data(*itertools.product([True, False], [True, False], ["question", "discussion"], [True, False]))
@ddt.unpack @ddt.unpack
@@ -102,7 +102,7 @@ class GetEditableFieldsTest(ModuleStoreTestCase):
expected |= {"raw_body"} expected |= {"raw_body"}
if (is_thread_author and thread_type == "question") or is_privileged: if (is_thread_author and thread_type == "question") or is_privileged:
expected |= {"endorsed"} expected |= {"endorsed"}
self.assertEqual(actual, expected) assert actual == expected
@ddt.ddt @ddt.ddt
@@ -113,7 +113,7 @@ class CanDeleteTest(ModuleStoreTestCase):
def test_thread(self, is_author, is_privileged): def test_thread(self, is_author, is_privileged):
thread = Thread(user_id="5" if is_author else "6") thread = Thread(user_id="5" if is_author else "6")
context = _get_context(requester_id="5", is_requester_privileged=is_privileged) context = _get_context(requester_id="5", is_requester_privileged=is_privileged)
self.assertEqual(can_delete(thread, context), is_author or is_privileged) assert can_delete(thread, context) == (is_author or is_privileged)
@ddt.data(*itertools.product([True, False], [True, False], [True, False])) @ddt.data(*itertools.product([True, False], [True, False], [True, False]))
@ddt.unpack @ddt.unpack
@@ -124,4 +124,4 @@ class CanDeleteTest(ModuleStoreTestCase):
is_requester_privileged=is_privileged, is_requester_privileged=is_privileged,
thread=Thread(user_id="5" if is_thread_author else "6") thread=Thread(user_id="5" if is_thread_author else "6")
) )
self.assertEqual(can_delete(comment, context), is_author or is_privileged) assert can_delete(comment, context) == (is_author or is_privileged)

View File

@@ -20,7 +20,7 @@ class RenderBodyTest(TestCase):
"""Tests for render_body""" """Tests for render_body"""
def test_empty(self): def test_empty(self):
self.assertEqual(render_body(""), "") assert render_body('') == ''
@ddt.data( @ddt.data(
("*", "em"), ("*", "em"),
@@ -29,10 +29,8 @@ class RenderBodyTest(TestCase):
) )
@ddt.unpack @ddt.unpack
def test_markdown_inline(self, delimiter, tag): def test_markdown_inline(self, delimiter, tag):
self.assertEqual( assert render_body(u'{delimiter}some text{delimiter}'.format(delimiter=delimiter)) == \
render_body(u"{delimiter}some text{delimiter}".format(delimiter=delimiter)), u'<p><{tag}>some text</{tag}></p>'.format(tag=tag)
u"<p><{tag}>some text</{tag}></p>".format(tag=tag)
)
@ddt.data( @ddt.data(
"b", "blockquote", "code", "del", "dd", "dl", "dt", "em", "h1", "h2", "h3", "i", "kbd", "b", "blockquote", "code", "del", "dd", "dl", "dt", "em", "h1", "h2", "h3", "i", "kbd",
@@ -42,52 +40,49 @@ class RenderBodyTest(TestCase):
raw_body = "<{tag}>some text</{tag}>".format(tag=tag) raw_body = "<{tag}>some text</{tag}>".format(tag=tag)
is_inline_tag = tag in ["b", "code", "del", "em", "i", "kbd", "s", "sup", "sub", "strong", "strike"] is_inline_tag = tag in ["b", "code", "del", "em", "i", "kbd", "s", "sup", "sub", "strong", "strike"]
rendered_body = _add_p_tags(raw_body) if is_inline_tag else raw_body rendered_body = _add_p_tags(raw_body) if is_inline_tag else raw_body
self.assertEqual(render_body(raw_body), rendered_body) assert render_body(raw_body) == rendered_body
@ddt.data("br", "hr") @ddt.data("br", "hr")
def test_selfclosing_tag(self, tag): def test_selfclosing_tag(self, tag):
raw_body = "<{tag}>".format(tag=tag) raw_body = "<{tag}>".format(tag=tag)
is_inline_tag = tag == "br" is_inline_tag = tag == "br"
rendered_body = _add_p_tags(raw_body) if is_inline_tag else raw_body rendered_body = _add_p_tags(raw_body) if is_inline_tag else raw_body
self.assertEqual(render_body(raw_body), rendered_body) assert render_body(raw_body) == rendered_body
@ddt.data("http", "https", "ftp") @ddt.data("http", "https", "ftp")
def test_allowed_a_tag(self, protocol): def test_allowed_a_tag(self, protocol):
raw_body = '<a href="{protocol}://foo" title="bar">baz</a>'.format(protocol=protocol) raw_body = '<a href="{protocol}://foo" title="bar">baz</a>'.format(protocol=protocol)
self.assertEqual(render_body(raw_body), _add_p_tags(raw_body)) assert render_body(raw_body) == _add_p_tags(raw_body)
def test_disallowed_a_tag(self): def test_disallowed_a_tag(self):
raw_body = '<a href="gopher://foo">link content</a>' raw_body = '<a href="gopher://foo">link content</a>'
self.assertEqual(render_body(raw_body), "<p>link content</p>") assert render_body(raw_body) == '<p>link content</p>'
@ddt.data("http", "https") @ddt.data("http", "https")
def test_allowed_img_tag(self, protocol): def test_allowed_img_tag(self, protocol):
raw_body = '<img src="{protocol}://foo" width="111" height="222" alt="bar" title="baz">'.format( raw_body = '<img src="{protocol}://foo" width="111" height="222" alt="bar" title="baz">'.format(
protocol=protocol protocol=protocol
) )
self.assertEqual(render_body(raw_body), _add_p_tags(raw_body)) assert render_body(raw_body) == _add_p_tags(raw_body)
def test_disallowed_img_tag(self): def test_disallowed_img_tag(self):
raw_body = '<img src="gopher://foo">' raw_body = '<img src="gopher://foo">'
self.assertEqual(render_body(raw_body), "<p></p>") assert render_body(raw_body) == '<p></p>'
def test_script_tag(self): def test_script_tag(self):
raw_body = '<script type="text/javascript">alert("evil script");</script>' raw_body = '<script type="text/javascript">alert("evil script");</script>'
self.assertEqual(render_body(raw_body), 'alert("evil script");') assert render_body(raw_body) == 'alert("evil script");'
@ddt.data("p", "br", "li", "hr") # img is tested above @ddt.data("p", "br", "li", "hr") # img is tested above
def test_allowed_unpaired_tags(self, tag): def test_allowed_unpaired_tags(self, tag):
raw_body = "foo<{tag}>bar".format(tag=tag) raw_body = "foo<{tag}>bar".format(tag=tag)
self.assertEqual(render_body(raw_body), _add_p_tags(raw_body)) assert render_body(raw_body) == _add_p_tags(raw_body)
def test_unpaired_start_tag(self): def test_unpaired_start_tag(self):
self.assertEqual(render_body("foo<i>bar"), "<p>foobar</p>") assert render_body('foo<i>bar') == '<p>foobar</p>'
def test_unpaired_end_tag(self): def test_unpaired_end_tag(self):
self.assertEqual(render_body("foo</i>bar"), "<p>foobar</p>") assert render_body('foo</i>bar') == '<p>foobar</p>'
def test_interleaved_tags(self): def test_interleaved_tags(self):
self.assertEqual( assert render_body('foo<i>bar<b>baz</i>quux</b>greg') == '<p>foo<i>barbaz</i>quuxgreg</p>'
render_body("foo<i>bar<b>baz</i>quux</b>greg"),
"<p>foo<i>barbaz</i>quuxgreg</p>"
)

View File

@@ -100,7 +100,7 @@ class SerializerTestMixin(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetM
self.make_cs_content({"anonymous": anonymous, "anonymous_to_peers": anonymous_to_peers}) self.make_cs_content({"anonymous": anonymous, "anonymous_to_peers": anonymous_to_peers})
) )
actual_serialized_anonymous = serialized["author"] is None actual_serialized_anonymous = serialized["author"] is None
self.assertEqual(actual_serialized_anonymous, expected_serialized_anonymous) assert actual_serialized_anonymous == expected_serialized_anonymous
@ddt.data( @ddt.data(
(FORUM_ROLE_ADMINISTRATOR, False, "Staff"), (FORUM_ROLE_ADMINISTRATOR, False, "Staff"),
@@ -128,17 +128,17 @@ class SerializerTestMixin(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetM
""" """
self.create_role(role_name, [self.author]) self.create_role(role_name, [self.author])
serialized = self.serialize(self.make_cs_content({"anonymous": anonymous})) serialized = self.serialize(self.make_cs_content({"anonymous": anonymous}))
self.assertEqual(serialized["author_label"], expected_label) assert serialized['author_label'] == expected_label
def test_abuse_flagged(self): def test_abuse_flagged(self):
serialized = self.serialize(self.make_cs_content({"abuse_flaggers": [str(self.user.id)]})) serialized = self.serialize(self.make_cs_content({"abuse_flaggers": [str(self.user.id)]}))
self.assertEqual(serialized["abuse_flagged"], True) assert serialized['abuse_flagged'] is True
def test_voted(self): def test_voted(self):
thread_id = "test_thread" thread_id = "test_thread"
self.register_get_user_response(self.user, upvoted_ids=[thread_id]) self.register_get_user_response(self.user, upvoted_ids=[thread_id])
serialized = self.serialize(self.make_cs_content({"id": thread_id})) serialized = self.serialize(self.make_cs_content({"id": thread_id}))
self.assertEqual(serialized["voted"], True) assert serialized['voted'] is True
@ddt.ddt @ddt.ddt
@@ -188,7 +188,7 @@ class ThreadSerializerSerializationTest(SerializerTestMixin, SharedModuleStoreTe
"pinned": True, "pinned": True,
"editable_fields": ["abuse_flagged", "following", "read", "voted"], "editable_fields": ["abuse_flagged", "following", "read", "voted"],
}) })
self.assertEqual(self.serialize(thread), expected) assert self.serialize(thread) == expected
thread["thread_type"] = "question" thread["thread_type"] = "question"
expected.update({ expected.update({
@@ -201,7 +201,7 @@ class ThreadSerializerSerializationTest(SerializerTestMixin, SharedModuleStoreTe
"http://testserver/api/discussion/v1/comments/?thread_id=test_thread&endorsed=False" "http://testserver/api/discussion/v1/comments/?thread_id=test_thread&endorsed=False"
), ),
}) })
self.assertEqual(self.serialize(thread), expected) assert self.serialize(thread) == expected
def test_pinned_missing(self): def test_pinned_missing(self):
""" """
@@ -212,34 +212,34 @@ class ThreadSerializerSerializationTest(SerializerTestMixin, SharedModuleStoreTe
del thread_data["pinned"] del thread_data["pinned"]
self.register_get_thread_response(thread_data) self.register_get_thread_response(thread_data)
serialized = self.serialize(thread_data) serialized = self.serialize(thread_data)
self.assertEqual(serialized["pinned"], False) assert serialized['pinned'] is False
def test_group(self): def test_group(self):
self.course.cohort_config = {"cohorted": True} self.course.cohort_config = {"cohorted": True}
modulestore().update_item(self.course, ModuleStoreEnum.UserID.test) modulestore().update_item(self.course, ModuleStoreEnum.UserID.test)
cohort = CohortFactory.create(course_id=self.course.id) cohort = CohortFactory.create(course_id=self.course.id)
serialized = self.serialize(self.make_cs_content({"group_id": cohort.id})) serialized = self.serialize(self.make_cs_content({"group_id": cohort.id}))
self.assertEqual(serialized["group_id"], cohort.id) assert serialized['group_id'] == cohort.id
self.assertEqual(serialized["group_name"], cohort.name) assert serialized['group_name'] == cohort.name
def test_following(self): def test_following(self):
thread_id = "test_thread" thread_id = "test_thread"
self.register_get_user_response(self.user, subscribed_thread_ids=[thread_id]) self.register_get_user_response(self.user, subscribed_thread_ids=[thread_id])
serialized = self.serialize(self.make_cs_content({"id": thread_id})) serialized = self.serialize(self.make_cs_content({"id": thread_id}))
self.assertEqual(serialized["following"], True) assert serialized['following'] is True
def test_response_count(self): def test_response_count(self):
thread_data = self.make_cs_content({"resp_total": 2}) thread_data = self.make_cs_content({"resp_total": 2})
self.register_get_thread_response(thread_data) self.register_get_thread_response(thread_data)
serialized = self.serialize(thread_data) serialized = self.serialize(thread_data)
self.assertEqual(serialized["response_count"], 2) assert serialized['response_count'] == 2
def test_response_count_missing(self): def test_response_count_missing(self):
thread_data = self.make_cs_content({}) thread_data = self.make_cs_content({})
del thread_data["resp_total"] del thread_data["resp_total"]
self.register_get_thread_response(thread_data) self.register_get_thread_response(thread_data)
serialized = self.serialize(thread_data) serialized = self.serialize(thread_data)
self.assertNotIn("response_count", serialized) assert 'response_count' not in serialized
@ddt.ddt @ddt.ddt
@@ -313,7 +313,7 @@ class CommentSerializerTest(SerializerTestMixin, SharedModuleStoreTestCase):
"editable_fields": ["abuse_flagged", "voted"], "editable_fields": ["abuse_flagged", "voted"],
"child_count": 0, "child_count": 0,
} }
self.assertEqual(self.serialize(comment), expected) assert self.serialize(comment) == expected
@ddt.data( @ddt.data(
*itertools.product( *itertools.product(
@@ -344,7 +344,7 @@ class CommentSerializerTest(SerializerTestMixin, SharedModuleStoreTestCase):
) )
actual_endorser_anonymous = serialized["endorsed_by"] is None actual_endorser_anonymous = serialized["endorsed_by"] is None
expected_endorser_anonymous = endorser_role_name == FORUM_ROLE_STUDENT and thread_anonymous expected_endorser_anonymous = endorser_role_name == FORUM_ROLE_STUDENT and thread_anonymous
self.assertEqual(actual_endorser_anonymous, expected_endorser_anonymous) assert actual_endorser_anonymous == expected_endorser_anonymous
@ddt.data( @ddt.data(
(FORUM_ROLE_ADMINISTRATOR, "Staff"), (FORUM_ROLE_ADMINISTRATOR, "Staff"),
@@ -366,11 +366,11 @@ class CommentSerializerTest(SerializerTestMixin, SharedModuleStoreTestCase):
""" """
self.create_role(role_name, [self.endorser]) self.create_role(role_name, [self.endorser])
serialized = self.serialize(self.make_cs_content(with_endorsement=True)) serialized = self.serialize(self.make_cs_content(with_endorsement=True))
self.assertEqual(serialized["endorsed_by_label"], expected_label) assert serialized['endorsed_by_label'] == expected_label
def test_endorsed_at(self): def test_endorsed_at(self):
serialized = self.serialize(self.make_cs_content(with_endorsement=True)) serialized = self.serialize(self.make_cs_content(with_endorsement=True))
self.assertEqual(serialized["endorsed_at"], self.endorsed_at) assert serialized['endorsed_at'] == self.endorsed_at
def test_children(self): def test_children(self):
comment = self.make_cs_content({ comment = self.make_cs_content({
@@ -393,12 +393,12 @@ class CommentSerializerTest(SerializerTestMixin, SharedModuleStoreTestCase):
], ],
}) })
serialized = self.serialize(comment) serialized = self.serialize(comment)
self.assertEqual(serialized["children"][0]["id"], "test_child_1") assert serialized['children'][0]['id'] == 'test_child_1'
self.assertEqual(serialized["children"][0]["parent_id"], "test_root") assert serialized['children'][0]['parent_id'] == 'test_root'
self.assertEqual(serialized["children"][1]["id"], "test_child_2") assert serialized['children'][1]['id'] == 'test_child_2'
self.assertEqual(serialized["children"][1]["parent_id"], "test_root") assert serialized['children'][1]['parent_id'] == 'test_root'
self.assertEqual(serialized["children"][1]["children"][0]["id"], "test_grandchild") assert serialized['children'][1]['children'][0]['id'] == 'test_grandchild'
self.assertEqual(serialized["children"][1]["children"][0]["parent_id"], "test_child_2") assert serialized['children'][1]['children'][0]['parent_id'] == 'test_child_2'
@ddt.ddt @ddt.ddt
@@ -458,69 +458,57 @@ class ThreadSerializerDeserializationTest(
partial=(instance is not None), partial=(instance is not None),
context=get_context(self.course, self.request) context=get_context(self.course, self.request)
) )
self.assertTrue(serializer.is_valid()) assert serializer.is_valid()
serializer.save() serializer.save()
return serializer.data return serializer.data
def test_create_minimal(self): def test_create_minimal(self):
self.register_post_thread_response({"id": "test_id", "username": self.user.username}) self.register_post_thread_response({"id": "test_id", "username": self.user.username})
saved = self.save_and_reserialize(self.minimal_data) saved = self.save_and_reserialize(self.minimal_data)
self.assertEqual( assert urlparse(httpretty.last_request().path).path ==\
urlparse(httpretty.last_request().path).path, # lint-amnesty, pylint: disable=no-member '/api/v1/test_topic/threads' # lint-amnesty, pylint: disable=no-member
"/api/v1/test_topic/threads" assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
) 'course_id': [six.text_type(self.course.id)],
self.assertEqual( 'commentable_id': ['test_topic'],
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member 'thread_type': ['discussion'],
{ 'title': ['Test Title'],
"course_id": [six.text_type(self.course.id)], 'body': ['Test body'],
"commentable_id": ["test_topic"], 'user_id': [str(self.user.id)]
"thread_type": ["discussion"], }
"title": ["Test Title"], assert saved['id'] == 'test_id'
"body": ["Test body"],
"user_id": [str(self.user.id)],
}
)
self.assertEqual(saved["id"], "test_id")
def test_create_all_fields(self): def test_create_all_fields(self):
self.register_post_thread_response({"id": "test_id", "username": self.user.username}) self.register_post_thread_response({"id": "test_id", "username": self.user.username})
data = self.minimal_data.copy() data = self.minimal_data.copy()
data["group_id"] = 42 data["group_id"] = 42
self.save_and_reserialize(data) self.save_and_reserialize(data)
self.assertEqual( assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member 'course_id': [six.text_type(self.course.id)],
{ 'commentable_id': ['test_topic'],
"course_id": [six.text_type(self.course.id)], 'thread_type': ['discussion'],
"commentable_id": ["test_topic"], 'title': ['Test Title'],
"thread_type": ["discussion"], 'body': ['Test body'],
"title": ["Test Title"], 'user_id': [str(self.user.id)],
"body": ["Test body"], 'group_id': ['42']
"user_id": [str(self.user.id)], }
"group_id": ["42"],
}
)
def test_create_missing_field(self): def test_create_missing_field(self):
for field in self.minimal_data: for field in self.minimal_data:
data = self.minimal_data.copy() data = self.minimal_data.copy()
data.pop(field) data.pop(field)
serializer = ThreadSerializer(data=data) serializer = ThreadSerializer(data=data)
self.assertFalse(serializer.is_valid()) assert not serializer.is_valid()
self.assertEqual( assert serializer.errors == {field: ['This field is required.']}
serializer.errors,
{field: ["This field is required."]}
)
@ddt.data("", " ") @ddt.data("", " ")
def test_create_empty_string(self, value): def test_create_empty_string(self, value):
data = self.minimal_data.copy() data = self.minimal_data.copy()
data.update({field: value for field in ["topic_id", "title", "raw_body"]}) data.update({field: value for field in ["topic_id", "title", "raw_body"]})
serializer = ThreadSerializer(data=data, context=get_context(self.course, self.request)) serializer = ThreadSerializer(data=data, context=get_context(self.course, self.request))
self.assertFalse(serializer.is_valid()) assert not serializer.is_valid()
self.assertEqual( assert serializer.errors == {
serializer.errors, field: ['This field may not be blank.'] for field in ['topic_id', 'title', 'raw_body']
{field: ["This field may not be blank."] for field in ["topic_id", "title", "raw_body"]} }
)
def test_create_type(self): def test_create_type(self):
self.register_post_thread_response({"id": "test_id", "username": self.user.username}) self.register_post_thread_response({"id": "test_id", "username": self.user.username})
@@ -530,27 +518,24 @@ class ThreadSerializerDeserializationTest(
data["type"] = "invalid_type" data["type"] = "invalid_type"
serializer = ThreadSerializer(data=data) serializer = ThreadSerializer(data=data)
self.assertFalse(serializer.is_valid()) assert not serializer.is_valid()
def test_update_empty(self): def test_update_empty(self):
self.register_put_thread_response(self.existing_thread.attributes) self.register_put_thread_response(self.existing_thread.attributes)
self.save_and_reserialize({}, self.existing_thread) self.save_and_reserialize({}, self.existing_thread)
self.assertEqual( assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member 'course_id': [six.text_type(self.course.id)],
{ 'commentable_id': ['original_topic'],
"course_id": [six.text_type(self.course.id)], 'thread_type': ['discussion'],
"commentable_id": ["original_topic"], 'title': ['Original Title'],
"thread_type": ["discussion"], 'body': ['Original body'],
"title": ["Original Title"], 'anonymous': ['False'],
"body": ["Original body"], 'anonymous_to_peers': ['False'],
"anonymous": ["False"], 'closed': ['False'],
"anonymous_to_peers": ["False"], 'pinned': ['False'],
"closed": ["False"], 'user_id': [str(self.user.id)],
"pinned": ["False"], 'read': ['False']
"user_id": [str(self.user.id)], }
"read": ["False"],
}
)
@ddt.data(True, False) @ddt.data(True, False)
def test_update_all(self, read): def test_update_all(self, read):
@@ -563,24 +548,21 @@ class ThreadSerializerDeserializationTest(
"read": read, "read": read,
} }
saved = self.save_and_reserialize(data, self.existing_thread) saved = self.save_and_reserialize(data, self.existing_thread)
self.assertEqual( assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member 'course_id': [six.text_type(self.course.id)],
{ 'commentable_id': ['edited_topic'],
"course_id": [six.text_type(self.course.id)], 'thread_type': ['question'],
"commentable_id": ["edited_topic"], 'title': ['Edited Title'],
"thread_type": ["question"], 'body': ['Edited body'],
"title": ["Edited Title"], 'anonymous': ['False'],
"body": ["Edited body"], 'anonymous_to_peers': ['False'],
"anonymous": ["False"], 'closed': ['False'],
"anonymous_to_peers": ["False"], 'pinned': ['False'],
"closed": ["False"], 'user_id': [str(self.user.id)],
"pinned": ["False"], 'read': [str(read)]
"user_id": [str(self.user.id)], }
"read": [str(read)],
}
)
for key in data: for key in data:
self.assertEqual(saved[key], data[key]) assert saved[key] == data[key]
@ddt.data("", " ") @ddt.data("", " ")
def test_update_empty_string(self, value): def test_update_empty_string(self, value):
@@ -590,11 +572,10 @@ class ThreadSerializerDeserializationTest(
partial=True, partial=True,
context=get_context(self.course, self.request) context=get_context(self.course, self.request)
) )
self.assertFalse(serializer.is_valid()) assert not serializer.is_valid()
self.assertEqual( assert serializer.errors == {
serializer.errors, field: ['This field may not be blank.'] for field in ['topic_id', 'title', 'raw_body']
{field: ["This field may not be blank."] for field in ["topic_id", "title", "raw_body"]} }
)
def test_update_course_id(self): def test_update_course_id(self):
serializer = ThreadSerializer( serializer = ThreadSerializer(
@@ -603,11 +584,8 @@ class ThreadSerializerDeserializationTest(
partial=True, partial=True,
context=get_context(self.course, self.request) context=get_context(self.course, self.request)
) )
self.assertFalse(serializer.is_valid()) assert not serializer.is_valid()
self.assertEqual( assert serializer.errors == {'course_id': ['This field is not allowed in an update.']}
serializer.errors,
{"course_id": ["This field is not allowed in an update."]}
)
@ddt.ddt @ddt.ddt
@@ -657,7 +635,7 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
partial=(instance is not None), partial=(instance is not None),
context=context context=context
) )
self.assertTrue(serializer.is_valid()) assert serializer.is_valid()
serializer.save() serializer.save()
return serializer.data return serializer.data
@@ -677,17 +655,14 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
"/api/v1/comments/{}".format(parent_id) if parent_id else "/api/v1/comments/{}".format(parent_id) if parent_id else
"/api/v1/threads/test_thread/comments" "/api/v1/threads/test_thread/comments"
) )
self.assertEqual(urlparse(httpretty.last_request().path).path, expected_url) # lint-amnesty, pylint: disable=no-member assert urlparse(httpretty.last_request().path).path == expected_url # lint-amnesty, pylint: disable=no-member
self.assertEqual( assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member 'course_id': [six.text_type(self.course.id)],
{ 'body': ['Test body'],
"course_id": [six.text_type(self.course.id)], 'user_id': [str(self.user.id)]
"body": ["Test body"], }
"user_id": [str(self.user.id)], assert saved['id'] == 'test_comment'
} assert saved['parent_id'] == parent_id
)
self.assertEqual(saved["id"], "test_comment")
self.assertEqual(saved["parent_id"], parent_id)
def test_create_all_fields(self): def test_create_all_fields(self):
data = self.minimal_data.copy() data = self.minimal_data.copy()
@@ -700,15 +675,12 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
parent_id="test_parent" parent_id="test_parent"
) )
self.save_and_reserialize(data) self.save_and_reserialize(data)
self.assertEqual( assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member 'course_id': [six.text_type(self.course.id)],
{ 'body': ['Test body'],
"course_id": [six.text_type(self.course.id)], 'user_id': [str(self.user.id)],
"body": ["Test body"], 'endorsed': ['True']
"user_id": [str(self.user.id)], }
"endorsed": ["True"],
}
)
def test_create_parent_id_nonexistent(self): def test_create_parent_id_nonexistent(self):
self.register_get_comment_error_response("bad_parent", 404) self.register_get_comment_error_response("bad_parent", 404)
@@ -716,15 +688,10 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
data["parent_id"] = "bad_parent" data["parent_id"] = "bad_parent"
context = get_context(self.course, self.request, make_minimal_cs_thread()) context = get_context(self.course, self.request, make_minimal_cs_thread())
serializer = CommentSerializer(data=data, context=context) serializer = CommentSerializer(data=data, context=context)
self.assertFalse(serializer.is_valid()) assert not serializer.is_valid()
self.assertEqual( assert serializer.errors == {
serializer.errors, 'non_field_errors': ['parent_id does not identify a comment in the thread identified by thread_id.']
{ }
"non_field_errors": [
"parent_id does not identify a comment in the thread identified by thread_id."
]
}
)
def test_create_parent_id_wrong_thread(self): def test_create_parent_id_wrong_thread(self):
self.register_get_comment_response({"thread_id": "different_thread", "id": "test_parent"}) self.register_get_comment_response({"thread_id": "different_thread", "id": "test_parent"})
@@ -732,15 +699,10 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
data["parent_id"] = "test_parent" data["parent_id"] = "test_parent"
context = get_context(self.course, self.request, make_minimal_cs_thread()) context = get_context(self.course, self.request, make_minimal_cs_thread())
serializer = CommentSerializer(data=data, context=context) serializer = CommentSerializer(data=data, context=context)
self.assertFalse(serializer.is_valid()) assert not serializer.is_valid()
self.assertEqual( assert serializer.errors == {
serializer.errors, 'non_field_errors': ['parent_id does not identify a comment in the thread identified by thread_id.']
{ }
"non_field_errors": [
"parent_id does not identify a comment in the thread identified by thread_id."
]
}
)
@ddt.data(None, -1, 0, 2, 5) @ddt.data(None, -1, 0, 2, 5)
def test_create_parent_id_too_deep(self, max_depth): def test_create_parent_id_too_deep(self, max_depth):
@@ -758,7 +720,7 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
else: else:
data["parent_id"] = None data["parent_id"] = None
serializer = CommentSerializer(data=data, context=context) serializer = CommentSerializer(data=data, context=context)
self.assertTrue(serializer.is_valid(), serializer.errors) assert serializer.is_valid(), serializer.errors
if max_depth is not None: if max_depth is not None:
if max_depth >= 0: if max_depth >= 0:
self.register_get_comment_response({ self.register_get_comment_response({
@@ -770,8 +732,8 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
else: else:
data["parent_id"] = None data["parent_id"] = None
serializer = CommentSerializer(data=data, context=context) serializer = CommentSerializer(data=data, context=context)
self.assertFalse(serializer.is_valid()) assert not serializer.is_valid()
self.assertEqual(serializer.errors, {"non_field_errors": ["Comment level is too deep."]}) assert serializer.errors == {'non_field_errors': ['Comment level is too deep.']}
def test_create_missing_field(self): def test_create_missing_field(self):
for field in self.minimal_data: for field in self.minimal_data:
@@ -781,11 +743,8 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
data=data, data=data,
context=get_context(self.course, self.request, make_minimal_cs_thread()) context=get_context(self.course, self.request, make_minimal_cs_thread())
) )
self.assertFalse(serializer.is_valid()) assert not serializer.is_valid()
self.assertEqual( assert serializer.errors == {field: ['This field is required.']}
serializer.errors,
{field: ["This field is required."]}
)
def test_create_endorsed(self): def test_create_endorsed(self):
# TODO: The comments service doesn't populate the endorsement field on # TODO: The comments service doesn't populate the endorsement field on
@@ -794,34 +753,28 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
data = self.minimal_data.copy() data = self.minimal_data.copy()
data["endorsed"] = True data["endorsed"] = True
saved = self.save_and_reserialize(data) saved = self.save_and_reserialize(data)
self.assertEqual( assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member 'course_id': [six.text_type(self.course.id)],
{ 'body': ['Test body'],
"course_id": [six.text_type(self.course.id)], 'user_id': [str(self.user.id)],
"body": ["Test body"], 'endorsed': ['True']
"user_id": [str(self.user.id)], }
"endorsed": ["True"], assert saved['endorsed']
} assert saved['endorsed_by'] is None
) assert saved['endorsed_by_label'] is None
self.assertTrue(saved["endorsed"]) assert saved['endorsed_at'] is None
self.assertIsNone(saved["endorsed_by"])
self.assertIsNone(saved["endorsed_by_label"])
self.assertIsNone(saved["endorsed_at"])
def test_update_empty(self): def test_update_empty(self):
self.register_put_comment_response(self.existing_comment.attributes) self.register_put_comment_response(self.existing_comment.attributes)
self.save_and_reserialize({}, instance=self.existing_comment) self.save_and_reserialize({}, instance=self.existing_comment)
self.assertEqual( assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member 'body': ['Original body'],
{ 'course_id': [six.text_type(self.course.id)],
"body": ["Original body"], 'user_id': [str(self.user.id)],
"course_id": [six.text_type(self.course.id)], 'anonymous': ['False'],
"user_id": [str(self.user.id)], 'anonymous_to_peers': ['False'],
"anonymous": ["False"], 'endorsed': ['False']
"anonymous_to_peers": ["False"], }
"endorsed": ["False"],
}
)
def test_update_all(self): def test_update_all(self):
cs_response_data = self.existing_comment.attributes.copy() cs_response_data = self.existing_comment.attributes.copy()
@@ -832,22 +785,19 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
self.register_put_comment_response(cs_response_data) self.register_put_comment_response(cs_response_data)
data = {"raw_body": "Edited body", "endorsed": True} data = {"raw_body": "Edited body", "endorsed": True}
saved = self.save_and_reserialize(data, instance=self.existing_comment) saved = self.save_and_reserialize(data, instance=self.existing_comment)
self.assertEqual( assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member 'body': ['Edited body'],
{ 'course_id': [six.text_type(self.course.id)],
"body": ["Edited body"], 'user_id': [str(self.user.id)],
"course_id": [six.text_type(self.course.id)], 'anonymous': ['False'],
"user_id": [str(self.user.id)], 'anonymous_to_peers': ['False'],
"anonymous": ["False"], 'endorsed': ['True'],
"anonymous_to_peers": ["False"], 'endorsement_user_id': [str(self.user.id)]
"endorsed": ["True"], }
"endorsement_user_id": [str(self.user.id)],
}
)
for key in data: for key in data:
self.assertEqual(saved[key], data[key]) assert saved[key] == data[key]
self.assertEqual(saved["endorsed_by"], self.user.username) assert saved['endorsed_by'] == self.user.username
self.assertEqual(saved["endorsed_at"], "2015-06-05T00:00:00Z") assert saved['endorsed_at'] == '2015-06-05T00:00:00Z'
@ddt.data("", " ") @ddt.data("", " ")
def test_update_empty_raw_body(self, value): def test_update_empty_raw_body(self, value):
@@ -857,11 +807,8 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
partial=True, partial=True,
context=get_context(self.course, self.request) context=get_context(self.course, self.request)
) )
self.assertFalse(serializer.is_valid()) assert not serializer.is_valid()
self.assertEqual( assert serializer.errors == {'raw_body': ['This field may not be blank.']}
serializer.errors,
{"raw_body": ["This field may not be blank."]}
)
@ddt.data("thread_id", "parent_id") @ddt.data("thread_id", "parent_id")
def test_update_non_updatable(self, field): def test_update_non_updatable(self, field):
@@ -871,8 +818,5 @@ class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMoc
partial=True, partial=True,
context=get_context(self.course, self.request) context=get_context(self.course, self.request)
) )
self.assertFalse(serializer.is_valid()) assert not serializer.is_valid()
self.assertEqual( assert serializer.errors == {field: ['This field is not allowed in an update.']}
serializer.errors,
{field: ["This field is not allowed in an update."]}
)

View File

@@ -82,9 +82,9 @@ class DiscussionAPIViewTestMixin(ForumsEnableMixin, CommentsServiceMockMixin, Ur
""" """
Assert that the response has the given status code and parsed content Assert that the response has the given status code and parsed content
""" """
self.assertEqual(response.status_code, expected_status) assert response.status_code == expected_status
parsed_content = json.loads(response.content.decode('utf-8')) parsed_content = json.loads(response.content.decode('utf-8'))
self.assertEqual(parsed_content, expected_content) assert parsed_content == expected_content
def register_thread(self, overrides=None): def register_thread(self, overrides=None):
""" """
@@ -190,10 +190,10 @@ class RetireViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
""" """
Assert that the response has the given status code and content Assert that the response has the given status code and content
""" """
self.assertEqual(response.status_code, expected_status) assert response.status_code == expected_status
if expected_content: if expected_content:
self.assertEqual(response.content.decode('utf-8'), expected_content) assert response.content.decode('utf-8') == expected_content
def build_jwt_headers(self, user): def build_jwt_headers(self, user):
""" """
@@ -258,10 +258,10 @@ class ReplaceUsernamesViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
""" """
Assert that the response has the given status code and content Assert that the response has the given status code and content
""" """
self.assertEqual(response.status_code, expected_status) assert response.status_code == expected_status
if expected_content: if expected_content:
self.assertEqual(text_type(response.content), expected_content) assert text_type(response.content) == expected_content
def build_jwt_headers(self, user): def build_jwt_headers(self, user):
""" """
@@ -288,7 +288,7 @@ class ReplaceUsernamesViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
"username_mappings": mapping_data "username_mappings": mapping_data
} }
response = self.call_api(self.client_user, data) response = self.call_api(self.client_user, data)
self.assertEqual(response.status_code, 400) assert response.status_code == 400
def test_auth(self): def test_auth(self):
""" Verify the endpoint only works with the service worker """ """ Verify the endpoint only works with the service worker """
@@ -301,16 +301,16 @@ class ReplaceUsernamesViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
# Test unauthenticated # Test unauthenticated
response = self.client.post(self.url, data) response = self.client.post(self.url, data)
self.assertEqual(response.status_code, 401) assert response.status_code == 401
# Test non-service worker # Test non-service worker
random_user = UserFactory() random_user = UserFactory()
response = self.call_api(random_user, data) response = self.call_api(random_user, data)
self.assertEqual(response.status_code, 403) assert response.status_code == 403
# Test service worker # Test service worker
response = self.call_api(self.client_user, data) response = self.call_api(self.client_user, data)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
def test_basic(self): def test_basic(self):
""" Check successful replacement """ """ Check successful replacement """
@@ -325,8 +325,8 @@ class ReplaceUsernamesViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
} }
self.register_get_username_replacement_response(self.user) self.register_get_username_replacement_response(self.user)
response = self.call_api(self.client_user, data) response = self.call_api(self.client_user, data)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertEqual(response.data, expected_response) assert response.data == expected_response
def test_not_authenticated(self): def test_not_authenticated(self):
""" """
@@ -663,10 +663,9 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
200, 200,
expected_response expected_response
) )
self.assertEqual( assert urlparse(
urlparse(httpretty.last_request().path).path, # lint-amnesty, pylint: disable=no-member httpretty.last_request().path # lint-amnesty, pylint: disable=no-member
"/api/v1/users/{}/subscribed_threads".format(self.user.id) ).path == '/api/v1/users/{}/subscribed_threads'.format(self.user.id)
)
@ddt.data(False, "false", "0") @ddt.data(False, "false", "0")
def test_following_false(self, following): def test_following_false(self, following):
@@ -798,13 +797,13 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
self.url, self.url,
{"course_id": text_type(self.course.id), "requested_fields": "profile_image"}, {"course_id": text_type(self.course.id), "requested_fields": "profile_image"},
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_threads = json.loads(response.content.decode('utf-8'))['results'] response_threads = json.loads(response.content.decode('utf-8'))['results']
for response_thread in response_threads: for response_thread in response_threads:
expected_profile_data = self.get_expected_user_profile(response_thread['author']) expected_profile_data = self.get_expected_user_profile(response_thread['author'])
response_users = response_thread['users'] response_users = response_thread['users']
self.assertEqual(expected_profile_data, response_users[response_thread['author']]) assert expected_profile_data == response_users[response_thread['author']]
def test_profile_image_requested_field_anonymous_user(self): def test_profile_image_requested_field_anonymous_user(self):
""" """
@@ -823,10 +822,10 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro
self.url, self.url,
{"course_id": text_type(self.course.id), "requested_fields": "profile_image"}, {"course_id": text_type(self.course.id), "requested_fields": "profile_image"},
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_thread = json.loads(response.content.decode('utf-8'))['results'][0] response_thread = json.loads(response.content.decode('utf-8'))['results'][0]
self.assertIsNone(response_thread['author']) assert response_thread['author'] is None
self.assertEqual({}, response_thread['users']) assert {} == response_thread['users']
@httpretty.activate @httpretty.activate
@@ -858,20 +857,17 @@ class ThreadViewSetCreateTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
json.dumps(request_data), json.dumps(request_data),
content_type="application/json" content_type="application/json"
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertEqual(response_data, self.expected_thread_data({"read": True})) assert response_data == self.expected_thread_data({'read': True})
self.assertEqual( assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member 'course_id': [text_type(self.course.id)],
{ 'commentable_id': ['test_topic'],
"course_id": [text_type(self.course.id)], 'thread_type': ['discussion'],
"commentable_id": ["test_topic"], 'title': ['Test Title'],
"thread_type": ["discussion"], 'body': ['Test body'],
"title": ["Test Title"], 'user_id': [str(self.user.id)]
"body": ["Test body"], }
"user_id": [str(self.user.id)],
}
)
def test_error(self): def test_error(self):
request_data = { request_data = {
@@ -888,9 +884,9 @@ class ThreadViewSetCreateTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
expected_response_data = { expected_response_data = {
"field_errors": {"course_id": {"developer_message": "This field is required."}} "field_errors": {"course_id": {"developer_message": "This field is required."}}
} }
self.assertEqual(response.status_code, 400) assert response.status_code == 400
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertEqual(response_data, expected_response_data) assert response_data == expected_response_data
@ddt.ddt @ddt.ddt
@@ -914,39 +910,31 @@ class ThreadViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTest
}) })
request_data = {"raw_body": "Edited body"} request_data = {"raw_body": "Edited body"}
response = self.request_patch(request_data) response = self.request_patch(request_data)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertEqual( assert response_data == self.expected_thread_data({
response_data, 'raw_body': 'Edited body',
self.expected_thread_data({ 'rendered_body': '<p>Edited body</p>',
"raw_body": "Edited body", 'editable_fields': ['abuse_flagged', 'following', 'raw_body', 'read', 'title', 'topic_id', 'type', 'voted'],
"rendered_body": "<p>Edited body</p>", 'created_at': 'Test Created Date',
"editable_fields": [ 'updated_at': 'Test Updated Date',
"abuse_flagged", "following", "raw_body", "read", "title", "topic_id", "type", "voted" 'comment_count': 1,
], 'read': True,
"created_at": "Test Created Date", 'response_count': 2
"updated_at": "Test Updated Date", })
"comment_count": 1, assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
"read": True, 'course_id': [text_type(self.course.id)],
"response_count": 2, 'commentable_id': ['test_topic'],
}) 'thread_type': ['discussion'],
) 'title': ['Test Title'],
self.assertEqual( 'body': ['Edited body'],
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member 'user_id': [str(self.user.id)],
{ 'anonymous': ['False'],
"course_id": [text_type(self.course.id)], 'anonymous_to_peers': ['False'],
"commentable_id": ["test_topic"], 'closed': ['False'],
"thread_type": ["discussion"], 'pinned': ['False'],
"title": ["Test Title"], 'read': ['True']
"body": ["Edited body"], }
"user_id": [str(self.user.id)],
"anonymous": ["False"],
"anonymous_to_peers": ["False"],
"closed": ["False"],
"pinned": ["False"],
"read": ["True"],
}
)
def test_error(self): def test_error(self):
self.register_get_user_response(self.user) self.register_get_user_response(self.user)
@@ -956,9 +944,9 @@ class ThreadViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTest
expected_response_data = { expected_response_data = {
"field_errors": {"title": {"developer_message": "This field may not be blank."}} "field_errors": {"title": {"developer_message": "This field may not be blank."}}
} }
self.assertEqual(response.status_code, 400) assert response.status_code == 400
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertEqual(response_data, expected_response_data) assert response_data == expected_response_data
@ddt.data( @ddt.data(
("abuse_flagged", True), ("abuse_flagged", True),
@@ -971,19 +959,15 @@ class ThreadViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTest
self.register_flag_response("thread", "test_thread") self.register_flag_response("thread", "test_thread")
request_data = {field: value} request_data = {field: value}
response = self.request_patch(request_data) response = self.request_patch(request_data)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertEqual( assert response_data == self.expected_thread_data({
response_data, 'read': True,
self.expected_thread_data({ 'closed': True,
"read": True, 'abuse_flagged': value,
"closed": True, 'editable_fields': ['abuse_flagged', 'read'],
"abuse_flagged": value, 'comment_count': 1, 'unread_comment_count': 0
"editable_fields": ["abuse_flagged", "read"], })
"comment_count": 1,
"unread_comment_count": 0,
})
)
@ddt.data( @ddt.data(
("raw_body", "Edited body"), ("raw_body", "Edited body"),
@@ -997,7 +981,7 @@ class ThreadViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTest
self.register_flag_response("thread", "test_thread") self.register_flag_response("thread", "test_thread")
request_data = {field: value} request_data = {field: value}
response = self.request_patch(request_data) response = self.request_patch(request_data)
self.assertEqual(response.status_code, 400) assert response.status_code == 400
def test_patch_read_owner_user(self): def test_patch_read_owner_user(self):
self.register_get_user_response(self.user) self.register_get_user_response(self.user)
@@ -1006,19 +990,14 @@ class ThreadViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTest
request_data = {"read": True} request_data = {"read": True}
response = self.request_patch(request_data) response = self.request_patch(request_data)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertEqual( assert response_data == self.expected_thread_data({
response_data, 'comment_count': 1,
self.expected_thread_data({ 'read': True,
"comment_count": 1, 'editable_fields': ['abuse_flagged', 'following', 'raw_body', 'read', 'title', 'topic_id', 'type', 'voted'],
"read": True, 'response_count': 2
"editable_fields": [ })
"abuse_flagged", "following", "raw_body", "read", "title", "topic_id", "type", "voted"
],
"response_count": 2,
})
)
def test_patch_read_non_owner_user(self): def test_patch_read_non_owner_user(self):
self.register_get_user_response(self.user) self.register_get_user_response(self.user)
@@ -1034,20 +1013,15 @@ class ThreadViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTest
request_data = {"read": True} request_data = {"read": True}
response = self.request_patch(request_data) response = self.request_patch(request_data)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertEqual( assert response_data == self.expected_thread_data({
response_data, 'author': str(thread_owner_user.username),
self.expected_thread_data({ 'comment_count': 1,
"author": str(thread_owner_user.username), 'read': True,
"comment_count": 1, 'editable_fields': ['abuse_flagged', 'following', 'read', 'voted'],
"read": True, 'response_count': 2
"editable_fields": [ })
"abuse_flagged", "following", "read", "voted"
],
"response_count": 2,
})
)
@httpretty.activate @httpretty.activate
@@ -1071,18 +1045,15 @@ class ThreadViewSetDeleteTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
self.register_get_thread_response(cs_thread) self.register_get_thread_response(cs_thread)
self.register_delete_thread_response(self.thread_id) self.register_delete_thread_response(self.thread_id)
response = self.client.delete(self.url) response = self.client.delete(self.url)
self.assertEqual(response.status_code, 204) assert response.status_code == 204
self.assertEqual(response.content, b"") assert response.content == b''
self.assertEqual( assert urlparse(httpretty.last_request().path).path == '/api/v1/threads/{}'.format(self.thread_id) # lint-amnesty, pylint: disable=no-member
urlparse(httpretty.last_request().path).path, # lint-amnesty, pylint: disable=no-member assert httpretty.last_request().method == 'DELETE'
"/api/v1/threads/{}".format(self.thread_id)
)
self.assertEqual(httpretty.last_request().method, "DELETE")
def test_delete_nonexistent_thread(self): def test_delete_nonexistent_thread(self):
self.register_get_thread_error_response(self.thread_id, 404) self.register_get_thread_error_response(self.thread_id, 404)
response = self.client.delete(self.url) response = self.client.delete(self.url)
self.assertEqual(response.status_code, 404) assert response.status_code == 404
@ddt.ddt @ddt.ddt
@@ -1277,7 +1248,7 @@ class CommentViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pr
"endorsed": endorsed, "endorsed": endorsed,
}) })
parsed_content = json.loads(response.content.decode('utf-8')) parsed_content = json.loads(response.content.decode('utf-8'))
self.assertEqual(parsed_content["results"][0]["id"], comment_id) assert parsed_content['results'][0]['id'] == comment_id
def test_question_invalid_endorsed(self): def test_question_invalid_endorsed(self):
response = self.client.get(self.url, { response = self.client.get(self.url, {
@@ -1374,12 +1345,12 @@ class CommentViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pr
self.create_profile_image(self.user, get_profile_image_storage()) self.create_profile_image(self.user, get_profile_image_storage())
response = self.client.get(self.url, {"thread_id": self.thread_id, "requested_fields": "profile_image"}) response = self.client.get(self.url, {"thread_id": self.thread_id, "requested_fields": "profile_image"})
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_comments = json.loads(response.content.decode('utf-8'))['results'] response_comments = json.loads(response.content.decode('utf-8'))['results']
for response_comment in response_comments: for response_comment in response_comments:
expected_profile_data = self.get_expected_user_profile(response_comment['author']) expected_profile_data = self.get_expected_user_profile(response_comment['author'])
response_users = response_comment['users'] response_users = response_comment['users']
self.assertEqual(expected_profile_data, response_users[response_comment['author']]) assert expected_profile_data == response_users[response_comment['author']]
def test_profile_image_requested_field_endorsed_comments(self): def test_profile_image_requested_field_endorsed_comments(self):
""" """
@@ -1417,14 +1388,14 @@ class CommentViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pr
"endorsed": True, "endorsed": True,
"requested_fields": "profile_image", "requested_fields": "profile_image",
}) })
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_comments = json.loads(response.content.decode('utf-8'))['results'] response_comments = json.loads(response.content.decode('utf-8'))['results']
for response_comment in response_comments: for response_comment in response_comments:
expected_author_profile_data = self.get_expected_user_profile(response_comment['author']) expected_author_profile_data = self.get_expected_user_profile(response_comment['author'])
expected_endorser_profile_data = self.get_expected_user_profile(response_comment['endorsed_by']) expected_endorser_profile_data = self.get_expected_user_profile(response_comment['endorsed_by'])
response_users = response_comment['users'] response_users = response_comment['users']
self.assertEqual(expected_author_profile_data, response_users[response_comment['author']]) assert expected_author_profile_data == response_users[response_comment['author']]
self.assertEqual(expected_endorser_profile_data, response_users[response_comment['endorsed_by']]) assert expected_endorser_profile_data == response_users[response_comment['endorsed_by']]
def test_profile_image_request_for_null_endorsed_by(self): def test_profile_image_request_for_null_endorsed_by(self):
""" """
@@ -1450,13 +1421,13 @@ class CommentViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pr
"endorsed": True, "endorsed": True,
"requested_fields": "profile_image", "requested_fields": "profile_image",
}) })
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_comments = json.loads(response.content.decode('utf-8'))['results'] response_comments = json.loads(response.content.decode('utf-8'))['results']
for response_comment in response_comments: for response_comment in response_comments:
expected_author_profile_data = self.get_expected_user_profile(response_comment['author']) expected_author_profile_data = self.get_expected_user_profile(response_comment['author'])
response_users = response_comment['users'] response_users = response_comment['users']
self.assertEqual(expected_author_profile_data, response_users[response_comment['author']]) assert expected_author_profile_data == response_users[response_comment['author']]
self.assertNotIn(response_comment['endorsed_by'], response_users) assert response_comment['endorsed_by'] not in response_users
@httpretty.activate @httpretty.activate
@@ -1487,18 +1458,15 @@ class CommentViewSetDeleteTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
self.register_get_comment_response(cs_comment) self.register_get_comment_response(cs_comment)
self.register_delete_comment_response(self.comment_id) self.register_delete_comment_response(self.comment_id)
response = self.client.delete(self.url) response = self.client.delete(self.url)
self.assertEqual(response.status_code, 204) assert response.status_code == 204
self.assertEqual(response.content, b"") assert response.content == b''
self.assertEqual( assert urlparse(httpretty.last_request().path).path == '/api/v1/comments/{}'.format(self.comment_id) # lint-amnesty, pylint: disable=no-member
urlparse(httpretty.last_request().path).path, # lint-amnesty, pylint: disable=no-member assert httpretty.last_request().method == 'DELETE'
"/api/v1/comments/{}".format(self.comment_id)
)
self.assertEqual(httpretty.last_request().method, "DELETE")
def test_delete_nonexistent_comment(self): def test_delete_nonexistent_comment(self):
self.register_get_comment_error_response(self.comment_id, 404) self.register_get_comment_error_response(self.comment_id, 404)
response = self.client.delete(self.url) response = self.client.delete(self.url)
self.assertEqual(response.status_code, 404) assert response.status_code == 404
@httpretty.activate @httpretty.activate
@@ -1544,21 +1512,15 @@ class CommentViewSetCreateTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
json.dumps(request_data), json.dumps(request_data),
content_type="application/json" content_type="application/json"
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertEqual(response_data, expected_response_data) assert response_data == expected_response_data
self.assertEqual( assert urlparse(httpretty.last_request().path).path == '/api/v1/threads/test_thread/comments' # lint-amnesty, pylint: disable=no-member
urlparse(httpretty.last_request().path).path, # lint-amnesty, pylint: disable=no-member assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
"/api/v1/threads/test_thread/comments" 'course_id': [text_type(self.course.id)],
) 'body': ['Test body'],
self.assertEqual( 'user_id': [str(self.user.id)]
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member }
{
"course_id": [text_type(self.course.id)],
"body": ["Test body"],
"user_id": [str(self.user.id)],
}
)
def test_error(self): def test_error(self):
response = self.client.post( response = self.client.post(
@@ -1569,9 +1531,9 @@ class CommentViewSetCreateTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
expected_response_data = { expected_response_data = {
"field_errors": {"thread_id": {"developer_message": "This field is required."}} "field_errors": {"thread_id": {"developer_message": "This field is required."}}
} }
self.assertEqual(response.status_code, 400) assert response.status_code == 400
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertEqual(response_data, expected_response_data) assert response_data == expected_response_data
def test_closed_thread(self): def test_closed_thread(self):
self.register_get_user_response(self.user) self.register_get_user_response(self.user)
@@ -1586,7 +1548,7 @@ class CommentViewSetCreateTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
json.dumps(request_data), json.dumps(request_data),
content_type="application/json" content_type="application/json"
) )
self.assertEqual(response.status_code, 403) assert response.status_code == 403
@ddt.ddt @ddt.ddt
@@ -1637,29 +1599,23 @@ class CommentViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTes
self.register_comment({"created_at": "Test Created Date", "updated_at": "Test Updated Date"}) self.register_comment({"created_at": "Test Created Date", "updated_at": "Test Updated Date"})
request_data = {"raw_body": "Edited body"} request_data = {"raw_body": "Edited body"}
response = self.request_patch(request_data) response = self.request_patch(request_data)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertEqual( assert response_data == self.expected_response_data({
response_data, 'raw_body': 'Edited body',
self.expected_response_data({ 'rendered_body': '<p>Edited body</p>',
"raw_body": "Edited body", 'editable_fields': ['abuse_flagged', 'raw_body', 'voted'],
"rendered_body": "<p>Edited body</p>", 'created_at': 'Test Created Date',
"editable_fields": ["abuse_flagged", "raw_body", "voted"], 'updated_at': 'Test Updated Date'
"created_at": "Test Created Date", })
"updated_at": "Test Updated Date", assert httpretty.last_request().parsed_body == { # lint-amnesty, pylint: disable=no-member
}) 'body': ['Edited body'],
) 'course_id': [text_type(self.course.id)],
self.assertEqual( 'user_id': [str(self.user.id)],
httpretty.last_request().parsed_body, # lint-amnesty, pylint: disable=no-member 'anonymous': ['False'],
{ 'anonymous_to_peers': ['False'],
"body": ["Edited body"], 'endorsed': ['False']
"course_id": [text_type(self.course.id)], }
"user_id": [str(self.user.id)],
"anonymous": ["False"],
"anonymous_to_peers": ["False"],
"endorsed": ["False"],
}
)
def test_error(self): def test_error(self):
self.register_thread() self.register_thread()
@@ -1669,9 +1625,9 @@ class CommentViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTes
expected_response_data = { expected_response_data = {
"field_errors": {"raw_body": {"developer_message": "This field may not be blank."}} "field_errors": {"raw_body": {"developer_message": "This field may not be blank."}}
} }
self.assertEqual(response.status_code, 400) assert response.status_code == 400
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertEqual(response_data, expected_response_data) assert response_data == expected_response_data
@ddt.data( @ddt.data(
("abuse_flagged", True), ("abuse_flagged", True),
@@ -1684,15 +1640,12 @@ class CommentViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTes
self.register_flag_response("comment", "test_comment") self.register_flag_response("comment", "test_comment")
request_data = {field: value} request_data = {field: value}
response = self.request_patch(request_data) response = self.request_patch(request_data)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertEqual( assert response_data == self.expected_response_data({
response_data, 'abuse_flagged': value,
self.expected_response_data({ 'editable_fields': ['abuse_flagged']
"abuse_flagged": value, })
"editable_fields": ["abuse_flagged"],
})
)
@ddt.data( @ddt.data(
("raw_body", "Edited body"), ("raw_body", "Edited body"),
@@ -1705,7 +1658,7 @@ class CommentViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTes
self.register_comment() self.register_comment()
request_data = {field: value} request_data = {field: value}
response = self.request_patch(request_data) response = self.request_patch(request_data)
self.assertEqual(response.status_code, 400) assert response.status_code == 400
@httpretty.activate @httpretty.activate
@@ -1730,17 +1683,14 @@ class ThreadViewSetRetrieveTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase,
}) })
self.register_get_thread_response(cs_thread) self.register_get_thread_response(cs_thread)
response = self.client.get(self.url) response = self.client.get(self.url)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertEqual( assert json.loads(response.content.decode('utf-8')) == self.expected_thread_data({'unread_comment_count': 1})
json.loads(response.content.decode('utf-8')), assert httpretty.last_request().method == 'GET'
self.expected_thread_data({"unread_comment_count": 1})
)
self.assertEqual(httpretty.last_request().method, "GET")
def test_retrieve_nonexistent_thread(self): def test_retrieve_nonexistent_thread(self):
self.register_get_thread_error_response(self.thread_id, 404) self.register_get_thread_error_response(self.thread_id, 404)
response = self.client.get(self.url) response = self.client.get(self.url)
self.assertEqual(response.status_code, 404) assert response.status_code == 404
def test_profile_image_requested_field(self): def test_profile_image_requested_field(self):
""" """
@@ -1756,10 +1706,10 @@ class ThreadViewSetRetrieveTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase,
self.register_get_thread_response(cs_thread) self.register_get_thread_response(cs_thread)
self.create_profile_image(self.user, get_profile_image_storage()) self.create_profile_image(self.user, get_profile_image_storage())
response = self.client.get(self.url, {"requested_fields": "profile_image"}) response = self.client.get(self.url, {"requested_fields": "profile_image"})
self.assertEqual(response.status_code, 200) assert response.status_code == 200
expected_profile_data = self.get_expected_user_profile(self.user.username) expected_profile_data = self.get_expected_user_profile(self.user.username)
response_users = json.loads(response.content.decode('utf-8'))['users'] response_users = json.loads(response.content.decode('utf-8'))['users']
self.assertEqual(expected_profile_data, response_users[self.user.username]) assert expected_profile_data == response_users[self.user.username]
@httpretty.activate @httpretty.activate
@@ -1825,13 +1775,13 @@ class CommentViewSetRetrieveTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase
} }
response = self.client.get(self.url) response = self.client.get(self.url)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertEqual(json.loads(response.content.decode('utf-8'))['results'][0], expected_response_data) assert json.loads(response.content.decode('utf-8'))['results'][0] == expected_response_data
def test_retrieve_nonexistent_comment(self): def test_retrieve_nonexistent_comment(self):
self.register_get_comment_error_response(self.comment_id, 404) self.register_get_comment_error_response(self.comment_id, 404)
response = self.client.get(self.url) response = self.client.get(self.url)
self.assertEqual(response.status_code, 404) assert response.status_code == 404
def test_pagination(self): def test_pagination(self):
""" """
@@ -1876,13 +1826,13 @@ class CommentViewSetRetrieveTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase
self.create_profile_image(self.user, get_profile_image_storage()) self.create_profile_image(self.user, get_profile_image_storage())
response = self.client.get(self.url, {'requested_fields': 'profile_image'}) response = self.client.get(self.url, {'requested_fields': 'profile_image'})
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_comments = json.loads(response.content.decode('utf-8'))['results'] response_comments = json.loads(response.content.decode('utf-8'))['results']
for response_comment in response_comments: for response_comment in response_comments:
expected_profile_data = self.get_expected_user_profile(response_comment['author']) expected_profile_data = self.get_expected_user_profile(response_comment['author'])
response_users = response_comment['users'] response_users = response_comment['users']
self.assertEqual(expected_profile_data, response_users[response_comment['author']]) assert expected_profile_data == response_users[response_comment['author']]
@ddt.ddt @ddt.ddt
@@ -1959,14 +1909,14 @@ class CourseDiscussionSettingsAPIViewTest(APITestCase, UrlResetMixin, ModuleStor
def _assert_current_settings(self, expected_response): def _assert_current_settings(self, expected_response):
"""Validate the current discussion settings against the expected response.""" """Validate the current discussion settings against the expected response."""
response = self.client.get(self.path) response = self.client.get(self.path)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
content = json.loads(response.content.decode('utf-8')) content = json.loads(response.content.decode('utf-8'))
self.assertEqual(content, expected_response) assert content == expected_response
def _assert_patched_settings(self, data, expected_response): def _assert_patched_settings(self, data, expected_response):
"""Validate the patched settings against the expected response.""" """Validate the patched settings against the expected response."""
response = self.patch_request(data) response = self.patch_request(data)
self.assertEqual(response.status_code, 204) assert response.status_code == 204
self._assert_current_settings(expected_response) self._assert_current_settings(expected_response)
@ddt.data('get', 'patch') @ddt.data('get', 'patch')
@@ -1974,7 +1924,7 @@ class CourseDiscussionSettingsAPIViewTest(APITestCase, UrlResetMixin, ModuleStor
"""Test and verify that authentication is required for this endpoint.""" """Test and verify that authentication is required for this endpoint."""
self.client.logout() self.client.logout()
response = getattr(self.client, method)(self.path) response = getattr(self.client, method)(self.path)
self.assertEqual(response.status_code, 401) assert response.status_code == 401
@ddt.data( @ddt.data(
{'is_staff': False, 'get_status': 403, 'put_status': 403}, {'is_staff': False, 'get_status': 403, 'put_status': 403},
@@ -1988,12 +1938,12 @@ class CourseDiscussionSettingsAPIViewTest(APITestCase, UrlResetMixin, ModuleStor
self.client.logout() self.client.logout()
response = self.client.get(self.path, **headers) response = self.client.get(self.path, **headers)
self.assertEqual(response.status_code, get_status) assert response.status_code == get_status
response = self.patch_request( response = self.patch_request(
{'always_divide_inline_discussions': True}, headers {'always_divide_inline_discussions': True}, headers
) )
self.assertEqual(response.status_code, put_status) assert response.status_code == put_status
def test_non_existent_course_id(self): def test_non_existent_course_id(self):
"""Test the response when this endpoint is passed a non-existent course id.""" """Test the response when this endpoint is passed a non-existent course id."""
@@ -2003,14 +1953,14 @@ class CourseDiscussionSettingsAPIViewTest(APITestCase, UrlResetMixin, ModuleStor
'course_id': 'a/b/c' 'course_id': 'a/b/c'
}) })
) )
self.assertEqual(response.status_code, 404) assert response.status_code == 404
def test_get_settings(self): def test_get_settings(self):
"""Test the current discussion settings against the expected response.""" """Test the current discussion settings against the expected response."""
divided_inline_discussions, divided_course_wide_discussions = self._create_divided_discussions() divided_inline_discussions, divided_course_wide_discussions = self._create_divided_discussions()
self._login_as_staff() self._login_as_staff()
response = self.client.get(self.path) response = self.client.get(self.path)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
expected_response = self._get_expected_response() expected_response = self._get_expected_response()
expected_response['divided_course_wide_discussions'] = [ expected_response['divided_course_wide_discussions'] = [
topic_name_to_id(self.course, name) for name in divided_course_wide_discussions topic_name_to_id(self.course, name) for name in divided_course_wide_discussions
@@ -2019,7 +1969,7 @@ class CourseDiscussionSettingsAPIViewTest(APITestCase, UrlResetMixin, ModuleStor
topic_name_to_id(self.course, name) for name in divided_inline_discussions topic_name_to_id(self.course, name) for name in divided_inline_discussions
] ]
content = json.loads(response.content.decode('utf-8')) content = json.loads(response.content.decode('utf-8'))
self.assertEqual(content, expected_response) assert content == expected_response
def test_available_schemes(self): def test_available_schemes(self):
"""Test the available division schemes against the expected response.""" """Test the available division schemes against the expected response."""
@@ -2045,10 +1995,10 @@ class CourseDiscussionSettingsAPIViewTest(APITestCase, UrlResetMixin, ModuleStor
"""Test the response status code on sending a PATCH request with an empty body or missing fields.""" """Test the response status code on sending a PATCH request with an empty body or missing fields."""
self._login_as_staff() self._login_as_staff()
response = self.patch_request("") response = self.patch_request("")
self.assertEqual(response.status_code, 400) assert response.status_code == 400
response = self.patch_request({}) response = self.patch_request({})
self.assertEqual(response.status_code, 400) assert response.status_code == 400
@ddt.data( @ddt.data(
{'abc': 123}, {'abc': 123},
@@ -2061,7 +2011,7 @@ class CourseDiscussionSettingsAPIViewTest(APITestCase, UrlResetMixin, ModuleStor
"""Test the response status code on sending a PATCH request with parameters having incorrect types.""" """Test the response status code on sending a PATCH request with parameters having incorrect types."""
self._login_as_staff() self._login_as_staff()
response = self.patch_request(body) response = self.patch_request(body)
self.assertEqual(response.status_code, 400) assert response.status_code == 400
def test_update_always_divide_inline_discussion_settings(self): def test_update_always_divide_inline_discussion_settings(self):
"""Test whether the 'always_divide_inline_discussions' setting is updated.""" """Test whether the 'always_divide_inline_discussions' setting is updated."""
@@ -2194,17 +2144,17 @@ class CourseDiscussionRolesAPIViewTest(APITestCase, UrlResetMixin, ModuleStoreTe
"""Test and verify that authentication is required for this endpoint.""" """Test and verify that authentication is required for this endpoint."""
self.client.logout() self.client.logout()
response = getattr(self.client, method)(self.path()) response = getattr(self.client, method)(self.path())
self.assertEqual(response.status_code, 401) assert response.status_code == 401
def test_oauth(self): def test_oauth(self):
"""Test that OAuth authentication works for this endpoint.""" """Test that OAuth authentication works for this endpoint."""
oauth_headers = self._get_oauth_headers(self.user) oauth_headers = self._get_oauth_headers(self.user)
self.client.logout() self.client.logout()
response = self.client.get(self.path(), **oauth_headers) response = self.client.get(self.path(), **oauth_headers)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
body = {'user_id': 'staff', 'action': 'allow'} body = {'user_id': 'staff', 'action': 'allow'}
response = self.client.post(self.path(), body, format='json', **oauth_headers) response = self.client.post(self.path(), body, format='json', **oauth_headers)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
@ddt.data( @ddt.data(
{'username': 'u1', 'is_staff': False, 'expected_status': 403}, {'username': 'u1', 'is_staff': False, 'expected_status': 403},
@@ -2216,10 +2166,10 @@ class CourseDiscussionRolesAPIViewTest(APITestCase, UrlResetMixin, ModuleStoreTe
UserFactory(username=username, password='edx', is_staff=is_staff) UserFactory(username=username, password='edx', is_staff=is_staff)
self.client.login(username=username, password='edx') self.client.login(username=username, password='edx')
response = self.client.get(self.path()) response = self.client.get(self.path())
self.assertEqual(response.status_code, expected_status) assert response.status_code == expected_status
response = self.client.post(self.path(), {'user_id': username, 'action': 'allow'}, format='json') response = self.client.post(self.path(), {'user_id': username, 'action': 'allow'}, format='json')
self.assertEqual(response.status_code, expected_status) assert response.status_code == expected_status
def test_non_existent_course_id(self): def test_non_existent_course_id(self):
"""Test the response when the endpoint URL contains a non-existent course id.""" """Test the response when the endpoint URL contains a non-existent course id."""
@@ -2227,10 +2177,10 @@ class CourseDiscussionRolesAPIViewTest(APITestCase, UrlResetMixin, ModuleStoreTe
path = self.path(course_id='a/b/c') path = self.path(course_id='a/b/c')
response = self.client.get(path) response = self.client.get(path)
self.assertEqual(response.status_code, 404) assert response.status_code == 404
response = self.client.post(path) response = self.client.post(path)
self.assertEqual(response.status_code, 404) assert response.status_code == 404
def test_non_existent_course_role(self): def test_non_existent_course_role(self):
"""Test the response when the endpoint URL contains a non-existent role.""" """Test the response when the endpoint URL contains a non-existent role."""
@@ -2238,10 +2188,10 @@ class CourseDiscussionRolesAPIViewTest(APITestCase, UrlResetMixin, ModuleStoreTe
path = self.path(role='A') path = self.path(role='A')
response = self.client.get(path) response = self.client.get(path)
self.assertEqual(response.status_code, 400) assert response.status_code == 400
response = self.client.post(path) response = self.client.post(path)
self.assertEqual(response.status_code, 400) assert response.status_code == 400
@ddt.data( @ddt.data(
{'role': 'Moderator', 'count': 0}, {'role': 'Moderator', 'count': 0},
@@ -2259,22 +2209,22 @@ class CourseDiscussionRolesAPIViewTest(APITestCase, UrlResetMixin, ModuleStoreTe
self._login_as_staff() self._login_as_staff()
response = self.client.get(self.path(role=role)) response = self.client.get(self.path(role=role))
self.assertEqual(response.status_code, 200) assert response.status_code == 200
content = json.loads(response.content.decode('utf-8')) content = json.loads(response.content.decode('utf-8'))
self.assertEqual(content['course_id'], 'x/y/z') assert content['course_id'] == 'x/y/z'
self.assertEqual(len(content['results']), count) assert len(content['results']) == count
expected_fields = ('username', 'email', 'first_name', 'last_name', 'group_name') expected_fields = ('username', 'email', 'first_name', 'last_name', 'group_name')
for item in content['results']: for item in content['results']:
for expected_field in expected_fields: for expected_field in expected_fields:
self.assertIn(expected_field, item) assert expected_field in item
self.assertEqual(content['division_scheme'], 'cohort') assert content['division_scheme'] == 'cohort'
def test_post_missing_body(self): def test_post_missing_body(self):
"""Test the response with a POST request without a body.""" """Test the response with a POST request without a body."""
self._login_as_staff() self._login_as_staff()
response = self.client.post(self.path()) response = self.client.post(self.path())
self.assertEqual(response.status_code, 400) assert response.status_code == 400
@ddt.data( @ddt.data(
{'a': 1}, {'a': 1},
@@ -2288,10 +2238,10 @@ class CourseDiscussionRolesAPIViewTest(APITestCase, UrlResetMixin, ModuleStoreTe
""" """
self._login_as_staff() self._login_as_staff()
response = self.client.post(self.path(), body) response = self.client.post(self.path(), body)
self.assertEqual(response.status_code, 400) assert response.status_code == 400
response = self.client.post(self.path(), body, format='json') response = self.client.post(self.path(), body, format='json')
self.assertEqual(response.status_code, 400) assert response.status_code == 400
@ddt.data( @ddt.data(
{'action': 'allow', 'user_in_role': False}, {'action': 'allow', 'user_in_role': False},
@@ -2309,7 +2259,7 @@ class CourseDiscussionRolesAPIViewTest(APITestCase, UrlResetMixin, ModuleStoreTe
self._add_users_to_role(users, role) self._add_users_to_role(users, role)
response = self.post(role, user.username, action) response = self.post(role, user.username, action)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
content = json.loads(response.content.decode('utf-8')) content = json.loads(response.content.decode('utf-8'))
assertion = self.assertTrue if action == 'allow' else self.assertFalse assertion = self.assertTrue if action == 'allow' else self.assertFalse
assertion(any(user.username in x['username'] for x in content['results'])) assertion(any(user.username in x['username'] for x in content['results']))

View File

@@ -359,7 +359,7 @@ class CommentsServiceMockMixin(object):
""" """
actual_params = dict(httpretty_request.querystring) actual_params = dict(httpretty_request.querystring)
actual_params.pop("request_id") # request_id is random actual_params.pop("request_id") # request_id is random
self.assertEqual(actual_params, expected_params) assert actual_params == expected_params
def assert_last_query_params(self, expected_params): def assert_last_query_params(self, expected_params):
""" """
@@ -519,12 +519,12 @@ class ProfileImageTestMixin(object):
""" """
for size, name in get_profile_image_names(user.username).items(): for size, name in get_profile_image_names(user.username).items():
if exist: if exist:
self.assertTrue(storage.exists(name)) assert storage.exists(name)
with closing(Image.open(storage.path(name))) as img: with closing(Image.open(storage.path(name))) as img:
self.assertEqual(img.size, (size, size)) assert img.size == (size, size)
self.assertEqual(img.format, 'JPEG') assert img.format == 'JPEG'
else: else:
self.assertFalse(storage.exists(name)) assert not storage.exists(name)
def get_expected_user_profile(self, username): def get_expected_user_profile(self, username):
""" """

View File

@@ -41,7 +41,7 @@ class SendMessageHandlerTestCase(TestCase): # lint-amnesty, pylint: disable=mis
def test_comment_created_signal_message_not_sent_without_site(self, mock_send_message, mock_get_current_site): # lint-amnesty, pylint: disable=unused-argument def test_comment_created_signal_message_not_sent_without_site(self, mock_send_message, mock_get_current_site): # lint-amnesty, pylint: disable=unused-argument
signals.comment_created.send(sender=self.sender, user=self.user, post=self.post) signals.comment_created.send(sender=self.sender, user=self.user, post=self.post)
self.assertFalse(mock_send_message.called) assert not mock_send_message.called
@mock.patch('lms.djangoapps.discussion.signals.handlers.get_current_site') @mock.patch('lms.djangoapps.discussion.signals.handlers.get_current_site')
@mock.patch('lms.djangoapps.discussion.signals.handlers.send_message') @mock.patch('lms.djangoapps.discussion.signals.handlers.send_message')
@@ -49,7 +49,7 @@ class SendMessageHandlerTestCase(TestCase): # lint-amnesty, pylint: disable=mis
mock_get_current_site.return_value = self.site mock_get_current_site.return_value = self.site
signals.comment_created.send(sender=self.sender, user=self.user, post=self.post) signals.comment_created.send(sender=self.sender, user=self.user, post=self.post)
self.assertFalse(mock_send_message.called) assert not mock_send_message.called
@mock.patch('lms.djangoapps.discussion.signals.handlers.get_current_site') @mock.patch('lms.djangoapps.discussion.signals.handlers.get_current_site')
@mock.patch('lms.djangoapps.discussion.signals.handlers.send_message') @mock.patch('lms.djangoapps.discussion.signals.handlers.send_message')
@@ -63,7 +63,7 @@ class SendMessageHandlerTestCase(TestCase): # lint-amnesty, pylint: disable=mis
mock_get_current_site.return_value = self.site mock_get_current_site.return_value = self.site
signals.comment_created.send(sender=self.sender, user=self.user, post=self.post) signals.comment_created.send(sender=self.sender, user=self.user, post=self.post)
self.assertFalse(mock_send_message.called) assert not mock_send_message.called
class CoursePublishHandlerTestCase(ModuleStoreTestCase): class CoursePublishHandlerTestCase(ModuleStoreTestCase):
@@ -78,7 +78,7 @@ class CoursePublishHandlerTestCase(ModuleStoreTestCase):
# create course # create course
course = CourseFactory(emit_signals=True, **course_key_args) course = CourseFactory(emit_signals=True, **course_key_args)
self.assertEqual(course.id, course_key) assert course.id == course_key
self._assert_discussion_id_map(course_key, {}) self._assert_discussion_id_map(course_key, {})
# create discussion block # create discussion block

View File

@@ -219,13 +219,13 @@ class TaskTestCase(ModuleStoreTestCase): # lint-amnesty, pylint: disable=missin
}) })
expected_recipient = Recipient(self.thread_author.username, self.thread_author.email) expected_recipient = Recipient(self.thread_author.username, self.thread_author.email)
actual_message = self.mock_ace_send.call_args_list[0][0][0] actual_message = self.mock_ace_send.call_args_list[0][0][0]
self.assertEqual(expected_message_context, actual_message.context) assert expected_message_context == actual_message.context
self.assertEqual(expected_recipient, actual_message.recipient) assert expected_recipient == actual_message.recipient
self.assertEqual(self.course.language, actual_message.language) assert self.course.language == actual_message.language
self._assert_rendered_email(actual_message) self._assert_rendered_email(actual_message)
else: else:
self.assertFalse(self.mock_ace_send.called) assert not self.mock_ace_send.called
def _assert_rendered_email(self, message): # lint-amnesty, pylint: disable=missing-function-docstring def _assert_rendered_email(self, message): # lint-amnesty, pylint: disable=missing-function-docstring
# check that we can actually render the message # check that we can actually render the message
@@ -257,8 +257,8 @@ class TaskTestCase(ModuleStoreTestCase): # lint-amnesty, pylint: disable=missin
'comment_id': comment_dict['id'], 'comment_id': comment_dict['id'],
'thread_id': thread['id'], 'thread_id': thread['id'],
}) })
self.assertEqual(actual_result, False) assert actual_result is False
self.assertFalse(self.mock_ace_send.called) assert not self.mock_ace_send.called
def test_subcomment_should_not_send_email(self): def test_subcomment_should_not_send_email(self):
self.run_should_not_send_email_test(self.thread, self.subcomment) self.run_should_not_send_email_test(self.thread, self.subcomment)

View File

@@ -123,7 +123,7 @@ class ViewsExceptionTestCase(UrlResetMixin, ModuleStoreTestCase): # lint-amnest
url = reverse('user_profile', url = reverse('user_profile',
kwargs={'course_id': text_type(self.course.id), 'user_id': '12345'}) # There is no user 12345 kwargs={'course_id': text_type(self.course.id), 'user_id': '12345'}) # There is no user 12345
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 404) assert response.status_code == 404
@patch('common.djangoapps.student.models.cc.User.from_django_user') @patch('common.djangoapps.student.models.cc.User.from_django_user')
@patch('common.djangoapps.student.models.cc.User.subscribed_threads') @patch('common.djangoapps.student.models.cc.User.subscribed_threads')
@@ -140,7 +140,7 @@ class ViewsExceptionTestCase(UrlResetMixin, ModuleStoreTestCase): # lint-amnest
url = reverse('followed_threads', url = reverse('followed_threads',
kwargs={'course_id': text_type(self.course.id), 'user_id': '12345'}) # There is no user 12345 kwargs={'course_id': text_type(self.course.id), 'user_id': '12345'}) # There is no user 12345
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 404) assert response.status_code == 404
def make_mock_thread_data( # lint-amnesty, pylint: disable=missing-function-docstring def make_mock_thread_data( # lint-amnesty, pylint: disable=missing-function-docstring
@@ -331,14 +331,16 @@ class SingleThreadTestCase(ForumsEnableMixin, ModuleStoreTestCase): # lint-amne
"test_thread_id" "test_thread_id"
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
# strip_none is being used to perform the same transform that the # strip_none is being used to perform the same transform that the
# django view performs prior to writing thread data to the response # django view performs prior to writing thread data to the response
self.assertEqual( assert response_data['content'] == strip_none(make_mock_thread_data(
response_data["content"], course=self.course,
strip_none(make_mock_thread_data(course=self.course, text=text, thread_id=thread_id, num_children=1)) text=text,
) thread_id=thread_id,
num_children=1
))
mock_request.assert_called_with( mock_request.assert_called_with(
"get", "get",
StringEndsWithMatcher(thread_id), # url StringEndsWithMatcher(thread_id), # url
@@ -367,14 +369,16 @@ class SingleThreadTestCase(ForumsEnableMixin, ModuleStoreTestCase): # lint-amne
"dummy_discussion_id", "dummy_discussion_id",
"test_thread_id" "test_thread_id"
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
# strip_none is being used to perform the same transform that the # strip_none is being used to perform the same transform that the
# django view performs prior to writing thread data to the response # django view performs prior to writing thread data to the response
self.assertEqual( assert response_data['content'] == strip_none(make_mock_thread_data(
response_data["content"], course=self.course,
strip_none(make_mock_thread_data(course=self.course, text=text, thread_id=thread_id, num_children=1)) text=text,
) thread_id=thread_id,
num_children=1
))
mock_request.assert_called_with( mock_request.assert_called_with(
"get", "get",
StringEndsWithMatcher(thread_id), # url StringEndsWithMatcher(thread_id), # url
@@ -398,7 +402,7 @@ class SingleThreadTestCase(ForumsEnableMixin, ModuleStoreTestCase): # lint-amne
"dummy_discussion_id", "dummy_discussion_id",
"dummy_thread_id" "dummy_thread_id"
) )
self.assertEqual(response.status_code, 405) assert response.status_code == 405
def test_not_found(self, mock_request): def test_not_found(self, mock_request):
request = RequestFactory().get("dummy_url") request = RequestFactory().get("dummy_url")
@@ -437,17 +441,14 @@ class SingleThreadTestCase(ForumsEnableMixin, ModuleStoreTestCase): # lint-amne
'thread_id': thread_id, 'thread_id': thread_id,
}) })
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertEqual(response['Content-Type'], 'text/html; charset=utf-8') assert response['Content-Type'] == 'text/html; charset=utf-8'
html = response.content.decode('utf-8') html = response.content.decode('utf-8')
# Verify that the access denied error message is in the HTML # Verify that the access denied error message is in the HTML
self.assertIn( assert 'This is a private discussion. You do not have permissions to view this discussion' in html
'This is a private discussion. You do not have permissions to view this discussion',
html
)
class AllowPlusOrMinusOneInt(int): class AllowPlusOrMinusOneInt(int): # pylint: disable=eq-without-hash
""" """
A workaround for the fact that assertNumQueries doesn't let you A workaround for the fact that assertNumQueries doesn't let you
specify a range or any tolerance. An 'int' that is 'equal to' its value, specify a range or any tolerance. An 'int' that is 'equal to' its value,
@@ -535,11 +536,8 @@ class SingleThreadQueryCountTestCase(ForumsEnableMixin, ModuleStoreTestCase):
"dummy_discussion_id", "dummy_discussion_id",
test_thread_id test_thread_id
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertEqual( assert len(json.loads(response.content.decode('utf-8'))['content']['children']) == num_thread_responses
len(json.loads(response.content.decode('utf-8'))["content"]["children"]),
num_thread_responses
)
# Test uncached first, then cached now that the cache is warm. # Test uncached first, then cached now that the cache is warm.
cached_calls = [ cached_calls = [
@@ -584,20 +582,17 @@ class SingleCohortedThreadTestCase(CohortedTestCase): # lint-amnesty, pylint: d
mock_thread_id mock_thread_id
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertEqual( assert response_data['content'] == make_mock_thread_data(
response_data["content"], course=self.course,
make_mock_thread_data( commentable_id='cohorted_topic',
course=self.course, text=mock_text,
commentable_id="cohorted_topic", thread_id=mock_thread_id,
text=mock_text, num_children=1,
thread_id=mock_thread_id, group_id=self.student_cohort.id,
num_children=1, group_name=self.student_cohort.name,
group_id=self.student_cohort.id, is_commentable_divided=True
group_name=self.student_cohort.name,
is_commentable_divided=True,
)
) )
def test_html(self, mock_request): def test_html(self, mock_request):
@@ -612,8 +607,8 @@ class SingleCohortedThreadTestCase(CohortedTestCase): # lint-amnesty, pylint: d
}) })
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertEqual(response['Content-Type'], 'text/html; charset=utf-8') assert response['Content-Type'] == 'text/html; charset=utf-8'
html = response.content.decode('utf-8') html = response.content.decode('utf-8')
# Verify that the group name is correctly included in the HTML # Verify that the group name is correctly included in the HTML
@@ -647,7 +642,7 @@ class SingleThreadAccessTestCase(CohortedTestCase): # lint-amnesty, pylint: dis
def test_student_non_cohorted(self, mock_request): def test_student_non_cohorted(self, mock_request):
resp = self.call_view(mock_request, "non_cohorted_topic", self.student, self.student_cohort.id) resp = self.call_view(mock_request, "non_cohorted_topic", self.student, self.student_cohort.id)
self.assertEqual(resp.status_code, 200) assert resp.status_code == 200
def test_student_same_cohort(self, mock_request): def test_student_same_cohort(self, mock_request):
resp = self.call_view( resp = self.call_view(
@@ -657,7 +652,7 @@ class SingleThreadAccessTestCase(CohortedTestCase): # lint-amnesty, pylint: dis
self.student_cohort.id, self.student_cohort.id,
thread_group_id=self.student_cohort.id thread_group_id=self.student_cohort.id
) )
self.assertEqual(resp.status_code, 200) assert resp.status_code == 200
# this test ensures that a thread response from the cs with group_id: null # this test ensures that a thread response from the cs with group_id: null
# behaves the same as a thread response without a group_id (see: TNL-444) # behaves the same as a thread response without a group_id (see: TNL-444)
@@ -669,23 +664,20 @@ class SingleThreadAccessTestCase(CohortedTestCase): # lint-amnesty, pylint: dis
self.student_cohort.id, self.student_cohort.id,
thread_group_id=None thread_group_id=None
) )
self.assertEqual(resp.status_code, 200) assert resp.status_code == 200
def test_student_different_cohort(self, mock_request): def test_student_different_cohort(self, mock_request):
self.assertRaises( pytest.raises(Http404, (lambda: self.call_view(
Http404, mock_request,
lambda: self.call_view( 'cohorted_topic',
mock_request, self.student,
"cohorted_topic", self.student_cohort.id,
self.student, thread_group_id=self.moderator_cohort.id
self.student_cohort.id, )))
thread_group_id=self.moderator_cohort.id
)
)
def test_moderator_non_cohorted(self, mock_request): def test_moderator_non_cohorted(self, mock_request):
resp = self.call_view(mock_request, "non_cohorted_topic", self.moderator, self.moderator_cohort.id) resp = self.call_view(mock_request, "non_cohorted_topic", self.moderator, self.moderator_cohort.id)
self.assertEqual(resp.status_code, 200) assert resp.status_code == 200
def test_moderator_same_cohort(self, mock_request): def test_moderator_same_cohort(self, mock_request):
resp = self.call_view( resp = self.call_view(
@@ -695,7 +687,7 @@ class SingleThreadAccessTestCase(CohortedTestCase): # lint-amnesty, pylint: dis
self.moderator_cohort.id, self.moderator_cohort.id,
thread_group_id=self.moderator_cohort.id thread_group_id=self.moderator_cohort.id
) )
self.assertEqual(resp.status_code, 200) assert resp.status_code == 200
def test_moderator_different_cohort(self, mock_request): def test_moderator_different_cohort(self, mock_request):
resp = self.call_view( resp = self.call_view(
@@ -705,7 +697,7 @@ class SingleThreadAccessTestCase(CohortedTestCase): # lint-amnesty, pylint: dis
self.moderator_cohort.id, self.moderator_cohort.id,
thread_group_id=self.student_cohort.id thread_group_id=self.student_cohort.id
) )
self.assertEqual(resp.status_code, 200) assert resp.status_code == 200
def test_private_team_thread(self, mock_request): def test_private_team_thread(self, mock_request):
CourseTeamFactory.create(discussion_topic_id='dummy_discussion_id') CourseTeamFactory.create(discussion_topic_id='dummy_discussion_id')
@@ -720,11 +712,8 @@ class SingleThreadAccessTestCase(CohortedTestCase): # lint-amnesty, pylint: dis
user_not_in_team, user_not_in_team,
'' ''
) )
self.assertEqual(403, response.status_code) assert 403 == response.status_code
self.assertEqual( assert views.TEAM_PERMISSION_MESSAGE == response.content.decode('utf-8')
views.TEAM_PERMISSION_MESSAGE,
response.content.decode('utf-8'),
)
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True) @patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@@ -801,7 +790,7 @@ class ForumFormDiscussionContentGroupTestCase(ForumsEnableMixin, ContentGroupTes
cohorts and non-cohorted modules. cohorts and non-cohorted modules.
""" """
discussion_data = json.loads(response.content.decode('utf-8'))['discussion_data'] discussion_data = json.loads(response.content.decode('utf-8'))['discussion_data']
self.assertEqual(len(discussion_data), expected_discussion_threads) assert len(discussion_data) == expected_discussion_threads
def call_view(self, mock_request, user): # lint-amnesty, pylint: disable=missing-function-docstring def call_view(self, mock_request, user): # lint-amnesty, pylint: disable=missing-function-docstring
mock_request.side_effect = make_mock_request_impl( mock_request.side_effect = make_mock_request_impl(
@@ -880,9 +869,9 @@ class SingleThreadContentGroupTestCase(ForumsEnableMixin, UrlResetMixin, Content
) )
if should_have_access: if should_have_access:
self.assertEqual(call_single_thread().status_code, 200) assert call_single_thread().status_code == 200
else: else:
self.assertEqual(call_single_thread().status_code, 404) assert call_single_thread().status_code == 404
def test_staff_user(self, mock_request): def test_staff_user(self, mock_request):
""" """
@@ -1005,7 +994,7 @@ class InlineDiscussionContextTestCase(ForumsEnableMixin, ModuleStoreTestCase):
) )
json_response = json.loads(response.content.decode('utf-8')) json_response = json.loads(response.content.decode('utf-8'))
self.assertEqual(json_response['discussion_data'][0]['context'], ThreadContext.STANDALONE) assert json_response['discussion_data'][0]['context'] == ThreadContext.STANDALONE
def test_private_team_discussion(self, mock_request): def test_private_team_discussion(self, mock_request):
# First set the team discussion to be private # First set the team discussion to be private
@@ -1026,8 +1015,8 @@ class InlineDiscussionContextTestCase(ForumsEnableMixin, ModuleStoreTestCase):
six.text_type(self.course.id), six.text_type(self.course.id),
self.discussion_topic_id, self.discussion_topic_id,
) )
self.assertEqual(response.status_code, 403) assert response.status_code == 403
self.assertEqual(response.content.decode('utf-8'), views.TEAM_PERMISSION_MESSAGE) assert response.content.decode('utf-8') == views.TEAM_PERMISSION_MESSAGE
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True) @patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
@@ -1219,14 +1208,14 @@ class UserProfileDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupI
) )
# Should never have a group_id if course_id was not included in the request. # Should never have a group_id if course_id was not included in the request.
params_without_course_id = get_params_from_user_info_call(False) params_without_course_id = get_params_from_user_info_call(False)
self.assertNotIn("group_id", params_without_course_id) assert 'group_id' not in params_without_course_id
params_with_course_id = get_params_from_user_info_call(True) params_with_course_id = get_params_from_user_info_call(True)
if expect_group_id_in_request: if expect_group_id_in_request:
self.assertIn("group_id", params_with_course_id) assert 'group_id' in params_with_course_id
self.assertEqual(group_id, params_with_course_id["group_id"]) assert group_id == params_with_course_id['group_id']
else: else:
self.assertNotIn("group_id", params_with_course_id) assert 'group_id' not in params_with_course_id
def test_group_id_passed_to_user_profile_student(self, mock_request): def test_group_id_passed_to_user_profile_student(self, mock_request):
""" """
@@ -1376,7 +1365,7 @@ class InlineDiscussionTestCase(ForumsEnableMixin, ModuleStoreTestCase): # lint-
team.add_user(self.student) team.add_user(self.student)
self.send_request(mock_request) self.send_request(mock_request)
self.assertEqual(mock_request.call_args[1]['params']['context'], ThreadContext.STANDALONE) assert mock_request.call_args[1]['params']['context'] == ThreadContext.STANDALONE
@patch('requests.request', autospec=True) @patch('requests.request', autospec=True)
@@ -1425,8 +1414,8 @@ class UserProfileTestCase(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
def check_html(self, mock_request, **params): # lint-amnesty, pylint: disable=missing-function-docstring def check_html(self, mock_request, **params): # lint-amnesty, pylint: disable=missing-function-docstring
response = self.get_response(mock_request, params) response = self.get_response(mock_request, params)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertEqual(response['Content-Type'], 'text/html; charset=utf-8') assert response['Content-Type'] == 'text/html; charset=utf-8'
html = response.content.decode('utf-8') html = response.content.decode('utf-8')
self.assertRegex(html, r'data-page="1"') self.assertRegex(html, r'data-page="1"')
self.assertRegex(html, r'data-num-pages="1"') self.assertRegex(html, r'data-num-pages="1"')
@@ -1442,19 +1431,16 @@ class UserProfileTestCase(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
def check_ajax(self, mock_request, **params): # lint-amnesty, pylint: disable=missing-function-docstring def check_ajax(self, mock_request, **params): # lint-amnesty, pylint: disable=missing-function-docstring
response = self.get_response(mock_request, params, HTTP_X_REQUESTED_WITH="XMLHttpRequest") response = self.get_response(mock_request, params, HTTP_X_REQUESTED_WITH="XMLHttpRequest")
self.assertEqual(response.status_code, 200) assert response.status_code == 200
self.assertEqual(response['Content-Type'], 'application/json; charset=utf-8') assert response['Content-Type'] == 'application/json; charset=utf-8'
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertEqual( assert sorted(response_data.keys()) == ['annotated_content_info', 'discussion_data', 'num_pages', 'page']
sorted(response_data.keys()), assert len(response_data['discussion_data']) == 1
["annotated_content_info", "discussion_data", "num_pages", "page"] assert response_data['page'] == 1
) assert response_data['num_pages'] == 1
self.assertEqual(len(response_data['discussion_data']), 1) assert response_data['discussion_data'][0]['id'] == self.TEST_THREAD_ID
self.assertEqual(response_data["page"], 1) assert response_data['discussion_data'][0]['title'] == self.TEST_THREAD_TEXT
self.assertEqual(response_data["num_pages"], 1) assert response_data['discussion_data'][0]['body'] == self.TEST_THREAD_TEXT
self.assertEqual(response_data['discussion_data'][0]['id'], self.TEST_THREAD_ID)
self.assertEqual(response_data['discussion_data'][0]['title'], self.TEST_THREAD_TEXT)
self.assertEqual(response_data['discussion_data'][0]['body'], self.TEST_THREAD_TEXT)
def test_html(self, mock_request): def test_html(self, mock_request):
self.check_html(mock_request) self.check_html(mock_request)
@@ -1470,7 +1456,7 @@ class UserProfileTestCase(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
unenrolled_user = UserFactory.create() unenrolled_user = UserFactory.create()
request = RequestFactory().get("dummy_url") request = RequestFactory().get("dummy_url")
request.user = self.student request.user = self.student
with self.assertRaises(Http404): with pytest.raises(Http404):
views.user_profile( views.user_profile(
request, request,
text_type(self.course.id), text_type(self.course.id),
@@ -1480,7 +1466,7 @@ class UserProfileTestCase(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
def test_404_profiled_user(self, _mock_request): def test_404_profiled_user(self, _mock_request):
request = RequestFactory().get("dummy_url") request = RequestFactory().get("dummy_url")
request.user = self.student request.user = self.student
with self.assertRaises(Http404): with pytest.raises(Http404):
views.user_profile( views.user_profile(
request, request,
text_type(self.course.id), text_type(self.course.id),
@@ -1490,7 +1476,7 @@ class UserProfileTestCase(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
def test_404_course(self, _mock_request): def test_404_course(self, _mock_request):
request = RequestFactory().get("dummy_url") request = RequestFactory().get("dummy_url")
request.user = self.student request.user = self.student
with self.assertRaises(Http404): with pytest.raises(Http404):
views.user_profile( views.user_profile(
request, request,
"non/existent/course", "non/existent/course",
@@ -1508,7 +1494,7 @@ class UserProfileTestCase(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase)
text_type(self.course.id), text_type(self.course.id),
self.profiled_user.id self.profiled_user.id
) )
self.assertEqual(response.status_code, 405) assert response.status_code == 405
@patch('requests.request', autospec=True) @patch('requests.request', autospec=True)
@@ -1528,9 +1514,7 @@ class CommentsServiceRequestHeadersTestCase(ForumsEnableMixin, UrlResetMixin, Mo
self.course = CourseFactory.create(discussion_topics={'dummy discussion': {'id': 'dummy_discussion_id'}}) self.course = CourseFactory.create(discussion_topics={'dummy discussion': {'id': 'dummy_discussion_id'}})
self.student = UserFactory.create(username=username, password=password) self.student = UserFactory.create(username=username, password=password)
CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id) CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id)
self.assertTrue( assert self.client.login(username=username, password=password)
self.client.login(username=username, password=password)
)
self.addCleanup(translation.deactivate) self.addCleanup(translation.deactivate)
@@ -1544,7 +1528,7 @@ class CommentsServiceRequestHeadersTestCase(ForumsEnableMixin, UrlResetMixin, Mo
timeout=ANY timeout=ANY
) )
for actual in mock_request.call_args_list: for actual in mock_request.call_args_list:
self.assertEqual(expected, actual) assert expected == actual
def test_accept_language(self, mock_request): def test_accept_language(self, mock_request):
lang = "eo" lang = "eo"
@@ -1602,10 +1586,10 @@ class InlineDiscussionUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCa
response = views.inline_discussion( response = views.inline_discussion(
request, text_type(self.course.id), self.course.discussion_topics['General']['id'] request, text_type(self.course.id), self.course.discussion_topics['General']['id']
) )
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertEqual(response_data["discussion_data"][0]["title"], text) assert response_data['discussion_data'][0]['title'] == text
self.assertEqual(response_data["discussion_data"][0]["body"], text) assert response_data['discussion_data'][0]['body'] == text
class ForumFormDiscussionUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, UnicodeTestMixin): # lint-amnesty, pylint: disable=missing-class-docstring class ForumFormDiscussionUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, UnicodeTestMixin): # lint-amnesty, pylint: disable=missing-class-docstring
@@ -1631,10 +1615,10 @@ class ForumFormDiscussionUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTes
request.META["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" # so request.is_ajax() == True request.META["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" # so request.is_ajax() == True
response = views.forum_form_discussion(request, text_type(self.course.id)) response = views.forum_form_discussion(request, text_type(self.course.id))
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertEqual(response_data["discussion_data"][0]["title"], text) assert response_data['discussion_data'][0]['title'] == text
self.assertEqual(response_data["discussion_data"][0]["body"], text) assert response_data['discussion_data'][0]['body'] == text
@ddt.ddt @ddt.ddt
@@ -1651,7 +1635,7 @@ class ForumDiscussionXSSTestCase(ForumsEnableMixin, UrlResetMixin, ModuleStoreTe
self.course = CourseFactory.create() self.course = CourseFactory.create()
self.student = UserFactory.create(username=username, password=password) self.student = UserFactory.create(username=username, password=password)
CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id) CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id)
self.assertTrue(self.client.login(username=username, password=password)) assert self.client.login(username=username, password=password)
@ddt.data('"><script>alert(1)</script>', '<script>alert(1)</script>', '</script><script>alert(1)</script>') @ddt.data('"><script>alert(1)</script>', '<script>alert(1)</script>', '</script><script>alert(1)</script>')
@patch('common.djangoapps.student.models.cc.User.from_django_user') @patch('common.djangoapps.student.models.cc.User.from_django_user')
@@ -1719,10 +1703,10 @@ class ForumDiscussionSearchUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreT
request.META["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" # so request.is_ajax() == True request.META["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" # so request.is_ajax() == True
response = views.forum_form_discussion(request, text_type(self.course.id)) response = views.forum_form_discussion(request, text_type(self.course.id))
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertEqual(response_data["discussion_data"][0]["title"], text) assert response_data['discussion_data'][0]['title'] == text
self.assertEqual(response_data["discussion_data"][0]["body"], text) assert response_data['discussion_data'][0]['body'] == text
class SingleThreadUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, UnicodeTestMixin): # lint-amnesty, pylint: disable=missing-class-docstring class SingleThreadUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, UnicodeTestMixin): # lint-amnesty, pylint: disable=missing-class-docstring
@@ -1749,10 +1733,10 @@ class SingleThreadUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCase,
request.META["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" # so request.is_ajax() == True request.META["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" # so request.is_ajax() == True
response = views.single_thread(request, text_type(self.course.id), "dummy_discussion_id", thread_id) response = views.single_thread(request, text_type(self.course.id), "dummy_discussion_id", thread_id)
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertEqual(response_data["content"]["title"], text) assert response_data['content']['title'] == text
self.assertEqual(response_data["content"]["body"], text) assert response_data['content']['body'] == text
class UserProfileUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, UnicodeTestMixin): # lint-amnesty, pylint: disable=missing-class-docstring class UserProfileUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, UnicodeTestMixin): # lint-amnesty, pylint: disable=missing-class-docstring
@@ -1778,10 +1762,10 @@ class UserProfileUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, U
request.META["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" # so request.is_ajax() == True request.META["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" # so request.is_ajax() == True
response = views.user_profile(request, text_type(self.course.id), str(self.student.id)) response = views.user_profile(request, text_type(self.course.id), str(self.student.id))
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertEqual(response_data["discussion_data"][0]["title"], text) assert response_data['discussion_data'][0]['title'] == text
self.assertEqual(response_data["discussion_data"][0]["body"], text) assert response_data['discussion_data'][0]['body'] == text
class FollowedThreadsUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, UnicodeTestMixin): # lint-amnesty, pylint: disable=missing-class-docstring class FollowedThreadsUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, UnicodeTestMixin): # lint-amnesty, pylint: disable=missing-class-docstring
@@ -1807,10 +1791,10 @@ class FollowedThreadsUnicodeTestCase(ForumsEnableMixin, SharedModuleStoreTestCas
request.META["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" # so request.is_ajax() == True request.META["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest" # so request.is_ajax() == True
response = views.followed_threads(request, text_type(self.course.id), str(self.student.id)) response = views.followed_threads(request, text_type(self.course.id), str(self.student.id))
self.assertEqual(response.status_code, 200) assert response.status_code == 200
response_data = json.loads(response.content.decode('utf-8')) response_data = json.loads(response.content.decode('utf-8'))
self.assertEqual(response_data["discussion_data"][0]["title"], text) assert response_data['discussion_data'][0]['title'] == text
self.assertEqual(response_data["discussion_data"][0]["body"], text) assert response_data['discussion_data'][0]['body'] == text
class EnrollmentTestCase(ForumsEnableMixin, ModuleStoreTestCase): class EnrollmentTestCase(ForumsEnableMixin, ModuleStoreTestCase):
@@ -1831,7 +1815,7 @@ class EnrollmentTestCase(ForumsEnableMixin, ModuleStoreTestCase):
mock_request.side_effect = make_mock_request_impl(course=self.course, text='dummy') mock_request.side_effect = make_mock_request_impl(course=self.course, text='dummy')
request = RequestFactory().get('dummy_url') request = RequestFactory().get('dummy_url')
request.user = self.student request.user = self.student
with self.assertRaises(CourseAccessRedirect): with pytest.raises(CourseAccessRedirect):
views.forum_form_discussion(request, course_id=text_type(self.course.id)) # pylint: disable=no-value-for-parameter, unexpected-keyword-arg views.forum_form_discussion(request, course_id=text_type(self.course.id)) # pylint: disable=no-value-for-parameter, unexpected-keyword-arg
@@ -1854,9 +1838,7 @@ class EnterpriseConsentTestCase(EnterpriseTestConsentRequired, ForumsEnableMixin
self.course = CourseFactory.create(discussion_topics={'dummy discussion': {'id': self.discussion_id}}) self.course = CourseFactory.create(discussion_topics={'dummy discussion': {'id': self.discussion_id}})
self.student = UserFactory.create(username=username, password=password) self.student = UserFactory.create(username=username, password=password)
CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id) CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id)
self.assertTrue( assert self.client.login(username=username, password=password)
self.client.login(username=username, password=password)
)
self.addCleanup(translation.deactivate) self.addCleanup(translation.deactivate)
@@ -1970,7 +1952,7 @@ class CourseDiscussionTopicsTestCase(DividedDiscussionsTestCase):
'children': [['Chapter', TYPE_SUBCATEGORY]] 'children': [['Chapter', TYPE_SUBCATEGORY]]
} }
} }
self.assertEqual(response, expected_response) assert response == expected_response
class CourseDiscussionsHandlerTestCase(DividedDiscussionsTestCase): class CourseDiscussionsHandlerTestCase(DividedDiscussionsTestCase):
@@ -2012,14 +1994,14 @@ class CourseDiscussionsHandlerTestCase(DividedDiscussionsTestCase):
expected_response = self.get_expected_response() expected_response = self.get_expected_response()
self.assertEqual(response, expected_response) assert response == expected_response
expected_response['always_divide_inline_discussions'] = True expected_response['always_divide_inline_discussions'] = True
response = self.patch_handler( response = self.patch_handler(
self.course, data=expected_response, handler=course_discussions_settings_handler self.course, data=expected_response, handler=course_discussions_settings_handler
) )
self.assertEqual(response, expected_response) assert response == expected_response
def test_update_course_wide_discussion_settings(self): def test_update_course_wide_discussion_settings(self):
""" """
@@ -2036,14 +2018,14 @@ class CourseDiscussionsHandlerTestCase(DividedDiscussionsTestCase):
response = self.get_handler(self.course, handler=views.course_discussions_settings_handler) response = self.get_handler(self.course, handler=views.course_discussions_settings_handler)
expected_response = self.get_expected_response() expected_response = self.get_expected_response()
self.assertEqual(response, expected_response) assert response == expected_response
expected_response['divided_course_wide_discussions'] = [topic_name_to_id(self.course, "Topic B")] expected_response['divided_course_wide_discussions'] = [topic_name_to_id(self.course, "Topic B")]
response = self.patch_handler( response = self.patch_handler(
self.course, data=expected_response, handler=views.course_discussions_settings_handler self.course, data=expected_response, handler=views.course_discussions_settings_handler
) )
self.assertEqual(response, expected_response) assert response == expected_response
def test_update_inline_discussion_settings(self): def test_update_inline_discussion_settings(self):
""" """
@@ -2054,7 +2036,7 @@ class CourseDiscussionsHandlerTestCase(DividedDiscussionsTestCase):
response = self.get_handler(self.course, handler=views.course_discussions_settings_handler) response = self.get_handler(self.course, handler=views.course_discussions_settings_handler)
expected_response = self.get_expected_response() expected_response = self.get_expected_response()
self.assertEqual(response, expected_response) assert response == expected_response
RequestCache.clear_all_namespaces() RequestCache.clear_all_namespaces()
now = datetime.now() now = datetime.now()
@@ -2073,7 +2055,7 @@ class CourseDiscussionsHandlerTestCase(DividedDiscussionsTestCase):
self.course, data=expected_response, handler=views.course_discussions_settings_handler self.course, data=expected_response, handler=views.course_discussions_settings_handler
) )
self.assertEqual(response, expected_response) assert response == expected_response
def test_get_settings(self): def test_get_settings(self):
""" """
@@ -2089,7 +2071,7 @@ class CourseDiscussionsHandlerTestCase(DividedDiscussionsTestCase):
expected_response['divided_course_wide_discussions'] = [topic_name_to_id(self.course, name) expected_response['divided_course_wide_discussions'] = [topic_name_to_id(self.course, name)
for name in divided_course_wide_discussions] for name in divided_course_wide_discussions]
self.assertEqual(response, expected_response) assert response == expected_response
def test_update_settings_with_invalid_field_data_type(self): def test_update_settings_with_invalid_field_data_type(self):
""" """
@@ -2103,11 +2085,10 @@ class CourseDiscussionsHandlerTestCase(DividedDiscussionsTestCase):
expected_response_code=400, expected_response_code=400,
handler=views.course_discussions_settings_handler handler=views.course_discussions_settings_handler
) )
self.assertEqual( assert u'Incorrect field type for `{}`. Type must be `{}`'.format(
u"Incorrect field type for `{}`. Type must be `{}`".format('always_divide_inline_discussions', 'always_divide_inline_discussions',
bool.__name__), bool.__name__
response.get("error") ) == response.get('error')
)
def test_available_schemes(self): def test_available_schemes(self):
# Cohorts disabled, single enrollment mode. # Cohorts disabled, single enrollment mode.
@@ -2115,14 +2096,14 @@ class CourseDiscussionsHandlerTestCase(DividedDiscussionsTestCase):
response = self.get_handler(self.course, handler=views.course_discussions_settings_handler) response = self.get_handler(self.course, handler=views.course_discussions_settings_handler)
expected_response = self.get_expected_response() expected_response = self.get_expected_response()
expected_response['available_division_schemes'] = [] expected_response['available_division_schemes'] = []
self.assertEqual(response, expected_response) assert response == expected_response
# Add 2 enrollment modes # Add 2 enrollment modes
CourseModeFactory.create(course_id=self.course.id, mode_slug=CourseMode.AUDIT) CourseModeFactory.create(course_id=self.course.id, mode_slug=CourseMode.AUDIT)
CourseModeFactory.create(course_id=self.course.id, mode_slug=CourseMode.VERIFIED) CourseModeFactory.create(course_id=self.course.id, mode_slug=CourseMode.VERIFIED)
response = self.get_handler(self.course, handler=views.course_discussions_settings_handler) response = self.get_handler(self.course, handler=views.course_discussions_settings_handler)
expected_response['available_division_schemes'] = [CourseDiscussionSettings.ENROLLMENT_TRACK] expected_response['available_division_schemes'] = [CourseDiscussionSettings.ENROLLMENT_TRACK]
self.assertEqual(response, expected_response) assert response == expected_response
# Enable cohorts # Enable cohorts
config_course_cohorts(self.course, is_cohorted=True) config_course_cohorts(self.course, is_cohorted=True)
@@ -2130,7 +2111,7 @@ class CourseDiscussionsHandlerTestCase(DividedDiscussionsTestCase):
expected_response['available_division_schemes'] = [ expected_response['available_division_schemes'] = [
CourseDiscussionSettings.COHORT, CourseDiscussionSettings.ENROLLMENT_TRACK CourseDiscussionSettings.COHORT, CourseDiscussionSettings.ENROLLMENT_TRACK
] ]
self.assertEqual(response, expected_response) assert response == expected_response
class DefaultTopicIdGetterTestCase(ModuleStoreTestCase): class DefaultTopicIdGetterTestCase(ModuleStoreTestCase):
@@ -2147,7 +2128,7 @@ class DefaultTopicIdGetterTestCase(ModuleStoreTestCase):
course = CourseFactory.create(discussion_topics=discussion_topics) course = CourseFactory.create(discussion_topics=discussion_topics)
expected_id = None expected_id = None
result = _get_discussion_default_topic_id(course) result = _get_discussion_default_topic_id(course)
self.assertEqual(expected_id, result) assert expected_id == result
def test_default_topic_id(self): def test_default_topic_id(self):
discussion_topics = { discussion_topics = {
@@ -2162,7 +2143,7 @@ class DefaultTopicIdGetterTestCase(ModuleStoreTestCase):
course = CourseFactory.create(discussion_topics=discussion_topics) course = CourseFactory.create(discussion_topics=discussion_topics)
expected_id = 'another_discussion_id' expected_id = 'another_discussion_id'
result = _get_discussion_default_topic_id(course) result = _get_discussion_default_topic_id(course)
self.assertEqual(expected_id, result) assert expected_id == result
class ThreadViewedEventTestCase(EventTestMixin, ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase): class ThreadViewedEventTestCase(EventTestMixin, ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase):
@@ -2249,4 +2230,4 @@ class ThreadViewedEventTestCase(EventTestMixin, ForumsEnableMixin, UrlResetMixin
self.assert_event_emission_count('edx.forum.thread.viewed', 1) self.assert_event_emission_count('edx.forum.thread.viewed', 1)
_, event = self.get_latest_call_args() _, event = self.get_latest_call_args()
event_items = list(event.items()) event_items = list(event.items())
self.assertTrue(kv_pair in event_items for kv_pair in expected_event_items) assert ((kv_pair in event_items) for kv_pair in expected_event_items)