dimsum-e2e-tests 3.70.0-next.4 → 3.70.0-next.40

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.
Files changed (123) hide show
  1. package/CHANGELOG.md +204 -0
  2. package/ds-accordion/DSAccordion.visual.spec.js +6 -0
  3. package/ds-accordion/DSAccordionCO.js +11 -3
  4. package/ds-accordion/controlled/DSAccordion.controlled.func.spec.js +23 -0
  5. package/ds-accordion/header-structure/DSAccordion.header-structure.func.spec.js +49 -0
  6. package/ds-accordion/input-inside/DSAccordion.input-inside.func.spec.js +17 -0
  7. package/ds-accordion-native/DSAccordionNative.axe-core.func.spec.js +135 -0
  8. package/ds-accordion-native/DSAccordionNative.func.spec.js +200 -0
  9. package/ds-accordion-native/DSAccordionNative.visual.spec.js +158 -0
  10. package/ds-accordion-native/DSAccordionNativeCO.js +161 -0
  11. package/ds-accordion-native/QA_NOTES.md +88 -0
  12. package/ds-accordion-native/aria-disabled/DSAccordionNative.aria-disabled.axe-core.func.spec.js +25 -0
  13. package/ds-accordion-native/aria-disabled/DSAccordionNative.aria-disabled.visual.spec.js +28 -0
  14. package/ds-accordion-native/controlled/DSAccordionNative.controlled.func.spec.js +22 -0
  15. package/ds-accordion-native/header-structure/DSAccordionNative.header-structure.func.spec.js +53 -0
  16. package/ds-accordion-native/input-inside/DSAccordionNative.input-inside.func.spec.js +16 -0
  17. package/ds-accordion-native/role/DSAccordionNative.role-heading.func.spec.js +27 -0
  18. package/ds-accordion-native/scrollable-content/DSAccordionNative.scrollable-content.visual.spec.js +49 -0
  19. package/ds-accordion-native/slots/DSAccordionNative.slots.axe-core.func.spec.js +25 -0
  20. package/ds-accordion-native/slots/DSAccordionNative.slots.func.spec.js +73 -0
  21. package/ds-accordion-native/slots/DSAccordionNative.slots.visual.spec.js +21 -0
  22. package/ds-accordion-native/wrapLabel/DSAccordionNative.wrap-label.visual.spec.js +21 -0
  23. package/ds-apppicker/DSAppPickerCO.js +1 -1
  24. package/ds-autocomplete/DSAutocomplete.visual.spec.js +34 -0
  25. package/ds-autocomplete/DSAutocompleteCO.js +2 -0
  26. package/ds-card-v3/DSCardV3CO.js +14 -0
  27. package/ds-card-v3/accordion/DSCardV3.accordion-aria-structure.func.spec.js +41 -0
  28. package/ds-card-v3/disabled/DSCardV3.disabled-non-interactive.func.spec.js +25 -0
  29. package/ds-card-v3/multi-select/DSCardV3.multi-select.aria-grouping.func.spec.js +24 -0
  30. package/ds-card-v3/single-select/DSCardV3.single-select.aria-grouping.func.spec.js +24 -0
  31. package/ds-chat/DSChat.axe-core.func.spec.js +2 -2
  32. package/ds-chat/DSChat.visual.spec.js +3 -3
  33. package/ds-chat/DSChatCO.js +17 -23
  34. package/ds-chat/bubbles/slots/DSChatBubble.slots.axe-core.func.spec.js +24 -0
  35. package/ds-chat/bubbles/slots/DSChatBubble.slots.func.spec.js +49 -0
  36. package/ds-chat/bubbles/slots/DSChatBubble.slots.visual.spec.js +25 -0
  37. package/ds-chat/card/slots/DSChatCard.slots.axe-core.func.spec.js +24 -0
  38. package/ds-chat/card/slots/DSChatCard.slots.func.spec.js +47 -0
  39. package/ds-chat/card/slots/DSChatCard.slots.visual.spec.js +18 -0
  40. package/ds-chat/card/truncated-text/DSChatCard.truncated-text.func.spec.js +32 -0
  41. package/ds-chat/card/truncated-text/DSChatCard.truncated-text.visual.spec.js +26 -0
  42. package/ds-chat/card/with-notification-badges/DSChatCard.with-notification-badges.axe-core.func.spec.js +23 -0
  43. package/ds-chat/card/with-notification-badges/DSChatCard.with-notification-badges.visual.spec.js +17 -0
  44. package/ds-chat/components/BubbleCO.js +46 -3
  45. package/ds-chat/components/CardCO.js +77 -0
  46. package/ds-chat/components/ComposerCO.js +6 -6
  47. package/ds-chat/components/FloatingButtonCO.js +2 -2
  48. package/ds-chat/components/HeaderCO.js +2 -2
  49. package/ds-chat/components/TileCO.js +82 -0
  50. package/ds-chat/components/index.js +3 -2
  51. package/ds-chat/loadmore/DSChat-loadmore.func.spec.js +1 -1
  52. package/{ds-chat-tile → ds-chat/tile}/DSChat-tile.axe-core.func.spec.js +2 -2
  53. package/{ds-chat-tile → ds-chat/tile}/DSChat-tile.func.spec.js +1 -1
  54. package/{ds-chat-tile → ds-chat/tile}/DSChat-tile.visual.spec.js +2 -2
  55. package/{ds-chat-tile → ds-chat/tile}/aria-disabled/DSChat-tile.aria-disabled.axe-core.func.spec.js +2 -2
  56. package/{ds-chat-tile → ds-chat/tile}/aria-disabled/DSChat-tile.aria-disabled.visual.spec.js +1 -1
  57. package/ds-chat/tile/slots/DSChatTile.slots.func.spec.js +53 -0
  58. package/ds-chat/tile/slots/DSChatTile.slots.visual.spec.js +18 -0
  59. package/ds-controlled-form/ds-combobox/DSComboboxCO.js +2 -2
  60. package/ds-controlled-form/ds-controlled-checkbox/DSControlledCheckboxCO.js +1 -1
  61. package/ds-controlled-form/ds-controlled-inputgroup/DSControlledInputGroupCO.js +1 -1
  62. package/ds-data-table-async/DSDataTableCO.js +14 -12
  63. package/ds-data-table-async/basic/DSDataTable.basic.visual.spec.js +1 -1
  64. package/ds-data-table-async/components/FiltersCO.js +1 -1
  65. package/ds-data-table-async/menubutton/DSDataTable.MenuButton.keyboard.func.spec.js +8 -7
  66. package/ds-data-table-async/menubutton/DSDataTable.MenuButton.mouse.func.spec.js +6 -7
  67. package/ds-floating-context/DSFloatingContextCO.js +10 -0
  68. package/ds-floating-context/placement/DSFloatingContext.placement.visual.spec.js +48 -0
  69. package/ds-form-combobox-multi/DSComboboxMultiCO.js +11 -3
  70. package/ds-form-combobox-multi/aria-busy-loading/DSComboboxMulti.aria-busy-loading.axe-core.func.spec.js +55 -0
  71. package/ds-form-combobox-multi/aria-busy-loading/DSComboboxMulti.aria-busy-loading.func.spec.js +57 -0
  72. package/ds-form-combobox-multi/aria-disabled/DSComboboxMulti.aria-disabled.visual.spec.js +15 -0
  73. package/ds-form-combobox-multi/disabled/DSComboboxMulti.disabled.axe-core.func.spec.js +24 -0
  74. package/ds-form-combobox-multi/disabled/DSComboboxMulti.disabled.visual.spec.js +22 -0
  75. package/ds-form-combobox-multi/grouped/DSComboboxMulti.grouped.visual.spec.js +42 -0
  76. package/ds-form-combobox-multi/inline/DSComboboxMulti.inline.visual.spec.js +21 -0
  77. package/ds-form-combobox-multi/skeleton/DSComboboxMulti.skeleton.visual.spec.js +25 -0
  78. package/ds-form-combobox-single/DSComboboxSingleCO.js +11 -3
  79. package/ds-form-combobox-single/aria-busy-loading/DSComboboxSingle.aria-busy-loading.axe-core.func.spec.js +49 -0
  80. package/ds-form-combobox-single/aria-busy-loading/DSComboboxSingle.aria-busy-loading.func.spec.js +54 -0
  81. package/ds-form-combobox-single/aria-disabled/DSComboboxSingle.aria-disabled.visual.spec.js +18 -0
  82. package/ds-form-combobox-single/disabled/DSComboboxSingle.disabled.axe-core.func.spec.js +24 -0
  83. package/ds-form-combobox-single/disabled/DSComboboxSingle.disabled.visual.spec.js +22 -0
  84. package/ds-form-combobox-single/grouped/DSComboboxSingle.grouped.visual.spec.js +45 -0
  85. package/ds-form-combobox-single/inline/DSComboboxSingle.inline.visual.spec.js +23 -0
  86. package/ds-form-combobox-single/skeleton/DSComboboxSingle.skeleton.visual.spec.js +25 -0
  87. package/ds-form-date-range-picker/date-segment-aria-labels/DateRangePicker.date-segment-aria-labels.func.spec.js +64 -0
  88. package/ds-form-native-select/NativeSelect.axe-core.func.spec.js +39 -0
  89. package/ds-form-native-select/NativeSelect.visual.spec.js +33 -0
  90. package/ds-form-native-select/NativeSelectCO.js +6 -0
  91. package/ds-form-native-select/option-selection/NativeSelect.option-selection.func.spec.js +25 -0
  92. package/ds-leftnavigation/LeftNavigationCO.js +2 -2
  93. package/ds-menu-button/DSMenuButtonCO.js +23 -0
  94. package/ds-menu-button/slots/DSMenuButton.slots.func.spec.js +40 -0
  95. package/ds-menu-button/slots/DSMenuButton.slots.visual.spec.js +26 -0
  96. package/ds-modal-slide/ModalSlideCO.js +39 -0
  97. package/ds-modal-slide/custom-header/ModalSlide.customHeader.focusRing.visual.spec.js +2 -1
  98. package/ds-modal-slide/slots/ModalSlide.slots.func.spec.js +74 -0
  99. package/ds-modal-slide/slots/ModalSlide.slots.visual.spec.js +27 -0
  100. package/ds-notification-badge/DSNotificationBadge.visual.spec.js +17 -20
  101. package/ds-page-layout/PageLayoutCO.js +4 -4
  102. package/ds-progress-indicator/DSProgressIndicator.axe-core.func.spec.js +2 -0
  103. package/ds-progress-indicator/DSProgressIndicatorCO.js +1 -1
  104. package/ds-shuttle-v2/DSShuttleV2CO.js +11 -1
  105. package/ds-shuttle-v2/explicit-selection-ui/DSShuttleV2.explicit-selection-ui.func.spec.js +37 -0
  106. package/ds-shuttle-v2/explicit-selection-ui/DSShuttleV2.explicit-selection-ui.visual.spec.js +27 -0
  107. package/ds-shuttle-v2/skipped/DSShuttleV2.extra.axe-core.skipped.js +1 -1
  108. package/ds-shuttle-v2/skipped/DSShuttleV2.filter.axe-core.skipped.js +1 -1
  109. package/ds-shuttle-v2/skipped/DSShuttleV2.globalcheckbox.axe-core.skipped.js +1 -1
  110. package/ds-shuttle-v2/skipped/DSShuttleV2.items.axe-core.skipped.js +3 -3
  111. package/ds-shuttle-v2/skipped/DSShuttleV2.skipped.js +5 -5
  112. package/ds-tab-button/DSTabButton.func.spec.js +1 -1
  113. package/ds-tooltip-v3/DSTooltipV3CO.js +21 -0
  114. package/ds-tooltip-v3/aria-tooltip-pattern/DSTooltipV3.aria-tooltip-pattern.axe-core.func.spec.js +23 -0
  115. package/ds-tooltip-v3/aria-tooltip-pattern/DSTooltipV3.aria-tooltip-pattern.func.spec.js +29 -0
  116. package/ds-tooltip-v3/dialog/DSTooltipV3.dialog.func.spec.js +45 -0
  117. package/ds-tooltip-v3/dialog/DSTooltipV3.dialog.visual.spec.js +29 -0
  118. package/ds-treeview/DSTreeViewCO.js +25 -2
  119. package/ds-treeview/dragAndDrop/TreeView-dnd_keyboard.func.spec.js +96 -0
  120. package/package.json +150 -152
  121. package/paths.js +9 -1
  122. package/ds-chat-tile/TileCO.js +0 -35
  123. package/ds-treeview/dragAndDrop/TreeView-dnd_mouse.func.spec.js +0 -61
