From fe4c36f5664e23941407cb1c1e8c1a6e697dd32b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marker=20dao=20=C2=AE?= Date: Mon, 27 Jan 2025 09:01:54 +0100 Subject: [PATCH] List: Set item aria-label to make CheckBox/RadioGroup mock label not readable (T1248422) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: marker dao ® --- .../js/__internal/ui/list/m_list.edit.ts | 17 +++++ .../list.markup.tests.js | 67 +++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/packages/devextreme/js/__internal/ui/list/m_list.edit.ts b/packages/devextreme/js/__internal/ui/list/m_list.edit.ts index b107f79f7147..4c45990cd800 100644 --- a/packages/devextreme/js/__internal/ui/list/m_list.edit.ts +++ b/packages/devextreme/js/__internal/ui/list/m_list.edit.ts @@ -191,6 +191,23 @@ const ListEdit = ListBase.inherit({ this._editProvider.afterItemsRendered(); }, + _renderItem(index, itemData, $container, $itemToReplace) { + const { showSelectionControls, selectionMode } = this.option(); + const $itemFrame = this.callBase(index, itemData, $container, $itemToReplace); + + if (showSelectionControls && selectionMode !== 'none') { + this._updateItemAriaLabel($itemFrame, itemData); + } + + return $itemFrame; + }, + + _updateItemAriaLabel($itemFrame, itemData) { + const label = this._displayGetter?.(itemData) ?? itemData?.text ?? itemData; + + this.setAria('label', label, $itemFrame); + }, + _selectedItemClass() { return LIST_ITEM_SELECTED_CLASS; }, diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets/list.markup.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets/list.markup.tests.js index feb5f8a1f9fb..741959a3213e 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets/list.markup.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets/list.markup.tests.js @@ -491,6 +491,73 @@ QUnit.module('decorators markup', {}, () => { assert.notStrictEqual(window.getComputedStyle($deleteToggleIcon).backgroundImage, 'none', 'background image is defined'); }); + QUnit.module('list item aria-label should be equal to item text (T1248422)', { + beforeEach: function() { + const init = (options = {}) => { + this.$element = $('#list').dxList(options); + this.instance = this.$element.dxList('instance'); + }; + + init(); + + this.reinit = (options) => { + this.instance.dispose(); + + init(options); + }; + + this.getItem = () => this.$element.find(`.${LIST_ITEM_CLASS}`).eq(0); + + this.checkAriaLabel = (assert, updatedItems) => { + const { selectionMode, showSelectionControls } = this.instance.option(); + const isSelectionActive = selectionMode !== 'none' && showSelectionControls; + + assert.strictEqual(this.getItem().attr('aria-label'), isSelectionActive ? 'item 1' : undefined, 'aria-label is correct on init'); + + this.instance.option({ items: updatedItems }); + + assert.strictEqual(this.getItem().attr('aria-label'), isSelectionActive ? 'item 2' : undefined, 'aria-label is correct if items were changed in runtime'); + }; + }, + }, () => { + [true, false].forEach(showSelectionControls => { + [ 'multiple', 'single', 'all', 'none' ].forEach(selectionMode => { + QUnit.test(`showSelectionControls is ${showSelectionControls}, selectionMode is ${selectionMode}, items is string, displayExpr is not specified`, function(assert) { + this.reinit({ + showSelectionControls, + selectionMode, + items: ['item 1'], + displayExpr: null, + }); + + this.checkAriaLabel(assert, ['item 2']); + }); + + QUnit.test(`showSelectionControls is ${showSelectionControls}, selectionMode is ${selectionMode}, items is object, displayExpr is not specified`, function(assert) { + this.reinit({ + showSelectionControls, + selectionMode, + items: [{ text: 'item 1' }], + displayExpr: null, + }); + + this.checkAriaLabel(assert, [{ text: 'item 2' }]); + }); + + QUnit.test(`showSelectionControls is ${showSelectionControls}, selectionMode is ${selectionMode}, items is object, displayExpr is specified`, function(assert) { + this.reinit({ + showSelectionControls, + selectionMode, + items: [{ custom: 'item 1' }], + displayExpr: 'custom', + }); + + this.checkAriaLabel(assert, [{ custom: 'item 2' }]); + }); + }); + }); + }); + QUnit.test('list item markup, item select decorator', function(assert) { const $list = $($('#templated-list').dxList({ items: ['0'],