From b837427bd54679d865f919d806afdf998a1dfd6a Mon Sep 17 00:00:00 2001 From: wajeeha-khalid Date: Wed, 9 Nov 2016 12:48:51 +0500 Subject: [PATCH] MA-2554: DiscussionAPI - fixed unread_comment_count --- lms/djangoapps/discussion_api/serializers.py | 57 +++-- .../discussion_api/tests/test_api.py | 242 ++++-------------- .../discussion_api/tests/test_serializers.py | 45 +--- .../discussion_api/tests/test_views.py | 170 ++---------- lms/djangoapps/discussion_api/tests/utils.py | 37 +++ 5 files changed, 146 insertions(+), 405 deletions(-) diff --git a/lms/djangoapps/discussion_api/serializers.py b/lms/djangoapps/discussion_api/serializers.py index 623c8e2405..cea2e4d531 100644 --- a/lms/djangoapps/discussion_api/serializers.py +++ b/lms/djangoapps/discussion_api/serializers.py @@ -76,7 +76,9 @@ def validate_not_blank(value): class _ContentSerializer(serializers.Serializer): - """A base class for thread and comment serializers.""" + """ + A base class for thread and comment serializers. + """ id = serializers.CharField(read_only=True) # pylint: disable=invalid-name author = serializers.SerializerMethodField() author_label = serializers.SerializerMethodField() @@ -121,7 +123,9 @@ class _ContentSerializer(serializers.Serializer): ) def get_author(self, obj): - """Returns the author's username, or None if the content is anonymous.""" + """ + Returns the author's username, or None if the content is anonymous. + """ return None if self._is_anonymous(obj) else obj["username"] def _get_user_label(self, user_id): @@ -136,7 +140,9 @@ class _ContentSerializer(serializers.Serializer): ) def get_author_label(self, obj): - """Returns the role label for the content author.""" + """ + Returns the role label for the content author. + """ if self._is_anonymous(obj) or obj["user_id"] is None: return None else: @@ -144,7 +150,9 @@ class _ContentSerializer(serializers.Serializer): return self._get_user_label(user_id) def get_rendered_body(self, obj): - """Returns the rendered body content.""" + """ + Returns the rendered body content. + """ return render_body(obj["body"]) def get_abuse_flagged(self, obj): @@ -162,11 +170,15 @@ class _ContentSerializer(serializers.Serializer): return obj["id"] in self.context["cc_requester"]["upvoted_ids"] def get_vote_count(self, obj): - """Returns the number of votes for the content.""" + """ + Returns the number of votes for the content. + """ return obj.get("votes", {}).get("up_count", 0) def get_editable_fields(self, obj): - """Return the list of the fields the requester can edit""" + """ + Return the list of the fields the requester can edit + """ return sorted(get_editable_fields(obj, self.context)) @@ -196,7 +208,7 @@ class ThreadSerializer(_ContentSerializer): endorsed_comment_list_url = serializers.SerializerMethodField() non_endorsed_comment_list_url = serializers.SerializerMethodField() read = serializers.BooleanField(required=False) - has_endorsed = serializers.BooleanField(read_only=True, source="endorsed") + has_endorsed = serializers.BooleanField(source="endorsed", read_only=True) response_count = serializers.IntegerField(source="resp_total", read_only=True, required=False) non_updatable_fields = NON_UPDATABLE_THREAD_FIELDS @@ -216,7 +228,9 @@ class ThreadSerializer(_ContentSerializer): return bool(obj["pinned"]) def get_group_name(self, obj): - """Returns the name of the group identified by the thread's group_id.""" + """ + Returns the name of the group identified by the thread's group_id. + """ return self.context["group_ids_to_names"].get(obj["group_id"]) def get_following(self, obj): @@ -245,22 +259,31 @@ class ThreadSerializer(_ContentSerializer): ) def get_endorsed_comment_list_url(self, obj): - """Returns the URL to retrieve the thread's endorsed comments.""" + """ + Returns the URL to retrieve the thread's endorsed comments. + """ return self.get_comment_list_url(obj, endorsed=True) def get_non_endorsed_comment_list_url(self, obj): - """Returns the URL to retrieve the thread's non-endorsed comments.""" + """ + Returns the URL to retrieve the thread's non-endorsed comments. + """ return self.get_comment_list_url(obj, endorsed=False) def get_comment_count(self, obj): - """Increments comment count to include post and returns total count of - contributions (i.e. post + responses + comments) for the thread""" + """ + Increments comment count to include post and returns total count of + contributions (i.e. post + responses + comments) for the thread + """ return obj["comments_count"] + 1 def get_unread_comment_count(self, obj): - """Increments comment count to include post if thread is unread and returns - total count of unread contributions (i.e. post + responses + comments) for the thread""" - if not obj["read"]: + """ + Returns the number of unread comments. If the thread has never been read, + this additionally includes 1 for the post itself, in addition to its responses and + comments. + """ + if not obj["read"] and obj["comments_count"] == obj["unread_comments_count"]: return obj["unread_comments_count"] + 1 return obj["unread_comments_count"] @@ -333,7 +356,9 @@ class CommentSerializer(_ContentSerializer): return None def get_endorsed_at(self, obj): - """Returns the timestamp for the endorsement, if available.""" + """ + Returns the timestamp for the endorsement, if available. + """ endorsement = obj.get("endorsement") return endorsement["time"] if endorsement else None diff --git a/lms/djangoapps/discussion_api/tests/test_api.py b/lms/djangoapps/discussion_api/tests/test_api.py index f90bbee25b..95f5b4b5ac 100644 --- a/lms/djangoapps/discussion_api/tests/test_api.py +++ b/lms/djangoapps/discussion_api/tests/test_api.py @@ -645,107 +645,67 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix def test_thread_content(self): source_threads = [ - { - "type": "thread", + make_minimal_cs_thread({ "id": "test_thread_id_0", "course_id": unicode(self.course.id), "commentable_id": "topic_x", - "group_id": None, - "user_id": str(self.author.id), "username": self.author.username, - "anonymous": False, - "anonymous_to_peers": False, - "created_at": "2015-04-28T00:00:00Z", - "updated_at": "2015-04-28T11:11:11Z", - "thread_type": "discussion", + "user_id": str(self.author.id), "title": "Test Title", "body": "Test body", - "pinned": False, - "closed": False, - "abuse_flaggers": [], "votes": {"up_count": 4}, "comments_count": 5, "unread_comments_count": 3, "endorsed": True, "read": True, - }, - { - "type": "thread", + "created_at": "2015-04-28T00:00:00Z", + "updated_at": "2015-04-28T11:11:11Z", + }), + make_minimal_cs_thread({ "id": "test_thread_id_1", "course_id": unicode(self.course.id), "commentable_id": "topic_y", "group_id": self.cohort.id, - "user_id": str(self.author.id), "username": self.author.username, - "anonymous": False, - "anonymous_to_peers": False, - "created_at": "2015-04-28T22:22:22Z", - "updated_at": "2015-04-28T00:33:33Z", + "user_id": str(self.author.id), "thread_type": "question", "title": "Another Test Title", "body": "More content", - "pinned": False, - "closed": False, - "abuse_flaggers": [], "votes": {"up_count": 9}, "comments_count": 18, - "unread_comments_count": 0, - "endorsed": False, - "read": False, - }, + "created_at": "2015-04-28T22:22:22Z", + "updated_at": "2015-04-28T00:33:33Z", + }) ] expected_threads = [ - { + self.expected_thread_data({ "id": "test_thread_id_0", - "course_id": unicode(self.course.id), - "topic_id": "topic_x", - "group_id": None, - "group_name": None, "author": self.author.username, - "author_label": None, - "created_at": "2015-04-28T00:00:00Z", - "updated_at": "2015-04-28T11:11:11Z", - "type": "discussion", - "title": "Test Title", - "raw_body": "Test body", - "rendered_body": "

