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
178 lines
5.6 KiB
JavaScript
178 lines
5.6 KiB
JavaScript
"use strict";
|
|
|
|
const assert = require("node:assert/strict");
|
|
|
|
const {make_bot} = require("./lib/example_user.cjs");
|
|
const {mock_esm, zrequire} = require("./lib/namespace.cjs");
|
|
const {run_test, noop} = require("./lib/test.cjs");
|
|
const {$} = require("./lib/zjquery.cjs");
|
|
|
|
/*
|
|
|
|
Let's step back and review what we've done so far.
|
|
|
|
We've used fairly straightforward testing techniques
|
|
to explore the following modules:
|
|
|
|
filter
|
|
message_store
|
|
narrow_state
|
|
people
|
|
stream_data
|
|
util
|
|
|
|
We haven't gone deep on any of these objects, but if
|
|
you are interested, all of these objects have test
|
|
suites that have 100% line coverage on the modules
|
|
that implement those objects. For example, you can look
|
|
at people.test.cjs in this directory for more tests on the
|
|
people object.
|
|
|
|
We can quickly review some testing concepts:
|
|
|
|
zrequire - bring in real code
|
|
mock_esm - mock es6 modules
|
|
assert.equal - verify results
|
|
|
|
------
|
|
|
|
Let's talk about our next steps.
|
|
|
|
An app is pretty useless without an actual data source.
|
|
One of the primary ways that a Zulip client gets data
|
|
is through events. (We also get data at page load, and
|
|
we can also ask the server for data, but that's not in
|
|
the scope of this conversation yet.)
|
|
|
|
Chat systems are dynamic. If an admin adds a user, or
|
|
if a user sends a messages, the server immediately sends
|
|
events to all clients so that they can reflect appropriate
|
|
changes in their UI. We're not going to discuss the entire
|
|
"full stack" mechanism here. Instead, we'll focus on
|
|
the client code, starting at the boundary where we
|
|
process events.
|
|
|
|
Let's just get started...
|
|
|
|
*/
|
|
|
|
// We are going to use mock versions of some of our libraries.
|
|
const activity_ui = mock_esm("../src/activity_ui");
|
|
const message_live_update = mock_esm("../src/message_live_update");
|
|
const pm_list = mock_esm("../src/pm_list");
|
|
const settings_bots = mock_esm("../src/settings_bots");
|
|
const settings_users = mock_esm("../src/settings_users");
|
|
const user_profile = mock_esm("../src/user_profile");
|
|
mock_esm("../src/compose_recipient", {
|
|
update_user_name_in_compose() {},
|
|
});
|
|
mock_esm("../src/message_view_header", {
|
|
maybe_update_navbar_title_for_user() {},
|
|
});
|
|
|
|
// Use real versions of these modules.
|
|
const bot_data = zrequire("bot_data");
|
|
const people = zrequire("people");
|
|
const server_events_dispatch = zrequire("server_events_dispatch");
|
|
const {set_current_user} = zrequire("state_data");
|
|
|
|
set_current_user({});
|
|
|
|
const bob = make_bot({
|
|
email: "bob@example.com",
|
|
user_id: 33,
|
|
full_name: "Bob Roberts",
|
|
});
|
|
|
|
run_test("add users with event", ({override}) => {
|
|
people.init();
|
|
|
|
const event = {
|
|
type: "realm_user",
|
|
op: "add",
|
|
person: bob,
|
|
};
|
|
|
|
assert.ok(!people.is_known_user_id(bob.user_id));
|
|
|
|
// We need to override a stub here before dispatching the event.
|
|
// Keep reading to see how overriding works!
|
|
override(settings_bots, "redraw_all_bots_list", noop);
|
|
override(activity_ui, "check_should_redraw_new_user", noop);
|
|
override(pm_list, "update_private_messages", noop);
|
|
// Let's simulate dispatching our event!
|
|
server_events_dispatch.dispatch_normal_event(event);
|
|
|
|
// And it works!
|
|
assert.ok(people.is_known_user_id(bob.user_id));
|
|
});
|
|
|
|
/*
|
|
|
|
It's actually a little surprising that adding a user does
|
|
not have side effects beyond the people object, the bots list,
|
|
and the direct messages list. I guess we don't immediately
|
|
update the buddy list, but that's because the buddy list gets
|
|
updated on the next server fetch.
|
|
|
|
Let's try an update next. To make this work, we will want
|
|
to override some more of our stubs.
|
|
|
|
This is where we see a little extra benefit from the
|
|
run_test wrapper. It passes us in an object that we
|
|
can use to override data, and that works within the
|
|
scope of the function.
|
|
|
|
*/
|
|
|
|
run_test("update user with event", ({override}) => {
|
|
people.init();
|
|
people.add_active_user(bob);
|
|
bot_data.add({
|
|
default_all_public_streams: true,
|
|
default_events_register_stream: "register stream test",
|
|
default_sending_stream: "sending stream test",
|
|
user_id: bob.user_id,
|
|
services: [],
|
|
});
|
|
|
|
set_current_user({user_id: bob.user_id});
|
|
|
|
const $select = $.create("#user-self-role-select");
|
|
const $option = $.create('option[value="100"]');
|
|
$select.set_find_results('option[value="100"]', $option);
|
|
|
|
const new_bob = {
|
|
user_id: bob.user_id,
|
|
full_name: "The Artist Formerly Known as Bob",
|
|
};
|
|
|
|
const event = {
|
|
type: "realm_user",
|
|
op: "update",
|
|
person: new_bob,
|
|
};
|
|
|
|
// We have to stub a few things. We don't want to test
|
|
// the details of these functions, but we do want to
|
|
// verify that they run. Fortunately, the run_test()
|
|
// wrapper will tell us if we override a method that
|
|
// doesn't get called!
|
|
override(activity_ui, "redraw", noop);
|
|
override(message_live_update, "update_user_full_name", noop);
|
|
override(pm_list, "update_private_messages", noop);
|
|
override(settings_users, "update_user_data", noop);
|
|
override(settings_bots, "update_bot_data", noop);
|
|
override(user_profile, "update_profile_modal_ui", noop);
|
|
|
|
// Dispatch the realm_user/update event, which will update
|
|
// data structures and have other side effects that are
|
|
// stubbed out above.
|
|
server_events_dispatch.dispatch_normal_event(event);
|
|
|
|
const user = people.get_by_user_id(bob.user_id);
|
|
|
|
// Verify that the code actually did its main job:
|
|
assert.equal(user.full_name, "The Artist Formerly Known as Bob");
|
|
});
|