[IMP] mail, *: tests: use contains in click and insertText
* = account, calendar, im_livechat, mrp, project_todo, sms, snailmail,
test_mail, web, website_livechat
`contains` is more efficient than `afterNextRender` as it does not wait
for several extra animation frames, and it is functionally more
meaningful.
closes odoo/odoo#130451
Related: odoo/enterprise#44999
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
@@ -1,19 +1,20 @@
|
||||
/** @odoo-module **/
|
||||
/* @odoo-module */
|
||||
|
||||
import { start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { triggerHotkey } from "@web/../tests/helpers/utils";
|
||||
import { accountMove as accountMoveService} from '@account/components/account_move_service/account_move_service';
|
||||
import { accountMove as accountMoveService } from "@account/components/account_move_service/account_move_service";
|
||||
|
||||
QUnit.module("Views", {}, function (hooks) {
|
||||
QUnit.module('MoveFormView');
|
||||
import { click, insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { makeDeferred, triggerHotkey } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("Views", {}, function () {
|
||||
QUnit.module("MoveFormView");
|
||||
|
||||
QUnit.test("When I switch tabs, it saves", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const accountMove = pyEnv['account.move'].create([{ name: "move0" }]);
|
||||
const accountMove = pyEnv["account.move"].create([{ name: "move0" }]);
|
||||
|
||||
const views = {
|
||||
'account.move,false,form':
|
||||
`<form js_class='account_move_form'>
|
||||
"account.move,false,form": `<form js_class='account_move_form'>
|
||||
<sheet>
|
||||
<notebook>
|
||||
<page id="invoice_tab" name="invoice_tab" string="Invoice Lines">
|
||||
@@ -24,28 +25,28 @@ QUnit.module("Views", {}, function (hooks) {
|
||||
</sheet>
|
||||
</form>`,
|
||||
};
|
||||
const { click, insertText, openView } = await start({
|
||||
const def = makeDeferred();
|
||||
const { openFormView } = await start({
|
||||
serverData: { views },
|
||||
services: {
|
||||
'account_move': accountMoveService,
|
||||
account_move: accountMoveService,
|
||||
},
|
||||
async mockRPC(route) {
|
||||
if (route === "/web/dataset/call_kw/account.move/write") {
|
||||
assert.step("tab saved");
|
||||
def.resolve();
|
||||
}
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
res_id: accountMove,
|
||||
res_model: 'account.move',
|
||||
views: [[false, 'form']],
|
||||
});
|
||||
openFormView("account.move", accountMove);
|
||||
await insertText("[name='name'] input", "somebody save me!");
|
||||
triggerHotkey("Enter")
|
||||
triggerHotkey("Enter");
|
||||
|
||||
await click('a[name="aml_tab"]');
|
||||
assert.verifySteps(["tab saved"],
|
||||
"When clicking on a tab, the saving method should be called and succeed");
|
||||
await def;
|
||||
assert.verifySteps(
|
||||
["tab saved"],
|
||||
"When clicking on a tab, the saving method should be called and succeed"
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/** @odoo-module **/
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { start, startServer, click } from "@mail/../tests/helpers/test_utils";
|
||||
import { getFixture, patchDate, patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
|
||||
let target;
|
||||
@@ -29,7 +30,7 @@ QUnit.test("activity menu widget:today meetings", async function (assert) {
|
||||
},
|
||||
]);
|
||||
const { env } = await start();
|
||||
assert.containsOnce(target, ".o_menu_systray i[aria-label='Activities']");
|
||||
await contains(".o_menu_systray i[aria-label='Activities']");
|
||||
await click(".o_menu_systray i[aria-label='Activities']");
|
||||
patchWithCleanup(env.services.action, {
|
||||
doAction(action) {
|
||||
@@ -37,10 +38,10 @@ QUnit.test("activity menu widget:today meetings", async function (assert) {
|
||||
assert.step("action");
|
||||
},
|
||||
});
|
||||
assert.containsOnce(target, ".o-mail-ActivityGroup:contains(Today's Meetings)");
|
||||
assert.containsN(target, ".o-mail-ActivityGroup .o-calendar-metting", 2);
|
||||
assert.containsOnce(target, ".o-calendar-metting:contains(meeting1)");
|
||||
assert.containsOnce(target, ".o-calendar-metting:contains(meeting2)");
|
||||
await contains(".o-mail-ActivityGroup:contains(Today's Meetings)");
|
||||
await contains(".o-mail-ActivityGroup .o-calendar-metting", 2);
|
||||
await contains(".o-calendar-metting:contains(meeting1)");
|
||||
await contains(".o-calendar-metting:contains(meeting2)");
|
||||
assert.hasClass($(target).find("span:contains(meeting1)"), "fw-bold");
|
||||
assert.doesNotHaveClass($(target).find("span:contains(meeting2)"), "fw-bold");
|
||||
await click(".o-mail-ActivityMenu .o-mail-ActivityGroup");
|
||||
|
||||
@@ -1,17 +1,8 @@
|
||||
/** @odoo-module **/
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { getFixture } from "@web/../tests/helpers/utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
let target;
|
||||
|
||||
QUnit.module("activity", {
|
||||
async beforeEach() {
|
||||
target = getFixture();
|
||||
},
|
||||
});
|
||||
|
||||
QUnit.test("activity click on Reschedule", async function (assert) {
|
||||
QUnit.test("activity click on Reschedule", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const resPartnerId = pyEnv["res.partner"].create({});
|
||||
const meetingActivityTypeId = pyEnv["mail.activity.type"].create({
|
||||
@@ -36,7 +27,7 @@ QUnit.test("activity click on Reschedule", async function (assert) {
|
||||
calendar_event_id: calendaMeetingId,
|
||||
});
|
||||
const { openFormView } = await start();
|
||||
await openFormView("res.partner", resPartnerId);
|
||||
openFormView("res.partner", resPartnerId);
|
||||
await click(".btn:contains('Reschedule')");
|
||||
assert.containsOnce(target, ".o_calendar_view");
|
||||
await contains(".o_calendar_view");
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/** @odoo-module **/
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
import { ListController } from "@web/views/list/list_controller";
|
||||
@@ -65,6 +65,6 @@ QUnit.test("list activity widget: reschedule button in dropdown", async (assert)
|
||||
assert.strictEqual($(".o-mail-ListActivity-summary")[0].innerText, "OXP");
|
||||
|
||||
await click(".o-mail-ActivityButton"); // open the popover
|
||||
assert.containsNone($, ".o-mail-ActivityListPopoverItem-editbtn .fa-pencil");
|
||||
assert.containsOnce($, ".o-mail-ActivityListPopoverItem-editbtn .fa-calendar");
|
||||
await contains(".o-mail-ActivityListPopoverItem-editbtn .fa-pencil", 0);
|
||||
await contains(".o-mail-ActivityListPopoverItem-editbtn .fa-calendar");
|
||||
});
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
import { startServer } from "@bus/../tests/helpers/mock_python_environment";
|
||||
|
||||
import { Command } from "@mail/../tests/helpers/command";
|
||||
import { click, start } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
QUnit.module("Channel invite");
|
||||
|
||||
QUnit.test("Can invite a partner to a livechat channel", async (assert) => {
|
||||
QUnit.test("Can invite a partner to a livechat channel", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const userId = pyEnv["res.users"].create({ name: "James" });
|
||||
pyEnv["res.partner"].create({
|
||||
@@ -25,12 +25,13 @@ QUnit.test("Can invite a partner to a livechat channel", async (assert) => {
|
||||
livechat_operator_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("button[title='Add Users']");
|
||||
await click(".o-discuss-ChannelInvitation-selectable:contains(James) input");
|
||||
await click("button:contains(Invite)");
|
||||
await click("button:contains(Invite):not(:disabled)");
|
||||
await contains(".o-discuss-ChannelInvitation", 0);
|
||||
await click("button[title='Show Member List']");
|
||||
assert.containsOnce($, ".o-discuss-ChannelMember:contains(James)");
|
||||
await contains(".o-discuss-ChannelMember:contains(James)");
|
||||
});
|
||||
|
||||
QUnit.test("Available operators come first", async (assert) => {
|
||||
@@ -60,7 +61,7 @@ QUnit.test("Available operators come first", async (assert) => {
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
await click("button[title='Add Users']");
|
||||
const partnerSuggestions = document.querySelectorAll(".o-discuss-ChannelInvitation-selectable");
|
||||
const partnerSuggestions = await contains(".o-discuss-ChannelInvitation-selectable", 2);
|
||||
assert.ok(partnerSuggestions[0].textContent.includes("Ron"));
|
||||
assert.ok(partnerSuggestions[1].textContent.includes("Harry"));
|
||||
});
|
||||
@@ -101,10 +102,10 @@ QUnit.test("Partners invited most frequently by the current user come first", as
|
||||
await click(".o-mail-DiscussSidebarChannel:contains(Visitor #1)");
|
||||
await click("button[title='Add Users']");
|
||||
await click(".o-discuss-ChannelInvitation-selectable:contains(John) input");
|
||||
await click("button:contains(Invite)");
|
||||
await click("button:contains(Invite):not(:disabled)");
|
||||
await click(".o-mail-DiscussSidebarChannel:contains(Visitor #2)");
|
||||
await click("button[title='Add Users']");
|
||||
const partnerSuggestions = document.querySelectorAll(".o-discuss-ChannelInvitation-selectable");
|
||||
const partnerSuggestions = await contains(".o-discuss-ChannelInvitation-selectable", 2);
|
||||
assert.ok(partnerSuggestions[0].textContent.includes("John"));
|
||||
assert.ok(partnerSuggestions[1].textContent.includes("Albert"));
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
QUnit.module("chat window (patch)");
|
||||
|
||||
@@ -18,9 +18,9 @@ QUnit.test("No call buttons", async (assert) => {
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
assert.containsNone($, ".o-mail-ChatWindow-header .o-mail-ChatWindow-command i.fa-phone");
|
||||
assert.containsNone($, ".o-mail-ChatWindow-header .o-mail-ChatWindow-command i.fa-gear");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow-header .o-mail-ChatWindow-command i.fa-phone", 0);
|
||||
await contains(".o-mail-ChatWindow-header .o-mail-ChatWindow-command i.fa-gear", 0);
|
||||
});
|
||||
|
||||
QUnit.test("closing a chat window with no message from admin side unpins it", async (assert) => {
|
||||
|
||||
@@ -5,12 +5,13 @@ import { startServer } from "@bus/../tests/helpers/mock_python_environment";
|
||||
import {
|
||||
afterNextRender,
|
||||
click,
|
||||
contains,
|
||||
dragenterFiles,
|
||||
insertText,
|
||||
start,
|
||||
} from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { editInput, nextTick, triggerHotkey } from "@web/../tests/helpers/utils";
|
||||
import { nextTick, triggerHotkey } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("composer (patch)");
|
||||
|
||||
@@ -22,8 +23,8 @@ QUnit.test("No add attachments button", async (assert) => {
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-Composer");
|
||||
assert.containsNone($, "button[title='Attach files']");
|
||||
await contains(".o-mail-Composer");
|
||||
await contains("button[title='Attach files']", 0);
|
||||
});
|
||||
|
||||
QUnit.test("Attachment upload via drag and drop disabled", async (assert) => {
|
||||
@@ -36,10 +37,10 @@ QUnit.test("Attachment upload via drag and drop disabled", async (assert) => {
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-Composer");
|
||||
await contains(".o-mail-Composer");
|
||||
dragenterFiles($(".o-mail-Composer-input")[0]);
|
||||
await nextTick();
|
||||
assert.containsNone($, ".o-mail-Dropzone");
|
||||
await contains(".o-mail-Dropzone", 0);
|
||||
});
|
||||
|
||||
QUnit.test("Can execute help command on livechat channels", async (assert) => {
|
||||
@@ -64,9 +65,8 @@ QUnit.test("Can execute help command on livechat channels", async (assert) => {
|
||||
});
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
await editInput(document.body, ".o-mail-Composer-input", "/help");
|
||||
await insertText(".o-mail-Composer-input", "/help");
|
||||
triggerHotkey("Enter");
|
||||
await nextTick();
|
||||
assert.verifySteps(["execute_command_help"]);
|
||||
});
|
||||
|
||||
@@ -94,10 +94,10 @@ QUnit.test('Receives visitor typing status "is typing"', async (assert) => {
|
||||
})
|
||||
)
|
||||
);
|
||||
assert.containsOnce($, ".o-discuss-Typing:contains(Visitor 20 is typing...)");
|
||||
await contains(".o-discuss-Typing:contains(Visitor 20 is typing...)");
|
||||
});
|
||||
|
||||
QUnit.test('display canned response suggestions on typing ":"', async (assert) => {
|
||||
QUnit.test('display canned response suggestions on typing ":"', async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Mario",
|
||||
@@ -114,9 +114,10 @@ QUnit.test('display canned response suggestions on typing ":"', async (assert) =
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsNone($, ".o-mail-Composer-suggestionList .o-open");
|
||||
await contains(".o-mail-Composer-input");
|
||||
await contains(".o-mail-Composer-suggestionList .o-open", 0);
|
||||
await insertText(".o-mail-Composer-input", ":");
|
||||
assert.containsOnce($, ".o-mail-Composer-suggestionList .o-open");
|
||||
await contains(".o-mail-Composer-suggestionList .o-open");
|
||||
});
|
||||
|
||||
QUnit.test("use a canned response", async (assert) => {
|
||||
@@ -136,11 +137,12 @@ QUnit.test("use a canned response", async (assert) => {
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsNone($, ".o-mail-Composer-suggestionList .o-open");
|
||||
await contains(".o-mail-Composer-suggestionList");
|
||||
await contains(".o-mail-Composer-suggestionList .o-open", 0);
|
||||
assert.strictEqual($(".o-mail-Composer-input").val(), "");
|
||||
await insertText(".o-mail-Composer-input", ":");
|
||||
assert.containsOnce($, ".o-mail-Composer-suggestion");
|
||||
await click(".o-mail-Composer-suggestion");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
assert.strictEqual(
|
||||
$(".o-mail-Composer-input").val().replace(/\s/, " "),
|
||||
"Hello! How are you? ",
|
||||
@@ -165,13 +167,14 @@ QUnit.test("use a canned response some text", async (assert) => {
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsNone($, ".o-mail-Composer-suggestion");
|
||||
await contains(".o-mail-Composer-suggestionList");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
assert.strictEqual($(".o-mail-Composer-input").val(), "");
|
||||
await insertText(".o-mail-Composer-input", "bluhbluh ");
|
||||
assert.strictEqual($(".o-mail-Composer-input").val(), "bluhbluh ");
|
||||
await insertText(".o-mail-Composer-input", ":");
|
||||
assert.containsOnce($, ".o-mail-Composer-suggestion");
|
||||
await click(".o-mail-Composer-suggestion");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
assert.strictEqual(
|
||||
$(".o-mail-Composer-input").val().replace(/\s/, " "),
|
||||
"bluhbluh Hello! How are you? ",
|
||||
@@ -196,11 +199,12 @@ QUnit.test("add an emoji after a canned response", async (assert) => {
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsNone($, ".o-mail-Composer-suggestion");
|
||||
await contains(".o-mail-Composer-suggestionList");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
assert.strictEqual($(".o-mail-Composer-input").val(), "");
|
||||
await insertText(".o-mail-Composer-input", ":");
|
||||
assert.containsOnce($, ".o-mail-Composer-suggestion");
|
||||
await click(".o-mail-Composer-suggestion");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
assert.strictEqual(
|
||||
$(".o-mail-Composer-input").val().replace(/\s/, " "),
|
||||
"Hello! How are you? ",
|
||||
@@ -208,6 +212,7 @@ QUnit.test("add an emoji after a canned response", async (assert) => {
|
||||
);
|
||||
await click("button[aria-label='Emojis']");
|
||||
await click(".o-Emoji:contains(😊)");
|
||||
await contains(".o-Emoji", 0);
|
||||
assert.strictEqual(
|
||||
$(".o-mail-Composer-input").val().replace(/\s/, " "),
|
||||
"Hello! How are you? 😊"
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Command } from "@mail/../tests/helpers/command";
|
||||
import {
|
||||
afterNextRender,
|
||||
click,
|
||||
contains,
|
||||
insertText,
|
||||
start,
|
||||
startServer,
|
||||
@@ -128,7 +129,7 @@ QUnit.test("reaction button should not be present on livechat", async (assert) =
|
||||
const { insertText, openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "Test");
|
||||
await click(".o-mail-Composer-send");
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
await click(".o-mail-Message");
|
||||
assert.containsNone($, "[title='Add a Reaction']");
|
||||
});
|
||||
@@ -189,14 +190,14 @@ QUnit.test(
|
||||
]);
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.strictEqual($(".o-mail-DiscussSidebarChannel:eq(0)").text(), "Visitor 12");
|
||||
assert.strictEqual($(".o-mail-DiscussSidebarChannel:eq(1)").text(), "Visitor 11");
|
||||
await contains(".o-mail-DiscussSidebarChannel:eq(0):contains(Visitor 12)");
|
||||
await contains(".o-mail-DiscussSidebarChannel:eq(1):contains(Visitor 11)");
|
||||
// post a new message on the last channel
|
||||
await click(".o-mail-DiscussSidebarChannel:eq(1)");
|
||||
await insertText(".o-mail-Composer-input", "Blabla");
|
||||
await click(".o-mail-Composer-send");
|
||||
assert.containsN($, ".o-mail-DiscussSidebarChannel", 2);
|
||||
assert.strictEqual($(".o-mail-DiscussSidebarChannel:eq(0)").text(), "Visitor 11");
|
||||
assert.strictEqual($(".o-mail-DiscussSidebarChannel:eq(1)").text(), "Visitor 12");
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
await contains(".o-mail-DiscussSidebarChannel", 2);
|
||||
await contains(".o-mail-DiscussSidebarChannel:eq(0):contains(Visitor 11)");
|
||||
await contains(".o-mail-DiscussSidebarChannel:eq(1):contains(Visitor 12)");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -7,11 +7,9 @@ import { start, setCookie, loadDefaultConfig } from "@im_livechat/../tests/embed
|
||||
import { Command } from "@mail/../tests/helpers/command";
|
||||
import { contains } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { nextTick } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("autopopup");
|
||||
|
||||
QUnit.test("persisted session", async (assert) => {
|
||||
QUnit.test("persisted session", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const livechatChannelId = await loadDefaultConfig();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
@@ -29,10 +27,10 @@ QUnit.test("persisted session", async (assert) => {
|
||||
await contains(".o-mail-ChatWindow");
|
||||
});
|
||||
|
||||
QUnit.test("rule received in init", async (assert) => {
|
||||
QUnit.test("rule received in init", async () => {
|
||||
await startServer();
|
||||
await loadDefaultConfig();
|
||||
await start({
|
||||
start({
|
||||
mockRPC(route) {
|
||||
if (route === "/im_livechat/init") {
|
||||
return {
|
||||
@@ -42,6 +40,5 @@ QUnit.test("rule received in init", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
await nextTick();
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
});
|
||||
|
||||
@@ -5,26 +5,26 @@ import { startServer } from "@bus/../tests/helpers/mock_python_environment";
|
||||
import { RATING } from "@im_livechat/embed/core/livechat_service";
|
||||
import { loadDefaultConfig, start } from "@im_livechat/../tests/embed/helper/test_utils";
|
||||
|
||||
import { afterNextRender, click, insertText } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, insertText } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { triggerHotkey } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("feedback panel");
|
||||
|
||||
QUnit.test("Do not ask feedback if empty", async (assert) => {
|
||||
QUnit.test("Do not ask feedback if empty", async () => {
|
||||
await startServer();
|
||||
await loadDefaultConfig();
|
||||
await start();
|
||||
start();
|
||||
await click(".o-livechat-LivechatButton");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await click("[title='Close Chat Window']");
|
||||
assert.containsNone($, ".o-livechat-LivechatButton");
|
||||
await contains(".o-livechat-LivechatButton", 0);
|
||||
});
|
||||
|
||||
QUnit.test("Close without feedback", async (assert) => {
|
||||
await startServer();
|
||||
await loadDefaultConfig();
|
||||
await start({
|
||||
start({
|
||||
mockRPC(route) {
|
||||
if (route === "/im_livechat/visitor_leave_session") {
|
||||
assert.step(route);
|
||||
@@ -35,19 +35,20 @@ QUnit.test("Close without feedback", async (assert) => {
|
||||
},
|
||||
});
|
||||
await click(".o-livechat-LivechatButton");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await insertText(".o-mail-Composer-input", "Hello World!");
|
||||
await afterNextRender(() => triggerHotkey("Enter"));
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-Message:contains(Hello World!)");
|
||||
await click("[title='Close Chat Window']");
|
||||
await click("button:contains('Close')");
|
||||
assert.containsNone($, ".o-livechat-LivechatButton");
|
||||
await contains(".o-livechat-LivechatButton", 0);
|
||||
assert.verifySteps(["/im_livechat/visitor_leave_session"]);
|
||||
});
|
||||
|
||||
QUnit.test("Feedback with rating and comment", async (assert) => {
|
||||
await startServer();
|
||||
await loadDefaultConfig();
|
||||
await start({
|
||||
start({
|
||||
mockRPC(route, args) {
|
||||
if (route === "/im_livechat/visitor_leave_session") {
|
||||
assert.step(route);
|
||||
@@ -60,28 +61,30 @@ QUnit.test("Feedback with rating and comment", async (assert) => {
|
||||
},
|
||||
});
|
||||
await click(".o-livechat-LivechatButton");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await insertText(".o-mail-Composer-input", "Hello World!");
|
||||
await afterNextRender(() => triggerHotkey("Enter"));
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-Message:contains(Hello World!)");
|
||||
await click("[title='Close Chat Window']");
|
||||
assert.verifySteps(["/im_livechat/visitor_leave_session"]);
|
||||
await click(`img[data-alt="${RATING.GOOD}"]`);
|
||||
await insertText("textarea[placeholder='Explain your note']", "Good job!");
|
||||
await click("button:contains(Send)");
|
||||
assert.containsOnce($, "p:contains(Thank you for your feedback)");
|
||||
await click("button:contains(Send):not(:disabled)");
|
||||
await contains("p:contains(Thank you for your feedback)");
|
||||
assert.verifySteps(["/im_livechat/feedback"]);
|
||||
});
|
||||
|
||||
QUnit.test("Closing folded chat window should open it with feedback", async (assert) => {
|
||||
QUnit.test("Closing folded chat window should open it with feedback", async () => {
|
||||
await startServer();
|
||||
await loadDefaultConfig();
|
||||
await start();
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await insertText(".o-mail-Composer-input", "Hello World!");
|
||||
await afterNextRender(() => triggerHotkey("Enter"));
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-Message:contains(Hello World!)");
|
||||
await click("[title='Fold']");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow.o-folded");
|
||||
await contains(".o-mail-ChatWindow.o-folded");
|
||||
await click("[title='Close Chat Window']");
|
||||
assert.containsNone($, ".o-mail-ChatWindow.o-folded");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow:contains(Did we correctly answer your question?)");
|
||||
await contains(".o-mail-ChatWindow.o-folded", 0);
|
||||
await contains(".o-mail-ChatWindow:contains(Did we correctly answer your question?)");
|
||||
});
|
||||
|
||||
@@ -4,46 +4,47 @@ import { startServer } from "@bus/../tests/helpers/mock_python_environment";
|
||||
|
||||
import { loadDefaultConfig, start } from "@im_livechat/../tests/embed/helper/test_utils";
|
||||
|
||||
import { afterNextRender, click, insertText } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, insertText } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { triggerHotkey } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.test("open/close temporary channel", async (assert) => {
|
||||
QUnit.test("open/close temporary channel", async () => {
|
||||
await startServer();
|
||||
await loadDefaultConfig();
|
||||
await start();
|
||||
assert.containsOnce($, ".o-livechat-LivechatButton");
|
||||
start();
|
||||
await click(".o-livechat-LivechatButton");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
assert.containsNone($, ".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await contains(".o-livechat-LivechatButton", 0);
|
||||
await click("[title='Close Chat Window']");
|
||||
assert.containsNone($, ".o-mail-ChatWindow");
|
||||
assert.containsNone($, ".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-ChatWindow", 0);
|
||||
await contains(".o-livechat-LivechatButton", 0);
|
||||
});
|
||||
|
||||
QUnit.test("open/close persisted channel", async (assert) => {
|
||||
QUnit.test("open/close persisted channel", async () => {
|
||||
await startServer();
|
||||
await loadDefaultConfig();
|
||||
await start();
|
||||
assert.containsOnce($, ".o-livechat-LivechatButton");
|
||||
start();
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await insertText(".o-mail-Composer-input", "Hello");
|
||||
await afterNextRender(() => triggerHotkey("Enter"));
|
||||
await insertText(".o-mail-Composer-input", "How can I help?");
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-Message:contains(How can I help?)");
|
||||
await click("[title='Close Chat Window']");
|
||||
await contains(".o-mail-ChatWindow-content:contains(Did we correctly answer your question?)");
|
||||
await click("[title='Close Chat Window']");
|
||||
assert.containsNone($, ".o-mail-ChatWindow");
|
||||
assert.containsNone($, ".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-ChatWindow", 0);
|
||||
await contains(".o-livechat-LivechatButton", 0);
|
||||
});
|
||||
|
||||
QUnit.test("livechat not available", async (assert) => {
|
||||
QUnit.test("livechat not available", async () => {
|
||||
await startServer();
|
||||
await loadDefaultConfig();
|
||||
await start({
|
||||
start({
|
||||
mockRPC(route) {
|
||||
if (route === "/im_livechat/init") {
|
||||
return { available_for_me: false };
|
||||
}
|
||||
},
|
||||
});
|
||||
assert.containsNone($, ".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-ChatWindowContainer");
|
||||
await contains(".o-livechat-LivechatButton", 0);
|
||||
});
|
||||
|
||||
@@ -5,11 +5,11 @@ import { startServer } from "@bus/../tests/helpers/mock_python_environment";
|
||||
import { loadDefaultConfig, setCookie, start } from "@im_livechat/../tests/embed/helper/test_utils";
|
||||
|
||||
import { Command } from "@mail/../tests/helpers/command";
|
||||
import { click } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
QUnit.module("livechat service");
|
||||
|
||||
QUnit.test("persisted session history", async (assert) => {
|
||||
QUnit.test("persisted session history", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const livechatChannelId = await loadDefaultConfig();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
@@ -30,19 +30,18 @@ QUnit.test("persisted session history", async (assert) => {
|
||||
model: "discuss.channel",
|
||||
message_type: "comment",
|
||||
});
|
||||
|
||||
await start();
|
||||
assert.containsOnce($, ".o-mail-Message:contains(Old message in history)");
|
||||
start();
|
||||
await contains(".o-mail-Message:contains(Old message in history)");
|
||||
});
|
||||
|
||||
QUnit.test("previous operator prioritized", async (assert) => {
|
||||
QUnit.test("previous operator prioritized", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const livechatChannelId = await loadDefaultConfig();
|
||||
const userId = pyEnv["res.users"].create({ name: "John Doe", im_status: "online" });
|
||||
const previousOperatorId = pyEnv["res.partner"].create({ user_ids: [userId] });
|
||||
pyEnv["im_livechat.channel"].write([livechatChannelId], { user_ids: [Command.link(userId)] });
|
||||
setCookie("im_livechat_previous_operator_pid", JSON.stringify(previousOperatorId));
|
||||
await start();
|
||||
await click(".o-livechat-LivechatButton");
|
||||
assert.containsOnce($, ".o-mail-Message-author:contains(John Doe)");
|
||||
start();
|
||||
click(".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-Message-author:contains(John Doe)");
|
||||
});
|
||||
|
||||
@@ -6,13 +6,13 @@ import { loadDefaultConfig, setCookie, start } from "@im_livechat/../tests/embed
|
||||
import { LivechatButton } from "@im_livechat/embed/core_ui/livechat_button";
|
||||
|
||||
import { Command } from "@mail/../tests/helpers/command";
|
||||
import { afterNextRender, click, insertText } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, insertText } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { mockTimeout, triggerHotkey } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("livechat session");
|
||||
|
||||
QUnit.test("Unsuccessful message post shows session expired", async (assert) => {
|
||||
QUnit.test("Unsuccessful message post shows session expired", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const livechatChannelId = await loadDefaultConfig();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
@@ -26,7 +26,7 @@ QUnit.test("Unsuccessful message post shows session expired", async (assert) =>
|
||||
});
|
||||
const [channelInfo] = pyEnv.mockServer._mockDiscussChannelChannelInfo([channelId]);
|
||||
setCookie("im_livechat_session", JSON.stringify(channelInfo));
|
||||
await start({
|
||||
start({
|
||||
mockRPC(route) {
|
||||
if (route === "/im_livechat/chat_post") {
|
||||
return false;
|
||||
@@ -34,16 +34,16 @@ QUnit.test("Unsuccessful message post shows session expired", async (assert) =>
|
||||
},
|
||||
});
|
||||
await insertText(".o-mail-Composer-input", "Hello World!");
|
||||
await afterNextRender(() => triggerHotkey("Enter"));
|
||||
assert.containsOnce($, ".o_notification:contains(Session expired)");
|
||||
assert.containsNone($, ".o-mail-ChatWindow");
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o_notification:contains(Session expired)");
|
||||
await contains(".o-mail-ChatWindow", 0);
|
||||
});
|
||||
|
||||
QUnit.test("Session is reset after failing to persist the channel", async (assert) => {
|
||||
await startServer();
|
||||
await loadDefaultConfig();
|
||||
const { advanceTime } = mockTimeout();
|
||||
await start({
|
||||
start({
|
||||
mockRPC(route, args) {
|
||||
if (route === "/im_livechat/get_session" && args.persisted) {
|
||||
return false;
|
||||
@@ -52,15 +52,12 @@ QUnit.test("Session is reset after failing to persist the channel", async (asser
|
||||
});
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await insertText(".o-mail-Composer-input", "Hello World!");
|
||||
await afterNextRender(() => triggerHotkey("Enter"));
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o_notification:contains(No available collaborator, please try again later.)"
|
||||
);
|
||||
assert.containsOnce($, ".o-livechat-LivechatButton");
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o_notification:contains(No available collaborator, please try again later.)");
|
||||
await contains(".o-livechat-LivechatButton");
|
||||
await advanceTime(LivechatButton.DEBOUNCE_DELAY + 10);
|
||||
await click(".o-livechat-LivechatButton");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
});
|
||||
|
||||
QUnit.test("Thread state is saved on the session", async (assert) => {
|
||||
@@ -68,10 +65,13 @@ QUnit.test("Thread state is saved on the session", async (assert) => {
|
||||
await loadDefaultConfig();
|
||||
const env = await start();
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await contains(".o-mail-ChatWindow-content");
|
||||
assert.strictEqual(env.services["im_livechat.livechat"].sessionCookie.state, "open");
|
||||
await click(".o-mail-ChatWindow-header");
|
||||
await contains(".o-mail-ChatWindow-content", 0);
|
||||
assert.strictEqual(env.services["im_livechat.livechat"].sessionCookie.state, "folded");
|
||||
await click(".o-mail-ChatWindow-header");
|
||||
await contains(".o-mail-ChatWindow-content");
|
||||
assert.strictEqual(env.services["im_livechat.livechat"].sessionCookie.state, "open");
|
||||
});
|
||||
|
||||
@@ -82,7 +82,8 @@ QUnit.test("Seen message is saved on the session", async (assert) => {
|
||||
await click(".o-livechat-LivechatButton");
|
||||
assert.notOk(env.services["im_livechat.livechat"].sessionCookie.seen_message_id);
|
||||
await insertText(".o-mail-Composer-input", "Hello World!");
|
||||
await afterNextRender(() => triggerHotkey("Enter"));
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-Message", 2);
|
||||
assert.strictEqual(
|
||||
env.services["im_livechat.livechat"].sessionCookie.seen_message_id,
|
||||
env.services["im_livechat.livechat"].thread.newestMessage.id
|
||||
|
||||
@@ -4,7 +4,7 @@ import { startServer } from "@bus/../tests/helpers/mock_python_environment";
|
||||
|
||||
import { loadDefaultConfig, start } from "@im_livechat/../tests/embed/helper/test_utils";
|
||||
|
||||
import { afterNextRender, click, insertText } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, insertText } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { triggerHotkey } from "@web/../tests/helpers/utils";
|
||||
|
||||
@@ -13,7 +13,7 @@ QUnit.module("transcript sender");
|
||||
QUnit.test("send", async (assert) => {
|
||||
await startServer();
|
||||
await loadDefaultConfig();
|
||||
await start({
|
||||
start({
|
||||
mockRPC(route, args) {
|
||||
if (route === "/im_livechat/email_livechat_transcript") {
|
||||
assert.step(`send_transcript - ${args.email}`);
|
||||
@@ -22,20 +22,21 @@ QUnit.test("send", async (assert) => {
|
||||
});
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await insertText(".o-mail-Composer-input", "Hello World!");
|
||||
await afterNextRender(() => triggerHotkey("Enter"));
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-Message:contains(Hello World!)");
|
||||
await click(".o-mail-ChatWindow-command[title*='Close']");
|
||||
assert.containsOnce($, ".form-text:contains(Receive a copy of this conversation)");
|
||||
assert.containsOnce($, "button[data-action='sendTranscript']:disabled");
|
||||
await contains(".form-text:contains(Receive a copy of this conversation)");
|
||||
await contains("button[data-action='sendTranscript']:disabled");
|
||||
await insertText("input[placeholder='mail@example.com']", "odoobot@odoo.com");
|
||||
await click("button[data-action='sendTranscript']");
|
||||
await click("button[data-action='sendTranscript']:not(:disabled)");
|
||||
await contains(".form-text:contains(The conversation was sent)");
|
||||
assert.verifySteps(["send_transcript - odoobot@odoo.com"]);
|
||||
assert.containsOnce($, ".form-text:contains(The conversation was sent)");
|
||||
});
|
||||
|
||||
QUnit.test("send failed", async (assert) => {
|
||||
QUnit.test("send failed", async () => {
|
||||
await startServer();
|
||||
await loadDefaultConfig();
|
||||
await start({
|
||||
start({
|
||||
mockRPC(route) {
|
||||
if (route === "/im_livechat/email_livechat_transcript") {
|
||||
throw new Error();
|
||||
@@ -44,9 +45,10 @@ QUnit.test("send failed", async (assert) => {
|
||||
});
|
||||
await click(".o-livechat-LivechatButton");
|
||||
await insertText(".o-mail-Composer-input", "Hello World!");
|
||||
await afterNextRender(() => triggerHotkey("Enter"));
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-Message:contains(Hello World!)");
|
||||
await click(".o-mail-ChatWindow-command[title*='Close']");
|
||||
await insertText("input[placeholder='mail@example.com']", "odoobot@odoo.com");
|
||||
await click("button[data-action='sendTranscript']");
|
||||
assert.containsOnce($, ".form-text:contains(An error occurred. Please try again.)");
|
||||
await click("button[data-action='sendTranscript']:not(:disabled)");
|
||||
await contains(".form-text:contains(An error occurred. Please try again.)");
|
||||
});
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { patchUiSize } from "@mail/../tests/helpers/patch_ui_size";
|
||||
|
||||
QUnit.module("messaging menu (patch)");
|
||||
|
||||
QUnit.test('livechats should be in "chat" filter', async (assert) => {
|
||||
QUnit.test('livechats should be in "chat" filter', async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
@@ -18,15 +18,14 @@ QUnit.test('livechats should be in "chat" filter', async (assert) => {
|
||||
});
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsOnce($, ".o-mail-MessagingMenu button:contains(All)");
|
||||
assert.hasClass($(".o-mail-MessagingMenu button:contains(All)"), "fw-bolder");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem:contains(Visitor 11)");
|
||||
await contains(".o-mail-MessagingMenu button:contains(All).fw-bolder");
|
||||
await contains(".o-mail-NotificationItem:contains(Visitor 11)");
|
||||
await click(".o-mail-MessagingMenu button:contains(Chat)");
|
||||
assert.hasClass($(".o-mail-MessagingMenu button:contains(Chat)"), "fw-bolder");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem:contains(Visitor 11)");
|
||||
await contains(".o-mail-MessagingMenu button:contains(Chat).fw-bolder");
|
||||
await contains(".o-mail-NotificationItem:contains(Visitor 11)");
|
||||
});
|
||||
|
||||
QUnit.test('livechats should be in "livechat" tab in mobile', async (assert) => {
|
||||
QUnit.test('livechats should be in "livechat" tab in mobile', async () => {
|
||||
patchUiSize({ height: 360, width: 640 });
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
@@ -41,7 +40,7 @@ QUnit.test('livechats should be in "livechat" tab in mobile', async (assert) =>
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click("button:contains(Livechat)");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem:contains(Visitor 11)");
|
||||
await contains(".o-mail-NotificationItem:contains(Visitor 11)");
|
||||
await click("button:contains(Chat)");
|
||||
assert.containsNone($, ".o-mail-NotificationItem:contains(Visitor 11)");
|
||||
await contains(".o-mail-NotificationItem:contains(Visitor 11)", 0);
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { patchUiSize, SIZES } from "@mail/../tests/helpers/patch_ui_size";
|
||||
import { click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
QUnit.module("mobile messaging menu (patch)", {
|
||||
beforeEach() {
|
||||
@@ -9,29 +9,26 @@ QUnit.module("mobile messaging menu (patch)", {
|
||||
},
|
||||
});
|
||||
|
||||
QUnit.test("Livechat button is not present when there is no livechat thread", async (assert) => {
|
||||
QUnit.test("Livechat button is not present when there is no livechat thread", async () => {
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsOnce($, ".o-mail-MessagingMenu");
|
||||
assert.containsNone($, ".o-mail-MessagingMenu-navbar:contains(Livechat)");
|
||||
await contains(".o-mail-MessagingMenu");
|
||||
await contains(".o-mail-MessagingMenu-navbar:contains(Livechat)", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"Livechat button is present when there is at least one livechat thread",
|
||||
async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
[0, 0, { partner_id: pyEnv.publicPartnerId }],
|
||||
],
|
||||
channel_type: "livechat",
|
||||
livechat_operator_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsOnce($, ".o-mail-MessagingMenu");
|
||||
assert.containsOnce($, ".o-mail-MessagingMenu-navbar:contains(Livechat)");
|
||||
}
|
||||
);
|
||||
QUnit.test("Livechat button is present when there is at least one livechat thread", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
[0, 0, { partner_id: pyEnv.publicPartnerId }],
|
||||
],
|
||||
channel_type: "livechat",
|
||||
livechat_operator_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await contains(".o-mail-MessagingMenu");
|
||||
await contains(".o-mail-MessagingMenu-navbar:contains(Livechat)");
|
||||
});
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { afterNextRender, click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { makeFakeNotificationService } from "@web/../tests/helpers/mock_services";
|
||||
import { nextTick } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("discuss sidebar (patch)");
|
||||
|
||||
QUnit.test("Unknown visitor", async (assert) => {
|
||||
QUnit.test("Unknown visitor", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
@@ -19,12 +18,12 @@ QUnit.test("Unknown visitor", async (assert) => {
|
||||
livechat_operator_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsOnce($, ".o-mail-DiscussSidebar .o-mail-DiscussSidebarCategory-livechat");
|
||||
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(Visitor 11)");
|
||||
openDiscuss();
|
||||
await contains(".o-mail-DiscussSidebar .o-mail-DiscussSidebarCategory-livechat");
|
||||
await contains(".o-mail-DiscussSidebarChannel:contains(Visitor 11)");
|
||||
});
|
||||
|
||||
QUnit.test("Known user with country", async (assert) => {
|
||||
QUnit.test("Known user with country", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const countryId = pyEnv["res.country"].create({
|
||||
code: "be",
|
||||
@@ -43,11 +42,11 @@ QUnit.test("Known user with country", async (assert) => {
|
||||
livechat_operator_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(Jean (Belgium))");
|
||||
openDiscuss();
|
||||
await contains(".o-mail-DiscussSidebarChannel:contains(Jean (Belgium))");
|
||||
});
|
||||
|
||||
QUnit.test("Do not show channel when visitor is typing", async (assert) => {
|
||||
QUnit.test("Do not show channel when visitor is typing", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["res.users"].write([pyEnv.currentUserId], { im_status: "online" });
|
||||
const livechatChannelId = pyEnv["im_livechat.channel"].create({
|
||||
@@ -70,8 +69,9 @@ QUnit.test("Do not show channel when visitor is typing", async (assert) => {
|
||||
livechat_operator_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { env, openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsNone($, ".o-mail-DiscussSidebarCategory-livechat");
|
||||
openDiscuss();
|
||||
await contains(".o-mail-DiscussSidebarCategory", 2);
|
||||
await contains(".o-mail-DiscussSidebarCategory-livechat", 0);
|
||||
// simulate livechat visitor typing
|
||||
const channel = pyEnv["discuss.channel"].searchRead([["id", "=", channelId]])[0];
|
||||
await pyEnv.withUser(pyEnv.publicUserId, () =>
|
||||
@@ -80,8 +80,9 @@ QUnit.test("Do not show channel when visitor is typing", async (assert) => {
|
||||
uuid: channel.uuid,
|
||||
})
|
||||
);
|
||||
// weak test, no guaranteed that we waited long enough for the livechat to potentially appear
|
||||
await nextTick();
|
||||
assert.containsNone($, ".o-mail-DiscussSidebarCategory-livechat");
|
||||
await contains(".o-mail-DiscussSidebarCategory-livechat", 0);
|
||||
});
|
||||
|
||||
QUnit.test("Close should update the value on the server", async (assert) => {
|
||||
@@ -101,7 +102,7 @@ QUnit.test("Close should update the value on the server", async (assert) => {
|
||||
});
|
||||
const currentUserId = pyEnv.currentUserId;
|
||||
const { env, openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
openDiscuss();
|
||||
const initalSettings = await env.services.orm.call(
|
||||
"res.users.settings",
|
||||
"_find_or_create_for_user",
|
||||
@@ -134,7 +135,7 @@ QUnit.test("Open should update the value on the server", async (assert) => {
|
||||
});
|
||||
const currentUserId = pyEnv.currentUserId;
|
||||
const { env, openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
openDiscuss();
|
||||
const initalSettings = await env.services.orm.call(
|
||||
"res.users.settings",
|
||||
"_find_or_create_for_user",
|
||||
@@ -150,7 +151,7 @@ QUnit.test("Open should update the value on the server", async (assert) => {
|
||||
assert.ok(newSettings.is_discuss_sidebar_category_livechat_open);
|
||||
});
|
||||
|
||||
QUnit.test("Open from the bus", async (assert) => {
|
||||
QUnit.test("Open from the bus", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
@@ -166,26 +167,19 @@ QUnit.test("Open from the bus", async (assert) => {
|
||||
is_discuss_sidebar_category_livechat_open: false,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsNone(
|
||||
$,
|
||||
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel"
|
||||
);
|
||||
await afterNextRender(() => {
|
||||
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "mail.record/insert", {
|
||||
"res.users.settings": {
|
||||
id: settingsId,
|
||||
is_discuss_sidebar_category_livechat_open: true,
|
||||
},
|
||||
});
|
||||
openDiscuss();
|
||||
await contains(".o-mail-DiscussSidebarCategory-livechat");
|
||||
await contains(".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel", 0);
|
||||
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "mail.record/insert", {
|
||||
"res.users.settings": {
|
||||
id: settingsId,
|
||||
is_discuss_sidebar_category_livechat_open: true,
|
||||
},
|
||||
});
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel"
|
||||
);
|
||||
await contains(".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel");
|
||||
});
|
||||
|
||||
QUnit.test("Close from the bus", async (assert) => {
|
||||
QUnit.test("Close from the bus", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
@@ -201,26 +195,18 @@ QUnit.test("Close from the bus", async (assert) => {
|
||||
is_discuss_sidebar_category_livechat_open: true,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel"
|
||||
);
|
||||
await afterNextRender(() => {
|
||||
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "mail.record/insert", {
|
||||
"res.users.settings": {
|
||||
id: settingsId,
|
||||
is_discuss_sidebar_category_livechat_open: false,
|
||||
},
|
||||
});
|
||||
openDiscuss();
|
||||
await contains(".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel");
|
||||
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "mail.record/insert", {
|
||||
"res.users.settings": {
|
||||
id: settingsId,
|
||||
is_discuss_sidebar_category_livechat_open: false,
|
||||
},
|
||||
});
|
||||
assert.containsNone(
|
||||
$,
|
||||
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel"
|
||||
);
|
||||
await contains(".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel", 0);
|
||||
});
|
||||
|
||||
QUnit.test("Smiley face avatar for an anonymous livechat item", async (assert) => {
|
||||
QUnit.test("Smiley face avatar for an anonymous livechat item", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
@@ -232,15 +218,13 @@ QUnit.test("Smiley face avatar for an anonymous livechat item", async (assert) =
|
||||
livechat_operator_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.strictEqual(
|
||||
$(".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel img")[0].dataset
|
||||
.src,
|
||||
"/mail/static/src/img/smiley/avatar.jpg"
|
||||
openDiscuss();
|
||||
await contains(
|
||||
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel img[data-src='/mail/static/src/img/smiley/avatar.jpg']"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("Partner profile picture for livechat item linked to a partner", async (assert) => {
|
||||
QUnit.test("Partner profile picture for livechat item linked to a partner", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Jean" });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
@@ -252,15 +236,13 @@ QUnit.test("Partner profile picture for livechat item linked to a partner", asyn
|
||||
livechat_operator_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.strictEqual(
|
||||
$(".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel img")[0].dataset
|
||||
.src,
|
||||
`/web/image/res.partner/${partnerId}/avatar_128`
|
||||
openDiscuss(channelId);
|
||||
await contains(
|
||||
`.o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel img[data-src='/web/image/res.partner/${partnerId}/avatar_128']`
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("No counter if the category is unfolded and with unread messages", async (assert) => {
|
||||
QUnit.test("No counter if the category is unfolded and with unread messages", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
@@ -279,15 +261,12 @@ QUnit.test("No counter if the category is unfolded and with unread messages", as
|
||||
livechat_operator_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsNone(
|
||||
$,
|
||||
".o-mail-DiscussSidebarCategory-livechat .o-mail-Discuss-category-counter",
|
||||
"should not have a counter if the category is unfolded and with unread messages"
|
||||
);
|
||||
openDiscuss();
|
||||
await contains(".o-mail-DiscussSidebarCategory-livechat");
|
||||
await contains(".o-mail-DiscussSidebarCategory-livechat .o-mail-Discuss-category-counter", 0);
|
||||
});
|
||||
|
||||
QUnit.test("No counter if category is folded and without unread messages", async (assert) => {
|
||||
QUnit.test("No counter if category is folded and without unread messages", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
@@ -303,17 +282,14 @@ QUnit.test("No counter if category is folded and without unread messages", async
|
||||
is_discuss_sidebar_category_livechat_open: false,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsNone(
|
||||
$,
|
||||
".o-mail-DiscussSidebarCategory-livechat .o-discuss-badge",
|
||||
"should not have a counter if the category is unfolded and with unread messages"
|
||||
);
|
||||
openDiscuss();
|
||||
await contains(".o-mail-DiscussSidebarCategory-livechat");
|
||||
await contains(".o-mail-DiscussSidebarCategory-livechat .o-discuss-badge", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"Counter should have correct value of unread threads if category is folded and with unread messages",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
@@ -336,15 +312,12 @@ QUnit.test(
|
||||
is_discuss_sidebar_category_livechat_open: false,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.strictEqual(
|
||||
$(".o-mail-DiscussSidebarCategory-livechat .o-discuss-badge").text(),
|
||||
"1"
|
||||
);
|
||||
openDiscuss();
|
||||
await contains(".o-mail-DiscussSidebarCategory-livechat .o-discuss-badge:contains(1)");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("Close manually by clicking the title", async (assert) => {
|
||||
QUnit.test("Close manually by clicking the title", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
@@ -360,18 +333,14 @@ QUnit.test("Close manually by clicking the title", async (assert) => {
|
||||
is_discuss_sidebar_category_livechat_open: true,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel",
|
||||
"Category is unfolded initially"
|
||||
);
|
||||
openDiscuss();
|
||||
await contains(".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel");
|
||||
// fold the livechat category
|
||||
await click(".o-mail-DiscussSidebarCategory-livechat .btn");
|
||||
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
|
||||
await contains(".o-mail-DiscussSidebarChannel", 0);
|
||||
});
|
||||
|
||||
QUnit.test("Open manually by clicking the title", async (assert) => {
|
||||
QUnit.test("Open manually by clicking the title", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
@@ -387,21 +356,15 @@ QUnit.test("Open manually by clicking the title", async (assert) => {
|
||||
is_discuss_sidebar_category_livechat_open: false,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsNone(
|
||||
$,
|
||||
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel",
|
||||
"Category is folded initially"
|
||||
);
|
||||
openDiscuss();
|
||||
await contains(".o-mail-DiscussSidebarCategory-livechat");
|
||||
await contains(".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel", 0);
|
||||
// open the livechat category
|
||||
await click(".o-mail-DiscussSidebarCategory-livechat .btn");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel"
|
||||
);
|
||||
await contains(".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel");
|
||||
});
|
||||
|
||||
QUnit.test("Category item should be invisible if the category is closed", async (assert) => {
|
||||
QUnit.test("Category item should be invisible if the category is closed", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
@@ -413,51 +376,13 @@ QUnit.test("Category item should be invisible if the category is closed", async
|
||||
livechat_operator_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel"
|
||||
);
|
||||
openDiscuss();
|
||||
await contains(".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel");
|
||||
await click(".o-mail-DiscussSidebarCategory-livechat .btn");
|
||||
assert.containsNone(
|
||||
$,
|
||||
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel"
|
||||
);
|
||||
await contains(".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"Active category item should be visible even if the category is closed",
|
||||
async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
[0, 0, { partner_id: pyEnv.publicPartnerId }],
|
||||
],
|
||||
channel_type: "livechat",
|
||||
livechat_operator_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel"
|
||||
);
|
||||
await click(".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel.o-active"
|
||||
);
|
||||
await click(".o-mail-DiscussSidebarCategory-livechat .btn");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel"
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("Clicking on unpin button unpins the channel", async (assert) => {
|
||||
QUnit.test("Active category item should be visible even if the category is closed", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
@@ -468,17 +393,35 @@ QUnit.test("Clicking on unpin button unpins the channel", async (assert) => {
|
||||
channel_type: "livechat",
|
||||
livechat_operator_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start({
|
||||
services: {
|
||||
notification: makeFakeNotificationService((message) => assert.step(message)),
|
||||
},
|
||||
});
|
||||
await openDiscuss();
|
||||
await click(".o-mail-DiscussSidebarChannel [title='Unpin Conversation']");
|
||||
assert.verifySteps(["You unpinned your conversation with Visitor 11"]);
|
||||
const { openDiscuss } = await start();
|
||||
openDiscuss();
|
||||
await contains(".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel");
|
||||
await click(".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel");
|
||||
await contains(
|
||||
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel.o-active"
|
||||
);
|
||||
await click(".o-mail-DiscussSidebarCategory-livechat .btn");
|
||||
await contains(".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel");
|
||||
});
|
||||
|
||||
QUnit.test("Message unread counter", async (assert) => {
|
||||
QUnit.test("Clicking on unpin button unpins the channel", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
[0, 0, { partner_id: pyEnv.publicPartnerId }],
|
||||
],
|
||||
channel_type: "livechat",
|
||||
livechat_operator_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
openDiscuss();
|
||||
await click(".o-mail-DiscussSidebarChannel [title='Unpin Conversation']");
|
||||
await contains(".o_notification:contains(You unpinned your conversation with Visitor 11)");
|
||||
});
|
||||
|
||||
QUnit.test("Message unread counter", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
@@ -490,14 +433,12 @@ QUnit.test("Message unread counter", async (assert) => {
|
||||
livechat_operator_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { env, openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
await afterNextRender(() =>
|
||||
pyEnv.withUser(pyEnv.publicUserId, () =>
|
||||
env.services.rpc("/im_livechat/chat_post", {
|
||||
message_content: "hu",
|
||||
uuid: pyEnv["discuss.channel"].searchRead([["id", "=", channelId]])[0].uuid,
|
||||
})
|
||||
)
|
||||
openDiscuss();
|
||||
pyEnv.withUser(pyEnv.publicUserId, () =>
|
||||
env.services.rpc("/im_livechat/chat_post", {
|
||||
message_content: "hu",
|
||||
uuid: pyEnv["discuss.channel"].searchRead([["id", "=", channelId]])[0].uuid,
|
||||
})
|
||||
);
|
||||
assert.containsOnce($, ".o-mail-DiscussSidebarChannel .badge:contains(1)");
|
||||
await contains(".o-mail-DiscussSidebarChannel .badge:contains(1)");
|
||||
});
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Command } from "@mail/../tests/helpers/command";
|
||||
import { insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { contains, insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
QUnit.module("suggestion");
|
||||
|
||||
QUnit.test("Suggestions are shown after delimiter was used in text (:)", async (assert) => {
|
||||
QUnit.test("Suggestions are shown after delimiter was used in text (:)", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.shortcode"].create({
|
||||
source: "hello",
|
||||
@@ -22,10 +22,10 @@ QUnit.test("Suggestions are shown after delimiter was used in text (:)", async (
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", ":");
|
||||
assert.containsOnce($, ".o-mail-Composer-suggestion");
|
||||
await contains(".o-mail-Composer-suggestion");
|
||||
await insertText(".o-mail-Composer-input", ")");
|
||||
assert.containsNone($, ".o-mail-Composer-suggestion");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
await insertText(".o-mail-Composer-input", " ");
|
||||
await insertText(".o-mail-Composer-input", ":");
|
||||
assert.containsOnce($, ".o-mail-Composer-suggestion:contains(hello)");
|
||||
await contains(".o-mail-Composer-suggestion:contains(hello)");
|
||||
});
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
import { startServer } from "@bus/../tests/helpers/mock_python_environment";
|
||||
|
||||
import { Command } from "@mail/../tests/helpers/command";
|
||||
import { click, start } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
QUnit.module("Thread model");
|
||||
|
||||
QUnit.test("Thread name unchanged when inviting new users", async (assert) => {
|
||||
QUnit.test("Thread name unchanged when inviting new users", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const userId = pyEnv["res.users"].create({ name: "James" });
|
||||
pyEnv["res.partner"].create({
|
||||
@@ -25,11 +25,12 @@ QUnit.test("Thread name unchanged when inviting new users", async (assert) => {
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-Discuss-threadName[title='Visitor #20']");
|
||||
await contains(".o-mail-Discuss-threadName[title='Visitor #20']");
|
||||
await click("button[title='Add Users']");
|
||||
await click(".o-discuss-ChannelInvitation-selectable:contains(James) input");
|
||||
await click("button:contains(Invite)");
|
||||
await click("button:contains(Invite):not(:disabled)");
|
||||
await contains(".o-discuss-ChannelInvitation", 0);
|
||||
await click("button[title='Show Member List']");
|
||||
assert.containsOnce($, ".o-discuss-ChannelMember:contains(James)");
|
||||
assert.containsOnce($, ".o-mail-Discuss-threadName[title='Visitor #20']");
|
||||
await contains(".o-discuss-ChannelMember:contains(James)");
|
||||
await contains(".o-mail-Discuss-threadName[title='Visitor #20']");
|
||||
});
|
||||
|
||||
@@ -132,9 +132,9 @@ export class Attachment {
|
||||
return assignDefined(
|
||||
{},
|
||||
{
|
||||
access_token: this.accessToken,
|
||||
access_token: this.accessToken || undefined,
|
||||
filename: this.name || undefined,
|
||||
unique: this.checksum,
|
||||
unique: this.checksum || undefined,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -495,7 +495,7 @@ export class Composer extends Component {
|
||||
const el = this.ref.el;
|
||||
const attachments = this.props.composer.attachments;
|
||||
if (
|
||||
el.value.trim() ||
|
||||
this.props.composer.textInputContent.trim() ||
|
||||
(attachments.length > 0 && attachments.every(({ uploading }) => !uploading)) ||
|
||||
(this.message && this.message.attachments.length > 0)
|
||||
) {
|
||||
@@ -503,7 +503,7 @@ export class Composer extends Component {
|
||||
return;
|
||||
}
|
||||
this.state.active = false;
|
||||
await cb(el.value);
|
||||
await cb(this.props.composer.textInputContent);
|
||||
if (this.props.onPostCallback) {
|
||||
this.props.onPostCallback();
|
||||
}
|
||||
@@ -556,7 +556,10 @@ export class Composer extends Component {
|
||||
}
|
||||
|
||||
async editMessage() {
|
||||
if (this.ref.el.value || this.props.composer.message.attachments.length > 0) {
|
||||
if (
|
||||
this.props.composer.textInputContent ||
|
||||
this.props.composer.message.attachments.length > 0
|
||||
) {
|
||||
await this.processMessage(async (value) =>
|
||||
this.messageService.edit(
|
||||
this.props.composer.message,
|
||||
@@ -577,7 +580,7 @@ export class Composer extends Component {
|
||||
}
|
||||
|
||||
addEmoji(str) {
|
||||
const textContent = this.ref.el.value;
|
||||
const textContent = this.props.composer.textInputContent;
|
||||
const firstPart = textContent.slice(0, this.props.composer.selection.start);
|
||||
const secondPart = textContent.slice(this.props.composer.selection.end, textContent.length);
|
||||
this.props.composer.textInputContent = firstPart + str + secondPart;
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
/>
|
||||
</t>
|
||||
</div>
|
||||
<div class="o-mail-Discuss-header flex-shrink-0 d-flex align-items-center ms-1">
|
||||
<div class="flex-shrink-0 d-flex align-items-center ms-1">
|
||||
<t t-foreach="threadActions.actions" t-as="action" t-key="action.id">
|
||||
<button class="btn px-2" t-attf-class="{{ action.isActive ? 'o-isActive' : '' }}" t-att-disabled="action.disabledCondition" t-att-title="action.name" t-att-name="action.id" t-on-click="() => action.onSelect()">
|
||||
<i t-if="action.iconLarge" t-att-class="action.iconLarge"/> <span t-if="action.text" t-esc="action.text"/>
|
||||
|
||||
@@ -8,7 +8,6 @@ import { useService } from "@web/core/utils/hooks";
|
||||
export function useSuggestion() {
|
||||
const comp = useComponent();
|
||||
const sequential = useSequential();
|
||||
let pendingFetchCount = 0;
|
||||
/** @type {import("@mail/core/common/suggestion_service").SuggestionService} */
|
||||
const suggestionService = useService("mail.suggestion");
|
||||
const self = {
|
||||
@@ -34,14 +33,10 @@ export function useSuggestion() {
|
||||
if (selectionStart !== selectionEnd) {
|
||||
// avoid interfering with multi-char selection
|
||||
self.clearSearch();
|
||||
return;
|
||||
}
|
||||
const candidatePositions = [];
|
||||
// keep the current delimiter if it is still valid
|
||||
if (self.search.position !== undefined && self.search.position < selectionStart) {
|
||||
candidatePositions.push(self.search.position);
|
||||
}
|
||||
// consider the chars before the current cursor position if the
|
||||
// current delimiter is no longer valid (or if there is none)
|
||||
// consider the chars before the current cursor position
|
||||
let numberOfSpaces = 0;
|
||||
for (let index = selectionStart - 1; index >= 0; --index) {
|
||||
if (/\s/.test(content[index])) {
|
||||
@@ -56,6 +51,10 @@ export function useSuggestion() {
|
||||
}
|
||||
candidatePositions.push(index);
|
||||
}
|
||||
// keep the current delimiter if it is still valid
|
||||
if (self.search.position !== undefined && self.search.position < selectionStart) {
|
||||
candidatePositions.push(self.search.position);
|
||||
}
|
||||
const supportedDelimiters = suggestionService.getSupportedDelimiters(self.thread);
|
||||
for (const candidatePosition of candidatePositions) {
|
||||
if (candidatePosition < 0 || candidatePosition >= content.length) {
|
||||
@@ -122,7 +121,7 @@ export function useSuggestion() {
|
||||
count: 0,
|
||||
items: undefined,
|
||||
}),
|
||||
update({ clearSearchOnEmpty = true } = {}) {
|
||||
update() {
|
||||
if (!self.search.delimiter) {
|
||||
return;
|
||||
}
|
||||
@@ -133,11 +132,7 @@ export function useSuggestion() {
|
||||
);
|
||||
const { type, mainSuggestions, extraSuggestions = [] } = suggestions;
|
||||
if (!mainSuggestions.length && !extraSuggestions.length) {
|
||||
if (clearSearchOnEmpty) {
|
||||
self.clearSearch();
|
||||
} else {
|
||||
self.state.items = undefined;
|
||||
}
|
||||
self.state.items = undefined;
|
||||
return;
|
||||
}
|
||||
// arbitrary limit to avoid displaying too many elements at once
|
||||
@@ -152,27 +147,35 @@ export function useSuggestion() {
|
||||
},
|
||||
};
|
||||
useEffect(
|
||||
() => {
|
||||
self.update({ clearSearchOnEmpty: false });
|
||||
(delimiter, position, term) => {
|
||||
self.update();
|
||||
if (self.search.position === undefined || !self.search.delimiter) {
|
||||
return; // nothing else to fetch
|
||||
}
|
||||
sequential(async () => {
|
||||
if (self.search.position === undefined || !self.search.delimiter) {
|
||||
if (
|
||||
self.search.delimiter !== delimiter ||
|
||||
self.search.position !== position ||
|
||||
self.search.term !== term
|
||||
) {
|
||||
return; // ignore obsolete call
|
||||
}
|
||||
pendingFetchCount++;
|
||||
try {
|
||||
await suggestionService.fetchSuggestions(self.search, {
|
||||
thread: self.thread,
|
||||
onFetched() {
|
||||
if (owl.status(comp) === "destroyed") {
|
||||
return;
|
||||
}
|
||||
self.update({ clearSearchOnEmpty: pendingFetchCount === 0 });
|
||||
},
|
||||
});
|
||||
} finally {
|
||||
pendingFetchCount--;
|
||||
await suggestionService.fetchSuggestions(self.search, {
|
||||
thread: self.thread,
|
||||
});
|
||||
if (owl.status(comp) === "destroyed") {
|
||||
return;
|
||||
}
|
||||
self.update();
|
||||
if (
|
||||
self.search.delimiter === delimiter &&
|
||||
self.search.position === position &&
|
||||
self.search.term === term &&
|
||||
!self.state.items?.mainSuggestions.length &&
|
||||
!self.state.items?.extraSuggestions.length
|
||||
) {
|
||||
self.clearSearch();
|
||||
}
|
||||
self.update({ clearSearchOnEmpty: pendingFetchCount === 0 });
|
||||
});
|
||||
},
|
||||
() => {
|
||||
|
||||
@@ -23,15 +23,15 @@ export class SuggestionService {
|
||||
return [["@"], ["#"]];
|
||||
}
|
||||
|
||||
async fetchSuggestions({ delimiter, term }, { thread, onFetched } = {}) {
|
||||
async fetchSuggestions({ delimiter, term }, { thread } = {}) {
|
||||
const cleanedSearchTerm = cleanTerm(term);
|
||||
switch (delimiter) {
|
||||
case "@": {
|
||||
this.fetchPartners(cleanedSearchTerm, thread).then(onFetched);
|
||||
await this.fetchPartners(cleanedSearchTerm, thread);
|
||||
break;
|
||||
}
|
||||
case "#":
|
||||
this.fetchThreads(cleanedSearchTerm).then(onFetched);
|
||||
await this.fetchThreads(cleanedSearchTerm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -61,6 +61,9 @@ export class SuggestionService {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} term
|
||||
*/
|
||||
async fetchThreads(term) {
|
||||
const suggestedThreads = await this.orm.silent.call(
|
||||
"discuss.channel",
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
* To by-pass SCSS min() shadowing CSS min(), we rely on SCSS being case-sensitive while CSS isn't.
|
||||
*/
|
||||
max-width: Min(400px, 95vw);
|
||||
max-height: Min(500px, 95vh);
|
||||
}
|
||||
|
||||
.o-mail-Follower-avatar {
|
||||
|
||||
@@ -63,10 +63,7 @@ export class ChannelSelector extends Component {
|
||||
);
|
||||
useEffect(
|
||||
() => {
|
||||
this.state.navigableListProps.isLoading = true;
|
||||
this.fetchSuggestions().then(
|
||||
() => (this.state.navigableListProps.isLoading = false)
|
||||
);
|
||||
this.fetchSuggestions();
|
||||
},
|
||||
() => [this.state.value]
|
||||
);
|
||||
@@ -81,11 +78,14 @@ export class ChannelSelector extends Component {
|
||||
["name", "ilike", cleanedTerm],
|
||||
];
|
||||
const fields = ["name"];
|
||||
const results = await this.sequential(() =>
|
||||
this.orm.searchRead("discuss.channel", domain, fields, {
|
||||
const results = await this.sequential(async () => {
|
||||
this.state.navigableListProps.isLoading = true;
|
||||
const res = await this.orm.searchRead("discuss.channel", domain, fields, {
|
||||
limit: 10,
|
||||
})
|
||||
);
|
||||
});
|
||||
this.state.navigableListProps.isLoading = false;
|
||||
return res;
|
||||
});
|
||||
if (!results) {
|
||||
this.state.navigableListProps.options = [];
|
||||
return;
|
||||
@@ -106,13 +106,16 @@ export class ChannelSelector extends Component {
|
||||
return;
|
||||
}
|
||||
if (this.props.category.id === "chats") {
|
||||
const results = await this.sequential(() =>
|
||||
this.orm.call("res.partner", "im_search", [
|
||||
const results = await this.sequential(async () => {
|
||||
this.state.navigableListProps.isLoading = true;
|
||||
const res = await this.orm.call("res.partner", "im_search", [
|
||||
cleanedTerm,
|
||||
10,
|
||||
this.state.selectedPartners,
|
||||
])
|
||||
);
|
||||
]);
|
||||
this.state.navigableListProps.isLoading = false;
|
||||
return res;
|
||||
});
|
||||
if (!results) {
|
||||
this.state.navigableListProps.options = [];
|
||||
return;
|
||||
|
||||
@@ -8,9 +8,9 @@ patch(Composer.prototype, {
|
||||
get placeholder() {
|
||||
if (this.thread && this.thread.model !== "discuss.channel") {
|
||||
if (this.props.type === "message") {
|
||||
return _t("Send a message to followers...");
|
||||
return _t("Send a message to followers…");
|
||||
} else {
|
||||
return _t("Log an internal note...");
|
||||
return _t("Log an internal note…");
|
||||
}
|
||||
}
|
||||
return super.placeholder;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { nextTick, patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
import { makeDeferred, patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("activity mark as done popover");
|
||||
|
||||
QUnit.test("activity mark done popover simplest layout", async (assert) => {
|
||||
QUnit.test("activity mark done popover simplest layout", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
pyEnv["mail.activity"].create({
|
||||
@@ -16,23 +16,20 @@ QUnit.test("activity mark done popover simplest layout", async (assert) => {
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
await click(".btn:contains('Mark Done')");
|
||||
assert.containsOnce($, ".o-mail-ActivityMarkAsDone");
|
||||
assert.containsOnce($, ".o-mail-ActivityMarkAsDone textarea[placeholder='Write Feedback']");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o-mail-ActivityMarkAsDone button[aria-label='Done and Schedule Next']"
|
||||
);
|
||||
assert.containsOnce($, ".o-mail-ActivityMarkAsDone button[aria-label='Done']");
|
||||
assert.containsOnce($, ".o-mail-ActivityMarkAsDone button:contains(Discard)");
|
||||
await contains(".o-mail-ActivityMarkAsDone");
|
||||
await contains(".o-mail-ActivityMarkAsDone textarea[placeholder='Write Feedback']");
|
||||
await contains(".o-mail-ActivityMarkAsDone button[aria-label='Done and Schedule Next']");
|
||||
await contains(".o-mail-ActivityMarkAsDone button[aria-label='Done']");
|
||||
await contains(".o-mail-ActivityMarkAsDone button:contains(Discard)");
|
||||
});
|
||||
|
||||
QUnit.test("activity with force next mark done popover simplest layout", async (assert) => {
|
||||
QUnit.test("activity with force next mark done popover simplest layout", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
pyEnv["mail.activity"].create({
|
||||
@@ -43,20 +40,17 @@ QUnit.test("activity with force next mark done popover simplest layout", async (
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
await click(".btn:contains('Mark Done')");
|
||||
assert.containsOnce($, ".o-mail-ActivityMarkAsDone");
|
||||
assert.containsOnce($, ".o-mail-ActivityMarkAsDone textarea[placeholder='Write Feedback']");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o-mail-ActivityMarkAsDone button[aria-label='Done and Schedule Next']"
|
||||
);
|
||||
assert.containsNone($, ".o-mail-ActivityMarkAsDone button[aria-label='Done']");
|
||||
assert.containsOnce($, ".o-mail-ActivityMarkAsDone button:contains(Discard)");
|
||||
await contains(".o-mail-ActivityMarkAsDone");
|
||||
await contains(".o-mail-ActivityMarkAsDone textarea[placeholder='Write Feedback']");
|
||||
await contains(".o-mail-ActivityMarkAsDone button[aria-label='Done and Schedule Next']");
|
||||
await contains(".o-mail-ActivityMarkAsDone button[aria-label='Done']", 0);
|
||||
await contains(".o-mail-ActivityMarkAsDone button:contains(Discard)");
|
||||
});
|
||||
|
||||
QUnit.test("activity mark done popover mark done without feedback", async (assert) => {
|
||||
@@ -127,17 +121,16 @@ QUnit.test("activity mark done popover mark done with feedback", async (assert)
|
||||
}
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
await click(".btn:contains('Mark Done')");
|
||||
insertText(
|
||||
await insertText(
|
||||
".o-mail-ActivityMarkAsDone textarea[placeholder='Write Feedback']",
|
||||
"This task is done"
|
||||
).catch(() => {}); // no render
|
||||
await nextTick();
|
||||
);
|
||||
await click(".o-mail-ActivityMarkAsDone button[aria-label='Done']");
|
||||
assert.verifySteps(["action_feedback"]);
|
||||
});
|
||||
@@ -169,7 +162,7 @@ QUnit.test("activity mark done popover mark done and schedule next", async (asse
|
||||
}
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
@@ -183,11 +176,10 @@ QUnit.test("activity mark done popover mark done and schedule next", async (asse
|
||||
},
|
||||
});
|
||||
await click(".btn:contains('Mark Done')");
|
||||
insertText(
|
||||
await insertText(
|
||||
".o-mail-ActivityMarkAsDone textarea[placeholder='Write Feedback']",
|
||||
"This task is done"
|
||||
).catch(() => {}); // no render
|
||||
await nextTick();
|
||||
);
|
||||
await click(".o-mail-ActivityMarkAsDone button[aria-label='Done and Schedule Next']");
|
||||
assert.verifySteps(["action_feedback_schedule_next"]);
|
||||
});
|
||||
@@ -208,13 +200,15 @@ QUnit.test("[technical] activity mark done & schedule next with new action", asy
|
||||
}
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
const def = makeDeferred();
|
||||
patchWithCleanup(env.services.action, {
|
||||
doAction(action) {
|
||||
def.resolve();
|
||||
assert.step("activity_action");
|
||||
assert.deepEqual(
|
||||
action,
|
||||
@@ -225,5 +219,6 @@ QUnit.test("[technical] activity mark done & schedule next with new action", asy
|
||||
});
|
||||
await click(".btn:contains('Mark Done')");
|
||||
await click(".o-mail-ActivityMarkAsDone button[aria-label='Done and Schedule Next']");
|
||||
await def;
|
||||
assert.verifySteps(["activity_action"]);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
QUnit.module("activity menu");
|
||||
|
||||
@@ -14,5 +14,6 @@ QUnit.test("should update activities when opening the activity menu", async (ass
|
||||
res_model: "res.partner",
|
||||
});
|
||||
await click(".o_menu_systray i[aria-label='Activities']");
|
||||
await contains(".o-mail-ActivityMenu-counter:contains(1)");
|
||||
assert.strictEqual($(".o-mail-ActivityMenu-counter").text(), "1");
|
||||
});
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import {
|
||||
afterNextRender,
|
||||
click,
|
||||
contains,
|
||||
createFile,
|
||||
start,
|
||||
startServer,
|
||||
} from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, createFile, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { date_to_str } from "@web/legacy/js/core/time";
|
||||
import {
|
||||
@@ -33,7 +26,7 @@ const views = {
|
||||
|
||||
QUnit.module("activity");
|
||||
|
||||
QUnit.test("activity upload document is available", async (assert) => {
|
||||
QUnit.test("activity upload document is available", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const [activityTypeId] = pyEnv["mail.activity.type"].search([["name", "=", "Upload Document"]]);
|
||||
@@ -44,18 +37,14 @@ QUnit.test("activity upload document is available", async (assert) => {
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Activity-info:contains('Upload Document')");
|
||||
assert.containsOnce($, ".btn .fa-upload");
|
||||
assert.containsOnce($, ".o-mail-Activity .o_input_file");
|
||||
const { openFormView } = await start();
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Activity-info:contains('Upload Document')");
|
||||
await contains(".btn .fa-upload");
|
||||
await contains(".o-mail-Activity .o_input_file");
|
||||
});
|
||||
|
||||
QUnit.test("activity can upload a document", async (assert) => {
|
||||
QUnit.test("activity can upload a document", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const fakeId = pyEnv["res.partner"].create({});
|
||||
const [activityTypeId] = pyEnv["mail.activity.type"].search([["name", "=", "Upload Document"]]);
|
||||
@@ -67,42 +56,38 @@ QUnit.test("activity can upload a document", async (assert) => {
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { openFormView } = await start({ serverData: { views } });
|
||||
await openFormView("res.partner", fakeId);
|
||||
openFormView("res.partner", fakeId);
|
||||
const file = await createFile({
|
||||
content: "hello, world",
|
||||
contentType: "text/plain",
|
||||
name: "text.txt",
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Activity-info:contains('Upload Document')");
|
||||
await contains(".o-mail-Activity-info:contains('Upload Document')");
|
||||
inputFiles($(".o-mail-Activity .o_input_file")[0], [file]);
|
||||
await contains(".o-mail-Activity-info:contains('Upload Document')", 0);
|
||||
await contains("button[aria-label='Attach files']:contains(1)");
|
||||
});
|
||||
|
||||
QUnit.test("activity simplest layout", async (assert) => {
|
||||
QUnit.test("activity simplest layout", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
pyEnv["mail.activity"].create({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Activity");
|
||||
assert.containsOnce($, ".o-mail-Activity-sidebar");
|
||||
assert.containsOnce($, ".o-mail-Activity-user");
|
||||
assert.containsOnce($, ".o-mail-Activity-info");
|
||||
assert.containsNone($, ".o-mail-Activity-note");
|
||||
assert.containsNone($, ".o-mail-Activity-details");
|
||||
assert.containsNone($, ".o-mail-Activity-mailTemplates");
|
||||
assert.containsNone($, ".btn:contains('Edit')");
|
||||
assert.containsNone($, ".o-mail-Activity span:contains(Cancel)");
|
||||
assert.containsNone($, ".btn:contains('Mark Done')");
|
||||
assert.containsNone($, ".o-mail-Activity-info:contains('Upload Document')");
|
||||
const { openFormView } = await start();
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Activity");
|
||||
await contains(".o-mail-Activity-sidebar");
|
||||
await contains(".o-mail-Activity-user");
|
||||
await contains(".o-mail-Activity-info");
|
||||
await contains(".o-mail-Activity-note", 0);
|
||||
await contains(".o-mail-Activity-details", 0);
|
||||
await contains(".o-mail-Activity-mailTemplates", 0);
|
||||
await contains(".btn:contains('Edit')", 0);
|
||||
await contains(".o-mail-Activity span:contains(Cancel)", 0);
|
||||
await contains(".btn:contains('Mark Done')", 0);
|
||||
await contains(".o-mail-Activity-info:contains('Upload Document')", 0);
|
||||
});
|
||||
|
||||
QUnit.test("activity with note layout", async (assert) => {
|
||||
@@ -113,18 +98,14 @@ QUnit.test("activity with note layout", async (assert) => {
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Activity");
|
||||
assert.containsOnce($, ".o-mail-Activity-note");
|
||||
const { openFormView } = await start();
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Activity");
|
||||
await contains(".o-mail-Activity-note");
|
||||
assert.strictEqual($(".o-mail-Activity-note").text(), "There is no good or bad note");
|
||||
});
|
||||
|
||||
QUnit.test("activity info layout when planned after tomorrow", async (assert) => {
|
||||
QUnit.test("activity info layout when planned after tomorrow", async () => {
|
||||
patchDate(2023, 0, 11, 12, 0, 0);
|
||||
const today = new Date();
|
||||
const fiveDaysFromNow = new Date();
|
||||
@@ -137,18 +118,14 @@ QUnit.test("activity info layout when planned after tomorrow", async (assert) =>
|
||||
res_model: "res.partner",
|
||||
state: "planned",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Activity");
|
||||
assert.containsOnce($, ".o-mail-Activity .text-success");
|
||||
assert.containsOnce($, ".o-mail-Activity:contains('Due in 5 days:')");
|
||||
const { openFormView } = await start();
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Activity");
|
||||
await contains(".o-mail-Activity .text-success");
|
||||
await contains(".o-mail-Activity:contains('Due in 5 days:')");
|
||||
});
|
||||
|
||||
QUnit.test("activity info layout when planned tomorrow", async (assert) => {
|
||||
QUnit.test("activity info layout when planned tomorrow", async () => {
|
||||
patchDate(2023, 0, 11, 12, 0, 0);
|
||||
const today = new Date();
|
||||
const tomorrow = new Date();
|
||||
@@ -161,18 +138,14 @@ QUnit.test("activity info layout when planned tomorrow", async (assert) => {
|
||||
res_model: "res.partner",
|
||||
state: "planned",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Activity");
|
||||
assert.containsOnce($, ".o-mail-Activity .text-success");
|
||||
assert.containsOnce($, ".o-mail-Activity:contains('Tomorrow:')");
|
||||
const { openFormView } = await start();
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Activity");
|
||||
await contains(".o-mail-Activity .text-success");
|
||||
await contains(".o-mail-Activity:contains('Tomorrow:')");
|
||||
});
|
||||
|
||||
QUnit.test("activity info layout when planned today", async (assert) => {
|
||||
QUnit.test("activity info layout when planned today", async () => {
|
||||
patchDate(2023, 0, 11, 12, 0, 0);
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
@@ -182,18 +155,14 @@ QUnit.test("activity info layout when planned today", async (assert) => {
|
||||
res_model: "res.partner",
|
||||
state: "today",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Activity");
|
||||
assert.containsOnce($, ".o-mail-Activity .text-warning");
|
||||
assert.containsOnce($, ".o-mail-Activity:contains('Today:')");
|
||||
const { openFormView } = await start();
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Activity");
|
||||
await contains(".o-mail-Activity .text-warning");
|
||||
await contains(".o-mail-Activity:contains('Today:')");
|
||||
});
|
||||
|
||||
QUnit.test("activity info layout when planned yesterday", async (assert) => {
|
||||
QUnit.test("activity info layout when planned yesterday", async () => {
|
||||
patchDate(2023, 0, 11, 12, 0, 0);
|
||||
const today = new Date();
|
||||
const yesterday = new Date();
|
||||
@@ -206,18 +175,14 @@ QUnit.test("activity info layout when planned yesterday", async (assert) => {
|
||||
res_model: "res.partner",
|
||||
state: "overdue",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Activity");
|
||||
assert.containsOnce($, ".o-mail-Activity .text-danger");
|
||||
assert.containsOnce($, ".o-mail-Activity:contains('Yesterday:')");
|
||||
const { openFormView } = await start();
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Activity");
|
||||
await contains(".o-mail-Activity .text-danger");
|
||||
await contains(".o-mail-Activity:contains('Yesterday:')");
|
||||
});
|
||||
|
||||
QUnit.test("activity info layout when planned before yesterday", async (assert) => {
|
||||
QUnit.test("activity info layout when planned before yesterday", async () => {
|
||||
patchDate(2023, 0, 11, 12, 0, 0);
|
||||
const today = new Date();
|
||||
const fiveDaysBeforeNow = new Date();
|
||||
@@ -230,15 +195,11 @@ QUnit.test("activity info layout when planned before yesterday", async (assert)
|
||||
res_model: "res.partner",
|
||||
state: "overdue",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Activity");
|
||||
assert.containsOnce($, ".o-mail-Activity .text-danger");
|
||||
assert.containsOnce($, ".o-mail-Activity:contains('5 days overdue:')");
|
||||
const { openFormView } = await start();
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Activity");
|
||||
await contains(".o-mail-Activity .text-danger");
|
||||
await contains(".o-mail-Activity:contains('5 days overdue:')");
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -246,7 +207,7 @@ QUnit.test("activity info layout when planned before yesterday", async (assert)
|
||||
* Pass locally or if triggered on runbot manually, but fail on ci build.
|
||||
* The hook/runbot environment might not support this test, so skipped for now.
|
||||
*/
|
||||
QUnit.skip("activity info layout change at midnight", async (assert) => {
|
||||
QUnit.skip("activity info layout change at midnight", async () => {
|
||||
const mock = mockTimeout();
|
||||
patchDate(2023, 11, 7, 23, 59, 59);
|
||||
const today = new Date();
|
||||
@@ -260,24 +221,20 @@ QUnit.skip("activity info layout change at midnight", async (assert) => {
|
||||
res_model: "res.partner",
|
||||
state: "planned",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Activity");
|
||||
assert.containsOnce($, ".o-mail-Activity .text-success");
|
||||
assert.containsOnce($, ".o-mail-Activity:contains('Tomorrow:')");
|
||||
const { openFormView } = await start();
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Activity");
|
||||
await contains(".o-mail-Activity .text-success");
|
||||
await contains(".o-mail-Activity:contains('Tomorrow:')");
|
||||
|
||||
patchDate(2023, 11, 8, 0, 0, 1); // OXP is coming!
|
||||
await mock.advanceTime(2000);
|
||||
assert.containsOnce($, ".o-mail-Activity");
|
||||
assert.containsOnce($, ".o-mail-Activity .text-warning");
|
||||
assert.containsOnce($, ".o-mail-Activity:contains('Today:')");
|
||||
await contains(".o-mail-Activity");
|
||||
await contains(".o-mail-Activity .text-warning");
|
||||
await contains(".o-mail-Activity:contains('Today:')");
|
||||
});
|
||||
|
||||
QUnit.test("activity with a summary layout", async (assert) => {
|
||||
QUnit.test("activity with a summary layout", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
pyEnv["mail.activity"].create({
|
||||
@@ -285,16 +242,12 @@ QUnit.test("activity with a summary layout", async (assert) => {
|
||||
res_model: "res.partner",
|
||||
summary: "test summary",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Activity-info:contains('test summary')");
|
||||
const { openFormView } = await start();
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Activity-info:contains('test summary')");
|
||||
});
|
||||
|
||||
QUnit.test("activity without summary layout", async (assert) => {
|
||||
QUnit.test("activity without summary layout", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
pyEnv["mail.activity"].create({
|
||||
@@ -302,16 +255,12 @@ QUnit.test("activity without summary layout", async (assert) => {
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Activity-info:contains('Email')");
|
||||
const { openFormView } = await start();
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Activity-info:contains('Email')");
|
||||
});
|
||||
|
||||
QUnit.test("activity details toggle", async (assert) => {
|
||||
QUnit.test("activity details toggle", async () => {
|
||||
patchDate(2023, 0, 11, 12, 0, 0);
|
||||
const today = new Date();
|
||||
const tomorrow = new Date();
|
||||
@@ -326,21 +275,17 @@ QUnit.test("activity details toggle", async (assert) => {
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Activity");
|
||||
assert.containsNone($, ".o-mail-Activity-details");
|
||||
assert.containsOnce($, ".o-mail-Activity-info i[aria-label='Info']");
|
||||
const { openFormView } = await start();
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Activity");
|
||||
await contains(".o-mail-Activity-details", 0);
|
||||
await contains(".o-mail-Activity-info i[aria-label='Info']");
|
||||
|
||||
await click(".o-mail-Activity-info i[aria-label='Info']");
|
||||
assert.containsOnce($, ".o-mail-Activity-details");
|
||||
await contains(".o-mail-Activity-details");
|
||||
|
||||
await click(".o-mail-Activity-info i[aria-label='Info']");
|
||||
assert.containsNone($, ".o-mail-Activity-details");
|
||||
await contains(".o-mail-Activity-details", 0);
|
||||
});
|
||||
|
||||
QUnit.test("activity with mail template layout", async (assert) => {
|
||||
@@ -354,19 +299,15 @@ QUnit.test("activity with mail template layout", async (assert) => {
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Activity");
|
||||
assert.containsOnce($, ".o-mail-Activity-sidebar");
|
||||
assert.containsOnce($, ".o-mail-Activity-mailTemplates");
|
||||
assert.containsOnce($, ".o-mail-ActivityMailTemplate-name");
|
||||
const { openFormView } = await start();
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Activity");
|
||||
await contains(".o-mail-Activity-sidebar");
|
||||
await contains(".o-mail-Activity-mailTemplates");
|
||||
await contains(".o-mail-ActivityMailTemplate-name:contains(Dummy mail template)");
|
||||
assert.strictEqual($(".o-mail-ActivityMailTemplate-name").text(), "Dummy mail template");
|
||||
assert.containsOnce($, ".o-mail-ActivityMailTemplate-preview");
|
||||
assert.containsOnce($, ".o-mail-ActivityMailTemplate-send");
|
||||
await contains(".o-mail-ActivityMailTemplate-preview");
|
||||
await contains(".o-mail-ActivityMailTemplate-send");
|
||||
});
|
||||
|
||||
QUnit.test("activity with mail template: preview mail", async (assert) => {
|
||||
@@ -380,12 +321,8 @@ QUnit.test("activity with mail template: preview mail", async (assert) => {
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { env, openView } = await start();
|
||||
await openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
const { env, openFormView } = await start();
|
||||
openFormView("res.partner", partnerId);
|
||||
patchWithCleanup(env.services.action, {
|
||||
doAction(action) {
|
||||
assert.step("do_action");
|
||||
@@ -396,10 +333,10 @@ QUnit.test("activity with mail template: preview mail", async (assert) => {
|
||||
assert.strictEqual(action.res_model, "mail.compose.message");
|
||||
},
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Activity");
|
||||
assert.containsOnce($, ".o-mail-ActivityMailTemplate-preview");
|
||||
await contains(".o-mail-Activity");
|
||||
await contains(".o-mail-ActivityMailTemplate-preview");
|
||||
|
||||
$(".o-mail-ActivityMailTemplate-preview")[0].click();
|
||||
await click(".o-mail-ActivityMailTemplate-preview");
|
||||
assert.verifySteps(["do_action"]);
|
||||
});
|
||||
|
||||
@@ -414,7 +351,7 @@ QUnit.test("activity with mail template: send mail", async (assert) => {
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { openView } = await start({
|
||||
const { openFormView } = await start({
|
||||
async mockRPC(route, args) {
|
||||
if (args.method === "activity_send_mail") {
|
||||
assert.step("activity_send_mail");
|
||||
@@ -426,19 +363,15 @@ QUnit.test("activity with mail template: send mail", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Activity");
|
||||
assert.containsOnce($, ".o-mail-ActivityMailTemplate-send");
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Activity");
|
||||
await contains(".o-mail-ActivityMailTemplate-send");
|
||||
|
||||
click(".o-mail-ActivityMailTemplate-send").catch(() => {});
|
||||
await click(".o-mail-ActivityMailTemplate-send");
|
||||
assert.verifySteps(["activity_send_mail"]);
|
||||
});
|
||||
|
||||
QUnit.test("activity click on mark as done", async (assert) => {
|
||||
QUnit.test("activity click on mark as done", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const activityTypeId = pyEnv["mail.activity.type"].search([["name", "=", "Email"]])[0];
|
||||
@@ -449,20 +382,16 @@ QUnit.test("activity click on mark as done", async (assert) => {
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Activity");
|
||||
assert.containsOnce($, ".btn:contains('Mark Done')");
|
||||
const { openFormView } = await start();
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Activity");
|
||||
await contains(".btn:contains('Mark Done')");
|
||||
|
||||
await click(".btn:contains('Mark Done')");
|
||||
assert.containsOnce($, ".o-mail-ActivityMarkAsDone");
|
||||
await contains(".o-mail-ActivityMarkAsDone");
|
||||
|
||||
await click(".btn:contains('Mark Done')");
|
||||
assert.containsNone($, ".o-mail-ActivityMarkAsDone");
|
||||
await contains(".o-mail-ActivityMarkAsDone", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
@@ -478,18 +407,16 @@ QUnit.test(
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Activity");
|
||||
assert.containsOnce($, ".btn:contains('Mark Done')");
|
||||
const { openFormView } = await start();
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Activity");
|
||||
await contains(".btn:contains('Mark Done')");
|
||||
|
||||
await click(".btn:contains('Mark Done')");
|
||||
assert.strictEqual(
|
||||
$(".o-mail-ActivityMarkAsDone textarea[placeholder='Write Feedback']")[0],
|
||||
(
|
||||
await contains(".o-mail-ActivityMarkAsDone textarea[placeholder='Write Feedback']")
|
||||
)[0],
|
||||
document.activeElement
|
||||
);
|
||||
}
|
||||
@@ -507,12 +434,8 @@ QUnit.test("activity click on edit", async (assert) => {
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { env, openView } = await start();
|
||||
await openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
const { env, openFormView } = await start();
|
||||
openFormView("res.partner", partnerId);
|
||||
patchWithCleanup(env.services.action, {
|
||||
doAction(action) {
|
||||
assert.step("do_action");
|
||||
@@ -524,10 +447,7 @@ QUnit.test("activity click on edit", async (assert) => {
|
||||
return super.doAction(...arguments);
|
||||
},
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Activity");
|
||||
assert.containsOnce($, ".btn:contains('Edit')");
|
||||
|
||||
await click(".btn:contains('Edit')");
|
||||
await click(".o-mail-Activity .btn:contains('Edit')");
|
||||
assert.verifySteps(["do_action"]);
|
||||
});
|
||||
|
||||
@@ -541,7 +461,7 @@ QUnit.test("activity click on cancel", async (assert) => {
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { openView } = await start({
|
||||
const { openFormView } = await start({
|
||||
async mockRPC(route, args) {
|
||||
if (route === "/web/dataset/call_kw/mail.activity/unlink") {
|
||||
assert.step("unlink");
|
||||
@@ -550,20 +470,13 @@ QUnit.test("activity click on cancel", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Activity");
|
||||
assert.containsOnce($, ".o-mail-Activity span:contains(Cancel)");
|
||||
|
||||
openFormView("res.partner", partnerId);
|
||||
await click(".o-mail-Activity span:contains(Cancel)");
|
||||
await contains(".o-mail-Activity", 0);
|
||||
assert.verifySteps(["unlink"]);
|
||||
assert.containsNone($, ".o-mail-Activity");
|
||||
});
|
||||
|
||||
QUnit.test("activity mark done popover close on ESCAPE", async (assert) => {
|
||||
QUnit.test("activity mark done popover close on ESCAPE", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const activityTypeId = pyEnv["mail.activity.type"].search([["name", "=", "Email"]])[0];
|
||||
@@ -574,21 +487,17 @@ QUnit.test("activity mark done popover close on ESCAPE", async (assert) => {
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
const { openFormView } = await start();
|
||||
openFormView("res.partner", partnerId);
|
||||
|
||||
await click(".btn:contains('Mark Done')");
|
||||
assert.containsOnce($, ".o-mail-ActivityMarkAsDone");
|
||||
await contains(".o-mail-ActivityMarkAsDone");
|
||||
|
||||
await afterNextRender(() => triggerHotkey("Escape"));
|
||||
assert.containsNone($, ".o-mail-ActivityMarkAsDone");
|
||||
triggerHotkey("Escape");
|
||||
await contains(".o-mail-ActivityMarkAsDone", 0);
|
||||
});
|
||||
|
||||
QUnit.test("activity mark done popover click on discard", async (assert) => {
|
||||
QUnit.test("activity mark done popover click on discard", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const activityTypeId = pyEnv["mail.activity.type"].search([["name", "=", "Email"]])[0];
|
||||
@@ -599,21 +508,15 @@ QUnit.test("activity mark done popover click on discard", async (assert) => {
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
const { openFormView } = await start();
|
||||
openFormView("res.partner", partnerId);
|
||||
|
||||
await click(".btn:contains('Mark Done')");
|
||||
assert.containsOnce($, ".o-mail-ActivityMarkAsDone");
|
||||
assert.containsOnce($, ".o-mail-ActivityMarkAsDone button:contains(Discard)");
|
||||
await click(".o-mail-ActivityMarkAsDone button:contains(Discard)");
|
||||
assert.containsNone($, ".o-mail-ActivityMarkAsDone");
|
||||
await contains(".o-mail-ActivityMarkAsDone", 0);
|
||||
});
|
||||
|
||||
QUnit.test("Activity are sorted by deadline", async (assert) => {
|
||||
QUnit.test("Activity are sorted by deadline", async () => {
|
||||
patchDate(2023, 0, 11, 12, 0, 0);
|
||||
const today = new Date();
|
||||
const dateBefore = new Date();
|
||||
@@ -641,8 +544,8 @@ QUnit.test("Activity are sorted by deadline", async (assert) => {
|
||||
state: "overdue",
|
||||
});
|
||||
const { openFormView } = await start();
|
||||
await openFormView("res.partner", partnerId);
|
||||
assert.containsOnce($, ".o-mail-Activity:eq(0):contains(5 days overdue:)");
|
||||
assert.containsOnce($, ".o-mail-Activity:eq(1):contains(Today:)");
|
||||
assert.containsOnce($, ".o-mail-Activity:eq(2):contains(Due in 4 days:)");
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Activity:eq(0):contains(5 days overdue:)");
|
||||
await contains(".o-mail-Activity:eq(1):contains(Today:)");
|
||||
await contains(".o-mail-Activity:eq(2):contains(Due in 4 days:)");
|
||||
});
|
||||
|
||||
@@ -13,7 +13,7 @@ QUnit.module("chat window manager");
|
||||
|
||||
QUnit.test("chat window does not fetch messages if hidden", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create([
|
||||
const [channeId1, channelId2, channelId3] = pyEnv["discuss.channel"].create([
|
||||
{
|
||||
channel_member_ids: [
|
||||
Command.create({ is_minimized: true, partner_id: pyEnv.currentPartnerId }),
|
||||
@@ -30,6 +30,26 @@ QUnit.test("chat window does not fetch messages if hidden", async (assert) => {
|
||||
],
|
||||
},
|
||||
]);
|
||||
pyEnv["mail.message"].create([
|
||||
{
|
||||
body: "Orange",
|
||||
res_id: channeId1,
|
||||
message_type: "comment",
|
||||
model: "discuss.channel",
|
||||
},
|
||||
{
|
||||
body: "Apple",
|
||||
res_id: channelId2,
|
||||
message_type: "comment",
|
||||
model: "discuss.channel",
|
||||
},
|
||||
{
|
||||
body: "Banana",
|
||||
res_id: channelId3,
|
||||
message_type: "comment",
|
||||
model: "discuss.channel",
|
||||
},
|
||||
]);
|
||||
patchUiSize({ width: 900 });
|
||||
assert.ok(
|
||||
CHAT_WINDOW_END_GAP_WIDTH * 2 + CHAT_WINDOW_WIDTH * 2 + CHAT_WINDOW_INBETWEEN_WIDTH < 900
|
||||
@@ -45,14 +65,17 @@ QUnit.test("chat window does not fetch messages if hidden", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
assert.containsN($, ".o-mail-ChatWindow", 2);
|
||||
assert.containsOnce($, ".o-mail-ChatWindowHiddenToggler");
|
||||
await contains(".o-mail-ChatWindow", 2);
|
||||
await contains(".o-mail-ChatWindowHiddenToggler");
|
||||
await contains(".o-mail-Message:contains(Orange)");
|
||||
await contains(".o-mail-Message:contains(Apple)", 0);
|
||||
await contains(".o-mail-Message:contains(Banana)");
|
||||
assert.verifySteps(["fetch_messages", "fetch_messages"]);
|
||||
});
|
||||
|
||||
QUnit.test("click on hidden chat window should fetch its messages", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create([
|
||||
const [channeId1, channelId2, channelId3] = pyEnv["discuss.channel"].create([
|
||||
{
|
||||
channel_member_ids: [
|
||||
Command.create({ is_minimized: true, partner_id: pyEnv.currentPartnerId }),
|
||||
@@ -69,6 +92,26 @@ QUnit.test("click on hidden chat window should fetch its messages", async (asser
|
||||
],
|
||||
},
|
||||
]);
|
||||
pyEnv["mail.message"].create([
|
||||
{
|
||||
body: "Orange",
|
||||
res_id: channeId1,
|
||||
message_type: "comment",
|
||||
model: "discuss.channel",
|
||||
},
|
||||
{
|
||||
body: "Apple",
|
||||
res_id: channelId2,
|
||||
message_type: "comment",
|
||||
model: "discuss.channel",
|
||||
},
|
||||
{
|
||||
body: "Banana",
|
||||
res_id: channelId3,
|
||||
message_type: "comment",
|
||||
model: "discuss.channel",
|
||||
},
|
||||
]);
|
||||
patchUiSize({ width: 900 });
|
||||
assert.ok(
|
||||
CHAT_WINDOW_END_GAP_WIDTH * 2 + CHAT_WINDOW_WIDTH * 2 + CHAT_WINDOW_INBETWEEN_WIDTH < 900
|
||||
@@ -84,11 +127,17 @@ QUnit.test("click on hidden chat window should fetch its messages", async (asser
|
||||
}
|
||||
},
|
||||
});
|
||||
assert.containsN($, ".o-mail-ChatWindow", 2);
|
||||
assert.containsOnce($, ".o-mail-ChatWindowHiddenToggler");
|
||||
await contains(".o-mail-ChatWindow", 2);
|
||||
await contains(".o-mail-ChatWindowHiddenToggler");
|
||||
await contains(".o-mail-Message:contains(Orange)");
|
||||
await contains(".o-mail-Message:contains(Apple)", 0);
|
||||
await contains(".o-mail-Message:contains(Banana)");
|
||||
assert.verifySteps(["fetch_messages", "fetch_messages"]);
|
||||
await click(".o-mail-ChatWindowHiddenToggler");
|
||||
await click(".o-mail-ChatWindowHiddenMenu-item .o-mail-ChatWindow-command[title='Open']");
|
||||
await contains(".o-mail-Message:contains(Orange)");
|
||||
await contains(".o-mail-Message:contains(Apple)");
|
||||
await contains(".o-mail-Message:contains(Banana)", 0);
|
||||
assert.verifySteps(["fetch_messages"]);
|
||||
});
|
||||
|
||||
@@ -125,14 +174,14 @@ QUnit.test(
|
||||
await contains(
|
||||
".o-mail-ChatWindow-header:contains(channel-D) .o-mail-ChatWindow-command[title='Close Chat Window']"
|
||||
);
|
||||
assert.containsN($, ".o-mail-ChatWindow", 2);
|
||||
assert.containsOnce($, ".o-mail-ChatWindow:eq(0):contains(channel-A)");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow:eq(1):contains(channel-D)");
|
||||
assert.containsOnce($, ".o-mail-ChatWindowHiddenToggler:contains(2)");
|
||||
await contains(".o-mail-ChatWindow", 2);
|
||||
await contains(".o-mail-ChatWindow:eq(0):contains(channel-A)");
|
||||
await contains(".o-mail-ChatWindow:eq(1):contains(channel-D)");
|
||||
await contains(".o-mail-ChatWindowHiddenToggler:contains(2)");
|
||||
await click(
|
||||
".o-mail-ChatWindow-header:contains(channel-D) .o-mail-ChatWindow-command[title='Close Chat Window']"
|
||||
);
|
||||
assert.containsOnce($, ".o-mail-ChatWindow:eq(0):contains(channel-A)");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow:eq(1):contains(channel-C)");
|
||||
await contains(".o-mail-ChatWindow:eq(0):contains(channel-A)");
|
||||
await contains(".o-mail-ChatWindow:eq(1):contains(channel-C)");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
startServer,
|
||||
} from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { nextTick, triggerEvent, triggerHotkey } from "@web/../tests/helpers/utils";
|
||||
import { triggerHotkey } from "@web/../tests/helpers/utils";
|
||||
import { file } from "@web/../tests/legacy/helpers/test_utils";
|
||||
|
||||
const { inputFiles } = file;
|
||||
@@ -28,7 +28,7 @@ QUnit.module("chat window");
|
||||
|
||||
QUnit.test(
|
||||
"Mobile: chat window shouldn't open automatically after receiving a new message",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo" });
|
||||
const userId = pyEnv["res.users"].create({ partner_id: partnerId });
|
||||
@@ -41,7 +41,8 @@ QUnit.test(
|
||||
});
|
||||
patchUiSize({ size: SIZES.SM });
|
||||
const { env } = await start();
|
||||
|
||||
await contains(".o_menu_systray i[aria-label='Messages']");
|
||||
await contains(".o-mail-MessagingMenu-counter", 0);
|
||||
// simulate receiving a message
|
||||
pyEnv.withUser(userId, () =>
|
||||
env.services.rpc("/mail/message/post", {
|
||||
@@ -50,14 +51,14 @@ QUnit.test(
|
||||
thread_model: "discuss.channel",
|
||||
})
|
||||
);
|
||||
await nextAnimationFrame();
|
||||
assert.containsNone($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-MessagingMenu-counter:contains(1)");
|
||||
await contains(".o-mail-ChatWindow", 0);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
'chat window: post message on channel with "CTRL-Enter" keyboard shortcut for small screen size',
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
@@ -69,8 +70,8 @@ QUnit.test(
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
await insertText(".o-mail-ChatWindow .o-mail-Composer-input", "Test");
|
||||
await afterNextRender(() => triggerHotkey("control+Enter"));
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
triggerHotkey("control+Enter");
|
||||
await contains(".o-mail-Message");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -94,26 +95,19 @@ QUnit.test("Message post in chat window of chatter should log a note", async (as
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o-mail-Message:contains(A needaction message to have it in messaging menu)"
|
||||
);
|
||||
assert.containsOnce(
|
||||
$(".o-mail-Message:contains(A needaction message to have it in messaging menu)"),
|
||||
".o-mail-Message-bubble.border" // bordered bubble = "Send message" mode
|
||||
);
|
||||
assert.containsOnce($, ".o-mail-Composer [placeholder='Log an internal note...']");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await contains(".o-mail-Message:contains(A needaction message to have it in messaging menu)");
|
||||
await contains(
|
||||
".o-mail-Message:contains(A needaction message to have it in messaging menu) .o-mail-Message-bubble.border"
|
||||
); // bordered bubble = "Send message" mode
|
||||
await contains(".o-mail-Composer [placeholder='Log an internal note…']");
|
||||
await insertText(".o-mail-ChatWindow .o-mail-Composer-input", "Test");
|
||||
await afterNextRender(() => triggerHotkey("control+Enter"));
|
||||
assert.containsOnce($, ".o-mail-Message:contains(Test)");
|
||||
assert.containsNone(
|
||||
$(".o-mail-Message:contains(Test)"),
|
||||
".o-mail-Message-bubble.border" // non-bordered bubble = "Log note" mode
|
||||
);
|
||||
triggerHotkey("control+Enter");
|
||||
await contains(".o-mail-Message:contains(Test)");
|
||||
await contains(".o-mail-Message:contains(Test) .o-mail-Message-bubble.border", 0); // non-bordered bubble = "Log note" mode
|
||||
});
|
||||
|
||||
QUnit.test("load messages from opening chat window from messaging menu", async (assert) => {
|
||||
QUnit.test("load messages from opening chat window from messaging menu", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_type: "channel",
|
||||
@@ -130,7 +124,7 @@ QUnit.test("load messages from opening chat window from messaging menu", async (
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
assert.containsN($, ".o-mail-Message", 21);
|
||||
await contains(".o-mail-Message", 21);
|
||||
});
|
||||
|
||||
QUnit.test("chat window: basic rendering", async (assert) => {
|
||||
@@ -139,45 +133,45 @@ QUnit.test("chat window: basic rendering", async (assert) => {
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-header");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow-header");
|
||||
assert.containsOnce($(".o-mail-ChatWindow-header"), ".o-mail-ChatWindow-threadAvatar");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-name:contains(General)");
|
||||
assert.containsN($, ".o-mail-ChatWindow-command", 4);
|
||||
assert.containsOnce($, "[title='Start a Call']");
|
||||
assert.containsOnce($, "[title='Open Actions Menu']");
|
||||
assert.containsOnce($, "[title='Fold']");
|
||||
assert.containsOnce($, "[title='Close Chat Window']");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-content .o-mail-Thread");
|
||||
await contains(".o-mail-ChatWindow-name:contains(General)");
|
||||
await contains(".o-mail-ChatWindow-command", 4);
|
||||
await contains("[title='Start a Call']");
|
||||
await contains("[title='Open Actions Menu']");
|
||||
await contains("[title='Fold']");
|
||||
await contains("[title='Close Chat Window']");
|
||||
await contains(".o-mail-ChatWindow-content .o-mail-Thread");
|
||||
assert.strictEqual(
|
||||
$(".o-mail-ChatWindow-content .o-mail-Thread").text().trim(),
|
||||
"There are no messages in this conversation."
|
||||
);
|
||||
await click("[title='Open Actions Menu']");
|
||||
assert.containsN($, ".o-mail-ChatWindow-command", 9);
|
||||
assert.containsOnce($, "[title='Pinned Messages']");
|
||||
assert.containsOnce($, "[title='Add Users']");
|
||||
assert.containsOnce($, "[title='Show Member List']");
|
||||
assert.containsOnce($, "[title='Show Call Settings']");
|
||||
assert.containsOnce($, "[title='Open in Discuss']");
|
||||
await contains(".o-mail-ChatWindow-command", 9);
|
||||
await contains("[title='Pinned Messages']");
|
||||
await contains("[title='Add Users']");
|
||||
await contains("[title='Show Member List']");
|
||||
await contains("[title='Show Call Settings']");
|
||||
await contains("[title='Open in Discuss']");
|
||||
});
|
||||
|
||||
QUnit.test("Fold state of chat window is sync among browser tabs", async (assert) => {
|
||||
QUnit.test("Fold state of chat window is sync among browser tabs", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const tab1 = await start({ asTab: true });
|
||||
const tab2 = await start({ asTab: true });
|
||||
await tab1.click(".o_menu_systray i[aria-label='Messages']");
|
||||
await tab1.click(".o-mail-NotificationItem");
|
||||
await tab1.click(".o-mail-ChatWindow-header"); // Fold
|
||||
assert.containsNone(tab1.target, ".o-mail-ChatWindow .o-mail-ChatWindow-content");
|
||||
assert.containsNone(tab2.target, ".o-mail-ChatWindow .o-mail-ChatWindow-content");
|
||||
await tab2.click(".o-mail-ChatWindow-header"); // Unfold
|
||||
assert.containsOnce(tab1.target, ".o-mail-ChatWindow .o-mail-ChatWindow-content");
|
||||
assert.containsOnce(tab2.target, ".o-mail-ChatWindow .o-mail-ChatWindow-content");
|
||||
await tab1.click("[title='Close Chat Window']");
|
||||
assert.containsNone(tab1.target, ".o-mail-ChatWindow");
|
||||
assert.containsNone(tab2.target, ".o-mail-ChatWindow");
|
||||
await click(".o_menu_systray i[aria-label='Messages']", { target: tab1.target });
|
||||
await click(".o-mail-NotificationItem", { target: tab1.target });
|
||||
await click(".o-mail-ChatWindow-header", { target: tab1.target }); // Fold
|
||||
await contains(".o-mail-ChatWindow .o-mail-ChatWindow-content", 0, { target: tab1.target });
|
||||
await contains(".o-mail-ChatWindow .o-mail-ChatWindow-content", 0, { target: tab2.target });
|
||||
await click(".o-mail-ChatWindow-header", { target: tab2.target }); // Unfold
|
||||
await contains(".o-mail-ChatWindow .o-mail-ChatWindow-content", 1, { target: tab1.target });
|
||||
await contains(".o-mail-ChatWindow .o-mail-ChatWindow-content", 1, { target: tab2.target });
|
||||
await click("[title='Close Chat Window']", { target: tab1.target });
|
||||
await contains(".o-mail-ChatWindow", 0, { target: tab1.target });
|
||||
await contains(".o-mail-ChatWindow", 0, { target: tab2.target });
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
@@ -193,6 +187,7 @@ QUnit.test(
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
await click(".o-mail-ChatWindow");
|
||||
const [member] = pyEnv["discuss.channel.member"].searchRead([
|
||||
["channel_id", "=", channelId],
|
||||
["partner_id", "=", pyEnv.currentPartnerId],
|
||||
@@ -214,18 +209,18 @@ QUnit.test("chat window: fold", async (assert) => {
|
||||
// Open Thread
|
||||
await click("button i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow .o-mail-Thread");
|
||||
await contains(".o-mail-ChatWindow .o-mail-Thread");
|
||||
assert.verifySteps(["rpc:channel_fold/open"]);
|
||||
|
||||
// Fold chat window
|
||||
await click(".o-mail-ChatWindow-command[title='Fold']");
|
||||
await contains(".o-mail-ChatWindow .o-mail-Thread", 0);
|
||||
assert.verifySteps(["rpc:channel_fold/folded"]);
|
||||
assert.containsNone($, ".o-mail-ChatWindow .o-mail-Thread");
|
||||
|
||||
// Unfold chat window
|
||||
await click(".o-mail-ChatWindow-command[title='Open']");
|
||||
await contains(".o-mail-ChatWindow .o-mail-Thread");
|
||||
assert.verifySteps(["rpc:channel_fold/open"]);
|
||||
assert.containsOnce($, ".o-mail-ChatWindow .o-mail-Thread");
|
||||
});
|
||||
|
||||
QUnit.test("chat window: open / close", async (assert) => {
|
||||
@@ -238,20 +233,20 @@ QUnit.test("chat window: open / close", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
assert.containsNone($, ".o-mail-ChatWindow");
|
||||
await click("button i[aria-label='Messages']");
|
||||
await contains(".o-mail-ChatWindow", 0);
|
||||
await click(".o-mail-NotificationItem");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
assert.verifySteps(["rpc:channel_fold/open"]);
|
||||
|
||||
await click(".o-mail-ChatWindow-command[title='Close Chat Window']");
|
||||
assert.containsNone($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow", 0);
|
||||
assert.verifySteps(["rpc:channel_fold/closed"]);
|
||||
|
||||
// Reopen chat window
|
||||
await click("button i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
assert.verifySteps(["rpc:channel_fold/open"]);
|
||||
});
|
||||
|
||||
@@ -263,7 +258,7 @@ QUnit.test("open chat on very narrow device should work", async (assert) => {
|
||||
assert.ok(CHAT_WINDOW_WIDTH > 200, "Device is narrower than usual chat window width"); // scenario where this might fail
|
||||
await click("button i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
@@ -279,9 +274,9 @@ QUnit.test(
|
||||
await start();
|
||||
await click("button i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await click("[title='Close Chat Window']");
|
||||
assert.containsNone($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow", 0);
|
||||
const [member] = pyEnv["discuss.channel.member"].searchRead([
|
||||
["channel_id", "=", channelId],
|
||||
["partner_id", "=", pyEnv.currentPartnerId],
|
||||
@@ -304,17 +299,17 @@ QUnit.test("chat window: close on ESCAPE", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
|
||||
$(".o-mail-Composer-input")[0].focus();
|
||||
await afterNextRender(() => triggerHotkey("Escape"));
|
||||
assert.containsNone($, ".o-mail-ChatWindow");
|
||||
triggerHotkey("Escape");
|
||||
await contains(".o-mail-ChatWindow", 0);
|
||||
assert.verifySteps(["rpc:channel_fold/closed"]);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"Close composer suggestions in chat window with ESCAPE does not also close the chat window",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({
|
||||
email: "testpartner@odoo.com",
|
||||
@@ -330,14 +325,15 @@ QUnit.test(
|
||||
});
|
||||
await start();
|
||||
await insertText(".o-mail-Composer-input", "@");
|
||||
await afterNextRender(() => triggerHotkey("Escape"));
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
|
||||
triggerHotkey("Escape");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"Close emoji picker in chat window with ESCAPE does not also close the chat window",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
name: "general",
|
||||
@@ -347,9 +343,9 @@ QUnit.test(
|
||||
});
|
||||
await start();
|
||||
await click("button[aria-label='Emojis']");
|
||||
await afterNextRender(() => triggerHotkey("Escape"));
|
||||
assert.containsNone($, ".o-EmojiPicker");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
triggerHotkey("Escape");
|
||||
await contains(".o-EmojiPicker", 0);
|
||||
await contains(".o-mail-ChatWindow");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -364,8 +360,8 @@ QUnit.test("open 2 different chat windows: enough screen width [REQUIRE FOCUS]",
|
||||
await start();
|
||||
await click("button i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem:contains(Channel_1)");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-header:contains(Channel_1)");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow-header:contains(Channel_1)");
|
||||
assert.strictEqual(
|
||||
document.activeElement,
|
||||
$(".o-mail-ChatWindow-header:contains(Channel_1)")
|
||||
@@ -375,9 +371,9 @@ QUnit.test("open 2 different chat windows: enough screen width [REQUIRE FOCUS]",
|
||||
|
||||
await click("button i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem:contains(Channel_2)");
|
||||
assert.containsN($, ".o-mail-ChatWindow", 2);
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-header:contains(Channel_2)");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-header:contains(Channel_1)");
|
||||
await contains(".o-mail-ChatWindow", 2);
|
||||
await contains(".o-mail-ChatWindow-header:contains(Channel_2)");
|
||||
await contains(".o-mail-ChatWindow-header:contains(Channel_1)");
|
||||
assert.strictEqual(
|
||||
document.activeElement,
|
||||
$(".o-mail-ChatWindow-header:contains(Channel_2)")
|
||||
@@ -408,20 +404,20 @@ QUnit.test("open 3 different chat windows: not enough screen width", async (asse
|
||||
// open, from systray menu, chat windows of channels with Id 1, 2, then 3
|
||||
await click("button i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem:contains(Channel_1)");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
assert.containsNone($, ".o-mail-ChatWindowHiddenToggler");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindowHiddenToggler", 0);
|
||||
|
||||
await click("button i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem:contains(Channel_2)");
|
||||
assert.containsN($, ".o-mail-ChatWindow", 2);
|
||||
assert.containsNone($, ".o-mail-ChatWindowHiddenToggler");
|
||||
await contains(".o-mail-ChatWindow", 2);
|
||||
await contains(".o-mail-ChatWindowHiddenToggler", 0);
|
||||
|
||||
await click("button i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem:contains(Channel_3)");
|
||||
assert.containsN($, ".o-mail-ChatWindow", 2);
|
||||
assert.containsOnce($, ".o-mail-ChatWindowHiddenToggler");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-header:contains(Channel_1)");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-header:contains(Channel_3)");
|
||||
await contains(".o-mail-ChatWindow", 2);
|
||||
await contains(".o-mail-ChatWindowHiddenToggler");
|
||||
await contains(".o-mail-ChatWindow-header:contains(Channel_1)");
|
||||
await contains(".o-mail-ChatWindow-header:contains(Channel_3)");
|
||||
assert.strictEqual(
|
||||
document.activeElement,
|
||||
$(".o-mail-ChatWindow-header:contains(Channel_3)")
|
||||
@@ -458,15 +454,15 @@ QUnit.test("closing hidden chat window", async (assert) => {
|
||||
await click("i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem:contains(Ch_4)");
|
||||
await click(".o-mail-ChatWindowHiddenToggler");
|
||||
assert.containsOnce($, ":not(.o-mail-ChatWindowHiddenMenu) .o-mail-ChatWindow:contains(Ch_1)");
|
||||
assert.containsOnce($, ".o-mail-ChatWindowHiddenMenu .o-mail-ChatWindow:contains(Ch_2)");
|
||||
assert.containsOnce($, ".o-mail-ChatWindowHiddenMenu .o-mail-ChatWindow:contains(Ch_3)");
|
||||
assert.containsOnce($, ":not(.o-mail-ChatWindowHiddenMenu) .o-mail-ChatWindow:contains(Ch_4)");
|
||||
await contains(":not(.o-mail-ChatWindowHiddenMenu) .o-mail-ChatWindow:contains(Ch_1)");
|
||||
await contains(".o-mail-ChatWindowHiddenMenu .o-mail-ChatWindow:contains(Ch_2)");
|
||||
await contains(".o-mail-ChatWindowHiddenMenu .o-mail-ChatWindow:contains(Ch_3)");
|
||||
await contains(":not(.o-mail-ChatWindowHiddenMenu) .o-mail-ChatWindow:contains(Ch_4)");
|
||||
await click(".o-mail-ChatWindow:contains(Ch_2) [title='Close Chat Window']");
|
||||
assert.containsOnce($, ":not(.o-mail-ChatWindowHiddenMenu) .o-mail-ChatWindow:contains(Ch_1)");
|
||||
assert.containsNone($, ".o-mail-ChatWindow:contains(Ch_2)");
|
||||
assert.containsOnce($, ".o-mail-ChatWindowHiddenMenu .o-mail-ChatWindow:contains(Ch_3)");
|
||||
assert.containsOnce($, ":not(.o-mail-ChatWindowHiddenMenu) .o-mail-ChatWindow:contains(Ch_4)");
|
||||
await contains(":not(.o-mail-ChatWindowHiddenMenu) .o-mail-ChatWindow:contains(Ch_1)");
|
||||
await contains(".o-mail-ChatWindow:contains(Ch_2)", 0);
|
||||
await contains(".o-mail-ChatWindowHiddenMenu .o-mail-ChatWindow:contains(Ch_3)");
|
||||
await contains(":not(.o-mail-ChatWindowHiddenMenu) .o-mail-ChatWindow:contains(Ch_4)");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
@@ -510,14 +506,14 @@ QUnit.test(
|
||||
"should have enough space to open 2 chat windows simultaneously"
|
||||
);
|
||||
await start();
|
||||
assert.containsN($, ".o-mail-ChatWindow .o-mail-Composer-input", 2);
|
||||
await contains(".o-mail-ChatWindow .o-mail-Composer-input", 2);
|
||||
|
||||
$(".o-mail-ChatWindow-name:contains(MyTeam)")
|
||||
.closest(".o-mail-ChatWindow")
|
||||
.find(".o-mail-Composer-input")[0]
|
||||
.focus();
|
||||
await afterNextRender(() => triggerHotkey("Escape"));
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
triggerHotkey("Escape");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
assert.strictEqual(
|
||||
document.activeElement,
|
||||
$(".o-mail-ChatWindow-name:contains(General)")
|
||||
@@ -527,7 +523,7 @@ QUnit.test(
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("chat window: switch on TAB", async (assert) => {
|
||||
QUnit.test("chat window: switch on TAB [REQUIRE FOCUS]", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create([{ name: "channel1" }, { name: "channel2" }]);
|
||||
patchUiSize({ width: 1920 });
|
||||
@@ -538,43 +534,19 @@ QUnit.test("chat window: switch on TAB", async (assert) => {
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem:contains(channel1)");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-name:contains(channel1)");
|
||||
assert.strictEqual(
|
||||
document.activeElement,
|
||||
$(".o-mail-ChatWindow-name:contains(channel1)")
|
||||
.closest(".o-mail-ChatWindow")
|
||||
.find(".o-mail-Composer-input")[0]
|
||||
);
|
||||
await contains(".o-mail-ChatWindow", 1);
|
||||
await contains(".o-mail-ChatWindow:contains(channel1) .o-mail-Composer-input:focus");
|
||||
|
||||
await afterNextRender(() => triggerHotkey("Tab"));
|
||||
assert.strictEqual(
|
||||
document.activeElement,
|
||||
$(".o-mail-ChatWindow-name:contains(channel1)")
|
||||
.closest(".o-mail-ChatWindow")
|
||||
.find(".o-mail-Composer-input")[0]
|
||||
);
|
||||
triggerHotkey("Tab");
|
||||
await contains(".o-mail-ChatWindow:contains(channel1) .o-mail-Composer-input:focus");
|
||||
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem:contains(channel2)");
|
||||
assert.containsN($, ".o-mail-ChatWindow", 2);
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-name:contains(channel1)");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-name:contains(channel2)");
|
||||
assert.strictEqual(
|
||||
document.activeElement,
|
||||
$(".o-mail-ChatWindow-name:contains(channel2)")
|
||||
.closest(".o-mail-ChatWindow")
|
||||
.find(".o-mail-Composer-input")[0]
|
||||
);
|
||||
await contains(".o-mail-ChatWindow", 2);
|
||||
await contains(".o-mail-ChatWindow:contains(channel2) .o-mail-Composer-input:focus");
|
||||
|
||||
await afterNextRender(() => triggerHotkey("Tab"));
|
||||
assert.containsN($, ".o-mail-ChatWindow", 2);
|
||||
assert.strictEqual(
|
||||
document.activeElement,
|
||||
$(".o-mail-ChatWindow-name:contains(channel1)")
|
||||
.closest(".o-mail-ChatWindow")
|
||||
.find(".o-mail-Composer-input")[0]
|
||||
);
|
||||
triggerHotkey("Tab");
|
||||
await contains(".o-mail-ChatWindow:contains(channel1) .o-mail-Composer-input:focus");
|
||||
});
|
||||
|
||||
QUnit.test("chat window: TAB cycle with 3 open chat windows [REQUIRE FOCUS]", async (assert) => {
|
||||
@@ -631,40 +603,22 @@ QUnit.test("chat window: TAB cycle with 3 open chat windows [REQUIRE FOCUS]", as
|
||||
);
|
||||
await start();
|
||||
// FIXME: assumes ordering: MyProject, MyTeam, General
|
||||
assert.containsN($, ".o-mail-ChatWindow .o-mail-Composer-input", 3);
|
||||
await contains(".o-mail-ChatWindow .o-mail-Composer-input", 3);
|
||||
(await contains(".o-mail-ChatWindow:contains(MyProject) .o-mail-Composer-input"))[0].focus();
|
||||
|
||||
$(".o-mail-ChatWindow-name:contains(MyProject)")
|
||||
.closest(".o-mail-ChatWindow")
|
||||
.find(".o-mail-Composer-input")[0]
|
||||
.focus();
|
||||
await afterNextRender(() => triggerHotkey("Tab"));
|
||||
assert.strictEqual(
|
||||
document.activeElement,
|
||||
$(".o-mail-ChatWindow-name:contains(MyTeam)")
|
||||
.closest(".o-mail-ChatWindow")
|
||||
.find(".o-mail-Composer-input")[0]
|
||||
);
|
||||
triggerHotkey("Tab");
|
||||
await contains(".o-mail-ChatWindow:contains(MyTeam) .o-mail-Composer-input:focus");
|
||||
|
||||
await afterNextRender(() => triggerHotkey("Tab"));
|
||||
assert.strictEqual(
|
||||
document.activeElement,
|
||||
$(".o-mail-ChatWindow-name:contains(General)")
|
||||
.closest(".o-mail-ChatWindow")
|
||||
.find(".o-mail-Composer-input")[0]
|
||||
);
|
||||
triggerHotkey("Tab");
|
||||
await contains(".o-mail-ChatWindow:contains(General) .o-mail-Composer-input:focus");
|
||||
|
||||
await afterNextRender(() => triggerHotkey("Tab"));
|
||||
assert.strictEqual(
|
||||
document.activeElement,
|
||||
$(".o-mail-ChatWindow-name:contains(MyProject)")
|
||||
.closest(".o-mail-ChatWindow")
|
||||
.find(".o-mail-Composer-input")[0]
|
||||
);
|
||||
triggerHotkey("Tab");
|
||||
await contains(".o-mail-ChatWindow:contains(MyProject) .o-mail-Composer-input:focus");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"new message separator is shown in a chat window of a chat on receiving new message if there is a history of conversation",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo" });
|
||||
const userId = pyEnv["res.users"].create({ name: "Foreigner user", partner_id: partnerId });
|
||||
@@ -695,24 +649,22 @@ QUnit.test(
|
||||
pyEnv["discuss.channel.member"].write([memberId], { seen_message_id: messageId });
|
||||
const { env } = await start();
|
||||
// simulate receiving a message
|
||||
await afterNextRender(async () =>
|
||||
pyEnv.withUser(userId, () =>
|
||||
env.services.rpc("/mail/message/post", {
|
||||
post_data: { body: "hu", message_type: "comment" },
|
||||
thread_id: channelId,
|
||||
thread_model: "discuss.channel",
|
||||
})
|
||||
)
|
||||
pyEnv.withUser(userId, () =>
|
||||
env.services.rpc("/mail/message/post", {
|
||||
post_data: { body: "hu", message_type: "comment" },
|
||||
thread_id: channelId,
|
||||
thread_model: "discuss.channel",
|
||||
})
|
||||
);
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
assert.containsN($, ".o-mail-Message", 2);
|
||||
assert.containsOnce($, "hr + span:contains(New messages)");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await contains(".o-mail-Message", 2);
|
||||
await contains("hr + span:contains(New messages)");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"new message separator is shown in chat window of chat on receiving new message when there was no history",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo" });
|
||||
const userId = pyEnv["res.users"].create({
|
||||
@@ -728,20 +680,18 @@ QUnit.test(
|
||||
});
|
||||
const { env } = await start();
|
||||
// simulate receiving a message
|
||||
await afterNextRender(async () =>
|
||||
pyEnv.withUser(userId, () =>
|
||||
env.services.rpc("/mail/message/post", {
|
||||
post_data: { body: "hu", message_type: "comment" },
|
||||
thread_id: channelId,
|
||||
thread_model: "discuss.channel",
|
||||
})
|
||||
)
|
||||
pyEnv.withUser(userId, () =>
|
||||
env.services.rpc("/mail/message/post", {
|
||||
post_data: { body: "hu", message_type: "comment" },
|
||||
thread_id: channelId,
|
||||
thread_model: "discuss.channel",
|
||||
})
|
||||
);
|
||||
assert.containsOnce($, "hr + span:contains(New messages)");
|
||||
await contains("hr + span:contains(New messages)");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("chat window should open when receiving a new DM", async (assert) => {
|
||||
QUnit.test("chat window should open when receiving a new DM", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const userId = pyEnv["res.users"].create({ partner_id: partnerId });
|
||||
@@ -753,20 +703,18 @@ QUnit.test("chat window should open when receiving a new DM", async (assert) =>
|
||||
channel_type: "chat",
|
||||
});
|
||||
const { env } = await start();
|
||||
// simulate receiving the first message on chat
|
||||
await afterNextRender(() =>
|
||||
pyEnv.withUser(userId, () =>
|
||||
env.services.rpc("/mail/message/post", {
|
||||
post_data: { body: "new message", message_type: "comment" },
|
||||
thread_id: channelId,
|
||||
thread_model: "discuss.channel",
|
||||
})
|
||||
)
|
||||
await contains(".o-mail-ChatWindowContainer");
|
||||
pyEnv.withUser(userId, () =>
|
||||
env.services.rpc("/mail/message/post", {
|
||||
post_data: { body: "new message", message_type: "comment" },
|
||||
thread_id: channelId,
|
||||
thread_model: "discuss.channel",
|
||||
})
|
||||
);
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
});
|
||||
|
||||
QUnit.test("chat window should not open when receiving a new DM from odoobot", async (assert) => {
|
||||
QUnit.test("chat window should not open when receiving a new DM from odoobot", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const userId = pyEnv["res.users"].create({ partner_id: pyEnv.odoobotId });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
@@ -777,17 +725,15 @@ QUnit.test("chat window should not open when receiving a new DM from odoobot", a
|
||||
channel_type: "chat",
|
||||
});
|
||||
const { env } = await start();
|
||||
// simulate receiving new message from odoobot
|
||||
await afterNextRender(() =>
|
||||
pyEnv.withUser(userId, () =>
|
||||
env.services.rpc("/mail/message/post", {
|
||||
post_data: { body: "new message", message_type: "comment" },
|
||||
thread_id: channelId,
|
||||
thread_model: "discuss.channel",
|
||||
})
|
||||
)
|
||||
await contains(".o-mail-ChatWindowContainer");
|
||||
pyEnv.withUser(userId, () =>
|
||||
env.services.rpc("/mail/message/post", {
|
||||
post_data: { body: "new message", message_type: "comment" },
|
||||
thread_id: channelId,
|
||||
thread_model: "discuss.channel",
|
||||
})
|
||||
);
|
||||
assert.containsNone($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
@@ -816,16 +762,12 @@ QUnit.test(
|
||||
}
|
||||
await start();
|
||||
await insertText(".o-mail-Composer-input", "WOLOLO");
|
||||
await afterNextRender(() =>
|
||||
triggerEvent(document.body, ".o-mail-Composer-input", "keydown", {
|
||||
key: "Enter",
|
||||
})
|
||||
);
|
||||
triggerHotkey("Enter");
|
||||
assert.ok(isScrolledToBottom($(".o-mail-Thread")[0]));
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("chat window should remain folded when new message is received", async (assert) => {
|
||||
QUnit.test("chat window should remain folded when new message is received", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo" });
|
||||
const userId = pyEnv["res.users"].create({
|
||||
@@ -848,8 +790,8 @@ QUnit.test("chat window should remain folded when new message is received", asyn
|
||||
channel_type: "chat",
|
||||
});
|
||||
const { env } = await start();
|
||||
assert.hasClass($(".o-mail-ChatWindow"), "o-folded");
|
||||
|
||||
await contains(".o-mail-ChatWindow.o-folded");
|
||||
await contains(".o-mail-ChatWindow-counter", 0);
|
||||
pyEnv.withUser(userId, () =>
|
||||
env.services.rpc("/mail/message/post", {
|
||||
post_data: { body: "New Message", message_type: "comment" },
|
||||
@@ -857,8 +799,8 @@ QUnit.test("chat window should remain folded when new message is received", asyn
|
||||
thread_model: "discuss.channel",
|
||||
})
|
||||
);
|
||||
await nextTick();
|
||||
assert.hasClass($(".o-mail-ChatWindow"), "o-folded");
|
||||
await contains(".o-mail-ChatWindow-counter:contains(1)");
|
||||
await contains(".o-mail-ChatWindow.o-folded");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
@@ -884,7 +826,7 @@ QUnit.test(
|
||||
"should not have enough space to open 3 chat windows simultaneously"
|
||||
);
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
openDiscuss();
|
||||
// open, from systray menu, chat windows of channels with id 1, 2, 3
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem-name:contains(Channel-1)");
|
||||
@@ -893,11 +835,9 @@ QUnit.test(
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem-name:contains(Channel-3)");
|
||||
// simulate resize to go into mobile
|
||||
await afterNextRender(() => {
|
||||
patchUiSize({ size: SIZES.SM });
|
||||
window.dispatchEvent(new UIEvent("resize"));
|
||||
});
|
||||
assert.containsNone($, ".o-mail-ChatWindowHiddenToggler");
|
||||
patchUiSize({ size: SIZES.SM });
|
||||
window.dispatchEvent(new UIEvent("resize"));
|
||||
await contains(".o-mail-ChatWindowHiddenToggler", 0);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -909,7 +849,7 @@ QUnit.test("chat window: composer state conservation on toggle discuss", async (
|
||||
await click(".o-mail-NotificationItem");
|
||||
// Set content of the composer of the chat window
|
||||
await insertText(".o-mail-Composer-input", "XDU for the win !");
|
||||
assert.containsNone($, ".o-mail-Composer-footer .o-mail-AttachmentList .o-mail-AttachmentCard");
|
||||
await contains(".o-mail-Composer-footer .o-mail-AttachmentList .o-mail-AttachmentCard", 0);
|
||||
// Set attachments of the composer
|
||||
const files = [
|
||||
await createFile({
|
||||
@@ -940,7 +880,7 @@ QUnit.test("chat window: composer state conservation on toggle discuss", async (
|
||||
|
||||
QUnit.test(
|
||||
"focusing a chat window of a chat should make new message separator disappear [REQUIRE FOCUS]",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo" });
|
||||
const userId = pyEnv["res.users"].create({
|
||||
@@ -978,18 +918,16 @@ QUnit.test(
|
||||
const { env } = await start();
|
||||
$(".o-mail-Composer-input")[0].blur();
|
||||
// simulate receiving a message
|
||||
await afterNextRender(() =>
|
||||
pyEnv.withUser(userId, () =>
|
||||
env.services.rpc("/mail/message/post", {
|
||||
post_data: { body: "hu", message_type: "comment" },
|
||||
thread_id: channelId,
|
||||
thread_model: "discuss.channel",
|
||||
})
|
||||
)
|
||||
pyEnv.withUser(userId, () =>
|
||||
env.services.rpc("/mail/message/post", {
|
||||
post_data: { body: "hu", message_type: "comment" },
|
||||
thread_id: channelId,
|
||||
thread_model: "discuss.channel",
|
||||
})
|
||||
);
|
||||
assert.containsOnce($, "hr + span:contains(New messages)");
|
||||
await afterNextRender(() => $(".o-mail-Composer-input")[0].focus());
|
||||
assert.containsNone($, "hr + span:contains(New messages)");
|
||||
await contains("hr + span:contains(New messages)");
|
||||
$(".o-mail-Composer-input")[0].focus();
|
||||
await contains("hr + span:contains(New messages)", 0);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1005,17 +943,21 @@ QUnit.test("chat window: scroll conservation on toggle discuss", async (assert)
|
||||
}
|
||||
const { openDiscuss, openView } = await start();
|
||||
await click(".o_menu_systray .dropdown-toggle:has(i[aria-label='Messages'])");
|
||||
await click(".o-mail-NotificationItem");
|
||||
$(".o-mail-Thread")[0].scrollTop = 142;
|
||||
await openDiscuss(null, { waitUntilMessagesLoaded: false });
|
||||
assert.containsNone($, ".o-mail-ChatWindow");
|
||||
/**
|
||||
* The afterNextRender is necessary because otherwise useAutoScroll would
|
||||
* set the scroll to bottom after the manually set value from this test.
|
||||
*/
|
||||
await afterNextRender(async () => await click(".o-mail-NotificationItem"));
|
||||
(await contains(".o-mail-ChatWindow .o-mail-Thread"))[0].scrollTop = 142;
|
||||
openDiscuss(null, { waitUntilMessagesLoaded: false });
|
||||
await contains(".o-mail-ChatWindow", 0);
|
||||
|
||||
await openView({
|
||||
openView({
|
||||
res_id: channelId,
|
||||
res_model: "discuss.channel",
|
||||
views: [[false, "list"]],
|
||||
});
|
||||
assert.strictEqual($(".o-mail-Thread")[0].scrollTop, 142);
|
||||
assert.strictEqual((await contains(".o-mail-ChatWindow .o-mail-Thread"))[0].scrollTop, 142);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
@@ -1032,17 +974,19 @@ QUnit.test(
|
||||
}
|
||||
await start();
|
||||
await click(".o_menu_systray .dropdown-toggle:has(i[aria-label='Messages'])");
|
||||
await click(".o-mail-NotificationItem");
|
||||
// Set a scroll position to chat window
|
||||
$(".o-mail-Thread")[0].scrollTop = 142;
|
||||
assert.strictEqual($(".o-mail-Thread")[0].scrollTop, 142);
|
||||
/**
|
||||
* The afterNextRender is necessary because otherwise useAutoScroll would
|
||||
* set the scroll to bottom after the manually set value from this test.
|
||||
*/
|
||||
await afterNextRender(async () => await click(".o-mail-NotificationItem"));
|
||||
(await contains(".o-mail-ChatWindow .o-mail-Thread"))[0].scrollTop = 142;
|
||||
|
||||
// fold chat window
|
||||
await click(".o-mail-ChatWindow-command[title='Fold']");
|
||||
assert.containsNone($, ".o-mail-Thread");
|
||||
await contains(".o-mail-ChatWindow .o-mail-Thread", 0);
|
||||
// unfold chat window
|
||||
await click(".o-mail-ChatWindow-command[title='Open']");
|
||||
assert.strictEqual($(".o-mail-Thread")[0].scrollTop, 142);
|
||||
assert.strictEqual((await contains(".o-mail-ChatWindow .o-mail-Thread"))[0].scrollTop, 142);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1060,27 +1004,30 @@ QUnit.test(
|
||||
}
|
||||
const { openDiscuss, openView } = await start();
|
||||
await click(".o_menu_systray .dropdown-toggle:has(i[aria-label='Messages'])");
|
||||
await click(".o-mail-NotificationItem");
|
||||
/**
|
||||
* The afterNextRender is necessary because otherwise useAutoScroll would
|
||||
* set the scroll to bottom after the manually set value from this test.
|
||||
*/
|
||||
await afterNextRender(async () => await click(".o-mail-NotificationItem"));
|
||||
(await contains(".o-mail-ChatWindow .o-mail-Thread"))[0].scrollTop = 142;
|
||||
|
||||
// Set a scroll position to chat window
|
||||
$(".o-mail-Thread")[0].scrollTop = 142;
|
||||
// fold chat window
|
||||
await click(".o-mail-ChatWindow-command[title='Fold']");
|
||||
await openDiscuss(null, { waitUntilMessagesLoaded: false });
|
||||
assert.containsNone($, ".o-mail-ChatWindow");
|
||||
openDiscuss(null, { waitUntilMessagesLoaded: false });
|
||||
await contains(".o-mail-ChatWindow", 0);
|
||||
|
||||
await openView({
|
||||
openView({
|
||||
res_id: channelId,
|
||||
res_model: "discuss.channel",
|
||||
views: [[false, "list"]],
|
||||
});
|
||||
// unfold chat window
|
||||
await click(".o-mail-ChatWindow-command[title='Open']");
|
||||
assert.strictEqual($(".o-mail-Thread")[0].scrollTop, 142);
|
||||
assert.strictEqual((await contains(".o-mail-ChatWindow .o-mail-Thread"))[0].scrollTop, 142);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("folded chat window should hide member-list and settings buttons", async (assert) => {
|
||||
QUnit.test("folded chat window should hide member-list and settings buttons", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({});
|
||||
await start();
|
||||
@@ -1088,24 +1035,26 @@ QUnit.test("folded chat window should hide member-list and settings buttons", as
|
||||
await click("button i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
await click("[title='Open Actions Menu']");
|
||||
assert.containsOnce($, "[title='Show Member List']");
|
||||
assert.containsOnce($, "[title='Show Call Settings']");
|
||||
await contains("[title='Show Member List']");
|
||||
await contains("[title='Show Call Settings']");
|
||||
|
||||
await click(".o-mail-ChatWindow-header"); // click away to close the more menu
|
||||
await contains("[title='Show Member List']", 0);
|
||||
|
||||
// Fold chat window
|
||||
await click(".o-mail-ChatWindow-command[title='Fold']");
|
||||
assert.containsNone($, "[title='Open Actions Menu']");
|
||||
assert.containsNone($, "[title='Show Member List']");
|
||||
assert.containsNone($, "[title='Show Call Settings']");
|
||||
await contains("[title='Open Actions Menu']", 0);
|
||||
await contains("[title='Show Member List']", 0);
|
||||
await contains("[title='Show Call Settings']", 0);
|
||||
|
||||
// Unfold chat window
|
||||
await click(".o-mail-ChatWindow-command[title='Open']");
|
||||
await click("[title='Open Actions Menu']");
|
||||
assert.containsOnce($, "[title='Show Member List']");
|
||||
assert.containsOnce($, "[title='Show Call Settings']");
|
||||
await contains("[title='Show Member List']");
|
||||
await contains("[title='Show Call Settings']");
|
||||
});
|
||||
|
||||
QUnit.test("Chat window in mobile are not foldable", async (assert) => {
|
||||
QUnit.test("Chat window in mobile are not foldable", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
@@ -1116,13 +1065,13 @@ QUnit.test("Chat window in mobile are not foldable", async (assert) => {
|
||||
await start();
|
||||
await click("button i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
assert.containsNone($, ".o-mail-ChatWindow-header.cursor-pointer");
|
||||
await contains(".o-mail-ChatWindow-header.cursor-pointer", 0);
|
||||
click(".o-mail-ChatWindow-header").catch(() => {});
|
||||
await nextAnimationFrame();
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-content"); // content => non-folded
|
||||
await contains(".o-mail-ChatWindow-content"); // content => non-folded
|
||||
});
|
||||
|
||||
QUnit.test("Server-synced chat windows should not open at page load on mobile", async (assert) => {
|
||||
QUnit.test("Server-synced chat windows should not open at page load on mobile", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
@@ -1135,23 +1084,24 @@ QUnit.test("Server-synced chat windows should not open at page load on mobile",
|
||||
});
|
||||
patchUiSize({ size: SIZES.SM });
|
||||
await start();
|
||||
assert.containsNone($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindowContainer");
|
||||
await contains(".o-mail-ChatWindow", 0);
|
||||
});
|
||||
|
||||
QUnit.test("chat window of channels should not have 'Open in Discuss' (mobile)", async (assert) => {
|
||||
QUnit.test("chat window of channels should not have 'Open in Discuss' (mobile)", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({ name: "General" });
|
||||
patchUiSize({ size: SIZES.SM });
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
assert.containsOnce($, "[title='Open Actions Menu']");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await contains("[title='Open Actions Menu']");
|
||||
await click("[title='Open Actions Menu']");
|
||||
assert.containsNone($, "[title='Open in Discuss']");
|
||||
await contains("[title='Open in Discuss']", 0);
|
||||
});
|
||||
|
||||
QUnit.test("Open chat window of new inviter", async (assert) => {
|
||||
QUnit.test("Open chat window of new inviter", async () => {
|
||||
const pyEnv = await startServer();
|
||||
await start();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Newbie" });
|
||||
@@ -1162,15 +1112,14 @@ QUnit.test("Open chat window of new inviter", async (assert) => {
|
||||
partnerId,
|
||||
});
|
||||
await contains(".o-mail-ChatWindow:contains(Newbie)");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
await contains(
|
||||
".o_notification:contains(Newbie connected. This is their first connection. Wish them luck.)"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"keyboard navigation ArrowUp/ArrowDown on message action dropdown in chat window",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
pyEnv["mail.message"].create({
|
||||
@@ -1182,22 +1131,22 @@ QUnit.test(
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
await afterNextRender(() => {
|
||||
$(".o-mail-Message")[0].dispatchEvent(new window.MouseEvent("mouseenter"));
|
||||
});
|
||||
await click(".o-mail-Message [title='Expand']");
|
||||
$(".o-mail-Message [title='Expand']")[0].focus(); // necessary otherwise focus is in composer input
|
||||
assert.containsOnce($, ".o-mail-Message-moreMenu.dropdown-menu");
|
||||
await triggerHotkey("ArrowDown");
|
||||
assert.containsOnce($, ".o-mail-Message-moreMenu .dropdown-item:eq(0).focus");
|
||||
await triggerHotkey("ArrowDown");
|
||||
assert.containsOnce($, ".o-mail-Message-moreMenu .dropdown-item:eq(1).focus");
|
||||
await contains(".o-mail-ChatWindow .o-mail-Composer-input:focus");
|
||||
const expand = await click(".o-mail-Message [title='Expand']");
|
||||
await contains(".o-mail-Message-moreMenu.dropdown-menu");
|
||||
expand.focus(); // necessary otherwise focus is in composer input
|
||||
|
||||
triggerHotkey("ArrowDown");
|
||||
await contains(".o-mail-Message-moreMenu .dropdown-item:eq(0).focus");
|
||||
|
||||
triggerHotkey("ArrowDown");
|
||||
await contains(".o-mail-Message-moreMenu .dropdown-item:eq(1).focus");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"Close dropdown in chat window with ESCAPE does not also close the chat window",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
pyEnv["mail.message"].create({
|
||||
@@ -1209,14 +1158,11 @@ QUnit.test(
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
await afterNextRender(() => {
|
||||
$(".o-mail-Message")[0].dispatchEvent(new window.MouseEvent("mouseenter"));
|
||||
});
|
||||
await click(".o-mail-Message [title='Expand']");
|
||||
$(".o-mail-Message [title='Expand']")[0].focus(); // necessary otherwise focus is in composer input
|
||||
assert.containsOnce($, ".o-mail-Message-moreMenu.dropdown-menu");
|
||||
await triggerHotkey("Escape");
|
||||
assert.containsNone($, ".o-mail-Message-moreMenu.dropdown-menu");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
const expand = await click(".o-mail-Message [title='Expand']");
|
||||
await contains(".o-mail-Message-moreMenu.dropdown-menu");
|
||||
expand.focus(); // necessary otherwise focus is in composer input
|
||||
triggerHotkey("Escape");
|
||||
await contains(".o-mail-Message-moreMenu.dropdown-menu", 0);
|
||||
await contains(".o-mail-ChatWindow");
|
||||
}
|
||||
);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
import { click, contains, insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { makeDeferred, patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
|
||||
const views = {
|
||||
"res.fake,false,form": `
|
||||
@@ -16,7 +16,7 @@ const views = {
|
||||
|
||||
QUnit.module("suggested_recipients");
|
||||
|
||||
QUnit.test("with 3 or less suggested recipients: no 'show more' button", async (assert) => {
|
||||
QUnit.test("with 3 or less suggested recipients: no 'show more' button", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({
|
||||
display_name: "John Jane",
|
||||
@@ -27,9 +27,10 @@ QUnit.test("with 3 or less suggested recipients: no 'show more' button", async (
|
||||
partner_ids: [partnerId],
|
||||
});
|
||||
const { openFormView } = await start();
|
||||
await openFormView("res.fake", fakeId);
|
||||
openFormView("res.fake", fakeId);
|
||||
await click("button:contains(Send message)");
|
||||
assert.containsNone($, "button:contains(Show more)");
|
||||
await contains(".o-mail-SuggestedRecipient", 2);
|
||||
await contains("button:contains(Show more)", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
@@ -45,7 +46,8 @@ QUnit.test(
|
||||
partner_ids: [partnerId],
|
||||
});
|
||||
const { env, openFormView } = await start();
|
||||
await openFormView("res.fake", fakeId);
|
||||
openFormView("res.fake", fakeId);
|
||||
const def = makeDeferred();
|
||||
patchWithCleanup(env.services.action, {
|
||||
doAction(action) {
|
||||
assert.step("do-action");
|
||||
@@ -59,12 +61,13 @@ QUnit.test(
|
||||
johnTestPartnerId,
|
||||
partnerId,
|
||||
]);
|
||||
def.resolve();
|
||||
return Promise.resolve();
|
||||
},
|
||||
});
|
||||
await click("button:contains(Send message)");
|
||||
assert.containsOnce($, ".o-mail-SuggestedRecipient:contains(john@test.be)");
|
||||
assert.containsOnce($, ".o-mail-SuggestedRecipient:contains(John Jane)");
|
||||
await contains(".o-mail-SuggestedRecipient:contains(john@test.be)");
|
||||
await contains(".o-mail-SuggestedRecipient:contains(John Jane)");
|
||||
assert.ok(
|
||||
$(".o-mail-SuggestedRecipient:contains(john@test.be) input[type=checkbox]")[0].checked
|
||||
);
|
||||
@@ -72,6 +75,7 @@ QUnit.test(
|
||||
$(".o-mail-SuggestedRecipient:contains(John Jane) input[type=checkbox]")[0].checked
|
||||
);
|
||||
await click("button[title='Full composer']");
|
||||
await def;
|
||||
assert.verifySteps(["do-action"]);
|
||||
}
|
||||
);
|
||||
@@ -89,19 +93,21 @@ QUnit.test(
|
||||
partner_ids: [partnerId],
|
||||
});
|
||||
const { env, openFormView } = await start();
|
||||
await openFormView("res.fake", fakeId);
|
||||
openFormView("res.fake", fakeId);
|
||||
const def = makeDeferred();
|
||||
patchWithCleanup(env.services.action, {
|
||||
doAction(action) {
|
||||
assert.step("do-action");
|
||||
assert.strictEqual(action.name, "Log note");
|
||||
assert.strictEqual(action.context.default_subtype_xmlid, "mail.mt_note");
|
||||
assert.deepEqual(action.context.default_partner_ids, []);
|
||||
def.resolve();
|
||||
return Promise.resolve();
|
||||
},
|
||||
});
|
||||
await click("button:contains(Send message)");
|
||||
assert.containsOnce($, ".o-mail-SuggestedRecipient:contains(john@test.be)");
|
||||
assert.containsOnce($, ".o-mail-SuggestedRecipient:contains(John Jane)");
|
||||
await contains(".o-mail-SuggestedRecipient:contains(john@test.be)");
|
||||
await contains(".o-mail-SuggestedRecipient:contains(John Jane)");
|
||||
assert.ok(
|
||||
$(".o-mail-SuggestedRecipient:contains(john@test.be) input[type=checkbox]")[0].checked
|
||||
);
|
||||
@@ -110,33 +116,31 @@ QUnit.test(
|
||||
);
|
||||
await click("button:contains(Log note)");
|
||||
await click("button[title='Full composer']");
|
||||
await def;
|
||||
assert.verifySteps(["do-action"]);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"more than 3 suggested recipients: display only 3 and 'show more' button",
|
||||
async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const [partnerId_1, partnerId_2, partnerId_3, partnerId_4] = pyEnv["res.partner"].create([
|
||||
{ display_name: "John Jane", email: "john@jane.be" },
|
||||
{ display_name: "Jack Jone", email: "jack@jone.be" },
|
||||
{ display_name: "jack sparrow", email: "jsparrow@blackpearl.bb" },
|
||||
{ display_name: "jolly Roger", email: "Roger@skullflag.com" },
|
||||
]);
|
||||
const fakeId = pyEnv["res.fake"].create({
|
||||
partner_ids: [partnerId_1, partnerId_2, partnerId_3, partnerId_4],
|
||||
});
|
||||
const { openFormView } = await start({ serverData: { views } });
|
||||
await openFormView("res.fake", fakeId);
|
||||
await click("button:contains(Send message)");
|
||||
assert.containsOnce($, "button:contains(Show more)");
|
||||
}
|
||||
);
|
||||
QUnit.test("more than 3 suggested recipients: display only 3 and 'show more' button", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const [partnerId_1, partnerId_2, partnerId_3, partnerId_4] = pyEnv["res.partner"].create([
|
||||
{ display_name: "John Jane", email: "john@jane.be" },
|
||||
{ display_name: "Jack Jone", email: "jack@jone.be" },
|
||||
{ display_name: "jack sparrow", email: "jsparrow@blackpearl.bb" },
|
||||
{ display_name: "jolly Roger", email: "Roger@skullflag.com" },
|
||||
]);
|
||||
const fakeId = pyEnv["res.fake"].create({
|
||||
partner_ids: [partnerId_1, partnerId_2, partnerId_3, partnerId_4],
|
||||
});
|
||||
const { openFormView } = await start({ serverData: { views } });
|
||||
openFormView("res.fake", fakeId);
|
||||
await click("button:contains(Send message)");
|
||||
await contains("button:contains(Show more)");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"more than 3 suggested recipients: show all of them on click 'show more' button",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const [partnerId_1, partnerId_2, partnerId_3, partnerId_4] = pyEnv["res.partner"].create([
|
||||
{ display_name: "John Jane", email: "john@jane.be" },
|
||||
@@ -148,16 +152,16 @@ QUnit.test(
|
||||
partner_ids: [partnerId_1, partnerId_2, partnerId_3, partnerId_4],
|
||||
});
|
||||
const { openFormView } = await start({ serverData: { views } });
|
||||
await openFormView("res.fake", fakeId);
|
||||
openFormView("res.fake", fakeId);
|
||||
await click("button:contains(Send message)");
|
||||
await click("button:contains(Show more)");
|
||||
assert.containsN($, ".o-mail-SuggestedRecipient", 4);
|
||||
await contains(".o-mail-SuggestedRecipient", 4);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"more than 3 suggested recipients -> click 'show more' -> 'show less' button",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const [partnerId_1, partnerId_2, partnerId_3, partnerId_4] = pyEnv["res.partner"].create([
|
||||
{ display_name: "John Jane", email: "john@jane.be" },
|
||||
@@ -169,16 +173,16 @@ QUnit.test(
|
||||
partner_ids: [partnerId_1, partnerId_2, partnerId_3, partnerId_4],
|
||||
});
|
||||
const { openFormView } = await start({ serverData: { views } });
|
||||
await openFormView("res.fake", fakeId);
|
||||
openFormView("res.fake", fakeId);
|
||||
await click("button:contains(Send message)");
|
||||
await click("button:contains(Show more)");
|
||||
assert.containsOnce($, "button:contains(Show less)");
|
||||
await contains("button:contains(Show less)");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"suggested recipients list display 3 suggested recipient and 'show more' button when 'show less' button is clicked",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const [partnerId_1, partnerId_2, partnerId_3, partnerId_4] = pyEnv["res.partner"].create([
|
||||
{ display_name: "John Jane", email: "john@jane.be" },
|
||||
@@ -190,12 +194,12 @@ QUnit.test(
|
||||
partner_ids: [partnerId_1, partnerId_2, partnerId_3, partnerId_4],
|
||||
});
|
||||
const { openFormView } = await start({ serverData: { views } });
|
||||
await openFormView("res.fake", fakeId);
|
||||
openFormView("res.fake", fakeId);
|
||||
await click("button:contains(Send message)");
|
||||
await click("button:contains(Show more)");
|
||||
await click("button:contains(Show less)");
|
||||
assert.containsN($, ".o-mail-SuggestedRecipient", 3);
|
||||
assert.containsOnce($, "button:contains(Show more)");
|
||||
await contains(".o-mail-SuggestedRecipient", 3);
|
||||
await contains("button:contains(Show more)");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -212,9 +216,9 @@ QUnit.test(
|
||||
partner_ids: [partnerId],
|
||||
});
|
||||
const { openFormView } = await start({ serverData: { views } });
|
||||
await openFormView("res.fake", fakeId);
|
||||
openFormView("res.fake", fakeId);
|
||||
await click("button:contains(Send message)");
|
||||
assert.containsN($, ".o-mail-SuggestedRecipient input:checked", 2);
|
||||
await contains(".o-mail-SuggestedRecipient input:checked", 2);
|
||||
assert.ok(
|
||||
$(".o-mail-SuggestedRecipient:not([data-partner-id]) input[type=checkbox]")[0].checked
|
||||
);
|
||||
@@ -233,10 +237,10 @@ QUnit.test("display reason for suggested recipient on mouse over", async (assert
|
||||
});
|
||||
const fakeId = pyEnv["res.fake"].create({ partner_ids: [partnerId] });
|
||||
const { openFormView } = await start({ serverData: { views } });
|
||||
await openFormView("res.fake", fakeId);
|
||||
openFormView("res.fake", fakeId);
|
||||
await click("button:contains(Send message)");
|
||||
const partnerTitle = $(
|
||||
`.o-mail-SuggestedRecipient[data-partner-id="${partnerId}"]`
|
||||
const partnerTitle = (
|
||||
await contains(`.o-mail-SuggestedRecipient[data-partner-id="${partnerId}"]`)
|
||||
)[0].getAttribute("title");
|
||||
assert.strictEqual(partnerTitle, "Add as recipient and follower (reason: Email partner)");
|
||||
});
|
||||
@@ -258,10 +262,11 @@ QUnit.test(
|
||||
}
|
||||
},
|
||||
});
|
||||
await openFormView("res.fake", fakeId);
|
||||
openFormView("res.fake", fakeId);
|
||||
await click("button:contains(Log note)");
|
||||
await insertText(".o-mail-Composer-input", "Dummy Message");
|
||||
await click(".o-mail-Composer-send");
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
await contains(".o-mail-Message");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -277,10 +282,11 @@ QUnit.test(
|
||||
const { openFormView } = await start({
|
||||
serverData: { views },
|
||||
});
|
||||
await openFormView("res.fake", fakeId);
|
||||
openFormView("res.fake", fakeId);
|
||||
await click("button:contains(Send message)");
|
||||
await insertText(".o-mail-Composer-input", "Dummy Message");
|
||||
await click(".o-mail-Composer-send");
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
await contains(".o-mail-Message");
|
||||
assert.strictEqual($(".o-mail-Followers-counter").text(), "1");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,33 +1,27 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import {
|
||||
afterNextRender,
|
||||
click,
|
||||
contains,
|
||||
start,
|
||||
startServer,
|
||||
} from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { triggerHotkey, patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
import { patchWithCleanup, triggerHotkey } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("crosstab");
|
||||
|
||||
QUnit.test("Messages are received cross-tab", async (assert) => {
|
||||
QUnit.test("Messages are received cross-tab", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
name: "General",
|
||||
});
|
||||
const tab1 = await start({ asTab: true });
|
||||
const tab2 = await start({ asTab: true });
|
||||
await tab1.openDiscuss(channelId);
|
||||
await tab2.openDiscuss(channelId);
|
||||
tab1.openDiscuss(channelId);
|
||||
tab2.openDiscuss(channelId);
|
||||
await tab1.insertText(".o-mail-Composer-input", "Hello World!");
|
||||
await tab1.click("button:contains(Send)");
|
||||
assert.containsOnce(tab1.target, ".o-mail-Message:contains(Hello World!)");
|
||||
assert.containsOnce(tab2.target, ".o-mail-Message:contains(Hello World!)");
|
||||
await click("button:contains(Send):not(:disabled)", { target: tab1.target });
|
||||
await contains(".o-mail-Message:contains(Hello World!)", 1, { target: tab1.target });
|
||||
await contains(".o-mail-Message:contains(Hello World!)", 1, { target: tab2.target });
|
||||
});
|
||||
|
||||
QUnit.test("Delete starred message updates counter", async (assert) => {
|
||||
QUnit.test("Delete starred message updates counter", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
name: "General",
|
||||
@@ -40,71 +34,71 @@ QUnit.test("Delete starred message updates counter", async (assert) => {
|
||||
});
|
||||
const tab1 = await start({ asTab: true });
|
||||
const tab2 = await start({ asTab: true });
|
||||
await tab1.openDiscuss(channelId);
|
||||
await tab2.openDiscuss(channelId);
|
||||
assert.containsOnce(tab2.target, "button:contains(Starred1)");
|
||||
await afterNextRender(() =>
|
||||
tab1.env.services.rpc("/mail/message/update_content", {
|
||||
message_id: messageId,
|
||||
body: "",
|
||||
attachment_ids: [],
|
||||
})
|
||||
);
|
||||
assert.containsNone(tab2.target, "button:contains(Starred1)");
|
||||
tab1.openDiscuss(channelId);
|
||||
tab2.openDiscuss(channelId);
|
||||
await contains("button:contains(Starred1)", 1, { target: tab2.target });
|
||||
tab1.env.services.rpc("/mail/message/update_content", {
|
||||
message_id: messageId,
|
||||
body: "",
|
||||
attachment_ids: [],
|
||||
});
|
||||
await contains("button:contains(Starred1)", 0, { target: tab2.target });
|
||||
});
|
||||
|
||||
QUnit.test("Thread rename", async (assert) => {
|
||||
QUnit.test("Thread rename", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
create_uid: pyEnv.currentPartnerId,
|
||||
create_uid: pyEnv.currentUserId,
|
||||
name: "General",
|
||||
});
|
||||
const tab1 = await start({ asTab: true });
|
||||
const tab2 = await start({ asTab: true });
|
||||
await tab1.openDiscuss(channelId);
|
||||
await tab2.openDiscuss(channelId);
|
||||
await tab1.insertText(".o-mail-Discuss-threadName", "Sales", { replace: true });
|
||||
await afterNextRender(() => triggerHotkey("Enter"));
|
||||
assert.containsOnce(tab2.target, ".o-mail-Discuss-threadName[title='Sales']");
|
||||
assert.containsOnce(tab2.target, ".o-mail-DiscussSidebarChannel:contains(Sales)");
|
||||
tab1.openDiscuss(channelId);
|
||||
tab2.openDiscuss(channelId);
|
||||
await tab1.insertText(".o-mail-Discuss-threadName:not(:disabled)", "Sales", { replace: true });
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-Discuss-threadName[title='Sales']", 1, { target: tab2.target });
|
||||
await contains(".o-mail-DiscussSidebarChannel:contains(Sales)", 1, { target: tab2.target });
|
||||
});
|
||||
|
||||
QUnit.test("Thread description update", async (assert) => {
|
||||
QUnit.test("Thread description update", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
create_uid: pyEnv.currentPartnerId,
|
||||
create_uid: pyEnv.currentUserId,
|
||||
name: "General",
|
||||
});
|
||||
const tab1 = await start({ asTab: true });
|
||||
const tab2 = await start({ asTab: true });
|
||||
await tab1.openDiscuss(channelId);
|
||||
await tab2.openDiscuss(channelId);
|
||||
tab1.openDiscuss(channelId);
|
||||
tab2.openDiscuss(channelId);
|
||||
await tab1.insertText(".o-mail-Discuss-threadDescription", "The very best channel", {
|
||||
replace: true,
|
||||
});
|
||||
await afterNextRender(() => triggerHotkey("Enter"));
|
||||
assert.containsOnce(
|
||||
tab2.target,
|
||||
".o-mail-Discuss-threadDescription[title='The very best channel']"
|
||||
);
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-Discuss-threadDescription[title='The very best channel']", 1, {
|
||||
target: tab2.target,
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test("Channel subscription is renewed when channel is added from invite", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "Sales", channel_member_ids: [] });
|
||||
const [, channelId] = pyEnv["discuss.channel"].create([
|
||||
{ name: "R&D" },
|
||||
{ name: "Sales", channel_member_ids: [] },
|
||||
]);
|
||||
const { env, openDiscuss } = await start();
|
||||
patchWithCleanup(env.services["bus_service"], {
|
||||
forceUpdateChannels() {
|
||||
assert.step("update-channels");
|
||||
},
|
||||
});
|
||||
await openDiscuss();
|
||||
// simulate receiving invite
|
||||
await afterNextRender(() => {
|
||||
env.services.orm.call("discuss.channel", "add_members", [[channelId]], {
|
||||
partner_ids: [pyEnv.currentPartnerId],
|
||||
});
|
||||
openDiscuss();
|
||||
await contains(".o-mail-DiscussSidebarChannel");
|
||||
env.services.orm.call("discuss.channel", "add_members", [[channelId]], {
|
||||
partner_ids: [pyEnv.currentPartnerId],
|
||||
});
|
||||
await contains(".o-mail-DiscussSidebarChannel", 2);
|
||||
await new Promise((resolve) => setTimeout(resolve)); // update of channels is debounced
|
||||
assert.verifySteps(["update-channels"]);
|
||||
});
|
||||
|
||||
@@ -117,12 +111,14 @@ QUnit.test("Channel subscription is renewed when channel is left", async (assert
|
||||
assert.step("update-channels");
|
||||
},
|
||||
});
|
||||
await openDiscuss();
|
||||
openDiscuss();
|
||||
await click(".o-mail-DiscussSidebarChannel .btn[title='Leave this channel']");
|
||||
await contains(".o-mail-DiscussSidebarChannel", 0);
|
||||
await new Promise((resolve) => setTimeout(resolve)); // update of channels is debounced
|
||||
assert.verifySteps(["update-channels"]);
|
||||
});
|
||||
|
||||
QUnit.test("Adding attachments", async (assert) => {
|
||||
QUnit.test("Adding attachments", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "Hogwarts Legacy" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
@@ -133,23 +129,21 @@ QUnit.test("Adding attachments", async (assert) => {
|
||||
});
|
||||
const tab1 = await start({ asTab: true });
|
||||
const tab2 = await start({ asTab: true });
|
||||
await tab1.openDiscuss(channelId);
|
||||
await tab2.openDiscuss(channelId);
|
||||
tab1.openDiscuss(channelId);
|
||||
tab2.openDiscuss(channelId);
|
||||
const attachmentId = pyEnv["ir.attachment"].create({
|
||||
name: "test.txt",
|
||||
mimetype: "text/plain",
|
||||
});
|
||||
await afterNextRender(() =>
|
||||
tab1.env.services.rpc("/mail/message/update_content", {
|
||||
body: "Hello world!",
|
||||
attachment_ids: [attachmentId],
|
||||
message_id: messageId,
|
||||
})
|
||||
);
|
||||
assert.containsOnce(tab2.target, ".o-mail-AttachmentCard:contains(test.txt)");
|
||||
tab1.env.services.rpc("/mail/message/update_content", {
|
||||
body: "Hello world!",
|
||||
attachment_ids: [attachmentId],
|
||||
message_id: messageId,
|
||||
});
|
||||
await contains(".o-mail-AttachmentCard:contains(test.txt)", 1, { target: tab2.target });
|
||||
});
|
||||
|
||||
QUnit.test("Remove attachment from message", async (assert) => {
|
||||
QUnit.test("Remove attachment from message", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const attachmentId = pyEnv["ir.attachment"].create({
|
||||
@@ -165,15 +159,15 @@ QUnit.test("Remove attachment from message", async (assert) => {
|
||||
});
|
||||
const tab1 = await start({ asTab: true });
|
||||
const tab2 = await start({ asTab: true });
|
||||
await tab1.openDiscuss(channelId);
|
||||
await tab2.openDiscuss(channelId);
|
||||
assert.containsOnce(tab1.target, ".o-mail-AttachmentCard:contains(test.txt)");
|
||||
await tab2.click(".o-mail-AttachmentCard-unlink");
|
||||
await tab2.click(".modal-footer .btn:contains(Ok)");
|
||||
assert.containsNone(tab1.target, ".o-mail-AttachmentCard:contains(test.txt)");
|
||||
tab1.openDiscuss(channelId);
|
||||
tab2.openDiscuss(channelId);
|
||||
await contains(".o-mail-AttachmentCard:contains(test.txt)", 1, { target: tab1.target });
|
||||
await click(".o-mail-AttachmentCard-unlink", { target: tab2.target });
|
||||
await click(".modal-footer .btn:contains(Ok)", { target: tab2.target });
|
||||
await contains(".o-mail-AttachmentCard:contains(test.txt)", 0, { target: tab1.target });
|
||||
});
|
||||
|
||||
QUnit.test("Message delete notification", async (assert) => {
|
||||
QUnit.test("Message delete notification", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "Needaction message",
|
||||
@@ -190,8 +184,8 @@ QUnit.test("Message delete notification", async (assert) => {
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
openDiscuss();
|
||||
(await contains("[title='Expand']")).click();
|
||||
(await contains("[title='Mark as Todo']")).click();
|
||||
await click("[title='Expand']");
|
||||
await click("[title='Mark as Todo']");
|
||||
await contains("button:contains(Inbox) .badge");
|
||||
await contains("button:contains(Starred) .badge");
|
||||
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "mail.message/delete", {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { browser } from "@web/core/browser/browser";
|
||||
import { patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("call setting");
|
||||
|
||||
QUnit.test("Renders the call settings", async (assert) => {
|
||||
QUnit.test("Renders the call settings", async () => {
|
||||
patchWithCleanup(browser, {
|
||||
navigator: {
|
||||
...browser.navigator,
|
||||
@@ -31,19 +31,19 @@ QUnit.test("Renders the call settings", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "test" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-Discuss-header .fa-gear");
|
||||
assert.containsOnce($, ".o-discuss-CallSettings", "Should have a call settings menu");
|
||||
assert.containsOnce($, "label[aria-label='Input device']");
|
||||
assert.containsOnce($, "option[value=mockAudioDeviceId]");
|
||||
assert.containsNone($, "option[value=mockVideoDeviceId]");
|
||||
assert.containsOnce($, "input[title='toggle push-to-talk']");
|
||||
assert.containsOnce($, "label[aria-label='Voice detection threshold']");
|
||||
assert.containsOnce($, "input[title='Show video participants only']");
|
||||
assert.containsOnce($, "input[title='Blur video background']");
|
||||
await contains(".o-discuss-CallSettings");
|
||||
await contains("label[aria-label='Input device']");
|
||||
await contains("option[value=mockAudioDeviceId]");
|
||||
await contains("option[value=mockVideoDeviceId]", 0);
|
||||
await contains("input[title='toggle push-to-talk']");
|
||||
await contains("label[aria-label='Voice detection threshold']");
|
||||
await contains("input[title='Show video participants only']");
|
||||
await contains("input[title='Blur video background']");
|
||||
});
|
||||
|
||||
QUnit.test("activate push to talk", async (assert) => {
|
||||
QUnit.test("activate push to talk", async () => {
|
||||
patchWithCleanup(browser, {
|
||||
navigator: {
|
||||
...browser.navigator,
|
||||
@@ -55,15 +55,15 @@ QUnit.test("activate push to talk", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "test" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-Discuss-header .fa-gear");
|
||||
await click("input[title='toggle push-to-talk']");
|
||||
assert.containsOnce($, "i[aria-label='Register new key']");
|
||||
assert.containsOnce($, "label[aria-label='Delay after releasing push-to-talk']");
|
||||
assert.containsNone($, "label[aria-label='Voice detection threshold']");
|
||||
await contains("i[aria-label='Register new key']");
|
||||
await contains("label[aria-label='Delay after releasing push-to-talk']");
|
||||
await contains("label[aria-label='Voice detection threshold']", 0);
|
||||
});
|
||||
|
||||
QUnit.test("activate blur", async (assert) => {
|
||||
QUnit.test("activate blur", async () => {
|
||||
patchWithCleanup(browser, {
|
||||
navigator: {
|
||||
...browser.navigator,
|
||||
@@ -74,24 +74,25 @@ QUnit.test("activate blur", async (assert) => {
|
||||
});
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "test" });
|
||||
const { click, openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
const { openDiscuss } = await start();
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-Discuss-header .fa-gear");
|
||||
await click("input[title='Blur video background']");
|
||||
assert.containsOnce($, "label[aria-label='Background blur intensity']");
|
||||
assert.containsOnce($, "label[aria-label='Edge blur intensity']");
|
||||
await contains("label[aria-label='Background blur intensity']");
|
||||
await contains("label[aria-label='Edge blur intensity']");
|
||||
});
|
||||
|
||||
QUnit.test("Inbox should not have any call settings menu", async (assert) => {
|
||||
QUnit.test("Inbox should not have any call settings menu", async () => {
|
||||
await startServer();
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
assert.containsNone($, "button[title='Show Call Settings']");
|
||||
openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Thread");
|
||||
await contains("button[title='Show Call Settings']", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"Call settings menu should not be visible on selecting a mailbox (from being open)",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
patchWithCleanup(browser, {
|
||||
navigator: {
|
||||
...browser.navigator,
|
||||
@@ -103,10 +104,10 @@ QUnit.test(
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("button[title='Show Call Settings']");
|
||||
await click("button:contains(Inbox)");
|
||||
assert.containsNone($, "button[title='Hide Call Settings']");
|
||||
assert.containsNone($, ".o-discuss-CallSettings");
|
||||
await contains("button[title='Hide Call Settings']", 0);
|
||||
await contains(".o-discuss-CallSettings", 0);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -15,32 +15,32 @@ import { nextTick, patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("call");
|
||||
|
||||
QUnit.test("basic rendering", async (assert) => {
|
||||
QUnit.test("basic rendering", async () => {
|
||||
mockGetMedia();
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
name: "General",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-Discuss-header button[title='Start a Call']");
|
||||
assert.containsOnce($, ".o-discuss-Call");
|
||||
assert.containsOnce($, ".o-discuss-CallParticipantCard[aria-label='Mitchell Admin']");
|
||||
assert.containsOnce($, ".o-discuss-CallActionList");
|
||||
assert.containsOnce($, ".o-discuss-CallMenu-buttonContent");
|
||||
assert.containsN($, ".o-discuss-CallActionList button", 5);
|
||||
assert.containsOnce($, "button[aria-label='Unmute'], button[aria-label='Mute']"); // FIXME depends on current browser permission
|
||||
assert.containsOnce($, ".o-discuss-CallActionList button[aria-label='Deafen']");
|
||||
assert.containsOnce($, ".o-discuss-CallActionList button[aria-label='Turn camera on']");
|
||||
assert.containsOnce($, "button[title='More']");
|
||||
assert.containsOnce($, ".o-discuss-CallActionList button[aria-label='Disconnect']");
|
||||
await contains(".o-discuss-Call");
|
||||
await contains(".o-discuss-CallParticipantCard[aria-label='Mitchell Admin']");
|
||||
await contains(".o-discuss-CallActionList");
|
||||
await contains(".o-discuss-CallMenu-buttonContent");
|
||||
await contains(".o-discuss-CallActionList button", 5);
|
||||
await contains("button[aria-label='Unmute'], button[aria-label='Mute']"); // FIXME depends on current browser permission
|
||||
await contains(".o-discuss-CallActionList button[aria-label='Deafen']");
|
||||
await contains(".o-discuss-CallActionList button[aria-label='Turn camera on']");
|
||||
await contains("button[title='More']");
|
||||
await contains(".o-discuss-CallActionList button[aria-label='Disconnect']");
|
||||
await click("button[title='More']");
|
||||
assert.containsOnce($, "[title='Raise Hand']");
|
||||
assert.containsOnce($, "[title='Share Screen']");
|
||||
assert.containsOnce($, "[title='Enter Full Screen']");
|
||||
await contains("[title='Raise Hand']");
|
||||
await contains("[title='Share Screen']");
|
||||
await contains("[title='Enter Full Screen']");
|
||||
});
|
||||
|
||||
QUnit.test("no call with odoobot", async (assert) => {
|
||||
QUnit.test("no call with odoobot", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
@@ -50,43 +50,37 @@ QUnit.test("no call with odoobot", async (assert) => {
|
||||
channel_type: "chat",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsNone($, ".o-mail-Discuss-header button[title='Start a Call']");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Discuss-header");
|
||||
await contains(".o-mail-Discuss-header button[title='Start a Call']", 0);
|
||||
});
|
||||
|
||||
QUnit.test("should not display call UI when no more members (self disconnect)", async (assert) => {
|
||||
QUnit.test("should not display call UI when no more members (self disconnect)", async () => {
|
||||
mockGetMedia();
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const { openDiscuss } = await start();
|
||||
openDiscuss(channelId);
|
||||
(await contains(".o-mail-Discuss-header button[title='Start a Call']")).click();
|
||||
await click(".o-mail-Discuss-header button[title='Start a Call']");
|
||||
await contains(".o-discuss-Call");
|
||||
|
||||
click(".o-discuss-CallActionList button[aria-label='Disconnect']");
|
||||
await click(".o-discuss-CallActionList button[aria-label='Disconnect']");
|
||||
await contains(".o-discuss-Call", 0);
|
||||
});
|
||||
|
||||
QUnit.test("show call UI in chat window when in call", async (assert) => {
|
||||
QUnit.test("show call UI in chat window when in call", async () => {
|
||||
mockGetMedia();
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({ name: "General" });
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem:contains(General)");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
assert.containsNone($, ".o-discuss-Call");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o-mail-ChatWindow-header .o-mail-ChatWindow-command[title='Start a Call']"
|
||||
);
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await contains(".o-discuss-Call", 0);
|
||||
await contains(".o-mail-ChatWindow-header .o-mail-ChatWindow-command[title='Start a Call']");
|
||||
|
||||
await click(".o-mail-ChatWindow-header .o-mail-ChatWindow-command[title='Start a Call']");
|
||||
assert.containsOnce($, ".o-discuss-Call");
|
||||
assert.containsNone(
|
||||
$,
|
||||
".o-mail-ChatWindow-header .o-mail-ChatWindow-command[title='Start a Call']"
|
||||
);
|
||||
await contains(".o-discuss-Call");
|
||||
await contains(".o-mail-ChatWindow-header .o-mail-ChatWindow-command[title='Start a Call']", 0);
|
||||
});
|
||||
|
||||
QUnit.test("should disconnect when closing page while in call", async (assert) => {
|
||||
@@ -94,7 +88,7 @@ QUnit.test("should disconnect when closing page while in call", async (assert) =
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
patchWithCleanup(browser, {
|
||||
navigator: {
|
||||
...browser.navigator,
|
||||
@@ -110,7 +104,7 @@ QUnit.test("should disconnect when closing page while in call", async (assert) =
|
||||
});
|
||||
|
||||
await click(".o-mail-Discuss-header button[title='Start a Call']");
|
||||
assert.containsOnce($, ".o-discuss-Call");
|
||||
await contains(".o-discuss-Call");
|
||||
// simulate page close
|
||||
await afterNextRender(() => window.dispatchEvent(new Event("pagehide"), { bubble: true }));
|
||||
await nextTick();
|
||||
@@ -140,69 +134,64 @@ QUnit.test("should display invitations", async (assert) => {
|
||||
channel_id: channelId,
|
||||
});
|
||||
await start();
|
||||
// Simulate receive call invitation
|
||||
await afterNextRender(() => {
|
||||
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "mail.record/insert", {
|
||||
Thread: {
|
||||
id: channelId,
|
||||
model: "discuss.channel",
|
||||
rtcInvitingSession: { id: sessionId, channelMember: { id: memberId } },
|
||||
},
|
||||
});
|
||||
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "mail.record/insert", {
|
||||
Thread: {
|
||||
id: channelId,
|
||||
model: "discuss.channel",
|
||||
rtcInvitingSession: { id: sessionId, channelMember: { id: memberId } },
|
||||
},
|
||||
});
|
||||
assert.containsOnce($, ".o-discuss-CallInvitation");
|
||||
await contains(".o-discuss-CallInvitation");
|
||||
assert.verifySteps(["play_sound_effect"]);
|
||||
// Simulate stop receiving call invitation
|
||||
await afterNextRender(() => {
|
||||
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "mail.record/insert", {
|
||||
Thread: {
|
||||
id: channelId,
|
||||
model: "discuss.channel",
|
||||
rtcInvitingSession: [["unlink"]],
|
||||
},
|
||||
});
|
||||
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "mail.record/insert", {
|
||||
Thread: {
|
||||
id: channelId,
|
||||
model: "discuss.channel",
|
||||
rtcInvitingSession: [["unlink"]],
|
||||
},
|
||||
});
|
||||
assert.containsNone($, ".o-discuss-CallInvitation");
|
||||
await contains(".o-discuss-CallInvitation", 0);
|
||||
assert.verifySteps(["pause_sound_effect"]);
|
||||
});
|
||||
|
||||
QUnit.test("can share screen", async (assert) => {
|
||||
QUnit.test("can share screen", async () => {
|
||||
mockGetMedia();
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
name: "General",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-Discuss-header button[title='Start a Call']");
|
||||
await click(".o-discuss-CallActionList [title='More']");
|
||||
await click("[title='Share Screen']");
|
||||
assert.containsOnce($, ".o-discuss-CallParticipantCard video");
|
||||
await contains(".o-discuss-CallParticipantCard video");
|
||||
await click(".o-discuss-CallActionList [title='More']");
|
||||
await click("[title='Stop Sharing Screen']");
|
||||
assert.containsNone($, ".o-discuss-CallParticipantCard video");
|
||||
await contains(".o-discuss-CallParticipantCard video", 0);
|
||||
});
|
||||
|
||||
QUnit.test("can share user camera", async (assert) => {
|
||||
QUnit.test("can share user camera", async () => {
|
||||
mockGetMedia();
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
name: "General",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-Discuss-header button[title='Start a Call']");
|
||||
await click(".o-discuss-CallActionList button[title='Turn camera on']");
|
||||
assert.containsOnce($, ".o-discuss-CallParticipantCard video");
|
||||
await contains(".o-discuss-CallParticipantCard video");
|
||||
await click(".o-discuss-CallActionList button[title='Stop camera']");
|
||||
assert.containsNone($, ".o-discuss-CallParticipantCard video");
|
||||
await contains(".o-discuss-CallParticipantCard video", 0);
|
||||
});
|
||||
|
||||
QUnit.test("Create a direct message channel when clicking on start a meeting", async () => {
|
||||
mockGetMedia();
|
||||
const { openDiscuss } = await start();
|
||||
openDiscuss();
|
||||
(await contains("button:contains(Start a meeting)")).click();
|
||||
await click("button:contains(Start a meeting)");
|
||||
await contains(".o-mail-DiscussSidebarChannel:contains(Mitchell Admin)");
|
||||
await contains(".o-discuss-Call");
|
||||
await contains(".o-discuss-ChannelInvitation");
|
||||
|
||||
@@ -1,33 +1,29 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { afterNextRender, click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { editInput, triggerEvent } from "@web/../tests/helpers/utils";
|
||||
import { triggerHotkey } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("call");
|
||||
|
||||
QUnit.test("no default rtc after joining a chat conversation", async (assert) => {
|
||||
QUnit.test("no default rtc after joining a chat conversation", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Mario" });
|
||||
pyEnv["res.users"].create({ partner_id: partnerId });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
|
||||
|
||||
openDiscuss();
|
||||
await click(".o-mail-DiscussSidebar i[title='Start a conversation']");
|
||||
await afterNextRender(() =>
|
||||
editInput(document.body, ".o-discuss-ChannelSelector input", "mario")
|
||||
);
|
||||
await contains(".o-mail-DiscussSidebarChannel", 0);
|
||||
await insertText(".o-discuss-ChannelSelector input", "mario");
|
||||
await click(".o-discuss-ChannelSelector-suggestion");
|
||||
await triggerEvent(document.body, ".o-discuss-ChannelSelector input", "keydown", {
|
||||
key: "Enter",
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-DiscussSidebarChannel");
|
||||
assert.containsNone($, ".o-mail-Discuss-content .o-mail-Message");
|
||||
assert.containsNone($, ".o-discuss-Call");
|
||||
await contains(".o-discuss-ChannelSelector-suggestion", 0);
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-DiscussSidebarChannel");
|
||||
await contains(".o-mail-Discuss-content .o-mail-Message", 0);
|
||||
await contains(".o-discuss-Call", 0);
|
||||
});
|
||||
|
||||
QUnit.test("no default rtc after joining a group conversation", async (assert) => {
|
||||
QUnit.test("no default rtc after joining a group conversation", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const [partnerId_1, partnerId_2] = pyEnv["res.partner"].create([
|
||||
{ name: "Mario" },
|
||||
@@ -35,21 +31,15 @@ QUnit.test("no default rtc after joining a group conversation", async (assert) =
|
||||
]);
|
||||
pyEnv["res.users"].create([{ partner_id: partnerId_1 }, { partner_id: partnerId_2 }]);
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
|
||||
openDiscuss();
|
||||
await click(".o-mail-DiscussSidebar i[title='Start a conversation']");
|
||||
await afterNextRender(() =>
|
||||
editInput(document.body, ".o-discuss-ChannelSelector input", "mario")
|
||||
);
|
||||
await click(".o-discuss-ChannelSelector-suggestion");
|
||||
await afterNextRender(() =>
|
||||
editInput(document.body, ".o-discuss-ChannelSelector input", "luigi")
|
||||
);
|
||||
await click(".o-discuss-ChannelSelector-suggestion");
|
||||
await triggerEvent(document.body, ".o-discuss-ChannelSelector input", "keydown", {
|
||||
key: "Enter",
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-DiscussSidebarChannel");
|
||||
assert.containsNone($, ".o-mail-Discuss-content .o-mail-Message");
|
||||
assert.containsNone($, ".o-discuss-Call");
|
||||
await contains(".o-mail-DiscussSidebarChannel", 0);
|
||||
await insertText(".o-discuss-ChannelSelector input", "mario");
|
||||
await click(".o-discuss-ChannelSelector-suggestion:contains(Mario)");
|
||||
await insertText(".o-discuss-ChannelSelector input", "luigi", { replace: true });
|
||||
await click(".o-discuss-ChannelSelector-suggestion:contains(Luigi)");
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-DiscussSidebarChannel");
|
||||
await contains(".o-mail-Discuss-content .o-mail-Message", 0);
|
||||
await contains(".o-discuss-Call", 0);
|
||||
});
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Command } from "@mail/../tests/helpers/command";
|
||||
import { click, insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
QUnit.module("channel invitation form");
|
||||
|
||||
QUnit.test(
|
||||
"should display the channel invitation form after clicking on the invite button of a chat",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({
|
||||
email: "testpartner@odoo.com",
|
||||
@@ -23,13 +23,13 @@ QUnit.test(
|
||||
channel_type: "channel",
|
||||
});
|
||||
const { openDiscuss } = await start({ hasTimeControl: true });
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-Discuss-header button[title='Add Users']");
|
||||
assert.containsOnce($, ".o-discuss-ChannelInvitation");
|
||||
await contains(".o-discuss-ChannelInvitation");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("can invite users in channel from chat window", async (assert) => {
|
||||
QUnit.test("can invite users in channel from chat window", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({
|
||||
email: "testpartner@odoo.com",
|
||||
@@ -46,49 +46,45 @@ QUnit.test("can invite users in channel from chat window", async (assert) => {
|
||||
await start();
|
||||
await click("[title='Open Actions Menu']");
|
||||
await click("[title='Add Users']");
|
||||
assert.containsOnce($, ".o-discuss-ChannelInvitation");
|
||||
await contains(".o-discuss-ChannelInvitation");
|
||||
await click(
|
||||
".o-discuss-ChannelInvitation-selectable:contains(TestPartner) input[type='checkbox']"
|
||||
);
|
||||
await click("[title='Invite to Channel']");
|
||||
assert.containsNone($, ".o-discuss-ChannelInvitation");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
await click("[title='Invite to Channel']:not(:disabled)");
|
||||
await contains(".o-discuss-ChannelInvitation", 0);
|
||||
await contains(
|
||||
".o-mail-Thread .o-mail-NotificationMessage:contains(Mitchell Admin invited TestPartner to the channel)"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"should be able to search for a new user to invite from an existing chat",
|
||||
async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId_1 = pyEnv["res.partner"].create({
|
||||
email: "testpartner@odoo.com",
|
||||
name: "TestPartner",
|
||||
});
|
||||
const partnerId_2 = pyEnv["res.partner"].create({
|
||||
email: "testpartner2@odoo.com",
|
||||
name: "TestPartner2",
|
||||
});
|
||||
pyEnv["res.users"].create({ partner_id: partnerId_1 });
|
||||
pyEnv["res.users"].create({ partner_id: partnerId_2 });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
name: "TestChanel",
|
||||
channel_member_ids: [
|
||||
Command.create({ partner_id: pyEnv.currentPartnerId }),
|
||||
Command.create({ partner_id: partnerId_1 }),
|
||||
],
|
||||
channel_type: "channel",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
await click(".o-mail-Discuss-header button[title='Add Users']");
|
||||
await insertText(".o-discuss-ChannelInvitation-search", "TestPartner2");
|
||||
assert.strictEqual($(".o-discuss-ChannelInvitation-selectable").text(), "TestPartner2");
|
||||
}
|
||||
);
|
||||
QUnit.test("should be able to search for a new user to invite from an existing chat", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId_1 = pyEnv["res.partner"].create({
|
||||
email: "testpartner@odoo.com",
|
||||
name: "TestPartner",
|
||||
});
|
||||
const partnerId_2 = pyEnv["res.partner"].create({
|
||||
email: "testpartner2@odoo.com",
|
||||
name: "TestPartner2",
|
||||
});
|
||||
pyEnv["res.users"].create({ partner_id: partnerId_1 });
|
||||
pyEnv["res.users"].create({ partner_id: partnerId_2 });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
name: "TestChanel",
|
||||
channel_member_ids: [
|
||||
Command.create({ partner_id: pyEnv.currentPartnerId }),
|
||||
Command.create({ partner_id: partnerId_1 }),
|
||||
],
|
||||
channel_type: "channel",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-Discuss-header button[title='Add Users']");
|
||||
await insertText(".o-discuss-ChannelInvitation-search", "TestPartner2");
|
||||
await contains(".o-discuss-ChannelInvitation-selectable:contains(TestPartner2)");
|
||||
});
|
||||
|
||||
QUnit.test("Invitation form should display channel group restriction", async (assert) => {
|
||||
QUnit.test("Invitation form should display channel group restriction", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({
|
||||
email: "testpartner@odoo.com",
|
||||
@@ -105,15 +101,12 @@ QUnit.test("Invitation form should display channel group restriction", async (as
|
||||
group_public_id: groupId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-Discuss-header button[title='Add Users']");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
'.o-discuss-ChannelInvitation:contains(Access restricted to group "testGroup")'
|
||||
);
|
||||
await contains('.o-discuss-ChannelInvitation:contains(Access restricted to group "testGroup")');
|
||||
});
|
||||
|
||||
QUnit.test("should be able to create a new group chat from an existing chat", async (assert) => {
|
||||
QUnit.test("should be able to create a new group chat from an existing chat", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId_1 = pyEnv["res.partner"].create({
|
||||
email: "testpartner@odoo.com",
|
||||
@@ -134,13 +127,12 @@ QUnit.test("should be able to create a new group chat from an existing chat", as
|
||||
channel_type: "chat",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-Discuss-header button[title='Add Users']");
|
||||
await insertText(".o-discuss-ChannelInvitation-search", "TestPartner2");
|
||||
await click(".form-check-input");
|
||||
await click("button[title='Create Group Chat']");
|
||||
assert.strictEqual(
|
||||
$(".o-mail-Discuss-threadName").val(),
|
||||
"Mitchell Admin, TestPartner, and TestPartner2"
|
||||
await click(".o-discuss-ChannelInvitation-selectable:contains(TestPartner2)");
|
||||
await click("button[title='Create Group Chat']:not(:disabled)");
|
||||
await contains(
|
||||
".o-mail-DiscussSidebarChannel:contains(Mitchell Admin, TestPartner, and TestPartner2)"
|
||||
);
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { createLocalId } from "@mail/utils/common/misc";
|
||||
import { Command } from "@mail/../tests/helpers/command";
|
||||
import { click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { nextTick } from "@web/../tests/helpers/utils";
|
||||
|
||||
@@ -10,7 +10,7 @@ QUnit.module("channel member list");
|
||||
|
||||
QUnit.test(
|
||||
"there should be a button to show member list in the thread view topbar initially",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo" });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
@@ -22,14 +22,14 @@ QUnit.test(
|
||||
channel_type: "channel",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, "[title='Show Member List']");
|
||||
openDiscuss(channelId);
|
||||
await contains("[title='Show Member List']");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"should show member list when clicking on show member list button in thread view topbar",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo" });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
@@ -41,13 +41,13 @@ QUnit.test(
|
||||
channel_type: "channel",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("[title='Show Member List']");
|
||||
assert.containsOnce($, ".o-discuss-ChannelMemberList");
|
||||
await contains(".o-discuss-ChannelMemberList");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("should have correct members in member list", async (assert) => {
|
||||
QUnit.test("should have correct members in member list", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo" });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
@@ -59,16 +59,16 @@ QUnit.test("should have correct members in member list", async (assert) => {
|
||||
channel_type: "channel",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("[title='Show Member List']");
|
||||
assert.containsN($, ".o-discuss-ChannelMember", 2);
|
||||
assert.containsOnce($, `.o-discuss-ChannelMember:contains("${pyEnv.currentPartner.name}")`);
|
||||
assert.containsOnce($, ".o-discuss-ChannelMember:contains('Demo')");
|
||||
await contains(".o-discuss-ChannelMember", 2);
|
||||
await contains(`.o-discuss-ChannelMember:contains("${pyEnv.currentPartner.name}")`);
|
||||
await contains(".o-discuss-ChannelMember:contains('Demo')");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"there should be a button to hide member list in the thread view topbar when the member list is visible",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo" });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
@@ -80,9 +80,9 @@ QUnit.test(
|
||||
channel_type: "channel",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("[title='Show Member List']");
|
||||
assert.containsOnce($, "[title='Hide Member List']");
|
||||
await contains("[title='Hide Member List']");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -99,33 +99,30 @@ QUnit.test("chat with member should be opened after clicking on channel member",
|
||||
channel_type: "channel",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("[title='Show Member List']");
|
||||
await click(".o-discuss-ChannelMember.cursor-pointer");
|
||||
assert.containsOnce($, ".o-mail-AutoresizeInput[title='Demo']");
|
||||
await contains(".o-mail-AutoresizeInput[title='Demo']");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"should show a button to load more members if they are not all loaded",
|
||||
async (assert) => {
|
||||
// Test assumes at most 100 members are loaded at once.
|
||||
const pyEnv = await startServer();
|
||||
const channel_member_ids = [];
|
||||
for (let i = 0; i < 101; i++) {
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "name" + i });
|
||||
channel_member_ids.push(Command.create({ partner_id: partnerId }));
|
||||
}
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
name: "TestChanel",
|
||||
channel_type: "channel",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
pyEnv["discuss.channel"].write([channelId], { channel_member_ids });
|
||||
await click("[title='Show Member List']");
|
||||
assert.containsOnce($, "button:contains(Load more)");
|
||||
QUnit.test("should show a button to load more members if they are not all loaded", async () => {
|
||||
// Test assumes at most 100 members are loaded at once.
|
||||
const pyEnv = await startServer();
|
||||
const channel_member_ids = [];
|
||||
for (let i = 0; i < 101; i++) {
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "name" + i });
|
||||
channel_member_ids.push(Command.create({ partner_id: partnerId }));
|
||||
}
|
||||
);
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
name: "TestChanel",
|
||||
channel_type: "channel",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
openDiscuss(channelId);
|
||||
pyEnv["discuss.channel"].write([channelId], { channel_member_ids });
|
||||
await click("[title='Show Member List']");
|
||||
await contains("button:contains(Load more)");
|
||||
});
|
||||
|
||||
QUnit.test("Load more button should load more members", async (assert) => {
|
||||
// Test assumes at most 100 members are loaded at once.
|
||||
@@ -140,11 +137,11 @@ QUnit.test("Load more button should load more members", async (assert) => {
|
||||
channel_type: "channel",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
pyEnv["discuss.channel"].write([channelId], { channel_member_ids });
|
||||
await click("[title='Show Member List']");
|
||||
await click("[title='Load more']");
|
||||
assert.containsN($, ".o-discuss-ChannelMember", 102);
|
||||
await contains(".o-discuss-ChannelMember", 102);
|
||||
});
|
||||
|
||||
QUnit.test("Channel member count update after user joined", async (assert) => {
|
||||
@@ -152,15 +149,16 @@ QUnit.test("Channel member count update after user joined", async (assert) => {
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const userId = pyEnv["res.users"].create({ name: "Harry" });
|
||||
pyEnv["res.partner"].create({ name: "Harry", user_ids: [userId] });
|
||||
const { env, openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
const thread = env.services["mail.store"].threads[createLocalId("discuss.channel", channelId)];
|
||||
assert.strictEqual(thread.memberCount, 1);
|
||||
const { openDiscuss } = await start();
|
||||
openDiscuss(channelId);
|
||||
await click("[title='Show Member List']");
|
||||
await contains(".o-discuss-ChannelMemberList:contains(Offline - 1)");
|
||||
await click("[title='Add Users']");
|
||||
await click(".o-discuss-ChannelInvitation-selectable:contains(Harry)");
|
||||
await click("[title='Invite to Channel']");
|
||||
assert.strictEqual(thread.memberCount, 2);
|
||||
await click("[title='Invite to Channel']:not(:disabled)");
|
||||
await contains(".o-discuss-ChannelInvitation", 0);
|
||||
await click("[title='Show Member List']");
|
||||
await contains(".o-discuss-ChannelMemberList:contains(Offline - 2)");
|
||||
});
|
||||
|
||||
QUnit.test("Channel member count update after user left", async (assert) => {
|
||||
@@ -175,7 +173,7 @@ QUnit.test("Channel member count update after user left", async (assert) => {
|
||||
],
|
||||
});
|
||||
const { env, openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
const thread = env.services["mail.store"].threads[createLocalId("discuss.channel", channelId)];
|
||||
assert.strictEqual(thread.memberCount, 2);
|
||||
await pyEnv.withUser(userId, () =>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Composer } from "@mail/core/common/composer";
|
||||
import { click, insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
|
||||
@@ -26,7 +26,7 @@ QUnit.test('do not send typing notification on typing "/" command', async (asser
|
||||
}
|
||||
},
|
||||
});
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "/");
|
||||
assert.verifySteps([], "No rpc done");
|
||||
});
|
||||
@@ -43,9 +43,10 @@ QUnit.test(
|
||||
}
|
||||
},
|
||||
});
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "/");
|
||||
await click(".o-mail-Composer-suggestion");
|
||||
await click(".o-mail-Composer-suggestion:eq(0)");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
await insertText(".o-mail-Composer-input", " is user?");
|
||||
assert.verifySteps([], "No rpc done");
|
||||
}
|
||||
@@ -58,11 +59,11 @@ QUnit.test("add an emoji after a command", async (assert) => {
|
||||
channel_type: "channel",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsNone($, ".o-mail-Composer-suggestionList .o-open");
|
||||
assert.strictEqual($(".o-mail-Composer-input").val(), "");
|
||||
openDiscuss(channelId);
|
||||
assert.strictEqual((await contains(".o-mail-Composer-input")).val(), "");
|
||||
await insertText(".o-mail-Composer-input", "/");
|
||||
await click(".o-mail-Composer-suggestion");
|
||||
await click(".o-mail-Composer-suggestion:eq(0)");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
assert.strictEqual(
|
||||
$(".o-mail-Composer-input").val().replace(/\s/, " "),
|
||||
"/who ",
|
||||
@@ -71,5 +72,6 @@ QUnit.test("add an emoji after a command", async (assert) => {
|
||||
|
||||
await click("button[aria-label='Emojis']");
|
||||
await click(".o-Emoji:contains(😊)");
|
||||
await contains(".o-Emoji", 0);
|
||||
assert.strictEqual($(".o-mail-Composer-input").val().replace(/\s/, " "), "/who 😊");
|
||||
});
|
||||
|
||||
@@ -1,27 +1,28 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Command } from "@mail/../tests/helpers/command";
|
||||
import { click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
QUnit.module("crosstab");
|
||||
|
||||
QUnit.test("Add member to channel", async (assert) => {
|
||||
QUnit.test("Add member to channel", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const userId = pyEnv["res.users"].create({ name: "Harry" });
|
||||
pyEnv["res.partner"].create({ name: "Harry", user_ids: [userId] });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("[title='Show Member List']");
|
||||
assert.containsOnce($, ".o-discuss-ChannelMember:contains(Mitchell Admin)");
|
||||
await contains(".o-discuss-ChannelMember:contains(Mitchell Admin)");
|
||||
await click("[title='Add Users']");
|
||||
await click(".o-discuss-ChannelInvitation-selectable:contains(Harry)");
|
||||
await click("[title='Invite to Channel']");
|
||||
await click("[title='Invite to Channel']:not(:disabled)");
|
||||
await contains(".o-discuss-ChannelInvitation", 0);
|
||||
await click("[title='Show Member List']");
|
||||
assert.containsOnce($, ".o-discuss-ChannelMember:contains(Harry)");
|
||||
await contains(".o-discuss-ChannelMember:contains(Harry)");
|
||||
});
|
||||
|
||||
QUnit.test("Remove member from channel", async (assert) => {
|
||||
QUnit.test("Remove member from channel", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const userId = pyEnv["res.users"].create({ name: "Harry" });
|
||||
const partnerId = pyEnv["res.partner"].create({
|
||||
@@ -36,10 +37,11 @@ QUnit.test("Remove member from channel", async (assert) => {
|
||||
],
|
||||
});
|
||||
const { env, openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("[title='Show Member List']");
|
||||
assert.containsOnce($, ".o-discuss-ChannelMember:contains(Harry)");
|
||||
await contains(".o-discuss-ChannelMember:contains(Harry)");
|
||||
pyEnv.withUser(userId, () =>
|
||||
env.services.orm.call("discuss.channel", "action_unfollow", [channelId])
|
||||
);
|
||||
await contains(".o-discuss-ChannelMember:contains(Harry)", 0);
|
||||
});
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
QUnit.module("discuss");
|
||||
|
||||
QUnit.test("Member list and settings menu are exclusive", async (assert) => {
|
||||
QUnit.test("Member list and settings menu are exclusive", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("[title='Show Member List']");
|
||||
assert.containsOnce($, ".o-discuss-ChannelMemberList");
|
||||
await contains(".o-discuss-ChannelMemberList");
|
||||
await click("[title='Show Call Settings']");
|
||||
assert.containsOnce($, ".o-discuss-CallSettings");
|
||||
assert.containsNone($, ".o-discuss-ChannelMemberList");
|
||||
await contains(".o-discuss-CallSettings");
|
||||
await contains(".o-discuss-ChannelMemberList", 0);
|
||||
});
|
||||
|
||||
@@ -2,13 +2,7 @@
|
||||
|
||||
import { Composer } from "@mail/core/common/composer";
|
||||
import { Command } from "@mail/../tests/helpers/command";
|
||||
import {
|
||||
afterNextRender,
|
||||
click,
|
||||
insertText,
|
||||
start,
|
||||
startServer,
|
||||
} from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
|
||||
@@ -23,28 +17,31 @@ QUnit.module("suggestion", {
|
||||
},
|
||||
});
|
||||
|
||||
QUnit.test('display command suggestions on typing "/"', async (assert) => {
|
||||
QUnit.test('display command suggestions on typing "/"', async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
name: "General",
|
||||
channel_type: "channel",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsNone($, ".o-mail-Composer-suggestionList .o-open");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Composer-suggestionList");
|
||||
await contains(".o-mail-Composer-suggestionList .o-open", 0);
|
||||
await insertText(".o-mail-Composer-input", "/");
|
||||
assert.containsOnce($, ".o-mail-Composer-suggestionList .o-open");
|
||||
await contains(".o-mail-Composer-suggestionList .o-open");
|
||||
});
|
||||
|
||||
QUnit.test("use a command for a specific channel type", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ channel_type: "chat" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsNone($, ".o-mail-Composer-suggestionList .o-open");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Composer-suggestionList");
|
||||
await contains(".o-mail-Composer-suggestionList .o-open", 0);
|
||||
assert.strictEqual($(".o-mail-Composer-input").val(), "");
|
||||
await insertText(".o-mail-Composer-input", "/");
|
||||
await click(".o-mail-Composer-suggestion");
|
||||
await click(".o-mail-Composer-suggestion:eq(0)");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
assert.strictEqual(
|
||||
$(".o-mail-Composer-input").val().replace(/\s/, " "),
|
||||
"/who ",
|
||||
@@ -61,13 +58,14 @@ QUnit.test(
|
||||
channel_type: "channel",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsNone($, ".o-mail-Composer-suggestionList .o-open");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Composer-suggestionList");
|
||||
await contains(".o-mail-Composer-suggestionList .o-open", 0);
|
||||
assert.strictEqual($(".o-mail-Composer-input").val(), "");
|
||||
await insertText(".o-mail-Composer-input", "bluhbluh ");
|
||||
assert.strictEqual($(".o-mail-Composer-input").val(), "bluhbluh ");
|
||||
await insertText(".o-mail-Composer-input", "/");
|
||||
assert.containsNone($, ".o-mail-Composer-suggestionList .o-open");
|
||||
await contains(".o-mail-Composer-suggestionList .o-open", 0);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -117,21 +115,21 @@ QUnit.test("Sort partner suggestions by recent chats", async (assert) => {
|
||||
},
|
||||
]);
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
openDiscuss();
|
||||
await click(".o-mail-DiscussSidebarChannel:contains('User 2')");
|
||||
await insertText(".o-mail-Composer-input", "This is a test");
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
assert.containsOnce($, ".o-mail-Message:contains('This is a test')");
|
||||
await contains(".o-mail-Message:contains('This is a test')");
|
||||
await click(".o-mail-DiscussSidebarChannel:contains('General')");
|
||||
await insertText(".o-mail-Composer-input", "@");
|
||||
await insertText(".o-mail-Composer-input[placeholder='Message #General…']", "@");
|
||||
await insertText(".o-mail-Composer-input", "User");
|
||||
assert.containsN($, ".o-mail-Composer-suggestion", 3);
|
||||
await contains(".o-mail-Composer-suggestion", 3);
|
||||
assert.strictEqual($(".o-mail-Composer-suggestion").eq(0).text(), "User 2");
|
||||
assert.strictEqual($(".o-mail-Composer-suggestion").eq(1).text(), "User 1");
|
||||
assert.strictEqual($(".o-mail-Composer-suggestion").eq(2).text(), "User 3");
|
||||
});
|
||||
|
||||
QUnit.test("suggestion are shown after deleting a character", async (assert) => {
|
||||
QUnit.test("mention suggestion are shown after deleting a character", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "John Doe" });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
@@ -144,13 +142,35 @@ QUnit.test("suggestion are shown after deleting a character", async (assert) =>
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "@");
|
||||
await insertText(".o-mail-Composer-input", "John Da");
|
||||
assert.containsNone($, ".o-mail-Composer-suggestion:contains(John Doe)");
|
||||
await insertText(".o-mail-Composer-input", "@John D");
|
||||
await contains(".o-mail-Composer-suggestion:contains(John Doe)");
|
||||
await insertText(".o-mail-Composer-input", "a");
|
||||
await contains(".o-mail-Composer-suggestion:contains(John D)", 0);
|
||||
// Simulate pressing backspace
|
||||
await afterNextRender(() => {
|
||||
const textarea = document.querySelector(".o-mail-Composer-input");
|
||||
textarea.value = textarea.value.slice(0, -1);
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Composer-suggestion:contains(John Doe)");
|
||||
const textarea = document.querySelector(".o-mail-Composer-input");
|
||||
textarea.value = textarea.value.slice(0, -1);
|
||||
await contains(".o-mail-Composer-suggestion:contains(John Doe)");
|
||||
});
|
||||
|
||||
QUnit.test("command suggestion are shown after deleting a character", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "John Doe" });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
name: "General",
|
||||
channel_type: "channel",
|
||||
channel_member_ids: [
|
||||
Command.create({ partner_id: pyEnv.currentPartnerId }),
|
||||
Command.create({ partner_id: partnerId }),
|
||||
],
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "/he");
|
||||
await contains(".o-mail-Composer-suggestion:contains(help)");
|
||||
await insertText(".o-mail-Composer-input", "e");
|
||||
await contains(".o-mail-Composer-suggestion:contains(help)", 0);
|
||||
// Simulate pressing backspace
|
||||
const textarea = document.querySelector(".o-mail-Composer-input");
|
||||
textarea.value = textarea.value.slice(0, -1);
|
||||
await contains(".o-mail-Composer-suggestion:contains(help)");
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@ import { patchUiSize } from "@mail/../tests/helpers/patch_ui_size";
|
||||
import {
|
||||
afterNextRender,
|
||||
click,
|
||||
contains,
|
||||
insertText,
|
||||
start,
|
||||
startServer,
|
||||
@@ -23,55 +24,52 @@ QUnit.test("basic rendering", async (assert) => {
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click("button:contains(New Message)");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-header");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-header .o-mail-ChatWindow-name");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow-header");
|
||||
await contains(".o-mail-ChatWindow-header .o-mail-ChatWindow-name");
|
||||
assert.strictEqual(
|
||||
$(".o-mail-ChatWindow-header .o-mail-ChatWindow-name").text(),
|
||||
"New message"
|
||||
);
|
||||
assert.containsN($, ".o-mail-ChatWindow-header .o-mail-ChatWindow-command", 2);
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-header .o-mail-ChatWindow-command[title='Fold']");
|
||||
await contains(".o-mail-ChatWindow-header .o-mail-ChatWindow-command", 2);
|
||||
await contains(".o-mail-ChatWindow-header .o-mail-ChatWindow-command[title='Fold']");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o-mail-ChatWindow-header .o-mail-ChatWindow-command[title='Close Chat Window']"
|
||||
);
|
||||
assert.containsOnce($, "span:contains('To :')");
|
||||
assert.containsOnce($, ".o-discuss-ChannelSelector");
|
||||
await contains("span:contains('To :')");
|
||||
await contains(".o-discuss-ChannelSelector");
|
||||
});
|
||||
|
||||
QUnit.test("focused on open [REQUIRE FOCUS]", async (assert) => {
|
||||
QUnit.test("focused on open [REQUIRE FOCUS]", async () => {
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click("button:contains(New Message)");
|
||||
assert.strictEqual(
|
||||
document.activeElement,
|
||||
$(".o-mail-ChatWindow .o-discuss-ChannelSelector input")[0]
|
||||
);
|
||||
await contains(".o-mail-ChatWindow .o-discuss-ChannelSelector input:focus");
|
||||
});
|
||||
|
||||
QUnit.test("close", async (assert) => {
|
||||
QUnit.test("close", async () => {
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click("button:contains(New Message)");
|
||||
await click(".o-mail-ChatWindow-header .o-mail-ChatWindow-command[title='Close Chat Window']");
|
||||
assert.containsNone($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow", 0);
|
||||
});
|
||||
|
||||
QUnit.test("fold", async (assert) => {
|
||||
QUnit.test("fold", async () => {
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click("button:contains(New Message)");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-content");
|
||||
assert.containsOnce($, ".o-discuss-ChannelSelector");
|
||||
await contains(".o-mail-ChatWindow-content");
|
||||
await contains(".o-discuss-ChannelSelector");
|
||||
|
||||
await click(".o-mail-ChatWindow-command[title='Fold']");
|
||||
assert.containsNone($, ".o-mail-ChatWindow .o-mail-ChatWindow-content");
|
||||
assert.containsNone($, ".o-mail-ChatWindow .o-discuss-ChannelSelector");
|
||||
await contains(".o-mail-ChatWindow .o-mail-ChatWindow-content", 0);
|
||||
await contains(".o-mail-ChatWindow .o-discuss-ChannelSelector", 0);
|
||||
|
||||
await click(".o-mail-ChatWindow-command[title='Open']");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow .o-mail-ChatWindow-content");
|
||||
assert.containsOnce($, ".o-discuss-ChannelSelector");
|
||||
await contains(".o-mail-ChatWindow .o-mail-ChatWindow-content");
|
||||
await contains(".o-discuss-ChannelSelector");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
@@ -110,14 +108,12 @@ QUnit.test(
|
||||
}
|
||||
},
|
||||
});
|
||||
assert.containsNone($, ".o-mail-ChatWindow-header:contains(New message)");
|
||||
|
||||
// open "new message" chat window
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click("button:contains(New Message)");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-header:contains(New message)");
|
||||
assert.containsN($, ".o-mail-ChatWindow", 2);
|
||||
assert.containsOnce($, ".o-mail-ChatWindow .o-discuss-ChannelSelector");
|
||||
await contains(".o-mail-ChatWindow-header:contains(New message)");
|
||||
await contains(".o-mail-ChatWindow", 2);
|
||||
await contains(".o-mail-ChatWindow .o-discuss-ChannelSelector");
|
||||
assert.ok(
|
||||
Array.from(document.querySelectorAll(".o-mail-ChatWindow"))
|
||||
.pop()
|
||||
@@ -127,7 +123,7 @@ QUnit.test(
|
||||
// open channel-2
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem .o-mail-NotificationItem-name:contains(channel-2)");
|
||||
assert.containsN($, ".o-mail-ChatWindow", 3);
|
||||
await contains(".o-mail-ChatWindow", 3);
|
||||
assert.ok(
|
||||
Array.from(document.querySelectorAll(".o-mail-ChatWindow"))[1].textContent.includes(
|
||||
"New message"
|
||||
@@ -139,19 +135,19 @@ QUnit.test(
|
||||
await insertText(".o-discuss-ChannelSelector input", "131");
|
||||
await imSearchDef;
|
||||
});
|
||||
assert.containsOnce($, ".o-discuss-ChannelSelector-suggestion a");
|
||||
await contains(".o-discuss-ChannelSelector-suggestion a");
|
||||
const $link = $(".o-discuss-ChannelSelector-suggestion a");
|
||||
assert.strictEqual($link.text(), "Partner 131");
|
||||
|
||||
await click($link);
|
||||
assert.containsNone($, ".o-mail-ChatWindow-header:contains(New message)");
|
||||
await contains(".o-mail-ChatWindow-header:contains(New message)", 0);
|
||||
assert.strictEqual($(".o-mail-ChatWindow-name:eq(1)").text(), "Partner 131");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"new message chat window should close on selecting the user if chat with the user is already open",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Partner 131" });
|
||||
pyEnv["res.users"].create({ partner_id: partnerId });
|
||||
@@ -176,30 +172,18 @@ QUnit.test(
|
||||
await click("button:contains(New Message)");
|
||||
await insertText(".o-discuss-ChannelSelector", "131");
|
||||
await click(".o-discuss-ChannelSelector-suggestion a");
|
||||
assert.containsNone($, ".o-mail-ChatWindow-header:contains(New message)");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow-header:contains(New message)", 0);
|
||||
await contains(".o-mail-ChatWindow");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("new message autocomplete should automatically select first result", async (assert) => {
|
||||
QUnit.test("new message autocomplete should automatically select first result", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Partner 131" });
|
||||
pyEnv["res.users"].create({ partner_id: partnerId });
|
||||
const imSearchDef = makeDeferred();
|
||||
await start({
|
||||
mockRPC(route, args) {
|
||||
if (args.method === "im_search") {
|
||||
imSearchDef.resolve();
|
||||
}
|
||||
},
|
||||
});
|
||||
// open "new message" chat window
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click("button:contains(New Message)");
|
||||
// search for a user in "new message" autocomplete
|
||||
await afterNextRender(async () => {
|
||||
await insertText(".o-discuss-ChannelSelector", "131");
|
||||
await imSearchDef;
|
||||
});
|
||||
assert.hasClass($(".o-discuss-ChannelSelector-suggestion a"), "o-mail-NavigableList-active");
|
||||
await insertText(".o-discuss-ChannelSelector", "131");
|
||||
await contains(".o-discuss-ChannelSelector-suggestion a.o-mail-NavigableList-active");
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { afterNextRender, click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { Command } from "@mail/../tests/helpers/command";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { commandService } from "@web/core/commands/command_service";
|
||||
import { registry } from "@web/core/registry";
|
||||
@@ -22,18 +22,18 @@ QUnit.module("command palette", {
|
||||
},
|
||||
});
|
||||
|
||||
QUnit.test("open the chatWindow of a user from the command palette", async (assert) => {
|
||||
QUnit.test("open the chatWindow of a user from the command palette", async () => {
|
||||
const { advanceTime } = await start({ hasTimeControl: true });
|
||||
triggerHotkey("control+k");
|
||||
await nextTick();
|
||||
// Switch to partners
|
||||
await editSearchBar("@");
|
||||
await afterNextRender(() => advanceTime(commandSetupRegistry.get("@").debounceDelay));
|
||||
advanceTime(commandSetupRegistry.get("@").debounceDelay);
|
||||
await click(".o_command.focused");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
});
|
||||
|
||||
QUnit.test("open the chatWindow of a channel from the command palette", async (assert) => {
|
||||
QUnit.test("open the chatWindow of a channel from the command palette", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({ name: "general" });
|
||||
pyEnv["discuss.channel"].create({ name: "project" });
|
||||
@@ -42,16 +42,16 @@ QUnit.test("open the chatWindow of a channel from the command palette", async (a
|
||||
await nextTick();
|
||||
// Switch to channels
|
||||
await editSearchBar("#");
|
||||
await afterNextRender(() => advanceTime(commandSetupRegistry.get("#").debounceDelay));
|
||||
assert.containsOnce($, ".o_command:contains(general)");
|
||||
assert.containsOnce($, ".o_command:contains(project)");
|
||||
advanceTime(commandSetupRegistry.get("#").debounceDelay);
|
||||
await contains(".o_command:contains(general)");
|
||||
await contains(".o_command:contains(project)");
|
||||
|
||||
await click(".o_command.focused");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-name:contains(general)");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow-name:contains(general)");
|
||||
});
|
||||
|
||||
QUnit.test("Channel mentions in the command palette of Discuss app with @", async (assert) => {
|
||||
QUnit.test("Channel mentions in the command palette of Discuss app with @", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Mario" });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
@@ -77,40 +77,33 @@ QUnit.test("Channel mentions in the command palette of Discuss app with @", asyn
|
||||
triggerHotkey("control+k");
|
||||
await nextTick();
|
||||
await editSearchBar("@");
|
||||
await afterNextRender(() => advanceTime(commandSetupRegistry.get("@").debounceDelay));
|
||||
assert.containsOnce($, ".o_command_palette:contains('Mentions')");
|
||||
assert.containsOnce(
|
||||
$(".o_command_category:contains('Mentions')"),
|
||||
".o_command:contains('Mitchell Admin and Mario')"
|
||||
advanceTime(commandSetupRegistry.get("@").debounceDelay);
|
||||
await contains(".o_command_palette:contains('Mentions')");
|
||||
await contains(
|
||||
".o_command_category:contains('Mentions') .o_command:contains('Mitchell Admin and Mario')"
|
||||
);
|
||||
assert.containsOnce(
|
||||
$(".o_command_category:not(:contains('Mentions'))"),
|
||||
".o_command:contains('Mario')"
|
||||
await contains(
|
||||
$(".o_command_category:not(:contains('Mentions')) .o_command:contains('Mario')")
|
||||
);
|
||||
assert.containsOnce(
|
||||
$(".o_command_category:not(:contains('Mentions'))"),
|
||||
".o_command:contains('Mitchell Admin')"
|
||||
await contains(
|
||||
$(".o_command_category:not(:contains('Mentions')) .o_command:contains('Mitchell Admin')")
|
||||
);
|
||||
assert.containsOnce($, ".o_command.focused:contains('Mitchell Admin and Mario')");
|
||||
|
||||
await contains(".o_command.focused:contains('Mitchell Admin and Mario')");
|
||||
await click(".o_command.focused");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow:contains('Mitchell Admin and Mario')");
|
||||
await contains(".o-mail-ChatWindow:contains('Mitchell Admin and Mario')");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"Max 3 most recent channels in command palette of Discuss app with #",
|
||||
async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({ name: "channel_1" });
|
||||
pyEnv["discuss.channel"].create({ name: "channel_2" });
|
||||
pyEnv["discuss.channel"].create({ name: "channel_3" });
|
||||
pyEnv["discuss.channel"].create({ name: "channel_4" });
|
||||
const { advanceTime } = await start({ hasTimeControl: true });
|
||||
triggerHotkey("control+k");
|
||||
await nextTick();
|
||||
await editSearchBar("#");
|
||||
await afterNextRender(() => advanceTime(commandSetupRegistry.get("#").debounceDelay));
|
||||
assert.containsOnce($, ".o_command_palette:contains('Recent')");
|
||||
assert.containsN($(".o_command_category:contains('Recent')"), ".o_command", 3);
|
||||
}
|
||||
);
|
||||
QUnit.test("Max 3 most recent channels in command palette of Discuss app with #", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({ name: "channel_1" });
|
||||
pyEnv["discuss.channel"].create({ name: "channel_2" });
|
||||
pyEnv["discuss.channel"].create({ name: "channel_3" });
|
||||
pyEnv["discuss.channel"].create({ name: "channel_4" });
|
||||
const { advanceTime } = await start({ hasTimeControl: true });
|
||||
triggerHotkey("control+k");
|
||||
await nextTick();
|
||||
await editSearchBar("#");
|
||||
advanceTime(commandSetupRegistry.get("#").debounceDelay);
|
||||
await contains(".o_command_palette:contains('Recent')");
|
||||
await contains(".o_command_category:contains('Recent') .o_command", 3);
|
||||
});
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import {
|
||||
afterNextRender,
|
||||
click,
|
||||
insertText,
|
||||
start,
|
||||
startServer,
|
||||
} from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { triggerHotkey, patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
import { patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("crosstab");
|
||||
|
||||
@@ -21,9 +15,11 @@ QUnit.test("Channel subscription is renewed when channel is manually added", asy
|
||||
assert.step("update-channels");
|
||||
},
|
||||
});
|
||||
await openDiscuss();
|
||||
openDiscuss();
|
||||
await click("[title='Add or join a channel']");
|
||||
await insertText(".o-discuss-ChannelSelector", "General");
|
||||
await afterNextRender(() => triggerHotkey("Enter"));
|
||||
await click(".o-discuss-ChannelSelector-suggestion:eq(0)");
|
||||
await contains(".o-mail-DiscussSidebarChannel", 1);
|
||||
await new Promise((resolve) => setTimeout(resolve)); // update of channels is debounced
|
||||
assert.verifySteps(["update-channels"]);
|
||||
});
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import {
|
||||
afterNextRender,
|
||||
click,
|
||||
insertText,
|
||||
start,
|
||||
startServer,
|
||||
} from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { editInput, triggerEvent, triggerHotkey } from "@web/../tests/helpers/utils";
|
||||
import { triggerHotkey } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("discuss");
|
||||
|
||||
@@ -28,16 +22,13 @@ QUnit.test("can create a new channel [REQUIRE FOCUS]", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
await openDiscuss();
|
||||
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
|
||||
|
||||
openDiscuss();
|
||||
await click(".o-mail-DiscussSidebar i[title='Add or join a channel']");
|
||||
await afterNextRender(() =>
|
||||
editInput(document.body, ".o-discuss-ChannelSelector input", "abc")
|
||||
);
|
||||
await contains(".o-mail-DiscussSidebarChannel", 0);
|
||||
await insertText(".o-discuss-ChannelSelector input", "abc");
|
||||
await click(".o-discuss-ChannelSelector-suggestion");
|
||||
assert.containsOnce($, ".o-mail-DiscussSidebarChannel");
|
||||
assert.containsNone($, ".o-mail-Discuss-content .o-mail-Message");
|
||||
await contains(".o-mail-DiscussSidebarChannel");
|
||||
await contains(".o-mail-Discuss-content .o-mail-Message", 0);
|
||||
assert.verifySteps([
|
||||
"/mail/init_messaging",
|
||||
"/mail/load_message_failures",
|
||||
@@ -50,35 +41,24 @@ QUnit.test("can create a new channel [REQUIRE FOCUS]", async (assert) => {
|
||||
|
||||
QUnit.test(
|
||||
"do not close channel selector when creating chat conversation after selection",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Mario" });
|
||||
pyEnv["res.users"].create({ partner_id: partnerId });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
|
||||
|
||||
openDiscuss();
|
||||
await click("i[title='Start a conversation']");
|
||||
await afterNextRender(() =>
|
||||
editInput(document.body, ".o-discuss-ChannelSelector input", "mario")
|
||||
);
|
||||
await insertText(".o-discuss-ChannelSelector input", "mario");
|
||||
await click(".o-discuss-ChannelSelector-suggestion");
|
||||
assert.containsOnce($, ".o-discuss-ChannelSelector span[title='Mario']");
|
||||
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
|
||||
|
||||
await triggerEvent(document.body, ".o-discuss-ChannelSelector input", "keydown", {
|
||||
key: "Backspace",
|
||||
});
|
||||
assert.containsNone($, ".o-discuss-ChannelSelector span[title='Mario']");
|
||||
|
||||
await afterNextRender(() =>
|
||||
editInput(document.body, ".o-discuss-ChannelSelector input", "mario")
|
||||
);
|
||||
await triggerEvent(document.body, ".o-discuss-ChannelSelector input", "keydown", {
|
||||
key: "Enter",
|
||||
});
|
||||
assert.containsOnce($, ".o-discuss-ChannelSelector span[title='Mario']");
|
||||
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
|
||||
await contains(".o-discuss-ChannelSelector span[title='Mario']");
|
||||
await contains(".o-mail-DiscussSidebarChannel", 0);
|
||||
triggerHotkey("Backspace");
|
||||
await contains(".o-discuss-ChannelSelector span[title='Mario']", 0);
|
||||
await insertText(".o-discuss-ChannelSelector input", "mario");
|
||||
await contains(".o-discuss-ChannelSelector-suggestion");
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-discuss-ChannelSelector span[title='Mario']");
|
||||
await contains(".o-mail-DiscussSidebarChannel", 0);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -100,19 +80,15 @@ QUnit.test("can join a chat conversation", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
await openDiscuss();
|
||||
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
|
||||
|
||||
openDiscuss();
|
||||
await click(".o-mail-DiscussSidebar i[title='Start a conversation']");
|
||||
await afterNextRender(() =>
|
||||
editInput(document.body, ".o-discuss-ChannelSelector input", "mario")
|
||||
);
|
||||
await contains(".o-mail-DiscussSidebarChannel", 0);
|
||||
await insertText(".o-discuss-ChannelSelector input", "mario");
|
||||
await click(".o-discuss-ChannelSelector-suggestion");
|
||||
await triggerEvent(document.body, ".o-discuss-ChannelSelector input", "keydown", {
|
||||
key: "Enter",
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-DiscussSidebarChannel");
|
||||
assert.containsNone($, ".o-mail-Message");
|
||||
await contains(".o-discuss-ChannelSelector-suggestion", 0);
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-DiscussSidebarChannel");
|
||||
await contains(".o-mail-Message", 0);
|
||||
assert.verifySteps([
|
||||
"/mail/init_messaging",
|
||||
"/mail/load_message_failures",
|
||||
@@ -122,7 +98,7 @@ QUnit.test("can join a chat conversation", async (assert) => {
|
||||
]);
|
||||
});
|
||||
|
||||
QUnit.test("can create a group chat conversation", async (assert) => {
|
||||
QUnit.test("can create a group chat conversation", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const [partnerId_1, partnerId_2] = pyEnv["res.partner"].create([
|
||||
{ name: "Mario" },
|
||||
@@ -130,18 +106,18 @@ QUnit.test("can create a group chat conversation", async (assert) => {
|
||||
]);
|
||||
pyEnv["res.users"].create([{ partner_id: partnerId_1 }, { partner_id: partnerId_2 }]);
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
|
||||
openDiscuss();
|
||||
await click(".o-mail-DiscussSidebar i[title='Start a conversation']");
|
||||
await contains(".o-mail-DiscussSidebarChannel", 0);
|
||||
await insertText(".o-discuss-ChannelSelector input", "Mario");
|
||||
await click(".o-discuss-ChannelSelector-suggestion");
|
||||
await contains(".o-discuss-ChannelSelector-suggestion", 0);
|
||||
await insertText(".o-discuss-ChannelSelector input", "Luigi");
|
||||
await click(".o-discuss-ChannelSelector-suggestion");
|
||||
await triggerEvent(document.body, ".o-discuss-ChannelSelector input", "keydown", {
|
||||
key: "Enter",
|
||||
});
|
||||
assert.containsN($, ".o-mail-DiscussSidebarChannel", 1);
|
||||
assert.containsNone($, ".o-mail-Message");
|
||||
await contains(".o-discuss-ChannelSelector-suggestion", 0);
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-DiscussSidebarChannel");
|
||||
await contains(".o-mail-Message", 0);
|
||||
});
|
||||
|
||||
QUnit.test("should create DM chat when adding self and another user", async (assert) => {
|
||||
@@ -149,73 +125,75 @@ QUnit.test("should create DM chat when adding self and another user", async (ass
|
||||
const partner_id = pyEnv["res.partner"].create([{ name: "Mario", im_status: "online" }]);
|
||||
pyEnv["res.users"].create({ partner_id });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
|
||||
openDiscuss();
|
||||
await click(".o-mail-DiscussSidebar i[title='Start a conversation']");
|
||||
await contains(".o-mail-DiscussSidebarChannel", 0);
|
||||
await insertText(".o-discuss-ChannelSelector input", "Mi"); // Mitchell Admin
|
||||
await click(".o-discuss-ChannelSelector-suggestion");
|
||||
await contains(".o-discuss-ChannelSelector-suggestion", 0);
|
||||
await insertText(".o-discuss-ChannelSelector input", "Mario");
|
||||
await click(".o-discuss-ChannelSelector-suggestion");
|
||||
await triggerEvent(document.body, ".o-discuss-ChannelSelector input", "keydown", {
|
||||
key: "Enter",
|
||||
});
|
||||
assert.strictEqual($(".o-mail-DiscussSidebarChannel:contains(Mario)").text(), "Mario");
|
||||
await contains(".o-discuss-ChannelSelector-suggestion", 0);
|
||||
triggerHotkey("Enter");
|
||||
assert.strictEqual(
|
||||
(await contains(".o-mail-DiscussSidebarChannel:contains(Mario)")).text(),
|
||||
"Mario"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("chat search should display no result when no matches found", async (assert) => {
|
||||
QUnit.test("chat search should display no result when no matches found", async () => {
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
openDiscuss();
|
||||
await click(".o-mail-DiscussSidebar i[title='Start a conversation']");
|
||||
await insertText(".o-discuss-ChannelSelector", "Rainbow Panda");
|
||||
assert.containsOnce($, ".o-discuss-ChannelSelector-suggestion:contains(No results found)");
|
||||
await contains(".o-discuss-ChannelSelector-suggestion:contains(No results found)");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"chat search should not be visible when clicking outside of the field",
|
||||
async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Panda" });
|
||||
pyEnv["res.users"].create({ partner_id: partnerId });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
|
||||
await click(".o-mail-DiscussSidebar i[title='Start a conversation']");
|
||||
await insertText(".o-discuss-ChannelSelector", "Panda");
|
||||
assert.containsOnce($, ".o-discuss-ChannelSelector-suggestion");
|
||||
await click(".o-mail-DiscussSidebar");
|
||||
assert.containsNone($, ".o-discuss-ChannelSelector-suggestion");
|
||||
}
|
||||
);
|
||||
QUnit.test("chat search should not be visible when clicking outside of the field", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Panda" });
|
||||
pyEnv["res.users"].create({ partner_id: partnerId });
|
||||
const { openDiscuss } = await start();
|
||||
openDiscuss();
|
||||
await click(".o-mail-DiscussSidebar i[title='Start a conversation']");
|
||||
await insertText(".o-discuss-ChannelSelector", "Panda");
|
||||
await contains(".o-discuss-ChannelSelector-suggestion");
|
||||
await click(".o-mail-DiscussSidebar");
|
||||
await contains(".o-discuss-ChannelSelector-suggestion", 0);
|
||||
});
|
||||
|
||||
QUnit.test("sidebar: add channel", async (assert) => {
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o-mail-DiscussSidebarCategory-channel .o-mail-DiscussSidebarCategory-add"
|
||||
);
|
||||
openDiscuss();
|
||||
await contains(".o-mail-DiscussSidebarCategory-channel .o-mail-DiscussSidebarCategory-add");
|
||||
assert.hasAttrValue(
|
||||
$(".o-mail-DiscussSidebarCategory-channel .o-mail-DiscussSidebarCategory-add")[0],
|
||||
"title",
|
||||
"Add or join a channel"
|
||||
);
|
||||
await click(".o-mail-DiscussSidebarCategory-channel .o-mail-DiscussSidebarCategory-add");
|
||||
assert.containsOnce($, ".o-discuss-ChannelSelector");
|
||||
assert.containsOnce($, ".o-discuss-ChannelSelector input[placeholder='Add or join a channel']");
|
||||
await contains(".o-discuss-ChannelSelector");
|
||||
await contains(".o-discuss-ChannelSelector input[placeholder='Add or join a channel']");
|
||||
});
|
||||
|
||||
QUnit.test("Chat is added to discuss on other tab that the one that joined", async (assert) => {
|
||||
QUnit.test("Chat is added to discuss on other tab that the one that joined", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Jerry Golay" });
|
||||
pyEnv["res.users"].create({ partner_id: partnerId });
|
||||
const tab1 = await start({ asTab: true });
|
||||
const tab2 = await start({ asTab: true });
|
||||
await tab1.openDiscuss();
|
||||
await tab2.openDiscuss();
|
||||
await tab1.click(".o-mail-DiscussSidebarCategory-chat .o-mail-DiscussSidebarCategory-add");
|
||||
tab1.openDiscuss();
|
||||
tab2.openDiscuss();
|
||||
await click(".o-mail-DiscussSidebarCategory-chat .o-mail-DiscussSidebarCategory-add", {
|
||||
target: tab1.target,
|
||||
});
|
||||
await tab1.insertText(".o-discuss-ChannelSelector input", "Jer");
|
||||
await tab1.click(".o-discuss-ChannelSelector-suggestion");
|
||||
await afterNextRender(() => triggerHotkey("Enter"));
|
||||
assert.containsOnce(tab1.target, ".o-mail-DiscussSidebarChannel:contains(Jerry Golay)");
|
||||
assert.containsOnce(tab2.target, ".o-mail-DiscussSidebarChannel:contains(Jerry Golay)");
|
||||
await click(".o-discuss-ChannelSelector-suggestion", { target: tab1.target });
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-DiscussSidebarChannel:contains(Jerry Golay)", 1, {
|
||||
target: tab1.target,
|
||||
});
|
||||
await contains(".o-mail-DiscussSidebarChannel:contains(Jerry Golay)", 1, {
|
||||
target: tab2.target,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,62 +1,59 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import {
|
||||
afterNextRender,
|
||||
click,
|
||||
insertText,
|
||||
start,
|
||||
startServer,
|
||||
} from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { patchUiSize } from "@mail/../tests/helpers/patch_ui_size";
|
||||
import { triggerHotkey } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("messaging menu");
|
||||
|
||||
QUnit.test('"Start a conversation" item selection opens chat', async (assert) => {
|
||||
QUnit.test('"Start a conversation" item selection opens chat', async () => {
|
||||
patchUiSize({ height: 360, width: 640 });
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Gandalf" });
|
||||
pyEnv["res.users"].create({ partner_id: partnerId });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
openDiscuss();
|
||||
await click("button:contains(Chat)");
|
||||
await click("button:contains(Start a conversation)");
|
||||
await insertText("input[placeholder='Start a conversation']", "Gandalf");
|
||||
await click(".o-discuss-ChannelSelector-suggestion");
|
||||
await afterNextRender(() => triggerHotkey("Enter"));
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-name[title='Gandalf']");
|
||||
await contains(".o-discuss-ChannelSelector-suggestion", 0);
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-mail-ChatWindow-name[title='Gandalf']");
|
||||
});
|
||||
|
||||
QUnit.test('"New channel" item selection opens channel (existing)', async (assert) => {
|
||||
QUnit.test('"New channel" item selection opens channel (existing)', async () => {
|
||||
patchUiSize({ height: 360, width: 640 });
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({ name: "Gryffindors" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
openDiscuss();
|
||||
await click("button:contains(Channel)");
|
||||
await click("button:contains(New Channel)");
|
||||
await insertText("input[placeholder='Add or join a channel']", "Gryff");
|
||||
await click(".o-discuss-ChannelSelector-suggestion");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-name[title='Gryffindors']");
|
||||
await click(".o-discuss-ChannelSelector-suggestion:eq(0)");
|
||||
await contains(".o-discuss-ChannelSelector-suggestion", 0);
|
||||
await contains(".o-mail-ChatWindow-name[title='Gryffindors']");
|
||||
});
|
||||
|
||||
QUnit.test('"New channel" item selection opens channel (new)', async (assert) => {
|
||||
QUnit.test('"New channel" item selection opens channel (new)', async () => {
|
||||
patchUiSize({ height: 360, width: 640 });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
openDiscuss();
|
||||
await click("button:contains(Channel)");
|
||||
await click("button:contains(New Channel)");
|
||||
await insertText("input[placeholder='Add or join a channel']", "slytherins");
|
||||
await click(".o-discuss-ChannelSelector-suggestion");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow-name[title='slytherins']");
|
||||
await contains(".o-discuss-ChannelSelector-suggestion", 0);
|
||||
await contains(".o-mail-ChatWindow-name[title='slytherins']");
|
||||
});
|
||||
|
||||
QUnit.test("new message [REQUIRE FOCUS]", async (assert) => {
|
||||
QUnit.test("new message [REQUIRE FOCUS]", async () => {
|
||||
await start();
|
||||
await click(".o_menu_systray .dropdown-toggle:has(i[aria-label='Messages'])");
|
||||
await click('.o-mail-MessagingMenu button:contains("New Message")');
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow .o-discuss-ChannelSelector");
|
||||
assert.containsOnce($, ".o-discuss-ChannelSelector input:focus");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow .o-discuss-ChannelSelector");
|
||||
await contains(".o-discuss-ChannelSelector input:focus");
|
||||
});
|
||||
|
||||
@@ -1,19 +1,11 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Command } from "@mail/../tests/helpers/command";
|
||||
import {
|
||||
click,
|
||||
insertText,
|
||||
nextAnimationFrame,
|
||||
start,
|
||||
startServer,
|
||||
} from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { makeDeferred } from "@web/../tests/helpers/utils";
|
||||
import { click, contains, insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
QUnit.module("discuss sidebar");
|
||||
|
||||
QUnit.test("sidebar find shows channels matching search term", async (assert) => {
|
||||
QUnit.test("sidebar find shows channels matching search term", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [],
|
||||
@@ -21,29 +13,20 @@ QUnit.test("sidebar find shows channels matching search term", async (assert) =>
|
||||
group_public_id: false,
|
||||
name: "test",
|
||||
});
|
||||
const def = makeDeferred();
|
||||
const { openDiscuss } = await start({
|
||||
async mockRPC(route, args) {
|
||||
if (args.method === "search_read") {
|
||||
def.resolve();
|
||||
}
|
||||
},
|
||||
});
|
||||
await openDiscuss();
|
||||
await click(".o-mail-DiscussSidebarCategory-add");
|
||||
const { openDiscuss } = await start();
|
||||
openDiscuss();
|
||||
await click(".o-mail-DiscussSidebarCategory-add:eq(0)");
|
||||
await insertText(".o-discuss-ChannelSelector input", "test");
|
||||
await def;
|
||||
await nextAnimationFrame(); // ensures search_read rpc is rendered.
|
||||
// When searching for a single existing channel, the results list will have at least 2 lines:
|
||||
// One for the existing channel itself
|
||||
// One for creating a channel with the search term
|
||||
assert.containsN($, ".o-mail-NavigableList-item", 2);
|
||||
assert.containsN($, ".o-mail-NavigableList-item:contains(test)", 2);
|
||||
await contains(".o-mail-NavigableList-item", 2);
|
||||
await contains(".o-mail-NavigableList-item:contains(test)", 2);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"sidebar find shows channels matching search term even when user is member",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [Command.create({ partner_id: pyEnv.currentPartnerId })],
|
||||
@@ -51,23 +34,14 @@ QUnit.test(
|
||||
group_public_id: false,
|
||||
name: "test",
|
||||
});
|
||||
const def = makeDeferred();
|
||||
const { openDiscuss } = await start({
|
||||
async mockRPC(route, args) {
|
||||
if (args.method === "search_read") {
|
||||
def.resolve();
|
||||
}
|
||||
},
|
||||
});
|
||||
await openDiscuss();
|
||||
await click(".o-mail-DiscussSidebarCategory-add");
|
||||
const { openDiscuss } = await start();
|
||||
openDiscuss();
|
||||
await click(".o-mail-DiscussSidebarCategory-add:eq(0)");
|
||||
await insertText(".o-discuss-ChannelSelector input", "test");
|
||||
await def;
|
||||
await nextAnimationFrame(); // ensures search_read rpc is rendered.
|
||||
// When searching for a single existing channel, the results list will have at least 2 lines:
|
||||
// One for the existing channel itself
|
||||
// One for creating a channel with the search term
|
||||
assert.containsN($, ".o-mail-NavigableList-item", 2);
|
||||
assert.containsN($, ".o-mail-NavigableList-item:contains(test)", 2);
|
||||
await contains(".o-mail-NavigableList-item", 2);
|
||||
await contains(".o-mail-NavigableList-item:contains(test)", 2);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { nextTick, patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("pinned messages");
|
||||
|
||||
QUnit.test("Pin message", async (assert) => {
|
||||
QUnit.test("Pin message", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
pyEnv["mail.message"].create({
|
||||
@@ -15,16 +15,15 @@ QUnit.test("Pin message", async (assert) => {
|
||||
res_id: channelId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-Discuss-header button[title='Pinned Messages']");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
await contains(
|
||||
".o-discuss-PinnedMessagesPanel:contains(This channel doesn't have any pinned messages.)"
|
||||
);
|
||||
await click(".o-mail-Message [title='Expand']");
|
||||
await click(".dropdown-item:contains(Pin)");
|
||||
await click(".modal-footer button:contains(pin it)");
|
||||
assert.containsOnce($, ".o-discuss-PinnedMessagesPanel .o-mail-Message:contains(Hello world)");
|
||||
await contains(".o-discuss-PinnedMessagesPanel .o-mail-Message:contains(Hello world)");
|
||||
});
|
||||
|
||||
QUnit.test("Unpin message", async (assert) => {
|
||||
@@ -37,13 +36,13 @@ QUnit.test("Unpin message", async (assert) => {
|
||||
pinned_at: "2023-03-30 11:27:11",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-Discuss-header button[title='Pinned Messages']");
|
||||
assert.containsOnce($, ".o-discuss-PinnedMessagesPanel .o-mail-Message");
|
||||
await contains(".o-discuss-PinnedMessagesPanel .o-mail-Message");
|
||||
await click(".o-mail-Message [title='Expand']");
|
||||
await click(".dropdown-item:contains(Unpin)");
|
||||
await click(".modal-footer button:contains(Yes)");
|
||||
assert.containsNone($, ".o-discuss-PinnedMessagesPanel .o-mail-Message");
|
||||
await contains(".o-discuss-PinnedMessagesPanel .o-mail-Message", 0);
|
||||
});
|
||||
|
||||
QUnit.test("Deleted messages are not pinned", async (assert) => {
|
||||
@@ -57,13 +56,13 @@ QUnit.test("Deleted messages are not pinned", async (assert) => {
|
||||
pinned_at: "2023-03-30 11:27:11",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-Discuss-header button[title='Pinned Messages']");
|
||||
assert.containsOnce($, ".o-discuss-PinnedMessagesPanel .o-mail-Message");
|
||||
await contains(".o-discuss-PinnedMessagesPanel .o-mail-Message");
|
||||
await click(".o-mail-Message [title='Expand']");
|
||||
await click(".dropdown-item:contains(Delete)");
|
||||
await click("button:contains(Confirm)");
|
||||
assert.containsNone($, ".o-discuss-PinnedMessagesPanel .o-mail-Message");
|
||||
await contains(".o-discuss-PinnedMessagesPanel .o-mail-Message", 0);
|
||||
});
|
||||
|
||||
QUnit.test("Open pinned panel from notification", async (assert) => {
|
||||
@@ -75,13 +74,13 @@ QUnit.test("Open pinned panel from notification", async (assert) => {
|
||||
res_id: channelId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-Message:eq(0) [title='Expand']");
|
||||
await click(".dropdown-item:contains(Pin)");
|
||||
await click(".modal-footer button:contains(pin it)");
|
||||
assert.containsNone($, ".o-discuss-PinnedMessagesPanel");
|
||||
await contains(".o-discuss-PinnedMessagesPanel", 0);
|
||||
await click(".o_mail_notification a:contains(See all pinned messages)");
|
||||
assert.containsOnce($, ".o-discuss-PinnedMessagesPanel");
|
||||
await contains(".o-discuss-PinnedMessagesPanel");
|
||||
});
|
||||
|
||||
QUnit.test("Jump to message", async (assert) => {
|
||||
@@ -108,7 +107,7 @@ QUnit.test("Jump to message", async (assert) => {
|
||||
});
|
||||
}
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-Discuss-header button[title='Pinned Messages']");
|
||||
await click(".o-discuss-PinnedMessagesPanel button:contains(Jump)");
|
||||
await nextTick();
|
||||
@@ -138,11 +137,11 @@ QUnit.test("Jump to message from notification", async (assert) => {
|
||||
});
|
||||
}
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-Message:eq(0) [title='Expand']");
|
||||
await click(".dropdown-item:contains(Pin)");
|
||||
await click(".modal-footer button:contains(pin it)");
|
||||
await click(".o_mail_notification a:contains(message)");
|
||||
await click(".o_mail_notification a:contains(message):eq(0)");
|
||||
await nextTick();
|
||||
assert.isVisible($(".o-mail-Message:contains(Hello world!)"));
|
||||
});
|
||||
|
||||
@@ -119,7 +119,7 @@ function patchAudio() {
|
||||
};
|
||||
}
|
||||
|
||||
QUnit.test("make voice message in chat", async (assert) => {
|
||||
QUnit.test("make voice message in chat", async () => {
|
||||
const file = await createFile({
|
||||
content: Array(500).map(() => new Int8Array()), // some non-empty content
|
||||
contentType: "audio/mp3",
|
||||
@@ -158,26 +158,23 @@ QUnit.test("make voice message in chat", async (assert) => {
|
||||
channel_type: "chat",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, "button[title='Voice Message']");
|
||||
openDiscuss(channelId);
|
||||
await click("button[title='Voice Message']");
|
||||
assert.containsOnce($, ".o-mail-VoiceRecorder");
|
||||
assert.containsOnce($, ".o-mail-VoiceRecorder:contains(00 : 00)");
|
||||
await contains(".o-mail-VoiceRecorder:contains(00 : 00)");
|
||||
await nextAnimationFrame();
|
||||
// simulate 10 sec elapsed
|
||||
patchDate(2023, 6, 31, 13, 0, 11); // +1 so exactly 10 sec elapsed
|
||||
// simulate some microphone data
|
||||
audioProcessor.process([[new Float32Array(128)]]);
|
||||
await contains(".o-mail-VoiceRecorder:contains(00 : 10)");
|
||||
assert.containsOnce($, "button[title='Stop Recording']");
|
||||
await click("button[title='Stop Recording']");
|
||||
assert.containsOnce($, ".o-mail-VoicePlayer");
|
||||
await contains(".o-mail-VoicePlayer");
|
||||
// wait for audio stream decode + drawing of waves
|
||||
await voicePlayerDrawing;
|
||||
await nextAnimationFrame();
|
||||
assert.containsOnce($, ".o-mail-VoicePlayer button[title='Play']");
|
||||
assert.containsN($, ".o-mail-VoicePlayer canvas", 2); // 1 for global waveforms, 1 for played waveforms
|
||||
assert.containsOnce($, ".o-mail-VoicePlayer:contains(00 : 04)"); // duration of call_02_in_.mp3
|
||||
assert.containsOnce($, ".o-mail-VoiceRecorder button[title='Voice Message']");
|
||||
assert.ok($(".o-mail-VoiceRecorder button[title='Voice Message']")[0].disabled);
|
||||
await contains(".o-mail-VoicePlayer button[title='Play']");
|
||||
await contains(".o-mail-VoicePlayer canvas", 2); // 1 for global waveforms, 1 for played waveforms
|
||||
await contains(".o-mail-VoicePlayer:contains(00 : 04)"); // duration of call_02_in_.mp3
|
||||
await contains(".o-mail-VoiceRecorder button[title='Voice Message']:disabled");
|
||||
cleanUp();
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,13 +4,13 @@ import { UPDATE_BUS_PRESENCE_DELAY } from "@bus/im_status_service";
|
||||
|
||||
import { createLocalId } from "@mail/utils/common/misc";
|
||||
import { Command } from "@mail/../tests/helpers/command";
|
||||
import { afterNextRender, click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { nextTick } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("im status");
|
||||
|
||||
QUnit.test("initially online", async (assert) => {
|
||||
QUnit.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({
|
||||
@@ -21,11 +21,11 @@ QUnit.test("initially online", async (assert) => {
|
||||
channel_type: "chat",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-ImStatus i[title='Online']");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-ImStatus i[title='Online']");
|
||||
});
|
||||
|
||||
QUnit.test("initially offline", async (assert) => {
|
||||
QUnit.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({
|
||||
@@ -36,11 +36,11 @@ QUnit.test("initially offline", async (assert) => {
|
||||
channel_type: "chat",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-ImStatus i[title='Offline']");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-ImStatus i[title='Offline']");
|
||||
});
|
||||
|
||||
QUnit.test("initially away", async (assert) => {
|
||||
QUnit.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({
|
||||
@@ -51,11 +51,11 @@ QUnit.test("initially away", async (assert) => {
|
||||
channel_type: "chat",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-ImStatus i[title='Idle']");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-ImStatus i[title='Idle']");
|
||||
});
|
||||
|
||||
QUnit.test("change icon on change partner im_status", async (assert) => {
|
||||
QUnit.test("change icon on change partner im_status", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo", im_status: "online" });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
@@ -66,20 +66,20 @@ QUnit.test("change icon on change partner im_status", async (assert) => {
|
||||
channel_type: "chat",
|
||||
});
|
||||
const { advanceTime, openDiscuss } = await start({ hasTimeControl: true });
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-ImStatus i[title='Online']");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-ImStatus i[title='Online']");
|
||||
|
||||
pyEnv["res.partner"].write([partnerId], { im_status: "offline" });
|
||||
await afterNextRender(() => advanceTime(UPDATE_BUS_PRESENCE_DELAY));
|
||||
assert.containsOnce($, ".o-mail-ImStatus i[title='Offline']");
|
||||
advanceTime(UPDATE_BUS_PRESENCE_DELAY);
|
||||
await contains(".o-mail-ImStatus i[title='Offline']");
|
||||
|
||||
pyEnv["res.partner"].write([partnerId], { im_status: "away" });
|
||||
await afterNextRender(() => advanceTime(UPDATE_BUS_PRESENCE_DELAY));
|
||||
assert.containsOnce($, ".o-mail-ImStatus i[title='Idle']");
|
||||
advanceTime(UPDATE_BUS_PRESENCE_DELAY);
|
||||
await contains(".o-mail-ImStatus i[title='Idle']");
|
||||
|
||||
pyEnv["res.partner"].write([partnerId], { im_status: "online" });
|
||||
await afterNextRender(() => advanceTime(UPDATE_BUS_PRESENCE_DELAY));
|
||||
assert.containsOnce($, ".o-mail-ImStatus i[title='Online']");
|
||||
advanceTime(UPDATE_BUS_PRESENCE_DELAY);
|
||||
await contains(".o-mail-ImStatus i[title='Online']");
|
||||
});
|
||||
|
||||
QUnit.test("Can handle im_status of unknown partner", async (assert) => {
|
||||
@@ -98,7 +98,7 @@ QUnit.test("Can handle im_status of unknown partner", async (assert) => {
|
||||
assert.ok(persona.im_status === "online");
|
||||
});
|
||||
|
||||
QUnit.test("show im status in messaging menu preview of chat", async (assert) => {
|
||||
QUnit.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({
|
||||
@@ -110,8 +110,5 @@ QUnit.test("show im status in messaging menu preview of chat", async (assert) =>
|
||||
});
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o-mail-NotificationItem:contains(Demo) i[aria-label='User is online']"
|
||||
);
|
||||
await contains(".o-mail-NotificationItem:contains(Demo) i[aria-label='User is online']");
|
||||
});
|
||||
|
||||
@@ -3,12 +3,18 @@
|
||||
import {
|
||||
afterNextRender,
|
||||
click,
|
||||
contains,
|
||||
insertText,
|
||||
start,
|
||||
startServer,
|
||||
} from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { patchWithCleanup, triggerHotkey, mockTimeout } from "@web/../tests/helpers/utils";
|
||||
import {
|
||||
patchWithCleanup,
|
||||
triggerHotkey,
|
||||
mockTimeout,
|
||||
makeDeferred,
|
||||
} from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("discuss inbox");
|
||||
|
||||
@@ -29,13 +35,13 @@ QUnit.test("reply: discard on reply button toggle", async (assert) => {
|
||||
res_partner_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
openDiscuss();
|
||||
await contains(".o-mail-Message");
|
||||
|
||||
await click("[title='Reply']");
|
||||
assert.containsOnce($, ".o-mail-Composer");
|
||||
await contains(".o-mail-Composer");
|
||||
await click("[title='Reply']");
|
||||
assert.containsNone($, ".o-mail-Composer");
|
||||
await contains(".o-mail-Composer", 0);
|
||||
});
|
||||
|
||||
QUnit.test("reply: discard on pressing escape", async (assert) => {
|
||||
@@ -58,29 +64,29 @@ QUnit.test("reply: discard on pressing escape", async (assert) => {
|
||||
res_partner_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
openDiscuss();
|
||||
await contains(".o-mail-Message");
|
||||
|
||||
await click(".o-mail-Message [title='Reply']");
|
||||
assert.containsOnce($, ".o-mail-Composer");
|
||||
await contains(".o-mail-Composer");
|
||||
|
||||
// Escape on emoji picker does not stop replying
|
||||
await click(".o-mail-Composer button[aria-label='Emojis']");
|
||||
assert.containsOnce($, ".o-EmojiPicker");
|
||||
await afterNextRender(() => triggerHotkey("Escape"));
|
||||
assert.containsNone($, ".o-EmojiPicker");
|
||||
assert.containsOnce($, ".o-mail-Composer");
|
||||
await contains(".o-EmojiPicker");
|
||||
triggerHotkey("Escape");
|
||||
await contains(".o-EmojiPicker", 0);
|
||||
await contains(".o-mail-Composer");
|
||||
|
||||
// Escape on suggestion prompt does not stop replying
|
||||
await insertText(".o-mail-Composer-input", "@");
|
||||
assert.containsOnce($, ".o-mail-Composer-suggestionList .o-open");
|
||||
await afterNextRender(() => triggerHotkey("Escape"));
|
||||
assert.containsNone($, ".o-mail-Composer-suggestionList .o-open");
|
||||
assert.containsOnce($, ".o-mail-Composer");
|
||||
await contains(".o-mail-Composer-suggestionList .o-open");
|
||||
triggerHotkey("Escape");
|
||||
await contains(".o-mail-Composer-suggestionList .o-open", 0);
|
||||
await contains(".o-mail-Composer");
|
||||
|
||||
click(".o-mail-Composer-input").catch(() => {});
|
||||
await afterNextRender(() => triggerHotkey("Escape"));
|
||||
assert.containsNone($, ".o-mail-Composer");
|
||||
triggerHotkey("Escape");
|
||||
await contains(".o-mail-Composer", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
@@ -111,13 +117,13 @@ QUnit.test(
|
||||
}
|
||||
},
|
||||
});
|
||||
await openDiscuss();
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
|
||||
openDiscuss();
|
||||
await contains(".o-mail-Message");
|
||||
await click("[title='Reply']");
|
||||
assert.containsOnce($, ".o-mail-Composer [placeholder='Log an internal note...']");
|
||||
await contains(".o-mail-Composer [placeholder='Log an internal note…']");
|
||||
await insertText(".o-mail-Composer-input", "Test");
|
||||
await click(".o-mail-Composer-send");
|
||||
await click(".o-mail-Composer-send:not(:disabled):contains(Log)");
|
||||
await contains(".o-mail-Composer", 0);
|
||||
assert.verifySteps(["/mail/message/post"]);
|
||||
}
|
||||
);
|
||||
@@ -150,19 +156,18 @@ QUnit.test(
|
||||
}
|
||||
},
|
||||
});
|
||||
await openDiscuss();
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
|
||||
openDiscuss();
|
||||
await contains(".o-mail-Message");
|
||||
await click("[title='Reply']");
|
||||
assert.strictEqual($(".o-mail-Composer-send").text().trim(), "Send");
|
||||
|
||||
await contains(".o-mail-Composer [placeholder='Send a message to followers…']");
|
||||
await insertText(".o-mail-Composer-input", "Test");
|
||||
await click(".o-mail-Composer-send");
|
||||
await click(".o-mail-Composer-send:not(:disabled):contains(Send)");
|
||||
await contains(".o-mail-Composer-send", 0);
|
||||
assert.verifySteps(["/mail/message/post"]);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("show subject of message in Inbox", async (assert) => {
|
||||
QUnit.test("show subject of message in Inbox", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
@@ -178,12 +183,12 @@ QUnit.test("show subject of message in Inbox", async (assert) => {
|
||||
res_partner_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsOnce($, ".o-mail-Message:contains(Subject: Salutations, voyageur)");
|
||||
openDiscuss();
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message:contains(Subject: Salutations, voyageur)");
|
||||
});
|
||||
|
||||
QUnit.test("show subject of message in history", async (assert) => {
|
||||
QUnit.test("show subject of message in history", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
@@ -199,38 +204,36 @@ QUnit.test("show subject of message in history", async (assert) => {
|
||||
res_partner_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss("mail.box_history");
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsOnce($, ".o-mail-Message:contains(Subject: Salutations, voyageur)");
|
||||
openDiscuss("mail.box_history");
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message:contains(Subject: Salutations, voyageur)");
|
||||
});
|
||||
|
||||
QUnit.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: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message-content");
|
||||
await contains(".o-mail-Message-content:contains(Salutations, voyageur)", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"subject should not be shown when subject is the same as the thread name",
|
||||
async (assert) => {
|
||||
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: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
assert.containsNone($, ".o-mail-Message-content:contains(Salutations, voyageur)");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"subject should not be shown when subject is the same as the thread name and both have the same prefix",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "Re: Salutations, voyageur" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
@@ -247,14 +250,15 @@ QUnit.test(
|
||||
res_partner_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
assert.containsNone($, ".o-mail-Message-content:contains(Salutations, voyageur)");
|
||||
openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message-content");
|
||||
await contains(".o-mail-Message-content:contains(Salutations, voyageur)", 0);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
'subject should not be shown when subject differs from thread name only by the "Re:" prefix',
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "Salutations, voyageur" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
@@ -271,14 +275,15 @@ QUnit.test(
|
||||
res_partner_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
assert.containsNone($, ".o-mail-Message-content:contains(Salutations, voyageur)");
|
||||
openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message-content");
|
||||
await contains(".o-mail-Message-content:contains(Salutations, voyageur)", 0);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
'subject should not be shown when subject differs from thread name only by the "Fw:" and "Re:" prefix',
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "Salutations, voyageur" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
@@ -295,14 +300,15 @@ QUnit.test(
|
||||
res_partner_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
assert.containsNone($, ".o-mail-Message-contente:contains(Salutations, voyageur)");
|
||||
openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message-content");
|
||||
await contains(".o-mail-Message-content:contains(Salutations, voyageur)", 0);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"subject should be shown when the thread name has an extra prefix compared to subject",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "Re: Salutations, voyageur" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
@@ -319,14 +325,15 @@ QUnit.test(
|
||||
res_partner_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
assert.containsNone($, ".o-mail-Message-content:contains(Salutations, voyageur)");
|
||||
openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message-content");
|
||||
await contains(".o-mail-Message-content:contains(Salutations, voyageur)", 0);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
'subject should not be shown when subject differs from thread name only by the "fw:" prefix and both contain another common prefix',
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "Re: Salutations, voyageur" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
@@ -343,14 +350,15 @@ QUnit.test(
|
||||
res_partner_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
assert.containsNone($, ".o-mail-Message-content:contains(Salutations, voyageur)");
|
||||
openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message-content");
|
||||
await contains(".o-mail-Message-content:contains(Salutations, voyageur)", 0);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
'subject should not be shown when subject differs from thread name only by the "Re: Re:" prefix',
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "Salutations, voyageur" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
@@ -367,8 +375,9 @@ QUnit.test(
|
||||
res_partner_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss("mail.box_inbox");
|
||||
assert.containsNone($, ".o-mail-Message-content:contains(Salutations, voyageur)");
|
||||
openDiscuss("mail.box_inbox");
|
||||
await contains(".o-mail-Message-content");
|
||||
await contains(".o-mail-Message-content:contains(Salutations, voyageur)", 0);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -402,16 +411,16 @@ QUnit.test("inbox: mark all messages as read", async (assert) => {
|
||||
},
|
||||
]);
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsOnce($, "button:contains(Inbox) .badge:contains(2)");
|
||||
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(General) .badge:contains(2)");
|
||||
assert.containsN($, ".o-mail-Discuss-content .o-mail-Message", 2);
|
||||
openDiscuss();
|
||||
await contains("button:contains(Inbox) .badge:contains(2)");
|
||||
await contains(".o-mail-DiscussSidebarChannel:contains(General) .badge:contains(2)");
|
||||
await contains(".o-mail-Discuss-content .o-mail-Message", 2);
|
||||
assert.notOk($("button:contains(Mark all read)")[0].disabled);
|
||||
|
||||
await click(".o-mail-Discuss-header button:contains(Mark all read)");
|
||||
assert.containsNone($, "button:contains(Inbox) .badge");
|
||||
assert.containsNone($, ".o-mail-DiscussSidebarChannel:contains(General) .badge");
|
||||
assert.containsNone($, ".o-mail-Message");
|
||||
await contains("button:contains(Inbox) .badge", 0);
|
||||
await contains(".o-mail-DiscussSidebarChannel:contains(General) .badge", 0);
|
||||
await contains(".o-mail-Message", 0);
|
||||
assert.ok($("button:contains(Mark all read)")[0].disabled);
|
||||
});
|
||||
|
||||
@@ -434,7 +443,8 @@ QUnit.test(
|
||||
res_partner_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { env, openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
openDiscuss();
|
||||
const def = makeDeferred();
|
||||
patchWithCleanup(env.services.action, {
|
||||
doAction(action) {
|
||||
// Callback of doing an action (action manager).
|
||||
@@ -445,18 +455,18 @@ QUnit.test(
|
||||
assert.deepEqual(action.views, [[false, "form"]]);
|
||||
assert.strictEqual(action.res_model, "res.fake");
|
||||
assert.strictEqual(action.res_id, fakeId);
|
||||
def.resolve();
|
||||
return Promise.resolve();
|
||||
},
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsOnce($, ".o-mail-Message-header a:contains(Some record)");
|
||||
|
||||
click(".o-mail-Message-header a:contains(Some record)").catch(() => {});
|
||||
await contains(".o-mail-Message");
|
||||
await click(".o-mail-Message-header a:contains(Some record)");
|
||||
await def;
|
||||
assert.verifySteps(["do-action"]);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("inbox messages are never squashed", async (assert) => {
|
||||
QUnit.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" });
|
||||
@@ -497,15 +507,15 @@ QUnit.test("inbox messages are never squashed", async (assert) => {
|
||||
},
|
||||
]);
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsN($, ".o-mail-Message", 2);
|
||||
assert.doesNotHaveClass($(".o-mail-Message:contains(body1)"), "o-squashed");
|
||||
assert.doesNotHaveClass($(".o-mail-Message:contains(body2)"), "o-squashed");
|
||||
openDiscuss();
|
||||
await contains(".o-mail-Message", 2);
|
||||
await contains(".o-mail-Message:contains(body1):not(.o-squashed)");
|
||||
await contains(".o-mail-Message:contains(body2):not(.o-squashed)");
|
||||
await click(".o-mail-DiscussSidebarChannel:contains(test)");
|
||||
assert.hasClass($(".o-mail-Message:contains(body2)"), "o-squashed");
|
||||
await contains(".o-mail-Message:contains(body2).o-squashed");
|
||||
});
|
||||
|
||||
QUnit.test("reply: stop replying button click", async (assert) => {
|
||||
QUnit.test("reply: stop replying button click", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
@@ -522,18 +532,18 @@ QUnit.test("reply: stop replying button click", async (assert) => {
|
||||
res_partner_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
openDiscuss();
|
||||
await contains(".o-mail-Message");
|
||||
|
||||
await click("[title='Reply']");
|
||||
assert.containsOnce($, ".o-mail-Composer");
|
||||
assert.containsOnce($, "i[title='Stop replying']");
|
||||
await contains(".o-mail-Composer");
|
||||
await contains("i[title='Stop replying']");
|
||||
|
||||
await click("i[title='Stop replying']");
|
||||
assert.containsNone($, ".o-mail-Composer");
|
||||
await contains(".o-mail-Composer", 0);
|
||||
});
|
||||
|
||||
QUnit.test("error notifications should not be shown in Inbox", async (assert) => {
|
||||
QUnit.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({
|
||||
@@ -550,17 +560,16 @@ QUnit.test("error notifications should not be shown in Inbox", async (assert) =>
|
||||
res_partner_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsOnce($, ".o-mail-Message-header:contains(on Demo User)");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
openDiscuss();
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message-header:contains(on Demo User)");
|
||||
await contains(
|
||||
`.o-mail-Message-header a:contains(Demo User)[href*='/web#model=res.partner&id=${partnerId}']`
|
||||
);
|
||||
assert.containsNone($, ".o-mail-Message-notification");
|
||||
await contains(".o-mail-Message-notification", 0);
|
||||
});
|
||||
|
||||
QUnit.test("emptying inbox displays rainbow man in inbox", async (assert) => {
|
||||
QUnit.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([
|
||||
@@ -579,12 +588,12 @@ QUnit.test("emptying inbox displays rainbow man in inbox", async (assert) => {
|
||||
},
|
||||
]);
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
openDiscuss();
|
||||
await click("button:contains(Mark all read)");
|
||||
assert.containsOnce($, ".o_reward_rainbow");
|
||||
await contains(".o_reward_rainbow");
|
||||
});
|
||||
|
||||
QUnit.test("emptying inbox doesn't display rainbow man in another thread", async (assert) => {
|
||||
QUnit.test("emptying inbox doesn't display rainbow man in another thread", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
@@ -603,13 +612,13 @@ QUnit.test("emptying inbox doesn't display rainbow man in another thread", async
|
||||
},
|
||||
]);
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, "button:contains(Inbox) .badge:contains(1)");
|
||||
openDiscuss(channelId);
|
||||
await contains("button:contains(Inbox) .badge:contains(1)");
|
||||
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "mail.message/mark_as_read", {
|
||||
message_ids: [messageId],
|
||||
needaction_inbox_counter: 0,
|
||||
});
|
||||
await afterNextRender(() => mockTimeout().execRegisteredTimeouts);
|
||||
assert.containsNone($, "button:contains(Inbox) .badge");
|
||||
assert.containsNone($, ".o_reward_rainbow");
|
||||
await contains("button:contains(Inbox) .badge", 0);
|
||||
await contains(".o_reward_rainbow", 0);
|
||||
});
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
import { PRESENT_THRESHOLD } from "@mail/core/common/thread";
|
||||
import {
|
||||
afterNextRender,
|
||||
click,
|
||||
contains,
|
||||
nextAnimationFrame,
|
||||
start,
|
||||
startServer,
|
||||
@@ -36,16 +36,21 @@ QUnit.test("Basic jump to present when scrolling to outdated messages", async (a
|
||||
});
|
||||
}
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
assert.ok(
|
||||
$(".o-mail-Thread")[0].scrollHeight > PRESENT_THRESHOLD,
|
||||
(await contains(".o-mail-Thread"))[0].scrollHeight > PRESENT_THRESHOLD,
|
||||
"should have enough scroll height to trigger jump to present"
|
||||
);
|
||||
await afterNextRender(() => $(".o-mail-Thread").scrollTop(0));
|
||||
assert.containsOnce($, ".o-mail-Thread:contains(You're viewing older messagesJump to Present)");
|
||||
/**
|
||||
* The nextAnimationFrame is necessary because otherwise useAutoScroll would
|
||||
* set the scroll to bottom after the manually set value from this test.
|
||||
*/
|
||||
await nextAnimationFrame();
|
||||
$(".o-mail-Thread").scrollTop(0);
|
||||
await contains(".o-mail-Thread:contains(You're viewing older messagesJump to Present)");
|
||||
await click(".o-mail-Thread-jumpPresent");
|
||||
await nextTick();
|
||||
assert.containsNone($, ".o-mail-Thread:contains(You're viewing older messagesJump to Present)");
|
||||
await contains(".o-mail-Thread:contains(You're viewing older messagesJump to Present)", 0);
|
||||
assert.ok(
|
||||
$(".o-mail-Thread")[0].scrollHeight - $(".o-mail-Thread")[0].scrollTop <=
|
||||
$(".o-mail-Thread")[0].clientHeight
|
||||
@@ -88,18 +93,18 @@ QUnit.test("Jump to old reply should prompt jump to presence", async (assert) =>
|
||||
parent_id: oldestMessageId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-MessageInReply .cursor-pointer");
|
||||
assert.isVisible($(".o-mail-Message:contains(Hello world!):eq(0)")[0]);
|
||||
await nextAnimationFrame(); // wait for scroll into view
|
||||
assert.isVisible((await contains(".o-mail-Message:contains(Hello world!):eq(0)"))[0]);
|
||||
assert.strictEqual(
|
||||
$(".o-mail-Message-body:contains(Hello world!):eq(0)").text(),
|
||||
"Hello world!",
|
||||
"should correctly execute HTML tags in parent message when using 'load around' feature"
|
||||
);
|
||||
assert.containsOnce($, ".o-mail-Thread:contains(You're viewing older messagesJump to Present)");
|
||||
await contains(".o-mail-Thread:contains(You're viewing older messagesJump to Present)");
|
||||
await click(".o-mail-Thread-jumpPresent");
|
||||
await nextAnimationFrame();
|
||||
assert.containsNone($, ".o-mail-Thread:contains(You're viewing older messagesJump to Present)");
|
||||
await contains(".o-mail-Thread:contains(You're viewing older messagesJump to Present)", 0);
|
||||
assert.ok(
|
||||
$(".o-mail-Thread")[0].scrollHeight - $(".o-mail-Thread")[0].scrollTop <=
|
||||
$(".o-mail-Thread")[0].clientHeight
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,107 +1,93 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { EMOJI_PER_ROW } from "@web/core/emoji_picker/emoji_picker";
|
||||
import {
|
||||
afterNextRender,
|
||||
click,
|
||||
insertText,
|
||||
start,
|
||||
startServer,
|
||||
} from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { triggerHotkey } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("emoji");
|
||||
|
||||
QUnit.test("search emoji from keywords", async (assert) => {
|
||||
QUnit.test("search emoji from keywords", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("button[aria-label='Emojis']");
|
||||
await insertText("input[placeholder='Search for an emoji']", "mexican");
|
||||
assert.containsOnce($, ".o-Emoji:contains(🌮)");
|
||||
await contains(".o-Emoji:contains(🌮)");
|
||||
});
|
||||
|
||||
QUnit.test("search emoji from keywords should be case insensitive", async (assert) => {
|
||||
QUnit.test("search emoji from keywords should be case insensitive", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("button[aria-label='Emojis']");
|
||||
await insertText("input[placeholder='Search for an emoji']", "ok");
|
||||
assert.containsOnce($, ".o-Emoji:contains(🆗)"); // all search terms are uppercase OK
|
||||
await contains(".o-Emoji:contains(🆗)"); // all search terms are uppercase OK
|
||||
});
|
||||
|
||||
QUnit.test("search emoji from keywords with special regex character", async (assert) => {
|
||||
QUnit.test("search emoji from keywords with special regex character", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("button[aria-label='Emojis']");
|
||||
await insertText("input[placeholder='Search for an emoji']", "(blood");
|
||||
assert.containsOnce($, ".o-Emoji:contains(🆎)");
|
||||
await contains(".o-Emoji:contains(🆎)");
|
||||
});
|
||||
|
||||
QUnit.test("Press Escape in emoji picker closes the emoji picker", async (assert) => {
|
||||
QUnit.test("Press Escape in emoji picker closes the emoji picker", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("button[aria-label='Emojis']");
|
||||
await afterNextRender(() => triggerHotkey("Escape"));
|
||||
assert.containsNone($, ".o-EmojiPicker");
|
||||
triggerHotkey("Escape");
|
||||
await contains(".o-EmojiPicker", 0);
|
||||
});
|
||||
|
||||
QUnit.test("Basic keyboard navigation", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("button[aria-label='Emojis']");
|
||||
assert.containsOnce($, ".o-EmojiPicker-content .o-Emoji[data-index=0].bg-200"); // bg-200 means active
|
||||
await afterNextRender(() => triggerHotkey("ArrowRight"));
|
||||
assert.containsOnce($, ".o-EmojiPicker-content .o-Emoji[data-index=1].bg-200");
|
||||
await afterNextRender(() => triggerHotkey("ArrowDown"));
|
||||
assert.containsOnce(
|
||||
$,
|
||||
`.o-EmojiPicker-content .o-Emoji[data-index=${EMOJI_PER_ROW + 1}].bg-200`
|
||||
);
|
||||
await afterNextRender(() => triggerHotkey("ArrowLeft"));
|
||||
assert.containsOnce(
|
||||
$,
|
||||
`.o-EmojiPicker-content .o-Emoji[data-index=${EMOJI_PER_ROW}].bg-200`
|
||||
);
|
||||
await afterNextRender(() => triggerHotkey("ArrowUp"));
|
||||
assert.containsOnce($, ".o-EmojiPicker-content .o-Emoji[data-index=0].bg-200");
|
||||
const codepoints = $(".o-EmojiPicker-content .o-Emoji[data-index=0].bg-200").data(
|
||||
"codepoints"
|
||||
);
|
||||
await afterNextRender(() => triggerHotkey("Enter"));
|
||||
await contains(".o-EmojiPicker-content .o-Emoji[data-index=0].bg-200"); // bg-200 means active
|
||||
triggerHotkey("ArrowRight");
|
||||
await contains(".o-EmojiPicker-content .o-Emoji[data-index=1].bg-200");
|
||||
triggerHotkey("ArrowDown");
|
||||
await contains(`.o-EmojiPicker-content .o-Emoji[data-index=${EMOJI_PER_ROW + 1}].bg-200`);
|
||||
triggerHotkey("ArrowLeft");
|
||||
await contains(`.o-EmojiPicker-content .o-Emoji[data-index=${EMOJI_PER_ROW}].bg-200`);
|
||||
triggerHotkey("ArrowUp");
|
||||
await contains(".o-EmojiPicker-content .o-Emoji[data-index=0].bg-200");
|
||||
const codepoints = $(".o-EmojiPicker-content .o-Emoji[data-index=0].bg-200").data("codepoints");
|
||||
triggerHotkey("Enter");
|
||||
await contains(".o-EmojiPicker", 0);
|
||||
assert.strictEqual($(".o-mail-Composer-input").val(), codepoints);
|
||||
});
|
||||
|
||||
QUnit.test("recent category (basic)", async (assert) => {
|
||||
QUnit.test("recent category (basic)", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("button[aria-label='Emojis']");
|
||||
assert.containsNone($, ".o-EmojiPicker-navbar [title='Frequently used']");
|
||||
await contains(".o-EmojiPicker-navbar [title='Frequently used']", 0);
|
||||
await click(".o-EmojiPicker-content .o-Emoji:contains(😀)");
|
||||
await click("button[aria-label='Emojis']");
|
||||
assert.containsOnce($, ".o-EmojiPicker-navbar [title='Frequently used']");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
await contains(".o-EmojiPicker-navbar [title='Frequently used']");
|
||||
await contains(
|
||||
"span:contains(Frequently used) ~ .o-Emoji:contains(😀) ~ span:contains(Smileys & Emotion)"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("emoji usage amount orders frequent emojis", async (assert) => {
|
||||
QUnit.test("emoji usage amount orders frequent emojis", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("button[aria-label='Emojis']");
|
||||
await click(".o-EmojiPicker-content .o-Emoji:contains(😀)");
|
||||
await click("button[aria-label='Emojis']");
|
||||
@@ -109,56 +95,51 @@ QUnit.test("emoji usage amount orders frequent emojis", async (assert) => {
|
||||
await click("button[aria-label='Emojis']");
|
||||
await click(".o-EmojiPicker-content .o-Emoji:contains(👽)");
|
||||
await click("button[aria-label='Emojis']");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
await contains(
|
||||
"span:contains(Frequently used) ~ .o-Emoji:contains(😀) ~ span:contains(Smileys & Emotion)"
|
||||
);
|
||||
assert.containsOnce(
|
||||
$,
|
||||
await contains(
|
||||
"span:contains(Frequently used) ~ .o-Emoji:contains(👽) ~ span:contains(Smileys & Emotion)"
|
||||
);
|
||||
assert.containsOnce(
|
||||
$,
|
||||
await contains(
|
||||
"span:contains(Frequently used) ~ .o-Emoji:contains(👽) ~ .o-Emoji:contains(😀) ~ span:contains(Smileys & Emotion)"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("posting :wink: in message should impact recent", async (assert) => {
|
||||
QUnit.test("posting :wink: in message should impact recent", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", ":wink:");
|
||||
await click(".o-mail-Composer button[aria-label='Send']");
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
await click("button[aria-label='Emojis']");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
await contains(
|
||||
"span:contains(Frequently used) ~ .o-Emoji:contains(😉) ~ span:contains(Smileys & Emotion)"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("posting :snowman: in message should impact recent", async (assert) => {
|
||||
QUnit.test("posting :snowman: in message should impact recent", async () => {
|
||||
// the snowman emoji is composed of two codepoints, making it a corner case
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", ":snowman:");
|
||||
await click(".o-mail-Composer button[aria-label='Send']");
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
await click("button[aria-label='Emojis']");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
await contains(
|
||||
"span:contains(Frequently used) ~ .o-Emoji:contains(☃️) ~ span:contains(Smileys & Emotion)"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("first category should be highlight by default", async (assert) => {
|
||||
QUnit.test("first category should be highlighted by default", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("button[aria-label='Emojis']");
|
||||
assert.containsOnce($, ".o-EmojiPicker-navbar .o-Emoji:eq(0).bg-300");
|
||||
await contains(".o-EmojiPicker-navbar .o-Emoji:eq(0).bg-300");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
@@ -167,14 +148,13 @@ QUnit.test(
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("button[aria-label='Emojis']");
|
||||
await afterNextRender(() =>
|
||||
$(".o-EmojiPicker-content .o-Emoji:contains(👺)")[0].dispatchEvent(
|
||||
new MouseEvent("click", { shiftKey: true })
|
||||
)
|
||||
(await contains(".o-EmojiPicker-content .o-Emoji:contains(👺)"))[0].dispatchEvent(
|
||||
new MouseEvent("click", { shiftKey: true })
|
||||
);
|
||||
assert.containsOnce($, ".o-EmojiPicker");
|
||||
await contains(".o-EmojiPicker-navbar [title='Frequently used']");
|
||||
await contains(".o-EmojiPicker");
|
||||
assert.strictEqual($(".o-mail-Composer-input").val(), "👺");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -82,24 +82,24 @@ const rpc = {
|
||||
|
||||
QUnit.module("GIF picker");
|
||||
|
||||
QUnit.test("composer should display a GIF button", async (assert) => {
|
||||
QUnit.test("composer should display a GIF button", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, "button[aria-label='GIFs']");
|
||||
openDiscuss(channelId);
|
||||
await contains("button[aria-label='GIFs']");
|
||||
});
|
||||
|
||||
QUnit.test("Composer GIF button should open the GIF picker", async (assert) => {
|
||||
QUnit.test("Composer GIF button should open the GIF picker", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("button[aria-label='GIFs']");
|
||||
assert.containsOnce($, ".o-discuss-GifPicker");
|
||||
await contains(".o-discuss-GifPicker");
|
||||
});
|
||||
|
||||
QUnit.test("Searching for a GIF", async (assert) => {
|
||||
QUnit.test("Searching for a GIF", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "" });
|
||||
const { openDiscuss } = await start({
|
||||
@@ -110,7 +110,7 @@ QUnit.test("Searching for a GIF", async (assert) => {
|
||||
},
|
||||
});
|
||||
openDiscuss(channelId);
|
||||
(await contains("button[aria-label='GIFs']")).click();
|
||||
await click("button[aria-label='GIFs']");
|
||||
insertText((await contains("input[placeholder='Search for a gif']"))[0], "search");
|
||||
await contains("i[aria-label='back']");
|
||||
await contains(".o-discuss-Gif", 2);
|
||||
@@ -130,8 +130,8 @@ QUnit.test("Open a GIF category trigger the search for the category", async (ass
|
||||
},
|
||||
});
|
||||
openDiscuss(channelId);
|
||||
(await contains("button[aria-label='GIFs']")).click();
|
||||
(await contains("img[data-src='https://media.tenor.com/6uIlQAHIkNoAAAAM/cry.gif']")).click();
|
||||
await click("button[aria-label='GIFs']");
|
||||
await click("img[data-src='https://media.tenor.com/6uIlQAHIkNoAAAAM/cry.gif']");
|
||||
await contains(".o-discuss-Gif", 2);
|
||||
assert.strictEqual(
|
||||
document.querySelector("input[placeholder='Search for a gif']").value,
|
||||
@@ -139,7 +139,7 @@ QUnit.test("Open a GIF category trigger the search for the category", async (ass
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("Reopen GIF category list when going back", async (assert) => {
|
||||
QUnit.test("Reopen GIF category list when going back", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "" });
|
||||
const { openDiscuss } = await start({
|
||||
@@ -152,14 +152,14 @@ QUnit.test("Reopen GIF category list when going back", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("button[aria-label='GIFs']");
|
||||
await click("img[data-src='https://media.tenor.com/6uIlQAHIkNoAAAAM/cry.gif']");
|
||||
await click("i[aria-label='back']");
|
||||
assert.containsOnce($, ".o-discuss-GifPicker div[aria-label='list']");
|
||||
await contains(".o-discuss-GifPicker div[aria-label='list']");
|
||||
});
|
||||
|
||||
QUnit.test("Add GIF to favorite", async (assert) => {
|
||||
QUnit.test("Add GIF to favorite", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "" });
|
||||
const { openDiscuss } = await start({
|
||||
@@ -172,35 +172,35 @@ QUnit.test("Add GIF to favorite", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("button[aria-label='GIFs']");
|
||||
await click("img[data-src='https://media.tenor.com/6uIlQAHIkNoAAAAM/cry.gif']");
|
||||
await click($(".o-discuss-Gif .fa-star-o"));
|
||||
assert.containsOnce($, ".o-discuss-Gif .fa-star");
|
||||
await click(".o-discuss-Gif .fa-star-o:eq(0)");
|
||||
await contains(".o-discuss-Gif .fa-star");
|
||||
await click("i[aria-label='back']");
|
||||
await click(".o-discuss-GifPicker div[aria-label='list-item']:contains(Favorites)");
|
||||
assert.containsOnce($, ".o-discuss-Gif");
|
||||
await contains(".o-discuss-Gif");
|
||||
});
|
||||
|
||||
QUnit.test("Chatter should not have the GIF button", async (assert) => {
|
||||
QUnit.test("Chatter should not have the GIF button", async () => {
|
||||
const { openFormView, pyEnv } = await start();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "John Doe" });
|
||||
await openFormView("res.partner", partnerId);
|
||||
openFormView("res.partner", partnerId);
|
||||
await click("button:contains(Log note)");
|
||||
assert.containsNone($, "button[aria-label='GIFs']");
|
||||
await contains("button[aria-label='GIFs']", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"Composer GIF button should open the GIF picker keyboard for mobile device",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "channel" });
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
patchUiSize({ size: SIZES.SM });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId, { waitUntilMessagesLoaded: false });
|
||||
await click("span:contains(channel)");
|
||||
openDiscuss(channelId, { waitUntilMessagesLoaded: false });
|
||||
await click("span:contains(General)");
|
||||
await click("button[aria-label='GIFs']");
|
||||
assert.containsNone($, ".popover .o-discuss-GifPicker");
|
||||
assert.containsOnce($, ".o-mail-Composer-footer .o-discuss-GifPicker");
|
||||
await contains(".popover .o-discuss-GifPicker", 0);
|
||||
await contains(".o-mail-Composer-footer .o-discuss-GifPicker");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -199,7 +199,7 @@ patch(MockServer.prototype, {
|
||||
);
|
||||
const otherMembers = this.getRecords("discuss.channel.member", [
|
||||
["channel_id", "=", channel.id],
|
||||
["id", "!=", memberOfCurrentUser?.id],
|
||||
["id", "!=", memberOfCurrentUser?.id || false],
|
||||
]);
|
||||
for (const member of otherMembers) {
|
||||
this.pyEnv["discuss.channel.member"].write([member.id], {
|
||||
@@ -666,7 +666,7 @@ patch(MockServer.prototype, {
|
||||
let is_editable;
|
||||
switch (channel.channel_type) {
|
||||
case "channel":
|
||||
is_editable = channel.create_uid === this.pyEnv.currentPartnerId;
|
||||
is_editable = channel.create_uid === this.pyEnv.currentUserId;
|
||||
break;
|
||||
case "group":
|
||||
is_editable = memberOfCurrentUser;
|
||||
|
||||
@@ -125,23 +125,6 @@ function getAfterEvent({ messagingBus }) {
|
||||
};
|
||||
}
|
||||
|
||||
function getClick({ target, afterNextRender }) {
|
||||
return async function click(selector) {
|
||||
await afterNextRender(() => {
|
||||
if (typeof selector === "string") {
|
||||
$(target ?? document.body)
|
||||
.find(selector)[0]
|
||||
.click();
|
||||
} else if (selector instanceof HTMLElement) {
|
||||
selector.click();
|
||||
} else {
|
||||
// jquery
|
||||
selector[0].click();
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function getMouseenter({ afterNextRender }) {
|
||||
return async function mouseenter(selector) {
|
||||
await afterNextRender(() =>
|
||||
@@ -431,7 +414,6 @@ async function start(param0 = {}) {
|
||||
advanceTime,
|
||||
afterEvent,
|
||||
afterNextRender,
|
||||
click: getClick({ target, afterNextRender }),
|
||||
env: webClient.env,
|
||||
insertText,
|
||||
mouseenter: getMouseenter({ afterNextRender }),
|
||||
@@ -538,19 +520,24 @@ function pasteFiles(el, files) {
|
||||
*/
|
||||
export async function insertText(target, content, { replace = false } = {}) {
|
||||
if (typeof target === "string") {
|
||||
target = document.querySelector(target);
|
||||
target = (await contains(target))[0];
|
||||
}
|
||||
await afterNextRender(() => {
|
||||
if (replace) {
|
||||
target.value = "";
|
||||
}
|
||||
target.focus();
|
||||
for (const char of content) {
|
||||
document.execCommand("insertText", false, char);
|
||||
target.dispatchEvent(new window.KeyboardEvent("keydown", { key: char }));
|
||||
target.dispatchEvent(new window.KeyboardEvent("keyup", { key: char }));
|
||||
}
|
||||
});
|
||||
if (replace) {
|
||||
target.value = "";
|
||||
}
|
||||
target.focus();
|
||||
for (const char of content) {
|
||||
document.execCommand("insertText", false, char);
|
||||
target.dispatchEvent(new window.KeyboardEvent("keydown", { key: char }));
|
||||
target.dispatchEvent(new window.KeyboardEvent("keyup", { key: char }));
|
||||
target.dispatchEvent(new window.InputEvent("input"));
|
||||
target.dispatchEvent(new window.InputEvent("change"));
|
||||
}
|
||||
if (!content) {
|
||||
target.dispatchEvent(new window.InputEvent("input"));
|
||||
target.dispatchEvent(new window.InputEvent("change"));
|
||||
}
|
||||
return $(target);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -671,36 +658,62 @@ export {
|
||||
startServer,
|
||||
};
|
||||
|
||||
export const click = getClick({ afterNextRender });
|
||||
export async function click(selector, { target = document.body } = {}) {
|
||||
if (typeof selector === "string") {
|
||||
const $e = await contains(selector, 1, { target });
|
||||
$e[0].click();
|
||||
return $($e[0]);
|
||||
} else if (selector instanceof HTMLElement) {
|
||||
selector.click();
|
||||
return Promise.resolve($(selector));
|
||||
} else {
|
||||
// jquery
|
||||
selector[0].click();
|
||||
return Promise.resolve($(selector[0]));
|
||||
}
|
||||
}
|
||||
|
||||
let hasUsedContainsPositively = false;
|
||||
QUnit.testStart(() => (hasUsedContainsPositively = false));
|
||||
/**
|
||||
* Function that wait until a selector is present in the DOM
|
||||
* Function that waits until a selector is present in the DOM.
|
||||
*
|
||||
* @param {string} selector
|
||||
* @param {number} [count=1]
|
||||
* @returns {JQuery<HTMLElement>}
|
||||
*/
|
||||
export function until(selector, count = 1) {
|
||||
const res = $(selector);
|
||||
export function contains(selector, count = 1, { target = document.body } = {}) {
|
||||
if (count) {
|
||||
hasUsedContainsPositively = true;
|
||||
} else if (!hasUsedContainsPositively) {
|
||||
throw new Error(
|
||||
`Starting a test with "contains" of count 0 for selector "${selector}" is useless because it might immediately resolve. Start the test by checking that an expected element actually exists.`
|
||||
);
|
||||
}
|
||||
const res = $(target).find(selector);
|
||||
const resMessage = `Found ${count} occurrence(s) of ${selector}`;
|
||||
if (res.length === count) {
|
||||
QUnit.assert.ok(true, resMessage);
|
||||
return Promise.resolve(res);
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
let done = false;
|
||||
const timer = setTimeout(() => {
|
||||
observer.disconnect();
|
||||
const res = $(selector);
|
||||
const res = $(target).find(selector);
|
||||
const message = `Waited 5 second for ${count} occurrence(s) of ${selector}. Found ${res.length} instead.`;
|
||||
QUnit.assert.ok(false, message);
|
||||
reject(new Error(message));
|
||||
done = true;
|
||||
}, 5000);
|
||||
const observer = new MutationObserver(() => {
|
||||
const res = $(selector);
|
||||
const res = $(target).find(selector);
|
||||
if (res.length === count) {
|
||||
observer.disconnect();
|
||||
QUnit.assert.ok(true, resMessage);
|
||||
resolve(res);
|
||||
observer.disconnect();
|
||||
clearTimeout(timer);
|
||||
done = true;
|
||||
}
|
||||
});
|
||||
observer.observe(document.body, {
|
||||
@@ -708,5 +721,16 @@ export function until(selector, count = 1) {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
});
|
||||
registerCleanup(() => {
|
||||
if (!done) {
|
||||
observer.disconnect();
|
||||
const res = $(target).find(selector);
|
||||
const message = `Test ended while waiting for ${count} occurrence(s) of ${selector}. Found ${res.length} instead.`;
|
||||
QUnit.assert.ok(false, message);
|
||||
reject(new Error(message));
|
||||
clearTimeout(timer);
|
||||
done = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { addLink, parseAndTransform } from "@mail/utils/common/format";
|
||||
import { start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
QUnit.module("Mail utils");
|
||||
|
||||
@@ -97,76 +97,75 @@ QUnit.test("addLink: linkify inside text node (2 occurrences)", function (assert
|
||||
assert.strictEqual(div.querySelectorAll(":scope a")[1].textContent, "https://somelink2.com");
|
||||
});
|
||||
|
||||
QUnit.test("url", async (assert) => {
|
||||
QUnit.test("url", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const { click, insertText, openDiscuss } = await start();
|
||||
const { insertText, openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
// see: https://www.ietf.org/rfc/rfc1738.txt
|
||||
const messageBody = "https://odoo.com?test=~^|`{}[]#";
|
||||
await insertText(".o-mail-Composer-input", messageBody);
|
||||
await click("button:contains(Send)");
|
||||
assert.containsOnce($, `.o-mail-Message a:contains(${messageBody})`);
|
||||
await click("button:contains(Send):not(:disabled)");
|
||||
await contains(`.o-mail-Message a:contains(${messageBody})`);
|
||||
});
|
||||
|
||||
QUnit.test("url with comma at the end", async (assert) => {
|
||||
QUnit.test("url with comma at the end", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const { click, insertText, openDiscuss } = await start();
|
||||
const { insertText, openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
const messageBody = "Go to https://odoo.com, it's great!";
|
||||
await insertText(".o-mail-Composer-input", messageBody);
|
||||
await click("button:contains(Send)");
|
||||
assert.containsOnce($, `.o-mail-Message a:contains(https://odoo.com)`);
|
||||
assert.containsOnce($, `.o-mail-Message:contains(${messageBody})`);
|
||||
await click("button:contains(Send):not(:disabled)");
|
||||
await contains(`.o-mail-Message a:contains(https://odoo.com)`);
|
||||
await contains(`.o-mail-Message:contains(${messageBody})`);
|
||||
});
|
||||
|
||||
QUnit.test("url with dot at the end", async (assert) => {
|
||||
QUnit.test("url with dot at the end", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const { click, insertText, openDiscuss } = await start();
|
||||
const { insertText, openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
const messageBody = "Go to https://odoo.com. It's great!";
|
||||
await insertText(".o-mail-Composer-input", messageBody);
|
||||
await click("button:contains(Send)");
|
||||
assert.containsOnce($, `.o-mail-Message a:contains(https://odoo.com)`);
|
||||
assert.containsOnce($, `.o-mail-Message:contains(${messageBody})`);
|
||||
await click("button:contains(Send):not(:disabled)");
|
||||
await contains(`.o-mail-Message a:contains(https://odoo.com)`);
|
||||
await contains(`.o-mail-Message:contains(${messageBody})`);
|
||||
});
|
||||
|
||||
QUnit.test("url with semicolon at the end", async (assert) => {
|
||||
QUnit.test("url with semicolon at the end", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const { click, insertText, openDiscuss } = await start();
|
||||
const { insertText, openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
const messageBody = "Go to https://odoo.com; it's great!";
|
||||
await insertText(".o-mail-Composer-input", messageBody);
|
||||
await click("button:contains(Send)");
|
||||
assert.containsOnce($, `.o-mail-Message a:contains(https://odoo.com)`);
|
||||
assert.containsOnce($, `.o-mail-Message:contains(${messageBody})`);
|
||||
await click("button:contains(Send):not(:disabled)");
|
||||
await contains(`.o-mail-Message a:contains(https://odoo.com)`);
|
||||
await contains(`.o-mail-Message:contains(${messageBody})`);
|
||||
});
|
||||
|
||||
QUnit.test("url with ellipsis at the end", async (assert) => {
|
||||
QUnit.test("url with ellipsis at the end", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const { click, insertText, openDiscuss } = await start();
|
||||
const { insertText, openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
const messageBody = "Go to https://odoo.com... it's great!";
|
||||
await insertText(".o-mail-Composer-input", messageBody);
|
||||
await click("button:contains(Send)");
|
||||
assert.containsOnce($, `.o-mail-Message a:contains(https://odoo.com)`);
|
||||
assert.containsOnce($, `.o-mail-Message:contains(${messageBody})`);
|
||||
await click("button:contains(Send):not(:disabled)");
|
||||
await contains(`.o-mail-Message a:contains(https://odoo.com)`);
|
||||
await contains(`.o-mail-Message:contains(${messageBody})`);
|
||||
});
|
||||
|
||||
QUnit.test("url with number in subdomain", async (assert) => {
|
||||
QUnit.test("url with number in subdomain", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const { click, insertText, openDiscuss } = await start();
|
||||
const { insertText, openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
const messageBody = "https://www.45017478-master-all.runbot134.odoo.com/web";
|
||||
await insertText(".o-mail-Composer-input", messageBody);
|
||||
await click("button:contains(Send)");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
await click("button:contains(Send):not(:disabled)");
|
||||
await contains(
|
||||
`.o-mail-Message a:contains(https://www.45017478-master-all.runbot134.odoo.com/web)`
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, nextAnimationFrame, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import {
|
||||
click,
|
||||
contains,
|
||||
nextAnimationFrame,
|
||||
start,
|
||||
startServer,
|
||||
} from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
QUnit.module("link preview");
|
||||
|
||||
QUnit.test("auto layout with link preview list", async (assert) => {
|
||||
QUnit.test("auto layout with link preview list", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const linkPreviewId = pyEnv["mail.link.preview"].create({
|
||||
og_description: "test description",
|
||||
@@ -23,11 +29,11 @@ QUnit.test("auto layout with link preview list", async (assert) => {
|
||||
res_id: channelId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-Message .o-mail-LinkPreviewList");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Message .o-mail-LinkPreviewList");
|
||||
});
|
||||
|
||||
QUnit.test("auto layout with link preview as gif", async (assert) => {
|
||||
QUnit.test("auto layout with link preview as gif", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const linkPreviewId = pyEnv["mail.link.preview"].create({
|
||||
og_description: "test description",
|
||||
@@ -46,11 +52,11 @@ QUnit.test("auto layout with link preview as gif", async (assert) => {
|
||||
res_id: channelId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-LinkPreviewImage");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-LinkPreviewImage");
|
||||
});
|
||||
|
||||
QUnit.test("simplest card layout", async (assert) => {
|
||||
QUnit.test("simplest card layout", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const linkPreviewId = pyEnv["mail.link.preview"].create({
|
||||
og_description: "Description",
|
||||
@@ -67,13 +73,13 @@ QUnit.test("simplest card layout", async (assert) => {
|
||||
res_id: channelId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-LinkPreviewCard");
|
||||
assert.containsOnce($, ".o-mail-LinkPreviewCard:contains(Article title)");
|
||||
assert.containsOnce($, ".o-mail-LinkPreviewCard:contains(Description)");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-LinkPreviewCard");
|
||||
await contains(".o-mail-LinkPreviewCard:contains(Article title)");
|
||||
await contains(".o-mail-LinkPreviewCard:contains(Description)");
|
||||
});
|
||||
|
||||
QUnit.test("simplest card layout with image", async (assert) => {
|
||||
QUnit.test("simplest card layout with image", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const linkPreviewId = pyEnv["mail.link.preview"].create({
|
||||
og_description: "Description",
|
||||
@@ -91,14 +97,14 @@ QUnit.test("simplest card layout with image", async (assert) => {
|
||||
res_id: channelId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-LinkPreviewCard");
|
||||
assert.containsOnce($, ".o-mail-LinkPreviewCard:contains(Article title)");
|
||||
assert.containsOnce($, ".o-mail-LinkPreviewCard:contains(Description)");
|
||||
assert.containsOnce($, ".o-mail-LinkPreviewCard img");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-LinkPreviewCard");
|
||||
await contains(".o-mail-LinkPreviewCard:contains(Article title)");
|
||||
await contains(".o-mail-LinkPreviewCard:contains(Description)");
|
||||
await contains(".o-mail-LinkPreviewCard img");
|
||||
});
|
||||
|
||||
QUnit.test("Link preview video layout", async (assert) => {
|
||||
QUnit.test("Link preview video layout", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const linkPreviewId = pyEnv["mail.link.preview"].create({
|
||||
og_description: "Description",
|
||||
@@ -116,14 +122,14 @@ QUnit.test("Link preview video layout", async (assert) => {
|
||||
res_id: channelId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-LinkPreviewVideo");
|
||||
assert.containsOnce($, ".o-mail-LinkPreviewVideo:contains(video title)");
|
||||
assert.containsOnce($, ".o-mail-LinkPreviewVideo:contains(Description)");
|
||||
assert.containsOnce($, ".o-mail-LinkPreviewVideo-overlay");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-LinkPreviewVideo");
|
||||
await contains(".o-mail-LinkPreviewVideo:contains(video title)");
|
||||
await contains(".o-mail-LinkPreviewVideo:contains(Description)");
|
||||
await contains(".o-mail-LinkPreviewVideo-overlay");
|
||||
});
|
||||
|
||||
QUnit.test("Link preview image layout", async (assert) => {
|
||||
QUnit.test("Link preview image layout", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const linkPreviewId = pyEnv["mail.link.preview"].create({
|
||||
image_mimetype: "image/jpg",
|
||||
@@ -139,11 +145,11 @@ QUnit.test("Link preview image layout", async (assert) => {
|
||||
res_id: channelId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-LinkPreviewImage");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-LinkPreviewImage");
|
||||
});
|
||||
|
||||
QUnit.test("Remove link preview Gif", async (assert) => {
|
||||
QUnit.test("Remove link preview Gif", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const linkPreviewId = pyEnv["mail.link.preview"].create({
|
||||
og_description: "test description",
|
||||
@@ -162,14 +168,14 @@ QUnit.test("Remove link preview Gif", async (assert) => {
|
||||
res_id: channelId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-LinkPreviewImage button[aria-label='Remove']");
|
||||
assert.containsOnce($, "p:contains(Do you really want to delete this preview?)");
|
||||
await contains("p:contains(Do you really want to delete this preview?)");
|
||||
await click(".modal-footer button:contains(Ok)");
|
||||
assert.containsNone($, ".o-mail-LinkPreviewImage");
|
||||
await contains(".o-mail-LinkPreviewImage", 0);
|
||||
});
|
||||
|
||||
QUnit.test("Remove link preview card", async (assert) => {
|
||||
QUnit.test("Remove link preview card", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const linkPreviewId = pyEnv["mail.link.preview"].create({
|
||||
og_description: "Description",
|
||||
@@ -186,14 +192,14 @@ QUnit.test("Remove link preview card", async (assert) => {
|
||||
res_id: channelId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-LinkPreviewCard button[aria-label='Remove']");
|
||||
assert.containsOnce($, "p:contains(Do you really want to delete this preview?)");
|
||||
await contains("p:contains(Do you really want to delete this preview?)");
|
||||
await click(".modal-footer button:contains(Ok)");
|
||||
assert.containsNone($, ".o-mail-LinkPreviewCard");
|
||||
await contains(".o-mail-LinkPreviewCard", 0);
|
||||
});
|
||||
|
||||
QUnit.test("Remove link preview video", async (assert) => {
|
||||
QUnit.test("Remove link preview video", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const linkPreviewId = pyEnv["mail.link.preview"].create({
|
||||
og_description: "Description",
|
||||
@@ -211,14 +217,14 @@ QUnit.test("Remove link preview video", async (assert) => {
|
||||
res_id: channelId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-LinkPreviewVideo button[aria-label='Remove']");
|
||||
assert.containsOnce($, "p:contains(Do you really want to delete this preview?)");
|
||||
await contains("p:contains(Do you really want to delete this preview?)");
|
||||
await click(".modal-footer button:contains(Ok)");
|
||||
assert.containsNone($, ".o-mail-LinkPreviewVideo");
|
||||
await contains(".o-mail-LinkPreviewVideo", 0);
|
||||
});
|
||||
|
||||
QUnit.test("Remove link preview image", async (assert) => {
|
||||
QUnit.test("Remove link preview image", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const linkPreviewId = pyEnv["mail.link.preview"].create({
|
||||
image_mimetype: "image/jpg",
|
||||
@@ -234,11 +240,11 @@ QUnit.test("Remove link preview image", async (assert) => {
|
||||
res_id: channelId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-LinkPreviewImage button[aria-label='Remove']");
|
||||
assert.containsOnce($, "p:contains(Do you really want to delete this preview?)");
|
||||
await contains("p:contains(Do you really want to delete this preview?)");
|
||||
await click(".modal-footer button:contains(Ok)");
|
||||
assert.containsNone($, ".o-mail-LinkPreviewImage");
|
||||
await contains(".o-mail-LinkPreviewImage", 0);
|
||||
});
|
||||
|
||||
QUnit.test("No crash on receiving link preview of non-known message", async (assert) => {
|
||||
@@ -257,7 +263,7 @@ QUnit.test("No crash on receiving link preview of non-known message", async (ass
|
||||
res_id: channelId,
|
||||
});
|
||||
const { env, openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
openDiscuss();
|
||||
env.services.rpc("/mail/link_preview", { message_id: messageId });
|
||||
await nextAnimationFrame();
|
||||
assert.ok(true);
|
||||
@@ -268,7 +274,7 @@ QUnit.test("No crash on receiving link preview of non-known message", async (ass
|
||||
|
||||
QUnit.test(
|
||||
"Squash the message and the link preview when the link preview is an image and the link is the only text in the message",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const linkPreviewId = pyEnv["mail.link.preview"].create({
|
||||
image_mimetype: "image/jpg",
|
||||
@@ -284,14 +290,15 @@ QUnit.test(
|
||||
res_id: channelId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsNone($, ".o-mail-Message-bubble");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-LinkPreviewImage");
|
||||
await contains(".o-mail-Message-bubble", 0);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"Link preview and message should not be squashed when the link preview is not an image",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const linkPreviewId = pyEnv["mail.link.preview"].create({
|
||||
og_description: "Description",
|
||||
@@ -308,14 +315,14 @@ QUnit.test(
|
||||
res_id: channelId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-Message-bubble");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Message-bubble");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"Link preview and message should not be squashed when there is more than the link in the message",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const linkPreviewId = pyEnv["mail.link.preview"].create({
|
||||
image_mimetype: "image/jpg",
|
||||
@@ -331,7 +338,7 @@ QUnit.test(
|
||||
res_id: channelId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-Message-bubble");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Message-bubble");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { nextTick, patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("message reply");
|
||||
|
||||
QUnit.test("click on message in reply to highlight the parent message", async (assert) => {
|
||||
QUnit.test("click on message in reply to highlight the parent message", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "general" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
@@ -23,9 +23,9 @@ QUnit.test("click on message in reply to highlight the parent message", async (a
|
||||
res_id: channelId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-Message:contains(Reply to Hey) .o-mail-MessageInReply-message");
|
||||
assert.containsOnce($, ".o-mail-Message:contains(Hey lol).o-highlighted");
|
||||
await contains(".o-mail-Message:contains(Hey lol).o-highlighted");
|
||||
});
|
||||
|
||||
QUnit.test("click on message in reply to scroll to the parent message", async (assert) => {
|
||||
@@ -55,7 +55,7 @@ QUnit.test("click on message in reply to scroll to the parent message", async (a
|
||||
res_id: channelId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(
|
||||
".o-mail-Message:contains(Response to first message) .o-mail-MessageInReply-message"
|
||||
);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -83,7 +83,7 @@ QUnit.test(
|
||||
const { openDiscuss, openFormView } = await start();
|
||||
await openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "test https://www.odoo.com/");
|
||||
await click(".o-mail-Composer-send");
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
// leaving discuss.
|
||||
await openFormView("res.partner", partnerId);
|
||||
assert.containsNone($, ".o-mail-ChatWindow-header:contains(Dumbledore)");
|
||||
|
||||
@@ -17,23 +17,23 @@ import { patchWithCleanup, triggerEvent } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("messaging menu");
|
||||
|
||||
QUnit.test("should have messaging menu button in systray", async (assert) => {
|
||||
QUnit.test("should have messaging menu button in systray", async () => {
|
||||
await start();
|
||||
assert.containsOnce($, ".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsNone($, ".o-mail-MessagingMenu", "messaging menu closed by default");
|
||||
assert.hasClass($(".o_menu_systray i[aria-label='Messages']"), "fa-comments");
|
||||
await contains(".o_menu_systray i[aria-label='Messages']");
|
||||
await contains(".o-mail-MessagingMenu", 0);
|
||||
await contains(".o_menu_systray i[aria-label='Messages'].fa-comments");
|
||||
});
|
||||
|
||||
QUnit.test("messaging menu should have topbar buttons", async (assert) => {
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsOnce($, ".o-mail-MessagingMenu");
|
||||
assert.containsN($, ".o-mail-MessagingMenu-header button", 4);
|
||||
assert.containsOnce($, "button:contains(All)");
|
||||
assert.containsOnce($, "button:contains(Chat)");
|
||||
assert.containsOnce($, "button:contains(Channel)");
|
||||
assert.containsOnce($, "button:contains(New Message)");
|
||||
assert.hasClass($("button:contains(All)"), "fw-bolder");
|
||||
await contains(".o-mail-MessagingMenu");
|
||||
await contains(".o-mail-MessagingMenu-header button", 4);
|
||||
await contains("button:contains(All)");
|
||||
await contains("button:contains(Chat)");
|
||||
await contains("button:contains(Channel)");
|
||||
await contains("button:contains(New Message)");
|
||||
await contains("button:contains(All).fw-bolder");
|
||||
assert.doesNotHaveClass($("button:contains(Chat)"), "fw-bolder");
|
||||
assert.doesNotHaveClass($("button:contains(Channel)"), "fw-bolder");
|
||||
});
|
||||
@@ -59,17 +59,17 @@ QUnit.test("counter is taking into account failure notification", async (assert)
|
||||
notification_type: "email",
|
||||
});
|
||||
await start();
|
||||
assert.containsOnce($, ".o-mail-MessagingMenu-counter");
|
||||
assert.strictEqual($(".o-mail-MessagingMenu-counter.badge").text(), "1");
|
||||
await contains(".o-mail-MessagingMenu-counter");
|
||||
assert.strictEqual($(".o-mail-MessagingMenu-counter").text(), "1");
|
||||
});
|
||||
|
||||
QUnit.test("rendering with OdooBot has a request (default)", async (assert) => {
|
||||
patchBrowserNotification("default");
|
||||
await start();
|
||||
assert.containsOnce($, ".o-mail-MessagingMenu-counter");
|
||||
await contains(".o-mail-MessagingMenu-counter");
|
||||
assert.strictEqual($(".o-mail-MessagingMenu-counter").text(), "1");
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem");
|
||||
await contains(".o-mail-NotificationItem");
|
||||
assert.ok(
|
||||
$(".o-mail-NotificationItem img")
|
||||
.data("src")
|
||||
@@ -78,20 +78,20 @@ QUnit.test("rendering with OdooBot has a request (default)", async (assert) => {
|
||||
assert.strictEqual($(".o-mail-NotificationItem-name").text().trim(), "OdooBot has a request");
|
||||
});
|
||||
|
||||
QUnit.test("rendering without OdooBot has a request (denied)", async (assert) => {
|
||||
QUnit.test("rendering without OdooBot has a request (denied)", async () => {
|
||||
patchBrowserNotification("denied");
|
||||
await start();
|
||||
assert.containsNone($, ".o-mail-MessagingMenu-counter-badge");
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsNone($, ".o-mail-NotificationItem");
|
||||
await contains(".o-mail-MessagingMenu-counter", 0);
|
||||
await contains(".o-mail-NotificationItem", 0);
|
||||
});
|
||||
|
||||
QUnit.test("rendering without OdooBot has a request (accepted)", async (assert) => {
|
||||
QUnit.test("rendering without OdooBot has a request (accepted)", async () => {
|
||||
patchBrowserNotification("granted");
|
||||
await start();
|
||||
assert.containsNone($, ".o-mail-MessagingMenu-counter-badge");
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsNone($, ".o-mail-NotificationItem");
|
||||
await contains(".o-mail-MessagingMenu-counter", 0);
|
||||
await contains(".o-mail-NotificationItem", 0);
|
||||
});
|
||||
|
||||
QUnit.test("respond to notification prompt (denied)", async (assert) => {
|
||||
@@ -106,9 +106,9 @@ QUnit.test("respond to notification prompt (denied)", async (assert) => {
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
assert.verifySteps(["confirmation_denied_toast"]);
|
||||
assert.containsNone($, ".o-mail-MessagingMenu-counter-badge");
|
||||
await contains(".o-mail-MessagingMenu-counter", 0);
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsNone($, ".o-mail-NotificationItem");
|
||||
await contains(".o-mail-NotificationItem", 0);
|
||||
});
|
||||
|
||||
QUnit.test("respond to notification prompt (granted)", async (assert) => {
|
||||
@@ -125,44 +125,44 @@ QUnit.test("respond to notification prompt (granted)", async (assert) => {
|
||||
assert.verifySteps(["confirmation_granted_toast"]);
|
||||
});
|
||||
|
||||
QUnit.test("no 'OdooBot has a request' in mobile app", async (assert) => {
|
||||
QUnit.test("no 'OdooBot has a request' in mobile app", async () => {
|
||||
patchBrowserNotification("default");
|
||||
// simulate Android Odoo App
|
||||
patchWithCleanup(browser.navigator, {
|
||||
userAgent: "Chrome/0.0.0 Android (OdooMobile; Linux; Android 13; Odoo TestSuite)",
|
||||
});
|
||||
await start();
|
||||
assert.containsNone($, ".o-mail-MessagingMenu-counter");
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsNone($, ".o-mail-NotificationItem");
|
||||
await contains(".o-mail-MessagingMenu-counter", 0);
|
||||
await contains(".o-mail-NotificationItem", 0);
|
||||
});
|
||||
|
||||
QUnit.test("Is closed after clicking on new message", async (assert) => {
|
||||
QUnit.test("Is closed after clicking on new message", async () => {
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click("button:contains(New Message)");
|
||||
assert.containsNone($, ".o-mail-MessagingMenu");
|
||||
await contains(".o-mail-MessagingMenu", 0);
|
||||
});
|
||||
|
||||
QUnit.test("no 'New Message' button when discuss is open", async (assert) => {
|
||||
QUnit.test("no 'New Message' button when discuss is open", async () => {
|
||||
const { openDiscuss, openView } = await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsOnce($, "button:contains(New Message)");
|
||||
await contains("button:contains(New Message)");
|
||||
|
||||
await openDiscuss();
|
||||
assert.containsNone($, "button:contains(New Message)");
|
||||
await contains("button:contains(New Message)", 0);
|
||||
|
||||
await openView({
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, "button:contains(New Message)");
|
||||
await contains("button:contains(New Message)");
|
||||
|
||||
await openDiscuss();
|
||||
assert.containsNone($, "button:contains(New Message)");
|
||||
await contains("button:contains(New Message)", 0);
|
||||
});
|
||||
|
||||
QUnit.test("grouped notifications by document", async (assert) => {
|
||||
QUnit.test("grouped notifications by document", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const [messageId_1, messageId_2] = pyEnv["mail.message"].create([
|
||||
{
|
||||
@@ -192,12 +192,12 @@ QUnit.test("grouped notifications by document", async (assert) => {
|
||||
]);
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem:contains(Partner) .badge:contains(2)");
|
||||
assert.containsNone($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-NotificationItem");
|
||||
await contains(".o-mail-NotificationItem:contains(Partner) .badge:contains(2)");
|
||||
await contains(".o-mail-ChatWindow", 0);
|
||||
|
||||
await click(".o-mail-NotificationItem");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
});
|
||||
|
||||
QUnit.test("grouped notifications by document model", async (assert) => {
|
||||
@@ -252,7 +252,7 @@ QUnit.test("grouped notifications by document model", async (assert) => {
|
||||
},
|
||||
});
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem:contains(Partner) .badge:contains(2)");
|
||||
await contains(".o-mail-NotificationItem:contains(Partner) .badge:contains(2)");
|
||||
|
||||
$(".o-mail-NotificationItem")[0].click();
|
||||
assert.verifySteps(["do_action"]);
|
||||
@@ -300,13 +300,13 @@ QUnit.test(
|
||||
]);
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsN($, ".o-mail-NotificationItem", 2);
|
||||
await contains(".o-mail-NotificationItem", 2);
|
||||
assert.ok($(".o-mail-NotificationItem:eq(0)").text().includes("Company"));
|
||||
assert.ok($(".o-mail-NotificationItem:eq(1)").text().includes("Partner"));
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("non-failure notifications are ignored", async (assert) => {
|
||||
QUnit.test("non-failure notifications are ignored", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
@@ -321,7 +321,7 @@ QUnit.test("non-failure notifications are ignored", async (assert) => {
|
||||
});
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsNone($, ".o-mail-NotificationItem");
|
||||
await contains(".o-mail-NotificationItem", 0);
|
||||
});
|
||||
|
||||
QUnit.test("mark unread channel as read", async (assert) => {
|
||||
@@ -350,15 +350,15 @@ QUnit.test("mark unread channel as read", async (assert) => {
|
||||
},
|
||||
});
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await triggerEvent($(".o-mail-NotificationItem")[0], null, "mouseenter");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem [title='Mark As Read']");
|
||||
await triggerEvent((await contains(".o-mail-NotificationItem"))[0], null, "mouseenter");
|
||||
await contains(".o-mail-NotificationItem [title='Mark As Read']");
|
||||
|
||||
await click(".o-mail-NotificationItem [title='Mark As Read']");
|
||||
assert.verifySteps(["set_last_seen_message"]);
|
||||
assert.hasClass($(".o-mail-NotificationItem"), "o-muted");
|
||||
await contains(".o-mail-NotificationItem.o-muted");
|
||||
await triggerEvent($(".o-mail-NotificationItem")[0], null, "mouseenter");
|
||||
assert.containsNone($, ".o-mail-NotificationItem [title='Mark As Read']");
|
||||
assert.containsNone($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-NotificationItem [title='Mark As Read']", 0);
|
||||
await contains(".o-mail-ChatWindow", 0);
|
||||
});
|
||||
|
||||
QUnit.test("mark failure as read", async (assert) => {
|
||||
@@ -380,23 +380,20 @@ QUnit.test("mark failure as read", async (assert) => {
|
||||
});
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem:contains(Channel)");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o-mail-NotificationItem:contains(An error occurred when sending an email)"
|
||||
);
|
||||
await contains(".o-mail-NotificationItem:contains(Channel)");
|
||||
await contains(".o-mail-NotificationItem:contains(An error occurred when sending an email)");
|
||||
await triggerEvent($(".o-mail-NotificationItem:contains(Channel)")[0], null, "mouseenter");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem:contains(Channel) [title='Mark As Read']");
|
||||
await contains(".o-mail-NotificationItem:contains(Channel) [title='Mark As Read']");
|
||||
|
||||
await click(".o-mail-NotificationItem [title='Mark As Read']");
|
||||
assert.containsNone($, ".o-mail-NotificationItem:contains(Channel)");
|
||||
await contains(".o-mail-NotificationItem:contains(Channel)", 0);
|
||||
assert.containsNone(
|
||||
$,
|
||||
".o-mail-NotificationItem:contains(An error occurred when sending an email)"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("different discuss.channel are not grouped", async (assert) => {
|
||||
QUnit.test("different discuss.channel are not grouped", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const [channelId_1, channelId_2] = pyEnv["discuss.channel"].create([
|
||||
{ name: "Channel_1" },
|
||||
@@ -440,75 +437,72 @@ QUnit.test("different discuss.channel are not grouped", async (assert) => {
|
||||
]);
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsN($, ".o-mail-NotificationItem", 4);
|
||||
await contains(".o-mail-NotificationItem", 4);
|
||||
|
||||
const group_1 = $(".o-mail-NotificationItem:contains(Channel):first");
|
||||
await click(group_1);
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
});
|
||||
|
||||
QUnit.test("mobile: active icon is highlighted", async (assert) => {
|
||||
QUnit.test("mobile: active icon is highlighted", async () => {
|
||||
patchUiSize({ size: SIZES.SM });
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-MessagingMenu-tab:contains(Chat)");
|
||||
assert.hasClass($(".o-mail-MessagingMenu-tab:contains(Chat)"), "fw-bolder");
|
||||
await contains(".o-mail-MessagingMenu-tab:contains(Chat).fw-bolder");
|
||||
});
|
||||
|
||||
QUnit.test("open chat window from preview", async (assert) => {
|
||||
QUnit.test("open chat window from preview", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["discuss.channel"].create({ name: "test" });
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
'"Start a conversation" in mobile shows channel selector (+ click away)',
|
||||
async (assert) => {
|
||||
patchUiSize({ height: 360, width: 640 });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
await click("button:contains(Chat)");
|
||||
assert.containsOnce($, "button:contains(Start a conversation)");
|
||||
assert.containsNone($, "input[placeholder='Start a conversation']");
|
||||
QUnit.test('"Start a conversation" in mobile shows channel selector (+ click away)', async () => {
|
||||
patchUiSize({ height: 360, width: 640 });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
await click("button:contains(Chat)");
|
||||
await contains("button:contains(Start a conversation)");
|
||||
await contains("input[placeholder='Start a conversation']", 0);
|
||||
|
||||
await click("button:contains(Start a conversation)");
|
||||
assert.containsNone($, "button:contains(Start a conversation)");
|
||||
assert.containsOnce($, "input[placeholder='Start a conversation']");
|
||||
await click("button:contains(Start a conversation)");
|
||||
await contains("button:contains(Start a conversation)", 0);
|
||||
await contains("input[placeholder='Start a conversation']");
|
||||
|
||||
await click(".o-mail-MessagingMenu");
|
||||
assert.containsOnce($, "button:contains(Start a conversation)");
|
||||
assert.containsNone($, "input[placeholder='Start a conversation']");
|
||||
}
|
||||
);
|
||||
QUnit.test('"New Channel" in mobile shows channel selector (+ click away)', async (assert) => {
|
||||
await click(".o-mail-MessagingMenu");
|
||||
await contains("button:contains(Start a conversation)");
|
||||
await contains("input[placeholder='Start a conversation']", 0);
|
||||
});
|
||||
QUnit.test('"New Channel" in mobile shows channel selector (+ click away)', async () => {
|
||||
patchUiSize({ height: 360, width: 640 });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
await click("button:contains(Channel)");
|
||||
assert.containsOnce($, "button:contains(New Channel)");
|
||||
assert.containsNone($, "input[placeholder='Add or join a channel']");
|
||||
await contains("button:contains(New Channel)");
|
||||
await contains("input[placeholder='Add or join a channel']", 0);
|
||||
|
||||
await click("button:contains(New Channel)");
|
||||
assert.containsNone($, "button:contains(New Channel)");
|
||||
assert.containsOnce($, "input[placeholder='Add or join a channel']");
|
||||
await contains("button:contains(New Channel)", 0);
|
||||
await contains("input[placeholder='Add or join a channel']");
|
||||
|
||||
await click(".o-mail-MessagingMenu");
|
||||
assert.containsOnce($, "button:contains(New Channel)");
|
||||
assert.containsNone($, "input[placeholder='Add or join a channel']");
|
||||
await contains("button:contains(New Channel)");
|
||||
await contains("input[placeholder='Add or join a channel']", 0);
|
||||
});
|
||||
|
||||
QUnit.test("'New Message' button should open a chat window in mobile", async (assert) => {
|
||||
QUnit.test("'New Message' button should open a chat window in mobile", async () => {
|
||||
patchUiSize({ height: 360, width: 640 });
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click("button:contains(New Message)");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
});
|
||||
|
||||
QUnit.test("Counter is updated when receiving new message", async (assert) => {
|
||||
QUnit.test("Counter is updated when receiving new message", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Albert" });
|
||||
const userId = pyEnv["res.users"].create({ partner_id: partnerId });
|
||||
@@ -536,7 +530,7 @@ QUnit.test("Counter is updated when receiving new message", async (assert) => {
|
||||
})
|
||||
)
|
||||
);
|
||||
assert.containsOnce($, ".o-mail-MessagingMenu-counter.badge:contains(1)");
|
||||
await contains(".o-mail-MessagingMenu-counter:contains(1)");
|
||||
});
|
||||
|
||||
QUnit.test("basic rendering", async (assert) => {
|
||||
@@ -547,27 +541,27 @@ QUnit.test("basic rendering", async (assert) => {
|
||||
},
|
||||
});
|
||||
await start();
|
||||
assert.containsOnce($, ".o_menu_systray .dropdown-toggle:has(i[aria-label='Messages'])");
|
||||
await contains(".o_menu_systray .dropdown-toggle:has(i[aria-label='Messages'])");
|
||||
assert.doesNotHaveClass(
|
||||
$('.o_menu_systray .dropdown-toggle:has(i[aria-label="Messages"])'),
|
||||
"show"
|
||||
);
|
||||
assert.containsOnce($, ".o_menu_systray i[aria-label='Messages']");
|
||||
assert.hasClass($('.o_menu_systray i[aria-label="Messages"]'), "fa-comments");
|
||||
assert.containsNone($, ".o-mail-MessagingMenu");
|
||||
await contains(".o_menu_systray i[aria-label='Messages']");
|
||||
await contains('.o_menu_systray i[aria-label="Messages"].fa-comments');
|
||||
await contains(".o-mail-MessagingMenu", 0);
|
||||
await click(".o_menu_systray .dropdown-toggle:has(i[aria-label='Messages'])");
|
||||
assert.hasClass($('.o_menu_systray .dropdown:has(i[aria-label="Messages"])'), "show");
|
||||
assert.containsOnce($, ".o-mail-MessagingMenu");
|
||||
assert.containsOnce($, ".o-mail-MessagingMenu-header");
|
||||
assert.containsN($, ".o-mail-MessagingMenu-header button", 4);
|
||||
assert.containsOnce($, '.o-mail-MessagingMenu button:contains("All")');
|
||||
assert.containsOnce($, '.o-mail-MessagingMenu button:contains("Chats")');
|
||||
assert.containsOnce($, '.o-mail-MessagingMenu button:contains("Channels")');
|
||||
assert.hasClass($('.o-mail-MessagingMenu button:contains("All")'), "fw-bolder");
|
||||
assert.doesNotHaveClass($('.o-mail-MessagingMenu button:contains("Chats")'), "fw-bolder");
|
||||
assert.doesNotHaveClass($('.o-mail-MessagingMenu button:contains("Channels")'), "fw-bolder");
|
||||
assert.containsOnce($, "button:contains(New Message)");
|
||||
assert.containsOnce($, '.o-mail-MessagingMenu:contains("No conversation yet...")');
|
||||
await contains('.o_menu_systray .dropdown:has(i[aria-label="Messages"]).show');
|
||||
await contains(".o-mail-MessagingMenu");
|
||||
await contains(".o-mail-MessagingMenu-header");
|
||||
await contains(".o-mail-MessagingMenu-header button", 4);
|
||||
await contains('.o-mail-MessagingMenu button:contains("All")');
|
||||
await contains('.o-mail-MessagingMenu button:contains("Chats")');
|
||||
await contains('.o-mail-MessagingMenu button:contains("Channels")');
|
||||
await contains('.o-mail-MessagingMenu button:contains("All").fw-bolder');
|
||||
await contains('.o-mail-MessagingMenu button:contains("Chats"):not(.fw-bolder)');
|
||||
await contains('.o-mail-MessagingMenu button:contains("Channels"):not(.fw-bolder)');
|
||||
await contains("button:contains(New Message)");
|
||||
await contains('.o-mail-MessagingMenu:contains("No conversation yet...")');
|
||||
await click(".o_menu_systray .dropdown-toggle:has(i[aria-label='Messages'])");
|
||||
assert.doesNotHaveClass(
|
||||
$('.o_menu_systray .dropdown-toggle:has(i[aria-label="Messages"])'),
|
||||
@@ -575,30 +569,30 @@ QUnit.test("basic rendering", async (assert) => {
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("switch tab", async (assert) => {
|
||||
QUnit.test("switch tab", async () => {
|
||||
await start();
|
||||
await click(".o_menu_systray .dropdown-toggle:has(i[aria-label='Messages'])");
|
||||
assert.containsOnce($, '.o-mail-MessagingMenu button:contains("All")');
|
||||
assert.containsOnce($, '.o-mail-MessagingMenu button:contains("Chats")');
|
||||
assert.containsOnce($, '.o-mail-MessagingMenu button:contains("Channels")');
|
||||
assert.hasClass($('.o-mail-MessagingMenu button:contains("All")'), "fw-bolder");
|
||||
assert.doesNotHaveClass($('.o-mail-MessagingMenu button:contains("Chats")'), "fw-bolder");
|
||||
assert.doesNotHaveClass($('.o-mail-MessagingMenu button:contains("Channels")'), "fw-bolder");
|
||||
await contains('.o-mail-MessagingMenu button:contains("All")');
|
||||
await contains('.o-mail-MessagingMenu button:contains("Chats")');
|
||||
await contains('.o-mail-MessagingMenu button:contains("Channels")');
|
||||
await contains('.o-mail-MessagingMenu button:contains("All").fw-bolder');
|
||||
await contains('.o-mail-MessagingMenu button:contains("Chats"):not(.fw-bolder)');
|
||||
await contains('.o-mail-MessagingMenu button:contains("Channels"):not(.fw-bolder)');
|
||||
await click('.o-mail-MessagingMenu button:contains("Chats")');
|
||||
assert.doesNotHaveClass($('.o-mail-MessagingMenu button:contains("All")'), "fw-bolder");
|
||||
assert.hasClass($('.o-mail-MessagingMenu button:contains("Chats")'), "fw-bolder");
|
||||
assert.doesNotHaveClass($('.o-mail-MessagingMenu button:contains("Channels")'), "fw-bolder");
|
||||
await contains('.o-mail-MessagingMenu button:contains("All"):not(.fw-bolder)');
|
||||
await contains('.o-mail-MessagingMenu button:contains("Chats").fw-bolder');
|
||||
await contains('.o-mail-MessagingMenu button:contains("Channels"):not(.fw-bolder)');
|
||||
await click('.o-mail-MessagingMenu button:contains("Channels")');
|
||||
assert.doesNotHaveClass($('.o-mail-MessagingMenu button:contains("All")'), "fw-bolder");
|
||||
assert.doesNotHaveClass($('.o-mail-MessagingMenu button:contains("Chats")'), "fw-bolder");
|
||||
assert.hasClass($('.o-mail-MessagingMenu button:contains("Channels")'), "fw-bolder");
|
||||
await contains('.o-mail-MessagingMenu button:contains("All"):not(.fw-bolder)');
|
||||
await contains('.o-mail-MessagingMenu button:contains("Chats"):not(.fw-bolder)');
|
||||
await contains('.o-mail-MessagingMenu button:contains("Channels").fw-bolder');
|
||||
await click('.o-mail-MessagingMenu button:contains("All")');
|
||||
assert.hasClass($('.o-mail-MessagingMenu button:contains("All")'), "fw-bolder");
|
||||
assert.doesNotHaveClass($('.o-mail-MessagingMenu button:contains("Chats")'), "fw-bolder");
|
||||
assert.doesNotHaveClass($('.o-mail-MessagingMenu button:contains("Channels")'), "fw-bolder");
|
||||
await contains('.o-mail-MessagingMenu button:contains("All").fw-bolder');
|
||||
await contains('.o-mail-MessagingMenu button:contains("Chats"):not(.fw-bolder)');
|
||||
await contains('.o-mail-MessagingMenu button:contains("Channels"):not(.fw-bolder)');
|
||||
});
|
||||
|
||||
QUnit.test("channel preview: basic rendering", async (assert) => {
|
||||
QUnit.test("channel preview: basic rendering", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo" });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
@@ -612,13 +606,13 @@ QUnit.test("channel preview: basic rendering", async (assert) => {
|
||||
});
|
||||
await start();
|
||||
await click(".o_menu_systray .dropdown-toggle:has(i[aria-label='Messages'])");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem img");
|
||||
assert.containsOnce($, '.o-mail-NotificationItem:contains("General")');
|
||||
assert.containsOnce($, '.o-mail-NotificationItem:contains("Demo: test")');
|
||||
await contains(".o-mail-NotificationItem");
|
||||
await contains(".o-mail-NotificationItem img");
|
||||
await contains('.o-mail-NotificationItem:contains("General")');
|
||||
await contains('.o-mail-NotificationItem:contains("Demo: test")');
|
||||
});
|
||||
|
||||
QUnit.test("filtered previews", async (assert) => {
|
||||
QUnit.test("filtered previews", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const [channelId_1, channelId_2] = pyEnv["discuss.channel"].create([
|
||||
{ channel_type: "chat" },
|
||||
@@ -636,18 +630,18 @@ QUnit.test("filtered previews", async (assert) => {
|
||||
]);
|
||||
await start();
|
||||
await click(".o_menu_systray .dropdown-toggle:has(i[aria-label='Messages'])");
|
||||
assert.containsN($, ".o-mail-NotificationItem", 2);
|
||||
assert.containsOnce($, '.o-mail-NotificationItem:contains("Mitchell Admin")');
|
||||
assert.containsOnce($, '.o-mail-NotificationItem:contains("channel1")');
|
||||
await contains(".o-mail-NotificationItem", 2);
|
||||
await contains('.o-mail-NotificationItem:contains("Mitchell Admin")');
|
||||
await contains('.o-mail-NotificationItem:contains("channel1")');
|
||||
await click('.o-mail-MessagingMenu button:contains("Chats")');
|
||||
assert.containsOnce($, '.o-mail-NotificationItem:contains("Mitchell Admin")');
|
||||
await contains('.o-mail-NotificationItem:contains("Mitchell Admin")');
|
||||
await click('.o-mail-MessagingMenu button:contains("Channels")');
|
||||
assert.containsOnce($, '.o-mail-NotificationItem:contains("channel1")');
|
||||
await contains('.o-mail-NotificationItem:contains("channel1")');
|
||||
await click('.o-mail-MessagingMenu button:contains("All")');
|
||||
assert.containsN($, ".o-mail-NotificationItem", 2);
|
||||
assert.containsOnce($, '.o-mail-NotificationItem:contains("Mitchell Admin")');
|
||||
await contains(".o-mail-NotificationItem", 2);
|
||||
await contains('.o-mail-NotificationItem:contains("Mitchell Admin")');
|
||||
await click('.o-mail-MessagingMenu button:contains("Channels")');
|
||||
assert.containsOnce($, '.o-mail-NotificationItem:contains("channel1")');
|
||||
await contains('.o-mail-NotificationItem:contains("channel1")');
|
||||
});
|
||||
|
||||
QUnit.test("no code injection in message body preview", async (assert) => {
|
||||
@@ -660,7 +654,7 @@ QUnit.test("no code injection in message body preview", async (assert) => {
|
||||
});
|
||||
await start();
|
||||
await click(".o_menu_systray .dropdown-toggle:has(i[aria-label='Messages'])");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem");
|
||||
await contains(".o-mail-NotificationItem");
|
||||
assert.strictEqual(
|
||||
$(".o-mail-NotificationItem-text").text().replace(/\s/g, ""),
|
||||
"You:&shoulnotberaisedthrownewError('CodeInjectionError');"
|
||||
@@ -678,8 +672,8 @@ QUnit.test("no code injection in message body preview from sanitized message", a
|
||||
});
|
||||
await start();
|
||||
await click(".o_menu_systray .dropdown-toggle:has(i[aria-label='Messages'])");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem-text");
|
||||
await contains(".o-mail-NotificationItem");
|
||||
await contains(".o-mail-NotificationItem-text");
|
||||
assert.strictEqual(
|
||||
$(".o-mail-NotificationItem-text").text().replace(/\s/g, ""),
|
||||
"You:<em>&shoulnotberaised</em><script>thrownewError('CodeInjectionError');</script>"
|
||||
@@ -697,8 +691,8 @@ QUnit.test("<br/> tags in message body preview are transformed in spaces", async
|
||||
});
|
||||
await start();
|
||||
await click(".o_menu_systray .dropdown-toggle:has(i[aria-label='Messages'])");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem-text");
|
||||
await contains(".o-mail-NotificationItem");
|
||||
await contains(".o-mail-NotificationItem-text");
|
||||
assert.strictEqual($(".o-mail-NotificationItem-text").text(), "You: a b c d");
|
||||
});
|
||||
|
||||
@@ -722,7 +716,10 @@ QUnit.test(
|
||||
});
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.strictEqual($(".o-mail-NotificationItem").text().split("Demo User").length - 1, 1);
|
||||
assert.strictEqual(
|
||||
(await contains(".o-mail-NotificationItem")).text().split("Demo User").length - 1,
|
||||
1
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -734,11 +731,11 @@ QUnit.test(
|
||||
await start();
|
||||
await click(".o_menu_systray .dropdown-toggle:has(i[aria-label='Messages'])");
|
||||
await click('.o-mail-MessagingMenu button:contains("Chats")');
|
||||
assert.containsOnce($, ".o-mail-NotificationItem");
|
||||
await contains(".o-mail-NotificationItem");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("click on preview should mark as read and open the thread", async (assert) => {
|
||||
QUnit.test("click on preview should mark as read and open the thread", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Frodo Baggins" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
@@ -757,12 +754,12 @@ QUnit.test("click on preview should mark as read and open the thread", async (as
|
||||
});
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem:contains(Frodo Baggins)");
|
||||
assert.containsNone($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-NotificationItem:contains(Frodo Baggins)");
|
||||
await contains(".o-mail-ChatWindow", 0);
|
||||
await click(".o-mail-NotificationItem:contains(Frodo Baggins)");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsNone($, ".o-mail-NotificationItem:contains(Frodo Baggins)");
|
||||
await contains(".o-mail-NotificationItem:contains(Frodo Baggins)", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
@@ -795,14 +792,14 @@ QUnit.test(
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem:contains(Frodo Baggins)");
|
||||
await click(".o-mail-ChatWindow-command i.fa-expand");
|
||||
assert.containsNone($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow", 0);
|
||||
assert.verifySteps(["do_action"], "should have done an action to open the form view");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"preview should display last needaction message preview even if there is a more recent message that is not needaction in the thread",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Stranger" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
@@ -827,7 +824,7 @@ QUnit.test(
|
||||
});
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem:contains(I am the oldest but needaction)");
|
||||
await contains(".o-mail-NotificationItem:contains(I am the oldest but needaction)");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -865,14 +862,14 @@ QUnit.test(
|
||||
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsN($, ".o-mail-NotificationItem", 1);
|
||||
await contains(".o-mail-NotificationItem");
|
||||
assert.ok($(".o-mail-NotificationItem").text().includes("Test"));
|
||||
assert.ok($(".o-mail-NotificationItem .badge").text().includes("1"));
|
||||
assert.ok($(".o-mail-NotificationItem").text().includes("Message with needaction"));
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("chat should show unread counter on receiving new messages", async (assert) => {
|
||||
QUnit.test("chat should show unread counter on receiving new messages", async () => {
|
||||
// unread and needaction are conceptually the same in chat
|
||||
// however message_needaction_counter is not updated
|
||||
// so special care for chat to simulate needaction with unread
|
||||
@@ -905,7 +902,7 @@ QUnit.test("chat should show unread counter on receiving new messages", async (a
|
||||
await contains(".o-mail-NotificationItem .badge:contains('1')");
|
||||
});
|
||||
|
||||
QUnit.test("preview for channel should show latest non-deleted message", async (assert) => {
|
||||
QUnit.test("preview for channel should show latest non-deleted message", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Partner1" });
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "Test" });
|
||||
@@ -925,7 +922,7 @@ QUnit.test("preview for channel should show latest non-deleted message", async (
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem:contains(message-2)");
|
||||
await contains(".o-mail-NotificationItem:contains(message-2)");
|
||||
// Simulate deletion of message-2
|
||||
await afterNextRender(() =>
|
||||
env.services.rpc("/mail/message/update_content", {
|
||||
@@ -934,10 +931,10 @@ QUnit.test("preview for channel should show latest non-deleted message", async (
|
||||
attachment_ids: [],
|
||||
})
|
||||
);
|
||||
assert.containsOnce($, ".o-mail-NotificationItem:contains(message-1)");
|
||||
await contains(".o-mail-NotificationItem:contains(message-1)");
|
||||
});
|
||||
|
||||
QUnit.test("failure notifications are shown before channel preview", async (assert) => {
|
||||
QUnit.test("failure notifications are shown before channel preview", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Partner1" });
|
||||
const failedMessageId = pyEnv["mail.message"].create({
|
||||
@@ -964,23 +961,19 @@ QUnit.test("failure notifications are shown before channel preview", async (asse
|
||||
pyEnv["discuss.channel.member"].write([memberId], { seen_message_id: messageId });
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o-mail-NotificationItem:contains(An error occurred when sending an email)"
|
||||
);
|
||||
assert.containsOnce($, ".o-mail-NotificationItem:contains(message)");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
await contains(".o-mail-NotificationItem:contains(An error occurred when sending an email)");
|
||||
await contains(".o-mail-NotificationItem:contains(message)");
|
||||
await contains(
|
||||
".o-mail-NotificationItem:contains(An error occurred when sending an email) ~ .o-mail-NotificationItem:contains(message)"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("messaging menu should show new needaction messages from chatter", async (assert) => {
|
||||
QUnit.test("messaging menu should show new needaction messages from chatter", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Frodo Baggins" });
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsNone($, ".o-mail-NotificationItem:contains(@Mitchell Admin)");
|
||||
await contains(".o-mail-NotificationItem:contains(@Mitchell Admin)", 0);
|
||||
|
||||
// simulate receiving a new needaction message
|
||||
await afterNextRender(() => {
|
||||
@@ -993,5 +986,5 @@ QUnit.test("messaging menu should show new needaction messages from chatter", as
|
||||
record_name: "Frodo Baggins",
|
||||
});
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-NotificationItem:contains(@Mitchell Admin)");
|
||||
await contains(".o-mail-NotificationItem:contains(@Mitchell Admin)");
|
||||
});
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { afterNextRender, click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { Command } from "@mail/../tests/helpers/command";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { browser } from "@web/core/browser/browser";
|
||||
import { patchWithCleanup, triggerEvent } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("notification");
|
||||
@@ -30,14 +30,13 @@ QUnit.test("basic layout", async (assert) => {
|
||||
]);
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem-name:contains(Channel)");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem-counter:contains(2)");
|
||||
await contains(".o-mail-NotificationItem-name:contains(Channel)");
|
||||
await contains(".o-mail-NotificationItem-counter:contains(2)");
|
||||
assert.containsOnce(
|
||||
$(".o-mail-NotificationItem-name:contains(Channel)").closest(".o-mail-NotificationItem"),
|
||||
".o-mail-NotificationItem-date:contains(now)"
|
||||
);
|
||||
assert.containsOnce(
|
||||
$,
|
||||
await contains(
|
||||
".o-mail-NotificationItem-text:contains(An error occurred when sending an email)"
|
||||
);
|
||||
});
|
||||
@@ -59,7 +58,9 @@ QUnit.test("mark as read", async (assert) => {
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await triggerEvent(
|
||||
$(".o-mail-NotificationItem-name:contains(Channel)").closest(".o-mail-NotificationItem")[0],
|
||||
(
|
||||
await contains(".o-mail-NotificationItem-name:contains(Channel)")
|
||||
).closest(".o-mail-NotificationItem")[0],
|
||||
null,
|
||||
"mouseenter"
|
||||
);
|
||||
@@ -179,14 +180,10 @@ QUnit.test("different discuss.channel are not grouped", async (assert) => {
|
||||
]);
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsN(
|
||||
$,
|
||||
".o-mail-NotificationItem:contains(An error occurred when sending an email)",
|
||||
2
|
||||
);
|
||||
await contains(".o-mail-NotificationItem:contains(An error occurred when sending an email)", 2);
|
||||
});
|
||||
|
||||
QUnit.test("multiple grouped notifications by model", async (assert) => {
|
||||
QUnit.test("multiple grouped notifications by model", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const [messageId_1, messageId_2] = pyEnv["mail.message"].create([
|
||||
{
|
||||
@@ -226,11 +223,11 @@ QUnit.test("multiple grouped notifications by model", async (assert) => {
|
||||
]);
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsN($, ".o-mail-NotificationItem", 2);
|
||||
assert.containsN($, ".o-mail-NotificationItem-counter:contains(2)", 2);
|
||||
await contains(".o-mail-NotificationItem", 2);
|
||||
await contains(".o-mail-NotificationItem-counter:contains(2)", 2);
|
||||
});
|
||||
|
||||
QUnit.test("non-failure notifications are ignored", async (assert) => {
|
||||
QUnit.test("non-failure notifications are ignored", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
@@ -245,7 +242,7 @@ QUnit.test("non-failure notifications are ignored", async (assert) => {
|
||||
});
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsNone($, ".o-mail-NotificationItem");
|
||||
await contains(".o-mail-NotificationItem", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
@@ -270,13 +267,13 @@ QUnit.test(
|
||||
]);
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsN($, ".o-mail-NotificationItem-name", 2);
|
||||
await contains(".o-mail-NotificationItem-name", 2);
|
||||
assert.strictEqual($(".o-mail-NotificationItem-name:eq(0)").text(), "Channel 2020");
|
||||
assert.strictEqual($(".o-mail-NotificationItem-name:eq(1)").text(), "Channel 2019");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("thread notifications are re-ordered on receiving a new message", async (assert) => {
|
||||
QUnit.test("thread notifications are re-ordered on receiving a new message", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const [channelId_1, channelId_2] = pyEnv["discuss.channel"].create([
|
||||
{ name: "Channel 2019" },
|
||||
@@ -296,45 +293,56 @@ QUnit.test("thread notifications are re-ordered on receiving a new message", asy
|
||||
]);
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsN($, ".o-mail-NotificationItem", 2);
|
||||
await contains(".o-mail-NotificationItem", 2);
|
||||
|
||||
const channel_1 = pyEnv["discuss.channel"].searchRead([["id", "=", channelId_1]])[0];
|
||||
await afterNextRender(() => {
|
||||
pyEnv["bus.bus"]._sendone(channel_1, "discuss.channel/new_message", {
|
||||
id: channelId_1,
|
||||
message: {
|
||||
author: { id: 7, name: "Demo User" },
|
||||
body: "<p>New message !</p>",
|
||||
date: "2020-03-23 10:00:00",
|
||||
id: 44,
|
||||
message_type: "comment",
|
||||
model: "discuss.channel",
|
||||
record_name: "Channel 2019",
|
||||
res_id: channelId_1,
|
||||
},
|
||||
});
|
||||
pyEnv["bus.bus"]._sendone(channel_1, "discuss.channel/new_message", {
|
||||
id: channelId_1,
|
||||
message: {
|
||||
author: { id: 7, name: "Demo User" },
|
||||
body: "<p>New message !</p>",
|
||||
date: "2020-03-23 10:00:00",
|
||||
id: 44,
|
||||
message_type: "comment",
|
||||
model: "discuss.channel",
|
||||
record_name: "Channel 2019",
|
||||
res_id: channelId_1,
|
||||
},
|
||||
});
|
||||
assert.containsN($, ".o-mail-NotificationItem", 2);
|
||||
assert.containsOnce(
|
||||
$(".o-mail-NotificationItem:eq(0)"),
|
||||
".o-mail-NotificationItem-name:contains(Channel 2019)"
|
||||
await contains(".o-mail-NotificationItem", 2);
|
||||
await contains(
|
||||
".o-mail-NotificationItem:eq(0) .o-mail-NotificationItem-name:contains(Channel 2019)"
|
||||
);
|
||||
assert.containsOnce(
|
||||
$(".o-mail-NotificationItem:eq(1)"),
|
||||
".o-mail-NotificationItem-name:contains(Channel 2020)"
|
||||
await contains(
|
||||
".o-mail-NotificationItem:eq(1) .o-mail-NotificationItem-name:contains(Channel 2020)"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"messaging menu counter should ignore unread messages in channels that are unpinned",
|
||||
async (assert) => {
|
||||
patchWithCleanup(browser, {
|
||||
Notification: {
|
||||
...browser.Notification,
|
||||
permission: "denied",
|
||||
},
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
Command.create({
|
||||
is_pinned: false,
|
||||
message_unread_counter: 1,
|
||||
partner_id: pyEnv.currentPartnerId,
|
||||
}),
|
||||
Command.create({ partner_id: partnerId }),
|
||||
],
|
||||
});
|
||||
pyEnv["mail.message"].create([
|
||||
{
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
author_id: partnerId,
|
||||
message_type: "email",
|
||||
},
|
||||
]);
|
||||
await start();
|
||||
assert.containsNone($, ".o-mail-MessagingMenu-counter-badge");
|
||||
await contains(".o_menu_systray i[aria-label='Messages']");
|
||||
await contains(".o-mail-MessagingMenu-counter", 0);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { patchUiSize } from "@mail/../tests/helpers/patch_ui_size";
|
||||
import { click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
QUnit.module("mobile");
|
||||
|
||||
QUnit.test("auto-select 'Inbox' when discuss had channel as active thread", async (assert) => {
|
||||
QUnit.test("auto-select 'Inbox' when discuss had channel as active thread", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "test" });
|
||||
|
||||
patchUiSize({ height: 360, width: 640 });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId, { waitUntilMessagesLoaded: false });
|
||||
assert.containsOnce($, ".o-mail-MessagingMenu-tab.text-primary.fw-bolder:contains(Channel)");
|
||||
openDiscuss(channelId, { waitUntilMessagesLoaded: false });
|
||||
await contains(".o-mail-MessagingMenu-tab.text-primary.fw-bolder:contains(Channel)");
|
||||
|
||||
await click("button:contains(Mailboxes)");
|
||||
assert.containsOnce($, ".o-mail-MessagingMenu-tab.text-primary.fw-bolder:contains(Mailboxes)");
|
||||
assert.containsOnce($, "button:contains(Inbox).active");
|
||||
await contains(".o-mail-MessagingMenu-tab.text-primary.fw-bolder:contains(Mailboxes)");
|
||||
await contains("button:contains(Inbox).active");
|
||||
});
|
||||
|
||||
@@ -2,14 +2,9 @@
|
||||
|
||||
import { Composer } from "@mail/core/common/composer";
|
||||
import { Command } from "@mail/../tests/helpers/command";
|
||||
import { click, insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import {
|
||||
makeDeferred,
|
||||
nextTick,
|
||||
patchWithCleanup,
|
||||
triggerHotkey,
|
||||
} from "@web/../tests/helpers/utils";
|
||||
import { makeDeferred, nextTick, patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("suggestion", {
|
||||
async beforeEach() {
|
||||
@@ -22,7 +17,7 @@ QUnit.module("suggestion", {
|
||||
},
|
||||
});
|
||||
|
||||
QUnit.test('display partner mention suggestions on typing "@"', async (assert) => {
|
||||
QUnit.test('display partner mention suggestions on typing "@"', async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId_1 = pyEnv["res.partner"].create({
|
||||
email: "testpartner@odoo.com",
|
||||
@@ -42,16 +37,17 @@ QUnit.test('display partner mention suggestions on typing "@"', async (assert) =
|
||||
],
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsNone($, ".o-mail-Composer-suggestion");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Composer-input");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
|
||||
await insertText(".o-mail-Composer-input", "@");
|
||||
assert.containsN($, ".o-mail-Composer-suggestion", 3);
|
||||
await contains(".o-mail-Composer-suggestion", 3);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
'post a first message then display partner mention suggestions on typing "@"',
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId_1 = pyEnv["res.partner"].create({
|
||||
email: "testpartner@odoo.com",
|
||||
@@ -71,28 +67,28 @@ QUnit.test(
|
||||
],
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsNone($, ".o-mail-Composer-suggestion");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Composer-input");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
await insertText(".o-mail-Composer-input", "first message");
|
||||
triggerHotkey("Enter");
|
||||
await nextTick();
|
||||
|
||||
await click("button:contains(Send):not(:disabled)");
|
||||
await contains(".o-mail-Message");
|
||||
await insertText(".o-mail-Composer-input", "@");
|
||||
assert.containsN($, ".o-mail-Composer-suggestion", 3);
|
||||
await contains(".o-mail-Composer-suggestion", 3);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test('display partner mention suggestions on typing "@" in chatter', async (assert) => {
|
||||
QUnit.test('display partner mention suggestions on typing "@" in chatter', async () => {
|
||||
const pyEnv = await startServer();
|
||||
const { openFormView } = await start();
|
||||
await openFormView("res.partner", pyEnv.currentPartnerId);
|
||||
openFormView("res.partner", pyEnv.currentPartnerId);
|
||||
await click("button:contains(Send message)");
|
||||
assert.containsNone($, ".o-mail-Composer-suggestion");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
await insertText(".o-mail-Composer-input", "@");
|
||||
assert.containsOnce($, ".o-mail-Composer-suggestion:contains(Mitchell Admin)");
|
||||
await contains(".o-mail-Composer-suggestion:contains(Mitchell Admin)");
|
||||
});
|
||||
|
||||
QUnit.test("show other channel member in @ mention", async (assert) => {
|
||||
QUnit.test("show other channel member in @ mention", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({
|
||||
email: "testpartner@odoo.com",
|
||||
@@ -106,9 +102,9 @@ QUnit.test("show other channel member in @ mention", async (assert) => {
|
||||
],
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "@");
|
||||
assert.containsOnce($, ".o-mail-Composer-suggestion:contains(TestPartner)");
|
||||
await contains(".o-mail-Composer-suggestion:contains(TestPartner)");
|
||||
});
|
||||
|
||||
QUnit.test("select @ mention insert mention text in composer", async (assert) => {
|
||||
@@ -125,23 +121,25 @@ QUnit.test("select @ mention insert mention text in composer", async (assert) =>
|
||||
],
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "@");
|
||||
await click(".o-mail-Composer-suggestion:contains(TestPartner)");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
assert.strictEqual($(".o-mail-Composer-input").val().trim(), "@TestPartner");
|
||||
});
|
||||
|
||||
QUnit.test('display channel mention suggestions on typing "#"', async (assert) => {
|
||||
QUnit.test('display channel mention suggestions on typing "#"', async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
name: "General",
|
||||
channel_type: "channel",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsNone($, ".o-mail-Composer-suggestionList .o-open");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Composer-suggestionList");
|
||||
await contains(".o-mail-Composer-suggestionList .o-open", 0);
|
||||
await insertText(".o-mail-Composer-input", "#");
|
||||
assert.containsOnce($, ".o-mail-Composer-suggestionList .o-open");
|
||||
await contains(".o-mail-Composer-suggestionList .o-open");
|
||||
});
|
||||
|
||||
QUnit.test("mention a channel", async (assert) => {
|
||||
@@ -151,12 +149,13 @@ QUnit.test("mention a channel", async (assert) => {
|
||||
channel_type: "channel",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsNone($, ".o-mail-Composer-suggestionList .o-open");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Composer-suggestionList");
|
||||
await contains(".o-mail-Composer-suggestionList .o-open", 0);
|
||||
assert.strictEqual($(".o-mail-Composer-input").val(), "");
|
||||
await insertText(".o-mail-Composer-input", "#");
|
||||
assert.containsOnce($, ".o-mail-Composer-suggestion");
|
||||
await click(".o-mail-Composer-suggestion");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
assert.strictEqual(
|
||||
$(".o-mail-Composer-input").val().replace(/\s/, " "),
|
||||
"#General ",
|
||||
@@ -179,7 +178,7 @@ QUnit.test("Channel suggestions do not crash after rpc returns", async (assert)
|
||||
return originalFn(args, params);
|
||||
},
|
||||
});
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
pyEnv["discuss.channel"].create({ name: "foo" });
|
||||
insertText(".o-mail-Composer-input", "#");
|
||||
await nextTick();
|
||||
@@ -188,30 +187,59 @@ QUnit.test("Channel suggestions do not crash after rpc returns", async (assert)
|
||||
assert.verifySteps(["get_mention_suggestions"]);
|
||||
});
|
||||
|
||||
QUnit.test("Suggestions are shown after delimiter was used in text (@)", async (assert) => {
|
||||
QUnit.test("Suggestions are shown after delimiter was used in text (@)", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "@");
|
||||
assert.containsOnce($, ".o-mail-Composer-suggestion");
|
||||
await contains(".o-mail-Composer-suggestion");
|
||||
await insertText(".o-mail-Composer-input", "NonExistingUser");
|
||||
assert.containsNone($, ".o-mail-Composer-suggestion");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
await insertText(".o-mail-Composer-input", " ");
|
||||
await insertText(".o-mail-Composer-input", "@");
|
||||
assert.containsOnce($, ".o-mail-Composer-suggestion:contains(Mitchell Admin)");
|
||||
await contains(".o-mail-Composer-suggestion:contains(Mitchell Admin)");
|
||||
});
|
||||
|
||||
QUnit.test("Suggestions are shown after delimiter was used in text (#)", async (assert) => {
|
||||
QUnit.test("Suggestions are shown after delimiter was used in text (#)", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "#");
|
||||
assert.containsOnce($, ".o-mail-Composer-suggestion");
|
||||
await contains(".o-mail-Composer-suggestion");
|
||||
await insertText(".o-mail-Composer-input", "NonExistingChannel");
|
||||
assert.containsNone($, ".o-mail-Composer-suggestion");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
await insertText(".o-mail-Composer-input", " ");
|
||||
await insertText(".o-mail-Composer-input", "#");
|
||||
assert.containsOnce($, ".o-mail-Composer-suggestion:contains(General)");
|
||||
await contains(".o-mail-Composer-suggestion:contains(General)");
|
||||
});
|
||||
|
||||
QUnit.test("display partner mention when typing more than 2 words if they match", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["res.partner"].create([
|
||||
{
|
||||
email: "test1@example.com",
|
||||
name: "My Best Partner",
|
||||
},
|
||||
{
|
||||
email: "test2@example.com",
|
||||
name: "My Test User",
|
||||
},
|
||||
{
|
||||
email: "test3@example.com",
|
||||
name: "My Test Partner",
|
||||
},
|
||||
]);
|
||||
const { openFormView } = await start();
|
||||
openFormView("res.partner", pyEnv.currentPartnerId);
|
||||
await click("button:contains(Send message)");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
await insertText(".o-mail-Composer-input", "@My ");
|
||||
await contains(".o-mail-Composer-suggestion", 3);
|
||||
await insertText(".o-mail-Composer-input", "Test ");
|
||||
await contains(".o-mail-Composer-suggestion", 2);
|
||||
await insertText(".o-mail-Composer-input", "Partner");
|
||||
await contains(".o-mail-Composer-suggestion");
|
||||
await contains(".o-mail-Composer-suggestion:contains(My Test Partner)");
|
||||
});
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { afterNextRender, click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { getOrigin } from "@web/core/utils/urls";
|
||||
import { nextTick } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("attachment list");
|
||||
@@ -24,18 +25,18 @@ QUnit.test("simplest layout", async (assert) => {
|
||||
message_type: "comment",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-Message .o-mail-AttachmentList");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Message .o-mail-AttachmentList");
|
||||
assert.hasAttrValue($(".o-mail-AttachmentCard"), "title", "test.txt");
|
||||
assert.containsOnce($, ".o-mail-AttachmentCard-image");
|
||||
await contains(".o-mail-AttachmentCard-image");
|
||||
assert.hasClass($(".o-mail-AttachmentCard-image"), "o_image"); // required for mimetype.scss style
|
||||
assert.hasAttrValue($(".o-mail-AttachmentCard-image"), "data-mimetype", "text/plain"); // required for mimetype.scss style
|
||||
assert.containsN($, ".o-mail-AttachmentCard-aside button", 2);
|
||||
assert.containsOnce($, ".o-mail-AttachmentCard-unlink");
|
||||
assert.containsOnce($, ".o-mail-AttachmentCard-aside button[title='Download']");
|
||||
await contains(".o-mail-AttachmentCard-unlink");
|
||||
await contains(".o-mail-AttachmentCard-aside button[title='Download']");
|
||||
});
|
||||
|
||||
QUnit.test("layout with card details and filename and extension", async (assert) => {
|
||||
QUnit.test("layout with card details and filename and extension", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_type: "channel",
|
||||
@@ -53,9 +54,9 @@ QUnit.test("layout with card details and filename and extension", async (assert)
|
||||
message_type: "comment",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-AttachmentCard:contains('test.txt')");
|
||||
assert.containsOnce($, ".o-mail-AttachmentCard small:contains('txt')");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-AttachmentCard:contains('test.txt')");
|
||||
await contains(".o-mail-AttachmentCard small:contains('txt')");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
@@ -84,18 +85,17 @@ QUnit.test(
|
||||
}
|
||||
},
|
||||
});
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-AttachmentCard-unlink");
|
||||
await afterNextRender(() => {
|
||||
$(".modal-footer .btn-primary")[0].click();
|
||||
$(".modal-footer .btn-primary")[0].click();
|
||||
$(".modal-footer .btn-primary")[0].click();
|
||||
});
|
||||
click(".modal-footer .btn-primary");
|
||||
click(".modal-footer .btn-primary");
|
||||
click(".modal-footer .btn-primary");
|
||||
await contains(".o-mail-AttachmentCard-unlink", 0);
|
||||
assert.verifySteps(["attachment_unlink"], "The unlink method must be called once");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("view attachment", async (assert) => {
|
||||
QUnit.test("view attachment", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_type: "channel",
|
||||
@@ -113,13 +113,13 @@ QUnit.test("view attachment", async (assert) => {
|
||||
message_type: "comment",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-AttachmentImage img");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-AttachmentImage img");
|
||||
await click(".o-mail-AttachmentImage");
|
||||
assert.containsOnce($, ".o-FileViewer");
|
||||
await contains(".o-FileViewer");
|
||||
});
|
||||
|
||||
QUnit.test("close attachment viewer", async (assert) => {
|
||||
QUnit.test("close attachment viewer", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_type: "channel",
|
||||
@@ -137,14 +137,14 @@ QUnit.test("close attachment viewer", async (assert) => {
|
||||
message_type: "comment",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-AttachmentImage img");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-AttachmentImage img");
|
||||
|
||||
await click(".o-mail-AttachmentImage");
|
||||
assert.containsOnce($, ".o-FileViewer");
|
||||
await contains(".o-FileViewer");
|
||||
|
||||
await click(".o-FileViewer div[aria-label='Close']");
|
||||
assert.containsNone($, ".o-FileViewer");
|
||||
await contains(".o-FileViewer", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
@@ -176,9 +176,9 @@ QUnit.test(
|
||||
message_type: "comment",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click(".o-mail-AttachmentImage");
|
||||
const image = $(".o-FileViewer-viewImage")[0];
|
||||
const image = (await contains(".o-FileViewer-viewImage"))[0];
|
||||
await click(".o-FileViewer div[aria-label='Close']");
|
||||
// Simulate image becoming loaded.
|
||||
let successfulLoad;
|
||||
@@ -193,7 +193,7 @@ QUnit.test(
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("plain text file is viewable", async (assert) => {
|
||||
QUnit.test("plain text file is viewable", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_type: "channel",
|
||||
@@ -211,11 +211,11 @@ QUnit.test("plain text file is viewable", async (assert) => {
|
||||
message_type: "comment",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.hasClass($(".o-mail-AttachmentCard"), "o-viewable");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-AttachmentCard.o-viewable");
|
||||
});
|
||||
|
||||
QUnit.test("HTML file is viewable", async (assert) => {
|
||||
QUnit.test("HTML file is viewable", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_type: "channel",
|
||||
@@ -233,11 +233,11 @@ QUnit.test("HTML file is viewable", async (assert) => {
|
||||
message_type: "comment",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.hasClass($(".o-mail-AttachmentCard"), "o-viewable");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-AttachmentCard.o-viewable");
|
||||
});
|
||||
|
||||
QUnit.test("ODT file is not viewable", async (assert) => {
|
||||
QUnit.test("ODT file is not viewable", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_type: "channel",
|
||||
@@ -255,11 +255,11 @@ QUnit.test("ODT file is not viewable", async (assert) => {
|
||||
message_type: "comment",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.doesNotHaveClass($(".o-mail-AttachmentCard"), "o-viewable");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-AttachmentCard:not(.o-viewable)");
|
||||
});
|
||||
|
||||
QUnit.test("DOCX file is not viewable", async (assert) => {
|
||||
QUnit.test("DOCX file is not viewable", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_type: "channel",
|
||||
@@ -277,8 +277,8 @@ QUnit.test("DOCX file is not viewable", async (assert) => {
|
||||
message_type: "comment",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.doesNotHaveClass($(".o-mail-AttachmentCard"), "o-viewable");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-AttachmentCard:not(.o-viewable)");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
@@ -307,22 +307,22 @@ QUnit.test(
|
||||
message_type: "comment",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-AttachmentImage[title='test.png']");
|
||||
assert.containsOnce($, ".o-mail-AttachmentCard:contains(test.odt)");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-AttachmentImage[title='test.png']");
|
||||
await contains(".o-mail-AttachmentCard:contains(test.odt)");
|
||||
assert.hasClass($(".o-mail-AttachmentImage[title='test.png'] img"), "o-viewable");
|
||||
assert.doesNotHaveClass($(".o-mail-AttachmentCard:contains(test.odt)"), "o-viewable");
|
||||
|
||||
click(".o-mail-AttachmentCard:contains(test.odt)").catch(() => {});
|
||||
await nextTick();
|
||||
assert.containsNone($, ".o-FileViewer");
|
||||
await contains(".o-FileViewer", 0);
|
||||
|
||||
await click(".o-mail-AttachmentImage[title='test.png']");
|
||||
assert.containsOnce($, ".o-FileViewer");
|
||||
await contains(".o-FileViewer");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("img file has proper src in discuss.channel", async (assert) => {
|
||||
QUnit.test("img file has proper src in discuss.channel", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_type: "channel",
|
||||
@@ -342,10 +342,8 @@ QUnit.test("img file has proper src in discuss.channel", async (assert) => {
|
||||
message_type: "comment",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.ok(
|
||||
$(".o-mail-AttachmentImage[title='test.png'] img")
|
||||
.data("src")
|
||||
.includes(`/discuss/channel/${channelId}/image`)
|
||||
openDiscuss(channelId);
|
||||
await contains(
|
||||
`.o-mail-AttachmentImage[title='test.png'] img[data-src='${getOrigin()}/discuss/channel/${channelId}/image/${attachmentId}?filename=test.png&width=1920&height=300']`
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { afterNextRender, click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { editInput } from "@web/../tests/helpers/utils";
|
||||
import { file } from "@web/../tests/legacy/helpers/test_utils";
|
||||
@@ -9,7 +9,7 @@ const { createFile } = file;
|
||||
|
||||
QUnit.module("file upload");
|
||||
|
||||
QUnit.test("no conflicts between file uploads", async (assert) => {
|
||||
QUnit.test("no conflicts between file uploads", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const channelId = pyEnv["discuss.channel"].create({});
|
||||
@@ -20,7 +20,7 @@ QUnit.test("no conflicts between file uploads", async (assert) => {
|
||||
});
|
||||
const { openView } = await start();
|
||||
// Uploading file in the first thread: res.partner chatter.
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
@@ -31,9 +31,8 @@ QUnit.test("no conflicts between file uploads", async (assert) => {
|
||||
content: "hello, world",
|
||||
contentType: "text/plain",
|
||||
});
|
||||
await afterNextRender(() =>
|
||||
editInput(document.body, ".o-mail-Chatter .o-mail-Composer input[type=file]", file1)
|
||||
);
|
||||
await contains(".o-mail-Chatter .o-mail-Composer input[type=file]");
|
||||
editInput(document.body, ".o-mail-Chatter .o-mail-Composer input[type=file]", file1);
|
||||
// Uploading file in the second thread: discuss.channel in chatWindow.
|
||||
await click("i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
@@ -42,14 +41,13 @@ QUnit.test("no conflicts between file uploads", async (assert) => {
|
||||
content: "hello, world",
|
||||
contentType: "text/plain",
|
||||
});
|
||||
await afterNextRender(() =>
|
||||
editInput(document.body, ".o-mail-ChatWindow input[type=file]", file2)
|
||||
);
|
||||
assert.containsOnce($, ".o-mail-Chatter .o-mail-AttachmentCard");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow .o-mail-AttachmentCard");
|
||||
await contains(".o-mail-ChatWindow .o-mail-Composer input[type=file]");
|
||||
editInput(document.body, ".o-mail-ChatWindow input[type=file]", file2);
|
||||
await contains(".o-mail-Chatter .o-mail-AttachmentCard");
|
||||
await contains(".o-mail-ChatWindow .o-mail-AttachmentCard");
|
||||
});
|
||||
|
||||
QUnit.test("Attachment shows spinner during upload", async (assert) => {
|
||||
QUnit.test("Attachment shows spinner during upload", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "channel_1" });
|
||||
const { openDiscuss } = await start({
|
||||
@@ -66,8 +64,6 @@ QUnit.test("Attachment shows spinner during upload", async (assert) => {
|
||||
content: "hello, world",
|
||||
contentType: "text/plain",
|
||||
});
|
||||
await afterNextRender(() =>
|
||||
editInput(document.body, ".o-mail-Composer input[type=file]", file)
|
||||
);
|
||||
assert.containsOnce($, ".o-mail-AttachmentCard .fa-spinner");
|
||||
editInput(document.body, ".o-mail-Composer input[type=file]", file);
|
||||
await contains(".o-mail-AttachmentCard .fa-spinner");
|
||||
});
|
||||
|
||||
@@ -16,17 +16,15 @@ import {
|
||||
|
||||
import { config as transitionConfig } from "@web/core/transition";
|
||||
import {
|
||||
editInput,
|
||||
makeDeferred,
|
||||
nextTick,
|
||||
patchWithCleanup,
|
||||
triggerEvents,
|
||||
triggerHotkey,
|
||||
} from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("thread");
|
||||
|
||||
QUnit.test("dragover files on thread with composer", async (assert) => {
|
||||
QUnit.test("dragover files on thread with composer", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_type: "channel",
|
||||
@@ -34,12 +32,12 @@ QUnit.test("dragover files on thread with composer", async (assert) => {
|
||||
name: "General",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
await afterNextRender(() => dragenterFiles($(".o-mail-Thread")[0]));
|
||||
assert.containsOnce($, ".o-mail-Dropzone");
|
||||
openDiscuss(channelId);
|
||||
dragenterFiles((await contains(".o-mail-Thread"))[0]);
|
||||
await contains(".o-mail-Dropzone");
|
||||
});
|
||||
|
||||
QUnit.test("load more messages from channel (auto-load on scroll)", async (assert) => {
|
||||
QUnit.test("load more messages from channel (auto-load on scroll)", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_type: "channel",
|
||||
@@ -54,55 +52,53 @@ QUnit.test("load more messages from channel (auto-load on scroll)", async (asser
|
||||
});
|
||||
}
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsN($, "button:contains(Load More) ~ .o-mail-Message", 30);
|
||||
|
||||
await afterNextRender(() => ($(".o-mail-Thread")[0].scrollTop = 0));
|
||||
assert.containsN($, ".o-mail-Message", 60);
|
||||
openDiscuss(channelId);
|
||||
await contains("button:contains(Load More) ~ .o-mail-Message", 30);
|
||||
/**
|
||||
* The nextAnimationFrame is necessary because otherwise useAutoScroll would
|
||||
* set the scroll to bottom after the manually set value from this test.
|
||||
*/
|
||||
await nextAnimationFrame();
|
||||
$(".o-mail-Thread")[0].scrollTop = 0;
|
||||
await contains(".o-mail-Message", 60);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"show message subject when subject is not the same as the thread name",
|
||||
async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_type: "channel",
|
||||
group_public_id: false,
|
||||
name: "General",
|
||||
});
|
||||
pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
subject: "Salutations, voyageur",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsOnce($, ".o-mail-Message:contains(Subject: Salutations, voyageur)");
|
||||
}
|
||||
);
|
||||
QUnit.test("show message subject when subject is not the same as the thread name", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_type: "channel",
|
||||
group_public_id: false,
|
||||
name: "General",
|
||||
});
|
||||
pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
subject: "Salutations, voyageur",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message:contains(Subject: Salutations, voyageur)");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"do not show message subject when subject is the same as the thread name",
|
||||
async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_type: "channel",
|
||||
group_public_id: false,
|
||||
name: "Salutations, voyageur",
|
||||
});
|
||||
pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
subject: "Salutations, voyageur",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsNone($, ".o-mail-Message:contains(Salutations, voyageur)");
|
||||
}
|
||||
);
|
||||
QUnit.test("do not show message subject when subject is the same as the thread name", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_type: "channel",
|
||||
group_public_id: false,
|
||||
name: "Salutations, voyageur",
|
||||
});
|
||||
pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
subject: "Salutations, voyageur",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Message:not(:contains(Salutations, voyageur))");
|
||||
});
|
||||
|
||||
QUnit.test("auto-scroll to bottom of thread on load", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
@@ -115,12 +111,12 @@ QUnit.test("auto-scroll to bottom of thread on load", async (assert) => {
|
||||
});
|
||||
}
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsN($, ".o-mail-Message", 25);
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Message", 25);
|
||||
assert.ok(isScrolledToBottom($(".o-mail-Thread")[0]));
|
||||
});
|
||||
|
||||
QUnit.test("display day separator before first message of the day", async (assert) => {
|
||||
QUnit.test("display day separator before first message of the day", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "" });
|
||||
pyEnv["mail.message"].create([
|
||||
@@ -136,11 +132,11 @@ QUnit.test("display day separator before first message of the day", async (asser
|
||||
},
|
||||
]);
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-Thread-date");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Thread-date");
|
||||
});
|
||||
|
||||
QUnit.test("do not display day separator if all messages of the day are empty", async (assert) => {
|
||||
QUnit.test("do not display day separator if all messages of the day are empty", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "" });
|
||||
pyEnv["mail.message"].create({
|
||||
@@ -149,8 +145,9 @@ QUnit.test("do not display day separator if all messages of the day are empty",
|
||||
res_id: channelId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsNone($, ".o-mail-Thread-date");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Thread-empty");
|
||||
await contains(".o-mail-Thread-date", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
@@ -172,15 +169,29 @@ QUnit.test(
|
||||
}))
|
||||
);
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId_1);
|
||||
openDiscuss(channelId_1);
|
||||
await contains(".o-mail-Thread");
|
||||
/**
|
||||
* The nextAnimationFrame is necessary because otherwise useAutoScroll would
|
||||
* set the scroll to bottom after the manually set value from this test.
|
||||
*/
|
||||
await nextAnimationFrame();
|
||||
const scrolltop_1 = $(".o-mail-Thread")[0].scrollHeight / 2;
|
||||
$(".o-mail-Thread")[0].scrollTo({ top: scrolltop_1 });
|
||||
await click(".o-mail-DiscussSidebarChannel:contains(channel-2)");
|
||||
await contains(".o-mail-DiscussSidebarChannel:contains(channel-2).o-active");
|
||||
/**
|
||||
* The nextAnimationFrame is necessary because otherwise useAutoScroll would
|
||||
* set the scroll to bottom after the manually set value from this test.
|
||||
*/
|
||||
await nextAnimationFrame();
|
||||
const scrolltop_2 = $(".o-mail-Thread")[0].scrollHeight / 3;
|
||||
$(".o-mail-Thread")[0].scrollTo({ top: scrolltop_2 });
|
||||
await click(".o-mail-DiscussSidebarChannel:contains(channel-1)");
|
||||
await contains(".o-mail-DiscussSidebarChannel:contains(channel-1).o-active");
|
||||
assert.ok(isScrolledTo($(".o-mail-Thread")[0], scrolltop_1));
|
||||
await click(".o-mail-DiscussSidebarChannel:contains(channel-2)");
|
||||
await contains(".o-mail-DiscussSidebarChannel:contains(channel-2).o-active");
|
||||
assert.ok(isScrolledTo($(".o-mail-Thread")[0], scrolltop_2));
|
||||
}
|
||||
);
|
||||
@@ -199,11 +210,19 @@ QUnit.test("thread is still scrolling after scrolling up then to bottom", async
|
||||
}))
|
||||
);
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Thread");
|
||||
/**
|
||||
* The nextAnimationFrame is necessary because otherwise useAutoScroll would
|
||||
* set the scroll to bottom after the manually set value from this test.
|
||||
*/
|
||||
await nextAnimationFrame();
|
||||
assert.ok(isScrolledToBottom($(".o-mail-Thread")[0]));
|
||||
$(".o-mail-Thread")[0].scrollTo({ top: $(".o-mail-Thread")[0].scrollHeight / 2 });
|
||||
$(".o-mail-Thread")[0].scrollTo({ top: $(".o-mail-Thread")[0].scrollHeight });
|
||||
await insertText(".o-mail-Composer-input", "123");
|
||||
await click(".o-mail-Composer-send");
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
await contains(".o-mail-Message", 21);
|
||||
assert.ok(isScrolledToBottom($(".o-mail-Thread")[0]));
|
||||
});
|
||||
|
||||
@@ -211,11 +230,12 @@ QUnit.test("mention a channel with space in the name", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General good boy" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "#");
|
||||
await click(".o-mail-Composer-suggestion");
|
||||
await click(".o-mail-Composer-send");
|
||||
assert.containsOnce($(".o-mail-Message-body"), ".o_channel_redirect");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
await contains(".o-mail-Message-body .o_channel_redirect");
|
||||
assert.strictEqual($(".o_channel_redirect").text(), "#General good boy");
|
||||
});
|
||||
|
||||
@@ -223,11 +243,12 @@ QUnit.test('mention a channel with "&" in the name', async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General & good" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "#");
|
||||
await click(".o-mail-Composer-suggestion");
|
||||
await click(".o-mail-Composer-send");
|
||||
assert.containsOnce($(".o-mail-Message-body"), ".o_channel_redirect");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
await contains(".o-mail-Message-body .o_channel_redirect");
|
||||
assert.strictEqual($(".o_channel_redirect").text(), "#General & good");
|
||||
});
|
||||
|
||||
@@ -302,8 +323,8 @@ QUnit.test(
|
||||
}
|
||||
},
|
||||
});
|
||||
await openDiscuss(channelId);
|
||||
$(".o-mail-Composer-input")[0].focus();
|
||||
openDiscuss(channelId);
|
||||
(await contains(".o-mail-Composer-input"))[0].focus();
|
||||
// simulate receiving a message
|
||||
await pyEnv.withUser(userId, () =>
|
||||
env.services.rpc("/mail/message/post", {
|
||||
@@ -339,7 +360,7 @@ QUnit.test(
|
||||
const { env } = await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
assert.ok(isScrolledToBottom($(".o-mail-Thread")[0]));
|
||||
assert.ok(isScrolledToBottom((await contains(".o-mail-Thread"))[0]));
|
||||
|
||||
// simulate receiving a message
|
||||
await afterNextRender(() =>
|
||||
@@ -376,13 +397,13 @@ QUnit.test(
|
||||
}
|
||||
const { env } = await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
assert.ok(isScrolledToBottom($(".o-mail-Thread")[0]));
|
||||
|
||||
/**
|
||||
* The afterNextRender is necessary because otherwise useAutoScroll would
|
||||
* set the scroll to bottom after the manually set value from this test.
|
||||
*/
|
||||
await afterNextRender(() => click(".o-mail-NotificationItem"));
|
||||
assert.ok(isScrolledToBottom((await contains(".o-mail-Thread"))[0]));
|
||||
$(".o-mail-Thread").scrollTop(0);
|
||||
await nextAnimationFrame();
|
||||
assert.strictEqual($(".o-mail-Thread")[0].scrollTop, 0);
|
||||
|
||||
// simulate receiving a message
|
||||
await afterNextRender(() =>
|
||||
pyEnv.withUser(userId, () =>
|
||||
@@ -397,23 +418,23 @@ QUnit.test(
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("show empty placeholder when thread contains no message", async (assert) => {
|
||||
QUnit.test("show empty placeholder when thread contains no message", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "general" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-Thread:contains(There are no messages in this conversation.)");
|
||||
assert.containsNone($, ".o-mail-Message");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Thread:contains(There are no messages in this conversation.)");
|
||||
await contains(".o-mail-Message", 0);
|
||||
});
|
||||
|
||||
QUnit.test("show empty placeholder when thread contains only empty messages", async (assert) => {
|
||||
QUnit.test("show empty placeholder when thread contains only empty messages", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
pyEnv["mail.message"].create({ model: "discuss.channel", res_id: channelId });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-Thread:contains(There are no messages in this conversation.)");
|
||||
assert.containsNone($, ".o-mail-Message");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Thread:contains(There are no messages in this conversation.)");
|
||||
await contains(".o-mail-Message", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
@@ -436,10 +457,10 @@ QUnit.test(
|
||||
pyEnv["mail.message"].create({ model: "discuss.channel", res_id: channelId });
|
||||
}
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
// initial load: +30 empty ; (auto) load more: +20 empty +10 non-empty
|
||||
assert.containsN($, ".o-mail-Message", 10);
|
||||
assert.containsOnce($, "button:contains(Load More)"); // still 40 non-empty
|
||||
await contains(".o-mail-Message", 10);
|
||||
await contains("button:contains(Load More)"); // still 40 non-empty
|
||||
}
|
||||
);
|
||||
|
||||
@@ -465,22 +486,20 @@ QUnit.test(
|
||||
]);
|
||||
pyEnv["discuss.channel.member"].write([memberId], { seen_message_id: messageId });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsNone($, "hr + span:contains(New messages)");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Message");
|
||||
await contains("hr + span:contains(New messages)", 0);
|
||||
|
||||
await insertText(".o-mail-Composer-input", "hey!");
|
||||
await afterNextRender(() => {
|
||||
// need to remove focus from text area to avoid set_last_seen_message
|
||||
$(".o-mail-Composer-send")[0].focus();
|
||||
$(".o-mail-Composer-send")[0].click();
|
||||
});
|
||||
assert.containsN($, ".o-mail-Message", 2);
|
||||
assert.containsNone($, "hr + span:contains(New messages)");
|
||||
// need to remove focus from text area to avoid set_last_seen_message
|
||||
(await contains(".o-mail-Composer-send:not(:disabled)"))[0].focus();
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
await contains(".o-mail-Message", 2);
|
||||
await contains("hr + span:contains(New messages)", 0);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("new messages separator on receiving new message [REQUIRE FOCUS]", async (assert) => {
|
||||
QUnit.test("new messages separator on receiving new message [REQUIRE FOCUS]", async () => {
|
||||
patchWithCleanup(transitionConfig, { disabled: true });
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Foreigner partner" });
|
||||
@@ -507,9 +526,9 @@ QUnit.test("new messages separator on receiving new message [REQUIRE FOCUS]", as
|
||||
]);
|
||||
pyEnv["discuss.channel.member"].write([memberId], { seen_message_id: messageId });
|
||||
const { env, openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-Message", "should have an initial message");
|
||||
assert.containsNone($, "hr + span:contains(New messages)");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Message");
|
||||
await contains("hr + span:contains(New messages)", 0);
|
||||
|
||||
$(".o-mail-Composer-input")[0].blur();
|
||||
// simulate receiving a message
|
||||
@@ -522,16 +541,16 @@ QUnit.test("new messages separator on receiving new message [REQUIRE FOCUS]", as
|
||||
})
|
||||
)
|
||||
);
|
||||
assert.containsN($, ".o-mail-Message", 2);
|
||||
assert.containsOnce($, "hr + span:contains(New messages)");
|
||||
assert.containsOnce($, ".o-mail-Thread-newMessage ~ .o-mail-Message:contains(hu)");
|
||||
await contains(".o-mail-Message", 2);
|
||||
await contains("hr + span:contains(New messages)");
|
||||
await contains(".o-mail-Thread-newMessage ~ .o-mail-Message:contains(hu)");
|
||||
|
||||
$(".o-mail-Composer-input")[0].focus();
|
||||
await nextTick();
|
||||
assert.containsNone($, "hr + span:contains(New messages)");
|
||||
await contains("hr + span:contains(New messages)", 0);
|
||||
});
|
||||
|
||||
QUnit.test("no new messages separator on posting message (no message history)", async (assert) => {
|
||||
QUnit.test("no new messages separator on posting message (no message history)", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
@@ -541,14 +560,15 @@ QUnit.test("no new messages separator on posting message (no message history)",
|
||||
name: "General",
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsNone($, ".o-mail-Message");
|
||||
assert.containsNone($, "hr + span:contains(New messages)");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Composer-input");
|
||||
await contains(".o-mail-Message", 0);
|
||||
await contains("hr + span:contains(New messages)", 0);
|
||||
|
||||
await insertText(".o-mail-Composer-input", "hey!");
|
||||
await click(".o-mail-Composer-send");
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsNone($, "hr + span:contains(New messages)");
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
await contains(".o-mail-Message");
|
||||
await contains("hr + span:contains(New messages)", 0);
|
||||
});
|
||||
|
||||
QUnit.test("Mention a partner with special character (e.g. apostrophe ')", async (assert) => {
|
||||
@@ -565,18 +585,18 @@ QUnit.test("Mention a partner with special character (e.g. apostrophe ')", async
|
||||
],
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "@");
|
||||
await insertText(".o-mail-Composer-input", "Pyn");
|
||||
await click(".o-mail-Composer-suggestion");
|
||||
await click(".o-mail-Composer-send");
|
||||
assert.containsOnce(
|
||||
$(".o-mail-Message-body"),
|
||||
`.o_mail_redirect[data-oe-id="${partnerId}"][data-oe-model="res.partner"]:contains("@Pynya's spokesman")`
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
await contains(
|
||||
`.o-mail-Message-body .o_mail_redirect[data-oe-id="${partnerId}"][data-oe-model="res.partner"]:contains("@Pynya's spokesman")`
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("mention 2 different partners that have the same name", async (assert) => {
|
||||
QUnit.test("mention 2 different partners that have the same name", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const [partnerId_1, partnerId_2] = pyEnv["res.partner"].create([
|
||||
{
|
||||
@@ -597,22 +617,19 @@ QUnit.test("mention 2 different partners that have the same name", async (assert
|
||||
],
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "@");
|
||||
await insertText(".o-mail-Composer-input", "Te");
|
||||
openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "@Te");
|
||||
await click(".o-mail-Composer-suggestion:eq(0)");
|
||||
await insertText(".o-mail-Composer-input", "@");
|
||||
await insertText(".o-mail-Composer-input", "Te");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
await insertText(".o-mail-Composer-input", "@Te");
|
||||
await click(".o-mail-Composer-suggestion:eq(1)");
|
||||
await click(".o-mail-Composer-send");
|
||||
assert.containsOnce($, ".o-mail-Message-body");
|
||||
assert.containsOnce(
|
||||
$(".o-mail-Message-body"),
|
||||
`.o_mail_redirect[data-oe-id="${partnerId_1}"][data-oe-model="res.partner"]:contains("@TestPartner")`
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
await contains(
|
||||
`.o-mail-Message-body .o_mail_redirect[data-oe-id="${partnerId_1}"][data-oe-model="res.partner"]:contains("@TestPartner")`
|
||||
);
|
||||
assert.containsOnce(
|
||||
$(".o-mail-Message-body"),
|
||||
`.o_mail_redirect[data-oe-id="${partnerId_2}"][data-oe-model="res.partner"]:contains("@TestPartner")`
|
||||
await contains(
|
||||
`.o-mail-Message-body .o_mail_redirect[data-oe-id="${partnerId_2}"][data-oe-model="res.partner"]:contains("@TestPartner")`
|
||||
);
|
||||
});
|
||||
|
||||
@@ -620,34 +637,34 @@ QUnit.test("mention a channel on a second line when the first line contains #",
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General good" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "#blabla\n");
|
||||
await insertText(".o-mail-Composer-input", "#");
|
||||
openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "#blabla\n#");
|
||||
await click(".o-mail-Composer-suggestion");
|
||||
await click(".o-mail-Composer-send");
|
||||
assert.containsOnce($(".o-mail-Message-body"), ".o_channel_redirect");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
await contains(".o-mail-Message-body .o_channel_redirect");
|
||||
assert.strictEqual($(".o_channel_redirect").text(), "#General good");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"mention a channel when replacing the space after the mention by another char",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General good" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "#");
|
||||
await click(".o-mail-Composer-suggestion");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
const text = $(".o-mail-Composer-input").val();
|
||||
$(".o-mail-Composer-input").val(text.slice(0, -1));
|
||||
await insertText(".o-mail-Composer-input", ", test");
|
||||
await click(".o-mail-Composer-send");
|
||||
assert.containsOnce($(".o-mail-Message-body"), ".o_channel_redirect");
|
||||
assert.strictEqual($(".o_channel_redirect").text(), "#General good");
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
await contains(".o-mail-Message-body .o_channel_redirect:contains(#General good)");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("mention 2 different channels that have the same name", async (assert) => {
|
||||
QUnit.test("mention 2 different channels that have the same name", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const [channelId_1, channelId_2] = pyEnv["discuss.channel"].create([
|
||||
{
|
||||
@@ -661,28 +678,25 @@ QUnit.test("mention 2 different channels that have the same name", async (assert
|
||||
},
|
||||
]);
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId_1);
|
||||
await insertText(".o-mail-Composer-input", "#");
|
||||
await insertText(".o-mail-Composer-input", "m");
|
||||
openDiscuss(channelId_1);
|
||||
await insertText(".o-mail-Composer-input", "#m");
|
||||
await click(".o-mail-Composer-suggestion:eq(0)");
|
||||
await insertText(".o-mail-Composer-input", "#");
|
||||
await insertText(".o-mail-Composer-input", "m");
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
await insertText(".o-mail-Composer-input", "#m");
|
||||
await click(".o-mail-Composer-suggestion:eq(1)");
|
||||
await click(".o-mail-Composer-send");
|
||||
assert.containsOnce($, ".o-mail-Message-body");
|
||||
assert.containsOnce(
|
||||
$(".o-mail-Message-body"),
|
||||
`.o_channel_redirect[data-oe-id="${channelId_1}"][data-oe-model="discuss.channel"]:contains("#my channel")`
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
await contains(
|
||||
`.o-mail-Message-body .o_channel_redirect[data-oe-id="${channelId_1}"][data-oe-model="discuss.channel"]:contains("#my channel")`
|
||||
);
|
||||
assert.containsOnce(
|
||||
$(".o-mail-Message-body"),
|
||||
`.o_channel_redirect[data-oe-id="${channelId_2}"][data-oe-model="discuss.channel"]:contains("#my channel")`
|
||||
await contains(
|
||||
`.o-mail-Message-body .o_channel_redirect[data-oe-id="${channelId_2}"][data-oe-model="discuss.channel"]:contains("#my channel")`
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"Post a message containing an email address followed by a mention on another line",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({
|
||||
email: "testpartner@odoo.com",
|
||||
@@ -696,20 +710,18 @@ QUnit.test(
|
||||
],
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "email@odoo.com\n");
|
||||
await insertText(".o-mail-Composer-input", "@");
|
||||
await insertText(".o-mail-Composer-input", "Te");
|
||||
openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "email@odoo.com\n@Te");
|
||||
await click(".o-mail-Composer-suggestion");
|
||||
await click(".o-mail-Composer-send");
|
||||
assert.containsOnce(
|
||||
$(".o-mail-Message-body"),
|
||||
`.o_mail_redirect[data-oe-id="${partnerId}"][data-oe-model="res.partner"]:contains("@TestPartner")`
|
||||
await contains(".o-mail-Composer-suggestion", 0);
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
await contains(
|
||||
`.o-mail-Message-body .o_mail_redirect[data-oe-id="${partnerId}"][data-oe-model="res.partner"]:contains("@TestPartner")`
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("basic rendering of canceled notification", async (assert) => {
|
||||
QUnit.test("basic rendering of canceled notification", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "test" });
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Someone" });
|
||||
@@ -727,18 +739,18 @@ QUnit.test("basic rendering of canceled notification", async (assert) => {
|
||||
res_partner_id: partnerId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-Message-notification .fa-envelope-o");
|
||||
openDiscuss(channelId);
|
||||
await contains(".o-mail-Message-notification .fa-envelope-o");
|
||||
|
||||
await click(".o-mail-Message-notification");
|
||||
assert.containsOnce($, ".o-mail-MessageNotificationPopover");
|
||||
assert.containsOnce($, ".o-mail-MessageNotificationPopover .fa-trash-o");
|
||||
assert.containsOnce($, ".o-mail-MessageNotificationPopover:contains(Someone)");
|
||||
await contains(".o-mail-MessageNotificationPopover");
|
||||
await contains(".o-mail-MessageNotificationPopover .fa-trash-o");
|
||||
await contains(".o-mail-MessageNotificationPopover:contains(Someone)");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"first unseen message should be directly preceded by the new message separator if there is a transient message just before it while composer is not focused [REQUIRE FOCUS]",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
// The goal of removing the focus is to ensure the thread is not marked as seen automatically.
|
||||
// Indeed that would trigger set_last_seen_message no matter what, which is already covered by other tests.
|
||||
// The goal of this test is to cover the conditions specific to transient messages,
|
||||
@@ -766,25 +778,24 @@ QUnit.test(
|
||||
},
|
||||
]);
|
||||
const { openDiscuss, env } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
// send a command that leads to receiving a transient message
|
||||
await insertText(".o-mail-Composer-input", "/who");
|
||||
await click(".o-mail-Composer-send");
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
await contains(".o-mail-Message", 2);
|
||||
// composer is focused by default, we remove that focus
|
||||
$(".o-mail-Composer-input")[0].blur();
|
||||
// simulate receiving a message
|
||||
await afterNextRender(() =>
|
||||
pyEnv.withUser(userId, () =>
|
||||
env.services.rpc("/mail/message/post", {
|
||||
post_data: { body: "test", message_type: "comment" },
|
||||
thread_id: channelId,
|
||||
thread_model: "discuss.channel",
|
||||
})
|
||||
)
|
||||
pyEnv.withUser(userId, () =>
|
||||
env.services.rpc("/mail/message/post", {
|
||||
post_data: { body: "test", message_type: "comment" },
|
||||
thread_id: channelId,
|
||||
thread_model: "discuss.channel",
|
||||
})
|
||||
);
|
||||
assert.containsN($, ".o-mail-Message", 3);
|
||||
assert.containsOnce($, "hr + span:contains(New messages)");
|
||||
assert.containsOnce($, ".o-mail-Message[aria-label='Note'] + .o-mail-Thread-newMessage");
|
||||
await contains(".o-mail-Message", 3);
|
||||
await contains("hr + span:contains(New messages)");
|
||||
await contains(".o-mail-Message[aria-label='Note'] + .o-mail-Thread-newMessage");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -794,39 +805,36 @@ QUnit.test(
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "test" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "Dummy Message");
|
||||
await click(".o-mail-Composer-send");
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
assert.strictEqual(document.activeElement, $(".o-mail-Composer-input")[0]);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"chat window header should not have unread counter for non-channel thread",
|
||||
async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "test" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
author_id: partnerId,
|
||||
body: "not empty",
|
||||
model: "res.partner",
|
||||
needaction: true,
|
||||
needaction_partner_ids: [pyEnv.currentPartnerId],
|
||||
res_id: partnerId,
|
||||
});
|
||||
pyEnv["mail.notification"].create({
|
||||
mail_message_id: messageId,
|
||||
notification_status: "sent",
|
||||
notification_type: "inbox",
|
||||
res_partner_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem-name");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
assert.containsNone($, ".o-mail-ChatWindow-header:contains('(1)')");
|
||||
}
|
||||
);
|
||||
QUnit.test("chat window header should not have unread counter for non-channel thread", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "test" });
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
author_id: partnerId,
|
||||
body: "not empty",
|
||||
model: "res.partner",
|
||||
needaction: true,
|
||||
needaction_partner_ids: [pyEnv.currentPartnerId],
|
||||
res_id: partnerId,
|
||||
});
|
||||
pyEnv["mail.notification"].create({
|
||||
mail_message_id: messageId,
|
||||
notification_status: "sent",
|
||||
notification_type: "inbox",
|
||||
res_partner_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem-name");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow-header:contains('(1)')", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"[technical] opening a non-channel chat window should not call channel_fold",
|
||||
@@ -861,11 +869,11 @@ QUnit.test(
|
||||
},
|
||||
});
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem");
|
||||
assert.containsNone($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-NotificationItem");
|
||||
await contains(".o-mail-ChatWindow", 0);
|
||||
|
||||
await click(".o-mail-NotificationItem");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -893,11 +901,11 @@ QUnit.test("Thread messages are only loaded once", async (assert) => {
|
||||
},
|
||||
]);
|
||||
openDiscuss();
|
||||
(await contains(".o-mail-DiscussSidebarChannel:eq(0)")).click();
|
||||
await click(".o-mail-DiscussSidebarChannel:eq(0)");
|
||||
await contains(".o-mail-Message:contains(channel1)");
|
||||
(await contains(".o-mail-DiscussSidebarChannel:eq(1)")).click();
|
||||
await click(".o-mail-DiscussSidebarChannel:eq(1)");
|
||||
await contains(".o-mail-Message:contains(channel2)");
|
||||
(await contains(".o-mail-DiscussSidebarChannel:eq(0)")).click();
|
||||
await click(".o-mail-DiscussSidebarChannel:eq(0)");
|
||||
await contains(".o-mail-Message:contains(channel1)");
|
||||
assert.verifySteps([`load messages - ${channelIds[0]}`, `load messages - ${channelIds[1]}`]);
|
||||
});
|
||||
@@ -919,10 +927,11 @@ QUnit.test(
|
||||
}
|
||||
},
|
||||
});
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
// ensure focusout is triggered on composers' textarea
|
||||
await triggerEvents($(".o-mail-Composer-input")[0], null, ["blur", "focusout"]);
|
||||
triggerEvents((await contains(".o-mail-Composer-input"))[0], null, ["blur", "focusout"]);
|
||||
await click("button:contains(Inbox)");
|
||||
await contains("h4:contains(Congratulations, your inbox is empty)");
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
author_id: partnerId,
|
||||
body: "@Mitchel Admin",
|
||||
@@ -941,10 +950,7 @@ QUnit.test(
|
||||
const [formattedMessage] = await env.services.orm.call("mail.message", "message_format", [
|
||||
[messageId],
|
||||
]);
|
||||
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "discuss.channel/new_message", {
|
||||
id: channelId,
|
||||
message: formattedMessage,
|
||||
});
|
||||
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "mail.message/inbox", formattedMessage);
|
||||
await contains("button:contains(Inbox) .badge:contains(1)");
|
||||
click("button:contains(General)");
|
||||
await contains(".o-discuss-badge", 0);
|
||||
@@ -965,7 +971,7 @@ QUnit.test(
|
||||
}
|
||||
},
|
||||
});
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await click("button:contains(Inbox)");
|
||||
await env.services.rpc("/mail/message/post", {
|
||||
post_data: {
|
||||
@@ -981,7 +987,7 @@ QUnit.test(
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("can be marked as read while loading", async function (assert) {
|
||||
QUnit.test("can be marked as read while loading", async function () {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo" });
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
@@ -1005,47 +1011,46 @@ QUnit.test("can be marked as read while loading", async function (assert) {
|
||||
}
|
||||
},
|
||||
});
|
||||
await openDiscuss(undefined, { waitUntilMessagesLoaded: false });
|
||||
assert.containsOnce($, ".o-discuss-badge:contains(1)");
|
||||
openDiscuss(undefined, { waitUntilMessagesLoaded: false });
|
||||
await contains(".o-discuss-badge:contains(1)");
|
||||
await click(".o-mail-DiscussSidebarChannel:contains(Demo)");
|
||||
await afterNextRender(loadDeferred.resolve);
|
||||
assert.containsNone($, ".o-discuss-badge");
|
||||
await contains(".o-discuss-badge", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"New message separator not appearing after showing composer on thread",
|
||||
async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.message"].create([
|
||||
{
|
||||
model: "res.partner",
|
||||
res_id: pyEnv.currentPartnerId,
|
||||
body: "Message on partner",
|
||||
},
|
||||
{
|
||||
model: "res.partner",
|
||||
res_id: pyEnv.currentPartnerId,
|
||||
body: "Message on partner",
|
||||
},
|
||||
]);
|
||||
const { openFormView } = await start();
|
||||
await openFormView("res.partner", pyEnv.currentPartnerId);
|
||||
assert.containsNone($, ".o-mail-Thread-newMessage");
|
||||
await click("button:contains(Log note)");
|
||||
assert.containsNone($, ".o-mail-Thread-newMessage");
|
||||
}
|
||||
);
|
||||
QUnit.test("New message separator not appearing after showing composer on thread", async () => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.message"].create([
|
||||
{
|
||||
model: "res.partner",
|
||||
res_id: pyEnv.currentPartnerId,
|
||||
body: "Message on partner",
|
||||
},
|
||||
{
|
||||
model: "res.partner",
|
||||
res_id: pyEnv.currentPartnerId,
|
||||
body: "Message on partner",
|
||||
},
|
||||
]);
|
||||
const { openFormView } = await start();
|
||||
openFormView("res.partner", pyEnv.currentPartnerId);
|
||||
await contains("button:contains(Log note)");
|
||||
await contains(".o-mail-Thread-newMessage", 0);
|
||||
await click("button:contains(Log note)");
|
||||
await contains(".o-mail-Thread-newMessage", 0);
|
||||
});
|
||||
|
||||
QUnit.test("Transient messages are added at the end of the thread", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
openDiscuss(channelId);
|
||||
await insertText(".o-mail-Composer-input", "Dummy Message");
|
||||
await click(".o-mail-Composer-send");
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
await editInput(document.body, ".o-mail-Composer-input", "/help");
|
||||
await afterNextRender(() => triggerHotkey("Enter"));
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
await contains(".o-mail-Message");
|
||||
await insertText(".o-mail-Composer-input", "/help");
|
||||
await click(".o-mail-Composer-send:not(:disabled)");
|
||||
await contains(".o-mail-Message", 2);
|
||||
const lastMessage = document.querySelectorAll(".o-mail-Message")[1];
|
||||
assert.ok(lastMessage.innerText.includes("You are in channel #General"));
|
||||
});
|
||||
|
||||
@@ -64,7 +64,7 @@ registry.category("web_tour.tours").add("mail/static/tests/tours/discuss_public_
|
||||
},
|
||||
{
|
||||
content: "Send message",
|
||||
trigger: ".o-mail-Composer-send",
|
||||
trigger: ".o-mail-Composer-send:not(:disabled)",
|
||||
},
|
||||
{
|
||||
content: "Check message is shown",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { ROUTES_TO_IGNORE } from "@mail/../tests/helpers/webclient_setup";
|
||||
|
||||
import { ListController } from "@web/views/list/list_controller";
|
||||
@@ -41,7 +41,7 @@ QUnit.test("list activity widget with no activity", async (assert) => {
|
||||
views: [[false, "list"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-ActivityButton i.text-muted");
|
||||
assert.strictEqual($(".o-mail-ListActivity-summary")[0].innerText, "");
|
||||
await contains(".o-mail-ListActivity-summary:eq(0):contains()");
|
||||
assert.verifySteps(["/web/dataset/call_kw/res.users/unity_web_search_read"]);
|
||||
});
|
||||
|
||||
@@ -141,7 +141,7 @@ QUnit.test("list activity widget with exception", async (assert) => {
|
||||
views: [[false, "list"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-ActivityButton i.text-warning.fa-warning");
|
||||
assert.strictEqual($(".o-mail-ListActivity-summary")[0].innerText, "Warning");
|
||||
await contains(".o-mail-ListActivity-summary:eq(0):contains(Warning)");
|
||||
assert.verifySteps(["/web/dataset/call_kw/res.users/unity_web_search_read"]);
|
||||
});
|
||||
|
||||
@@ -220,12 +220,12 @@ QUnit.test("list activity widget: open dropdown", async (assert) => {
|
||||
res_model: "res.users",
|
||||
views: [[false, "list"]],
|
||||
});
|
||||
assert.strictEqual($(".o-mail-ListActivity-summary")[0].innerText, "Call with Al");
|
||||
await contains(".o-mail-ListActivity-summary:eq(0):contains(Call with Al)");
|
||||
|
||||
await click(".o-mail-ActivityButton"); // open the popover
|
||||
await click(".o-mail-ActivityListPopoverItem-markAsDone"); // mark the first activity as done
|
||||
await click(".o-mail-ActivityListPopoverItem-markAsDone:eq(0)"); // mark the first activity as done
|
||||
await click(".o-mail-ActivityMarkAsDone button[aria-label='Done']"); // confirm
|
||||
assert.strictEqual($(".o-mail-ListActivity-summary")[0].innerText, "Meet FP");
|
||||
await contains(".o-mail-ListActivity-summary:eq(0):contains(Meet FP)");
|
||||
assert.verifySteps(["unity_web_search_read", "activity_format", "action_feedback", "web_read"]);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { patchUiSize, SIZES } from "@mail/../tests/helpers/patch_ui_size";
|
||||
import { click, nextAnimationFrame, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import {
|
||||
click,
|
||||
contains,
|
||||
nextAnimationFrame,
|
||||
start,
|
||||
startServer,
|
||||
} from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
QUnit.module("attachment box");
|
||||
|
||||
QUnit.test("base empty rendering", async (assert) => {
|
||||
QUnit.test("base empty rendering", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const views = {
|
||||
@@ -19,17 +25,17 @@ QUnit.test("base empty rendering", async (assert) => {
|
||||
`,
|
||||
};
|
||||
const { openView } = await start({ serverData: { views } });
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-AttachmentBox");
|
||||
assert.containsOnce($, "button:contains('Attach files')");
|
||||
assert.containsNone($, ".o-mail-Chatter .o-mail-AttachmentImage");
|
||||
await contains(".o-mail-AttachmentBox");
|
||||
await contains("button:contains('Attach files')");
|
||||
await contains(".o-mail-Chatter .o-mail-AttachmentImage", 0);
|
||||
});
|
||||
|
||||
QUnit.test("base non-empty rendering", async (assert) => {
|
||||
QUnit.test("base non-empty rendering", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
pyEnv["ir.attachment"].create([
|
||||
@@ -57,18 +63,18 @@ QUnit.test("base non-empty rendering", async (assert) => {
|
||||
`,
|
||||
};
|
||||
const { openView } = await start({ serverData: { views } });
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-AttachmentBox");
|
||||
assert.containsOnce($, "button:contains('Attach files')");
|
||||
assert.containsOnce($, ".o-mail-Chatter input[type='file']");
|
||||
assert.containsOnce($, ".o-mail-AttachmentList");
|
||||
await contains(".o-mail-AttachmentBox");
|
||||
await contains("button:contains('Attach files')");
|
||||
await contains(".o-mail-Chatter input[type='file']");
|
||||
await contains(".o-mail-AttachmentList");
|
||||
});
|
||||
|
||||
QUnit.test("remove attachment should ask for confirmation", async (assert) => {
|
||||
QUnit.test("remove attachment should ask for confirmation", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
pyEnv["ir.attachment"].create({
|
||||
@@ -88,23 +94,23 @@ QUnit.test("remove attachment should ask for confirmation", async (assert) => {
|
||||
`,
|
||||
};
|
||||
const { openView } = await start({ serverData: { views } });
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-AttachmentCard");
|
||||
assert.containsOnce($, "button[title='Remove']");
|
||||
await contains(".o-mail-AttachmentCard");
|
||||
await contains("button[title='Remove']");
|
||||
|
||||
await click("button[title='Remove']");
|
||||
assert.containsOnce($, ".modal-body:contains('Do you really want to delete \"Blah.txt\"?')");
|
||||
await contains(".modal-body:contains('Do you really want to delete \"Blah.txt\"?')");
|
||||
|
||||
// Confirm the deletion
|
||||
await click(".modal-footer .btn-primary");
|
||||
assert.containsNone($, ".o-mail-AttachmentImage");
|
||||
await contains(".o-mail-AttachmentImage", 0);
|
||||
});
|
||||
|
||||
QUnit.test("view attachments", async (assert) => {
|
||||
QUnit.test("view attachments", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
pyEnv["ir.attachment"].create([
|
||||
@@ -130,22 +136,22 @@ QUnit.test("view attachments", async (assert) => {
|
||||
</form>`,
|
||||
};
|
||||
const { openView } = await start({ serverData: { views } });
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
await click('.o-mail-AttachmentCard[aria-label="Blah.txt"] .o-mail-AttachmentCard-image');
|
||||
assert.containsOnce($, ".o-FileViewer");
|
||||
assert.containsOnce($, ".o-FileViewer-header:contains(Blah.txt)");
|
||||
assert.containsOnce($, ".o-FileViewer div[aria-label='Next']");
|
||||
await contains(".o-FileViewer");
|
||||
await contains(".o-FileViewer-header:contains(Blah.txt)");
|
||||
await contains(".o-FileViewer div[aria-label='Next']");
|
||||
|
||||
await click(".o-FileViewer div[aria-label='Next']");
|
||||
assert.containsOnce($, ".o-FileViewer-header:contains(Blu.txt)");
|
||||
assert.containsOnce($, ".o-FileViewer div[aria-label='Next']");
|
||||
await contains(".o-FileViewer-header:contains(Blu.txt)");
|
||||
await contains(".o-FileViewer div[aria-label='Next']");
|
||||
|
||||
await click(".o-FileViewer div[aria-label='Next']");
|
||||
assert.containsOnce($, ".o-FileViewer-header:contains(Blah.txt)");
|
||||
await contains(".o-FileViewer-header:contains(Blah.txt)");
|
||||
});
|
||||
|
||||
QUnit.test("scroll to attachment box when toggling on", async (assert) => {
|
||||
@@ -166,7 +172,7 @@ QUnit.test("scroll to attachment box when toggling on", async (assert) => {
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
@@ -177,7 +183,7 @@ QUnit.test("scroll to attachment box when toggling on", async (assert) => {
|
||||
assert.isVisible($(".o-mail-AttachmentBox"));
|
||||
});
|
||||
|
||||
QUnit.test("attachment box should order attachments from newest to oldest", async (assert) => {
|
||||
QUnit.test("attachment box should order attachments from newest to oldest", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const resData = { res_id: partnerId, res_model: "res.partner" };
|
||||
@@ -187,14 +193,14 @@ QUnit.test("attachment box should order attachments from newest to oldest", asyn
|
||||
{ name: "C.txt", mimetype: "text/plain", ...resData },
|
||||
]);
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Chatter [aria-label='Attach files']:contains(3)");
|
||||
await contains(".o-mail-Chatter [aria-label='Attach files']:contains(3)");
|
||||
await click(".o-mail-Chatter [aria-label='Attach files']"); // open attachment box
|
||||
assert.containsOnce($, ".o-mail-AttachmentCard:eq(0):contains(C.txt)");
|
||||
assert.containsOnce($, ".o-mail-AttachmentCard:eq(1):contains(B.txt)");
|
||||
assert.containsOnce($, ".o-mail-AttachmentCard:eq(2):contains(A.txt)");
|
||||
await contains(".o-mail-AttachmentCard:eq(0):contains(C.txt)");
|
||||
await contains(".o-mail-AttachmentCard:eq(1):contains(B.txt)");
|
||||
await contains(".o-mail-AttachmentCard:eq(2):contains(A.txt)");
|
||||
});
|
||||
|
||||
@@ -9,12 +9,13 @@ import {
|
||||
dropFiles,
|
||||
insertText,
|
||||
isScrolledTo,
|
||||
nextAnimationFrame,
|
||||
start,
|
||||
startServer,
|
||||
} from "@mail/../tests/helpers/test_utils";
|
||||
import { DELAY_FOR_SPINNER } from "@mail/core/web/chatter";
|
||||
|
||||
import { editInput, triggerHotkey } from "@web/../tests/helpers/utils";
|
||||
import { triggerHotkey } from "@web/../tests/helpers/utils";
|
||||
import { file } from "@web/../tests/legacy/helpers/test_utils";
|
||||
|
||||
const { createFile } = file;
|
||||
@@ -30,9 +31,9 @@ QUnit.test("simple chatter on a record", async (assert) => {
|
||||
},
|
||||
});
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "John Doe" });
|
||||
await openFormView("res.partner", partnerId);
|
||||
assert.containsOnce($, ".o-mail-Chatter-topbar");
|
||||
assert.containsOnce($, ".o-mail-Thread");
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Chatter-topbar");
|
||||
await contains(".o-mail-Thread");
|
||||
assert.verifySteps([
|
||||
"/mail/init_messaging",
|
||||
"/mail/load_message_failures",
|
||||
@@ -67,17 +68,18 @@ QUnit.test("can post a message on a record thread", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
await openFormView("res.partner", partnerId);
|
||||
assert.containsNone($, ".o-mail-Composer");
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains("button:contains(Send message)");
|
||||
await contains(".o-mail-Composer", 0);
|
||||
|
||||
await click("button:contains(Send message)");
|
||||
assert.containsOnce($, ".o-mail-Composer");
|
||||
await contains(".o-mail-Composer");
|
||||
|
||||
await editInput(document.body, ".o-mail-Composer-input", "hey");
|
||||
assert.containsNone($, ".o-mail-Message");
|
||||
await insertText(".o-mail-Composer-input", "hey");
|
||||
await contains(".o-mail-Message", 0);
|
||||
|
||||
await click(".o-mail-Composer button:contains(Send)");
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
await click(".o-mail-Composer button:contains(Send):not(:disabled)");
|
||||
await contains(".o-mail-Message");
|
||||
assert.verifySteps(["/mail/message/post"]);
|
||||
});
|
||||
|
||||
@@ -107,30 +109,31 @@ QUnit.test("can post a note on a record thread", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
await openFormView("res.partner", partnerId);
|
||||
assert.containsNone($, ".o-mail-Composer");
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains("button:contains(Log note)");
|
||||
await contains(".o-mail-Composer", 0);
|
||||
|
||||
await click("button:contains(Log note)");
|
||||
assert.containsOnce($, ".o-mail-Composer");
|
||||
await contains(".o-mail-Composer");
|
||||
|
||||
await editInput(document.body, ".o-mail-Composer-input", "hey");
|
||||
assert.containsNone($, ".o-mail-Message");
|
||||
await insertText(".o-mail-Composer-input", "hey");
|
||||
await contains(".o-mail-Message", 0);
|
||||
|
||||
await click(".o-mail-Composer button:contains(Log)");
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
await click(".o-mail-Composer button:contains(Log):not(:disabled)");
|
||||
await contains(".o-mail-Message");
|
||||
assert.verifySteps(["/mail/message/post"]);
|
||||
});
|
||||
|
||||
QUnit.test("No attachment loading spinner when creating records", async (assert) => {
|
||||
QUnit.test("No attachment loading spinner when creating records", async () => {
|
||||
const { openFormView } = await start();
|
||||
await openFormView("res.partner");
|
||||
assert.containsOnce($, "button[aria-label='Attach files']");
|
||||
assert.containsNone($, "button[aria-label='Attach files'] .fa-spin");
|
||||
openFormView("res.partner");
|
||||
await contains("button[aria-label='Attach files']");
|
||||
await contains("button[aria-label='Attach files'] .fa-spin", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"No attachment loading spinner when switching from loading record to creation of record",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const { advanceTime, openFormView, pyEnv } = await start({
|
||||
hasTimeControl: true,
|
||||
async mockRPC(route) {
|
||||
@@ -140,20 +143,21 @@ QUnit.test(
|
||||
},
|
||||
});
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "John" });
|
||||
await openFormView("res.partner", partnerId, { waitUntilDataLoaded: false });
|
||||
openFormView("res.partner", partnerId, { waitUntilDataLoaded: false });
|
||||
await contains("button[aria-label='Attach files']");
|
||||
await advanceTime(DELAY_FOR_SPINNER);
|
||||
await waitUntil("button[aria-label='Attach files'] .fa-spin");
|
||||
await click(".o_form_button_create");
|
||||
assert.containsNone($, "button[aria-label='Attach files'] .fa-spin");
|
||||
await contains("button[aria-label='Attach files'] .fa-spin");
|
||||
await click(".o_form_button_create:eq(0)");
|
||||
await contains("button[aria-label='Attach files'] .fa-spin", 0);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("Composer toggle state is kept when switching from aside to bottom", async (assert) => {
|
||||
QUnit.test("Composer toggle state is kept when switching from aside to bottom", async () => {
|
||||
patchUiSize({ size: SIZES.XXL });
|
||||
const { openFormView, pyEnv } = await start();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "John Doe" });
|
||||
openFormView("res.partner", partnerId);
|
||||
(await contains("button:contains(Send message)")).click();
|
||||
await click("button:contains(Send message)");
|
||||
await contains(".o-mail-Form-chatter.o-aside .o-mail-Composer-input");
|
||||
patchUiSize({ size: SIZES.LG });
|
||||
window.dispatchEvent(new Event("resize"));
|
||||
@@ -165,9 +169,9 @@ QUnit.test("Textarea content is kept when switching from aside to bottom", async
|
||||
const { openFormView, pyEnv } = await start();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "John Doe" });
|
||||
openFormView("res.partner", partnerId);
|
||||
(await contains("button:contains(Send message)")).click();
|
||||
await click("button:contains(Send message)");
|
||||
await contains(".o-mail-Form-chatter.o-aside .o-mail-Composer-input");
|
||||
await editInput(document.body, ".o-mail-Composer-input", "Hello world !");
|
||||
await insertText(".o-mail-Composer-input", "Hello world !");
|
||||
patchUiSize({ size: SIZES.LG });
|
||||
window.dispatchEvent(new Event("resize"));
|
||||
await contains(".o-mail-Form-chatter:not(.o-aside) .o-mail-Composer-input");
|
||||
@@ -178,7 +182,7 @@ QUnit.test("Composer type is kept when switching from aside to bottom", async (a
|
||||
patchUiSize({ size: SIZES.XXL });
|
||||
const { openFormView, pyEnv } = await start();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "John Doe" });
|
||||
await openFormView("res.partner", partnerId);
|
||||
openFormView("res.partner", partnerId);
|
||||
await click("button:contains(Log note)");
|
||||
patchUiSize({ size: SIZES.LG });
|
||||
window.dispatchEvent(new Event("resize"));
|
||||
@@ -195,7 +199,7 @@ QUnit.test("chatter: drop attachments", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
@@ -213,8 +217,8 @@ QUnit.test("chatter: drop attachments", async (assert) => {
|
||||
}),
|
||||
];
|
||||
await afterNextRender(() => dragenterFiles($(".o-mail-Chatter")[0]));
|
||||
assert.containsOnce($, ".o-mail-Dropzone");
|
||||
assert.containsNone($, ".o-mail-AttachmentCard");
|
||||
await contains(".o-mail-Dropzone");
|
||||
await contains(".o-mail-AttachmentCard", 0);
|
||||
|
||||
await afterNextRender(() => dropFiles($(".o-mail-Dropzone")[0], files));
|
||||
assert.containsN($, ".o-mail-AttachmentCard", 2);
|
||||
@@ -231,7 +235,7 @@ QUnit.test("chatter: drop attachments", async (assert) => {
|
||||
assert.containsN($, ".o-mail-AttachmentCard", 3);
|
||||
});
|
||||
|
||||
QUnit.test("should display subject when subject isn't infered from the record", async (assert) => {
|
||||
QUnit.test("should display subject when subject isn't infered from the record", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
pyEnv["mail.message"].create({
|
||||
@@ -241,15 +245,15 @@ QUnit.test("should display subject when subject isn't infered from the record",
|
||||
subject: "Salutations, voyageur",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Message:contains(Subject: Salutations, voyageur)");
|
||||
await contains(".o-mail-Message:contains(Subject: Salutations, voyageur)");
|
||||
});
|
||||
|
||||
QUnit.test("should not display user notification messages in chatter", async (assert) => {
|
||||
QUnit.test("should not display user notification messages in chatter", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
pyEnv["mail.message"].create({
|
||||
@@ -258,29 +262,29 @@ QUnit.test("should not display user notification messages in chatter", async (as
|
||||
res_id: partnerId,
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsNone($, ".o-mail-Message");
|
||||
await contains(".o-mail-Thread-empty");
|
||||
await contains(".o-mail-Message", 0);
|
||||
});
|
||||
|
||||
QUnit.test('post message with "CTRL-Enter" keyboard shortcut in chatter', async (assert) => {
|
||||
QUnit.test('post message with "CTRL-Enter" keyboard shortcut in chatter', async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsNone($, ".o-mail-Message");
|
||||
|
||||
await click("button:contains(Send message)");
|
||||
await contains(".o-mail-Message", 0);
|
||||
await insertText(".o-mail-Composer-input", "Test");
|
||||
await afterNextRender(() => triggerHotkey("control+Enter"));
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
triggerHotkey("control+Enter");
|
||||
await contains(".o-mail-Message");
|
||||
});
|
||||
|
||||
QUnit.test("base rendering when chatter has no attachment", async (assert) => {
|
||||
@@ -294,36 +298,36 @@ QUnit.test("base rendering when chatter has no attachment", async (assert) => {
|
||||
});
|
||||
}
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Chatter");
|
||||
assert.containsOnce($, ".o-mail-Chatter-topbar");
|
||||
assert.containsNone($, ".o-mail-AttachmentBox");
|
||||
assert.containsOnce($, ".o-mail-Thread");
|
||||
await contains(".o-mail-Chatter");
|
||||
await contains(".o-mail-Chatter-topbar");
|
||||
await contains(".o-mail-AttachmentBox", 0);
|
||||
await contains(".o-mail-Thread");
|
||||
assert.containsN($, ".o-mail-Message", 30);
|
||||
});
|
||||
|
||||
QUnit.test("base rendering when chatter has no record", async (assert) => {
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Chatter");
|
||||
assert.containsOnce($, ".o-mail-Chatter-topbar");
|
||||
assert.containsNone($, ".o-mail-AttachmentBox");
|
||||
assert.containsOnce($, ".o-mail-Chatter .o-mail-Thread");
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
await contains(".o-mail-Chatter");
|
||||
await contains(".o-mail-Chatter-topbar");
|
||||
await contains(".o-mail-AttachmentBox", 0);
|
||||
await contains(".o-mail-Chatter .o-mail-Thread");
|
||||
await contains(".o-mail-Message");
|
||||
assert.strictEqual($(".o-mail-Message-body").text(), "Creating a new record...");
|
||||
assert.containsNone($, "button:contains(Load More)");
|
||||
assert.containsOnce($, ".o-mail-Message-actions");
|
||||
assert.containsNone($, ".o-mail-Message-actions i");
|
||||
await contains("button:contains(Load More)", 0);
|
||||
await contains(".o-mail-Message-actions");
|
||||
await contains(".o-mail-Message-actions i", 0);
|
||||
});
|
||||
|
||||
QUnit.test("base rendering when chatter has attachments", async (assert) => {
|
||||
QUnit.test("base rendering when chatter has attachments", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
pyEnv["ir.attachment"].create([
|
||||
@@ -341,17 +345,17 @@ QUnit.test("base rendering when chatter has attachments", async (assert) => {
|
||||
},
|
||||
]);
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Chatter");
|
||||
assert.containsOnce($, ".o-mail-Chatter-topbar");
|
||||
assert.containsNone($, ".o-mail-AttachmentBox");
|
||||
await contains(".o-mail-Chatter");
|
||||
await contains(".o-mail-Chatter-topbar");
|
||||
await contains(".o-mail-AttachmentBox", 0);
|
||||
});
|
||||
|
||||
QUnit.test("show attachment box", async (assert) => {
|
||||
QUnit.test("show attachment box", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
pyEnv["ir.attachment"].create([
|
||||
@@ -369,91 +373,88 @@ QUnit.test("show attachment box", async (assert) => {
|
||||
},
|
||||
]);
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Chatter");
|
||||
assert.containsOnce($, ".o-mail-Chatter-topbar");
|
||||
assert.containsOnce($, "button[aria-label='Attach files']");
|
||||
assert.containsOnce($, "button[aria-label='Attach files']:contains(2)");
|
||||
assert.containsNone($, ".o-mail-AttachmentBox");
|
||||
await contains(".o-mail-Chatter");
|
||||
await contains(".o-mail-Chatter-topbar");
|
||||
await contains("button[aria-label='Attach files']");
|
||||
await contains("button[aria-label='Attach files']:contains(2)");
|
||||
await contains(".o-mail-AttachmentBox", 0);
|
||||
|
||||
await click("button[aria-label='Attach files']");
|
||||
assert.containsOnce($, ".o-mail-AttachmentBox");
|
||||
await contains(".o-mail-AttachmentBox");
|
||||
});
|
||||
|
||||
QUnit.test("composer show/hide on log note/send message [REQUIRE FOCUS]", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, "button:contains(Send message)");
|
||||
assert.containsOnce($, "button:contains(Log note)");
|
||||
assert.containsNone($, ".o-mail-Composer");
|
||||
await contains("button:contains(Send message)");
|
||||
await contains("button:contains(Log note)");
|
||||
await contains(".o-mail-Composer", 0);
|
||||
|
||||
await click("button:contains(Send message)");
|
||||
assert.containsOnce($, ".o-mail-Composer");
|
||||
await contains(".o-mail-Composer");
|
||||
assert.strictEqual(document.activeElement, $(".o-mail-Composer-input")[0]);
|
||||
|
||||
await click("button:contains(Log note)");
|
||||
assert.containsOnce($, ".o-mail-Composer");
|
||||
await contains(".o-mail-Composer");
|
||||
assert.strictEqual(document.activeElement, $(".o-mail-Composer-input")[0]);
|
||||
|
||||
await click("button:contains(Log note)");
|
||||
assert.containsNone($, ".o-mail-Composer");
|
||||
await contains(".o-mail-Composer", 0);
|
||||
|
||||
await click("button:contains(Send message)");
|
||||
assert.containsOnce($, ".o-mail-Composer");
|
||||
await contains(".o-mail-Composer");
|
||||
|
||||
await click("button:contains(Send message)");
|
||||
assert.containsNone($, ".o-mail-Composer");
|
||||
await contains(".o-mail-Composer", 0);
|
||||
});
|
||||
|
||||
QUnit.test('do not post message with "Enter" keyboard shortcut', async (assert) => {
|
||||
QUnit.test('do not post message with "Enter" keyboard shortcut', async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsNone($, ".o-mail-Message");
|
||||
|
||||
await click("button:contains(Send message)");
|
||||
await contains(".o-mail-Message", 0);
|
||||
await insertText(".o-mail-Composer-input", "Test");
|
||||
await triggerHotkey("Enter");
|
||||
assert.containsNone($, ".o-mail-Message");
|
||||
triggerHotkey("Enter");
|
||||
// weak test, no guarantee that we waited long enough for the potential message to be posted
|
||||
await contains(".o-mail-Message", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"should not display subject when subject is the same as the thread name",
|
||||
async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({
|
||||
name: "Salutations, voyageur",
|
||||
});
|
||||
pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "res.partner",
|
||||
res_id: partnerId,
|
||||
subject: "Salutations, voyageur",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsNone($, ".o-mail-Message:contains(Salutations, voyageur)");
|
||||
}
|
||||
);
|
||||
QUnit.test("should not display subject when subject is the same as the thread name", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({
|
||||
name: "Salutations, voyageur",
|
||||
});
|
||||
pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "res.partner",
|
||||
res_id: partnerId,
|
||||
subject: "Salutations, voyageur",
|
||||
});
|
||||
const { openView } = await start();
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
await contains(".o-mail-Message:not(:contains(Salutations, voyageur))");
|
||||
});
|
||||
|
||||
QUnit.test("scroll position is kept when navigating from one record to another", async (assert) => {
|
||||
patchUiSize({ size: SIZES.XXL });
|
||||
@@ -472,20 +473,42 @@ QUnit.test("scroll position is kept when navigating from one record to another",
|
||||
}))
|
||||
);
|
||||
const { openFormView } = await start();
|
||||
await openFormView("res.partner", partnerId_1);
|
||||
openFormView("res.partner", partnerId_1);
|
||||
await contains(".o_breadcrumb:contains(Harry Potter)");
|
||||
await contains(".o-mail-Chatter");
|
||||
/**
|
||||
* The nextAnimationFrame is necessary because otherwise useAutoScroll would
|
||||
* set the scroll to bottom after the manually set value from this test.
|
||||
*/
|
||||
await nextAnimationFrame();
|
||||
const scrolltop_1 = $(".o-mail-Chatter")[0].scrollHeight / 2;
|
||||
$(".o-mail-Chatter")[0].scrollTo({ top: scrolltop_1 });
|
||||
await openFormView("res.partner", partnerId_2);
|
||||
openFormView("res.partner", partnerId_2);
|
||||
await contains(".o_breadcrumb:contains(Ron Weasley)");
|
||||
/**
|
||||
* The nextAnimationFrame is necessary because otherwise useAutoScroll would
|
||||
* set the scroll to bottom after the manually set value from this test.
|
||||
*/
|
||||
await nextAnimationFrame();
|
||||
const scrolltop_2 = $(".o-mail-Chatter")[0].scrollHeight / 3;
|
||||
$(".o-mail-Chatter")[0].scrollTo({ top: scrolltop_2 });
|
||||
await openFormView("res.partner", partnerId_1);
|
||||
openFormView("res.partner", partnerId_1);
|
||||
await contains(".o_breadcrumb:contains(Harry Potter)");
|
||||
/**
|
||||
* The nextAnimationFrame is necessary to give time for scroll to be restored.
|
||||
*/
|
||||
await nextAnimationFrame();
|
||||
assert.ok(isScrolledTo($(".o-mail-Chatter")[0], scrolltop_1));
|
||||
|
||||
await openFormView("res.partner", partnerId_2);
|
||||
openFormView("res.partner", partnerId_2);
|
||||
await contains(".o_breadcrumb:contains(Ron Weasley)");
|
||||
/**
|
||||
* The nextAnimationFrame is necessary to give time for scroll to be restored.
|
||||
*/
|
||||
await nextAnimationFrame();
|
||||
assert.ok(isScrolledTo($(".o-mail-Chatter")[0], scrolltop_2));
|
||||
});
|
||||
|
||||
QUnit.test("basic chatter rendering", async (assert) => {
|
||||
QUnit.test("basic chatter rendering", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ display_name: "second partner" });
|
||||
const views = {
|
||||
@@ -498,15 +521,15 @@ QUnit.test("basic chatter rendering", async (assert) => {
|
||||
</form>`,
|
||||
};
|
||||
const { openView } = await start({ serverData: { views } });
|
||||
await openView({
|
||||
openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Chatter");
|
||||
await contains(".o-mail-Chatter");
|
||||
});
|
||||
|
||||
QUnit.test("basic chatter rendering without activities", async (assert) => {
|
||||
QUnit.test("basic chatter rendering without activities", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ display_name: "second partner" });
|
||||
const views = {
|
||||
@@ -522,22 +545,22 @@ QUnit.test("basic chatter rendering without activities", async (assert) => {
|
||||
</form>`,
|
||||
};
|
||||
const { openView } = await start({ serverData: { views } });
|
||||
await openView({
|
||||
openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Chatter");
|
||||
assert.containsOnce($, ".o-mail-Chatter-topbar");
|
||||
assert.containsOnce($, "button[aria-label='Attach files']");
|
||||
assert.containsNone($, "button:contains(Activities)");
|
||||
assert.containsOnce($, ".o-mail-Followers");
|
||||
assert.containsOnce($, ".o-mail-Thread");
|
||||
await contains(".o-mail-Chatter");
|
||||
await contains(".o-mail-Chatter-topbar");
|
||||
await contains("button[aria-label='Attach files']");
|
||||
await contains("button:contains(Activities)", 0);
|
||||
await contains(".o-mail-Followers");
|
||||
await contains(".o-mail-Thread");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
'chatter just contains "creating a new record" message during the creation of a new record after having displayed a chatter for an existing record',
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const views = {
|
||||
@@ -552,20 +575,20 @@ QUnit.test(
|
||||
</form>`,
|
||||
};
|
||||
const { openView } = await start({ serverData: { views } });
|
||||
await openView({
|
||||
openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
await click(".o_form_button_create");
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsOnce($, ".o-mail-Message-body:contains(Creating a new record...)");
|
||||
await click(".o_form_button_create:eq(0)");
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message-body:contains(Creating a new record...)");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"should not display subject when subject is the same as the default subject",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const fakeId = pyEnv["res.fake"].create({ name: "Salutations, voyageur" });
|
||||
pyEnv["mail.message"].create({
|
||||
@@ -575,14 +598,14 @@ QUnit.test(
|
||||
subject: "Custom Default Subject", // default subject for res.fake, set on the model
|
||||
});
|
||||
const { openFormView } = await start();
|
||||
await openFormView("res.fake", fakeId);
|
||||
assert.containsNone($, ".o-mail-Message:contains(Custom Default Subject)");
|
||||
openFormView("res.fake", fakeId);
|
||||
await contains(".o-mail-Message:not(:contains(Custom Default Subject))");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"should not display subject when subject is the same as the thread name with custom default subject",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const fakeId = pyEnv["res.fake"].create({ name: "Salutations, voyageur" });
|
||||
pyEnv["mail.message"].create({
|
||||
@@ -592,8 +615,8 @@ QUnit.test(
|
||||
subject: "Salutations, voyageur",
|
||||
});
|
||||
const { openFormView } = await start();
|
||||
await openFormView("res.fake", fakeId);
|
||||
assert.containsNone($, ".o-mail-Message:contains(Custom Default Subject)");
|
||||
openFormView("res.fake", fakeId);
|
||||
await contains(".o-mail-Message:not(:contains(Custom Default Subject))");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -613,21 +636,21 @@ QUnit.test("basic chatter rendering without followers", async (assert) => {
|
||||
</form>`,
|
||||
};
|
||||
const { openView } = await start({ serverData: { views } });
|
||||
await openView({
|
||||
openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Chatter");
|
||||
assert.containsOnce($, ".o-mail-Chatter-topbar");
|
||||
assert.containsOnce($, "button[aria-label='Attach files']");
|
||||
assert.containsOnce($, "button:contains(Activities)");
|
||||
await contains(".o-mail-Chatter");
|
||||
await contains(".o-mail-Chatter-topbar");
|
||||
await contains("button[aria-label='Attach files']");
|
||||
await contains("button:contains(Activities)");
|
||||
assert.containsNone(
|
||||
$,
|
||||
".o-mail-Followers",
|
||||
"there should be no followers menu because the 'message_follower_ids' field is not present in 'oe_chatter'"
|
||||
);
|
||||
assert.containsOnce($, ".o-mail-Chatter .o-mail-Thread");
|
||||
await contains(".o-mail-Chatter .o-mail-Thread");
|
||||
});
|
||||
|
||||
QUnit.test("basic chatter rendering without messages", async (assert) => {
|
||||
@@ -646,16 +669,16 @@ QUnit.test("basic chatter rendering without messages", async (assert) => {
|
||||
</form>`,
|
||||
};
|
||||
const { openView } = await start({ serverData: { views } });
|
||||
await openView({
|
||||
openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Chatter");
|
||||
assert.containsOnce($, ".o-mail-Chatter-topbar");
|
||||
assert.containsOnce($, "button[aria-label='Attach files']");
|
||||
assert.containsOnce($, "button:contains(Activities)");
|
||||
assert.containsOnce($, ".o-mail-Followers");
|
||||
await contains(".o-mail-Chatter");
|
||||
await contains(".o-mail-Chatter-topbar");
|
||||
await contains("button[aria-label='Attach files']");
|
||||
await contains("button:contains(Activities)");
|
||||
await contains(".o-mail-Followers");
|
||||
assert.containsNone(
|
||||
$,
|
||||
".o-mail-Chatter .o-mail-Thread",
|
||||
@@ -686,14 +709,14 @@ QUnit.test("chatter updating", async (assert) => {
|
||||
</form>`,
|
||||
};
|
||||
const { openFormView } = await start({ serverData: { views } });
|
||||
await openFormView("res.partner", partnerId_1, {
|
||||
openFormView("res.partner", partnerId_1, {
|
||||
props: { resIds: [partnerId_1, partnerId_2] },
|
||||
});
|
||||
await click(".o_pager_next");
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
await contains(".o-mail-Message");
|
||||
});
|
||||
|
||||
QUnit.test("post message on draft record", async (assert) => {
|
||||
QUnit.test("post message on draft record", async () => {
|
||||
const views = {
|
||||
"res.partner,false,form": `
|
||||
<form string="Partners">
|
||||
@@ -706,20 +729,20 @@ QUnit.test("post message on draft record", async (assert) => {
|
||||
</form>`,
|
||||
};
|
||||
const { openView } = await start({ serverData: { views } });
|
||||
await openView({
|
||||
openView({
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
await click("button:contains(Send message)");
|
||||
await editInput(document.body, ".o-mail-Composer-input", "Test");
|
||||
await click(".o-mail-Composer button:contains(Send)");
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsOnce($, ".o-mail-Message:contains(Test)");
|
||||
await insertText(".o-mail-Composer-input", "Test");
|
||||
await click(".o-mail-Composer button:contains(Send):not(:disabled)");
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message:contains(Test)");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"schedule activities on draft record should prompt with scheduling an activity (proceed with action)",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const views = {
|
||||
"res.partner,false,form": `
|
||||
<form string="Partners">
|
||||
@@ -731,14 +754,14 @@ QUnit.test(
|
||||
</div>
|
||||
</form>`,
|
||||
};
|
||||
const { openView } = await start({ serverData: { views } });
|
||||
await openView({ res_model: "res.partner", views: [[false, "form"]] });
|
||||
const { openFormView } = await start({ serverData: { views } });
|
||||
openFormView("res.partner");
|
||||
await click("button:contains(Activities)");
|
||||
assert.containsOnce($, ".o_dialog:contains(Schedule Activity)");
|
||||
await contains(".o_dialog:contains(Schedule Activity)");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("upload attachment on draft record", async (assert) => {
|
||||
QUnit.test("upload attachment on draft record", async () => {
|
||||
const views = {
|
||||
"res.partner,false,form": `
|
||||
<form string="Partners">
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import {
|
||||
afterNextRender,
|
||||
click,
|
||||
contains,
|
||||
nextAnimationFrame,
|
||||
start,
|
||||
startServer,
|
||||
waitUntil,
|
||||
} from "@mail/../tests/helpers/test_utils";
|
||||
import { DELAY_FOR_SPINNER } from "@mail/core/web/chatter";
|
||||
|
||||
@@ -14,22 +13,21 @@ import { makeDeferred } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("chatter topbar");
|
||||
|
||||
QUnit.test("base rendering", async (assert) => {
|
||||
QUnit.test("base rendering", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
|
||||
assert.containsOnce($, ".o-mail-Chatter-topbar");
|
||||
assert.containsOnce($, "button:contains(Send message)");
|
||||
assert.containsOnce($, "button:contains(Log note)");
|
||||
assert.containsOnce($, "button:contains(Activities)");
|
||||
assert.containsOnce($, "button[aria-label='Attach files']");
|
||||
assert.containsOnce($, ".o-mail-Followers");
|
||||
await contains(".o-mail-Chatter-topbar");
|
||||
await contains("button:contains(Send message)");
|
||||
await contains("button:contains(Log note)");
|
||||
await contains("button:contains(Activities)");
|
||||
await contains("button[aria-label='Attach files']");
|
||||
await contains(".o-mail-Followers");
|
||||
});
|
||||
|
||||
QUnit.test("rendering with multiple partner followers", async (assert) => {
|
||||
@@ -52,109 +50,106 @@ QUnit.test("rendering with multiple partner followers", async (assert) => {
|
||||
},
|
||||
]);
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId_3,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
|
||||
assert.containsOnce($, ".o-mail-Followers");
|
||||
assert.containsOnce($, ".o-mail-Followers-button");
|
||||
await contains(".o-mail-Followers");
|
||||
await contains(".o-mail-Followers-button");
|
||||
|
||||
await click(".o-mail-Followers-button");
|
||||
assert.containsOnce($, ".o-mail-Followers-dropdown");
|
||||
assert.containsN($, ".o-mail-Follower", 2);
|
||||
await contains(".o-mail-Followers-dropdown");
|
||||
await contains(".o-mail-Follower", 2);
|
||||
assert.strictEqual($(".o-mail-Follower:eq(0)").text().trim(), "Jean Michang");
|
||||
assert.strictEqual($(".o-mail-Follower:eq(1)").text().trim(), "Eden Hazard");
|
||||
});
|
||||
|
||||
QUnit.test("log note toggling", async (assert) => {
|
||||
QUnit.test("log note toggling", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, "button:contains(Log note)");
|
||||
assert.doesNotHaveClass($("button:contains(Log note)"), "active");
|
||||
assert.containsNone($, ".o-mail-Composer");
|
||||
await contains("button:contains(Log note)");
|
||||
await contains("button:contains(Log note):not(.active)");
|
||||
await contains(".o-mail-Composer", 0);
|
||||
|
||||
await click("button:contains(Log note)");
|
||||
assert.hasClass($("button:contains(Log note)"), "active");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o-mail-Composer .o-mail-Composer-input[placeholder='Log an internal note...']"
|
||||
);
|
||||
await contains("button:contains(Log note).active");
|
||||
await contains(".o-mail-Composer .o-mail-Composer-input[placeholder='Log an internal note…']");
|
||||
|
||||
await click("button:contains(Log note)");
|
||||
assert.doesNotHaveClass($("button:contains(Log note)"), "active");
|
||||
assert.containsNone($, ".o-mail-Composer");
|
||||
await contains("button:contains(Log note):not(.active)");
|
||||
await contains(".o-mail-Composer", 0);
|
||||
});
|
||||
|
||||
QUnit.test("send message toggling", async (assert) => {
|
||||
QUnit.test("send message toggling", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, "button:contains(Send message)");
|
||||
assert.doesNotHaveClass($("button:contains(Send message)"), "active");
|
||||
assert.containsNone($, ".o-mail-Composer");
|
||||
await contains("button:contains(Send message)");
|
||||
await contains("button:contains(Send message):not(.active)");
|
||||
await contains(".o-mail-Composer", 0);
|
||||
|
||||
await click("button:contains(Send message)");
|
||||
assert.hasClass($("button:contains(Send message)"), "active");
|
||||
assert.containsOnce($, ".o-mail-Composer-input[placeholder='Send a message to followers...']");
|
||||
await contains("button:contains(Send message).active");
|
||||
await contains(".o-mail-Composer-input[placeholder='Send a message to followers…']");
|
||||
|
||||
await click("button:contains(Send message)");
|
||||
assert.doesNotHaveClass($("button:contains(Send message)"), "active");
|
||||
assert.containsNone($, ".o-mail-Composer");
|
||||
await contains("button:contains(Send message):not(.active)");
|
||||
await contains(".o-mail-Composer", 0);
|
||||
});
|
||||
|
||||
QUnit.test("log note/send message switching", async (assert) => {
|
||||
QUnit.test("log note/send message switching", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, "button:contains(Send message)");
|
||||
assert.doesNotHaveClass($("button:contains(Send message)"), "active");
|
||||
assert.containsOnce($, "button:contains(Log note)");
|
||||
assert.doesNotHaveClass($("button:contains(Log note)"), "active");
|
||||
assert.containsNone($, ".o-mail-Composer");
|
||||
await contains("button:contains(Send message)");
|
||||
await contains("button:contains(Send message):not(.active)");
|
||||
await contains("button:contains(Log note)");
|
||||
await contains("button:contains(Log note):not(.active)");
|
||||
await contains(".o-mail-Composer", 0);
|
||||
|
||||
await click("button:contains(Send message)");
|
||||
assert.hasClass($("button:contains(Send message)"), "active");
|
||||
assert.doesNotHaveClass($("button:contains(Log note)"), "active");
|
||||
assert.containsOnce($, ".o-mail-Composer-input[placeholder='Send a message to followers...']");
|
||||
await contains("button:contains(Send message).active");
|
||||
await contains("button:contains(Log note):not(.active)");
|
||||
await contains(".o-mail-Composer-input[placeholder='Send a message to followers…']");
|
||||
|
||||
await click("button:contains(Log note)");
|
||||
assert.doesNotHaveClass($("button:contains(Send message)"), "active");
|
||||
assert.hasClass($("button:contains(Log note)"), "active");
|
||||
assert.containsOnce($, ".o-mail-Composer-input[placeholder='Log an internal note...']");
|
||||
await contains("button:contains(Send message):not(.active)");
|
||||
await contains("button:contains(Log note).active");
|
||||
await contains(".o-mail-Composer-input[placeholder='Log an internal note…']");
|
||||
});
|
||||
|
||||
QUnit.test("attachment counter without attachments", async (assert) => {
|
||||
QUnit.test("attachment counter without attachments", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, "button[aria-label='Attach files']");
|
||||
assert.containsNone($, "button[aria-label='Attach files']:contains(0)");
|
||||
await contains("button[aria-label='Attach files']");
|
||||
await contains("button[aria-label='Attach files']:contains(0)", 0);
|
||||
});
|
||||
|
||||
QUnit.test("attachment counter with attachments", async (assert) => {
|
||||
QUnit.test("attachment counter with attachments", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
pyEnv["ir.attachment"].create([
|
||||
@@ -172,15 +167,15 @@ QUnit.test("attachment counter with attachments", async (assert) => {
|
||||
},
|
||||
]);
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, "button[aria-label='Attach files']:contains(2)");
|
||||
await contains("button[aria-label='Attach files']:contains(2)");
|
||||
});
|
||||
|
||||
QUnit.test("attachment counter while loading attachments", async (assert) => {
|
||||
QUnit.test("attachment counter while loading attachments", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const { advanceTime, openView } = await start({
|
||||
@@ -191,17 +186,18 @@ QUnit.test("attachment counter while loading attachments", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
await contains("button[aria-label='Attach files']");
|
||||
await advanceTime(DELAY_FOR_SPINNER);
|
||||
await waitUntil("button[aria-label='Attach files'] .fa-spin");
|
||||
assert.containsNone($, "button[aria-label='Attach files']:contains(0)");
|
||||
await contains("button[aria-label='Attach files'] .fa-spin");
|
||||
await contains("button[aria-label='Attach files']:contains(0)", 0);
|
||||
});
|
||||
|
||||
QUnit.test("attachment counter transition when attachments become loaded", async (assert) => {
|
||||
QUnit.test("attachment counter transition when attachments become loaded", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const deferred = makeDeferred();
|
||||
@@ -213,37 +209,37 @@ QUnit.test("attachment counter transition when attachments become loaded", async
|
||||
}
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
await contains("button[aria-label='Attach files']");
|
||||
await advanceTime(DELAY_FOR_SPINNER);
|
||||
await waitUntil("button[aria-label='Attach files'] .fa-spin");
|
||||
|
||||
await afterNextRender(() => deferred.resolve());
|
||||
assert.containsNone($, "button[aria-label='Attach files'] .fa-spin");
|
||||
await contains("button[aria-label='Attach files'] .fa-spin");
|
||||
deferred.resolve();
|
||||
await contains("button[aria-label='Attach files'] .fa-spin", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"attachment icon open directly the file uploader if there is no attachment yet",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Chatter-fileUploader");
|
||||
assert.containsNone($, ".o-mail-AttachmentBox");
|
||||
await contains(".o-mail-Chatter-fileUploader");
|
||||
await contains(".o-mail-AttachmentBox", 0);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"attachment icon open the attachment box when there is at least 1 attachment",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
pyEnv["ir.attachment"].create([
|
||||
@@ -255,33 +251,36 @@ QUnit.test(
|
||||
},
|
||||
]);
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsNone($, ".o-mail-Chatter-fileUploader");
|
||||
await contains("button[aria-label='Attach files']");
|
||||
await contains(".o-mail-AttachmentBox", 0);
|
||||
await contains(".o-mail-Chatter-fileUploader", 0);
|
||||
await click("button[aria-label='Attach files']");
|
||||
assert.containsOnce($, ".o-mail-AttachmentBox");
|
||||
await contains(".o-mail-AttachmentBox");
|
||||
await contains(".o-mail-Chatter-fileUploader");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("composer state conserved when clicking on another topbar button", async (assert) => {
|
||||
QUnit.test("composer state conserved when clicking on another topbar button", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const { openFormView } = await start();
|
||||
await openFormView("res.partner", partnerId);
|
||||
assert.containsOnce($, ".o-mail-Chatter-topbar");
|
||||
assert.containsOnce($, "button:contains(Send message)");
|
||||
assert.containsOnce($, "button:contains(Log note)");
|
||||
assert.containsOnce($, "button[aria-label='Attach files']");
|
||||
await contains(".o-mail-Chatter-topbar");
|
||||
await contains("button:contains(Send message)");
|
||||
await contains("button:contains(Log note)");
|
||||
await contains("button[aria-label='Attach files']");
|
||||
|
||||
await click("button:contains(Log note)");
|
||||
assert.containsOnce($, "button:contains(Log note).active");
|
||||
assert.containsNone($, "button:contains(Send message).active");
|
||||
await contains("button:contains(Log note).active");
|
||||
await contains("button:contains(Send message).active", 0);
|
||||
|
||||
$(`button[aria-label='Attach files']`)[0].click();
|
||||
await nextAnimationFrame();
|
||||
assert.containsOnce($, "button:contains(Log note).active");
|
||||
assert.containsNone($, "button:contains(Send message).active");
|
||||
await contains("button:contains(Log note).active");
|
||||
await contains("button:contains(Send message).active", 0);
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Avatar } from "@mail/views/web/fields/avatar/avatar";
|
||||
import { click, start } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { getFixture, mount } from "@web/../tests/helpers/utils";
|
||||
|
||||
@@ -17,13 +17,13 @@ QUnit.test("basic rendering", async (assert) => {
|
||||
displayName: "User display name",
|
||||
},
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Avatar");
|
||||
assert.containsOnce($, ".o-mail-Avatar img");
|
||||
await contains(".o-mail-Avatar");
|
||||
await contains(".o-mail-Avatar img");
|
||||
assert.strictEqual($(".o-mail-Avatar img")[0].dataset.src, "/web/image/res.users/2/avatar_128");
|
||||
assert.containsOnce($, ".o-mail-Avatar span");
|
||||
await contains(".o-mail-Avatar span");
|
||||
assert.strictEqual($(".o-mail-Avatar span")[0].innerText, "User display name");
|
||||
assert.containsNone($, ".o-mail-ChatWindow");
|
||||
|
||||
await click(".o-mail-Avatar img");
|
||||
assert.containsOnce($, ".o-mail-ChatWindow");
|
||||
await contains(".o-mail-ChatWindow");
|
||||
});
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { afterNextRender, click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
QUnit.module("follow button");
|
||||
|
||||
QUnit.test("base rendering not editable", async (assert) => {
|
||||
QUnit.test("base rendering not editable", async () => {
|
||||
const { openView, pyEnv } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: pyEnv.currentPartnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Chatter-follow");
|
||||
await contains(".o-mail-Chatter-follow");
|
||||
});
|
||||
|
||||
QUnit.test("hover following button", async (assert) => {
|
||||
QUnit.test("hover following button", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const threadId = pyEnv["res.partner"].create({});
|
||||
pyEnv["mail.followers"].create({
|
||||
@@ -24,37 +24,35 @@ QUnit.test("hover following button", async (assert) => {
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: threadId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, "button:contains(Following)");
|
||||
assert.containsNone($, ".fa-times + span:contains(Following)");
|
||||
assert.containsOnce($, ".fa-check + span:contains(Following)");
|
||||
await contains("button:contains(Following)");
|
||||
await contains(".fa-times + span:contains(Following)", 0);
|
||||
await contains(".fa-check + span:contains(Following)");
|
||||
|
||||
await afterNextRender(() => {
|
||||
$("button:contains(Following)")[0].dispatchEvent(new window.MouseEvent("mouseenter"));
|
||||
});
|
||||
assert.containsOnce($, "button:contains(Unfollow)");
|
||||
assert.containsOnce($, ".fa-times + span:contains(Unfollow)");
|
||||
assert.containsNone($, ".fa-check + span:contains(Unfollow)");
|
||||
$("button:contains(Following)")[0].dispatchEvent(new window.MouseEvent("mouseenter"));
|
||||
await contains("button:contains(Unfollow)");
|
||||
await contains(".fa-times + span:contains(Unfollow)");
|
||||
await contains(".fa-check + span:contains(Unfollow)", 0);
|
||||
});
|
||||
|
||||
QUnit.test('click on "follow" button', async (assert) => {
|
||||
QUnit.test('click on "follow" button', async () => {
|
||||
const { openView, pyEnv } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: pyEnv.currentPartnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, "button:contains(Follow)");
|
||||
await contains("button:contains(Follow)");
|
||||
|
||||
await click("button:contains(Follow)");
|
||||
assert.containsOnce($, "button:contains(Following)");
|
||||
await contains("button:contains(Following)");
|
||||
});
|
||||
|
||||
QUnit.test('Click on "follow" button should save draft record', async (assert) => {
|
||||
QUnit.test('Click on "follow" button should save draft record', async () => {
|
||||
const views = {
|
||||
"res.partner,false,form": `
|
||||
<form string="Partners">
|
||||
@@ -67,15 +65,14 @@ QUnit.test('Click on "follow" button should save draft record', async (assert) =
|
||||
</form>`,
|
||||
};
|
||||
const { openFormView } = await start({ serverData: { views } });
|
||||
await openFormView("res.partner");
|
||||
assert.containsOnce($, "button:contains(Follow)");
|
||||
assert.containsOnce($, "div.o_field_char");
|
||||
|
||||
openFormView("res.partner");
|
||||
await contains("button:contains(Follow)");
|
||||
await contains("div.o_field_char");
|
||||
await click("button:contains(Follow)");
|
||||
assert.containsOnce($, "div.o_field_invalid");
|
||||
await contains("div.o_field_invalid");
|
||||
});
|
||||
|
||||
QUnit.test('click on "unfollow" button', async (assert) => {
|
||||
QUnit.test('click on "unfollow" button', async () => {
|
||||
const pyEnv = await startServer();
|
||||
const threadId = pyEnv["res.partner"].create({});
|
||||
pyEnv["mail.followers"].create({
|
||||
@@ -85,13 +82,11 @@ QUnit.test('click on "unfollow" button', async (assert) => {
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: threadId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, "button:contains(Following)");
|
||||
|
||||
await click("button:contains(Following)");
|
||||
assert.containsOnce($, "button:contains(Follow)");
|
||||
await contains("button:contains(Follow)");
|
||||
});
|
||||
|
||||
@@ -1,29 +1,31 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { afterNextRender, click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import {
|
||||
click,
|
||||
contains,
|
||||
nextAnimationFrame,
|
||||
start,
|
||||
startServer,
|
||||
} from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
import { nextTick } from "@web/../tests/legacy/helpers/test_utils";
|
||||
|
||||
QUnit.module("follower list menu");
|
||||
|
||||
QUnit.test("base rendering not editable", async (assert) => {
|
||||
QUnit.test("base rendering not editable", async () => {
|
||||
const { openView } = await start();
|
||||
await openView(
|
||||
openView(
|
||||
{
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
},
|
||||
{ mode: "edit" }
|
||||
);
|
||||
assert.containsOnce($, ".o-mail-Followers");
|
||||
assert.containsOnce($, ".o-mail-Followers-button");
|
||||
assert.ok($(".o-mail-Followers-button")[0].disabled);
|
||||
assert.containsNone($, ".o-mail-Followers-dropdown");
|
||||
|
||||
$(".o-mail-Followers-button")[0].click();
|
||||
await nextTick();
|
||||
assert.containsNone($, ".o-mail-Followers-dropdown");
|
||||
await contains(".o-mail-Followers");
|
||||
await contains(".o-mail-Followers-button:disabled");
|
||||
await contains(".o-mail-Followers-dropdown", 0);
|
||||
await click(".o-mail-Followers-button");
|
||||
await contains(".o-mail-Followers-dropdown", 0);
|
||||
});
|
||||
|
||||
QUnit.test("base rendering editable", async (assert) => {
|
||||
@@ -39,18 +41,18 @@ QUnit.test("base rendering editable", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Followers");
|
||||
assert.containsOnce($, ".o-mail-Followers-button");
|
||||
await contains(".o-mail-Followers");
|
||||
await contains(".o-mail-Followers-button");
|
||||
assert.notOk($(".o-mail-Followers-button")[0].disabled);
|
||||
assert.containsNone($, ".o-mail-Followers-dropdown");
|
||||
await contains(".o-mail-Followers-dropdown", 0);
|
||||
|
||||
await click(".o-mail-Followers-button");
|
||||
assert.containsOnce($, ".o-mail-Followers-dropdown");
|
||||
await contains(".o-mail-Followers-dropdown");
|
||||
});
|
||||
|
||||
QUnit.test('click on "add followers" button', async (assert) => {
|
||||
@@ -78,7 +80,7 @@ QUnit.test('click on "add followers" button', async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId_1,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
@@ -102,21 +104,21 @@ QUnit.test('click on "add followers" button', async (assert) => {
|
||||
},
|
||||
});
|
||||
|
||||
assert.containsOnce($, ".o-mail-Followers");
|
||||
assert.containsOnce($, ".o-mail-Followers-button");
|
||||
await contains(".o-mail-Followers");
|
||||
await contains(".o-mail-Followers-button");
|
||||
assert.strictEqual($(".o-mail-Followers-counter").text(), "1");
|
||||
|
||||
await click(".o-mail-Followers-button");
|
||||
assert.containsOnce($, ".o-mail-Followers-dropdown");
|
||||
assert.containsOnce($, "a:contains(Add Followers)");
|
||||
await contains(".o-mail-Followers-dropdown");
|
||||
await contains("a:contains(Add Followers)");
|
||||
|
||||
await click("a:contains(Add Followers)");
|
||||
assert.containsNone($, ".o-mail-Followers-dropdown");
|
||||
await contains(".o-mail-Followers-dropdown", 0);
|
||||
assert.verifySteps(["action:open_view"]);
|
||||
assert.strictEqual($(".o-mail-Followers-counter").text(), "2");
|
||||
|
||||
await click(".o-mail-Followers-button");
|
||||
assert.containsN($, ".o-mail-Follower", 2);
|
||||
await contains(".o-mail-Follower", 2);
|
||||
assert.strictEqual($(".o-mail-Follower").text(), "François PerussePartner3");
|
||||
});
|
||||
|
||||
@@ -148,24 +150,24 @@ QUnit.test("click on remove follower", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId_1,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
|
||||
await click(".o-mail-Followers-button");
|
||||
assert.containsOnce($, ".o-mail-Follower");
|
||||
assert.containsOnce($, "button[title='Remove this follower']");
|
||||
await contains(".o-mail-Follower");
|
||||
await contains("button[title='Remove this follower']");
|
||||
|
||||
await click("button[title='Remove this follower']");
|
||||
assert.verifySteps(["message_unsubscribe"]);
|
||||
assert.containsNone($, ".o-mail-Follower");
|
||||
await contains(".o-mail-Follower", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
'Hide "Add follower" and subtypes edition/removal buttons except own user on read only record',
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const [partnerId_1, partnerId_2] = pyEnv["res.partner"].create([
|
||||
{ name: "Partner1" },
|
||||
@@ -195,23 +197,22 @@ QUnit.test(
|
||||
}
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId_1,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
|
||||
await click(".o-mail-Followers-button");
|
||||
assert.containsNone($, "a:contains(Add Followers)");
|
||||
const $followers = $(".o-mail-Follower");
|
||||
assert.containsOnce($followers[0], "button[title='Edit subscription']");
|
||||
assert.containsOnce($followers[0], "button[title='Remove this follower']");
|
||||
assert.containsNone($followers[1], "button[title='Edit subscription']");
|
||||
assert.containsNone($followers[1], "button[title='Remove this follower']");
|
||||
await contains("a:contains(Add Followers)", 0);
|
||||
await contains(".o-mail-Follower:eq(0) button[title='Edit subscription']");
|
||||
await contains(".o-mail-Follower:eq(0) button[title='Remove this follower']");
|
||||
await contains(".o-mail-Follower:eq(1):not(:has(button[title='Edit subscription']))");
|
||||
await contains(".o-mail-Follower:eq(1):not(:has(button[title='Remove this follower']))");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("Load 100 followers at once", async (assert) => {
|
||||
QUnit.test("Load 100 followers at once", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerIds = pyEnv["res.partner"].create(
|
||||
[...Array(210).keys()].map((i) => ({ display_name: `Partner${i}`, name: `Partner${i}` }))
|
||||
@@ -228,22 +229,17 @@ QUnit.test("Load 100 followers at once", async (assert) => {
|
||||
);
|
||||
const { openFormView } = await start();
|
||||
await openFormView("res.partner", partnerIds[0]);
|
||||
assert.containsOnce($, "button[title='Show Followers']:contains(210)");
|
||||
await contains("button[title='Show Followers']:contains(210)");
|
||||
|
||||
await click("button[title='Show Followers']");
|
||||
assert.containsOnce($, ".o-mail-Follower:contains(Mitchell Admin)");
|
||||
assert.containsN($, ".o-mail-Follower", 100);
|
||||
assert.containsOnce($, ".o-mail-Followers-dropdown span:contains(Load more)");
|
||||
await afterNextRender(() =>
|
||||
$(".o-mail-Followers-dropdown span:contains(Load more)")[0].scrollIntoView()
|
||||
);
|
||||
assert.containsN($, ".o-mail-Follower", 200);
|
||||
assert.containsOnce($, ".o-mail-Followers-dropdown span:contains(Load more)");
|
||||
await afterNextRender(() =>
|
||||
$(".o-mail-Followers-dropdown span:contains(Load more)")[0].scrollIntoView()
|
||||
);
|
||||
assert.containsN($, ".o-mail-Follower", 210);
|
||||
assert.containsNone($, ".o-mail-Followers-dropdown span:contains(Load more)");
|
||||
await contains(".o-mail-Follower:contains(Mitchell Admin)");
|
||||
await contains(".o-mail-Follower", 100);
|
||||
$(".o-mail-Followers-dropdown span:contains(Load more)")[0].scrollIntoView();
|
||||
await contains(".o-mail-Follower", 200);
|
||||
await nextAnimationFrame(); // give enough time for the Load more button to scroll out of view
|
||||
$(".o-mail-Followers-dropdown span:contains(Load more)")[0].scrollIntoView();
|
||||
await contains(".o-mail-Follower", 210);
|
||||
await contains(".o-mail-Followers-dropdown span:contains(Load more)", 0);
|
||||
});
|
||||
|
||||
QUnit.test("Load 100 recipients at once", async (assert) => {
|
||||
@@ -267,26 +263,18 @@ QUnit.test("Load 100 recipients at once", async (assert) => {
|
||||
);
|
||||
const { openFormView } = await start();
|
||||
await openFormView("res.partner", partnerIds[0]);
|
||||
assert.containsOnce($, "button[title='Show Followers']:contains(210)");
|
||||
await contains("button[title='Show Followers']:contains(210)");
|
||||
await click("button:contains(Send message)");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o-mail-Chatter:contains('me, partner1, partner2, partner3, partner4, …')"
|
||||
);
|
||||
assert.containsOnce($, "button[title='Show all recipients']");
|
||||
await contains(".o-mail-Chatter:contains('me, partner1, partner2, partner3, partner4, …')");
|
||||
await contains("button[title='Show all recipients']");
|
||||
await click("button[title='Show all recipients']");
|
||||
assert.containsN($, ".o-mail-RecipientList li", 100);
|
||||
assert.containsOnce($, ".o-mail-RecipientList span:contains(Load more)");
|
||||
await afterNextRender(() =>
|
||||
$(".o-mail-RecipientList span:contains(Load more)")[0].scrollIntoView()
|
||||
);
|
||||
assert.containsN($, ".o-mail-RecipientList li", 200);
|
||||
assert.containsOnce($, ".o-mail-RecipientList span:contains(Load more)");
|
||||
await afterNextRender(() =>
|
||||
$(".o-mail-RecipientList span:contains(Load more)")[0].scrollIntoView()
|
||||
);
|
||||
assert.containsN($, ".o-mail-RecipientList li", 210);
|
||||
assert.containsNone($, ".o-mail-RecipientList span:contains(Load more)");
|
||||
await contains(".o-mail-RecipientList li", 100);
|
||||
$(".o-mail-RecipientList span:contains(Load more)")[0].scrollIntoView();
|
||||
await contains(".o-mail-RecipientList li", 200);
|
||||
await nextAnimationFrame(); // give enough time for the Load more button to scroll out of view
|
||||
$(".o-mail-RecipientList span:contains(Load more)")[0].scrollIntoView();
|
||||
await contains(".o-mail-RecipientList li", 210);
|
||||
await contains(".o-mail-RecipientList span:contains(Load more)", 0);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
@@ -321,14 +309,14 @@ QUnit.test(
|
||||
}
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId_1,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
|
||||
await click(".o-mail-Followers-button");
|
||||
assert.containsOnce($, "a:contains(Add Followers)");
|
||||
await contains("a:contains(Add Followers)");
|
||||
const $followers = $(".o-mail-Follower");
|
||||
assert.containsOnce($followers[0], "button[title='Edit subscription']");
|
||||
assert.containsOnce($followers[0], "button[title='Remove this follower']");
|
||||
@@ -352,13 +340,13 @@ QUnit.test(
|
||||
}
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
|
||||
await click(".o-mail-Followers-button");
|
||||
assert.containsOnce($, "div:contains(No Followers).disabled");
|
||||
await contains("div:contains(No Followers).disabled");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { makeFakeNotificationService } from "@web/../tests/helpers/mock_services";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
QUnit.module("follower subtype");
|
||||
|
||||
QUnit.test("simplest layout of a followed subtype", async (assert) => {
|
||||
QUnit.test("simplest layout of a followed subtype", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const subtypeId = pyEnv["mail.message.subtype"].create({
|
||||
default: true,
|
||||
@@ -31,128 +29,114 @@ QUnit.test("simplest layout of a followed subtype", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
openView({
|
||||
res_model: "res.partner",
|
||||
res_id: pyEnv.currentPartnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
await click(".o-mail-Followers-button");
|
||||
await click("button[title='Edit subscription']");
|
||||
assert.containsOnce($, ".o-mail-FollowerSubtypeDialog-subtype:contains(TestSubtype)");
|
||||
assert.containsOnce($(".o-mail-FollowerSubtypeDialog-subtype:contains(TestSubtype)"), "label");
|
||||
assert.containsOnce(
|
||||
$(".o-mail-FollowerSubtypeDialog-subtype:contains(TestSubtype)"),
|
||||
"input[type='checkbox']"
|
||||
await contains(
|
||||
`.o-mail-FollowerSubtypeDialog-subtype[data-follower-subtype-id=${subtypeId}] label:contains(TestSubtype)`
|
||||
);
|
||||
assert.strictEqual(
|
||||
$(".o-mail-FollowerSubtypeDialog-subtype:contains(TestSubtype) label").text(),
|
||||
"TestSubtype"
|
||||
);
|
||||
assert.ok(
|
||||
$(".o-mail-FollowerSubtypeDialog-subtype:contains(TestSubtype) input[type='checkbox']")[0]
|
||||
.checked
|
||||
await contains(
|
||||
$(
|
||||
`.o-mail-FollowerSubtypeDialog-subtype[data-follower-subtype-id=${subtypeId}] input[type='checkbox']:checked`
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("simplest layout of a not followed subtype", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.message.subtype"].create({
|
||||
default: true,
|
||||
name: "TestSubtype",
|
||||
});
|
||||
const followerId = pyEnv["mail.followers"].create({
|
||||
display_name: "François Perusse",
|
||||
partner_id: pyEnv.currentPartnerId,
|
||||
res_model: "res.partner",
|
||||
res_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
pyEnv["res.partner"].write([pyEnv.currentPartnerId], { message_follower_ids: [followerId] });
|
||||
const { openView } = await start({
|
||||
// FIXME: should adapt mock server code to provide "hasWriteAccess"
|
||||
async mockRPC(route, args, performRPC) {
|
||||
if (route === "/mail/thread/data") {
|
||||
// mimic user with write access
|
||||
const res = await performRPC(...arguments);
|
||||
res["hasWriteAccess"] = true;
|
||||
return res;
|
||||
}
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
res_model: "res.partner",
|
||||
res_id: pyEnv.currentPartnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
await click(".o-mail-Followers-button");
|
||||
await click("button[title='Edit subscription']");
|
||||
assert.notOk(
|
||||
$(".o-mail-FollowerSubtypeDialog-subtype:contains(TestSubtype) input[type='checkbox']")[0]
|
||||
.checked,
|
||||
"checkbox should not be checked as follower subtype is not followed"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("toggle follower subtype checkbox", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.message.subtype"].create({
|
||||
default: true,
|
||||
name: "TestSubtype",
|
||||
});
|
||||
const followerId = pyEnv["mail.followers"].create({
|
||||
display_name: "François Perusse",
|
||||
partner_id: pyEnv.currentPartnerId,
|
||||
res_model: "res.partner",
|
||||
res_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
pyEnv["res.partner"].write([pyEnv.currentPartnerId], { message_follower_ids: [followerId] });
|
||||
const { openView } = await start({
|
||||
// FIXME: should adapt mock server code to provide "hasWriteAccess"
|
||||
async mockRPC(route, args, performRPC) {
|
||||
if (route === "/mail/thread/data") {
|
||||
// mimic user with write access
|
||||
const res = await performRPC(...arguments);
|
||||
res["hasWriteAccess"] = true;
|
||||
return res;
|
||||
}
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
res_model: "res.partner",
|
||||
res_id: pyEnv.currentPartnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
await click(".o-mail-Followers-button");
|
||||
await click("button[title='Edit subscription']");
|
||||
assert.notOk(
|
||||
$(".o-mail-FollowerSubtypeDialog-subtype:contains(TestSubtype) input[type='checkbox']")[0]
|
||||
.checked,
|
||||
"checkbox should not be checked as follower subtype is not followed"
|
||||
);
|
||||
|
||||
await click(
|
||||
".o-mail-FollowerSubtypeDialog-subtype:contains(TestSubtype) input[type='checkbox']"
|
||||
);
|
||||
assert.ok(
|
||||
$(".o-mail-FollowerSubtypeDialog-subtype:contains(TestSubtype) input[type='checkbox']")[0]
|
||||
.checked
|
||||
);
|
||||
|
||||
await click(
|
||||
".o-mail-FollowerSubtypeDialog-subtype:contains(TestSubtype) input[type='checkbox']"
|
||||
);
|
||||
assert.notOk(
|
||||
$(".o-mail-FollowerSubtypeDialog-subtype:contains(TestSubtype) input[type='checkbox']")[0]
|
||||
.checked
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("follower subtype apply", async (assert) => {
|
||||
QUnit.test("simplest layout of a not followed subtype", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const subtypeId = pyEnv["mail.message.subtype"].create({
|
||||
default: true,
|
||||
name: "TestSubtype",
|
||||
});
|
||||
const followerId = pyEnv["mail.followers"].create({
|
||||
display_name: "François Perusse",
|
||||
partner_id: pyEnv.currentPartnerId,
|
||||
res_model: "res.partner",
|
||||
res_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
pyEnv["res.partner"].write([pyEnv.currentPartnerId], { message_follower_ids: [followerId] });
|
||||
const { openView } = await start({
|
||||
// FIXME: should adapt mock server code to provide "hasWriteAccess"
|
||||
async mockRPC(route, args, performRPC) {
|
||||
if (route === "/mail/thread/data") {
|
||||
// mimic user with write access
|
||||
const res = await performRPC(...arguments);
|
||||
res["hasWriteAccess"] = true;
|
||||
return res;
|
||||
}
|
||||
},
|
||||
});
|
||||
openView({
|
||||
res_model: "res.partner",
|
||||
res_id: pyEnv.currentPartnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
await click(".o-mail-Followers-button");
|
||||
await click("button[title='Edit subscription']");
|
||||
await contains(
|
||||
`.o-mail-FollowerSubtypeDialog-subtype[data-follower-subtype-id=${subtypeId}] input[type='checkbox']:not(:checked)`
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("toggle follower subtype checkbox", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const subtypeId = pyEnv["mail.message.subtype"].create({
|
||||
default: true,
|
||||
name: "TestSubtype",
|
||||
});
|
||||
const followerId = pyEnv["mail.followers"].create({
|
||||
display_name: "François Perusse",
|
||||
partner_id: pyEnv.currentPartnerId,
|
||||
res_model: "res.partner",
|
||||
res_id: pyEnv.currentPartnerId,
|
||||
});
|
||||
pyEnv["res.partner"].write([pyEnv.currentPartnerId], { message_follower_ids: [followerId] });
|
||||
const { openView } = await start({
|
||||
// FIXME: should adapt mock server code to provide "hasWriteAccess"
|
||||
async mockRPC(route, args, performRPC) {
|
||||
if (route === "/mail/thread/data") {
|
||||
// mimic user with write access
|
||||
const res = await performRPC(...arguments);
|
||||
res["hasWriteAccess"] = true;
|
||||
return res;
|
||||
}
|
||||
},
|
||||
});
|
||||
openView({
|
||||
res_model: "res.partner",
|
||||
res_id: pyEnv.currentPartnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
await click(".o-mail-Followers-button");
|
||||
await click("button[title='Edit subscription']");
|
||||
await contains(
|
||||
`.o-mail-FollowerSubtypeDialog-subtype[data-follower-subtype-id=${subtypeId}] input[type='checkbox']:not(:checked)`
|
||||
);
|
||||
await click(
|
||||
`.o-mail-FollowerSubtypeDialog-subtype[data-follower-subtype-id=${subtypeId}] input[type='checkbox']`
|
||||
);
|
||||
await contains(
|
||||
`.o-mail-FollowerSubtypeDialog-subtype[data-follower-subtype-id=${subtypeId}] input[type='checkbox']:checked`
|
||||
);
|
||||
await click(
|
||||
`.o-mail-FollowerSubtypeDialog-subtype[data-follower-subtype-id=${subtypeId}] input[type='checkbox']`
|
||||
);
|
||||
await contains(
|
||||
`.o-mail-FollowerSubtypeDialog-subtype[data-follower-subtype-id=${subtypeId}] input[type='checkbox']:not(:checked)`
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("follower subtype apply", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const subtypeId1 = pyEnv["mail.message.subtype"].create({
|
||||
default: true,
|
||||
name: "TestSubtype1",
|
||||
});
|
||||
pyEnv["mail.message.subtype"].create({
|
||||
const subtypeId2 = pyEnv["mail.message.subtype"].create({
|
||||
default: true,
|
||||
name: "TestSubtype2",
|
||||
});
|
||||
@@ -161,20 +145,11 @@ QUnit.test("follower subtype apply", async (assert) => {
|
||||
partner_id: pyEnv.currentPartnerId,
|
||||
res_model: "res.partner",
|
||||
res_id: pyEnv.currentPartnerId,
|
||||
subtype_ids: [subtypeId],
|
||||
subtype_ids: [subtypeId1],
|
||||
});
|
||||
pyEnv["res.partner"].write([pyEnv.currentPartnerId], { message_follower_ids: [followerId] });
|
||||
const { openView } = await start({
|
||||
services: {
|
||||
notification: makeFakeNotificationService((message) => {
|
||||
assert.strictEqual(
|
||||
message,
|
||||
"The subscription preferences were successfully applied."
|
||||
);
|
||||
}),
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
const { openView } = await start();
|
||||
openView({
|
||||
res_model: "res.partner",
|
||||
res_id: pyEnv.currentPartnerId,
|
||||
views: [[false, "form"]],
|
||||
@@ -182,15 +157,26 @@ QUnit.test("follower subtype apply", async (assert) => {
|
||||
await click(".o-mail-Followers-button");
|
||||
await click("button[title='Edit subscription']");
|
||||
|
||||
const subtype1 =
|
||||
".o-mail-FollowerSubtypeDialog-subtype:contains(TestSubtype1) input[type='checkbox']";
|
||||
const subtype2 =
|
||||
".o-mail-FollowerSubtypeDialog-subtype:contains(TestSubtype2) input[type='checkbox']";
|
||||
assert.ok($(subtype1)[0].checked);
|
||||
assert.notOk($(subtype2)[0].checked);
|
||||
await click(subtype1);
|
||||
assert.notOk($(subtype1)[0].checked);
|
||||
await click(subtype2);
|
||||
assert.ok($(subtype2)[0].checked);
|
||||
await contains(
|
||||
`.o-mail-FollowerSubtypeDialog-subtype[data-follower-subtype-id=${subtypeId1}] input[type='checkbox']:checked`
|
||||
);
|
||||
await contains(
|
||||
`.o-mail-FollowerSubtypeDialog-subtype[data-follower-subtype-id=${subtypeId2}] input[type='checkbox']:not(:checked)`
|
||||
);
|
||||
await click(
|
||||
`.o-mail-FollowerSubtypeDialog-subtype[data-follower-subtype-id=${subtypeId1}] input[type='checkbox']`
|
||||
);
|
||||
await contains(
|
||||
`.o-mail-FollowerSubtypeDialog-subtype[data-follower-subtype-id=${subtypeId1}] input[type='checkbox']:not(:checked)`
|
||||
);
|
||||
await click(
|
||||
`.o-mail-FollowerSubtypeDialog-subtype[data-follower-subtype-id=${subtypeId2}] input[type='checkbox']`
|
||||
);
|
||||
await contains(
|
||||
`.o-mail-FollowerSubtypeDialog-subtype[data-follower-subtype-id=${subtypeId2}] input[type='checkbox']:checked`
|
||||
);
|
||||
await click(".modal-footer button:contains(Apply)");
|
||||
await contains(
|
||||
".o_notification:contains(The subscription preferences were successfully applied.)"
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, nextAnimationFrame, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { editInput, makeDeferred, patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("follower");
|
||||
|
||||
QUnit.test("base rendering not editable", async (assert) => {
|
||||
QUnit.test("base rendering not editable", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const [threadId, partnerId] = pyEnv["res.partner"].create([{}, {}]);
|
||||
pyEnv["mail.followers"].create({
|
||||
@@ -25,19 +25,19 @@ QUnit.test("base rendering not editable", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
openView({
|
||||
res_id: threadId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
await click(".o-mail-Followers-button");
|
||||
assert.containsOnce($, ".o-mail-Follower");
|
||||
assert.containsOnce($, ".o-mail-Follower-details");
|
||||
assert.containsOnce($, ".o-mail-Follower-avatar");
|
||||
assert.containsNone($, ".o-mail-Follower-action");
|
||||
await contains(".o-mail-Follower");
|
||||
await contains(".o-mail-Follower-details");
|
||||
await contains(".o-mail-Follower-avatar");
|
||||
await contains(".o-mail-Follower-action", 0);
|
||||
});
|
||||
|
||||
QUnit.test("base rendering editable", async (assert) => {
|
||||
QUnit.test("base rendering editable", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const [threadId, partnerId] = pyEnv["res.partner"].create([{}, {}]);
|
||||
pyEnv["mail.followers"].create({
|
||||
@@ -47,18 +47,18 @@ QUnit.test("base rendering editable", async (assert) => {
|
||||
res_model: "res.partner",
|
||||
});
|
||||
const { openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: threadId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
await click(".o-mail-Followers-button");
|
||||
assert.containsOnce($, ".o-mail-Follower");
|
||||
assert.containsOnce($, ".o-mail-Follower-details");
|
||||
assert.containsOnce($, ".o-mail-Follower-avatar");
|
||||
assert.containsOnce($, ".o-mail-Follower");
|
||||
assert.containsOnce($, "button[title='Edit subscription']");
|
||||
assert.containsOnce($, "button[title='Remove this follower']");
|
||||
await contains(".o-mail-Follower");
|
||||
await contains(".o-mail-Follower-details");
|
||||
await contains(".o-mail-Follower-avatar");
|
||||
await contains(".o-mail-Follower");
|
||||
await contains("button[title='Edit subscription']");
|
||||
await contains("button[title='Remove this follower']");
|
||||
});
|
||||
|
||||
QUnit.test("click on partner follower details", async (assert) => {
|
||||
@@ -72,7 +72,7 @@ QUnit.test("click on partner follower details", async (assert) => {
|
||||
});
|
||||
const openFormDef = makeDeferred();
|
||||
const { env, openView } = await start();
|
||||
await openView({
|
||||
openView({
|
||||
res_id: threadId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
@@ -87,8 +87,8 @@ QUnit.test("click on partner follower details", async (assert) => {
|
||||
},
|
||||
});
|
||||
await click(".o-mail-Followers-button");
|
||||
assert.containsOnce($, ".o-mail-Follower");
|
||||
assert.containsOnce($, ".o-mail-Follower-details");
|
||||
await contains(".o-mail-Follower");
|
||||
await contains(".o-mail-Follower-details");
|
||||
|
||||
$(".o-mail-Follower-details")[0].click();
|
||||
await openFormDef;
|
||||
@@ -111,19 +111,19 @@ QUnit.test("click on edit follower", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
openView({
|
||||
res_id: threadId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
await click(".o-mail-Followers-button");
|
||||
assert.containsOnce($, ".o-mail-Follower");
|
||||
assert.containsOnce($, "button[title='Edit subscription']");
|
||||
await contains(".o-mail-Follower");
|
||||
await contains("button[title='Edit subscription']");
|
||||
|
||||
await click("button[title='Edit subscription']");
|
||||
assert.containsNone($, ".o-mail-Follower");
|
||||
await contains(".o-mail-Follower", 0);
|
||||
assert.verifySteps(["fetch_subtypes"]);
|
||||
assert.containsOnce($, ".o-mail-FollowerSubtypeDialog");
|
||||
await contains(".o-mail-FollowerSubtypeDialog");
|
||||
});
|
||||
|
||||
QUnit.test("edit follower and close subtype dialog", async (assert) => {
|
||||
@@ -142,21 +142,21 @@ QUnit.test("edit follower and close subtype dialog", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
await openView({
|
||||
openView({
|
||||
res_id: threadId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
await click(".o-mail-Followers-button");
|
||||
assert.containsOnce($, ".o-mail-Follower");
|
||||
assert.containsOnce($, "button[title='Edit subscription']");
|
||||
await contains(".o-mail-Follower");
|
||||
await contains("button[title='Edit subscription']");
|
||||
|
||||
await click("button[title='Edit subscription']");
|
||||
await contains(".o-mail-FollowerSubtypeDialog");
|
||||
assert.verifySteps(["fetch_subtypes"]);
|
||||
assert.containsOnce($, ".o-mail-FollowerSubtypeDialog");
|
||||
|
||||
await click(".o-mail-FollowerSubtypeDialog button:contains(Cancel)");
|
||||
assert.containsNone($, ".o-mail-FollowerSubtypeDialog");
|
||||
await contains(".o-mail-FollowerSubtypeDialog", 0);
|
||||
});
|
||||
|
||||
QUnit.test("remove a follower in a dirty form view", async (assert) => {
|
||||
@@ -181,19 +181,17 @@ QUnit.test("remove a follower in a dirty form view", async (assert) => {
|
||||
</form>`,
|
||||
};
|
||||
const { openFormView } = await start({ serverData: { views } });
|
||||
await openFormView("res.partner", threadId);
|
||||
click(".o_field_many2many_tags[name='channel_ids'] input").catch(() => {});
|
||||
await nextAnimationFrame();
|
||||
click(".dropdown-item:contains(General)").catch(() => {});
|
||||
await nextAnimationFrame();
|
||||
assert.containsOnce($, ".o_tag:contains(General)");
|
||||
assert.strictEqual($(".o-mail-Followers-counter")[0].innerText, "1");
|
||||
openFormView("res.partner", threadId);
|
||||
await click(".o_field_many2many_tags[name='channel_ids'] input");
|
||||
await click(".dropdown-item:contains(General)");
|
||||
await contains(".o_tag:contains(General)");
|
||||
await contains(".o-mail-Followers-counter:contains(1)");
|
||||
await editInput(document.body, ".o_field_char[name=name] input", "some value");
|
||||
await click(".o-mail-Followers-button");
|
||||
await click("button[title='Remove this follower']");
|
||||
assert.strictEqual($(".o-mail-Followers-counter")[0].innerText, "0");
|
||||
await contains(".o-mail-Followers-counter:contains(0)");
|
||||
assert.strictEqual($(".o_field_char[name=name] input").val(), "some value");
|
||||
assert.containsOnce($, ".o_tag:contains(General)");
|
||||
await contains(".o_tag:contains(General)");
|
||||
});
|
||||
|
||||
QUnit.test("removing a follower should reload form view", async function (assert) {
|
||||
@@ -212,9 +210,11 @@ QUnit.test("removing a follower should reload form view", async function (assert
|
||||
}
|
||||
},
|
||||
});
|
||||
await openFormView("res.partner", threadId);
|
||||
openFormView("res.partner", threadId);
|
||||
await contains(".o-mail-Followers-button");
|
||||
assert.verifySteps([`read ${threadId}`]);
|
||||
await click(".o-mail-Followers-button");
|
||||
await click("button[title='Remove this follower']");
|
||||
await contains(".o-mail-Followers-counter:contains(0)");
|
||||
assert.verifySteps([`read ${threadId}`]);
|
||||
});
|
||||
|
||||
@@ -1,37 +1,10 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { patchUiSize, SIZES } from "@mail/../tests/helpers/patch_ui_size";
|
||||
import { click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
QUnit.module("Form renderer");
|
||||
|
||||
QUnit.test(
|
||||
"schedule activities on draft record should prompt with scheduling an activity (proceed with action)",
|
||||
async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
const views = {
|
||||
"res.partner,false,form": `
|
||||
<form string="Partners">
|
||||
<sheet>
|
||||
<field name="name"/>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="activity_ids"/>
|
||||
</div>
|
||||
</form>`,
|
||||
};
|
||||
const { openView } = await start({ serverData: { views } });
|
||||
await openView({
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
await click("button:contains(Activities)");
|
||||
assert.containsOnce($, ".o_dialog:contains(Schedule Activity)");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("Form view not scrolled when switching record", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const [partnerId_1, partnerId_2] = pyEnv["res.partner"].create([
|
||||
@@ -62,7 +35,7 @@ QUnit.test("Form view not scrolled when switching record", async (assert) => {
|
||||
};
|
||||
patchUiSize({ size: SIZES.LG });
|
||||
const { openView } = await start({ serverData: { views } });
|
||||
await openView(
|
||||
openView(
|
||||
{
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId_1,
|
||||
@@ -70,12 +43,12 @@ QUnit.test("Form view not scrolled when switching record", async (assert) => {
|
||||
},
|
||||
{ resIds: [partnerId_1, partnerId_2] }
|
||||
);
|
||||
assert.strictEqual($(".o_breadcrumb .active").text(), "Partner 1");
|
||||
await contains(".o_breadcrumb .active:contains(Partner 1)");
|
||||
assert.strictEqual($(".o_content")[0].scrollTop, 0);
|
||||
$(".o_content")[0].scrollTop = 150;
|
||||
|
||||
await click(".o_pager_next");
|
||||
assert.strictEqual($(".o_breadcrumb .active").text(), "Partner 2");
|
||||
await contains(".o_breadcrumb .active:contains(Partner 2)");
|
||||
assert.strictEqual($(".o_content")[0].scrollTop, 0);
|
||||
|
||||
await click(".o_pager_previous");
|
||||
@@ -84,7 +57,7 @@ QUnit.test("Form view not scrolled when switching record", async (assert) => {
|
||||
|
||||
QUnit.test(
|
||||
"Attachments that have been unlinked from server should be visually unlinked from record",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
// Attachments that have been fetched from a record at certain time and then
|
||||
// removed from the server should be reflected on the UI when the current
|
||||
// partner accesses this record again.
|
||||
@@ -117,7 +90,7 @@ QUnit.test(
|
||||
</form>`,
|
||||
};
|
||||
const { openView } = await start({ serverData: { views } });
|
||||
await openView(
|
||||
openView(
|
||||
{
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId_1,
|
||||
@@ -128,21 +101,21 @@ QUnit.test(
|
||||
resIds: [partnerId_1, partnerId_2],
|
||||
}
|
||||
);
|
||||
assert.containsOnce($, ".o-mail-Chatter button:contains(2)");
|
||||
|
||||
await contains("button[aria-label='Attach files']:contains(2)");
|
||||
// The attachment links are updated on (re)load,
|
||||
// so using pager is a way to reload the record "Partner1".
|
||||
await click(".o_pager_next");
|
||||
await contains("button[aria-label='Attach files']:not(:has(span))");
|
||||
// Simulate unlinking attachment 1 from Partner 1.
|
||||
pyEnv["ir.attachment"].write([attachmentId_1], { res_id: 0 });
|
||||
await click(".o_pager_previous");
|
||||
assert.containsOnce($, ".o-mail-Chatter button:contains(1)");
|
||||
await contains("button[aria-label='Attach files']:contains(1)");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"read more/less links are not duplicated when switching from read to edit mode",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
pyEnv["mail.message"].create({
|
||||
@@ -179,10 +152,10 @@ QUnit.test(
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
};
|
||||
await openView(openViewAction);
|
||||
assert.containsOnce($, ".o-mail-Chatter");
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsOnce($, ".o-mail-read-more-less");
|
||||
openView(openViewAction);
|
||||
await contains(".o-mail-Chatter");
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-read-more-less");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -225,18 +198,18 @@ QUnit.test("read more links becomes read less after being clicked", async (asser
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
};
|
||||
await openView(openViewAction);
|
||||
assert.containsOnce($, ".o-mail-Chatter");
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsOnce($, ".o-mail-read-more-less:contains(Read More)");
|
||||
openView(openViewAction);
|
||||
await contains(".o-mail-Chatter");
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-read-more-less:contains(Read More)");
|
||||
|
||||
await click(".o-mail-read-more-less");
|
||||
assert.containsOnce($, ".o-mail-read-more-less:contains(Read Less)");
|
||||
await contains(".o-mail-read-more-less:contains(Read Less)");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"[TECHNICAL] unfolded read more/less links should not fold on message click besides those button links",
|
||||
async (assert) => {
|
||||
async () => {
|
||||
// message click triggers a re-render. Before writing of this test, the
|
||||
// insertion of read more/less links were done during render. This meant
|
||||
// any re-render would re-insert the read more/less links. If some button
|
||||
@@ -277,22 +250,22 @@ QUnit.test(
|
||||
</form>`,
|
||||
};
|
||||
const { openView } = await start({ serverData: { views } });
|
||||
await openView({
|
||||
openView({
|
||||
res_model: "res.partner",
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-read-more-less:contains(Read More)");
|
||||
await contains(".o-mail-read-more-less:contains(Read More)");
|
||||
|
||||
await click(".o-mail-read-more-less");
|
||||
assert.containsOnce($, ".o-mail-read-more-less:contains(Read Less)");
|
||||
await contains(".o-mail-read-more-less:contains(Read Less)");
|
||||
|
||||
await click(".o-mail-Message");
|
||||
assert.containsOnce($, ".o-mail-read-more-less:contains(Read Less)");
|
||||
await contains(".o-mail-read-more-less:contains(Read Less)");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test("read more/less links on message of type notification", async (assert) => {
|
||||
QUnit.test("read more/less links on message of type notification", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({});
|
||||
pyEnv["mail.message"].create({
|
||||
@@ -330,6 +303,6 @@ QUnit.test("read more/less links on message of type notification", async (assert
|
||||
res_id: partnerId,
|
||||
views: [[false, "form"]],
|
||||
};
|
||||
await openView(openViewAction);
|
||||
assert.containsOnce($, ".o-mail-Message a:contains(Read More)");
|
||||
openView(openViewAction);
|
||||
await contains(".o-mail-Message a:contains(Read More)");
|
||||
});
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
/** @odoo-module **/
|
||||
/* @odoo-module */
|
||||
|
||||
import testUtils from '@web/../tests/legacy/helpers/test_utils';
|
||||
import { registry } from "@web/core/registry";
|
||||
import {
|
||||
getFixture,
|
||||
nextTick,
|
||||
} from '@web/../tests/helpers/utils';
|
||||
import { setupViewRegistries } from "@web/../tests/views/helpers";
|
||||
import { contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { addModelNamesToFetch } from "@bus/../tests/helpers/model_definitions_helpers";
|
||||
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { fileUploadService } from "@web/core/file_upload/file_upload_service";
|
||||
import { registry } from "@web/core/registry";
|
||||
import testUtils from "@web/../tests/legacy/helpers/test_utils";
|
||||
import { getFixture, nextTick } from "@web/../tests/helpers/utils";
|
||||
import { setupViewRegistries } from "@web/../tests/views/helpers";
|
||||
|
||||
import { addModelNamesToFetch } from '@bus/../tests/helpers/model_definitions_helpers';
|
||||
addModelNamesToFetch([
|
||||
'mrp.document',
|
||||
]);
|
||||
addModelNamesToFetch(["mrp.document"]);
|
||||
|
||||
const serviceRegistry = registry.category("services");
|
||||
|
||||
@@ -223,9 +219,9 @@ QUnit.module('MrpDocumentsKanbanView', {
|
||||
res_model: "mrp.document",
|
||||
views: [[false, "kanban"]],
|
||||
});
|
||||
(await contains(".o_kanban_previewer")).click();
|
||||
await click(".o_kanban_previewer");
|
||||
await contains(".o-FileViewer");
|
||||
(await contains(".o-FileViewer-headerButton .fa-times")).click();
|
||||
await click(".o-FileViewer-headerButton .fa-times");
|
||||
await contains(".o-FileViewer", 0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,75 +1,76 @@
|
||||
/** @odoo-module **/
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, start } from "@mail/../tests/helpers/test_utils";
|
||||
import { getFixture, editInput, patchDate } from "@web/../tests/helpers/utils";
|
||||
import { click, contains, insertText, start } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
let target;
|
||||
import { editInput, patchDate } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("todo activity menu", {
|
||||
async beforeEach() {
|
||||
target = getFixture();
|
||||
},
|
||||
});
|
||||
|
||||
QUnit.test("create todo from activity menu without date", async function (assert) {
|
||||
QUnit.test("create todo from activity menu without date", async function () {
|
||||
await start();
|
||||
assert.containsOnce(target, ".o_menu_systray i[aria-label='Activities']");
|
||||
assert.containsNone(target, ".o-mail-ActivityMenu-counter");
|
||||
await contains(".o_menu_systray i[aria-label='Activities']");
|
||||
await contains(".o-mail-ActivityMenu-counter", 0);
|
||||
await click(".o_menu_systray i[aria-label='Activities']");
|
||||
assert.containsOnce(
|
||||
target,
|
||||
await contains(
|
||||
".o-mail-ActivityMenu:contains(Congratulations, you're done with your activities.)"
|
||||
);
|
||||
assert.containsOnce(target, ".btn:contains(Add a To-do)");
|
||||
await click(".btn:contains(Add a To-do)");
|
||||
assert.containsNone(target, ".btn:contains(Add a To-do)");
|
||||
assert.containsOnce(target, ".o-mail-ActivityMenu-show");
|
||||
await editInput(target, "input.o-mail-ActivityMenu-input", "New To-do");
|
||||
await contains(".btn:contains(Add a To-do)", 0);
|
||||
await contains(".o-mail-ActivityMenu-show");
|
||||
await insertText("input.o-mail-ActivityMenu-input", "New To-do");
|
||||
await click(".btn:contains(SAVE)");
|
||||
await contains(
|
||||
".o_notification:contains(Your to-do has been successfully added to your tasks and scheduled for completion.)"
|
||||
);
|
||||
// Need to reopen systray as it automatically closes when a todo is created
|
||||
await click(".o_menu_systray i[aria-label='Activities']");
|
||||
await contains(".o-mail-ActivityMenu-counter:contains(1)");
|
||||
await contains(".o-mail-ActivityGroup");
|
||||
await contains(".o-mail-ActivityGroup:contains(project.task)");
|
||||
await contains(".btn:contains(1 Today)");
|
||||
await contains(".btn:contains(Add a To-do)");
|
||||
await contains(".o-mail-ActivityMenu-show", 0);
|
||||
await contains(".o-mail-ActivityMenu-input", 0);
|
||||
await click(".btn:contains(Add a To-do)");
|
||||
await contains(".btn:contains(Add a To-do)", 0);
|
||||
await insertText("input.o-mail-ActivityMenu-input", "New To-do");
|
||||
await click(".btn:contains(SAVE)");
|
||||
// Need to reopen systray as it automatically closes when a todo is created
|
||||
assert.containsOnce(target, ".o_menu_systray i[aria-label='Activities']");
|
||||
await contains(
|
||||
".o_notification:contains(Your to-do has been successfully added to your tasks and scheduled for completion.)",
|
||||
2
|
||||
);
|
||||
await click(".o_menu_systray i[aria-label='Activities']");
|
||||
assert.containsOnce(target, ".o-mail-ActivityMenu-counter:contains(1)");
|
||||
assert.containsOnce(target, ".o-mail-ActivityGroup");
|
||||
assert.containsOnce(target, ".o-mail-ActivityGroup:contains(project.task)");
|
||||
assert.containsOnce(target, ".btn:contains(1 Today)");
|
||||
assert.containsOnce(target, ".btn:contains(Add a To-do)");
|
||||
assert.containsNone(target, ".o-mail-ActivityMenu-show");
|
||||
assert.containsNone(target, ".o-mail-ActivityMenu-input");
|
||||
await click(".btn:contains(Add a To-do)");
|
||||
assert.containsNone(target, ".btn:contains(Add a To-do)");
|
||||
await editInput(target, "input.o-mail-ActivityMenu-input", "New To-do");
|
||||
await click(".btn:contains(SAVE)");
|
||||
// Need to reopen systray as it automatically closes when a todo is created
|
||||
assert.containsOnce(target, ".o_menu_systray i[aria-label='Activities']");
|
||||
await click(".o_menu_systray i[aria-label='Activities']");
|
||||
assert.containsOnce(target, ".o-mail-ActivityMenu-counter:contains(2)");
|
||||
assert.containsOnce(target, ".btn:contains(2 Today)");
|
||||
await contains(".o-mail-ActivityMenu-counter:contains(2)");
|
||||
await contains(".btn:contains(2 Today)");
|
||||
});
|
||||
|
||||
QUnit.test("create to-do from activity menu with date", async function (assert) {
|
||||
QUnit.test("create to-do from activity menu with date", async function () {
|
||||
patchDate(2023, 1, 1, 6, 0, 0);
|
||||
const { DateTime } = luxon;
|
||||
const today = DateTime.utc();
|
||||
const futureDay = today.plus({ days: 2 });
|
||||
await start();
|
||||
assert.containsOnce(target, ".o_menu_systray i[aria-label='Activities']");
|
||||
assert.containsNone(target, ".o-mail-ActivityMenu-counter");
|
||||
await contains(".o_menu_systray i[aria-label='Activities']");
|
||||
await contains(".o-mail-ActivityMenu-counter", 0);
|
||||
|
||||
await click(".o_menu_systray i[aria-label='Activities']");
|
||||
await click(".btn:contains(Add a To-do)");
|
||||
await editInput(target, "input.o-mail-ActivityMenu-input", "New To-do");
|
||||
await insertText("input.o-mail-ActivityMenu-input", "New To-do");
|
||||
await editInput(
|
||||
target,
|
||||
document.body,
|
||||
"input.o_datetime_input",
|
||||
futureDay.toString(luxon.DateTime.DATE_SHORT)
|
||||
futureDay.toString(luxon.DateTime.DATE_SHORT),
|
||||
{
|
||||
replace: true,
|
||||
}
|
||||
);
|
||||
await click(".btn:contains(SAVE)");
|
||||
await contains(
|
||||
".o_notification:contains(Your to-do has been successfully added to your tasks and scheduled for completion.)"
|
||||
);
|
||||
// Need to reopen systray as it automatically closes when a todo is created
|
||||
assert.containsOnce(target, ".o_menu_systray i[aria-label='Activities']");
|
||||
await click(".o_menu_systray i[aria-label='Activities']");
|
||||
assert.containsOnce(target, ".o-mail-ActivityMenu-counter:contains(1)");
|
||||
assert.containsOnce(target, ".o-mail-ActivityGroup");
|
||||
assert.containsOnce(target, ".o-mail-ActivityGroup:contains(project.task)");
|
||||
assert.containsOnce(target, ".btn:contains(1 Future)");
|
||||
await contains(".o-mail-ActivityMenu-counter:contains(1)");
|
||||
await contains(".o-mail-ActivityGroup");
|
||||
await contains(".o-mail-ActivityGroup:contains(project.task)");
|
||||
await contains(".btn:contains(1 Future)");
|
||||
});
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
/** @odoo-module **/
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { start, startServer, click } from "@mail/../tests/helpers/test_utils";
|
||||
import { patchWithCleanup, triggerEvent } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("messaging menu (patch)");
|
||||
|
||||
QUnit.test("mark as read", async (assert) => {
|
||||
QUnit.test("mark as read", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const messageId = pyEnv["mail.message"].create({
|
||||
message_type: "sms",
|
||||
@@ -20,15 +21,12 @@ QUnit.test("mark as read", async (assert) => {
|
||||
});
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem");
|
||||
await contains(".o-mail-NotificationItem");
|
||||
await triggerEvent($(".o-mail-NotificationItem")[0], null, "mouseenter");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem [title='Mark As Read']");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
".o-mail-NotificationItem:contains(An error occurred when sending an SMS)"
|
||||
);
|
||||
await contains(".o-mail-NotificationItem [title='Mark As Read']");
|
||||
await contains(".o-mail-NotificationItem:contains(An error occurred when sending an SMS)");
|
||||
await click(".o-mail-NotificationItem [title='Mark As Read']");
|
||||
assert.containsNone($, ".o-mail-NotificationItem");
|
||||
await contains(".o-mail-NotificationItem", 0);
|
||||
});
|
||||
|
||||
QUnit.test("notifications grouped by notification_type", async (assert) => {
|
||||
@@ -72,7 +70,7 @@ QUnit.test("notifications grouped by notification_type", async (assert) => {
|
||||
]);
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsN($, ".o-mail-NotificationItem", 2);
|
||||
await contains(".o-mail-NotificationItem", 2);
|
||||
const items = $(".o-mail-NotificationItem");
|
||||
assert.ok(items[0].textContent.includes("Partner"));
|
||||
assert.ok(items[0].textContent.includes("2")); // counter
|
||||
@@ -135,8 +133,8 @@ QUnit.test("grouped notifications by document model", async (assert) => {
|
||||
});
|
||||
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem:contains(Partner) .badge:contains(2)");
|
||||
await contains(".o-mail-NotificationItem");
|
||||
await contains(".o-mail-NotificationItem:contains(Partner) .badge:contains(2)");
|
||||
await click(".o-mail-NotificationItem");
|
||||
assert.verifySteps(["do_action"]);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/** @odoo-module **/
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, contains, startServer, start } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { startServer, start, click } from "@mail/../tests/helpers/test_utils";
|
||||
import { makeDeferred, patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("message (patch)");
|
||||
@@ -21,17 +22,17 @@ QUnit.test("Notification Sent", async (assert) => {
|
||||
res_partner_id: partnerId,
|
||||
});
|
||||
const { openFormView } = await start();
|
||||
await openFormView("res.partner", partnerId);
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsOnce($, ".o-mail-Message-notification");
|
||||
assert.containsOnce($, ".o-mail-Message-notification i");
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message-notification");
|
||||
await contains(".o-mail-Message-notification i");
|
||||
assert.hasClass($(".o-mail-Message-notification i"), "fa-mobile");
|
||||
|
||||
await click(".o-mail-Message-notification");
|
||||
assert.containsOnce($, ".o-mail-MessageNotificationPopover");
|
||||
assert.containsOnce($, ".o-mail-MessageNotificationPopover i");
|
||||
await contains(".o-mail-MessageNotificationPopover");
|
||||
await contains(".o-mail-MessageNotificationPopover i");
|
||||
assert.hasClass($(".o-mail-MessageNotificationPopover i"), "fa-check");
|
||||
assert.containsOnce($, ".o-mail-MessageNotificationPopover:contains(Someone)");
|
||||
await contains(".o-mail-MessageNotificationPopover:contains(Someone)");
|
||||
});
|
||||
|
||||
QUnit.test("Notification Error", async (assert) => {
|
||||
@@ -51,7 +52,7 @@ QUnit.test("Notification Error", async (assert) => {
|
||||
res_partner_id: partnerId,
|
||||
});
|
||||
const { env, openFormView } = await start();
|
||||
await openFormView("res.partner", partnerId);
|
||||
openFormView("res.partner", partnerId);
|
||||
patchWithCleanup(env.services.action, {
|
||||
doAction(action, options) {
|
||||
assert.step("do_action");
|
||||
@@ -61,11 +62,11 @@ QUnit.test("Notification Error", async (assert) => {
|
||||
},
|
||||
});
|
||||
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsOnce($, ".o-mail-Message-notification");
|
||||
assert.containsOnce($, ".o-mail-Message-notification i");
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message-notification");
|
||||
await contains(".o-mail-Message-notification i");
|
||||
assert.hasClass($(".o-mail-Message-notification i"), "fa-mobile");
|
||||
click(".o-mail-Message-notification").catch(() => {});
|
||||
await click(".o-mail-Message-notification");
|
||||
await openResendActionDef;
|
||||
assert.verifySteps(["do_action"]);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/** @odoo-module **/
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { start, startServer, click } from "@mail/../tests/helpers/test_utils";
|
||||
import { makeDeferred, patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("message (patch)");
|
||||
@@ -24,15 +25,15 @@ QUnit.test("Sent", async (assert) => {
|
||||
res_partner_id: partnerId,
|
||||
});
|
||||
const { openFormView } = await start();
|
||||
await openFormView("res.partner", partnerId);
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsOnce($, ".o-mail-Message-notification");
|
||||
assert.containsOnce($, ".o-mail-Message-notification i");
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message-notification");
|
||||
await contains(".o-mail-Message-notification i");
|
||||
assert.hasClass($(".o-mail-Message-notification i"), "fa-paper-plane");
|
||||
|
||||
await click(".o-mail-Message-notification");
|
||||
assert.containsOnce($, ".o-snailmail-SnailmailNotificationPopover");
|
||||
assert.containsOnce($, ".o-snailmail-SnailmailNotificationPopover i");
|
||||
await contains(".o-snailmail-SnailmailNotificationPopover");
|
||||
await contains(".o-snailmail-SnailmailNotificationPopover i");
|
||||
assert.hasClass($(".o-snailmail-SnailmailNotificationPopover i"), "fa-check");
|
||||
assert.strictEqual($(".o-snailmail-SnailmailNotificationPopover").text(), "Sent");
|
||||
});
|
||||
@@ -56,15 +57,15 @@ QUnit.test("Canceled", async (assert) => {
|
||||
res_partner_id: partnerId,
|
||||
});
|
||||
const { openFormView } = await start();
|
||||
await openFormView("res.partner", partnerId);
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsOnce($, ".o-mail-Message-notification");
|
||||
assert.containsOnce($, ".o-mail-Message-notification i");
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message-notification");
|
||||
await contains(".o-mail-Message-notification i");
|
||||
assert.hasClass($(".o-mail-Message-notification i"), "fa-paper-plane");
|
||||
|
||||
await click(".o-mail-Message-notification");
|
||||
assert.containsOnce($, ".o-snailmail-SnailmailNotificationPopover");
|
||||
assert.containsOnce($, ".o-snailmail-SnailmailNotificationPopover i");
|
||||
await contains(".o-snailmail-SnailmailNotificationPopover");
|
||||
await contains(".o-snailmail-SnailmailNotificationPopover i");
|
||||
assert.hasClass($(".o-snailmail-SnailmailNotificationPopover i"), "fa-trash-o");
|
||||
assert.strictEqual($(".o-snailmail-SnailmailNotificationPopover").text(), "Canceled");
|
||||
});
|
||||
@@ -88,15 +89,15 @@ QUnit.test("Pending", async (assert) => {
|
||||
res_partner_id: partnerId,
|
||||
});
|
||||
const { openFormView } = await start();
|
||||
await openFormView("res.partner", partnerId);
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsOnce($, ".o-mail-Message-notification");
|
||||
assert.containsOnce($, ".o-mail-Message-notification i");
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message-notification");
|
||||
await contains(".o-mail-Message-notification i");
|
||||
assert.hasClass($(".o-mail-Message-notification i"), "fa-paper-plane");
|
||||
|
||||
await click(".o-mail-Message-notification");
|
||||
assert.containsOnce($, ".o-snailmail-SnailmailNotificationPopover");
|
||||
assert.containsOnce($, ".o-snailmail-SnailmailNotificationPopover i");
|
||||
await contains(".o-snailmail-SnailmailNotificationPopover");
|
||||
await contains(".o-snailmail-SnailmailNotificationPopover i");
|
||||
assert.hasClass($(".o-snailmail-SnailmailNotificationPopover i"), "fa-clock-o");
|
||||
assert.strictEqual($(".o-snailmail-SnailmailNotificationPopover").text(), "Awaiting Dispatch");
|
||||
});
|
||||
@@ -131,21 +132,21 @@ QUnit.test("No Price Available", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
await openFormView("res.partner", partnerId);
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsOnce($, ".o-mail-Message-notification");
|
||||
assert.containsOnce($, ".o-mail-Message-notification i");
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message-notification");
|
||||
await contains(".o-mail-Message-notification i");
|
||||
assert.hasClass($(".o-mail-Message-notification i"), "fa-paper-plane");
|
||||
|
||||
await click(".o-mail-Message-notification");
|
||||
assert.containsOnce($, ".o-snailmail-SnailmailError");
|
||||
await contains(".o-snailmail-SnailmailError");
|
||||
assert.strictEqual(
|
||||
$(".o-snailmail-SnailmailError .modal-body").text().trim(),
|
||||
"The country to which you want to send the letter is not supported by our service."
|
||||
);
|
||||
assert.containsOnce($, "button:contains(Cancel letter)");
|
||||
await contains("button:contains(Cancel letter)");
|
||||
await click("button:contains(Cancel letter)");
|
||||
assert.containsNone($, ".o-snailmail-SnailmailError");
|
||||
await contains(".o-snailmail-SnailmailError", 0);
|
||||
assert.verifySteps(["cancel_letter"]);
|
||||
});
|
||||
|
||||
@@ -179,22 +180,22 @@ QUnit.test("Credit Error", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
await openFormView("res.partner", partnerId);
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsOnce($, ".o-mail-Message-notification");
|
||||
assert.containsOnce($, ".o-mail-Message-notification i");
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message-notification");
|
||||
await contains(".o-mail-Message-notification i");
|
||||
assert.hasClass($(".o-mail-Message-notification i"), "fa-paper-plane");
|
||||
|
||||
await click(".o-mail-Message-notification");
|
||||
assert.containsOnce($, ".o-snailmail-SnailmailError");
|
||||
await contains(".o-snailmail-SnailmailError");
|
||||
assert.strictEqual(
|
||||
$(".o-snailmail-SnailmailError p").text().trim(),
|
||||
"The letter could not be sent due to insufficient credits on your IAP account."
|
||||
);
|
||||
assert.containsOnce($, "button:contains(Re-send letter)");
|
||||
assert.containsOnce($, "button:contains(Cancel letter)");
|
||||
await contains("button:contains(Re-send letter)");
|
||||
await contains("button:contains(Cancel letter)");
|
||||
await click("button:contains(Re-send letter)");
|
||||
assert.containsNone($, ".o-snailmail-SnailmailError");
|
||||
await contains(".o-snailmail-SnailmailError", 0);
|
||||
assert.verifySteps(["send_letter"]);
|
||||
});
|
||||
|
||||
@@ -228,22 +229,22 @@ QUnit.test("Trial Error", async (assert) => {
|
||||
}
|
||||
},
|
||||
});
|
||||
await openFormView("res.partner", partnerId);
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsOnce($, ".o-mail-Message-notification");
|
||||
assert.containsOnce($, ".o-mail-Message-notification i");
|
||||
openFormView("res.partner", partnerId);
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message-notification");
|
||||
await contains(".o-mail-Message-notification i");
|
||||
assert.hasClass($(".o-mail-Message-notification i"), "fa-paper-plane");
|
||||
|
||||
await click(".o-mail-Message-notification");
|
||||
assert.containsOnce($, ".o-snailmail-SnailmailError");
|
||||
await contains(".o-snailmail-SnailmailError");
|
||||
assert.strictEqual(
|
||||
$(".o-snailmail-SnailmailError p").text().trim(),
|
||||
"You need credits on your IAP account to send a letter."
|
||||
);
|
||||
assert.containsOnce($, "button:contains(Re-send letter)");
|
||||
assert.containsOnce($, "button:contains(Cancel letter)");
|
||||
await contains("button:contains(Re-send letter)");
|
||||
await contains("button:contains(Cancel letter)");
|
||||
await click("button:contains(Re-send letter)");
|
||||
assert.containsNone($, ".o-snailmail-SnailmailError");
|
||||
await contains(".o-snailmail-SnailmailError", 0);
|
||||
assert.verifySteps(["send_letter"]);
|
||||
});
|
||||
|
||||
@@ -268,7 +269,7 @@ QUnit.test("Format Error", async (assert) => {
|
||||
res_partner_id: partnerId,
|
||||
});
|
||||
const { env, openFormView } = await start();
|
||||
await openFormView("res.partner", partnerId);
|
||||
openFormView("res.partner", partnerId);
|
||||
patchWithCleanup(env.services.action, {
|
||||
doAction(action, options) {
|
||||
assert.step("do_action");
|
||||
@@ -277,9 +278,9 @@ QUnit.test("Format Error", async (assert) => {
|
||||
openFormatErrorActionDef.resolve();
|
||||
},
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsOnce($, ".o-mail-Message-notification");
|
||||
assert.containsOnce($, ".o-mail-Message-notification i");
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message-notification");
|
||||
await contains(".o-mail-Message-notification i");
|
||||
assert.hasClass($(".o-mail-Message-notification i"), "fa-paper-plane");
|
||||
|
||||
click(".o-mail-Message-notification").then(() => {});
|
||||
@@ -307,7 +308,7 @@ QUnit.test("Missing Required Fields", async (assert) => {
|
||||
message_id: messageId,
|
||||
});
|
||||
const { env, openFormView } = await start();
|
||||
await openFormView("res.partner", partnerId);
|
||||
openFormView("res.partner", partnerId);
|
||||
patchWithCleanup(env.services.action, {
|
||||
doAction(action, options) {
|
||||
assert.step("do_action");
|
||||
@@ -316,9 +317,9 @@ QUnit.test("Missing Required Fields", async (assert) => {
|
||||
openRequiredFieldsActionDef.resolve();
|
||||
},
|
||||
});
|
||||
assert.containsOnce($, ".o-mail-Message");
|
||||
assert.containsOnce($, ".o-mail-Message-notification");
|
||||
assert.containsOnce($, ".o-mail-Message-notification i");
|
||||
await contains(".o-mail-Message");
|
||||
await contains(".o-mail-Message-notification");
|
||||
await contains(".o-mail-Message-notification i");
|
||||
assert.hasClass($(".o-mail-Message-notification i"), "fa-paper-plane");
|
||||
|
||||
click(".o-mail-Message-notification").then(() => {});
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
/** @odoo-module **/
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { start, startServer, click } from "@mail/../tests/helpers/test_utils";
|
||||
import { patchWithCleanup, triggerEvent } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("messaging menu (patch)");
|
||||
|
||||
QUnit.test("mark as read", async (assert) => {
|
||||
QUnit.test("mark as read", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const messageId = pyEnv["mail.message"].create([
|
||||
{
|
||||
@@ -22,15 +23,14 @@ QUnit.test("mark as read", async (assert) => {
|
||||
});
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem");
|
||||
await contains(".o-mail-NotificationItem");
|
||||
await triggerEvent($(".o-mail-NotificationItem")[0], null, "mouseenter");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem [title='Mark As Read']");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
await contains(".o-mail-NotificationItem [title='Mark As Read']");
|
||||
await contains(
|
||||
".o-mail-NotificationItem:contains(An error occurred when sending a letter with Snailmail.)"
|
||||
);
|
||||
await click(".o-mail-NotificationItem [title='Mark As Read']");
|
||||
assert.containsNone($, ".o-mail-NotificationItem");
|
||||
await contains(".o-mail-NotificationItem", 0);
|
||||
});
|
||||
|
||||
QUnit.test("notifications grouped by notification_type", async (assert) => {
|
||||
@@ -74,7 +74,7 @@ QUnit.test("notifications grouped by notification_type", async (assert) => {
|
||||
]);
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsN($, ".o-mail-NotificationItem", 2);
|
||||
await contains(".o-mail-NotificationItem", 2);
|
||||
assert.ok($(".o-mail-NotificationItem:eq(0)").text().includes("Partner"));
|
||||
assert.ok($(".o-mail-NotificationItem:eq(0)").text().includes("2")); // counter
|
||||
assert.ok(
|
||||
@@ -144,9 +144,9 @@ QUnit.test("grouped notifications by document model", async (assert) => {
|
||||
},
|
||||
});
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem:contains(Partner)");
|
||||
assert.containsOnce($, ".o-mail-NotificationItem:contains(2)"); // counter
|
||||
await contains(".o-mail-NotificationItem");
|
||||
await contains(".o-mail-NotificationItem:contains(Partner)");
|
||||
await contains(".o-mail-NotificationItem:contains(2)"); // counter
|
||||
await click(".o-mail-NotificationItem");
|
||||
assert.verifySteps(["do_action"]);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/** @odoo-module **/
|
||||
/* @odoo-module */
|
||||
|
||||
import { start, startServer, click } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
QUnit.module("properties field");
|
||||
|
||||
@@ -63,7 +63,7 @@ async function testPropertyFieldAvatarOpenChat(assert, propertyType) {
|
||||
);
|
||||
assert.verifySteps(["read res.users"]);
|
||||
|
||||
const chatter = document.querySelectorAll(".o-mail-ChatWindow-name");
|
||||
const chatter = await contains(".o-mail-ChatWindow-name");
|
||||
assert.strictEqual(chatter.length, 1);
|
||||
assert.strictEqual(chatter[0].innerText, "Partner Test");
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/** @odoo-module **/
|
||||
/* @odoo-module */
|
||||
|
||||
import { start, startServer, click } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import { session } from "@web/session";
|
||||
import { date_to_str } from "@web/legacy/js/core/time";
|
||||
import { session } from "@web/session";
|
||||
import { patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module("activity menu");
|
||||
|
||||
QUnit.test("menu with no records", async (assert) => {
|
||||
QUnit.test("menu with no records", async () => {
|
||||
await start({
|
||||
async mockRPC(route, args) {
|
||||
if (args.method === "systray_get_activities") {
|
||||
@@ -17,13 +17,12 @@ QUnit.test("menu with no records", async (assert) => {
|
||||
},
|
||||
});
|
||||
await click(".o_menu_systray .dropdown-toggle:has(i[aria-label='Activities'])");
|
||||
assert.containsOnce(
|
||||
$,
|
||||
await contains(
|
||||
".o-mail-ActivityMenu:contains(Congratulations, you're done with your activities.)"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("do not show empty text when at least some future activities", async (assert) => {
|
||||
QUnit.test("do not show empty text when at least some future activities", async () => {
|
||||
const tomorrow = new Date();
|
||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||
const pyEnv = await startServer();
|
||||
@@ -37,9 +36,9 @@ QUnit.test("do not show empty text when at least some future activities", async
|
||||
]);
|
||||
await start();
|
||||
await click(".o_menu_systray .dropdown-toggle:has(i[aria-label='Activities'])");
|
||||
assert.containsNone(
|
||||
$,
|
||||
".o-mail-ActivityMenu:contains(Congratulations, you're done with your activities.)"
|
||||
await contains(
|
||||
".o-mail-ActivityMenu:contains(Congratulations, you're done with your activities.)",
|
||||
0
|
||||
);
|
||||
});
|
||||
|
||||
@@ -71,9 +70,9 @@ QUnit.test("activity menu widget: activity menu with 2 models", async (assert) =
|
||||
},
|
||||
]);
|
||||
const { env } = await start();
|
||||
assert.containsOnce($, ".o_menu_systray i[aria-label='Activities']");
|
||||
assert.containsOnce($, ".o-mail-ActivityMenu-counter");
|
||||
assert.containsOnce($, ".o-mail-ActivityMenu-counter:contains(5)");
|
||||
await contains(".o_menu_systray i[aria-label='Activities']");
|
||||
await contains(".o-mail-ActivityMenu-counter");
|
||||
await contains(".o-mail-ActivityMenu-counter:contains(5)");
|
||||
let context = {};
|
||||
patchWithCleanup(env.services.action, {
|
||||
doAction(action) {
|
||||
@@ -85,22 +84,24 @@ QUnit.test("activity menu widget: activity menu with 2 models", async (assert) =
|
||||
search_default_activities_overdue: 1,
|
||||
};
|
||||
await click(".o_menu_systray i[aria-label='Activities']");
|
||||
assert.containsOnce($, ".o-mail-ActivityMenu");
|
||||
assert.containsN($, ".o-mail-ActivityMenu .o-mail-ActivityGroup", 2);
|
||||
await contains(".o-mail-ActivityMenu");
|
||||
await contains(".o-mail-ActivityMenu .o-mail-ActivityGroup", 2);
|
||||
await click(".o-mail-ActivityMenu .o-mail-ActivityGroup button:contains('Late')");
|
||||
assert.containsNone($, ".o-mail-ActivityMenu");
|
||||
await contains(".o-mail-ActivityMenu", 0);
|
||||
context = {
|
||||
force_search_count: 1,
|
||||
search_default_activities_today: 1,
|
||||
};
|
||||
await click(".o_menu_systray .dropdown-toggle:has(i[aria-label='Activities'])");
|
||||
await click(".o-mail-ActivityMenu .o-mail-ActivityGroup button:contains('Today')");
|
||||
await click(".o-mail-ActivityMenu .o-mail-ActivityGroup button:contains('Today'):eq(0)");
|
||||
await contains(".o-mail-ActivityMenu", 0);
|
||||
context = {
|
||||
force_search_count: 1,
|
||||
search_default_activities_upcoming_all: 1,
|
||||
};
|
||||
await click(".o_menu_systray i[aria-label='Activities']");
|
||||
await click(".o-mail-ActivityMenu .o-mail-ActivityGroup button:contains('Future')");
|
||||
await contains(".o-mail-ActivityMenu", 0);
|
||||
context = {
|
||||
force_search_count: 1,
|
||||
search_default_activities_overdue: 1,
|
||||
@@ -108,6 +109,7 @@ QUnit.test("activity menu widget: activity menu with 2 models", async (assert) =
|
||||
};
|
||||
await click(".o_menu_systray i[aria-label='Activities']");
|
||||
await click(".o-mail-ActivityMenu .o-mail-ActivityGroup:contains('mail.test.activity')");
|
||||
await contains(".o-mail-ActivityMenu", 0);
|
||||
});
|
||||
|
||||
QUnit.test("activity menu widget: activity view icon", async (assert) => {
|
||||
@@ -139,7 +141,7 @@ QUnit.test("activity menu widget: activity view icon", async (assert) => {
|
||||
]);
|
||||
const { env } = await start();
|
||||
await click(".o_menu_systray i[aria-label='Activities']");
|
||||
assert.containsN($, "button[title='Summary']", 2);
|
||||
await contains("button[title='Summary']", 2);
|
||||
const first = $(".o-mail-ActivityGroup:contains('res.partner') button[title='Summary']");
|
||||
const second = $(
|
||||
".o-mail-ActivityGroup:contains('mail.test.activity') button[title='Summary']"
|
||||
@@ -161,7 +163,7 @@ QUnit.test("activity menu widget: activity view icon", async (assert) => {
|
||||
},
|
||||
});
|
||||
await click(".o-mail-ActivityGroup:contains('mail.test.activity') button[title='Summary']");
|
||||
assert.containsNone($, ".o-dropdown-menu");
|
||||
await contains(".o-dropdown-menu", 0);
|
||||
await click(".o_menu_systray i[aria-label='Activities']");
|
||||
await click(".o-mail-ActivityGroup:contains('res.partner') button[title='Summary']");
|
||||
assert.verifySteps(["do_action:mail.test.activity", "do_action:res.partner"]);
|
||||
@@ -170,7 +172,7 @@ QUnit.test("activity menu widget: activity view icon", async (assert) => {
|
||||
QUnit.test("activity menu widget: close on messaging menu click", async (assert) => {
|
||||
await start();
|
||||
await click(".o_menu_systray i[aria-label='Activities']");
|
||||
assert.containsOnce($, ".o-mail-ActivityMenu");
|
||||
await contains(".o-mail-ActivityMenu");
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
assert.containsNone($, ".o-mail-ActivityMenu");
|
||||
await contains(".o-mail-ActivityMenu", 0);
|
||||
});
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
/** @odoo-module **/
|
||||
/* @odoo-module */
|
||||
|
||||
import { click, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
import { click, contains, insertText, start, startServer } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
import {
|
||||
editInput,
|
||||
editSelect,
|
||||
selectDropdownItem,
|
||||
patchWithCleanup,
|
||||
patchTimeZone,
|
||||
getFixture,
|
||||
} from "@web/../tests/helpers/utils";
|
||||
|
||||
import session from "web.session";
|
||||
import testUtils from "@web/../tests/legacy/helpers/test_utils";
|
||||
|
||||
@@ -56,172 +54,139 @@ QUnit.module("tracking value", {
|
||||
},
|
||||
});
|
||||
|
||||
QUnit.test("basic rendering of tracking value (float type)", async function (assert) {
|
||||
QUnit.test("basic rendering of tracking value (float type)", async function () {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({ float_field: 12.3 });
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
await editInput(target, "div[name=float_field] input", 45.67);
|
||||
await insertText("div[name=float_field] input", "45.67", { replace: true });
|
||||
await click(".o_form_button_save");
|
||||
assert.containsOnce(target, ".o-mail-Message-tracking");
|
||||
assert.containsOnce(target, ".o-mail-Message-trackingField");
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o-mail-Message-trackingField").textContent,
|
||||
"(Float)"
|
||||
);
|
||||
assert.containsOnce(target, ".o-mail-Message-trackingOld");
|
||||
assert.strictEqual(target.querySelector(".o-mail-Message-trackingOld").textContent, "12.30");
|
||||
assert.containsOnce(target, ".o-mail-Message-trackingSeparator");
|
||||
assert.containsOnce(target, ".o-mail-Message-trackingNew");
|
||||
assert.strictEqual(target.querySelector(".o-mail-Message-trackingNew").textContent, "45.67");
|
||||
await contains(".o-mail-Message-tracking");
|
||||
await contains(".o-mail-Message-trackingField");
|
||||
await contains(".o-mail-Message-trackingField:contains('(Float)')");
|
||||
await contains(".o-mail-Message-trackingOld");
|
||||
await contains(".o-mail-Message-trackingOld:contains('12.30')");
|
||||
await contains(".o-mail-Message-trackingSeparator");
|
||||
await contains(".o-mail-Message-trackingNew");
|
||||
await contains(".o-mail-Message-trackingNew:contains('45.67')");
|
||||
});
|
||||
|
||||
QUnit.test("rendering of tracked field of type float: from non-0 to 0", async function (assert) {
|
||||
QUnit.test("rendering of tracked field of type float: from non-0 to 0", async function () {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({
|
||||
float_field: 1,
|
||||
});
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
await editInput(target, "div[name=float_field] input", 0);
|
||||
await insertText("div[name=float_field] input", "0", { replace: true });
|
||||
await click(".o_form_button_save");
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o-mail-Message-tracking").textContent,
|
||||
"1.000.00(Float)"
|
||||
);
|
||||
await contains(".o-mail-Message-tracking:contains('1.000.00(Float)')");
|
||||
});
|
||||
|
||||
QUnit.test("rendering of tracked field of type float: from 0 to non-0", async function (assert) {
|
||||
QUnit.test("rendering of tracked field of type float: from 0 to non-0", async function () {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({
|
||||
float_field: 0,
|
||||
});
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
await editInput(target, "div[name=float_field] input", 1);
|
||||
await insertText("div[name=float_field] input", "1", { replace: true });
|
||||
await click(".o_form_button_save");
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o-mail-Message-tracking").textContent,
|
||||
"0.001.00(Float)"
|
||||
);
|
||||
await contains(".o-mail-Message-tracking:contains('0.001.00(Float)')");
|
||||
});
|
||||
|
||||
QUnit.test("rendering of tracked field of type integer: from non-0 to 0", async function (assert) {
|
||||
QUnit.test("rendering of tracked field of type integer: from non-0 to 0", async function () {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({
|
||||
integer_field: 1,
|
||||
});
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
await editInput(target, "div[name=integer_field] input", 0);
|
||||
await insertText("div[name=integer_field] input", "0", { replace: true });
|
||||
await click(".o_form_button_save");
|
||||
assert.strictEqual(target.querySelector(".o-mail-Message-tracking").textContent, "10(Integer)");
|
||||
await contains(".o-mail-Message-tracking:contains('10(Integer)')");
|
||||
});
|
||||
|
||||
QUnit.test("rendering of tracked field of type integer: from 0 to non-0", async function (assert) {
|
||||
QUnit.test("rendering of tracked field of type integer: from 0 to non-0", async function () {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({
|
||||
integer_field: 0,
|
||||
});
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
await editInput(target, "div[name=integer_field] input", 1);
|
||||
await insertText("div[name=integer_field] input", "1", { replace: true });
|
||||
await click(".o_form_button_save");
|
||||
assert.strictEqual(target.querySelector(".o-mail-Message-tracking").textContent, "01(Integer)");
|
||||
await contains(".o-mail-Message-tracking:contains('01(Integer)')");
|
||||
});
|
||||
|
||||
QUnit.test("rendering of tracked field of type monetary: from non-0 to 0", async function (assert) {
|
||||
QUnit.test("rendering of tracked field of type monetary: from non-0 to 0", async function () {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({
|
||||
monetary_field: 1,
|
||||
});
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
await editInput(target, "div[name=monetary_field] input", 0);
|
||||
await insertText("div[name=monetary_field] input", "0", { replace: true });
|
||||
await click(".o_form_button_save");
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o-mail-Message-tracking").textContent,
|
||||
"1.000.00(Monetary)"
|
||||
);
|
||||
await contains(".o-mail-Message-tracking:contains('1.000.00(Monetary)')");
|
||||
});
|
||||
|
||||
QUnit.test("rendering of tracked field of type monetary: from 0 to non-0", async function (assert) {
|
||||
QUnit.test("rendering of tracked field of type monetary: from 0 to non-0", async function () {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({
|
||||
monetary_field: 0,
|
||||
});
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
await editInput(target, "div[name=monetary_field] input", 1);
|
||||
await insertText("div[name=monetary_field] input", "1", { replace: true });
|
||||
await click(".o_form_button_save");
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o-mail-Message-tracking").textContent,
|
||||
"0.001.00(Monetary)"
|
||||
);
|
||||
await contains(".o-mail-Message-tracking:contains('0.001.00(Monetary)')");
|
||||
});
|
||||
|
||||
QUnit.test("rendering of tracked field of type boolean: from true to false", async function () {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({
|
||||
boolean_field: true,
|
||||
});
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
click(".o_field_boolean input").catch(() => {});
|
||||
await click(".o_form_button_save");
|
||||
await contains(".o-mail-Message-tracking:contains('YesNo(Boolean)')");
|
||||
});
|
||||
|
||||
QUnit.test("rendering of tracked field of type boolean: from false to true", async function () {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({});
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
click(".o_field_boolean input").catch(() => {});
|
||||
await click(".o_form_button_save");
|
||||
await contains(".o-mail-Message-tracking:contains('NoYes(Boolean)')");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"rendering of tracked field of type boolean: from true to false",
|
||||
async function (assert) {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({
|
||||
boolean_field: true,
|
||||
});
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
click(".o_field_boolean input").catch(() => {});
|
||||
await click(".o_form_button_save");
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o-mail-Message-tracking").textContent,
|
||||
"YesNo(Boolean)"
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"rendering of tracked field of type boolean: from false to true",
|
||||
async function (assert) {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({});
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
click(".o_field_boolean input").catch(() => {});
|
||||
await click(".o_form_button_save");
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o-mail-Message-tracking").textContent,
|
||||
"NoYes(Boolean)"
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"rendering of tracked field of type char: from a string to empty string",
|
||||
async function (assert) {
|
||||
async function () {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({
|
||||
char_field: "Marc",
|
||||
});
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
await editInput(target, "div[name=char_field] input", "");
|
||||
await insertText("div[name=char_field] input", "", { replace: true });
|
||||
await click(".o_form_button_save");
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o-mail-Message-tracking").textContent,
|
||||
"MarcNone(Char)"
|
||||
);
|
||||
await contains(".o-mail-Message-tracking:contains('MarcNone(Char)')");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"rendering of tracked field of type char: from empty string to a string",
|
||||
async function (assert) {
|
||||
async function () {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({
|
||||
char_field: "",
|
||||
});
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
await editInput(target, "div[name=char_field] input", "Marc");
|
||||
await insertText("div[name=char_field] input", "Marc", { replace: true });
|
||||
await click(".o_form_button_save");
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o-mail-Message-tracking").textContent,
|
||||
"NoneMarc(Char)"
|
||||
);
|
||||
await contains(".o-mail-Message-tracking:contains('NoneMarc(Char)')");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"rendering of tracked field of type date: from no date to a set date",
|
||||
async function (assert) {
|
||||
async function () {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({
|
||||
date_field: false,
|
||||
@@ -233,16 +198,13 @@ QUnit.test(
|
||||
["change"]
|
||||
);
|
||||
await click(".o_form_button_save");
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o-mail-Message-tracking").textContent,
|
||||
"None12/14/2018(Date)"
|
||||
);
|
||||
await contains(".o-mail-Message-tracking:contains('None12/14/2018(Date)')");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"rendering of tracked field of type date: from a set date to no date",
|
||||
async function (assert) {
|
||||
async function () {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({
|
||||
date_field: "2018-12-14",
|
||||
@@ -254,10 +216,7 @@ QUnit.test(
|
||||
["change"]
|
||||
);
|
||||
await click(".o_form_button_save");
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o-mail-Message-tracking").textContent,
|
||||
"12/14/2018None(Date)"
|
||||
);
|
||||
await contains(".o-mail-Message-tracking:contains('12/14/2018None(Date)')");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -276,20 +235,17 @@ QUnit.test(
|
||||
["change"]
|
||||
);
|
||||
await click(".o_form_button_save");
|
||||
await contains(".o-mail-Message-tracking:contains('None12/14/2018 13:42:28(Datetime)')");
|
||||
const savedRecord = pyEnv
|
||||
.getData()
|
||||
["mail.test.track.all"].records.find(({ id }) => id === mailTestTrackAllId1);
|
||||
assert.strictEqual(savedRecord.datetime_field, "2018-12-14 10:42:28");
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o-mail-Message-tracking").textContent,
|
||||
"None12/14/2018 13:42:28(Datetime)"
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"rendering of tracked field of type datetime: from a set date and time to no date and time",
|
||||
async function (assert) {
|
||||
async function () {
|
||||
patchTimeZone(180);
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({
|
||||
@@ -302,50 +258,35 @@ QUnit.test(
|
||||
["change"]
|
||||
);
|
||||
await click(".o_form_button_save");
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o-mail-Message-tracking").textContent,
|
||||
"12/14/2018 16:42:28None(Datetime)"
|
||||
);
|
||||
await contains(".o-mail-Message-tracking:contains('12/14/2018 16:42:28None(Datetime)')");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"rendering of tracked field of type text: from some text to empty",
|
||||
async function (assert) {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({
|
||||
text_field: "Marc",
|
||||
});
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
await editInput(target, "div[name=text_field] textarea", "");
|
||||
await click(".o_form_button_save");
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o-mail-Message-tracking").textContent,
|
||||
"MarcNone(Text)"
|
||||
);
|
||||
}
|
||||
);
|
||||
QUnit.test("rendering of tracked field of type text: from some text to empty", async function () {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({
|
||||
text_field: "Marc",
|
||||
});
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
await insertText("div[name=text_field] textarea", "", { replace: true });
|
||||
await click(".o_form_button_save");
|
||||
await contains(".o-mail-Message-tracking:contains('MarcNone(Text)')");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"rendering of tracked field of type text: from empty to some text",
|
||||
async function (assert) {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({
|
||||
text_field: "",
|
||||
});
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
await editInput(target, "div[name=text_field] textarea", "Marc");
|
||||
await click(".o_form_button_save");
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o-mail-Message-tracking").textContent,
|
||||
"NoneMarc(Text)"
|
||||
);
|
||||
}
|
||||
);
|
||||
QUnit.test("rendering of tracked field of type text: from empty to some text", async function () {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({
|
||||
text_field: "",
|
||||
});
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
await insertText("div[name=text_field] textarea", "Marc", { replace: true });
|
||||
await click(".o_form_button_save");
|
||||
await contains(".o-mail-Message-tracking:contains('NoneMarc(Text)')");
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"rendering of tracked field of type selection: from a selection to no selection",
|
||||
async function (assert) {
|
||||
async function () {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({
|
||||
selection_field: "first",
|
||||
@@ -353,58 +294,46 @@ QUnit.test(
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
await editSelect(target, "div[name=selection_field] select", false);
|
||||
await click(".o_form_button_save");
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o-mail-Message-tracking").textContent,
|
||||
"firstNone(Selection)"
|
||||
);
|
||||
await contains(".o-mail-Message-tracking:contains('firstNone(Selection)')");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"rendering of tracked field of type selection: from no selection to a selection",
|
||||
async function (assert) {
|
||||
async function () {
|
||||
const pyEnv = await startServer();
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({});
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
await editSelect(target, "div[name=selection_field] select", '"first"');
|
||||
await click(".o_form_button_save");
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o-mail-Message-tracking").textContent,
|
||||
"Nonefirst(Selection)"
|
||||
);
|
||||
await contains(".o-mail-Message-tracking:contains('Nonefirst(Selection)')");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"rendering of tracked field of type many2one: from having a related record to no related record",
|
||||
async function (assert) {
|
||||
async function () {
|
||||
const pyEnv = await startServer();
|
||||
const resPartnerId1 = pyEnv["res.partner"].create({ display_name: "Marc" });
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({
|
||||
many2one_field_id: resPartnerId1,
|
||||
});
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
await editInput(target, ".o_field_many2one_selection input", "");
|
||||
await insertText(".o_field_many2one_selection input", "", { replace: true });
|
||||
await click(".o_form_button_save");
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o-mail-Message-tracking").textContent,
|
||||
"MarcNone(Many2one)"
|
||||
);
|
||||
await contains(".o-mail-Message-tracking:contains('MarcNone(Many2one)')");
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"rendering of tracked field of type many2one: from no related record to having a related record",
|
||||
async function (assert) {
|
||||
async function () {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["res.partner"].create({ display_name: "Marc" });
|
||||
const mailTestTrackAllId1 = pyEnv["mail.test.track.all"].create({});
|
||||
await this.start({ res_id: mailTestTrackAllId1 });
|
||||
await selectDropdownItem(target, "many2one_field_id", "Marc");
|
||||
await click(".o_form_button_save");
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o-mail-Message-tracking").textContent,
|
||||
"NoneMarc(Many2one)"
|
||||
);
|
||||
await contains(".o-mail-Message-tracking:contains('NoneMarc(Many2one)')");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
Component,
|
||||
onMounted,
|
||||
onPatched,
|
||||
onWillDestroy,
|
||||
onWillPatch,
|
||||
onWillStart,
|
||||
onWillUnmount,
|
||||
@@ -128,7 +129,6 @@ export class EmojiPicker extends Component {
|
||||
static props = ["onSelect", "className?", "close?", "onClose?", "storeScroll?"];
|
||||
static template = "web.EmojiPicker";
|
||||
|
||||
recent = [];
|
||||
categories = null;
|
||||
emojis = null;
|
||||
shouldScrollElem = null;
|
||||
@@ -140,8 +140,20 @@ export class EmojiPicker extends Component {
|
||||
this.state = useState({
|
||||
activeEmojiIndex: 0,
|
||||
categoryId: null,
|
||||
recent: JSON.parse(browser.localStorage.getItem("web.emoji.frequent") || "{}"),
|
||||
searchStr: "",
|
||||
});
|
||||
const onStorage = (ev) => {
|
||||
if (ev.key === "web.emoji.frequent") {
|
||||
this.state.recent = ev.newValue ? JSON.parse(ev.newValue) : {};
|
||||
} else if (ev.key === null) {
|
||||
this.state.recent = {};
|
||||
}
|
||||
};
|
||||
browser.addEventListener("storage", onStorage);
|
||||
onWillDestroy(() => {
|
||||
browser.removeEventListener("storage", onStorage);
|
||||
});
|
||||
onWillStart(async () => {
|
||||
const { categories, emojis } = await loadEmoji();
|
||||
this.categories = categories;
|
||||
@@ -150,7 +162,6 @@ export class EmojiPicker extends Component {
|
||||
this.emojis.map((emoji) => [emoji.codepoints, emoji])
|
||||
);
|
||||
this.state.categoryId = this.categories[0]?.sortId;
|
||||
this.recent = JSON.parse(browser.localStorage.getItem("web.emoji.frequent") || "{}");
|
||||
this.recentCategory = {
|
||||
name: "Frequently used",
|
||||
displayName: _t("Frequently used"),
|
||||
@@ -211,7 +222,7 @@ export class EmojiPicker extends Component {
|
||||
}
|
||||
|
||||
get recentEmojis() {
|
||||
return Object.entries(this.recent)
|
||||
return Object.entries(this.state.recent)
|
||||
.sort(([, usage_1], [, usage_2]) => usage_2 - usage_1)
|
||||
.slice(0, 42)
|
||||
.map(([codepoints]) => this.emojiByCodepoints[codepoints]);
|
||||
@@ -289,9 +300,9 @@ export class EmojiPicker extends Component {
|
||||
selectEmoji(ev) {
|
||||
const codepoints = ev.currentTarget.dataset.codepoints;
|
||||
this.props.onSelect(codepoints);
|
||||
this.recent[codepoints] ??= 0;
|
||||
this.recent[codepoints]++;
|
||||
browser.localStorage.setItem("web.emoji.frequent", JSON.stringify(this.recent));
|
||||
this.state.recent[codepoints] ??= 0;
|
||||
this.state.recent[codepoints]++;
|
||||
browser.localStorage.setItem("web.emoji.frequent", JSON.stringify(this.state.recent));
|
||||
this.gridRef.el.scrollTop = 0;
|
||||
if (!ev.shiftKey) {
|
||||
this.props.close?.();
|
||||
|
||||
@@ -173,6 +173,8 @@ addons/spreadsheet/static/src/o_spreadsheet/o_spreadsheet.js
|
||||
# Whitelist mail
|
||||
!addons/mail/
|
||||
!addons/mail/**/*
|
||||
!addons/test_mail/
|
||||
!addons/test_mail/**/*
|
||||
|
||||
# Whitelist im_livechat
|
||||
!addons/im_livechat/
|
||||
|
||||
@@ -41,7 +41,8 @@
|
||||
"@pos_sale/*": ["addons/pos_sale/static/src/*"],
|
||||
"@pos_sale_product_configurator/*": ["addons/pos_sale_product_configurator/static/src/*"],
|
||||
"@pos_six/*": ["addons/pos_six/static/src/*"],
|
||||
"@pos_stripe/*": ["addons/pos_stripe/static/src/*"]
|
||||
"@pos_stripe/*": ["addons/pos_stripe/static/src/*"],
|
||||
"@test_mail/*": ["addons/test_mail/static/src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["**/*.js", "**/*.ts"],
|
||||
|
||||
@@ -69,7 +69,7 @@ export const feedback = [
|
||||
},
|
||||
{
|
||||
content: "Send the feedback",
|
||||
trigger: "button:contains(Send)",
|
||||
trigger: "button:contains(Send):not(:disabled)",
|
||||
},
|
||||
{
|
||||
content: "Check if feedback has been sent",
|
||||
|
||||
Reference in New Issue
Block a user