set_global('document', 'document-stub'); set_global('$', global.make_zjquery()); set_global('blueslip', global.make_zblueslip()); 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 = $(''); 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 ''; }); 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 = $(''); 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 ''; }); stream_list.create_sidebar_row(social); assert.equal(social_value.text(), '42'); }()); const split = '
'; const devel_sidebar = $(''); const social_sidebar = $(''); let appended_elems; $('#stream_filters').append = function (elems) { appended_elems = elems; }; stream_list.build_stream_list(); const expected_elems = [ devel_sidebar, //pinned split, //separator social_sidebar, //not pinned ]; assert.deepEqual(appended_elems, expected_elems); const social_li = $(''); 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 '
privacy-html'; }); stream_list.redraw_stream_privacy(social); assert.equal(privacy_elem.html(), '
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 = $(''); 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 = $(''); 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.set_click_handlers = noop; topic_list.close = noop; topic_list.remove_expanded_topics = noop; topic_list.rebuild = noop; topic_list.active_stream_id = noop; topic_list.get_stream_li = noop; stream_list.zoom_out_topics = noop; scroll_util.scroll_element_into_container = noop; set_global('ui', { get_scroll_element: element => element, }); assert(!$('').hasClass('active-filter')); stream_list.set_event_handlers(); let filter; filter = new Filter([ {operator: 'stream', operand: 'devel'}, ]); stream_list.handle_narrow_activated(filter); assert($('').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(!$('').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($('').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 = '
'; const expected_elems = [ $(''), $(''), $(''), split, $(''), $(''), split, $(''), ]; 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); // dorment 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 = '
'; const expected_elems = [ // pinned $(''), $(''), split, // dormant $(''), ]; 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 $(''), $(''), // 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( $(''), '', '' ); $('').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($('').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($('').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 '
stub-html-' + data.name; }); // Test this code with stubs above... stream_list.create_initial_sidebar_rows(); assert.equal(html_dict.get(1000), '
stub-html-devel'); assert.equal(html_dict.get(5000), '
stub-html-Denmark'); });