snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
This commit is contained in:
265
web/tests/typing_data.test.cjs
Normal file
265
web/tests/typing_data.test.cjs
Normal file
@@ -0,0 +1,265 @@
|
||||
"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,
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user