@@ -8,8 +8,12 @@ export default class DSTooltipV3CO extends PageObject {
8
8
 
9
9
  static uncontrolledTestUrl = new Urlbuilder(PATH_E2E_TOOLTIP_V3, 'uncontrolled-test');
10
10
 
11
+ static basicTestUrl = new Urlbuilder(PATH_E2E_TOOLTIP_V3, 'basic-test');
12
+
11
13
  static slotsURL = new Urlbuilder(PATH_E2E_TOOLTIP_V3, 'slots-test');
12
14
 
15
+ static inADialogTestUrl = new Urlbuilder(PATH_E2E_TOOLTIP_V3, 'in-a-dialog-test');
16
+
13
17
  // Snapshots
14
18
  static snapshotPath(example = 'basic') {
15
19
  return PageObject.getSnapshotPathBuilder('TooltipV3', example);
@@ -20,10 +24,27 @@ export default class DSTooltipV3CO extends PageObject {
20
24
  return $('[data-testid="ds-tooltip-v3-tooltip-text-wrapper"]');
21
25
  }
22
26
 
27
+ static async getBasicTestTriggerButton() {
28
+ return $('button[aria-describedby="basic-tooltip"]');
29
+ }
30
+
23
31
  static async getTooltipContentByIndex(index = 0) {
24
32
  return $$('[data-testid="ds-tooltip-v3-tooltip-text-wrapper"] [data-testid="ds-typography-element"]')[index];
25
33
  }
26
34
 
35
+ // "tooltip in a dialog" selectors (PUI-18012 dismissal mechanism)
36
+ static async getOpenDialogButton() {
37
+ return $('[data-testid="open-dialog-button"]');
38
+ }
39
+
40
+ static async getDialogContainer() {
41
+ return $('[data-testid="ds-dialog-container"]');
42
+ }
43
+
44
+ static async getInADialogTriggerButton() {
45
+ return $('button[aria-describedby="in-a-dialog-tooltip"]');
46
+ }
47
+
27
48
  // slot selectors
28
49
  static async getRootSlot() {
29
50
  return $('[data-dimsum-slot="dsTooltipv3Root"]');
@@ -0,0 +1,23 @@
1
+ import DSTooltipV3CO from '../DSTooltipV3CO';
2
+ import { axeCoreCheck } from '../../helpers';
3
+
4
+ if (
5
+ (!browser.capabilities['ice:options'].isPhone &&
6
+ !browser.capabilities['ice:options'].isTablet &&
7
+ browser.capabilities.browserName === 'chrome') ||
8
+ browser.capabilities.browserName === 'Chrome'
9
+ ) {
10
+ describe('PUI-18498 - TooltipV3:: WAI-ARIA tooltip pattern - AxeCore', () => {
11
+ before('loading page', async () => {
12
+ const errorOnGo = await DSTooltipV3CO.basicTestUrl.go();
13
+ if (errorOnGo) throw errorOnGo;
14
+ });
15
+
16
+ it('01: should render the basic tooltip pattern and pass axe-core scan', async () => {
17
+ const tooltipContainer = await DSTooltipV3CO.getTooltip();
18
+ await tooltipContainer.waitForDisplayed();
19
+ const result = await axeCoreCheck();
20
+ expect(result.length).toBe(0);
21
+ });
22
+ });
23
+ }
@@ -0,0 +1,29 @@
1
+ import DSTooltipV3CO from '../DSTooltipV3CO';
2
+
3
+ // Tests for the fix introduced in PUI-18011 / PUI-18010:
4
+ // the tooltip container must expose role="tooltip" and its `id` so that consumers
5
+ // can wire `aria-describedby` from the trigger element (W3C WAI-ARIA tooltip pattern).
6
+ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
7
+ describe('PUI-18495 - TooltipV3:: WAI-ARIA tooltip pattern (role + aria-describedby) - func', () => {
8
+ before('loading page', async () => {
9
+ const errorOnGo = await DSTooltipV3CO.basicTestUrl.go();
10
+ if (errorOnGo) throw errorOnGo;
11
+ });
12
+
13
+ it('01: should expose role="tooltip", a matching id on the container and aria-describedby on trigger', async () => {
14
+ const tooltipContainer = await DSTooltipV3CO.getTooltip();
15
+ const triggerButton = await DSTooltipV3CO.getBasicTestTriggerButton();
16
+
17
+ await expect(tooltipContainer).toBeExisting();
18
+ await expect(tooltipContainer).toHaveAttribute('role', 'tooltip');
19
+ await expect(tooltipContainer).toHaveAttribute('id', 'basic-tooltip');
20
+
21
+ await expect(triggerButton).toBeExisting();
22
+ await expect(triggerButton).toHaveAttribute('aria-describedby', 'basic-tooltip');
23
+
24
+ const containerId = await tooltipContainer.getAttribute('id');
25
+ const triggerDescribedBy = await triggerButton.getAttribute('aria-describedby');
26
+ await expect(containerId).toBe(triggerDescribedBy);
27
+ });
28
+ });
29
+ }
@@ -0,0 +1,45 @@
1
+ import { Key } from 'webdriverio';
2
+ import { mouseOver } from '../../helpers';
3
+ import DSTooltipV3CO from '../DSTooltipV3CO';
4
+
5
+ // Tests for the fix introduced in PUI-18012 (a tooltip inside a dialog must be dismissible with ESC
6
+ // without closing the dialog — WCAG 2.2 SC 1.4.13 Content on Hover or Focus, Dismissible).
7
+ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
8
+ describe('PUI-18592 - TooltipV3:: dismissal and behavior of a tooltip inside a dialog -Func', () => {
9
+ before('loading page', async () => {
10
+ const errorOnGo = await DSTooltipV3CO.inADialogTestUrl.go();
11
+ if (errorOnGo) throw errorOnGo;
12
+ });
13
+
14
+ it('01: should open the dialog and show the tooltip with its text on hover', async () => {
15
+ const openButton = await DSTooltipV3CO.getOpenDialogButton();
16
+ await openButton.click();
17
+
18
+ const dialog = await DSTooltipV3CO.getDialogContainer();
19
+ await expect(dialog).toBeDisplayed();
20
+
21
+ const trigger = await DSTooltipV3CO.getInADialogTriggerButton();
22
+ await mouseOver(trigger);
23
+
24
+ const tooltip = await DSTooltipV3CO.getTooltip();
25
+ await expect(tooltip).toBeDisplayed();
26
+ await expect(tooltip).toHaveText(expect.stringContaining('Tooltip text 3'));
27
+ });
28
+
29
+ it('02: should dismiss only the tooltip on ESC, keeping the dialog open', async () => {
30
+ const tooltip = await DSTooltipV3CO.getTooltip();
31
+ await browser.keys(Key.Escape);
32
+
33
+ await expect(tooltip).not.toBeDisplayed();
34
+ const dialog = await DSTooltipV3CO.getDialogContainer();
35
+ await expect(dialog).toBeDisplayed();
36
+ });
37
+
38
+ it('03: should close the dialog on a subsequent ESC once the tooltip is dismissed', async () => {
39
+ await browser.keys(Key.Escape);
40
+
41
+ const dialog = await DSTooltipV3CO.getDialogContainer();
42
+ await expect(dialog).not.toBeDisplayed();
43
+ });
44
+ });
45
+ }
@@ -0,0 +1,29 @@
1
+ import { mouseOver } from '../../helpers';
2
+ import DSTooltipV3CO from '../DSTooltipV3CO';
3
+
4
+ // Visual coverage for PUI-18012: how a tooltip looks when displayed inside a dialog.
5
+ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
6
+ describe('PUI-18593 - TooltipV3:: tooltip displayed inside a dialog -Visual', () => {
7
+ before('loading page', async () => {
8
+ const errorOnGo = await DSTooltipV3CO.inADialogTestUrl.go();
9
+ if (errorOnGo) throw errorOnGo;
10
+ });
11
+
12
+ it('01: should display the tooltip inside the open dialog', async () => {
13
+ const openButton = await DSTooltipV3CO.getOpenDialogButton();
14
+ await openButton.click();
15
+
16
+ const dialog = await DSTooltipV3CO.getDialogContainer();
17
+ await expect(dialog).toBeDisplayed();
18
+
19
+ const trigger = await DSTooltipV3CO.getInADialogTriggerButton();
20
+ await mouseOver(trigger);
21
+
22
+ const tooltip = await DSTooltipV3CO.getTooltip();
23
+ await expect(tooltip).toBeDisplayed();
24
+
25
+ const snapshot = await browser.percyCheckScreenshot(DSTooltipV3CO.snapshotPath('tooltip-in-dialog'));
26
+ await expect(snapshot).toEqual(0);
27
+ });
28
+ });
29
+ }
@@ -226,7 +226,7 @@ export default class DSTreeViewCO extends PageObject {
226
226
  }
