""" Tools for creating discussion content fixture data. """ from datetime import datetime import json 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): class Meta(object): model = dict id = None user_id = "1234" username = "dummy-username" course_id = "dummy-course-id" commentable_id = "dummy-commentable-id" anonymous = False anonymous_to_peers = False at_position_list = [] abuse_flaggers = [] created_at = datetime.utcnow().isoformat() updated_at = datetime.utcnow().isoformat() endorsed = False closed = False votes = {"up_count": 0} @classmethod def _adjust_kwargs(cls, **kwargs): # The discussion code assumes that user_id is a string. This ensures that it always will be. if 'user_id' in kwargs: kwargs['user_id'] = str(kwargs['user_id']) return kwargs class Thread(ContentFactory): thread_type = "discussion" anonymous = False anonymous_to_peers = False comments_count = 0 unread_comments_count = 0 title = "dummy thread title" body = "dummy thread body" type = "thread" group_id = None pinned = False read = False class Comment(ContentFactory): thread_id = "dummy thread" depth = 0 type = "comment" body = "dummy comment body" class Response(Comment): depth = 1 body = "dummy response body" class SearchResult(factory.Factory): class Meta(object): model = dict discussion_data = [] annotated_content_info = {} num_pages = 1 page = 1 corrected_text = None class DiscussionContentFixture(object): def push(self): """ Push the data to the stub comments service. """ requests.put( '{}/set_config'.format(COMMENTS_STUB_URL), data=self.get_config_data() ) def get_config_data(self): """ return a dictionary with the fixture's data serialized for PUTting to the stub server's config endpoint. """ raise NotImplementedError() class SingleThreadViewFixture(DiscussionContentFixture): def __init__(self, thread): self.thread = thread def addResponse(self, response, comments=[]): response['children'] = comments if self.thread["thread_type"] == "discussion": responseListAttr = "children" elif response["endorsed"]: responseListAttr = "endorsed_responses" else: responseListAttr = "non_endorsed_responses" self.thread.setdefault(responseListAttr, []).append(response) self.thread['comments_count'] += len(comments) + 1 def _get_comment_map(self): """ Generate a dict mapping each response/comment in the thread by its `id`. """ def _visit(obj): res = [] for child in obj.get('children', []): res.append((child['id'], child)) if 'children' in child: res += _visit(child) return res return dict(_visit(self.thread)) def get_config_data(self): return { "threads": json.dumps({self.thread['id']: self.thread}), "comments": json.dumps(self._get_comment_map()) } class MultipleThreadFixture(DiscussionContentFixture): def __init__(self, threads): self.threads = threads def get_config_data(self): threads_list = {thread['id']: thread for thread in self.threads} return {"threads": json.dumps(threads_list), "comments": '{}'} def add_response(self, response, comments, thread): """ Add responses to the thread """ response['children'] = comments if thread["thread_type"] == "discussion": response_list_attr = "children" elif response["endorsed"]: response_list_attr = "endorsed_responses" else: response_list_attr = "non_endorsed_responses" thread.setdefault(response_list_attr, []).append(response) thread['comments_count'] += len(comments) + 1 class UserProfileViewFixture(DiscussionContentFixture): def __init__(self, threads): self.threads = threads def get_config_data(self): return {"active_threads": json.dumps(self.threads)} class SearchResultFixture(DiscussionContentFixture): def __init__(self, result): self.result = result 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()