Skip to content

Commit 6f522f3

Browse files
Ali-Salman29ormsbee
authored andcommitted
feat!: remove cs_comments_service support for forum's flag APIs
This will force the use of the new v2 forum's APIs for flaging/unflaging.
1 parent 6109062 commit 6f522f3

12 files changed

Lines changed: 2307 additions & 1011 deletions

File tree

lms/djangoapps/discussion/django_comment_client/base/tests.py

Lines changed: 2 additions & 364 deletions
Large diffs are not rendered by default.

lms/djangoapps/discussion/django_comment_client/base/tests_v2.py

Lines changed: 661 additions & 10 deletions
Large diffs are not rendered by default.

lms/djangoapps/discussion/django_comment_client/tests/mixins.py

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@
88
class MockForumApiMixin:
99
"""Mixin to mock forum_api across different test cases with a single mock instance."""
1010

11-
@classmethod
12-
def setUpClass(cls):
13-
"""Apply a single forum_api mock at the class level."""
14-
cls.setUpClassAndForumMock()
15-
1611
@classmethod
1712
def setUpClassAndForumMock(cls):
1813
"""
@@ -49,11 +44,6 @@ def disposeForumMocks(cls):
4944
for patcher in cls.forum_api_patchers:
5045
patcher.stop()
5146

52-
@classmethod
53-
def tearDownClass(cls):
54-
"""Stop patches after tests complete."""
55-
cls.disposeForumMocks()
56-
5747
def set_mock_return_value(self, function_name, return_value):
5848
"""
5949
Set a return value for a specific method in forum_api mock.
@@ -65,3 +55,50 @@ def set_mock_return_value(self, function_name, return_value):
6555
setattr(
6656
self.mock_forum_api, function_name, mock.Mock(return_value=return_value)
6757
)
58+
59+
def set_mock_side_effect(self, function_name, side_effect_fn):
60+
"""
61+
Set a side effect for a specific method in forum_api mock.
62+
63+
Args:
64+
function_name (str): The method name in the mock to set a side effect for.
65+
side_effect_fn (Callable): A function to be called when the mock is called.
66+
"""
67+
setattr(
68+
self.mock_forum_api, function_name, mock.Mock(side_effect=side_effect_fn)
69+
)
70+
71+
def check_mock_called_with(self, function_name, index, *parms, **kwargs):
72+
"""
73+
Check if a specific method in forum_api mock was called with the given parameters.
74+
75+
Args:
76+
function_name (str): The method name in the mock to check.
77+
parms (tuple): The parameters to check the method was called with.
78+
"""
79+
call_args = getattr(self.mock_forum_api, function_name).call_args_list[index]
80+
assert call_args == mock.call(*parms, **kwargs)
81+
82+
def check_mock_called(self, function_name):
83+
"""
84+
Check if a specific method in the forum_api mock was called.
85+
86+
Args:
87+
function_name (str): The method name in the mock to check.
88+
89+
Returns:
90+
bool: True if the method was called, False otherwise.
91+
"""
92+
return getattr(self.mock_forum_api, function_name).called
93+
94+
def get_mock_func_calls(self, function_name):
95+
"""
96+
Returns a list of call arguments for a specific method in the mock_forum_api.
97+
98+
Args:
99+
function_name (str): The name of the method in the mock_forum_api to retrieve call arguments for.
100+
101+
Returns:
102+
list: A list of call arguments for the specified method.
103+
"""
104+
return getattr(self.mock_forum_api, function_name).call_args_list

lms/djangoapps/discussion/rest_api/tests/test_api.py

Lines changed: 0 additions & 220 deletions
Original file line numberDiff line numberDiff line change
@@ -2153,18 +2153,6 @@ def test_following(self):
21532153
assert cs_request.method == 'POST'
21542154
assert parsed_body(cs_request) == {'source_type': ['thread'], 'source_id': ['test_id']}
21552155

