mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	The `assert_message_groups_list_equal` and `assert_message_list_equal` helpers were always returning `true`, as they were doing a bogus traversal of the data structures and always comparing empty arrays, even when there was real data. To prevent this pitfall in the future, we assert that the extracted data is truth-y, and for the empty cases we just directly assert deep equality to `[]`.
		
			
				
	
	
		
			488 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			488 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
set_global('$', global.make_zjquery());
 | 
						|
set_global('document', 'document-stub');
 | 
						|
 | 
						|
zrequire('util');
 | 
						|
zrequire('XDate', 'node_modules/xdate/src/xdate');
 | 
						|
zrequire('Filter', 'js/filter');
 | 
						|
zrequire('FetchStatus', 'js/fetch_status');
 | 
						|
zrequire('MessageListData', 'js/message_list_data');
 | 
						|
zrequire('MessageListView', 'js/message_list_view');
 | 
						|
zrequire('message_list');
 | 
						|
 | 
						|
var noop = function () {};
 | 
						|
 | 
						|
set_global('page_params', {
 | 
						|
    twenty_four_hour_time: false,
 | 
						|
});
 | 
						|
set_global('home_msg_list', null);
 | 
						|
set_global('feature_flags', {twenty_four_hour_time: false});
 | 
						|
set_global('people', {small_avatar_url: function () { return ''; }});
 | 
						|
set_global('unread', {message_unread: function () {}});
 | 
						|
// timerender calls setInterval when imported
 | 
						|
set_global('timerender', {
 | 
						|
    render_date: function (time1, time2) {
 | 
						|
        if (time2 === undefined) {
 | 
						|
            return [{outerHTML: String(time1.getTime())}];
 | 
						|
        }
 | 
						|
        return [{outerHTML: String(time1.getTime()) + ' - ' + String(time2.getTime())}];
 | 
						|
    },
 | 
						|
    stringify_time: function (time) {
 | 
						|
        if (page_params.twenty_four_hour_time) {
 | 
						|
            return time.toString('HH:mm');
 | 
						|
        }
 | 
						|
        return time.toString('h:mm TT');
 | 
						|
    },
 | 
						|
});
 | 
						|
 | 
						|
set_global('rows', {
 | 
						|
    get_table: function () {
 | 
						|
        return {
 | 
						|
            children: function () {
 | 
						|
                return {
 | 
						|
                    detach: noop,
 | 
						|
                };
 | 
						|
            },
 | 
						|
        };
 | 
						|
    },
 | 
						|
});
 | 
						|
 | 
						|
