mirror of
				https://github.com/zulip/zulip.git
				synced 2025-10-31 03:53:50 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			377 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			377 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| "use strict";
 | |
| 
 | |
| const assert = require("node:assert/strict");
 | |
| 
 | |
| const _ = require("lodash");
 | |
| 
 | |
| const {
 | |
|     clear_buddy_list,
 | |
|     override_user_matches_narrow_using_loaded_data,
 | |
|     buddy_list_add_user_matching_view,
 | |
|     buddy_list_add_other_user,
 | |
|     stub_buddy_list_elements,
 | |
| } = require("./lib/buddy_list.cjs");
 | |
| const {make_realm} = require("./lib/example_realm.cjs");
 | |
| const {mock_esm, zrequire} = require("./lib/namespace.cjs");
 | |
| const {run_test, noop} = require("./lib/test.cjs");
 | |
| const blueslip = require("./lib/zblueslip.cjs");
 | |
| const $ = require("./lib/zjquery.cjs");
 | |
| 
 | |
| const padded_widget = mock_esm("../src/padded_widget");
 | |
| const message_viewport = mock_esm("../src/message_viewport");
 | |
| 
 | |
| const buddy_data = zrequire("buddy_data");
 | |
| const {BuddyList} = zrequire("buddy_list");
 | |
| const people = zrequire("people");
 | |
| const {set_realm} = zrequire("state_data");
 | |
| const {initialize_user_settings} = zrequire("user_settings");
 | |
| 
 | |
| set_realm(make_realm());
 | |
| initialize_user_settings({user_settings: {}});
 | |
| 
 | |
| function init_simulated_scrolling() {
 | |
|     const elem = {
 | |
|         dataset: {},
 | |
|         scrollTop: 0,
 | |
|         scrollHeight: 0,
 | |
|     };
 | |
| 
 | |
|     $.create("#buddy_list_wrapper", {children: [elem]});
 | |
| 
 | |
|     $("#buddy_list_wrapper_padding").set_height(0);
 | |
| 
 | |
|     return elem;
 | |
| }
 | |
| 
 | |
| const alice = {
 | |
|     email: "alice@zulip.com",
 | |
|     user_id: 10,
 | |
|     full_name: "Alice Smith",
 | |
| };
 | |
| people.add_active_user(alice);
 | |
| const bob = {
 | |
|     email: "bob@zulip.com",
 | |
|     user_id: 15,
 | |
|     full_name: "Bob Smith",
 | |
| };
 | |
| people.add_active_user(bob);
 | |
| const chris = {
 | |
|     email: "chris@zulip.com",
 | |
|     user_id: 20,
 | |
|     full_name: "Chris Smith",
 | |
| };
 | |
| people.add_active_user(chris);
 | |
| const $alice_li = $.create("alice-stub");
 | |
| const $bob_li = $.create("bob-stub");
 | |
| 
 | |
| run_test("basics", ({override, mock_template}) => {
 | |
|     const buddy_list = new BuddyList();
 | |
|     init_simulated_scrolling();
 | |
| 
 | |
|     override(buddy_list, "items_to_html", () => "<html-stub>");
 | |
|     override(message_viewport, "height", () => 550);
 | |
|     override(padded_widget, "update_padding", noop);
 | |
|     stub_buddy_list_elements();
 | |
|     mock_template("buddy_list/view_all_users.hbs", false, () => "<view-all-users-stub>");
 | |
| 
 | |
|     buddy_list.populate({
 | |
|         all_user_ids: [alice.user_id],
 | |
|     });
 | |
| 
 | |
|     const $alice_li = "alice-stub";
 | |
| 
 | |
|     override(buddy_list, "get_li_from_user_id", (opts) => {
 | |
|         const user_id = opts.user_id;
 | |
| 
 | |
|         assert.equal(user_id, alice.user_id);
 | |
|         return $alice_li;
 | |
|     });
 | |
| 
 | |
|     const $li = buddy_list.find_li({
 | |
|         key: alice.user_id,
 | |
|     });
 | |
|     assert.equal($li, $alice_li);
 | |
| });
 | |
| 
 | |
| run_test("split list", ({override, override_rewire, mock_template}) => {
 | |
|     const buddy_list = new BuddyList();
 | |
|     init_simulated_scrolling();
 | |
|     stub_buddy_list_elements();
 | |
|     mock_template("buddy_list/view_all_users.hbs", false, () => "<view-all-users-stub>");
 | |
| 
 | |
|     override_rewire(
 | |
|         buddy_data,
 | |
|         "user_matches_narrow_using_loaded_data",
 | |
|         override_user_matches_narrow_using_loaded_data,
 | |
|     );
 | |
| 
 | |
|     override(buddy_list, "items_to_html", (opts) => {
 | |
|         assert.ok(opts.items.length > 0);
 | |
|         return "<html-stub>";
 | |
|     });
 | |
|     override(message_viewport, "height", () => 550);
 | |
|     override(padded_widget, "update_padding", noop);
 | |
| 
 | |
|     let appended_to_users_matching_view = false;
 | |
|     $("#buddy-list-users-matching-view").append = ($element) => {
 | |
|         if ($element.selector === "<html-stub>") {
 | |
|             appended_to_users_matching_view = true;
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     let appended_to_other_users = false;
 | |
|     $("#buddy-list-other-users").append = ($element) => {
 | |
|         if ($element.selector === "<html-stub>") {
 | |
|             appended_to_other_users = true;
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     // one user matching the view
 | |
|     buddy_list_add_user_matching_view(alice.user_id, $alice_li);
 | |
|     buddy_list.populate({
 | |
|         all_user_ids: [alice.user_id],
 | |
|     });
 | |
|     assert.ok(appended_to_users_matching_view);
 | |
|     assert.ok(!appended_to_other_users);
 | |
|     appended_to_users_matching_view = false;
 | |
| 
 | |
|     // one other user
 | |
|     clear_buddy_list(buddy_list);
 | |
|     buddy_list_add_other_user(alice.user_id, $alice_li);
 | |
|     buddy_list.populate({
 | |
|         all_user_ids: [alice.user_id],
 | |
|     });
 | |
|     assert.ok(!appended_to_users_matching_view);
 | |
|     assert.ok(appended_to_other_users);
 | |
|     appended_to_other_users = false;
 | |
| 
 | |
|     // a user matching the view, and another user
 | |
|     clear_buddy_list(buddy_list);
 | |
|     buddy_list_add_user_matching_view(alice.user_id, $alice_li);
 | |
|     buddy_list_add_other_user(bob.user_id, $bob_li);
 | |
|     buddy_list.populate({
 | |
|         all_user_ids: [alice.user_id, bob.user_id],
 | |
|     });
 | |
|     assert.ok(appended_to_users_matching_view);
 | |
|     assert.ok(appended_to_other_users);
 | |
| });
 | |
| 
 | |
| run_test("find_li", ({override, mock_template}) => {
 | |
|     const buddy_list = new BuddyList();
 | |
| 
 | |
|     override(buddy_list, "fill_screen_with_content", noop);
 | |
|     mock_template("buddy_list/view_all_users.hbs", false, () => "<view-all-users-stub>");
 | |
|     stub_buddy_list_elements();
 | |
| 
 | |
|     clear_buddy_list(buddy_list);
 | |
|     buddy_list_add_user_matching_view(alice.user_id, $alice_li);
 | |
|     buddy_list_add_other_user(bob.user_id, $bob_li);
 | |
| 
 | |
|     let $li = buddy_list.find_li({
 | |
|         key: alice.user_id,
 | |
|     });
 | |
|     assert.equal($li, $alice_li);
 | |
| 
 | |
|     $li = buddy_list.find_li({
 | |
|         key: bob.user_id,
 | |
|     });
 | |
|     assert.equal($li, $bob_li);
 | |
| });
 | |
| 
 | |
| run_test("fill_screen_with_content early break on big list", ({override, mock_template}) => {
 | |
|     stub_buddy_list_elements();
 | |
|     const buddy_list = new BuddyList();
 | |
|     const elem = init_simulated_scrolling();
 | |
|     stub_buddy_list_elements();
 | |
|     mock_template("buddy_list/view_all_users.hbs", false, () => "<view-all-users-stub>");
 | |
| 
 | |
|     let chunks_inserted = 0;
 | |
|     override(buddy_list, "render_more", () => {
 | |
|         elem.scrollHeight += 100;
 | |
|         chunks_inserted += 1;
 | |
|     });
 | |
|     override(message_viewport, "height", () => 550);
 | |
| 
 | |
|     // We will have more than enough users, but still
 | |
|     // only do 6 chunks of data (20 users per chunk)
 | |
|     // because of exiting early from fill_screen_with_content
 | |
|     // because of not scrolling enough to fetch more users.
 | |
|     const num_users = 300;
 | |
|     const user_ids = [];
 | |
| 
 | |
|     _.times(num_users, (i) => {
 | |
|         const person = {
 | |
|             email: "foo" + i + "@zulip.com",
 | |
|             user_id: 100 + i,
 | |
|             full_name: "Somebody " + i,
 | |
|         };
 | |
|         people.add_active_user(person);
 | |
|         user_ids.push(person.user_id);
 | |
|     });
 | |
| 
 | |
|     buddy_list.populate({
 | |
|         all_user_ids: user_ids,
 | |
|     });
 | |
| 
 | |
|     // Only 6 chunks, even though that's 120 users instead of the full 300.
 | |
|     assert.equal(chunks_inserted, 6);
 | |
| });
 | |
| 
 | |
| run_test("big_list", ({override, override_rewire, mock_template}) => {
 | |
|     const buddy_list = new BuddyList();
 | |
|     init_simulated_scrolling();
 | |
| 
 | |
|     stub_buddy_list_elements();
 | |
|     override(padded_widget, "update_padding", noop);
 | |
|     override(message_viewport, "height", () => 550);
 | |
|     override_rewire(
 | |
|         buddy_data,
 | |
|         "user_matches_narrow_using_loaded_data",
 | |
|         override_user_matches_narrow_using_loaded_data,
 | |
|     );
 | |
|     mock_template("buddy_list/view_all_users.hbs", false, () => "<view-all-users-stub>");
 | |
| 
 | |
|     let items_to_html_call_count = 0;
 | |
|     override(buddy_list, "items_to_html", () => {
 | |
|         items_to_html_call_count += 1;
 | |
|         return "<html-stub>";
 | |
|     });
 | |
| 
 | |
|     const num_users = 300;
 | |
|     const user_ids = [];
 | |
| 
 | |
|     // This isn't a great way of testing this, but this is here for
 | |
|     // the sake of code coverage. Essentially, for a very long list,
 | |
|     // these buddy list sections can collect empty messages in the middle
 | |
|     // of populating (i.e. once a chunk is rendered) which later might need
 | |
|     // to be removed to add users from future chunks.
 | |
|     //
 | |
|     // For example: chunk1 populates only users in the list of users matching,
 | |
|     // the view and the empty list says "None", but chunk2 adds users to the
 | |
|     // other list so the "None" message should be removed.
 | |
|     //
 | |
|     // Here we're just saying both lists are rendered as empty from start,
 | |
|     // which doesn't actually happen, since I don't know how to properly
 | |
|     // get it set in the middle of buddy_list.populate().
 | |
|     $("#buddy-list-users-matching-view .empty-list-message").length = 1;
 | |
|     $("#buddy-list-other-users .empty-list-message").length = 1;
 | |
| 
 | |
|     _.times(num_users, (i) => {
 | |
|         const person = {
 | |
|             email: "foo" + i + "@zulip.com",
 | |
|             user_id: 100 + i,
 | |
|             full_name: "Somebody " + i,
 | |
|         };
 | |
|         people.add_active_user(person);
 | |
|         if (i < 100 || i % 2 === 0) {
 | |
|             buddy_list_add_user_matching_view(person.user_id, $.create("stub" + i));
 | |
|         } else {
 | |
|             buddy_list_add_other_user(person.user_id, $.create("stub" + i));
 | |
|         }
 | |
|         user_ids.push(person.user_id);
 | |
|     });
 | |
| 
 | |
|     buddy_list.populate({
 | |
|         all_user_ids: user_ids,
 | |
|     });
 | |
| 
 | |
|     // Chunks are default size 20, so there should be 300/20 = 15 chunks
 | |
|     // For the first 100/20 = 5 chunks, we only call to add a user matching ivew.
 | |
|     // For the last 10 chunks, there are two calls: one for users_matching_view
 | |
|     // and one for other_users.
 | |
|     assert.equal(items_to_html_call_count, 5 + 10 * 2);
 | |
| });
 | |
| 
 | |
| run_test("force_render", ({override}) => {
 | |
|     const buddy_list = new BuddyList();
 | |
|     buddy_list.render_count = 50;
 | |
| 
 | |
|     let num_rendered = 0;
 | |
|     override(buddy_list, "render_more", (opts) => {
 | |
|         num_rendered += opts.chunk_size;
 | |
|     });
 | |
| 
 | |
|     buddy_list.force_render({
 | |
|         pos: 60,
 | |
|     });
 | |
| 
 | |
|     assert.equal(num_rendered, 60 - 50 + 3);
 | |
| 
 | |
|     // Force a contrived error case for line coverage.
 | |
|     blueslip.expect("error", "cannot show user id at this position");
 | |
|     buddy_list.force_render({
 | |
|         pos: 10,
 | |
|     });
 | |
| });
 | |
| 
 | |
| run_test("find_li w/force_render", ({override}) => {
 | |
|     const buddy_list = new BuddyList();
 | |
| 
 | |
|     // If we call find_li w/force_render set, and the
 | |
|     // user_id is not already rendered in DOM, then the
 | |
|     // widget will force-render it.
 | |
|     const user_id = "999";
 | |
|     const $stub_li = "stub-li";
 | |
| 
 | |
|     override(buddy_list, "get_li_from_user_id", (opts) => {
 | |
|         assert.equal(opts.user_id, user_id);
 | |
|         return $stub_li;
 | |
|     });
 | |
| 
 | |
|     buddy_list.all_user_ids = ["foo", "bar", user_id, "baz"];
 | |
| 
 | |
|     let shown;
 | |
| 
 | |
|     override(buddy_list, "force_render", (opts) => {
 | |
|         assert.equal(opts.pos, 2);
 | |
|         shown = true;
 | |
|     });
 | |
| 
 | |
|     const $hidden_li = buddy_list.find_li({
 | |
|         key: user_id,
 | |
|     });
 | |
|     assert.equal($hidden_li, $stub_li);
 | |
|     assert.ok(!shown);
 | |
| 
 | |
|     const $li = buddy_list.find_li({
 | |
|         key: user_id,
 | |
|         force_render: true,
 | |
|     });
 | |
| 
 | |
|     assert.equal($li, $stub_li);
 | |
|     assert.ok(shown);
 | |
| });
 | |
| 
 | |
| run_test("find_li w/bad key", ({override}) => {
 | |
|     const buddy_list = new BuddyList();
 | |
|     override(buddy_list, "get_li_from_user_id", () => "stub-li");
 | |
| 
 | |
|     const $undefined_li = buddy_list.find_li({
 | |
|         key: "not-there",
 | |
|         force_render: true,
 | |
|     });
 | |
| 
 | |
|     assert.deepEqual($undefined_li, undefined);
 | |
| });
 | |
| 
 | |
| run_test("scrolling", ({override, mock_template}) => {
 | |
|     const buddy_list = new BuddyList();
 | |
|     let tried_to_fill;
 | |
|     override(buddy_list, "fill_screen_with_content", () => {
 | |
|         tried_to_fill = true;
 | |
|     });
 | |
|     mock_template("buddy_list/view_all_users.hbs", false, () => "<view-all-users-stub>");
 | |
|     stub_buddy_list_elements();
 | |
|     init_simulated_scrolling();
 | |
|     stub_buddy_list_elements();
 | |
| 
 | |
|     clear_buddy_list(buddy_list);
 | |
|     assert.ok(tried_to_fill);
 | |
|     tried_to_fill = false;
 | |
| 
 | |
|     buddy_list.start_scroll_handler();
 | |
|     $(buddy_list.scroll_container_selector).trigger("scroll");
 | |
| 
 | |
|     assert.ok(tried_to_fill);
 | |
| });
 |