Test body

", - "pinned": False, - "closed": False, - "following": False, - "abuse_flagged": False, - "voted": False, + "topic_id": "topic_x", "vote_count": 4, "comment_count": 6, "unread_comment_count": 3, "comment_list_url": "http://testserver/api/discussion/v1/comments/?thread_id=test_thread_id_0", - "endorsed_comment_list_url": None, - "non_endorsed_comment_list_url": None, "editable_fields": ["abuse_flagged", "following", "read", "voted"], "has_endorsed": True, "read": True, - }, - { + "created_at": "2015-04-28T00:00:00Z", + "updated_at": "2015-04-28T11:11:11Z", + }), + self.expected_thread_data({ "id": "test_thread_id_1", - "course_id": unicode(self.course.id), + "author": self.author.username, "topic_id": "topic_y", "group_id": self.cohort.id, "group_name": self.cohort.name, - "author": self.author.username, - "author_label": None, - "created_at": "2015-04-28T22:22:22Z", - "updated_at": "2015-04-28T00:33:33Z", "type": "question", "title": "Another Test Title", "raw_body": "More content", "rendered_body": "

More content

", - "pinned": False, - "closed": False, - "following": False, - "abuse_flagged": False, - "voted": False, "vote_count": 9, "comment_count": 19, - "unread_comment_count": 1, + "created_at": "2015-04-28T22:22:22Z", + "updated_at": "2015-04-28T00:33:33Z", "comment_list_url": None, "endorsed_comment_list_url": ( "http://testserver/api/discussion/v1/comments/?thread_id=test_thread_id_1&endorsed=True" @@ -754,9 +714,7 @@ class GetThreadListTest(ForumsEnableMixin, CommentsServiceMockMixin, UrlResetMix "http://testserver/api/discussion/v1/comments/?thread_id=test_thread_id_1&endorsed=False" ), "editable_fields": ["abuse_flagged", "following", "read", "voted"], - "has_endorsed": False, - "read": False, - }, + }), ] expected_result = make_paginated_api_response( @@ -1479,42 +1437,17 @@ class CreateThreadTest( cs_thread = make_minimal_cs_thread({ "id": "test_id", "username": self.user.username, - "created_at": "2015-05-19T00:00:00Z", - "updated_at": "2015-05-19T00:00:00Z", + "read": True, }) self.register_post_thread_response(cs_thread) with self.assert_signal_sent(api, 'thread_created', sender=None, user=self.user, exclude_args=('post',)): actual = create_thread(self.request, self.minimal_data) - expected = { + expected = self.expected_thread_data({ "id": "test_id", "course_id": unicode(self.course.id), - "topic_id": "test_topic", - "group_id": None, - "group_name": None, - "author": self.user.username, - "author_label": None, - "created_at": "2015-05-19T00:00:00Z", - "updated_at": "2015-05-19T00:00:00Z", - "type": "discussion", - "title": "Test Title", - "raw_body": "Test body", - "rendered_body": "

