diff --git a/addons/account/static/tests/account_move_form_tests.js b/addons/account/static/tests/account_move_form_tests.js index e40c7efac4a..d50601008ee 100644 --- a/addons/account/static/tests/account_move_form_tests.js +++ b/addons/account/static/tests/account_move_form_tests.js @@ -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': - `
`, }; - 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" + ); }); - }); diff --git a/addons/calendar/static/tests/activity_menu_tests.js b/addons/calendar/static/tests/activity_menu_tests.js index 854c384df37..8d734434818 100644 --- a/addons/calendar/static/tests/activity_menu_tests.js +++ b/addons/calendar/static/tests/activity_menu_tests.js @@ -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"); diff --git a/addons/calendar/static/tests/activity_tests.js b/addons/calendar/static/tests/activity_tests.js index ed29eead240..ae13debe588 100644 --- a/addons/calendar/static/tests/activity_tests.js +++ b/addons/calendar/static/tests/activity_tests.js @@ -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"); }); diff --git a/addons/calendar/static/tests/activity_widget_tests.js b/addons/calendar/static/tests/activity_widget_tests.js index ba51161ad8a..f79c74538ba 100644 --- a/addons/calendar/static/tests/activity_widget_tests.js +++ b/addons/calendar/static/tests/activity_widget_tests.js @@ -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"); }); diff --git a/addons/im_livechat/static/tests/channel_invite_tests.js b/addons/im_livechat/static/tests/channel_invite_tests.js index 0089557aa1e..cbe3f635fbb 100644 --- a/addons/im_livechat/static/tests/channel_invite_tests.js +++ b/addons/im_livechat/static/tests/channel_invite_tests.js @@ -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")); }); diff --git a/addons/im_livechat/static/tests/chat_window_patch_tests.js b/addons/im_livechat/static/tests/chat_window_patch_tests.js index 8002cc2767d..8145ba31a25 100644 --- a/addons/im_livechat/static/tests/chat_window_patch_tests.js +++ b/addons/im_livechat/static/tests/chat_window_patch_tests.js @@ -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) => { diff --git a/addons/im_livechat/static/tests/composer_patch_tests.js b/addons/im_livechat/static/tests/composer_patch_tests.js index 1eec45f4a55..b73a6c2a0af 100644 --- a/addons/im_livechat/static/tests/composer_patch_tests.js +++ b/addons/im_livechat/static/tests/composer_patch_tests.js @@ -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? 😊" diff --git a/addons/im_livechat/static/tests/discuss_patch_tests.js b/addons/im_livechat/static/tests/discuss_patch_tests.js index e405a54ce27..cccaaafc381 100644 --- a/addons/im_livechat/static/tests/discuss_patch_tests.js +++ b/addons/im_livechat/static/tests/discuss_patch_tests.js @@ -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)"); } ); diff --git a/addons/im_livechat/static/tests/embed/autopopup_tests.js b/addons/im_livechat/static/tests/embed/autopopup_tests.js index ef58519f511..2e1ce014b66 100644 --- a/addons/im_livechat/static/tests/embed/autopopup_tests.js +++ b/addons/im_livechat/static/tests/embed/autopopup_tests.js @@ -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"); }); diff --git a/addons/im_livechat/static/tests/embed/feedback_panel_tests.js b/addons/im_livechat/static/tests/embed/feedback_panel_tests.js index 39a117c8402..b372b97216b 100644 --- a/addons/im_livechat/static/tests/embed/feedback_panel_tests.js +++ b/addons/im_livechat/static/tests/embed/feedback_panel_tests.js @@ -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?)"); }); diff --git a/addons/im_livechat/static/tests/embed/livechat_button_tests.js b/addons/im_livechat/static/tests/embed/livechat_button_tests.js index b4eee0de872..f1edae97507 100644 --- a/addons/im_livechat/static/tests/embed/livechat_button_tests.js +++ b/addons/im_livechat/static/tests/embed/livechat_button_tests.js @@ -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); }); diff --git a/addons/im_livechat/static/tests/embed/livechat_service_tests.js b/addons/im_livechat/static/tests/embed/livechat_service_tests.js index 6e002f38713..9e902494fa7 100644 --- a/addons/im_livechat/static/tests/embed/livechat_service_tests.js +++ b/addons/im_livechat/static/tests/embed/livechat_service_tests.js @@ -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)"); }); diff --git a/addons/im_livechat/static/tests/embed/livechat_session_tests.js b/addons/im_livechat/static/tests/embed/livechat_session_tests.js index da4c83dab3c..3a52c24712f 100644 --- a/addons/im_livechat/static/tests/embed/livechat_session_tests.js +++ b/addons/im_livechat/static/tests/embed/livechat_session_tests.js @@ -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 diff --git a/addons/im_livechat/static/tests/embed/transcript_sender_tests.js b/addons/im_livechat/static/tests/embed/transcript_sender_tests.js index d0fcd926c0b..54123e27596 100644 --- a/addons/im_livechat/static/tests/embed/transcript_sender_tests.js +++ b/addons/im_livechat/static/tests/embed/transcript_sender_tests.js @@ -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.)"); }); diff --git a/addons/im_livechat/static/tests/messaging_menu_patch_tests.js b/addons/im_livechat/static/tests/messaging_menu_patch_tests.js index d40c8796887..19576e44e6b 100644 --- a/addons/im_livechat/static/tests/messaging_menu_patch_tests.js +++ b/addons/im_livechat/static/tests/messaging_menu_patch_tests.js @@ -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); }); diff --git a/addons/im_livechat/static/tests/mobile_messaging_menu_patch_tests.js b/addons/im_livechat/static/tests/mobile_messaging_menu_patch_tests.js index 0105c3460bf..ee65f396d90 100644 --- a/addons/im_livechat/static/tests/mobile_messaging_menu_patch_tests.js +++ b/addons/im_livechat/static/tests/mobile_messaging_menu_patch_tests.js @@ -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)"); +}); diff --git a/addons/im_livechat/static/tests/sidebar_patch_tests.js b/addons/im_livechat/static/tests/sidebar_patch_tests.js index 6ea3f43bba3..589db4c154d 100644 --- a/addons/im_livechat/static/tests/sidebar_patch_tests.js +++ b/addons/im_livechat/static/tests/sidebar_patch_tests.js @@ -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)"); }); diff --git a/addons/im_livechat/static/tests/suggestions_tests.js b/addons/im_livechat/static/tests/suggestions_tests.js index 201183b662e..c96fd46fbd8 100644 --- a/addons/im_livechat/static/tests/suggestions_tests.js +++ b/addons/im_livechat/static/tests/suggestions_tests.js @@ -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)"); }); diff --git a/addons/im_livechat/static/tests/thread_model_patch_tests.js b/addons/im_livechat/static/tests/thread_model_patch_tests.js index 25a26469e47..3a5dffef76d 100644 --- a/addons/im_livechat/static/tests/thread_model_patch_tests.js +++ b/addons/im_livechat/static/tests/thread_model_patch_tests.js @@ -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']"); }); diff --git a/addons/mail/static/src/core/common/attachment_model.js b/addons/mail/static/src/core/common/attachment_model.js index 3c8a730e0ee..66554a80bab 100644 --- a/addons/mail/static/src/core/common/attachment_model.js +++ b/addons/mail/static/src/core/common/attachment_model.js @@ -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, } ); } diff --git a/addons/mail/static/src/core/common/composer.js b/addons/mail/static/src/core/common/composer.js index 76afb4d11af..1814efbedcc 100644 --- a/addons/mail/static/src/core/common/composer.js +++ b/addons/mail/static/src/core/common/composer.js @@ -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; diff --git a/addons/mail/static/src/core/common/discuss.xml b/addons/mail/static/src/core/common/discuss.xml index e6e40d5f22e..ef60cbc2d80 100644 --- a/addons/mail/static/src/core/common/discuss.xml +++ b/addons/mail/static/src/core/common/discuss.xml @@ -39,7 +39,7 @@ /> -