mirror of
https://github.com/zulip/zulip.git
synced 2025-11-07 07:23:22 +00:00
This is a fairly straightforward extraction. It's good to test this with Iago, and then go into Manage Streams and add/remove subscribers for a stream like devel. I copy/pasted two small functions that will soon diverge from stream_edit. The get_stream_id function will either use a module variable (since we're generally only editing subscribers for one stream, and we already have the singleton assumption with `input_pill`) or a more strict CSS selector. And then get_sub_for_target depends on get_stream_id. We may not always need full subs, anyway, and when we adapt some of this code for creating streams, things are likely to change. I stopped exporting a couple functions that have no callers outside of this module. The main entry point for the module is enable_subscriber_management. We continue to export invite_user_to_stream and remove_user_from_stream, which should possibly be just pulled into their own module to lessen some dependencies, but they don't have too much baggage, since they just wrap channel calls.
391 lines
13 KiB
JavaScript
391 lines
13 KiB
JavaScript
"use strict";
|
|
|
|
const {strict: assert} = require("assert");
|
|
|
|
const {mock_esm, zrequire} = require("../zjsunit/namespace");
|
|
const {run_test} = require("../zjsunit/test");
|
|
const $ = require("../zjsunit/zjquery");
|
|
const {page_params, user_settings} = require("../zjsunit/zpage_params");
|
|
|
|
const noop = () => {};
|
|
|
|
const typeahead_helper = mock_esm("../../static/js/typeahead_helper");
|
|
const ui = mock_esm("../../static/js/ui", {
|
|
get_scroll_element: noop,
|
|
});
|
|
|
|
mock_esm("../../static/js/browser_history", {update: noop});
|
|
mock_esm("../../static/js/hash_util", {
|
|
stream_edit_uri: noop,
|
|
by_stream_uri: noop,
|
|
active_stream: noop,
|
|
});
|
|
mock_esm("../../static/js/list_widget", {
|
|
create: () => ({init: noop}),
|
|
});
|
|
mock_esm("../../static/js/stream_color", {
|
|
set_colorpicker_color: noop,
|
|
});
|
|
mock_esm("../../static/js/components", {
|
|
toggle: () => ({
|
|
get: () => [],
|
|
}),
|
|
});
|
|
|
|
const peer_data = zrequire("peer_data");
|
|
const people = zrequire("people");
|
|
const stream_data = zrequire("stream_data");
|
|
const stream_edit = zrequire("stream_edit");
|
|
const stream_pill = zrequire("stream_pill");
|
|
const user_groups = zrequire("user_groups");
|
|
const user_group_pill = zrequire("user_group_pill");
|
|
const user_pill = zrequire("user_pill");
|
|
const stream_subscribers_ui = zrequire("stream_subscribers_ui");
|
|
const stream_ui_updates = zrequire("stream_ui_updates");
|
|
const settings_config = zrequire("settings_config");
|
|
|
|
const jill = {
|
|
email: "jill@zulip.com",
|
|
user_id: 10,
|
|
full_name: "Jill Hill",
|
|
};
|
|
const mark = {
|
|
email: "mark@zulip.com",
|
|
user_id: 20,
|
|
full_name: "Marky Mark",
|
|
};
|
|
const fred = {
|
|
email: "fred@zulip.com",
|
|
user_id: 30,
|
|
full_name: "Fred Flintstone",
|
|
};
|
|
const me = {
|
|
email: "me@example.com",
|
|
user_id: 40,
|
|
full_name: "me",
|
|
};
|
|
|
|
const persons = [jill, mark, fred, me];
|
|
for (const person of persons) {
|
|
people.add_active_user(person);
|
|
}
|
|
|
|
const admins = {
|
|
name: "Admins",
|
|
description: "foo",
|
|
id: 1,
|
|
members: [jill.user_id, mark.user_id],
|
|
};
|
|
const testers = {
|
|
name: "Testers",
|
|
description: "bar",
|
|
id: 2,
|
|
members: [mark.user_id, fred.user_id, me.user_id],
|
|
};
|
|
|
|
const groups = [admins, testers];
|
|
for (const group of groups) {
|
|
user_groups.add(group);
|
|
}
|
|
|
|
const denmark = {
|
|
stream_id: 1,
|
|
name: "Denmark",
|
|
subscribed: true,
|
|
render_subscribers: true,
|
|
};
|
|
peer_data.set_subscribers(denmark.stream_id, [me.user_id, mark.user_id]);
|
|
|
|
const sweden = {
|
|
stream_id: 2,
|
|
name: "Sweden",
|
|
subscribed: false,
|
|
};
|
|
peer_data.set_subscribers(sweden.stream_id, [mark.user_id, jill.user_id]);
|
|
|
|
const subs = [denmark, sweden];
|
|
for (const sub of subs) {
|
|
stream_data.add_sub(sub);
|
|
}
|
|
|
|
function test_ui(label, f) {
|
|
run_test(label, ({override, mock_template}) => {
|
|
page_params.user_id = me.user_id;
|
|
stream_subscribers_ui.initialize();
|
|
stream_edit.initialize();
|
|
f({override, mock_template});
|
|
});
|
|
}
|
|
|
|
test_ui("subscriber_pills", ({override, mock_template}) => {
|
|
mock_template("input_pill.hbs", true, (data, html) => {
|
|
assert.equal(typeof data.display_value, "string");
|
|
return html;
|
|
});
|
|
mock_template("stream_settings/stream_settings.hbs", false, () => "stream_settings");
|
|
mock_template(
|
|
"stream_settings/stream_subscription_request_result.hbs",
|
|
false,
|
|
() => "stream_subscription_request_result",
|
|
);
|
|
|
|
override(people, "sort_but_pin_current_user_on_top", noop);
|
|
|
|
const subscriptions_table_selector = "#subscriptions_table";
|
|
const input_field_stub = $.create(".input");
|
|
|
|
input_field_stub.before = () => {};
|
|
|
|
const sub_settings_selector = `#subscription_overlay .subscription_settings[data-stream-id='${CSS.escape(
|
|
denmark.stream_id,
|
|
)}']`;
|
|
|
|
const pill_container_stub = $.create("pill-container-stub");
|
|
pill_container_stub.find = () => input_field_stub;
|
|
|
|
const $sub_settings_container = $.create(sub_settings_selector);
|
|
|
|
$sub_settings_container.find = (selector) => {
|
|
switch (selector) {
|
|
case ".colorpicker": {
|
|
return undefined;
|
|
}
|
|
case ".pill-container": {
|
|
return pill_container_stub;
|
|
}
|
|
case ".subscriber_table": {
|
|
return $.create("subscriber-table-stub");
|
|
}
|
|
case ".subscriber_list_container": {
|
|
return undefined;
|
|
}
|
|
// No default
|
|
}
|
|
throw new Error(`unexpected selector ${selector}`);
|
|
};
|
|
|
|
const $subscription_settings = $.create(".subscription_settings");
|
|
$subscription_settings.addClass = noop;
|
|
$subscription_settings.closest = () => $subscription_settings;
|
|
$subscription_settings.attr("data-stream-id", denmark.stream_id);
|
|
$subscription_settings.length = 0;
|
|
|
|
const $add_subscribers_form = $.create(".subscriber_list_add form");
|
|
$add_subscribers_form.closest = () => $subscription_settings;
|
|
|
|
let template_rendered = false;
|
|
ui.get_content_element = () => {
|
|
template_rendered = true;
|
|
return {html: noop};
|
|
};
|
|
|
|
let expected_user_ids = [];
|
|
let input_typeahead_called = false;
|
|
let add_subscribers_request = false;
|
|
override(stream_subscribers_ui, "invite_user_to_stream", (user_ids, sub) => {
|
|
assert.equal(sub.stream_id, denmark.stream_id);
|
|
assert.deepEqual(user_ids.sort(), expected_user_ids.sort());
|
|
add_subscribers_request = true;
|
|
});
|
|
|
|
input_field_stub.typeahead = (config) => {
|
|
assert.equal(config.items, 5);
|
|
assert.ok(config.fixed);
|
|
assert.ok(config.dropup);
|
|
assert.ok(config.stopAdvance);
|
|
|
|
assert.equal(typeof config.source, "function");
|
|
assert.equal(typeof config.highlighter, "function");
|
|
assert.equal(typeof config.matcher, "function");
|
|
assert.equal(typeof config.sorter, "function");
|
|
assert.equal(typeof config.updater, "function");
|
|
|
|
const fake_stream_this = {
|
|
query: "#Denmark",
|
|
};
|
|
const fake_person_this = {
|
|
query: "me",
|
|
};
|
|
const fake_group_this = {
|
|
query: "test",
|
|
};
|
|
|
|
(function test_highlighter() {
|
|
const fake_html = $.create("fake-html");
|
|
typeahead_helper.render_stream = function () {
|
|
return fake_html;
|
|
};
|
|
assert.equal(config.highlighter.call(fake_stream_this, denmark), fake_html);
|
|
|
|
typeahead_helper.render_user_group = function () {
|
|
return fake_html;
|
|
};
|
|
|
|
typeahead_helper.render_person = function () {
|
|
return fake_html;
|
|
};
|
|
|
|
assert.equal(config.highlighter.call(fake_group_this, testers), fake_html);
|
|
assert.equal(config.highlighter.call(fake_person_this, me), fake_html);
|
|
})();
|
|
|
|
(function test_matcher() {
|
|
let result = config.matcher.call(fake_stream_this, denmark);
|
|
assert.ok(result);
|
|
result = config.matcher.call(fake_stream_this, sweden);
|
|
assert.ok(!result);
|
|
|
|
result = config.matcher.call(fake_group_this, testers);
|
|
assert.ok(result);
|
|
result = config.matcher.call(fake_group_this, admins);
|
|
assert.ok(!result);
|
|
|
|
result = config.matcher.call(fake_person_this, me);
|
|
assert.ok(result);
|
|
result = config.matcher.call(fake_person_this, jill);
|
|
assert.ok(!result);
|
|
})();
|
|
|
|
(function test_sorter() {
|
|
let sort_streams_called = false;
|
|
typeahead_helper.sort_streams = () => {
|
|
sort_streams_called = true;
|
|
};
|
|
config.sorter.call(fake_stream_this);
|
|
assert.ok(sort_streams_called);
|
|
|
|
let sort_recipients_called = false;
|
|
typeahead_helper.sort_recipients = function () {
|
|
sort_recipients_called = true;
|
|
};
|
|
config.sorter.call(fake_group_this, [testers]);
|
|
assert.ok(sort_recipients_called);
|
|
|
|
sort_recipients_called = false;
|
|
config.sorter.call(fake_person_this, [me]);
|
|
assert.ok(sort_recipients_called);
|
|
})();
|
|
|
|
(function test_updater() {
|
|
function number_of_pills() {
|
|
const pills = stream_subscribers_ui.pill_widget.items();
|
|
return pills.length;
|
|
}
|
|
|
|
assert.equal(number_of_pills(), 0);
|
|
config.updater.call(fake_stream_this, denmark);
|
|
assert.equal(number_of_pills(), 1);
|
|
config.updater.call(fake_person_this, me);
|
|
assert.equal(number_of_pills(), 2);
|
|
config.updater.call(fake_group_this, testers);
|
|
assert.equal(number_of_pills(), 3);
|
|
})();
|
|
|
|
(function test_source() {
|
|
let result = config.source.call(fake_stream_this);
|
|
const stream_ids = result.map((stream) => stream.stream_id);
|
|
const expected_stream_ids = [sweden.stream_id];
|
|
assert.deepEqual(stream_ids, expected_stream_ids);
|
|
|
|
result = config.source.call(fake_group_this);
|
|
const group_ids = result.map((group) => group.id).filter(Boolean);
|
|
const expected_group_ids = [admins.id];
|
|
assert.deepEqual(group_ids, expected_group_ids);
|
|
|
|
result = config.source.call(fake_person_this);
|
|
const user_ids = result.map((user) => user.user_id).filter(Boolean);
|
|
const expected_user_ids = [jill.user_id, fred.user_id];
|
|
assert.deepEqual(user_ids, expected_user_ids);
|
|
})();
|
|
|
|
input_typeahead_called = true;
|
|
};
|
|
|
|
// Initialize pill widget upon displaying subscription settings page.
|
|
const stream_row_handler = $(subscriptions_table_selector).get_on_handler(
|
|
"click",
|
|
".stream-row",
|
|
);
|
|
|
|
let fake_this = $subscription_settings;
|
|
let event = {target: fake_this};
|
|
|
|
override(stream_ui_updates, "update_toggler_for_sub", noop);
|
|
override(stream_ui_updates, "update_add_subscriptions_elements", noop);
|
|
|
|
const {stream_notification_settings, pm_mention_notification_settings} = settings_config;
|
|
for (const setting of [...stream_notification_settings, ...pm_mention_notification_settings]) {
|
|
user_settings[setting] = true;
|
|
}
|
|
|
|
stream_row_handler.call(fake_this, event);
|
|
assert.ok(template_rendered);
|
|
assert.ok(input_typeahead_called);
|
|
|
|
let add_subscribers_handler = $(subscriptions_table_selector).get_on_handler(
|
|
"submit",
|
|
".subscriber_list_add form",
|
|
);
|
|
|
|
fake_this = $add_subscribers_form;
|
|
fake_this.closest = () => $subscription_settings;
|
|
event = {
|
|
target: fake_this,
|
|
preventDefault: () => {},
|
|
};
|
|
|
|
// We cannot subscribe ourselves (`me`) as
|
|
// we are already subscribed to denmark stream.
|
|
const potential_denmark_stream_subscribers = Array.from(
|
|
peer_data.get_subscribers(denmark.stream_id),
|
|
).filter((id) => id !== me.user_id);
|
|
|
|
// `denmark` stream pill, `me` user pill and
|
|
// `testers` user group pill are stubbed.
|
|
// Thus request is sent to add all the users.
|
|
expected_user_ids = [mark.user_id, fred.user_id];
|
|
add_subscribers_handler(event);
|
|
|
|
add_subscribers_handler = $(subscriptions_table_selector).get_on_handler(
|
|
"keyup",
|
|
".subscriber_list_add form",
|
|
);
|
|
event.key = "Enter";
|
|
|
|
// Only Denmark stream pill is created and a
|
|
// request is sent to add all it's subscribers.
|
|
override(user_pill, "get_user_ids", () => []);
|
|
override(user_group_pill, "get_user_ids", () => []);
|
|
expected_user_ids = potential_denmark_stream_subscribers;
|
|
add_subscribers_handler(event);
|
|
|
|
// No request is sent when there are no users to subscribe.
|
|
stream_pill.get_user_ids = () => [];
|
|
add_subscribers_request = false;
|
|
add_subscribers_handler(event);
|
|
assert.ok(!add_subscribers_request);
|
|
|
|
// No request is sent if we try to subscribe ourselves
|
|
// only and are already subscribed to the stream.
|
|
override(user_pill, "get_user_ids", () => [me.user_id]);
|
|
add_subscribers_handler(event);
|
|
assert.ok(!add_subscribers_request);
|
|
|
|
// Denmark stream pill and fred and mark user pills are created.
|
|
// But only one request for mark is sent even though a mark user
|
|
// pill is created and mark is also a subscriber of Denmark stream.
|
|
override(user_pill, "get_user_ids", () => [mark.user_id, fred.user_id]);
|
|
stream_pill.get_user_ids = () => peer_data.get_subscribers(denmark.stream_id);
|
|
expected_user_ids = potential_denmark_stream_subscribers.concat(fred.user_id);
|
|
add_subscribers_handler(event);
|
|
|
|
function is_person_active(user_id) {
|
|
return user_id === mark.user_id;
|
|
}
|
|
// Deactivated user_id is not included in request.
|
|
override(user_pill, "get_user_ids", () => [mark.user_id, fred.user_id]);
|
|
override(people, "is_person_active", is_person_active);
|
|
expected_user_ids = [mark.user_id];
|
|
add_subscribers_handler(event);
|
|
});
|