zulip/frontend_tests/node_tests/stream_list.js

764 lines
19 KiB
JavaScript

set_global('document', 'document-stub');
set_global('$', global.make_zjquery());
zrequire('unread_ui');
zrequire('Filter', 'js/filter');
zrequire('topic_data');
zrequire('stream_sort');
zrequire('colorspace');
zrequire('stream_color');
zrequire('hash_util');
zrequire('unread');
zrequire('stream_data');
zrequire('scroll_util');
zrequire('list_cursor');
zrequire('stream_list');
zrequire('topic_zoom');
zrequire('ui');
set_global('page_params', {
is_admin: false,
realm_users: [],
});
stream_color.initialize();
const noop = function () {};
const return_false = function () { return false; };
const return_true = function () { return true; };
set_global('topic_list', {});
set_global('overlays', {});
set_global('popovers', {});
set_global('keydown_util', {
handle: noop,
});
run_test('create_sidebar_row', () => {
// Make a couple calls to create_sidebar_row() and make sure they
// generate the right markup as well as play nice with get_stream_li().
page_params.demote_inactive_streams = 1;
const devel = {
name: 'devel',
stream_id: 100,
color: 'blue',
subscribed: true,
pin_to_top: true,
};
global.stream_data.add_sub(devel);
const social = {
name: 'social',
stream_id: 200,
color: 'green',
subscribed: true,
};
global.stream_data.add_sub(social);
global.unread.num_unread_for_stream = function () {
return 42;
};
(function create_devel_sidebar_row() {
const devel_value = $.create('devel-value');
const devel_count = $.create('devel-count');
const sidebar_row = $('<devel sidebar row>');
sidebar_row.set_find_results('.count', devel_count);
devel_count.set_find_results('.value', devel_value);
devel_count.set_parent(sidebar_row);
global.stub_templates(function (template_name, data) {
assert.equal(template_name, 'stream_sidebar_row');
assert.equal(data.uri, '#narrow/stream/100-devel');
return '<devel sidebar row>';
});
stream_list.create_sidebar_row(devel);
assert.equal(devel_value.text(), '42');
}());
(function create_social_sidebar_row() {
const social_value = $.create('social-value');
const social_count = $.create('social-count');
const sidebar_row = $('<social sidebar row>');
sidebar_row.set_find_results('.count', social_count);
social_count.set_find_results('.value', social_value);
social_count.set_parent(sidebar_row);
global.stub_templates(function (template_name, data) {
assert.equal(template_name, 'stream_sidebar_row');
assert.equal(data.uri, '#narrow/stream/200-social');
return '<social sidebar row>';
});
stream_list.create_sidebar_row(social);
assert.equal(social_value.text(), '42');
}());
const split = '<hr class="stream-split">';
const devel_sidebar = $('<devel sidebar row>');
const social_sidebar = $('<social sidebar row>');
let appended_elems;
$('#stream_filters').append = function (elems) {
appended_elems = elems;
};
let topic_list_cleared;
topic_list.clear = () => {
topic_list_cleared = true;
};
stream_list.build_stream_list();
assert(topic_list_cleared);
const expected_elems = [
devel_sidebar, //pinned
split, //separator
social_sidebar, //not pinned
];
assert.deepEqual(appended_elems, expected_elems);
const social_li = $('<social sidebar row>');
const stream_id = social.stream_id;
social_li.length = 0;
const privacy_elem = $.create('privacy-stub');
social_li.set_find_results('.stream-privacy', privacy_elem);
social.invite_only = true;
social.color = '#222222';
global.stub_templates(function (template_name, data) {
assert.equal(template_name, 'stream_privacy');
assert.equal(data.invite_only, true);
assert.equal(data.dark_background, 'dark_background');
return '<div>privacy-html';
});
stream_list.redraw_stream_privacy(social);
assert.equal(privacy_elem.html(), '<div>privacy-html');
stream_list.set_in_home_view(stream_id, false);
assert(social_li.hasClass('out_of_home_view'));
stream_list.set_in_home_view(stream_id, true);
assert(!social_li.hasClass('out_of_home_view'));
const row = stream_list.stream_sidebar.get_row(stream_id);
stream_data.is_active = return_true;
row.update_whether_active();
assert(!social_li.hasClass('inactive_stream'));
stream_data.is_active = return_false;
row.update_whether_active();
assert(social_li.hasClass('inactive_stream'));
let removed;
social_li.remove = function () {
removed = true;
};
row.remove();
assert(removed);
});
run_test('pinned_streams_never_inactive', () => {
// Ensure that pinned streams are never treated as dormant ie never given "inactive" class
stream_data.clear_subscriptions();
const devel = {
name: 'devel',
stream_id: 100,
color: 'blue',
subscribed: true,
pin_to_top: true,
};
global.stream_data.add_sub(devel);
const social = {
name: 'social',
stream_id: 200,
color: 'green',
subscribed: true,
};
global.stream_data.add_sub(social);
// we use social and devel created in create_social_sidebar_row() and create_devel_sidebar_row()
// non-pinned streams can be made inactive
const social_sidebar = $('<social sidebar row>');
let stream_id = social.stream_id;
let row = stream_list.stream_sidebar.get_row(stream_id);
stream_data.is_active = return_false;
stream_list.build_stream_list();
assert(social_sidebar.hasClass('inactive_stream'));
stream_data.is_active = return_true;
row.update_whether_active();
assert(!social_sidebar.hasClass('inactive_stream'));
stream_data.is_active = return_false;
row.update_whether_active();
assert(social_sidebar.hasClass('inactive_stream'));
// pinned streams can never be made inactive
const devel_sidebar = $('<devel sidebar row>');
stream_id = devel.stream_id;
row = stream_list.stream_sidebar.get_row(stream_id);
stream_data.is_active = return_false;
stream_list.build_stream_list();
assert(!devel_sidebar.hasClass('inactive_stream'));
row.update_whether_active();
assert(!devel_sidebar.hasClass('inactive_stream'));
});
set_global('$', global.make_zjquery());
function add_row(sub) {
global.stream_data.add_sub(sub);
const row = {
update_whether_active: function () {},
get_li: function () {
const html = '<' + sub.name + ' sidebar row html>';
const obj = $(html);
obj.length = 1; // bypass blueslip error
return obj;
},
};
stream_list.stream_sidebar.set_row(sub.stream_id, row);
}
function initialize_stream_data() {
stream_data.clear_subscriptions();
// pinned streams
const develSub = {
name: 'devel',
stream_id: 1000,
color: 'blue',
pin_to_top: true,
subscribed: true,
};
add_row(develSub);
const RomeSub = {
name: 'Rome',
stream_id: 2000,
color: 'blue',
pin_to_top: true,
subscribed: true,
};
add_row(RomeSub);
const testSub = {
name: 'test',
stream_id: 3000,
color: 'blue',
pin_to_top: true,
subscribed: true,
};
add_row(testSub);
// unpinned streams
const announceSub = {
name: 'announce',
stream_id: 4000,
color: 'green',
pin_to_top: false,
subscribed: true,
};
add_row(announceSub);
const DenmarkSub = {
name: 'Denmark',
stream_id: 5000,
color: 'green',
pin_to_top: false,
subscribed: true,
};
add_row(DenmarkSub);
const carSub = {
name: 'cars',
stream_id: 6000,
color: 'green',
pin_to_top: false,
subscribed: true,
};
add_row(carSub);
}
function elem($obj) {
return {to_$: () => $obj};
}
run_test('zoom_in_and_zoom_out', () => {
const label1 = $.create('label1 stub');
const label2 = $.create('label2 stub');
label1.show();
label2.show();
assert(label1.visible());
assert(label2.visible());
$('.stream-filters-label').each = (f) => {
f.call(elem(label1));
f.call(elem(label2));
};
const splitter = $.create('hr stub');
splitter.show();
assert(splitter.visible());
$('.stream-split').each = (f) => {
f.call(elem(splitter));
};
const stream_li1 = $.create('stream1 stub');
const stream_li2 = $.create('stream2 stub');
function make_attr(arg) {
return (sel) => {
assert.equal(sel, 'data-stream-id');
return arg;
};
}
stream_li1.attr = make_attr('42');
stream_li1.hide();
stream_li2.attr = make_attr('99');
$('#stream_filters li.narrow-filter').each = (f) => {
f.call(elem(stream_li1));
f.call(elem(stream_li2));
};
$('#stream-filters-container')[0] = {
dataset: {},
};
stream_list.set_event_handlers();
stream_list.zoom_in_topics({stream_id: 42});
assert(!label1.visible());
assert(!label2.visible());
assert(!splitter.visible());
assert(stream_li1.visible());
assert(!stream_li2.visible());
assert($('#streams_list').hasClass('zoom-in'));
$('#stream_filters li.narrow-filter').show = () => {
stream_li1.show();
stream_li2.show();
};
stream_li1.length = 1;
stream_list.zoom_out_topics({stream_li: stream_li1});
assert(label1.visible());
assert(label2.visible());
assert(splitter.visible());
assert(stream_li1.visible());
assert(stream_li2.visible());
assert($('#streams_list').hasClass('zoom-out'));
});
set_global('$', global.make_zjquery());
run_test('narrowing', () => {
initialize_stream_data();
set_global('narrow_state', {
stream: function () { return 'devel'; },
topic: noop,
});
topic_list.close = noop;
topic_list.rebuild = noop;
topic_list.active_stream_id = noop;
topic_list.get_stream_li = noop;
scroll_util.scroll_element_into_container = noop;
set_global('ui', {
get_scroll_element: element => element,
});
assert(!$('<devel sidebar row html>').hasClass('active-filter'));
stream_list.set_event_handlers();
let filter;
filter = new Filter([
{operator: 'stream', operand: 'devel'},
]);
stream_list.handle_narrow_activated(filter);
assert($('<devel sidebar row html>').hasClass('active-filter'));
filter = new Filter([
{operator: 'stream', operand: 'cars'},
{operator: 'topic', operand: 'sedans'},
]);
stream_list.handle_narrow_activated(filter);
assert(!$("ul.filters li").hasClass('active-filter'));
assert(!$('<cars sidebar row html>').hasClass('active-filter')); // false because of topic
filter = new Filter([
{operator: 'stream', operand: 'cars'},
]);
stream_list.handle_narrow_activated(filter);
assert(!$("ul.filters li").hasClass('active-filter'));
assert($('<cars sidebar row html>').hasClass('active-filter'));
let removed_classes;
$("ul#stream_filters li").removeClass = (classes) => {
removed_classes = classes;
};
let topics_closed;
topic_list.close = () => {
topics_closed = true;
};
stream_list.handle_narrow_deactivated();
assert.equal(removed_classes, 'active-filter');
assert(topics_closed);
});
run_test('focusout_user_filter', () => {
const e = { };
const click_handler = $('.stream-list-filter').get_on_handler('focusout');
click_handler(e);
});
run_test('focus_user_filter', () => {
const e = {
stopPropagation: function () {},
};
const click_handler = $('.stream-list-filter').get_on_handler('click');
click_handler(e);
});
run_test('sort_streams', () => {
stream_data.clear_subscriptions();
// Get coverage on early-exit.
stream_list.build_stream_list();
initialize_stream_data();
global.stream_data.is_active = function (sub) {
return sub.name !== 'cars';
};
let appended_elems;
$('#stream_filters').append = function (elems) {
appended_elems = elems;
};
stream_list.build_stream_list();
const split = '<hr class="stream-split">';
const expected_elems = [
$('<devel sidebar row html>'),
$('<Rome sidebar row html>'),
$('<test sidebar row html>'),
split,
$('<announce sidebar row html>'),
$('<Denmark sidebar row html>'),
split,
$('<cars sidebar row html>'),
];
assert.deepEqual(appended_elems, expected_elems);
const streams = global.stream_sort.get_streams();
assert.deepEqual(streams, [
// three groups: pinned, normal, dormant
'devel',
'Rome',
'test',
//
'announce',
'Denmark',
//
'cars',
]);
const denmark_sub = stream_data.get_sub('Denmark');
const stream_id = denmark_sub.stream_id;
assert(stream_list.stream_sidebar.has_row_for(stream_id));
stream_list.remove_sidebar_row(stream_id);
assert(!stream_list.stream_sidebar.has_row_for(stream_id));
});
run_test('separators_only_pinned_and_dormant', () => {
// Test only pinned and dormant streams
stream_data.clear_subscriptions();
// Get coverage on early-exit.
stream_list.build_stream_list();
// pinned streams
const develSub = {
name: 'devel',
stream_id: 1000,
color: 'blue',
pin_to_top: true,
subscribed: true,
};
add_row(develSub);
const RomeSub = {
name: 'Rome',
stream_id: 2000,
color: 'blue',
pin_to_top: true,
subscribed: true,
};
add_row(RomeSub);
// dormant stream
const DenmarkSub = {
name: 'Denmark',
stream_id: 3000,
color: 'blue',
pin_to_top: false,
subscribed: true,
};
add_row(DenmarkSub);
global.stream_data.is_active = function (sub) {
return sub.name !== 'Denmark';
};
let appended_elems;
$('#stream_filters').append = function (elems) {
appended_elems = elems;
};
stream_list.build_stream_list();
const split = '<hr class="stream-split">';
const expected_elems = [
// pinned
$('<devel sidebar row html>'),
$('<Rome sidebar row html>'),
split,
// dormant
$('<Denmark sidebar row html>'),
];
assert.deepEqual(appended_elems, expected_elems);
});
run_test('separators_only_pinned', () => {
// Test only pinned streams
stream_data.clear_subscriptions();
// Get coverage on early-exit.
stream_list.build_stream_list();
// pinned streams
const develSub = {
name: 'devel',
stream_id: 1000,
color: 'blue',
pin_to_top: true,
subscribed: true,
};
add_row(develSub);
const RomeSub = {
name: 'Rome',
stream_id: 2000,
color: 'blue',
pin_to_top: true,
subscribed: true,
};
add_row(RomeSub);
let appended_elems;
$('#stream_filters').append = function (elems) {
appended_elems = elems;
};
stream_list.build_stream_list();
const expected_elems = [
// pinned
$('<devel sidebar row html>'),
$('<Rome sidebar row html>'),
// no separator at the end as no stream follows
];
assert.deepEqual(appended_elems, expected_elems);
});
run_test('update_count_in_dom', () => {
function make_elem(elem, count_selector, value_selector) {
const count = $(count_selector);
const value = $(value_selector);
elem.set_find_results('.count', count);
count.set_find_results('.value', value);
count.set_parent(elem);
return elem;
}
const stream_li = make_elem(
$('<stream li>'),
'<stream-count>',
'<stream-value>'
);
$('<stream li>').length = 0;
stream_li.addClass('subscription_block');
stream_li.addClass('stream-with-count');
assert(stream_li.hasClass('stream-with-count'));
const stream_count = new Map();
const stream_id = 11;
const stream_row = {
get_li: function () { return stream_li; },
};
stream_list.stream_sidebar.set_row(stream_id, stream_row);
stream_count.set(stream_id, 0);
const counts = {
stream_count: stream_count,
topic_count: new Map(),
};
stream_list.update_dom_with_unread_counts(counts);
assert.equal($('<stream li>').text(), 'never-been-set');
assert(!stream_li.hasClass('stream-with-count'));
stream_count.set(stream_id, 99);
stream_list.update_dom_with_unread_counts(counts);
assert.equal($('<stream-value>').text(), '99');
assert(stream_li.hasClass('stream-with-count'));
});
narrow_state.active = () => false;
run_test('rename_stream', () => {
const sub = stream_data.get_sub_by_name('devel');
const new_name = 'Development';
stream_data.rename_sub(sub, new_name);
const li_stub = $.create('li stub');
li_stub.length = 0;
global.stub_templates((name, payload) => {
assert.equal(name, 'stream_sidebar_row');
assert.deepEqual(payload, {
name: 'Development',
id: 1000,
uri: '#narrow/stream/1000-Development',
is_muted: false,
invite_only: undefined,
is_web_public: undefined,
color: payload.color,
pin_to_top: true,
dark_background: payload.dark_background,
});
return {to_$: () => li_stub};
});
let count_updated;
stream_list.update_count_in_dom = (li) => {
assert.equal(li, li_stub);
count_updated = true;
};
stream_list.rename_stream(sub);
assert(count_updated);
});
set_global('$', global.make_zjquery());
run_test('refresh_pin', () => {
initialize_stream_data();
const sub = {
name: 'maybe_pin',
stream_id: 100,
color: 'blue',
pin_to_top: false,
};
stream_data.add_sub(sub);
const pinned_sub = {
...sub,
pin_to_top: true,
};
const li_stub = $.create('li stub');
li_stub.length = 0;
global.stub_templates(() => {
return {to_$: () => li_stub};
});
stream_list.update_count_in_dom = noop;
$('#stream_filters').append = noop;
let scrolled;
stream_list.scroll_stream_into_view = (li) => {
assert.equal(li, li_stub);
scrolled = true;
};
stream_list.refresh_pinned_or_unpinned_stream(pinned_sub);
assert(scrolled);
});
run_test('create_initial_sidebar_rows', () => {
initialize_stream_data();
const html_dict = new Map();
stream_list.stream_sidebar = {
has_row_for: return_false,
set_row: function (stream_id, widget) {
html_dict.set(stream_id, widget.get_li().html());
},
};
stream_list.update_count_in_dom = noop;
global.stub_templates(function (template_name, data) {
assert.equal(template_name, 'stream_sidebar_row');
return '<div>stub-html-' + data.name;
});
// Test this code with stubs above...
stream_list.create_initial_sidebar_rows();
assert.equal(html_dict.get(1000), '<div>stub-html-devel');
assert.equal(html_dict.get(5000), '<div>stub-html-Denmark');
});