""" Helper functions and classes for discussion tests. """ import json from uuid import uuid4 from common.test.acceptance.fixtures import LMS_BASE_URL from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.fixtures.discussion import ( ForumsConfigMixin, MultipleThreadFixture, Response, SingleThreadViewFixture, Thread ) from common.test.acceptance.pages.lms.discussion import DiscussionTabSingleThreadPage from common.test.acceptance.tests.helpers import UniqueCourseTest class BaseDiscussionMixin(object): """ A mixin containing methods common to discussion tests. """ def setup_thread(self, num_responses, **thread_kwargs): """ Create a test thread with the given number of responses, passing all keyword arguments through to the Thread fixture, then invoke setup_thread_page. """ thread_id = "test_thread_{}".format(uuid4().hex) thread_fixture = SingleThreadViewFixture( Thread(id=thread_id, commentable_id=self.discussion_id, **thread_kwargs) ) for i in range(num_responses): thread_fixture.addResponse(Response(id=str(i), body=str(i))) thread_fixture.push() self.setup_thread_page(thread_id) return thread_id def setup_multiple_threads(self, thread_count, **thread_kwargs): """ Set up multiple threads on the page by passing 'thread_count'. """ self.thread_ids = [] # pylint: disable=attribute-defined-outside-init threads = [] # pylint: disable=attribute-defined-outside-init for i in range(thread_count): thread_id = "test_thread_{}_{}".format(i, uuid4().hex) thread_body = "Dummy long text body." * 50 threads.append( Thread(id=thread_id, commentable_id=self.discussion_id, body=thread_body, **thread_kwargs), ) self.thread_ids.append(thread_id) thread_fixture = MultipleThreadFixture(threads) thread_fixture.push() class CohortTestMixin(object): """ Mixin for tests of cohorted courses """ def setup_cohort_config(self, course_fixture, auto_cohort_groups=None): """ Sets up the course to use cohorting with the given list of auto_cohort_groups. If auto_cohort_groups is None, no auto cohorts are set. """ course_fixture._update_xblock(course_fixture._course_location, { "metadata": { u"cohort_config": { "auto_cohort_groups": auto_cohort_groups or [], "cohorted_discussions": [], "cohorted": True, }, }, }) def enable_cohorting(self, course_fixture): """ Enables cohorting for the specified course fixture. """ url = LMS_BASE_URL + "/courses/" + course_fixture._course_key + '/cohorts/settings' data = json.dumps({'is_cohorted': True}) response = course_fixture.session.patch(url, data=data, headers=course_fixture.headers) self.assertTrue(response.ok, "Failed to enable cohorts") def enable_always_divide_inline_discussions(self, course_fixture): """ Enables "always_divide_inline_discussions" (but does not enabling cohorting). """ discussions_url = LMS_BASE_URL + "/courses/" + course_fixture._course_key + '/discussions/settings' discussions_data = json.dumps({'always_divide_inline_discussions': True}) course_fixture.session.patch(discussions_url, data=discussions_data, headers=course_fixture.headers) def disable_cohorting(self, course_fixture): """ Disables cohorting for the specified course fixture. """ url = LMS_BASE_URL + "/courses/" + course_fixture._course_key + '/cohorts/settings' data = json.dumps({'is_cohorted': False}) response = course_fixture.session.patch(url, data=data, headers=course_fixture.headers) self.assertTrue(response.ok, "Failed to disable cohorts") def add_manual_cohort(self, course_fixture, cohort_name): """ Adds a cohort by name, returning its ID. """ url = LMS_BASE_URL + "/courses/" + course_fixture._course_key + '/cohorts/' data = json.dumps({"name": cohort_name, 'assignment_type': 'manual'}) response = course_fixture.session.post(url, data=data, headers=course_fixture.headers) self.assertTrue(response.ok, "Failed to create cohort") return response.json()['id'] def add_user_to_cohort(self, course_fixture, username, cohort_id): """ Adds a user to the specified cohort. """ url = LMS_BASE_URL + "/courses/" + course_fixture._course_key + "/cohorts/{}/add".format(cohort_id) data = {"users": username} course_fixture.headers['Content-type'] = 'application/x-www-form-urlencoded' response = course_fixture.session.post(url, data=data, headers=course_fixture.headers) self.assertTrue(response.ok, "Failed to add user to cohort") class BaseDiscussionTestCase(UniqueCourseTest, ForumsConfigMixin): """Base test case class for all discussions-related tests.""" def setUp(self): super(BaseDiscussionTestCase, self).setUp() self.discussion_id = "test_discussion_{}".format(uuid4().hex) self.course_fixture = CourseFixture(**self.course_info) self.course_fixture.add_children( XBlockFixtureDesc("chapter", "Test Section").add_children( XBlockFixtureDesc("sequential", "Test Subsection").add_children( XBlockFixtureDesc("vertical", "Test Unit").add_children( XBlockFixtureDesc( "discussion", "Test Discussion", metadata={"discussion_id": self.discussion_id} ) ) ) ) ) self.course_fixture.add_advanced_settings( {'discussion_topics': {'value': {'General': {'id': 'course'}}}} ) self.course_fixture.install() self.enable_forums() def create_single_thread_page(self, thread_id): """ Sets up a `DiscussionTabSingleThreadPage` for a given `thread_id`. """ return DiscussionTabSingleThreadPage(self.browser, self.course_id, self.discussion_id, thread_id)