mirror of
https://github.com/bringout/oca-ocb-mail.git
synced 2026-04-22 19:22:03 +02:00
19.0 vanilla
This commit is contained in:
parent
5df8c07b59
commit
daa394e8b0
2114 changed files with 564841 additions and 299642 deletions
|
|
@ -0,0 +1,52 @@
|
|||
import {
|
||||
defineLivechatModels,
|
||||
loadDefaultEmbedConfig,
|
||||
} from "@im_livechat/../tests/livechat_test_helpers";
|
||||
import { contains, setupChatHub, start, startServer } from "@mail/../tests/mail_test_helpers";
|
||||
import { describe, test } from "@odoo/hoot";
|
||||
import { Command, patchWithCleanup, serverState } from "@web/../tests/web_test_helpers";
|
||||
import { mailDataHelpers } from "@mail/../tests/mock_server/mail_mock_server";
|
||||
|
||||
describe.current.tags("desktop");
|
||||
defineLivechatModels();
|
||||
|
||||
test("persisted session", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const livechatChannelId = await loadDefaultEmbedConfig();
|
||||
const guestId = pyEnv["mail.guest"].create({ name: "Visitor 11" });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
Command.create({ partner_id: serverState.partnerId }),
|
||||
Command.create({ guest_id: guestId }),
|
||||
],
|
||||
channel_type: "livechat",
|
||||
livechat_channel_id: livechatChannelId,
|
||||
livechat_operator_id: serverState.partnerId,
|
||||
});
|
||||
setupChatHub({ opened: [channelId] });
|
||||
await start({
|
||||
authenticateAs: { ...pyEnv["mail.guest"].read(guestId)[0], _name: "mail.guest" },
|
||||
});
|
||||
await contains(".o-mail-ChatWindow");
|
||||
});
|
||||
|
||||
test("rule received in init", async () => {
|
||||
const pyEnv = await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
const autopopupRuleId = pyEnv["im_livechat.channel.rule"].create({
|
||||
auto_popup_timer: 0,
|
||||
action: "auto_popup",
|
||||
});
|
||||
patchWithCleanup(mailDataHelpers, {
|
||||
_process_request_for_all(store) {
|
||||
super._process_request_for_all(...arguments);
|
||||
store.add(pyEnv["im_livechat.channel.rule"].browse(autopopupRuleId), {
|
||||
action: "auto_popup",
|
||||
auto_popup_timer: 0,
|
||||
});
|
||||
store.add({ livechat_rule: autopopupRuleId });
|
||||
},
|
||||
});
|
||||
await start({ authenticateAs: false });
|
||||
await contains(".o-mail-ChatWindow");
|
||||
});
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
import {
|
||||
defineLivechatModels,
|
||||
loadDefaultEmbedConfig,
|
||||
} from "@im_livechat/../tests/livechat_test_helpers";
|
||||
import { contains, setupChatHub, start, startServer } from "@mail/../tests/mail_test_helpers";
|
||||
import { describe, test } from "@odoo/hoot";
|
||||
import { Command, makeMockEnv, serverState } from "@web/../tests/web_test_helpers";
|
||||
|
||||
describe.current.tags("desktop");
|
||||
defineLivechatModels();
|
||||
|
||||
test("Do not show bot IM status", async () => {
|
||||
const pyEnv = await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
await makeMockEnv({ embedLivechat: true });
|
||||
const partnerId1 = pyEnv["res.partner"].create({ name: "Mitchell", im_status: "online" });
|
||||
pyEnv["res.users"].create({ partner_id: partnerId1 });
|
||||
const channelId1 = pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
Command.create({ partner_id: partnerId1, livechat_member_type: "visitor" }),
|
||||
],
|
||||
channel_type: "chat",
|
||||
});
|
||||
const partnerId2 = pyEnv["res.partner"].create({ name: "Dummy" });
|
||||
const channelId2 = pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
Command.create({ partner_id: serverState.partnerId, livechat_member_type: "visitor" }),
|
||||
Command.create({ partner_id: partnerId2, livechat_member_type: "bot" }),
|
||||
],
|
||||
channel_type: "livechat",
|
||||
livechat_operator_id: partnerId2,
|
||||
});
|
||||
setupChatHub({ folded: [channelId1, channelId2] });
|
||||
await start({ authenticateAs: false });
|
||||
await contains(".o-mail-ChatBubble[name='Mitchell'] .o-mail-ImStatus");
|
||||
await contains(".o-mail-ChatBubble[name='Dummy']");
|
||||
await contains(".o-mail-ChatBubble[name='Dummy'] .o-mail-ImStatus", { count: 0 });
|
||||
});
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
import {
|
||||
defineLivechatModels,
|
||||
loadDefaultEmbedConfig,
|
||||
} from "@im_livechat/../tests/livechat_test_helpers";
|
||||
import {
|
||||
assertChatBubbleAndWindowImStatus,
|
||||
click,
|
||||
contains,
|
||||
inputFiles,
|
||||
insertText,
|
||||
mockGetMedia,
|
||||
onRpcBefore,
|
||||
start,
|
||||
startServer,
|
||||
triggerHotkey,
|
||||
} from "@mail/../tests/mail_test_helpers";
|
||||
import { describe, test } from "@odoo/hoot";
|
||||
import { asyncStep, serverState, waitForSteps, withUser } from "@web/../tests/web_test_helpers";
|
||||
|
||||
import { deserializeDateTime } from "@web/core/l10n/dates";
|
||||
import { rpc } from "@web/core/network/rpc";
|
||||
import { getOrigin } from "@web/core/utils/urls";
|
||||
|
||||
describe.current.tags("desktop");
|
||||
defineLivechatModels();
|
||||
|
||||
test("internal users can upload file to temporary thread", async () => {
|
||||
const pyEnv = await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
const [partnerUser] = pyEnv["res.users"].search_read([["id", "=", serverState.partnerId]]);
|
||||
await start({ authenticateAs: partnerUser });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
const file = new File(["hello, world"], "text.txt", { type: "text/plain" });
|
||||
await contains(".o-mail-Composer");
|
||||
await click(".o-mail-Composer button[title='More Actions']");
|
||||
await contains(".dropdown-item:contains('Attach files')");
|
||||
await inputFiles(".o-mail-Composer .o_input_file", [file]);
|
||||
await contains(".o-mail-AttachmentContainer:not(.o-isUploading):contains(text.txt) .fa-check");
|
||||
await triggerHotkey("Enter");
|
||||
await contains(".o-mail-Message .o-mail-AttachmentContainer:contains(text.txt)");
|
||||
});
|
||||
|
||||
test("Conversation name is operator livechat user name", async () => {
|
||||
const pyEnv = await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
pyEnv["res.partner"].write(serverState.partnerId, { user_livechat_username: "MitchellOp" });
|
||||
await start({ authenticateAs: false });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-ChatWindow-header", { text: "MitchellOp" });
|
||||
});
|
||||
|
||||
test("Portal users should not be able to start a call", async () => {
|
||||
mockGetMedia();
|
||||
const pyEnv = await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
const joelUid = pyEnv["res.users"].create({
|
||||
name: "Joel",
|
||||
share: true,
|
||||
login: "joel",
|
||||
password: "joel",
|
||||
});
|
||||
const joelPid = pyEnv["res.partner"].create({
|
||||
name: "Joel",
|
||||
user_ids: [joelUid],
|
||||
});
|
||||
pyEnv["res.partner"].write(serverState.partnerId, { user_livechat_username: "MitchellOp" });
|
||||
await start({ authenticateAs: { login: "joel", password: "joel" } });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-ChatWindow-header:text('MitchellOp')");
|
||||
await insertText(".o-mail-Composer-input", "Hello MitchellOp!");
|
||||
await triggerHotkey("Enter");
|
||||
await contains(".o-mail-Message[data-persistent]:contains('Hello MitchellOp!')");
|
||||
await contains(".o-mail-ChatWindow-header .o-mail-ActionList-button", { count: 2 });
|
||||
await contains(".o-mail-ChatWindow-header .o-mail-ActionList-button[title='Fold']");
|
||||
await contains(".o-mail-ChatWindow-header .o-mail-ActionList-button[title*='Close']");
|
||||
await contains(".o-discuss-Call", { count: 0 });
|
||||
// simulate operator starts call
|
||||
const [channelId] = pyEnv["discuss.channel"].search([
|
||||
["channel_type", "=", "livechat"],
|
||||
[
|
||||
"channel_member_ids",
|
||||
"in",
|
||||
pyEnv["discuss.channel.member"].search([["partner_id", "=", joelPid]]),
|
||||
],
|
||||
]);
|
||||
await withUser(serverState.userId, () =>
|
||||
rpc("/mail/rtc/channel/join_call", { channel_id: channelId }, { silent: true })
|
||||
);
|
||||
await contains(".o-discuss-Call button", { count: 2 });
|
||||
await contains(".o-discuss-Call button[title='Join Video Call']");
|
||||
await contains(".o-discuss-Call button[title='Join Call']");
|
||||
// still same actions in header
|
||||
await contains(".o-mail-ChatWindow-header .o-mail-ActionList-button", { count: 2 });
|
||||
await contains(".o-mail-ChatWindow-header .o-mail-ActionList-button[title='Fold']");
|
||||
await contains(".o-mail-ChatWindow-header .o-mail-ActionList-button[title*='Close']");
|
||||
});
|
||||
|
||||
test("avatar url contains access token for non-internal users", async () => {
|
||||
const pyEnv = await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
pyEnv["res.partner"].write(serverState.partnerId, { user_livechat_username: "MitchellOp" });
|
||||
const [partner] = pyEnv["res.partner"].search_read([["id", "=", serverState.partnerId]]);
|
||||
await start({ authenticateAs: false });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await contains(
|
||||
`.o-mail-ChatWindow-threadAvatar img[data-src="${getOrigin()}/web/image/res.partner/${
|
||||
partner.id
|
||||
}/avatar_128?access_token=${partner.id}&unique=${
|
||||
deserializeDateTime(partner.write_date).ts
|
||||
}"]`
|
||||
);
|
||||
await contains(
|
||||
`.o-mail-Message-avatar[data-src="${getOrigin()}/web/image/res.partner/${
|
||||
partner.id
|
||||
}/avatar_128?access_token=${partner.id}&unique=${
|
||||
deserializeDateTime(partner.write_date).ts
|
||||
}"]`
|
||||
);
|
||||
await insertText(".o-mail-Composer-input", "Hello World!");
|
||||
triggerHotkey("Enter");
|
||||
const guestId = pyEnv.cookie.get("dgid");
|
||||
const [guest] = pyEnv["mail.guest"].read(guestId);
|
||||
await contains(
|
||||
`.o-mail-Message-avatar[data-src="${getOrigin()}/web/image/mail.guest/${
|
||||
guest.id
|
||||
}/avatar_128?access_token=${guest.id}&unique=${deserializeDateTime(guest.write_date).ts}"]`
|
||||
);
|
||||
});
|
||||
|
||||
test("can close confirm livechat with keyboard", async () => {
|
||||
await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
onRpcBefore((route) => {
|
||||
if (route === "/im_livechat/visitor_leave_session") {
|
||||
asyncStep(route);
|
||||
}
|
||||
});
|
||||
await start({ authenticateAs: false });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await insertText(".o-mail-Composer-input", "Hello");
|
||||
await triggerHotkey("Enter");
|
||||
await contains(".o-mail-Thread:not([data-transient])");
|
||||
await triggerHotkey("Escape");
|
||||
await contains(".o-livechat-CloseConfirmation", {
|
||||
text: "Leaving will end the live chat. Do you want to proceed?",
|
||||
});
|
||||
await triggerHotkey("Escape");
|
||||
await contains(".o-livechat-CloseConfirmation", { count: 0 });
|
||||
await triggerHotkey("Escape");
|
||||
await contains(".o-livechat-CloseConfirmation", {
|
||||
text: "Leaving will end the live chat. Do you want to proceed?",
|
||||
});
|
||||
await triggerHotkey("Enter");
|
||||
await waitForSteps(["/im_livechat/visitor_leave_session"]);
|
||||
await contains(".o-mail-ChatWindow", { text: "Did we correctly answer your question?" });
|
||||
});
|
||||
|
||||
test("Should not show IM status of agents", async () => {
|
||||
mockGetMedia();
|
||||
const pyEnv = await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
const joelUid = pyEnv["res.users"].create({
|
||||
name: "Joel",
|
||||
share: true,
|
||||
login: "joel",
|
||||
password: "joel",
|
||||
});
|
||||
pyEnv["res.partner"].create({ name: "Joel", user_ids: [joelUid] });
|
||||
pyEnv["res.partner"].write(serverState.partnerId, {
|
||||
im_status: "online",
|
||||
user_livechat_username: "MitchellOp",
|
||||
});
|
||||
await start({ authenticateAs: { login: "joel", password: "joel" } });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-ChatWindow-header:text('MitchellOp')");
|
||||
await insertText(".o-mail-Composer-input", "Hello MitchellOp!");
|
||||
await triggerHotkey("Enter");
|
||||
await contains(".o-mail-Message[data-persistent]:contains('Hello MitchellOp!')");
|
||||
await click(".o-mail-ChatWindow-header");
|
||||
await contains(".o-mail-ChatBubble");
|
||||
await assertChatBubbleAndWindowImStatus("MitchellOp", 0);
|
||||
});
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
import { expirableStorage } from "@im_livechat/core/common/expirable_storage";
|
||||
|
||||
import { describe, expect, test } from "@odoo/hoot";
|
||||
import { mockDate } from "@odoo/hoot-mock";
|
||||
import { asyncStep, waitForSteps } from "@web/../tests/web_test_helpers";
|
||||
|
||||
describe.current.tags("desktop");
|
||||
|
||||
test("value is removed from expirable storage after expiration", () => {
|
||||
mockDate("2023-01-01 00:00:00");
|
||||
const ONE_DAY = 60 * 60 * 24;
|
||||
expirableStorage.setItem("foo", "bar", ONE_DAY);
|
||||
expect(expirableStorage.getItem("foo")).toBe("bar");
|
||||
mockDate("2023-01-01 23:00:00");
|
||||
expect(expirableStorage.getItem("foo")).toBe("bar");
|
||||
mockDate("2023-01-02 00:00:01");
|
||||
expect(expirableStorage.getItem("foo")).toBe(null);
|
||||
});
|
||||
|
||||
test("subscribe/unsubscribe to storage changes", async () => {
|
||||
const fooCallback = (value) => asyncStep(`foo - ${value}`);
|
||||
const barCallback = (value) => asyncStep(`bar - ${value}`);
|
||||
expirableStorage.onChange("foo", fooCallback);
|
||||
expirableStorage.onChange("bar", barCallback);
|
||||
expirableStorage.setItem("foo", 1);
|
||||
await waitForSteps(["foo - 1"]);
|
||||
expirableStorage.setItem("bar", 2);
|
||||
await waitForSteps(["bar - 2"]);
|
||||
expirableStorage.removeItem("foo");
|
||||
await waitForSteps(["foo - null"]);
|
||||
expirableStorage.offChange("foo", fooCallback);
|
||||
expirableStorage.setItem("foo", 3);
|
||||
expirableStorage.removeItem("bar");
|
||||
await waitForSteps(["bar - null"]);
|
||||
});
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
import {
|
||||
defineLivechatModels,
|
||||
loadDefaultEmbedConfig,
|
||||
} from "@im_livechat/../tests/livechat_test_helpers";
|
||||
import { RATING } from "@im_livechat/embed/common/livechat_service";
|
||||
import {
|
||||
click,
|
||||
contains,
|
||||
insertText,
|
||||
onRpcBefore,
|
||||
start,
|
||||
startServer,
|
||||
triggerHotkey,
|
||||
} from "@mail/../tests/mail_test_helpers";
|
||||
import { expect, test } from "@odoo/hoot";
|
||||
import {
|
||||
asyncStep,
|
||||
Command,
|
||||
getService,
|
||||
patchWithCleanup,
|
||||
serverState,
|
||||
waitForSteps,
|
||||
withUser,
|
||||
} from "@web/../tests/web_test_helpers";
|
||||
|
||||
defineLivechatModels();
|
||||
|
||||
test("Do not ask feedback if empty", async () => {
|
||||
await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
await start({ authenticateAs: false });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await click("[title*='Close Chat Window']");
|
||||
});
|
||||
|
||||
test("Close without feedback", async () => {
|
||||
await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
onRpcBefore((route) => {
|
||||
if (route === "/im_livechat/visitor_leave_session" || route === "/im_livechat/feedback") {
|
||||
asyncStep(route);
|
||||
}
|
||||
});
|
||||
await start({ authenticateAs: false });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await insertText(".o-mail-Composer-input", "Hello World!");
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-Thread:not([data-transient])");
|
||||
await click("[title*='Close Chat Window']");
|
||||
await click(".o-livechat-CloseConfirmation-leave");
|
||||
await click("button", { text: "Close" });
|
||||
await contains(".o-livechat-LivechatButton");
|
||||
await waitForSteps(["/im_livechat/visitor_leave_session"]);
|
||||
});
|
||||
|
||||
test("Last operator leaving ends the livechat", async () => {
|
||||
await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
const operatorUserId = serverState.userId;
|
||||
await start({ authenticateAs: false });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await insertText(".o-mail-Composer-input", "Hello World!");
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-Message-content", { text: "Hello World!" });
|
||||
// simulate operator leaving
|
||||
await withUser(operatorUserId, () =>
|
||||
getService("orm").call("discuss.channel", "action_unfollow", [
|
||||
[Object.values(getService("mail.store").Thread.records).at(-1).id],
|
||||
])
|
||||
);
|
||||
await contains("span", { text: "This livechat conversation has ended" });
|
||||
await contains(".o-mail-Composer-input", { count: 0 });
|
||||
await click("[title*='Close Chat Window']");
|
||||
await contains("p", { text: "Did we correctly answer your question?" }); // shows immediately feedback
|
||||
});
|
||||
|
||||
test("Feedback with rating and comment", async () => {
|
||||
await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
onRpcBefore((route, args) => {
|
||||
if (route === "/im_livechat/visitor_leave_session") {
|
||||
asyncStep(route);
|
||||
}
|
||||
if (route === "/im_livechat/feedback") {
|
||||
asyncStep(route);
|
||||
expect(args.reason).toInclude("Good job!");
|
||||
expect(args.rate).toBe(RATING.OK);
|
||||
}
|
||||
});
|
||||
await start({ authenticateAs: false });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await insertText(".o-mail-Composer-input", "Hello World!");
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-Thread:not([data-transient])");
|
||||
await click("[title*='Close Chat Window']");
|
||||
await click(".o-livechat-CloseConfirmation-leave");
|
||||
await waitForSteps(["/im_livechat/visitor_leave_session"]);
|
||||
await click(`img[alt="${RATING.OK}"]`);
|
||||
await insertText("textarea[placeholder='Explain your note']", "Good job!");
|
||||
await click("button:contains(Send):enabled");
|
||||
await contains("p", { text: "Thank you for your feedback" });
|
||||
await waitForSteps(["/im_livechat/feedback"]);
|
||||
});
|
||||
|
||||
test("Closing folded chat window should open it with feedback", async () => {
|
||||
await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
await start({ authenticateAs: false });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await insertText(".o-mail-Composer-input", "Hello World!");
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-Thread:not([data-transient])");
|
||||
await click("[title='Fold']");
|
||||
await click(".o-mail-ChatBubble");
|
||||
await click("[title*='Close Chat Window']");
|
||||
await click(".o-livechat-CloseConfirmation-leave");
|
||||
await click(".o-mail-ChatHub-bubbleBtn");
|
||||
await contains(".o-mail-ChatWindow p", { text: "Did we correctly answer your question?" });
|
||||
});
|
||||
|
||||
test("Start new session from feedback panel", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = await loadDefaultEmbedConfig();
|
||||
await start({ authenticateAs: false });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-ChatWindow", { text: "Mitchell Admin" });
|
||||
await insertText(".o-mail-Composer-input", "Hello World!");
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-Thread:not([data-transient])");
|
||||
await click("[title*='Close Chat Window']");
|
||||
await click(".o-livechat-CloseConfirmation-leave");
|
||||
pyEnv["im_livechat.channel"].write([channelId], {
|
||||
user_ids: [Command.clear(serverState.userId)],
|
||||
});
|
||||
pyEnv["im_livechat.channel"].write([channelId], {
|
||||
user_ids: [
|
||||
pyEnv["res.users"].create({
|
||||
partner_id: pyEnv["res.partner"].create({ name: "Bob Operator" }),
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
await click("button", { text: "New Session" });
|
||||
await contains(".o-mail-ChatWindow", { count: 1 });
|
||||
await contains(".o-mail-ChatWindow", { text: "Bob Operator" });
|
||||
});
|
||||
|
||||
test("open review link on good rating", async () => {
|
||||
patchWithCleanup(window, {
|
||||
open: (...args) => {
|
||||
expect.step("window.open");
|
||||
expect(args[0]).toBe("https://www.odoo.com");
|
||||
expect(args[1]).toBe("_blank");
|
||||
},
|
||||
});
|
||||
await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
await start({ authenticateAs: false });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await insertText(".o-mail-Composer-input", "Hello World!");
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-Message-content", { text: "Hello World!" });
|
||||
await click("[title*='Close Chat Window']");
|
||||
await click(".o-livechat-CloseConfirmation-leave");
|
||||
await click(`img[alt="${RATING.GOOD}"]`);
|
||||
await insertText("textarea[placeholder='Explain your note']", "Good job!");
|
||||
await click("button:contains(Send):enabled");
|
||||
await expect.waitForSteps(["window.open"]);
|
||||
});
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
import {
|
||||
defineLivechatModels,
|
||||
loadDefaultEmbedConfig,
|
||||
} from "@im_livechat/../tests/livechat_test_helpers";
|
||||
import { click, start, startServer } from "@mail/../tests/mail_test_helpers";
|
||||
import { describe, test } from "@odoo/hoot";
|
||||
import { press, waitFor } from "@odoo/hoot-dom";
|
||||
import {
|
||||
asyncStep,
|
||||
contains,
|
||||
getService,
|
||||
onRpc,
|
||||
serverState,
|
||||
waitForSteps,
|
||||
} from "@web/../tests/web_test_helpers";
|
||||
|
||||
describe.current.tags("desktop");
|
||||
defineLivechatModels();
|
||||
|
||||
test("Handle livechat history command", async () => {
|
||||
const pyEnv = await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
onRpc("/im_livechat/history", ({ url }) => {
|
||||
asyncStep(new URL(url).pathname);
|
||||
return true;
|
||||
});
|
||||
await start({ authenticateAs: false });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-Composer-input").edit("Hello World!", { confirm: false });
|
||||
await press("Enter");
|
||||
await waitFor(".o-mail-Message:contains(Hello World!)");
|
||||
const thread = Object.values(getService("mail.store").Thread.records).at(-1);
|
||||
const guestId = pyEnv.cookie.get("dgid");
|
||||
const [guest] = pyEnv["mail.guest"].read(guestId);
|
||||
pyEnv["bus.bus"]._sendone(guest, "im_livechat.history_command", {
|
||||
id: thread.id,
|
||||
partner_id: serverState.partnerId,
|
||||
});
|
||||
await waitForSteps(["/im_livechat/history"]);
|
||||
});
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
import {
|
||||
defineLivechatModels,
|
||||
loadDefaultEmbedConfig,
|
||||
} from "@im_livechat/../tests/livechat_test_helpers";
|
||||
import {
|
||||
click,
|
||||
contains,
|
||||
insertText,
|
||||
start,
|
||||
startServer,
|
||||
triggerHotkey,
|
||||
} from "@mail/../tests/mail_test_helpers";
|
||||
import { mailDataHelpers } from "@mail/../tests/mock_server/mail_mock_server";
|
||||
import { describe, test } from "@odoo/hoot";
|
||||
import { asyncStep, patchWithCleanup, waitForSteps } from "@web/../tests/web_test_helpers";
|
||||
|
||||
describe.current.tags("desktop");
|
||||
defineLivechatModels();
|
||||
|
||||
test("open/close temporary channel", async () => {
|
||||
await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
await start({ authenticateAs: false });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await contains(".o-livechat-LivechatButton", { count: 0 });
|
||||
await click("[title*='Close Chat Window']");
|
||||
await contains(".o-mail-ChatWindow", { count: 0 });
|
||||
await contains(".o-livechat-LivechatButton", { count: 1 });
|
||||
});
|
||||
|
||||
test("open/close persisted channel", async () => {
|
||||
await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
const env = await start({ authenticateAs: false });
|
||||
env.services.bus_service.subscribe("discuss.channel/new_message", () =>
|
||||
asyncStep("discuss.channel/new_message")
|
||||
);
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await insertText(".o-mail-Composer-input", "How can I help?");
|
||||
await triggerHotkey("Enter");
|
||||
await contains(".o-mail-Thread:not([data-transient])");
|
||||
await contains(".o-mail-Message-content", { text: "How can I help?" });
|
||||
await waitForSteps(["discuss.channel/new_message"]);
|
||||
await click("[title*='Close Chat Window']");
|
||||
await click(".o-livechat-CloseConfirmation-leave");
|
||||
await contains(".o-mail-ChatWindow", { text: "Did we correctly answer your question?" });
|
||||
await click("[title*='Close Chat Window']");
|
||||
await contains(".o-mail-ChatWindow", { count: 0 });
|
||||
await contains(".o-livechat-LivechatButton", { count: 1 });
|
||||
});
|
||||
|
||||
test("livechat not available", async () => {
|
||||
await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
patchWithCleanup(mailDataHelpers, {
|
||||
_process_request_for_all(store) {
|
||||
super._process_request_for_all(...arguments);
|
||||
store.add({ livechat_available: false });
|
||||
},
|
||||
});
|
||||
await start({ authenticateAs: false });
|
||||
await contains(".o-mail-ChatHub");
|
||||
await contains(".o-livechat-LivechatButton", { count: 0 });
|
||||
});
|
||||
|
||||
test("clicking on notification opens the chat", async () => {
|
||||
const pyEnv = await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
const btnAndTextRuleId = pyEnv["im_livechat.channel.rule"].create({
|
||||
action: "display_button_and_text",
|
||||
});
|
||||
patchWithCleanup(mailDataHelpers, {
|
||||
_process_request_for_all(store) {
|
||||
super._process_request_for_all(...arguments);
|
||||
store.add(pyEnv["im_livechat.channel.rule"].browse(btnAndTextRuleId), {
|
||||
action: "display_button_and_text",
|
||||
});
|
||||
store.add({ livechat_rule: btnAndTextRuleId });
|
||||
},
|
||||
});
|
||||
await start({ authenticateAs: false });
|
||||
await click(".o-livechat-LivechatButton-notification", {
|
||||
text: "Need help? Chat with us.",
|
||||
});
|
||||
await contains(".o-mail-ChatWindow");
|
||||
});
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
import {
|
||||
defineLivechatModels,
|
||||
loadDefaultEmbedConfig,
|
||||
} from "@im_livechat/../tests/livechat_test_helpers";
|
||||
import { expirableStorage } from "@im_livechat/core/common/expirable_storage";
|
||||
import {
|
||||
click,
|
||||
contains,
|
||||
insertText,
|
||||
listenStoreFetch,
|
||||
onRpcBefore,
|
||||
setupChatHub,
|
||||
start,
|
||||
startServer,
|
||||
STORE_FETCH_ROUTES,
|
||||
triggerHotkey,
|
||||
userContext,
|
||||
waitStoreFetch,
|
||||
} from "@mail/../tests/mail_test_helpers";
|
||||
import { describe, test } from "@odoo/hoot";
|
||||
import {
|
||||
asyncStep,
|
||||
Command,
|
||||
onRpc,
|
||||
serverState,
|
||||
waitForSteps,
|
||||
} from "@web/../tests/web_test_helpers";
|
||||
|
||||
describe.current.tags("desktop");
|
||||
defineLivechatModels();
|
||||
|
||||
test("persisted session history", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const livechatChannelId = await loadDefaultEmbedConfig();
|
||||
const guestId = pyEnv["mail.guest"].create({ name: "Visitor 11" });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
Command.create({ partner_id: serverState.partnerId }),
|
||||
Command.create({ guest_id: guestId }),
|
||||
],
|
||||
channel_type: "livechat",
|
||||
livechat_channel_id: livechatChannelId,
|
||||
livechat_operator_id: serverState.partnerId,
|
||||
});
|
||||
expirableStorage.setItem(
|
||||
"im_livechat.saved_state",
|
||||
JSON.stringify({
|
||||
store: { "discuss.channel": [{ id: channelId }] },
|
||||
persisted: true,
|
||||
livechatUserId: serverState.publicUserId,
|
||||
})
|
||||
);
|
||||
pyEnv["mail.message"].create({
|
||||
author_id: serverState.partnerId,
|
||||
body: "Old message in history",
|
||||
res_id: channelId,
|
||||
model: "discuss.channel",
|
||||
message_type: "comment",
|
||||
});
|
||||
setupChatHub({ opened: [channelId] });
|
||||
await start({
|
||||
authenticateAs: { ...pyEnv["mail.guest"].read(guestId)[0], _name: "mail.guest" },
|
||||
});
|
||||
await contains(".o-mail-Message-content", { text: "Old message in history" });
|
||||
});
|
||||
|
||||
test("previous operator prioritized", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const livechatChannelId = await loadDefaultEmbedConfig();
|
||||
const userId = pyEnv["res.users"].create({ name: "John Doe", im_status: "online" });
|
||||
const previousOperatorId = pyEnv["res.partner"].create({
|
||||
name: "John Doe",
|
||||
user_ids: [userId],
|
||||
});
|
||||
pyEnv["im_livechat.channel"].write([livechatChannelId], { user_ids: [Command.link(userId)] });
|
||||
expirableStorage.setItem("im_livechat_previous_operator", JSON.stringify(previousOperatorId));
|
||||
await start({ authenticateAs: false });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-Message-author", { text: "John Doe" });
|
||||
});
|
||||
|
||||
test("Only necessary requests are made when creating a new chat", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const livechatChannelId = await loadDefaultEmbedConfig();
|
||||
const operatorPartnerId = serverState.partnerId;
|
||||
onRpcBefore((route, args) => {
|
||||
if (!route.includes("assets") && !STORE_FETCH_ROUTES.includes(route)) {
|
||||
asyncStep(`${route} - ${JSON.stringify(args)}`);
|
||||
}
|
||||
});
|
||||
listenStoreFetch(undefined, { logParams: ["init_livechat"] });
|
||||
await start({ authenticateAs: false });
|
||||
await contains(".o-livechat-LivechatButton");
|
||||
await waitStoreFetch([
|
||||
"failures", // called because mail/core/web is loaded in test bundle
|
||||
"systray_get_activities", // called because mail/core/web is loaded in test bundle
|
||||
"init_messaging",
|
||||
["init_livechat", livechatChannelId],
|
||||
]);
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-Message", { text: "Hello, how may I help you?" });
|
||||
await waitForSteps([
|
||||
`/im_livechat/get_session - ${JSON.stringify({
|
||||
channel_id: livechatChannelId,
|
||||
previous_operator_id: null,
|
||||
persisted: false,
|
||||
})}`,
|
||||
]);
|
||||
await insertText(".o-mail-Composer-input", "Hello!");
|
||||
await waitForSteps([]);
|
||||
await triggerHotkey("Enter");
|
||||
await contains(".o-mail-Message", { text: "Hello!" });
|
||||
const [threadId] = pyEnv["discuss.channel"].search([], { order: "id DESC" });
|
||||
await waitStoreFetch(
|
||||
[
|
||||
"failures", // called because mail/core/web is loaded in test bundle
|
||||
"systray_get_activities", // called because mail/core/web is loaded in test bundle
|
||||
"init_messaging",
|
||||
],
|
||||
{
|
||||
stepsBefore: [
|
||||
`/im_livechat/get_session - ${JSON.stringify({
|
||||
channel_id: livechatChannelId,
|
||||
previous_operator_id: operatorPartnerId,
|
||||
persisted: true,
|
||||
})}`,
|
||||
`/mail/message/post - ${JSON.stringify({
|
||||
post_data: {
|
||||
body: "Hello!",
|
||||
email_add_signature: true,
|
||||
message_type: "comment",
|
||||
subtype_xmlid: "mail.mt_comment",
|
||||
},
|
||||
thread_id: threadId,
|
||||
thread_model: "discuss.channel",
|
||||
context: { ...userContext(), temporary_id: 0.8200000000000001 },
|
||||
})}`,
|
||||
],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("do not create new thread when operator answers to visitor", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const livechatChannelId = await loadDefaultEmbedConfig();
|
||||
const guestId = pyEnv["mail.guest"].create({ name: "Visitor 11" });
|
||||
onRpc("/im_livechat/get_session", async () => asyncStep("/im_livechat/get_session"));
|
||||
onRpc("/mail/message/post", async () => asyncStep("/mail/message/post"));
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
Command.create({ partner_id: serverState.partnerId }),
|
||||
Command.create({ guest_id: guestId }),
|
||||
],
|
||||
channel_type: "livechat",
|
||||
livechat_channel_id: livechatChannelId,
|
||||
livechat_operator_id: serverState.partnerId,
|
||||
create_uid: serverState.publicUserId,
|
||||
});
|
||||
setupChatHub({ opened: [channelId] });
|
||||
await start({
|
||||
authenticateAs: pyEnv["res.users"].search_read([["id", "=", serverState.userId]])[0],
|
||||
});
|
||||
await insertText(".o-mail-Composer-input", "Hello!");
|
||||
await triggerHotkey("Enter");
|
||||
await contains(".o-mail-Message", { text: "Hello!" });
|
||||
await waitForSteps(["/mail/message/post"]);
|
||||
});
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
import { waitUntilSubscribe } from "@bus/../tests/bus_test_helpers";
|
||||
import {
|
||||
defineLivechatModels,
|
||||
loadDefaultEmbedConfig,
|
||||
} from "@im_livechat/../tests/livechat_test_helpers";
|
||||
import {
|
||||
assertChatHub,
|
||||
click,
|
||||
contains,
|
||||
focus,
|
||||
insertText,
|
||||
onRpcBefore,
|
||||
start,
|
||||
startServer,
|
||||
triggerHotkey,
|
||||
} from "@mail/../tests/mail_test_helpers";
|
||||
import { describe, expect, test } from "@odoo/hoot";
|
||||
import { advanceTime } from "@odoo/hoot-mock";
|
||||
import { getService, serverState, withUser } from "@web/../tests/web_test_helpers";
|
||||
|
||||
import { LivechatButton } from "@im_livechat/embed/common/livechat_button";
|
||||
import { queryFirst } from "@odoo/hoot-dom";
|
||||
import { rpc } from "@web/core/network/rpc";
|
||||
|
||||
describe.current.tags("desktop");
|
||||
defineLivechatModels();
|
||||
|
||||
test("Session is reset after failing to persist the channel", async () => {
|
||||
await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
onRpcBefore("/im_livechat/get_session", (args) => {
|
||||
if (args.persisted) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
await start({ authenticateAs: false });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await insertText(".o-mail-Composer-input", "Hello World!");
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o_notification", {
|
||||
text: "No available collaborator, please try again later.",
|
||||
});
|
||||
await contains(".o-livechat-LivechatButton");
|
||||
await advanceTime(LivechatButton.DEBOUNCE_DELAY + 10);
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
});
|
||||
|
||||
test("Fold state is saved", async () => {
|
||||
await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
await start({ authenticateAs: false });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-Thread");
|
||||
await insertText(".o-mail-Composer-input", "Hello World!");
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-Thread:not([data-transient])");
|
||||
assertChatHub({ opened: [1] });
|
||||
await click(".o-mail-ChatWindow-header");
|
||||
await contains(".o-mail-Thread", { count: 0 });
|
||||
assertChatHub({ folded: [1] });
|
||||
await click(".o-mail-ChatBubble");
|
||||
assertChatHub({ opened: [1] });
|
||||
});
|
||||
|
||||
test.tags("focus required");
|
||||
test("Seen message is saved on the server", async () => {
|
||||
const pyEnv = await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
const userId = serverState.userId;
|
||||
await start({ authenticateAs: false });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-Thread");
|
||||
await insertText(".o-mail-Composer-input", "Hello, I need help!");
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-Message", { text: "Hello, I need help!" });
|
||||
await waitUntilSubscribe();
|
||||
const initialSeenMessageId = Object.values(getService("mail.store").Thread.records).at(-1)
|
||||
.self_member_id.seen_message_id?.id;
|
||||
queryFirst(".o-mail-Composer-input").blur();
|
||||
await withUser(userId, () =>
|
||||
rpc("/mail/message/post", {
|
||||
post_data: {
|
||||
body: "Hello World!",
|
||||
message_type: "comment",
|
||||
subtype_xmlid: "mail.mt_comment",
|
||||
},
|
||||
thread_id: Object.values(getService("mail.store").Thread.records).at(-1).id,
|
||||
thread_model: "discuss.channel",
|
||||
})
|
||||
);
|
||||
await contains(".o-mail-Thread-newMessage");
|
||||
await contains(".o-mail-ChatWindow-counter", { text: "1" });
|
||||
await focus(".o-mail-Composer-input");
|
||||
await contains(".o-mail-ChatWindow-counter", { count: 0 });
|
||||
const guestId = pyEnv.cookie.get("dgid");
|
||||
const [member] = pyEnv["discuss.channel.member"].search_read([
|
||||
["guest_id", "=", guestId],
|
||||
["channel_id", "=", Object.values(getService("mail.store").Thread.records).at(-1).id],
|
||||
]);
|
||||
expect(initialSeenMessageId).not.toBe(member.seen_message_id[0]);
|
||||
expect(
|
||||
Object.values(getService("mail.store").Thread.records).at(-1).self_member_id.seen_message_id
|
||||
.id
|
||||
).toBe(member.seen_message_id[0]);
|
||||
});
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
import {
|
||||
defineLivechatModels,
|
||||
loadDefaultEmbedConfig,
|
||||
} from "@im_livechat/../tests/livechat_test_helpers";
|
||||
import { expirableStorage } from "@im_livechat/core/common/expirable_storage";
|
||||
|
||||
import {
|
||||
click,
|
||||
contains,
|
||||
hover,
|
||||
setupChatHub,
|
||||
start,
|
||||
startServer,
|
||||
} from "@mail/../tests/mail_test_helpers";
|
||||
|
||||
import { describe, test } from "@odoo/hoot";
|
||||
|
||||
import { Command, serverState } from "@web/../tests/web_test_helpers";
|
||||
|
||||
defineLivechatModels();
|
||||
describe.current.tags("desktop");
|
||||
|
||||
test("user custom live chat user name for message reactions", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const livechatChannelId = await loadDefaultEmbedConfig();
|
||||
pyEnv["res.partner"].write([serverState.partnerId], { user_livechat_username: "Michou" });
|
||||
const guestId = pyEnv["mail.guest"].create({ name: "Visitor 11" });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
Command.create({ partner_id: serverState.partnerId }),
|
||||
Command.create({ guest_id: guestId }),
|
||||
],
|
||||
channel_type: "livechat",
|
||||
livechat_channel_id: livechatChannelId,
|
||||
livechat_operator_id: serverState.partnerId,
|
||||
});
|
||||
pyEnv["mail.message"].create({
|
||||
body: "Hello world",
|
||||
res_id: channelId,
|
||||
message_type: "comment",
|
||||
model: "discuss.channel",
|
||||
reaction_ids: [
|
||||
pyEnv["mail.message.reaction"].create({
|
||||
content: "👍",
|
||||
partner_id: serverState.partnerId,
|
||||
}),
|
||||
],
|
||||
});
|
||||
expirableStorage.setItem(
|
||||
"im_livechat.saved_state",
|
||||
JSON.stringify({
|
||||
store: { "discuss.channel": [{ id: channelId }] },
|
||||
persisted: true,
|
||||
livechatUserId: serverState.publicUserId,
|
||||
})
|
||||
);
|
||||
setupChatHub({ opened: [channelId] });
|
||||
await start({
|
||||
authenticateAs: { ...pyEnv["mail.guest"].read(guestId)[0], _name: "mail.guest" },
|
||||
});
|
||||
await hover(".o-mail-MessageReaction");
|
||||
await click(".o-mail-MessageReactionList-preview", {
|
||||
text: "👍:+1: reacted by Michou",
|
||||
});
|
||||
await contains(".o-mail-MessageReactionMenu-persona", { text: "Michou" });
|
||||
});
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
import {
|
||||
defineLivechatModels,
|
||||
loadDefaultEmbedConfig,
|
||||
} from "@im_livechat/../tests/livechat_test_helpers";
|
||||
import {
|
||||
click,
|
||||
contains,
|
||||
insertText,
|
||||
onRpcBefore,
|
||||
start,
|
||||
startServer,
|
||||
triggerHotkey,
|
||||
} from "@mail/../tests/mail_test_helpers";
|
||||
import { describe, expect, test } from "@odoo/hoot";
|
||||
import { onRpc } from "@web/../tests/web_test_helpers";
|
||||
|
||||
describe.current.tags("desktop");
|
||||
defineLivechatModels();
|
||||
|
||||
test("send", async () => {
|
||||
const pyEnv = await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
onRpcBefore("/im_livechat/email_livechat_transcript", () => expect.step(`send_transcript`));
|
||||
const partnerId = pyEnv["res.partner"].create({ email: "paul@example.com", name: "Paul" });
|
||||
pyEnv["res.users"].create({ partner_id: partnerId, login: "paul", password: "paul" });
|
||||
await start({ authenticateAs: { login: "paul", password: "paul" } });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await insertText(".o-mail-Composer-input", "Hello World!");
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-Thread:not([data-transient])");
|
||||
await click(".o-mail-ChatWindow-header [title*='Close']");
|
||||
await click(".o-livechat-CloseConfirmation-leave");
|
||||
await contains("label", { text: "Receive a copy of this conversation" });
|
||||
await contains("input:enabled", { value: "paul@example.com" });
|
||||
await click("button[data-action='sendTranscript']:enabled");
|
||||
await contains(".form-text", { text: "The conversation was sent." });
|
||||
await expect.waitForSteps(["send_transcript"]);
|
||||
});
|
||||
|
||||
test("send failed", async () => {
|
||||
const pyEnv = await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
onRpc("/im_livechat/email_livechat_transcript", () => {
|
||||
throw new Error();
|
||||
});
|
||||
const partnerId = pyEnv["res.partner"].create({ email: "paul@example.com", name: "Paul" });
|
||||
pyEnv["res.users"].create({ partner_id: partnerId, login: "paul", password: "paul" });
|
||||
await start({ authenticateAs: { login: "paul", password: "paul" } });
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await insertText(".o-mail-Composer-input", "Hello World!");
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-Thread:not([data-transient])");
|
||||
await click(".o-mail-ChatWindow-header [title*='Close']");
|
||||
await click(".o-livechat-CloseConfirmation-leave");
|
||||
await contains("input", { value: "paul@example.com" });
|
||||
await click("button[data-action='sendTranscript']:enabled");
|
||||
await contains(".form-text", { text: "An error occurred. Please try again." });
|
||||
});
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
import { waitUntilSubscribe } from "@bus/../tests/bus_test_helpers";
|
||||
import { expirableStorage } from "@im_livechat/core/common/expirable_storage";
|
||||
import {
|
||||
defineLivechatModels,
|
||||
loadDefaultEmbedConfig,
|
||||
} from "@im_livechat/../tests/livechat_test_helpers";
|
||||
import {
|
||||
click,
|
||||
contains,
|
||||
focus,
|
||||
insertText,
|
||||
listenStoreFetch,
|
||||
setupChatHub,
|
||||
start,
|
||||
startServer,
|
||||
triggerHotkey,
|
||||
waitStoreFetch,
|
||||
} from "@mail/../tests/mail_test_helpers";
|
||||
import { describe, test } from "@odoo/hoot";
|
||||
import { asyncStep, Command, onRpc, serverState, withUser } from "@web/../tests/web_test_helpers";
|
||||
|
||||
import { queryFirst } from "@odoo/hoot-dom";
|
||||
import { rpc } from "@web/core/network/rpc";
|
||||
|
||||
describe.current.tags("desktop");
|
||||
defineLivechatModels();
|
||||
|
||||
test("new message from operator displays unread counter", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const livechatChannelId = await loadDefaultEmbedConfig();
|
||||
const guestId = pyEnv["mail.guest"].create({ name: "Visitor 11" });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
Command.create({ partner_id: serverState.partnerId }),
|
||||
Command.create({ guest_id: guestId }),
|
||||
],
|
||||
channel_type: "livechat",
|
||||
livechat_channel_id: livechatChannelId,
|
||||
livechat_operator_id: serverState.partnerId,
|
||||
});
|
||||
expirableStorage.setItem(
|
||||
"im_livechat.saved_state",
|
||||
JSON.stringify({
|
||||
store: { "discuss.channel": [{ id: channelId }] },
|
||||
persisted: true,
|
||||
livechatUserId: serverState.publicUserId,
|
||||
})
|
||||
);
|
||||
setupChatHub({ opened: [channelId] });
|
||||
onRpc("/discuss/channel/messages", () => asyncStep("/discuss/channel/message"));
|
||||
const userId = serverState.userId;
|
||||
listenStoreFetch(["init_messaging", "init_livechat", "discuss.channel"]);
|
||||
await start({
|
||||
authenticateAs: { ...pyEnv["mail.guest"].read(guestId)[0], _name: "mail.guest" },
|
||||
});
|
||||
await waitStoreFetch(["init_messaging", "init_livechat", "discuss.channel"], {
|
||||
stepsAfter: ["/discuss/channel/message"],
|
||||
});
|
||||
// send after init_messaging because bus subscription is done after init_messaging
|
||||
await withUser(userId, () =>
|
||||
rpc("/mail/message/post", {
|
||||
post_data: { body: "Are you there?", message_type: "comment" },
|
||||
thread_id: channelId,
|
||||
thread_model: "discuss.channel",
|
||||
})
|
||||
);
|
||||
await contains(".o-mail-ChatWindow-counter", { text: "1" });
|
||||
});
|
||||
|
||||
test.tags("focus required");
|
||||
test("focus on unread livechat marks it as read", async () => {
|
||||
const pyEnv = await startServer();
|
||||
await loadDefaultEmbedConfig();
|
||||
const userId = serverState.userId;
|
||||
listenStoreFetch(["init_messaging", "init_livechat"]);
|
||||
await start({ authenticateAs: false });
|
||||
await waitStoreFetch(["init_messaging", "init_livechat"]);
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await insertText(".o-mail-Composer-input", "Hello World!");
|
||||
await triggerHotkey("Enter");
|
||||
// Wait for bus subscription to be done after persisting the thread:
|
||||
// presence of the message is not enough (temporary message).
|
||||
await waitUntilSubscribe();
|
||||
await contains(".o-mail-Message-content", { text: "Hello World!" });
|
||||
const [channelId] = pyEnv["discuss.channel"].search([
|
||||
["channel_type", "=", "livechat"],
|
||||
[
|
||||
"channel_member_ids",
|
||||
"in",
|
||||
pyEnv["discuss.channel.member"].search([["guest_id", "=", pyEnv.cookie.get("dgid")]]),
|
||||
],
|
||||
]);
|
||||
await waitStoreFetch("init_messaging");
|
||||
queryFirst(".o-mail-Composer-input").blur();
|
||||
// send after init_messaging because bus subscription is done after init_messaging
|
||||
await withUser(userId, () =>
|
||||
rpc("/mail/message/post", {
|
||||
post_data: { body: "Are you there?", message_type: "comment" },
|
||||
thread_id: channelId,
|
||||
thread_model: "discuss.channel",
|
||||
})
|
||||
);
|
||||
await contains(".o-mail-ChatWindow-counter", { text: "1" });
|
||||
await contains(".o-mail-Message", { text: "Are you there?" });
|
||||
await focus(".o-mail-Composer-input");
|
||||
await contains(".o-mail-ChatWindow-counter", { count: 0 });
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue