mirror of
https://github.com/zulip/zulip.git
synced 2025-10-23 16:14:02 +00:00
624 lines
21 KiB
JavaScript
624 lines
21 KiB
JavaScript
set_global('$', global.make_zjquery());
|
|
set_global('document', 'document-stub');
|
|
|
|
zrequire('util');
|
|
zrequire('XDate', '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('msg_edited_vars', () => {
|
|
// This is a test to verify that only one of the three bools,
|
|
// `edited_in_left_col`, `edited_alongside_sender`, `edited_status_msg`
|
|
// is not false; Tests for three different kinds of messages:
|
|
// * "/me" message
|
|
// * message that includes sender
|
|
// * message without sender
|
|
|
|
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, {
|
|
is_me_message: false,
|
|
last_edit_timestamp: _.uniqueId(),
|
|
});
|
|
return message_context;
|
|
}
|
|
|
|
function build_message_group(messages) {
|
|
return { message_containers: messages };
|
|
}
|
|
|
|
function build_list(message_groups) {
|
|
var list = new MessageListView(undefined, undefined, true);
|
|
list._message_groups = message_groups;
|
|
return list;
|
|
}
|
|
|
|
function assert_left_col(message_container) {
|
|
assert.equal(message_container.edited_in_left_col, true);
|
|
assert.equal(message_container.edited_alongside_sender, false);
|
|
assert.equal(message_container.edited_status_msg, false);
|
|
}
|
|
|
|
function assert_alongside_sender(message_container) {
|
|
assert.equal(message_container.edited_in_left_col, false);
|
|
assert.equal(message_container.edited_alongside_sender, true);
|
|
assert.equal(message_container.edited_status_msg, false);
|
|
}
|
|
|
|
function assert_status_msg(message_container) {
|
|
assert.equal(message_container.edited_in_left_col, false);
|
|
assert.equal(message_container.edited_alongside_sender, false);
|
|
assert.equal(message_container.edited_status_msg, true);
|
|
}
|
|
|
|
(function test_msg_edited_vars() {
|
|
var messages = [
|
|
build_message_context(),
|
|
build_message_context({}, { include_sender: false }),
|
|
build_message_context({ is_me_message: true, content: "<p>/me test</p>" }),
|
|
];
|
|
var message_group = build_message_group(messages);
|
|
var list = build_list([message_group]);
|
|
|
|
_.each(messages, function (message_container) {
|
|
list._maybe_format_me_message(message_container);
|
|
list._add_msg_edited_vars(message_container);
|
|
});
|
|
|
|
var result = list._message_groups[0].message_containers;
|
|
|
|
assert_alongside_sender(result[0]);
|
|
assert_left_col(result[1]);
|
|
assert_status_msg(result[2]);
|
|
}());
|
|
});
|
|
|
|
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',
|
|
topic: '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_'),
|
|
};
|
|
}
|
|
|
|
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_next_same_sender, []);
|
|
}());
|
|
|
|
(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_next_same_sender, [message1]);
|
|
}());
|
|
|
|
(function test_append_message_different_subject() {
|
|
|
|
var message1 = build_message_context();
|
|
var message_group1 = build_message_group([
|
|
message1,
|
|
]);
|
|
|
|
var message2 = build_message_context({topic: '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.group_date_divider_html);
|
|
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_next_same_sender, []);
|
|
}());
|
|
|
|
(function test_append_message_different_subject_and_days() {
|
|
|
|
var message1 = build_message_context({timestamp: 1000});
|
|
var message_group1 = build_message_group([
|
|
message1,
|
|
]);
|
|
|
|
var message2 = build_message_context({topic: 'Test subject 2',
|
|
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_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_next_same_sender, []);
|
|
assert.equal(
|
|
message_group2.group_date_divider_html,
|
|
'900000000 - 1000000');
|
|
}());
|
|
|
|
(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_groups_list_equal(list._message_groups, [message_group1]);
|
|
assert.deepEqual(result.append_groups, []);
|
|
assert.deepEqual(result.prepend_groups, []);
|
|
assert.deepEqual(result.rerender_groups, []);
|
|
assert.deepEqual(result.append_messages, [message2]);
|
|
assert.deepEqual(result.rerender_messages_next_same_sender, [message1]);
|
|
assert(list._message_groups[0].message_containers[1].want_date_divider);
|
|
}());
|
|
|
|
(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_next_same_sender, []);
|
|
}());
|
|
|
|
(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_next_same_sender, [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_next_same_sender, []);
|
|
}());
|
|
|
|
(function test_prepend_message_different_subject() {
|
|
|
|
var message1 = build_message_context();
|
|
var message_group1 = build_message_group([
|
|
message1,
|
|
]);
|
|
|
|
var message2 = build_message_context({topic: '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_next_same_sender, []);
|
|
}());
|
|
|
|
(function test_prepend_message_different_subject_and_day() {
|
|
|
|
var message1 = build_message_context({timestamp: 900000});
|
|
var message_group1 = build_message_group([
|
|
message1,
|
|
]);
|
|
|
|
var message2 = build_message_context({topic: 'Test Subject 2',
|
|
timestamp: 1000});
|
|
var message_group2 = build_message_group([
|
|
message2,
|
|
]);
|
|
|
|
var list = build_list([message_group1]);
|
|
var result = list.merge_message_groups([message_group2], 'top');
|
|
|
|
// We should have a group date divider between the recipient blocks.
|
|
assert.equal(
|
|
message_group1.group_date_divider_html,
|
|
'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.deepEqual(result.rerender_groups, [message_group1]);
|
|
assert.deepEqual(result.append_messages, []);
|
|
assert.deepEqual(result.rerender_messages_next_same_sender, []);
|
|
}());
|
|
|
|
(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');
|
|
|
|
// We should have a group date divider within the single recipient block.
|
|
assert.equal(
|
|
message_group2.message_containers[1].date_divider_html,
|
|
'900000000 - 1000000');
|
|
assert_message_groups_list_equal(
|
|
list._message_groups,
|
|
[message_group2]);
|
|
assert.deepEqual(result.append_groups, []);
|
|
assert.deepEqual(result.prepend_groups, []);
|
|
assert_message_groups_list_equal(result.rerender_groups, [message_group2]);
|
|
assert.deepEqual(result.append_messages, []);
|
|
assert.deepEqual(result.rerender_messages_next_same_sender, []);
|
|
}());
|
|
|
|
(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_next_same_sender, []);
|
|
}());
|
|
|
|
});
|
|
|
|
// TODO: Add a test suite for rerender_messages_next_same_sender() that includes cases
|
|
// where new messages added via local echo have a different date from
|
|
// the older 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);
|
|
});
|