Files
zulip/frontend_tests/node_tests/notifications.js
Anders Kaseorg c520890f54 node_tests: Remove low-hanging uses of __Rewire__.
When we were preparing the conversion to ES modules in 2019, the
primary obstacle was that the Node tests extensively relied on the
ability to reach into modules and mutate their CommonJS exports in
order to mock things.  ES module bindings are not mutable, so in
commit 173c9cee42 we added
babel-plugin-rewire-ts as a kludgy transpilation-based workaround for
this to unblock the conversion.

However, babel-plugin-rewire-ts is slow, buggy, nonstandard,
confusing, and unmaintained.  It’s incompatible with running our ES
modules as native ES modules, and prevents us from taking advantage of
modern tools for ES modules.  So we want to excise all use of
__Rewire__ (and the disallow_rewire, override_rewire helper functions
that rely on it) from the tests and remove babel-plugin-rewire-ts.

Commits 64abdc199e and
e17ba5260a (#20730) prepared for this by
letting us see where __Rewire__ is being used.  Now we go through and
remove most of the uses that are easy to remove without modifying the
production code at all.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2022-07-13 16:27:30 -07:00

386 lines
13 KiB
JavaScript

"use strict";
const {strict: assert} = require("assert");
const {set_global, zrequire} = require("../zjsunit/namespace");
const {run_test} = require("../zjsunit/test");
const $ = require("../zjsunit/zjquery");
const {page_params, user_settings} = require("../zjsunit/zpage_params");
// Dependencies
set_global("document", {
hasFocus() {
return true;
},
});
const _navigator = {
userAgent: "Mozilla/5.0 AppleWebKit/537.36 Chrome/64.0.3282.167 Safari/537.36",
};
set_global("navigator", _navigator);
const muted_topics = zrequire("muted_topics");
const stream_data = zrequire("stream_data");
const spoilers = zrequire("spoilers");
spoilers.hide_spoilers_in_notification = () => {};
const notifications = zrequire("notifications");
// Not muted streams
const general = {
subscribed: true,
name: "general",
stream_id: 10,
is_muted: false,
wildcard_mentions_notify: null,
};
// Muted streams
const muted = {
subscribed: true,
name: "muted",
stream_id: 20,
is_muted: true,
wildcard_mentions_notify: null,
};
stream_data.add_sub(general);
stream_data.add_sub(muted);
muted_topics.add_muted_topic(general.stream_id, "muted topic");
function test(label, f) {
run_test(label, (helpers) => {
page_params.is_admin = false;
page_params.realm_users = [];
user_settings.enable_desktop_notifications = true;
user_settings.enable_sounds = true;
user_settings.wildcard_mentions_notify = true;
user_settings.notification_sound = "ding";
f(helpers);
});
}
test("message_is_notifiable", () => {
// A notification is sent if both message_is_notifiable(message)
// and the appropriate should_send_*_notification function return
// true.
// Case 1: If the message was sent by this user,
// DO NOT notify the user
// In this test, all other circumstances should trigger notification
// EXCEPT sent_by_me, which should trump them
let message = {
id: muted.stream_id,
content: "message number 1",
sent_by_me: true,
notification_sent: false,
mentioned: true,
mentioned_me_directly: true,
type: "stream",
stream: "general",
stream_id: general.stream_id,
topic: "whatever",
};
assert.equal(notifications.should_send_desktop_notification(message), true);
assert.equal(notifications.should_send_audible_notification(message), true);
// Not notifiable because it was sent by the current user
assert.equal(notifications.message_is_notifiable(message), false);
// Case 2: If the user has already been sent a notification about this message,
// DO NOT notify the user
// In this test, all other circumstances should trigger notification
// EXCEPT notification_sent, which should trump them
// (ie: it mentions user, it's not muted, etc)
message = {
id: general.stream_id,
content: "message number 2",
sent_by_me: false,
notification_sent: true,
mentioned: true,
mentioned_me_directly: true,
type: "stream",
stream: "general",
stream_id: general.stream_id,
topic: "whatever",
};
assert.equal(notifications.should_send_desktop_notification(message), true);
assert.equal(notifications.should_send_audible_notification(message), true);
assert.equal(notifications.message_is_notifiable(message), false);
// Case 3: If a message mentions the user directly,
// DO notify the user
// Mentioning trumps muting
message = {
id: 30,
content: "message number 3",
sent_by_me: false,
notification_sent: false,
mentioned: true,
mentioned_me_directly: true,
type: "stream",
stream: "muted",
stream_id: muted.stream_id,
topic: "topic_three",
};
assert.equal(notifications.should_send_desktop_notification(message), true);
assert.equal(notifications.should_send_audible_notification(message), true);
assert.equal(notifications.message_is_notifiable(message), true);
// Case 4:
// Mentioning should trigger notification in unmuted topic
message = {
id: 40,
content: "message number 4",
sent_by_me: false,
notification_sent: false,
mentioned: true,
mentioned_me_directly: true,
type: "stream",
stream: "general",
stream_id: general.stream_id,
topic: "vanilla",
};
assert.equal(notifications.should_send_desktop_notification(message), true);
assert.equal(notifications.should_send_audible_notification(message), true);
assert.equal(notifications.message_is_notifiable(message), true);
// Case 5:
// Wildcard mention should trigger notification in unmuted topic
// if wildcard_mentions_notify
message = {
id: 40,
content: "message number 4",
sent_by_me: false,
notification_sent: false,
mentioned: true,
mentioned_me_directly: false,
type: "stream",
stream: "general",
stream_id: general.stream_id,
topic: "vanilla",
};
assert.equal(notifications.should_send_desktop_notification(message), true);
assert.equal(notifications.should_send_audible_notification(message), true);
assert.equal(notifications.message_is_notifiable(message), true);
// But not if it's disabled
user_settings.wildcard_mentions_notify = false;
assert.equal(notifications.should_send_desktop_notification(message), false);
assert.equal(notifications.should_send_audible_notification(message), false);
assert.equal(notifications.message_is_notifiable(message), true);
// And the stream-level setting overrides the global setting
general.wildcard_mentions_notify = true;
assert.equal(notifications.should_send_desktop_notification(message), true);
assert.equal(notifications.should_send_audible_notification(message), true);
assert.equal(notifications.message_is_notifiable(message), true);
// Reset state
user_settings.wildcard_mentions_notify = true;
general.wildcard_mentions_notify = null;
// Case 6: If a message is in a muted stream
// and does not mention the user DIRECTLY (i.e. wildcard mention),
// DO NOT notify the user
message = {
id: 50,
content: "message number 5",
sent_by_me: false,
notification_sent: false,
mentioned: true,
mentioned_me_directly: false,
type: "stream",
stream: "muted",
stream_id: muted.stream_id,
topic: "whatever",
};
assert.equal(notifications.should_send_desktop_notification(message), true);
assert.equal(notifications.should_send_audible_notification(message), true);
assert.equal(notifications.message_is_notifiable(message), false);
// Case 7: If a message is in a muted stream
// and does mention the user DIRECTLY,
// DO notify the user
message = {
id: 50,
content: "message number 5",
sent_by_me: false,
notification_sent: false,
mentioned: true,
mentioned_me_directly: true,
type: "stream",
stream: "muted",
stream_id: muted.stream_id,
topic: "whatever",
};
assert.equal(notifications.should_send_desktop_notification(message), true);
assert.equal(notifications.should_send_audible_notification(message), true);
assert.equal(notifications.message_is_notifiable(message), true);
// Case 8: If a message is in a muted topic
// and does not mention the user DIRECTLY (i.e. wildcard mention),
// DO NOT notify the user
message = {
id: 50,
content: "message number 6",
sent_by_me: false,
notification_sent: false,
mentioned: true,
mentioned_me_directly: false,
type: "stream",
stream: "general",
stream_id: general.stream_id,
topic: "muted topic",
};
assert.equal(notifications.should_send_desktop_notification(message), true);
assert.equal(notifications.should_send_audible_notification(message), true);
assert.equal(notifications.message_is_notifiable(message), false);
// Case 9: If `None` is selected as the notification sound, send no
// audible notification, no matter what other user configurations are.
message = {
id: 50,
content: "message number 7",
sent_by_me: false,
notification_sent: false,
mentioned: true,
mentioned_me_directly: true,
type: "stream",
stream: "general",
stream_id: general.stream_id,
topic: "whatever",
};
user_settings.notification_sound = "none";
assert.equal(notifications.should_send_desktop_notification(message), true);
assert.equal(notifications.should_send_audible_notification(message), false);
assert.equal(notifications.message_is_notifiable(message), true);
// Reset state
user_settings.notification_sound = "ding";
// If none of the above cases apply
// (ie: topic is not muted, message does not mention user,
// no notification sent before, message not sent by user),
// return true to pass it to notifications settings, which will return false.
message = {
id: 60,
content: "message number 8",
sent_by_me: false,
notification_sent: false,
mentioned: false,
mentioned_me_directly: false,
type: "stream",
stream: "general",
stream_id: general.stream_id,
topic: "whatever",
};
assert.equal(notifications.should_send_desktop_notification(message), false);
assert.equal(notifications.should_send_audible_notification(message), false);
assert.equal(notifications.message_is_notifiable(message), true);
});
test("basic_notifications", () => {
$("<div>").set_find_results(".emoji", {replaceWith() {}});
let n; // Object for storing all notification data for assertions.
let last_closed_message_id = null;
let last_shown_message_id = null;
// Notifications API stub
class StubNotification {
constructor(title, {icon, body, tag}) {
this.icon = icon;
this.body = body;
this.tag = tag;
// properties for testing.
this.tests = {
shown: false,
};
last_shown_message_id = this.tag;
}
addEventListener() {}
close() {
last_closed_message_id = this.tag;
}
}
notifications.set_notification_api(StubNotification);
const message_1 = {
id: 1000,
content: "@-mentions the user",
avatar_url: "url",
sent_by_me: false,
sender_full_name: "Jesse Pinkman",
notification_sent: false,
mentioned_me_directly: true,
type: "stream",
stream: "general",
stream_id: muted.stream_id,
topic: "whatever",
};
const message_2 = {
id: 1500,
avatar_url: "url",
content: "@-mentions the user",
sent_by_me: false,
sender_full_name: "Gus Fring",
notification_sent: false,
mentioned_me_directly: true,
type: "stream",
stream: "general",
stream_id: muted.stream_id,
topic: "lunch",
};
// Send notification.
notifications.process_notification({message: message_1, desktop_notify: true});
n = notifications.get_notifications();
assert.equal(n.has("Jesse Pinkman to general > whatever"), true);
assert.equal(n.size, 1);
assert.equal(last_shown_message_id, message_1.id);
// Remove notification.
notifications.close_notification(message_1);
n = notifications.get_notifications();
assert.equal(n.has("Jesse Pinkman to general > whatever"), false);
assert.equal(n.size, 0);
assert.equal(last_closed_message_id, message_1.id);
// Send notification.
message_1.id = 1001;
notifications.process_notification({message: message_1, desktop_notify: true});
n = notifications.get_notifications();
assert.equal(n.has("Jesse Pinkman to general > whatever"), true);
assert.equal(n.size, 1);
assert.equal(last_shown_message_id, message_1.id);
// Process same message again. Notification count shouldn't increase.
message_1.id = 1002;
notifications.process_notification({message: message_1, desktop_notify: true});
n = notifications.get_notifications();
assert.equal(n.has("Jesse Pinkman to general > whatever"), true);
assert.equal(n.size, 1);
assert.equal(last_shown_message_id, message_1.id);
// Send another message. Notification count should increase.
notifications.process_notification({message: message_2, desktop_notify: true});
n = notifications.get_notifications();
assert.equal(n.has("Gus Fring to general > lunch"), true);
assert.equal(n.has("Jesse Pinkman to general > whatever"), true);
assert.equal(n.size, 2);
assert.equal(last_shown_message_id, message_2.id);
// Remove notifications.
notifications.close_notification(message_1);
notifications.close_notification(message_2);
n = notifications.get_notifications();
assert.equal(n.has("Jesse Pinkman to general > whatever"), false);
assert.equal(n.size, 0);
assert.equal(last_closed_message_id, message_2.id);
});