Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix censor comment causing negative discussion count #2061

Merged
merged 5 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions src/researchhub_comment/tests/test_comments.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,3 +261,88 @@ def test_do_not_notify_unqualified_users_about_bounty(self):
notification = Notification.objects.filter(recipient=user1_with_expertise)

self.assertEqual(notification.exists(), False)

def test_censor_comment_updates_discussion_count(self):
# Create a parent comment with multiple children
parent_comment = self._create_paper_comment(self.paper.id, self.user_1)
child1 = self._create_paper_comment(
self.paper.id, self.user_2, parent_id=parent_comment.data["id"]
)
child2 = self._create_paper_comment(
self.paper.id, self.user_3, parent_id=parent_comment.data["id"]
)

# Verify initial discussion count
paper_res = self.client.get(f"/api/paper/{self.paper.id}/")
initial_count = paper_res.data["discussion_count"]
self.assertEqual(initial_count, 3)

# Censor parent comment
self.client.force_authenticate(self.moderator)
censor_res = self.client.delete(
f"/api/paper/{self.paper.id}/comments/{parent_comment.data['id']}/censor/"
)

# Verify discussion count was reduced by 3 (parent + 2 children)
paper_res = self.client.get(f"/api/paper/{self.paper.id}/")
self.assertEqual(paper_res.data["discussion_count"], 0)

def test_censor_child_with_deleted_parent_preserves_count(self):
# Create a comment chain: parent -> child1 -> child2
parent_comment = self._create_paper_comment(self.paper.id, self.user_1)
child1 = self._create_paper_comment(
self.paper.id, self.user_2, parent_id=parent_comment.data["id"]
)
child2 = self._create_paper_comment(
self.paper.id, self.user_3, parent_id=child1.data["id"]
)

# Get initial count
paper_res = self.client.get(f"/api/paper/{self.paper.id}/")
initial_count = paper_res.data["discussion_count"]
self.assertEqual(initial_count, 3)

# Censor parent first
self.client.force_authenticate(self.moderator)
self.client.delete(
f"/api/paper/{self.paper.id}/comments/{parent_comment.data['id']}/censor/"
)

# Verify count reduced by 3
paper_res = self.client.get(f"/api/paper/{self.paper.id}/")
self.assertEqual(paper_res.data["discussion_count"], 0)

# Now censor child2 - this shouldn't change the count since parent is already censored
censor_res = self.client.delete(
f"/api/paper/{self.paper.id}/comments/{child2.data['id']}/censor/"
)

paper_res = self.client.get(f"/api/paper/{self.paper.id}/")
self.assertEqual(paper_res.data["discussion_count"], 0)

def test_censor_nested_comments(self):
# Create a deeply nested chain of comments
parent = self._create_paper_comment(self.paper.id, self.user_1)
child1 = self._create_paper_comment(
self.paper.id, self.user_2, parent_id=parent.data["id"]
)
child2 = self._create_paper_comment(
self.paper.id, self.user_3, parent_id=child1.data["id"]
)
child3 = self._create_paper_comment(
self.paper.id, self.user_4, parent_id=child2.data["id"]
)

# Verify initial count
paper_res = self.client.get(f"/api/paper/{self.paper.id}/")
self.assertEqual(paper_res.data["discussion_count"], 4)

# Censor child2 (middle of chain)
self.client.force_authenticate(self.moderator)
self.client.delete(
f"/api/paper/{self.paper.id}/comments/{child2.data['id']}/censor/"
)

# Should reduce count by 2 (child2 and child3)
paper_res = self.client.get(f"/api/paper/{self.paper.id}/")
self.assertEqual(paper_res.data["discussion_count"], 2)
22 changes: 20 additions & 2 deletions src/researchhub_comment/views/rh_comment_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,26 @@ def censor_comment(comment):
if not cancelled:
raise Exception("Failed to close bounties on comment")

comment_count = len(RhCommentModel.objects.raw(query, [comment.id]))
comment._update_related_discussion_count(-comment_count)
# Only update discussion count if no parent is deleted since if a parent is deleted,
# we've already reduced the count for this comment and children. Same for if the comment
# is deleted.
if not has_deleted_parent(comment) and not comment.is_removed:
comment_count = len(RhCommentModel.objects.raw(query, [comment.id]))
comment._update_related_discussion_count(-comment_count)


def has_deleted_parent(comment):
"""Check if any parent comment is deleted/removed."""
current = comment
while current.parent_id:
try:
current = RhCommentModel.objects.get(id=current.parent_id)
if current.is_removed:
return True
except RhCommentModel.DoesNotExist:
# If we can't find the parent, treat it as deleted
return True
return False


class CommentPagination(PageNumberPagination):
Expand Down
Loading