/* @odoo-module */

import { startServer } from "@bus/../tests/helpers/mock_python_environment";

import { DELAY_FOR_SPINNER } from "@mail/core/web/chatter";
import { patchUiSize, SIZES } from "@mail/../tests/helpers/patch_ui_size";
import { start } from "@mail/../tests/helpers/test_utils";

import {
    getFixture,
    makeDeferred,
    patchWithCleanup,
    triggerHotkey,
} from "@web/../tests/helpers/utils";
import {
    click,
    contains,
    createFile,
    dragenterFiles,
    dropFiles,
    insertText,
    scroll,
} from "@web/../tests/utils";

QUnit.module("chatter");

QUnit.test("simple chatter on a record", async (assert) => {
    const { openFormView, pyEnv } = await start({
        mockRPC(route, args) {
            if (route.startsWith("/mail")) {
                assert.step(route);
            }
        },
    });
    const partnerId = pyEnv["res.partner"].create({ name: "John Doe" });
    openFormView("res.partner", partnerId);
    await contains(".o-mail-Chatter-topbar");
    await contains(".o-mail-Thread");
    assert.verifySteps([
        "/mail/init_messaging",
        "/mail/load_message_failures",
        "/mail/thread/data",
        "/mail/thread/messages",
    ]);
});

QUnit.test("can post a message on a record thread", async (assert) => {
    const pyEnv = await startServer();
    const partnerId = pyEnv["res.partner"].create({ name: "John Doe" });
    const { openFormView } = await start({
        mockRPC(route, args) {
            if (route === "/mail/message/post") {
                assert.step(route);
                const expected = {
                    context: args.context,
                    post_data: {
                        body: "hey",
                        attachment_ids: [],
                        attachment_tokens: [],
                        canned_response_ids: [],
                        message_type: "comment",
                        partner_additional_values: {},
                        partner_emails: [],
                        partner_ids: [],
                        subtype_xmlid: "mail.mt_comment",
                    },
                    thread_id: partnerId,
                    thread_model: "res.partner",
                };
                assert.deepEqual(args, expected);
            }
        },
    });
    openFormView("res.partner", partnerId);
    await contains("button", { text: "Send message" });
    await contains(".o-mail-Composer", { count: 0 });

    await click("button", { text: "Send message" });
    await contains(".o-mail-Composer");

    await insertText(".o-mail-Composer-input", "hey");
    await contains(".o-mail-Message", { count: 0 });

    await click(".o-mail-Composer button:enabled", { text: "Send" });
    await contains(".o-mail-Message");
    assert.verifySteps(["/mail/message/post"]);
});

QUnit.test("can post a note on a record thread", async (assert) => {
    const pyEnv = await startServer();
    const partnerId = pyEnv["res.partner"].create({ name: "John Doe" });
    const { openFormView } = await start({
        mockRPC(route, args) {
            if (route === "/mail/message/post") {
                assert.step(route);
                const expected = {
                    context: args.context,
                    post_data: {
                        attachment_ids: [],
                        attachment_tokens: [],
                        body: "hey",
                        canned_response_ids: [],
                        message_type: "comment",
                        partner_additional_values: {},
                        partner_emails: [],
                        partner_ids: [],
                        subtype_xmlid: "mail.mt_note",
                    },
                    thread_id: partnerId,
                    thread_model: "res.partner",
                };
                assert.deepEqual(args, expected);
            }
        },
    });
    openFormView("res.partner", partnerId);
    await contains("button", { text: "Log note" });
    await contains(".o-mail-Composer", { count: 0 });

    await click("button", { text: "Log note" });
    await contains(".o-mail-Composer");

    await insertText(".o-mail-Composer-input", "hey");
    await contains(".o-mail-Message", { count: 0 });

    await click(".o-mail-Composer button:enabled", { text: "Log" });
    await contains(".o-mail-Message");
    assert.verifySteps(["/mail/message/post"]);
});

QUnit.test("No attachment loading spinner when creating records", async () => {
    const { openFormView } = await start();
    openFormView("res.partner");
    await contains("button[aria-label='Attach files']");
    await contains("button[aria-label='Attach files'] .fa-spin", { count: 0 });
});

QUnit.test(
    "No attachment loading spinner when switching from loading record to creation of record",
    async () => {
        const { advanceTime, openFormView, pyEnv } = await start({
            hasTimeControl: true,
            async mockRPC(route) {
                if (route === "/mail/thread/data") {
                    await new Promise(() => {});
                }
            },
        });
        const partnerId = pyEnv["res.partner"].create({ name: "John" });
        openFormView("res.partner", partnerId);
        await contains("button[aria-label='Attach files']");
        await advanceTime(DELAY_FOR_SPINNER);
        await contains("button[aria-label='Attach files'] .fa-spin");
        await click(".o_control_panel_collapsed_create .o_form_button_create");
        await contains("button[aria-label='Attach files'] .fa-spin", { count: 0 });
    }
);

QUnit.test("Composer toggle state is kept when switching from aside to bottom", async () => {
    patchUiSize({ size: SIZES.XXL });
    const { openFormView, pyEnv } = await start();
    const partnerId = pyEnv["res.partner"].create({ name: "John Doe" });
    openFormView("res.partner", partnerId);
    await click("button", { text: "Send message" });
    await contains(".o-mail-Form-chatter.o-aside .o-mail-Composer-input");
    patchUiSize({ size: SIZES.LG });
    window.dispatchEvent(new Event("resize"));
    await contains(".o-mail-Form-chatter:not(.o-aside) .o-mail-Composer-input");
});

QUnit.test("Textarea content is kept when switching from aside to bottom", async () => {
    patchUiSize({ size: SIZES.XXL });
    const { openFormView, pyEnv } = await start();
    const partnerId = pyEnv["res.partner"].create({ name: "John Doe" });
    openFormView("res.partner", partnerId);
    await click("button", { text: "Send message" });
    await contains(".o-mail-Form-chatter.o-aside .o-mail-Composer-input");
    await insertText(".o-mail-Composer-input", "Hello world !");
    patchUiSize({ size: SIZES.LG });
    window.dispatchEvent(new Event("resize"));
    await contains(".o-mail-Form-chatter:not(.o-aside) .o-mail-Composer-input");
    await contains(".o-mail-Composer-input", { value: "Hello world !" });
});

QUnit.test("Composer type is kept when switching from aside to bottom", async () => {
    patchUiSize({ size: SIZES.XXL });
    const { openFormView, pyEnv } = await start();
    const partnerId = pyEnv["res.partner"].create({ name: "John Doe" });
    openFormView("res.partner", partnerId);
    await click("button", { text: "Log note" });
    patchUiSize({ size: SIZES.LG });
    window.dispatchEvent(new Event("resize"));
    await contains(".o-mail-Form-chatter:not(.o-aside) .o-mail-Composer-input");
    await contains("button.btn-primary", { text: "Log note" });
    await contains("button:not(.btn-primary)", { text: "Send message" });
});

QUnit.test("chatter: drop attachments", async () => {
    const pyEnv = await startServer();
    const partnerId = pyEnv["res.partner"].create({});
    const { openView } = await start();
    openView({
        res_id: partnerId,
        res_model: "res.partner",
        views: [[false, "form"]],
    });
    const files = [
        await createFile({
            content: "hello, world",
            contentType: "text/plain",
            name: "text.txt",
        }),
        await createFile({
            content: "hello, worlduh",
            contentType: "text/plain",
            name: "text2.txt",
        }),
    ];
    await dragenterFiles(".o-mail-Chatter", files);
    await contains(".o-mail-Dropzone");
    await contains(".o-mail-AttachmentCard", { count: 0 });
    await dropFiles(".o-mail-Dropzone", files);
    await contains(".o-mail-AttachmentCard", { count: 2 });
    const extraFiles = [
        await createFile({
            content: "hello, world",
            contentType: "text/plain",
            name: "text3.txt",
        }),
    ];
    await dragenterFiles(".o-mail-Chatter", extraFiles);
    await dropFiles(".o-mail-Dropzone", extraFiles);
    await contains(".o-mail-AttachmentCard", { count: 3 });
});

QUnit.test(
    "chatter: drop attachment should refresh thread data with hasParentReloadOnAttachmentsChange prop",
    async () => {
        patchUiSize({ size: SIZES.XXL });
        const pyEnv = await startServer();
        const partnerId = pyEnv["res.partner"].create({});
        const views = {
            "res.partner,false,form": `
            <form>
                <sheet>
                    <field name="name"/>
                </sheet>
                <div class="o_attachment_preview" />
                <div class="oe_chatter">
                    <field name="message_main_attachment_id" invisible="1" on_change="1" />
                    <field name="message_ids" options="{'post_refresh': 'always'}"/>
                </div>
            </form>`,
        };
        const target = getFixture();
        target.classList.add("o_web_client");
        const { openFormView } = await start({
            serverData: { views },
            target,
            async mockRPC(route) {
                if (route === "/mail/attachment/upload") {
                    const attachmentId = pyEnv["ir.attachment"].create([
                        {
                            res_id: partnerId,
                            res_model: "res.partner",
                            mimetype: "application/pdf",
                        },
                    ]);
                    pyEnv["res.partner"].write([partnerId], {
                        message_main_attachment_id: attachmentId,
                    });
                    return Promise.resolve();
                }
            },
        });
        await openFormView("res.partner", partnerId);
        const files = [
            await createFile({
                contentType: "application/pdf",
                name: "text.pdf",
            }),
        ];
        await dragenterFiles(".o-mail-Chatter", files);
        await dropFiles(".o-mail-Dropzone", files);
        await contains(".o-mail-Attachment iframe", { count: 1 });
    }
);

QUnit.test("should display subject when subject isn't infered from the record", async () => {
    const pyEnv = await startServer();
    const partnerId = pyEnv["res.partner"].create({});
    pyEnv["mail.message"].create({
        body: "not empty",
        model: "res.partner",
        res_id: partnerId,
        subject: "Salutations, voyageur",
    });
    const { openView } = await start();
    openView({
        res_id: partnerId,
        res_model: "res.partner",
        views: [[false, "form"]],
    });
    await contains(".o-mail-Message", { text: "Subject: Salutations, voyageurnot empty" });
});

QUnit.test("should not display user notification messages in chatter", async () => {
    const pyEnv = await startServer();
    const partnerId = pyEnv["res.partner"].create({});
    pyEnv["mail.message"].create({
        message_type: "user_notification",
        model: "res.partner",
        res_id: partnerId,
    });
    const { openView } = await start();
    openView({
        res_id: partnerId,
        res_model: "res.partner",
        views: [[false, "form"]],
    });
    await contains(".o-mail-Thread", { text: "There are no messages in this conversation." });
    await contains(".o-mail-Message", { count: 0 });
});

QUnit.test('post message with "CTRL-Enter" keyboard shortcut in chatter', async () => {
    const pyEnv = await startServer();
    const partnerId = pyEnv["res.partner"].create({});
    const { openView } = await start();
    openView({
        res_id: partnerId,
        res_model: "res.partner",
        views: [[false, "form"]],
    });
    await click("button", { text: "Send message" });
    await contains(".o-mail-Message", { count: 0 });
    await insertText(".o-mail-Composer-input", "Test");
    triggerHotkey("control+Enter");
    await contains(".o-mail-Message");
});

QUnit.test("base rendering when chatter has no attachment", async (assert) => {
    const pyEnv = await startServer();
    const partnerId = pyEnv["res.partner"].create({});
    for (let i = 0; i < 60; i++) {
        pyEnv["mail.message"].create({
            body: "not empty",
            model: "res.partner",
            res_id: partnerId,
        });
    }
    const { openView } = await start();
    openView({
        res_id: partnerId,
        res_model: "res.partner",
        views: [[false, "form"]],
    });
    await contains(".o-mail-Chatter");
    await contains(".o-mail-Chatter-topbar");
    await contains(".o-mail-AttachmentBox", { count: 0 });
    await contains(".o-mail-Thread");
    await contains(".o-mail-Message", { count: 30 });
});

QUnit.test("base rendering when chatter has no record", async () => {
    const { openView } = await start();
    openView({
        res_model: "res.partner",
        views: [[false, "form"]],
    });
    await contains(".o-mail-Chatter");
    await contains(".o-mail-Chatter-topbar");
    await contains(".o-mail-AttachmentBox", { count: 0 });
    await contains(".o-mail-Chatter .o-mail-Thread");
    await contains(".o-mail-Message");
    await contains(".o-mail-Message-author", { text: "Mitchell Admin" });
    await contains(".o-mail-Message-body", { text: "Creating a new record..." });
    await contains("button", { count: 0, text: "Load More" });
    await contains(".o-mail-Message-actions");
});

