/
githubmirror
/
zulip
Обзор
Документация
Войти
/
githubmirror
/
zulip
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
web/tests/upload.test.cjs
795 строк
27 KB
Anders Kaseorg
eslint: Fix no-useless-assignment.
29 июл 2026, 02:35
29 июл 2026, 02:35
539e85c
Код
Авторство
О чём код?
"use strict"; const assert = require("node:assert/strict"); const {mock_banners} = require("./lib/compose_banner.cjs"); const {make_realm} = require("./lib/example_realm.cjs"); const {mock_esm, set_global, zrequire} = require("./lib/namespace.cjs"); const {run_test, noop} = require("./lib/test.cjs"); const {$} = require("./lib/zjquery.cjs"); class ClipboardEvent { constructor({clipboardData}) { this.clipboardData = clipboardData; } } set_global("ClipboardEvent", ClipboardEvent); set_global("navigator", { userAgent: "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", }); let uppy_stub; mock_esm("@uppy/core", { Uppy: function Uppy(options) { return uppy_stub.call(this, options); }, }); mock_esm("@uppy/tus", {default: class Tus {}}); const compose_actions = mock_esm("../src/compose_actions"); const compose_reply = mock_esm("../src/compose_reply"); const compose_state = mock_esm("../src/compose_state"); const rows = mock_esm("../src/rows"); const compose_ui = zrequire("compose_ui"); const upload = zrequire("upload"); const message_lists = mock_esm("../src/message_lists"); const {set_realm} = zrequire("state_data"); const compose_validate = zrequire("compose_validate"); const realm = make_realm(); set_realm(realm); message_lists.current = { id: "1", }; function test(label, f) { run_test(label, (helpers) => { helpers.override(realm, "max_file_upload_size_mib", 25); return f(helpers); }); } test("feature_check", ({override}) => { assert.ok(!upload.feature_check()); override(window, "XMLHttpRequest", () => ({upload: true})); assert.ok(upload.feature_check()); }); test("config", () => { assert.equal(upload.compose_config.textarea()[0], $("textarea#compose-textarea")[0]); assert.equal( upload.compose_config.upload_banner_message("id_1")[0], $("#compose_banners .upload_banner.file_id_1 .upload_msg")[0], ); assert.equal( upload.compose_config.upload_banner_cancel_button("id_2")[0], $("#compose_banners .upload_banner.file_id_2 .upload_banner_cancel_button")[0], ); assert.equal( upload.compose_config.upload_banner_hide_button("id_2")[0], $("#compose_banners .upload_banner.file_id_2 .main-view-banner-close-button")[0], ); assert.equal(upload.compose_config.file_input_identifier(), "#compose input.file_input"); assert.equal(upload.compose_config.source(), "compose-file-input"); assert.equal(upload.compose_config.drag_drop_container()[0], $("#compose")[0]); assert.equal( upload.compose_config.markdown_preview_hide_button()[0], $("#compose .undo_markdown_preview")[0], ); assert.equal( upload.edit_config(1).textarea()[0], $(`#edit_form_${CSS.escape(1)} textarea.message_edit_content`)[0], ); $(`#edit_form_${CSS.escape(2)}`).set_find_results( ".message_edit_save", $(".message_edit_save"), ); assert.equal(upload.edit_config(2).send_button()[0], $(".message_edit_save")[0]); assert.equal( upload.edit_config(11).upload_banner_identifier("id_3"), `#edit_form_${CSS.escape(11)} .upload_banner.file_id_3`, ); assert.equal( upload.edit_config(75).upload_banner("id_60")[0], $(`#edit_form_${CSS.escape(75)} .upload_banner.file_id_60`)[0], ); $(`#edit_form_${CSS.escape(2)} .upload_banner`).set_find_results( ".upload_banner_cancel_button", $(".upload_banner_cancel_button"), ); assert.equal( upload.edit_config(2).upload_banner_cancel_button("id_34")[0], $(`#edit_form_${CSS.escape(2)} .upload_banner.file_id_34 .upload_banner_cancel_button`)[0], ); $(`#edit_form_${CSS.escape(2)} .upload_banner`).set_find_results( ".main-view-banner-close-button", $(".main-view-banner-close-button"), ); assert.equal( upload.edit_config(2).upload_banner_hide_button("id_34")[0], $( `#edit_form_${CSS.escape(2)} .upload_banner.file_id_34 .main-view-banner-close-button`, )[0], ); $(`#edit_form_${CSS.escape(22)} .upload_banner.file_id_234`).set_find_results( ".upload_msg", $(".upload_msg"), ); assert.equal( upload.edit_config(22).upload_banner_message("id_234")[0], $(`#edit_form_${CSS.escape(22)} .upload_banner.file_id_234 .upload_msg`)[0], ); assert.equal( upload.edit_config(123).file_input_identifier(), `#edit_form_${CSS.escape(123)} input.file_input`, ); assert.equal(upload.edit_config(123).source(), "message-edit-file-input"); assert.equal( upload.edit_config(1).drag_drop_container()[0], $(`#message-row-1-${CSS.escape(1)} .message_edit_form`)[0], ); assert.equal( upload.edit_config(65).markdown_preview_hide_button()[0], $(`#edit_form_${CSS.escape(65)} .undo_markdown_preview`)[0], ); }); test("show_error_message", ({mock_template}) => { mock_banners(); let banner_shown = false; mock_template("compose_banner/upload_banner.hbs", false, (data) => { assert.equal(data.banner_type, "error"); assert.equal(data.banner_text, "Error message"); banner_shown = true; return "<banner-stub>"; }); upload.show_error_message(upload.compose_config, "Error message"); assert.ok(!$("#compose-send-button").hasClass("disabled-message-send-controls")); assert.ok(banner_shown); mock_template("compose_banner/upload_banner.hbs", false, (data) => { assert.equal(data.banner_type, "error"); assert.equal(data.banner_text, "translated: An unknown error occurred."); banner_shown = true; return "<banner-stub>"; }); upload.show_error_message(upload.compose_config); }); test("upload_files", async ({mock_template, override, override_rewire}) => { mock_banners(); let files = [ { name: "budapest.png", type: "image/png", }, ]; let uppy_add_file_called = false; let remove_file_called = false; const uppy = { addFile(params) { uppy_add_file_called = true; assert.equal(params.source, "compose-file-input"); assert.equal(params.name, "budapest.png"); assert.equal(params.type, "image/png"); assert.equal(params.data, files[0]); return "id_123"; }, removeFile() { remove_file_called = true; }, }; let hide_upload_banner_called; override_rewire(upload, "hide_upload_banner", (_uppy, config) => { hide_upload_banner_called = true; assert.equal(config.mode, "compose"); }); const config = upload.compose_config; $("#compose-send-button").removeClass("disabled-message-send-controls"); await upload.upload_files(uppy, config, []); assert.ok(!$("#compose-send-button").hasClass("disabled-message-send-controls")); let banner_shown = false; mock_template("compose_banner/upload_banner.hbs", false, (data) => { assert.equal(data.banner_type, "error"); assert.equal( data.banner_text, "translated: File and image uploads have been disabled for this organization.", ); banner_shown = true; return "<banner-stub>"; }); override(realm, "max_file_upload_size_mib", 0); await upload.upload_files(uppy, config, files); assert.ok(banner_shown); override(realm, "max_file_upload_size_mib", 25); let compose_ui_insert_syntax_and_focus_called = false; override_rewire(compose_ui, "insert_syntax_and_focus", () => { compose_ui_insert_syntax_and_focus_called = true; }); let compose_ui_autosize_textarea_called = false; override_rewire(compose_ui, "autosize_textarea", () => { compose_ui_autosize_textarea_called = true; }); let markdown_preview_hide_button_clicked = false; $("#compose .undo_markdown_preview").on("click", () => { markdown_preview_hide_button_clicked = true; }); $("#compose-send-button").removeClass("disabled-message-send-controls"); banner_shown = false; mock_template("compose_banner/upload_banner.hbs", false, () => { banner_shown = true; return "<banner-stub>"; }); override_rewire(compose_validate, "validate", () => false); await upload.upload_files(uppy, config, files); assert.ok($("#compose-send-button").hasClass("disabled-message-send-controls")); assert.ok(banner_shown); assert.ok(compose_ui_insert_syntax_and_focus_called); assert.ok(compose_ui_autosize_textarea_called); assert.ok(markdown_preview_hide_button_clicked); assert.ok(uppy_add_file_called); banner_shown = false; files = [ { name: "budapest.png", type: "image/png", }, { name: "prague.png", type: "image/png", }, ]; let add_file_counter = 0; uppy.addFile = (file) => { add_file_counter += 1; if (file.name === "budapest.png") { throw new Error("some error"); } return `id_${add_file_counter}`; }; await upload.upload_files(uppy, config, files); assert.ok(banner_shown); assert.equal(add_file_counter, 2); hide_upload_banner_called = false; let compose_ui_replace_syntax_called = false; override_rewire(compose_ui, "replace_syntax", (old_syntax, new_syntax, $textarea) => { compose_ui_replace_syntax_called = true; assert.equal(old_syntax, "[translated: Uploading budapest.png…]()"); assert.equal(new_syntax, ""); assert.equal($textarea[0], $("textarea#compose-textarea")[0]); }); $("#compose_banners .upload_banner.file_id_123 .upload_banner_cancel_button").trigger("click"); assert.ok(remove_file_called); assert.ok(hide_upload_banner_called); assert.ok(compose_ui_autosize_textarea_called); assert.ok(compose_ui_replace_syntax_called); hide_upload_banner_called = false; compose_ui_replace_syntax_called = false; remove_file_called = false; $("textarea#compose-textarea").val("user modified text"); $("#compose_banners .upload_banner.file_id_123 .upload_banner_cancel_button").trigger("click"); assert.ok(remove_file_called); assert.ok(hide_upload_banner_called); assert.ok(compose_ui_autosize_textarea_called); assert.ok(compose_ui_replace_syntax_called); assert.equal($("textarea#compose-textarea").val(), "user modified text"); }); test("uppy_config", () => { let uppy_stub_called = false; let uppy_used_tusupload = false; uppy_stub = function (config) { uppy_stub_called = true; assert.equal(config.debug, false); assert.equal(config.autoProceed, true); assert.equal(config.restrictions.maxFileSize, 25 * 1024 * 1024); assert.equal(Object.keys(config.locale.strings).length, 2); assert.ok("exceedsSize" in config.locale.strings); return { use(func, params) { const func_name = func.name; if (func_name === "Tus") { uppy_used_tusupload = true; assert.equal(params.endpoint, "/api/v1/tus/"); assert.equal(params.limit, 5); } else { /* istanbul ignore next */ assert.fail(`Missing tests for ${func_name}`); } }, on() {}, }; }; upload.setup_upload(upload.compose_config); assert.equal(uppy_stub_called, true); assert.equal(uppy_used_tusupload, true); }); test("file_input", ({override_rewire}) => { upload.setup_upload(upload.compose_config); const change_handler = $("#compose input.file_input").get_on_handler("change"); const files = ["file1", "file2"]; const event = { target: { files, value: "C:\\fakepath\\portland.png", }, }; let upload_files_called = false; override_rewire(upload, "upload_files", (_uppy, config, files) => { assert.equal(config.mode, "compose"); assert.equal(files, files); upload_files_called = true; }); change_handler(event); assert.ok(upload_files_called); }); test("file_drop", ({override, override_rewire}) => { override(compose_state, "composing", () => false); upload.setup_upload(upload.compose_config); let prevent_default_counter = 0; const drag_event = { preventDefault() { prevent_default_counter += 1; }, }; const dragover_handler = $("#compose").get_on_handler("dragover"); dragover_handler(drag_event); assert.equal(prevent_default_counter, 1); const dragenter_handler = $("#compose").get_on_handler("dragenter"); dragenter_handler(drag_event); assert.equal(prevent_default_counter, 2); let stop_propagation_counter = 0; const files = ["file1", "file2"]; const drop_event = { preventDefault() { prevent_default_counter += 1; }, stopPropagation() { stop_propagation_counter += 1; }, originalEvent: { dataTransfer: { files, }, }, }; const drop_handler = $("#compose").get_on_handler("drop"); let upload_files_called = false; override_rewire(upload, "upload_files", () => { upload_files_called = true; }); let compose_actions_start_called = false; override(compose_reply, "respond_to_message", () => { compose_actions_start_called = true; }); drop_handler(drop_event); assert.ok(compose_actions_start_called); assert.equal(prevent_default_counter, 3); assert.equal(stop_propagation_counter, 1); assert.equal(upload_files_called, true); }); test("copy_paste", ({override, override_rewire}) => { override(compose_state, "composing", () => false); upload.setup_upload(upload.compose_config); const paste_handler = $("#compose").get_on_handler("paste"); let get_as_file_called = false; let event = { originalEvent: new ClipboardEvent({ clipboardData: { items: [ { kind: "file", getAsFile() { get_as_file_called = true; }, }, { kind: "notfile", getAsFile: () => null, }, ], }, }), preventDefault() {}, }; let upload_files_called = false; override_rewire(upload, "upload_files", () => { upload_files_called = true; }); let compose_actions_start_called = false; override(compose_reply, "respond_to_message", () => { compose_actions_start_called = true; }); paste_handler(event); assert.ok(get_as_file_called); assert.ok(upload_files_called); assert.ok(compose_actions_start_called); upload_files_called = false; event = { originalEvent: new ClipboardEvent({}), }; paste_handler(event); assert.equal(upload_files_called, false); }); test("uppy_events", ({override_rewire, mock_template}) => { mock_banners(); override_rewire(compose_ui, "smart_insert_inline", noop); override_rewire(compose_validate, "validate_and_update_send_button_status", noop); const callbacks = {}; let state = {}; let tus_options; const file = { id: "uppy-copenhagen.png", name: "copenhagen.png", type: "image/png", meta: { name: "copenhagen.png", }, }; uppy_stub = function () { return { setMeta() {}, use(_plugin, options) { tus_options = options; }, on(event_name, callback) { callbacks[event_name] = callback; }, removeFile() {}, getFiles() { return []; }, getState: () => ({ info: [ { type: state.type, details: state.details, message: state.message, }, ], }), }; }; upload.setup_upload(upload.compose_config); assert.equal(Object.keys(callbacks).length, 6); // Simulate tus-js-client having recorded this upload in our // InMemoryUrlStorage, which it does while uploading -- keyed by its // `/api/v1/tus/...` upload URL. That URL is what upload-success uses // to find the entry and store/recover the result. const tus_upload_url = "/api/v1/tus/rue1c-MlMUjDAUdkRrEM4BTJ"; tus_options.urlStorage.urlStorage.set("fingerprint::1", { uploadUrl: tus_upload_url, metadata: {}, size: null, creationTime: "", urlStorageKey: "fingerprint::1", parallelUploadUrls: null, }); const on_upload_success_callback = callbacks["upload-success"]; let response = { status: 200, uploadURL: tus_upload_url, body: { xhr: { responseText: JSON.stringify({ url: "/user_uploads/4/cb/rue1c-MlMUjDAUdkRrEM4BTJ/copenhagen.png", filename: "modified-name-copenhagen.png", }), }, }, }; let compose_ui_replace_syntax_called = false; override_rewire(compose_ui, "replace_syntax", (old_syntax, new_syntax, $textarea) => { compose_ui_replace_syntax_called = true; assert.equal(old_syntax, "[translated: Uploading copenhagen.png…]()"); assert.equal( new_syntax, "", ); assert.equal($textarea[0], $("textarea#compose-textarea")[0]); }); let compose_ui_autosize_textarea_called = false; override_rewire(compose_ui, "autosize_textarea", () => { compose_ui_autosize_textarea_called = true; }); on_upload_success_callback(file, response); assert.ok(compose_ui_replace_syntax_called); assert.ok(compose_ui_autosize_textarea_called); // Re-uploading the same file makes tus-js-client short-circuit to a // HEAD request that returns no response body. We must still recover // the URL and filename stored from the first upload above and insert // the same syntax, rather than stalling on the placeholder. The // replace_syntax override below continues to assert the same syntax. compose_ui_replace_syntax_called = false; const reupload_response = { status: 200, uploadURL: tus_upload_url, body: { xhr: { responseText: "", }, }, }; on_upload_success_callback(file, reupload_response); assert.ok(compose_ui_replace_syntax_called); mock_template("compose_banner/upload_banner.hbs", false, (data) => { assert.equal(data.banner_type, "error"); assert.equal(data.banner_text, "Some error message"); return "<banner-stub>"; }); state = { type: "error", details: "Some error", message: "Some error message", }; const on_info_visible_callback = callbacks["info-visible"]; compose_ui_replace_syntax_called = false; const on_restriction_failed_callback = callbacks["restriction-failed"]; on_info_visible_callback(); override_rewire(compose_ui, "replace_syntax", (old_syntax, new_syntax, $textarea) => { compose_ui_replace_syntax_called = true; assert.equal(old_syntax, "[translated: Uploading copenhagen.png…]()"); assert.equal(new_syntax, ""); assert.equal($textarea[0], $("textarea#compose-textarea")[0]); }); on_restriction_failed_callback(file, null, null); assert.ok(compose_ui_replace_syntax_called); compose_ui_replace_syntax_called = false; $("textarea#compose-textarea").val("user modified text"); on_restriction_failed_callback(file, null, null); assert.ok(compose_ui_replace_syntax_called); assert.equal($("textarea#compose-textarea").val(), "user modified text"); state = { type: "error", message: "No Internet connection", }; on_info_visible_callback(); state = { type: "error", details: "Upload Error", }; on_info_visible_callback(); let hide_upload_banner_called = false; override_rewire(upload, "hide_upload_banner", (_uppy, config) => { hide_upload_banner_called = true; assert.equal(config.mode, "compose"); }); const on_upload_error_callback = callbacks["upload-error"]; const $error_msg = upload.compose_config.upload_banner_message(file.id); compose_ui_replace_syntax_called = false; response = { body: { msg: "Response message", }, }; on_upload_error_callback(file, null, response); assert.ok(compose_ui_replace_syntax_called); assert.equal($error_msg.text(), "Response message"); // With no response body, we fall back to a generic error message. compose_ui_replace_syntax_called = false; on_upload_error_callback(file, null, undefined); assert.ok(compose_ui_replace_syntax_called); assert.equal($error_msg.text(), "translated: An unknown error occurred."); assert.ok(hide_upload_banner_called); $("textarea#compose-textarea").val("user modified text"); on_upload_error_callback(file, null); assert.ok(compose_ui_replace_syntax_called); assert.equal($("textarea#compose-textarea").val(), "user modified text"); }); test("main_file_drop_compose_mode", ({override, override_rewire}) => { uppy_stub = function () { return { setMeta() {}, use() {}, cancelAll() {}, on() {}, getFiles() {}, removeFile() {}, }; }; upload.initialize(); let prevent_default_counter = 0; const drag_event = { preventDefault() { prevent_default_counter += 1; }, }; // dragover event test const dragover_handler = $(".app, #navbar-fixed-container").get_on_handler("dragover"); dragover_handler(drag_event); assert.equal(prevent_default_counter, 1); // dragenter event test const dragenter_handler = $(".app, #navbar-fixed-container").get_on_handler("dragenter"); dragenter_handler(drag_event); assert.equal(prevent_default_counter, 2); const files = ["file1", "file2"]; const drop_event = { target: "target", preventDefault() { prevent_default_counter += 1; }, originalEvent: { dataTransfer: { files, }, }, }; $.set_results(".message_edit_form form", []); const drop_handler = $(".app, #navbar-fixed-container").get_on_handler("drop"); // Test drop on compose box let upload_files_called = false; override_rewire(upload, "upload_files", () => { upload_files_called = true; }); override(compose_state, "composing", () => true); drop_handler(drop_event); assert.equal(upload_files_called, true); assert.equal(prevent_default_counter, 3); // Test reply to message if no edit and compose box open upload_files_called = false; override(compose_state, "composing", () => false); const msg = { type: "stream", stream: "Denmark", topic: "python", sender_full_name: "Bob Roberts", sender_id: 40, }; let compose_actions_start_called = false; let compose_actions_respond_to_message_called = false; override(message_lists, "current", { selected_message() { return msg; }, }); compose_actions.start = () => { compose_actions_start_called = true; }; compose_reply.respond_to_message = () => { compose_actions_respond_to_message_called = true; }; drop_handler(drop_event); assert.equal(upload_files_called, true); assert.equal(compose_actions_start_called, false); assert.equal(compose_actions_respond_to_message_called, true); // Test drop on Recent Conversations view compose_actions_respond_to_message_called = false; override(message_lists, "current", { selected_message() { return undefined; }, }); upload_files_called = false; drop_handler(drop_event); assert.equal(upload_files_called, true); assert.equal(compose_actions_start_called, true); assert.equal(compose_actions_respond_to_message_called, false); }); test("main_file_drop_edit_mode", ({override, override_rewire}) => { uppy_stub = function () { return { setMeta() {}, use() {}, cancelAll() {}, on() {}, getFiles() {}, removeFile() {}, }; }; upload.setup_upload(upload.edit_config(40)); upload.initialize(); override(compose_state, "composing", () => false); let prevent_default_counter = 0; const drag_event = { preventDefault() { prevent_default_counter += 1; }, }; const $drag_drop_container = $(`#message-row-1-${CSS.escape(40)} .message_edit_form`); // Dragover event test const dragover_handler = $(".app, #navbar-fixed-container").get_on_handler("dragover"); dragover_handler(drag_event); assert.equal(prevent_default_counter, 1); // Dragenter event test const dragenter_handler = $(".app, #navbar-fixed-container").get_on_handler("dragenter"); dragenter_handler(drag_event); assert.equal(prevent_default_counter, 2); const files = ["file1", "file2"]; const drop_event = { target: "target", preventDefault() { prevent_default_counter += 1; }, originalEvent: { dataTransfer: { files, }, }, }; const drop_handler = $(".app, #navbar-fixed-container").get_on_handler("drop"); let upload_files_called = false; let dropped_row_id = -1; override_rewire(upload, "upload_files", (_, config) => { dropped_row_id = config.row; upload_files_called = true; }); override(rows, "get_message_id", () => 40); // Edit box which registered the event handler no longer exists. $drag_drop_container.set_closest_results("html", []); drop_handler(drop_event); assert.equal(upload_files_called, false); $drag_drop_container.set_closest_results("html", $.create("html")); // Drag and dropped in one of the edit boxes. The event would be taken care of by // drag_drop_container event handlers. override(rows, "get_message_id", () => 40); // Edit box open drop_handler(drop_event); assert.equal(upload_files_called, true); assert.equal(dropped_row_id, 40); });