Test body

", - "pinned": False, - "closed": False, - "following": False, - "abuse_flagged": False, - "voted": False, - "vote_count": 0, - "comment_count": 1, - "unread_comment_count": 1, "comment_list_url": "http://testserver/api/discussion/v1/comments/?thread_id=test_id", - "endorsed_comment_list_url": None, - "non_endorsed_comment_list_url": None, - "editable_fields": ["abuse_flagged", "following", "raw_body", "read", "title", "topic_id", "type", "voted"], - 'read': False, - 'has_endorsed': False, - 'response_count': 0, - } + "read": True, + }) self.assertEqual(actual, expected) self.assertEqual( httpretty.last_request().parsed_body, @@ -2002,8 +1935,6 @@ class UpdateThreadTest( "commentable_id": "original_topic", "username": self.user.username, "user_id": str(self.user.id), - "created_at": "2015-05-29T00:00:00Z", - "updated_at": "2015-05-29T00:00:00Z", "thread_type": "discussion", "title": "Original Title", "body": "Original body", @@ -2025,37 +1956,14 @@ class UpdateThreadTest( self.register_thread() 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"}) - expected = { - "id": "test_thread", - "course_id": unicode(self.course.id), - "topic_id": "original_topic", - "group_id": None, - "group_name": None, - "author": self.user.username, - "author_label": None, - "created_at": "2015-05-29T00:00:00Z", - "updated_at": "2015-05-29T00:00:00Z", - "type": "discussion", - "title": "Original Title", + + self.assertEqual(actual, self.expected_thread_data({ "raw_body": "Edited body", "rendered_body": "