QUnit.test("base rendering when chatter has attachments", async () => {
    const pyEnv = await startServer();
    const partnerId = pyEnv["res.partner"].create({});
    pyEnv["ir.attachment"].create([
        {
            mimetype: "text/plain",
            name: "Blah.txt",
            res_id: partnerId,
            res_model: "res.partner",
        },
        {
            mimetype: "text/plain",
            name: "Blu.txt",
            res_id: partnerId,
            res_model: "res.partner",
        },
    ]);
    const { openView } = await start();
    openView({
        res_id: partnerId,
        res_model: "res.partner",
        views: [[false, "form"]],
    });
    await contains(".o-mail-Chatter");
    await contains(".o-mail-Chatter-topbar");
    await contains(".o-mail-AttachmentBox", { count: 0 });
});

QUnit.test("show attachment box", async () => {
    const pyEnv = await startServer();
    const partnerId = pyEnv["res.partner"].create({});
    pyEnv["ir.attachment"].create([
        {
            mimetype: "text/plain",
            name: "Blah.txt",
            res_id: partnerId,
            res_model: "res.partner",
        },
        {
            mimetype: "text/plain",
            name: "Blu.txt",
            res_id: partnerId,
            res_model: "res.partner",
        },
    ]);
    const { openView } = await start();
    openView({
        res_id: partnerId,
        res_model: "res.partner",
        views: [[false, "form"]],
    });
    await contains(".o-mail-Chatter");
    await contains(".o-mail-Chatter-topbar");
    await contains("button[aria-label='Attach files']");
    await contains("button[aria-label='Attach files']", { text: "2" });
    await contains(".o-mail-AttachmentBox", { count: 0 });

    await click("button[aria-label='Attach files']");
    await contains(".o-mail-AttachmentBox");
});

QUnit.test("composer show/hide on log note/send message [REQUIRE FOCUS]", async (assert) => {
    const pyEnv = await startServer();
    const partnerId = pyEnv["res.partner"].create({});
    const { openView } = await start();
    openView({
        res_id: partnerId,
        res_model: "res.partner",
        views: [[false, "form"]],
    });
    await contains("button", { text: "Send message" });
    await contains("button", { text: "Log note" });
    await contains(".o-mail-Composer", { count: 0 });

    await click("button", { text: "Send message" });
    await contains(".o-mail-Composer");
    assert.strictEqual(document.activeElement, $(".o-mail-Composer-input")[0]);

    await click("button", { text: "Log note" });
    await contains(".o-mail-Composer");
    assert.strictEqual(document.activeElement, $(".o-mail-Composer-input")[0]);

    await click("button", { text: "Log note" });
    await contains(".o-mail-Composer", { count: 0 });

    await click("button", { text: "Send message" });
    await contains(".o-mail-Composer");

    await click("button", { text: "Send message" });
    await contains(".o-mail-Composer", { count: 0 });
});

QUnit.test('do not post message with "Enter" keyboard shortcut', async () => {
    const pyEnv = await startServer();
    const partnerId = pyEnv["res.partner"].create({});
    const { openView } = await start();
    openView({
        res_id: partnerId,
        res_model: "res.partner",
        views: [[false, "form"]],
    });
    await click("button", { text: "Send message" });
    await contains(".o-mail-Message", { count: 0 });
    await insertText(".o-mail-Composer-input", "Test");
    triggerHotkey("Enter");
    // weak test, no guarantee that we waited long enough for the potential message to be posted
    await contains(".o-mail-Message", { count: 0 });
});

QUnit.test("should not display subject when subject is the same as the thread name", async () => {
    const pyEnv = await startServer();
    const partnerId = pyEnv["res.partner"].create({
        name: "Salutations, voyageur",
    });
    pyEnv["mail.message"].create({
        body: "not empty",
        model: "res.partner",
        res_id: partnerId,
        subject: "Salutations, voyageur",
    });
    const { openView } = await start();
    openView({
        res_id: partnerId,
        res_model: "res.partner",
        views: [[false, "form"]],
    });
    await contains(".o-mail-Message", { text: "not empty" });
    await contains(".o-mail-Message", {
        count: 0,
        text: "Subject: Salutations, voyageurnot empty",
    });
});

QUnit.test("scroll position is kept when navigating from one record to another", async () => {
    patchUiSize({ size: SIZES.XXL });
    const pyEnv = await startServer();
    const partnerId_1 = pyEnv["res.partner"].create({ name: "Harry Potter" });
    const partnerId_2 = pyEnv["res.partner"].create({ name: "Ron Weasley" });
    // Fill both channels with random messages in order for the scrollbar to
    // appear.
    pyEnv["mail.message"].create(
        Array(50)
            .fill(0)
            .map((_, index) => ({
                body: "Non Empty Body ".repeat(25),
                model: "res.partner",
                res_id: index < 20 ? partnerId_1 : partnerId_2,
            }))
    );
    const { openFormView } = await start();
    openFormView("res.partner", partnerId_1);
    await contains(".o-mail-Message", { count: 20 });
    const clientHeight1 = $(".o-mail-Chatter")[0].clientHeight; // client height might change (cause: breadcrumb)
    const scrollValue1 = $(".o-mail-Chatter")[0].scrollHeight / 2;
    await contains(".o-mail-Chatter", { scroll: 0 });
    await scroll(".o-mail-Chatter", scrollValue1);
    openFormView("res.partner", partnerId_2);
    await contains(".o-mail-Message", { count: 30 });
    const clientHeight2 = $(".o-mail-Chatter")[0].clientHeight;
    const scrollValue2 = $(".o-mail-Chatter")[0].scrollHeight / 3;
    await scroll(".o-mail-Chatter", scrollValue2);
    openFormView("res.partner", partnerId_1);
    await contains(".o-mail-Message", { count: 20 });
    const clientHeight3 = $(".o-mail-Chatter")[0].clientHeight;
    await contains(".o-mail-Chatter", { scroll: scrollValue1 - (clientHeight3 - clientHeight1) });
    openFormView("res.partner", partnerId_2);
    await contains(".o-mail-Message", { count: 30 });
    const clientHeight4 = $(".o-mail-Chatter")[0].clientHeight;
    await contains(".o-mail-Chatter", { scroll: scrollValue2 - (clientHeight4 - clientHeight2) });
});

QUnit.test("basic chatter rendering", async () => {
    const pyEnv = await startServer();
    const partnerId = pyEnv["res.partner"].create({ display_name: "second partner" });
    const views = {
        "res.partner,false,form": `
            <form string="Partners">
                <sheet>
                    <field name="name"/>
                </sheet>
                <div class="oe_chatter"></div>
            </form>`,
    };
    const { openView } = await start({ serverData: { views } });
    openView({
        res_model: "res.partner",
        res_id: partnerId,
        views: [[false, "form"]],
    });
    await contains(".o-mail-Chatter");
});

QUnit.test("basic chatter rendering without activities", async () => {
    const pyEnv = await startServer();
    const partnerId = pyEnv["res.partner"].create({ display_name: "second partner" });
    const views = {
        "res.partner,false,form": `
            <form string="Partners">
                <sheet>
                    <field name="name"/>
                </sheet>
                <div class="oe_chatter">
                    <field name="message_follower_ids"/>
                    <field name="message_ids"/>
                </div>
            </form>`,
    };
    const { openView } = await start({ serverData: { views } });
    openView({
        res_model: "res.partner",
        res_id: partnerId,
        views: [[false, "form"]],
    });
    await contains(".o-mail-Chatter");
    await contains(".o-mail-Chatter-topbar");
    await contains("button[aria-label='Attach files']");
    await contains("button", { count: 0, text: "Activities" });

    await contains(".o-mail-Followers");
    await contains(".o-mail-Thread");
});

QUnit.test(
    'chatter just contains "creating a new record" message during the creation of a new record after having displayed a chatter for an existing record',
    async () => {
        const pyEnv = await startServer();
        const partnerId = pyEnv["res.partner"].create({});
        const views = {
            "res.partner,false,form": `
                <form string="Partners">
                    <sheet>
                        <field name="name"/>
                    </sheet>
                    <div class="oe_chatter">
                        <field name="message_ids"/>
                    </div>
                </form>`,
        };
        const { openView } = await start({ serverData: { views } });
        openView({
            res_model: "res.partner",
            res_id: partnerId,
            views: [[false, "form"]],
        });
        await click(".o_control_panel_collapsed_create .o_form_button_create");
        await contains(".o-mail-Message");
        await contains(".o-mail-Message-body", { text: "Creating a new record..." });
    }
);

