Skip to content

Commit

Permalink
Chat: should send message on enter key if some text is entered (#28003)
Browse files Browse the repository at this point in the history
Signed-off-by: Anton Kuznetsov <[email protected]>
Co-authored-by: ksercs <[email protected]>
  • Loading branch information
Zedwag and ksercs authored Sep 9, 2024
1 parent f851de4 commit 042a14c
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 3 deletions.
23 changes: 21 additions & 2 deletions packages/devextreme/js/__internal/ui/chat/chat_message_box.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { Properties as DOMComponentProperties } from '@ts/core/widget/dom_c
import DOMComponent from '@ts/core/widget/dom_component';
import type { OptionChanged } from '@ts/core/widget/types';

import type { EnterKeyEvent } from '../../../ui/text_area';
import type dxTextArea from '../../../ui/text_area';
import TextArea from '../m_text_area';

Expand Down Expand Up @@ -59,6 +60,12 @@ class MessageBox extends DOMComponent<MessageBox, Properties> {
this._renderButton();
}

_isValuableTextEntered(): boolean {
const { text } = this._textArea.option();

return !!text?.trim();
}

_renderTextArea(): void {
const {
activeStateEnabled,
Expand All @@ -77,7 +84,19 @@ class MessageBox extends DOMComponent<MessageBox, Properties> {
stylingMode: 'outlined',
placeholder: 'Type a message',
autoResizeEnabled: true,
valueChangeEvent: 'input',
maxHeight: '20em',
onEnterKey: (e: EnterKeyEvent): void => {
if (!e.event?.shiftKey) {
this._sendHandler(e);
}
},
});

this._textArea.registerKeyHandler('enter', (event: KeyboardEvent) => {
if (!event.shiftKey && this._isValuableTextEntered()) {
event.preventDefault();
}
});
}

Expand Down Expand Up @@ -112,10 +131,10 @@ class MessageBox extends DOMComponent<MessageBox, Properties> {
);
}

_sendHandler(e: ClickEvent): void {
_sendHandler(e: ClickEvent | EnterKeyEvent): void {
const { text } = this._textArea.option();

if (!text?.trim()) {
if (!this._isValuableTextEntered()) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ QUnit.module('MessageBox', moduleConfig, () => {
placeholder: 'Type a message',
autoResizeEnabled: true,
maxHeight: '20em',
valueChangeEvent: 'input'
};

const textArea = TextArea.getInstance(this.$textArea);
Expand All @@ -82,7 +83,6 @@ QUnit.module('MessageBox', moduleConfig, () => {
this.$sendButton.trigger('dxclick');

assert.strictEqual(this.$input.val(), '');
assert.strictEqual(this.$input.val(), '');
});

QUnit.test('textarea should be cleared when the send button is clicked if the input contains a value consisting only of spaces', function(assert) {
Expand Down Expand Up @@ -113,6 +113,20 @@ QUnit.module('MessageBox', moduleConfig, () => {
assert.strictEqual(onMessageSendStub.callCount, 1);
});

QUnit.test('should be fired on enter key if the textarea input contains a value', function(assert) {
const onMessageSendStub = sinon.stub();

this.reinit({ onMessageSend: onMessageSendStub });

keyboardMock(this.$input)
.focus()
.type('new text message')
.keyUp('enter');


assert.strictEqual(onMessageSendStub.callCount, 1);
});

QUnit.test('should not be fired when the send button is clicked if the textarea input does not contain a value', function(assert) {
const onMessageSendStub = sinon.stub();

Expand All @@ -123,6 +137,25 @@ QUnit.module('MessageBox', moduleConfig, () => {
assert.strictEqual(onMessageSendStub.callCount, 0);
});

QUnit.test('should not be fired on enter key if the textarea input does not contain a value (excluding spaces)', function(assert) {
const onMessageSendStub = sinon.stub();

this.reinit({ onMessageSend: onMessageSendStub });

keyboardMock(this.$input)
.focus()
.keyUp('enter');

assert.strictEqual(onMessageSendStub.callCount, 0);

keyboardMock(this.$input)
.focus()
.type(' ')
.keyUp('enter');

assert.strictEqual(onMessageSendStub.callCount, 0);
});

QUnit.test('should be possible to update it at runtime', function(assert) {
const eventHandlerStub = sinon.stub();

Expand Down Expand Up @@ -176,6 +209,31 @@ QUnit.module('MessageBox', moduleConfig, () => {

this.$sendButton.trigger('dxclick');
});

QUnit.test('should be fired with correct arguments when enter is pressed', function(assert) {
assert.expect(6);

const text = ' new text message ';

this.reinit({
onMessageSend: (e) => {
const { component, element, event, text } = e;

assert.strictEqual(component, this.instance, 'component field is correct');
assert.strictEqual(isRenderer(element), !!config().useJQuery, 'element is correct');
assert.strictEqual($(element).is(this.$element), true, 'element field is correct');
assert.strictEqual(event.type, 'keyup', 'e.event.type is correct');
assert.strictEqual(event.target, this.$input.get(0), 'event target is correct');
assert.strictEqual(text, text, 'message field is correct');
},
});

keyboardMock(this.$input)
.focus()
.type(text)
.keyDown('enter')
.keyUp('enter');
});
});

QUnit.module('Proxy state options', () => {
Expand Down Expand Up @@ -217,4 +275,67 @@ QUnit.module('MessageBox', moduleConfig, () => {
});
});
});

QUnit.module('Keyboard navigation', () => {
QUnit.test('textarea should not be cleared on enter key if the input contains a value consisting only of spaces', function(assert) {
keyboardMock(this.$input)
.focus()
.type(' ')
.keyDown('enter')
.keyUp('enter');

assert.strictEqual(this.$input.val(), ' ');
});

QUnit.test('textarea should be cleared on enter key when some text is entered', function(assert) {
keyboardMock(this.$input)
.focus()
.type('some text')
.keyDown('enter')
.keyUp('enter');

assert.strictEqual(this.$input.val(), '');
});

QUnit.test('enter keydown event should be prevented if input text has non-space characters', function(assert) {
const enterKeyDownEvent = $.Event('keydown', { key: 'enter' });

keyboardMock(this.$input).type('1');

this.$input.trigger(enterKeyDownEvent);

assert.ok(enterKeyDownEvent.isDefaultPrevented(), 'empty line is not added before sending');
});

QUnit.test('enter keydown event with Shift modificator should not be prevented', function(assert) {
const enterKeyDownEvent = $.Event('keydown', { key: 'enter', shiftKey: true });

keyboardMock(this.$input).focus().type('1');

this.$input.trigger(enterKeyDownEvent);

assert.notOk(enterKeyDownEvent.isDefaultPrevented(), 'empty line is added when shift is used');
});

QUnit.test('enter keydown event should not be prevented if input text consists only from space characters', function(assert) {
const enterKeyDownEvent = $.Event('keydown', { key: 'enter' });

keyboardMock(this.$input).type(' \n \n');

this.$input.trigger(enterKeyDownEvent);

assert.notOk(enterKeyDownEvent.isDefaultPrevented(), 'empty line is added');
});

QUnit.test('textarea should restore its height after enter press when multiline text was entered', function(assert) {
const initialTextAreaHeight = this.$textArea.height();

keyboardMock(this.$input)
.type('1\n2\n3')
.keyDown('enter')
.keyUp('enter');

assert.roughEqual(this.$textArea.height(), initialTextAreaHeight, 0.1, 'textarea height is restored');
});
});
});

0 comments on commit 042a14c

Please sign in to comment.