mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			504 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			504 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
"use strict";
 | 
						|
 | 
						|
const {strict: assert} = require("assert");
 | 
						|
 | 
						|
const {set_global, zrequire} = require("../zjsunit/namespace");
 | 
						|
const {run_test} = require("../zjsunit/test");
 | 
						|
const $ = require("../zjsunit/zjquery");
 | 
						|
 | 
						|
const noop = function () {};
 | 
						|
const return_false = function () {
 | 
						|
    return false;
 | 
						|
};
 | 
						|
const return_true = function () {
 | 
						|
    return true;
 | 
						|
};
 | 
						|
 | 
						|
set_global("document", {
 | 
						|
    location: {}, // we need this to load compose.js
 | 
						|
});
 | 
						|
 | 
						|
set_global("page_params", {});
 | 
						|
 | 
						|
const compose_pm_pill = set_global("compose_pm_pill", {});
 | 
						|
 | 
						|
const hash_util = set_global("hash_util", {});
 | 
						|
 | 
						|
const people = zrequire("people");
 | 
						|
const compose_ui = zrequire("compose_ui");
 | 
						|
const compose = zrequire("compose");
 | 
						|
const compose_state = zrequire("compose_state");
 | 
						|
const compose_actions = zrequire("compose_actions");
 | 
						|
const stream_data = zrequire("stream_data");
 | 
						|
 | 
						|
set_global("document", "document-stub");
 | 
						|
 | 
						|
compose_actions.update_placeholder_text = noop;
 | 
						|
 | 
						|
const start = compose_actions.start;
 | 
						|
const cancel = compose_actions.cancel;
 | 
						|
const get_focus_area = compose_actions._get_focus_area;
 | 
						|
const respond_to_message = compose_actions.respond_to_message;
 | 
						|
const reply_with_mention = compose_actions.reply_with_mention;
 | 
						|
const quote_and_reply = compose_actions.quote_and_reply;
 | 
						|
 | 
						|
compose_state.private_message_recipient = (function () {
 | 
						|
    let recipient;
 | 
						|
 | 
						|
    return function (arg) {
 | 
						|
        if (arg === undefined) {
 | 
						|
            return recipient;
 | 
						|
        }
 | 
						|
 | 
						|
        recipient = arg;
 | 
						|
        return undefined;
 | 
						|
    };
 | 
						|
})();
 | 
						|
 | 
						|
set_global("reload_state", {
 | 
						|
    is_in_progress: return_false,
 | 
						|
});
 | 
						|
 | 
						|
set_global("notifications", {
 | 
						|
    clear_compose_notifications: noop,
 | 
						|
});
 | 
						|
 | 
						|
const compose_fade = set_global("compose_fade", {
 | 
						|
    clear_compose: noop,
 | 
						|
});
 | 
						|
 | 
						|
set_global("drafts", {
 | 
						|
    update_draft: noop,
 | 
						|
});
 | 
						|
 | 
						|
const narrow_state = set_global("narrow_state", {
 | 
						|
    set_compose_defaults: noop,
 | 
						|
});
 | 
						|
 | 
						|
set_global("unread_ops", {
 | 
						|
    notify_server_message_read: noop,
 | 
						|
});
 | 
						|
 | 
						|
set_global("common", {
 | 
						|
    status_classes: "status_classes",
 | 
						|
});
 | 
						|
 | 
						|
function stub_selected_message(msg) {
 | 
						|
    set_global("current_msg_list", {
 | 
						|
        selected_message() {
 | 
						|
            return msg;
 | 
						|
        },
 | 
						|
        can_mark_messages_read() {
 | 
						|
            return true;
 | 
						|
        },
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
function stub_channel_get(success_value) {
 | 
						|
    set_global("channel", {
 | 
						|
        get(opts) {
 | 
						|
            opts.success(success_value);
 | 
						|
        },
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
function assert_visible(sel) {
 | 
						|
    assert($(sel).visible());
 | 
						|
}
 | 
						|
 | 
						|
function assert_hidden(sel) {
 | 
						|
    assert(!$(sel).visible());
 | 
						|
}
 | 
						|
 | 
						|
run_test("initial_state", () => {
 | 
						|
    assert.equal(compose_state.composing(), false);
 | 
						|
    assert.equal(compose_state.get_message_type(), false);
 | 
						|
    assert.equal(compose_state.has_message_content(), false);
 | 
						|
});
 | 
						|
 | 
						|
run_test("start", () => {
 | 
						|
    compose_actions.autosize_message_content = noop;
 | 
						|
    compose_actions.expand_compose_box = noop;
 | 
						|
    compose_actions.set_focus = noop;
 | 
						|
    compose_actions.complete_starting_tasks = noop;
 | 
						|
    compose_actions.blur_compose_inputs = noop;
 | 
						|
    compose_actions.clear_textarea = noop;
 | 
						|
 | 
						|
    // Start stream message
 | 
						|
    narrow_state.set_compose_defaults = function () {
 | 
						|
        const opts = {};
 | 
						|
        opts.stream = "stream1";
 | 
						|
        opts.topic = "topic1";
 | 
						|
        return opts;
 | 
						|
    };
 | 
						|
 | 
						|
    let opts = {};
 | 
						|
    start("stream", opts);
 | 
						|
 | 
						|
    assert_visible("#stream-message");
 | 
						|
    assert_hidden("#private-message");
 | 
						|
 | 
						|
    assert.equal($("#stream_message_recipient_stream").val(), "stream1");
 | 
						|
    assert.equal($("#stream_message_recipient_topic").val(), "topic1");
 | 
						|
    assert.equal(compose_state.get_message_type(), "stream");
 | 
						|
    assert(compose_state.composing());
 | 
						|
 | 
						|
    // Autofill stream field for single subscription
 | 
						|
    const denmark = {
 | 
						|
        subscribed: true,
 | 
						|
        color: "blue",
 | 
						|
        name: "Denmark",
 | 
						|
        stream_id: 1,
 | 
						|
    };
 | 
						|
    stream_data.add_sub(denmark);
 | 
						|
 | 
						|
    narrow_state.set_compose_defaults = function () {
 | 
						|
        const opts = {};
 | 
						|
        opts.trigger = "new topic button";
 | 
						|
        return opts;
 | 
						|
    };
 | 
						|
 | 
						|
    opts = {};
 | 
						|
    start("stream", opts);
 | 
						|
    assert.equal($("#stream_message_recipient_stream").val(), "Denmark");
 | 
						|
    assert.equal($("#stream_message_recipient_topic").val(), "");
 | 
						|
 | 
						|
    narrow_state.set_compose_defaults = function () {
 | 
						|
        const opts = {};
 | 
						|
        opts.trigger = "compose_hotkey";
 | 
						|
        return opts;
 | 
						|
    };
 | 
						|
 | 
						|
    opts = {};
 | 
						|
    start("stream", opts);
 | 
						|
    assert.equal($("#stream_message_recipient_stream").val(), "Denmark");
 | 
						|
    assert.equal($("#stream_message_recipient_topic").val(), "");
 | 
						|
 | 
						|
    const social = {
 | 
						|
        subscribed: true,
 | 
						|
        color: "red",
 | 
						|
        name: "social",
 | 
						|
        stream_id: 2,
 | 
						|
    };
 | 
						|
    stream_data.add_sub(social);
 | 
						|
 | 
						|
    // More than 1 subscription, do not autofill
 | 
						|
    opts = {};
 | 
						|
    start("stream", opts);
 | 
						|
    assert.equal($("#stream_message_recipient_stream").val(), "");
 | 
						|
    assert.equal($("#stream_message_recipient_topic").val(), "");
 | 
						|
    stream_data.clear_subscriptions();
 | 
						|
 | 
						|
    // Start PM
 | 
						|
    narrow_state.set_compose_defaults = function () {
 | 
						|
        const opts = {};
 | 
						|
        opts.private_message_recipient = "foo@example.com";
 | 
						|
        return opts;
 | 
						|
    };
 | 
						|
 | 
						|
    opts = {
 | 
						|
        content: "hello",
 | 
						|
    };
 | 
						|
 | 
						|
    start("private", opts);
 | 
						|
 | 
						|
    assert_hidden("#stream-message");
 | 
						|
    assert_visible("#private-message");
 | 
						|
 | 
						|
    assert.equal(compose_state.private_message_recipient(), "foo@example.com");
 | 
						|
    assert.equal($("#compose-textarea").val(), "hello");
 | 
						|
    assert.equal(compose_state.get_message_type(), "private");
 | 
						|
    assert(compose_state.composing());
 | 
						|
 | 
						|
    // Cancel compose.
 | 
						|
    let pill_cleared;
 | 
						|
    compose_pm_pill.clear = function () {
 | 
						|
        pill_cleared = true;
 | 
						|
    };
 | 
						|
 | 
						|
    let abort_xhr_called = false;
 | 
						|
    compose.abort_xhr = () => {
 | 
						|
        abort_xhr_called = true;
 | 
						|
    };
 | 
						|
 | 
						|
    $("#compose-textarea").set_height(50);
 | 
						|
 | 
						|
    assert_hidden("#compose_controls");
 | 
						|
    cancel();
 | 
						|
    assert(abort_xhr_called);
 | 
						|
    assert(pill_cleared);
 | 
						|
    assert_visible("#compose_controls");
 | 
						|
    assert_hidden("#private-message");
 | 
						|
    assert(!compose_state.composing());
 | 
						|
});
 | 
						|
 | 
						|
run_test("respond_to_message", () => {
 | 
						|
    // Test PM
 | 
						|
    const person = {
 | 
						|
        user_id: 22,
 | 
						|
        email: "alice@example.com",
 | 
						|
        full_name: "Alice",
 | 
						|
    };
 | 
						|
    people.add_active_user(person);
 | 
						|
 | 
						|
    let msg = {
 | 
						|
        type: "private",
 | 
						|
        sender_id: person.user_id,
 | 
						|
    };
 | 
						|
    stub_selected_message(msg);
 | 
						|
 | 
						|
    let opts = {
 | 
						|
        reply_type: "personal",
 | 
						|
    };
 | 
						|
 | 
						|
    respond_to_message(opts);
 | 
						|
    assert.equal(compose_state.private_message_recipient(), "alice@example.com");
 | 
						|
 | 
						|
    // Test stream
 | 
						|
    msg = {
 | 
						|
        type: "stream",
 | 
						|
        stream: "devel",
 | 
						|
        topic: "python",
 | 
						|
        reply_to: "bob", // compose.start needs this for dubious reasons
 | 
						|
    };
 | 
						|
    stub_selected_message(msg);
 | 
						|
 | 
						|
    opts = {};
 | 
						|
 | 
						|
    respond_to_message(opts);
 | 
						|
    assert.equal($("#stream_message_recipient_stream").val(), "devel");
 | 
						|
});
 | 
						|
 | 
						|
run_test("reply_with_mention", (override) => {
 | 
						|
    const msg = {
 | 
						|
        type: "stream",
 | 
						|
        stream: "devel",
 | 
						|
        topic: "python",
 | 
						|
        reply_to: "bob", // compose.start needs this for dubious reasons
 | 
						|
        sender_full_name: "Bob Roberts",
 | 
						|
        sender_id: 40,
 | 
						|
    };
 | 
						|
    stub_selected_message(msg);
 | 
						|
 | 
						|
    let syntax_to_insert;
 | 
						|
    override(compose_ui, "insert_syntax_and_focus", (syntax) => {
 | 
						|
        syntax_to_insert = syntax;
 | 
						|
    });
 | 
						|
 | 
						|
    const opts = {};
 | 
						|
 | 
						|
    reply_with_mention(opts);
 | 
						|
    assert.equal($("#stream_message_recipient_stream").val(), "devel");
 | 
						|
    assert.equal(syntax_to_insert, "@**Bob Roberts**");
 | 
						|
 | 
						|
    // Test for extended mention syntax
 | 
						|
    const bob_1 = {
 | 
						|
        user_id: 30,
 | 
						|
        email: "bob1@example.com",
 | 
						|
        full_name: "Bob Roberts",
 | 
						|
    };
 | 
						|
    people.add_active_user(bob_1);
 | 
						|
    const bob_2 = {
 | 
						|
        user_id: 40,
 | 
						|
        email: "bob2@example.com",
 | 
						|
        full_name: "Bob Roberts",
 | 
						|
    };
 | 
						|
    people.add_active_user(bob_2);
 | 
						|
 | 
						|
    reply_with_mention(opts);
 | 
						|
    assert.equal($("#stream_message_recipient_stream").val(), "devel");
 | 
						|
    assert.equal(syntax_to_insert, "@**Bob Roberts|40**");
 | 
						|
});
 | 
						|
 | 
						|
run_test("quote_and_reply", () => {
 | 
						|
    const msg = {
 | 
						|
        type: "stream",
 | 
						|
        stream: "devel",
 | 
						|
        topic: "python",
 | 
						|
        reply_to: "bob",
 | 
						|
        sender_full_name: "Bob Roberts",
 | 
						|
        sender_id: 40,
 | 
						|
    };
 | 
						|
    hash_util.by_conversation_and_time_uri = () => "link_to_message";
 | 
						|
    stub_selected_message(msg);
 | 
						|
    stub_channel_get({
 | 
						|
        raw_content: "Testing.",
 | 
						|
    });
 | 
						|
 | 
						|
    current_msg_list.selected_id = function () {
 | 
						|
        return 100;
 | 
						|
    };
 | 
						|
 | 
						|
    compose_ui.insert_syntax_and_focus = function (syntax) {
 | 
						|
        assert.equal(syntax, "[Quoting…]\n");
 | 
						|
    };
 | 
						|
 | 
						|
    compose_ui.replace_syntax = function (syntax, replacement) {
 | 
						|
        assert.equal(syntax, "[Quoting…]");
 | 
						|
        assert.equal(
 | 
						|
            replacement,
 | 
						|
            "@_**Bob Roberts|40** [said](link_to_message):\n```quote\nTesting.\n```",
 | 
						|
        );
 | 
						|
    };
 | 
						|
 | 
						|
    const opts = {
 | 
						|
        reply_type: "personal",
 | 
						|
    };
 | 
						|
 | 
						|
    $("#compose-textarea").caret = (pos) => {
 | 
						|
        assert.equal(pos, 0);
 | 
						|
    };
 | 
						|
 | 
						|
    quote_and_reply(opts);
 | 
						|
 | 
						|
    current_msg_list.selected_message = function () {
 | 
						|
        return {
 | 
						|
            type: "stream",
 | 
						|
            stream: "devel",
 | 
						|
            topic: "test",
 | 
						|
            reply_to: "bob",
 | 
						|
            sender_full_name: "Bob Roberts",
 | 
						|
            sender_id: 40,
 | 
						|
            raw_content: "Testing.",
 | 
						|
        };
 | 
						|
    };
 | 
						|
 | 
						|
    set_global("channel", {
 | 
						|
        get() {
 | 
						|
            assert.fail("channel.get should not be used if raw_content is present");
 | 
						|
        },
 | 
						|
    });
 | 
						|
 | 
						|
    quote_and_reply(opts);
 | 
						|
 | 
						|
    current_msg_list.selected_message = function () {
 | 
						|
        return {
 | 
						|
            type: "stream",
 | 
						|
            stream: "devel",
 | 
						|
            topic: "test",
 | 
						|
            reply_to: "bob",
 | 
						|
            sender_full_name: "Bob Roberts",
 | 
						|
            sender_id: 40,
 | 
						|
            raw_content: "```\nmultiline code block\nshoudln't mess with quotes\n```",
 | 
						|
        };
 | 
						|
    };
 | 
						|
    compose_ui.replace_syntax = function (syntax, replacement) {
 | 
						|
        assert.equal(syntax, "[Quoting…]");
 | 
						|
        assert.equal(
 | 
						|
            replacement,
 | 
						|
            "@_**Bob Roberts|40** [said](link_to_message):\n````quote\n```\nmultiline code block\nshoudln't mess with quotes\n```\n````",
 | 
						|
        );
 | 
						|
    };
 | 
						|
    quote_and_reply(opts);
 | 
						|
});
 | 
						|
 | 
						|
run_test("get_focus_area", () => {
 | 
						|
    assert.equal(get_focus_area("private", {}), "#private_message_recipient");
 | 
						|
    assert.equal(
 | 
						|
        get_focus_area("private", {
 | 
						|
            private_message_recipient: "bob@example.com",
 | 
						|
        }),
 | 
						|
        "#compose-textarea",
 | 
						|
    );
 | 
						|
    assert.equal(get_focus_area("stream", {}), "#stream_message_recipient_stream");
 | 
						|
    assert.equal(get_focus_area("stream", {stream: "fun"}), "#stream_message_recipient_topic");
 | 
						|
    assert.equal(get_focus_area("stream", {stream: "fun", topic: "more"}), "#compose-textarea");
 | 
						|
    assert.equal(
 | 
						|
        get_focus_area("stream", {stream: "fun", topic: "more", trigger: "new topic button"}),
 | 
						|
        "#stream_message_recipient_topic",
 | 
						|
    );
 | 
						|
});
 | 
						|
 | 
						|
run_test("focus_in_empty_compose", () => {
 | 
						|
    $("#compose-textarea").is = function (attr) {
 | 
						|
        assert.equal(attr, ":focus");
 | 
						|
        return $("#compose-textarea").is_focused;
 | 
						|
    };
 | 
						|
 | 
						|
    compose_state.composing = return_true;
 | 
						|
    $("#compose-textarea").val("");
 | 
						|
    $("#compose-textarea").trigger("focus");
 | 
						|
    assert(compose_state.focus_in_empty_compose());
 | 
						|
 | 
						|
    compose_state.composing = return_false;
 | 
						|
    assert(!compose_state.focus_in_empty_compose());
 | 
						|
 | 
						|
    $("#compose-textarea").val("foo");
 | 
						|
    assert(!compose_state.focus_in_empty_compose());
 | 
						|
 | 
						|
    $("#compose-textarea").trigger("blur");
 | 
						|
    assert(!compose_state.focus_in_empty_compose());
 | 
						|
});
 | 
						|
 | 
						|
run_test("on_narrow", () => {
 | 
						|
    let cancel_called = false;
 | 
						|
    compose_actions.cancel = function () {
 | 
						|
        cancel_called = true;
 | 
						|
    };
 | 
						|
    compose_actions.on_narrow({
 | 
						|
        force_close: true,
 | 
						|
    });
 | 
						|
    assert(cancel_called);
 | 
						|
 | 
						|
    let on_topic_narrow_called = false;
 | 
						|
    compose_actions.on_topic_narrow = function () {
 | 
						|
        on_topic_narrow_called = true;
 | 
						|
    };
 | 
						|
    narrow_state.narrowed_by_topic_reply = function () {
 | 
						|
        return true;
 | 
						|
    };
 | 
						|
    compose_actions.on_narrow({
 | 
						|
        force_close: false,
 | 
						|
    });
 | 
						|
    assert(on_topic_narrow_called);
 | 
						|
 | 
						|
    let update_message_list_called = false;
 | 
						|
    narrow_state.narrowed_by_topic_reply = function () {
 | 
						|
        return false;
 | 
						|
    };
 | 
						|
    compose_fade.update_message_list = function () {
 | 
						|
        update_message_list_called = true;
 | 
						|
    };
 | 
						|
    compose_state.has_message_content = function () {
 | 
						|
        return true;
 | 
						|
    };
 | 
						|
    compose_actions.on_narrow({
 | 
						|
        force_close: false,
 | 
						|
    });
 | 
						|
    assert(update_message_list_called);
 | 
						|
 | 
						|
    compose_state.has_message_content = function () {
 | 
						|
        return false;
 | 
						|
    };
 | 
						|
    let start_called = false;
 | 
						|
    compose_actions.start = function () {
 | 
						|
        start_called = true;
 | 
						|
    };
 | 
						|
    narrow_state.narrowed_by_pm_reply = function () {
 | 
						|
        return true;
 | 
						|
    };
 | 
						|
    compose_actions.on_narrow({
 | 
						|
        force_close: false,
 | 
						|
        trigger: "not-search",
 | 
						|
        private_message_recipient: "not@empty.com",
 | 
						|
    });
 | 
						|
    assert(start_called);
 | 
						|
 | 
						|
    start_called = false;
 | 
						|
    compose_actions.on_narrow({
 | 
						|
        force_close: false,
 | 
						|
        trigger: "search",
 | 
						|
        private_message_recipient: "",
 | 
						|
    });
 | 
						|
    assert(!start_called);
 | 
						|
 | 
						|
    narrow_state.narrowed_by_pm_reply = function () {
 | 
						|
        return false;
 | 
						|
    };
 | 
						|
    cancel_called = false;
 | 
						|
    compose_actions.on_narrow({
 | 
						|
        force_close: false,
 | 
						|
    });
 | 
						|
    assert(cancel_called);
 | 
						|
});
 |