mirror of
				https://github.com/zulip/zulip.git
				synced 2025-10-31 20:13:46 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			386 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			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 {page_params} = 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 ui = zrequire("ui");
 | |
| 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, ({override}) => {
 | |
|         page_params.is_admin = false;
 | |
|         page_params.realm_users = [];
 | |
|         page_params.enable_desktop_notifications = true;
 | |
|         page_params.enable_sounds = true;
 | |
|         page_params.wildcard_mentions_notify = true;
 | |
|         page_params.notification_sound = "ding";
 | |
|         f({override});
 | |
|     });
 | |
| }
 | |
| 
 | |
| 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
 | |
|     page_params.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
 | |
|     page_params.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",
 | |
|     };
 | |
|     page_params.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
 | |
|     page_params.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", ({override}) => {
 | |
|     override(ui, "replace_emoji_with_text", () => {});
 | |
| 
 | |
|     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);
 | |
| });
 |