zulip/frontend_tests/node_tests/search_legacy.js

306 lines
9.0 KiB
JavaScript
Raw Normal View History

"use strict";
const {strict: assert} = require("assert");
const rewiremock = require("rewiremock/node");
const {set_global, zrequire} = require("../zjsunit/namespace");
const {run_test} = require("../zjsunit/test");
const $ = require("../zjsunit/zjquery");
set_global("page_params", {
search_pills_enabled: false,
});
const noop = () => {};
const narrow_state = {__esModule: true};
rewiremock("../../static/js/narrow_state").with(narrow_state);
const search_suggestion = set_global("search_suggestion", {});
set_global("ui_util", {
change_tab_to: noop,
});
const narrow = set_global("narrow", {});
const Filter = {};
rewiremock("../../static/js/filter").with({
Filter,
});
set_global("setTimeout", (func) => func());
rewiremock.enable();
const search = zrequire("search");
zrequire("message_view_header");
run_test("update_button_visibility", () => {
const search_query = $("#search_query");
const search_button = $(".search_button");
search_query.is = () => false;
search_query.val("");
narrow_state.active = () => false;
search_button.prop("disabled", true);
search.update_button_visibility();
assert(search_button.prop("disabled"));
search_query.is = () => true;
search_query.val("");
narrow_state.active = () => false;
search_button.prop("disabled", true);
search.update_button_visibility();
assert(!search_button.prop("disabled"));
search_query.is = () => false;
search_query.val("Test search term");
narrow_state.active = () => false;
search_button.prop("disabled", true);
search.update_button_visibility();
assert(!search_button.prop("disabled"));
search_query.is = () => false;
search_query.val("");
narrow_state.active = () => true;
search_button.prop("disabled", true);
search.update_button_visibility();
assert(!search_button.prop("disabled"));
});
run_test("initialize", () => {
const search_query_box = $("#search_query");
const searchbox_form = $("#searchbox_form");
const search_button = $(".search_button");
search_suggestion.max_num_of_search_results = 999;
search_query_box.typeahead = (opts) => {
assert.equal(opts.fixed, true);
assert.equal(opts.items, 999);
assert.equal(opts.naturalSearch, true);
assert.equal(opts.helpOnEmptyStrings, true);
assert.equal(opts.matcher(), true);
{
const search_suggestions = {
lookup_table: new Map([
[
"stream:Verona",
{
description: "Stream <strong>Ver</strong>ona",
search_string: "stream:Verona",
},
],
[
"ver",
{
description: "Search for ver",
search_string: "ver",
},
],
]),
strings: ["ver", "stream:Verona"],
};
/* Test source */
search suggestions: De-duplicate legacy search codepath. This merges the `exports.get_search_result_legacy` and `exports.get_search_result` function. The key differences between the two code paths are as follows: * We only want to generate suggestions for the queries which the user is typing or can edit. For the legacy version, suggestions are displayed for the entire search string in the searchbox. (`all_operators`) For the pills enabled version, suggestions are displayed only for the input which hasn't been converted to pills. (`query_operators`) `all_operators` = `base_query_operators` + " " + `query_operators`. trim is added at the end just to handle the legacy case where we pass the `base_query` as ''. * It is not possible to detect whether the user wants to continue typing in the legacy version. However if the the searchbox is still focused even after pill creation we can assume the user still wants to continue typing. To handle this we push an empty term as the `last` operator. This is possible since the previous queries have been completely entered as evident from it's generated pill. * When using the legacy version, `search_operators` are the same as `all_operators`, as mentioned in point 1. In the pills enabled version we perform most of the computations from the `query_operators`, but we do require all `all_operators`, only for filtering the last query's suggestion. * And there is just one block unique to the legacy search system. More details are mentioned in the comments of that block. We also refactor both the search suggestions node tests, mainly to make them similar and easier to detect differences when we switch over to the new version.
2020-06-01 15:00:42 +02:00
search_suggestion.get_suggestions = () => search_suggestions;
const expected_source_value = search_suggestions.strings;
const source = opts.source("ver");
assert.equal(source, expected_source_value);
/* Test highlighter */
let expected_value = "Search for ver";
assert.equal(opts.highlighter(source[0]), expected_value);
expected_value = "Stream <strong>Ver</strong>ona";
assert.equal(opts.highlighter(source[1]), expected_value);
/* Test sorter */
assert.equal(opts.sorter(search_suggestions.strings), search_suggestions.strings);
}
{
let operators;
let is_blurred;
search_query_box.on("blur", () => {
is_blurred = true;
});
/* Test updater */
const _setup = (search_box_val) => {
is_blurred = false;
search_query_box.val(search_box_val);
Filter.parse = (search_string) => {
assert.equal(search_string, search_box_val);
return operators;
};
narrow.activate = (raw_operators, options) => {
assert.deepEqual(raw_operators, operators);
assert.deepEqual(options, {trigger: "search"});
};
};
operators = [
{
negated: false,
operator: "search",
operand: "ver",
},
];
_setup("ver");
assert.equal(opts.updater("ver"), "ver");
assert(is_blurred);
operators = [
{
negated: false,
operator: "stream",
operand: "Verona",
},
];
_setup("stream:Verona");
assert.equal(opts.updater("stream:Verona"), "stream:Verona");
assert(is_blurred);
search.is_using_input_method = true;
_setup("stream:Verona");
assert.equal(opts.updater("stream:Verona"), "stream:Verona");
assert(!is_blurred);
search_query_box.off("blur");
}
};
search.initialize();
search_button.prop("disabled", true);
search_query_box.trigger("focus");
assert(!search_button.prop("disabled"));
search_query_box.val("test string");
narrow_state.search_string = () => "ver";
search_query_box.trigger("blur");
assert.equal(search_query_box.val(), "test string");
search.is_using_input_method = false;
searchbox_form.trigger("compositionend");
assert(search.is_using_input_method);
const keydown = searchbox_form.get_on_handler("keydown");
let default_prevented = false;
let ev = {
type: "keydown",
which: 15,
preventDefault() {
default_prevented = true;
},
};
search_query_box.is = () => false;
assert.equal(keydown(ev), undefined);
assert(!default_prevented);
ev.which = 13;
assert.equal(keydown(ev), undefined);
assert(!default_prevented);
ev.which = 13;
search_query_box.is = () => true;
assert.equal(keydown(ev), undefined);
assert(default_prevented);
ev = {
type: "keyup",
};
let operators;
let is_blurred;
narrow_state.active = () => false;
search_query_box.off("blur");
search_query_box.on("blur", () => {
is_blurred = true;
});
const _setup = (search_box_val) => {
is_blurred = false;
search_button.prop("disabled", false);
search_query_box.val(search_box_val);
Filter.parse = (search_string) => {
assert.equal(search_string, search_box_val);
return operators;
};
narrow.activate = (raw_operators, options) => {
assert.deepEqual(raw_operators, operators);
assert.deepEqual(options, {trigger: "search"});
};
};
operators = [
{
negated: false,
operator: "search",
operand: "",
},
];
_setup("");
ev.which = 15;
search_query_box.is = () => false;
searchbox_form.trigger(ev);
assert(!is_blurred);
assert(!search_button.prop("disabled"));
ev.which = 13;
search_query_box.is = () => false;
searchbox_form.trigger(ev);
assert(!is_blurred);
assert(!search_button.prop("disabled"));
ev.which = 13;
search_query_box.is = () => true;
searchbox_form.trigger(ev);
assert(is_blurred);
_setup("ver");
search.is_using_input_method = true;
searchbox_form.trigger(ev);
// No change on Enter keyup event when using input tool
assert(!is_blurred);
assert(!search_button.prop("disabled"));
_setup("ver");
ev.which = 13;
search_query_box.is = () => true;
searchbox_form.trigger(ev);
assert(is_blurred);
assert(!search_button.prop("disabled"));
});
run_test("initiate_search", () => {
// open typeahead and select text when navbar is open
// this implicitly expects the code to used the chained
// function calls, which is something to keep in mind if
// this test ever fails unexpectedly.
narrow_state.filter = () => ({is_search: () => true});
let typeahead_forced_open = false;
let is_searchbox_text_selected = false;
$("#search_query").typeahead = (lookup) => {
if (lookup === "lookup") {
typeahead_forced_open = true;
}
return $("#search_query");
};
$("#search_query").on("select", () => {
is_searchbox_text_selected = true;
});
search.initiate_search();
assert(typeahead_forced_open);
assert(is_searchbox_text_selected);
assert.equal($("#search_query").val(), "ver");
// test that we append space for user convenience
narrow_state.filter = () => ({is_search: () => false});
search.initiate_search();
assert.equal($("#search_query").val(), "ver ");
});
rewiremock.disable();