diff --git a/addons/mail/static/tests/helpers/test_utils.js b/addons/mail/static/tests/helpers/test_utils.js index 00ca735d2c9..59b5c2a57f8 100644 --- a/addons/mail/static/tests/helpers/test_utils.js +++ b/addons/mail/static/tests/helpers/test_utils.js @@ -953,6 +953,7 @@ async function start(param0 = {}) { createMessagingMenuComponent: getCreateMessagingMenuComponent({ env: testEnv, widget }), createNotificationListComponent: getCreateNotificationListComponent({ env: testEnv, modelManager, widget }), createThreadViewComponent: getCreateThreadViewComponent({ afterEvent, env: testEnv, widget }), + insertText, messaging: modelManager.messaging, openDiscuss, }; @@ -1007,6 +1008,25 @@ function pasteFiles(el, files) { el.dispatchEvent(ev); } +//------------------------------------------------------------------------------ +// Public: input utilities +//------------------------------------------------------------------------------ + +/** + * @param {string} selector + * @param {string} content + */ + async function insertText(selector, content) { + await afterNextRender(() => { + document.querySelector(selector).focus(); + for (const char of content) { + document.execCommand('insertText', false, char); + document.querySelector(selector).dispatchEvent(new window.KeyboardEvent('keydown', { key: char })); + document.querySelector(selector).dispatchEvent(new window.KeyboardEvent('keyup', { key: char })); + } + }); +} + //------------------------------------------------------------------------------ // Export //------------------------------------------------------------------------------ diff --git a/addons/mail/static/tests/qunit_suite_tests/components/chat_window_manager_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/chat_window_manager_tests.js index 67da32720cf..3f28a1c16d6 100644 --- a/addons/mail/static/tests/qunit_suite_tests/components/chat_window_manager_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/components/chat_window_manager_tests.js @@ -756,7 +756,7 @@ QUnit.test('chat window: close on ESCAPE', async function (assert) { const pyEnv = await startServer(); pyEnv['res.partner'].create({ name: "TestPartner" }); pyEnv['mail.channel'].create({ is_minimized: true }); - await this.start({ + const { insertText } = await this.start({ mockRPC(route, args) { if (args.method === 'channel_fold') { assert.step(`rpc:channel_fold/${args.kwargs.state}`); @@ -794,14 +794,7 @@ QUnit.test('chat window: close on ESCAPE', async function (assert) { "chat window should still be opened after pressing escape on emojis button" ); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "@"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', "@"); assert.hasClass( document.querySelector('.o_ComposerSuggestionList_list'), 'show', diff --git a/addons/mail/static/tests/qunit_suite_tests/components/composer_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/composer_tests.js index 768ac8bbf0c..6234643ba1e 100644 --- a/addons/mail/static/tests/qunit_suite_tests/components/composer_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/components/composer_tests.js @@ -289,7 +289,7 @@ QUnit.test('display canned response suggestions on typing ":"', async function ( const pyEnv = await startServer(); const mailChanelId1 = pyEnv['mail.channel'].create(); pyEnv['mail.shortcode'].create({ source: "hello", substitution: "Hello! How are you?" }); - const { createComposerComponent, messaging } = await start(); + const { createComposerComponent, insertText, messaging } = await start(); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: mailChanelId1, model: 'mail.channel', @@ -301,14 +301,7 @@ QUnit.test('display canned response suggestions on typing ":"', async function ( '.o_ComposerSuggestionList_list', "Canned responses suggestions list should not be present" ); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, ":"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', ':'); assert.hasClass( document.querySelector('.o_ComposerSuggestionList_list'), 'show', @@ -322,7 +315,7 @@ QUnit.test('use a canned response', async function (assert) { const pyEnv = await startServer(); const mailChanelId1 = pyEnv['mail.channel'].create(); pyEnv['mail.shortcode'].create({ source: "hello", substitution: "Hello! How are you?" }); - const { createComposerComponent, messaging } = await start(); + const { createComposerComponent, insertText, messaging } = await start(); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: mailChanelId1, model: 'mail.channel', @@ -339,14 +332,7 @@ QUnit.test('use a canned response', async function (assert) { "", "text content of composer should be empty initially" ); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, ":"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', ':'); assert.containsOnce( document.body, '.o_ComposerSuggestion', @@ -368,7 +354,7 @@ QUnit.test('use a canned response some text', async function (assert) { const pyEnv = await startServer(); const mailChanelId1 = pyEnv['mail.channel'].create(); pyEnv['mail.shortcode'].create({ source: "hello", substitution: "Hello! How are you?" }); - const { createComposerComponent, messaging } = await start(); + const { createComposerComponent, insertText, messaging } = await start(); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: mailChanelId1, model: 'mail.channel', @@ -385,22 +371,13 @@ QUnit.test('use a canned response some text', async function (assert) { "", "text content of composer should be empty initially" ); - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - await afterNextRender(() => - document.execCommand('insertText', false, "bluhbluh ") - ); + await insertText('.o_ComposerTextInput_textarea', "bluhbluh "); assert.strictEqual( document.querySelector(`.o_ComposerTextInput_textarea`).value, "bluhbluh ", "text content of composer should have content" ); - await afterNextRender(() => { - document.execCommand('insertText', false, ":"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', ':'); assert.containsOnce( document.body, '.o_ComposerSuggestion', @@ -422,7 +399,7 @@ QUnit.test('add an emoji after a canned response', async function (assert) { const pyEnv = await startServer(); const mailChanelId1 = pyEnv['mail.channel'].create(); pyEnv['mail.shortcode'].create({ source: "hello", substitution: "Hello! How are you?" }); - const { createComposerComponent, messaging } = await start(); + const { createComposerComponent, insertText, messaging } = await start(); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: mailChanelId1, model: 'mail.channel', @@ -439,14 +416,7 @@ QUnit.test('add an emoji after a canned response', async function (assert) { "", "text content of composer should be empty initially" ); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, ":"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', ':'); assert.containsOnce( document.body, '.o_ComposerSuggestion', @@ -480,7 +450,7 @@ QUnit.test('display channel mention suggestions on typing "#"', async function ( const pyEnv = await startServer(); const mailChanelId1 = pyEnv['mail.channel'].create({ name: "General", public: "groups" }); - const { createComposerComponent, messaging } = await start(); + const { createComposerComponent, insertText, messaging } = await start(); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: mailChanelId1, model: 'mail.channel', @@ -492,14 +462,7 @@ QUnit.test('display channel mention suggestions on typing "#"', async function ( '.o_ComposerSuggestionList_list', "channel mention suggestions list should not be present" ); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "#"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', "#"); assert.hasClass( document.querySelector('.o_ComposerSuggestionList_list'), 'show', @@ -512,7 +475,7 @@ QUnit.test('mention a channel', async function (assert) { const pyEnv = await startServer(); const mailChanelId1 = pyEnv['mail.channel'].create({ name: "General", public: "groups" }); - const { createComposerComponent, messaging } = await start(); + const { createComposerComponent, insertText, messaging } = await start(); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: mailChanelId1, model: 'mail.channel', @@ -529,14 +492,7 @@ QUnit.test('mention a channel', async function (assert) { "", "text content of composer should be empty initially" ); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "#"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', "#"); assert.containsOnce( document.body, '.o_ComposerSuggestion', @@ -557,7 +513,7 @@ QUnit.test('mention a channel after some text', async function (assert) { const pyEnv = await startServer(); const mailChanelId1 = pyEnv['mail.channel'].create({ name: "General", public: "groups" }); - const { createComposerComponent, messaging } = await start(); + const { createComposerComponent, insertText, messaging } = await start(); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: mailChanelId1, model: 'mail.channel', @@ -583,13 +539,7 @@ QUnit.test('mention a channel after some text', async function (assert) { "bluhbluh ", "text content of composer should have content" ); - await afterNextRender(() => { - document.execCommand('insertText', false, "#"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', "#"); assert.containsOnce( document.body, '.o_ComposerSuggestion', @@ -610,7 +560,7 @@ QUnit.test('add an emoji after a channel mention', async function (assert) { const pyEnv = await startServer(); const mailChanelId1 = pyEnv['mail.channel'].create({ name: "General", public: "groups" }); - const { createComposerComponent, messaging } = await start(); + const { createComposerComponent, insertText, messaging } = await start(); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: mailChanelId1, model: 'mail.channel', @@ -627,14 +577,7 @@ QUnit.test('add an emoji after a channel mention', async function (assert) { "", "text content of composer should be empty initially" ); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "#"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', "#"); assert.containsOnce( document.body, '.o_ComposerSuggestion', @@ -668,7 +611,7 @@ QUnit.test('display command suggestions on typing "/"', async function (assert) const pyEnv = await startServer(); const mailChanelId1 = pyEnv['mail.channel'].create({ channel_type: 'channel' }); - const { createComposerComponent, messaging } = await start(); + const { createComposerComponent, insertText, messaging } = await start(); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: mailChanelId1, model: 'mail.channel', @@ -680,14 +623,7 @@ QUnit.test('display command suggestions on typing "/"', async function (assert) '.o_ComposerSuggestionList_list', "command suggestions list should not be present" ); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "/"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', "/"); assert.hasClass( document.querySelector('.o_ComposerSuggestionList_list'), 'show', @@ -700,7 +636,7 @@ QUnit.test('do not send typing notification on typing "/" command', async functi const pyEnv = await startServer(); const mailChannelId1 = pyEnv['mail.channel'].create(); - await start({ + const { insertText } = await start({ autoOpenDiscuss: true, discuss: { params: { @@ -716,14 +652,7 @@ QUnit.test('do not send typing notification on typing "/" command', async functi }, }); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "/"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', "/"); assert.verifySteps([], "No rpc done"); }); @@ -732,7 +661,7 @@ QUnit.test('do not send typing notification on typing after selecting suggestion const pyEnv = await startServer(); const mailChannelId1 = pyEnv['mail.channel'].create(); - await start({ + const { insertText } = await start({ autoOpenDiscuss: true, discuss: { params: { @@ -748,35 +677,20 @@ QUnit.test('do not send typing notification on typing after selecting suggestion }, }); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "/"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', "/"); await afterNextRender(() => document.querySelector('.o_ComposerSuggestion').click() ); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, " is user?"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', " is user?"); assert.verifySteps([], "No rpc done"); }); QUnit.test('use a command for a specific channel type', async function (assert) { assert.expect(3); - const pyEnv = await startServer(); const mailChanelId1 = pyEnv['mail.channel'].create({ channel_type: 'chat' }); - const { createComposerComponent, messaging } = await start(); + const { createComposerComponent, insertText, messaging } = await start(); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: mailChanelId1, model: 'mail.channel', @@ -793,14 +707,7 @@ QUnit.test('use a command for a specific channel type', async function (assert) "", "text content of composer should be empty initially" ); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "/"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', "/"); await afterNextRender(() => document.querySelector('.o_ComposerSuggestion').click() ); @@ -816,7 +723,7 @@ QUnit.test('command suggestion should only open if command is the first characte const pyEnv = await startServer(); const mailChanelId1 = pyEnv['mail.channel'].create({ channel_type: 'channel' }); - const { createComposerComponent, messaging } = await start(); + const { createComposerComponent, insertText, messaging } = await start(); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: mailChanelId1, model: 'mail.channel', @@ -832,22 +739,13 @@ QUnit.test('command suggestion should only open if command is the first characte "", "text content of composer should be empty initially" ); - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - await afterNextRender(() => - document.execCommand('insertText', false, "bluhbluh ") - ); + await insertText('.o_ComposerTextInput_textarea', "bluhbluh "); assert.strictEqual( document.querySelector(`.o_ComposerTextInput_textarea`).value, "bluhbluh ", "text content of composer should have content" ); - await afterNextRender(() => { - document.execCommand('insertText', false, "/"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', "/"); assert.containsNone( document.body, '.o_ComposerSuggestion', @@ -860,7 +758,7 @@ QUnit.test('add an emoji after a command', async function (assert) { const pyEnv = await startServer(); const mailChanelId1 = pyEnv['mail.channel'].create({ channel_type: 'channel' }); - const { createComposerComponent, messaging } = await start(); + const { createComposerComponent, insertText, messaging } = await start(); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: mailChanelId1, model: 'mail.channel', @@ -877,14 +775,7 @@ QUnit.test('add an emoji after a command', async function (assert) { "", "text content of composer should be empty initially" ); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "/"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', "/"); await afterNextRender(() => document.querySelector('.o_ComposerSuggestion').click() ); @@ -917,7 +808,7 @@ QUnit.test('display partner mention suggestions on typing "@"', async function ( pyEnv['res.partner'].create({ email: "testpartner2@odoo.com", name: "TestPartner2" }); pyEnv['res.users'].create({ partner_id: resPartnerId1 }); const mailChannelId1 = pyEnv['mail.channel'].create(); - const { createComposerComponent, messaging } = await start(); + const { createComposerComponent, insertText, messaging } = await start(); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: mailChannelId1, model: 'mail.channel', @@ -929,14 +820,7 @@ QUnit.test('display partner mention suggestions on typing "@"', async function ( '.o_ComposerSuggestionList_list', "mention suggestions list should not be present" ); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "@"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', "@"); assert.hasClass( document.querySelector('.o_ComposerSuggestionList_list'), 'show', @@ -955,7 +839,7 @@ QUnit.test('mention a partner', async function (assert) { const pyEnv = await startServer(); pyEnv['res.partner'].create({ email: "testpartner@odoo.com", name: "TestPartner" }); const mailChannelId1 = pyEnv['mail.channel'].create(); - const { createComposerComponent, messaging } = await start(); + const { createComposerComponent, insertText, messaging } = await start(); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: mailChannelId1, model: 'mail.channel', @@ -972,24 +856,7 @@ QUnit.test('mention a partner', async function (assert) { "", "text content of composer should be empty initially" ); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "@"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - document.execCommand('insertText', false, "T"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - document.execCommand('insertText', false, "e"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', '@Te'); assert.containsOnce( document.body, '.o_ComposerSuggestion', @@ -1011,7 +878,7 @@ QUnit.test('mention a partner after some text', async function (assert) { const pyEnv = await startServer(); pyEnv['res.partner'].create({ email: "testpartner@odoo.com", name: "TestPartner" }); const mailChannelId1 = pyEnv['mail.channel'].create(); - const { createComposerComponent, messaging } = await start(); + const { createComposerComponent, insertText, messaging } = await start(); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: mailChannelId1, model: 'mail.channel', @@ -1037,24 +904,7 @@ QUnit.test('mention a partner after some text', async function (assert) { "bluhbluh ", "text content of composer should have content" ); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "@"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - document.execCommand('insertText', false, "T"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - document.execCommand('insertText', false, "e"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', "@Te"); assert.containsOnce( document.body, '.o_ComposerSuggestion', @@ -1076,7 +926,7 @@ QUnit.test('add an emoji after a partner mention', async function (assert) { const pyEnv = await startServer(); pyEnv['res.partner'].create({ email: "testpartner@odoo.com", name: "TestPartner" }); const mailChannelId1 = pyEnv['mail.channel'].create(); - const { createComposerComponent, messaging } = await start(); + const { createComposerComponent, insertText, messaging } = await start(); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: mailChannelId1, model: 'mail.channel', @@ -1093,24 +943,7 @@ QUnit.test('add an emoji after a partner mention', async function (assert) { "", "text content of composer should be empty initially" ); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "@"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - document.execCommand('insertText', false, "T"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - document.execCommand('insertText', false, "e"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', "@Te"); assert.containsOnce( document.body, '.o_ComposerSuggestion', @@ -1343,7 +1176,7 @@ QUnit.test('current partner notify is typing to other thread members', async fun // with a random unique id that will be referenced in the test const pyEnv = await startServer(); const mailChannelId1 = pyEnv['mail.channel'].create(); - await start({ + const { insertText } = await start({ autoOpenDiscuss: true, discuss: { params: { @@ -1359,11 +1192,7 @@ QUnit.test('current partner notify is typing to other thread members', async fun }, }); - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "a"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown', { key: 'a' })); - + await insertText('.o_ComposerTextInput_textarea', 'a'); assert.verifySteps( ['notify_typing:true'], "should have notified current partner typing status" @@ -1377,7 +1206,7 @@ QUnit.test('current partner is typing should not translate on textual typing sta // with a random unique id that will be referenced in the test const pyEnv = await startServer(); const mailChannelId1 = pyEnv['mail.channel'].create(); - await start({ + const { insertText } = await start({ autoOpenDiscuss: true, discuss: { params: { @@ -1394,10 +1223,7 @@ QUnit.test('current partner is typing should not translate on textual typing sta }, }); - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "a"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown', { key: 'a' })); + await insertText('.o_ComposerTextInput_textarea', 'a'); assert.verifySteps( ['notify_typing:true'], @@ -1419,7 +1245,7 @@ QUnit.test('current partner notify no longer is typing to thread members after 5 // with a random unique id that will be referenced in the test const pyEnv = await startServer(); const mailChannelId1 = pyEnv['mail.channel'].create(); - const { env } = await start({ + const { env, insertText } = await start({ autoOpenDiscuss: true, discuss: { params: { @@ -1436,10 +1262,7 @@ QUnit.test('current partner notify no longer is typing to thread members after 5 }, }); - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "a"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown', { key: 'a' })); + await insertText('.o_ComposerTextInput_textarea', 'a'); assert.verifySteps( ['notify_typing:true'], @@ -1460,7 +1283,7 @@ QUnit.test('current partner notify is typing again to other members every 50s of // with a random unique id that will be referenced in the test const pyEnv = await startServer(); const mailChannelId1 = pyEnv['mail.channel'].create(); - const { env } = await start({ + const { env, insertText } = await start({ autoOpenDiscuss: true, discuss: { params: { @@ -1477,10 +1300,7 @@ QUnit.test('current partner notify is typing again to other members every 50s of }, }); - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "a"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown', { key: 'a' })); + await insertText('.o_ComposerTextInput_textarea', "a"); assert.verifySteps( ['notify_typing:true'], "should have notified current partner is typing" @@ -1490,9 +1310,7 @@ QUnit.test('current partner notify is typing again to other members every 50s of let totalTimeElapsed = 0; const elapseTickTime = 2.5 * 1000; while (totalTimeElapsed < 50 * 1000) { - document.execCommand('insertText', false, "a"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown', { key: 'a' })); + await insertText('.o_ComposerTextInput_textarea', 'a'); totalTimeElapsed += elapseTickTime; await env.testUtils.advanceTime(elapseTickTime); } diff --git a/addons/mail/static/tests/qunit_suite_tests/components/discuss_inbox_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/discuss_inbox_tests.js index ee6651d2b26..4c8f9cb70f3 100644 --- a/addons/mail/static/tests/qunit_suite_tests/components/discuss_inbox_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/components/discuss_inbox_tests.js @@ -44,7 +44,7 @@ QUnit.test('reply: discard on pressing escape', async function (assert) { notification_type: 'inbox', res_partner_id: pyEnv.currentPartnerId, }); - await this.start({ + const { insertText } = await this.start({ waitUntilEvent: { eventName: 'o-thread-view-hint-processed', message: "should wait until inbox displayed its messages", @@ -96,24 +96,7 @@ QUnit.test('reply: discard on pressing escape', async function (assert) { "reply composer should still be opened after pressing escape on emojis button" ); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "@"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - document.execCommand('insertText', false, "T"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - document.execCommand('insertText', false, "e"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', "@Te"); assert.containsOnce( document.body, '.o_ComposerSuggestion', diff --git a/addons/mail/static/tests/qunit_suite_tests/components/discuss_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/discuss_tests.js index 3f52cda3e85..3ceec272d5f 100644 --- a/addons/mail/static/tests/qunit_suite_tests/components/discuss_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/components/discuss_tests.js @@ -2533,7 +2533,7 @@ QUnit.test('composer state: text save and restore', async function (assert) { { name: "General" }, { name: "Special" }, ]); - await this.start({ + const { insertText } = await this.start({ discuss: { params: { default_active_id: `mail.channel_${mailChannelId1}`, @@ -2541,21 +2541,11 @@ QUnit.test('composer state: text save and restore', async function (assert) { }, }); // Write text in composer for #general - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "A message"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('input')); - }); + await insertText('.o_ComposerTextInput_textarea', "A message"); await afterNextRender(() => document.querySelector(`.o_DiscussSidebarCategoryItem[data-thread-name="Special"]`).click() ); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "An other message"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('input')); - }); + await insertText('.o_ComposerTextInput_textarea', "An other message"); // Switch back to #general await afterNextRender(() => document.querySelector(`.o_DiscussSidebarCategoryItem[data-thread-name="General"]`).click() diff --git a/addons/mail/static/tests/qunit_suite_tests/components/thread_view_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/thread_view_tests.js index 6945d0b5725..b69e85fd2a9 100644 --- a/addons/mail/static/tests/qunit_suite_tests/components/thread_view_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/components/thread_view_tests.js @@ -1084,7 +1084,7 @@ QUnit.test('Post a message containing an email address followed by a mention on email: "testpartner@odoo.com", name: "TestPartner", }); - const { createThreadViewComponent, messaging } = await start({ data: this.data }); + const { createThreadViewComponent, insertText, messaging } = await start({ data: this.data }); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: 11, model: 'mail.channel', @@ -1095,17 +1095,8 @@ QUnit.test('Post a message containing an email address followed by a mention on thread: link(thread), }); await createThreadViewComponent(threadViewer.threadView); - document.querySelector('.o_ComposerTextInput_textarea').focus(); - await afterNextRender(() => document.execCommand('insertText', false, "email@odoo.com\n")); - await afterNextRender(() => { - ["@", "T", "e"].forEach((char)=>{ - document.execCommand('insertText', false, char); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); - }); + await insertText('.o_ComposerTextInput_textarea', "email@odoo.com\n"); + await insertText('.o_ComposerTextInput_textarea', "@Te"); await afterNextRender(() => document.querySelector('.o_ComposerSuggestion').click() ); @@ -1128,7 +1119,7 @@ QUnit.test(`Mention a partner with special character (e.g. apostrophe ')`, async email: "usatyi@example.com", name: "Pynya's spokesman", }); - const { createThreadViewComponent, messaging } = await start({ data: this.data }); + const { createThreadViewComponent, insertText, messaging } = await start({ data: this.data }); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: 11, model: 'mail.channel', @@ -1139,16 +1130,7 @@ QUnit.test(`Mention a partner with special character (e.g. apostrophe ')`, async thread: link(thread), }); await createThreadViewComponent(threadViewer.threadView); - document.querySelector('.o_ComposerTextInput_textarea').focus(); - await afterNextRender(() => { - ["@", "P", "y", "n"].forEach((char)=>{ - document.execCommand('insertText', false, char); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); - }); + await insertText('.o_ComposerTextInput_textarea', "@Pyn"); await afterNextRender(() => document.querySelector('.o_ComposerSuggestion').click() ); @@ -1177,7 +1159,7 @@ QUnit.test('mention 2 different partners that have the same name', async functio name: "TestPartner", }, ); - const { createThreadViewComponent, messaging } = await start({ data: this.data }); + const { createThreadViewComponent, insertText, messaging } = await start({ data: this.data }); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: 11, model: 'mail.channel', @@ -1188,26 +1170,9 @@ QUnit.test('mention 2 different partners that have the same name', async functio thread: link(thread), }); await createThreadViewComponent(threadViewer.threadView); - document.querySelector('.o_ComposerTextInput_textarea').focus(); - await afterNextRender(() => { - ["@", "T", "e"].forEach((char)=>{ - document.execCommand('insertText', false, char); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); - }); + await insertText('.o_ComposerTextInput_textarea', "@Te"); await afterNextRender(() => document.querySelectorAll('.o_ComposerSuggestion')[0].click()); - await afterNextRender(() => { - ["@", "T", "e"].forEach((char)=>{ - document.execCommand('insertText', false, char); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); - }); + await insertText('.o_ComposerTextInput_textarea', "@Te"); await afterNextRender(() => document.querySelectorAll('.o_ComposerSuggestion')[1].click()); await afterNextRender(() => document.querySelector('.o_Composer_buttonSend').click()); assert.containsOnce(document.body, '.o_Message_content', 'should have one message after posting it'); @@ -1230,7 +1195,7 @@ QUnit.test('mention a channel with space in the name', async function (assert) { id: 7, name: "General good boy", }); - const { createThreadViewComponent, messaging } = await start({ data: this.data }); + const { createThreadViewComponent, insertText, messaging } = await start({ data: this.data }); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: 7, model: 'mail.channel', @@ -1242,14 +1207,7 @@ QUnit.test('mention a channel with space in the name', async function (assert) { }); await createThreadViewComponent(threadViewer.threadView); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "#"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', "#"); await afterNextRender(() => document.querySelector('.o_ComposerSuggestion').click() ); @@ -1275,7 +1233,7 @@ QUnit.test('mention a channel with "&" in the name', async function (assert) { id: 7, name: "General & good", }); - const { createThreadViewComponent, messaging } = await start({ data: this.data }); + const { createThreadViewComponent, insertText, messaging } = await start({ data: this.data }); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: 7, model: 'mail.channel', @@ -1287,14 +1245,7 @@ QUnit.test('mention a channel with "&" in the name', async function (assert) { }); await createThreadViewComponent(threadViewer.threadView); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "#"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', "#"); await afterNextRender(() => document.querySelector('.o_ComposerSuggestion').click() ); @@ -1320,7 +1271,7 @@ QUnit.test('mention a channel on a second line when the first line contains #', id: 7, name: "General good", }); - const { createThreadViewComponent, messaging } = await start({ data: this.data }); + const { createThreadViewComponent, insertText, messaging } = await start({ data: this.data }); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: 7, model: 'mail.channel', @@ -1332,14 +1283,8 @@ QUnit.test('mention a channel on a second line when the first line contains #', }); await createThreadViewComponent(threadViewer.threadView); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "#blabla\n#"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', "#blabla\n"); + await insertText('.o_ComposerTextInput_textarea', "#"); await afterNextRender(() => { document.querySelector('.o_ComposerSuggestion').click(); }); @@ -1365,7 +1310,7 @@ QUnit.test('mention a channel when replacing the space after the mention by anot id: 7, name: "General good", }); - const { createThreadViewComponent, messaging } = await start({ data: this.data }); + const { createThreadViewComponent, insertText, messaging } = await start({ data: this.data }); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: 7, model: 'mail.channel', @@ -1377,26 +1322,13 @@ QUnit.test('mention a channel when replacing the space after the mention by anot }); await createThreadViewComponent(threadViewer.threadView); - await afterNextRender(() => { - document.querySelector(`.o_ComposerTextInput_textarea`).focus(); - document.execCommand('insertText', false, "#"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + await insertText('.o_ComposerTextInput_textarea', "#"); await afterNextRender(() => { document.querySelector('.o_ComposerSuggestion').click(); }); - await afterNextRender(() => { - const text = document.querySelector(`.o_ComposerTextInput_textarea`).value; - document.querySelector(`.o_ComposerTextInput_textarea`).value = text.slice(0, -1); - document.execCommand('insertText', false, ", test"); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); + const text = document.querySelector(`.o_ComposerTextInput_textarea`).value; + document.querySelector(`.o_ComposerTextInput_textarea`).value = text.slice(0, -1); + await insertText('.o_ComposerTextInput_textarea', ", test"); await afterNextRender(() => { document.querySelector('.o_Composer_buttonSend').click(); }); @@ -1426,7 +1358,7 @@ QUnit.test('mention 2 different channels that have the same name', async functio name: "my channel", }, ); - const { createThreadViewComponent, messaging } = await start({ data: this.data }); + const { createThreadViewComponent, insertText, messaging } = await start({ data: this.data }); const thread = messaging.models['Thread'].findFromIdentifyingData({ id: 11, model: 'mail.channel', @@ -1438,25 +1370,9 @@ QUnit.test('mention 2 different channels that have the same name', async functio }); await createThreadViewComponent(threadViewer.threadView); document.querySelector('.o_ComposerTextInput_textarea').focus(); - await afterNextRender(() => { - ["#", "m", "y"].forEach((char)=>{ - document.execCommand('insertText', false, char); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); - }); + await insertText('.o_ComposerTextInput_textarea', "#my"); await afterNextRender(() => document.querySelectorAll('.o_ComposerSuggestion')[0].click()); - await afterNextRender(() => { - ["#", "m", "y"].forEach((char)=>{ - document.execCommand('insertText', false, char); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keydown')); - document.querySelector(`.o_ComposerTextInput_textarea`) - .dispatchEvent(new window.KeyboardEvent('keyup')); - }); - }); + await insertText('.o_ComposerTextInput_textarea', "#my"); await afterNextRender(() => document.querySelectorAll('.o_ComposerSuggestion')[1].click()); await afterNextRender(() => document.querySelector('.o_Composer_buttonSend').click()); assert.containsOnce(document.body, '.o_Message_content', 'should have one message after posting it');