Skip to content

Commit

Permalink
model: Add toggle_topic_resolve_status function to (un)resolve topics.
Browse files Browse the repository at this point in the history
The function calls get_latest_message_in_topic to fetch recent message
in topic to be (un)resolved. It verifies user and editing conditions
using can_user_edit_topic function and finally add or remove
RESOLVED_TOPIC_PREFIX from topic name.

Fixes zulip#1075.

Co-authored-by: Shivam Deotarse <[email protected]>
  • Loading branch information
rsashank and srdeotarse committed Sep 5, 2024
1 parent 7116761 commit 82e3b87
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 0 deletions.
134 changes: 134 additions & 0 deletions tests/model/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from pytest_mock import MockerFixture
from zulip import Client, ZulipError

from zulipterminal.api_types import RESOLVED_TOPIC_PREFIX
from zulipterminal.config.symbols import STREAM_TOPIC_SEPARATOR
from zulipterminal.helper import initial_index, powerset
from zulipterminal.model import (
Expand Down Expand Up @@ -1360,6 +1361,139 @@ def test_can_user_edit_topic(
else:
report_error.assert_called_once_with(expected_response[user_type][0])

@pytest.mark.parametrize(
"topic_name, timestamp, server_feature_level, topic_editing_limit_seconds,"
" move_messages_within_stream_limit_seconds, expected_new_topic_name,"
" expected_footer_error,",
[
case(
"hi!",
11662271397,
12,
259200,
None,
RESOLVED_TOPIC_PREFIX + "hi!",
None,
id="topic_resolved:Zulip2.1+:ZFL12",
),
case(
"hi!",
11662271397,
0,
None,
None,
RESOLVED_TOPIC_PREFIX + "hi!",
None,
id="topic_resolved:Zulip2.1+:ZFL0",
),
case(
RESOLVED_TOPIC_PREFIX + "hi!",
11662271397,
0,
None,
None,
"hi!",
None,
id="topic_unresolved:Zulip2.1+:ZFL0",
),
case(
RESOLVED_TOPIC_PREFIX + "hi!",
11662271397,
10,
86400,
None,
"hi!",
None,
id="topic_unresolved:Zulip2.1+:ZFL10",
),
case(
"hi!",
11662271397,
162,
None,
86400,
RESOLVED_TOPIC_PREFIX + "hi!",
None,
id="topic_resolved:Zulip7.0+:ZFL162",
),
case(
RESOLVED_TOPIC_PREFIX + "hi!",
11662271397,
162,
None,
259200,
"hi!",
None,
id="topic_unresolved:Zulip7.0+:ZFL162",
),
case(
"hi!",
0,
12,
86400,
None,
"hi!",
" Time limit for editing topic has been exceeded.",
id="time_limit_exceeded:Zulip2.1+:ZFL12",
),
case(
"hi!",
0,
162,
None,
259200,
"hi!",
" Time limit for editing topic has been exceeded.",
id="time_limit_exceeded:Zulip7.0+:ZFL162",
),
],
)
def test_toggle_topic_resolve_status(
self,
mocker,
model,
initial_data,
topic_name,
timestamp,
server_feature_level,
topic_editing_limit_seconds,
move_messages_within_stream_limit_seconds,
expected_new_topic_name,
expected_footer_error,
stream_id=1,
):
model.initial_data = initial_data
model.server_feature_level = server_feature_level
initial_data[
"realm_community_topic_editing_limit_seconds"
] = topic_editing_limit_seconds
initial_data[
"realm_move_messages_within_stream_limit_seconds"
] = move_messages_within_stream_limit_seconds
# If user can't edit topic, topic (un)resolve is disabled. Therefore,
# default return_value=True
model.can_user_edit_topic = mocker.Mock(return_value=True)
model.get_latest_message_in_topic = mocker.Mock(
return_value={
"subject": topic_name,
"timestamp": timestamp,
"id": 1,
}
)
model.update_stream_message = mocker.Mock(return_value={"result": "success"})
report_error = model.controller.report_error

model.toggle_topic_resolve_status(stream_id, topic_name)

if not expected_footer_error:
model.update_stream_message.assert_called_once_with(
message_id=1,
topic=expected_new_topic_name,
propagate_mode="change_all",
)
else:
report_error.assert_called_once_with(expected_footer_error)

# NOTE: This tests only getting next-unread, not a fixed anchor
def test_success_get_messages(
self,
Expand Down
39 changes: 39 additions & 0 deletions zulipterminal/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
MAX_TOPIC_NAME_LENGTH,
PRESENCE_OFFLINE_THRESHOLD_SECS,
PRESENCE_PING_INTERVAL_SECS,
RESOLVED_TOPIC_PREFIX,
TYPING_STARTED_EXPIRY_PERIOD,
TYPING_STARTED_WAIT_PERIOD,
TYPING_STOPPED_WAIT_PERIOD,
Expand Down Expand Up @@ -709,6 +710,44 @@ def can_user_edit_topic(self) -> bool:
self.controller.report_error("User not found")
return False

def toggle_topic_resolve_status(self, stream_id: int, topic_name: str) -> None:
if self.can_user_edit_topic():
latest_msg = self.get_latest_message_in_topic(stream_id, topic_name)
if latest_msg:
time_since_msg_sent = time.time() - latest_msg["timestamp"]
# ZFL < 11, community_topic_editing_limit_seconds
# was hardcoded as int value in secs eg. 86400s (1 day) or None
if 11 <= self.server_feature_level < 162:
edit_time_limit = self.initial_data.get(
"realm_community_topic_editing_limit_seconds", None
)
# ZFL >= 162, realm_move_messages_within_stream_limit_seconds was
# introduced in place of realm_community_topic_editing_limit_seconds
elif self.server_feature_level >= 162:
edit_time_limit = self.initial_data.get(
"realm_move_messages_within_stream_limit_seconds", None
)
else:
edit_time_limit = 86400
# Don't allow editing topic if time-limit exceeded.
if (
edit_time_limit is not None
and time_since_msg_sent >= edit_time_limit
):
self.controller.report_error(
" Time limit for editing topic has been exceeded."
)
else:
if topic_name.startswith(RESOLVED_TOPIC_PREFIX):
topic_name = topic_name[2:]
else:
topic_name = RESOLVED_TOPIC_PREFIX + topic_name
self.update_stream_message(
message_id=latest_msg["id"],
topic=topic_name,
propagate_mode="change_all",
)

def generate_all_emoji_data(
self, custom_emoji: Dict[str, RealmEmojiData]
) -> Tuple[NamedEmojiData, List[str]]:
Expand Down

0 comments on commit 82e3b87

Please sign in to comment.