web: Add is:watched alias for search operator.

This commit replaces `is:alerted` with `is:watched` as part of the migration from
alert words to watched phrases.
This commit is contained in:
Aditya Kumar Kasaudhan 2024-11-07 15:38:57 +05:30
parent 1ff669c1d4
commit 46b57e6605
20 changed files with 135 additions and 93 deletions

View File

@ -43,7 +43,7 @@ const alert_regex_replacements = new Map<string, string>([
export function process_message(message: Message): void {
// Parsing for alert words is expensive, so we rely on the host
// to tell us there any alert words to even look for.
if (!message.alerted) {
if (!message.watched) {
return;
}
@ -89,7 +89,7 @@ export function notifies(message: Message): boolean {
// alert words into a message, just because that can be annoying for
// certain types of workflows where everybody on your team, including
// yourself, sets up an alert word to effectively mention the team.
return !people.is_current_user(message.sender_email) && message.alerted;
return !people.is_current_user(message.sender_email) && message.watched;
}
export const initialize = (params: StateData["alert_words"]): void => {

View File

@ -73,7 +73,7 @@ type LocalEditRequest = Partial<{
starred: boolean;
historical: boolean;
collapsed: boolean;
alerted: boolean;
watched: boolean;
mentioned: boolean;
mentioned_me_directly: boolean;
}>;
@ -403,7 +403,7 @@ export function edit_locally(message: Message, request: LocalEditRequest): Messa
message.content = request.content;
message.mentioned = request.mentioned ?? false;
message.mentioned_me_directly = request.mentioned_me_directly ?? false;
message.alerted = request.alerted ?? false;
message.watched = request.watched ?? false;
} else {
// Otherwise, we Markdown-render the message; this resets
// all flags, so we need to restore those flags that are

View File

@ -167,8 +167,8 @@ function message_matches_search_term(message: Message, operator: string, operand
return message.starred;
case "mentioned":
return message.mentioned;
case "alerted":
return message.alerted;
case "watched":
return message.watched;
case "unread":
return message.unread;
case "resolved":
@ -553,7 +553,7 @@ export class Filter {
"private",
"starred",
"mentioned",
"alerted",
"watched",
"unread",
"resolved",
"followed",
@ -646,7 +646,7 @@ export class Filter {
"sender",
"near",
"id",
"is-alerted",
"is-watched",
"is-mentioned",
"is-dm",
"is-starred",
@ -1412,8 +1412,8 @@ export class Filter {
// These cases return false for is_common_narrow, and therefore are not
// formatted in the message view header. They are used in narrow.js to
// update the browser title.
case "is-alerted":
return $t({defaultMessage: "Alerted messages"});
case "is-watched":
return $t({defaultMessage: "Messages with watched phrases"});
case "is-unread":
return $t({defaultMessage: "Unread messages"});
}

View File

@ -81,7 +81,7 @@ type EchoedMessageData = {
// These flags are rendering artifacts we'll want if the
// edit fails and we need to revert to the original
// rendering of the message.
alerted: boolean;
watched: boolean;
mentioned: boolean;
mentioned_me_directly: boolean;
};
@ -1135,7 +1135,7 @@ export function save_message_row_edit($row: JQuery): void {
starred: message.starred,
historical: message.historical,
collapsed: message.collapsed,
alerted: message.alerted,
watched: message.watched,
mentioned: message.mentioned,
mentioned_me_directly: message.mentioned,
});
@ -1194,7 +1194,7 @@ export function save_message_row_edit($row: JQuery): void {
raw_content: echo_data.orig_raw_content,
mentioned: echo_data.mentioned,
mentioned_me_directly: echo_data.mentioned_me_directly,
alerted: echo_data.alerted,
watched: echo_data.watched,
});
$row = message_lists.current.get_row(message_id);

View File

@ -124,7 +124,7 @@ export let update_views_filtered_on_message_property = (
"is-starred",
"is-unread",
"is-mentioned",
"is-alerted",
"is-watched",
];
if (message_ids.length === 0 || !supported_term_types.includes(property_term_type)) {
@ -777,8 +777,8 @@ export function update_messages(events) {
"is-mentioned",
is_mentioned,
);
const is_alerted = event.flags.includes("has_alert_word");
update_views_filtered_on_message_property([event.message_id], "is-alerted", is_alerted);
const is_watched = event.flags.includes("has_alert_word");
update_views_filtered_on_message_property([event.message_id], "is-watched", is_watched);
}
}

View File

@ -79,7 +79,7 @@ function debug_notification_source_value(message: Message | TestNotificationMess
notification_source = "pm";
} else if (message.mentioned) {
notification_source = "mention";
} else if (message.alerted) {
} else if (message.watched) {
notification_source = "alert";
} else {
notification_source = "stream";

View File

@ -120,7 +120,7 @@ export type MessageWithBooleans = (
topic_wildcard_mentioned: boolean;
collapsed: boolean;
condensed?: boolean;
alerted: boolean;
watched: boolean;
};
export type MessageCleanReaction = {
@ -258,7 +258,7 @@ export function convert_raw_message_to_message_with_booleans(
stream_wildcard_mentioned: convert_flag("stream_wildcard_mentioned"),
topic_wildcard_mentioned: convert_flag("topic_wildcard_mentioned"),
collapsed: convert_flag("collapsed"),
alerted: convert_flag("has_alert_word"),
watched: convert_flag("has_alert_word"),
};
// Once we have set boolean flags here, the `flags` attribute is
@ -294,7 +294,7 @@ export function update_booleans(message: Message, flags: string[]): void {
message.mentioned_me_directly = convert_flag("mentioned");
message.stream_wildcard_mentioned = convert_flag("stream_wildcard_mentioned");
message.topic_wildcard_mentioned = convert_flag("topic_wildcard_mentioned");
message.alerted = convert_flag("has_alert_word");
message.watched = convert_flag("has_alert_word");
}
export function update_sender_full_name(user_id: number, new_name: string): void {

View File

@ -688,10 +688,10 @@ function get_is_filter_suggestions(last: NarrowTerm, terms: NarrowTerm[]): Sugge
],
},
{
search_string: "is:alerted",
search_string: "is:watched",
description_html: "messages with watched phrases",
is_people: false,
incompatible_patterns: [{operator: "is", operand: "alerted"}],
incompatible_patterns: [{operator: "is", operand: "watched"}],
},
{
search_string: "is:unread",

View File

@ -30,7 +30,11 @@
{{~!-- squash whitespace --~}}
{{this.verb}}@-mentions
{{~!-- squash whitespace --~}}
{{else if (or (eq this.operand "starred") (eq this.operand "alerted") (eq this.operand "unread"))}}
{{else if (eq this.operand "watched")}}
{{~!-- squash whitespace --~}}
{{this.verb}}Messages with watched phrases
{{~!-- squash whitespace --~}}
{{else if (or (eq this.operand "starred") (eq this.operand "unread"))}}
{{~!-- squash whitespace --~}}
{{this.verb}}{{this.operand}} messages
{{~!-- squash whitespace --~}}

View File

@ -110,7 +110,7 @@
</td>
</tr>
<tr>
<td class="operator">is:alerted</td>
<td class="operator">is:watched</td>
<td class="definition">
{{t 'Narrow to messages with watched phrases.'}}
</td>

View File

@ -44,62 +44,62 @@ const regular_message = {
const own_message = {
sender_email: "tester@zulip.com",
content: "<p>hey this message alertone</p>",
alerted: true,
watched: true,
};
const other_message = {
sender_email: "another@zulip.com",
content: "<p>another alertone message</p>",
alerted: true,
watched: true,
};
const caps_message = {
sender_email: "another@zulip.com",
content: "<p>another ALERTtwo message</p>",
alerted: true,
watched: true,
};
const alertwordboundary_message = {
sender_email: "another@zulip.com",
content: "<p>another alertthreemessage</p>",
alerted: false,
watched: false,
};
const multialert_message = {
sender_email: "another@zulip.com",
content: "<p>another emoji alertone and then alerttwo</p>",
alerted: true,
watched: true,
};
const unsafe_word_message = {
sender_email: "another@zulip.com",
content: "<p>gotta al*rt.*s all</p>",
alerted: true,
watched: true,
};
const alert_in_url_message = {
sender_email: "another@zulip.com",
content: "<p>http://www.google.com/alertone/me</p>",
alerted: true,
watched: true,
};
const question_word_message = {
sender_email: "another@zulip.com",
content: "<p>still alertone? me</p>",
alerted: true,
watched: true,
};
const typo_word_message = {
sender_email: "another@zulip.com",
content: "<p>alertones alerttwo alerttwo alertthreez</p>",
alerted: true,
watched: true,
};
const alert_domain_message = {
sender_email: "another@zulip.com",
content:
'<p>now with link <a href="http://www.alerttwo.us/foo/bar" target="_blank" title="http://www.alerttwo.us/foo/bar">www.alerttwo.us/foo/bar</a></p>',
alerted: true,
watched: true,
};
// This test ensure we are not mucking up rendered HTML content.
const message_with_emoji = {
sender_email: "another@zulip.com",
content:
'<p>I <img alt=":heart:" class="emoji" src="/static/generated/emoji/images/emoji/unicode/2764.png" title="heart"> emoji!</p>',
alerted: true,
watched: true,
};
run_test("notifications", () => {
@ -188,7 +188,7 @@ run_test("munging", () => {
{
sender_email: "another@zulip.com",
content: `<p>FD&amp;C &lt;3 &gt;8 5'11" 5&#39;11&quot;</p>`,
alerted: true,
watched: true,
},
`<p><span class='alert-word'>FD&amp;C</span> <span class='alert-word'>&lt;3</span> <span class='alert-word'>&gt;8</span> <span class='alert-word'>5'11"</span> <span class='alert-word'>5&#39;11&quot;</span></p>`,
);

View File

@ -68,14 +68,14 @@ run_test("message_store", () => {
const in_message = {...messages.isaac_to_denmark_stream};
assert.equal(in_message.alerted, undefined);
assert.equal(in_message.watched, undefined);
// Let's add a message into our message_store via
// message_helper.process_new_message.
assert.equal(message_store.get(in_message.id), undefined);
message_helper.process_new_message(in_message);
const message = message_store.get(in_message.id);
assert.equal(message.alerted, true);
assert.equal(message.watched, true);
// There are more side effects.
const topic_names = stream_topic_history.get_recent_topic_names(denmark_stream.stream_id);

View File

@ -537,11 +537,11 @@ function assert_not_mark_read_with_is_operands(additional_terms_to_test) {
filter = new Filter([...additional_terms_to_test, ...is_operator]);
assert.ok(!filter.can_mark_messages_read());
is_operator = [{operator: "is", operand: "alerted"}];
is_operator = [{operator: "is", operand: "watched"}];
filter = new Filter([...additional_terms_to_test, ...is_operator]);
assert.ok(!filter.can_mark_messages_read());
is_operator = [{operator: "is", operand: "alerted", negated: true}];
is_operator = [{operator: "is", operand: "watched", negated: true}];
filter = new Filter([...additional_terms_to_test, ...is_operator]);
assert.ok(!filter.can_mark_messages_read());
@ -970,9 +970,9 @@ test("predicate_basics", ({override}) => {
assert.ok(predicate({unread: true}));
assert.ok(!predicate({unread: false}));
predicate = get_predicate([["is", "alerted"]]);
assert.ok(predicate({alerted: true}));
assert.ok(!predicate({alerted: false}));
predicate = get_predicate([["is", "watched"]]);
assert.ok(predicate({watched: true}));
assert.ok(!predicate({watched: false}));
assert.ok(!predicate({}));
predicate = get_predicate([["is", "mentioned"]]);
@ -1537,8 +1537,8 @@ test("describe", ({mock_template}) => {
string = "@-mentions";
assert.equal(Filter.search_description_as_html(narrow), string);
narrow = [{operator: "is", operand: "alerted"}];
string = "alerted messages";
narrow = [{operator: "is", operand: "watched"}];
string = "Messages with watched phrases";
assert.equal(Filter.search_description_as_html(narrow), string);
narrow = [{operator: "is", operand: "resolved"}];
@ -1779,16 +1779,16 @@ test("term_type", () => {
});
test("first_valid_id_from", ({override}) => {
const terms = [{operator: "is", operand: "alerted"}];
const terms = [{operator: "is", operand: "watched"}];
const filter = new Filter(terms);
const messages = {
5: {id: 5, alerted: true},
5: {id: 5, watched: true},
10: {id: 10},
20: {id: 20, alerted: true},
20: {id: 20, watched: true},
30: {id: 30, type: stream_message},
40: {id: 40, alerted: false},
40: {id: 40, watched: false},
};
const msg_ids = [10, 20, 30, 40];
@ -2130,7 +2130,7 @@ test("navbar_helpers", ({override}) => {
{operator: "dm", operand: "joe@example.com,STEVE@foo.com,sally@doesnotexist.com"},
];
// not common narrows, but used for browser title updates
const is_alerted = [{operator: "is", operand: "alerted"}];
const is_watched = [{operator: "is", operand: "watched"}];
const is_unread = [{operator: "is", operand: "unread"}];
const channel_topic_near = [
{operator: "channel", operand: foo_stream_id.toString()},
@ -2317,10 +2317,10 @@ test("navbar_helpers", ({override}) => {
link: "/help/emoji-reactions",
},
{
terms: is_alerted,
terms: is_watched,
is_common_narrow: false,
icon: undefined,
title: "translated: Alerted messages",
title: "translated: Messages with watched phrases",
redirect_url_with_search: "#",
},
{

View File

@ -134,7 +134,7 @@ run_test("update_messages", ({override}) => {
assert.deepEqual(rendered_mgs, [
{
display_reply_to: undefined,
alerted: false,
watched: false,
clean_reactions: new Map(),
collapsed: false,
content: "<b>new content</b>",

View File

@ -118,7 +118,7 @@ test("process_new_message", () => {
assert.equal(message.reply_to, "bob@example.com,cindy@example.com");
assert.equal(message.to_user_ids, "103,104");
assert.equal(message.display_reply_to, "Bob, Cindy");
assert.equal(message.alerted, true);
assert.equal(message.watched, true);
assert.equal(message.is_me_message, false);
const retrieved_message = message_store.get(2067);
@ -151,7 +151,7 @@ test("process_new_message", () => {
message = message_helper.process_new_message(message);
assert.equal(message.reply_to, "denise@example.com");
assert.deepEqual(message.flags, undefined);
assert.equal(message.alerted, false);
assert.equal(message.watched, false);
assert.deepEqual(message_user_ids.user_ids().sort(), [
me.user_id,
@ -187,7 +187,7 @@ test("message_booleans_parity", () => {
mentioned_me_directly: false,
stream_wildcard_mentioned: true,
topic_wildcard_mentioned: false,
alerted: false,
watched: false,
});
assert_bool_match(["topic_wildcard_mentioned"], {
@ -195,7 +195,7 @@ test("message_booleans_parity", () => {
mentioned_me_directly: false,
stream_wildcard_mentioned: false,
topic_wildcard_mentioned: true,
alerted: false,
watched: false,
});
assert_bool_match(["mentioned"], {
@ -203,7 +203,7 @@ test("message_booleans_parity", () => {
mentioned_me_directly: true,
stream_wildcard_mentioned: false,
topic_wildcard_mentioned: false,
alerted: false,
watched: false,
});
assert_bool_match(["has_alert_word"], {
@ -211,7 +211,7 @@ test("message_booleans_parity", () => {
mentioned_me_directly: false,
stream_wildcard_mentioned: false,
topic_wildcard_mentioned: false,
alerted: true,
watched: true,
});
});
@ -269,7 +269,7 @@ test("update_booleans", () => {
message.mentioned_me_directly = false;
message.stream_wildcard_mentioned = false;
message.topic_wildcard_mentioned = false;
message.alerted = false;
message.watched = false;
let flags = ["mentioned", "has_alert_word", "read"];
message_store.update_booleans(message, flags);
@ -277,7 +277,7 @@ test("update_booleans", () => {
assert.equal(message.mentioned_me_directly, true);
assert.equal(message.stream_wildcard_mentioned, false);
assert.equal(message.topic_wildcard_mentioned, false);
assert.equal(message.alerted, true);
assert.equal(message.watched, true);
flags = ["stream_wildcard_mentioned", "unread"];
message_store.update_booleans(message, flags);
@ -297,7 +297,7 @@ test("update_booleans", () => {
message_store.update_booleans(message, flags);
assert.equal(message.mentioned, false);
assert.equal(message.mentioned_me_directly, false);
assert.equal(message.alerted, false);
assert.equal(message.watched, false);
assert.equal(message.stream_wildcard_mentioned, false);
assert.equal(message.topic_wildcard_mentioned, false);

View File

@ -285,16 +285,16 @@ run_test("is:mentioned with no unreads and no matches", () => {
test_with(fixture);
});
run_test("is:alerted with no unreads and one match", () => {
run_test("is:watched with no unreads and one match", () => {
const fixture = {
filter_terms: [{operator: "is", operand: "alerted"}],
filter_terms: [{operator: "is", operand: "watched"}],
unread_info: {
flavor: "not_found",
},
has_found_newest: true,
all_messages: [
{id: 55, topic: "whatever", alerted: true},
{id: 57, topic: "whatever", alerted: false},
{id: 55, topic: "whatever", watched: true},
{id: 57, topic: "whatever", watched: false},
],
expected_id_info: {
target_id: undefined,

View File

@ -164,7 +164,6 @@ test("dm_suggestions", ({override, mock_template}) => {
suggestions = get_suggestions(query);
expected = [
"is:dm al",
"is:dm is:alerted",
"is:dm dm:alice@zulip.com",
"is:dm sender:alice@zulip.com",
"is:dm dm-including:alice@zulip.com",
@ -238,16 +237,15 @@ test("dm_suggestions", ({override, mock_template}) => {
assert.deepEqual(suggestions.strings, expected);
// Make sure suggestions still work if preceding tokens
query = "is:alerted sender:ted@zulip.com";
query = "is:watched sender:ted@zulip.com";
suggestions = get_suggestions(query);
expected = ["is:alerted sender:ted@zulip.com", "is:alerted"];
expected = ["is:watched sender:ted@zulip.com", "is:watched"];
assert.deepEqual(suggestions.strings, expected);
query = "is:starred has:link is:dm al";
suggestions = get_suggestions(query);
expected = [
"is:starred has:link is:dm al",
"is:starred has:link is:dm is:alerted",
"is:starred has:link is:dm dm:alice@zulip.com",
"is:starred has:link is:dm sender:alice@zulip.com",
"is:starred has:link is:dm dm-including:alice@zulip.com",
@ -374,7 +372,7 @@ test("empty_query_suggestions", () => {
"is:starred",
"is:mentioned",
"is:followed",
"is:alerted",
"is:watched",
"is:unread",
"is:resolved",
"sender:myself@zulip.com",
@ -394,7 +392,7 @@ test("empty_query_suggestions", () => {
assert.equal(describe("is:dm"), "Direct messages");
assert.equal(describe("is:starred"), "Starred messages");
assert.equal(describe("is:mentioned"), "@-mentions");
assert.equal(describe("is:alerted"), "Messages with watched phrases");
assert.equal(describe("is:watched"), "Messages with watched phrases");
assert.equal(describe("is:unread"), "Unread messages");
assert.equal(describe("is:resolved"), "Topics marked as resolved");
assert.equal(describe("is:followed"), "Followed topics");
@ -457,9 +455,9 @@ test("has_suggestions", ({override, mock_template}) => {
assert.deepEqual(suggestions.strings, expected);
// 66 is misc channel id.
query = "channel:66 is:alerted has:lin";
query = "channel:66 is:watched has:lin";
suggestions = get_suggestions(query);
expected = ["channel:66 is:alerted has:link", "channel:66 is:alerted", "channel:66"];
expected = ["channel:66 is:watched has:link", "channel:66 is:watched", "channel:66"];
assert.deepEqual(suggestions.strings, expected);
});
@ -477,7 +475,7 @@ test("check_is_suggestions", ({override, mock_template}) => {
"is:starred",
"is:mentioned",
"is:followed",
"is:alerted",
"is:watched",
"is:unread",
"is:resolved",
"dm:alice@zulip.com",
@ -494,7 +492,7 @@ test("check_is_suggestions", ({override, mock_template}) => {
assert.equal(describe("is:dm"), "Direct messages");
assert.equal(describe("is:starred"), "Starred messages");
assert.equal(describe("is:mentioned"), "@-mentions");
assert.equal(describe("is:alerted"), "Messages with watched phrases");
assert.equal(describe("is:watched"), "Messages with watched phrases");
assert.equal(describe("is:unread"), "Unread messages");
assert.equal(describe("is:resolved"), "Topics marked as resolved");
assert.equal(describe("is:followed"), "Followed topics");
@ -507,7 +505,7 @@ test("check_is_suggestions", ({override, mock_template}) => {
"-is:starred",
"-is:mentioned",
"-is:followed",
"-is:alerted",
"-is:watched",
"-is:unread",
"-is:resolved",
];
@ -516,7 +514,7 @@ test("check_is_suggestions", ({override, mock_template}) => {
assert.equal(describe("-is:dm"), "Exclude direct messages");
assert.equal(describe("-is:starred"), "Exclude starred messages");
assert.equal(describe("-is:mentioned"), "Exclude @-mentions");
assert.equal(describe("-is:alerted"), "Exclude messages with watched phrases");
assert.equal(describe("-is:watched"), "Exclude messages with watched phrases");
assert.equal(describe("-is:unread"), "Exclude unread messages");
assert.equal(describe("-is:resolved"), "Exclude topics marked as resolved");
assert.equal(describe("-is:followed"), "Exclude followed topics");
@ -530,7 +528,7 @@ test("check_is_suggestions", ({override, mock_template}) => {
"is:starred",
"is:mentioned",
"is:followed",
"is:alerted",
"is:watched",
"is:unread",
"is:resolved",
];
@ -707,13 +705,13 @@ test("topic_suggestions", ({override, mock_template}) => {
];
assert.deepEqual(suggestions.strings, expected);
suggestions = get_suggestions(`is:alerted channel:${devel_id} is:starred topic:`);
suggestions = get_suggestions(`is:watched channel:${devel_id} is:starred topic:`);
expected = [
`is:alerted channel:${devel_id} is:starred topic:`,
`is:alerted channel:${devel_id} is:starred topic:REXX`,
`is:alerted channel:${devel_id} is:starred`,
`is:alerted channel:${devel_id}`,
"is:alerted",
`is:watched channel:${devel_id} is:starred topic:`,
`is:watched channel:${devel_id} is:starred topic:REXX`,
`is:watched channel:${devel_id} is:starred`,
`is:watched channel:${devel_id}`,
"is:watched",
];
assert.deepEqual(suggestions.strings, expected);
@ -1008,13 +1006,13 @@ test("operator_suggestions", ({override, mock_template}) => {
assert.deepEqual(suggestions.strings, expected);
// 66 is a misc channel id.
query = "channel:66 is:alerted -f";
query = "channel:66 is:watched -f";
suggestions = get_suggestions(query);
expected = [
"channel:66 is:alerted -f",
"channel:66 is:alerted -sender:myself@zulip.com",
"channel:66 is:alerted -sender:",
"channel:66 is:alerted",
"channel:66 is:watched -f",
"channel:66 is:watched -sender:myself@zulip.com",
"channel:66 is:watched -sender:",
"channel:66 is:watched",
"channel:66",
];
assert.deepEqual(suggestions.strings, expected);

View File

@ -403,7 +403,7 @@ class NarrowBuilder:
)
cond = column("flags", Integer).op("&")(mention_flags_mask) != 0
return query.where(maybe_negate(cond))
elif operand == "alerted":
elif operand in ["alerted", "watched"]:
cond = column("flags", Integer).op("&")(UserMessage.flags.has_alert_word.mask) != 0
return query.where(maybe_negate(cond))
elif operand == "resolved":

View File

@ -63,7 +63,7 @@ def build_narrow_predicate(
elif operator == "is" and operand == "unread":
if "read" in flags:
return False
elif operator == "is" and operand in ["alerted", "mentioned"]:
elif operator == "is" and operand in ["alerted", "mentioned", "watched"]:
if "mentioned" not in flags:
return False
elif operator == "is" and operand == "resolved":

View File

@ -228,7 +228,7 @@ class NarrowBuilderTest(ZulipTestCase):
self._do_add_term_test(term, "WHERE (flags & %(flags_1)s) = %(param_1)s")
def test_add_term_using_is_operator_and_non_dm_operand(self) -> None:
for operand in ["starred", "mentioned", "alerted"]:
for operand in ["starred", "mentioned", "alerted", "watched"]:
term = NarrowParameter(operator="is", operand=operand)
self._do_add_term_test(term, "WHERE (flags & %(flags_1)s) != %(param_1)s")
@ -257,6 +257,16 @@ class NarrowBuilderTest(ZulipTestCase):
)
self._do_add_term_test(term, where_clause, params)
self._do_add_term_test(term, where_clause, params)
term = NarrowParameter(operator="is", operand="watched", negated=True)
where_clause = "WHERE (flags & %(flags_1)s) = %(param_1)s"
params = dict(
flags_1=UserMessage.flags.has_alert_word.mask,
param_1=0,
)
self._do_add_term_test(term, where_clause, params)
term = NarrowParameter(operator="is", operand="mentioned", negated=True)
where_clause = "WHERE (flags & %(flags_1)s) = %(param_1)s"
mention_flags_mask = (
@ -897,6 +907,13 @@ class NarrowLibraryTest(ZulipTestCase):
)
)
self.assertFalse(
narrow_predicate(
message={},
flags=["watched"],
)
)
###
narrow_predicate = build_narrow_predicate([NarrowTerm(operator="is", operand="alerted")])
@ -917,6 +934,24 @@ class NarrowLibraryTest(ZulipTestCase):
###
narrow_predicate = build_narrow_predicate([NarrowTerm(operator="is", operand="watched")])
self.assertTrue(
narrow_predicate(
message={},
flags=["mentioned"],
)
)
self.assertFalse(
narrow_predicate(
message={},
flags=["starred"],
)
)
###
narrow_predicate = build_narrow_predicate([NarrowTerm(operator="is", operand="mentioned")])
self.assertTrue(
@ -1155,6 +1190,11 @@ class IncludeHistoryTest(ZulipTestCase):
NarrowParameter(operator="is", operand="alerted"),
]
self.assertFalse(ok_to_include_history(narrow, user_profile, False))
narrow = [
NarrowParameter(operator="channels", operand="public"),
NarrowParameter(operator="is", operand="watched"),
]
self.assertFalse(ok_to_include_history(narrow, user_profile, False))
narrow = [
NarrowParameter(operator="channels", operand="public"),
NarrowParameter(operator="is", operand="resolved"),