227
227
 
228
228
  static async getElementsTexts() {
229
- return $$('[data-testid="DS-SimpleTruncateText"]');
229
+ return $$('[data-testid="tree-item-content"]');
230
230
  }
231
231
 
232
232
  static async getCollapseBtn() {
@@ -241,6 +241,12 @@ export default class DSTreeViewCO extends PageObject {
241
241
  return (await $$('[data-testid="drag-handle"]'))[index];
242
242
  }
243
243
 
244
+ // Drag handles carry a stable id of the form `${itemId}-drag-handle`, so this selects a row's
245
+ // handle independent of its current position/index (which shifts with the expansion state).
246
+ static async getDragHandleByItemId(itemId) {
247
+ return $(`[id="${itemId}-drag-handle"]`);
248
+ }
249
+
244
250
  static async getFirstDragHandle() {
245
251
  return $$('[data-testid="drag-handle"]')[0];
246
252
  }
@@ -269,7 +275,7 @@ export default class DSTreeViewCO extends PageObject {
269
275
  }
270
276
 
271
277
  static async getTooltip() {
272
- return $('[data-testid="popover-container"]');
278
+ return $('[data-testid="ds-floating-wrapper-root"]');
273
279
  }
274
280
 
275
281
  static async noItemsFound() {
@@ -317,6 +323,23 @@ export default class DSTreeViewCO extends PageObject {
317
323
  ]);
318
324
  }
319
325
 
326
+ // Expands a row identified by its content text, but only if it is currently collapsed.
327
+ // Idempotent on purpose: after a drag-and-drop, whether the target group is auto-expanded
328
+ // varies by browser, so a blind toggle would re-collapse an already-expanded row.
329
+ static async ensureRowExpandedByText(text) {
330
+ return browser.execute((rowText) => {
331
+ const items = Array.from(document.querySelectorAll('[data-testid="tree-item"]'));
332
+ const item = items.find((node) => {
333
+ const content = node.querySelector('[data-testid="tree-item-content"]');
334
+ return content && content.textContent.trim() === rowText;
335
+ });
336
+ if (item && item.getAttribute('aria-expanded') === 'false') {
337
+ const toggle = item.querySelector('[data-testid="tree-item-expand-toggle"]');
338
+ if (toggle) toggle.click();
339
+ }
340
+ }, text);
341
+ }
342
+
320
343
  static async isExpanded(index) {
321
344
  return (await this.getRow(index)).getAttribute('aria-expanded');
322
345
  }
@@ -0,0 +1,96 @@
1
+ /* eslint-disable wdio/no-pause */
2
+ import { Key } from 'webdriverio';
3
+ import DSTreeViewCO from '../DSTreeViewCO';
4
+
5
+ // The TreeView uses @dnd-kit (pointer + keyboard sensors), not HTML5 native drag.
6
+ // WDIO's mouse `.dragAndDrop()` only actuates the pointer sensor reliably under
7
+ // geckodriver (Firefox); Chromedriver/safaridriver synthesize the drag differently,
8
+ // so the mouse-driven version of these tests passed only in Firefox. These tests are
9
+ // therefore driven through the dnd-kit keyboard sensor (Space to pick up, ArrowDown
10
+ // to move/nest, Space to drop), which is deterministic and stable across all browsers
11
+ // — mirroring the keyboard-driven dnd tests in ds-data-table-async. Do not convert
12
+ // back to mouse `.dragAndDrop()`.
13
+
14
+ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
15
+ describe('PUI-11320 - TreeView, Basic Drag and Drop Functionality (keyboard)', () => {
16
+ before(async () => {
17
+ const errorOnGo = await DSTreeViewCO.dragAndDrop.go();
18
+ if (errorOnGo) throw errorOnGo;
19
+ });
20
+ it('01: drag and drop in the same position - parent item', async () => {
21
+ const dragHandleFirstRow = await DSTreeViewCO.getDragHandle(0);
22
+ await dragHandleFirstRow.click();
23
+ await browser.keys(Key.Space); // pick up
24
+ await browser.pause(300);
25
+ await browser.keys(Key.Space); // drop in place
26
+ await browser.pause(300);
27
+ const firstRow = await DSTreeViewCO.getRowContent(0);
28
+ await expect(firstRow).toHaveText(expect.stringContaining('Parent. id: 1'));
29
+ });
30
+ it('02: drag and drop in the same position - child item', async () => {
31
+ const expandableBtnFirstRow = await DSTreeViewCO.getToggleBtn(0);
32
+ await expandableBtnFirstRow.click();
33
+ await browser.pause(300);
34
+ const dragHandleFirstChild = await DSTreeViewCO.getDragHandle(1);
35
+ await dragHandleFirstChild.click();
36
+ await browser.keys(Key.Space); // pick up
37
+ await browser.pause(300);
38
+ await browser.keys(Key.Space); // drop in place
39
+ await browser.pause(300);
40
+ const firstChildRow = await DSTreeViewCO.getRowContent(1);
41
+ await expect(firstChildRow).toHaveText(expect.stringContaining('Child of 1. id: 2'));
42
+ });
43
+ it('03: drag a parent and drop it in another parent', async () => {
44
+ const dragHandleParentId1 = await DSTreeViewCO.getDragHandle(0);
45
+ await dragHandleParentId1.click();
46
+ await browser.keys(Key.Space); // pick up Parent id 1
47
+ await browser.pause(300);
48
+ await browser.keys(Key.ArrowDown); // move into Parent id 4
49
+ await browser.pause(300);
50
+ await browser.keys(Key.Space); // drop
51
+ await browser.pause(300);
52
+ await DSTreeViewCO.expandCollapseAll();
53
+ await browser.pause(300);
54
+ const firstRow = await DSTreeViewCO.getRowContent(0);
55
+ await expect(firstRow).toHaveText(expect.stringContaining('Parent. id: 4'));
56
+ });
57
+ // Safari's WebKit driver is non-deterministic for TreeView keyboard drag-and-drop (the drag
58
+ // intermittently fails to nest the item), so this scenario is not registered on Safari —
59
+ // consistent with PUI-8198, which is also skipped on Safari. It still runs on Chrome, Edge and
60
+ // Firefox.
61
+ if (browser.capabilities.browserName !== 'Safari') {
62
+ it('04: drag a child of a parent and drop it in another parent with no children', async () => {
63
+ // Make the dragged child (id 3) visible regardless of the expansion state the previous test
64
+ // left behind (expandCollapseAll is browser-dependent), then select it by its stable handle
65
+ // id instead of an absolute index — an absolute index points at the wrong row when an
66
+ // ancestor group is collapsed.
67
+ await DSTreeViewCO.ensureRowExpandedByText('Parent. id: 4');
68
+ await DSTreeViewCO.ensureRowExpandedByText('Parent. id: 1');
69
+ await browser.pause(300);
70
+ const dragHandleChildOfParent1 = await DSTreeViewCO.getDragHandleByItemId(3);
71
+ await dragHandleChildOfParent1.click();
72
+ await browser.keys(Key.Space); // pick up Child of 1. Also parent. id 3
73
+ await browser.pause(300);
74
+ await browser.keys(Key.ArrowDown); // move into Item with no children. id 7
75
+ await browser.pause(300);
76
+ await browser.keys(Key.Space); // drop
77
+ await browser.pause(300);
78
+ // Reveal the dragged child by expanding its new parent (id 7), but only when collapsed.
79
+ // expandCollapseAll() is avoided: it is a focus-dependent toggle that behaves inconsistently
80
+ // across browsers after a keyboard drop, and whether the drop auto-expands id 7 also varies.
81
+ await DSTreeViewCO.ensureRowExpandedByText('Item with no children. id: 7');
82
+ await browser.pause(300);
83
+
84
+ // Assert relative to id 7 rather than an absolute row index: the exact indices depend on how
85
+ // many ancestor groups are expanded (which varies across browsers). The dragged child (id 3)
86
+ // is always the row immediately after its new parent (id 7).
87
+ const rowContents = await DSTreeViewCO.getElementsTexts();
88
+ // WebdriverIO's element-array `.map()` is an async helper that resolves to the values
89
+ // directly — do not wrap it in Promise.all (that passes a Promise to Promise.all).
90
+ const rowTexts = await rowContents.map((row) => row.getText());
91
+ const parentId7Index = rowTexts.indexOf('Item with no children. id: 7');
92
+ await expect(rowTexts[parentId7Index + 1]).toEqual('Child of 1. Also parent. id: 3');
93
+ });
94
+ }
95
+ });
96
+ }