dimsum-e2e-tests 3.70.0-next.7 → 3.70.0-next.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1079 -721
- package/ds-accordion/DSAccordion.visual.spec.js +6 -0
- package/ds-accordion/DSAccordionCO.js +15 -3
- package/ds-accordion/QA_NOTES.md +105 -0
- package/ds-accordion/controlled/DSAccordion.controlled.func.spec.js +23 -0
- package/ds-accordion/header-structure/DSAccordion.header-structure.func.spec.js +65 -0
- package/ds-accordion/input-inside/DSAccordion.input-inside.func.spec.js +19 -0
- package/ds-apppicker/DSAppPickerCO.js +101 -3
- package/ds-apppicker/aria-pattern/DSAppPicker.aria-pattern.func.spec.js +100 -0
- package/ds-apppicker/basic/DSAppPicker.basic.keyboard-nav.func.spec.js +18 -7
- package/ds-apppicker/closeAfterSelection/DSAppPicker.closeAfterSelection.func.spec.js +1 -1
- package/ds-apppicker/custom-trigger-focus/DSAppPicker.custom-trigger-focus.func.spec.js +82 -0
- package/ds-apppicker/label-expansion-dismissal/DSAppPicker.label-expansion-dismissal.visual.spec.js +108 -0
- package/ds-apppicker/reflow/DSAppPicker.reflow.func.spec.js +32 -0
- package/ds-apppicker/reflow/DSAppPicker.reflow.visual.spec.js +5 -6
- package/ds-apppicker/truncation/DSAppPicker.truncation.visual.spec.js +5 -9
- package/ds-autocomplete/DSAutocomplete.visual.spec.js +34 -0
- package/ds-autocomplete/DSAutocompleteCO.js +36 -1
- package/ds-autocomplete/aria-busy-loading/DSAutocomplete.aria-busy-loading.axe-core.func.spec.js +50 -0
- package/ds-autocomplete/aria-busy-loading/DSAutocomplete.aria-busy-loading.func.spec.js +122 -0
- package/ds-autocomplete/aria-busy-loading/DSAutocomplete.aria-busy-loading.visual.spec.js +48 -0
- package/ds-autocomplete/slots/DSAutocomplete.slots.func.spec.js +6 -1
- package/ds-banner/DSBanner.text-resize.visual.spec.js +5 -2
- package/ds-banner/DSBannerCO.js +4 -0
- package/ds-button-v3/DSButtonV3.aria-disabled-attribute.func.spec.js +33 -0
- package/ds-button-v3/DSButtonV3CO.js +10 -0
- package/ds-button-v3/theme-font/DSButtonV3.theme-font.func.spec.js +30 -0
- package/ds-card/DSCard.cardv2_v1.func.spec.js +54 -0
- package/ds-card/DSCard.cardv2_v1.visual.spec.js +29 -0
- package/ds-card/DSCardCO.js +50 -0
- package/ds-card/detail-slots/DSCard.detail-slots.axe-core.func.spec.js +29 -0
- package/ds-card/detail-slots/DSCard.detail-slots.func.spec.js +72 -0
- package/ds-card/detail-slots/DSCard.detail-slots.visual.spec.js +19 -0
- package/ds-card-v3/DSCardV3CO.js +93 -1
- package/ds-card-v3/accordion/DSCardV3.accordion-aria-structure.func.spec.js +41 -0
- package/ds-card-v3/accordion/DSCardV3.accordion-aria.keyboard.func.spec.js +49 -0
- package/ds-card-v3/accordion/DSCardV3.accordion.axe-core.func.spec.js +28 -0
- package/ds-card-v3/accordion/DSCardV3.accordion.visual.spec.js +4 -6
- package/ds-card-v3/action/DSCardV3.action.axe-core.func.spec.js +24 -0
- package/ds-card-v3/action/DSCardV3.action.func.spec.js +53 -0
- package/ds-card-v3/action/DSCardV3.action.visual.spec.js +28 -0
- package/ds-card-v3/drag-n-drop/DSCardV3.DnD.axe-core.func.spec.js +42 -0
- package/ds-card-v3/drag-n-drop/DSCardV3.DnD.func.spec.js +129 -0
- package/ds-card-v3/drag-n-drop/DSCardV3.DnD.reorder.func.spec.js +73 -0
- package/ds-card-v3/drag-n-drop/DSCardV3.DnD.visual.spec.js +5 -12
- package/ds-card-v3/global-attributes/DSCardV3.global-attributes.axe-core.func.spec.js +33 -0
- package/ds-card-v3/global-attributes/DSCardV3.global-attributes.visual.spec.js +20 -0
- package/ds-card-v3/multi-select/DSCardV3.multi-select.aria-grouping.func.spec.js +24 -0
- package/ds-card-v3/multi-select/DSCardV3.multiselect.axe-core.func.spec.js +47 -0
- package/ds-card-v3/multi-select/DSCardV3.multiselect.keyboard.func.spec.js +65 -0
- package/ds-card-v3/multi-select/DSCardV3.multiselect.visual.spec.js +17 -0
- package/ds-card-v3/multiple-action/DSCardV3.multiple-action.axe-core.func.spec.js +35 -0
- package/ds-card-v3/multiple-action/DSCardV3.multiple-action.func.spec.js +53 -0
- package/ds-card-v3/multiple-action/DSCardV3.multiple-action.visual.spec.js +18 -0
- package/ds-card-v3/multiple-control/DSCardV3.multi-control.axe-core.func.spec.js +34 -0
- package/ds-card-v3/multiple-control/DSCardV3.multi-control.func.spec.js +26 -0
- package/ds-card-v3/multiple-control/DSCardV3.multi-control.visual.spec.js +29 -0
- package/ds-card-v3/no-action/DSCardV3.no-action.axe-core.func.spec.js +22 -0
- package/ds-card-v3/no-action/DSCardV3.no-action.func.spec.js +23 -0
- package/ds-card-v3/no-action/DSCardV3.no-action.visual.spec.js +15 -0
- package/ds-card-v3/notification-badges/DSCardV3.notification-badges.axe-core.func.spec.js +33 -0
- package/ds-card-v3/notification-badges/DSCardV3.notification-badges.func.spec.js +19 -0
- package/ds-card-v3/notification-badges/DSCardV3.notification-badges.visual.spec.js +28 -0
- package/ds-card-v3/reflow/DSCardV3.reflow.axe-core.func.spec.js +28 -0
- package/ds-card-v3/reflow/DSCardV3.reflow.func.spec.js +36 -0
- package/ds-card-v3/reflow/DSCardV3.reflow.visual.spec.js +3 -2
- package/ds-card-v3/single-select/DSCardV3.single-select.aria-grouping.func.spec.js +24 -0
- package/ds-card-v3/single-select/DSCardV3.single-select.axe-core.func.spec.js +37 -0
- package/ds-card-v3/single-select/DSCardV3.single-select.visual.spec.js +1 -2
- package/ds-card-v3/slots/DSCardV3.slots.visual.spec.js +1 -2
- package/ds-card-v3/variant-accented/DSCardV3.variant-accented.axe-core.func.spec.js +45 -0
- package/ds-card-v3/variant-accented/DSCardV3.variant-accented.func.spec.js +28 -0
- package/ds-card-v3/variant-accented/DSCardV3.variant-accented.visual.spec.js +35 -0
- package/ds-card-v3/variant-accented-disabled/DSCardV3.variant-accented-disabled.axe-core.func.spec.js +35 -0
- package/ds-card-v3/variant-accented-disabled/DSCardV3.variant-accented-disabled.func.spec.js +53 -0
- package/ds-card-v3/variant-accented-disabled/DSCardV3.variant-accented-disabled.visual.spec.js +28 -0
- package/ds-card-v3/variant-disabled/DSCardV3.variant-disabled.axe-core.func.spec.js +22 -0
- package/ds-card-v3/variant-disabled/DSCardV3.variant-disabled.func.spec.js +61 -0
- package/ds-card-v3/variant-disabled/DSCardV3.variant-disabled.visual.spec.js +20 -0
- package/ds-card-v3/variant-disabled/DSCardV3.variantDisabled-non-interactive.func.spec.js +25 -0
- package/ds-chat/DSChat.axe-core.func.spec.js +2 -2
- package/ds-chat/DSChat.visual.spec.js +4 -4
- package/ds-chat/DSChatCO.js +18 -24
- package/ds-chat/bubbles/slots/DSChatBubble.slots.axe-core.func.spec.js +24 -0
- package/ds-chat/bubbles/slots/DSChatBubble.slots.func.spec.js +49 -0
- package/ds-chat/bubbles/slots/DSChatBubble.slots.visual.spec.js +25 -0
- package/ds-chat/card/slots/DSChatCard.slots.axe-core.func.spec.js +24 -0
- package/ds-chat/card/slots/DSChatCard.slots.func.spec.js +47 -0
- package/ds-chat/card/slots/DSChatCard.slots.visual.spec.js +18 -0
- package/ds-chat/card/truncated-text/DSChatCard.truncated-text.func.spec.js +32 -0
- package/ds-chat/card/truncated-text/DSChatCard.truncated-text.visual.spec.js +26 -0
- package/ds-chat/card/with-notification-badges/DSChatCard.with-notification-badges.axe-core.func.spec.js +23 -0
- package/ds-chat/card/with-notification-badges/DSChatCard.with-notification-badges.visual.spec.js +17 -0
- package/ds-chat/components/BubbleCO.js +46 -3
- package/ds-chat/components/CardCO.js +75 -0
- package/ds-chat/components/ComposerCO.js +6 -6
- package/ds-chat/components/FloatingButtonCO.js +5 -3
- package/ds-chat/components/HeaderCO.js +2 -2
- package/ds-chat/components/TileCO.js +82 -0
- package/ds-chat/components/index.js +3 -2
- package/ds-chat/floatingbutton/DSChat-floating-button.visual.spec.js +1 -1
- package/ds-chat/loadmore/DSChat-loadmore.func.spec.js +1 -1
- package/{ds-chat-tile → ds-chat/tile}/DSChat-tile.axe-core.func.spec.js +2 -2
- package/{ds-chat-tile → ds-chat/tile}/DSChat-tile.func.spec.js +1 -1
- package/{ds-chat-tile → ds-chat/tile}/DSChat-tile.visual.spec.js +2 -2
- package/{ds-chat-tile → ds-chat/tile}/aria-disabled/DSChat-tile.aria-disabled.axe-core.func.spec.js +2 -2
- package/{ds-chat-tile → ds-chat/tile}/aria-disabled/DSChat-tile.aria-disabled.visual.spec.js +1 -1
- package/ds-chat/tile/slots/DSChatTile.slots.func.spec.js +53 -0
- package/ds-chat/tile/slots/DSChatTile.slots.visual.spec.js +18 -0
- package/ds-chip/label-expansion-dismissal/DSChip.label-expansion-dismissal.visual.spec.js +84 -0
- package/ds-controlled-form/ds-combobox/creatable/DSCombobox.creatable-tooltip.func.spec.js +47 -0
- package/ds-controlled-form/ds-combobox/creatable/DSCombobox.creatable.visual.spec.js +12 -21
- package/ds-controlled-form/ds-combobox/disabled/DSCombobox.disabled.visual.spec.js +6 -1
- package/ds-controlled-form/ds-controlled-checkbox/Basic/DSControlledCheckbox.axe-core.basic.func.spec.js +4 -4
- package/ds-controlled-form/ds-controlled-checkbox/Basic/DSControlledCheckbox.basic.visual.spec.js +56 -0
- package/ds-controlled-form/ds-controlled-checkbox/DSControlledCheckboxCO.js +54 -1
- package/ds-controlled-form/ds-controlled-checkbox/Disabled/DSControlledCheckbox.axe-core.disabled.func.spec.js +1 -1
- package/ds-controlled-form/ds-controlled-checkbox/Disabled/DSControlledCheckbox.disabled.visual.spec.js +1 -1
- package/ds-controlled-form/ds-controlled-checkbox/HasError/DSControlledCheckbox.axe-core.hasError.func.spec.js +4 -4
- package/ds-controlled-form/ds-controlled-checkbox/HasError/DSControlledCheckbox.has-error.visual.spec.js +71 -1
- package/ds-controlled-form/ds-controlled-checkbox/Mixed/DSControlledCheckbox.axe-core.mixed.func.spec.js +4 -4
- package/ds-controlled-form/ds-controlled-checkbox/Mixed/DSControlledCheckbox.mixed.visual.spec.js +1 -1
- package/ds-controlled-form/ds-controlled-checkbox/ReadOnly/DSControlledCheckbox.axe-core.read-only.func.spec.js +3 -3
- package/ds-controlled-form/ds-controlled-checkbox/ReadOnly/DSControlledCheckbox.read-only.visual.spec.js +1 -1
- package/ds-controlled-form/ds-controlled-checkbox/WithTooltip/DSControlledCheckbox.axe-core.with-tooltip.func.spec.js +1 -1
- package/ds-controlled-form/ds-controlled-checkbox/WithTooltip/DSControlledCheckbox.with-tooltip.visual.spec.js +1 -3
- package/ds-controlled-form/ds-controlled-checkbox/WrapLabel/DSControlledCheckbox.axe-core.wrap-label.func.spec.js +1 -1
- package/ds-controlled-form/ds-controlled-checkbox/WrapLabel/DSControlledCheckbox.wrap-label.visual.spec.js +1 -1
- package/ds-controlled-form/ds-controlled-checkbox/aria-disabled/DSControlledCheckbox.aria-disabled.visual.spec.js +2 -6
- package/ds-controlled-form/ds-controlled-checkbox/aria-disabled/DSControlledCheckbox.axe-core.aria-disabled.func.spec.js +1 -1
- package/ds-controlled-form/ds-controlled-checkbox/slots/DSControlledCheckbox.slots.func.spec.js +78 -0
- package/ds-controlled-form/ds-controlled-checkbox/theme-font/DSControlledCheckbox.theme-font.func.spec.js +30 -0
- package/ds-controlled-form/ds-controlled-checkbox-group/DSControlledCheckboxGroup.axe-core.func.spec.js +4 -4
- package/ds-controlled-form/ds-controlled-checkbox-group/DSControlledCheckboxGroup.visual.spec.js +1 -1
- package/ds-controlled-form/ds-controlled-radio/DSControlledRadioCO.js +50 -1
- package/ds-controlled-form/ds-controlled-radio/aria-disabled/DSControlledRadio.aria-disabled.axe-core.func.spec.js +16 -2
- package/ds-controlled-form/ds-controlled-radio/aria-disabled/DSControlledRadio.aria-disabled.func.spec.js +37 -0
- package/ds-controlled-form/ds-controlled-radio/slots/DSControlledRadio.slots.func.spec.js +78 -0
- package/ds-controlled-form/ds-controlled-radio/theme-font/DSControlledRadio.theme-font.func.spec.js +30 -0
- package/ds-controlled-form/react-hook-form/ReactHook.func.spec.js +1 -3
- package/ds-data-table-async/DSDataTableCO.js +187 -10
- package/ds-data-table-async/basic/DSDataTable.basic.visual.spec.js +1 -1
- package/ds-data-table-async/components/FilterBarCO.js +7 -0
- package/ds-data-table-async/components/FiltersCO.js +1 -1
- package/ds-data-table-async/components/HeaderCO.js +37 -1
- package/ds-data-table-async/dnd/DSDataTable.dnd-keyboard-scroll.func.spec.js +51 -0
- package/ds-data-table-async/filter-menu-close/DSDataTable.filter-menu-close.func.spec.js +77 -0
- package/ds-data-table-async/filter-popover-boundary/DSDataTable.filter-popover-boundary.func.spec.js +98 -0
- package/ds-data-table-async/filters/DSDataTable.filters-creatable-active-descendant.func.spec.js +51 -0
- package/ds-data-table-async/filters/DSDataTable.filters-creatable.func.spec.js +55 -0
- package/ds-data-table-async/filters/DSDataTable.filters.axe-core.func.spec.js +11 -9
- package/ds-data-table-async/filtersV2/DSDataTable.filtersV2-creatablemultiselect.keyboard.func.spec.js +2 -2
- package/ds-data-table-async/filtersV2/DSDataTable.filtersV2-creatableselect.keyboard.func.spec.js +2 -2
- package/ds-data-table-async/filtersV2/DSDataTable.filtersV2.axe-core.func.spec.js +45 -29
- package/ds-data-table-async/filtersV2/pill-label/DSDataTable.pillLabel.axe-core.func.spec.js +23 -0
- package/ds-data-table-async/filtersV2/pill-label/DSDataTable.pillLabel.func.spec.js +50 -0
- package/ds-data-table-async/filtersV2/pill-label/DSDataTable.pillLabel.visual.spec.js +21 -0
- package/ds-data-table-async/header-affordances/DSDataTable.header-affordances.func.spec.js +92 -0
- package/ds-data-table-async/helpers/getInputSelection.js +6 -0
- package/ds-data-table-async/helpers/index.js +1 -0
- package/ds-data-table-async/keyboard-scroll/DSDataTable.keyboard-scroll.func.spec.js +39 -0
- package/ds-data-table-async/menubutton/DSDataTable.MenuButton.keyboard.func.spec.js +8 -7
- package/ds-data-table-async/menubutton/DSDataTable.MenuButton.mouse.func.spec.js +6 -7
- package/ds-data-table-async/pagination/DSDataTable.pagination.func.spec.js +3 -2
- package/ds-data-table-async/resizable/DSDataTable.resize-min-clamp.func.spec.js +72 -0
- package/ds-data-table-async/resizable/DSDataTable.resizerA11y.axe-core.func.spec.js +42 -0
- package/ds-data-table-async/resizable/DSDataTable.resizerA11y.func.spec.js +98 -0
- package/ds-data-table-async/textwrapping/DSDataTable.header-wrap-alignment.axe-core.func.spec.js +23 -0
- package/ds-data-table-async/textwrapping/DSDataTable.header-wrap-alignment.visual.spec.js +106 -0
- package/ds-data-table-async/textwrapping/DSDataTable.text-wrap-toolbar.visual.spec.js +27 -0
- package/ds-data-table-async/toggle-cell-focus/DSDataTable.toggle-cell-enter-focus.func.spec.js +31 -0
- package/ds-data-table-async/vissibility/DSDataTable.vissibility.visual.spec.js +2 -0
- package/ds-dataviz/DSDataViz.axis.visual.spec.js +1 -2
- package/ds-dataviz/DSDataViz.ticks.visual.spec.js +1 -2
- package/ds-dataviz/DSDataVizCO.js +2 -0
- package/ds-dataviz/axecore/DSDataViz.axis.axe-core.func.spec.js +1 -1
- package/ds-floating-context/DSFloatingContextCO.js +10 -0
- package/ds-floating-context/placement/DSFloatingContext.placement.visual.spec.js +48 -0
- package/ds-form-combobox-multi/DSComboboxMultiCO.js +36 -9
- package/ds-form-combobox-multi/aria-busy-loading/DSComboboxMulti.aria-busy-loading.axe-core.func.spec.js +55 -0
- package/ds-form-combobox-multi/aria-busy-loading/DSComboboxMulti.aria-busy-loading.func.spec.js +57 -0
- package/ds-form-combobox-multi/aria-disabled/DSComboboxMulti.aria-disabled.visual.spec.js +19 -2
- package/ds-form-combobox-multi/disabled/DSComboboxMulti.disabled.axe-core.func.spec.js +24 -0
- package/ds-form-combobox-multi/disabled/DSComboboxMulti.disabled.mouse.func.spec.js +0 -2
- package/ds-form-combobox-multi/disabled/DSComboboxMulti.disabled.visual.spec.js +22 -0
- package/ds-form-combobox-multi/grouped/DSComboboxMulti.grouped.visual.spec.js +42 -0
- package/ds-form-combobox-multi/inline/DSComboboxMulti.inline.visual.spec.js +21 -0
- package/ds-form-combobox-multi/pills/DSComboboxMulti.pills.func.spec.js +59 -0
- package/ds-form-combobox-multi/pills/DSComboboxMulti.pills.visual.spec.js +39 -0
- package/ds-form-combobox-multi/skeleton/DSComboboxMulti.skeleton.visual.spec.js +25 -0
- package/ds-form-combobox-multi/theme-font/DSComboboxMulti.theme-font.func.spec.js +38 -0
- package/ds-form-combobox-multi/with-tooltip/DSComboboxMulti.with-tooltip.axe-core.func.spec.js +39 -0
- package/ds-form-combobox-multi/with-tooltip/DSComboboxMulti.with-tooltip.func.spec.js +39 -0
- package/ds-form-combobox-multi/with-tooltip/DSComboboxMulti.with-tooltip.visual.spec.js +29 -0
- package/ds-form-combobox-single/DSComboboxSingleCO.js +25 -9
- package/ds-form-combobox-single/aria-busy-loading/DSComboboxSingle.aria-busy-loading.axe-core.func.spec.js +49 -0
- package/ds-form-combobox-single/aria-busy-loading/DSComboboxSingle.aria-busy-loading.func.spec.js +54 -0
- package/ds-form-combobox-single/aria-disabled/DSComboboxSingle.aria-disabled.visual.spec.js +18 -0
- package/ds-form-combobox-single/creatable/DSComboboxSingle.creatable.visual.spec.js +30 -0
- package/ds-form-combobox-single/disabled/DSComboboxSingle.disabled.axe-core.func.spec.js +24 -0
- package/ds-form-combobox-single/disabled/DSComboboxSingle.disabled.mouse.func.spec.js +0 -2
- package/ds-form-combobox-single/disabled/DSComboboxSingle.disabled.visual.spec.js +22 -0
- package/ds-form-combobox-single/grouped/DSComboboxSingle.grouped.visual.spec.js +45 -0
- package/ds-form-combobox-single/inline/DSComboboxSingle.inline.visual.spec.js +23 -0
- package/ds-form-combobox-single/skeleton/DSComboboxSingle.skeleton.visual.spec.js +25 -0
- package/ds-form-combobox-single/theme-font/DSComboboxSingle.theme-font.func.spec.js +34 -0
- package/ds-form-combobox-single/with-tooltip/DSComboboxSingle.with-tooltip.axe-core.func.spec.js +39 -0
- package/ds-form-combobox-single/with-tooltip/DSComboboxSingle.with-tooltip.func.spec.js +39 -0
- package/ds-form-combobox-single/with-tooltip/DSComboboxSingle.with-tooltip.visual.spec.js +29 -0
- package/ds-form-date-range-picker/DateRangePicker.axe-core.spec.js +5 -0
- package/ds-form-date-range-picker/DateRangePicker.functional.spec.js +80 -18
- package/ds-form-date-range-picker/DateRangePickerCO.js +19 -0
- package/ds-form-date-range-picker/date-segment-aria-labels/DateRangePicker.date-segment-aria-labels.func.spec.js +66 -0
- package/ds-form-date-range-picker/grouped-field-error-announcement/DateRangePicker.grouped-field-error-announcement.func.spec.js +59 -0
- package/ds-form-date-range-picker/picker-callbacks/DateRangePicker.picker-callbacks.func.spec.js +36 -0
- package/ds-form-date-time-picker/DSControlledDateTimePickerCO.js +7 -0
- package/ds-form-date-time-picker/date-time-full/DateTimeFull.axe-core.func.spec.js +8 -1
- package/ds-form-date-time-picker/date-time-full/DateTimePicker.DateTimeFull.visual.spec.js +9 -0
- package/ds-form-date-time-picker/partial-date-open-focus/DateTimePicker.partial-date-open-focus.func.spec.js +45 -0
- package/ds-form-native-select/NativeSelect.axe-core.func.spec.js +39 -0
- package/ds-form-native-select/NativeSelect.visual.spec.js +33 -0
- package/ds-form-native-select/NativeSelectCO.js +6 -0
- package/ds-form-native-select/option-selection/NativeSelect.option-selection.func.spec.js +25 -0
- package/ds-form-toggle/DSToggle.func.spec.js +20 -23
- package/ds-form-toggle/DSToggleCO.js +11 -2
- package/ds-global-header/GlobalHeader.announcements.func.spec.js +27 -0
- package/ds-global-header/GlobalHeader.axe-core.func.spec.js +15 -15
- package/ds-global-header/GlobalHeader.func.spec.js +70 -1
- package/ds-global-header/GlobalHeaderCO.js +120 -2
- package/ds-global-header/app-picker-passthrough/GlobalHeader.app-picker-passthrough.func.spec.js +113 -0
- package/ds-global-header/popup-menu-focus/GlobalHeader.popup-menu-focus.func.spec.js +63 -0
- package/ds-global-header/popup-menu-slots/GlobalHeader.popup-menu-slots.func.spec.js +70 -0
- package/ds-global-header/search-toggle-slots/GlobalHeader.search-toggle-slots.func.spec.js +118 -0
- package/ds-global-header/toolbar-item-attributes/GlobalHeader.toolbar-item-attributes.func.spec.js +53 -0
- package/ds-grid/DSGridCO.js +20 -0
- package/ds-grid/layout-mode/DSGrid.layout-mode.func.spec.js +51 -0
- package/ds-grid/layout-mode/DSGrid.layout-mode.visual.spec.js +22 -0
- package/ds-hooks/DSHook.UseFontSizeMedia.visual.spec.js +5 -2
- package/ds-hooks/DSHook.usetree.func.spec.js +3 -2
- package/ds-hooks/DSHookCO.js +56 -23
- package/ds-hooks/useFocusStack/DSHook.useFocusStack.func.spec.js +83 -0
- package/ds-hooks/useFocusTrap/UseFocusTrapCO.js +2 -0
- package/ds-hooks/useFocusTrap/UseFocusTrapToggle.func.spec.js +48 -0
- package/ds-hooks/useMask/Number/UseNumberMask.axe-core.func.spec.js +48 -0
- package/ds-menu-button/DSMenuButtonCO.js +23 -0
- package/ds-menu-button/slots/DSMenuButton.slots.axe-core.func.spec.js +28 -0
- package/ds-menu-button/slots/DSMenuButton.slots.func.spec.js +59 -0
- package/ds-menu-button/slots/DSMenuButton.slots.visual.spec.js +26 -0
- package/ds-modal-slide/ModalSlideCO.js +7 -0
- package/ds-modal-slide/custom-header/ModalSlide.customHeader.focusRing.visual.spec.js +2 -1
- package/ds-modal-slide/heading-level/ModalSlide.headingLevel.axe-core.func.spec.js +25 -0
- package/ds-modal-slide/heading-level/ModalSlide.headingLevel.func.spec.js +25 -0
- package/ds-modal-slide/slots/ModalSlide.slots.func.spec.js +18 -0
- package/ds-notification-badge/DSNotificationBadge.visual.spec.js +17 -20
- package/ds-page-layout/PageLayoutCO.js +4 -4
- package/ds-pills-v2/DSPillsV2CO.js +12 -0
- package/ds-pills-v2/apply-aria-disabled/DSPills.applyAriaDisabled.func.spec.js +53 -0
- package/ds-pills-v2/apply-aria-disabled/DSPills.applyAriaDisabled.visual.spec.js +26 -0
- package/ds-pills-v2/disabled/DSPills.disabled.func.spec.js +53 -0
- package/ds-pills-v2/disabled/DSPills.disabled.visual.spec.js +33 -0
- package/ds-progress-indicator/DSProgressIndicator.axe-core.func.spec.js +2 -0
- package/ds-progress-indicator/DSProgressIndicatorCO.js +1 -1
- package/ds-query-builder/DSQueryBuilder.visual.spec.js +6 -6
- package/ds-shuttle-v2/DSShuttleV2CO.js +15 -1
- package/ds-shuttle-v2/breadcrumb-a11y/DSShuttleV2.breadcrumb-a11y.func.spec.js +43 -0
- package/ds-shuttle-v2/explicit-selection-ui/DSShuttleV2.explicit-selection-ui.func.spec.js +37 -0
- package/ds-shuttle-v2/explicit-selection-ui/DSShuttleV2.explicit-selection-ui.visual.spec.js +30 -0
- package/ds-shuttle-v2/extra/DSShuttleV2.extra.visual.spec.js +8 -3
- package/ds-shuttle-v2/items/DSShuttleV2.items.func.spec.js +4 -2
- package/ds-shuttle-v2/skipped/DSShuttleV2.extra.axe-core.skipped.js +1 -1
- package/ds-shuttle-v2/skipped/DSShuttleV2.filter.axe-core.skipped.js +1 -1
- package/ds-shuttle-v2/skipped/DSShuttleV2.globalcheckbox.axe-core.skipped.js +1 -1
- package/ds-shuttle-v2/skipped/DSShuttleV2.items.axe-core.skipped.js +3 -3
- package/ds-shuttle-v2/skipped/DSShuttleV2.skipped.js +5 -5
- package/ds-slider-v2/DSSliderV2.func.spec.js +36 -25
- package/ds-slider-v2/DSSliderV2CO.js +10 -0
- package/ds-slider-v2/min-range/DSSliderV2.min-range.func.spec.js +69 -0
- package/ds-tab-button/DSTabButton.func.spec.js +1 -1
- package/ds-tabs/DSTabsCO.js +4 -0
- package/ds-tabs/notification-badge/DSTabs.notification-badge.axe-core.func.spec.js +28 -0
- package/ds-tabs/notification-badge/DSTabs.notification-badge.func.spec.js +51 -0
- package/ds-tooltip-v3/DSTooltipV3CO.js +21 -0
- package/ds-tooltip-v3/aria-tooltip-pattern/DSTooltipV3.aria-tooltip-pattern.axe-core.func.spec.js +23 -0
- package/ds-tooltip-v3/aria-tooltip-pattern/DSTooltipV3.aria-tooltip-pattern.func.spec.js +29 -0
- package/ds-tooltip-v3/dialog/DSTooltipV3.dialog.func.spec.js +45 -0
- package/ds-tooltip-v3/dialog/DSTooltipV3.dialog.visual.spec.js +29 -0
- package/ds-treeview/DSTreeViewCO.js +23 -0
- package/ds-treeview/dragAndDrop/TreeView-dnd_keyboard.func.spec.js +96 -0
- package/ds-typography/DSTypographyCO.js +10 -0
- package/ds-typography/theme-font/DSTypography.theme-font.func.spec.js +30 -0
- package/package.json +150 -153
- package/paths.js +16 -6
- package/ds-card-v3/disabled/DSCardV3.disabled.visual.spec.js +0 -17
- package/ds-chat-tile/TileCO.js +0 -35
- package/ds-hooks/DSHook.func.spec.js +0 -60
- package/ds-hooks/useFocusStack/DSHook.useFocusStack.skipped.js +0 -57
- package/ds-treeview/dragAndDrop/TreeView-dnd_mouse.func.spec.js +0 -61
|
@@ -81,6 +81,12 @@ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:o
|
|
|
81
81
|
if (errorOnGo) throw errorOnGo;
|
|
82
82
|
});
|
|
83
83
|
it('01: should display accordion with global height, not trimmed', async () => {
|
|
84
|
+
const addRow = await $('[data-testid="add-row"]');
|
|
85
|
+
await addRow.click();
|
|
86
|
+
await addRow.click();
|
|
87
|
+
await addRow.click();
|
|
88
|
+
const content = await DSAccordionCO.getContents(0);
|
|
89
|
+
await content.waitForDisplayed();
|
|
84
90
|
const snapshot = await browser.checkSnapshot(DSAccordionCO.snapshotPath('accordion-globalheight'));
|
|
85
91
|
await expect(snapshot).toEqual(0);
|
|
86
92
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable import/no-relative-packages */
|
|
2
|
-
import { PATH_E2E_ACCORDION } from '../paths';
|
|
2
|
+
import { PATH_E2E_ACCORDION, PATH_E2E_ACCORDION_PITFALLS } from '../paths';
|
|
3
3
|
import { PageObject, Urlbuilder, getElementByIndex } from '../helpers';
|
|
4
4
|
|
|
5
5
|
export default class DSAccordionCO extends PageObject {
|
|
@@ -20,7 +20,9 @@ export default class DSAccordionCO extends PageObject {
|
|
|
20
20
|
|
|
21
21
|
static tooltip = new Urlbuilder(PATH_E2E_ACCORDION, 'tooltip');
|
|
22
22
|
|
|
23
|
-
static inputInside = new Urlbuilder(PATH_E2E_ACCORDION, '
|
|
23
|
+
static inputInside = new Urlbuilder(PATH_E2E_ACCORDION, 'pui-9261-input-inside');
|
|
24
|
+
|
|
25
|
+
static controlled = new Urlbuilder(PATH_E2E_ACCORDION, 'controlled-test');
|
|
24
26
|
|
|
25
27
|
static datepickerInside = new Urlbuilder(PATH_E2E_ACCORDION, 'actionable-within');
|
|
26
28
|
|
|
@@ -34,7 +36,7 @@ export default class DSAccordionCO extends PageObject {
|
|
|
34
36
|
|
|
35
37
|
static keepContentURL = new Urlbuilder(PATH_E2E_ACCORDION, 'keep-content-mounted');
|
|
36
38
|
|
|
37
|
-
static focusOnItemURL = new Urlbuilder(
|
|
39
|
+
static focusOnItemURL = new Urlbuilder(PATH_E2E_ACCORDION_PITFALLS, 'focus-on-item-test');
|
|
38
40
|
|
|
39
41
|
static applyAriaDisabled = new Urlbuilder(PATH_E2E_ACCORDION, 'apply-aria-disabled-test');
|
|
40
42
|
|
|
@@ -100,11 +102,21 @@ export default class DSAccordionCO extends PageObject {
|
|
|
100
102
|
|
|
101
103
|
static getToolbarByIndex = async (index) => getElementByIndex(this.getToolbarTriggers, index);
|
|
102
104
|
|
|
105
|
+
static async getToolbarMenuByIndex(index = 0) {
|
|
106
|
+
return $$('[data-testid="ds-menuitem-menu-item-wrapper"]')[index];
|
|
107
|
+
}
|
|
108
|
+
|
|
103
109
|
static getAccordionItemHeaderContainers = async () => $$('[data-testid="ds-accordion-item-header-container"]');
|
|
104
110
|
|
|
105
111
|
static getAccordionItemHeaderContainerByIndex = async (index) =>
|
|
106
112
|
getElementByIndex(this.getAccordionItemHeaderContainers, index);
|
|
107
113
|
|
|
114
|
+
static getAccordionItemHeaderCustomActionsContainers = async () =>
|
|
115
|
+
$$('[data-testid="ds-accordion-item-header-custom-actions-container"]');
|
|
116
|
+
|
|
117
|
+
static getAccordionItemHeaderCustomActionsContainerByIndex = async (index) =>
|
|
118
|
+
getElementByIndex(this.getAccordionItemHeaderCustomActionsContainers, index);
|
|
119
|
+
|
|
108
120
|
// slots
|
|
109
121
|
|
|
110
122
|
static async getAccordionContainerSlotByIndex(index = 0) {
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# QA Notes — ds-accordion E2E
|
|
2
|
+
|
|
3
|
+
Durable QA knowledge for the `accordion` suite. Carried over from the `ds-accordion-native` POC
|
|
4
|
+
notes ([PUI-18083](https://jira.elliemae.io/browse/PUI-18083)) when that parallel suite was removed —
|
|
5
|
+
see "Native migration" below.
|
|
6
|
+
|
|
7
|
+
## Native migration ([PUI-18742](https://jira.elliemae.io/browse/PUI-18742))
|
|
8
|
+
|
|
9
|
+
`ds-accordion` now renders a native `<details>` / `<summary>` disclosure instead of the previous
|
|
10
|
+
WAI-ARIA button pattern. Public API, slot names and `data-testid` values are unchanged; only the DOM
|
|
11
|
+
engine changed. Full contract: [`stories/ds-accordion/docs/NativeDisclosureMigration.md`](../../stories/ds-accordion/docs/NativeDisclosureMigration.md).
|
|
12
|
+
|
|
13
|
+
```html
|
|
14
|
+
<div data-testid="ds-accordion_item">
|
|
15
|
+
<details data-testid="ds-accordion-item-details">
|
|
16
|
+
<summary data-testid="ds-accordion_item-header" aria-expanded aria-controls="ds-accordion-content-0">
|
|
17
|
+
<div data-testid="ds-accordion-item-header-container">… chevron + title(s) …</div>
|
|
18
|
+
</summary>
|
|
19
|
+
<div data-testid="ds-accordion_item-content" role="region" aria-labelledby="ds-accordion-header-0">…</div>
|
|
20
|
+
</details>
|
|
21
|
+
<div data-testid="ds-accordion-item-header-custom-actions-container">… custom actions …</div>
|
|
22
|
+
</div>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**What this changes for specs:**
|
|
26
|
+
|
|
27
|
+
- The trigger is a `<summary>`, **not** a `<button>`. `getAccordionHeader(i)` returns the `<summary>`.
|
|
28
|
+
- The heading container lives **inside** the summary (inverse of the pre-migration nesting).
|
|
29
|
+
- `role="heading"` + `aria-level` are **not** emitted by the component. They are opt-in per consumer
|
|
30
|
+
through the `dsAccordionItemHeaderContainer` slot prop. Only stories that set that prop
|
|
31
|
+
(e.g. `WithSecondaryTitleTest`, `AdvancedHeadingStructureCustomization`) expose heading semantics —
|
|
32
|
+
`HeaderControlExamplesTest` does not. Assert the role only on a story that opts in
|
|
33
|
+
(`role/DSAccordion.role-heading.func.spec.js`).
|
|
34
|
+
- Custom actions render as a **sibling of `<details>`**, outside the trigger. Nothing interactive is
|
|
35
|
+
nested inside the `<summary>`.
|
|
36
|
+
- `ds-accordion-item-details` is an additive slot/testid introduced by the migration.
|
|
37
|
+
|
|
38
|
+
The former `ds-accordion-native` E2E suite was deleted here — `ds-accordion` **is** the native engine
|
|
39
|
+
now, so the parity suite had no stories left to point at (`stories/ds-accordion-native` and
|
|
40
|
+
`PATH_E2E_ACCORDION_NATIVE` were removed in PUI-18742).
|
|
41
|
+
|
|
42
|
+
## header-structure func — test 04 flaky "Login not displayed" (cloud)
|
|
43
|
+
|
|
44
|
+
**Status:** spec hardened (spec-only + one additive CO helper). Investigated 2026-07-02 on the native
|
|
45
|
+
suite; the same hardening now lives in `header-structure/DSAccordion.header-structure.func.spec.js`.
|
|
46
|
+
|
|
47
|
+
**Symptom:** in the cloud run (`E2E_BACKEND=cloud`, `BASE_URL`=NEXT/d3, Chrome-only) test
|
|
48
|
+
`04: toolbar trigger in custom actions should open dropdown menu on click` broke with
|
|
49
|
+
`element ("*=Login") still not displayed after 10000ms`. Only that browser runs it (the spec is
|
|
50
|
+
Chrome-guarded), so it surfaces as 1 broken.
|
|
51
|
+
|
|
52
|
+
**Not a defect.** Reproduced against NEXT/d3 at the SDK viewport (1920×1080): the click opens the
|
|
53
|
+
`DSDropdownMenuV2` (`dropdown-menu-listbox` + `ds-floating-wrapper-root` present), `Login` resolves to
|
|
54
|
+
a single visible `<p>`, not clipped by any overflow ancestor and not occluded (`elementFromPoint` at
|
|
55
|
+
its center returns the element), and it stays open at 3s. Selectors, story and package are correct.
|
|
56
|
+
Passed 100% locally, broke 100% in cloud → the delta is real-Chrome + BrowserStack +
|
|
57
|
+
`browser.maximizeWindow()` (cloud-only).
|
|
58
|
+
|
|
59
|
+
**Root cause:** the pattern "one-shot click on a toggle + `waitForDisplayed` on a deep descendant" is
|
|
60
|
+
fragile. If the click doesn't leave the menu open in that driver, the wait sits the full 10s on a menu
|
|
61
|
+
that never opened.
|
|
62
|
+
|
|
63
|
+
**Fix:** wait for the trigger to be clickable, click it, then assert the `DSDropdownMenuV2` item
|
|
64
|
+
wrapper (`getToolbarMenuByIndex` → `ds-menuitem-menu-item-wrapper`) is displayed _before_ checking the
|
|
65
|
+
first option, and tag-qualify the option selector as `p*=Login` (`DSTypography variant="b1"` renders a
|
|
66
|
+
`<p>`). The SDK's retries absorb residual flakiness. Optional broader mitigation: enable
|
|
67
|
+
`config.specFileRetries` in `wdio.config.mjs`.
|
|
68
|
+
|
|
69
|
+
## input-inside func — `data-testid` is on the `<input>`, not a wrapper
|
|
70
|
+
|
|
71
|
+
`DSInputText` forwards `data-testid` through its global attributes straight onto `StyledInput`, i.e.
|
|
72
|
+
the `<input>` element. A descendant selector like `[data-testid="task-name"] input` matches nothing
|
|
73
|
+
and breaks on every browser. Target the testid directly.
|
|
74
|
+
|
|
75
|
+
## Open defects from the native POC — re-verify against ds-accordion
|
|
76
|
+
|
|
77
|
+
These were logged against `ds-accordion-native` while it was a separate POC package. Now that
|
|
78
|
+
`ds-accordion` ships the native engine, **each needs re-verification against `ds-accordion`** before
|
|
79
|
+
being closed or re-pointed — they are listed here so the findings are not lost with the deleted suite,
|
|
80
|
+
not as confirmed `ds-accordion` defects.
|
|
81
|
+
|
|
82
|
+
| Ticket | Summary |
|
|
83
|
+
| ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
84
|
+
| [PUI-18640](https://jira.elliemae.io/browse/PUI-18640) | Content-container slot did not apply style-props — `maxHeight`/`overflow` (scrollable-content) and padding `p` (XstyledpropsInContent) — the way pre-migration `ds-accordion` did. Breaking for consumers styling content via the slot. |
|
|
85
|
+
| [PUI-18641](https://jira.elliemae.io/browse/PUI-18641) | Default title behavior changed from truncate-with-tooltip to wrap. With `wrapLabel={false}` the title truncates but shows no tooltip on hover → full text unreadable. Backwards-incompatible default + readability gap. |
|
|
86
|
+
| [PUI-18642](https://jira.elliemae.io/browse/PUI-18642) | Arrow Icon visual spec violations (Accordion Draft v1.5.0): region width is not the spec'd 20px; when the title wraps the icon is center-aligned instead of top-aligned ("Fixed Top-aligned — Region A"). |
|
|
87
|
+
| [PUI-18695](https://jira.elliemae.io/browse/PUI-18695) | _Safari-only:_ Tab does not move focus between accordion headers after a click. Click-focus, focus ring and Enter all work; only Tab traversal is broken. Found by E2E visual PUI-14324 - 02 (Safari). |
|
|
88
|
+
|
|
89
|
+
Related upstream: [WebKit bug #319162](https://bugs.webkit.org/show_bug.cgi?id=319162) — in Safari,
|
|
90
|
+
tabbing away from a `<summary>` that contains nested elements after **mouse** activation does not
|
|
91
|
+
advance focus correctly. Keyboard-only navigation is unaffected. Unresolved upstream.
|
|
92
|
+
|
|
93
|
+
## Known visual baseline note — slots (`PUI-15348 - 01`)
|
|
94
|
+
|
|
95
|
+
Percy flagged a ~0.05% diff: a small lavender box at the left of each "… Secondary" row. Not a
|
|
96
|
+
regression. `StyledHeading` moved from `display: contents` → `display: flex`; an element with
|
|
97
|
+
`display: contents` generates no box and therefore never paints its `background`, so the `SlotsTest`
|
|
98
|
+
story's lavender `item-heading` background was silently dropped before and paints now. Only visible in
|
|
99
|
+
that synthetic story (every slot painted a loud color). Re-approve the baseline if it resurfaces.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
_Historical detail (A/B/C/D divergence audit, Percy mechanism, run commands) lived in
|
|
104
|
+
`stories/ds-accordion-native/POC_FINDINGS.md`, removed in PUI-18742. Recover with
|
|
105
|
+
`git show 3468ca3ccb4^:stories/ds-accordion-native/POC_FINDINGS.md`._
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import DSAccordionCO from '../DSAccordionCO';
|
|
2
|
+
|
|
3
|
+
if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
|
|
4
|
+
// New coverage for the ControlledTest story (previously untested).
|
|
5
|
+
describe('PUI-18650 - Accordion, controlled -func', () => {
|
|
6
|
+
before('loading page', async () => {
|
|
7
|
+
const errorOnGo = await DSAccordionCO.controlled.go();
|
|
8
|
+
if (errorOnGo) throw errorOnGo;
|
|
9
|
+
});
|
|
10
|
+
it('01: single-open: opening another item collapses the previously open one', async () => {
|
|
11
|
+
await expect(await DSAccordionCO.getAccordionHeader(0)).toHaveAttribute('aria-expanded', 'true');
|
|
12
|
+
await (await DSAccordionCO.getAccordionHeader(1)).click();
|
|
13
|
+
await expect(await DSAccordionCO.getAccordionHeader(1)).toHaveAttribute('aria-expanded', 'true');
|
|
14
|
+
await expect(await DSAccordionCO.getAccordionHeader(0)).toHaveAttribute('aria-expanded', 'false');
|
|
15
|
+
});
|
|
16
|
+
it('02: multiple-open: opening two items keeps both expanded', async () => {
|
|
17
|
+
await (await DSAccordionCO.getAccordionHeader(3)).click();
|
|
18
|
+
await (await DSAccordionCO.getAccordionHeader(4)).click();
|
|
19
|
+
await expect(await DSAccordionCO.getAccordionHeader(3)).toHaveAttribute('aria-expanded', 'true');
|
|
20
|
+
await expect(await DSAccordionCO.getAccordionHeader(4)).toHaveAttribute('aria-expanded', 'true');
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import DSAccordionCO from '../DSAccordionCO';
|
|
2
|
+
|
|
3
|
+
if (
|
|
4
|
+
(!browser.capabilities['ice:options'].isPhone &&
|
|
5
|
+
!browser.capabilities['ice:options'].isTablet &&
|
|
6
|
+
browser.capabilities.browserName === 'chrome') ||
|
|
7
|
+
browser.capabilities.browserName === 'Chrome'
|
|
8
|
+
) {
|
|
9
|
+
// Structural coverage for custom actions living OUTSIDE the disclosure trigger.
|
|
10
|
+
// Originally written for PUI-17912 (custom actions moved out of the role="heading" container).
|
|
11
|
+
// PUI-18742 migrated ds-accordion to a native <details>/<summary> disclosure, which supersedes
|
|
12
|
+
// that fix: the <summary> IS the toggle, the heading container now sits INSIDE it, and heading
|
|
13
|
+
// semantics (role="heading" + aria-level) are opt-in per consumer via the
|
|
14
|
+
// dsAccordionItemHeaderContainer slot prop — see role/DSAccordion.role-heading.func.spec.js.
|
|
15
|
+
// The invariant that still matters here: nothing interactive is nested inside the trigger.
|
|
16
|
+
describe('PUI-18621 - DSAccordion:: heading container structure after renderCustomActions fix - func', () => {
|
|
17
|
+
before('loading page', async () => {
|
|
18
|
+
const errorOnGo = await DSAccordionCO.headerControls.go();
|
|
19
|
+
if (errorOnGo) throw errorOnGo;
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('01: summary trigger should wrap the heading container and no other interactive elements', async () => {
|
|
23
|
+
const trigger = await DSAccordionCO.getAccordionHeader(0);
|
|
24
|
+
await expect(await trigger.getTagName()).toBe('summary');
|
|
25
|
+
|
|
26
|
+
const headingContainer = await DSAccordionCO.getAccordionItemHeaderContainerByIndex(0);
|
|
27
|
+
await expect(headingContainer).toExist();
|
|
28
|
+
|
|
29
|
+
// The <summary> is the toggle itself, so no nested <button> may live inside it.
|
|
30
|
+
const buttonsInsideTrigger = await trigger.$$('button');
|
|
31
|
+
await expect(buttonsInsideTrigger.length).toBe(0);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('02: custom actions container should exist outside the heading container', async () => {
|
|
35
|
+
const customActionsContainer = await DSAccordionCO.getAccordionItemHeaderCustomActionsContainerByIndex(0);
|
|
36
|
+
await expect(customActionsContainer).toExist();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('03: action buttons in custom actions container should reflect correct enabled/disabled state', async () => {
|
|
40
|
+
const enabledContainer = await DSAccordionCO.getAccordionItemHeaderCustomActionsContainerByIndex(0);
|
|
41
|
+
const enabledButton = await enabledContainer.$('[data-testid="ds-button"]');
|
|
42
|
+
await expect(enabledButton).toBeDisplayed();
|
|
43
|
+
await expect(enabledButton).toBeEnabled();
|
|
44
|
+
|
|
45
|
+
const disabledContainer = await DSAccordionCO.getAccordionItemHeaderCustomActionsContainerByIndex(2);
|
|
46
|
+
const disabledButton = await disabledContainer.$('[data-testid="ds-button"]');
|
|
47
|
+
await expect(disabledButton).toBeDisplayed();
|
|
48
|
+
await expect(disabledButton).not.toBeEnabled();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('04: toolbar trigger in custom actions should open dropdown menu on click', async () => {
|
|
52
|
+
// Hardened after the cloud-only "Login not displayed" flake (see QA_NOTES.md): wait for the
|
|
53
|
+
// trigger to be clickable, then assert the DSDropdownMenuV2 item wrapper is displayed before
|
|
54
|
+
// reaching for the option, so a menu that never opened fails fast instead of burning the
|
|
55
|
+
// 10s waitForDisplayed. `p*=Login` is tag-qualified — DSTypography variant="b1" renders a <p>.
|
|
56
|
+
const toolbar = await DSAccordionCO.getToolbarByIndex(0);
|
|
57
|
+
await toolbar.waitForClickable({ timeout: 10000 });
|
|
58
|
+
await toolbar.click();
|
|
59
|
+
const menu = await DSAccordionCO.getToolbarMenuByIndex(0);
|
|
60
|
+
await expect(menu).toBeDisplayed();
|
|
61
|
+
const firstMenuOption = await $('p*=Login');
|
|
62
|
+
await expect(firstMenuOption).toBeDisplayed();
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import DSAccordionCO from '../DSAccordionCO';
|
|
2
|
+
|
|
3
|
+
if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
|
|
4
|
+
// New coverage for the PUI9261InputInside story (previously untested).
|
|
5
|
+
describe('PUI-18651 - Accordion, input inside content -func', () => {
|
|
6
|
+
before('loading page', async () => {
|
|
7
|
+
const errorOnGo = await DSAccordionCO.inputInside.go();
|
|
8
|
+
if (errorOnGo) throw errorOnGo;
|
|
9
|
+
});
|
|
10
|
+
it('01: should type into an input rendered inside the open accordion item', async () => {
|
|
11
|
+
// DSInputText forwards `data-testid` through its global attributes onto the <input> itself
|
|
12
|
+
// (StyledInput), not onto the wrapper — so the testid IS the input, never its ancestor.
|
|
13
|
+
const input = await $('[data-testid="task-name"]');
|
|
14
|
+
await input.waitForDisplayed();
|
|
15
|
+
await input.setValue('Test task');
|
|
16
|
+
await expect(input).toHaveValue('Test task');
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
}
|
|
@@ -18,14 +18,27 @@ export default class DSAppPickerCO extends PageObject {
|
|
|
18
18
|
|
|
19
19
|
static reflowURL = new Urlbuilder(`${PATH_E2E_APP_PICKER}`, 'reflow-test');
|
|
20
20
|
|
|
21
|
+
// PUI-18647 — the two custom-trigger APIs side by side. Storybook kebab-cases the
|
|
22
|
+
// `PUI18647CustomTriggers...` export with a hyphen after the prefix, hence `pui-18647`.
|
|
23
|
+
static customTriggerFocusURL = new Urlbuilder(
|
|
24
|
+
`${PATH_E2E_APP_PICKER}`,
|
|
25
|
+
'pui-18647-custom-triggers-focus-parity-with-deprecated',
|
|
26
|
+
);
|
|
27
|
+
|
|
21
28
|
// Snapshots
|
|
22
29
|
static snapshotPath(example = 'basic') {
|
|
23
30
|
return PageObject.getSnapshotPathBuilder('AppPicker', example);
|
|
24
31
|
}
|
|
25
32
|
|
|
26
33
|
// selectors
|
|
34
|
+
// Anchored on data-testid, NOT on the `#app-picker__button` id this used to select. The trigger's
|
|
35
|
+
// `id` is the per-instance dialog label id the dialog's aria-labelledby resolves to
|
|
36
|
+
// (`ds-app-picker-<uid>-dialog-trigger-btn`), deliberately uid-based so several pickers can
|
|
37
|
+
// coexist — documented under "Multiple pickers on one page" in the AccessibilityBehavior docs,
|
|
38
|
+
// which points automation at either a `data-testid` or an `id` prop passed to DSAppPicker.
|
|
39
|
+
// data-testid is the QA-stability-protected identifier, so it is the correct anchor here.
|
|
27
40
|
static async getOpenAppPicker() {
|
|
28
|
-
return $(
|
|
41
|
+
return $('[data-testid="app-picker__button"]');
|
|
29
42
|
}
|
|
30
43
|
|
|
31
44
|
static getChips = async () => $$('[data-testid="app-picker__chip"]');
|
|
@@ -51,12 +64,97 @@ export default class DSAppPickerCO extends PageObject {
|
|
|
51
64
|
return $('[data-testid="ds-apppicker-root"]');
|
|
52
65
|
}
|
|
53
66
|
|
|
67
|
+
// The floating layer that wraps the panel — carries role="dialog" + aria-labelledby. It sits two
|
|
68
|
+
// levels ABOVE the panel root and is portaled to document.body, so it is not reachable from the
|
|
69
|
+
// root selector.
|
|
70
|
+
static async getFloatingWrapper() {
|
|
71
|
+
return $('[data-testid="ds-apppicker-floating-wrapper"]');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// One per section (apps + customApps) — the ARIA group tying a section title to its chips.
|
|
75
|
+
static getGroups = async () => $$('[data-testid="ds-apppicker-group"]');
|
|
76
|
+
|
|
77
|
+
static getGroupByIndex = async (index) => getElementByIndex(this.getGroups, index);
|
|
78
|
+
|
|
79
|
+
static getTitles = async () => $$('[data-testid="ds-apppicker-title"]');
|
|
80
|
+
|
|
81
|
+
static getTitleByIndex = async (index) => getElementByIndex(this.getTitles, index);
|
|
82
|
+
|
|
83
|
+
// Full-width layout rows holding a section title or the separator — purely presentational.
|
|
84
|
+
static getRows = async () => $$('[data-testid="ds-apppicker-row"]');
|
|
85
|
+
|
|
86
|
+
static async openPanel() {
|
|
87
|
+
const trigger = await this.getOpenAppPicker();
|
|
88
|
+
await trigger.waitForDisplayed();
|
|
89
|
+
await trigger.click();
|
|
90
|
+
await (await this.getAppPickerRoot()).waitForDisplayed();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Reads one value per element in a wdio element array. Element arrays in wdio 9 expose their own
|
|
94
|
+
// promise-returning `map`, so `Promise.all(list.map(fn))` is handed a Promise rather than an
|
|
95
|
+
// iterable and throws. `length` + index access behave like a plain array in every version, so the
|
|
96
|
+
// iteration is built from those instead.
|
|
97
|
+
static async collect(elements, read) {
|
|
98
|
+
return Promise.all(Array.from({ length: elements.length }, (_, index) => read(elements[index])));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Measures every chip in the open panel and buckets them by vertical offset — one bucket per
|
|
102
|
+
// rendered grid row. Row membership is derived, not hardcoded: the 3-column grid reflows with
|
|
103
|
+
// viewport width and font size, so which chips share a row is a runtime fact.
|
|
104
|
+
static async getChipRowsGeometry() {
|
|
105
|
+
const chips = await this.getChips();
|
|
106
|
+
const measured = await DSAppPickerCO.collect(chips, async (chip) => {
|
|
107
|
+
const { y } = await chip.getLocation();
|
|
108
|
+
const { height } = await chip.getSize();
|
|
109
|
+
return { label: await chip.getAttribute('aria-label'), top: Math.round(y), height: Math.round(height) };
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const rowsByTop = measured.reduce((acc, chip) => {
|
|
113
|
+
acc[chip.top] = [...(acc[chip.top] ?? []), chip];
|
|
114
|
+
return acc;
|
|
115
|
+
}, {});
|
|
116
|
+
|
|
117
|
+
return Object.values(rowsByTop).map(DSAppPickerCO.summariseChipRow);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Reduces one measured row to the numbers a height assertion needs, plus a human-readable
|
|
121
|
+
// breakdown so a failure names the offending chips and their pixel heights.
|
|
122
|
+
static summariseChipRow(row) {
|
|
123
|
+
const heights = row.map((chip) => chip.height);
|
|
124
|
+
return {
|
|
125
|
+
chipCount: row.length,
|
|
126
|
+
tallest: Math.max(...heights),
|
|
127
|
+
shortest: Math.min(...heights),
|
|
128
|
+
breakdown: row.map((chip) => `${chip.label} (${chip.height}px)`).join(', '),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
54
132
|
static async getChipLabelByIndex(index) {
|
|
55
133
|
return $$('[data-testid="ds-chip-label"]')[index];
|
|
56
134
|
}
|
|
57
135
|
|
|
136
|
+
// Selection is exposed as `aria-current="true"`, not `aria-selected`. The chips are `role="button"`,
|
|
137
|
+
// which does not support `aria-selected` — PUI-17213/PUI-17860 (#8260) swapped it for `aria-current`
|
|
138
|
+
// plus the "X of Y" position announcement, signed off with the A11y SME.
|
|
139
|
+
// The attribute is omitted (not `false`) when unselected, so `getAttribute` resolves to null: compare
|
|
140
|
+
// the value instead of calling a string method on it, so an unselected chip returns false rather than
|
|
141
|
+
// throwing.
|
|
58
142
|
static async isSelected(element) {
|
|
59
|
-
return (await element.getAttribute('aria-
|
|
143
|
+
return (await element.getAttribute('aria-current')) === 'true';
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// PUI-18647 selectors
|
|
147
|
+
|
|
148
|
+
// The supported API: DSAppPicker hands the trigger renderer `innerRef` plus the internal handlers,
|
|
149
|
+
// so it can drive the first-app/selected-app focus logic on open.
|
|
150
|
+
static async getSupportedCustomTrigger() {
|
|
151
|
+
return $('[data-testid="pui18647-trigger-component"]');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// The deprecated API: `renderTrigger` receives only `ref`, so it cannot reach those handlers. It
|
|
155
|
+
// keeps its pre-existing behaviour by design — this is not a bug, it is the documented delta.
|
|
156
|
+
static async getDeprecatedCustomTrigger() {
|
|
157
|
+
return $('[data-testid="pui18647-render-trigger"]');
|
|
60
158
|
}
|
|
61
159
|
|
|
62
160
|
// Slots
|
|
@@ -78,6 +176,6 @@ export default class DSAppPickerCO extends PageObject {
|
|
|
78
176
|
}
|
|
79
177
|
|
|
80
178
|
static async getTitleSlotByIndex(index = 0) {
|
|
81
|
-
return $$('[data-dimsum-slot="dsApppickerTitle"]')[index];
|
|
179
|
+
return $$('[data-dimsum-parent-slot="dsApppickerTitle"]')[index];
|
|
82
180
|
}
|
|
83
181
|
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import DSAppPickerCO from '../DSAppPickerCO';
|
|
2
|
+
|
|
3
|
+
// Tests for the fix introduced in PUI-17213 (Roles and Pattern Mismatch): the AppPicker was built
|
|
4
|
+
// as a menu but carried neither the menu nor the dialog ARIA contract. It is now a dialog —
|
|
5
|
+
// aria-haspopup="dialog" + no aria-expanded on the trigger, role="dialog" + aria-labelledby on the
|
|
6
|
+
// floating layer, one role="group" per section labelled by its <h3> title, presentational layout
|
|
7
|
+
// rows, and chips left with their native button semantics instead of role="option".
|
|
8
|
+
//
|
|
9
|
+
// Every id in this component is namespaced by a per-instance uid, so the assertions are relational
|
|
10
|
+
// (the dialog's aria-labelledby resolves to the trigger's id) rather than matching literal strings.
|
|
11
|
+
if (
|
|
12
|
+
(!browser.capabilities['ice:options'].isPhone &&
|
|
13
|
+
!browser.capabilities['ice:options'].isTablet &&
|
|
14
|
+
browser.capabilities.browserName === 'chrome') ||
|
|
15
|
+
browser.capabilities.browserName === 'Chrome'
|
|
16
|
+
) {
|
|
17
|
+
describe('PUI-18911 - DSAppPicker:: dialog ARIA pattern roles and relationships - Func', () => {
|
|
18
|
+
before('loading page', async () => {
|
|
19
|
+
const errorOnGo = await DSAppPickerCO.basicURL.go();
|
|
20
|
+
if (errorOnGo) throw errorOnGo;
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('01: should expose the closed trigger as a dialog popup button', async () => {
|
|
24
|
+
const trigger = await DSAppPickerCO.getOpenAppPicker();
|
|
25
|
+
await trigger.waitForDisplayed();
|
|
26
|
+
|
|
27
|
+
await expect(trigger).toHaveAttribute('aria-haspopup', 'dialog');
|
|
28
|
+
await expect(trigger).toHaveAttribute('aria-label', 'Application picker');
|
|
29
|
+
// aria-expanded belongs to disclosure patterns; on a dialog popup it produces a conflicting
|
|
30
|
+
// announcement, so it must be absent both closed and open (re-checked in 02).
|
|
31
|
+
await expect(await trigger.getAttribute('aria-expanded')).toBe(null);
|
|
32
|
+
await expect(await trigger.getAttribute('id')).not.toBe(null);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('02: should open a dialog whose accessible name comes from the trigger', async () => {
|
|
36
|
+
const trigger = await DSAppPickerCO.getOpenAppPicker();
|
|
37
|
+
await DSAppPickerCO.openPanel();
|
|
38
|
+
|
|
39
|
+
const dialog = await DSAppPickerCO.getFloatingWrapper();
|
|
40
|
+
await expect(dialog).toHaveAttribute('role', 'dialog');
|
|
41
|
+
// The dialog and the trigger share one accessible name: aria-labelledby points at the trigger.
|
|
42
|
+
await expect(await dialog.getAttribute('aria-labelledby')).toBe(await trigger.getAttribute('id'));
|
|
43
|
+
// The replaced aria-label="popup menu" must not have come back alongside aria-labelledby.
|
|
44
|
+
await expect(await dialog.getAttribute('aria-label')).toBe(null);
|
|
45
|
+
|
|
46
|
+
// The panel root is roleless (the former role="region" is gone), so it carries no name either.
|
|
47
|
+
const root = await DSAppPickerCO.getAppPickerRoot();
|
|
48
|
+
await expect(await root.getAttribute('role')).toBe(null);
|
|
49
|
+
await expect(await root.getAttribute('aria-label')).toBe(null);
|
|
50
|
+
|
|
51
|
+
await expect(await trigger.getAttribute('aria-expanded')).toBe(null);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('03: should group each section and label it with its own h3 heading', async () => {
|
|
55
|
+
const groups = await DSAppPickerCO.getGroups();
|
|
56
|
+
const titles = await DSAppPickerCO.getTitles();
|
|
57
|
+
// The story renders apps + customApps, so both sections are present.
|
|
58
|
+
await expect(groups.length).toBe(2);
|
|
59
|
+
await expect(titles.length).toBe(2);
|
|
60
|
+
|
|
61
|
+
const mainGroup = await DSAppPickerCO.getGroupByIndex(0);
|
|
62
|
+
const mainTitle = await DSAppPickerCO.getTitleByIndex(0);
|
|
63
|
+
await expect(mainGroup).toHaveAttribute('role', 'group');
|
|
64
|
+
await expect(await mainGroup.getAttribute('aria-labelledby')).toBe(await mainTitle.getAttribute('id'));
|
|
65
|
+
|
|
66
|
+
const customGroup = await DSAppPickerCO.getGroupByIndex(1);
|
|
67
|
+
const customTitle = await DSAppPickerCO.getTitleByIndex(1);
|
|
68
|
+
await expect(customGroup).toHaveAttribute('role', 'group');
|
|
69
|
+
await expect(await customGroup.getAttribute('aria-labelledby')).toBe(await customTitle.getAttribute('id'));
|
|
70
|
+
|
|
71
|
+
// The titles stay real headings: role="presentation" would hide them from screen reader
|
|
72
|
+
// heading navigation in browse mode.
|
|
73
|
+
await expect(await mainTitle.getTagName()).toBe('h3');
|
|
74
|
+
await expect(await customTitle.getTagName()).toBe('h3');
|
|
75
|
+
await expect(await mainTitle.getAttribute('role')).toBe(null);
|
|
76
|
+
await expect(await customTitle.getAttribute('role')).toBe(null);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('04: should keep layout rows presentational and chips as buttons', async () => {
|
|
80
|
+
// The full-row wrappers around the titles and the separator are layout only: role="group" was
|
|
81
|
+
// reserved for the real sections (03) and aria-hidden="true" would drop them from the tree
|
|
82
|
+
// instead of conveying them as presentation.
|
|
83
|
+
const rows = await DSAppPickerCO.getRows();
|
|
84
|
+
await expect(rows.length).toBeGreaterThan(0);
|
|
85
|
+
const rowRoles = await DSAppPickerCO.collect(rows, (row) => row.getAttribute('role'));
|
|
86
|
+
const rowAriaHidden = await DSAppPickerCO.collect(rows, (row) => row.getAttribute('aria-hidden'));
|
|
87
|
+
await expect(rowRoles.every((role) => role === null)).toBe(true);
|
|
88
|
+
await expect(rowAriaHidden.every((hidden) => hidden === null)).toBe(true);
|
|
89
|
+
|
|
90
|
+
// Chips keep their native button semantics inside the dialog — role="option" claimed a
|
|
91
|
+
// listbox parent that never existed.
|
|
92
|
+
const chips = await DSAppPickerCO.getChips();
|
|
93
|
+
await expect(chips.length).toBeGreaterThan(0);
|
|
94
|
+
const chipTags = await DSAppPickerCO.collect(chips, (chip) => chip.getTagName());
|
|
95
|
+
const chipRoles = await DSAppPickerCO.collect(chips, (chip) => chip.getAttribute('role'));
|
|
96
|
+
await expect(chipTags.every((tag) => tag === 'button')).toBe(true);
|
|
97
|
+
await expect(chipRoles.every((role) => role === 'button')).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { Key } from 'webdriverio';
|
|
2
2
|
import DSAppPickerCO from '../DSAppPickerCO';
|
|
3
3
|
|
|
4
|
-
if (
|
|
5
|
-
!browser.capabilities['ice:options'].isPhone &&
|
|
6
|
-
!browser.capabilities['ice:options'].isTablet &&
|
|
7
|
-
browser.capabilities.browserName !== 'Safari'
|
|
8
|
-
) {
|
|
4
|
+
if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
|
|
9
5
|
describe('PUI-8030 - AppPicker:: Basic - keyboard nav func', () => {
|
|
10
6
|
before('loading page', async () => {
|
|
11
7
|
const errorOnGo = await DSAppPickerCO.basicURL.go();
|
|
@@ -34,12 +30,27 @@ if (
|
|
|
34
30
|
const appPickerChip = await DSAppPickerCO.getChipByIndex(1);
|
|
35
31
|
await expect(appPickerChip).toBeFocused();
|
|
36
32
|
});
|
|
37
|
-
|
|
33
|
+
// PUI-17950 made Escape the dismissal mechanism for a chip's expanded label, satisfying the
|
|
34
|
+
// "Dismissible" clause of WCAG 2.1 AA 1.4.13. Escape on an open panel is therefore two-stage
|
|
35
|
+
// whenever the focused chip's label truncates: the first press dismisses the expansion, only
|
|
36
|
+
// the second reaches the dialog. Chip 1 here truncates, so both presses are needed. The
|
|
37
|
+
// dismissal is conditional, not blanket — on a chip whose label fits, Escape still closes the
|
|
38
|
+
// panel in a single press, so this is not a rule that can be applied by rote to every spec.
|
|
39
|
+
it('05: should dismiss the expanded chip label and keep the menu open - Escape', async () => {
|
|
40
|
+
const appPickerChip = await DSAppPickerCO.getChipByIndex(1);
|
|
41
|
+
expect(await appPickerChip.getAttribute('data-expanded')).toEqual('true');
|
|
42
|
+
await browser.keys(Key.Escape);
|
|
43
|
+
const appPicker = await DSAppPickerCO.getAppPickerRoot();
|
|
44
|
+
await expect(appPicker).toBeDisplayedInViewport();
|
|
45
|
+
await expect(appPickerChip).toBeFocused();
|
|
46
|
+
expect(await appPickerChip.getAttribute('data-expanded')).not.toEqual('true');
|
|
47
|
+
});
|
|
48
|
+
it('06: should close the menu - Escape', async () => {
|
|
38
49
|
const openAppPickerBtn = await DSAppPickerCO.getOpenAppPicker();
|
|
39
50
|
await browser.keys(Key.Escape);
|
|
40
51
|
await expect(openAppPickerBtn).toBeFocused();
|
|
41
52
|
});
|
|
42
|
-
it('
|
|
53
|
+
it('07: should reopen the menu and focus the first enabled chip - Space', async () => {
|
|
43
54
|
await browser.keys(Key.Space);
|
|
44
55
|
const appPicker = await DSAppPickerCO.getAppPickerRoot();
|
|
45
56
|
const appPickerChip = await DSAppPickerCO.getChipByIndex(1);
|
|
@@ -20,7 +20,7 @@ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:o
|
|
|
20
20
|
await expect(appPicker).not.toBeDisplayedInViewport();
|
|
21
21
|
await expect(triggerBtn).toBeFocused();
|
|
22
22
|
});
|
|
23
|
-
it('03: should
|
|
23
|
+
it('03: should reopen appPicker with the selected app still marked as current', async () => {
|
|
24
24
|
const openAppPickerBtn = await DSAppPickerCO.getOpenAppPicker();
|
|
25
25
|
await openAppPickerBtn.click();
|
|
26
26
|
const reportChip = await DSAppPickerCO.getChipByIndex(6);
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Key } from 'webdriverio';
|
|
2
|
+
import DSAppPickerCO from '../DSAppPickerCO';
|
|
3
|
+
|
|
4
|
+
// Tests for the change introduced in PUI-18647 (GlobalHeader -> DSAppPicker contract passthrough).
|
|
5
|
+
// Widening the hand-off meant a consumer can finally supply a custom trigger, which exposed two
|
|
6
|
+
// different focus stories that now need pinning:
|
|
7
|
+
//
|
|
8
|
+
// - `TriggerComponent` (supported) receives `innerRef` AND the internal open handlers, so a keyboard
|
|
9
|
+
// open can run the selected-app focus logic and land on the selected chip.
|
|
10
|
+
// - `renderTrigger` (deprecated) receives only `ref`, so it cannot reach those handlers and falls
|
|
11
|
+
// back to focusing the panel on every path. Unchanged by design.
|
|
12
|
+
//
|
|
13
|
+
// The mouse path is the RE-BASELINE: a TriggerComponent picker opened with the mouse used to land on
|
|
14
|
+
// the FIRST app and now lands on the panel, matching the built-in trigger. Kept on the full browser
|
|
15
|
+
// matrix because pointer-driven focus is exactly where engines disagree.
|
|
16
|
+
if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
|
|
17
|
+
describe('PUI-19014 - DSAppPicker:: custom trigger open focus destinations - Func', () => {
|
|
18
|
+
before('loading page', async () => {
|
|
19
|
+
const errorOnGo = await DSAppPickerCO.customTriggerFocusURL.go();
|
|
20
|
+
if (errorOnGo) throw errorOnGo;
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('01: should focus the panel when the supported trigger is opened with the mouse', async () => {
|
|
24
|
+
const trigger = await DSAppPickerCO.getSupportedCustomTrigger();
|
|
25
|
+
await trigger.waitForDisplayed();
|
|
26
|
+
await trigger.click();
|
|
27
|
+
|
|
28
|
+
const panel = await DSAppPickerCO.getAppPickerRoot();
|
|
29
|
+
await panel.waitForDisplayed();
|
|
30
|
+
await expect(panel).toBeFocused();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('02: should focus the selected app when the supported trigger is opened with Enter', async () => {
|
|
34
|
+
// Escape closes the panel opened in 01 and returns focus to the trigger, which is also the
|
|
35
|
+
// starting state this case needs.
|
|
36
|
+
await browser.keys(Key.Escape);
|
|
37
|
+
const trigger = await DSAppPickerCO.getSupportedCustomTrigger();
|
|
38
|
+
await expect(trigger).toBeFocused();
|
|
39
|
+
|
|
40
|
+
await browser.keys(Key.Enter);
|
|
41
|
+
await (await DSAppPickerCO.getAppPickerRoot()).waitForDisplayed();
|
|
42
|
+
|
|
43
|
+
// 'Reports' is deliberately the third app, so "landed on the selected app" cannot be mistaken
|
|
44
|
+
// for "landed on the first app".
|
|
45
|
+
const selectedChip = await DSAppPickerCO.getChipByLabel('Reports');
|
|
46
|
+
await expect(selectedChip).toBeFocused();
|
|
47
|
+
await expect(await DSAppPickerCO.isSelected(selectedChip)).toBe(true);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('03: should focus the panel when the deprecated trigger is opened with the mouse', async () => {
|
|
51
|
+
await browser.keys(Key.Escape);
|
|
52
|
+
|
|
53
|
+
const trigger = await DSAppPickerCO.getDeprecatedCustomTrigger();
|
|
54
|
+
await trigger.waitForDisplayed();
|
|
55
|
+
await trigger.click();
|
|
56
|
+
|
|
57
|
+
const panel = await DSAppPickerCO.getAppPickerRoot();
|
|
58
|
+
await panel.waitForDisplayed();
|
|
59
|
+
await expect(panel).toBeFocused();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('04: should focus the panel when the deprecated trigger is opened with Enter', async () => {
|
|
63
|
+
// The panel 03 left open is controlled from the story and has no Escape handler, so it is
|
|
64
|
+
// dismissed by clicking its trigger again. Where a dismissal click leaves focus is NOT what
|
|
65
|
+
// this case is about and is not consistent across engines — clicking a <button> does not focus
|
|
66
|
+
// it on macOS, and the panel unmounting mid-click can blur. So the keyboard starting state is
|
|
67
|
+
// established explicitly instead of being inherited from the click.
|
|
68
|
+
const trigger = await DSAppPickerCO.getDeprecatedCustomTrigger();
|
|
69
|
+
await trigger.click();
|
|
70
|
+
await (await DSAppPickerCO.getAppPickerRoot()).waitForDisplayed({ reverse: true });
|
|
71
|
+
|
|
72
|
+
await browser.execute((el) => el.focus(), trigger);
|
|
73
|
+
await expect(trigger).toBeFocused();
|
|
74
|
+
|
|
75
|
+
await browser.keys(Key.Enter);
|
|
76
|
+
|
|
77
|
+
const panel = await DSAppPickerCO.getAppPickerRoot();
|
|
78
|
+
await panel.waitForDisplayed();
|
|
79
|
+
await expect(panel).toBeFocused();
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
}
|