Edited body

", - "pinned": False, - "closed": False, - "following": False, - "abuse_flagged": False, - "voted": False, - "vote_count": 0, - "comment_count": 1, - "unread_comment_count": 0, - "comment_list_url": "http://testserver/api/discussion/v1/comments/?thread_id=test_thread", - "endorsed_comment_list_url": None, - "non_endorsed_comment_list_url": None, - "editable_fields": ["abuse_flagged", "following", "raw_body", "read", "title", "topic_id", "type", "voted"], - 'read': True, - 'has_endorsed': False, - 'response_count': 0 - } - self.assertEqual(actual, expected) + "topic_id": "original_topic", + "read": True, + "title": "Original Title", + })) self.assertEqual( httpretty.last_request().parsed_body, { @@ -3096,12 +3004,12 @@ class RetrieveThreadTest( httpretty.reset() httpretty.enable() self.addCleanup(httpretty.disable) - self.thread_author = UserFactory.create() - self.register_get_user_response(self.thread_author) + self.user = UserFactory.create() + self.register_get_user_response(self.user) self.request = RequestFactory().get("/test_path") - self.request.user = self.thread_author + self.request.user = self.user self.thread_id = "test_thread" - CourseEnrollmentFactory.create(user=self.thread_author, course_id=self.course.id) + CourseEnrollmentFactory.create(user=self.user, course_id=self.course.id) def register_thread(self, overrides=None): """ @@ -3113,12 +3021,10 @@ class RetrieveThreadTest( "id": self.thread_id, "course_id": unicode(self.course.id), "commentable_id": "test_topic", - "username": self.thread_author.username, - "user_id": str(self.thread_author.id), + "username": self.user.username, + "user_id": str(self.user.id), "title": "Test Title", "body": "Test body", - "created_at": "2015-05-29T00:00:00Z", - "updated_at": "2015-05-29T00:00:00Z", "resp_total": 0, }) @@ -3126,38 +3032,11 @@ class RetrieveThreadTest( self.register_get_thread_response(cs_data) def test_basic(self): - expected_response_data = { - "author": self.thread_author.username, - "author_label": None, - "created_at": "2015-05-29T00:00:00Z", - "updated_at": "2015-05-29T00:00:00Z", - "raw_body": "Test body", - "rendered_body": "

Test body

", - "abuse_flagged": False, - "voted": False, - "vote_count": 0, - "editable_fields": ["abuse_flagged", "following", "raw_body", "read", "title", "topic_id", "type", "voted"], - "course_id": unicode(self.course.id), - "topic_id": "test_topic", - "group_id": None, - "group_name": None, - "title": "Test Title", - "pinned": False, - "closed": False, - "following": False, - "comment_count": 1, - "unread_comment_count": 1, - "comment_list_url": "http://testserver/api/discussion/v1/comments/?thread_id=test_thread", - "endorsed_comment_list_url": None, - "non_endorsed_comment_list_url": None, - "read": False, - "has_endorsed": False, - "id": "test_thread", - "type": "discussion", - "response_count": 2, - } self.register_thread({"resp_total": 2}) - self.assertEqual(get_thread(self.request, self.thread_id), expected_response_data) + self.assertEqual(get_thread(self.request, self.thread_id), self.expected_thread_data({ + "response_count": 2, + "unread_comment_count": 1, + })) self.assertEqual(httpretty.last_request().method, "GET") def test_thread_id_not_found(self): @@ -3166,42 +3045,15 @@ class RetrieveThreadTest( get_thread(self.request, "missing_thread") def test_nonauthor_enrolled_in_course(self): - expected_response_data = { - "author": self.thread_author.username, - "author_label": None, - "created_at": "2015-05-29T00:00:00Z", - "updated_at": "2015-05-29T00:00:00Z", - "raw_body": "Test body", - "rendered_body": "