QUnit.test(
    "should display subject when subject is not the same as the default subject",
    async () => {
        const pyEnv = await startServer();
        const fakeId = pyEnv["res.fake"].create({ name: "Salutations, voyageur" });
        pyEnv["mail.message"].create({
            body: "not empty",
            model: "res.fake",
            res_id: fakeId,
            subject: "Another Subject",
        });
        const { openFormView } = await start();
        openFormView("res.fake", fakeId);
        await contains(".o-mail-Message", { text: "Subject: Another Subjectnot empty" });
    }
);

QUnit.test(
    "should not display subject when subject is the same as the default subject",
    async () => {
        const pyEnv = await startServer();
        const fakeId = pyEnv["res.fake"].create({ name: "Salutations, voyageur" });
        pyEnv["mail.message"].create({
            body: "not empty",
            model: "res.fake",
            res_id: fakeId,
            subject: "Custom Default Subject",
        });
        const { openFormView } = await start();
        openFormView("res.fake", fakeId);
        await contains(".o-mail-Message", { text: "not empty" });
        await contains(".o-mail-Message", {
            count: 0,
            text: "Subject: Custom Default Subjectnot empty",
        });
    }
);

QUnit.test(
    "should not display subject when subject is the same as the thread name with custom default subject",
    async () => {
        const pyEnv = await startServer();
        const fakeId = pyEnv["res.fake"].create({ name: "Salutations, voyageur" });
        pyEnv["mail.message"].create({
            body: "not empty",
            model: "res.fake",
            res_id: fakeId,
            subject: "Salutations, voyageur",
        });
        const { openFormView } = await start();
        openFormView("res.fake", fakeId);
        await contains(".o-mail-Message", { text: "not empty" });
        await contains(".o-mail-Message", {
            count: 0,
            text: "Subject: Custom Default Subjectnot empty",
        });
    }
);

QUnit.test("basic chatter rendering without followers", async () => {
    const pyEnv = await startServer();
    const partnerId = pyEnv["res.partner"].create({ display_name: "second partner" });
    const views = {
        "res.partner,false,form": `
            <form string="Partners">
                <sheet>
                    <field name="name"/>
                </sheet>
                <div class="oe_chatter">
                    <field name="activity_ids"/>
                    <field name="message_ids"/>
                    <!-- no message_follower_ids field -->
                </div>
            </form>`,
    };
    const { openView } = await start({ serverData: { views } });
    openView({
        res_model: "res.partner",
        res_id: partnerId,
        views: [[false, "form"]],
    });
    await contains(".o-mail-Chatter");
    await contains(".o-mail-Chatter-topbar");
    await contains("button[aria-label='Attach files']");
    await contains("button", { text: "Activities" });
    await contains(".o-mail-Chatter .o-mail-Thread");
    await contains(".o-mail-Followers", { count: 0 });
});

QUnit.test("basic chatter rendering without messages", async () => {
    const pyEnv = await startServer();
    const partnerId = pyEnv["res.partner"].create({ display_name: "second partner" });
    const views = {
        "res.partner,false,form": `
            <form string="Partners">
                <sheet>
                    <field name="name"/>
                </sheet>
                <div class="oe_chatter">
                    <field name="message_follower_ids"/>
                    <field name="activity_ids"/>
                    <!-- no message_ids field -->
                </div>
            </form>`,
    };
    const { openView } = await start({ serverData: { views } });
    openView({
        res_model: "res.partner",
        res_id: partnerId,
        views: [[false, "form"]],
    });
    await contains(".o-mail-Chatter");
    await contains(".o-mail-Chatter-topbar");
    await contains("button[aria-label='Attach files']");
    await contains("button", { text: "Activities" });
    await contains(".o-mail-Followers");
    await contains(".o-mail-Chatter .o-mail-Thread", { count: 0 });
});

QUnit.test("chatter updating", async () => {
    const pyEnv = await startServer();
    const [partnerId_1, partnerId_2] = pyEnv["res.partner"].create([
        { display_name: "first partner" },
        { display_name: "second partner" },
    ]);
    pyEnv["mail.message"].create({
        body: "not empty",
        model: "res.partner",
        res_id: partnerId_2,
    });
    const views = {
        "res.partner,false,form": `
            <form string="Partners">
                <sheet>
                    <field name="name"/>
                </sheet>
                <div class="oe_chatter">
                    <field name="message_ids"/>
                </div>
            </form>`,
    };
    const { openFormView } = await start({ serverData: { views } });
    openFormView("res.partner", partnerId_1, {
        props: { resIds: [partnerId_1, partnerId_2] },
    });
    await click(".o_pager_next");
    await contains(".o-mail-Message");
});

QUnit.test("post message on draft record", async () => {
    const views = {
        "res.partner,false,form": `
            <form string="Partners">
                <sheet>
                    <field name="name"/>
                </sheet>
                <div class="oe_chatter">
                    <field name="message_ids"/>
                </div>
            </form>`,
    };
    const { openView } = await start({ serverData: { views } });
    openView({
        res_model: "res.partner",
        views: [[false, "form"]],
    });
    await click("button", { text: "Send message" });
    await insertText(".o-mail-Composer-input", "Test");
    await click(".o-mail-Composer button:enabled", { text: "Send" });
    await contains(".o-mail-Message");
    await contains(".o-mail-Message-content", { text: "Test" });
});

QUnit.test(
    "schedule activities on draft record should prompt with scheduling an activity (proceed with action)",
    async (assert) => {
        const views = {
            "res.partner,false,form": `
                <form string="Partners">
                    <sheet>
                        <field name="name"/>
                    </sheet>
                    <div class="oe_chatter">
                        <field name="activity_ids"/>
                    </div>
                </form>`,
        };
        const { env, openFormView } = await start({ serverData: { views } });
        const wizardOpened = makeDeferred();
        patchWithCleanup(env.services.action, {
            doAction(action, options) {
                if (action.res_model === "res.partner") {
                    return super.doAction(action, options);
                } else if (action.res_model === "mail.activity.schedule") {
                    assert.step("mail.activity.schedule");
                    assert.equal(action.context.active_model, "res.partner");
                    assert.ok(Number(action.context.active_id));
                    options.onClose();
                    wizardOpened.resolve();
                } else {
                    assert.step("Unexpected action" + action.res_model);
                }
            },
        });
        await openFormView("res.partner");
        await click("button", { text: "Activities" });
        await wizardOpened;
        assert.verifySteps(["mail.activity.schedule"]);
    }
);

QUnit.test("upload attachment on draft record", async () => {
    const views = {
        "res.partner,false,form": `
            <form string="Partners">
                <sheet>
                    <field name="name"/>
                </sheet>
                <div class="oe_chatter">
                    <field name="message_ids"/>
                </div>
            </form>`,
    };
    const { openView } = await start({ serverData: { views } });
    openView({
        res_model: "res.partner",
        views: [[false, "form"]],
    });
    await contains("button[aria-label='Attach files']");
    await contains("button[aria-label='Attach files']", { count: 0, text: "1" });
    const files = [
        await createFile({
            content: "hello, world",
            contentType: "text/plain",
            name: "text.txt",
        }),
    ];
    await dragenterFiles(".o-mail-Chatter", files);
    await dropFiles(".o-mail-Dropzone", files);
    await contains("button[aria-label='Attach files']", { text: "1" });
});

QUnit.test("Follower count of draft record is set to 0", async () => {
    const { openView } = await start();
    await openView({ res_model: "res.partner", views: [[false, "form"]] });
    await contains(".o-mail-Followers", { text: "0" });
});

QUnit.test("Mentions in composer should still work when using pager", async () => {
    const pyEnv = await startServer();
    const [partnerId_1, partnerId_2] = pyEnv["res.partner"].create([
        { display_name: "Partner 1" },
        { display_name: "Partner 2" },
    ]);
    const views = {
        "res.partner,false,form": `
            <form string="Partners">
                <sheet>
                    <field name="name"/>
                </sheet>
                <div class="oe_chatter">
                    <field name="message_ids"/>
                </div>
            </form>`,
    };
    patchUiSize({ size: SIZES.LG });
    const { openView } = await start({ serverData: { views } });
    await openView(
        {
            res_model: "res.partner",
            res_id: partnerId_1,
            views: [[false, "form"]],
        },
        { resIds: [partnerId_1, partnerId_2] }
    );

    await click("button", { text: "Log note" });
    await click(".o_pager_next");
    await insertText(".o-mail-Composer-input", "@");
    await contains(".o-mail-Composer-suggestion", { count: 2 });
});
