From 8fb6cdb9f0c828ca92ce4a1700367d50e1ba7d45 Mon Sep 17 00:00:00 2001 From: Nikki Gonzales <38495263+nikkithelegendarypokemonster@users.noreply.github.com> Date: Fri, 25 Oct 2024 21:53:24 +0800 Subject: [PATCH] Chat: implement avatarAlt in user option (#28237) --- .../js/__internal/ui/chat/avatar.ts | 9 ++- .../js/__internal/ui/chat/messagegroup.ts | 3 + .../chatParts/avatar.tests.js | 71 +++++++++++++------ .../chatParts/messageGroup.tests.js | 22 ++++++ .../DevExpress.ui/defaultOptions.tests.js | 1 + 5 files changed, 84 insertions(+), 22 deletions(-) diff --git a/packages/devextreme/js/__internal/ui/chat/avatar.ts b/packages/devextreme/js/__internal/ui/chat/avatar.ts index 5eb46e4c6ee6..b794a3904ffe 100644 --- a/packages/devextreme/js/__internal/ui/chat/avatar.ts +++ b/packages/devextreme/js/__internal/ui/chat/avatar.ts @@ -13,6 +13,7 @@ const AVATAR_IMAGE_CLASS = 'dx-avatar-image'; export interface Properties extends WidgetOptions { name?: string; url?: string; + alt?: string; } class Avatar extends Widget { @@ -23,6 +24,7 @@ class Avatar extends Widget { ...super._getDefaultOptions(), name: 'Unknown User', url: '', + alt: '', }; } @@ -82,10 +84,12 @@ class Avatar extends Widget { } _updateAlt(): void { - const { name } = this.option(); + const { alt, name } = this.option(); // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - this._$content?.attr('alt', name || messageLocalization.format('dxAvatar-defaultImageAlt')); + const altText = alt || name || messageLocalization.format('dxAvatar-defaultImageAlt'); + + this._$content?.attr('alt', altText); } _isValuableUrl(): boolean { @@ -119,6 +123,7 @@ class Avatar extends Widget { const { name } = args; switch (name) { + case 'alt': case 'name': case 'url': this._renderAvatarContent(); diff --git a/packages/devextreme/js/__internal/ui/chat/messagegroup.ts b/packages/devextreme/js/__internal/ui/chat/messagegroup.ts index 5b2234ab0863..475b4a65bb7a 100644 --- a/packages/devextreme/js/__internal/ui/chat/messagegroup.ts +++ b/packages/devextreme/js/__internal/ui/chat/messagegroup.ts @@ -83,10 +83,13 @@ class MessageGroup extends Widget { const { author } = items[0]; const authorName = author?.name; const authorAvatarUrl = author?.avatarUrl; + // @ts-expect-error + const authorAvatarAlt = author?.avatarAlt; this._avatar = this._createComponent($avatar, Avatar, { name: authorName, url: authorAvatarUrl, + alt: authorAvatarAlt, }); } diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets/chatParts/avatar.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets/chatParts/avatar.tests.js index ef4d6ef5b03d..5a58e3888f1a 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets/chatParts/avatar.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets/chatParts/avatar.tests.js @@ -104,11 +104,13 @@ QUnit.module('ChatAvatar', moduleConfig, () => { }); }); - QUnit.module('Image rendering', () => { + QUnit.module('Image rendering', { + beforeEach: function() { + this.getImage = () => this.$element.find(`.${AVATAR_IMAGE_CLASS}`); + } + }, () => { QUnit.test('img element should not be rendered if url is empty', function(assert) { - const $img = this.$element.find(`.${AVATAR_IMAGE_CLASS}`); - - assert.strictEqual($img.length, 0); + assert.strictEqual(this.getImage().length, 0); }); QUnit.test('img element should not be rendered if url became empty in runtime', function(assert) { @@ -119,20 +121,47 @@ QUnit.module('ChatAvatar', moduleConfig, () => { this.instance.option({ url: '' }); - const $img = this.$element.find(`.${AVATAR_IMAGE_CLASS}`); + assert.strictEqual(this.getImage().length, 0); + }); + + QUnit.test('img should have default alt attribute if alt and name is not defined', function(assert) { + this.reinit({ + name: '', + url: 'url', + }); - assert.strictEqual($img.length, 0); + assert.strictEqual(this.getImage().attr('alt'), 'Avatar'); }); - QUnit.test('img element should have correct alt attribute', function(assert) { + QUnit.test('img alt should be set to "alt" option value if it is passed', function(assert) { this.reinit({ name: 'User name', url: 'url', + alt: 'Test Name' }); - const $img = this.$element.find(`.${AVATAR_IMAGE_CLASS}`); + assert.strictEqual(this.getImage().attr('alt'), 'Test Name'); + }); - assert.strictEqual($img.attr('alt'), 'User name'); + QUnit.test('img alt should be set to "name" option if it is passed but "alt" is not passed', function(assert) { + this.reinit({ + name: 'User name', + url: 'url', + }); + + assert.strictEqual(this.getImage().attr('alt'), 'User name'); + }); + + QUnit.test('img element should have correct alt attribute if alt was changed in runtime', function(assert) { + this.reinit({ + name: 'User name', + url: 'url', + alt: 'Test Name' + }); + + this.instance.option({ alt: 'New name' }); + + assert.strictEqual(this.getImage().attr('alt'), 'New name'); }); QUnit.test('img element should have correct alt attribute if name was changed in runtime', function(assert) { @@ -142,9 +171,17 @@ QUnit.module('ChatAvatar', moduleConfig, () => { }); this.instance.option({ name: 'New name' }); - const $img = this.$element.find(`.${AVATAR_IMAGE_CLASS}`); + assert.strictEqual(this.getImage().attr('alt'), 'New name'); + }); + + QUnit.test('img element should have correct alt attribute if alt is empty', function(assert) { + this.reinit({ + name: 'Test Name', + url: 'url', + alt: '', + }); - assert.strictEqual($img.attr('alt'), 'New name'); + assert.strictEqual(this.getImage().attr('alt'), 'Test Name'); }); QUnit.test('img element should have correct alt attribute if name is empty', function(assert) { @@ -153,26 +190,20 @@ QUnit.module('ChatAvatar', moduleConfig, () => { url: 'url', }); - const $img = this.$element.find(`.${AVATAR_IMAGE_CLASS}`); - - assert.strictEqual($img.attr('alt'), 'Avatar'); + assert.strictEqual(this.getImage().attr('alt'), 'Avatar'); }); QUnit.test('img element should have correct src attribute', function(assert) { this.reinit({ url: 'url' }); - const $img = this.$element.find(`.${AVATAR_IMAGE_CLASS}`); - - assert.strictEqual($img.attr('src'), 'url'); + assert.strictEqual(this.getImage().attr('src'), 'url'); }); QUnit.test('img element should have correct src attribute if url was changed in runtime', function(assert) { this.reinit({ url: 'url' }); this.instance.option({ url: 'New url' }); - const $img = this.$element.find(`.${AVATAR_IMAGE_CLASS}`); - - assert.strictEqual($img.attr('src'), 'New url'); + assert.strictEqual(this.getImage().attr('src'), 'New url'); }); }); }); diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets/chatParts/messageGroup.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets/chatParts/messageGroup.tests.js index 8d656586f69e..c6285053d0f1 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets/chatParts/messageGroup.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets/chatParts/messageGroup.tests.js @@ -167,6 +167,28 @@ QUnit.module('MessageGroup', moduleConfig, () => { assert.deepEqual(avatar.option('url'), passedUrlValue); }); }); + + QUnit.test('avatar component should be initialized with correct alt property', function(assert) { + [ + { items: [{}], passedAltValue: undefined }, + { items: [{ author: {} }], passedAltValue: undefined }, + { items: [{ author: undefined }], passedAltValue: undefined }, + { items: [{ author: { avatarAlt: undefined } }], passedAltValue: undefined }, + { items: [{ author: { avatarAlt: null } }], passedAltValue: null }, + { items: [{ author: { avatarAlt: '' } }], passedAltValue: '' }, + { items: [{ author: { avatarAlt: ' ' } }], passedAltValue: ' ' }, + { items: [{ author: { avatarAlt: 888 } }], passedAltValue: 888 }, + { items: [{ author: { avatarAlt: NaN } }], passedAltValue: NaN }, + ].forEach(({ items, passedAltValue }) => { + this.reinit({ + items, + }); + + const avatar = ChatAvatar.getInstance(this.$element.find(`.${AVATAR_CLASS}`)); + + assert.deepEqual(avatar.option('alt'), passedAltValue); + }); + }); }); }); diff --git a/packages/devextreme/testing/tests/DevExpress.ui/defaultOptions.tests.js b/packages/devextreme/testing/tests/DevExpress.ui/defaultOptions.tests.js index 924cb2480901..265c576b618d 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui/defaultOptions.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui/defaultOptions.tests.js @@ -1360,6 +1360,7 @@ testComponentDefaults(Avatar, { name: 'Unknown User', url: '', + alt: '', } );