Test body

", - "abuse_flagged": False, - "voted": False, - "vote_count": 0, - "editable_fields": ["abuse_flagged", "following", "read", "voted"], - "course_id": unicode(self.course.id), - "topic_id": "test_topic", - "group_id": None, - "group_name": None, - "title": "Test Title", - "pinned": False, - "closed": False, - "following": False, - "comment_count": 1, - "unread_comment_count": 1, - "comment_list_url": "http://testserver/api/discussion/v1/comments/?thread_id=test_thread", - "endorsed_comment_list_url": None, - "non_endorsed_comment_list_url": None, - "read": False, - "has_endorsed": False, - "id": "test_thread", - "type": "discussion", - "response_count": 0, - } non_author_user = UserFactory.create() self.register_get_user_response(non_author_user) CourseEnrollmentFactory.create(user=non_author_user, course_id=self.course.id) self.register_thread() self.request.user = non_author_user - self.assertEqual(get_thread(self.request, self.thread_id), expected_response_data) + self.assertEqual(get_thread(self.request, self.thread_id), self.expected_thread_data({ + "editable_fields": ["abuse_flagged", "following", "read", "voted"], + "unread_comment_count": 1, + })) self.assertEqual(httpretty.last_request().method, "GET") def test_not_enrolled_in_course(self): @@ -3233,10 +3085,10 @@ class RetrieveThreadTest( the student role is the author and the thread is in the author's cohort. """ cohort_course = CourseFactory.create(cohort_config={"cohorted": course_is_cohorted}) - CourseEnrollmentFactory.create(user=self.thread_author, course_id=cohort_course.id) - cohort = CohortFactory.create(course_id=cohort_course.id, users=[self.thread_author]) + CourseEnrollmentFactory.create(user=self.user, course_id=cohort_course.id) + cohort = CohortFactory.create(course_id=cohort_course.id, users=[self.user]) role = Role.objects.create(name=role_name, course_id=cohort_course.id) - role.users = [self.thread_author] + role.users = [self.user] self.register_thread({ "course_id": unicode(cohort_course.id), "group_id": ( diff --git a/lms/djangoapps/discussion_api/tests/test_serializers.py b/lms/djangoapps/discussion_api/tests/test_serializers.py index 0b78746897..c38c8de24f 100644 --- a/lms/djangoapps/discussion_api/tests/test_serializers.py +++ b/lms/djangoapps/discussion_api/tests/test_serializers.py @@ -161,60 +161,27 @@ class ThreadSerializerSerializationTest(SerializerTestMixin, SharedModuleStoreTe return ThreadSerializer(thread, context=get_context(self.course, self.request)).data def test_basic(self): - thread = { - "type": "thread", + thread = make_minimal_cs_thread({ "id": "test_thread", "course_id": unicode(self.course.id), "commentable_id": "test_topic", - "group_id": None, "user_id": str(self.author.id), "username": self.author.username, - "anonymous": False, - "anonymous_to_peers": False, - "created_at": "2015-04-28T00:00:00Z", - "updated_at": "2015-04-28T11:11:11Z", - "thread_type": "discussion", "title": "Test Title", "body": "Test body", "pinned": True, - "closed": False, - "abuse_flaggers": [], "votes": {"up_count": 4}, "comments_count": 5, "unread_comments_count": 3, - "read": False, - "endorsed": False, - "response_count": None, - } - expected = { - "id": "test_thread", - "course_id": unicode(self.course.id), - "topic_id": "test_topic", - "group_id": None, - "group_name": None, + }) + expected = self.expected_thread_data({ "author": self.author.username, - "author_label": None, - "created_at": "2015-04-28T00:00:00Z", - "updated_at": "2015-04-28T11:11:11Z", - "type": "discussion", - "title": "Test Title", - "raw_body": "Test body", - "rendered_body": "

