[FIX] mail: allow composer text input to send message with ctrl+enter
Also allow meta+enter task-2296863 closes odoo/odoo#57050 X-original-commit: 6bad3666be3d3631eaadae409d0cabcdd02661a8 Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
This commit is contained in:
committed by
Alexandre Kühn
parent
b840bf3e9f
commit
09c77f6c89
@@ -14,9 +14,9 @@
|
||||
t-att-class="{ 'o-bordered': chatter.hasExternalBorder }"
|
||||
composerLocalId="chatter.thread.composer.localId"
|
||||
hasMentionSuggestionsBelowPosition="true"
|
||||
hasTextInputSendOnEnterEnabled="false"
|
||||
isCompact="false"
|
||||
isExpandable="true"
|
||||
textInputSendShortcuts="['ctrl-enter', 'meta-enter']"
|
||||
t-on-o-message-posted="_onComposerMessagePosted"
|
||||
t-ref="composer"
|
||||
/>
|
||||
|
||||
@@ -342,6 +342,111 @@ QUnit.test('should not display user notification messages in chatter', async fun
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('post message with "CTRL-Enter" keyboard shortcut', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
this.data['res.partner'].records.push({ id: 100 });
|
||||
await this.start();
|
||||
const chatter = this.env.models['mail.chatter'].create({
|
||||
threadId: 100,
|
||||
threadModel: 'res.partner',
|
||||
});
|
||||
await this.createChatterComponent({ chatter });
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_Message',
|
||||
"should not have any message initially in chatter"
|
||||
);
|
||||
|
||||
await afterNextRender(() =>
|
||||
document.querySelector('.o_ChatterTopbar_buttonSendMessage').click()
|
||||
);
|
||||
await afterNextRender(() => {
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).focus();
|
||||
document.execCommand('insertText', false, "Test");
|
||||
});
|
||||
await afterNextRender(() => {
|
||||
const kevt = new window.KeyboardEvent('keydown', { ctrlKey: true, key: "Enter" });
|
||||
document.querySelector('.o_ComposerTextInput_textarea').dispatchEvent(kevt);
|
||||
});
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_Message',
|
||||
"should now have single message in chatter after posting message from pressing 'CTRL-Enter' in text input of composer"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('post message with "META-Enter" keyboard shortcut', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
this.data['res.partner'].records.push({ id: 100 });
|
||||
await this.start();
|
||||
const chatter = this.env.models['mail.chatter'].create({
|
||||
threadId: 100,
|
||||
threadModel: 'res.partner',
|
||||
});
|
||||
await this.createChatterComponent({ chatter });
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_Message',
|
||||
"should not have any message initially in chatter"
|
||||
);
|
||||
|
||||
await afterNextRender(() =>
|
||||
document.querySelector('.o_ChatterTopbar_buttonSendMessage').click()
|
||||
);
|
||||
await afterNextRender(() => {
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).focus();
|
||||
document.execCommand('insertText', false, "Test");
|
||||
});
|
||||
await afterNextRender(() => {
|
||||
const kevt = new window.KeyboardEvent('keydown', { key: "Enter", metaKey: true });
|
||||
document.querySelector('.o_ComposerTextInput_textarea').dispatchEvent(kevt);
|
||||
});
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_Message',
|
||||
"should now have single message in channel after posting message from pressing 'META-Enter' in text input of composer"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('do not post message with "Enter" keyboard shortcut', async function (assert) {
|
||||
// Note that test doesn't assert Enter makes a newline, because this
|
||||
// default browser cannot be simulated with just dispatching
|
||||
// programmatically crafted events...
|
||||
assert.expect(2);
|
||||
|
||||
this.data['res.partner'].records.push({ id: 100 });
|
||||
await this.start();
|
||||
const chatter = this.env.models['mail.chatter'].create({
|
||||
threadId: 100,
|
||||
threadModel: 'res.partner',
|
||||
});
|
||||
await this.createChatterComponent({ chatter });
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_Message',
|
||||
"should not have any message initially in chatter"
|
||||
);
|
||||
|
||||
await afterNextRender(() =>
|
||||
document.querySelector('.o_ChatterTopbar_buttonSendMessage').click()
|
||||
);
|
||||
await afterNextRender(() => {
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).focus();
|
||||
document.execCommand('insertText', false, "Test");
|
||||
});
|
||||
await afterNextRender(() => {
|
||||
const kevt = new window.KeyboardEvent('keydown', { key: "Enter" });
|
||||
document.querySelector('.o_ComposerTextInput_textarea').dispatchEvent(kevt);
|
||||
});
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_Message',
|
||||
"should still not have any message in mailing channel after pressing 'Enter' in text input of composer"
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -261,6 +261,13 @@ class Composer extends Component {
|
||||
this._postMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_onComposerTextInputSendShortcut() {
|
||||
this._postMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when some files have been dropped in the dropzone.
|
||||
*
|
||||
@@ -340,13 +347,6 @@ class Composer extends Component {
|
||||
await this._fileUploaderRef.comp.uploadFiles(ev.clipboardData.files);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_onTextInputKeydownEnter() {
|
||||
this._postMessage();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Object.assign(Composer, {
|
||||
@@ -357,7 +357,6 @@ Object.assign(Composer, {
|
||||
hasDiscardButton: false,
|
||||
hasFollowers: false,
|
||||
hasSendButton: true,
|
||||
hasTextInputSendOnEnterEnabled: true,
|
||||
hasThreadName: false,
|
||||
hasThreadTyping: false,
|
||||
isCompact: true,
|
||||
@@ -381,7 +380,6 @@ Object.assign(Composer, {
|
||||
optional: true,
|
||||
},
|
||||
hasSendButton: Boolean,
|
||||
hasTextInputSendOnEnterEnabled: Boolean,
|
||||
hasThreadName: Boolean,
|
||||
hasThreadTyping: Boolean,
|
||||
showAttachmentsExtensions: {
|
||||
@@ -403,6 +401,15 @@ Object.assign(Composer, {
|
||||
},
|
||||
isCompact: Boolean,
|
||||
isExpandable: Boolean,
|
||||
/**
|
||||
* If set, keyboard shortcuts from text input to send message.
|
||||
* If not set, will use default values from `ComposerTextInput`.
|
||||
*/
|
||||
textInputSendShortcuts: {
|
||||
type: Array,
|
||||
element: String,
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
template: 'mail.Composer',
|
||||
});
|
||||
|
||||
@@ -75,9 +75,9 @@
|
||||
}"
|
||||
composerLocalId="composer.localId"
|
||||
hasMentionSuggestionsBelowPosition="props.hasMentionSuggestionsBelowPosition"
|
||||
hasSendOnEnterEnabled="props.hasTextInputSendOnEnterEnabled"
|
||||
isCompact="props.isCompact"
|
||||
t-on-o-keydown-enter="_onTextInputKeydownEnter"
|
||||
sendShortcuts="props.textInputSendShortcuts"
|
||||
t-on-o-composer-text-input-send-shortcut="_onComposerTextInputSendShortcut"
|
||||
t-on-paste="_onPasteTextInput"
|
||||
t-ref="textInput"
|
||||
/>
|
||||
|
||||
@@ -590,6 +590,116 @@ QUnit.test('composer: paste attachments', async function (assert) {
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('send message when enter is pressed while holding ctrl key (this shortcut is available)', async function (assert) {
|
||||
// Note that test doesn't assert ENTER makes no newline, because this
|
||||
// default browser cannot be simulated with just dispatching
|
||||
// programmatically crafted events...
|
||||
assert.expect(5);
|
||||
|
||||
this.data['mail.channel'].records.push({ id: 20 });
|
||||
await this.start({
|
||||
async mockRPC(route, args) {
|
||||
if (args.method === 'message_post') {
|
||||
assert.step('message_post');
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
});
|
||||
const thread = this.env.models['mail.thread'].find(thread =>
|
||||
thread.id === 20 &&
|
||||
thread.model === 'mail.channel'
|
||||
);
|
||||
await this.createComposerComponent(thread.composer, {
|
||||
textInputSendShortcuts: ['ctrl-enter'],
|
||||
});
|
||||
// Type message
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).focus();
|
||||
document.execCommand('insertText', false, "test message");
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value,
|
||||
"test message",
|
||||
"should have inserted text content in editable"
|
||||
);
|
||||
|
||||
await afterNextRender(() => {
|
||||
const enterEvent = new window.KeyboardEvent('keydown', { key: 'Enter' });
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`)
|
||||
.dispatchEvent(enterEvent);
|
||||
});
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value,
|
||||
"test message",
|
||||
"should have inserted text content in editable as message has not been posted"
|
||||
);
|
||||
|
||||
// Send message with ctrl+enter
|
||||
await afterNextRender(() =>
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`)
|
||||
.dispatchEvent(new window.KeyboardEvent('keydown', { ctrlKey: true, key: 'Enter' }))
|
||||
);
|
||||
assert.verifySteps(['message_post']);
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value,
|
||||
"",
|
||||
"should have no content in composer input as message has been posted"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('send message when enter is pressed while holding meta key (this shortcut is available)', async function (assert) {
|
||||
// Note that test doesn't assert ENTER makes no newline, because this
|
||||
// default browser cannot be simulated with just dispatching
|
||||
// programmatically crafted events...
|
||||
assert.expect(5);
|
||||
|
||||
this.data['mail.channel'].records.push({ id: 20 });
|
||||
await this.start({
|
||||
async mockRPC(route, args) {
|
||||
if (args.method === 'message_post') {
|
||||
assert.step('message_post');
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
});
|
||||
const thread = this.env.models['mail.thread'].find(thread =>
|
||||
thread.id === 20 &&
|
||||
thread.model === 'mail.channel'
|
||||
);
|
||||
await this.createComposerComponent(thread.composer, {
|
||||
textInputSendShortcuts: ['meta-enter'],
|
||||
});
|
||||
// Type message
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).focus();
|
||||
document.execCommand('insertText', false, "test message");
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value,
|
||||
"test message",
|
||||
"should have inserted text content in editable"
|
||||
);
|
||||
|
||||
await afterNextRender(() => {
|
||||
const enterEvent = new window.KeyboardEvent('keydown', { key: 'Enter' });
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`)
|
||||
.dispatchEvent(enterEvent);
|
||||
});
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value,
|
||||
"test message",
|
||||
"should have inserted text content in editable as message has not been posted"
|
||||
);
|
||||
|
||||
// Send message with meta+enter
|
||||
await afterNextRender(() =>
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`)
|
||||
.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter', metaKey: true }))
|
||||
);
|
||||
assert.verifySteps(['message_post']);
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value,
|
||||
"",
|
||||
"should have no content in composer input as message has been posted"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('composer text input cleared on message post', async function (assert) {
|
||||
assert.expect(4);
|
||||
|
||||
@@ -610,8 +720,10 @@ QUnit.test('composer text input cleared on message post', async function (assert
|
||||
);
|
||||
await this.createComposerComponent(thread.composer);
|
||||
// Type message
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).focus();
|
||||
document.execCommand('insertText', false, "test message");
|
||||
await afterNextRender(() => {
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).focus();
|
||||
document.execCommand('insertText', false, "test message");
|
||||
});
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value,
|
||||
"test message",
|
||||
@@ -620,8 +732,7 @@ QUnit.test('composer text input cleared on message post', async function (assert
|
||||
|
||||
// Send message
|
||||
await afterNextRender(() =>
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`)
|
||||
.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter' }))
|
||||
document.querySelector('.o_Composer_buttonSend').click()
|
||||
);
|
||||
assert.verifySteps(['message_post']);
|
||||
assert.strictEqual(
|
||||
@@ -691,8 +802,7 @@ QUnit.test('composer inputs cleared on message post in composer of a mailing cha
|
||||
|
||||
// Send message
|
||||
await afterNextRender(() =>
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`)
|
||||
.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter' }))
|
||||
document.querySelector('.o_Composer_buttonSend').click()
|
||||
);
|
||||
assert.verifySteps(['message_post']);
|
||||
assert.strictEqual(
|
||||
@@ -956,7 +1066,7 @@ QUnit.test('composer: send button is disabled if attachment upload is not finish
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('warning when attempting to post message when attachments are still uploading', async function (assert) {
|
||||
QUnit.test('warning on send with shortcut when attempting to post message with still-uploading attachments', async function (assert) {
|
||||
assert.expect(7);
|
||||
|
||||
await this.start({
|
||||
@@ -991,7 +1101,9 @@ QUnit.test('warning when attempting to post message when attachments are still u
|
||||
id: 20,
|
||||
model: 'res.partner',
|
||||
});
|
||||
await this.createComposerComponent(thread.composer);
|
||||
await this.createComposerComponent(thread.composer, {
|
||||
textInputSendShortcuts: ['enter'],
|
||||
});
|
||||
const file = await createFile({
|
||||
content: 'hello, world',
|
||||
contentType: 'text/plain',
|
||||
|
||||
@@ -241,18 +241,41 @@ class ComposerTextInput extends Component {
|
||||
_onKeydownTextareaEnter(ev) {
|
||||
if (this.composer.hasSuggestedPartners) {
|
||||
ev.preventDefault();
|
||||
} else {
|
||||
if (!this.props.hasSendOnEnterEnabled) {
|
||||
return;
|
||||
}
|
||||
if (ev.shiftKey) {
|
||||
return;
|
||||
}
|
||||
if (this.env.messaging.device.isMobile) {
|
||||
return;
|
||||
}
|
||||
this.trigger('o-keydown-enter');
|
||||
return;
|
||||
}
|
||||
if (
|
||||
this.props.sendShortcuts.includes('ctrl-enter') &&
|
||||
!ev.altKey &&
|
||||
ev.ctrlKey &&
|
||||
!ev.metaKey &&
|
||||
!ev.shiftKey
|
||||
) {
|
||||
this.trigger('o-composer-text-input-send-shortcut');
|
||||
ev.preventDefault();
|
||||
return;
|
||||
}
|
||||
if (
|
||||
this.props.sendShortcuts.includes('enter') &&
|
||||
!ev.altKey &&
|
||||
!ev.ctrlKey &&
|
||||
!ev.metaKey &&
|
||||
!ev.shiftKey &&
|
||||
!this.env.messaging.device.isMobile
|
||||
) {
|
||||
this.trigger('o-composer-text-input-send-shortcut');
|
||||
ev.preventDefault();
|
||||
return;
|
||||
}
|
||||
if (
|
||||
this.props.sendShortcuts.includes('meta-enter') &&
|
||||
!ev.altKey &&
|
||||
!ev.ctrlKey &&
|
||||
ev.metaKey &&
|
||||
!ev.shiftKey
|
||||
) {
|
||||
this.trigger('o-composer-text-input-send-shortcut');
|
||||
ev.preventDefault();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,13 +364,27 @@ Object.assign(ComposerTextInput, {
|
||||
components,
|
||||
defaultProps: {
|
||||
hasMentionSuggestionsBelowPosition: false,
|
||||
hasSendOnEnterEnabled: true,
|
||||
sendShortcuts: [],
|
||||
},
|
||||
props: {
|
||||
composerLocalId: String,
|
||||
hasMentionSuggestionsBelowPosition: Boolean,
|
||||
hasSendOnEnterEnabled: Boolean,
|
||||
isCompact: Boolean,
|
||||
/**
|
||||
* Keyboard shortcuts from text input to send message.
|
||||
*/
|
||||
sendShortcuts: {
|
||||
type: Array,
|
||||
element: String,
|
||||
validate: prop => {
|
||||
for (const shortcut of prop) {
|
||||
if (!['ctrl-enter', 'enter', 'meta-enter'].includes(shortcut)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
},
|
||||
},
|
||||
template: 'mail.ComposerTextInput',
|
||||
});
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
hasCurrentPartnerAvatar="!env.messaging.device.isMobile"
|
||||
hasDiscardButton="true"
|
||||
hasThreadName="true"
|
||||
textInputSendShortcuts="['ctrl-enter', 'meta-enter']"
|
||||
t-on-o-message-posted="_onReplyingToMessageMessagePosted"
|
||||
t-ref="composer"
|
||||
/>
|
||||
|
||||
@@ -312,11 +312,12 @@ QUnit.test('"reply to" composer should log note if message replied to is a note'
|
||||
"Send button text should be 'Log'"
|
||||
);
|
||||
|
||||
await afterNextRender(() => {
|
||||
document.execCommand('insertText', false, "Test");
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`)
|
||||
.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter' }));
|
||||
});
|
||||
await afterNextRender(() =>
|
||||
document.execCommand('insertText', false, "Test")
|
||||
);
|
||||
await afterNextRender(() =>
|
||||
document.querySelector('.o_Composer_buttonSend').click()
|
||||
);
|
||||
assert.verifySteps(['message_post']);
|
||||
});
|
||||
|
||||
@@ -363,11 +364,12 @@ QUnit.test('"reply to" composer should send message if message replied to is not
|
||||
"Send button text should be 'Send'"
|
||||
);
|
||||
|
||||
await afterNextRender(() => {
|
||||
document.execCommand('insertText', false, "Test");
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`)
|
||||
.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter' }));
|
||||
});
|
||||
await afterNextRender(() =>
|
||||
document.execCommand('insertText', false, "Test")
|
||||
);
|
||||
await afterNextRender(() =>
|
||||
document.querySelector('.o_Composer_buttonSend').click()
|
||||
);
|
||||
assert.verifySteps(['message_post']);
|
||||
});
|
||||
|
||||
|
||||
@@ -2846,8 +2846,10 @@ QUnit.test('post a simple message', async function (assert) {
|
||||
);
|
||||
|
||||
// insert some HTML in editable
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).focus();
|
||||
document.execCommand('insertText', false, "Test");
|
||||
await afterNextRender(() => {
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).focus();
|
||||
document.execCommand('insertText', false, "Test");
|
||||
});
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value,
|
||||
"Test",
|
||||
@@ -2855,8 +2857,7 @@ QUnit.test('post a simple message', async function (assert) {
|
||||
);
|
||||
|
||||
await afterNextRender(() =>
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`)
|
||||
.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter' }))
|
||||
document.querySelector('.o_Composer_buttonSend').click()
|
||||
);
|
||||
assert.verifySteps(['message_post']);
|
||||
assert.strictEqual(
|
||||
@@ -2887,6 +2888,187 @@ QUnit.test('post a simple message', async function (assert) {
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('post message on non-mailing channel with "Enter" keyboard shortcut', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
// channel expected to be found in the sidebar
|
||||
// with a random unique id that will be referenced in the test
|
||||
this.data['mail.channel'].records.push({ id: 20, mass_mailing: false });
|
||||
await this.start({
|
||||
discuss: {
|
||||
params: {
|
||||
default_active_id: 'mail.channel_20',
|
||||
},
|
||||
},
|
||||
});
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_Message',
|
||||
"should not have any message initially in channel"
|
||||
);
|
||||
|
||||
// insert some HTML in editable
|
||||
await afterNextRender(() => {
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).focus();
|
||||
document.execCommand('insertText', false, "Test");
|
||||
});
|
||||
await afterNextRender(() => {
|
||||
const kevt = new window.KeyboardEvent('keydown', { key: "Enter" });
|
||||
document.querySelector('.o_ComposerTextInput_textarea').dispatchEvent(kevt);
|
||||
});
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_Message',
|
||||
"should now have single message in channel after posting message from pressing 'Enter' in text input of composer"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('do not post message on non-mailing channel with "SHIFT-Enter" keyboard shortcut', async function (assert) {
|
||||
// Note that test doesn't assert SHIFT-Enter makes a newline, because this
|
||||
// default browser cannot be simulated with just dispatching
|
||||
// programmatically crafted events...
|
||||
assert.expect(2);
|
||||
|
||||
// channel expected to be found in the sidebar
|
||||
// with a random unique id that will be referenced in the test
|
||||
this.data['mail.channel'].records.push({ id: 20, mass_mailing: true });
|
||||
await this.start({
|
||||
discuss: {
|
||||
params: {
|
||||
default_active_id: 'mail.channel_20',
|
||||
},
|
||||
},
|
||||
});
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_Message',
|
||||
"should not have any message initially in channel"
|
||||
);
|
||||
|
||||
// insert some HTML in editable
|
||||
await afterNextRender(() => {
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).focus();
|
||||
document.execCommand('insertText', false, "Test");
|
||||
});
|
||||
await afterNextRender(() => {
|
||||
const kevt = new window.KeyboardEvent('keydown', { key: "Enter", shiftKey: true });
|
||||
document.querySelector('.o_ComposerTextInput_textarea').dispatchEvent(kevt);
|
||||
});
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_Message',
|
||||
"should still not have any message in channel after pressing 'Shift-Enter' in text input of composer"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('post message on mailing channel with "CTRL-Enter" keyboard shortcut', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
// channel expected to be found in the sidebar
|
||||
// with a random unique id that will be referenced in the test
|
||||
this.data['mail.channel'].records.push({ id: 20, mass_mailing: true });
|
||||
await this.start({
|
||||
discuss: {
|
||||
params: {
|
||||
default_active_id: 'mail.channel_20',
|
||||
},
|
||||
},
|
||||
});
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_Message',
|
||||
"should not have any message initially in channel"
|
||||
);
|
||||
|
||||
// insert some HTML in editable
|
||||
await afterNextRender(() => {
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).focus();
|
||||
document.execCommand('insertText', false, "Test");
|
||||
});
|
||||
await afterNextRender(() => {
|
||||
const kevt = new window.KeyboardEvent('keydown', { ctrlKey: true, key: "Enter" });
|
||||
document.querySelector('.o_ComposerTextInput_textarea').dispatchEvent(kevt);
|
||||
});
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_Message',
|
||||
"should now have single message in channel after posting message from pressing 'CTRL-Enter' in text input of composer"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('post message on mailing channel with "META-Enter" keyboard shortcut', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
// channel expected to be found in the sidebar
|
||||
// with a random unique id that will be referenced in the test
|
||||
this.data['mail.channel'].records.push({ id: 20, mass_mailing: true });
|
||||
await this.start({
|
||||
discuss: {
|
||||
params: {
|
||||
default_active_id: 'mail.channel_20',
|
||||
},
|
||||
},
|
||||
});
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_Message',
|
||||
"should not have any message initially in channel"
|
||||
);
|
||||
|
||||
// insert some HTML in editable
|
||||
await afterNextRender(() => {
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).focus();
|
||||
document.execCommand('insertText', false, "Test");
|
||||
});
|
||||
await afterNextRender(() => {
|
||||
const kevt = new window.KeyboardEvent('keydown', { key: "Enter", metaKey: true });
|
||||
document.querySelector('.o_ComposerTextInput_textarea').dispatchEvent(kevt);
|
||||
});
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_Message',
|
||||
"should now have single message in channel after posting message from pressing 'META-Enter' in text input of composer"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('do not post message on mailing channel with "Enter" keyboard shortcut', async function (assert) {
|
||||
// Note that test doesn't assert Enter makes a newline, because this
|
||||
// default browser cannot be simulated with just dispatching
|
||||
// programmatically crafted events...
|
||||
assert.expect(2);
|
||||
|
||||
// channel expected to be found in the sidebar
|
||||
// with a random unique id that will be referenced in the test
|
||||
this.data['mail.channel'].records.push({ id: 20, mass_mailing: true });
|
||||
await this.start({
|
||||
discuss: {
|
||||
params: {
|
||||
default_active_id: 'mail.channel_20',
|
||||
},
|
||||
},
|
||||
});
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_Message',
|
||||
"should not have any message initially in mailing channel"
|
||||
);
|
||||
|
||||
// insert some HTML in editable
|
||||
await afterNextRender(() => {
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).focus();
|
||||
document.execCommand('insertText', false, "Test");
|
||||
});
|
||||
await afterNextRender(() => {
|
||||
const kevt = new window.KeyboardEvent('keydown', { key: "Enter" });
|
||||
document.querySelector('.o_ComposerTextInput_textarea').dispatchEvent(kevt);
|
||||
});
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_Message',
|
||||
"should still not have any message in mailing channel after pressing 'Enter' in text input of composer"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('rendering of inbox message', async function (assert) {
|
||||
// AKU TODO: kinda message specific test
|
||||
assert.expect(7);
|
||||
@@ -3205,11 +3387,12 @@ QUnit.test('reply to message from inbox (message linked to document)', async fun
|
||||
"composer text input should be auto-focus"
|
||||
);
|
||||
|
||||
await afterNextRender(() => {
|
||||
document.execCommand('insertText', false, "Test");
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`)
|
||||
.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter' }));
|
||||
});
|
||||
await afterNextRender(() =>
|
||||
document.execCommand('insertText', false, "Test")
|
||||
);
|
||||
await afterNextRender(() =>
|
||||
document.querySelector('.o_Composer_buttonSend').click()
|
||||
);
|
||||
assert.verifySteps(['message_post']);
|
||||
assert.notOk(
|
||||
document.querySelector('.o_Composer'),
|
||||
|
||||
@@ -30,11 +30,11 @@
|
||||
composerLocalId="threadView.thread.composer.localId"
|
||||
hasCurrentPartnerAvatar="props.hasComposerCurrentPartnerAvatar"
|
||||
hasSendButton="props.hasComposerSendButton"
|
||||
hasTextInputSendOnEnterEnabled="(threadView.thread.model === 'mail.channel' and threadView.thread.mass_mailing) ? false : undefined"
|
||||
hasThreadTyping="props.hasComposerThreadTyping"
|
||||
isCompact="(threadView.thread.model === 'mail.channel' and threadView.thread.mass_mailing) ? false : undefined"
|
||||
showAttachmentsExtensions="props.showComposerAttachmentsExtensions"
|
||||
showAttachmentsFilenames="props.showComposerAttachmentsFilenames"
|
||||
textInputSendShortcuts="(threadView.thread.model === 'mail.channel' and threadView.thread.mass_mailing) ? ['ctrl-enter', 'meta-enter'] : ['enter']"
|
||||
t-ref="composer"
|
||||
/>
|
||||
</t>
|
||||
|
||||
Reference in New Issue
Block a user