/
githubmirror
/
zulip
Обзор
Документация
Войти
/
githubmirror
/
zulip
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
web/tests/drafts.test.cjs
896 строк
28 KB
Anders Kaseorg
web: Use named import for jQuery.
29 июл 2026, 02:35
29 июл 2026, 02:35
52a10e8
Код
Авторство
О чём код?
"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 {make_stream} = require("./lib/example_stream.cjs"); const {make_user} = require("./lib/example_user.cjs"); const {clock, mock_esm, mock_cjs, set_global, zrequire} = require("./lib/namespace.cjs"); const {run_test, noop} = require("./lib/test.cjs"); const {$} = require("./lib/zjquery.cjs"); const user_pill = mock_esm("../src/user_pill", {get_user_ids: () => []}); const settings_data = mock_esm("../src/settings_data"); const messages_overlay_ui = mock_esm("../src/messages_overlay_ui"); const channel = mock_esm("../src/channel"); const people = zrequire("people"); const compose_state = zrequire("compose_state"); const compose_recipient = zrequire("compose_recipient"); const stream_data = zrequire("stream_data"); const stream_color = zrequire("stream_color"); const {initialize_user_settings} = zrequire("user_settings"); const {set_current_user, set_realm} = zrequire("state_data"); class Clipboard { on() {} } mock_cjs("clipboard", Clipboard); initialize_user_settings({user_settings: {}}); const REALM_EMPTY_TOPIC_DISPLAY_NAME = "test general chat"; const realm = make_realm({realm_empty_topic_display_name: REALM_EMPTY_TOPIC_DISPLAY_NAME}); set_realm(realm); const aaron = make_user({ email: "aaron@zulip.com", user_id: 6, full_name: "Aaron", }); const iago = make_user({ email: "iago@zulip.com", user_id: 2, full_name: "Iago", }); const zoe = make_user({ email: "zoe@zulip.com", user_id: 3, full_name: "Zoe", }); set_current_user(aaron); people.add_active_user(aaron); people.add_valid_user_id(aaron.user_id); people.initialize_current_user(aaron.user_id); people.add_active_user(iago); people.add_valid_user_id(iago.user_id); people.add_active_user(zoe); people.add_valid_user_id(zoe.user_id); const stream_A = make_stream({ subscribed: false, name: "A", stream_id: 1, }); const stream_B = make_stream({ subscribed: false, name: "B", stream_id: 2, }); const stream_1 = make_stream({ subscribed: false, name: "stream 1", stream_id: 30, color: "c2726a", }); const stream_2 = make_stream({ subscribed: false, name: "stream 2", stream_id: 40, color: "e2226a", invite_only: false, is_web_public: false, }); stream_data.add_sub_for_tests(stream_A); stream_data.add_sub_for_tests(stream_B); stream_data.add_sub_for_tests(stream_1); stream_data.add_sub_for_tests(stream_2); const setTimeout_delay = new Set([0, 3000]); set_global("setTimeout", (f, delay) => { assert.ok(setTimeout_delay.has(delay)); f(); }); const markdown = mock_esm("../src/markdown", { render: noop, contains_backend_only_syntax: () => false, }); const overlays = mock_esm("../src/overlays", { open_overlay: noop, }); mock_esm("../src/rendered_markdown", { update_elements: noop, }); const tippy_sel = ".top_left_drafts .unread_count"; let tippy_args; let tippy_show_called; let tippy_destroy_called; mock_esm("tippy.js", { default(sel, opts) { assert.equal(sel, tippy_sel); assert.deepEqual(opts, tippy_args); return [ { show() { tippy_show_called = true; }, destroy() { tippy_destroy_called = true; }, }, ]; }, delegate: noop, }); const {localstorage} = zrequire("localstorage"); const drafts = zrequire("drafts"); const drafts_overlay_ui = zrequire("drafts_overlay_ui"); zrequire("timerender"); const mock_current_timestamp = 1234; const stream_id = 30; const draft_1 = { stream_id, topic: "topic", type: "stream", content: "Test stream message", updatedAt: mock_current_timestamp, is_sending_saving: false, drafts_version: 1, }; const draft_2 = { private_message_recipient_ids: [aaron.user_id], type: "private", content: "Test direct message", updatedAt: mock_current_timestamp, is_sending_saving: false, drafts_version: 1, }; const short_msg = { stream_id, topic: "topic", type: "stream", content: "a", updatedAt: mock_current_timestamp, is_sending_saving: false, drafts_version: 1, }; function test(label, f) { run_test(label, (helpers) => { $(".top_left_drafts").set_find_results(".unread_count", $("<unread-count-stub>")); $(".compose-drafts-count-container").set_find_results( ".compose-drafts-count", $("<compose-drafts-count-stub>"), ); window.localStorage.clear(); f(helpers); }); } // There were some buggy drafts that had their topics // renamed to `undefined` in #23238. // TODO/compatibility: The next two tests can be deleted // when we get to delete drafts.fix_drafts_with_undefined_topics. // // This test must run before others, so that // fixed_buggy_drafts and fixed_private_draft_recipient_ids are false. test("fix buggy drafts", () => { const buggy_draft = { stream_id: stream_B.stream_id, topic: undefined, type: "stream", content: "Test stream message", updatedAt: Date.now(), }; const draft_with_pm_emails = { private_message_recipient: "iago@zulip.com,zoe@zulip.com", reply_to: "iago@zulip.com,zoe@zulip.com", type: "private", content: "Test direct message", updatedAt: Date.now(), }; // 999 is an invalid user ID not present in the people store. const draft_with_invalid_recipient = { private_message_recipient_ids: [iago.user_id, 999], type: "private", content: "Test direct message 2", updatedAt: Date.now(), is_sending_saving: false, drafts_version: 1, }; const draft_with_only_invalid_recipients = { private_message_recipient_ids: [999], type: "private", content: "Test direct message 3", updatedAt: Date.now(), is_sending_saving: false, drafts_version: 1, }; const ls = localstorage(); ls.set("drafts", { id1: buggy_draft, id2: draft_with_pm_emails, id3: draft_with_invalid_recipient, id4: draft_with_only_invalid_recipients, }); const draft_model = drafts.draft_model; // The draft is fixed in this codepath. drafts.rename_stream_recipient( stream_B.stream_id, "old_topic", stream_A.stream_id, "new_topic", ); const draft = draft_model.getDraft("id1"); assert.equal(draft.stream_id, stream_B.stream_id); assert.equal(draft.topic, ""); const fixed_draft = draft_model.getDraft("id2"); assert.equal(fixed_draft.private_message_recipient, undefined); assert.deepEqual(fixed_draft.private_message_recipient_ids, [iago.user_id, zoe.user_id]); // reply_to field is also removed since it is not present in the // zod schema. assert.equal(fixed_draft.reply_to, undefined); // fix_private_draft_recipient_ids removes invalid user IDs. const fixed_invalid_recipient_draft = draft_model.getDraft("id3"); assert.deepEqual(fixed_invalid_recipient_draft.private_message_recipient_ids, [iago.user_id]); const fixed_only_invalid_recipients_draft = draft_model.getDraft("id4"); assert.deepEqual(fixed_only_invalid_recipients_draft.private_message_recipient_ids, []); }); test("draft_model add", () => { const draft_model = drafts.draft_model; const ls = localstorage(); assert.equal(ls.get("draft"), undefined); const id = draft_model.addDraft(draft_1); assert.deepEqual(draft_model.getDraft(id), draft_1); }); test("draft_model edit", () => { const draft_model = drafts.draft_model; const ls = localstorage(); assert.equal(ls.get("draft"), undefined); const id = draft_model.addDraft(draft_1); assert.deepEqual(draft_model.getDraft(id), draft_1); draft_model.editDraft(id, draft_2); assert.deepEqual(draft_model.getDraft(id), draft_2); }); test("draft_model delete", () => { const draft_model = drafts.draft_model; const ls = localstorage(); assert.equal(ls.get("draft"), undefined); const id = draft_model.addDraft(draft_1); assert.deepEqual(draft_model.getDraft(id), draft_1); draft_model.deleteDrafts([id]); assert.deepEqual(draft_model.getDraft(id), false); }); test("snapshot_message", ({override}) => { override(user_pill, "get_user_ids", () => [aaron.user_id]); mock_banners(); let curr_draft; function set_compose_state() { compose_state.set_message_type(curr_draft.type); compose_state.message_content(curr_draft.content); if (curr_draft.type === "private") { compose_state.set_compose_recipient_id(compose_recipient.DIRECT_MESSAGE_ID); } else { compose_state.set_stream_id(curr_draft.stream_id); } compose_state.topic(curr_draft.topic); } compose_state.set_stream_id(stream_1.stream_id); override(Date, "now", () => mock_current_timestamp); curr_draft = draft_1; set_compose_state(); assert.deepEqual(drafts.snapshot_message(), draft_1); curr_draft = draft_2; set_compose_state(); assert.deepEqual(drafts.snapshot_message(), draft_2); curr_draft = short_msg; set_compose_state(); assert.deepEqual(drafts.snapshot_message(), undefined); curr_draft = {type: false}; set_compose_state(); assert.equal(drafts.snapshot_message(), undefined); }); test("initialize", ({override_rewire}) => { window.addEventListener = (event_name, f) => { assert.equal(event_name, "beforeunload"); let called = false; override_rewire(drafts, "update_draft", () => { called = true; return 100; }); f(); assert.ok(called); }; drafts.initialize(); drafts.initialize_ui(); drafts_overlay_ui.initialize(); }); test("update_draft", ({override}) => { compose_state.set_message_type(undefined); let draft_id = drafts.update_draft(); assert.equal(draft_id, undefined); override(user_pill, "get_user_ids", () => [aaron.user_id]); compose_state.set_message_type("private"); compose_state.message_content("dummy content"); tippy_args = { content: "translated: Saved as draft", arrow: true, placement: "right", }; tippy_show_called = false; tippy_destroy_called = false; override(Date, "now", () => 5); override(Math, "random", () => 2); draft_id = drafts.update_draft(); assert.equal(draft_id, "5-2"); assert.ok(tippy_show_called); assert.ok(tippy_destroy_called); override(Date, "now", () => 6); compose_state.message_content("dummy content edited once"); tippy_show_called = false; tippy_destroy_called = false; draft_id = drafts.update_draft(); assert.equal(draft_id, "5-2"); assert.ok(tippy_show_called); assert.ok(tippy_destroy_called); override(Date, "now", () => 7); // message contents not edited tippy_show_called = false; tippy_destroy_called = false; draft_id = drafts.update_draft(); assert.equal(draft_id, "5-2"); assert.ok(!tippy_show_called); assert.ok(!tippy_destroy_called); override(Date, "now", () => 8); compose_state.message_content("dummy content edited a second time"); tippy_show_called = false; tippy_destroy_called = false; draft_id = drafts.update_draft({no_notify: true}); assert.equal(draft_id, "5-2"); assert.ok(!tippy_show_called); assert.ok(!tippy_destroy_called); }); test("rename_stream_recipient", () => { const draft_1 = { stream_id: stream_A.stream_id, topic: "a", type: "stream", content: "Test stream message", updatedAt: Date.now(), }; const draft_2 = { stream_id: stream_A.stream_id, topic: "b", type: "stream", content: "Test stream message", updatedAt: Date.now(), }; const draft_3 = { stream_id: stream_B.stream_id, topic: "a", type: "stream", content: "Test stream message", updatedAt: Date.now(), }; const draft_4 = { stream_id: stream_B.stream_id, topic: "c", type: "stream", content: "Test stream message", updatedAt: Date.now(), }; const data = {id1: draft_1, id2: draft_2, id3: draft_3, id4: draft_4}; const ls = localstorage(); ls.set("drafts", data); const draft_model = drafts.draft_model; function assert_draft(draft_id, stream_id, topic_name) { const draft = draft_model.getDraft(draft_id); assert.equal(draft.topic, topic_name); assert.equal(draft.stream_id, stream_id); } // There are no drafts in B>b, so moving messages from there doesn't change drafts drafts.rename_stream_recipient(stream_B.stream_id, "b", undefined, "c"); assert_draft("id1", stream_A.stream_id, "a"); assert_draft("id2", stream_A.stream_id, "b"); assert_draft("id3", stream_B.stream_id, "a"); assert_draft("id4", stream_B.stream_id, "c"); // Update with both stream and topic changes Bc -> Aa drafts.rename_stream_recipient(stream_B.stream_id, "c", stream_A.stream_id, "a"); assert_draft("id1", stream_A.stream_id, "a"); assert_draft("id2", stream_A.stream_id, "b"); assert_draft("id3", stream_B.stream_id, "a"); assert_draft("id4", stream_A.stream_id, "a"); // Update with only stream change Aa -> Ba drafts.rename_stream_recipient(stream_A.stream_id, "a", stream_B.stream_id, undefined); assert_draft("id1", stream_B.stream_id, "a"); assert_draft("id2", stream_A.stream_id, "b"); assert_draft("id3", stream_B.stream_id, "a"); assert_draft("id4", stream_B.stream_id, "a"); // Update with only topic change, affecting three messages drafts.rename_stream_recipient(stream_B.stream_id, "a", undefined, "e"); assert_draft("id1", stream_B.stream_id, "e"); assert_draft("id2", stream_A.stream_id, "b"); assert_draft("id3", stream_B.stream_id, "e"); assert_draft("id4", stream_B.stream_id, "e"); }); test("delete_all_drafts", () => { const draft_model = drafts.draft_model; const ls = localstorage(); const data = {draft_1, draft_2, short_msg}; ls.set("drafts", data); assert.deepEqual(draft_model.get(), data); drafts.delete_all_drafts(); assert.deepEqual(draft_model.get(), {}); }); test("format_drafts", ({override, mock_template}) => { override(settings_data, "using_dark_theme", () => false); function feb12() { return new Date(1549958107000); // 2/12/2019 07:55:07 AM (UTC+0) } function date(offset) { return feb12().setDate(offset); } const draft_1 = { topic: "topic", type: "stream", content: "Test stream message", stream_id: 30, updatedAt: feb12().getTime(), is_sending_saving: false, drafts_version: 1, }; const draft_2 = { private_message_recipient_ids: [aaron.user_id], type: "private", content: "Test direct message", updatedAt: date(-1), is_sending_saving: false, drafts_version: 1, }; const draft_3 = { topic: "topic", type: "stream", stream_id: 40, content: "Test stream message 2", updatedAt: date(-10), is_sending_saving: false, drafts_version: 1, }; const draft_4 = { private_message_recipient_ids: [iago.user_id], type: "private", content: "Test direct message 2", updatedAt: date(-5), is_sending_saving: false, drafts_version: 1, }; const draft_5 = { private_message_recipient_ids: [zoe.user_id, iago.user_id], type: "private", content: "Test direct message 3", updatedAt: date(-2), is_sending_saving: false, drafts_version: 1, }; const draft_6 = { topic: "", type: "stream", stream_id: 40, content: "Test stream message 3", updatedAt: date(-11), is_sending_saving: false, drafts_version: 1, }; const draft_7 = { private_message_recipient_ids: [], type: "private", content: "Test direct message 4", updatedAt: date(-12), is_sending_saving: false, drafts_version: 1, }; const expected = [ { draft_id: "id1", is_stream: true, stream_name: stream_1.name, stream_id: 30, recipient_bar_color: stream_color.get_recipient_bar_color(stream_1.color), stream_privacy_icon_color: stream_color.get_stream_privacy_icon_color(stream_1.color), topic_display_name: "topic", is_empty_string_topic: false, raw_content: "Test stream message", time_stamp: "7:55 AM", invite_only: stream_1.invite_only, is_web_public: stream_1.is_web_public, is_sending_saving: false, }, { draft_id: "id2", is_dm_with_self: true, is_stream: false, has_recipient_data: true, recipients: "Aaron", raw_content: "Test direct message", time_stamp: "Jan 30", is_sending_saving: false, }, { draft_id: "id5", is_dm_with_self: false, is_stream: false, recipients: "Iago, Zoe", has_recipient_data: true, raw_content: "Test direct message 3", time_stamp: "Jan 29", is_sending_saving: false, }, { draft_id: "id4", is_dm_with_self: false, is_stream: false, recipients: "Iago", has_recipient_data: true, raw_content: "Test direct message 2", time_stamp: "Jan 26", is_sending_saving: false, }, { draft_id: "id3", is_stream: true, stream_name: stream_2.name, stream_id: 40, recipient_bar_color: stream_color.get_recipient_bar_color(stream_2.color), stream_privacy_icon_color: stream_color.get_stream_privacy_icon_color(stream_2.color), topic_display_name: "topic", is_empty_string_topic: false, raw_content: "Test stream message 2", time_stamp: "Jan 21", invite_only: stream_2.invite_only, is_web_public: stream_2.is_web_public, is_sending_saving: false, }, { draft_id: "id6", is_stream: true, stream_name: stream_2.name, stream_id: 40, recipient_bar_color: stream_color.get_recipient_bar_color(stream_2.color), stream_privacy_icon_color: stream_color.get_stream_privacy_icon_color(stream_2.color), topic_display_name: REALM_EMPTY_TOPIC_DISPLAY_NAME, is_empty_string_topic: true, raw_content: "Test stream message 3", time_stamp: "Jan 20", invite_only: stream_2.invite_only, is_web_public: stream_2.is_web_public, is_sending_saving: false, }, { draft_id: "id7", is_stream: false, has_recipient_data: false, recipients: "", raw_content: "Test direct message 4", time_stamp: "Jan 19", is_sending_saving: false, }, ]; const draft_model = drafts.draft_model; const ls = localstorage(); const data = { id1: draft_1, id2: draft_2, id3: draft_3, id4: draft_4, id5: draft_5, id6: draft_6, id7: draft_7, }; ls.set("drafts", data); assert.deepEqual(draft_model.get(), data); override(realm, "realm_topics_policy", "disable_empty_topic"); expected[5].topic_display_name = "translated: No topic entered"; expected[5].is_empty_string_topic = true; assert.deepEqual(draft_model.get(), data); clock.setSystemTime(1549958107000); override(user_pill, "get_user_ids", () => []); compose_state.set_message_type("private"); mock_template("draft_table_body.hbs", false, (data) => { // Tests formatting and time-sorting of drafts assert.deepEqual(data.context.narrow_drafts, []); assert.deepEqual(data.context.other_drafts, expected); assert.ok(data); return "<draft table stub>"; }); override(messages_overlay_ui, "set_initial_element", noop); override(messages_overlay_ui, "get_and_clear_pending_restore_element_id", () => undefined); $.set_results(".drafts-list", []); $.set_results(".drafts-tab-pane .overlay-message-row", []); $.set_results(".draft-selection-checkbox", []); drafts_overlay_ui.launch(); }); test("filter_drafts", ({override, mock_template}) => { override(settings_data, "using_dark_theme", () => true); function feb12() { return new Date(1549958107000); // 2/12/2019 07:55:07 AM (UTC+0) } function date(offset) { return feb12().setDate(offset); } const stream_draft_1 = { topic: "topic", type: "stream", content: "Test stream message", stream_id: 30, updatedAt: feb12().getTime(), is_sending_saving: false, drafts_version: 1, }; const pm_draft_1 = { private_message_recipient_ids: [aaron.user_id], type: "private", content: "Test direct message", updatedAt: date(-1), is_sending_saving: false, drafts_version: 1, }; const stream_draft_2 = { topic: "topic", type: "stream", stream_id: 40, content: "Test stream message 2", updatedAt: date(-10), is_sending_saving: false, drafts_version: 1, }; const pm_draft_2 = { private_message_recipient_ids: [aaron.user_id], type: "private", content: "Test direct message 2", updatedAt: date(-5), is_sending_saving: false, drafts_version: 1, }; const pm_draft_3 = { private_message_recipient_ids: [aaron.user_id], type: "private", content: "Test direct message 3", updatedAt: date(-2), is_sending_saving: false, drafts_version: 1, }; const expected_pm_drafts = [ { draft_id: "id2", is_dm_with_self: true, is_stream: false, has_recipient_data: true, recipients: "Aaron", raw_content: "Test direct message", time_stamp: "Jan 30", is_sending_saving: false, }, { draft_id: "id5", is_dm_with_self: true, is_stream: false, has_recipient_data: true, recipients: "Aaron", raw_content: "Test direct message 3", time_stamp: "Jan 29", is_sending_saving: false, }, { draft_id: "id4", is_dm_with_self: true, is_stream: false, has_recipient_data: true, recipients: "Aaron", raw_content: "Test direct message 2", time_stamp: "Jan 26", is_sending_saving: false, }, ]; const expected_other_drafts = [ { draft_id: "id1", is_stream: true, stream_name: stream_1.name, stream_id: 30, recipient_bar_color: stream_color.get_recipient_bar_color(stream_1.color), stream_privacy_icon_color: stream_color.get_stream_privacy_icon_color(stream_1.color), topic_display_name: "topic", is_empty_string_topic: false, raw_content: "Test stream message", time_stamp: "7:55 AM", invite_only: stream_1.invite_only, is_web_public: stream_1.is_web_public, is_sending_saving: false, }, { draft_id: "id3", is_stream: true, stream_name: stream_2.name, stream_id: 40, recipient_bar_color: stream_color.get_recipient_bar_color(stream_2.color), stream_privacy_icon_color: stream_color.get_stream_privacy_icon_color(stream_2.color), topic_display_name: "topic", is_empty_string_topic: false, raw_content: "Test stream message 2", time_stamp: "Jan 21", invite_only: stream_2.invite_only, is_web_public: stream_2.is_web_public, is_sending_saving: false, }, ]; const draft_model = drafts.draft_model; const ls = localstorage(); const data = { id1: stream_draft_1, id2: pm_draft_1, id3: stream_draft_2, id4: pm_draft_2, id5: pm_draft_3, }; ls.set("drafts", data); assert.deepEqual(draft_model.get(), data); clock.setSystemTime(1549958107000); mock_template("draft_table_body.hbs", false, (data) => { // Tests splitting up drafts by current narrow. assert.deepEqual(data.context.narrow_drafts, expected_pm_drafts); assert.deepEqual(data.context.other_drafts, expected_other_drafts); return "<draft table stub>"; }); override(messages_overlay_ui, "set_initial_element", noop); override(messages_overlay_ui, "get_and_clear_pending_restore_element_id", () => undefined); override(user_pill, "get_user_ids", () => [aaron.user_id]); compose_state.set_message_type("private"); $.set_results(".drafts-list", []); $.set_results(".drafts-tab-pane .overlay-message-row", []); $.set_results(".draft-selection-checkbox", []); drafts_overlay_ui.launch(); }); test("server_rendering_for_backend_only_syntax", ({override, mock_template}) => { override(settings_data, "using_dark_theme", () => false); const now = Date.now(); const draft_with_image = { topic: "topic", type: "stream", content: "Look at this screenshot: https://user-uploads.zulipdev.org/upload/image.png", stream_id: 30, updatedAt: now, is_sending_saving: false, drafts_version: 1, }; const draft_without_image = { topic: "topic", type: "stream", content: "This is a plain text draft", stream_id: 30, updatedAt: now - 1000, is_sending_saving: false, drafts_version: 1, }; const draft_model = drafts.draft_model; const ls = localstorage(); ls.set("drafts", {id1: draft_with_image, id2: draft_without_image}); assert.deepEqual(draft_model.get(), {id1: draft_with_image, id2: draft_without_image}); override( markdown, "contains_backend_only_syntax", (content) => content === draft_with_image.content, ); const locally_rendered_content = '<p>Look at this screenshot: <a href="https://user-uploads.zulipdev.org/upload/image.png">https://user-uploads.zulipdev.org/upload/image.png</a></p>'; const server_rendered_content = '<p>Look at this screenshot: <a href="https://user-uploads.zulipdev.org/upload/image.png" target="_blank" rel="noopener noreferrer" title="https://user-uploads.zulipdev.org/upload/image.png"><img src="/thumbnail?url=user_uploads%2Fimage.png&size=thumbnail"></a></p>'; let post_calls = 0; const $content_element = $.create('[data-draft-id="id1"] .message_content'); $content_element.html(locally_rendered_content); override(overlays, "drafts_open", () => true); mock_template("draft_table_body.hbs", false, () => "<draft table stub>"); override(messages_overlay_ui, "set_initial_element", noop); override(messages_overlay_ui, "get_and_clear_pending_restore_element_id", () => undefined); // These selectors are accessed during render_widgets() and // update_bulk_delete_ui() inside launch(). $.set_results(".drafts-list", []); $.set_results(".drafts-tab-pane .overlay-message-row", []); $.set_results(".draft-selection-checkbox", []); override(channel, "post", (payload) => { post_calls += 1; assert.equal(payload.url, "/json/messages/render"); assert.equal(payload.data.content, draft_with_image.content); const resp = { msg: "", result: "success", rendered: server_rendered_content, }; payload.success(resp); assert.equal($content_element.html(), server_rendered_content); }); drafts_overlay_ui.launch(); // Only the draft with the image triggered a server render request; // the plain text draft did not. assert.equal(post_calls, 1); });