Test body

", - "pinned": True, - "closed": False, - "following": False, - "abuse_flagged": False, - "voted": False, "vote_count": 4, "comment_count": 6, - "unread_comment_count": 4, - "comment_list_url": "http://testserver/api/discussion/v1/comments/?thread_id=test_thread", - "endorsed_comment_list_url": None, - "non_endorsed_comment_list_url": None, + "unread_comment_count": 3, + "pinned": True, "editable_fields": ["abuse_flagged", "following", "read", "voted"], - "read": False, - "has_endorsed": False, - } + }) self.assertEqual(self.serialize(thread), expected) thread["thread_type"] = "question" diff --git a/lms/djangoapps/discussion_api/tests/test_views.py b/lms/djangoapps/discussion_api/tests/test_views.py index 2bb961e4f8..cba01d4fad 100644 --- a/lms/djangoapps/discussion_api/tests/test_views.py +++ b/lms/djangoapps/discussion_api/tests/test_views.py @@ -77,12 +77,12 @@ class DiscussionAPIViewTestMixin(ForumsEnableMixin, CommentsServiceMockMixin, Ur cs_thread = make_minimal_cs_thread({ "id": "test_thread", "course_id": unicode(self.course.id), - "commentable_id": "original_topic", + "commentable_id": "test_topic", "username": self.user.username, "user_id": str(self.user.id), "thread_type": "discussion", - "title": "Original Title", - "body": "Original body", + "title": "Test Title", + "body": "Test body", }) cs_thread.update(overrides or {}) self.register_get_thread_response(cs_thread) @@ -318,43 +318,6 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro self.author = UserFactory.create() self.url = reverse("thread-list") - def make_expected_thread(self, overrides=None): - """ - Create a sample expected thread for response - """ - thread = { - "id": "test_thread", - "course_id": unicode(self.course.id), - "topic_id": "test_topic", - "group_id": None, - "group_name": None, - "author": "dummy", - "author_label": None, - "created_at": "1970-01-01T00:00:00Z", - "updated_at": "1970-01-01T00:00:00Z", - "type": "discussion", - "title": "dummy", - "raw_body": "dummy", - "rendered_body": "

dummy

", - "pinned": False, - "closed": False, - "following": False, - "abuse_flagged": False, - "voted": False, - "vote_count": 0, - "comment_count": 1, - "unread_comment_count": 1, - "comment_list_url": "http://testserver/api/discussion/v1/comments/?thread_id=test_thread", - "endorsed_comment_list_url": None, - "non_endorsed_comment_list_url": None, - "editable_fields": ["abuse_flagged", "following", "read", "voted"], - "read": False, - "has_endorsed": False, - "response_count": 0, - } - thread.update(overrides or {}) - return thread - def create_source_thread(self, overrides=None): """ Create a sample source cs_thread @@ -398,17 +361,15 @@ class ThreadViewSetListTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, Pro source_threads = [ self.create_source_thread({"user_id": str(self.author.id), "username": self.author.username}) ] - expected_threads = [self.make_expected_thread({ + expected_threads = [self.expected_thread_data({ "created_at": "2015-04-28T00:00:00Z", "updated_at": "2015-04-28T11:11:11Z", - "raw_body": "Test body", - "rendered_body": "

Test body

", - "title": "Test Title", "vote_count": 4, "comment_count": 6, - "unread_comment_count": 4, + "unread_comment_count": 3, "voted": True, - "author": self.author.username + "author": self.author.username, + "editable_fields": ["abuse_flagged", "following", "read", "voted"], })] self.register_get_threads_response(source_threads, page=1, num_pages=2) response = self.client.get(self.url, {"course_id": unicode(self.course.id), "following": ""}) @@ -701,8 +662,6 @@ class ThreadViewSetCreateTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase): cs_thread = make_minimal_cs_thread({ "id": "test_thread", "username": self.user.username, - "created_at": "2015-05-19T00:00:00Z", - "updated_at": "2015-05-19T00:00:00Z", "read": True, }) self.register_post_thread_response(cs_thread) @@ -713,36 +672,6 @@ class ThreadViewSetCreateTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase): "title": "Test Title", "raw_body": "Test body", } - expected_response_data = { - "id": "test_thread", - "course_id": unicode(self.course.id), - "topic_id": "test_topic", - "group_id": None, - "group_name": None, - "author": self.user.username, - "author_label": None, - "created_at": "2015-05-19T00:00:00Z", - "updated_at": "2015-05-19T00:00:00Z", - "type": "discussion", - "title": "Test Title", - "raw_body": "Test body", - "rendered_body": "

Test body

", - "pinned": False, - "closed": False, - "following": False, - "abuse_flagged": False, - "voted": False, - "vote_count": 0, - "comment_count": 1, - "unread_comment_count": 0, - "comment_list_url": "http://testserver/api/discussion/v1/comments/?thread_id=test_thread", - "endorsed_comment_list_url": None, - "non_endorsed_comment_list_url": None, - "editable_fields": ["abuse_flagged", "following", "raw_body", "read", "title", "topic_id", "type", "voted"], - "read": True, - "has_endorsed": False, - "response_count": 0, - } response = self.client.post( self.url, json.dumps(request_data), @@ -750,7 +679,7 @@ class ThreadViewSetCreateTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase): ) self.assertEqual(response.status_code, 200) response_data = json.loads(response.content) - self.assertEqual(response_data, expected_response_data) + self.assertEqual(response_data, self.expected_thread_data({"read": True})) self.assertEqual( httpretty.last_request().parsed_body, { @@ -795,43 +724,6 @@ class ThreadViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTest super(ThreadViewSetPartialUpdateTest, self).setUp() self.url = reverse("thread-detail", kwargs={"thread_id": "test_thread"}) - def expected_response_data(self, overrides=None): - """ - create expected response data from comment update endpoint - """ - response_data = { - "id": "test_thread", - "course_id": unicode(self.course.id), - "topic_id": "original_topic", - "group_id": None, - "group_name": None, - "author": self.user.username, - "author_label": None, - "created_at": "1970-01-01T00:00:00Z", - "updated_at": "1970-01-01T00:00:00Z", - "type": "discussion", - "title": "Original Title", - "raw_body": "Original body", - "rendered_body": "

Original body

", - "pinned": False, - "closed": False, - "following": False, - "abuse_flagged": False, - "voted": False, - "vote_count": 0, - "comment_count": 0, - "unread_comment_count": 0, - "comment_list_url": "http://testserver/api/discussion/v1/comments/?thread_id=test_thread", - "endorsed_comment_list_url": None, - "non_endorsed_comment_list_url": None, - "editable_fields": [], - "read": False, - "has_endorsed": False, - "response_count": 0, - } - response_data.update(overrides or {}) - return response_data - def test_basic(self): self.register_get_user_response(self.user) self.register_thread({ @@ -846,7 +738,7 @@ class ThreadViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTest response_data = json.loads(response.content) self.assertEqual( response_data, - self.expected_response_data({ + self.expected_thread_data({ "raw_body": "Edited body", "rendered_body": "

Edited body