2156-
def test_abuse_flagged(self):
2157-
self.register_post_thread_response({"id": "test_id", "username": self.user.username})
2158-
self.register_thread_flag_response("test_id")
2159-
data = self.minimal_data.copy()
2160-
data["abuse_flagged"] = "True"
2161-
result = create_thread(self.request, data)
2162-
assert result['abuse_flagged'] is True
2163-
cs_request = httpretty.last_request()
2164-
assert urlparse(cs_request.path).path == '/api/v1/threads/test_id/abuse_flag' # lint-amnesty, pylint: disable=no-member
2165-
assert cs_request.method == 'PUT'
2166-
assert parsed_body(cs_request) == {'user_id': [str(self.user.id)]}
2167-
21682156
def test_course_id_missing(self):
21692157
with pytest.raises(ValidationError) as assertion:
21702158
create_thread(self.request, {})
@@ -2513,18 +2501,6 @@ def test_endorsed(self, role_name, is_thread_author, thread_type):
25132501
except ValidationError:
25142502
assert expected_error
25152503

2516-
def test_abuse_flagged(self):
2517-
self.register_post_comment_response({"id": "test_comment", "username": self.user.username}, "test_thread")
2518-
self.register_comment_flag_response("test_comment")
2519-
data = self.minimal_data.copy()
2520-
data["abuse_flagged"] = "True"
2521-
result = create_comment(self.request, data)
2522-
assert result['abuse_flagged'] is True
2523-
cs_request = httpretty.last_request()
2524-
assert urlparse(cs_request.path).path == '/api/v1/comments/test_comment/abuse_flag' # lint-amnesty, pylint: disable=no-member
2525-
assert cs_request.method == 'PUT'
2526-
assert parsed_body(cs_request) == {'user_id': [str(self.user.id)]}
2527-
25282504
def test_thread_id_missing(self):
25292505
with pytest.raises(ValidationError) as assertion:
25302506
create_comment(self.request, {})
@@ -2960,108 +2936,6 @@ def test_vote_count_two_users(
29602936
assert result['vote_count'] == vote_count
29612937
self.register_get_user_response(self.user, upvoted_ids=[])
29622938

2963-
@ddt.data(*itertools.product([True, False], [True, False]))
2964-
@ddt.unpack
2965-
@mock.patch("eventtracking.tracker.emit")
2966-
def test_abuse_flagged(self, old_flagged, new_flagged, mock_emit):
2967-
"""
2968-
Test attempts to edit the "abuse_flagged" field.
2969-
2970-
old_flagged indicates whether the thread should be flagged at the start
2971-
of the test. new_flagged indicates the value for the "abuse_flagged"
2972-
field in the update. If old_flagged and new_flagged are the same, no
2973-
update should be made. Otherwise, a PUT should be made to the flag or
2974-
or unflag endpoint according to the new_flagged value.
2975-
"""
2976-
self.register_get_user_response(self.user)
2977-
self.register_thread_flag_response("test_thread")
2978-
self.register_thread({"abuse_flaggers": [str(self.user.id)] if old_flagged else []})
2979-
data = {"abuse_flagged": new_flagged}
2980-
result = update_thread(self.request, "test_thread", data)
2981-
assert result['abuse_flagged'] == new_flagged
2982-
last_request_path = urlparse(httpretty.last_request().path).path # lint-amnesty, pylint: disable=no-member
2983-
flag_url = "/api/v1/threads/test_thread/abuse_flag"
2984-
unflag_url = "/api/v1/threads/test_thread/abuse_unflag"
2985-
if old_flagged == new_flagged:
2986-
assert last_request_path != flag_url
2987-
assert last_request_path != unflag_url
2988-
else:
2989-
assert last_request_path == (flag_url if new_flagged else unflag_url)
2990-
assert httpretty.last_request().method == 'PUT'
2991-
assert parsed_body(httpretty.last_request()) == {'user_id': [str(self.user.id)]}
2992-
2993-
expected_event_name = 'edx.forum.thread.reported' if new_flagged else 'edx.forum.thread.unreported'
2994-
expected_event_data = {
2995-
'body': 'Original body',
2996-
'id': 'test_thread',
2997-
'content_type': 'Post',
2998-
'commentable_id': 'original_topic',
2999-
'url': '',
3000-
'user_course_roles': [],
3001-
'user_forums_roles': [FORUM_ROLE_STUDENT],
3002-
'target_username': self.user.username,
3003-
'title_truncated': False,
3004-
'title': 'Original Title',
3005-
'thread_type': 'discussion',
3006-
'group_id': None,
3007-
'truncated': False,
3008-
}
3009-
if not new_flagged:
3010-
expected_event_data['reported_status_cleared'] = False
3011-
3012-
actual_event_name, actual_event_data = mock_emit.call_args[0]
3013-
self.assertEqual(actual_event_name, expected_event_name)
3014-
self.assertEqual(actual_event_data, expected_event_data)
3015-
3016-
@ddt.data(
3017-
(False, True),
3018-
(True, True),
3019-
)
3020-
@ddt.unpack
3021-
@mock.patch("eventtracking.tracker.emit")
3022-
def test_thread_un_abuse_flag_for_moderator_role(self, is_author, remove_all, mock_emit):
3023-
"""
3024-
Test un-abuse flag for moderator role.
3025-
3026-
When moderator unflags a reported thread, it should
3027-
pass the "all" flag to the api. This will indicate
3028-
to the api to clear all abuse_flaggers, and mark the
3029-
thread as unreported.
3030-
"""
3031-
_assign_role_to_user(user=self.user, course_id=self.course.id, role=FORUM_ROLE_ADMINISTRATOR)
3032-
self.register_get_user_response(self.user)
3033-
self.register_thread_flag_response("test_thread")
3034-
self.register_thread({"abuse_flaggers": ["11"], "user_id": str(self.user.id) if is_author else "12"})
3035-
data = {"abuse_flagged": False}
3036-
update_thread(self.request, "test_thread", data)
3037-
assert httpretty.last_request().method == 'PUT'
3038-
query_params = {'user_id': [str(self.user.id)]}
3039-
if remove_all:
3040-
query_params.update({'all': ['True']})
3041-
assert parsed_body(httpretty.last_request()) == query_params
3042-
3043-
expected_event_name = 'edx.forum.thread.unreported'
3044-
expected_event_data = {
3045-
'body': 'Original body',
3046-
'id': 'test_thread',
3047-
'content_type': 'Post',
3048-
'commentable_id': 'original_topic',
3049-
'url': '',
3050-
'user_course_roles': [],
3051-
'user_forums_roles': [FORUM_ROLE_STUDENT, FORUM_ROLE_ADMINISTRATOR],
3052-
'target_username': self.user.username,
3053-
'title_truncated': False,
3054-
'title': 'Original Title',
3055-
'reported_status_cleared': False,
3056-
'thread_type': 'discussion',
3057-
'group_id': None,
3058-
'truncated': False,
3059-
}
3060-
3061-
actual_event_name, actual_event_data = mock_emit.call_args[0]
3062-
self.assertEqual(actual_event_name, expected_event_name)
3063-
self.assertEqual(actual_event_data, expected_event_data)
3064-
30652939
def test_invalid_field(self):
30662940
self.register_thread()
30672941
with pytest.raises(ValidationError) as assertion:
@@ -3569,100 +3443,6 @@ def test_vote_count_two_users(
35693443
assert result['vote_count'] == vote_count
35703444
self.register_get_user_response(self.user, upvoted_ids=[])
35713445

3572-
@ddt.data(*itertools.product([True, False], [True, False]))
3573-
@ddt.unpack
3574-
@mock.patch("eventtracking.tracker.emit")
3575-
def test_abuse_flagged(self, old_flagged, new_flagged, mock_emit):
3576-
"""
3577-
Test attempts to edit the "abuse_flagged" field.
3578-
3579-
old_flagged indicates whether the comment should be flagged at the start
3580-
of the test. new_flagged indicates the value for the "abuse_flagged"
3581-
field in the update. If old_flagged and new_flagged are the same, no
3582-
update should be made. Otherwise, a PUT should be made to the flag or
3583-
or unflag endpoint according to the new_flagged value.
3584-
"""
3585-
self.register_get_user_response(self.user)
3586-
self.register_comment_flag_response("test_comment")
3587-
self.register_comment({"abuse_flaggers": [str(self.user.id)] if old_flagged else []})
3588-
data = {"abuse_flagged": new_flagged}
3589-
result = update_comment(self.request, "test_comment", data)
3590-
assert result['abuse_flagged'] == new_flagged
3591-
last_request_path = urlparse(httpretty.last_request().path).path # lint-amnesty, pylint: disable=no-member
3592-
flag_url = "/api/v1/comments/test_comment/abuse_flag"
3593-
unflag_url = "/api/v1/comments/test_comment/abuse_unflag"
3594-
if old_flagged == new_flagged:
3595-
assert last_request_path != flag_url
3596-
assert last_request_path != unflag_url
3597-
else:
3598-
assert last_request_path == (flag_url if new_flagged else unflag_url)
3599-
assert httpretty.last_request().method == 'PUT'
3600-
assert parsed_body(httpretty.last_request()) == {'user_id': [str(self.user.id)]}
3601-
3602-
expected_event_name = 'edx.forum.response.reported' if new_flagged else 'edx.forum.response.unreported'
3603-
expected_event_data = {
3604-
'body': 'Original body',
3605-
'id': 'test_comment',
3606-
'content_type': 'Response',
3607-
'commentable_id': 'dummy',
3608-
'url': '',
3609-
'truncated': False,
3610-
'user_course_roles': [],
3611-
'user_forums_roles': [FORUM_ROLE_STUDENT],
3612-
'target_username': self.user.username,
3613-
}
3614-
if not new_flagged:
3615-
expected_event_data['reported_status_cleared'] = False
3616-
3617-
actual_event_name, actual_event_data = mock_emit.call_args[0]
3618-
self.assertEqual(actual_event_name, expected_event_name)
3619-
self.assertEqual(actual_event_data, expected_event_data)
3620-
3621-
@ddt.data(
3622-
(False, True),
3623-
(True, True),
3624-
)
3625-
@ddt.unpack
3626-
@mock.patch("eventtracking.tracker.emit")
3627-
def test_comment_un_abuse_flag_for_moderator_role(self, is_author, remove_all, mock_emit):
3628-
"""
3629-
Test un-abuse flag for moderator role.
3630-
3631-
When moderator unflags a reported comment, it should
3632-
pass the "all" flag to the api. This will indicate
3633-
to the api to clear all abuse_flaggers, and mark the
3634-
comment as unreported.
3635-
"""
3636-
_assign_role_to_user(user=self.user, course_id=self.course.id, role=FORUM_ROLE_ADMINISTRATOR)
3637-
self.register_get_user_response(self.user)
3638-
self.register_comment_flag_response("test_comment")
3639-
self.register_comment({"abuse_flaggers": ["11"], "user_id": str(self.user.id) if is_author else "12"})
3640-
data = {"abuse_flagged": False}
3641-
update_comment(self.request, "test_comment", data)
3642-
assert httpretty.last_request().method == 'PUT'
3643-
query_params = {'user_id': [str(self.user.id)]}
3644-
if remove_all:
3645-
query_params.update({'all': ['True']})
3646-
assert parsed_body(httpretty.last_request()) == query_params
3647-
3648-
expected_event_name = 'edx.forum.response.unreported'
3649-
expected_event_data = {
3650-
'body': 'Original body',
3651-
'id': 'test_comment',
3652-
'content_type': 'Response',
3653-
'commentable_id': 'dummy',
3654-
'truncated': False,
3655-
'url': '',
3656-
'user_course_roles': [],
3657-
'user_forums_roles': [FORUM_ROLE_STUDENT, FORUM_ROLE_ADMINISTRATOR],
3658-
'target_username': self.user.username,
3659-
'reported_status_cleared': False,
3660-
}
3661-
3662-
actual_event_name, actual_event_data = mock_emit.call_args[0]
3663-
self.assertEqual(actual_event_name, expected_event_name)
3664-
self.assertEqual(actual_event_data, expected_event_data)
3665-
36663446
@ddt.data(
36673447
FORUM_ROLE_ADMINISTRATOR,
36683448
FORUM_ROLE_MODERATOR,

0 commit comments

Comments
 (0)