diff --git a/tools/test-js-with-node b/tools/test-js-with-node
index 1a4f5b22a4..d0af69e20e 100755
--- a/tools/test-js-with-node
+++ b/tools/test-js-with-node
@@ -215,7 +215,6 @@ EXEMPT_FILES = make_set(
"web/src/settings_streams.js",
"web/src/settings_toggle.js",
"web/src/settings_ui.ts",
- "web/src/settings_user_groups_legacy.js",
"web/src/settings_user_topics.js",
"web/src/settings_users.js",
"web/src/setup.ts",
@@ -269,6 +268,7 @@ EXEMPT_FILES = make_set(
"web/src/user_group_popover.js",
"web/src/user_group_ui_updates.js",
"web/src/user_groups.ts",
+ "web/src/user_pill.ts",
"web/src/user_profile.js",
"web/src/user_settings.ts",
"web/src/user_sort.ts",
diff --git a/web/src/admin.js b/web/src/admin.js
index b3b7e911ca..8cdda5dbdf 100644
--- a/web/src/admin.js
+++ b/web/src/admin.js
@@ -77,7 +77,6 @@ function insert_tip_box() {
$(".organization-box")
.find(".settings-section")
.not("#emoji-settings")
- .not("#user-groups-admin")
.not("#organization-auth-settings")
.not("#admin-bot-list")
.not("#admin-invites-list")
@@ -116,7 +115,6 @@ export function build_page() {
realm_inline_url_embed_preview: page_params.realm_inline_url_embed_preview,
server_inline_url_embed_preview: page_params.server_inline_url_embed_preview,
realm_authentication_methods: page_params.realm_authentication_methods,
- realm_user_group_edit_policy: page_params.realm_user_group_edit_policy,
realm_name_changes_disabled: page_params.realm_name_changes_disabled,
realm_email_changes_disabled: page_params.realm_email_changes_disabled,
realm_avatar_changes_disabled: page_params.realm_avatar_changes_disabled,
@@ -174,7 +172,6 @@ export function build_page() {
can_create_multiuse_invite: settings_data.user_can_create_multiuse_invite(),
can_invite_users_by_email: settings_data.user_can_invite_users_by_email(),
realm_invite_required: page_params.realm_invite_required,
- can_edit_user_groups: settings_data.user_can_edit_user_groups(),
policy_values: settings_config.common_policy_values,
realm_delete_own_message_policy: page_params.realm_delete_own_message_policy,
DELETE_OWN_MESSAGE_POLICY_ADMINS_ONLY:
diff --git a/web/src/server_events_dispatch.js b/web/src/server_events_dispatch.js
index e3e51b88ab..f466ff3ea6 100644
--- a/web/src/server_events_dispatch.js
+++ b/web/src/server_events_dispatch.js
@@ -62,7 +62,6 @@ import * as settings_profile_fields from "./settings_profile_fields";
import * as settings_realm_domains from "./settings_realm_domains";
import * as settings_realm_user_settings_defaults from "./settings_realm_user_settings_defaults";
import * as settings_streams from "./settings_streams";
-import * as settings_user_groups_legacy from "./settings_user_groups_legacy";
import * as settings_users from "./settings_users";
import * as sidebar_ui from "./sidebar_ui";
import * as starred_messages from "./starred_messages";
@@ -882,7 +881,6 @@ export function dispatch_normal_event(event) {
blueslip.error("Unexpected event type user_group/" + event.op);
break;
}
- settings_user_groups_legacy.reload();
break;
case "user_status":
diff --git a/web/src/settings_sections.js b/web/src/settings_sections.js
index 1fbc6aef3d..e82a0c45cc 100644
--- a/web/src/settings_sections.js
+++ b/web/src/settings_sections.js
@@ -15,7 +15,6 @@ import * as settings_playgrounds from "./settings_playgrounds";
import * as settings_profile_fields from "./settings_profile_fields";
import * as settings_realm_user_settings_defaults from "./settings_realm_user_settings_defaults";
import * as settings_streams from "./settings_streams";
-import * as settings_user_groups_legacy from "./settings_user_groups_legacy";
import * as settings_user_topics from "./settings_user_topics";
import * as settings_users from "./settings_users";
@@ -72,7 +71,6 @@ export function initialize() {
load_func_dict.set("linkifier-settings", settings_linkifiers.set_up);
load_func_dict.set("playground-settings", settings_playgrounds.set_up);
load_func_dict.set("invites-list-admin", settings_invites.set_up);
- load_func_dict.set("user-groups-admin", settings_user_groups_legacy.set_up);
load_func_dict.set("profile-field-settings", settings_profile_fields.set_up);
load_func_dict.set("data-exports-admin", settings_exports.set_up);
load_func_dict.set(
@@ -112,7 +110,6 @@ export function reset_sections() {
settings_org.reset();
settings_profile_fields.reset();
settings_streams.reset();
- settings_user_groups_legacy.reset();
settings_user_topics.reset();
settings_muted_users.reset();
alert_words_ui.reset();
diff --git a/web/src/settings_user_groups_legacy.js b/web/src/settings_user_groups_legacy.js
deleted file mode 100644
index 925316ce7a..0000000000
--- a/web/src/settings_user_groups_legacy.js
+++ /dev/null
@@ -1,407 +0,0 @@
-import $ from "jquery";
-import _ from "lodash";
-
-import render_confirm_delete_user from "../templates/confirm_dialog/confirm_delete_user.hbs";
-import render_add_user_group_modal from "../templates/settings/add_user_group_modal.hbs";
-import render_admin_user_group_list from "../templates/settings/admin_user_group_list.hbs";
-
-import * as channel from "./channel";
-import * as confirm_dialog from "./confirm_dialog";
-import * as dialog_widget from "./dialog_widget";
-import {$t, $t_html} from "./i18n";
-import * as keydown_util from "./keydown_util";
-import {page_params} from "./page_params";
-import * as people from "./people";
-import * as pill_typeahead from "./pill_typeahead";
-import * as settings_data from "./settings_data";
-import * as ui_report from "./ui_report";
-import * as user_groups from "./user_groups";
-import * as user_pill from "./user_pill";
-
-const meta = {
- loaded: false,
-};
-
-export function reset() {
- meta.loaded = false;
-}
-
-export function reload() {
- if (!meta.loaded) {
- return;
- }
-
- const $user_groups_section = $("#user-groups").expectOne();
- $user_groups_section.empty();
- populate_user_groups();
-}
-
-export function can_edit(group_id) {
- if (!settings_data.user_can_edit_user_groups()) {
- return false;
- }
-
- // Admins and moderators are allowed to edit user groups even if they
- // are not a member of that user group. Members can edit user groups
- // only if they belong to that group.
- if (page_params.is_admin || page_params.is_moderator) {
- return true;
- }
-
- return user_groups.is_direct_member_of(people.my_current_user_id(), group_id);
-}
-
-export function populate_user_groups() {
- const $user_groups_section = $("#user-groups").expectOne();
- const user_groups_array = user_groups.get_realm_user_groups();
-
- for (const data of user_groups_array) {
- $user_groups_section.append(
- render_admin_user_group_list({
- user_group: {
- name: data.name,
- id: data.id,
- description: data.description,
- },
- }),
- );
-
- const pill_config = {
- show_user_status_emoji: false,
- };
-
- const $pill_container = $(`.pill-container[data-group-pills="${CSS.escape(data.id)}"]`);
- const pills = user_pill.create_pills($pill_container, pill_config);
-
- function get_pill_user_ids() {
- return user_pill.get_user_ids(pills);
- }
-
- const $userg = $(`div.user-group[id="${CSS.escape(data.id)}"]`);
- for (const user_id of data.members) {
- const user = people.get_by_user_id(user_id);
- user_pill.append_user(user, pills);
- }
-
- function update_membership(group_id) {
- if (can_edit(group_id)) {
- return;
- }
- $userg.find(".name").attr("contenteditable", "false");
- $userg.find(".description").attr("contenteditable", "false");
- $userg.addClass("ntm");
- $pill_container.find(".input").attr("contenteditable", "false");
- $pill_container.find(".input").css("display", "none");
- $pill_container.addClass("not-editable");
- $pill_container.off("keydown", ".pill");
- $pill_container.off("keydown", ".input");
- $pill_container.off("click");
- $pill_container.on("click", (e) => {
- e.stopPropagation();
- });
- $pill_container.find(".pill").on("mouseenter", () => {
- $pill_container.find(".pill").find(".exit").css("opacity", "0.5");
- });
- }
- update_membership(data.id);
-
- function is_user_group_changed() {
- const draft_group = get_pill_user_ids();
- const group_data = user_groups.get_user_group_from_id(data.id);
- const original_group = [...group_data.members];
- const same_groups = _.isEqual(_.sortBy(draft_group), _.sortBy(original_group));
- const description = $(`#user-groups #${CSS.escape(data.id)} .description`)
- .text()
- .trim();
- const name = $(`#user-groups #${CSS.escape(data.id)} .name`)
- .text()
- .trim();
- const $user_group_status = $(`#user-groups #${CSS.escape(data.id)} .user-group-status`);
-
- if ($user_group_status.is(":visible")) {
- return false;
- }
-
- if (
- group_data.description === description &&
- group_data.name === name &&
- (!draft_group.length || same_groups)
- ) {
- return false;
- }
- return true;
- }
-
- function update_cancel_button() {
- if (!can_edit(data.id)) {
- return;
- }
- const $cancel_button = $(
- `#user-groups #${CSS.escape(data.id)} .save-status.btn-danger`,
- );
- const $saved_button = $(`#user-groups #${CSS.escape(data.id)} .save-status.sea-green`);
- const $save_instructions = $(`#user-groups #${CSS.escape(data.id)} .save-instructions`);
-
- if (is_user_group_changed() && !$cancel_button.is(":visible")) {
- $saved_button.fadeOut(0);
- $cancel_button.css({display: "inline-block", opacity: "0"}).fadeTo(400, 1);
- $save_instructions.css({display: "block", opacity: "0"}).fadeTo(400, 1);
- } else if (!is_user_group_changed() && $cancel_button.is(":visible")) {
- $cancel_button.fadeOut();
- $save_instructions.fadeOut();
- }
- }
-
- function show_saved_button() {
- const $cancel_button = $(
- `#user-groups #${CSS.escape(data.id)} .save-status.btn-danger`,
- );
- const $saved_button = $(`#user-groups #${CSS.escape(data.id)} .save-status.sea-green`);
- const $save_instructions = $(`#user-groups #${CSS.escape(data.id)} .save-instructions`);
- if (!$saved_button.is(":visible")) {
- $cancel_button.fadeOut(0);
- $save_instructions.fadeOut(0);
- $saved_button
- .css({display: "inline-block", opacity: "0"})
- .fadeTo(400, 1)
- .delay(2000)
- .fadeTo(400, 0);
- }
- }
-
- function save_members() {
- const draft_group = get_pill_user_ids();
- const group_data = user_groups.get_user_group_from_id(data.id);
- const original_group = [...group_data.members];
- const same_groups = _.isEqual(_.sortBy(draft_group), _.sortBy(original_group));
- if (!draft_group.length || same_groups) {
- return;
- }
- const added = _.difference(draft_group, original_group);
- const removed = _.difference(original_group, draft_group);
- channel.post({
- url: "/json/user_groups/" + data.id + "/members",
- data: {
- add: JSON.stringify(added),
- delete: JSON.stringify(removed),
- },
- success() {
- setTimeout(show_saved_button, 200);
- },
- });
- }
-
- function save_name_desc() {
- const $user_group_status = $(`#user-groups #${CSS.escape(data.id)} .user-group-status`);
- const group_data = user_groups.get_user_group_from_id(data.id);
- const description = $(`#user-groups #${CSS.escape(data.id)} .description`)
- .text()
- .trim();
- const name = $(`#user-groups #${CSS.escape(data.id)} .name`)
- .text()
- .trim();
-
- if (group_data.description === description && group_data.name === name) {
- return;
- }
-
- channel.patch({
- url: "/json/user_groups/" + data.id,
- data: {
- name,
- description,
- },
- success() {
- $user_group_status.hide();
- setTimeout(show_saved_button, 200);
- },
- error(xhr) {
- ui_report.error($t_html({defaultMessage: "Failed"}), xhr, $user_group_status);
- update_cancel_button();
- $(`#user-groups #${CSS.escape(data.id)} .name`).text(group_data.name);
- $(`#user-groups #${CSS.escape(data.id)} .description`).text(
- group_data.description,
- );
- },
- });
- }
-
- function do_not_blur(except_class, event) {
- // Event generated from or inside the typeahead.
- if ($(event.relatedTarget).closest(".typeahead").length) {
- return true;
- }
-
- if ($(event.relatedTarget).closest(`#user-groups #${CSS.escape(data.id)}`).length) {
- return [".pill-container", ".name", ".description", ".input", ".delete"].some(
- (class_name) =>
- class_name !== except_class &&
- $(event.relatedTarget).closest(class_name).length,
- );
- }
- return false;
- }
-
- function auto_save(class_name, event) {
- if (!can_edit(data.id)) {
- return;
- }
-
- if (do_not_blur(class_name, event)) {
- return;
- }
- if (
- $(event.relatedTarget).closest(`#user-groups #${CSS.escape(data.id)}`) &&
- $(event.relatedTarget).closest(".save-status.btn-danger").length
- ) {
- reload();
- return;
- }
- save_name_desc();
- save_members();
- }
-
- $(`#user-groups #${CSS.escape(data.id)}`).on("blur", ".input", (event) => {
- auto_save(".input", event);
- });
-
- $(`#user-groups #${CSS.escape(data.id)}`).on("blur", ".name", (event) => {
- auto_save(".name", event);
- });
- $(`#user-groups #${CSS.escape(data.id)}`).on("input", ".name", () => {
- update_cancel_button();
- });
-
- $(`#user-groups #${CSS.escape(data.id)}`).on("blur", ".description", (event) => {
- auto_save(".description", event);
- });
- $(`#user-groups #${CSS.escape(data.id)}`).on("input", ".description", () => {
- update_cancel_button();
- });
-
- const $input = $pill_container.children(".input");
- if (can_edit(data.id)) {
- const opts = {update_func: update_cancel_button, user: true};
- pill_typeahead.set_up($input, pills, opts);
- }
-
- if (can_edit(data.id)) {
- pills.onPillRemove(() => {
- // onPillRemove is fired before the pill is removed from
- // the DOM.
- update_cancel_button();
- setTimeout(() => {
- $input.trigger("focus");
- }, 100);
- });
- }
- }
-}
-
-export function add_user_group() {
- const $user_group_status = $("#dialog_error");
-
- const group = {
- members: JSON.stringify([people.my_current_user_id()]),
- };
-
- for (const obj of $("#add-user-group-form").serializeArray()) {
- if (obj.value.trim() === "") {
- continue;
- }
- group[obj.name] = obj.value;
- }
-
- channel.post({
- url: "/json/user_groups/create",
- data: group,
- success() {
- $user_group_status.hide();
- ui_report.success($t_html({defaultMessage: "User group added!"}), $user_group_status);
- dialog_widget.close();
- },
- error(xhr) {
- $user_group_status.hide();
- ui_report.error($t_html({defaultMessage: "Failed"}), xhr, $user_group_status);
- },
- });
-}
-
-function show_add_user_group_modal() {
- const html_body = render_add_user_group_modal();
-
- function add_user_group_post_render() {
- const $add_user_group_input_element = $("#user_group_name");
- const $add_user_group_submit_button = $("#add-user-group-modal .dialog_submit_button");
- $add_user_group_submit_button.prop("disabled", true);
-
- $add_user_group_input_element.on("input", () => {
- $add_user_group_submit_button.prop(
- "disabled",
- $add_user_group_input_element.val() === "",
- );
- });
- }
-
- dialog_widget.launch({
- html_heading: $t_html({defaultMessage: "Add new user group"}),
- html_body,
- html_submit_button: $t_html({defaultMessage: "Save"}),
- help_link: "/help/user-groups",
- form_id: "add-user-group-form",
- id: "add-user-group-modal",
- on_click: add_user_group,
- on_shown: () => $("#user_group_name").trigger("focus"),
- post_render: add_user_group_post_render,
- });
-}
-
-export function set_up() {
- meta.loaded = true;
- populate_user_groups();
-
- $("#show-add-user-group-modal").on("click", (e) => {
- e.preventDefault();
- e.stopPropagation();
- show_add_user_group_modal();
- });
-
- $("#user-groups").on("click", ".delete", function () {
- const group_id = Number.parseInt($(this).parents(".user-group").attr("id"), 10);
- if (!can_edit(group_id)) {
- return;
- }
- const user_group = user_groups.get_user_group_from_id(group_id);
- const $btn = $(this);
-
- function delete_user_group() {
- channel.del({
- url: "/json/user_groups/" + group_id,
- data: {
- id: group_id,
- },
- error() {
- $btn.text($t({defaultMessage: "Failed!"}));
- },
- });
- }
-
- const html_body = render_confirm_delete_user({
- group_name: user_group.name,
- });
-
- const user_group_name = user_group.name;
-
- confirm_dialog.launch({
- html_heading: $t_html({defaultMessage: "Delete {user_group_name}?"}, {user_group_name}),
- html_body,
- on_click: delete_user_group,
- });
- });
-
- $("#user-groups").on("keypress", ".user-group h4 > span", (e) => {
- if (keydown_util.is_enter_event(e)) {
- e.preventDefault();
- }
- });
-}
diff --git a/web/styles/dark_theme.css b/web/styles/dark_theme.css
index e1b9ce9180..924ac9371d 100644
--- a/web/styles/dark_theme.css
+++ b/web/styles/dark_theme.css
@@ -651,7 +651,6 @@
.clear_search_button:focus,
.clear_search_button:active,
.clear_search_button:disabled:hover,
- #user-groups .save-instructions,
.close {
color: hsl(236deg 33% 80%);
}
diff --git a/web/styles/settings.css b/web/styles/settings.css
index 44d230ed8a..79f6a6b737 100644
--- a/web/styles/settings.css
+++ b/web/styles/settings.css
@@ -687,19 +687,6 @@ input[type="checkbox"] {
text-align: right;
}
-#show-add-user-group-modal {
- margin-bottom: 10px;
-}
-
-#add-user-group-form {
- margin: 0;
-
- /* This 14px is the border and padding of the input element */
- #user_group_description {
- width: calc(100% - 14px);
- }
-}
-
.add-new-export-box {
margin: 10px 0;
}
@@ -1220,102 +1207,6 @@ $option_title_width: 180px;
margin-right: 5px;
}
-#user-groups {
- .user-group {
- margin-bottom: 20px;
- padding: 10px;
- border-radius: 5px;
-
- & h4 {
- font-weight: normal;
- margin: 0;
- display: flex;
- align-items: center;
- justify-content: left;
- }
-
- & span[contenteditable] {
- display: inline-block;
- word-break: break-all;
-
- &:empty::before {
- opacity: 0.5;
- display: inline-block;
- content: attr(data-placeholder);
- }
- }
-
- & span[contenteditable]:focus,
- span[contenteditable="true"]:hover {
- border-bottom: 1px solid hsl(0deg 0% 80%);
- margin-bottom: -1px;
- outline: none;
- }
-
- .pill-container .input[contenteditable]:empty::after {
- content: attr(data-placeholder);
- opacity: 0.5;
- }
- }
-
- .user-group-status {
- margin-bottom: 10px;
- }
-
- & p {
- line-height: 2;
- margin: 0;
- }
-
- .spacer {
- margin: 0 2px;
- }
-
- .subscribers,
- .user-group h4 > .name {
- font-weight: bold;
- }
-
- .ntm {
- cursor: not-allowed;
-
- & h4 > .button {
- cursor: not-allowed;
- display: none;
-
- &:hover {
- border-color: hsl(4deg 56% 82%);
- }
- }
- }
-
- .save-status {
- background-color: transparent;
- padding: 2px 5px;
- border-radius: 4px;
- margin-left: 10px;
- border-style: solid;
- border-width: 1px;
- display: none;
- opacity: 0;
- }
-
- .checkmark {
- height: 12px;
- }
-
- .delete {
- margin-left: auto;
- }
-
- .save-instructions {
- display: none;
- opacity: 0;
- color: hsl(0deg 0% 20%);
- font-size: 0.9em;
- }
-}
-
/* -- new settings overlay -- */
#settings_page {
height: 95vh;
diff --git a/web/templates/settings/admin_tab.hbs b/web/templates/settings/admin_tab.hbs
index 5548ad101e..6cfed7300b 100644
--- a/web/templates/settings/admin_tab.hbs
+++ b/web/templates/settings/admin_tab.hbs
@@ -29,8 +29,6 @@
{{> invites_list_admin }}
-{{> user_groups_admin }}
-
{{> profile_field_settings_admin }}
{{> data_exports_admin }}
diff --git a/web/templates/settings/admin_user_group_list.hbs b/web/templates/settings/admin_user_group_list.hbs
deleted file mode 100644
index f50389de19..0000000000
--- a/web/templates/settings/admin_user_group_list.hbs
+++ /dev/null
@@ -1,27 +0,0 @@
-{{#with user_group}}
-
-
-
- {{name}}
- —
- {{description}}
-
-
- {{t 'Saved' }}
-
-
-
-
-
-
-
-
-
{{t 'Subscribers' }}
-
-
- {{t "Click outside the input box to save. We'll automatically notify anyone that was added or removed."}}
-
-
-{{/with}}
diff --git a/web/templates/settings/user_groups_admin.hbs b/web/templates/settings/user_groups_admin.hbs
deleted file mode 100644
index 92fe55656f..0000000000
--- a/web/templates/settings/user_groups_admin.hbs
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
- {{#if (eq realm_user_group_edit_policy policy_values.by_members.code) }}
-
{{t 'This organization is configured so that administrators, moderators and group members can modify user groups.' }}
- {{else if (eq realm_user_group_edit_policy policy_values.by_full_members.code) }}
-
{{t 'This organization is configured so that administrators, moderators and full members belonging to the group can modify user groups.' }}
- {{else if (eq realm_user_group_edit_policy policy_values.by_moderators_only.code) }}
-
{{t 'This organization is configured so that administrators and moderators can modify user groups.' }}
- {{else}}
-
{{t 'This organization is configured so that only administrators can modify user groups.' }}
- {{/if}}
-
- {{#unless is_guest}}
-
- {{#tr}}
- User groups allow you to mention multiple users at once. When you mention a user group, everyone in the group is notified as if they were individually mentioned.
- {{#*inline "z-link"}}{{> @partial-block}} {{/inline}}
- {{/tr}}
-
- {{#if can_edit_user_groups}}
-
- {{t 'Add a new user group' }}
-
- {{/if}}
- {{/unless}}
-
-
-
diff --git a/web/templates/settings_overlay.hbs b/web/templates/settings_overlay.hbs
index bcafdf4d6a..f7ef6354e5 100644
--- a/web/templates/settings_overlay.hbs
+++ b/web/templates/settings_overlay.hbs
@@ -86,12 +86,6 @@
{{#unless is_guest}}
-
-
- {{t "User groups" }}
-
- {{/unless}}
- {{#unless is_guest}}
{{t "Users" }}
diff --git a/web/tests/dispatch.test.js b/web/tests/dispatch.test.js
index cc3e04f5c6..9751d7004e 100644
--- a/web/tests/dispatch.test.js
+++ b/web/tests/dispatch.test.js
@@ -63,7 +63,6 @@ const settings_realm_user_settings_defaults = mock_esm(
);
const settings_realm_domains = mock_esm("../src/settings_realm_domains");
const settings_streams = mock_esm("../src/settings_streams");
-const settings_user_groups_legacy = mock_esm("../src/settings_user_groups_legacy");
const settings_users = mock_esm("../src/settings_users");
const sidebar_ui = mock_esm("../src/sidebar_ui");
const stream_data = mock_esm("../src/stream_data");
@@ -171,7 +170,6 @@ run_test("attachments", ({override}) => {
run_test("user groups", ({override}) => {
let event = event_fixtures.user_group__add;
- override(settings_user_groups_legacy, "reload", noop);
{
const stub = make_stub();
const user_group_settings_ui_stub = make_stub();
@@ -1165,7 +1163,7 @@ run_test("realm_export", ({override}) => {
assert.equal(args.exports, event.exports);
});
-run_test("server_event_dispatch_op_errors", ({override}) => {
+run_test("server_event_dispatch_op_errors", () => {
blueslip.expect("error", "Unexpected event type subscription/other");
server_events_dispatch.dispatch_normal_event({type: "subscription", op: "other"});
blueslip.expect("error", "Unexpected event type reaction/other");
@@ -1190,7 +1188,6 @@ run_test("server_event_dispatch_op_errors", ({override}) => {
sender: {user_id: 5},
op: "other",
});
- override(settings_user_groups_legacy, "reload", noop);
blueslip.expect("error", "Unexpected event type user_group/other");
server_events_dispatch.dispatch_normal_event({type: "user_group", op: "other"});
});
diff --git a/web/tests/pill_typeahead.test.js b/web/tests/pill_typeahead.test.js
index b32916160a..03649acf2c 100644
--- a/web/tests/pill_typeahead.test.js
+++ b/web/tests/pill_typeahead.test.js
@@ -124,6 +124,11 @@ run_test("set_up", ({mock_template}) => {
get_text_from_item: noop,
});
+ let update_func_called = false;
+ function update_func() {
+ update_func_called = true;
+ }
+
let opts = {};
$fake_input.typeahead = (config) => {
assert.equal(config.items, 5);
@@ -297,6 +302,8 @@ run_test("set_up", ({mock_template}) => {
assert.equal(number_of_pills(), 2);
config.updater.call(fake_group_this, testers);
assert.equal(number_of_pills(), 3);
+
+ assert.ok(update_func_called);
}
})();
@@ -324,7 +331,7 @@ run_test("set_up", ({mock_template}) => {
{user_group: true, stream: true},
{user_group: true, user: true},
{user: true, stream: true},
- {user_group: true, stream: true, user: true},
+ {user_group: true, stream: true, user: true, update_func},
];
for (const config of all_possible_opts) {
diff --git a/web/tests/settings_user_groups_legacy.test.js b/web/tests/settings_user_groups_legacy.test.js
deleted file mode 100644
index dedcce4bfd..0000000000
--- a/web/tests/settings_user_groups_legacy.test.js
+++ /dev/null
@@ -1,854 +0,0 @@
-"use strict";
-
-const {strict: assert} = require("assert");
-
-const {$t} = require("./lib/i18n");
-const {mock_esm, set_global, zrequire} = require("./lib/namespace");
-const {run_test} = require("./lib/test");
-const blueslip = require("./lib/zblueslip");
-const $ = require("./lib/zjquery");
-const {page_params} = require("./lib/zpage_params");
-
-const noop = () => {};
-
-const pills = {
- pill: {},
-};
-
-let create_item_handler;
-
-const channel = mock_esm("../src/channel");
-const confirm_dialog = mock_esm("../src/confirm_dialog");
-const dialog_widget = mock_esm("../src/dialog_widget");
-const input_pill = mock_esm("../src/input_pill");
-const settings_data = mock_esm("../src/settings_data");
-const typeahead_helper = mock_esm("../src/typeahead_helper");
-const user_groups = mock_esm("../src/user_groups", {
- get_user_group_from_id: noop,
- remove: noop,
- add: noop,
-});
-const ui_report = mock_esm("../src/ui_report");
-
-const people = zrequire("people");
-const settings_user_groups_legacy = zrequire("settings_user_groups_legacy");
-const user_pill = zrequire("user_pill");
-
-function reset_test_setup($pill_container_stub) {
- function input_pill_stub(opts) {
- assert.equal(opts.$container, $pill_container_stub);
- create_item_handler = opts.create_item_from_text;
- assert.ok(create_item_handler);
- return pills;
- }
- input_pill.create = input_pill_stub;
-}
-
-function test_ui(label, f) {
- // The sloppy_$ flag lets us reuse setup from prior tests.
- run_test(label, f, {sloppy_$: true});
-}
-
-test_ui("can_edit", ({override}) => {
- override(settings_data, "user_can_edit_user_groups", () => false);
- assert.ok(!settings_user_groups_legacy.can_edit(1));
-
- override(settings_data, "user_can_edit_user_groups", () => true);
- user_groups.is_direct_member_of = (user_id, group_id) => {
- assert.equal(group_id, 1);
- assert.equal(user_id, undefined);
- return false;
- };
- assert.ok(!settings_user_groups_legacy.can_edit(1));
-
- page_params.is_admin = true;
- assert.ok(settings_user_groups_legacy.can_edit(1));
-
- page_params.is_admin = false;
- page_params.is_moderator = true;
- assert.ok(settings_user_groups_legacy.can_edit(1));
-
- page_params.is_admin = false;
- page_params.is_moderator = false;
- user_groups.is_direct_member_of = (user_id, group_id) => {
- assert.equal(group_id, 1);
- assert.equal(user_id, undefined);
- return true;
- };
- assert.ok(settings_user_groups_legacy.can_edit(1));
-});
-
-const user_group_selector = `#user-groups #${CSS.escape(1)}`;
-const cancel_selector = `#user-groups #${CSS.escape(1)} .save-status.btn-danger`;
-const saved_selector = `#user-groups #${CSS.escape(1)} .save-status.sea-green`;
-const name_selector = `#user-groups #${CSS.escape(1)} .name`;
-const description_selector = `#user-groups #${CSS.escape(1)} .description`;
-const instructions_selector = `#user-groups #${CSS.escape(1)} .save-instructions`;
-
-test_ui("populate_user_groups", ({mock_template, override, override_rewire}) => {
- override(settings_data, "user_can_edit_user_groups", () => true);
-
- const realm_user_group = {
- id: 1,
- name: "Mobile",
- description: "All mobile people",
- members: new Set([2, 4]),
- };
- const iago = {
- email: "iago@zulip.com",
- user_id: 2,
- full_name: "Iago",
- };
- const alice = {
- email: "alice@example.com",
- user_id: 31,
- full_name: "Alice",
- };
- const bob = {
- email: "bob@example.com",
- user_id: 32,
- full_name: "Bob",
- };
-
- people.add_active_user(iago);
- people.add_active_user(alice);
- people.add_active_user(bob);
-
- override_rewire(people, "get_realm_users", () => [iago, alice, bob]);
-
- user_groups.get_realm_user_groups = () => [realm_user_group];
-
- let templates_render_called = false;
- const $fake_rendered_temp = $.create("fake_admin_user_group_list_template_rendered");
- mock_template("settings/admin_user_group_list.hbs", false, (args) => {
- assert.equal(args.user_group.id, 1);
- assert.equal(args.user_group.name, "Mobile");
- assert.equal(args.user_group.description, "All mobile people");
- templates_render_called = true;
- return $fake_rendered_temp;
- });
-
- let user_groups_list_append_called = false;
- $("#user-groups").append = (rendered_temp) => {
- assert.equal(rendered_temp, $fake_rendered_temp);
- user_groups_list_append_called = true;
- };
-
- let get_by_user_id_called = false;
- override_rewire(people, "get_by_user_id", (user_id) => {
- if (user_id === iago.user_id) {
- return iago;
- }
- assert.equal(user_id, 4);
- blueslip.expect("warn", "Undefined user in function append_user");
- get_by_user_id_called = true;
- return undefined;
- });
- override_rewire(
- people,
- "is_known_user",
- () => people.get_by_user_id !== undefined && people.get_by_user_id !== noop,
- );
-
- page_params.is_admin = true;
-
- const all_pills = new Map();
-
- const $pill_container_stub = $(`.pill-container[data-group-pills="${CSS.escape(1)}"]`);
- pills.appendValidatedData = (item) => {
- const id = item.user_id;
- assert.ok(!all_pills.has(id));
- all_pills.set(id, item);
- };
- pills.items = () => [...all_pills.values()];
-
- let text_cleared;
- pills.clear_text = () => {
- text_cleared = true;
- };
-
- const $input_field_stub = $.create("fake-input-field");
- $pill_container_stub.children = () => $input_field_stub;
-
- let input_typeahead_called = false;
- $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");
-
- (function test_highlighter() {
- const $fake_person = $.create("fake-person");
- typeahead_helper.render_person = () => $fake_person;
- assert.equal(config.highlighter(), $fake_person);
- })();
-
- const fake_context = {
- query: "ali",
- };
-
- const fake_context_for_email = {
- query: "am",
- };
-
- (function test_source() {
- const result = config.source.call(fake_context, iago);
- const emails = result.map((user) => user.email).sort();
- assert.deepEqual(emails, [alice.email, bob.email]);
- })();
-
- (function test_matcher() {
- /* Here the query doesn't begin with an '@' because typeahead is triggered
- by the '@' sign and thus removed in the query. */
- let result = config.matcher.call(fake_context, iago);
- assert.ok(!result);
-
- result = config.matcher.call(fake_context, alice);
- assert.ok(result);
-
- bob.delivery_email = null;
- result = config.matcher.call(fake_context_for_email, bob);
- assert.ok(!result);
-
- bob.delivery_email = "bob-delivery@example.com";
- result = config.matcher.call(fake_context_for_email, bob);
- assert.ok(result);
- })();
-
- (function test_sorter() {
- let sort_recipients_typeahead_called = false;
- typeahead_helper.sort_recipients = function () {
- sort_recipients_typeahead_called = true;
- };
- config.sorter.call(fake_context, []);
- assert.ok(sort_recipients_typeahead_called);
- })();
-
- (function test_updater() {
- $input_field_stub.text("@ali");
- user_groups.get_user_group_from_id = () => realm_user_group;
-
- let saved_fade_out_called = false;
- let cancel_fade_to_called = false;
- let instructions_fade_to_called = false;
- $(saved_selector).fadeOut = () => {
- saved_fade_out_called = true;
- };
- $(cancel_selector).css = (data) => {
- assert.equal(typeof data, "object");
- assert.equal(data.display, "inline-block");
- assert.equal(data.opacity, "0");
- return $(cancel_selector);
- };
- $(cancel_selector).fadeTo = () => {
- cancel_fade_to_called = true;
- };
- $(instructions_selector).css = (data) => {
- assert.equal(typeof data, "object");
- assert.equal(data.display, "block");
- assert.equal(data.opacity, "0");
- return $(instructions_selector);
- };
- $(instructions_selector).fadeTo = () => {
- instructions_fade_to_called = true;
- };
-
- text_cleared = false;
- config.updater(alice);
- // update_cancel_button is called.
- assert.ok(saved_fade_out_called);
- assert.ok(cancel_fade_to_called);
- assert.ok(instructions_fade_to_called);
- assert.equal(text_cleared, true);
- })();
- input_typeahead_called = true;
- };
-
- let get_by_email_called = false;
- override_rewire(people, "get_by_email", (user_email) => {
- get_by_email_called = true;
- switch (user_email) {
- case iago.email:
- return iago;
- case bob.email:
- return bob;
- /* istanbul ignore next */
- default:
- throw new Error("Expected user email to be of Iago or Bob here.");
- }
- });
-
- function test_create_item(handler) {
- (function test_rejection_path() {
- const item = handler(iago.email, pills.items());
- assert.ok(get_by_email_called);
- assert.equal(item, undefined);
- })();
-
- (function test_success_path() {
- get_by_email_called = false;
- const res = handler(bob.email, pills.items());
- assert.ok(get_by_email_called);
- assert.equal(typeof res, "object");
- assert.equal(res.user_id, bob.user_id);
- assert.equal(res.display_value, bob.full_name);
- })();
-
- (function test_deactivated_pill() {
- people.deactivate(bob);
- get_by_email_called = false;
- const res = handler(bob.email, pills.items());
- assert.ok(get_by_email_called);
- assert.equal(typeof res, "object");
- assert.equal(res.user_id, bob.user_id);
- assert.equal(res.display_value, bob.full_name);
- assert.ok(res.deactivated);
- people.add_active_user(bob);
- })();
- }
-
- pills.onPillRemove = (handler) => {
- set_global("setTimeout", (func) => {
- func();
- });
- realm_user_group.members = new Set([2, 31]);
- handler();
- };
-
- reset_test_setup($pill_container_stub);
- settings_user_groups_legacy.set_up();
- assert.ok(templates_render_called);
- assert.ok(user_groups_list_append_called);
- assert.ok(get_by_user_id_called);
- assert.ok(input_typeahead_called);
- test_create_item(create_item_handler);
-
- // Tests for settings_user_groups_legacy.set_up workflow.
- assert.equal(typeof $("#user-groups").get_on_handler("click", ".delete"), "function");
- assert.equal(
- typeof $("#user-groups").get_on_handler("keypress", ".user-group h4 > span"),
- "function",
- );
-});
-test_ui("with_external_user", ({disallow_rewire, override_rewire, mock_template}) => {
- const realm_user_group = {
- id: 1,
- name: "Mobile",
- description: "All mobile people",
- members: new Set([2, 4]),
- };
-
- user_groups.get_realm_user_groups = () => [realm_user_group];
-
- // These are already tested, so we skip them
- disallow_rewire(people, "get_realm_users");
-
- mock_template(
- "settings/admin_user_group_list.hbs",
- false,
- () => "settings/admin_user_group_list.hbs",
- );
-
- override_rewire(people, "get_by_user_id", () => "user stub");
-
- override_rewire(user_pill, "append_person", noop);
-
- let can_edit_called = 0;
- override_rewire(settings_user_groups_legacy, "can_edit", () => {
- can_edit_called += 1;
- return false;
- });
-
- // Reset zjquery to test stuff with user who cannot edit
- $.clear_all_elements();
-
- let user_group_find_called = 0;
- const $user_group_stub = $(`div.user-group[id="${CSS.escape(1)}"]`);
- const $name_field_stub = $.create("fake-name-field");
- const $description_field_stub = $.create("fake-description-field");
- const $input_stub = $.create("fake-input");
- $user_group_stub.find = (elem) => {
- user_group_find_called += 1;
- switch (elem) {
- case ".name":
- return $name_field_stub;
- case ".description":
- return $description_field_stub;
- /* istanbul ignore next */
- default:
- throw new Error(`Unknown element ${elem}`);
- }
- };
-
- const $pill_container_stub = $(`.pill-container[data-group-pills="${CSS.escape(1)}"]`);
- const $pill_stub = $.create("fake-pill");
- let pill_container_find_called = 0;
- $pill_container_stub.find = (elem) => {
- pill_container_find_called += 1;
- switch (elem) {
- case ".input":
- return $input_stub;
- case ".pill":
- return $pill_stub;
- /* istanbul ignore next */
- default:
- throw new Error(`Unknown element ${elem}`);
- }
- };
-
- $input_stub.css = (property, val) => {
- assert.equal(property, "display");
- assert.equal(val, "none");
- };
-
- // Test the 'off' handlers on the pill-container
- const turned_off = {};
- $pill_container_stub.off = (event_name, sel = "whole") => {
- turned_off[event_name + "/" + sel] = true;
- };
-
- const $exit_button = $.create("fake-pill-exit");
- $pill_stub.set_find_results(".exit", $exit_button);
- let exit_button_called = false;
- $exit_button.css = (property, value) => {
- exit_button_called = true;
- assert.equal(property, "opacity");
- assert.equal(value, "0.5");
- };
-
- // We return [] because these are already tested, so we skip them
- $pill_container_stub.children = () => [];
-
- $("#user-groups").append = noop;
-
- reset_test_setup($pill_container_stub);
-
- settings_user_groups_legacy.set_up();
-
- let set_parents_result_called = 0;
- let set_attributes_called = 0;
-
- // Test different handlers with an external user
- const delete_handler = $("#user-groups").get_on_handler("click", ".delete");
- const $fake_delete = $.create("fk-#user-groups.delete_btn");
- $fake_delete.set_parents_result(".user-group", $(".user-group"));
- set_parents_result_called += 1;
- $(".user-group").attr("id", "1");
- set_attributes_called += 1;
-
- const name_update_handler = $(user_group_selector).get_on_handler("input", ".name");
-
- const des_update_handler = $(user_group_selector).get_on_handler("input", ".description");
-
- const member_change_handler = $(user_group_selector).get_on_handler("blur", ".input");
-
- const name_change_handler = $(user_group_selector).get_on_handler("blur", ".name");
-
- const des_change_handler = $(user_group_selector).get_on_handler("blur", ".description");
-
- const event = {
- stopPropagation: noop,
- };
- const pill_mouseenter_handler = $pill_stub.get_on_handler("mouseenter");
- const pill_click_handler = $pill_container_stub.get_on_handler("click");
- pill_mouseenter_handler(event);
- pill_click_handler(event);
- assert.equal(delete_handler.call($fake_delete), undefined);
- assert.equal(name_update_handler(), undefined);
- assert.equal(des_update_handler(), undefined);
- assert.equal(member_change_handler(), undefined);
- assert.equal(name_change_handler(), undefined);
- assert.equal(des_change_handler(), undefined);
- assert.equal(set_parents_result_called, 1);
- assert.equal(set_attributes_called, 1);
- assert.equal(can_edit_called, 9);
- assert.ok(exit_button_called);
- assert.equal(user_group_find_called, 2);
- assert.equal(pill_container_find_called, 4);
- assert.equal(turned_off["keydown/.pill"], true);
- assert.equal(turned_off["keydown/.input"], true);
- assert.equal(turned_off["click/whole"], true);
-});
-
-test_ui("reload", ({override_rewire}) => {
- $("#user-groups").html("Some text");
- let populate_user_groups_called = false;
- override_rewire(settings_user_groups_legacy, "populate_user_groups", () => {
- populate_user_groups_called = true;
- });
- settings_user_groups_legacy.reload();
- assert.ok(populate_user_groups_called);
- assert.equal($("#user-groups").html(), "");
-});
-
-test_ui("reset", () => {
- settings_user_groups_legacy.reset();
- const result = settings_user_groups_legacy.reload();
- assert.equal(result, undefined);
-});
-
-test_ui("on_events", ({mock_template, override, override_rewire}) => {
- override(settings_data, "user_can_edit_user_groups", () => true);
- mock_template("confirm_dialog/confirm_delete_user.hbs", false, (data) => {
- assert.deepEqual(data, {
- group_name: "Mobile",
- });
- return "stub";
- });
-
- page_params.is_admin = true;
-
- (function test_admin_user_group_form_submit_triggered() {
- const handler = settings_user_groups_legacy.add_user_group;
- const event = {
- stopPropagation: noop,
- preventDefault: noop,
- };
- const $fake_this = $.create("#add-user-group-form");
- const fake_object_array = [
- {
- name: "fake-name",
- value: "",
- },
- {
- name: "fake-name",
- value: "fake-value",
- },
- ];
- $fake_this.serializeArray = () => fake_object_array;
- channel.post = (opts) => {
- const data = {
- members: "[null]",
- };
- data[fake_object_array[1].name] = fake_object_array[1].value;
- assert.equal(opts.url, "/json/user_groups/create");
- assert.deepEqual(opts.data, data);
-
- (function test_post_success() {
- $("#dialog_error").show();
- $("#add-user-group-form input[type='text']").val("fake-content");
- ui_report.success = (text, ele) => {
- assert.equal(text, "translated HTML: User group added!");
- assert.equal(ele, $("#dialog_error"));
- };
- dialog_widget.close = () => {};
-
- opts.success();
-
- assert.ok(!$("#dialog_error").visible());
- })();
- (function test_post_error() {
- $("#dialog_error").show();
- ui_report.error = (error_msg, error_obj, ele) => {
- assert.equal(error_msg, "translated HTML: Failed");
- assert.deepEqual(error_obj, {responseJson: {msg: "fake-msg"}});
- assert.equal(ele, $("#dialog_error"));
- };
- opts.error({responseJson: {msg: "fake-msg"}});
-
- assert.ok(!$("#dialog_error").visible());
- })();
- };
-
- handler(event);
- })();
-
- (function test_user_groups_delete_click_triggered() {
- const handler = $("#user-groups").get_on_handler("click", ".delete");
- const $fake_this = $.create("fake-#user-groups.delete_btn");
- $fake_this.set_parents_result(".user-group", $(".user-group"));
- $(".user-group").attr("id", "1");
-
- channel.del = (opts) => {
- const data = {
- id: 1,
- };
- assert.equal(opts.url, "/json/user_groups/1");
- assert.deepEqual(opts.data, data);
-
- $fake_this.text($t({defaultMessage: "fake-text"}));
- opts.error();
- assert.equal($fake_this.text(), "translated: Failed!");
- };
-
- confirm_dialog.launch = (conf) => {
- conf.on_click();
- };
-
- handler.call($fake_this);
- })();
-
- (function test_user_groups_keypress_enter_triggered() {
- const handler = $("#user-groups").get_on_handler("keypress", ".user-group h4 > span");
- let default_action_for_enter_stopped = false;
- const event = {
- key: "Enter",
- preventDefault() {
- default_action_for_enter_stopped = true;
- },
- };
- handler(event);
- assert.ok(default_action_for_enter_stopped);
- })();
-
- (function test_do_not_blur() {
- const blur_event_classes = [".name", ".description", ".input"];
- let api_endpoint_called = false;
- /* istanbul ignore next */
- channel.post = () => {
- api_endpoint_called = true;
- };
- channel.patch = noop;
- const $fake_this = $.create("fake-#user-groups_do_not_blur");
- const event = {
- // FIXME: event.relatedTarget should not be a jQuery object
- relatedTarget: $fake_this,
- };
-
- // Any of the blur_exceptions trigger blur event.
- for (const class_name of blur_event_classes) {
- const handler = $(user_group_selector).get_on_handler("blur", class_name);
-
- for (const blur_exception of [
- ".pill-container",
- ".name",
- ".description",
- ".input",
- ".delete",
- ]) {
- if (blur_exception === class_name) {
- continue;
- }
- api_endpoint_called = false;
- $fake_this.closest = (class_name) => {
- if (class_name === blur_exception || class_name === user_group_selector) {
- return [1];
- }
- return [];
- };
- handler.call($fake_this, event);
- assert.ok(!api_endpoint_called);
- }
-
- api_endpoint_called = false;
- $fake_this.closest = (class_name) => {
- assert.equal(class_name, ".typeahead");
- return [1];
- };
- handler.call($fake_this, event);
- assert.ok(!api_endpoint_called);
-
- // Cancel button triggers blur event.
- let settings_user_groups_legacy_reload_called = false;
- override_rewire(settings_user_groups_legacy, "reload", () => {
- settings_user_groups_legacy_reload_called = true;
- });
- api_endpoint_called = false;
- $fake_this.closest = (class_name) => {
- if (
- class_name === ".save-status.btn-danger" ||
- class_name === user_group_selector
- ) {
- return [1];
- }
- return [];
- };
- handler.call($fake_this, event);
- assert.ok(!api_endpoint_called);
- assert.ok(settings_user_groups_legacy_reload_called);
- }
- })();
-
- (function test_update_cancel_button() {
- const handler_name = $(user_group_selector).get_on_handler("input", ".name");
- const handler_desc = $(user_group_selector).get_on_handler("input", ".description");
- const $sib_des = $(description_selector);
- const $sib_name = $(name_selector);
- $sib_name.text($t({defaultMessage: "mobile"}));
- $sib_des.text($t({defaultMessage: "All mobile members"}));
-
- const group_data = {
- name: "translated: mobile",
- description: "translated: All mobile members",
- members: new Set([2, 31]),
- };
- user_groups.get_user_group_from_id = () => group_data;
-
- let cancel_fade_out_called = false;
- let instructions_fade_out_called = false;
- $(cancel_selector).show();
- $(cancel_selector).fadeOut = () => {
- cancel_fade_out_called = true;
- };
- $(instructions_selector).fadeOut = () => {
- instructions_fade_out_called = true;
- };
-
- // Cancel button removed if user group if user group has no changes.
- const $fake_this = $.create("fake-#update_cancel_button");
- handler_name.call($fake_this);
- assert.ok(cancel_fade_out_called);
- assert.ok(instructions_fade_out_called);
-
- // Check if cancel button removed if user group error is showing.
- $(user_group_selector + " .user-group-status").show();
- cancel_fade_out_called = false;
- instructions_fade_out_called = false;
- handler_name.call($fake_this);
- assert.ok(cancel_fade_out_called);
- assert.ok(instructions_fade_out_called);
-
- // Check for handler_desc to achieve 100% coverage.
- cancel_fade_out_called = false;
- instructions_fade_out_called = false;
- handler_desc.call($fake_this);
- assert.ok(cancel_fade_out_called);
- assert.ok(instructions_fade_out_called);
- })();
-
- (function test_user_groups_save_group_changes_triggered() {
- const handler_name = $(user_group_selector).get_on_handler("blur", ".name");
- const handler_desc = $(user_group_selector).get_on_handler("blur", ".description");
- const $sib_des = $(description_selector);
- const $sib_name = $(name_selector);
- $sib_name.text($t({defaultMessage: "mobile"}));
- $sib_des.text($t({defaultMessage: "All mobile members"}));
-
- const group_data = {members: new Set([2, 31])};
- user_groups.get_user_group_from_id = () => group_data;
- let api_endpoint_called = false;
- let cancel_fade_out_called = false;
- let saved_fade_to_called = false;
- let instructions_fade_out_called = false;
- $(instructions_selector).fadeOut = () => {
- instructions_fade_out_called = true;
- };
- $(cancel_selector).fadeOut = () => {
- cancel_fade_out_called = true;
- };
- $(saved_selector).css = (data) => {
- assert.equal(typeof data, "object");
- assert.equal(data.display, "inline-block");
- assert.equal(data.opacity, "0");
- return $(saved_selector);
- };
- $(saved_selector).fadeTo = () => {
- saved_fade_to_called = true;
- return $(saved_selector);
- };
-
- channel.patch = (opts) => {
- assert.equal(opts.url, "/json/user_groups/1");
- assert.equal(opts.data.name, "translated: mobile");
- assert.equal(opts.data.description, "translated: All mobile members");
- api_endpoint_called = true;
- (function test_post_success() {
- set_global("setTimeout", (func) => {
- func();
- });
- opts.success();
- assert.ok(cancel_fade_out_called);
- assert.ok(instructions_fade_out_called);
- assert.ok(saved_fade_to_called);
- })();
- (function test_post_error() {
- const $user_group_error = $(user_group_selector + " .user-group-status");
- $user_group_error.show();
- ui_report.error = (error_msg, error_obj, ele) => {
- assert.equal(error_msg, "translated HTML: Failed");
- assert.deepEqual(error_obj, {responseJson: {msg: "fake-msg"}});
- assert.equal(ele, $user_group_error);
- };
- opts.error({responseJson: {msg: "fake-msg"}});
-
- assert.ok($user_group_error.visible());
- })();
- };
-
- const $fake_this = $.create("fake-#user-groups_blur_name");
- $fake_this.closest = () => [];
- $fake_this.set_parents_result(user_group_selector, $(user_group_selector));
- const event = {
- // FIXME: event.relatedTarget should not be a jQuery object
- relatedTarget: $fake_this,
- };
-
- api_endpoint_called = false;
- handler_name.call($fake_this, event);
- assert.ok(api_endpoint_called);
-
- // Check API endpoint isn't called if name and desc haven't changed.
- group_data.name = "translated: mobile";
- group_data.description = "translated: All mobile members";
- api_endpoint_called = false;
- handler_name.call($fake_this, event);
- assert.ok(!api_endpoint_called);
-
- // Check for handler_desc to achieve 100% coverage.
- api_endpoint_called = false;
- handler_desc.call($fake_this, event);
- assert.ok(!api_endpoint_called);
- })();
-
- (function test_user_groups_save_member_changes_triggered() {
- const handler = $(user_group_selector).get_on_handler("blur", ".input");
- const realm_user_group = {
- id: 1,
- name: "Mobile",
- description: "All mobile people",
- members: new Set([2, 4]),
- };
-
- user_groups.get_user_group_from_id = (id) => {
- assert.equal(id, 1);
- return realm_user_group;
- };
-
- let cancel_fade_out_called = false;
- let saved_fade_to_called = false;
- let instructions_fade_out_called = false;
- $(instructions_selector).fadeOut = () => {
- instructions_fade_out_called = true;
- };
- $(cancel_selector).fadeOut = () => {
- cancel_fade_out_called = true;
- };
- $(saved_selector).css = () => $(saved_selector);
- $(saved_selector).fadeTo = () => {
- saved_fade_to_called = true;
- return $(saved_selector);
- };
-
- let api_endpoint_called = false;
- channel.post = (opts) => {
- assert.equal(opts.url, "/json/user_groups/1/members");
- assert.equal(opts.data.add, "[31]");
- assert.equal(opts.data.delete, "[4]");
- api_endpoint_called = true;
-
- (function test_post_success() {
- opts.success();
- assert.ok(cancel_fade_out_called);
- assert.ok(instructions_fade_out_called);
- assert.ok(saved_fade_to_called);
- })();
- };
-
- const $fake_this = $.create("fake-#user-groups_blur_input");
- $fake_this.set_parents_result(user_group_selector, $(user_group_selector));
- $fake_this.closest = () => [];
- const event = {
- // FIXME: event.relatedTarget should not be a jQuery object
- relatedTarget: $fake_this,
- };
-
- api_endpoint_called = false;
- handler.call($fake_this, event);
- assert.ok(api_endpoint_called);
- })();
-});
diff --git a/web/tests/user_pill.test.js b/web/tests/user_pill.test.js
index 8d6565172e..ab4249d721 100644
--- a/web/tests/user_pill.test.js
+++ b/web/tests/user_pill.test.js
@@ -4,6 +4,7 @@ const {strict: assert} = require("assert");
const {zrequire} = require("./lib/namespace");
const {run_test} = require("./lib/test");
+const blueslip = require("./lib/zblueslip");
const {page_params} = require("./lib/zpage_params");
const people = zrequire("people");
@@ -102,6 +103,9 @@ test("append", () => {
assert.ok(appended);
assert.ok(cleared);
+
+ blueslip.expect("warn", "Undefined user in function append_user");
+ user_pill.append_user(undefined, pill_widget);
});
test("get_items", () => {