Commit 2acb4a6c by Toby Lawrence

[PERF-386] Utilize ForumsConfig to enable and disable forums.

This specifically enables/disables the underlying comment service client
used to make calls to the service.  When disabled, this client will now
throw an exception which can be propagated upwards so that callers can
make the right decision about how to notify users of the error, or
handle retry, etc etc.
parent fa2b1ae4
import logging
from django.conf import settings
from django.db import models
from django.contrib.auth.models import User
......@@ -150,8 +151,15 @@ def all_permissions_for_user_in_course(user, course_id): # pylint: disable=inva
class ForumsConfig(ConfigurationModel):
"""Config for the connection to the cs_comments_service forums backend."""
# For now, just tweak the connection timeout settings. We can add more later.
connection_timeout = models.FloatField(default=5.0)
connection_timeout = models.FloatField(
default=5.0,
help_text="Seconds to wait when trying to connect to the comment service.",
)
@property
def api_key(self):
"""The API key used to authenticate to the comments service."""
return getattr(settings, "COMMENTS_SERVICE_KEY", None)
def __unicode__(self):
"""Simple representation so the admin screen looks less ugly."""
......
......@@ -21,6 +21,7 @@ from openedx.core.djangoapps.external_auth.models import ExternalAuthMap
import student
from student.models import UserAttribute
from student.views import REGISTRATION_AFFILIATE_ID, REGISTRATION_UTM_PARAMETERS, REGISTRATION_UTM_CREATED_AT
from django_comment_common.models import ForumsConfig
TEST_CS_URL = 'https://comments.service.test:123/'
......@@ -694,6 +695,10 @@ class TestCreateCommentsServiceUser(TransactionTestCase):
"terms_of_service": "true",
}
config = ForumsConfig.current()
config.enabled = True
config.save()
def test_cs_user_created(self, request):
"If user account creation succeeds, we should create a comments service user"
response = self.client.post(self.url, self.params)
......
......@@ -9,6 +9,7 @@ import factory
import requests
from common.test.acceptance.fixtures import COMMENTS_STUB_URL
from common.test.acceptance.fixtures.config import ConfigModelFixture
class ContentFactory(factory.Factory):
......@@ -170,3 +171,12 @@ class SearchResultFixture(DiscussionContentFixture):
def get_config_data(self):
return {"search_result": json.dumps(self.result)}
class ForumsConfigMixin(object):
"""Mixin providing a method used to configure the forums integration."""
def enable_forums(self, is_enabled=True):
"""Configures whether or not forums are enabled."""
ConfigModelFixture('/config/forums', {
'enabled': is_enabled,
}).install()
......@@ -11,6 +11,7 @@ from common.test.acceptance.fixtures.discussion import (
SingleThreadViewFixture,
Thread,
Response,
ForumsConfigMixin,
)
from common.test.acceptance.pages.lms.discussion import DiscussionTabSingleThreadPage
from common.test.acceptance.tests.helpers import UniqueCourseTest
......@@ -86,7 +87,8 @@ class CohortTestMixin(object):
self.assertTrue(response.ok, "Failed to add user to cohort")
class BaseDiscussionTestCase(UniqueCourseTest):
class BaseDiscussionTestCase(UniqueCourseTest, ForumsConfigMixin):
"""Base test case class for all discussions-related tests."""
def setUp(self):
super(BaseDiscussionTestCase, self).setUp()
......@@ -97,6 +99,8 @@ class BaseDiscussionTestCase(UniqueCourseTest):
)
self.course_fixture.install()
self.enable_forums()
def create_single_thread_page(self, thread_id):
"""
Sets up a `DiscussionTabSingleThreadPage` for a given
......
......@@ -180,7 +180,8 @@ class DiscussionResponsePaginationTestMixin(BaseDiscussionMixin):
self.assertFalse(self.thread_page.has_add_response_button())
class DiscussionHomePageTest(UniqueCourseTest):
@attr(shard=2)
class DiscussionHomePageTest(BaseDiscussionTestCase):
"""
Tests for the discussion home page.
"""
......@@ -189,7 +190,6 @@ class DiscussionHomePageTest(UniqueCourseTest):
def setUp(self):
super(DiscussionHomePageTest, self).setUp()
CourseFixture(**self.course_info).install()
AutoAuthPage(self.browser, course_id=self.course_id).visit()
self.page = DiscussionTabHomePage(self.browser, self.course_id)
self.page.visit()
......
......@@ -16,7 +16,8 @@ from common.test.acceptance.fixtures import LMS_BASE_URL
from common.test.acceptance.fixtures.course import CourseFixture
from common.test.acceptance.fixtures.discussion import (
Thread,
MultipleThreadFixture
MultipleThreadFixture,
ForumsConfigMixin,
)
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.course_info import CourseInfoPage
......@@ -37,7 +38,7 @@ from common.test.acceptance.pages.common.utils import confirm_prompt
TOPICS_PER_PAGE = 12
class TeamsTabBase(EventsTestMixin, UniqueCourseTest):
class TeamsTabBase(EventsTestMixin, ForumsConfigMixin, UniqueCourseTest):
"""Base class for Teams Tab tests"""
def setUp(self):
super(TeamsTabBase, self).setUp()
......@@ -47,6 +48,8 @@ class TeamsTabBase(EventsTestMixin, UniqueCourseTest):
# TODO: Refactor so resetting events database is not necessary
self.reset_event_tracking()
self.enable_forums()
def create_topics(self, num_topics):
"""Create `num_topics` test topics."""
return [{u"description": i, u"name": i, u"id": i} for i in map(str, xrange(num_topics))]
......
......@@ -49,6 +49,7 @@ from django_comment_common.models import (
FORUM_ROLE_STUDENT,
Role,
)
from django_comment_client.tests.utils import ForumsEnableMixin
from openedx.core.djangoapps.course_groups.models import CourseUserGroupPartitionGroup
from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory
from openedx.core.lib.exceptions import CourseNotFoundError, PageNotFoundError
......@@ -85,7 +86,7 @@ def _discussion_disabled_course_for(user):
@attr(shard=2)
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
class GetCourseTest(UrlResetMixin, SharedModuleStoreTestCase):
class GetCourseTest(ForumsEnableMixin, UrlResetMixin, SharedModuleStoreTestCase):
"""Test for get_course"""
@classmethod
......@@ -133,7 +134,7 @@ class GetCourseTest(UrlResetMixin, SharedModuleStoreTestCase):
@attr(shard=2)
@ddt.ddt
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
class GetCourseTestBlackouts(UrlResetMixin, ModuleStoreTestCase):
class GetCourseTestBlackouts(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase):
"""
Tests of get_course for courses that have blackout dates.
"""
......@@ -177,7 +178,7 @@ class GetCourseTestBlackouts(UrlResetMixin, ModuleStoreTestCase):
@attr(shard=2)
@mock.patch.dict("django.conf.settings.FEATURES", {"DISABLE_START_DATES": False})
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
class GetCourseTopicsTest(UrlResetMixin, ModuleStoreTestCase):
class GetCourseTopicsTest(ForumsEnableMixin, UrlResetMixin, ModuleStoreTestCase):
"""Test for get_course_topics"""
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
def setUp(self):
......@@ -551,7 +552,7 @@ class GetCourseTopicsTest(UrlResetMixin, ModuleStoreTestCase):
@attr(shard=2)
@ddt.ddt
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
class GetThreadListTest(CommentsServiceMockMixin, UrlResetMixin, SharedModuleStoreTestCase):
class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMixin, SharedModuleStoreTestCase):
"""Test for get_thread_list"""
@classmethod
......@@ -1006,7 +1007,7 @@ class GetThreadListTest(CommentsServiceMockMixin, UrlResetMixin, SharedModuleSto
@attr(shard=2)
@ddt.ddt
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
class GetCommentListTest(CommentsServiceMockMixin, SharedModuleStoreTestCase):
class GetCommentListTest(ForumsEnableMixin, CommentsServiceMockMixin, SharedModuleStoreTestCase):
"""Test for get_comment_list"""
@classmethod
......@@ -1442,6 +1443,7 @@ class GetCommentListTest(CommentsServiceMockMixin, SharedModuleStoreTestCase):
@disable_signal(api, 'thread_voted')
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
class CreateThreadTest(
ForumsEnableMixin,
CommentsServiceMockMixin,
UrlResetMixin,
SharedModuleStoreTestCase,
......@@ -1694,6 +1696,7 @@ class CreateThreadTest(
@disable_signal(api, 'comment_voted')
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
class CreateCommentTest(
ForumsEnableMixin,
CommentsServiceMockMixin,
UrlResetMixin,
SharedModuleStoreTestCase,
......@@ -1962,6 +1965,7 @@ class CreateCommentTest(
@disable_signal(api, 'thread_voted')
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
class UpdateThreadTest(
ForumsEnableMixin,
CommentsServiceMockMixin,
UrlResetMixin,
SharedModuleStoreTestCase,
......@@ -2370,6 +2374,7 @@ class UpdateThreadTest(
@disable_signal(api, 'comment_voted')
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
class UpdateCommentTest(
ForumsEnableMixin,
CommentsServiceMockMixin,
UrlResetMixin,
SharedModuleStoreTestCase,
......@@ -2774,6 +2779,7 @@ class UpdateCommentTest(
@disable_signal(api, 'thread_deleted')
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
class DeleteThreadTest(
ForumsEnableMixin,
CommentsServiceMockMixin,
UrlResetMixin,
SharedModuleStoreTestCase,
......@@ -2914,6 +2920,7 @@ class DeleteThreadTest(
@disable_signal(api, 'comment_deleted')
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
class DeleteCommentTest(
ForumsEnableMixin,
CommentsServiceMockMixin,
UrlResetMixin,
SharedModuleStoreTestCase,
......@@ -3072,6 +3079,7 @@ class DeleteCommentTest(
@ddt.ddt
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
class RetrieveThreadTest(
ForumsEnableMixin,
CommentsServiceMockMixin,
UrlResetMixin,
SharedModuleStoreTestCase
......
......@@ -31,10 +31,11 @@ from util.testing import UrlResetMixin
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory
from django_comment_client.tests.utils import ForumsEnableMixin
@ddt.ddt
class SerializerTestMixin(CommentsServiceMockMixin, UrlResetMixin):
class SerializerTestMixin(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMixin):
@classmethod
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
def setUpClass(cls):
......@@ -426,7 +427,12 @@ class CommentSerializerTest(SerializerTestMixin, SharedModuleStoreTestCase):
@ddt.ddt
class ThreadSerializerDeserializationTest(CommentsServiceMockMixin, UrlResetMixin, SharedModuleStoreTestCase):
class ThreadSerializerDeserializationTest(
ForumsEnableMixin,
CommentsServiceMockMixin,
UrlResetMixin,
SharedModuleStoreTestCase
):
"""Tests for ThreadSerializer deserialization."""
@classmethod
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
......@@ -629,7 +635,7 @@ class ThreadSerializerDeserializationTest(CommentsServiceMockMixin, UrlResetMixi
@ddt.ddt
class CommentSerializerDeserializationTest(CommentsServiceMockMixin, SharedModuleStoreTestCase):
class CommentSerializerDeserializationTest(ForumsEnableMixin, CommentsServiceMockMixin, SharedModuleStoreTestCase):
"""Tests for ThreadSerializer deserialization."""
@classmethod
def setUpClass(cls):
......
......@@ -27,13 +27,14 @@ from discussion_api.tests.utils import (
make_minimal_cs_thread,
make_paginated_api_response,
ProfileImageTestMixin)
from django_comment_client.tests.utils import ForumsEnableMixin
from student.tests.factories import CourseEnrollmentFactory, UserFactory
from util.testing import UrlResetMixin, PatchMediaTypeMixin
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, check_mongo_calls, ItemFactory
class DiscussionAPIViewTestMixin(CommentsServiceMockMixin, UrlResetMixin):
class DiscussionAPIViewTestMixin(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMixin):
"""
Mixin for common code in tests of Discussion API views. This includes
creation of common structures (e.g. a course, user, and enrollment), logging
......
......@@ -17,7 +17,7 @@ from lms.lib.comment_client import Thread
from common.test.utils import MockSignalHandlerMixin, disable_signal
from django_comment_client.base import views
from django_comment_client.tests.group_id import CohortedTopicGroupIdTestMixin, NonCohortedTopicGroupIdTestMixin, GroupIdAssertionMixin
from django_comment_client.tests.utils import CohortedTestCase
from django_comment_client.tests.utils import CohortedTestCase, ForumsEnableMixin
from django_comment_client.tests.unicode import UnicodeTestMixin
from django_comment_common.models import Role
from django_comment_common.utils import seed_permissions_roles, ThreadContext
......@@ -346,7 +346,13 @@ class ViewsTestCaseMixin(object):
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
@disable_signal(views, 'thread_created')
@disable_signal(views, 'thread_edited')
class ViewsQueryCountTestCase(UrlResetMixin, ModuleStoreTestCase, MockRequestSetupMixin, ViewsTestCaseMixin):
class ViewsQueryCountTestCase(
ForumsEnableMixin,
UrlResetMixin,
ModuleStoreTestCase,
MockRequestSetupMixin,
ViewsTestCaseMixin
):
CREATE_USER = False
ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']
......@@ -392,6 +398,7 @@ class ViewsQueryCountTestCase(UrlResetMixin, ModuleStoreTestCase, MockRequestSet
@ddt.ddt
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
class ViewsTestCase(
ForumsEnableMixin,
UrlResetMixin,
SharedModuleStoreTestCase,
MockRequestSetupMixin,
......@@ -1019,7 +1026,7 @@ class ViewsTestCase(
@attr(shard=2)
@patch("lms.lib.comment_client.utils.requests.request", autospec=True)
@disable_signal(views, 'comment_endorsed')
class ViewPermissionsTestCase(UrlResetMixin, SharedModuleStoreTestCase, MockRequestSetupMixin):
class ViewPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStoreTestCase, MockRequestSetupMixin):
@classmethod
def setUpClass(cls):
......@@ -1127,7 +1134,11 @@ class ViewPermissionsTestCase(UrlResetMixin, SharedModuleStoreTestCase, MockRequ
@attr(shard=2)
class CreateThreadUnicodeTestCase(SharedModuleStoreTestCase, UnicodeTestMixin, MockRequestSetupMixin):
class CreateThreadUnicodeTestCase(
ForumsEnableMixin,
SharedModuleStoreTestCase,
UnicodeTestMixin,
MockRequestSetupMixin):
@classmethod
def setUpClass(cls):
......@@ -1143,6 +1154,9 @@ class CreateThreadUnicodeTestCase(SharedModuleStoreTestCase, UnicodeTestMixin, M
cls.student = UserFactory.create()
CourseEnrollmentFactory(user=cls.student, course_id=cls.course.id)
def setUp(self):
super(CreateThreadUnicodeTestCase, self).setUp()
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
def _test_unicode_data(self, text, mock_request,):
"""
......@@ -1164,7 +1178,12 @@ class CreateThreadUnicodeTestCase(SharedModuleStoreTestCase, UnicodeTestMixin, M
@attr(shard=2)
@disable_signal(views, 'thread_edited')
class UpdateThreadUnicodeTestCase(SharedModuleStoreTestCase, UnicodeTestMixin, MockRequestSetupMixin):
class UpdateThreadUnicodeTestCase(
ForumsEnableMixin,
SharedModuleStoreTestCase,
UnicodeTestMixin,
MockRequestSetupMixin
):
@classmethod
def setUpClass(cls):
......@@ -1180,6 +1199,9 @@ class UpdateThreadUnicodeTestCase(SharedModuleStoreTestCase, UnicodeTestMixin, M
cls.student = UserFactory.create()
CourseEnrollmentFactory(user=cls.student, course_id=cls.course.id)
def setUp(self):
super(UpdateThreadUnicodeTestCase, self).setUp()
@patch('django_comment_client.utils.get_discussion_categories_ids', return_value=["test_commentable"])
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
def _test_unicode_data(self, text, mock_request, mock_get_discussion_id_map):
......@@ -1202,7 +1224,12 @@ class UpdateThreadUnicodeTestCase(SharedModuleStoreTestCase, UnicodeTestMixin, M
@attr(shard=2)
@disable_signal(views, 'comment_created')
class CreateCommentUnicodeTestCase(SharedModuleStoreTestCase, UnicodeTestMixin, MockRequestSetupMixin):
class CreateCommentUnicodeTestCase(
ForumsEnableMixin,
SharedModuleStoreTestCase,
UnicodeTestMixin,
MockRequestSetupMixin
):
@classmethod
def setUpClass(cls):
......@@ -1218,6 +1245,9 @@ class CreateCommentUnicodeTestCase(SharedModuleStoreTestCase, UnicodeTestMixin,
cls.student = UserFactory.create()
CourseEnrollmentFactory(user=cls.student, course_id=cls.course.id)
def setUp(self):
super(CreateCommentUnicodeTestCase, self).setUp()
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
def _test_unicode_data(self, text, mock_request):
commentable_id = "non_team_dummy_id"
......@@ -1245,7 +1275,12 @@ class CreateCommentUnicodeTestCase(SharedModuleStoreTestCase, UnicodeTestMixin,
@attr(shard=2)
@disable_signal(views, 'comment_edited')
class UpdateCommentUnicodeTestCase(SharedModuleStoreTestCase, UnicodeTestMixin, MockRequestSetupMixin):
class UpdateCommentUnicodeTestCase(
ForumsEnableMixin,
SharedModuleStoreTestCase,
UnicodeTestMixin,
MockRequestSetupMixin
):
@classmethod
def setUpClass(cls):
......@@ -1261,6 +1296,9 @@ class UpdateCommentUnicodeTestCase(SharedModuleStoreTestCase, UnicodeTestMixin,
cls.student = UserFactory.create()
CourseEnrollmentFactory(user=cls.student, course_id=cls.course.id)
def setUp(self):
super(UpdateCommentUnicodeTestCase, self).setUp()
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
def _test_unicode_data(self, text, mock_request):
self._set_mock_request_data(mock_request, {
......@@ -1279,7 +1317,12 @@ class UpdateCommentUnicodeTestCase(SharedModuleStoreTestCase, UnicodeTestMixin,
@attr(shard=2)
@disable_signal(views, 'comment_created')
class CreateSubCommentUnicodeTestCase(SharedModuleStoreTestCase, UnicodeTestMixin, MockRequestSetupMixin):
class CreateSubCommentUnicodeTestCase(
ForumsEnableMixin,
SharedModuleStoreTestCase,
UnicodeTestMixin,
MockRequestSetupMixin
):
"""
Make sure comments under a response can handle unicode.
"""
......@@ -1297,6 +1340,9 @@ class CreateSubCommentUnicodeTestCase(SharedModuleStoreTestCase, UnicodeTestMixi
cls.student = UserFactory.create()
CourseEnrollmentFactory(user=cls.student, course_id=cls.course.id)
def setUp(self):
super(CreateSubCommentUnicodeTestCase, self).setUp()
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
def _test_unicode_data(self, text, mock_request):
"""
......@@ -1332,7 +1378,7 @@ class CreateSubCommentUnicodeTestCase(SharedModuleStoreTestCase, UnicodeTestMixi
@disable_signal(views, 'comment_created')
@disable_signal(views, 'comment_voted')
@disable_signal(views, 'comment_deleted')
class TeamsPermissionsTestCase(UrlResetMixin, SharedModuleStoreTestCase, MockRequestSetupMixin):
class TeamsPermissionsTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStoreTestCase, MockRequestSetupMixin):
# Most of the test points use the same ddt data.
# args: user, commentable_id, status_code
ddt_permissions_args = [
......@@ -1599,7 +1645,7 @@ TEAM_COMMENTABLE_ID = 'test-team-discussion'
@attr(shard=2)
@disable_signal(views, 'comment_created')
@ddt.ddt
class ForumEventTestCase(SharedModuleStoreTestCase, MockRequestSetupMixin):
class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockRequestSetupMixin):
"""
Forum actions are expected to launch analytics events. Test these here.
"""
......@@ -1620,6 +1666,9 @@ class ForumEventTestCase(SharedModuleStoreTestCase, MockRequestSetupMixin):
cls.student.roles.add(Role.objects.get(name="Student", course_id=cls.course.id))
CourseAccessRoleFactory(course_id=cls.course.id, user=cls.student, role='Wizard')
def setUp(self):
super(ForumEventTestCase, self).setUp()
@patch('eventtracking.tracker.emit')
@patch('lms.lib.comment_client.utils.requests.request', autospec=True)
def test_thread_event(self, __, mock_emit):
......@@ -1783,7 +1832,7 @@ class ForumEventTestCase(SharedModuleStoreTestCase, MockRequestSetupMixin):
@attr(shard=2)
class UsersEndpointTestCase(SharedModuleStoreTestCase, MockRequestSetupMixin):
class UsersEndpointTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockRequestSetupMixin):
@classmethod
def setUpClass(cls):
......@@ -1802,6 +1851,9 @@ class UsersEndpointTestCase(SharedModuleStoreTestCase, MockRequestSetupMixin):
cls.other_user = UserFactory.create(username="other")
CourseEnrollmentFactory(user=cls.other_user, course_id=cls.course.id)
def setUp(self):
super(UsersEndpointTestCase, self).setUp()
def set_post_counts(self, mock_request, threads_count=1, comments_count=1):
"""
sets up a mock response from the comments service for getting post counts for our other_user
......
......@@ -3,6 +3,7 @@ import datetime
import json
import ddt
import mock
from mock import patch, Mock
from nose.plugins.attrib import attr
from pytz import UTC
from django.utils.timezone import UTC as django_utc
......@@ -14,6 +15,8 @@ from edxmako import add_lookup
from django_comment_client.tests.factories import RoleFactory
from django_comment_client.tests.unicode import UnicodeTestMixin
import django_comment_client.utils as utils
from lms.lib.comment_client.utils import perform_request, CommentClientMaintenanceError
from django_comment_common.models import ForumsConfig
from courseware.tests.factories import InstructorFactory
from courseware.tabs import get_course_tab_list
......@@ -1417,3 +1420,32 @@ class PermissionsTestCase(ModuleStoreTestCase):
# content has no known author
del content['user_id']
self.assertFalse(utils.is_content_authored_by(content, user))
class ClientConfigurationTestCase(TestCase):
"""Simple test cases to ensure enabling/disabling the use of the comment service works as intended."""
def test_disabled(self):
"""Ensures that an exception is raised when forums are disabled."""
config = ForumsConfig.current()
config.enabled = False
config.save()
with self.assertRaises(CommentClientMaintenanceError):
perform_request('GET', 'http://www.google.com')
@patch('requests.request')
def test_enabled(self, mock_request):
"""Ensures that requests proceed normally when forums are enabled."""
config = ForumsConfig.current()
config.enabled = True
config.save()
response = Mock()
response.status_code = 200
response.json = lambda: {}
mock_request.return_value = response
result = perform_request('GET', 'http://www.google.com')
self.assertEqual(result, {})
......@@ -4,7 +4,7 @@ Utilities for tests within the django_comment_client module.
from mock import patch
from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory
from django_comment_common.models import Role
from django_comment_common.models import Role, ForumsConfig
from django_comment_common.utils import seed_permissions_roles
from student.tests.factories import CourseEnrollmentFactory, UserFactory
from util.testing import UrlResetMixin
......@@ -12,7 +12,19 @@ from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
class CohortedTestCase(UrlResetMixin, SharedModuleStoreTestCase):
class ForumsEnableMixin(object):
"""
Ensures that the forums are enabled for a given test class.
"""
def setUp(self):
super(ForumsEnableMixin, self).setUp()
config = ForumsConfig.current()
config.enabled = True
config.save()
class CohortedTestCase(ForumsEnableMixin, UrlResetMixin, SharedModuleStoreTestCase):
"""
Sets up a course with a student, a moderator and their cohorts.
"""
......
......@@ -55,6 +55,10 @@ def perform_request(method, url, data_or_params=None, raw=False,
metric_action=None, metric_tags=None, paged_results=False):
# To avoid dependency conflict
from django_comment_common.models import ForumsConfig
config = ForumsConfig.current()
if not config.enabled:
raise CommentClientMaintenanceError('service disabled')
if metric_tags is None:
metric_tags = []
......@@ -66,7 +70,7 @@ def perform_request(method, url, data_or_params=None, raw=False,
if data_or_params is None:
data_or_params = {}
headers = {
'X-Edx-Api-Key': getattr(settings, "COMMENTS_SERVICE_KEY", None),
'X-Edx-Api-Key': config.api_key,
'Accept-Language': get_language(),
}
request_id = uuid4()
......@@ -79,7 +83,6 @@ def perform_request(method, url, data_or_params=None, raw=False,
data = None
params = merge_dict(data_or_params, request_id_dict)
with request_timer(request_id, method, url, metric_tags):
config = ForumsConfig.current()
response = requests.request(
method,
url,
......@@ -112,7 +115,7 @@ def perform_request(method, url, data_or_params=None, raw=False,
data = response.json()
except ValueError:
raise CommentClientError(
u"Comments service returned invalid JSON for request {request_id}; first 100 characters: '{content}'".format(
u"Invalid JSON response for request {request_id}; first 100 characters: '{content}'".format(
request_id=request_id,
content=response.text[:100]
)
......
......@@ -15,6 +15,7 @@ from openedx.core.djangoapps.auth_exchange.views import LoginWithAccessTokenView
from openedx.core.djangoapps.catalog.models import CatalogIntegration
from openedx.core.djangoapps.programs.models import ProgramsApiConfig
from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration
from django_comment_common.models import ForumsConfig
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
# Uncomment the next two lines to enable the admin:
......@@ -905,6 +906,7 @@ urlpatterns += (
url(r'config/self_paced', ConfigurationModelCurrentAPIView.as_view(model=SelfPacedConfiguration)),
url(r'config/programs', ConfigurationModelCurrentAPIView.as_view(model=ProgramsApiConfig)),
url(r'config/catalog', ConfigurationModelCurrentAPIView.as_view(model=CatalogIntegration)),
url(r'config/forums', ConfigurationModelCurrentAPIView.as_view(model=ForumsConfig)),
)
urlpatterns = patterns(*urlpatterns)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment