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; let rendered_fred;
mock_template("user_presence_row.hbs", false, (data) => { mock_template("user_presence_row.hbs", false, (data) => {
if (data.user_id === alice.user_id) { switch (data.user_id) {
rendered_alice = true; case alice.user_id:
assert.deepEqual(data, { rendered_alice = true;
faded: true, assert.deepEqual(data, {
href: "#narrow/pm-with/1-alice", faded: true,
is_current_user: false, href: "#narrow/pm-with/1-alice",
my_user_status: undefined, is_current_user: false,
name: "Alice Smith", my_user_status: undefined,
num_unread: 0, name: "Alice Smith",
user_circle_class: "user_circle_green", num_unread: 0,
user_circle_status: "translated: Active", user_circle_class: "user_circle_green",
user_id: alice.user_id, user_circle_status: "translated: Active",
status_emoji_info: undefined, user_id: alice.user_id,
}); status_emoji_info: undefined,
} else if (data.user_id === fred.user_id) { });
rendered_fred = true; break;
assert.deepEqual(data, { case fred.user_id:
href: "#narrow/pm-with/2-fred", rendered_fred = true;
name: "Fred Flintstone", assert.deepEqual(data, {
user_id: fred.user_id, href: "#narrow/pm-with/2-fred",
my_user_status: undefined, name: "Fred Flintstone",
is_current_user: false, user_id: fred.user_id,
num_unread: 0, my_user_status: undefined,
user_circle_class: "user_circle_green", is_current_user: false,
user_circle_status: "translated: Active", num_unread: 0,
faded: false, user_circle_class: "user_circle_green",
status_emoji_info: undefined, user_circle_status: "translated: Active",
}); faded: false,
} else { status_emoji_info: undefined,
throw new Error(`we did not expect to have to render a row for ${data.name}`); });
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", () => { test("redraw_muted_user", () => {
muted_users.add_muted_user(mark.user_id); 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); 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}) => { 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); assert.ok(confirm_license_modal_shown);
override(helpers, "is_valid_input", () => false); override(helpers, "is_valid_input", () => false);
let prevent_default_called = false;
const event = { const event = {
prevent_default: () => { preventDefault: /* istanbul ignore next */ () => {
prevent_default_called = true; throw new Error("unexpected preventDefault call");
}, },
}; };
update_licenses_button_click_handler(event); update_licenses_button_click_handler(event);
assert.ok(!prevent_default_called);
const update_next_renewal_licenses_button_click_handler = $( const update_next_renewal_licenses_button_click_handler = $(
"#update-licenses-at-next-renewal-button", "#update-licenses-at-next-renewal-button",

View File

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

View File

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

View File

@ -145,10 +145,6 @@ test_ui("send_message", ({override, override_rewire}) => {
return stub_state; return stub_state;
} }
set_global("setTimeout", (func) => {
func();
});
override(server_events, "assert_get_events_running", () => { override(server_events, "assert_get_events_running", () => {
stub_state.get_events_running_called += 1; stub_state.get_events_running_called += 1;
}); });
@ -635,13 +631,15 @@ test_ui("on_events", ({override, override_rewire}) => {
); );
helper.$container.data = (field) => { helper.$container.data = (field) => {
if (field === "user-id") { switch (field) {
return "34"; 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); helper.$target.prop("disabled", false);
@ -737,9 +735,6 @@ test_ui("on_events", ({override, override_rewire}) => {
(function test_attach_files_compose_clicked() { (function test_attach_files_compose_clicked() {
const handler = $("#compose").get_on_handler("click", ".compose_upload_file"); const handler = $("#compose").get_on_handler("click", ".compose_upload_file");
$("#compose .file_input").clone = (param) => {
assert.ok(param);
};
let compose_file_input_clicked = false; let compose_file_input_clicked = false;
$("#compose .file_input").on("click", () => { $("#compose .file_input").on("click", () => {
compose_file_input_clicked = true; compose_file_input_clicked = true;

View File

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

View File

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

View File

@ -71,6 +71,7 @@ function make_textbox(s) {
}; };
$widget.val = function (new_val) { $widget.val = function (new_val) {
/* istanbul ignore if */
if (new_val) { if (new_val) {
$widget.s = new_val; $widget.s = new_val;
return this; return this;
@ -301,6 +302,7 @@ run_test("quote_and_reply", ({override, override_rewire}) => {
textarea_caret_pos = arg; textarea_caret_pos = arg;
return this; return this;
} }
/* istanbul ignore if */
if (typeof arg !== "string") { if (typeof arg !== "string") {
console.info(arg); console.info(arg);
throw new Error("We expected the actual code to pass in a string."); 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(); add_content_to_compose_box();
let zephyr_checked = false; let zephyr_checked = false;
$("#zephyr-mirror-error").is = () => { $("#zephyr-mirror-error").is = (arg) => {
if (!zephyr_checked) { assert.equal(arg, ":visible");
zephyr_checked = true; zephyr_checked = true;
return true; return true;
}
return false;
}; };
assert.ok(!compose_validate.validate()); assert.ok(!compose_validate.validate());
assert.ok(zephyr_checked); assert.ok(zephyr_checked);
@ -740,14 +738,17 @@ test_ui("warn_if_mentioning_unsubscribed_user", ({override, override_rewire, moc
let looked_for_existing; let looked_for_existing;
$warning_row.data = (field) => { $warning_row.data = (field) => {
if (field === "user-id") { switch (field) {
looked_for_existing = true; case "user-id":
return "34"; 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"); const $previous_users = $("#compose_invite_users .compose_invite_user");

View File

@ -32,6 +32,7 @@ const compose = zrequire("compose");
function stub_out_video_calls() { function stub_out_video_calls() {
const $elem = $("#below-compose-content .video_link"); const $elem = $("#below-compose-content .video_link");
$elem.toggle = (show) => { $elem.toggle = (show) => {
/* istanbul ignore if */
if (show) { if (show) {
$elem.show(); $elem.show();
} else { } else {
@ -77,8 +78,6 @@ test("videos", ({override, override_rewire}) => {
compose.initialize(); compose.initialize();
(function test_no_provider_video_link_compose_clicked() { (function test_no_provider_video_link_compose_clicked() {
let called = false;
const $textarea = $.create("target-stub"); const $textarea = $.create("target-stub");
$textarea.set_parents_result(".message_edit_form", []); $textarea.set_parents_result(".message_edit_form", []);
@ -90,15 +89,19 @@ test("videos", ({override, override_rewire}) => {
}, },
}; };
override_rewire(compose_ui, "insert_syntax_and_focus", () => { override_rewire(
called = true; 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"); const handler = $("body").get_on_handler("click", ".video_link");
$("#compose-textarea").val(""); $("#compose-textarea").val("");
handler(ev); handler(ev);
assert.ok(!called);
})(); })();
(function test_jitsi_video_link_compose_clicked() { (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 settings_config = zrequire("settings_config");
const pygments_data = zrequire("../generated/pygments_data.json"); 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; const ct = composebox_typeahead;
// Use a slightly larger value than what's user-facing // Use a slightly larger value than what's user-facing
@ -143,19 +140,10 @@ const emojis_by_name = new Map(
headphones: emoji_headphones, headphones: emoji_headphones,
}), }),
); );
const emoji_list = Array.from(emojis_by_name.values(), (emoji_dict) => { const emoji_list = Array.from(emojis_by_name.values(), (emoji_dict) => ({
if (emoji_dict.is_realm_emoji === true) { emoji_name: emoji_dict.name,
return { emoji_code: emoji_dict.emoji_code,
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 me_slash = { const me_slash = {
name: "me", name: "me",
@ -1070,14 +1058,8 @@ test("initialize", ({override, override_rewire, mock_template}) => {
stopPropagation: noop, stopPropagation: noop,
}; };
$("#stream_message_recipient_topic").data = () => ({typeahead: {shown: true}});
$("form#send_message_form").trigger(event); $("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); $("form#send_message_form").trigger(event);
event.key = "Tab"; event.key = "Tab";
@ -1144,7 +1126,6 @@ test("initialize", ({override, override_rewire, mock_template}) => {
preventDefault: noop, preventDefault: noop,
}; };
// We trigger keydown in order to make nextFocus !== false // We trigger keydown in order to make nextFocus !== false
$("#stream_message_recipient_topic").data = () => ({typeahead: {shown: true}});
$("form#send_message_form").trigger(event); $("form#send_message_form").trigger(event);
$("#stream_message_recipient_topic").off("mouseup"); $("#stream_message_recipient_topic").off("mouseup");
event.type = "keyup"; event.type = "keyup";

View File

@ -78,7 +78,7 @@ run_test("no_default_value", () => {
widget_name: "my_setting", widget_name: "my_setting",
data: ["one", "two", "three"].map((x) => ({name: x, value: x})), data: ["one", "two", "three"].map((x) => ({name: x, value: x})),
default_text: $t({defaultMessage: "not set"}), default_text: $t({defaultMessage: "not set"}),
render_text: (text) => `rendered: ${text}`, render_text: /* istanbul ignore next */ (text) => `rendered: ${text}`,
null_value: "null-value", 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. // Let's say you have to test the following code.
const app = { const app = {
/* istanbul ignore next */
notify_server_of_deposit(deposit_amount) { notify_server_of_deposit(deposit_amount) {
// simulate difficulty // simulate difficulty
throw new Error(`We cannot report this value without wifi: ${deposit_amount}`); throw new Error(`We cannot report this value without wifi: ${deposit_amount}`);
}, },
/* istanbul ignore next */
pop_up_fancy_confirmation_screen(deposit_amount, label) { pop_up_fancy_confirmation_screen(deposit_amount, label) {
// simulate difficulty // simulate difficulty
throw new Error(`We cannot make a ${label} dialog for amount ${deposit_amount}`); 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. // We don't want recent topics to process message for this test.
override_rewire(recent_topics_util, "is_visible", () => false); 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 // Make our test message appear to be unread, so that
// we then need to subsequently process them as read. // we then need to subsequently process them as read.

View File

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

View File

@ -644,7 +644,7 @@ run_test("appendValue/clear", ({mock_template}) => {
const config = { const config = {
$container, $container,
create_item_from_text: (s) => ({type: "color", display_value: s}), 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 = () => {}; $pill_input.before = () => {};

View File

@ -11,7 +11,7 @@ run_test("test_early_returns", () => {
const opts = { const opts = {
$elem: $stub, $elem: $stub,
handlers: { handlers: {
ArrowLeft: () => { ArrowLeft: /* istanbul ignore next */ () => {
throw new Error("do not dispatch this with alt key"); 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}) => { run_test("misc errors", ({override}) => {
const conf = basic_conf({ const conf = basic_conf({
first_key: () => undefined, first_key: () => undefined,
prev_key: () => undefined, prev_key: /* istanbul ignore next */ () => undefined,
next_key: () => undefined, next_key: /* istanbul ignore next */ () => undefined,
}); });
const cursor = new ListCursor(conf); const cursor = new ListCursor(conf);
@ -64,7 +64,7 @@ run_test("single item list", ({override}) => {
const valid_key = "42"; const valid_key = "42";
const conf = basic_conf({ const conf = basic_conf({
first_key: () => valid_key, first_key: /* istanbul ignore next */ () => valid_key,
next_key: () => undefined, next_key: () => undefined,
prev_key: () => undefined, prev_key: () => undefined,
}); });
@ -91,7 +91,7 @@ run_test("single item list", ({override}) => {
run_test("multiple item list", ({override}) => { run_test("multiple item list", ({override}) => {
const conf = basic_conf({ const conf = basic_conf({
first_key: () => 1, first_key: /* istanbul ignore next */ () => 1,
next_key: (key) => (key < 3 ? key + 1 : undefined), next_key: (key) => (key < 3 ? key + 1 : undefined),
prev_key: (key) => (key > 1 ? 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() { function make_container() {
const $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 // Make our append function just set a field we can
// check in our tests. // check in our tests.
$container.append = ($data) => { $container.append = ($data) => {
@ -123,6 +116,7 @@ function make_search_input() {
// Allow ourselves to be wrapped by $(...) and // Allow ourselves to be wrapped by $(...) and
// return ourselves. // return ourselves.
/* istanbul ignore next */
$element.to_jquery = () => $element; $element.to_jquery = () => $element;
$element.on = (event_name, f) => { $element.on = (event_name, f) => {
@ -322,6 +316,7 @@ function sort_button(opts) {
return opts.sort_type; return opts.sort_type;
case "sort-prop": case "sort-prop":
return opts.prop_name; return opts.prop_name;
/* istanbul ignore next */
default: default:
throw new Error("unknown selector: " + sel); throw new Error("unknown selector: " + sel);
} }
@ -549,7 +544,7 @@ run_test("clear_event_handlers", () => {
modifier: () => {}, modifier: () => {},
filter: { filter: {
$element: $filter_element, $element: $filter_element,
predicate: () => true, predicate: /* istanbul ignore next */ () => true,
}, },
$simplebar_container: $scroll_container, $simplebar_container: $scroll_container,
}; };
@ -602,8 +597,8 @@ run_test("errors", () => {
blueslip.expect("error", "Filterer and predicate are mutually exclusive."); blueslip.expect("error", "Filterer and predicate are mutually exclusive.");
ListWidget.create($container, list, { ListWidget.create($container, list, {
filter: { filter: {
filterer: () => true, filterer: /* istanbul ignore next */ () => true,
predicate: () => true, predicate: /* istanbul ignore next */ () => true,
}, },
$simplebar_container: $scroll_container, $simplebar_container: $scroll_container,
}); });
@ -795,7 +790,8 @@ run_test("render item", () => {
blueslip.expect("error", "html_selector should be a function."); blueslip.expect("error", "html_selector should be a function.");
ListWidget.create($container, list, { ListWidget.create($container, list, {
name: "replace-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, get_item,
html_selector: "hello world", html_selector: "hello world",
$simplebar_container: $scroll_container, $simplebar_container: $scroll_container,
@ -855,6 +851,7 @@ run_test("Multiselect dropdown retain_selected_items", () => {
if (element) { if (element) {
return true; return true;
} }
/* istanbul ignore next */
return false; return false;
} }

View File

@ -27,11 +27,6 @@ const example_realm_linkifiers = [
]; ];
user_settings.translate_emoticons = false; user_settings.translate_emoticons = false;
function Image() {
return {};
}
set_global("Image", Image);
set_global("document", {compatMode: "CSS1Compat"}); set_global("document", {compatMode: "CSS1Compat"});
const emoji = zrequire("emoji"); const emoji = zrequire("emoji");
@ -244,6 +239,7 @@ test("marked_shared", () => {
for (const test of tests) { for (const test of tests) {
// Ignore tests if specified // Ignore tests if specified
/* istanbul ignore if */
if (test.ignore === true) { if (test.ignore === true) {
continue; 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) { 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(); 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 // There's a separate call with anchor="newest" that happens
// unconditionally; do basic verification of that call. // unconditionally; do basic verification of that call.
if (opts.data.anchor === "newest") { if (opts.data.anchor === "newest") {
if (!called_with_newest_flag) { assert.ok(!called_with_newest_flag, "Only one 'newest' call allowed");
called_with_newest_flag = true; called_with_newest_flag = true;
assert.equal(opts.data.num_after, 0); assert.equal(opts.data.num_after, 0);
return; return;
}
throw new Error("Only one 'newest' call allowed");
} }
if (called && !conf.can_call_again) { assert.ok(!called || conf.can_call_again, "only use this for one call");
throw new Error("only use this for one call");
}
if (!conf.can_call_again) { if (!conf.can_call_again) {
assert.equal(self.success, undefined); assert.equal(self.success, undefined);
} }

View File

@ -2,19 +2,10 @@
const {strict: assert} = require("assert"); const {strict: assert} = require("assert");
const { const {with_function_call_disallowed_rewire, zrequire} = require("../zjsunit/namespace");
set_global,
with_function_call_disallowed_rewire,
zrequire,
} = require("../zjsunit/namespace");
const {run_test} = require("../zjsunit/test"); const {run_test} = require("../zjsunit/test");
const blueslip = require("../zjsunit/zblueslip"); const blueslip = require("../zjsunit/zblueslip");
set_global("setTimeout", (f, delay) => {
assert.equal(delay, 0);
return f();
});
const muted_topics = zrequire("muted_topics"); const muted_topics = zrequire("muted_topics");
const muted_users = zrequire("muted_users"); const muted_users = zrequire("muted_users");
const {MessageListData} = zrequire("../js/message_list_data"); 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 {mock_esm, set_global, zrequire} = require("../zjsunit/namespace");
const {run_test} = require("../zjsunit/test"); const {run_test} = require("../zjsunit/test");
const {user_settings} = require("../zjsunit/zpage_params");
set_global("document", "document-stub"); set_global("document", "document-stub");
const noop = () => {}; const noop = () => {};
user_settings.twenty_four_hour_time = false;
mock_esm("../../static/js/message_lists", {home: "stub"}); mock_esm("../../static/js/message_lists", {home: "stub"});
// timerender calls setInterval when imported // timerender calls setInterval when imported
@ -25,9 +22,6 @@ mock_esm("../../static/js/timerender", {
return [{outerHTML: String(time1.getTime()) + " - " + String(time2.getTime())}]; return [{outerHTML: String(time1.getTime()) + " - " + String(time2.getTime())}];
}, },
stringify_time(time) { stringify_time(time) {
if (user_settings.twenty_four_hour_time) {
return time.toString("HH:mm");
}
return time.toString("h:mm TT"); return time.toString("h:mm TT");
}, },
}); });

View File

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

View File

@ -26,7 +26,6 @@ const alice = {
people.init(); people.init();
people.add_active_user(alice); people.add_active_user(alice);
people.is_my_user_id = () => false;
function set_filter(terms) { function set_filter(terms) {
const filter = new 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); assert.equal(navbar_alerts.should_show_notifications(ls), false);
// Avoid showing if notification is already granted. // Avoid showing if notification is already granted.
/* istanbul ignore next */
notifications.permission_state = () => "granted"; notifications.permission_state = () => "granted";
notifications.granted_desktop_notifications_permission = () => "granted"; notifications.granted_desktop_notifications_permission = () => "granted";
assert.equal(navbar_alerts.should_show_notifications(ls), false); assert.equal(navbar_alerts.should_show_notifications(ls), false);
// Don't ask for permission to spectator. // Don't ask for permission to spectator.
/* istanbul ignore next */
util.is_mobile = () => false; util.is_mobile = () => false;
/* istanbul ignore next */
notifications.granted_desktop_notifications_permission = () => false; notifications.granted_desktop_notifications_permission = () => false;
/* istanbul ignore next */
notifications.permission_state = () => "granted"; notifications.permission_state = () => "granted";
page_params.is_spectator = true; page_params.is_spectator = true;
assert.equal(navbar_alerts.should_show_notifications(ls), false); assert.equal(navbar_alerts.should_show_notifications(ls), false);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -60,15 +60,16 @@ run_test("settings", ({override_rewire}) => {
let topic_data_called = 0; let topic_data_called = 0;
$topic_tr_html.attr = (opts) => { $topic_tr_html.attr = (opts) => {
if (opts === "data-stream-id") { topic_data_called += 1;
topic_data_called += 1; switch (opts) {
return frontend.stream_id; 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; let unmute_topic_called = false;

View File

@ -51,11 +51,9 @@ run_test("settings", ({override_rewire}) => {
let row_attribute_fetched = false; let row_attribute_fetched = false;
$fake_row.attr = (opts) => { $fake_row.attr = (opts) => {
if (opts === "data-user-id") { assert.equal(opts, "data-user-id");
row_attribute_fetched += 1; row_attribute_fetched += 1;
return "5"; return "5";
}
throw new Error(`Unknown attribute ${opts}`);
}; };
let unmute_user_called = false; 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 stream_settings_data = zrequire("stream_settings_data");
const settings_account = zrequire("settings_account"); const settings_account = zrequire("settings_account");
const settings_org = zrequire("settings_org"); const settings_org = zrequire("settings_org");
const sub_store = zrequire("sub_store");
const dropdown_list_widget = zrequire("dropdown_list_widget"); const dropdown_list_widget = zrequire("dropdown_list_widget");
function test(label, f) { function test(label, f) {
@ -195,7 +194,6 @@ function test_submit_settings_form(override, submit_form) {
let stubs = createSaveButtons(subsection); let stubs = createSaveButtons(subsection);
let $save_button = stubs.$save_button; let $save_button = stubs.$save_button;
$save_button.attr("id", `org-submit-${subsection}`); $save_button.attr("id", `org-submit-${subsection}`);
$save_button.replace = () => `${subsection}`;
$("#id_realm_waiting_period_threshold").val(10); $("#id_realm_waiting_period_threshold").val(10);
@ -241,6 +239,7 @@ function test_submit_settings_form(override, submit_form) {
$add_custom_emoji_policy_elem, $add_custom_emoji_policy_elem,
$create_public_stream_policy_elem, $create_public_stream_policy_elem,
$create_private_stream_policy_elem, $create_private_stream_policy_elem,
$invite_to_realm_policy_elem,
$invite_to_stream_policy_elem, $invite_to_stream_policy_elem,
]); ]);
@ -250,6 +249,7 @@ function test_submit_settings_form(override, submit_form) {
let expected_value = { let expected_value = {
bot_creation_policy: 1, bot_creation_policy: 1,
invite_to_realm_policy: 2,
invite_to_stream_policy: 1, invite_to_stream_policy: 1,
email_address_visibility: 1, email_address_visibility: 1,
add_custom_emoji_policy: 1, add_custom_emoji_policy: 1,
@ -925,10 +925,6 @@ test("misc", ({override_rewire}) => {
let setting_name = "realm_notifications_stream_id"; let setting_name = "realm_notifications_stream_id";
let $elem = $(`#${CSS.escape(setting_name)}_widget #${CSS.escape(setting_name)}_name`); let $elem = $(`#${CSS.escape(setting_name)}_widget #${CSS.escape(setting_name)}_name`);
$elem.closest = () => $stub_notification_disable_parent; $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); settings_org.notifications_stream_widget.render(42);
assert.equal($elem.text(), "#some_stream"); assert.equal($elem.text(), "#some_stream");
assert.ok(!$elem.hasClass("text-warning")); assert.ok(!$elem.hasClass("text-warning"));
@ -940,10 +936,6 @@ test("misc", ({override_rewire}) => {
setting_name = "realm_signup_notifications_stream_id"; setting_name = "realm_signup_notifications_stream_id";
$elem = $(`#${CSS.escape(setting_name)}_widget #${CSS.escape(setting_name)}_name`); $elem = $(`#${CSS.escape(setting_name)}_widget #${CSS.escape(setting_name)}_name`);
$elem.closest = () => $stub_notification_disable_parent; $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); settings_org.signup_notifications_stream_widget.render(75);
assert.equal($elem.text(), "#some_stream"); assert.equal($elem.text(), "#some_stream");
assert.ok(!$elem.hasClass("text-warning")); 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]; user_groups.get_realm_user_groups = () => [realm_user_group];
people.get_visible_email = () => bob.email;
let templates_render_called = false; let templates_render_called = false;
const $fake_rendered_temp = $.create("fake_admin_user_group_list_template_rendered"); const $fake_rendered_temp = $.create("fake_admin_user_group_list_template_rendered");
mock_template("settings/admin_user_group_list.hbs", false, (args) => { 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) { if (user_id === iago.user_id) {
return iago; return iago;
} }
if (user_id === alice.user_id) {
return alice;
}
if (user_id === undefined) {
return noop;
}
assert.equal(user_id, 4); assert.equal(user_id, 4);
blueslip.expect("warn", "Undefined user in function append_user"); blueslip.expect("warn", "Undefined user in function append_user");
get_by_user_id_called = true; get_by_user_id_called = true;
@ -246,9 +238,6 @@ test_ui("populate_user_groups", ({override_rewire, mock_template}) => {
saved_fade_out_called = true; saved_fade_out_called = true;
}; };
$(cancel_selector).css = (data) => { $(cancel_selector).css = (data) => {
if (typeof data === "string") {
assert.equal(data, "display");
}
assert.equal(typeof data, "object"); assert.equal(typeof data, "object");
assert.equal(data.display, "inline-block"); assert.equal(data.display, "inline-block");
assert.equal(data.opacity, "0"); assert.equal(data.opacity, "0");
@ -258,9 +247,6 @@ test_ui("populate_user_groups", ({override_rewire, mock_template}) => {
cancel_fade_to_called = true; cancel_fade_to_called = true;
}; };
$(instructions_selector).css = (data) => { $(instructions_selector).css = (data) => {
if (typeof data === "string") {
assert.equal(data, "display");
}
assert.equal(typeof data, "object"); assert.equal(typeof data, "object");
assert.equal(data.display, "block"); assert.equal(data.display, "block");
assert.equal(data.opacity, "0"); assert.equal(data.opacity, "0");
@ -284,17 +270,15 @@ test_ui("populate_user_groups", ({override_rewire, mock_template}) => {
let get_by_email_called = false; let get_by_email_called = false;
people.get_by_email = (user_email) => { people.get_by_email = (user_email) => {
get_by_email_called = true; get_by_email_called = true;
if (user_email === iago.email) { switch (user_email) {
return iago; 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) { 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]; user_groups.get_realm_user_groups = () => [realm_user_group];
// We return noop because these are already tested, so we skip them // We return [] because these are already tested, so we skip them
people.get_realm_users = () => noop; /* istanbul ignore next */
people.get_realm_users = () => [];
mock_template( mock_template(
"settings/admin_user_group_list.hbs", "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", () => "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; let can_edit_called = 0;
override_rewire(settings_user_groups, "can_edit", () => { 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 $description_field_stub = $.create("fake-description-field");
const $input_stub = $.create("fake-input"); const $input_stub = $.create("fake-input");
$user_group_stub.find = (elem) => { $user_group_stub.find = (elem) => {
if (elem === ".name") { user_group_find_called += 1;
user_group_find_called += 1; switch (elem) {
return $name_field_stub; 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_container_stub = $(`.pill-container[data-group-pills="${CSS.escape(1)}"]`);
const $pill_stub = $.create("fake-pill"); const $pill_stub = $.create("fake-pill");
let pill_container_find_called = 0; let pill_container_find_called = 0;
$pill_container_stub.find = (elem) => { $pill_container_stub.find = (elem) => {
if (elem === ".input") { pill_container_find_called += 1;
pill_container_find_called += 1; switch (elem) {
return $input_stub; 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) => { $input_stub.css = (property, val) => {
@ -437,10 +424,10 @@ test_ui("with_external_user", ({override_rewire, mock_template}) => {
assert.equal(value, "0.5"); assert.equal(value, "0.5");
}; };
// We return noop because these are already tested, so we skip them // We return [] because these are already tested, so we skip them
$pill_container_stub.children = () => noop; $pill_container_stub.children = () => [];
$("#user-groups").append = () => noop; $("#user-groups").append = noop;
reset_test_setup($pill_container_stub); reset_test_setup($pill_container_stub);
@ -621,6 +608,7 @@ test_ui("on_events", ({override_rewire, mock_template}) => {
(function test_do_not_blur() { (function test_do_not_blur() {
const blur_event_classes = [".name", ".description", ".input"]; const blur_event_classes = [".name", ".description", ".input"];
let api_endpoint_called = false; let api_endpoint_called = false;
/* istanbul ignore next */
channel.post = () => { channel.post = () => {
api_endpoint_called = true; api_endpoint_called = true;
}; };
@ -658,10 +646,8 @@ test_ui("on_events", ({override_rewire, mock_template}) => {
api_endpoint_called = false; api_endpoint_called = false;
$fake_this.closest = (class_name) => { $fake_this.closest = (class_name) => {
if (class_name === ".typeahead") { assert.equal(class_name, ".typeahead");
return [1]; return [1];
}
return [];
}; };
handler.call($fake_this, event); handler.call($fake_this, event);
assert.ok(!api_endpoint_called); assert.ok(!api_endpoint_called);
@ -755,9 +741,6 @@ test_ui("on_events", ({override_rewire, mock_template}) => {
cancel_fade_out_called = true; cancel_fade_out_called = true;
}; };
$(saved_selector).css = (data) => { $(saved_selector).css = (data) => {
if (typeof data === "string") {
assert.equal(data, "display");
}
assert.equal(typeof data, "object"); assert.equal(typeof data, "object");
assert.equal(data.display, "inline-block"); assert.equal(data.display, "inline-block");
assert.equal(data.opacity, "0"); assert.equal(data.opacity, "0");

View File

@ -10,7 +10,6 @@ const denmark_stream_id = 101;
const ui = mock_esm("../../static/js/ui", { const ui = mock_esm("../../static/js/ui", {
get_content_element: ($element) => $element, get_content_element: ($element) => $element,
get_scroll_element: ($element) => $element,
}); });
mock_esm("../../static/js/hash_util", { 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); max_message_id = stream_topic_history.get_max_message_id(stream_id);
assert.deepEqual(max_message_id, 103); 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. // Removing first topic1 message has no effect.
stream_topic_history.remove_messages({ stream_topic_history.remove_messages({
stream_id, stream_id,
@ -163,8 +163,6 @@ test("server_history", () => {
const stream_id = sub.stream_id; const stream_id = sub.stream_id;
stream_data.add_sub(sub); 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); assert.equal(stream_topic_history.is_complete_for_stream_id(stream_id), false);
stream_topic_history.add_message({ stream_topic_history.add_message({
@ -332,6 +330,7 @@ test("server_history_end_to_end", () => {
// Try getting server history for a second time. // Try getting server history for a second time.
/* istanbul ignore next */
channel.get = () => { channel.get = () => {
throw new Error("We should not get more data."); 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", () => { run_test("transmit_message_ajax_reload_pending", () => {
/* istanbul ignore next */
const success = () => { const success = () => {
throw new Error("unexpected success"); throw new Error("unexpected success");
}; };
/* istanbul ignore next */
const error = () => {
throw new Error("unexpected error");
};
reload_state.is_pending = () => true; reload_state.is_pending = () => true;
@ -80,13 +85,6 @@ run_test("transmit_message_ajax_reload_pending", () => {
const request = {foo: "bar"}; 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) => { channel.post = (opts) => {
assert.equal(opts.url, "/json/messages"); assert.equal(opts.url, "/json/messages");
assert.equal(opts.data.foo, "bar"); assert.equal(opts.data.foo, "bar");
@ -94,7 +92,6 @@ run_test("transmit_message_ajax_reload_pending", () => {
opts.error(xhr, "bad request"); opts.error(xhr, "bad request");
}; };
transmit.send_message(request, success, error); transmit.send_message(request, success, error);
assert.ok(!error_func_called);
assert.ok(reload_initiated); assert.ok(reload_initiated);
}); });
@ -143,8 +140,6 @@ run_test("reply_message_private", ({override_rewire}) => {
}; };
people.add_active_user(fred); people.add_active_user(fred);
people.is_my_user_id = () => false;
const pm_message = { const pm_message = {
type: "private", type: "private",
display_recipient: [{id: fred.user_id}], display_recipient: [{id: fred.user_id}],

View File

@ -453,6 +453,7 @@ test("sort_recipients pm counts", () => {
"zman@test.net", "zman@test.net",
]); ]);
/* istanbul ignore next */
function compare() { function compare() {
throw new Error("We do not expect to need a tiebreaker here."); 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; const stream_id = 301;
override_rewire(sub_store, "get", (arg) => { override_rewire(sub_store, "get", (arg) => {
if (arg === stream_id) { assert.equal(arg, stream_id);
return {name: "Some stream"}; return {name: "Some stream"};
}
throw new Error(`Unknown stream ${arg}`);
}); });
let count = unread.num_unread_for_topic(stream_id, "lunch"); let count = unread.num_unread_for_topic(stream_id, "lunch");

View File

@ -63,6 +63,7 @@ run_test("initialize", ({override_rewire}) => {
}; };
success_callback(); success_callback();
break; break;
/* istanbul ignore next */
default: default:
throw new Error("Unhandled case"); throw new Error("Unhandled case");
} }
@ -85,9 +86,6 @@ run_test("initialize", ({override_rewire}) => {
$("input[type=radio][name=schedule]:checked").val = () => $("input[type=radio][name=schedule]:checked").val = () =>
document.querySelector("input[type=radio][name=schedule]:checked").value; 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(); const initialize_function = $.get_initialize_function();
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>"); assert.equal(rendered_html, "<ul>\n<li>foo1</li>\n<li>foo2</li>\n<li>foo3</li>\n</ul>");
/* istanbul ignore next */
replace_content = () => { replace_content = () => {
throw new Error("should not replace entire html"); throw new Error("should not replace entire html");
}; };
@ -209,6 +210,7 @@ run_test("partial updates", () => {
}); });
run_test("eq_array easy cases", () => { run_test("eq_array easy cases", () => {
/* istanbul ignore next */
const bogus_eq = () => { const bogus_eq = () => {
throw new Error("we should not be comparing elements"); throw new Error("we should not be comparing elements");
}; };

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,9 +2,6 @@
class FakeEvent { class FakeEvent {
constructor(type, props) { constructor(type, props) {
if (!(this instanceof FakeEvent)) {
return new FakeEvent(type, props);
}
this.type = type; this.type = type;
Object.assign(this, props); 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: # We do not yet require 100% line coverage for these files:
EXEMPT_FILES = make_set( EXEMPT_FILES = make_set(
[ [
"frontend_tests/node_tests/event_status.js",
"frontend_tests/zjsunit/mdiff.js",
"static/js/about_zulip.js", "static/js/about_zulip.js",
"static/js/add_subscribers_pill.js", "static/js/add_subscribers_pill.js",
"static/js/admin.js", "static/js/admin.js",
@ -372,14 +374,16 @@ def read_coverage() -> Any:
def enforce_proper_coverage(coverage_json: Any) -> bool: def enforce_proper_coverage(coverage_json: Any) -> bool:
all_js_files = set( all_js_files = {
glob.glob("static/js/*.js") *glob.glob("frontend_tests/node_tests/*.js"),
+ glob.glob("static/js/*.ts") *glob.glob("frontend_tests/zjsunit/*.js"),
+ glob.glob("static/shared/js/*.js") *glob.glob("static/js/*.js"),
+ glob.glob("static/shared/js/*.ts") *glob.glob("static/js/*.ts"),
+ glob.glob("static/js/billing/*.js"), *glob.glob("static/shared/js/*.js"),
) *glob.glob("static/shared/js/*.ts"),
enforce_fully_covered = all_js_files - EXEMPT_FILES *glob.glob("static/js/billing/*.js"),
}
enforce_fully_covered = sorted(all_js_files - EXEMPT_FILES)
coverage_lost = False coverage_lost = False
for relative_path in enforce_fully_covered: for relative_path in enforce_fully_covered: