Files
zulip/web/tests/typing_data.test.cjs
opmkumar 2a15da47d9 message_edit: Show typing indicator for message editing.
This commit adds typing indicators for message editing in stream
as well as in dm, if the send typing notification
for corresponding is enabled.

Based on earlier work in #28585.

Co-authored-by: Rohan Gudimetla <rohan.gudimetla07@gmail.com>

Fixes #25719.
2025-02-12 15:08:56 -08:00

266 lines
8.4 KiB
JavaScript

"use strict";
const assert = require("node:assert/strict");
const {set_global, zrequire} = require("./lib/namespace.cjs");
const {run_test} = require("./lib/test.cjs");
const muted_users = zrequire("muted_users");
const typing_data = zrequire("typing_data");
function test(label, f) {
run_test(label, ({override}) => {
typing_data.clear_for_testing();
muted_users.set_muted_users([]);
f({override});
});
}
test("basics", () => {
// The typing_data needs to be robust with lists of
// user ids being in arbitrary sorting order. So all
// the apparent randomness in these tests has a purpose.
const stream_id = 1;
const topic = "typing notifications";
const topic_typing_key = typing_data.get_topic_key(stream_id, topic);
let status;
typing_data.add_typist(typing_data.get_direct_message_conversation_key([5, 10, 15]), 15);
assert.deepEqual(typing_data.get_group_typists([15, 10, 5]), [15]);
typing_data.add_typist(topic_typing_key, 12);
assert.deepEqual(typing_data.get_topic_typists(stream_id, topic), [12]);
// test that you can add a message_id to messages editing state
typing_data.add_edit_message_typing_id(3);
assert.deepEqual(typing_data.is_message_editing(3), true);
typing_data.add_edit_message_typing_id(7);
assert.deepEqual(typing_data.is_message_editing(7), true);
// test removing a message from editing state
status = typing_data.remove_edit_message_typing_id(3);
assert.deepEqual(status, true);
assert.deepEqual(typing_data.is_message_editing(3), false);
// test removing message_id that doesn't exist from editing
assert.deepEqual(typing_data.is_message_editing(3), false);
status = typing_data.remove_edit_message_typing_id(3);
assert.deepEqual(status, false);
// test that you can add twice
typing_data.add_typist(typing_data.get_direct_message_conversation_key([5, 10, 15]), 15);
// add another id to our first group
typing_data.add_typist(typing_data.get_direct_message_conversation_key([5, 10, 15]), 10);
assert.deepEqual(typing_data.get_group_typists([10, 15, 5]), [10, 15]);
typing_data.add_typist(topic_typing_key, 12);
// add another typist to our stream/topic
typing_data.add_typist(topic_typing_key, 13);
assert.deepEqual(typing_data.get_topic_typists(stream_id, topic), [12, 13]);
// start adding to a new group
typing_data.add_typist(typing_data.get_direct_message_conversation_key([7, 15]), 7);
typing_data.add_typist(typing_data.get_direct_message_conversation_key([7, 15]), 15);
// test get_all_direct_message_typists
assert.deepEqual(typing_data.get_all_direct_message_typists(), [7, 10, 15]);
// test basic removal
assert.ok(
typing_data.remove_typist(typing_data.get_direct_message_conversation_key([15, 7]), 7),
);
assert.deepEqual(typing_data.get_group_typists([7, 15]), [15]);
assert.ok(typing_data.remove_typist(topic_typing_key, 12));
assert.deepEqual(typing_data.get_topic_typists(stream_id, topic), [13]);
// test removing an id that is not there
assert.ok(
!typing_data.remove_typist(typing_data.get_direct_message_conversation_key([15, 7]), 7),
);
assert.deepEqual(typing_data.get_group_typists([7, 15]), [15]);
assert.deepEqual(typing_data.get_all_direct_message_typists(), [10, 15]);
// remove user from one group, but "15" will still be among
// "all typists"
assert.ok(
typing_data.remove_typist(typing_data.get_direct_message_conversation_key([15, 7]), 15),
);
assert.deepEqual(typing_data.get_all_direct_message_typists(), [10, 15]);
// now remove from the other group
assert.ok(
typing_data.remove_typist(typing_data.get_direct_message_conversation_key([5, 15, 10]), 15),
);
assert.deepEqual(typing_data.get_all_direct_message_typists(), [10]);
// test duplicate ids in a groups
typing_data.add_typist(typing_data.get_direct_message_conversation_key([20, 40, 20]), 20);
assert.deepEqual(typing_data.get_group_typists([20, 40]), [20]);
// test clearing out typing data
typing_data.clear_typing_data();
assert.deepEqual(typing_data.get_group_typists(), []);
assert.deepEqual(typing_data.get_all_direct_message_typists(), []);
assert.deepEqual(typing_data.get_topic_typists(stream_id, topic), []);
});
test("muted_typists_excluded", () => {
const stream_id = 1;
const topic = "typing notifications";
const topic_typing_key = typing_data.get_topic_key(stream_id, topic);
typing_data.add_typist(typing_data.get_direct_message_conversation_key([5, 10, 15]), 5);
typing_data.add_typist(typing_data.get_direct_message_conversation_key([5, 10, 15]), 10);
typing_data.add_typist(topic_typing_key, 7);
typing_data.add_typist(topic_typing_key, 12);
// Nobody is muted.
assert.deepEqual(typing_data.get_group_typists([5, 10, 15]), [5, 10]);
assert.deepEqual(typing_data.get_all_direct_message_typists(), [5, 10]);
assert.deepEqual(typing_data.get_topic_typists(stream_id, topic), [7, 12]);
// Mute a user, and test that the get_* functions exclude that user.
muted_users.add_muted_user(10);
muted_users.add_muted_user(7);
assert.deepEqual(typing_data.get_group_typists([5, 10, 15]), [5]);
assert.deepEqual(typing_data.get_all_direct_message_typists(), [5]);
assert.deepEqual(typing_data.get_topic_typists(stream_id, topic), [12]);
});
test("timers", () => {
const events = {};
const stub_timer_id = "timer_id_stub";
const stub_group = [5, 10, 15];
const stub_delay = 99;
const stub_f = "function";
const stub_stream_id = 1;
const stub_topic = "typing notifications";
const topic_typing_key = typing_data.get_topic_key(stub_stream_id, stub_topic);
function set_timeout(f, delay) {
assert.equal(delay, stub_delay);
events.f = f;
events.timer_set = true;
return stub_timer_id;
}
function clear_timeout(timer) {
assert.equal(timer, stub_timer_id);
events.timer_cleared = true;
}
function reset_events() {
events.f = undefined;
events.timer_cleared = false;
events.timer_set = false;
}
function kickstart() {
reset_events();
typing_data.kickstart_inbound_timer(
typing_data.get_direct_message_conversation_key(stub_group),
stub_delay,
stub_f,
);
}
function clear() {
reset_events();
typing_data.clear_inbound_timer(
typing_data.get_direct_message_conversation_key(stub_group),
);
}
function streams_kickstart() {
reset_events();
typing_data.kickstart_inbound_timer(topic_typing_key, stub_delay, stub_f);
}
function streams_clear() {
reset_events();
typing_data.clear_inbound_timer(topic_typing_key);
}
set_global("setTimeout", set_timeout);
set_global("clearTimeout", clear_timeout);
// first time, we set
kickstart();
assert.deepEqual(events, {
f: stub_f,
timer_cleared: false,
timer_set: true,
});
// second time we clear and set
kickstart();
assert.deepEqual(events, {
f: stub_f,
timer_cleared: true,
timer_set: true,
});
// clearing out typing data
kickstart();
typing_data.clear_typing_data();
assert.deepEqual(events, {
f: stub_f,
timer_cleared: true,
timer_set: true,
});
kickstart();
// first time clearing, we clear
clear();
assert.deepEqual(events, {
f: undefined,
timer_cleared: true,
timer_set: false,
});
// second time clearing, we noop
clear();
assert.deepEqual(events, {
f: undefined,
timer_cleared: false,
timer_set: false,
});
// first time, we set
streams_kickstart();
assert.deepEqual(events, {
f: stub_f,
timer_cleared: false,
timer_set: true,
});
// second time we clear and set
streams_kickstart();
assert.deepEqual(events, {
f: stub_f,
timer_cleared: true,
timer_set: true,
});
// first time clearing, we clear
streams_clear();
assert.deepEqual(events, {
f: undefined,
timer_cleared: true,
timer_set: false,
});
// second time clearing, we noop
streams_clear();
assert.deepEqual(events, {
f: undefined,
timer_cleared: false,
timer_set: false,
});
});