run_test('merge_message_groups', () => {
 | 
						|
    // MessageListView has lots of DOM code, so we are going to test the message
 | 
						|
    // group mearging logic on its own.
 | 
						|
 | 
						|
    function build_message_context(message, message_context) {
 | 
						|
        if (message_context === undefined) {
 | 
						|
            message_context = {};
 | 
						|
        }
 | 
						|
        if (message === undefined) {
 | 
						|
            message = {};
 | 
						|
        }
 | 
						|
        message_context = _.defaults(message_context, {
 | 
						|
            include_sender: true,
 | 
						|
        });
 | 
						|
        message_context.msg = _.defaults(message, {
 | 
						|
            id: _.uniqueId('test_message_'),
 | 
						|
            status_message: false,
 | 
						|
            type: 'stream',
 | 
						|
            stream: 'Test Stream 1',
 | 
						|
            subject: 'Test Subject 1',
 | 
						|
            sender_email: 'test@example.com',
 | 
						|
            timestamp: _.uniqueId(),
 | 
						|
        });
 | 
						|
        return message_context;
 | 
						|
    }
 | 
						|
 | 
						|
    function build_message_group(messages) {
 | 
						|
        return {
 | 
						|
            message_containers: messages,
 | 
						|
            message_group_id: _.uniqueId('test_message_group_'),
 | 
						|
            show_date: true,
 | 
						|
        };
 | 
						|
    }
 | 
						|
 | 
						|
    function build_list(message_groups) {
 | 
						|
        var list = new MessageListView(undefined, undefined, true);
 | 
						|
        list._message_groups = message_groups;
 | 
						|
        list.list = {
 | 
						|
            unsubscribed_bookend_content: function () {},
 | 
						|
            subscribed_bookend_content: function () {},
 | 
						|
        };
 | 
						|
        return list;
 | 
						|
    }
 | 
						|
 | 
						|
    function extract_message_ids(lst) {
 | 
						|
        return _.map(lst, (item) => {
 | 
						|
            return item.msg.id;
 | 
						|
        });
 | 
						|
    }
 | 
						|
 | 
						|
    function assert_message_list_equal(list1, list2) {
 | 
						|
        var ids1 = extract_message_ids(list1);
 | 
						|
        var ids2 = extract_message_ids(list2);
 | 
						|
        assert(ids1.length);
 | 
						|
        assert.deepEqual(ids1, ids2);
 | 
						|
    }
 | 
						|
 | 
						|
    function extract_group(group) {
 | 
						|
        return extract_message_ids(group.message_containers);
 | 
						|
    }
 | 
						|
 | 
						|
    function assert_message_groups_list_equal(list1, list2) {
 | 
						|
        var ids1 = _.map(list1, extract_group);
 | 
						|
        var ids2 = _.map(list2, extract_group);
 | 
						|
        assert(ids1.length);
 | 
						|
        assert.deepEqual(ids1, ids2);
 | 
						|
    }
 | 
						|
 | 
						|
    (function test_empty_list_bottom() {
 | 
						|
        var list = build_list([]);
 | 
						|
        var message_group = build_message_group([
 | 
						|
            build_message_context(),
 | 
						|
        ]);
 | 
						|
 | 
						|
        var result = list.merge_message_groups([message_group], 'bottom');
 | 
						|
 | 
						|
        assert_message_groups_list_equal(list._message_groups, [message_group]);
 | 
						|
        assert_message_groups_list_equal(result.append_groups, [message_group]);
 | 
						|
        assert.deepEqual(result.prepend_groups, []);
 | 
						|
        assert.deepEqual(result.rerender_groups, []);
 | 
						|
        assert.deepEqual(result.append_messages, []);
 | 
						|
        assert.deepEqual(result.rerender_messages, []);
 | 
						|
    }());
 | 
						|
 | 
						|
    (function test_append_message_same_subject() {
 | 
						|
 | 
						|
        var message1 = build_message_context();
 | 
						|
        var message_group1 = build_message_group([
 | 
						|
            message1,
 | 
						|
        ]);
 | 
						|
 | 
						|
        var message2 = build_message_context();
 | 
						|
        var message_group2 = build_message_group([
 | 
						|
            message2,
 | 
						|
        ]);
 | 
						|
 | 
						|
        var list = build_list([message_group1]);
 | 
						|
        var result = list.merge_message_groups([message_group2], 'bottom');
 | 
						|
 | 
						|
        assert_message_groups_list_equal(
 | 
						|
            list._message_groups,
 | 
						|
            [build_message_group([message1, message2])]);
 | 
						|
        assert.deepEqual(result.append_groups, []);
 | 
						|
        assert.deepEqual(result.prepend_groups, []);
 | 
						|
        assert.deepEqual(result.rerender_groups, []);
 | 
						|
        assert_message_list_equal(result.append_messages, [message2]);
 | 
						|
        assert_message_list_equal(result.rerender_messages, [message1]);
 | 
						|
    }());
 | 
						|
 | 
						|
    (function test_append_message_different_subject() {
 | 
						|
 | 
						|
        var message1 = build_message_context();
 | 
						|
        var message_group1 = build_message_group([
 | 
						|
            message1,
 | 
						|
        ]);
 | 
						|
 | 
						|
        var message2 = build_message_context({subject: 'Test subject 2'});
 | 
						|
        var message_group2 = build_message_group([
 | 
						|
            message2,
 | 
						|
        ]);
 | 
						|
 | 
						|
        var list = build_list([message_group1]);
 | 
						|
        var result = list.merge_message_groups([message_group2], 'bottom');
 | 
						|
 | 
						|
        assert(!message_group2.show_date);
 | 
						|
        assert_message_groups_list_equal(
 | 
						|
            list._message_groups,
 | 
						|
            [message_group1, message_group2]);
 | 
						|
        assert_message_groups_list_equal(result.append_groups, [message_group2]);
 | 
						|
        assert.deepEqual(result.prepend_groups, []);
 | 
						|
        assert.deepEqual(result.rerender_groups, []);
 | 
						|
        assert.deepEqual(result.append_messages, []);
 | 
						|
        assert.deepEqual(result.rerender_messages, []);
 | 
						|
    }());
 | 
						|
 | 
						|
    (function test_append_message_different_day() {
 | 
						|
 | 
						|
        var message1 = build_message_context({timestamp: 1000});
 | 
						|
        var message_group1 = build_message_group([
 | 
						|
            message1,
 | 
						|
        ]);
 | 
						|
 | 
						|
        var message2 = build_message_context({timestamp: 900000});
 | 
						|
        var message_group2 = build_message_group([
 | 
						|
            message2,
 | 
						|
        ]);
 | 
						|
 | 
						|
        var list = build_list([message_group1]);
 | 
						|
        var result = list.merge_message_groups([message_group2], 'bottom');
 | 
						|
 | 
						|
        assert(message_group2.show_date);
 | 
						|
        assert_message_groups_list_equal(
 | 
						|
            list._message_groups,
 | 
						|
            [message_group1, message_group2]);
 | 
						|
        assert_message_groups_list_equal(result.append_groups, [message_group2]);
 | 
						|
        assert.deepEqual(result.prepend_groups, []);
 | 
						|
        assert.deepEqual(result.rerender_groups, []);
 | 
						|
        assert.deepEqual(result.append_messages, []);
 | 
						|
        assert.deepEqual(result.rerender_messages, []);
 | 
						|
    }());
 | 
						|
 | 
						|
    (function test_append_message_historical() {
 | 
						|
 | 
						|
        var message1 = build_message_context({historical: false});
 | 
						|
        var message_group1 = build_message_group([
 | 
						|
            message1,
 | 
						|
        ]);
 | 
						|
 | 
						|
        var message2 = build_message_context({historical: true});
 | 
						|
        var message_group2 = build_message_group([
 | 
						|
            message2,
 | 
						|
        ]);
 | 
						|
 | 
						|
        var list = build_list([message_group1]);
 | 
						|
        var result = list.merge_message_groups([message_group2], 'bottom');
 | 
						|
 | 
						|
        assert(message_group2.bookend_top);
 | 
						|
        assert_message_groups_list_equal(
 | 
						|
            list._message_groups,
 | 
						|
            [message_group1, message_group2]);
 | 
						|
        assert_message_groups_list_equal(result.append_groups, [message_group2]);
 | 
						|
        assert.deepEqual(result.prepend_groups, []);
 | 
						|
        assert.deepEqual(result.rerender_groups, []);
 | 
						|
        assert.deepEqual(result.append_messages, []);
 | 
						|
        assert.deepEqual(result.rerender_messages, []);
 | 
						|
    }());
 | 
						|
 | 
						|
    (function test_append_message_same_subject_me_message() {
 | 
						|
 | 
						|
        var message1 = build_message_context();
 | 
						|
        var message_group1 = build_message_group([
 | 
						|
            message1,
 | 
						|
        ]);
 | 
						|
 | 
						|
        var message2 = build_message_context({is_me_message: true});
 | 
						|
        var message_group2 = build_message_group([
 | 
						|
            message2,
 | 
						|
        ]);
 | 
						|
 | 
						|
        var list = build_list([message_group1]);
 | 
						|
        var result = list.merge_message_groups([message_group2], 'bottom');
 | 
						|
 | 
						|
        assert(message2.include_sender);
 | 
						|
        assert_message_groups_list_equal(
 | 
						|
            list._message_groups,
 | 
						|
            [build_message_group([message1, message2])]);
 | 
						|
        assert.deepEqual(result.append_groups, []);
 | 
						|
        assert.deepEqual(result.prepend_groups, []);
 | 
						|
        assert.deepEqual(result.rerender_groups, []);
 | 
						|
        assert_message_list_equal(result.append_messages, [message2]);
 | 
						|
        assert_message_list_equal(result.rerender_messages, [message1]);
 | 
						|
    }());
 | 
						|
 | 
						|
 | 
						|
    (function test_prepend_message_same_subject() {
 | 
						|
 | 
						|
        var message1 = build_message_context();
 | 
						|
        var message_group1 = build_message_group([
 | 
						|
            message1,
 | 
						|
        ]);
 | 
						|
 | 
						|
        var message2 = build_message_context();
 | 
						|
        var message_group2 = build_message_group([
 | 
						|
            message2,
 | 
						|
        ]);
 | 
						|
 | 
						|
        var list = build_list([message_group1]);
 | 
						|
        var result = list.merge_message_groups([message_group2], 'top');
 | 
						|
 | 
						|
        assert_message_groups_list_equal(
 | 
						|
            list._message_groups,
 | 
						|
            [build_message_group([message2, message1])]);
 | 
						|
        assert.deepEqual(result.append_groups, []);
 | 
						|
        assert.deepEqual(result.prepend_groups, []);
 | 
						|
        assert_message_groups_list_equal(result.rerender_groups,
 | 
						|
                                         [build_message_group([message2, message1])]);
 | 
						|
        assert.deepEqual(result.append_messages, []);
 | 
						|
        assert.deepEqual(result.rerender_messages, []);
 | 
						|
    }());
 | 
						|
 | 
						|
    (function test_prepend_message_different_subject() {
 | 
						|
 | 
						|
        var message1 = build_message_context();
 | 
						|
        var message_group1 = build_message_group([
 | 
						|
            message1,
 | 
						|
        ]);
 | 
						|
 | 
						|
        var message2 = build_message_context({subject: 'Test Subject 2'});
 | 
						|
        var message_group2 = build_message_group([
 | 
						|
            message2,
 | 
						|
        ]);
 | 
						|
 | 
						|
        var list = build_list([message_group1]);
 | 
						|
        var result = list.merge_message_groups([message_group2], 'top');
 | 
						|
 | 
						|
        assert_message_groups_list_equal(
 | 
						|
            list._message_groups,
 | 
						|
            [message_group2, message_group1]);
 | 
						|
        assert.deepEqual(result.append_groups, []);
 | 
						|
        assert_message_groups_list_equal(result.prepend_groups, [message_group2]);
 | 
						|
        assert.deepEqual(result.rerender_groups, []);
 | 
						|
        assert.deepEqual(result.append_messages, []);
 | 
						|
        assert.deepEqual(result.rerender_messages, []);
 | 
						|
    }());
 | 
						|
 | 
						|
    (function test_prepend_message_different_day() {
 | 
						|
 | 
						|
        var message1 = build_message_context({timestamp: 900000});
 | 
						|
        var message_group1 = build_message_group([
 | 
						|
            message1,
 | 
						|
        ]);
 | 
						|
 | 
						|
        var message2 = build_message_context({timestamp: 1000});
 | 
						|
        var message_group2 = build_message_group([
 | 
						|
            message2,
 | 
						|
        ]);
 | 
						|
 | 
						|
        var list = build_list([message_group1]);
 | 
						|
        var result = list.merge_message_groups([message_group2], 'top');
 | 
						|
 | 
						|
        assert.equal(
 | 
						|
            message_group1.show_date,
 | 
						|
            '900000000 - 1000000');
 | 
						|
        assert_message_groups_list_equal(
 | 
						|
            list._message_groups,
 | 
						|
            [message_group2, message_group1]);
 | 
						|
        assert.deepEqual(result.append_groups, []);
 | 
						|
        assert_message_groups_list_equal(result.prepend_groups, [message_group2]);
 | 
						|
        assert_message_groups_list_equal(result.rerender_groups, [message_group1]);
 | 
						|
        assert.deepEqual(result.append_messages, []);
 | 
						|
        assert.deepEqual(result.rerender_messages, []);
 | 
						|
    }());
 | 
						|
 | 
						|
    (function test_prepend_message_historical() {
 | 
						|
 | 
						|
        var message1 = build_message_context({historical: false});
 | 
						|
        var message_group1 = build_message_group([
 | 
						|
            message1,
 | 
						|
        ]);
 | 
						|
 | 
						|
        var message2 = build_message_context({historical: true});
 | 
						|
        var message_group2 = build_message_group([
 | 
						|
            message2,
 | 
						|
        ]);
 | 
						|
 | 
						|
        var list = build_list([message_group1]);
 | 
						|
        var result = list.merge_message_groups([message_group2], 'top');
 | 
						|
 | 
						|
        assert(message_group1.bookend_top);
 | 
						|
        assert_message_groups_list_equal(
 | 
						|
            list._message_groups,
 | 
						|
            [message_group2, message_group1]);
 | 
						|
        assert.deepEqual(result.append_groups, []);
 | 
						|
        assert_message_groups_list_equal(result.prepend_groups, [message_group2]);
 | 
						|
        assert.deepEqual(result.rerender_groups, []);
 | 
						|
        assert.deepEqual(result.append_messages, []);
 | 
						|
        assert.deepEqual(result.rerender_messages, []);
 | 
						|
    }());
 | 
						|
 | 
						|
});
 | 
						|
 | 
						|
run_test('render_windows', () => {
 | 
						|
    // We only render up to 400 messages at a time in our message list,
 | 
						|
    // and we only change the window (which is a range, really, with
 | 
						|
    // start/end) when the pointer moves outside of the window or close
 | 
						|
    // to the edges.
 | 
						|
 | 
						|
    var view = (function make_view() {
 | 
						|
        var table_name = 'zfilt';
 | 
						|
        var filter = new Filter();
 | 
						|
 | 
						|
        var list = new message_list.MessageList({
 | 
						|
            table_name: table_name,
 | 
						|
            filter: filter,
 | 
						|
        });
 | 
						|
 | 
						|
        var view = list.view;
 | 
						|
 | 
						|
        // Stub out functionality that is not core to the rendering window
 | 
						|
        // logic.
 | 
						|
        list.data.unmuted_messages = function (messages) {
 | 
						|
            return messages;
 | 
						|
        };
 | 
						|
 | 
						|
        // We don't need to actually render the DOM.  The windowing logic
 | 
						|
        // sits above that layer.
 | 
						|
        view.render = noop;
 | 
						|
        view.rerender_preserving_scrolltop = noop;
 | 
						|
 | 
						|
        return view;
 | 
						|
    }());
 | 
						|
 | 
						|
    var list = view.list;
 | 
						|
 | 
						|
    (function test_with_empty_list() {
 | 
						|
        // The function should early exit here.
 | 
						|
        var rendered = view.maybe_rerender();
 | 
						|
        assert.equal(rendered, false);
 | 
						|
    }());
 | 
						|
 | 
						|
    var messages;
 | 
						|
 | 
						|
    function reset_list(opts) {
 | 
						|
        messages = _.map(_.range(opts.count), function (i) {
 | 
						|
            return {
 | 
						|
                id: i,
 | 
						|
            };
 | 
						|
        });
 | 
						|
        list.selected_idx = function () { return 0; };
 | 
						|
        list.clear();
 | 
						|
 | 
						|
        list.add_messages(messages, {});
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    function verify_no_move_range(start, end) {
 | 
						|
        // In our render window, there are up to 300 positions in
 | 
						|
        // the list where we can move the pointer without forcing
 | 
						|
        // a re-render.  The code avoids hasty re-renders for
 | 
						|
        // performance reasons.
 | 
						|
        _.each(_.range(start, end), function (idx) {
 | 
						|
            list.selected_idx = function () { return idx; };
 | 
						|
            var rendered = view.maybe_rerender();
 | 
						|
            assert.equal(rendered, false);
 | 
						|
        });
 | 
						|
    }
 | 
						|
 | 
						|
    function verify_move(idx, range) {
 | 
						|
        var start = range[0];
 | 
						|
        var end = range[1];
 | 
						|
 | 
						|
        list.selected_idx = function () { return idx; };
 | 
						|
        var rendered = view.maybe_rerender();
 | 
						|
        assert.equal(rendered, true);
 | 
						|
        assert.equal(view._render_win_start, start);
 | 
						|
        assert.equal(view._render_win_end, end);
 | 
						|
    }
 | 
						|
 | 
						|
    reset_list({count: 51});
 | 
						|
    verify_no_move_range(0, 51);
 | 
						|
 | 
						|
    reset_list({count: 450});
 | 
						|
    verify_no_move_range(0, 350);
 | 
						|
 | 
						|
    verify_move(350, [150, 450]);
 | 
						|
    verify_no_move_range(200, 400);
 | 
						|
 | 
						|
    verify_move(199, [0, 400]);
 | 
						|
    verify_no_move_range(50, 350);
 | 
						|
 | 
						|
    verify_move(350, [150, 450]);
 | 
						|
    verify_no_move_range(200, 400);
 | 
						|
 | 
						|
    verify_move(199, [0, 400]);
 | 
						|
    verify_no_move_range(0, 350);
 | 
						|
 | 
						|
    verify_move(400, [200, 450]);
 | 
						|
 | 
						|
    reset_list({count: 800});
 | 
						|
    verify_no_move_range(0, 350);
 | 
						|
 | 
						|
    verify_move(350, [150, 550]);
 | 
						|
    verify_no_move_range(200, 500);
 | 
						|
 | 
						|
    verify_move(500, [300, 700]);
 | 
						|
    verify_no_move_range(350, 650);
 | 
						|
 | 
						|
    verify_move(650, [450, 800]);
 | 
						|
    verify_no_move_range(500, 750);
 | 
						|
 | 
						|
    verify_move(499, [299, 699]);
 | 
						|
    verify_no_move_range(349, 649);
 | 
						|
 | 
						|
    verify_move(348, [148, 548]);
 | 
						|
    verify_no_move_range(198, 398);
 | 
						|
 | 
						|
    verify_move(197, [0, 400]);
 | 
						|
    verify_no_move_range(0, 350);
 | 
						|
});
 |