mirror of
https://github.com/bringout/oca-ocb-core.git
synced 2026-04-20 11:52:04 +02:00
19.0 vanilla
This commit is contained in:
parent
d1963a3c3a
commit
2d3ee4855a
7430 changed files with 2687981 additions and 2965473 deletions
|
|
@ -0,0 +1,60 @@
|
|||
import { addBusServiceListeners, lockWebsocketConnect } from "@bus/../tests/bus_test_helpers";
|
||||
import { getWebSocketWorker } from "@bus/../tests/mock_websocket";
|
||||
import { WEBSOCKET_CLOSE_CODES } from "@bus/workers/websocket_worker";
|
||||
import { defineMailModels, openDiscuss, start } from "@mail/../tests/mail_test_helpers";
|
||||
import { describe, expect, test } from "@odoo/hoot";
|
||||
import { animationFrame, runAllTimers, waitFor, waitForNone } from "@odoo/hoot-dom";
|
||||
|
||||
import {
|
||||
asyncStep,
|
||||
makeMockServer,
|
||||
MockServer,
|
||||
patchWithCleanup,
|
||||
waitForSteps,
|
||||
} from "@web/../tests/web_test_helpers";
|
||||
import { browser } from "@web/core/browser/browser";
|
||||
|
||||
defineMailModels();
|
||||
describe.current.tags("desktop");
|
||||
|
||||
test("show warning when bus connection encounters issues", async () => {
|
||||
await makeMockServer();
|
||||
// Avoid excessively long exponential backoff.
|
||||
patchWithCleanup(getWebSocketWorker(), {
|
||||
INITIAL_RECONNECT_DELAY: 50,
|
||||
RECONNECT_JITTER: 50,
|
||||
});
|
||||
// The bus service listens to online/offline events. Prevent them to make the
|
||||
// test deterministic.
|
||||
for (const event of ["online", "offline"]) {
|
||||
browser.addEventListener(
|
||||
event,
|
||||
(ev) => {
|
||||
ev.preventDefault();
|
||||
ev.stopImmediatePropagation();
|
||||
},
|
||||
{ capture: true }
|
||||
);
|
||||
}
|
||||
addBusServiceListeners(
|
||||
["BUS:CONNECT", () => asyncStep("BUS:CONNECT")],
|
||||
["BUS:RECONNECT", () => asyncStep("BUS:RECONNECT")],
|
||||
["BUS:RECONNECTING", () => asyncStep("BUS:RECONNECTING")]
|
||||
);
|
||||
await start();
|
||||
await openDiscuss();
|
||||
await waitForSteps(["BUS:CONNECT"]);
|
||||
const unlockWebsocket = lockWebsocketConnect();
|
||||
MockServer.env["bus.bus"]._simulateDisconnection(WEBSOCKET_CLOSE_CODES.ABNORMAL_CLOSURE);
|
||||
await waitForSteps(["BUS:RECONNECTING"]);
|
||||
expect(await waitFor(".o-bus-ConnectionAlert", { timeout: 2500 })).toHaveText(
|
||||
"Real-time connection lost..."
|
||||
);
|
||||
await runAllTimers();
|
||||
await animationFrame();
|
||||
expect(".o-bus-ConnectionAlert").toHaveText("Real-time connection lost...");
|
||||
unlockWebsocket();
|
||||
await runAllTimers();
|
||||
await waitForSteps(["BUS:RECONNECT"]);
|
||||
await waitForNone(".o-bus-ConnectionAlert");
|
||||
});
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,108 @@
|
|||
import {
|
||||
click,
|
||||
contains,
|
||||
defineMailModels,
|
||||
openDiscuss,
|
||||
start,
|
||||
startServer,
|
||||
} from "@mail/../tests/mail_test_helpers";
|
||||
import { Store } from "@mail/core/common/store_service";
|
||||
import { describe, test } from "@odoo/hoot";
|
||||
import { Command, patchWithCleanup, serverState } from "@web/../tests/web_test_helpers";
|
||||
|
||||
describe.current.tags("desktop");
|
||||
defineMailModels();
|
||||
|
||||
test("initially online", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo", im_status: "online" });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
Command.create({ partner_id: serverState.partnerId }),
|
||||
Command.create({ partner_id: partnerId }),
|
||||
],
|
||||
channel_type: "chat",
|
||||
});
|
||||
await start();
|
||||
await openDiscuss(channelId);
|
||||
await contains(".o-mail-DiscussContent-header .o-mail-ImStatus i[title='Online']");
|
||||
});
|
||||
|
||||
test("initially offline", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo", im_status: "offline" });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
Command.create({ partner_id: serverState.partnerId }),
|
||||
Command.create({ partner_id: partnerId }),
|
||||
],
|
||||
channel_type: "chat",
|
||||
});
|
||||
await start();
|
||||
await openDiscuss(channelId);
|
||||
await contains(".o-mail-DiscussContent-header .o-mail-ImStatus i[title='Offline']");
|
||||
});
|
||||
|
||||
test("initially away", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo", im_status: "away" });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
Command.create({ partner_id: serverState.partnerId }),
|
||||
Command.create({ partner_id: partnerId }),
|
||||
],
|
||||
channel_type: "chat",
|
||||
});
|
||||
await start();
|
||||
await openDiscuss(channelId);
|
||||
await contains(".o-mail-DiscussContent-header .o-mail-ImStatus i[title='Idle']");
|
||||
});
|
||||
|
||||
test("change icon on change partner im_status", async () => {
|
||||
patchWithCleanup(Store, { IM_STATUS_DEBOUNCE_DELAY: 0 });
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ channel_type: "chat" });
|
||||
pyEnv["res.partner"].write([serverState.partnerId], { im_status: "online" });
|
||||
await start();
|
||||
await openDiscuss(channelId);
|
||||
await contains(".o-mail-DiscussContent-header .o-mail-ImStatus i[title='Online']");
|
||||
pyEnv["res.partner"].write([serverState.partnerId], { im_status: "offline" });
|
||||
pyEnv["bus.bus"]._sendone(serverState.partnerId, "bus.bus/im_status_updated", {
|
||||
partner_id: serverState.partnerId,
|
||||
im_status: "offline",
|
||||
presence_status: "offline",
|
||||
});
|
||||
await contains(".o-mail-DiscussContent-header .o-mail-ImStatus i[title='Offline']");
|
||||
pyEnv["res.partner"].write([serverState.partnerId], { im_status: "away" });
|
||||
pyEnv["bus.bus"]._sendone(serverState.partnerId, "bus.bus/im_status_updated", {
|
||||
partner_id: serverState.partnerId,
|
||||
im_status: "away",
|
||||
presence_status: "away",
|
||||
});
|
||||
await contains(".o-mail-DiscussContent-header .o-mail-ImStatus i[title='Idle']");
|
||||
pyEnv["res.partner"].write([serverState.partnerId], { im_status: "online" });
|
||||
pyEnv["bus.bus"]._sendone(serverState.partnerId, "bus.bus/im_status_updated", {
|
||||
partner_id: serverState.partnerId,
|
||||
im_status: "online",
|
||||
presence_status: "online",
|
||||
});
|
||||
await contains(".o-mail-DiscussContent-header .o-mail-ImStatus i[title='Online']");
|
||||
});
|
||||
|
||||
test("show im status in messaging menu preview of chat", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo", im_status: "online" });
|
||||
pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
Command.create({ partner_id: serverState.partnerId }),
|
||||
Command.create({ partner_id: partnerId }),
|
||||
],
|
||||
channel_type: "chat",
|
||||
});
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await contains(".o-mail-NotificationItem", {
|
||||
text: "Demo",
|
||||
contains: ["i[aria-label='User is online']"],
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,762 @@
|
|||
import {
|
||||
click,
|
||||
contains,
|
||||
defineMailModels,
|
||||
insertText,
|
||||
onRpcBefore,
|
||||
openDiscuss,
|
||||
scroll,
|
||||
start,
|
||||
startServer,
|
||||
triggerHotkey,
|
||||
} from "@mail/../tests/mail_test_helpers";
|
||||
import { describe, expect, test } from "@odoo/hoot";
|
||||
import { Deferred } from "@odoo/hoot-mock";
|
||||
import {
|
||||
asyncStep,
|
||||
mockService,
|
||||
serverState,
|
||||
waitForSteps,
|
||||
withUser,
|
||||
} from "@web/../tests/web_test_helpers";
|
||||
|
||||
import { rpc } from "@web/core/network/rpc";
|
||||
|
||||
describe.current.tags("desktop");
|
||||
defineMailModels();
|
||||
|
||||
test("reply: discard on reply button toggle", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "res.partner",
|
||||
needaction: true,
|
||||
res_id: partnerId,
|
||||
});
|
||||
pyEnv["mail.notification"].create({
|
||||
mail_message_id: messageId,
|
||||
notification_status: "sent",
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
});
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message");
|
||||
await click("[title='Expand']");
|
||||
await click(".o-dropdown-item:contains('Reply')");
|
||||
await contains(".o-mail-Composer");
|
||||
await click("[title='Expand']");
|
||||
await click(".o-dropdown-item:contains('Reply')");
|
||||
await contains(".o-mail-Composer", { count: 0 });
|
||||
});
|
||||
|
||||
test.tags("focus required");
|
||||
test("reply: discard on pressing escape", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({
|
||||
email: "testpartnert@odoo.com",
|
||||
name: "TestPartner",
|
||||
});
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "res.partner",
|
||||
needaction: true,
|
||||
res_id: partnerId,
|
||||
});
|
||||
pyEnv["mail.notification"].create({
|
||||
mail_message_id: messageId,
|
||||
notification_status: "sent",
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
});
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message");
|
||||
await click("[title='Expand']");
|
||||
await click(".o-dropdown-item:contains('Reply')");
|
||||
await contains(".o-mail-Composer");
|
||||
// Escape on emoji picker does not stop replying
|
||||
await click(".o-mail-Composer button[title='Add Emojis']");
|
||||
await contains(".o-EmojiPicker");
|
||||
triggerHotkey("Escape");
|
||||
await contains(".o-EmojiPicker", { count: 0 });
|
||||
await contains(".o-mail-Composer");
|
||||
// Escape on suggestion prompt does not stop replying
|
||||
await insertText(".o-mail-Composer-input", "@");
|
||||
await contains(".o-mail-Composer-suggestionList .o-open");
|
||||
triggerHotkey("Escape");
|
||||
await contains(".o-mail-Composer-suggestionList .o-open", { count: 0 });
|
||||
await contains(".o-mail-Composer");
|
||||
await click(".o-mail-Composer-input").catch(() => {});
|
||||
await contains(".o-mail-Composer.o-focused");
|
||||
triggerHotkey("Escape");
|
||||
await contains(".o-mail-Composer", { count: 0 });
|
||||
});
|
||||
|
||||
test('"reply to" composer should log note if message replied to is a note', async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
subtype_id: pyEnv["mail.message.subtype"].search([
|
||||
["subtype_xmlid", "=", "mail.mt_note"],
|
||||
])[0],
|
||||
model: "res.partner",
|
||||
needaction: true,
|
||||
res_id: partnerId,
|
||||
});
|
||||
pyEnv["mail.notification"].create({
|
||||
mail_message_id: messageId,
|
||||
notification_status: "sent",
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
});
|
||||
onRpcBefore("/mail/message/post", (args) => {
|
||||
asyncStep("/mail/message/post");
|
||||
expect(args.post_data.message_type).toBe("comment");
|
||||
expect(args.post_data.subtype_xmlid).toBe("mail.mt_note");
|
||||
});
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message");
|
||||
await click("[title='Expand']");
|
||||
await click(".o-dropdown-item:contains('Reply')");
|
||||
await contains(".o-mail-Composer [placeholder='Log an internal note…']");
|
||||
await insertText(".o-mail-Composer-input", "Test");
|
||||
await click(".o-mail-Composer button[title='Log']");
|
||||
await contains(".o-mail-Composer", { count: 0 });
|
||||
await waitForSteps(["/mail/message/post"]);
|
||||
});
|
||||
|
||||
test('"reply to" composer should send message if message replied to is not a note', async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
subtype_id: pyEnv["mail.message.subtype"].search([
|
||||
["subtype_xmlid", "=", "mail.mt_comment"],
|
||||
])[0],
|
||||
model: "res.partner",
|
||||
needaction: true,
|
||||
res_id: partnerId,
|
||||
});
|
||||
pyEnv["mail.notification"].create({
|
||||
mail_message_id: messageId,
|
||||
notification_status: "sent",
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
});
|
||||
onRpcBefore("/mail/message/post", (args) => {
|
||||
asyncStep("/mail/message/post");
|
||||
expect(args.post_data.message_type).toBe("comment");
|
||||
expect(args.post_data.subtype_xmlid).toBe("mail.mt_comment");
|
||||
});
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message");
|
||||
await click("[title='Expand']");
|
||||
await click(".o-dropdown-item:contains('Reply')");
|
||||
await contains(".o-mail-Composer [placeholder='Send a message to followers…']");
|
||||
await insertText(".o-mail-Composer-input", "Test");
|
||||
await click(".o-mail-Composer button[title='Send']:enabled");
|
||||
await contains(".o-mail-Composer button[title='Send']", { count: 0 });
|
||||
await waitForSteps(["/mail/message/post"]);
|
||||
});
|
||||
|
||||
test("show subject of message in Inbox", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "discuss.channel",
|
||||
needaction: true,
|
||||
subject: "Salutations, voyageur",
|
||||
});
|
||||
pyEnv["mail.notification"].create({
|
||||
mail_message_id: messageId,
|
||||
notification_status: "sent",
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
});
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message", { text: "Subject: Salutations, voyageurnot empty" });
|
||||
});
|
||||
|
||||
test("show subject of message in history", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "discuss.channel",
|
||||
subject: "Salutations, voyageur",
|
||||
});
|
||||
pyEnv["mail.notification"].create({
|
||||
is_read: true,
|
||||
mail_message_id: messageId,
|
||||
notification_status: "sent",
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
});
|
||||
await start();
|
||||
await openDiscuss("mail.box_history");
|
||||
await contains(".o-mail-Message", { text: "Subject: Salutations, voyageurnot empty" });
|
||||
});
|
||||
|
||||
test("subject should not be shown when subject is the same as the thread name", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "Salutations, voyageur" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
needaction: true,
|
||||
subject: "Salutations, voyageur",
|
||||
});
|
||||
pyEnv["mail.notification"].create({
|
||||
mail_message_id: messageId,
|
||||
notification_status: "sent",
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
});
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message", {
|
||||
count: 0,
|
||||
text: "Subject: Salutations, voyageurnot empty",
|
||||
});
|
||||
});
|
||||
|
||||
test("subject should not be shown when subject is the same as the thread name and both have the same prefix", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "Re: Salutations, voyageur" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
needaction: true,
|
||||
subject: "Re: Salutations, voyageur",
|
||||
});
|
||||
pyEnv["mail.notification"].create({
|
||||
mail_message_id: messageId,
|
||||
notification_status: "sent",
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
});
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message", {
|
||||
count: 0,
|
||||
text: "Subject: Salutations, voyageurnot empty",
|
||||
});
|
||||
});
|
||||
|
||||
test('subject should not be shown when subject differs from thread name only by the "Re:" prefix', async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "Salutations, voyageur" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
needaction: true,
|
||||
subject: "Re: Salutations, voyageur",
|
||||
});
|
||||
pyEnv["mail.notification"].create({
|
||||
mail_message_id: messageId,
|
||||
notification_status: "sent",
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
});
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message", {
|
||||
count: 0,
|
||||
text: "Subject: Salutations, voyageurnot empty",
|
||||
});
|
||||
});
|
||||
|
||||
test('subject should not be shown when subject differs from thread name only by the "Fw:" and "Re:" prefix', async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "Salutations, voyageur" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
needaction: true,
|
||||
subject: "Fw: Re: Salutations, voyageur",
|
||||
});
|
||||
pyEnv["mail.notification"].create({
|
||||
mail_message_id: messageId,
|
||||
notification_status: "sent",
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
});
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message", {
|
||||
count: 0,
|
||||
text: "Subject: Salutations, voyageurnot empty",
|
||||
});
|
||||
});
|
||||
|
||||
test("subject should be shown when the thread name has an extra prefix compared to subject", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "Re: Salutations, voyageur" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
needaction: true,
|
||||
subject: "Salutations, voyageur",
|
||||
});
|
||||
pyEnv["mail.notification"].create({
|
||||
mail_message_id: messageId,
|
||||
notification_status: "sent",
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
});
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message", {
|
||||
count: 0,
|
||||
text: "Subject: Salutations, voyageurnot empty",
|
||||
});
|
||||
});
|
||||
|
||||
test('subject should not be shown when subject differs from thread name only by the "fw:" prefix and both contain another common prefix', async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "Re: Salutations, voyageur" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
needaction: true,
|
||||
subject: "fw: re: Salutations, voyageur",
|
||||
});
|
||||
pyEnv["mail.notification"].create({
|
||||
mail_message_id: messageId,
|
||||
notification_status: "sent",
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
});
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message", {
|
||||
count: 0,
|
||||
text: "Subject: Salutations, voyageurnot empty",
|
||||
});
|
||||
});
|
||||
|
||||
test('subject should not be shown when subject differs from thread name only by the "Re: Re:" prefix', async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "Salutations, voyageur" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
needaction: true,
|
||||
subject: "Re: Re: Salutations, voyageur",
|
||||
});
|
||||
pyEnv["mail.notification"].create({
|
||||
mail_message_id: messageId,
|
||||
notification_status: "sent",
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
});
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message", {
|
||||
count: 0,
|
||||
text: "Subject: Salutations, voyageurnot empty",
|
||||
});
|
||||
});
|
||||
|
||||
test("inbox: mark all messages as read", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["res.users"].write(serverState.userId, { notification_type: "inbox" });
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const [messageId_1, messageId_2] = pyEnv["mail.message"].create([
|
||||
{
|
||||
body: "not empty",
|
||||
model: "discuss.channel",
|
||||
needaction: true,
|
||||
res_id: channelId,
|
||||
},
|
||||
{
|
||||
body: "not empty",
|
||||
model: "discuss.channel",
|
||||
needaction: true,
|
||||
res_id: channelId,
|
||||
},
|
||||
]);
|
||||
pyEnv["mail.notification"].create([
|
||||
{
|
||||
mail_message_id: messageId_1,
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
},
|
||||
{
|
||||
mail_message_id: messageId_2,
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
},
|
||||
]);
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains("button", { text: "Inbox", contains: [".badge", { text: "2" }] });
|
||||
await contains(".o-mail-DiscussSidebarChannel", {
|
||||
contains: [
|
||||
["span", { text: "General" }],
|
||||
[".badge", { text: "2" }],
|
||||
],
|
||||
});
|
||||
await contains(".o-mail-DiscussContent .o-mail-Message", { count: 2 });
|
||||
await click(".o-mail-DiscussContent-header button:enabled", { text: "Mark all read" });
|
||||
await contains("button", { text: "Inbox", contains: [".badge", { count: 0 }] });
|
||||
await contains(".o-mail-DiscussSidebarChannel", {
|
||||
contains: [
|
||||
["span", { text: "General" }],
|
||||
[".badge", { count: 0 }],
|
||||
],
|
||||
});
|
||||
await contains(".o-mail-Message", { count: 0 });
|
||||
await contains("button:disabled", { text: "Mark all read" });
|
||||
});
|
||||
|
||||
test("inbox: mark as read should not display jump to present", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const msgIds = pyEnv["mail.message"].create(
|
||||
Array(30)
|
||||
.keys()
|
||||
.map((i) => ({
|
||||
body: "not empty".repeat(100),
|
||||
model: "discuss.channel",
|
||||
needaction: true,
|
||||
res_id: channelId,
|
||||
}))
|
||||
);
|
||||
pyEnv["mail.notification"].create(
|
||||
Array(30)
|
||||
.keys()
|
||||
.map((i) => ({
|
||||
mail_message_id: msgIds[i],
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
}))
|
||||
);
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
// scroll up so that there's the "Jump to Present".
|
||||
// So that assertion of negative matches the positive assertion
|
||||
await contains(".o-mail-Message", { count: 30 });
|
||||
await scroll(".o-mail-Thread", 0);
|
||||
await contains("[title='Jump to Present']");
|
||||
await click(".o-mail-DiscussContent-header button:enabled", { text: "Mark all read" });
|
||||
await contains("[title='Jump to Present']", { count: 0 });
|
||||
});
|
||||
|
||||
test("click on (non-channel/non-partner) origin thread link should redirect to form view", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const fakeId = pyEnv["res.fake"].create({ name: "Some record" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "res.fake",
|
||||
needaction: true,
|
||||
res_id: fakeId,
|
||||
});
|
||||
pyEnv["mail.notification"].create({
|
||||
mail_message_id: messageId,
|
||||
notification_status: "sent",
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
});
|
||||
const def = new Deferred();
|
||||
mockService("action", {
|
||||
async doAction(action) {
|
||||
if (action?.res_model !== "res.fake") {
|
||||
return super.doAction(...arguments);
|
||||
}
|
||||
// Callback of doing an action (action manager).
|
||||
// Expected to be called on click on origin thread link,
|
||||
// which redirects to form view of record related to origin thread
|
||||
asyncStep("do-action");
|
||||
expect(action.type).toBe("ir.actions.act_window");
|
||||
expect(action.views).toEqual([[false, "form"]]);
|
||||
expect(action.res_model).toBe("res.fake");
|
||||
expect(action.res_id).toBe(fakeId);
|
||||
def.resolve();
|
||||
},
|
||||
});
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message");
|
||||
await click(".o-mail-Message-header a", { text: "Some record" });
|
||||
await def;
|
||||
await waitForSteps(["do-action"]);
|
||||
});
|
||||
|
||||
test("inbox messages are never squashed", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "test" });
|
||||
const [messageId_1, messageId_2] = pyEnv["mail.message"].create([
|
||||
{
|
||||
author_id: partnerId,
|
||||
body: "<p>body1</p>",
|
||||
date: "2019-04-20 10:00:00",
|
||||
message_type: "comment",
|
||||
model: "discuss.channel",
|
||||
needaction: true,
|
||||
res_id: channelId,
|
||||
},
|
||||
{
|
||||
author_id: partnerId,
|
||||
body: "<p>body2</p>",
|
||||
date: "2019-04-20 10:00:30",
|
||||
message_type: "comment",
|
||||
model: "discuss.channel",
|
||||
needaction: true,
|
||||
res_id: channelId,
|
||||
},
|
||||
]);
|
||||
pyEnv["mail.notification"].create([
|
||||
{
|
||||
mail_message_id: messageId_1,
|
||||
notification_status: "sent",
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
},
|
||||
{
|
||||
mail_message_id: messageId_2,
|
||||
notification_status: "sent",
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
},
|
||||
]);
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message", { count: 2 });
|
||||
await contains(".o-mail-Message:not(.o-squashed)", { text: "body1" });
|
||||
await contains(".o-mail-Message:not(.o-squashed)", { text: "body2" });
|
||||
await click(".o-mail-DiscussSidebarChannel", { text: "test" });
|
||||
await contains(".o-mail-Message.o-squashed", { text: "body2" });
|
||||
});
|
||||
|
||||
test("reply: stop replying button click", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "res.partner",
|
||||
needaction: true,
|
||||
res_id: partnerId,
|
||||
});
|
||||
pyEnv["mail.notification"].create({
|
||||
mail_message_id: messageId,
|
||||
notification_status: "sent",
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
});
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message");
|
||||
await click("[title='Expand']");
|
||||
await click(".o-dropdown-item:contains('Reply')");
|
||||
await contains(".o-mail-Composer");
|
||||
await contains("i[title='Stop replying']");
|
||||
await click("i[title='Stop replying']");
|
||||
await contains(".o-mail-Composer", { count: 0 });
|
||||
});
|
||||
|
||||
test("error notifications should not be shown in Inbox", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo User" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "res.partner",
|
||||
needaction: true,
|
||||
res_id: partnerId,
|
||||
});
|
||||
pyEnv["mail.notification"].create({
|
||||
mail_message_id: messageId,
|
||||
notification_status: "exception",
|
||||
notification_type: "email",
|
||||
res_partner_id: serverState.partnerId,
|
||||
});
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message-header small", { text: "on Demo User" });
|
||||
await contains(`.o-mail-Message-header a[href*='/odoo/res.partner/${partnerId}']`, {
|
||||
text: "Demo User",
|
||||
});
|
||||
await contains(".o-mail-Message-notification", { count: 0 });
|
||||
});
|
||||
|
||||
test("emptying inbox displays rainbow man in inbox", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const messageId1 = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "discuss.channel",
|
||||
needaction: true,
|
||||
res_id: channelId,
|
||||
});
|
||||
pyEnv["mail.notification"].create([
|
||||
{
|
||||
mail_message_id: messageId1,
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
},
|
||||
]);
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message");
|
||||
await click("button:enabled", { text: "Mark all read" });
|
||||
await contains(".o_reward_rainbow");
|
||||
});
|
||||
|
||||
test("emptying inbox doesn't display rainbow man in another thread", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["res.users"].write(serverState.userId, { notification_type: "inbox" });
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "res.partner",
|
||||
needaction: true,
|
||||
res_id: partnerId,
|
||||
});
|
||||
pyEnv["mail.notification"].create([
|
||||
{
|
||||
mail_message_id: messageId,
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
},
|
||||
]);
|
||||
await start();
|
||||
await openDiscuss(channelId);
|
||||
await contains("button", { text: "Inbox", contains: [".badge", { text: "1" }] });
|
||||
const [partner] = pyEnv["res.partner"].read(serverState.partnerId);
|
||||
pyEnv["bus.bus"]._sendone(partner, "mail.message/mark_as_read", {
|
||||
message_ids: [messageId],
|
||||
needaction_inbox_counter: 0,
|
||||
});
|
||||
await contains("button", { text: "Inbox", contains: [".badge", { count: 0 }] });
|
||||
// weak test, no guarantee that we waited long enough for the potential rainbow man to show
|
||||
await contains(".o_reward_rainbow", { count: 0 });
|
||||
});
|
||||
|
||||
test("Counter should be incremented by 1 when receiving a message with a mention in a channel", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["res.users"].write(serverState.userId, { notification_type: "inbox" });
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Thread" });
|
||||
const partnerUserId = pyEnv["res.partner"].create({ name: "partner1" });
|
||||
const userId = pyEnv["res.users"].create({ partner_id: partnerUserId });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "res.partner",
|
||||
needaction: true,
|
||||
res_id: partnerId,
|
||||
});
|
||||
pyEnv["mail.notification"].create([
|
||||
{
|
||||
mail_message_id: messageId,
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
},
|
||||
]);
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains("button", { text: "Inbox", contains: [".badge", { text: "1" }] });
|
||||
const mention = [serverState.partnerId];
|
||||
const mentionName = serverState.partnerName;
|
||||
withUser(userId, () =>
|
||||
rpc("/mail/message/post", {
|
||||
post_data: {
|
||||
body: `<a href="https://www.hoot.test/odoo/res.partner/17" class="o_mail_redirect" data-oe-id="${mention[0]}" data-oe-model="res.partner" target="_blank" contenteditable="false">@${mentionName}</a> mention`,
|
||||
message_type: "comment",
|
||||
partner_ids: mention,
|
||||
subtype_xmlid: "mail.mt_comment",
|
||||
},
|
||||
thread_id: channelId,
|
||||
thread_model: "discuss.channel",
|
||||
})
|
||||
);
|
||||
await contains("button", { text: "Inbox", contains: [".badge", { text: "2" }] });
|
||||
});
|
||||
|
||||
test("Clear need action counter when opening a channel", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const [messageId1, messageId2] = pyEnv["mail.message"].create([
|
||||
{
|
||||
body: "not empty",
|
||||
model: "discuss.channel",
|
||||
needaction: true,
|
||||
res_id: channelId,
|
||||
},
|
||||
{
|
||||
body: "not empty",
|
||||
model: "discuss.channel",
|
||||
needaction: true,
|
||||
res_id: channelId,
|
||||
},
|
||||
]);
|
||||
pyEnv["mail.notification"].create([
|
||||
{
|
||||
mail_message_id: messageId1,
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
},
|
||||
{
|
||||
mail_message_id: messageId2,
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
},
|
||||
]);
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-DiscussSidebar-item", {
|
||||
text: "General",
|
||||
contains: [".badge", { text: "2" }],
|
||||
});
|
||||
await click(".o-mail-DiscussSidebarChannel", { text: "General" });
|
||||
await contains(".o-mail-DiscussSidebar-item", {
|
||||
text: "General",
|
||||
contains: [".badge", { count: 0 }],
|
||||
});
|
||||
});
|
||||
|
||||
test("can reply to email message", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
author_id: null,
|
||||
email_from: "md@oilcompany.fr",
|
||||
body: "an email message",
|
||||
model: "res.partner",
|
||||
needaction: true,
|
||||
res_id: partnerId,
|
||||
});
|
||||
pyEnv["mail.notification"].create({
|
||||
mail_message_id: messageId,
|
||||
notification_status: "sent",
|
||||
notification_type: "inbox",
|
||||
res_partner_id: serverState.partnerId,
|
||||
});
|
||||
await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message");
|
||||
await click("[title='Expand']");
|
||||
await click(".o-dropdown-item:contains('Reply')");
|
||||
await contains(".o-mail-Composer", { text: "Replying to md@oilcompany.fr" });
|
||||
});
|
||||
|
|
@ -0,0 +1,314 @@
|
|||
import { describe, expect, test } from "@odoo/hoot";
|
||||
import { animationFrame, Deferred, press, queryFirst, tick } from "@odoo/hoot-dom";
|
||||
import {
|
||||
asyncStep,
|
||||
patchWithCleanup,
|
||||
serverState,
|
||||
waitForSteps,
|
||||
} from "@web/../tests/web_test_helpers";
|
||||
|
||||
import {
|
||||
SIZES,
|
||||
click,
|
||||
contains,
|
||||
defineMailModels,
|
||||
insertText,
|
||||
isInViewportOf,
|
||||
onRpcBefore,
|
||||
openDiscuss,
|
||||
openFormView,
|
||||
patchUiSize,
|
||||
scroll,
|
||||
start,
|
||||
startServer,
|
||||
} from "@mail/../tests/mail_test_helpers";
|
||||
import { PRESENT_VIEWPORT_THRESHOLD } from "@mail/core/common/thread";
|
||||
|
||||
describe.current.tags("desktop");
|
||||
defineMailModels();
|
||||
|
||||
test("Basic jump to present when scrolling to outdated messages", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
for (let i = 0; i < 20; i++) {
|
||||
pyEnv["mail.message"].create({
|
||||
body: "Non Empty Body ".repeat(100),
|
||||
message_type: "comment",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
});
|
||||
}
|
||||
await start();
|
||||
await openDiscuss(channelId);
|
||||
await contains(".o-mail-Message", { count: 20 });
|
||||
await contains(".o-mail-Thread");
|
||||
expect(document.querySelector(".o-mail-Thread").scrollHeight).toBeGreaterThan(
|
||||
PRESENT_VIEWPORT_THRESHOLD * document.querySelector(".o-mail-Thread").clientHeight,
|
||||
{ message: "should have enough scroll height to trigger jump to present" }
|
||||
);
|
||||
await click("[title='Jump to Present']");
|
||||
await contains("[title='Jump to Present']", { count: 0 });
|
||||
await contains(".o-mail-Thread", { scroll: "bottom" });
|
||||
});
|
||||
|
||||
test("Basic jump to present when scrolling to outdated messages (DESC, chatter aside)", async () => {
|
||||
patchUiSize({ size: SIZES.XXL });
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo User" });
|
||||
for (let i = 0; i < 20; i++) {
|
||||
pyEnv["mail.message"].create({
|
||||
body: "Non Empty Body ".repeat(100),
|
||||
message_type: "comment",
|
||||
model: "res.partner",
|
||||
res_id: partnerId,
|
||||
});
|
||||
}
|
||||
await start();
|
||||
await openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Message", { count: 20 });
|
||||
await contains(".o-mail-Thread");
|
||||
expect(document.querySelector(".o-mail-Chatter").scrollHeight).toBeGreaterThan(
|
||||
PRESENT_VIEWPORT_THRESHOLD * document.querySelector(".o-mail-Chatter").clientHeight,
|
||||
{ message: "should have enough scroll height to trigger jump to present" }
|
||||
);
|
||||
await contains(".o-mail-Chatter", { scroll: 0 });
|
||||
await scroll(".o-mail-Chatter", "bottom");
|
||||
await isInViewportOf("[title='Jump to Present']", ".o-mail-Thread");
|
||||
await click("[title='Jump to Present']");
|
||||
await contains("[title='Jump to Present']", { count: 0 });
|
||||
await contains(".o-mail-Chatter", { scroll: 0 });
|
||||
});
|
||||
|
||||
test("Basic jump to present when scrolling to outdated messages (DESC, chatter non-aside)", async () => {
|
||||
patchUiSize({ size: SIZES.MD });
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo User" });
|
||||
for (let i = 0; i < 20; i++) {
|
||||
pyEnv["mail.message"].create({
|
||||
body: "Non Empty Body ".repeat(100),
|
||||
message_type: "comment",
|
||||
model: "res.partner",
|
||||
res_id: partnerId,
|
||||
});
|
||||
}
|
||||
await start();
|
||||
await openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Message", { count: 20 });
|
||||
await contains(".o_content");
|
||||
expect(document.querySelector(".o_content").scrollHeight).toBeGreaterThan(
|
||||
PRESENT_VIEWPORT_THRESHOLD * document.querySelector(".o_content").clientHeight,
|
||||
{ message: "should have enough scroll height to trigger jump to present" }
|
||||
);
|
||||
await contains(".o_content", { scroll: 0 });
|
||||
await scroll(".o_content", "bottom");
|
||||
await isInViewportOf("[title='Jump to Present']", ".o_content");
|
||||
await click("[title='Jump to Present']");
|
||||
await contains("[title='Jump to Present']", { count: 0 });
|
||||
await contains(".o_content", { scroll: 0 });
|
||||
});
|
||||
|
||||
test("Jump to old reply should prompt jump to present", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const oldestMessageId = pyEnv["mail.message"].create({
|
||||
body: "<p>Hello world!</p>",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
});
|
||||
for (let i = 0; i < 100; i++) {
|
||||
pyEnv["mail.message"].create({
|
||||
body: "<p>Non Empty Body</p>".repeat(100),
|
||||
message_type: "comment",
|
||||
model: "discuss.channel",
|
||||
/**
|
||||
* The first message following the oldest message should have it as its parent message
|
||||
* so that the oldest message is inserted through the parent field during "load around"
|
||||
* to have the coverage of this part of the code (in particular having parent message
|
||||
* body being inserted with markup).
|
||||
*/
|
||||
parent_id: i === 0 ? oldestMessageId : undefined,
|
||||
res_id: channelId,
|
||||
});
|
||||
}
|
||||
const newestMessageId = pyEnv["mail.message"].create({
|
||||
body: "Most Recent!",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
parent_id: oldestMessageId,
|
||||
});
|
||||
const [selfMember] = pyEnv["discuss.channel.member"].search_read([
|
||||
["partner_id", "=", serverState.partnerId],
|
||||
["channel_id", "=", channelId],
|
||||
]);
|
||||
pyEnv["discuss.channel.member"].write([selfMember.id], {
|
||||
new_message_separator: newestMessageId + 1,
|
||||
});
|
||||
await start();
|
||||
await openDiscuss(channelId);
|
||||
await contains(".o-mail-Message", { count: 30 });
|
||||
await click(".o-mail-MessageInReply .cursor-pointer");
|
||||
await contains(".o-mail-Message", { count: 30 });
|
||||
await contains(":nth-child(1 of .o-mail-Message)", { text: "Hello world!" });
|
||||
await click("[title='Jump to Present']");
|
||||
await contains("[title='Jump to Present']", { count: 0 });
|
||||
await contains(".o-mail-Message", { count: 30 });
|
||||
await contains(".o-mail-Thread", { scroll: "bottom" });
|
||||
});
|
||||
|
||||
test("Jump to old reply should prompt jump to present (RPC small delay)", async () => {
|
||||
// same test as before but with a small RPC delay
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const oldestMessageId = pyEnv["mail.message"].create({
|
||||
body: "<p>Hello world!</p>",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
});
|
||||
for (let i = 0; i < 100; i++) {
|
||||
pyEnv["mail.message"].create({
|
||||
body: "<p>Non Empty Body</p>".repeat(100),
|
||||
message_type: "comment",
|
||||
model: "discuss.channel",
|
||||
/**
|
||||
* The first message following the oldest message should have it as its parent message
|
||||
* so that the oldest message is inserted through the parent field during "load around"
|
||||
* to have the coverage of this part of the code (in particular having parent message
|
||||
* body being inserted with markup).
|
||||
*/
|
||||
parent_id: i === 0 ? oldestMessageId : undefined,
|
||||
res_id: channelId,
|
||||
});
|
||||
}
|
||||
const newestMessageId = pyEnv["mail.message"].create({
|
||||
body: "Most Recent!",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
parent_id: oldestMessageId,
|
||||
});
|
||||
const [selfMember] = pyEnv["discuss.channel.member"].search_read([
|
||||
["partner_id", "=", serverState.partnerId],
|
||||
["channel_id", "=", channelId],
|
||||
]);
|
||||
pyEnv["discuss.channel.member"].write([selfMember.id], {
|
||||
new_message_separator: newestMessageId + 1,
|
||||
});
|
||||
onRpcBefore("/discuss/channel/messages", tick); // small delay
|
||||
await start();
|
||||
await openDiscuss(channelId);
|
||||
await contains(".o-mail-Message", { count: 30 });
|
||||
await click(".o-mail-MessageInReply .cursor-pointer");
|
||||
await click("[title='Jump to Present']");
|
||||
await contains("[title='Jump to Present']", { count: 0 });
|
||||
await contains(".o-mail-Thread", { scroll: "bottom" });
|
||||
});
|
||||
|
||||
test("Post message when seeing old message should jump to present", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const oldestMessageId = pyEnv["mail.message"].create({
|
||||
body: "<p>Hello world!</p>",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
});
|
||||
for (let i = 0; i < 100; i++) {
|
||||
pyEnv["mail.message"].create({
|
||||
body: "<p>Non Empty Body</p>".repeat(100),
|
||||
message_type: "comment",
|
||||
model: "discuss.channel",
|
||||
/**
|
||||
* The first message following the oldest message should have it as its parent message
|
||||
* so that the oldest message is inserted through the parent field during "load around"
|
||||
* to have the coverage of this part of the code (in particular having parent message
|
||||
* body being inserted with markup).
|
||||
*/
|
||||
parent_id: i === 0 ? oldestMessageId : undefined,
|
||||
res_id: channelId,
|
||||
});
|
||||
}
|
||||
pyEnv["mail.message"].create({
|
||||
body: "Most Recent!",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
parent_id: oldestMessageId,
|
||||
});
|
||||
await start();
|
||||
await openDiscuss(channelId);
|
||||
await contains(".o-mail-Message", { count: 30 });
|
||||
await click(".o-mail-MessageInReply .cursor-pointer");
|
||||
await contains("[title='Jump to Present']");
|
||||
await insertText(".o-mail-Composer-input", "Newly posted");
|
||||
await press("Enter");
|
||||
await contains("[title='Jump to Present']", { count: 0 });
|
||||
await contains(".o-mail-Thread", { scroll: "bottom" });
|
||||
await contains(".o-mail-Message-content", {
|
||||
text: "Newly posted",
|
||||
after: [".o-mail-Message-content", { text: "Most Recent!" }], // should load around present
|
||||
});
|
||||
});
|
||||
|
||||
test("when triggering jump to present, keeps showing old messages until recent ones are loaded", async () => {
|
||||
// make scroll behavior instantaneous.
|
||||
patchWithCleanup(Element.prototype, {
|
||||
scrollIntoView() {
|
||||
return super.scrollIntoView(true);
|
||||
},
|
||||
scrollTo(...args) {
|
||||
if (typeof args[0] === "object" && args[0]?.behavior === "smooth") {
|
||||
return super.scrollTo({ ...args[0], behavior: "instant" });
|
||||
}
|
||||
return super.scrollTo(...args);
|
||||
},
|
||||
});
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
for (let i = 0; i < 60; i++) {
|
||||
pyEnv["mail.message"].create({
|
||||
body: i === 0 ? "first-message" : "Non Empty Body ".repeat(100),
|
||||
message_type: "comment",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
pinned_at: i === 0 ? "2020-02-12 08:30:00" : undefined,
|
||||
});
|
||||
}
|
||||
let slowMessageFetchDeferred;
|
||||
onRpcBefore("/discuss/channel/messages", async () => {
|
||||
asyncStep("/discuss/channel/messages");
|
||||
await slowMessageFetchDeferred;
|
||||
});
|
||||
await start();
|
||||
await openDiscuss(channelId);
|
||||
await waitForSteps(["/discuss/channel/messages"]);
|
||||
await click("[title='Pinned Messages']");
|
||||
await click(".o-discuss-PinnedMessagesPanel a[role='button']", { text: "Jump" });
|
||||
await contains(".o-mail-Thread .o-mail-Message", { text: "first-message" });
|
||||
await animationFrame();
|
||||
slowMessageFetchDeferred = new Deferred();
|
||||
await click("[title='Jump to Present']");
|
||||
await animationFrame();
|
||||
await waitForSteps(["/discuss/channel/messages"]);
|
||||
await contains(".o-mail-Thread .o-mail-Message", { text: "first-message" });
|
||||
slowMessageFetchDeferred.resolve();
|
||||
await contains(".o-mail-Thread .o-mail-Message", { text: "first-message", count: 0 });
|
||||
await contains(".o-mail-Thread", { scroll: "bottom" });
|
||||
});
|
||||
|
||||
test("focus composer after jump to present", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
pyEnv["mail.message"].create(
|
||||
[...Array(40).keys()].map((i) => ({
|
||||
body: `<p>Non Empty Message ${i}</p>`,
|
||||
message_type: "comment",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
}))
|
||||
);
|
||||
await start();
|
||||
await openDiscuss(channelId);
|
||||
await contains(".o-mail-Message", { count: 30 });
|
||||
await contains(".o-mail-Composer.o-focused");
|
||||
queryFirst(".o-mail-Composer-input").blur();
|
||||
await contains(".o-mail-Composer.o-focused", { count: 0 });
|
||||
await click("[title='Jump to Present']");
|
||||
await contains(".o-mail-Composer.o-focused");
|
||||
});
|
||||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue