discussion.py 4.91 KB
Newer Older
1 2 3 4 5
"""
Tools for creating discussion content fixture data.
"""

import json
6
from datetime import datetime
7 8 9 10

import factory
import requests

11
from common.test.acceptance.fixtures import COMMENTS_STUB_URL
12
from common.test.acceptance.fixtures.config import ConfigModelFixture
13 14 15


class ContentFactory(factory.Factory):
16
    class Meta(object):
muhammad-ammar committed
17
        model = dict
18

19
    id = None
20
    user_id = "1234"
21 22 23 24 25 26 27 28 29 30 31 32 33
    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}

34 35 36 37 38 39 40
    @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

41 42

class Thread(ContentFactory):
43
    thread_type = "discussion"
44 45
    anonymous = False
    anonymous_to_peers = False
46 47 48 49 50 51 52 53
    comments_count = 0
    unread_comments_count = 0
    title = "dummy thread title"
    body = "dummy thread body"
    type = "thread"
    group_id = None
    pinned = False
    read = False
54
    context = "course"
55

56

57
class Comment(ContentFactory):
58
    thread_id = "dummy thread"
59 60 61 62 63 64 65 66 67 68
    depth = 0
    type = "comment"
    body = "dummy comment body"


class Response(Comment):
    depth = 1
    body = "dummy response body"


69
class SearchResult(factory.Factory):
70
    class Meta(object):
muhammad-ammar committed
71
        model = dict
72

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
    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):
99 100 101 102 103 104

    def __init__(self, thread):
        self.thread = thread

    def addResponse(self, response, comments=[]):
        response['children'] = comments
105 106 107 108 109 110 111
        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)
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
        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))

128 129 130 131 132
    def get_config_data(self):
        return {
            "threads": json.dumps({self.thread['id']: self.thread}),
            "comments": json.dumps(self._get_comment_map())
        }
133

134

135 136 137 138 139 140 141 142 143
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": '{}'}

144 145 146 147 148 149 150 151 152 153 154 155 156 157
    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

158

159
class UserProfileViewFixture(DiscussionContentFixture):
160 161 162 163

    def __init__(self, threads):
        self.threads = threads

164 165 166 167 168 169 170 171 172 173 174
    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)}
175 176 177 178 179 180 181 182 183


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()