mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 14:03:30 +00:00 
			
		
		
		
	We now treat util like a leaf module and use "require" to import it everywhere it's used. An earlier version of this commit moved util into our "shared" library, but we decided to wait on that. Once we're ready to do that, we should only need to do a simple search/replace on various require/zrequire statements plus a small tweak to one of the custom linter checks. It turns out we don't really need util.js for our most immediate code-sharing goal, which is to reuse our markdown code on mobile. There's a little bit of cleanup still remaining to break the dependency, but it's minor. The util module still calls the global blueslip module in one place, but that code is about to be removed in the next few commits. I am pretty confident that once we start sharing things like the typeahead code more aggressively, we'll start having dependencies on util. The module is barely more than 300 lines long, so we'll probably just move the whole thing into shared rather than break it apart. Also, we can continue to nibble away at the cruftier parts of the module.
		
			
				
	
	
		
			353 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			353 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
// Dependencies
 | 
						|
set_global('$', global.make_zjquery({
 | 
						|
    silent: true,
 | 
						|
}));
 | 
						|
set_global('blueslip', global.make_zblueslip());
 | 
						|
set_global('document', {
 | 
						|
    hasFocus: function () {
 | 
						|
        return true;
 | 
						|
    },
 | 
						|
});
 | 
						|
set_global('page_params', {
 | 
						|
    is_admin: false,
 | 
						|
    realm_users: [],
 | 
						|
    enable_desktop_notifications: true,
 | 
						|
    enable_sounds: true,
 | 
						|
    wildcard_mentions_notify: true,
 | 
						|
});
 | 
						|
const _navigator = {
 | 
						|
    userAgent: 'Mozilla/5.0 AppleWebKit/537.36 Chrome/64.0.3282.167 Safari/537.36',
 | 
						|
};
 | 
						|
set_global('navigator', _navigator);
 | 
						|
 | 
						|
set_global('i18n', global.stub_i18n);
 | 
						|
 | 
						|
zrequire('alert_words');
 | 
						|
zrequire('muting');
 | 
						|
zrequire('stream_data');
 | 
						|
zrequire('people');
 | 
						|
zrequire('ui');
 | 
						|
 | 
						|
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);
 | 
						|
 | 
						|
muting.add_muted_topic(general.stream_id, 'muted topic');
 | 
						|
 | 
						|
run_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 notificaton 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);
 | 
						|
 | 
						|
    // 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 7',
 | 
						|
        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);
 | 
						|
});
 | 
						|
 | 
						|
 | 
						|
run_test('basic_notifications', () => {
 | 
						|
 | 
						|
    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
 | 
						|
    notifications.set_notification_api({
 | 
						|
        createNotification: function createNotification(icon, title, content, tag) {
 | 
						|
            const notification_object = {icon: icon, body: content, tag: tag};
 | 
						|
            // properties for testing.
 | 
						|
            notification_object.tests = {
 | 
						|
                shown: false,
 | 
						|
            };
 | 
						|
            notification_object.show = function () {
 | 
						|
                last_shown_message_id = this.tag;
 | 
						|
            };
 | 
						|
            notification_object.close = function () {
 | 
						|
                last_closed_message_id = this.tag;
 | 
						|
            };
 | 
						|
            notification_object.cancel = function () { notification_object.close(); };
 | 
						|
            return notification_object;
 | 
						|
        },
 | 
						|
    });
 | 
						|
 | 
						|
    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);
 | 
						|
});
 |