Best Python code snippet using autotest_python
compose.js
Source:compose.js
1"use strict";2const {strict: assert} = require("assert");3const {JSDOM} = require("jsdom");4const MockDate = require("mockdate");5const {stub_templates} = require("../zjsunit/handlebars");6const {mock_cjs, mock_esm, set_global, zrequire} = require("../zjsunit/namespace");7const {run_test} = require("../zjsunit/test");8const blueslip = require("../zjsunit/zblueslip");9const $ = require("../zjsunit/zjquery");10mock_cjs("jquery", $);11const noop = () => {};12set_global("DOMParser", new JSDOM().window.DOMParser);13let compose_actions_start_checked;14let compose_actions_expected_opts;15mock_esm("../../static/js/compose_actions", {16 update_placeholder_text: noop,17 start(msg_type, opts) {18 assert.equal(msg_type, "stream");19 assert.deepEqual(opts, compose_actions_expected_opts);20 compose_actions_start_checked = true;21 },22});23const server_events = mock_esm("../../static/js/server_events");24const _navigator = {25 platform: "",26};27const _document = {28 execCommand() {29 return false;30 },31 location: {},32 to_$: () => $("document-stub"),33};34set_global("document", _document);35const channel = mock_esm("../../static/js/channel");36const loading = mock_esm("../../static/js/loading");37const local_message = mock_esm("../../static/js/local_message");38const markdown = mock_esm("../../static/js/markdown");39const page_params = set_global("page_params", {});40const reminder = mock_esm("../../static/js/reminder", {41 is_deferred_delivery: noop,42});43const resize = mock_esm("../../static/js/resize");44const sent_messages = mock_esm("../../static/js/sent_messages", {45 start_tracking_message: noop,46});47const stream_edit = mock_esm("../../static/js/stream_edit");48const subs = mock_esm("../../static/js/subs");49const transmit = mock_esm("../../static/js/transmit");50const ui_util = mock_esm("../../static/js/ui_util");51mock_esm("../../static/js/drafts", {52 delete_draft_after_send: noop,53});54mock_esm("../../static/js/notifications", {55 notify_above_composebox: noop,56 clear_compose_notifications: noop,57});58mock_esm("../../static/js/rendered_markdown", {59 update_elements: () => {},60});61set_global("navigator", _navigator);62// Setting these up so that we can test that links to uploads within messages are63// automatically converted to server relative links.64document.location.protocol = "https:";65document.location.host = "foo.com";66const fake_now = 555;67MockDate.set(new Date(fake_now * 1000));68const compose_fade = zrequire("compose_fade");69const peer_data = zrequire("peer_data");70const util = zrequire("util");71const rtl = zrequire("rtl");72const stream_data = zrequire("stream_data");73const compose_state = zrequire("compose_state");74const people = zrequire("people");75const compose_pm_pill = zrequire("compose_pm_pill");76const echo = zrequire("echo");77const compose = zrequire("compose");78const upload = zrequire("upload");79const settings_config = zrequire("settings_config");80people.small_avatar_url_for_person = () => "http://example.com/example.png";81function reset_jquery() {82 // Avoid leaks.83 $.clear_all_elements();84}85const new_user = {86 email: "new_user@example.com",87 user_id: 101,88 full_name: "New User",89 date_joined: new Date(),90};91const me = {92 email: "me@example.com",93 user_id: 30,94 full_name: "Me Myself",95 date_joined: new Date(),96};97const alice = {98 email: "alice@example.com",99 user_id: 31,100 full_name: "Alice",101};102const bob = {103 email: "bob@example.com",104 user_id: 32,105 full_name: "Bob",106};107people.add_active_user(new_user);108people.add_active_user(me);109people.initialize_current_user(me.user_id);110people.add_active_user(alice);111people.add_active_user(bob);112function test_ui(label, f) {113 // The sloppy_$ flag lets us re-use setup from prior tests.114 run_test(label, f, {sloppy_$: true});115}116test_ui("validate_stream_message_address_info", () => {117 const sub = {118 stream_id: 101,119 name: "social",120 subscribed: true,121 };122 stream_data.add_sub(sub);123 assert(compose.validate_stream_message_address_info("social"));124 sub.subscribed = false;125 stream_data.add_sub(sub);126 stub_templates((template_name) => {127 assert.equal(template_name, "compose_not_subscribed");128 return "compose_not_subscribed_stub";129 });130 assert(!compose.validate_stream_message_address_info("social"));131 assert.equal($("#compose-error-msg").html(), "compose_not_subscribed_stub");132 page_params.narrow_stream = false;133 channel.post = (payload) => {134 assert.equal(payload.data.stream, "social");135 payload.data.subscribed = true;136 payload.success(payload.data);137 };138 assert(compose.validate_stream_message_address_info("social"));139 sub.name = "Frontend";140 sub.stream_id = 102;141 stream_data.add_sub(sub);142 channel.post = (payload) => {143 assert.equal(payload.data.stream, "Frontend");144 payload.data.subscribed = false;145 payload.success(payload.data);146 };147 assert(!compose.validate_stream_message_address_info("Frontend"));148 assert.equal($("#compose-error-msg").html(), "compose_not_subscribed_stub");149 channel.post = (payload) => {150 assert.equal(payload.data.stream, "Frontend");151 payload.error({status: 404});152 };153 assert(!compose.validate_stream_message_address_info("Frontend"));154 assert.equal(155 $("#compose-error-msg").html(),156 "translated: <p>The stream <b>Frontend</b> does not exist.</p><p>Manage your subscriptions <a href='#streams/all'>on your Streams page</a>.</p>",157 );158 channel.post = (payload) => {159 assert.equal(payload.data.stream, "social");160 payload.error({status: 500});161 };162 assert(!compose.validate_stream_message_address_info("social"));163 assert.equal($("#compose-error-msg").html(), i18n.t("Error checking subscription"));164});165test_ui("validate", () => {166 function initialize_pm_pill() {167 reset_jquery();168 $("#compose-send-button").prop("disabled", false);169 $("#compose-send-button").trigger("focus");170 $("#sending-indicator").hide();171 const pm_pill_container = $.create("fake-pm-pill-container");172 $("#private_message_recipient")[0] = {};173 $("#private_message_recipient").set_parent(pm_pill_container);174 pm_pill_container.set_find_results(".input", $("#private_message_recipient"));175 $("#private_message_recipient").before = noop;176 compose_pm_pill.initialize();177 ui_util.place_caret_at_end = noop;178 $("#zephyr-mirror-error").is = noop;179 stub_templates((fn) => {180 assert.equal(fn, "input_pill");181 return "<div>pill-html</div>";182 });183 }184 function add_content_to_compose_box() {185 $("#compose-textarea").val("foobarfoobar");186 }187 initialize_pm_pill();188 assert(!compose.validate());189 assert(!$("#sending-indicator").visible());190 assert(!$("#compose-send-button").is_focused());191 assert.equal($("#compose-send-button").prop("disabled"), false);192 assert.equal($("#compose-error-msg").html(), i18n.t("You have nothing to send!"));193 reminder.is_deferred_delivery = () => true;194 compose.validate();195 assert.equal($("#sending-indicator").text(), "translated: Scheduling...");196 reminder.is_deferred_delivery = noop;197 add_content_to_compose_box();198 let zephyr_checked = false;199 $("#zephyr-mirror-error").is = () => {200 if (!zephyr_checked) {201 zephyr_checked = true;202 return true;203 }204 return false;205 };206 assert(!compose.validate());207 assert(zephyr_checked);208 assert.equal(209 $("#compose-error-msg").html(),210 i18n.t("You need to be running Zephyr mirroring in order to send messages!"),211 );212 initialize_pm_pill();213 add_content_to_compose_box();214 // test validating private messages215 compose_state.set_message_type("private");216 compose_state.private_message_recipient("");217 assert(!compose.validate());218 assert.equal(219 $("#compose-error-msg").html(),220 i18n.t("Please specify at least one valid recipient"),221 );222 initialize_pm_pill();223 add_content_to_compose_box();224 compose_state.private_message_recipient("foo@zulip.com");225 assert(!compose.validate());226 assert.equal(227 $("#compose-error-msg").html(),228 i18n.t("Please specify at least one valid recipient", {}),229 );230 compose_state.private_message_recipient("foo@zulip.com,alice@zulip.com");231 assert(!compose.validate());232 assert.equal(233 $("#compose-error-msg").html(),234 i18n.t("Please specify at least one valid recipient", {}),235 );236 people.add_active_user(bob);237 compose_state.private_message_recipient("bob@example.com");238 assert(compose.validate());239 page_params.realm_is_zephyr_mirror_realm = true;240 assert(compose.validate());241 page_params.realm_is_zephyr_mirror_realm = false;242 compose_state.set_message_type("stream");243 compose_state.stream_name("");244 assert(!compose.validate());245 assert.equal($("#compose-error-msg").html(), i18n.t("Please specify a stream"));246 compose_state.stream_name("Denmark");247 page_params.realm_mandatory_topics = true;248 compose_state.topic("");249 assert(!compose.validate());250 assert.equal($("#compose-error-msg").html(), i18n.t("Please specify a topic"));251});252test_ui("get_invalid_recipient_emails", (override) => {253 const welcome_bot = {254 email: "welcome-bot@example.com",255 user_id: 124,256 full_name: "Welcome Bot",257 };258 page_params.user_id = 30;259 const params = {};260 params.realm_users = [];261 params.realm_non_active_users = [];262 params.cross_realm_bots = [welcome_bot];263 people.initialize(page_params.user_id, params);264 override(compose_state, "private_message_recipient", () => "welcome-bot@example.com");265 assert.deepEqual(compose.get_invalid_recipient_emails(), []);266});267test_ui("test_wildcard_mention_allowed", () => {268 page_params.realm_wildcard_mention_policy =269 settings_config.wildcard_mention_policy_values.by_everyone.code;270 page_params.is_guest = true;271 page_params.is_admin = false;272 assert(compose.wildcard_mention_allowed());273 page_params.realm_wildcard_mention_policy =274 settings_config.wildcard_mention_policy_values.nobody.code;275 page_params.is_admin = true;276 assert(!compose.wildcard_mention_allowed());277 page_params.realm_wildcard_mention_policy =278 settings_config.wildcard_mention_policy_values.by_members.code;279 page_params.is_guest = true;280 page_params.is_admin = false;281 assert(!compose.wildcard_mention_allowed());282 page_params.is_guest = false;283 assert(compose.wildcard_mention_allowed());284 page_params.realm_wildcard_mention_policy =285 settings_config.wildcard_mention_policy_values.by_stream_admins_only.code;286 page_params.is_admin = false;287 assert(!compose.wildcard_mention_allowed());288 // TODO: Add a by_admins_only case when we implement stream-level administrators.289 page_params.is_admin = true;290 assert(compose.wildcard_mention_allowed());291 page_params.realm_wildcard_mention_policy =292 settings_config.wildcard_mention_policy_values.by_full_members.code;293 const person = people.get_by_user_id(page_params.user_id);294 person.date_joined = new Date(Date.now());295 page_params.realm_waiting_period_threshold = 10;296 assert(compose.wildcard_mention_allowed());297 page_params.is_admin = false;298 assert(!compose.wildcard_mention_allowed());299});300test_ui("validate_stream_message", (override) => {301 // This test is in kind of continuation to test_validate but since it is302 // primarily used to get coverage over functions called from validate()303 // we are separating it up in different test. Though their relative position304 // of execution should not be changed.305 page_params.realm_mandatory_topics = false;306 const sub = {307 stream_id: 101,308 name: "social",309 subscribed: true,310 };311 stream_data.add_sub(sub);312 compose_state.stream_name("social");313 assert(compose.validate());314 assert(!$("#compose-all-everyone").visible());315 assert(!$("#compose-send-status").visible());316 peer_data.get_subscriber_count = (stream_id) => {317 assert.equal(stream_id, 101);318 return 16;319 };320 stub_templates((template_name, data) => {321 assert.equal(template_name, "compose_all_everyone");322 assert.equal(data.count, 16);323 return "compose_all_everyone_stub";324 });325 let compose_content;326 $("#compose-all-everyone").append = (data) => {327 compose_content = data;328 };329 override(compose, "wildcard_mention_allowed", () => true);330 compose_state.message_content("Hey @**all**");331 assert(!compose.validate());332 assert.equal($("#compose-send-button").prop("disabled"), false);333 assert(!$("#compose-send-status").visible());334 assert.equal(compose_content, "compose_all_everyone_stub");335 assert($("#compose-all-everyone").visible());336 override(compose, "wildcard_mention_allowed", () => false);337 assert(!compose.validate());338 assert.equal(339 $("#compose-error-msg").html(),340 i18n.t("You do not have permission to use wildcard mentions in this stream."),341 );342});343test_ui("test_validate_stream_message_post_policy_admin_only", () => {344 // This test is in continuation with test_validate but it has been separated out345 // for better readability. Their relative position of execution should not be changed.346 // Although the position with respect to test_validate_stream_message does not matter347 // as different stream is used for this test.348 page_params.is_admin = false;349 const sub = {350 stream_id: 102,351 name: "stream102",352 subscribed: true,353 stream_post_policy: stream_data.stream_post_policy_values.admins.code,354 };355 compose_state.topic("subject102");356 compose_state.stream_name("stream102");357 stream_data.add_sub(sub);358 assert(!compose.validate());359 assert.equal(360 $("#compose-error-msg").html(),361 i18n.t("Only organization admins are allowed to post to this stream."),362 );363 // Reset error message.364 compose_state.stream_name("social");365 page_params.is_admin = false;366 page_params.is_guest = true;367 compose_state.topic("subject102");368 compose_state.stream_name("stream102");369 assert(!compose.validate());370 assert.equal(371 $("#compose-error-msg").html(),372 i18n.t("Only organization admins are allowed to post to this stream."),373 );374});375test_ui("test_validate_stream_message_post_policy_full_members_only", () => {376 page_params.is_admin = false;377 page_params.is_guest = true;378 const sub = {379 stream_id: 103,380 name: "stream103",381 subscribed: true,382 stream_post_policy: stream_data.stream_post_policy_values.non_new_members.code,383 };384 compose_state.topic("subject103");385 compose_state.stream_name("stream103");386 stream_data.add_sub(sub);387 assert(!compose.validate());388 assert.equal(389 $("#compose-error-msg").html(),390 i18n.t("Guests are not allowed to post to this stream."),391 );392 // reset compose_state.stream_name to 'social' again so that any tests occurring after this393 // do not reproduce this error.394 compose_state.stream_name("social");395 // Reset page_params396 page_params.is_guest = false;397});398test_ui("markdown_rtl", (override) => {399 const textarea = $("#compose-textarea");400 const event = {401 keyCode: 65, // A402 };403 override(rtl, "get_direction", (text) => {404 assert.equal(text, " foo");405 return "rtl";406 });407 assert.equal(textarea.hasClass("rtl"), false);408 textarea.val("```quote foo");409 compose.handle_keyup(event, $("#compose-textarea"));410 assert.equal(textarea.hasClass("rtl"), true);411});412test_ui("markdown_ltr", () => {413 const textarea = $("#compose-textarea");414 const event = {415 keyCode: 65, // A416 };417 assert.equal(textarea.hasClass("rtl"), true);418 textarea.val("```quote foo");419 compose.handle_keyup(event, textarea);420 assert.equal(textarea.hasClass("rtl"), false);421});422test_ui("markdown_shortcuts", () => {423 let queryCommandEnabled = true;424 const event = {425 keyCode: 66,426 target: {427 id: "compose-textarea",428 },429 stopPropagation: noop,430 preventDefault: noop,431 };432 let input_text = "";433 let range_start = 0;434 let range_length = 0;435 let compose_value = $("#compose_textarea").val();436 let selected_word = "";437 document.queryCommandEnabled = () => queryCommandEnabled;438 document.execCommand = (cmd, bool, markdown) => {439 const compose_textarea = $("#compose-textarea");440 const value = compose_textarea.val();441 $("#compose-textarea").val(442 value.slice(0, compose_textarea.range().start) +443 markdown +444 value.slice(compose_textarea.range().end),445 );446 };447 $("#compose-textarea")[0] = {};448 $("#compose-textarea").range = () => ({449 start: range_start,450 end: range_start + range_length,451 length: range_length,452 range: noop,453 text: $("#compose-textarea")454 .val()455 .slice(range_start, range_length + range_start),456 });457 $("#compose-textarea").caret = noop;458 function test_i_typed(isCtrl, isCmd) {459 // Test 'i' is typed correctly.460 $("#compose-textarea").val("i");461 event.keyCode = undefined;462 event.which = 73;463 event.metaKey = isCmd;464 event.ctrlKey = isCtrl;465 compose.handle_keydown(event, $("#compose-textarea"));466 assert.equal("i", $("#compose-textarea").val());467 }468 function all_markdown_test(isCtrl, isCmd) {469 input_text = "Any text.";470 $("#compose-textarea").val(input_text);471 compose_value = $("#compose-textarea").val();472 // Select "text" word in compose box.473 selected_word = "text";474 range_start = compose_value.search(selected_word);475 range_length = selected_word.length;476 // Test bold:477 // Mac env = Cmd+b478 // Windows/Linux = Ctrl+b479 event.keyCode = 66;480 event.ctrlKey = isCtrl;481 event.metaKey = isCmd;482 compose.handle_keydown(event, $("#compose-textarea"));483 assert.equal("Any **text**.", $("#compose-textarea").val());484 // Test if no text is selected.485 range_start = 0;486 // Change cursor to first position.487 range_length = 0;488 compose.handle_keydown(event, $("#compose-textarea"));489 assert.equal("****Any **text**.", $("#compose-textarea").val());490 // Test italic:491 // Mac = Cmd+I492 // Windows/Linux = Ctrl+I493 $("#compose-textarea").val(input_text);494 range_start = compose_value.search(selected_word);495 range_length = selected_word.length;496 event.keyCode = 73;497 event.shiftKey = false;498 compose.handle_keydown(event, $("#compose-textarea"));499 assert.equal("Any *text*.", $("#compose-textarea").val());500 // Test if no text is selected.501 range_length = 0;502 // Change cursor to first position.503 range_start = 0;504 compose.handle_keydown(event, $("#compose-textarea"));505 assert.equal("**Any *text*.", $("#compose-textarea").val());506 // Test link insertion:507 // Mac = Cmd+Shift+L508 // Windows/Linux = Ctrl+Shift+L509 $("#compose-textarea").val(input_text);510 range_start = compose_value.search(selected_word);511 range_length = selected_word.length;512 event.keyCode = 76;513 event.which = undefined;514 event.shiftKey = true;515 compose.handle_keydown(event, $("#compose-textarea"));516 assert.equal("Any [text](url).", $("#compose-textarea").val());517 // Test if exec command is not enabled in browser.518 queryCommandEnabled = false;519 compose.handle_keydown(event, $("#compose-textarea"));520 }521 // This function cross tests the Cmd/Ctrl + Markdown shortcuts in522 // Mac and Linux/Windows environments. So in short, this tests523 // that e.g. Cmd+B should be ignored on Linux/Windows and Ctrl+B524 // should be ignored on Mac.525 function os_specific_markdown_test(isCtrl, isCmd) {526 input_text = "Any text.";527 $("#compose-textarea").val(input_text);528 compose_value = $("#compose-textarea").val();529 selected_word = "text";530 range_start = compose_value.search(selected_word);531 range_length = selected_word.length;532 event.metaKey = isCmd;533 event.ctrlKey = isCtrl;534 event.keyCode = 66;535 compose.handle_keydown(event, $("#compose-textarea"));536 assert.equal(input_text, $("#compose-textarea").val());537 event.keyCode = 73;538 event.shiftKey = false;539 compose.handle_keydown(event, $("#compose-textarea"));540 assert.equal(input_text, $("#compose-textarea").val());541 event.keyCode = 76;542 event.shiftKey = true;543 compose.handle_keydown(event, $("#compose-textarea"));544 assert.equal(input_text, $("#compose-textarea").val());545 }546 // These keyboard shortcuts differ as to what key one should use547 // on MacOS vs. other platforms: Cmd (Mac) vs. Ctrl (non-Mac).548 // Default (Linux/Windows) userAgent tests:549 test_i_typed(false, false);550 // Check all the Ctrl + Markdown shortcuts work correctly551 all_markdown_test(true, false);552 // The Cmd + Markdown shortcuts should do nothing on Linux/Windows553 os_specific_markdown_test(false, true);554 // Setting following platform to test in mac env555 _navigator.platform = "MacIntel";556 // Mac userAgent tests:557 test_i_typed(false, false);558 // The Ctrl + Markdown shortcuts should do nothing on mac559 os_specific_markdown_test(true, false);560 // Check all the Cmd + Markdown shortcuts work correctly561 all_markdown_test(false, true);562 // Reset userAgent563 _navigator.userAgent = "";564});565test_ui("send_message_success", () => {566 $("#compose-textarea").val("foobarfoobar");567 $("#compose-textarea").trigger("blur");568 $("#compose-send-status").show();569 $("#compose-send-button").prop("disabled", true);570 $("#sending-indicator").show();571 let reify_message_id_checked;572 echo.reify_message_id = (local_id, message_id) => {573 assert.equal(local_id, "1001");574 assert.equal(message_id, 12);575 reify_message_id_checked = true;576 };577 compose.send_message_success("1001", 12, false);578 assert.equal($("#compose-textarea").val(), "");579 assert($("#compose-textarea").is_focused());580 assert(!$("#compose-send-status").visible());581 assert.equal($("#compose-send-button").prop("disabled"), false);582 assert(!$("#sending-indicator").visible());583 assert(reify_message_id_checked);584});585test_ui("send_message", (override) => {586 // This is the common setup stuff for all of the four tests.587 let stub_state;588 function initialize_state_stub_dict() {589 stub_state = {};590 stub_state.send_msg_called = 0;591 stub_state.get_events_running_called = 0;592 stub_state.reify_message_id_checked = 0;593 return stub_state;594 }595 set_global("setTimeout", (func) => {596 func();597 });598 override(server_events, "assert_get_events_running", () => {599 stub_state.get_events_running_called += 1;600 });601 // Tests start here.602 (function test_message_send_success_codepath() {603 stub_state = initialize_state_stub_dict();604 compose_state.topic("");605 compose_state.set_message_type("private");606 page_params.user_id = 101;607 override(compose_state, "private_message_recipient", () => "alice@example.com");608 const server_message_id = 127;609 local_message.insert_message = (message) => {610 assert.equal(message.timestamp, fake_now);611 };612 markdown.apply_markdown = () => {};613 markdown.add_topic_links = () => {};614 echo.try_deliver_locally = (message_request) => {615 const local_id_float = 123.04;616 return echo.insert_local_message(message_request, local_id_float);617 };618 transmit.send_message = (payload, success) => {619 const single_msg = {620 type: "private",621 content: "[foobar](/user_uploads/123456)",622 sender_id: 101,623 queue_id: undefined,624 stream: "",625 topic: "",626 to: `[${alice.user_id}]`,627 reply_to: "alice@example.com",628 private_message_recipient: "alice@example.com",629 to_user_ids: "31",630 local_id: "123.04",631 locally_echoed: true,632 };633 assert.deepEqual(payload, single_msg);634 payload.id = server_message_id;635 success(payload);636 stub_state.send_msg_called += 1;637 };638 echo.reify_message_id = (local_id, message_id) => {639 assert.equal(typeof local_id, "string");640 assert.equal(typeof message_id, "number");641 assert.equal(message_id, server_message_id);642 stub_state.reify_message_id_checked += 1;643 };644 // Setting message content with a host server link and we will assert645 // later that this has been converted to a relative link.646 $("#compose-textarea").val("[foobar](https://foo.com/user_uploads/123456)");647 $("#compose-textarea").trigger("blur");648 $("#compose-send-status").show();649 $("#compose-send-button").prop("disabled", true);650 $("#sending-indicator").show();651 compose.send_message();652 const state = {653 get_events_running_called: 1,654 reify_message_id_checked: 1,655 send_msg_called: 1,656 };657 assert.deepEqual(stub_state, state);658 assert.equal($("#compose-textarea").val(), "");659 assert($("#compose-textarea").is_focused());660 assert(!$("#compose-send-status").visible());661 assert.equal($("#compose-send-button").prop("disabled"), false);662 assert(!$("#sending-indicator").visible());663 })();664 // This is the additional setup which is common to both the tests below.665 transmit.send_message = (payload, success, error) => {666 stub_state.send_msg_called += 1;667 error("Error sending message: Server says 408");668 };669 let echo_error_msg_checked;670 echo.message_send_error = (local_id, error_response) => {671 assert.equal(local_id, 123.04);672 assert.equal(error_response, "Error sending message: Server says 408");673 echo_error_msg_checked = true;674 };675 // Tests start here.676 (function test_param_error_function_passed_from_send_message() {677 stub_state = initialize_state_stub_dict();678 compose.send_message();679 const state = {680 get_events_running_called: 1,681 reify_message_id_checked: 0,682 send_msg_called: 1,683 };684 assert.deepEqual(stub_state, state);685 assert(echo_error_msg_checked);686 })();687 (function test_error_codepath_local_id_undefined() {688 stub_state = initialize_state_stub_dict();689 $("#compose-textarea").val("foobarfoobar");690 $("#compose-textarea").trigger("blur");691 $("#compose-send-status").show();692 $("#compose-send-button").prop("disabled", true);693 $("#sending-indicator").show();694 $("#compose-textarea").off("select");695 echo_error_msg_checked = false;696 echo.try_deliver_locally = () => {};697 sent_messages.get_new_local_id = () => "loc-55";698 compose.send_message();699 const state = {700 get_events_running_called: 1,701 reify_message_id_checked: 0,702 send_msg_called: 1,703 };704 assert.deepEqual(stub_state, state);705 assert(!echo_error_msg_checked);706 assert.equal($("#compose-send-button").prop("disabled"), false);707 assert.equal($("#compose-error-msg").html(), "Error sending message: Server says 408");708 assert.equal($("#compose-textarea").val(), "foobarfoobar");709 assert($("#compose-textarea").is_focused());710 assert($("#compose-send-status").visible());711 assert.equal($("#compose-send-button").prop("disabled"), false);712 assert(!$("#sending-indicator").visible());713 })();714});715test_ui("enter_with_preview_open", (override) => {716 // Test sending a message with content.717 compose_state.set_message_type("stream");718 $("#compose-textarea").val("message me");719 $("#compose-textarea").hide();720 $("#undo_markdown_preview").show();721 $("#preview_message_area").show();722 $("#markdown_preview").hide();723 page_params.enter_sends = true;724 let send_message_called = false;725 override(compose, "send_message", () => {726 send_message_called = true;727 });728 compose.enter_with_preview_open();729 assert($("#compose-textarea").visible());730 assert(!$("#undo_markdown_preview").visible());731 assert(!$("#preview_message_area").visible());732 assert($("#markdown_preview").visible());733 assert(send_message_called);734 page_params.enter_sends = false;735 $("#compose-textarea").trigger("blur");736 compose.enter_with_preview_open();737 assert($("#compose-textarea").is_focused());738 // Test sending a message without content.739 $("#compose-textarea").val("");740 $("#preview_message_area").show();741 $("#enter_sends").prop("checked", true);742 page_params.enter_sends = true;743 compose.enter_with_preview_open();744 assert($("#enter_sends").prop("checked"));745 assert.equal($("#compose-error-msg").html(), i18n.t("You have nothing to send!"));746});747test_ui("finish", (override) => {748 (function test_when_compose_validation_fails() {749 $("#compose_invite_users").show();750 $("#compose-send-button").prop("disabled", false);751 $("#compose-send-button").trigger("focus");752 $("#sending-indicator").hide();753 $("#compose-textarea").off("select");754 $("#compose-textarea").val("");755 const res = compose.finish();756 assert.equal(res, false);757 assert(!$("#compose_invite_users").visible());758 assert(!$("#sending-indicator").visible());759 assert(!$("#compose-send-button").is_focused());760 assert.equal($("#compose-send-button").prop("disabled"), false);761 assert.equal($("#compose-error-msg").html(), i18n.t("You have nothing to send!"));762 })();763 (function test_when_compose_validation_succeed() {764 $("#compose-textarea").hide();765 $("#undo_markdown_preview").show();766 $("#preview_message_area").show();767 $("#markdown_preview").hide();768 $("#compose-textarea").val("foobarfoobar");769 compose_state.set_message_type("private");770 override(compose_state, "private_message_recipient", () => "bob@example.com");771 let compose_finished_event_checked = false;772 $(document).on("compose_finished.zulip", () => {773 compose_finished_event_checked = true;774 });775 let send_message_called = false;776 override(compose, "send_message", () => {777 send_message_called = true;778 });779 assert(compose.finish());780 assert($("#compose-textarea").visible());781 assert(!$("#undo_markdown_preview").visible());782 assert(!$("#preview_message_area").visible());783 assert($("#markdown_preview").visible());784 assert(send_message_called);785 assert(compose_finished_event_checked);786 })();787});788test_ui("warn_if_private_stream_is_linked", () => {789 const test_sub = {790 name: compose_state.stream_name(),791 stream_id: 99,792 };793 stream_data.add_sub(test_sub);794 peer_data.set_subscribers(test_sub.stream_id, [1, 2]);795 let denmark = {796 stream_id: 100,797 name: "Denmark",798 };799 stream_data.add_sub(denmark);800 peer_data.set_subscribers(denmark.stream_id, [1, 2, 3]);801 function test_noop_case(invite_only) {802 compose_state.set_message_type("stream");803 denmark.invite_only = invite_only;804 compose.warn_if_private_stream_is_linked(denmark);805 assert.equal($("#compose_private_stream_alert").visible(), false);806 }807 test_noop_case(false);808 // invite_only=true and current compose stream subscribers are a subset809 // of mentioned_stream subscribers.810 test_noop_case(true);811 $("#compose_private").hide();812 compose_state.set_message_type("stream");813 const checks = [814 (function () {815 let called;816 stub_templates((template_name, context) => {817 called = true;818 assert.equal(template_name, "compose_private_stream_alert");819 assert.equal(context.stream_name, "Denmark");820 return "fake-compose_private_stream_alert-template";821 });822 return function () {823 assert(called);824 };825 })(),826 (function () {827 let called;828 $("#compose_private_stream_alert").append = (html) => {829 called = true;830 assert.equal(html, "fake-compose_private_stream_alert-template");831 };832 return function () {833 assert(called);834 };835 })(),836 ];837 denmark = {838 invite_only: true,839 name: "Denmark",840 stream_id: 22,841 };842 stream_data.add_sub(denmark);843 compose.warn_if_private_stream_is_linked(denmark);844 assert.equal($("#compose_private_stream_alert").visible(), true);845 for (const f of checks) {846 f();847 }848});849test_ui("initialize", (override) => {850 // In this test we mostly do the setup stuff in addition to testing the851 // normal workflow of the function. All the tests for the on functions are852 // done in subsequent tests directly below this test.853 override(compose, "compute_show_video_chat_button", () => false);854 let resize_watch_manual_resize_checked = false;855 resize.watch_manual_resize = (elem) => {856 assert.equal("#compose-textarea", elem);857 resize_watch_manual_resize_checked = true;858 };859 let xmlhttprequest_checked = false;860 set_global("XMLHttpRequest", function () {861 this.upload = true;862 xmlhttprequest_checked = true;863 });864 $("#compose #attach_files").addClass("notdisplayed");865 set_global("document", "document-stub");866 set_global("csrf_token", "fake-csrf-token");867 page_params.max_file_upload_size_mib = 512;868 let setup_upload_called = false;869 let uppy_cancel_all_called = false;870 override(upload, "setup_upload", (config) => {871 assert.equal(config.mode, "compose");872 setup_upload_called = true;873 return {874 cancelAll: () => {875 uppy_cancel_all_called = true;876 },877 };878 });879 compose.initialize();880 assert(resize_watch_manual_resize_checked);881 assert(xmlhttprequest_checked);882 assert(!$("#compose #attach_files").hasClass("notdisplayed"));883 assert(setup_upload_called);884 function set_up_compose_start_mock(expected_opts) {885 compose_actions_start_checked = false;886 compose_actions_expected_opts = expected_opts;887 }888 (function test_page_params_narrow_path() {889 page_params.narrow = true;890 reset_jquery();891 set_up_compose_start_mock({});892 compose.initialize();893 assert(compose_actions_start_checked);894 })();895 (function test_page_params_narrow_topic() {896 page_params.narrow_topic = "testing";897 reset_jquery();898 set_up_compose_start_mock({topic: "testing"});899 compose.initialize();900 assert(compose_actions_start_checked);901 })();902 (function test_abort_xhr() {903 $("#compose-send-button").prop("disabled", true);904 reset_jquery();905 compose.initialize();906 compose.abort_xhr();907 assert.equal($("#compose-send-button").attr(), undefined);908 assert(uppy_cancel_all_called);909 })();910});911test_ui("update_fade", (override) => {912 const selector =913 "#stream_message_recipient_stream,#stream_message_recipient_topic,#private_message_recipient";914 const keyup_handler_func = $(selector).get_on_handler("keyup");915 let set_focused_recipient_checked = false;916 let update_all_called = false;917 override(compose_fade, "set_focused_recipient", (msg_type) => {918 assert.equal(msg_type, "private");919 set_focused_recipient_checked = true;920 });921 override(compose_fade, "update_all", () => {922 update_all_called = true;923 });924 compose_state.set_message_type(false);925 keyup_handler_func();926 assert(!set_focused_recipient_checked);927 assert(!update_all_called);928 compose_state.set_message_type("private");929 keyup_handler_func();930 assert(set_focused_recipient_checked);931 assert(update_all_called);932});933test_ui("trigger_submit_compose_form", (override) => {934 let prevent_default_checked = false;935 let compose_finish_checked = false;936 const e = {937 preventDefault() {938 prevent_default_checked = true;939 },940 };941 override(compose, "finish", () => {942 compose_finish_checked = true;943 });944 const submit_handler = $("#compose form").get_on_handler("submit");945 submit_handler(e);946 assert(prevent_default_checked);947 assert(compose_finish_checked);948});949test_ui("needs_subscribe_warning", () => {950 const invalid_user_id = 999;951 const test_bot = {952 full_name: "Test Bot",953 email: "test-bot@example.com",954 user_id: 135,955 is_bot: true,956 };957 people.add_active_user(test_bot);958 const sub = {959 stream_id: 110,960 name: "stream",961 can_access_subscribers: true,962 };963 stream_data.add_sub(sub);964 peer_data.set_subscribers(sub.stream_id, [bob.user_id, me.user_id]);965 blueslip.expect("error", "Unknown user_id in get_by_user_id: 999");966 // Test with an invalid user id.967 assert.equal(compose.needs_subscribe_warning(invalid_user_id, sub.stream_id), false);968 // Test with bot user.969 assert.equal(compose.needs_subscribe_warning(test_bot.user_id, sub.stream_id), false);970 // Test when user is subscribed to the stream.971 assert.equal(compose.needs_subscribe_warning(bob.user_id, sub.stream_id), false);972 peer_data.remove_subscriber(sub.stream_id, bob.user_id);973 // Test when the user is not subscribed.974 assert.equal(compose.needs_subscribe_warning(bob.user_id, sub.stream_id), true);975});976test_ui("warn_if_mentioning_unsubscribed_user", (override) => {977 let mentioned = {978 email: "foo@bar.com",979 };980 $("#compose_invite_users .compose_invite_user").length = 0;981 function test_noop_case(is_private, is_zephyr_mirror, is_broadcast) {982 const msg_type = is_private ? "private" : "stream";983 compose_state.set_message_type(msg_type);984 page_params.realm_is_zephyr_mirror_realm = is_zephyr_mirror;985 mentioned.is_broadcast = is_broadcast;986 compose.warn_if_mentioning_unsubscribed_user(mentioned);987 assert.equal($("#compose_invite_users").visible(), false);988 }989 test_noop_case(true, false, false);990 test_noop_case(false, true, false);991 test_noop_case(false, false, true);992 $("#compose_invite_users").hide();993 compose_state.set_message_type("stream");994 page_params.realm_is_zephyr_mirror_realm = false;995 // Test with empty stream name in compose box. It should return noop.996 assert.equal(compose_state.stream_name(), "");997 compose.warn_if_mentioning_unsubscribed_user(mentioned);998 assert.equal($("#compose_invite_users").visible(), false);999 compose_state.stream_name("random");1000 const sub = {1001 stream_id: 111,1002 name: "random",1003 };1004 // Test with invalid stream in compose box. It should return noop.1005 compose.warn_if_mentioning_unsubscribed_user(mentioned);1006 assert.equal($("#compose_invite_users").visible(), false);1007 // Test mentioning a user that should gets a warning.1008 const checks = [1009 (function () {1010 let called;1011 override(compose, "needs_subscribe_warning", (user_id, stream_id) => {1012 called = true;1013 assert.equal(user_id, 34);1014 assert.equal(stream_id, 111);1015 return true;1016 });1017 return function () {1018 assert(called);1019 };1020 })(),1021 (function () {1022 let called;1023 stub_templates((template_name, context) => {1024 called = true;1025 assert.equal(template_name, "compose_invite_users");1026 assert.equal(context.user_id, 34);1027 assert.equal(context.stream_id, 111);1028 assert.equal(context.name, "Foo Barson");1029 return "fake-compose-invite-user-template";1030 });1031 return function () {1032 assert(called);1033 };1034 })(),1035 (function () {1036 let called;1037 $("#compose_invite_users").append = (html) => {1038 called = true;1039 assert.equal(html, "fake-compose-invite-user-template");1040 };1041 return function () {1042 assert(called);1043 };1044 })(),1045 ];1046 mentioned = {1047 email: "foo@bar.com",1048 user_id: 34,1049 full_name: "Foo Barson",1050 };1051 stream_data.add_sub(sub);1052 compose.warn_if_mentioning_unsubscribed_user(mentioned);1053 assert.equal($("#compose_invite_users").visible(), true);1054 for (const f of checks) {1055 f();1056 }1057 // Simulate that the row was added to the DOM.1058 const warning_row = $("<warning row>");1059 let looked_for_existing;1060 warning_row.data = (field) => {1061 if (field === "user-id") {1062 looked_for_existing = true;1063 return "34";1064 }1065 if (field === "stream-id") {1066 return "111";1067 }1068 throw new Error(`Unknown field ${field}`);1069 };1070 const previous_users = $("#compose_invite_users .compose_invite_user");1071 previous_users.length = 1;1072 previous_users[0] = warning_row;1073 $("#compose_invite_users").hide();1074 // Now try to mention the same person again. The template should1075 // not render.1076 stub_templates(noop);1077 compose.warn_if_mentioning_unsubscribed_user(mentioned);1078 assert.equal($("#compose_invite_users").visible(), true);1079 assert(looked_for_existing);1080});1081test_ui("on_events", (override) => {1082 function setup_parents_and_mock_remove(container_sel, target_sel, parent) {1083 const container = $.create("fake " + container_sel);1084 let container_removed = false;1085 container.remove = () => {1086 container_removed = true;1087 };1088 const target = $.create("fake click target (" + target_sel + ")");1089 target.set_parents_result(parent, container);1090 const event = {1091 preventDefault: noop,1092 target,1093 };1094 const helper = {1095 event,1096 container,1097 target,1098 container_was_removed: () => container_removed,1099 };1100 return helper;1101 }1102 (function test_compose_all_everyone_confirm_clicked() {1103 const handler = $("#compose-all-everyone").get_on_handler(1104 "click",1105 ".compose-all-everyone-confirm",1106 );1107 const helper = setup_parents_and_mock_remove(1108 "compose-all-everyone",1109 "compose-all-everyone",1110 ".compose-all-everyone",1111 );1112 $("#compose-all-everyone").show();1113 $("#compose-send-status").show();1114 let compose_finish_checked = false;1115 override(compose, "finish", () => {1116 compose_finish_checked = true;1117 });1118 handler(helper.event);1119 assert(helper.container_was_removed());1120 assert(compose_finish_checked);1121 assert(!$("#compose-all-everyone").visible());1122 assert(!$("#compose-send-status").visible());1123 })();1124 (function test_compose_invite_users_clicked() {1125 const handler = $("#compose_invite_users").get_on_handler("click", ".compose_invite_link");1126 const subscription = {1127 stream_id: 102,1128 name: "test",1129 subscribed: true,1130 };1131 const mentioned = {1132 full_name: "Foo Barson",1133 email: "foo@bar.com",1134 user_id: 34,1135 };1136 people.add_active_user(mentioned);1137 let invite_user_to_stream_called = false;1138 stream_edit.invite_user_to_stream = (user_ids, sub, success) => {1139 invite_user_to_stream_called = true;1140 assert.deepEqual(user_ids, [mentioned.user_id]);1141 assert.equal(sub, subscription);1142 success(); // This will check success callback path.1143 };1144 const helper = setup_parents_and_mock_remove(1145 "compose_invite_users",1146 "compose_invite_link",1147 ".compose_invite_user",1148 );1149 helper.container.data = (field) => {1150 if (field === "user-id") {1151 return "34";1152 }1153 if (field === "stream-id") {1154 return "102";1155 }1156 throw new Error(`Unknown field ${field}`);1157 };1158 helper.target.prop("disabled", false);1159 // !sub will result in true here and we check the success code path.1160 stream_data.add_sub(subscription);1161 $("#stream_message_recipient_stream").val("test");1162 let all_invite_children_called = false;1163 $("#compose_invite_users").children = () => {1164 all_invite_children_called = true;1165 return [];1166 };1167 $("#compose_invite_users").show();1168 handler(helper.event);1169 assert(helper.container_was_removed());1170 assert(!$("#compose_invite_users").visible());1171 assert(invite_user_to_stream_called);1172 assert(all_invite_children_called);1173 })();1174 (function test_compose_invite_close_clicked() {1175 const handler = $("#compose_invite_users").get_on_handler("click", ".compose_invite_close");1176 const helper = setup_parents_and_mock_remove(1177 "compose_invite_users_close",1178 "compose_invite_close",1179 ".compose_invite_user",1180 );1181 let all_invite_children_called = false;1182 $("#compose_invite_users").children = () => {1183 all_invite_children_called = true;1184 return [];1185 };1186 $("#compose_invite_users").show();1187 handler(helper.event);1188 assert(helper.container_was_removed());1189 assert(all_invite_children_called);1190 assert(!$("#compose_invite_users").visible());1191 })();1192 (function test_compose_not_subscribed_clicked() {1193 const handler = $("#compose-send-status").get_on_handler("click", ".sub_unsub_button");1194 const subscription = {1195 stream_id: 102,1196 name: "test",1197 subscribed: false,1198 };1199 let compose_not_subscribed_called = false;1200 subs.sub_or_unsub = () => {1201 compose_not_subscribed_called = true;1202 };1203 const helper = setup_parents_and_mock_remove(1204 "compose-send-status",1205 "sub_unsub_button",1206 ".compose_not_subscribed",1207 );1208 handler(helper.event);1209 assert(compose_not_subscribed_called);1210 stream_data.add_sub(subscription);1211 $("#stream_message_recipient_stream").val("test");1212 $("#compose-send-status").show();1213 handler(helper.event);1214 assert(!$("#compose-send-status").visible());1215 })();1216 (function test_compose_not_subscribed_close_clicked() {1217 const handler = $("#compose-send-status").get_on_handler(1218 "click",1219 "#compose_not_subscribed_close",1220 );1221 const helper = setup_parents_and_mock_remove(1222 "compose_user_not_subscribed_close",1223 "compose_not_subscribed_close",1224 ".compose_not_subscribed",1225 );1226 $("#compose-send-status").show();1227 handler(helper.event);1228 assert(!$("#compose-send-status").visible());1229 })();1230 (function test_attach_files_compose_clicked() {1231 const handler = $("#compose").get_on_handler("click", "#attach_files");1232 $("#file_input").clone = (param) => {1233 assert(param);1234 };1235 let compose_file_input_clicked = false;1236 $("#compose #file_input").on("click", () => {1237 compose_file_input_clicked = true;1238 });1239 const event = {1240 preventDefault: noop,1241 };1242 handler(event);1243 assert(compose_file_input_clicked);1244 })();1245 (function test_markdown_preview_compose_clicked() {1246 // Tests setup1247 function setup_visibilities() {1248 $("#compose-textarea").show();1249 $("#markdown_preview").show();1250 $("#undo_markdown_preview").hide();1251 $("#preview_message_area").hide();1252 }1253 function assert_visibilities() {1254 assert(!$("#compose-textarea").visible());1255 assert(!$("#markdown_preview").visible());1256 assert($("#undo_markdown_preview").visible());1257 assert($("#preview_message_area").visible());1258 }1259 function setup_mock_markdown_contains_backend_only_syntax(msg_content, return_val) {1260 markdown.contains_backend_only_syntax = (msg) => {1261 assert.equal(msg, msg_content);1262 return return_val;1263 };1264 }1265 function setup_mock_markdown_is_status_message(msg_content, return_val) {1266 markdown.is_status_message = (content) => {1267 assert.equal(content, msg_content);1268 return return_val;1269 };1270 }1271 function test_post_success(success_callback) {1272 const resp = {1273 rendered: "Server: foobarfoobar",1274 };1275 success_callback(resp);1276 assert.equal($("#preview_content").html(), "Server: foobarfoobar");1277 }1278 function test_post_error(error_callback) {1279 error_callback();1280 assert.equal($("#preview_content").html(), "translated: Failed to generate preview");1281 }1282 function mock_channel_post(msg) {1283 channel.post = (payload) => {1284 assert.equal(payload.url, "/json/messages/render");1285 assert(payload.idempotent);1286 assert(payload.data);1287 assert.deepEqual(payload.data.content, msg);1288 function test(func, param) {1289 let destroy_indicator_called = false;1290 loading.destroy_indicator = (spinner) => {1291 assert.equal(spinner, $("#markdown_preview_spinner"));1292 destroy_indicator_called = true;1293 };1294 setup_mock_markdown_contains_backend_only_syntax(msg, true);1295 func(param);1296 assert(destroy_indicator_called);1297 }1298 test(test_post_error, payload.error);1299 test(test_post_success, payload.success);1300 };1301 }1302 const handler = $("#compose").get_on_handler("click", "#markdown_preview");1303 // Tests start here1304 $("#compose-textarea").val("");1305 setup_visibilities();1306 const event = {1307 preventDefault: noop,1308 };1309 handler(event);1310 assert.equal($("#preview_content").html(), "translated: Nothing to preview");1311 assert_visibilities();1312 let make_indicator_called = false;1313 $("#compose-textarea").val("```foobarfoobar```");1314 setup_visibilities();1315 setup_mock_markdown_contains_backend_only_syntax("```foobarfoobar```", true);1316 setup_mock_markdown_is_status_message("```foobarfoobar```", false);1317 loading.make_indicator = (spinner) => {1318 assert.equal(spinner.selector, "#markdown_preview_spinner");1319 make_indicator_called = true;1320 };1321 mock_channel_post("```foobarfoobar```");1322 handler(event);1323 assert(make_indicator_called);1324 assert_visibilities();1325 let apply_markdown_called = false;1326 $("#compose-textarea").val("foobarfoobar");1327 setup_visibilities();1328 setup_mock_markdown_contains_backend_only_syntax("foobarfoobar", false);1329 setup_mock_markdown_is_status_message("foobarfoobar", false);1330 mock_channel_post("foobarfoobar");1331 markdown.apply_markdown = (msg) => {1332 assert.equal(msg.raw_content, "foobarfoobar");1333 apply_markdown_called = true;1334 return msg;1335 };1336 handler(event);1337 assert(apply_markdown_called);1338 assert_visibilities();1339 assert.equal($("#preview_content").html(), "Server: foobarfoobar");1340 })();1341 (function test_undo_markdown_preview_clicked() {1342 const handler = $("#compose").get_on_handler("click", "#undo_markdown_preview");1343 $("#compose-textarea").hide();1344 $("#undo_markdown_preview").show();1345 $("#preview_message_area").show();1346 $("#markdown_preview").hide();1347 const event = {1348 preventDefault: noop,1349 };1350 handler(event);1351 assert($("#compose-textarea").visible());1352 assert(!$("#undo_markdown_preview").visible());1353 assert(!$("#preview_message_area").visible());1354 assert($("#markdown_preview").visible());1355 })();1356});1357test_ui("create_message_object", (override) => {1358 const sub = {1359 stream_id: 101,1360 name: "social",1361 subscribed: true,1362 };1363 stream_data.add_sub(sub);1364 $("#stream_message_recipient_stream").val("social");1365 $("#stream_message_recipient_topic").val("lunch");1366 $("#compose-textarea").val("burrito");1367 override(compose_state, "get_message_type", () => "stream");1368 let message = compose.create_message_object();1369 assert.equal(message.to, sub.stream_id);1370 assert.equal(message.topic, "lunch");1371 assert.equal(message.content, "burrito");1372 blueslip.expect("error", "Trying to send message with bad stream name: BOGUS STREAM");1373 $("#stream_message_recipient_stream").val("BOGUS STREAM");1374 message = compose.create_message_object();1375 assert.equal(message.to, "BOGUS STREAM");1376 assert.equal(message.topic, "lunch");1377 assert.equal(message.content, "burrito");1378 override(compose_state, "get_message_type", () => "private");1379 compose_state.__Rewire__(1380 "private_message_recipient",1381 () => "alice@example.com, bob@example.com",1382 );1383 message = compose.create_message_object();1384 assert.deepEqual(message.to, [alice.user_id, bob.user_id]);1385 assert.equal(message.to_user_ids, "31,32");1386 assert.equal(message.content, "burrito");1387 const {email_list_to_user_ids_string} = people;1388 people.email_list_to_user_ids_string = () => undefined;1389 message = compose.create_message_object();1390 assert.deepEqual(message.to, [alice.email, bob.email]);1391 people.email_list_to_user_ids_string = email_list_to_user_ids_string;1392});1393test_ui("nonexistent_stream_reply_error", () => {1394 reset_jquery();1395 const actions = [];1396 $("#nonexistent_stream_reply_error").show = () => {1397 actions.push("show");1398 };1399 $("#nonexistent_stream_reply_error").hide = () => {1400 actions.push("hide");1401 };1402 compose.nonexistent_stream_reply_error();1403 assert.equal($("#compose-reply-error-msg").html(), "There are no messages to reply to yet.");1404 assert.deepEqual(actions, ["show", "hide"]);1405});1406test_ui("narrow_button_titles", () => {1407 util.is_mobile = () => false;1408 compose.update_closed_compose_buttons_for_private();1409 assert.equal($("#left_bar_compose_stream_button_big").text(), i18n.t("New stream message"));1410 assert.equal($("#left_bar_compose_private_button_big").text(), i18n.t("New private message"));1411 compose.update_closed_compose_buttons_for_stream();1412 assert.equal($("#left_bar_compose_stream_button_big").text(), i18n.t("New topic"));1413 assert.equal($("#left_bar_compose_private_button_big").text(), i18n.t("New private message"));1414});...
test_docker.py
Source:test_docker.py
1# Licensed to the Apache Software Foundation (ASF) under one2# or more contributor license agreements. See the NOTICE file3# distributed with this work for additional information4# regarding copyright ownership. The ASF licenses this file5# to you under the Apache License, Version 2.0 (the6# "License"); you may not use this file except in compliance7# with the License. You may obtain a copy of the License at8#9# http://www.apache.org/licenses/LICENSE-2.010#11# Unless required by applicable law or agreed to in writing,12# software distributed under the License is distributed on an13# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY14# KIND, either express or implied. See the License for the15# specific language governing permissions and limitations16# under the License.17import collections18import os19import re20import subprocess21from unittest import mock22import pytest23from archery.docker import DockerCompose24from archery.testing import assert_subprocess_calls, override_env, PartialEnv25missing_service_compose_yml = """26version: '3.5'27x-hierarchy:28 - foo:29 - sub-foo:30 - sub-sub-foo31 - another-sub-sub-foo32 - bar:33 - sub-bar34 - baz35services:36 foo:37 image: org/foo38 sub-sub-foo:39 image: org/sub-sub-foo40 another-sub-sub-foo:41 image: org/another-sub-sub-foo42 bar:43 image: org/bar44 sub-bar:45 image: org/sub-bar46 baz:47 image: org/baz48"""49missing_node_compose_yml = """50version: '3.5'51x-hierarchy:52 - foo:53 - sub-foo:54 - sub-sub-foo55 - another-sub-sub-foo56 - bar57 - baz58services:59 foo:60 image: org/foo61 sub-foo:62 image: org/sub-foo63 sub-sub-foo:64 image: org/sub-foo-foo65 another-sub-sub-foo:66 image: org/another-sub-sub-foo67 bar:68 image: org/bar69 sub-bar:70 image: org/sub-bar71 baz:72 image: org/baz73"""74ok_compose_yml = """75version: '3.5'76x-hierarchy:77 - foo:78 - sub-foo:79 - sub-sub-foo80 - another-sub-sub-foo81 - bar:82 - sub-bar83 - baz84services:85 foo:86 image: org/foo87 sub-foo:88 image: org/sub-foo89 sub-sub-foo:90 image: org/sub-sub-foo91 another-sub-sub-foo:92 image: org/another-sub-sub-foo93 bar:94 image: org/bar95 sub-bar:96 image: org/sub-bar97 baz:98 image: org/baz99"""100arrow_compose_yml = """101version: '3.5'102x-with-gpus:103 - ubuntu-cuda104x-hierarchy:105 - conda-cpp:106 - conda-python:107 - conda-python-pandas108 - conda-python-dask109 - ubuntu-cpp:110 - ubuntu-cpp-cmake32111 - ubuntu-c-glib:112 - ubuntu-ruby113 - ubuntu-cuda114x-limit-presets:115 github:116 cpuset_cpus: [0, 1]117 memory: 7g118services:119 conda-cpp:120 image: org/conda-cpp121 build:122 context: .123 dockerfile: ci/docker/conda-cpp.dockerfile124 conda-python:125 image: org/conda-python126 build:127 context: .128 dockerfile: ci/docker/conda-cpp.dockerfile129 args:130 python: 3.8131 conda-python-pandas:132 image: org/conda-python-pandas133 build:134 context: .135 dockerfile: ci/docker/conda-python-pandas.dockerfile136 conda-python-dask:137 image: org/conda-python-dask138 ubuntu-cpp:139 image: org/ubuntu-cpp140 build:141 context: .142 dockerfile: ci/docker/ubuntu-${UBUNTU}-cpp.dockerfile143 ubuntu-cpp-cmake32:144 image: org/ubuntu-cpp-cmake32145 ubuntu-c-glib:146 image: org/ubuntu-c-glib147 ubuntu-ruby:148 image: org/ubuntu-ruby149 ubuntu-cuda:150 image: org/ubuntu-cuda151 environment:152 CUDA_ENV: 1153 OTHER_ENV: 2154 volumes:155 - /host:/container156 command: /bin/bash -c "echo 1 > /tmp/dummy && cat /tmp/dummy"157"""158arrow_compose_env = {159 'UBUNTU': '20.04', # overridden below160 'PYTHON': '3.8',161 'PANDAS': 'latest',162 'DASK': 'latest', # overridden below163}164def create_config(directory, yml_content, env_content=None):165 env_path = directory / '.env'166 config_path = directory / 'docker-compose.yml'167 with config_path.open('w') as fp:168 fp.write(yml_content)169 if env_content is not None:170 with env_path.open('w') as fp:171 for k, v in env_content.items():172 fp.write("{}={}\n".format(k, v))173 return config_path174def format_run(args):175 cmd = ["run", "--rm"]176 if isinstance(args, str):177 return " ".join(cmd + [args])178 else:179 return cmd + args180@pytest.fixture181def arrow_compose_path(tmpdir):182 return create_config(tmpdir, arrow_compose_yml, arrow_compose_env)183def test_config_validation(tmpdir):184 config_path = create_config(tmpdir, missing_service_compose_yml)185 msg = "`sub-foo` is defined in `x-hierarchy` bot not in `services`"186 with pytest.raises(ValueError, match=msg):187 DockerCompose(config_path)188 config_path = create_config(tmpdir, missing_node_compose_yml)189 msg = "`sub-bar` is defined in `services` but not in `x-hierarchy`"190 with pytest.raises(ValueError, match=msg):191 DockerCompose(config_path)192 config_path = create_config(tmpdir, ok_compose_yml)193 DockerCompose(config_path) # no issue194def assert_docker_calls(compose, expected_args):195 base_command = ['docker']196 expected_commands = []197 for args in expected_args:198 if isinstance(args, str):199 args = re.split(r"\s", args)200 expected_commands.append(base_command + args)201 return assert_subprocess_calls(expected_commands, check=True)202def assert_compose_calls(compose, expected_args, env=mock.ANY):203 base_command = ['docker-compose', '--file', str(compose.config.path)]204 expected_commands = []205 for args in expected_args:206 if isinstance(args, str):207 args = re.split(r"\s", args)208 expected_commands.append(base_command + args)209 return assert_subprocess_calls(expected_commands, check=True, env=env)210def test_arrow_example_validation_passes(arrow_compose_path):211 DockerCompose(arrow_compose_path)212def test_compose_default_params_and_env(arrow_compose_path):213 compose = DockerCompose(arrow_compose_path, params=dict(214 UBUNTU='18.04',215 DASK='master'216 ))217 assert compose.config.dotenv == arrow_compose_env218 assert compose.config.params == {219 'UBUNTU': '18.04',220 'DASK': 'master',221 }222def test_forwarding_env_variables(arrow_compose_path):223 expected_calls = [224 "pull --ignore-pull-failures conda-cpp",225 "build conda-cpp",226 ]227 expected_env = PartialEnv(228 MY_CUSTOM_VAR_A='a',229 MY_CUSTOM_VAR_B='b'230 )231 with override_env({'MY_CUSTOM_VAR_A': 'a', 'MY_CUSTOM_VAR_B': 'b'}):232 compose = DockerCompose(arrow_compose_path)233 with assert_compose_calls(compose, expected_calls, env=expected_env):234 assert os.environ['MY_CUSTOM_VAR_A'] == 'a'235 assert os.environ['MY_CUSTOM_VAR_B'] == 'b'236 compose.pull('conda-cpp')237 compose.build('conda-cpp')238def test_compose_pull(arrow_compose_path):239 compose = DockerCompose(arrow_compose_path)240 expected_calls = [241 "pull --ignore-pull-failures conda-cpp",242 ]243 with assert_compose_calls(compose, expected_calls):244 compose.clear_pull_memory()245 compose.pull('conda-cpp')246 expected_calls = [247 "pull --ignore-pull-failures conda-cpp",248 "pull --ignore-pull-failures conda-python",249 "pull --ignore-pull-failures conda-python-pandas"250 ]251 with assert_compose_calls(compose, expected_calls):252 compose.clear_pull_memory()253 compose.pull('conda-python-pandas')254 expected_calls = [255 "pull --ignore-pull-failures conda-cpp",256 "pull --ignore-pull-failures conda-python",257 ]258 with assert_compose_calls(compose, expected_calls):259 compose.clear_pull_memory()260 compose.pull('conda-python-pandas', pull_leaf=False)261def test_compose_pull_params(arrow_compose_path):262 expected_calls = [263 "pull --ignore-pull-failures conda-cpp",264 "pull --ignore-pull-failures conda-python",265 ]266 compose = DockerCompose(arrow_compose_path, params=dict(UBUNTU='18.04'))267 expected_env = PartialEnv(PYTHON='3.8', PANDAS='latest')268 with assert_compose_calls(compose, expected_calls, env=expected_env):269 compose.clear_pull_memory()270 compose.pull('conda-python-pandas', pull_leaf=False)271def test_compose_build(arrow_compose_path):272 compose = DockerCompose(arrow_compose_path)273 expected_calls = [274 "build conda-cpp",275 ]276 with assert_compose_calls(compose, expected_calls):277 compose.build('conda-cpp')278 expected_calls = [279 "build --no-cache conda-cpp"280 ]281 with assert_compose_calls(compose, expected_calls):282 compose.build('conda-cpp', use_cache=False)283 expected_calls = [284 "build conda-cpp",285 "build conda-python",286 "build conda-python-pandas"287 ]288 with assert_compose_calls(compose, expected_calls):289 compose.build('conda-python-pandas')290 expected_calls = [291 "build --no-cache conda-cpp",292 "build --no-cache conda-python",293 "build --no-cache conda-python-pandas",294 ]295 with assert_compose_calls(compose, expected_calls):296 compose.build('conda-python-pandas', use_cache=False)297 expected_calls = [298 "build conda-cpp",299 "build conda-python",300 "build --no-cache conda-python-pandas",301 ]302 with assert_compose_calls(compose, expected_calls):303 compose.build('conda-python-pandas', use_cache=True,304 use_leaf_cache=False)305@mock.patch.dict(os.environ, {"BUILDKIT_INLINE_CACHE": "1"})306def test_compose_buildkit_inline_cache(arrow_compose_path):307 compose = DockerCompose(arrow_compose_path)308 expected_calls = [309 "build --build-arg BUILDKIT_INLINE_CACHE=1 conda-cpp",310 ]311 with assert_compose_calls(compose, expected_calls):312 compose.build('conda-cpp')313def test_compose_build_params(arrow_compose_path):314 expected_calls = [315 "build ubuntu-cpp",316 ]317 compose = DockerCompose(arrow_compose_path, params=dict(UBUNTU='18.04'))318 expected_env = PartialEnv(UBUNTU="18.04")319 with assert_compose_calls(compose, expected_calls, env=expected_env):320 compose.build('ubuntu-cpp')321 compose = DockerCompose(arrow_compose_path, params=dict(UBUNTU='16.04'))322 expected_env = PartialEnv(UBUNTU="16.04")323 with assert_compose_calls(compose, expected_calls, env=expected_env):324 compose.build('ubuntu-cpp')325 expected_calls = [326 "build --no-cache conda-cpp",327 "build --no-cache conda-python",328 "build --no-cache conda-python-pandas",329 ]330 compose = DockerCompose(arrow_compose_path, params=dict(UBUNTU='18.04'))331 expected_env = PartialEnv(PYTHON='3.8', PANDAS='latest')332 with assert_compose_calls(compose, expected_calls, env=expected_env):333 compose.build('conda-python-pandas', use_cache=False)334def test_compose_run(arrow_compose_path):335 expected_calls = [336 format_run("conda-cpp"),337 ]338 compose = DockerCompose(arrow_compose_path)339 with assert_compose_calls(compose, expected_calls):340 compose.run('conda-cpp')341 expected_calls = [342 format_run("conda-python")343 ]344 expected_env = PartialEnv(PYTHON='3.8')345 with assert_compose_calls(compose, expected_calls, env=expected_env):346 compose.run('conda-python')347 compose = DockerCompose(arrow_compose_path, params=dict(PYTHON='3.9'))348 expected_env = PartialEnv(PYTHON='3.9')349 with assert_compose_calls(compose, expected_calls, env=expected_env):350 compose.run('conda-python')351 compose = DockerCompose(arrow_compose_path, params=dict(PYTHON='3.9'))352 for command in ["bash", "echo 1"]:353 expected_calls = [354 format_run(["conda-python", command]),355 ]356 expected_env = PartialEnv(PYTHON='3.9')357 with assert_compose_calls(compose, expected_calls, env=expected_env):358 compose.run('conda-python', command)359 expected_calls = [360 (361 format_run("-e CONTAINER_ENV_VAR_A=a -e CONTAINER_ENV_VAR_B=b "362 "conda-python")363 )364 ]365 compose = DockerCompose(arrow_compose_path)366 expected_env = PartialEnv(PYTHON='3.8')367 with assert_compose_calls(compose, expected_calls, env=expected_env):368 env = collections.OrderedDict([369 ("CONTAINER_ENV_VAR_A", "a"),370 ("CONTAINER_ENV_VAR_B", "b")371 ])372 compose.run('conda-python', env=env)373 expected_calls = [374 (375 format_run("--volume /host/build:/build --volume "376 "/host/ccache:/ccache:delegated conda-python")377 )378 ]379 compose = DockerCompose(arrow_compose_path)380 with assert_compose_calls(compose, expected_calls):381 volumes = ("/host/build:/build", "/host/ccache:/ccache:delegated")382 compose.run('conda-python', volumes=volumes)383def test_compose_run_with_resource_limits(arrow_compose_path):384 expected_calls = [385 format_run([386 "--cpuset-cpus=0,1",387 "--memory=7g",388 "--memory-swap=7g",389 "org/conda-cpp"390 ]),391 ]392 compose = DockerCompose(arrow_compose_path)393 with assert_docker_calls(compose, expected_calls):394 compose.run('conda-cpp', resource_limit="github")395def test_compose_push(arrow_compose_path):396 compose = DockerCompose(arrow_compose_path, params=dict(PYTHON='3.9'))397 expected_env = PartialEnv(PYTHON="3.9")398 expected_calls = [399 mock.call(["docker", "login", "-u", "user", "-p", "pass"], check=True),400 ]401 for image in ["conda-cpp", "conda-python", "conda-python-pandas"]:402 expected_calls.append(403 mock.call(["docker-compose", "--file", str(compose.config.path),404 "push", image], check=True, env=expected_env)405 )406 with assert_subprocess_calls(expected_calls):407 compose.push('conda-python-pandas', user='user', password='pass')408def test_compose_error(arrow_compose_path):409 compose = DockerCompose(arrow_compose_path, params=dict(410 PYTHON='3.8',411 PANDAS='master'412 ))413 error = subprocess.CalledProcessError(99, [])414 with mock.patch('subprocess.run', side_effect=error):415 with pytest.raises(RuntimeError) as exc:416 compose.run('conda-cpp')417 exception_message = str(exc.value)418 assert "exited with a non-zero exit code 99" in exception_message419 assert "PANDAS: latest" in exception_message420 assert "export PANDAS=master" in exception_message421def test_image_with_gpu(arrow_compose_path):422 compose = DockerCompose(arrow_compose_path)423 expected_calls = [424 [425 "run", "--rm", "--gpus", "all",426 "-e", "CUDA_ENV=1",427 "-e", "OTHER_ENV=2",428 "-v", "/host:/container:rw",429 "org/ubuntu-cuda",430 '/bin/bash -c "echo 1 > /tmp/dummy && cat /tmp/dummy"'431 ]432 ]433 with assert_docker_calls(compose, expected_calls):434 compose.run('ubuntu-cuda')435def test_listing_images(arrow_compose_path):436 compose = DockerCompose(arrow_compose_path)437 assert sorted(compose.images()) == [438 'conda-cpp',439 'conda-python',440 'conda-python-dask',441 'conda-python-pandas',442 'ubuntu-c-glib',443 'ubuntu-cpp',444 'ubuntu-cpp-cmake32',445 'ubuntu-cuda',446 'ubuntu-ruby',...
compose_actions.js
Source:compose_actions.js
...350 };351 override(compose_state, "composing", () => true);352 $("#compose-textarea").val("");353 $("#compose-textarea").trigger("focus");354 assert(compose_state.focus_in_empty_compose());355 override(compose_state, "composing", () => false);356 assert(!compose_state.focus_in_empty_compose());357 $("#compose-textarea").val("foo");358 assert(!compose_state.focus_in_empty_compose());359 $("#compose-textarea").trigger("blur");360 assert(!compose_state.focus_in_empty_compose());361});362test("on_narrow", (override) => {363 let narrowed_by_topic_reply;364 override(narrow_state, "narrowed_by_topic_reply", () => narrowed_by_topic_reply);365 let narrowed_by_pm_reply;366 override(narrow_state, "narrowed_by_pm_reply", () => narrowed_by_pm_reply);367 let has_message_content;368 override(compose_state, "has_message_content", () => has_message_content);369 let cancel_called = false;370 override(compose_actions, "cancel", () => {371 cancel_called = true;372 });373 compose_actions.on_narrow({374 force_close: true,...
compose-update
Source:compose-update
...42 raise Exception(f"Directory '{x}' contains more then one compose file, namely: {compose_file}")43 return os.path.join(x, compose_file.pop())44def pull_images(compose_path):45 return os.system(f'{compose_prefix} -f {compose_path} pull --quiet')46def update_compose(compose_path):47 return os.system(f'{compose_prefix} -f {compose_path} up -d')48class FilesDefaultToStdin(click.Argument):49 def __init__(self, *args, **kwargs):50 kwargs['nargs'] = -151 super().__init__(*args, **kwargs)52 def full_process_value(self, ctx, value):53 return super().process_value(ctx, value or get_stdin())54@click.command()55@click.option('--prune', '-p', default=False, help="Prune docker images after update process if set")56@click.argument('update_dirs', cls=FilesDefaultToStdin)57def update_composes(update_dirs, prune):58 """59 Update docker-compose images automatically. 60 ...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!