diff --git a/frontend_tests/node_tests/pill_typeahead.js b/frontend_tests/node_tests/pill_typeahead.js new file mode 100644 index 0000000000..499a6021d0 --- /dev/null +++ b/frontend_tests/node_tests/pill_typeahead.js @@ -0,0 +1,77 @@ +"use strict"; + +const {strict: assert} = require("assert"); + +const {zrequire} = require("../zjsunit/namespace"); +const {run_test} = require("../zjsunit/test"); +const blueslip = require("../zjsunit/zblueslip"); +const $ = require("../zjsunit/zjquery"); + +const input_pill = zrequire("input_pill"); +const pill_typeahead = zrequire("pill_typeahead"); +const noop = function () {}; + +run_test("set_up", () => { + // Test set_up without any type + let input_pill_typeahead_called = false; + const fake_input = $.create(".input"); + fake_input.typeahead = (config) => { + assert.equal(config.items, 5); + assert(config.fixed); + assert(config.dropup); + assert(config.stopAdvance); + + // Working of functions that are part of config + // is tested separately based on the widgets that + // try to use it. Here we just check if config + // passed to the typeahead is in the right format. + 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"); + + // input_pill_typeahead_called is set true if + // no exception occurs in pill_typeahead.set_up. + input_pill_typeahead_called = true; + }; + + const container = $.create(".pill-container"); + container.find = () => fake_input; + + const pill_widget = input_pill.create({ + container, + create_item_from_text: noop, + get_text_from_item: noop, + }); + + // call set_up with only user type in opts. + pill_typeahead.set_up(fake_input, pill_widget, {user: true}); + assert(input_pill_typeahead_called); + + // call set_up with only stream type in opts. + input_pill_typeahead_called = false; + pill_typeahead.set_up(fake_input, pill_widget, {stream: true}); + assert(input_pill_typeahead_called); + + // call set_up with only user_group type in opts. + input_pill_typeahead_called = false; + pill_typeahead.set_up(fake_input, pill_widget, {user_group: true}); + assert(input_pill_typeahead_called); + + // call set_up with combination two types in opts. + input_pill_typeahead_called = false; + pill_typeahead.set_up(fake_input, pill_widget, {user_group: true, stream: true}); + assert(input_pill_typeahead_called); + + // call set_up with all three types in opts. + input_pill_typeahead_called = false; + pill_typeahead.set_up(fake_input, pill_widget, {user_group: true, stream: true, user: true}); + assert(input_pill_typeahead_called); + + // call set_up without specifying type in opts. + input_pill_typeahead_called = false; + blueslip.expect("error", "Unspecified possible item types"); + pill_typeahead.set_up(fake_input, pill_widget, {}); + assert(!input_pill_typeahead_called); +}); diff --git a/static/js/pill_typeahead.js b/static/js/pill_typeahead.js index f2143412a2..95e4f14f1c 100644 --- a/static/js/pill_typeahead.js +++ b/static/js/pill_typeahead.js @@ -1,3 +1,4 @@ +import * as blueslip from "./blueslip"; import * as composebox_typeahead from "./composebox_typeahead"; import * as people from "./people"; import * as stream_pill from "./stream_pill"; @@ -21,6 +22,10 @@ function group_matcher(query, item) { } export function set_up(input, pills, opts) { + if (!opts.user && !opts.user_group && !opts.stream) { + blueslip.error("Unspecified possible item types"); + return; + } let source = opts.source; if (!opts.source) { source = () => user_pill.typeahead_source(pills); diff --git a/static/js/settings_account.js b/static/js/settings_account.js index 31edc6333b..bc9e324dd1 100644 --- a/static/js/settings_account.js +++ b/static/js/settings_account.js @@ -255,13 +255,13 @@ export function initialize_custom_user_type_fields( if (is_editable) { const input = pill_container.children(".input"); if (set_handler_on_update) { - const opts = {update_func: update_custom_user_field}; + const opts = {update_func: update_custom_user_field, user: true}; pill_typeahead.set_up(input, pills, opts); pills.onPillRemove(() => { update_custom_user_field(); }); } else { - pill_typeahead.set_up(input, pills, {}); + pill_typeahead.set_up(input, pills, {user: true}); } } user_pills.set(field.id, pills); diff --git a/static/js/settings_user_groups.js b/static/js/settings_user_groups.js index 79fb335734..93fd2f197e 100644 --- a/static/js/settings_user_groups.js +++ b/static/js/settings_user_groups.js @@ -275,7 +275,7 @@ export function populate_user_groups() { const input = pill_container.children(".input"); if (can_edit(data.id)) { - const opts = {update_func: update_cancel_button}; + const opts = {update_func: update_cancel_button, user: true}; pill_typeahead.set_up(input, pills, opts); } diff --git a/static/js/stream_edit.js b/static/js/stream_edit.js index ba22ddc7ac..59592a0cc4 100644 --- a/static/js/stream_edit.js +++ b/static/js/stream_edit.js @@ -418,7 +418,12 @@ function show_subscription_settings(sub) { simplebar_container: $(".subscriber_list_container"), }); - const opts = {source: get_users_for_subscriber_typeahead, stream: true, user_group: true}; + const opts = { + source: get_users_for_subscriber_typeahead, + stream: true, + user_group: true, + user: true, + }; pill_typeahead.set_up(sub_settings.find(".input"), pill_widget, opts); }