node_tests: Enforce 100% coverage for test files.

This makes it easier to find obsolete parts of the tests that should
be cleaned up.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2022-04-09 14:44:38 -07:00 committed by Steve Howell
parent 8aed6321bd
commit a682530fd4
59 changed files with 437 additions and 512 deletions

View File

@ -381,36 +381,40 @@ test("first/prev/next", ({override, mock_template}) => {
let rendered_fred;
mock_template("user_presence_row.hbs", false, (data) => {
if (data.user_id === alice.user_id) {
rendered_alice = true;
assert.deepEqual(data, {
faded: true,
href: "#narrow/pm-with/1-alice",
is_current_user: false,
my_user_status: undefined,
name: "Alice Smith",
num_unread: 0,
user_circle_class: "user_circle_green",
user_circle_status: "translated: Active",
user_id: alice.user_id,
status_emoji_info: undefined,
});
} else if (data.user_id === fred.user_id) {
rendered_fred = true;
assert.deepEqual(data, {
href: "#narrow/pm-with/2-fred",
name: "Fred Flintstone",
user_id: fred.user_id,
my_user_status: undefined,
is_current_user: false,
num_unread: 0,
user_circle_class: "user_circle_green",
user_circle_status: "translated: Active",
faded: false,
status_emoji_info: undefined,
});
} else {
throw new Error(`we did not expect to have to render a row for ${data.name}`);
switch (data.user_id) {
case alice.user_id:
rendered_alice = true;
assert.deepEqual(data, {
faded: true,
href: "#narrow/pm-with/1-alice",
is_current_user: false,
my_user_status: undefined,
name: "Alice Smith",
num_unread: 0,
user_circle_class: "user_circle_green",
user_circle_status: "translated: Active",
user_id: alice.user_id,
status_emoji_info: undefined,
});
break;
case fred.user_id:
rendered_fred = true;
assert.deepEqual(data, {
href: "#narrow/pm-with/2-fred",
name: "Fred Flintstone",
user_id: fred.user_id,
my_user_status: undefined,
is_current_user: false,
num_unread: 0,
user_circle_class: "user_circle_green",
user_circle_status: "translated: Active",
faded: false,
status_emoji_info: undefined,
});
break;
/* istanbul ignore next */
default:
throw new Error(`we did not expect to have to render a row for ${data.name}`);
}
});
@ -555,13 +559,8 @@ test("realm_presence_disabled", () => {
test("redraw_muted_user", () => {
muted_users.add_muted_user(mark.user_id);
let appended_html;
$("#user_presences").append = function (html) {
appended_html = html;
};
activity.redraw_user(mark.user_id);
assert.equal(appended_html, undefined);
assert.equal($("#user_presences").html(), "never-been-set");
});
test("update_presence_info", ({override, override_rewire}) => {

View File

@ -136,14 +136,12 @@ run_test("licensechange", ({override, override_rewire}) => {
assert.ok(confirm_license_modal_shown);
override(helpers, "is_valid_input", () => false);
let prevent_default_called = false;
const event = {
prevent_default: () => {
prevent_default_called = true;
preventDefault: /* istanbul ignore next */ () => {
throw new Error("unexpected preventDefault call");
},
};
update_licenses_button_click_handler(event);
assert.ok(!prevent_default_called);
const update_next_renewal_licenses_button_click_handler = $(
"#update-licenses-at-next-renewal-button",

View File

@ -399,19 +399,18 @@ test("while_reloading", () => {
assert.equal(channel.get({ignore_reload: false}), undefined);
let orig_success_called = false;
let orig_error_called = false;
test_with_mock_ajax({
run_code() {
channel.del({
url: "/json/endpoint",
ignore_reload: true,
/* istanbul ignore next */
success() {
orig_success_called = true;
throw new Error("unexpected success");
},
/* istanbul ignore next */
error() {
orig_error_called = true;
throw new Error("unexpected error");
},
});
},
@ -419,11 +418,9 @@ test("while_reloading", () => {
check_ajax_options(options) {
blueslip.expect("log", "Ignoring DELETE /json/endpoint response while reloading");
options.simulate_success();
assert.ok(!orig_success_called);
blueslip.expect("log", "Ignoring DELETE /json/endpoint error response while reloading");
options.simulate_error();
assert.ok(!orig_error_called);
},
});
});

View File

@ -106,6 +106,7 @@ function make_switcher() {
switch (sel) {
case ".ind-tab":
return ind_tab;
/* istanbul ignore next */
default:
throw new Error("unknown selector: " + sel);
}
@ -151,6 +152,7 @@ mock_jquery((sel, attributes) => {
);
return make_tab(tab_id);
}
/* istanbul ignore next */
default:
throw new Error("unknown selector: " + sel);
}

View File

@ -145,10 +145,6 @@ test_ui("send_message", ({override, override_rewire}) => {
return stub_state;
}
set_global("setTimeout", (func) => {
func();
});
override(server_events, "assert_get_events_running", () => {
stub_state.get_events_running_called += 1;
});
@ -635,13 +631,15 @@ test_ui("on_events", ({override, override_rewire}) => {
);
helper.$container.data = (field) => {
if (field === "user-id") {
return "34";
switch (field) {
case "user-id":
return "34";
case "stream-id":
return "102";
/* istanbul ignore next */
default:
throw new Error(`Unknown field ${field}`);
}
if (field === "stream-id") {
return "102";
}
throw new Error(`Unknown field ${field}`);
};
helper.$target.prop("disabled", false);
@ -737,9 +735,6 @@ test_ui("on_events", ({override, override_rewire}) => {
(function test_attach_files_compose_clicked() {
const handler = $("#compose").get_on_handler("click", ".compose_upload_file");
$("#compose .file_input").clone = (param) => {
assert.ok(param);
};
let compose_file_input_clicked = false;
$("#compose .file_input").on("click", () => {
compose_file_input_clicked = true;

View File

@ -390,6 +390,7 @@ test("quote_and_reply", ({override, override_rewire}) => {
raw_content: "Testing.",
};
/* istanbul ignore next */
function whiny_get() {
assert.fail("channel.get should not be used if raw_content is present");
}

View File

@ -19,6 +19,7 @@ mock_jquery((selector) => {
return "lunch";
},
};
/* istanbul ignore next */
default:
throw new Error(`Unknown selector ${selector}`);
}

View File

@ -41,8 +41,6 @@ run_test("pills", ({override}) => {
people.add_active_user(iago);
people.add_active_user(hamlet);
people.get_realm_users = () => [iago, othello, hamlet];
const $recipient_stub = $("#private_message_recipient");
const pill_container_stub = "pill-container";
$recipient_stub.set_parent(pill_container_stub);
@ -81,25 +79,29 @@ run_test("pills", ({override}) => {
let get_by_email_called = false;
people.get_by_email = (user_email) => {
get_by_email_called = true;
if (user_email === iago.email) {
return iago;
switch (user_email) {
case iago.email:
return iago;
case othello.email:
return othello;
/* istanbul ignore next */
default:
throw new Error(`Unknown user email ${user_email}`);
}
if (user_email === othello.email) {
return othello;
}
throw new Error(`Unknown user email ${user_email}`);
};
let get_by_user_id_called = false;
people.get_by_user_id = (id) => {
get_by_user_id_called = true;
if (id === othello.user_id) {
return othello;
switch (id) {
case othello.user_id:
return othello;
case hamlet.user_id:
return hamlet;
/* istanbul ignore next */
default:
throw new Error(`Unknown user ID ${id}`);
}
if (id === hamlet.user_id) {
return hamlet;
}
throw new Error(`Unknown user ID ${id}`);
};
function test_create_item(handler) {

View File

@ -71,6 +71,7 @@ function make_textbox(s) {
};
$widget.val = function (new_val) {
/* istanbul ignore if */
if (new_val) {
$widget.s = new_val;
return this;
@ -301,6 +302,7 @@ run_test("quote_and_reply", ({override, override_rewire}) => {
textarea_caret_pos = arg;
return this;
}
/* istanbul ignore if */
if (typeof arg !== "string") {
console.info(arg);
throw new Error("We expected the actual code to pass in a string.");

View File

@ -163,12 +163,10 @@ test_ui("validate", ({override, mock_template}) => {
add_content_to_compose_box();
let zephyr_checked = false;
$("#zephyr-mirror-error").is = () => {
if (!zephyr_checked) {
zephyr_checked = true;
return true;
}
return false;
$("#zephyr-mirror-error").is = (arg) => {
assert.equal(arg, ":visible");
zephyr_checked = true;
return true;
};
assert.ok(!compose_validate.validate());
assert.ok(zephyr_checked);
@ -740,14 +738,17 @@ test_ui("warn_if_mentioning_unsubscribed_user", ({override, override_rewire, moc
let looked_for_existing;
$warning_row.data = (field) => {
if (field === "user-id") {
looked_for_existing = true;
return "34";
switch (field) {
case "user-id":
looked_for_existing = true;
return "34";
/* istanbul ignore next */
case "stream-id":
return "111";
/* istanbul ignore next */
default:
throw new Error(`Unknown field ${field}`);
}
if (field === "stream-id") {
return "111";
}
throw new Error(`Unknown field ${field}`);
};
const $previous_users = $("#compose_invite_users .compose_invite_user");

View File

@ -32,6 +32,7 @@ const compose = zrequire("compose");
function stub_out_video_calls() {
const $elem = $("#below-compose-content .video_link");
$elem.toggle = (show) => {
/* istanbul ignore if */
if (show) {
$elem.show();
} else {
@ -77,8 +78,6 @@ test("videos", ({override, override_rewire}) => {
compose.initialize();
(function test_no_provider_video_link_compose_clicked() {
let called = false;
const $textarea = $.create("target-stub");
$textarea.set_parents_result(".message_edit_form", []);
@ -90,15 +89,19 @@ test("videos", ({override, override_rewire}) => {
},
};
override_rewire(compose_ui, "insert_syntax_and_focus", () => {
called = true;
});
override_rewire(
compose_ui,
"insert_syntax_and_focus",
/* istanbul ignore next */
() => {
throw new Error("unexpected insert_syntax_and_focus call");
},
);
const handler = $("body").get_on_handler("click", ".video_link");
$("#compose-textarea").val("");
handler(ev);
assert.ok(!called);
})();
(function test_jitsi_video_link_compose_clicked() {

View File

@ -54,9 +54,6 @@ const composebox_typeahead = zrequire("composebox_typeahead");
const settings_config = zrequire("settings_config");
const pygments_data = zrequire("../generated/pygments_data.json");
// To be eliminated in next commit:
stream_data.__Rewire__("set_filter_out_inactives", () => false);
const ct = composebox_typeahead;
// Use a slightly larger value than what's user-facing
@ -143,19 +140,10 @@ const emojis_by_name = new Map(
headphones: emoji_headphones,
}),
);
const emoji_list = Array.from(emojis_by_name.values(), (emoji_dict) => {
if (emoji_dict.is_realm_emoji === true) {
return {
emoji_name: emoji_dict.name,
emoji_url: emoji_dict.url,
is_realm_emoji: true,
};
}
return {
emoji_name: emoji_dict.name,
emoji_code: emoji_dict.emoji_code,
};
});
const emoji_list = Array.from(emojis_by_name.values(), (emoji_dict) => ({
emoji_name: emoji_dict.name,
emoji_code: emoji_dict.emoji_code,
}));
const me_slash = {
name: "me",
@ -1070,14 +1058,8 @@ test("initialize", ({override, override_rewire, mock_template}) => {
stopPropagation: noop,
};
$("#stream_message_recipient_topic").data = () => ({typeahead: {shown: true}});
$("form#send_message_form").trigger(event);
const stub_typeahead_hidden = () => ({typeahead: {shown: false}});
$("#stream_message_recipient_topic").data = stub_typeahead_hidden;
$("#stream_message_recipient_stream").data = stub_typeahead_hidden;
$("#private_message_recipient").data = stub_typeahead_hidden;
$("#compose-textarea").data = stub_typeahead_hidden;
$("form#send_message_form").trigger(event);
event.key = "Tab";
@ -1144,7 +1126,6 @@ test("initialize", ({override, override_rewire, mock_template}) => {
preventDefault: noop,
};
// We trigger keydown in order to make nextFocus !== false
$("#stream_message_recipient_topic").data = () => ({typeahead: {shown: true}});
$("form#send_message_form").trigger(event);
$("#stream_message_recipient_topic").off("mouseup");
event.type = "keyup";

View File

@ -78,7 +78,7 @@ run_test("no_default_value", () => {
widget_name: "my_setting",
data: ["one", "two", "three"].map((x) => ({name: x, value: x})),
default_text: $t({defaultMessage: "not set"}),
render_text: (text) => `rendered: ${text}`,
render_text: /* istanbul ignore next */ (text) => `rendered: ${text}`,
null_value: "null-value",
};

View File

@ -17,11 +17,13 @@ run_test("explore make_stub", ({override}) => {
// Let's say you have to test the following code.
const app = {
/* istanbul ignore next */
notify_server_of_deposit(deposit_amount) {
// simulate difficulty
throw new Error(`We cannot report this value without wifi: ${deposit_amount}`);
},
/* istanbul ignore next */
pop_up_fancy_confirmation_screen(deposit_amount, label) {
// simulate difficulty
throw new Error(`We cannot make a ${label} dialog for amount ${deposit_amount}`);

View File

@ -91,8 +91,6 @@ run_test("unread_ops", ({override, override_rewire}) => {
// We don't want recent topics to process message for this test.
override_rewire(recent_topics_util, "is_visible", () => false);
// Show message_viewport as not visible so that messages will be stored as unread.
override(message_viewport, "is_visible_and_focused", () => false);
// Make our test message appear to be unread, so that
// we then need to subsequently process them as read.

View File

@ -105,7 +105,6 @@ message_lists.current = {
flags: ["read", "starred"],
};
},
selected_row() {},
get_row() {
return 101;
},
@ -138,7 +137,6 @@ function stubbing_rewire(module, func_name_to_stub, test_function) {
}
// Set up defaults for most tests.
hotkey.__Rewire__("in_content_editable_widget", () => false);
hotkey.__Rewire__("processing_text", () => false);
run_test("mappings", () => {
@ -228,7 +226,7 @@ function process(s) {
};
try {
return hotkey.process_keypress(e);
} catch (error) {
} catch (error) /* istanbul ignore next */ {
// An exception will be thrown here if a different
// function is called than the one declared. Try to
// provide a useful error message.
@ -292,8 +290,8 @@ run_test("allow normal typing when processing text", ({override_rewire}) => {
run_test("streams", ({override}) => {
settings_data.user_can_create_private_streams = () => true;
settings_data.user_can_create_public_streams = () => true;
settings_data.user_can_create_web_public_streams = () => true;
delete settings_data.user_can_create_public_streams;
delete settings_data.user_can_create_web_public_streams;
override(overlays, "streams_open", () => true);
override(overlays, "is_active", () => true);
assert_mapping("S", stream_settings_ui, "keyboard_sub");
@ -435,7 +433,7 @@ run_test("motion_keys", () => {
try {
return hotkey.process_keydown(e);
} catch (error) {
} catch (error) /* istanbul ignore next */ {
// An exception will be thrown here if a different
// function is called than the one declared. Try to
// provide a useful error message.
@ -493,12 +491,12 @@ run_test("motion_keys", () => {
overlays.streams_open = () => true;
assert_mapping("up_arrow", stream_settings_ui, "switch_rows");
assert_mapping("down_arrow", stream_settings_ui, "switch_rows");
overlays.streams_open = () => false;
delete overlays.streams_open;
overlays.lightbox_open = () => true;
assert_mapping("left_arrow", lightbox, "prev");
assert_mapping("right_arrow", lightbox, "next");
overlays.lightbox_open = () => false;
delete overlays.lightbox_open;
overlays.settings_open = () => true;
assert_unmapped("end");
@ -507,12 +505,12 @@ run_test("motion_keys", () => {
assert_unmapped("page_up");
assert_unmapped("page_down");
assert_unmapped("spacebar");
overlays.settings_open = () => false;
delete overlays.settings_open;
overlays.is_active = () => true;
delete overlays.is_active;
overlays.drafts_open = () => true;
assert_mapping("up_arrow", drafts, "drafts_handle_events");
assert_mapping("down_arrow", drafts, "drafts_handle_events");
overlays.is_active = () => false;
overlays.drafts_open = () => false;
delete overlays.is_active;
delete overlays.drafts_open;
});

View File

@ -644,7 +644,7 @@ run_test("appendValue/clear", ({mock_template}) => {
const config = {
$container,
create_item_from_text: (s) => ({type: "color", display_value: s}),
get_text_from_item: (s) => s.display_value,
get_text_from_item: /* istanbul ignore next */ (s) => s.display_value,
};
$pill_input.before = () => {};

View File

@ -11,7 +11,7 @@ run_test("test_early_returns", () => {
const opts = {
$elem: $stub,
handlers: {
ArrowLeft: () => {
ArrowLeft: /* istanbul ignore next */ () => {
throw new Error("do not dispatch this with alt key");
},
},

View File

@ -34,8 +34,8 @@ function basic_conf({first_key, prev_key, next_key}) {
run_test("misc errors", ({override}) => {
const conf = basic_conf({
first_key: () => undefined,
prev_key: () => undefined,
next_key: () => undefined,
prev_key: /* istanbul ignore next */ () => undefined,
next_key: /* istanbul ignore next */ () => undefined,
});
const cursor = new ListCursor(conf);
@ -64,7 +64,7 @@ run_test("single item list", ({override}) => {
const valid_key = "42";
const conf = basic_conf({
first_key: () => valid_key,
first_key: /* istanbul ignore next */ () => valid_key,
next_key: () => undefined,
prev_key: () => undefined,
});
@ -91,7 +91,7 @@ run_test("single item list", ({override}) => {
run_test("multiple item list", ({override}) => {
const conf = basic_conf({
first_key: () => 1,
first_key: /* istanbul ignore next */ () => 1,
next_key: (key) => (key < 3 ? key + 1 : undefined),
prev_key: (key) => (key > 1 ? key - 1 : undefined),
});

View File

@ -43,13 +43,6 @@ const ListWidget = zrequire("list_widget");
function make_container() {
const $container = {};
$container.length = () => 1;
$container.is = () => false;
$container.css = (prop) => {
assert.equal(prop, "max-height");
return "none";
};
// Make our append function just set a field we can
// check in our tests.
$container.append = ($data) => {
@ -123,6 +116,7 @@ function make_search_input() {
// Allow ourselves to be wrapped by $(...) and
// return ourselves.
/* istanbul ignore next */
$element.to_jquery = () => $element;
$element.on = (event_name, f) => {
@ -322,6 +316,7 @@ function sort_button(opts) {
return opts.sort_type;
case "sort-prop":
return opts.prop_name;
/* istanbul ignore next */
default:
throw new Error("unknown selector: " + sel);
}
@ -549,7 +544,7 @@ run_test("clear_event_handlers", () => {
modifier: () => {},
filter: {
$element: $filter_element,
predicate: () => true,
predicate: /* istanbul ignore next */ () => true,
},
$simplebar_container: $scroll_container,
};
@ -602,8 +597,8 @@ run_test("errors", () => {
blueslip.expect("error", "Filterer and predicate are mutually exclusive.");
ListWidget.create($container, list, {
filter: {
filterer: () => true,
predicate: () => true,
filterer: /* istanbul ignore next */ () => true,
predicate: /* istanbul ignore next */ () => true,
},
$simplebar_container: $scroll_container,
});
@ -795,7 +790,8 @@ run_test("render item", () => {
blueslip.expect("error", "html_selector should be a function.");
ListWidget.create($container, list, {
name: "replace-list",
modifier: (item) => `<tr data-item=${item.value}>${item.text}</tr>\n`,
modifier: /* istanbul ignore next */ (item) =>
`<tr data-item=${item.value}>${item.text}</tr>\n`,
get_item,
html_selector: "hello world",
$simplebar_container: $scroll_container,
@ -855,6 +851,7 @@ run_test("Multiselect dropdown retain_selected_items", () => {
if (element) {
return true;
}
/* istanbul ignore next */
return false;
}

View File

@ -27,11 +27,6 @@ const example_realm_linkifiers = [
];
user_settings.translate_emoticons = false;
function Image() {
return {};
}
set_global("Image", Image);
set_global("document", {compatMode: "CSS1Compat"});
const emoji = zrequire("emoji");
@ -244,6 +239,7 @@ test("marked_shared", () => {
for (const test of tests) {
// Ignore tests if specified
/* istanbul ignore if */
if (test.ignore === true) {
continue;
}

View File

@ -24,7 +24,8 @@ function get_user_id_from_name(name) {
}
}
return undefined;
/* istanbul ignore next */
throw new Error(`unexpected name ${name}`);
}
function is_valid_full_name_and_user_id(name, user_id) {
@ -99,7 +100,8 @@ function get_emoji_name(codepoint) {
}
}
return undefined;
/* istanbul ignore next */
throw new Error(`unexpected codepoint ${codepoint}`);
}
const realm_emoji_map = new Map();

View File

@ -93,17 +93,13 @@ function config_fake_channel(conf) {
// There's a separate call with anchor="newest" that happens
// unconditionally; do basic verification of that call.
if (opts.data.anchor === "newest") {
if (!called_with_newest_flag) {
called_with_newest_flag = true;
assert.equal(opts.data.num_after, 0);
return;
}
throw new Error("Only one 'newest' call allowed");
assert.ok(!called_with_newest_flag, "Only one 'newest' call allowed");
called_with_newest_flag = true;
assert.equal(opts.data.num_after, 0);
return;
}
if (called && !conf.can_call_again) {
throw new Error("only use this for one call");
}
assert.ok(!called || conf.can_call_again, "only use this for one call");
if (!conf.can_call_again) {
assert.equal(self.success, undefined);
}

View File

@ -2,19 +2,10 @@
const {strict: assert} = require("assert");
const {
set_global,
with_function_call_disallowed_rewire,
zrequire,
} = require("../zjsunit/namespace");
const {with_function_call_disallowed_rewire, zrequire} = require("../zjsunit/namespace");
const {run_test} = require("../zjsunit/test");
const blueslip = require("../zjsunit/zblueslip");
set_global("setTimeout", (f, delay) => {
assert.equal(delay, 0);
return f();
});
const muted_topics = zrequire("muted_topics");
const muted_users = zrequire("muted_users");
const {MessageListData} = zrequire("../js/message_list_data");

View File

@ -6,14 +6,11 @@ const _ = require("lodash");
const {mock_esm, set_global, zrequire} = require("../zjsunit/namespace");
const {run_test} = require("../zjsunit/test");
const {user_settings} = require("../zjsunit/zpage_params");
set_global("document", "document-stub");
const noop = () => {};
user_settings.twenty_four_hour_time = false;
mock_esm("../../static/js/message_lists", {home: "stub"});
// timerender calls setInterval when imported
@ -25,9 +22,6 @@ mock_esm("../../static/js/timerender", {
return [{outerHTML: String(time1.getTime()) + " - " + String(time2.getTime())}];
},
stringify_time(time) {
if (user_settings.twenty_four_hour_time) {
return time.toString("HH:mm");
}
return time.toString("h:mm TT");
},
});

View File

@ -160,13 +160,6 @@ run_test("basics", () => {
all_messages_data.all_messages_data = {
all_messages: () => messages,
get: (msg_id) => {
assert.equal(msg_id, selected_id);
return selected_message;
},
fetch_status: {
has_found_newest: () => true,
},
empty: () => false,
first: () => ({id: 900}),
last: () => ({id: 1100}),

View File

@ -26,7 +26,6 @@ const alice = {
people.init();
people.add_active_user(alice);
people.is_my_user_id = () => false;
function set_filter(terms) {
const filter = new Filter(terms);

View File

@ -56,13 +56,17 @@ test("allow_notification_alert", () => {
assert.equal(navbar_alerts.should_show_notifications(ls), false);
// Avoid showing if notification is already granted.
/* istanbul ignore next */
notifications.permission_state = () => "granted";
notifications.granted_desktop_notifications_permission = () => "granted";
assert.equal(navbar_alerts.should_show_notifications(ls), false);
// Don't ask for permission to spectator.
/* istanbul ignore next */
util.is_mobile = () => false;
/* istanbul ignore next */
notifications.granted_desktop_notifications_permission = () => false;
/* istanbul ignore next */
notifications.permission_state = () => "granted";
page_params.is_spectator = true;
assert.equal(navbar_alerts.should_show_notifications(ls), false);

View File

@ -11,12 +11,15 @@ function password_field(min_length, min_guesses) {
const self = {};
self.data = (field) => {
if (field === "minLength") {
return min_length;
} else if (field === "minGuesses") {
return min_guesses;
switch (field) {
case "minLength":
return min_length;
case "minGuesses":
return min_guesses;
/* istanbul ignore next */
default:
throw new Error(`Unknown field ${field}`);
}
throw new Error(`Unknown field ${field}`);
};
return self;

View File

@ -835,9 +835,13 @@ test_people("extract_people_from_message", ({override_rewire}) => {
assert.ok(reported);
// Get line coverage
people.__Rewire__("report_late_add", () => {
throw new Error("unexpected late add");
});
people.__Rewire__(
"report_late_add",
/* istanbul ignore next */
() => {
throw new Error("unexpected late add");
},
);
message = {
type: "private",

View File

@ -49,9 +49,6 @@ const spectators = mock_esm("../../static/js/spectators", {
});
message_lists.current = {
selected_message() {
return {sent_by_me: true};
},
selected_row() {
return $(".selected-row");
},

View File

@ -63,9 +63,11 @@ const ListWidget = mock_esm("../../static/js/list_widget", {
hard_redraw: noop,
render_item: (item) => ListWidget.modifier(item),
replace_list_data: (data) => {
if (expected_data_to_replace_in_list_widget === undefined) {
throw new Error("You must set expected_data_to_replace_in_list_widget");
}
assert.notEqual(
expected_data_to_replace_in_list_widget,
undefined,
"You must set expected_data_to_replace_in_list_widget",
);
assert.deepEqual(data, expected_data_to_replace_in_list_widget);
expected_data_to_replace_in_list_widget = undefined;
},
@ -110,7 +112,6 @@ mock_esm("../../static/js/stream_data", {
// We only test via muted topics for now.
// TODO: Make muted streams and test them.
false,
is_subscribed: () => true,
});
mock_esm("../../static/js/stream_list", {
handle_narrow_deactivated: noop,

View File

@ -88,6 +88,7 @@ const get_content_element = () => {
// Fend off dumb security bugs by forcing devs to be
// intentional about HTML manipulation.
/* istanbul ignore next */
function security_violation() {
throw new Error(`
Be super careful about HTML manipulation.
@ -401,9 +402,7 @@ function test_code_playground(mock_template, viewing_code) {
// our case "fake" zjquery objects).
const prepends = [];
$pre.prepend = (arg) => {
if (!arg.__zjquery) {
throw new Error("We should only prepend jQuery objects.");
}
assert.ok(arg.__zjquery, "We should only prepend jQuery objects.");
prepends.push(arg);
};

View File

@ -2,7 +2,7 @@
const {strict: assert} = require("assert");
const {mock_esm, set_global, zrequire} = require("../zjsunit/namespace");
const {mock_esm, zrequire} = require("../zjsunit/namespace");
const {run_test} = require("../zjsunit/test");
const $ = require("../zjsunit/zjquery");
const {page_params} = require("../zjsunit/zpage_params");
@ -25,8 +25,6 @@ mock_esm("../../static/js/ui_util", {
place_caret_at_end: noop,
});
set_global("setTimeout", (func) => func());
const search = zrequire("search");
const search_pill = zrequire("search_pill");
const {Filter} = zrequire("../js/filter");
@ -63,14 +61,14 @@ test("update_button_visibility", () => {
$search_query.is = () => true;
$search_query.val("");
narrow_state.active = () => false;
delete narrow_state.active;
$search_button.prop("disabled", true);
search.update_button_visibility();
assert.ok(!$search_button.prop("disabled"));
$search_query.is = () => false;
$search_query.val("Test search term");
narrow_state.active = () => false;
delete narrow_state.active;
$search_button.prop("disabled", true);
search.update_button_visibility();
assert.ok(!$search_button.prop("disabled"));
@ -144,9 +142,13 @@ test("initialize", () => {
let operators;
let is_blurred;
let is_append_search_string_called;
$search_query_box.on("blur", () => {
is_blurred = true;
});
$search_query_box.on(
"blur",
/* istanbul ignore next */
() => {
is_blurred = true;
},
);
search_pill.append_search_string = () => {
is_append_search_string_called = true;
};
@ -155,14 +157,17 @@ test("initialize", () => {
is_blurred = false;
is_append_search_string_called = false;
$search_query_box.val(search_box_val);
/* istanbul ignore next */
Filter.parse = (search_string) => {
assert.equal(search_string, search_box_val);
return operators;
};
/* istanbul ignore next */
narrow.activate = (raw_operators, options) => {
assert.deepEqual(raw_operators, operators);
assert.deepEqual(options, {trigger: "search"});
};
/* istanbul ignore next */
search_pill.get_search_string_for_current_filter = () => search_box_val;
};
@ -285,6 +290,7 @@ test("initialize", () => {
type: "keyup",
which: 15,
};
/* istanbul ignore next */
$search_query_box.is = () => false;
$searchbox_form.trigger(ev);

View File

@ -53,14 +53,14 @@ run_test("update_button_visibility", () => {
$search_query.is = () => true;
$search_query.val("");
narrow_state.active = () => false;
delete narrow_state.active;
$search_button.prop("disabled", true);
search.update_button_visibility();
assert.ok(!$search_button.prop("disabled"));
$search_query.is = () => false;
$search_query.val("Test search term");
narrow_state.active = () => false;
delete narrow_state.active;
$search_button.prop("disabled", true);
search.update_button_visibility();
assert.ok(!$search_button.prop("disabled"));
@ -247,6 +247,7 @@ run_test("initialize", () => {
_setup("");
ev.key = "a";
/* istanbul ignore next */
$search_query_box.is = () => false;
$searchbox_form.trigger(ev);

View File

@ -676,8 +676,9 @@ test("topic_suggestions", ({override, override_rewire}) => {
return office_id;
case "devel":
return devel_id;
/* istanbul ignore next */
default:
return undefined;
throw new Error(`unknown stream ${stream_name}`);
}
});

View File

@ -641,8 +641,9 @@ test("topic_suggestions", ({override, override_rewire}) => {
return office_id;
case "devel":
return devel_id;
/* istanbul ignore next */
default:
return undefined;
throw new Error(`unknown stream ${stream_name}`);
}
});

View File

@ -40,9 +40,6 @@ mock_esm("../../static/js/ui_report", {
hide_error() {
return false;
},
show_error() {
return false;
},
});
mock_esm("../../static/js/stream_events", {

View File

@ -60,15 +60,16 @@ run_test("settings", ({override_rewire}) => {
let topic_data_called = 0;
$topic_tr_html.attr = (opts) => {
if (opts === "data-stream-id") {
topic_data_called += 1;
return frontend.stream_id;
topic_data_called += 1;
switch (opts) {
case "data-stream-id":
return frontend.stream_id;
case "data-topic":
return "js";
/* istanbul ignore next */
default:
throw new Error(`Unknown attribute ${opts}`);
}
if (opts === "data-topic") {
topic_data_called += 1;
return "js";
}
throw new Error(`Unknown attribute ${opts}`);
};
let unmute_topic_called = false;

View File

@ -51,11 +51,9 @@ run_test("settings", ({override_rewire}) => {
let row_attribute_fetched = false;
$fake_row.attr = (opts) => {
if (opts === "data-user-id") {
row_attribute_fetched += 1;
return "5";
}
throw new Error(`Unknown attribute ${opts}`);
assert.equal(opts, "data-user-id");
row_attribute_fetched += 1;
return "5";
};
let unmute_user_called = false;

View File

@ -47,7 +47,6 @@ const settings_bots = zrequire("settings_bots");
const stream_settings_data = zrequire("stream_settings_data");
const settings_account = zrequire("settings_account");
const settings_org = zrequire("settings_org");
const sub_store = zrequire("sub_store");
const dropdown_list_widget = zrequire("dropdown_list_widget");
function test(label, f) {
@ -195,7 +194,6 @@ function test_submit_settings_form(override, submit_form) {
let stubs = createSaveButtons(subsection);
let $save_button = stubs.$save_button;
$save_button.attr("id", `org-submit-${subsection}`);
$save_button.replace = () => `${subsection}`;
$("#id_realm_waiting_period_threshold").val(10);
@ -241,6 +239,7 @@ function test_submit_settings_form(override, submit_form) {
$add_custom_emoji_policy_elem,
$create_public_stream_policy_elem,
$create_private_stream_policy_elem,
$invite_to_realm_policy_elem,
$invite_to_stream_policy_elem,
]);
@ -250,6 +249,7 @@ function test_submit_settings_form(override, submit_form) {
let expected_value = {
bot_creation_policy: 1,
invite_to_realm_policy: 2,
invite_to_stream_policy: 1,
email_address_visibility: 1,
add_custom_emoji_policy: 1,
@ -925,10 +925,6 @@ test("misc", ({override_rewire}) => {
let setting_name = "realm_notifications_stream_id";
let $elem = $(`#${CSS.escape(setting_name)}_widget #${CSS.escape(setting_name)}_name`);
$elem.closest = () => $stub_notification_disable_parent;
sub_store.__Rewire__("get", (stream_id) => {
assert.equal(stream_id, 42);
return {name: "some_stream"};
});
settings_org.notifications_stream_widget.render(42);
assert.equal($elem.text(), "#some_stream");
assert.ok(!$elem.hasClass("text-warning"));
@ -940,10 +936,6 @@ test("misc", ({override_rewire}) => {
setting_name = "realm_signup_notifications_stream_id";
$elem = $(`#${CSS.escape(setting_name)}_widget #${CSS.escape(setting_name)}_name`);
$elem.closest = () => $stub_notification_disable_parent;
sub_store.__Rewire__("get", (stream_id) => {
assert.equal(stream_id, 75);
return {name: "some_stream"};
});
settings_org.signup_notifications_stream_widget.render(75);
assert.equal($elem.text(), "#some_stream");
assert.ok(!$elem.hasClass("text-warning"));

View File

@ -116,8 +116,6 @@ test_ui("populate_user_groups", ({override_rewire, mock_template}) => {
user_groups.get_realm_user_groups = () => [realm_user_group];
people.get_visible_email = () => bob.email;
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) => {
@ -139,12 +137,6 @@ test_ui("populate_user_groups", ({override_rewire, mock_template}) => {
if (user_id === iago.user_id) {
return iago;
}
if (user_id === alice.user_id) {
return alice;
}
if (user_id === undefined) {
return noop;
}
assert.equal(user_id, 4);
blueslip.expect("warn", "Undefined user in function append_user");
get_by_user_id_called = true;
@ -246,9 +238,6 @@ test_ui("populate_user_groups", ({override_rewire, mock_template}) => {
saved_fade_out_called = true;
};
$(cancel_selector).css = (data) => {
if (typeof data === "string") {
assert.equal(data, "display");
}
assert.equal(typeof data, "object");
assert.equal(data.display, "inline-block");
assert.equal(data.opacity, "0");
@ -258,9 +247,6 @@ test_ui("populate_user_groups", ({override_rewire, mock_template}) => {
cancel_fade_to_called = true;
};
$(instructions_selector).css = (data) => {
if (typeof data === "string") {
assert.equal(data, "display");
}
assert.equal(typeof data, "object");
assert.equal(data.display, "block");
assert.equal(data.opacity, "0");
@ -284,17 +270,15 @@ test_ui("populate_user_groups", ({override_rewire, mock_template}) => {
let get_by_email_called = false;
people.get_by_email = (user_email) => {
get_by_email_called = true;
if (user_email === iago.email) {
return iago;
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.");
}
if (user_email === bob.email) {
return bob;
}
throw new Error("Expected user email to be of Alice or Iago here.");
};
pills.onPillCreate = (handler) => {
assert.equal(typeof handler, "function");
handler();
};
function test_create_item(handler) {
@ -363,8 +347,9 @@ test_ui("with_external_user", ({override_rewire, mock_template}) => {
user_groups.get_realm_user_groups = () => [realm_user_group];
// We return noop because these are already tested, so we skip them
people.get_realm_users = () => noop;
// We return [] because these are already tested, so we skip them
/* istanbul ignore next */
people.get_realm_users = () => [];
mock_template(
"settings/admin_user_group_list.hbs",
@ -372,9 +357,9 @@ test_ui("with_external_user", ({override_rewire, mock_template}) => {
() => "settings/admin_user_group_list.hbs",
);
people.get_by_user_id = () => noop;
people.get_by_user_id = () => "user stub";
override_rewire(user_pill, "append_person", () => noop);
override_rewire(user_pill, "append_person", noop);
let can_edit_called = 0;
override_rewire(settings_user_groups, "can_edit", () => {
@ -391,30 +376,32 @@ test_ui("with_external_user", ({override_rewire, mock_template}) => {
const $description_field_stub = $.create("fake-description-field");
const $input_stub = $.create("fake-input");
$user_group_stub.find = (elem) => {
if (elem === ".name") {
user_group_find_called += 1;
return $name_field_stub;
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}`);
}
if (elem === ".description") {
user_group_find_called += 1;
return $description_field_stub;
}
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) => {
if (elem === ".input") {
pill_container_find_called += 1;
return $input_stub;
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}`);
}
if (elem === ".pill") {
pill_container_find_called += 1;
return $pill_stub;
}
throw new Error(`Unknown element ${elem}`);
};
$input_stub.css = (property, val) => {
@ -437,10 +424,10 @@ test_ui("with_external_user", ({override_rewire, mock_template}) => {
assert.equal(value, "0.5");
};
// We return noop because these are already tested, so we skip them
$pill_container_stub.children = () => noop;
// We return [] because these are already tested, so we skip them
$pill_container_stub.children = () => [];
$("#user-groups").append = () => noop;
$("#user-groups").append = noop;
reset_test_setup($pill_container_stub);
@ -621,6 +608,7 @@ test_ui("on_events", ({override_rewire, mock_template}) => {
(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;
};
@ -658,10 +646,8 @@ test_ui("on_events", ({override_rewire, mock_template}) => {
api_endpoint_called = false;
$fake_this.closest = (class_name) => {
if (class_name === ".typeahead") {
return [1];
}
return [];
assert.equal(class_name, ".typeahead");
return [1];
};
handler.call($fake_this, event);
assert.ok(!api_endpoint_called);
@ -755,9 +741,6 @@ test_ui("on_events", ({override_rewire, mock_template}) => {
cancel_fade_out_called = true;
};
$(saved_selector).css = (data) => {
if (typeof data === "string") {
assert.equal(data, "display");
}
assert.equal(typeof data, "object");
assert.equal(data.display, "inline-block");
assert.equal(data.opacity, "0");

View File

@ -10,7 +10,6 @@ const denmark_stream_id = 101;
const ui = mock_esm("../../static/js/ui", {
get_content_element: ($element) => $element,
get_scroll_element: ($element) => $element,
});
mock_esm("../../static/js/hash_util", {

View File

@ -81,7 +81,7 @@ test("basics", () => {
max_message_id = stream_topic_history.get_max_message_id(stream_id);
assert.deepEqual(max_message_id, 103);
message_util.get_messages_in_topic = () => [{id: 102}];
delete message_util.get_messages_in_topic;
// Removing first topic1 message has no effect.
stream_topic_history.remove_messages({
stream_id,
@ -163,8 +163,6 @@ test("server_history", () => {
const stream_id = sub.stream_id;
stream_data.add_sub(sub);
all_messages_data.all_messages_data.fetch_status.has_found_newest = () => false;
assert.equal(stream_topic_history.is_complete_for_stream_id(stream_id), false);
stream_topic_history.add_message({
@ -332,6 +330,7 @@ test("server_history_end_to_end", () => {
// Try getting server history for a second time.
/* istanbul ignore next */
channel.get = () => {
throw new Error("We should not get more data.");
};

View File

@ -60,9 +60,14 @@ run_test("transmit_message_ajax", () => {
});
run_test("transmit_message_ajax_reload_pending", () => {
/* istanbul ignore next */
const success = () => {
throw new Error("unexpected success");
};
/* istanbul ignore next */
const error = () => {
throw new Error("unexpected error");
};
reload_state.is_pending = () => true;
@ -80,13 +85,6 @@ run_test("transmit_message_ajax_reload_pending", () => {
const request = {foo: "bar"};
let error_func_called;
const error = (response) => {
assert.equal(response, "Error sending message");
error_func_called = true;
};
error_func_called = false;
channel.post = (opts) => {
assert.equal(opts.url, "/json/messages");
assert.equal(opts.data.foo, "bar");
@ -94,7 +92,6 @@ run_test("transmit_message_ajax_reload_pending", () => {
opts.error(xhr, "bad request");
};
transmit.send_message(request, success, error);
assert.ok(!error_func_called);
assert.ok(reload_initiated);
});
@ -143,8 +140,6 @@ run_test("reply_message_private", ({override_rewire}) => {
};
people.add_active_user(fred);
people.is_my_user_id = () => false;
const pm_message = {
type: "private",
display_recipient: [{id: fred.user_id}],

View File

@ -453,6 +453,7 @@ test("sort_recipients pm counts", () => {
"zman@test.net",
]);
/* istanbul ignore next */
function compare() {
throw new Error("We do not expect to need a tiebreaker here.");
}

View File

@ -250,10 +250,8 @@ test("num_unread_for_topic", ({override_rewire}) => {
const stream_id = 301;
override_rewire(sub_store, "get", (arg) => {
if (arg === stream_id) {
return {name: "Some stream"};
}
throw new Error(`Unknown stream ${arg}`);
assert.equal(arg, stream_id);
return {name: "Some stream"};
});
let count = unread.num_unread_for_topic(stream_id, "lunch");

View File

@ -63,6 +63,7 @@ run_test("initialize", ({override_rewire}) => {
};
success_callback();
break;
/* istanbul ignore next */
default:
throw new Error("Unhandled case");
}
@ -85,9 +86,6 @@ run_test("initialize", ({override_rewire}) => {
$("input[type=radio][name=schedule]:checked").val = () =>
document.querySelector("input[type=radio][name=schedule]:checked").value;
$("#autopay-form").data = (key) =>
document.querySelector("#autopay-form").getAttribute("data-" + key);
const initialize_function = $.get_initialize_function();
initialize_function();

View File

@ -175,6 +175,7 @@ run_test("partial updates", () => {
assert.equal(rendered_html, "<ul>\n<li>foo1</li>\n<li>foo2</li>\n<li>foo3</li>\n</ul>");
/* istanbul ignore next */
replace_content = () => {
throw new Error("should not replace entire html");
};
@ -209,6 +210,7 @@ run_test("partial updates", () => {
});
run_test("eq_array easy cases", () => {
/* istanbul ignore next */
const bogus_eq = () => {
throw new Error("we should not be comparing elements");
};

View File

@ -12,6 +12,7 @@ exports.intl = createIntl(
defaultRichTextElements: Object.fromEntries(
["b", "code", "em", "i", "kbd", "p", "strong"].map((tag) => [
tag,
/* istanbul ignore next */
(content_html) => `<${tag}>${content_html}</${tag}>`,
]),
),

View File

@ -1,5 +1,6 @@
"use strict";
const {strict: assert} = require("assert");
const path = require("path");
require("css.escape");
@ -39,9 +40,7 @@ function immediate(f) {
// Find the files we need to run.
const files = process.argv.slice(2);
if (files.length === 0) {
throw new Error("No tests found");
}
assert.notEqual(files.length, 0, "No tests found");
// Set up our namespace helpers.
const window = new Proxy(global, {
@ -73,6 +72,7 @@ handlebars.hook_require();
const noop = function () {};
/* istanbul ignore next */
function short_tb(tb) {
const lines = tb.split("\n");
@ -102,7 +102,6 @@ try {
for (const file of files) {
namespace.start();
namespace.set_global("window", window);
namespace.set_global("to_$", () => window);
namespace.set_global("location", dom.window.location);
window.location.href = "http://zulip.zulipdev.com/#";
namespace.set_global("setTimeout", noop);
@ -132,7 +131,7 @@ try {
namespace.finish();
}
} catch (error) {
} catch (error) /* istanbul ignore next */ {
if (process.env.USING_INSTRUMENTED_CODE) {
console.info(`
TEST FAILED! Before using the --coverage option please make sure that your

View File

@ -36,6 +36,7 @@ class MarkdownComparer {
constructor(output_formatter) {
this._output_formatter =
output_formatter ||
/* istanbul ignore next */
function (actual, expected) {
return ["Actual and expected output do not match.", actual, "!=", expected].join(
"\n",
@ -44,6 +45,7 @@ class MarkdownComparer {
this._document = new JSDOM().window.document;
}
/* istanbul ignore next */
setFormatter(output_formatter) {
this._output_formatter = output_formatter || this._output_formatter;
}
@ -88,6 +90,7 @@ class MarkdownComparer {
} else if (name_a > name_b) {
return 1;
}
/* istanbul ignore next */
return 0;
});
@ -139,6 +142,7 @@ class MarkdownComparer {
message = message || "";
message += "\n";
/* istanbul ignore if */
if (comparison_results.are_equivalent === false) {
throw new assert.AssertionError({
message:
@ -157,6 +161,7 @@ class MarkdownComparer {
message = message || "";
message += "\n";
/* istanbul ignore if */
if (comparison_results.are_equivalent) {
throw new assert.AssertionError({
message:
@ -174,11 +179,13 @@ class MarkdownComparer {
function returnComparer() {
if (!_markdownComparerInstance) {
_markdownComparerInstance = new MarkdownComparer((actual, expected) =>
[
"Actual and expected output do not match. Showing diff",
mdiff.diff_strings(actual, expected),
].join("\n"),
_markdownComparerInstance = new MarkdownComparer(
/* istanbul ignore next */
(actual, expected) =>
[
"Actual and expected output do not match. Showing diff",
mdiff.diff_strings(actual, expected),
].join("\n"),
);
}
return _markdownComparerInstance;
@ -193,6 +200,7 @@ module.exports = {
returnComparer().assertNotEqual(actual, expected, message);
},
/* istanbul ignore next */
setFormatter(output_formatter) {
returnComparer().setFormatter(output_formatter);
},

View File

@ -1,5 +1,6 @@
"use strict";
const {strict: assert} = require("assert");
const Module = require("module");
const path = require("path");
@ -24,6 +25,7 @@ let jquery_function;
const template_path = "/static/templates/";
/* istanbul ignore next */
function need_to_mock_template_error(filename) {
const i = filename.indexOf(template_path);
@ -100,6 +102,7 @@ function template_stub({filename, actual_render}) {
// Force devs to call mock_template on every top-level template
// render so they can introspect the data.
/* istanbul ignore if */
if (!template_mocks.has(filename)) {
throw new Error(need_to_mock_template_error(filename));
}
@ -126,9 +129,7 @@ function template_stub({filename, actual_render}) {
}
exports.start = () => {
if (actual_load !== undefined) {
throw new Error("namespace.start was called twice in a row.");
}
assert.equal(actual_load, undefined, "namespace.start was called twice in a row.");
actual_load = Module._load;
Module._load = load;
};
@ -163,11 +164,11 @@ exports.start = () => {
// format preferred by Webpack.
exports.mock_cjs = (module_path, obj) => {
if (module_path === "jquery") {
throw new Error(
"We automatically mock jquery to zjquery. Grep for mock_jquery if you want more control.",
);
}
assert.notEqual(
module_path,
"jquery",
"We automatically mock jquery to zjquery. Grep for mock_jquery if you want more control.",
);
const filename = Module._resolveFilename(
module_path,
@ -175,13 +176,12 @@ exports.mock_cjs = (module_path, obj) => {
false,
);
if (module_mocks.has(filename)) {
throw new Error(`You already set up a mock for ${filename}`);
}
assert.ok(!module_mocks.has(filename), `You already set up a mock for ${filename}`);
if (filename in require.cache) {
throw new Error(`It is too late to mock ${filename}; call this earlier.`);
}
assert.ok(
!(filename in require.cache),
`It is too late to mock ${filename}; call this earlier.`,
);
module_mocks.set(filename, obj);
return obj;
@ -199,11 +199,10 @@ exports._start_template_mocking = () => {
exports._finish_template_mocking = () => {
for (const filename of template_mocks.keys()) {
if (!used_templates.has(filename)) {
throw new Error(
`You called mock_template with ${filename} but we never saw it get used.`,
);
}
assert.ok(
used_templates.has(filename),
`You called mock_template with ${filename} but we never saw it get used.`,
);
}
template_mocks.clear();
used_templates.clear();
@ -222,9 +221,7 @@ exports._mock_template = (fn, exercise_template, f) => {
};
exports.mock_esm = (module_path, obj = {}) => {
if (typeof obj !== "object") {
throw new TypeError("An ES module must be mocked with an object");
}
assert.equal(typeof obj, "object", "An ES module must be mocked with an object");
return exports.mock_cjs(module_path, {...obj, __esModule: true});
};
@ -235,24 +232,19 @@ exports.unmock_module = (module_path) => {
false,
);
if (!module_mocks.has(filename)) {
throw new Error(`Cannot unmock ${filename}, which was not mocked`);
}
assert.ok(module_mocks.has(filename), `Cannot unmock ${filename}, which was not mocked`);
if (!used_module_mocks.has(filename)) {
throw new Error(`You asked to mock ${filename} but we never saw it during compilation.`);
}
assert.ok(
used_module_mocks.has(filename),
`You asked to mock ${filename} but we never saw it during compilation.`,
);
module_mocks.delete(filename);
used_module_mocks.delete(filename);
};
exports.set_global = function (name, val) {
if (val === null) {
throw new Error(`
We try to avoid using null in our codebase.
`);
}
assert.notEqual(val, null, `We try to avoid using null in our codebase.`);
if (!(name in old_globals)) {
if (!(name in global)) {
@ -265,14 +257,16 @@ exports.set_global = function (name, val) {
};
exports.zrequire = function (short_fn) {
if (short_fn === "templates") {
throw new Error(`
assert.notEqual(
short_fn,
"templates",
`
There is no need to zrequire templates.js.
The test runner automatically registers the
Handlebar extensions.
`);
}
`,
);
return require(`../../static/js/${short_fn}`);
};
@ -281,6 +275,7 @@ const staticPath = path.resolve(__dirname, "../../static") + path.sep;
exports.complain_about_unused_mocks = function () {
for (const filename of module_mocks.keys()) {
/* istanbul ignore if */
if (!used_module_mocks.has(filename)) {
console.error(`You asked to mock ${filename} but we never saw it during compilation.`);
}
@ -298,9 +293,7 @@ exports.finish = function () {
*/
jquery_function = undefined;
if (actual_load === undefined) {
throw new Error("namespace.finish was called without namespace.start.");
}
assert.notEqual(actual_load, undefined, "namespace.finish was called without namespace.start.");
Module._load = actual_load;
actual_load = undefined;
@ -321,11 +314,10 @@ exports.finish = function () {
};
exports.with_field = function (obj, field, val, f) {
if ("__esModule" in obj && "__Rewire__" in obj) {
throw new TypeError(
"Cannot mutate an ES module from outside. Consider exporting a test helper function from it instead.",
);
}
assert.ok(
!("__esModule" in obj && "__Rewire__" in obj),
"Cannot mutate an ES module from outside. Consider exporting a test helper function from it instead.",
);
const had_val = Object.hasOwn(obj, field);
const old_val = obj[field];
@ -350,9 +342,11 @@ exports.with_field_rewire = function (obj, field, val, f) {
// https://github.com/rosswarren/babel-plugin-rewire-ts/issues/15
const old_val = field in obj ? obj[field] : obj.__GetDependency__(field);
if (typeof old_val === "function") {
throw new TypeError("Please try to avoid mocking here, or use override_rewire.");
}
assert.notEqual(
typeof old_val,
"function",
"Please try to avoid mocking here, or use override_rewire.",
);
try {
obj.__Rewire__(field, val);
@ -369,14 +363,16 @@ exports.with_function_call_disallowed_rewire = function (obj, field, f) {
// https://github.com/rosswarren/babel-plugin-rewire-ts/issues/15
const old_val = field in obj ? obj[field] : obj.__GetDependency__(field);
if (typeof old_val !== "function") {
throw new TypeError(`Expected a function for ${field}`);
}
assert.equal(typeof old_val, "function", `Expected a function for ${field}`);
try {
obj.__Rewire__(field, () => {
throw new Error(`unexpected call to ${field}`);
});
obj.__Rewire__(
field,
/* istanbul ignore next */
() => {
throw new Error(`unexpected call to ${field}`);
},
);
return f();
} finally {
obj.__Rewire__(field, old_val);
@ -397,28 +393,29 @@ exports.with_overrides = function (test_function) {
// step. Generally our code calls `run_test`, which wraps
// `with_overrides`.
if ("__esModule" in obj && "__Rewire__" in obj) {
throw new TypeError(
"Cannot mutate an ES module from outside. Consider exporting a test helper function from it instead.",
);
}
assert.ok(
!("__esModule" in obj && "__Rewire__" in obj),
"Cannot mutate an ES module from outside. Consider exporting a test helper function from it instead.",
);
if (typeof f !== "function") {
throw new TypeError(
"You can only override with a function. Use with_field for non-functions.",
);
}
assert.equal(
typeof f,
"function",
"You can only override with a function. Use with_field for non-functions.",
);
if (typeof obj !== "object" && typeof obj !== "function") {
throw new TypeError(`We cannot override a function for ${typeof obj} objects`);
}
assert.ok(
typeof obj === "object" || typeof obj === "function",
`We cannot override a function for ${typeof obj} objects`,
);
if (obj[func_name] !== undefined && typeof obj[func_name] !== "function") {
throw new TypeError(`
assert.ok(
obj[func_name] === undefined || typeof obj[func_name] === "function",
`
You are overriding a non-function with a function.
This is almost certainly an error.
`);
}
`,
);
if (!unused_funcs.has(obj)) {
unused_funcs.set(obj, new Map());
@ -449,22 +446,24 @@ exports.with_overrides = function (test_function) {
// as exporting a helper function for tests from the module
// containing the function you need to mock.
if (typeof f !== "function") {
throw new TypeError(
"You can only override with a function. Use with_field for non-functions.",
);
}
assert.equal(
typeof f,
"function",
"You can only override with a function. Use with_field for non-functions.",
);
if (typeof obj !== "object" && typeof obj !== "function") {
throw new TypeError(`We cannot override a function for ${typeof obj} objects`);
}
assert.ok(
typeof obj === "object" || typeof obj === "function",
`We cannot override a function for ${typeof obj} objects`,
);
if (obj[func_name] !== undefined && typeof obj[func_name] !== "function") {
throw new TypeError(`
assert.ok(
obj[func_name] === undefined || typeof obj[func_name] === "function",
`
You are overriding a non-function with a function.
This is almost certainly an error.
`);
}
`,
);
if (!unused_funcs.has(obj)) {
unused_funcs.set(obj, new Map());
@ -497,6 +496,7 @@ exports.with_overrides = function (test_function) {
for (const module_unused_funcs of unused_funcs.values()) {
for (const unused_name of module_unused_funcs.keys()) {
/* istanbul ignore next */
throw new Error(unused_name + " never got invoked!");
}
}

View File

@ -19,6 +19,7 @@ exports.set_verbose = (value) => {
exports.run_test = (label, f, opts) => {
const {sloppy_$} = opts || {};
/* istanbul ignore if */
if (verbose) {
console.info(" test: " + label);
}
@ -34,7 +35,7 @@ exports.run_test = (label, f, opts) => {
f({override, override_rewire, mock_template: namespace._mock_template});
});
namespace._finish_template_mocking();
} catch (error) {
} catch (error) /* istanbul ignore next */ {
console.info("-".repeat(50));
console.info(`test failed: ${current_file_name} > ${label}`);
console.info();

View File

@ -1,5 +1,7 @@
"use strict";
const {strict: assert} = require("assert");
function make_zblueslip() {
const lib = {};
@ -15,6 +17,7 @@ function make_zblueslip() {
const names = Array.from(Object.keys(opts));
// For fatal messages, we should use assert.throws
/* istanbul ignore next */
lib.fatal = (msg) => {
throw new Error(msg);
};
@ -28,14 +31,13 @@ function make_zblueslip() {
lib.test_logs[name] = [];
}
lib.expect = (name, message, count = 1) => {
if (opts[name] === undefined) {
throw new Error("unexpected arg for expect: " + name);
}
if (count <= 0 && Number.isInteger(count)) {
throw new Error("expected count should be a positive integer");
}
const obj = {message, count, expected_count: count};
lib.expect = (name, message, expected_count = 1) => {
assert.notEqual(opts[name], undefined, `unexpected arg for expect: ${name}`);
assert.ok(
expected_count > 0 && Number.isInteger(expected_count),
"expected count should be a positive integer",
);
const obj = {message, count: 0, expected_count};
lib.test_data[name].push(obj);
};
@ -52,22 +54,16 @@ function make_zblueslip() {
}
continue;
}
lib.test_data[name][i].count -= 1;
lib.test_data[name][i].count += 1;
}
for (const obj of lib.test_data[name]) {
const message = obj.message;
if (obj.count > 0) {
throw new Error(
`We did not see expected ${obj.expected_count} of '${name}': ${message}`,
);
} else if (obj.count < 0) {
throw new Error(
`We saw ${obj.expected_count - obj.count} (expected ${
obj.expected_count
}) of '${name}': ${message}`,
);
}
assert.equal(
obj.count,
obj.expected_count,
`Expected ${obj.expected_count} of '${name}': ${message}`,
);
}
}
};
@ -95,6 +91,7 @@ function make_zblueslip() {
continue;
}
lib[name] = function (message, more_info, stack) {
/* istanbul ignore if */
if (typeof message !== "string") {
// We may catch exceptions in blueslip, and if
// so our stub should include that.
@ -121,6 +118,7 @@ function make_zblueslip() {
lib.measure_time = (label, f) => f();
/* istanbul ignore next */
lib.preview_node = (node) => "node:" + node;
return lib;

View File

@ -23,16 +23,15 @@ function verify_selector_for_zulip(selector) {
selector.includes(".") ||
(selector.includes("[") && selector.indexOf("]") >= selector.indexOf("["));
if (!is_valid) {
assert.ok(
is_valid,
// Check if selector has only english alphabets and space.
// Then, the user is probably trying to use a tag as a selector
// like $('div a').
if (/^[ A-Za-z]+$/.test(selector)) {
throw new Error("Selector too broad! Use id, class or attributes of target instead.");
} else {
throw new Error("Invalid selector: " + selector + " Use $.create() maybe?");
}
}
/^[ A-Za-z]+$/.test(selector)
? "Selector too broad! Use id, class or attributes of target instead."
: `Invalid selector: ${selector}. Use $.create() maybe?`,
);
}
function make_zjquery() {
@ -56,15 +55,16 @@ function make_zjquery() {
// Handle the special case of equality checks, which
// we can infer by assert.equal trying to access the
// "stack" key.
if (key === "stack") {
const error =
"\nInstead of doing equality checks on a full object, " +
'do `assert_equal($foo.selector, ".some_class")\n';
throw new Error(error);
}
assert.notEqual(
key,
"stack",
"\nInstead of doing equality checks on a full object, " +
'do `assert.equal($foo.selector, ".some_class")\n',
);
const val = target[key];
/* istanbul ignore if */
if (val === undefined && typeof key !== "symbol" && key !== "inspect") {
// For undefined values, we'll throw errors to devs saying
// they need to create stubs. We ignore certain keys that
@ -85,16 +85,17 @@ function make_zjquery() {
const zjquery = function (arg, arg2) {
if (typeof arg === "function") {
if (initialize_function) {
throw new Error(`
assert.ok(
!initialize_function,
`
We are trying to avoid the $(...) mechanism
for initializing modules in our codebase,
and the code that you are compiling/running
has tried to do this twice. Please either
clean up the real code or reduce the scope
of what you are testing in this test module.
`);
}
`,
);
initialize_function = arg;
return undefined;
}
@ -116,12 +117,15 @@ function make_zjquery() {
return arg.to_$();
}
if (arg2 !== undefined) {
throw new Error("We only use one-argument variations of $(...) in Zulip code.");
}
assert.equal(
arg2,
undefined,
"We only use one-argument variations of $(...) in Zulip code.",
);
const selector = arg;
/* istanbul ignore if */
if (typeof selector !== "string") {
console.info(arg);
throw new Error("zjquery does not know how to wrap this object yet");
@ -152,10 +156,7 @@ function make_zjquery() {
return $elem;
};
zjquery.trim = function (s) {
return s;
};
/* istanbul ignore next */
zjquery.state = function () {
// useful for debugging
let res = Array.from(elems.values(), ($v) => $v.debug());
@ -169,6 +170,7 @@ function make_zjquery() {
zjquery.Event = FakeEvent;
/* istanbul ignore next */
fn.popover = () => {
throw new Error(`
Do not try to test $.fn.popover code unless
@ -186,6 +188,7 @@ function make_zjquery() {
return true;
}
/* istanbul ignore next */
throw new Error(`
Please don't use node tests to test code
that extends $.fn unless you really know
@ -209,6 +212,7 @@ function make_zjquery() {
};
zjquery.validator = {
/* istanbul ignore next */
addMethod() {
throw new Error("You must create your own $.validator.addMethod stub.");
},
@ -229,6 +233,7 @@ const $ = new Proxy(make_zjquery(), {
return true;
}
/* istanbul ignore next */
throw new Error(`
Please don't modify $.${prop} if you are using zjquery.

View File

@ -48,6 +48,7 @@ function FakeElement(selector, opts) {
delay() {
return $self;
},
/* istanbul ignore next */
debug() {
return {
value,
@ -61,9 +62,6 @@ function FakeElement(selector, opts) {
}
return $self;
},
eq() {
return $self;
},
expectOne() {
// silently do nothing
return $self;
@ -80,6 +78,7 @@ function FakeElement(selector, opts) {
// if ($.find().length) { //success }
return [];
}
/* istanbul ignore next */
throw new Error(`
We need you to simulate the results of $(...).find(...)
by using set_find_results. You want something like this:
@ -100,9 +99,7 @@ function FakeElement(selector, opts) {
return classes.has(class_name);
},
height() {
if (height === undefined) {
throw new Error(`Please call $("${selector}").set_height`);
}
assert.notEqual(height, undefined, `Please call $("${selector}").set_height`);
return height;
},
hide() {
@ -117,13 +114,15 @@ function FakeElement(selector, opts) {
return html;
},
is(arg) {
if (arg === ":visible") {
return shown;
switch (arg) {
case ":visible":
return shown;
case ":focus":
return $self.is_focused();
/* istanbul ignore next */
default:
throw new Error("zjquery does not support this is() call");
}
if (arg === ":focus") {
return $self.is_focused();
}
return $self;
},
is_focused() {
// is_focused is not a jQuery thing; this is
@ -144,6 +143,7 @@ function FakeElement(selector, opts) {
event_store.on(...args);
return $self;
},
/* istanbul ignore next */
one(...args) {
event_store.one(...args);
return $self;
@ -181,6 +181,7 @@ function FakeElement(selector, opts) {
}
return $self;
},
/* istanbul ignore next */
remove() {
throw new Error(`
We don't support remove in zjquery.
@ -192,21 +193,12 @@ function FakeElement(selector, opts) {
`);
},
removeData: noop,
replaceWith() {
return $self;
},
scrollTop() {
return $self;
},
serializeArray() {
return $self;
},
set_find_results(find_selector, $jquery_object) {
if ($jquery_object === undefined) {
throw new Error(
"Please make the 'find result' be something like $.create('unused')",
);
}
assert.notEqual(
$jquery_object,
undefined,
"Please make the 'find result' be something like $.create('unused')",
);
find_results.set(find_selector, $jquery_object);
},
set_height(fake_height) {
@ -222,9 +214,6 @@ function FakeElement(selector, opts) {
shown = true;
return $self;
},
slice() {
return $self;
},
stop() {
return $self;
},
@ -242,9 +231,6 @@ function FakeElement(selector, opts) {
shown = show;
return $self;
},
tooltip() {
return $self;
},
trigger(ev) {
event_store.trigger($self, ev);
return $self;
@ -314,9 +300,7 @@ function make_event_store(selector) {
if (child_selector === undefined) {
handler = on_functions.get(name);
if (!handler) {
throw new Error("no " + name + " handler for " + selector);
}
assert.ok(handler, `no ${name} handler for ${selector}`);
return handler;
}
@ -325,9 +309,7 @@ function make_event_store(selector) {
handler = child_on.get(name);
}
if (!handler) {
throw new Error("no " + name + " handler for " + selector + " " + child_selector);
}
assert.ok(handler, `no ${name} handler for ${selector} ${child_selector}`);
return handler;
},
@ -342,6 +324,7 @@ function make_event_store(selector) {
// .off in code that we test: $(...).off('click', child_sel);
//
// So we don't support this for now.
/* istanbul ignore next */
throw new Error("zjquery does not support this call sequence");
},
@ -351,6 +334,7 @@ function make_event_store(selector) {
// (event_name, sel, handler)
if (args.length === 1) {
const [handler] = args;
/* istanbul ignore if */
if (on_functions.has(event_name)) {
console.info("\nEither the app or the test can be at fault here..");
console.info("(sometimes you just want to call $.clear_all_elements();)\n");
@ -361,9 +345,7 @@ function make_event_store(selector) {
return;
}
if (args.length !== 2) {
throw new Error("wrong number of arguments passed in");
}
assert.equal(args.length, 2, "wrong number of arguments passed in");
const [sel, handler] = args;
assert.equal(typeof sel, "string", "String selectors expected here.");
@ -375,13 +357,15 @@ function make_event_store(selector) {
const child_on = child_on_functions.get(sel);
if (child_on.has(event_name)) {
throw new Error("dup " + event_name + " handler for " + selector + " " + sel);
}
assert.ok(
!child_on.has(event_name),
`dup ${event_name} handler for ${selector} ${sel}`,
);
child_on.set(event_name, handler);
},
/* istanbul ignore next */
one(event_name, handler) {
self.on(event_name, function (ev) {
self.off(event_name);

View File

@ -2,9 +2,6 @@
class FakeEvent {
constructor(type, props) {
if (!(this instanceof FakeEvent)) {
return new FakeEvent(type, props);
}
this.type = type;
Object.assign(this, props);
}

View File

@ -44,6 +44,8 @@ def make_set(files: List[str]) -> Set[str]:
# We do not yet require 100% line coverage for these files:
EXEMPT_FILES = make_set(
[
"frontend_tests/node_tests/event_status.js",
"frontend_tests/zjsunit/mdiff.js",
"static/js/about_zulip.js",
"static/js/add_subscribers_pill.js",
"static/js/admin.js",
@ -372,14 +374,16 @@ def read_coverage() -> Any:
def enforce_proper_coverage(coverage_json: Any) -> bool:
all_js_files = set(
glob.glob("static/js/*.js")
+ glob.glob("static/js/*.ts")
+ glob.glob("static/shared/js/*.js")
+ glob.glob("static/shared/js/*.ts")
+ glob.glob("static/js/billing/*.js"),
)
enforce_fully_covered = all_js_files - EXEMPT_FILES
all_js_files = {
*glob.glob("frontend_tests/node_tests/*.js"),
*glob.glob("frontend_tests/zjsunit/*.js"),
*glob.glob("static/js/*.js"),
*glob.glob("static/js/*.ts"),
*glob.glob("static/shared/js/*.js"),
*glob.glob("static/shared/js/*.ts"),
*glob.glob("static/js/billing/*.js"),
}
enforce_fully_covered = sorted(all_js_files - EXEMPT_FILES)
coverage_lost = False
for relative_path in enforce_fully_covered: