From ecf1dc2bc01df32876037af4ddd51107e324077c Mon Sep 17 00:00:00 2001 From: "polosatov.alexander" Date: Fri, 29 Sep 2023 11:59:24 +0400 Subject: [PATCH] Gallery - fix Axe errors (#25540) --- .../js/localization/messages/ar.json | 4 +- .../js/localization/messages/ca.json | 4 +- .../js/localization/messages/cs.json | 4 +- .../js/localization/messages/de.json | 4 +- .../js/localization/messages/el.json | 4 +- .../js/localization/messages/en.json | 4 +- .../js/localization/messages/es.json | 4 +- .../js/localization/messages/fa.json | 4 +- .../js/localization/messages/fi.json | 4 +- .../js/localization/messages/fr.json | 4 +- .../js/localization/messages/hu.json | 4 +- .../js/localization/messages/it.json | 4 +- .../js/localization/messages/ja.json | 4 +- .../js/localization/messages/lt.json | 4 +- .../js/localization/messages/lv.json | 4 +- .../js/localization/messages/nb.json | 4 +- .../js/localization/messages/nl.json | 4 +- .../js/localization/messages/pt.json | 4 +- .../js/localization/messages/ro.json | 4 +- .../js/localization/messages/ru.json | 4 +- .../js/localization/messages/sl.json | 4 +- .../js/localization/messages/sv.json | 4 +- .../js/localization/messages/tr.json | 4 +- .../js/localization/messages/vi.json | 4 +- .../js/localization/messages/zh-tw.json | 4 +- .../js/localization/messages/zh.json | 4 +- packages/devextreme/js/ui/gallery.js | 20 ++-- .../testcafe/tests/gallery/accessibility.ts | 94 +++++++++++++++++++ .../gallery.markup.tests.js | 16 +++- .../DevExpress.ui.widgets/gallery.tests.js | 62 +++++++++--- 30 files changed, 252 insertions(+), 44 deletions(-) create mode 100644 packages/devextreme/testing/testcafe/tests/gallery/accessibility.ts diff --git a/packages/devextreme/js/localization/messages/ar.json b/packages/devextreme/js/localization/messages/ar.json index 269a0deec2c5..4e86df04950c 100644 --- a/packages/devextreme/js/localization/messages/ar.json +++ b/packages/devextreme/js/localization/messages/ar.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Show Resources", "dxGantt-showDependencies": "Show Dependencies", "dxGantt-dialogStartDateValidation": "Start date must be after {0}", - "dxGantt-dialogEndDateValidation": "End date must be after {0}" + "dxGantt-dialogEndDateValidation": "End date must be after {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/ca.json b/packages/devextreme/js/localization/messages/ca.json index f551e8989e99..2f78c133ad55 100644 --- a/packages/devextreme/js/localization/messages/ca.json +++ b/packages/devextreme/js/localization/messages/ca.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Mostrar recursos", "dxGantt-showDependencies": "Mostrar dependències", "dxGantt-dialogStartDateValidation": "La data d'inici ha de ser després de {0}", - "dxGantt-dialogEndDateValidation": "La data de finalització ha de ser després de {0}" + "dxGantt-dialogEndDateValidation": "La data de finalització ha de ser després de {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/cs.json b/packages/devextreme/js/localization/messages/cs.json index 46c34ed8e4c9..89e47e2d1de7 100644 --- a/packages/devextreme/js/localization/messages/cs.json +++ b/packages/devextreme/js/localization/messages/cs.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Show Resources", "dxGantt-showDependencies": "Show Dependencies", "dxGantt-dialogStartDateValidation": "Start date must be after {0}", - "dxGantt-dialogEndDateValidation": "End date must be after {0}" + "dxGantt-dialogEndDateValidation": "End date must be after {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/de.json b/packages/devextreme/js/localization/messages/de.json index 4ff7d6f219d0..47ee872b0987 100644 --- a/packages/devextreme/js/localization/messages/de.json +++ b/packages/devextreme/js/localization/messages/de.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Ressourcen Anzeigen", "dxGantt-showDependencies": "Abhängigkeiten Anzeigen", "dxGantt-dialogStartDateValidation": "Startdatum muss später sein als {0}", - "dxGantt-dialogEndDateValidation": "Enddatum muss später sein als {0}" + "dxGantt-dialogEndDateValidation": "Enddatum muss später sein als {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/el.json b/packages/devextreme/js/localization/messages/el.json index 2821a16256c4..92af94beff24 100644 --- a/packages/devextreme/js/localization/messages/el.json +++ b/packages/devextreme/js/localization/messages/el.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Show Resources", "dxGantt-showDependencies": "Show Dependencies", "dxGantt-dialogStartDateValidation": "Start date must be after {0}", - "dxGantt-dialogEndDateValidation": "End date must be after {0}" + "dxGantt-dialogEndDateValidation": "End date must be after {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/en.json b/packages/devextreme/js/localization/messages/en.json index 309343a7a7af..67693f092da1 100644 --- a/packages/devextreme/js/localization/messages/en.json +++ b/packages/devextreme/js/localization/messages/en.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Show Resources", "dxGantt-showDependencies": "Show Dependencies", "dxGantt-dialogStartDateValidation": "Start date must be after {0}", - "dxGantt-dialogEndDateValidation": "End date must be after {0}" + "dxGantt-dialogEndDateValidation": "End date must be after {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/es.json b/packages/devextreme/js/localization/messages/es.json index 54421aeb7db3..de9e3c00e157 100644 --- a/packages/devextreme/js/localization/messages/es.json +++ b/packages/devextreme/js/localization/messages/es.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Mostrar Recursos", "dxGantt-showDependencies": "Mostrar Dependencias", "dxGantt-dialogStartDateValidation": "La fecha de inicio debe ser anterior {0}", - "dxGantt-dialogEndDateValidation": "La fecha de finalización debe ser posterior {0}" + "dxGantt-dialogEndDateValidation": "La fecha de finalización debe ser posterior {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/fa.json b/packages/devextreme/js/localization/messages/fa.json index 48b413850231..340104fb4ca8 100644 --- a/packages/devextreme/js/localization/messages/fa.json +++ b/packages/devextreme/js/localization/messages/fa.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Show Resources", "dxGantt-showDependencies": "Show Dependencies", "dxGantt-dialogStartDateValidation": "Start date must be after {0}", - "dxGantt-dialogEndDateValidation": "End date must be after {0}" + "dxGantt-dialogEndDateValidation": "End date must be after {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/fi.json b/packages/devextreme/js/localization/messages/fi.json index 8b0cc7004645..65b6d98d4cde 100644 --- a/packages/devextreme/js/localization/messages/fi.json +++ b/packages/devextreme/js/localization/messages/fi.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Show Resources", "dxGantt-showDependencies": "Show Dependencies", "dxGantt-dialogStartDateValidation": "Start date must be after {0}", - "dxGantt-dialogEndDateValidation": "End date must be after {0}" + "dxGantt-dialogEndDateValidation": "End date must be after {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/fr.json b/packages/devextreme/js/localization/messages/fr.json index 999a9edc263d..cf5538942541 100644 --- a/packages/devextreme/js/localization/messages/fr.json +++ b/packages/devextreme/js/localization/messages/fr.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Afficher les ressources", "dxGantt-showDependencies": "Afficher les dépendances", "dxGantt-dialogStartDateValidation": "La date de début doit être postérieure au {0}", - "dxGantt-dialogEndDateValidation": "La date de fin doit être postérieure au {0}" + "dxGantt-dialogEndDateValidation": "La date de fin doit être postérieure au {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/hu.json b/packages/devextreme/js/localization/messages/hu.json index cbc12646453c..6de9bf3a8d5c 100644 --- a/packages/devextreme/js/localization/messages/hu.json +++ b/packages/devextreme/js/localization/messages/hu.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Show Resources", "dxGantt-showDependencies": "Show Dependencies", "dxGantt-dialogStartDateValidation": "Start date must be after {0}", - "dxGantt-dialogEndDateValidation": "End date must be after {0}" + "dxGantt-dialogEndDateValidation": "End date must be after {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/it.json b/packages/devextreme/js/localization/messages/it.json index b6bad7bb5563..b309040d0224 100644 --- a/packages/devextreme/js/localization/messages/it.json +++ b/packages/devextreme/js/localization/messages/it.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Show Resources", "dxGantt-showDependencies": "Show Dependencies", "dxGantt-dialogStartDateValidation": "Start date must be after {0}", - "dxGantt-dialogEndDateValidation": "End date must be after {0}" + "dxGantt-dialogEndDateValidation": "End date must be after {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/ja.json b/packages/devextreme/js/localization/messages/ja.json index b795daa22009..5150bbf705f3 100644 --- a/packages/devextreme/js/localization/messages/ja.json +++ b/packages/devextreme/js/localization/messages/ja.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "リソースを表示", "dxGantt-showDependencies": "依存関係を表示", "dxGantt-dialogStartDateValidation": "開始日を {0} 以降にする必要があります", - "dxGantt-dialogEndDateValidation": "終了日は {0} より後にする必要があります" + "dxGantt-dialogEndDateValidation": "終了日は {0} より後にする必要があります", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/lt.json b/packages/devextreme/js/localization/messages/lt.json index a12715a36adb..4d961aabfbb3 100644 --- a/packages/devextreme/js/localization/messages/lt.json +++ b/packages/devextreme/js/localization/messages/lt.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Rodyti resursus", "dxGantt-showDependencies": "Rodyti priklausomybes", "dxGantt-dialogStartDateValidation": "Pradžios data turi būti po {0}", - "dxGantt-dialogEndDateValidation": "Pabaigos data turi būti po {0}" + "dxGantt-dialogEndDateValidation": "Pabaigos data turi būti po {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/lv.json b/packages/devextreme/js/localization/messages/lv.json index a45e57941859..34b097da4507 100644 --- a/packages/devextreme/js/localization/messages/lv.json +++ b/packages/devextreme/js/localization/messages/lv.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Rādīt Resursus", "dxGantt-showDependencies": "Rādīt Sasaistes", "dxGantt-dialogStartDateValidation": "Sākuma datumam jābūt vēlākam par {0}", - "dxGantt-dialogEndDateValidation": "Beigu datumam jābūt vēlākam par {0}" + "dxGantt-dialogEndDateValidation": "Beigu datumam jābūt vēlākam par {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/nb.json b/packages/devextreme/js/localization/messages/nb.json index 391477300484..df0502f8a8de 100644 --- a/packages/devextreme/js/localization/messages/nb.json +++ b/packages/devextreme/js/localization/messages/nb.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Show Resources", "dxGantt-showDependencies": "Show Dependencies", "dxGantt-dialogStartDateValidation": "Start date must be after {0}", - "dxGantt-dialogEndDateValidation": "End date must be after {0}" + "dxGantt-dialogEndDateValidation": "End date must be after {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/nl.json b/packages/devextreme/js/localization/messages/nl.json index 5e1f826a0f0a..be5adcc46c93 100644 --- a/packages/devextreme/js/localization/messages/nl.json +++ b/packages/devextreme/js/localization/messages/nl.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Show Resources", "dxGantt-showDependencies": "Show Dependencies", "dxGantt-dialogStartDateValidation": "Start date must be after {0}", - "dxGantt-dialogEndDateValidation": "End date must be after {0}" + "dxGantt-dialogEndDateValidation": "End date must be after {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/pt.json b/packages/devextreme/js/localization/messages/pt.json index f89efce6a9e7..86f0ae4fcead 100644 --- a/packages/devextreme/js/localization/messages/pt.json +++ b/packages/devextreme/js/localization/messages/pt.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Mostrar recursos", "dxGantt-showDependencies": "Mostrar dependências", "dxGantt-dialogStartDateValidation": "A data de início deve ser após {0}", - "dxGantt-dialogEndDateValidation": "A data de término deve ser posterior a {0}" + "dxGantt-dialogEndDateValidation": "A data de término deve ser posterior a {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/ro.json b/packages/devextreme/js/localization/messages/ro.json index ed2b2ac20408..059925745f33 100644 --- a/packages/devextreme/js/localization/messages/ro.json +++ b/packages/devextreme/js/localization/messages/ro.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Show Resources", "dxGantt-showDependencies": "Show Dependencies", "dxGantt-dialogStartDateValidation": "Start date must be after {0}", - "dxGantt-dialogEndDateValidation": "End date must be after {0}" + "dxGantt-dialogEndDateValidation": "End date must be after {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/ru.json b/packages/devextreme/js/localization/messages/ru.json index 7a2f75c830ce..ffd95f1bb83a 100644 --- a/packages/devextreme/js/localization/messages/ru.json +++ b/packages/devextreme/js/localization/messages/ru.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Отображать Ресурсы", "dxGantt-showDependencies": "Отображать Зависимости", "dxGantt-dialogStartDateValidation": "Начальная дата должна быть позднее {0}", - "dxGantt-dialogEndDateValidation": "Конечная дата должна быть позднее {0}" + "dxGantt-dialogEndDateValidation": "Конечная дата должна быть позднее {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/sl.json b/packages/devextreme/js/localization/messages/sl.json index 3d4ad4524d7e..e811f8fb851a 100644 --- a/packages/devextreme/js/localization/messages/sl.json +++ b/packages/devextreme/js/localization/messages/sl.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Show Resources", "dxGantt-showDependencies": "Show Dependencies", "dxGantt-dialogStartDateValidation": "Start date must be after {0}", - "dxGantt-dialogEndDateValidation": "End date must be after {0}" + "dxGantt-dialogEndDateValidation": "End date must be after {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/sv.json b/packages/devextreme/js/localization/messages/sv.json index f5090d517d06..13c30cdc3625 100644 --- a/packages/devextreme/js/localization/messages/sv.json +++ b/packages/devextreme/js/localization/messages/sv.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Show Resources", "dxGantt-showDependencies": "Show Dependencies", "dxGantt-dialogStartDateValidation": "Start date must be after {0}", - "dxGantt-dialogEndDateValidation": "End date must be after {0}" + "dxGantt-dialogEndDateValidation": "End date must be after {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/tr.json b/packages/devextreme/js/localization/messages/tr.json index 3c384f523193..88e4b909c358 100644 --- a/packages/devextreme/js/localization/messages/tr.json +++ b/packages/devextreme/js/localization/messages/tr.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Show Resources", "dxGantt-showDependencies": "Show Dependencies", "dxGantt-dialogStartDateValidation": "Start date must be after {0}", - "dxGantt-dialogEndDateValidation": "End date must be after {0}" + "dxGantt-dialogEndDateValidation": "End date must be after {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/vi.json b/packages/devextreme/js/localization/messages/vi.json index a30b1af28310..4580bb9fe770 100644 --- a/packages/devextreme/js/localization/messages/vi.json +++ b/packages/devextreme/js/localization/messages/vi.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Show Resources", "dxGantt-showDependencies": "Show Dependencies", "dxGantt-dialogStartDateValidation": "Start date must be after {0}", - "dxGantt-dialogEndDateValidation": "End date must be after {0}" + "dxGantt-dialogEndDateValidation": "End date must be after {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/zh-tw.json b/packages/devextreme/js/localization/messages/zh-tw.json index 481ecbdae46c..1b2e36c64e0a 100644 --- a/packages/devextreme/js/localization/messages/zh-tw.json +++ b/packages/devextreme/js/localization/messages/zh-tw.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Show Resources", "dxGantt-showDependencies": "Show Dependencies", "dxGantt-dialogStartDateValidation": "Start date must be after {0}", - "dxGantt-dialogEndDateValidation": "End date must be after {0}" + "dxGantt-dialogEndDateValidation": "End date must be after {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/localization/messages/zh.json b/packages/devextreme/js/localization/messages/zh.json index 9571b5e91718..3631a20aa98e 100644 --- a/packages/devextreme/js/localization/messages/zh.json +++ b/packages/devextreme/js/localization/messages/zh.json @@ -702,6 +702,8 @@ "dxGantt-showResources": "Show Resources", "dxGantt-showDependencies": "Show Dependencies", "dxGantt-dialogStartDateValidation": "Start date must be after {0}", - "dxGantt-dialogEndDateValidation": "End date must be after {0}" + "dxGantt-dialogEndDateValidation": "End date must be after {0}", + + "dxGallery-itemName": "Gallery item" } } diff --git a/packages/devextreme/js/ui/gallery.js b/packages/devextreme/js/ui/gallery.js index ab5b26b184fa..af0446f0b560 100644 --- a/packages/devextreme/js/ui/gallery.js +++ b/packages/devextreme/js/ui/gallery.js @@ -18,6 +18,7 @@ import Swipeable from '../events/gesture/swipeable'; import { BindableTemplate } from '../core/templates/bindable_template'; import { Deferred } from '../core/utils/deferred'; import { triggerResizeEvent } from '../events/visibility_change'; +import messageLocalization from '../localization/message'; // STYLE gallery @@ -146,7 +147,10 @@ const Gallery = CollectionWidget.inherit({ */ - _itemAttributes: { role: 'option' }, + _itemAttributes: { + role: 'option', + 'aria-label': messageLocalization.format('dxGallery-itemName') + }, loopItemFocus: false, selectOnFocus: true, selectionMode: 'single', @@ -273,10 +277,13 @@ const Gallery = CollectionWidget.inherit({ this.callBase(); - this.setAria({ - 'role': 'listbox', + const useListBoxRole = this._itemsCount() > 0; + const ariaAttrs = { + 'role': useListBoxRole ? 'listbox' : undefined, 'label': 'gallery' - }); + }; + + this.setAria(ariaAttrs); }, _render: function() { @@ -392,10 +399,11 @@ const Gallery = CollectionWidget.inherit({ const $clonedItem = $(item) .clone(false) .addClass(GALLERY_LOOP_ITEM_CLASS) + .removeAttr('id') .css('margin', 0) .appendTo($container); - this.setAria({ role: 'presentation' }, $clonedItem); + this.setAria({ hidden: true }, $clonedItem); } }, @@ -946,7 +954,7 @@ const Gallery = CollectionWidget.inherit({ _setFocusOnSelect: function() { this._userInteraction = true; - const selectedItem = this.itemElements().filter('.' + GALLERY_ITEM_SELECTED_CLASS); + const selectedItem = this._getRealItems().filter('.' + GALLERY_ITEM_SELECTED_CLASS); this.option('focusedElement', getPublicElement(selectedItem)); this._userInteraction = false; }, diff --git a/packages/devextreme/testing/testcafe/tests/gallery/accessibility.ts b/packages/devextreme/testing/testcafe/tests/gallery/accessibility.ts new file mode 100644 index 000000000000..5c711562b127 --- /dev/null +++ b/packages/devextreme/testing/testcafe/tests/gallery/accessibility.ts @@ -0,0 +1,94 @@ +/* eslint-disable no-restricted-syntax */ +import url from '../../helpers/getPageUrl'; +import createWidget from '../../helpers/createWidget'; +import { a11yCheck } from '../../helpers/accessibilityUtils'; + +fixture.disablePageReloads`Gallery` + .page(url(__dirname, '../../container.html')); + +interface GalleryItem { + ID: string; + Name: string; +} + +interface GallerySettings { + items?: GalleryItem[]; + itemTemplate?: (item: GalleryItem) => HTMLDivElement; + width?: string; + loop?: boolean; + showIndicator?: boolean; +} + +const defaultItems: GalleryItem[] = [{ + ID: '1', + Name: 'First', +}, +{ + ID: '2', + Name: 'Second', +}]; + +function defaultItemTemplate(item: GalleryItem) { + const result = document.createElement('div'); + const span = document.createElement('span'); + + span.innerText = item.Name; + result.appendChild(span); + + return result; +} + +const allGallerySettings: GallerySettings = { + items: defaultItems, + itemTemplate: defaultItemTemplate, + width: '100%', + loop: true, + showIndicator: false, +}; + +function getTestName(gallerySettings: GallerySettings) { + const fields = Object.keys(gallerySettings); + + const messageParts = fields.map((field) => { + const fieldSkipped = gallerySettings[field] === undefined; + + return `${field} was ${fieldSkipped ? 'not' : ''} set`; + }); + + return `Checking Gallery via aXe. Settings: ${messageParts.join(', ')}`; +} + +function generateCombinations(allSettings: GallerySettings): GallerySettings[] { + const keys = Object.keys(allSettings); + const combinations: GallerySettings[] = []; + + const generate = (index: number, currentCombination: GallerySettings) => { + if (index === keys.length) { + combinations.push(currentCombination); + return; + } + + const key = keys[index]; + const value = allSettings[key]; + + generate(index + 1, currentCombination); + + const newCombination = { ...currentCombination, [key]: value }; + generate(index + 1, newCombination); + }; + + generate(0, {}); + return combinations; +} + +const settingsCombinations = generateCombinations(allGallerySettings); + +settingsCombinations.forEach((settings) => { + const testName = getTestName(settings); + test(testName, async (t) => { + await a11yCheck(t); + }).before(async () => createWidget( + 'dxGallery', + settings, + )); +}); diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets/gallery.markup.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets/gallery.markup.tests.js index 205c82f69f00..0ad57a7d3d22 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets/gallery.markup.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets/gallery.markup.tests.js @@ -66,9 +66,15 @@ QUnit.module('base', () => { QUnit.module('aria accessibility', () => { - QUnit.test('aria role', function(assert) { + QUnit.test('aria role should not be set when no items', function(assert) { const $element = $('#gallerySimple').dxGallery(); + assert.equal($element.attr('role'), undefined, 'aria role is correct'); + }); + + QUnit.test('aria role should be set when gallery has items to display', function(assert) { + const $element = $('#gallerySimple').dxGallery({ items: [1] }); + assert.equal($element.attr('role'), 'listbox', 'aria role is correct'); }); @@ -78,6 +84,14 @@ QUnit.module('aria accessibility', () => { assert.equal($element.attr('aria-label'), 'gallery', 'widget should have aria-label to have difference from text list'); }); + QUnit.test('aria label for items should be set', function(assert) { + const $gallery = $('#gallerySimple').dxGallery({ items: [1] }); + + const $item = $gallery.find(`.${GALLERY_ITEM_CLASS}`); + + assert.strictEqual($item.attr('aria-label'), 'Gallery item', 'item should have "aria-label"'); + }); + QUnit.test('aria role for items', function(assert) { const $element = $('#gallerySimple').dxGallery({ items: [1] }); const $item = $element.find('.' + GALLERY_ITEM_CLASS); diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets/gallery.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets/gallery.tests.js index 437f9226aa3b..8a32f4319dd5 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets/gallery.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets/gallery.tests.js @@ -385,17 +385,6 @@ QUnit.module('behavior', { assert.equal($loopItems.length, 2); }); - QUnit.test('duplicate items should have role="presentation"', function(assert) { - const $gallery = this.$element.dxGallery({ - items: [0, 1, 2, 3], - loop: true - }); - - const $loopItems = $gallery.find(`.${GALLERY_LOOP_ITEM_CLASS}`); - $loopItems.each((index, item) => { - assert.strictEqual($(item).attr('role'), 'presentation'); - }); - }); QUnit.test('duplicate items is not rendered when loop=false', function(assert) { const $gallery = this.$element.dxGallery({ @@ -2762,3 +2751,54 @@ QUnit.module('gallery with paginated dataSource', { }); }); +QUnit.module('accessibility', function() { + QUnit.test('duplicate items should have aria-hidden=true', function(assert) { + const $gallery = $('#gallerySimple').dxGallery({ + items: [0, 1, 2, 3], + loop: true + }); + + const $loopItems = $gallery.find(`.${GALLERY_LOOP_ITEM_CLASS}`); + $loopItems.each((index, item) => { + assert.strictEqual($(item).attr('aria-hidden'), 'true'); + }); + }); + + QUnit.test('aria-activedescendant should have link to the single element', function(assert) { + const $gallery = $('#gallerySimple').dxGallery({ + height: 100, + width: '100%', + showIndicator: false, + items: [1, 2], + loop: true + }); + + const $items = $gallery.find(`.${GALLERY_ITEM_CLASS}`); + + const itemsWithId = Array.from($items).filter(item => { + return Boolean($(item).attr('id')); + }); + + assert.strictEqual(itemsWithId.length, 1, 'id attribute should be exist only on one item'); + }); + + QUnit.test('aria-activedescendant should have link to the single element after resize', function(assert) { + const $gallery = $('#gallerySimple').dxGallery({ + height: 100, + showIndicator: false, + width: '100%', + items: [1, 2], + loop: true + }); + + $gallery.dxGallery('instance').option('width', 200); + + const $items = $gallery.find(`.${GALLERY_ITEM_CLASS}`); + + const itemsWithId = Array.from($items).filter(item => { + return Boolean($(item).attr('id')); + }); + + assert.strictEqual(itemsWithId.length, 1, 'id attribute should be exist only on one item'); + }); +});