", "editable_fields": [ @@ -863,9 +755,9 @@ class ThreadViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTest httpretty.last_request().parsed_body, { "course_id": [unicode(self.course.id)], - "commentable_id": ["original_topic"], + "commentable_id": ["test_topic"], "thread_type": ["discussion"], - "title": ["Original Title"], + "title": ["Test Title"], "body": ["Edited body"], "user_id": [str(self.user.id)], "anonymous": ["False"], @@ -903,7 +795,7 @@ class ThreadViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTest response_data = json.loads(response.content) self.assertEqual( response_data, - self.expected_response_data({ + self.expected_thread_data({ "read": True, "closed": True, "abuse_flagged": value, @@ -938,7 +830,7 @@ class ThreadViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTest response_data = json.loads(response.content) self.assertEqual( response_data, - self.expected_response_data({ + self.expected_thread_data({ "comment_count": 1, "read": True, "editable_fields": [ @@ -966,7 +858,7 @@ class ThreadViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTest response_data = json.loads(response.content) self.assertEqual( response_data, - self.expected_response_data({ + self.expected_thread_data({ "author": str(thread_owner_user.username), "comment_count": 1, "read": True, @@ -1655,43 +1547,11 @@ class ThreadViewSetRetrieveTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase, "user_id": str(self.user.id), "title": "Test Title", "body": "Test body", - "created_at": "2015-05-29T00:00:00Z", - "updated_at": "2015-05-29T00:00:00Z" }) - expected_response_data = { - "author": self.user.username, - "author_label": None, - "created_at": "2015-05-29T00:00:00Z", - "updated_at": "2015-05-29T00:00:00Z", - "raw_body": "Test body", - "rendered_body": "

Test body

", - "abuse_flagged": False, - "voted": False, - "vote_count": 0, - "editable_fields": ["abuse_flagged", "following", "raw_body", "read", "title", "topic_id", "type", "voted"], - "course_id": unicode(self.course.id), - "topic_id": "test_topic", - "group_id": None, - "group_name": None, - "title": "Test Title", - "pinned": False, - "closed": False, - "following": False, - "comment_count": 1, - "unread_comment_count": 1, - "comment_list_url": "http://testserver/api/discussion/v1/comments/?thread_id=test_thread", - "endorsed_comment_list_url": None, - "non_endorsed_comment_list_url": None, - "read": False, - "has_endorsed": False, - "id": "test_thread", - "type": "discussion", - "response_count": 0, - } self.register_get_thread_response(cs_thread) response = self.client.get(self.url) self.assertEqual(response.status_code, 200) - self.assertEqual(json.loads(response.content), expected_response_data) + self.assertEqual(json.loads(response.content), self.expected_thread_data({"unread_comment_count": 1})) self.assertEqual(httpretty.last_request().method, "GET") def test_retrieve_nonexistent_thread(self): diff --git a/lms/djangoapps/discussion_api/tests/utils.py b/lms/djangoapps/discussion_api/tests/utils.py index c02e7c0a60..dde68bd938 100644 --- a/lms/djangoapps/discussion_api/tests/utils.py +++ b/lms/djangoapps/discussion_api/tests/utils.py @@ -335,6 +335,43 @@ class CommentsServiceMockMixin(object): content_type="application/merge-patch+json" ) + def expected_thread_data(self, overrides=None): + """ + Returns expected thread data in API response + """ + response_data = { + "author": self.user.username, + "author_label": None, + "created_at": "1970-01-01T00:00:00Z", + "updated_at": "1970-01-01T00:00:00Z", + "raw_body": "Test body", + "rendered_body": "

Test body

", + "abuse_flagged": False, + "voted": False, + "vote_count": 0, + "editable_fields": ["abuse_flagged", "following", "raw_body", "read", "title", "topic_id", "type", "voted"], + "course_id": unicode(self.course.id), + "topic_id": "test_topic", + "group_id": None, + "group_name": None, + "title": "Test Title", + "pinned": False, + "closed": False, + "following": False, + "comment_count": 1, + "unread_comment_count": 0, + "comment_list_url": "http://testserver/api/discussion/v1/comments/?thread_id=test_thread", + "endorsed_comment_list_url": None, + "non_endorsed_comment_list_url": None, + "read": False, + "has_endorsed": False, + "id": "test_thread", + "type": "discussion", + "response_count": 0, + } + response_data.update(overrides or {}) + return response_data + def make_minimal_cs_thread(overrides=None): """