dimsum-e2e-tests 3.70.0-next.53 → 3.70.0-next.55

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 (96) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/ds-accordion/DSAccordionCO.js +4 -0
  3. package/ds-accordion/QA_NOTES.md +105 -0
  4. package/ds-accordion/header-structure/DSAccordion.header-structure.func.spec.js +24 -8
  5. package/ds-accordion/input-inside/DSAccordion.input-inside.func.spec.js +3 -1
  6. package/ds-apppicker/truncation/DSAppPicker.truncation.visual.spec.js +5 -9
  7. package/ds-card-v3/DSCardV3CO.js +1 -1
  8. package/ds-card-v3/accordion/DSCardV3.accordion-aria.keyboard.func.spec.js +49 -0
  9. package/ds-card-v3/accordion/DSCardV3.accordion.axe-core.func.spec.js +2 -2
  10. package/ds-card-v3/action/DSCardV3.action.axe-core.func.spec.js +24 -0
  11. package/ds-card-v3/action/DSCardV3.action.func.spec.js +53 -0
  12. package/ds-card-v3/action/DSCardV3.action.visual.spec.js +28 -0
  13. package/ds-card-v3/drag-n-drop/DSCardV3.DnD.axe-core.func.spec.js +0 -19
  14. package/ds-card-v3/multi-select/DSCardV3.multiselect.axe-core.func.spec.js +47 -0
  15. package/ds-card-v3/multiple-action/DSCardV3.multiple-action.axe-core.func.spec.js +35 -0
  16. package/ds-card-v3/multiple-control/DSCardV3.multi-control.axe-core.func.spec.js +34 -0
  17. package/ds-card-v3/multiple-control/DSCardV3.multi-control.func.spec.js +2 -1
  18. package/ds-card-v3/multiple-control/DSCardV3.multi-control.visual.spec.js +29 -0
  19. package/ds-card-v3/no-action/DSCardV3.no-action.axe-core.func.spec.js +1 -1
  20. package/ds-card-v3/notification-badges/DSCardV3.notification-badges.axe-core.func.spec.js +33 -0
  21. package/ds-card-v3/notification-badges/DSCardV3.notification-badges.visual.spec.js +28 -0
  22. package/ds-card-v3/variant-accented/DSCardV3.variant-accented.axe-core.func.spec.js +45 -0
  23. package/ds-card-v3/variant-accented-disabled/DSCardV3.variant-accented-disabled.axe-core.func.spec.js +35 -0
  24. package/ds-card-v3/variant-accented-disabled/DSCardV3.variant-accented-disabled.visual.spec.js +28 -0
  25. package/ds-card-v3/variant-disabled/DSCardV3.variant-disabled.axe-core.func.spec.js +1 -1
  26. package/ds-card-v3/variant-disabled/DSCardV3.variant-disabled.func.spec.js +61 -0
  27. package/ds-card-v3/variant-disabled/DSCardV3.variant-disabled.visual.spec.js +20 -0
  28. package/ds-card-v3/{disabled/DSCardV3.disabled-non-interactive.func.spec.js → variant-disabled/DSCardV3.variantDisabled-non-interactive.func.spec.js} +1 -1
  29. package/ds-chat/DSChat.visual.spec.js +1 -1
  30. package/ds-chat/DSChatCO.js +12 -12
  31. package/ds-chat/components/CardCO.js +1 -3
  32. package/ds-chat/components/ComposerCO.js +1 -1
  33. package/ds-chat/components/FloatingButtonCO.js +4 -2
  34. package/ds-chat/floatingbutton/DSChat-floating-button.visual.spec.js +1 -1
  35. package/ds-controlled-form/ds-controlled-checkbox/Basic/DSControlledCheckbox.axe-core.basic.func.spec.js +4 -4
  36. package/ds-controlled-form/ds-controlled-checkbox/Basic/DSControlledCheckbox.basic.visual.spec.js +56 -0
  37. package/ds-controlled-form/ds-controlled-checkbox/DSControlledCheckboxCO.js +4 -0
  38. package/ds-controlled-form/ds-controlled-checkbox/Disabled/DSControlledCheckbox.axe-core.disabled.func.spec.js +1 -1
  39. package/ds-controlled-form/ds-controlled-checkbox/Disabled/DSControlledCheckbox.disabled.visual.spec.js +1 -1
  40. package/ds-controlled-form/ds-controlled-checkbox/HasError/DSControlledCheckbox.axe-core.hasError.func.spec.js +4 -4
  41. package/ds-controlled-form/ds-controlled-checkbox/HasError/DSControlledCheckbox.has-error.visual.spec.js +71 -1
  42. package/ds-controlled-form/ds-controlled-checkbox/Mixed/DSControlledCheckbox.axe-core.mixed.func.spec.js +4 -4
  43. package/ds-controlled-form/ds-controlled-checkbox/Mixed/DSControlledCheckbox.mixed.visual.spec.js +1 -1
  44. package/ds-controlled-form/ds-controlled-checkbox/ReadOnly/DSControlledCheckbox.axe-core.read-only.func.spec.js +3 -3
  45. package/ds-controlled-form/ds-controlled-checkbox/ReadOnly/DSControlledCheckbox.read-only.visual.spec.js +1 -1
  46. package/ds-controlled-form/ds-controlled-checkbox/WithTooltip/DSControlledCheckbox.axe-core.with-tooltip.func.spec.js +1 -1
  47. package/ds-controlled-form/ds-controlled-checkbox/WithTooltip/DSControlledCheckbox.with-tooltip.visual.spec.js +1 -3
  48. package/ds-controlled-form/ds-controlled-checkbox/WrapLabel/DSControlledCheckbox.axe-core.wrap-label.func.spec.js +1 -1
  49. package/ds-controlled-form/ds-controlled-checkbox/WrapLabel/DSControlledCheckbox.wrap-label.visual.spec.js +1 -1
  50. package/ds-controlled-form/ds-controlled-checkbox/aria-disabled/DSControlledCheckbox.aria-disabled.visual.spec.js +2 -6
  51. package/ds-controlled-form/ds-controlled-checkbox/aria-disabled/DSControlledCheckbox.axe-core.aria-disabled.func.spec.js +1 -1
  52. package/ds-controlled-form/ds-controlled-checkbox-group/DSControlledCheckboxGroup.axe-core.func.spec.js +4 -4
  53. package/ds-controlled-form/ds-controlled-checkbox-group/DSControlledCheckboxGroup.visual.spec.js +1 -1
  54. package/ds-data-table-async/filtersV2/DSDataTable.filtersV2-creatablemultiselect.keyboard.func.spec.js +2 -2
  55. package/ds-data-table-async/filtersV2/DSDataTable.filtersV2-creatableselect.keyboard.func.spec.js +2 -2
  56. package/ds-data-table-async/pagination/DSDataTable.pagination.func.spec.js +3 -2
  57. package/ds-data-table-async/resizable/DSDataTable.resizerA11y.func.spec.js +14 -0
  58. package/ds-data-table-async/vissibility/DSDataTable.vissibility.visual.spec.js +2 -0
  59. package/ds-dataviz/DSDataVizCO.js +2 -0
  60. package/ds-dataviz/axecore/DSDataViz.axis.axe-core.func.spec.js +1 -1
  61. package/ds-form-combobox-multi/DSComboboxMultiCO.js +11 -0
  62. package/ds-form-combobox-multi/pills/DSComboboxMulti.pills.func.spec.js +59 -0
  63. package/ds-form-combobox-multi/pills/DSComboboxMulti.pills.visual.spec.js +39 -0
  64. package/ds-form-combobox-multi/with-tooltip/DSComboboxMulti.with-tooltip.axe-core.func.spec.js +39 -0
  65. package/ds-form-combobox-multi/with-tooltip/DSComboboxMulti.with-tooltip.func.spec.js +39 -0
  66. package/ds-form-combobox-multi/with-tooltip/DSComboboxMulti.with-tooltip.visual.spec.js +29 -0
  67. package/ds-form-combobox-single/DSComboboxSingleCO.js +2 -0
  68. package/ds-form-combobox-single/with-tooltip/DSComboboxSingle.with-tooltip.axe-core.func.spec.js +39 -0
  69. package/ds-form-combobox-single/with-tooltip/DSComboboxSingle.with-tooltip.func.spec.js +39 -0
  70. package/ds-form-combobox-single/with-tooltip/DSComboboxSingle.with-tooltip.visual.spec.js +29 -0
  71. package/ds-hooks/DSHook.usetree.func.spec.js +3 -2
  72. package/ds-hooks/useMask/Number/UseNumberMask.axe-core.func.spec.js +48 -0
  73. package/ds-pills-v2/DSPillsV2CO.js +12 -0
  74. package/ds-pills-v2/apply-aria-disabled/DSPills.applyAriaDisabled.func.spec.js +53 -0
  75. package/ds-pills-v2/apply-aria-disabled/DSPills.applyAriaDisabled.visual.spec.js +26 -0
  76. package/ds-pills-v2/disabled/DSPills.disabled.func.spec.js +53 -0
  77. package/ds-pills-v2/disabled/DSPills.disabled.visual.spec.js +33 -0
  78. package/package.json +150 -150
  79. package/paths.js +3 -3
  80. package/ds-accordion-native/DSAccordionNative.axe-core.func.spec.js +0 -135
  81. package/ds-accordion-native/DSAccordionNative.func.spec.js +0 -200
  82. package/ds-accordion-native/DSAccordionNative.visual.spec.js +0 -158
  83. package/ds-accordion-native/DSAccordionNativeCO.js +0 -178
  84. package/ds-accordion-native/QA_NOTES.md +0 -151
  85. package/ds-accordion-native/aria-disabled/DSAccordionNative.aria-disabled.axe-core.func.spec.js +0 -25
  86. package/ds-accordion-native/aria-disabled/DSAccordionNative.aria-disabled.visual.spec.js +0 -28
  87. package/ds-accordion-native/controlled/DSAccordionNative.controlled.func.spec.js +0 -22
  88. package/ds-accordion-native/header-structure/DSAccordionNative.header-structure.func.spec.js +0 -52
  89. package/ds-accordion-native/input-inside/DSAccordionNative.input-inside.func.spec.js +0 -16
  90. package/ds-accordion-native/role/DSAccordionNative.role-heading.func.spec.js +0 -27
  91. package/ds-accordion-native/scrollable-content/DSAccordionNative.scrollable-content.visual.spec.js +0 -49
  92. package/ds-accordion-native/slots/DSAccordionNative.slots.axe-core.func.spec.js +0 -25
  93. package/ds-accordion-native/slots/DSAccordionNative.slots.func.spec.js +0 -73
  94. package/ds-accordion-native/slots/DSAccordionNative.slots.visual.spec.js +0 -21
  95. package/ds-accordion-native/wrapLabel/DSAccordionNative.wrap-label.visual.spec.js +0 -21
  96. package/ds-card-v3/disabled/DSCardV3.disabled.visual.spec.js +0 -16
package/CHANGELOG.md CHANGED
@@ -3,6 +3,18 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## 3.70.0-next.55 (2026-08-10)
7
+
8
+ ### Bug Fixes
9
+
10
+ - ds-app-picker:: a11y fixes + axe-test fixes + markdown files fixes [PUI-17213](https://jira.elliemae.io/browse/PUI-17213) [PUI-17860](https://jira.elliemae.io/browse/PUI-17860) ([#8260](https://git.elliemae.io/platform-ui/dimsum/issues/8260)) ([f24df52](https://git.elliemae.io/platform-ui/dimsum/commit/f24df52d0565660595e557ca6df3c2e6fa815644))
11
+
12
+ ## 3.70.0-next.54 (2026-07-31)
13
+
14
+ ### Bug Fixes
15
+
16
+ - ds-app-picker:: re-organized data-flow for improved stability and long-term scaling [PUI-17213](https://jira.elliemae.io/browse/PUI-17213) ([#8242](https://git.elliemae.io/platform-ui/dimsum/issues/8242)) ([753be67](https://git.elliemae.io/platform-ui/dimsum/commit/753be67beb6d5dcca2c6d8808ebe6540cf76ffc3))
17
+
6
18
  ## 3.70.0-next.53 (2026-07-28)
7
19
 
8
20
  **Note:** Version bump only for package dimsum-e2e-tests
@@ -102,6 +102,10 @@ export default class DSAccordionCO extends PageObject {
102
102
 
103
103
  static getToolbarByIndex = async (index) => getElementByIndex(this.getToolbarTriggers, index);
104
104
 
105
+ static async getToolbarMenuByIndex(index = 0) {
106
+ return $$('[data-testid="ds-menuitem-menu-item-wrapper"]')[index];
107
+ }
108
+
105
109
  static getAccordionItemHeaderContainers = async () => $$('[data-testid="ds-accordion-item-header-container"]');
106
110
 
107
111
  static getAccordionItemHeaderContainerByIndex = async (index) =>
@@ -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`._
@@ -6,19 +6,29 @@ if (
6
6
  browser.capabilities.browserName === 'chrome') ||
7
7
  browser.capabilities.browserName === 'Chrome'
8
8
  ) {
9
- // Tests for the DOM structural fix introduced in PUI-17912
10
- // (custom action buttons moved out of role="heading" container into a sibling)
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.
11
16
  describe('PUI-18621 - DSAccordion:: heading container structure after renderCustomActions fix - func', () => {
12
17
  before('loading page', async () => {
13
18
  const errorOnGo = await DSAccordionCO.headerControls.go();
14
19
  if (errorOnGo) throw errorOnGo;
15
20
  });
16
21
 
17
- it('01: heading container should contain only the toggle button and no other interactive elements', async () => {
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
+
18
26
  const headingContainer = await DSAccordionCO.getAccordionItemHeaderContainerByIndex(0);
19
- await expect(headingContainer).toHaveAttribute('role', 'heading');
20
- const buttonsInsideHeading = await headingContainer.$$('button');
21
- await expect(buttonsInsideHeading.length).toBe(1);
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);
22
32
  });
23
33
 
24
34
  it('02: custom actions container should exist outside the heading container', async () => {
@@ -39,10 +49,16 @@ if (
39
49
  });
40
50
 
41
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>.
42
56
  const toolbar = await DSAccordionCO.getToolbarByIndex(0);
57
+ await toolbar.waitForClickable({ timeout: 10000 });
43
58
  await toolbar.click();
44
- const firstMenuOption = await $('*=Login');
45
- await firstMenuOption.waitForDisplayed();
59
+ const menu = await DSAccordionCO.getToolbarMenuByIndex(0);
60
+ await expect(menu).toBeDisplayed();
61
+ const firstMenuOption = await $('p*=Login');
46
62
  await expect(firstMenuOption).toBeDisplayed();
47
63
  });
48
64
  });
@@ -8,7 +8,9 @@ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:o
8
8
  if (errorOnGo) throw errorOnGo;
9
9
  });
10
10
  it('01: should type into an input rendered inside the open accordion item', async () => {
11
- const input = await $('[data-testid="task-name"] input');
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"]');
12
14
  await input.waitForDisplayed();
13
15
  await input.setValue('Test task');
14
16
  await expect(input).toHaveValue('Test task');
@@ -11,35 +11,31 @@ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:o
11
11
  await browser.maximizeWindow();
12
12
  });
13
13
  it('01: should show the full label on hover', async () => {
14
- // applitools is losing the hover when taking the snapshot
15
- await browser.eyesOpen();
16
14
  await (await DSAppPickerCO.getOpenAppPicker()).waitForDisplayed();
17
15
  const openAppPickerBtn = await DSAppPickerCO.getOpenAppPicker();
18
16
  await openAppPickerBtn.click();
19
17
  const secondChip = await DSAppPickerCO.getChipByLabel('Pipeline but with a really long label that will truncate');
20
18
  await mouseOver(secondChip);
21
19
  await browser.pause(500);
22
- const snapshot = await browser.eyesCheckSnapshot(DSAppPickerCO.snapshotPath('appPicker-truncation-hover'));
20
+ const snapshot = await browser.percyCheckScreenshot();
23
21
  await expect(snapshot).toEqual(0);
24
22
  });
25
23
  it('02: should show the full label on hover - disabled Chip', async () => {
26
- await browser.eyesOpen();
27
24
  const DisabledChip = await DSAppPickerCO.getChipByLabel(
28
25
  'Dashboard but with a really long label that will truncate',
29
26
  );
30
27
  await mouseOver(DisabledChip);
31
28
  await browser.pause(500);
32
- const snapshot = await browser.eyesCheckSnapshot(DSAppPickerCO.snapshotPath('appPicker-truncation-disabled'));
29
+ const snapshot = await browser.percyCheckScreenshot();
33
30
  await expect(snapshot).toEqual(0);
34
31
  });
35
32
  it('03: should show the full label on focus', async () => {
36
- await browser.eyesOpen();
37
- const openAppPickerBtn = await DSAppPickerCO.getOpenAppPicker();
38
- await openAppPickerBtn.click();
33
+ // the panel is already open from test 01 - since PUI-18354 the trigger
34
+ // toggles, so clicking it again would close it
39
35
  await browser.keys(Key.Tab);
40
36
  await browser.keys(Key.Enter);
41
37
  await browser.pause(500);
42
- const snapshot = await browser.eyesCheckSnapshot(DSAppPickerCO.snapshotPath('appPicker-truncation-focus'));
38
+ const snapshot = await browser.percyCheckScreenshot();
43
39
  await expect(snapshot).toEqual(0);
44
40
  });
45
41
  });
@@ -15,7 +15,7 @@ export default class DSCardV3CO extends PageObject {
15
15
 
16
16
  static dragAndDropURL = new Urlbuilder(PATH_E2E_CARD_V3, 'drag-and-drop-test');
17
17
 
18
- static multiActionURL = new Urlbuilder(PATH_E2E_CARD_V3, 'multi-action-test');
18
+ static multiActionURL = new Urlbuilder(PATH_E2E_CARD_V3, 'multiple-action-test');
19
19
 
20
20
  static multipleControlURL = new Urlbuilder(PATH_E2E_CARD_V3, 'multiple-control-test');
21
21
 
@@ -0,0 +1,49 @@
1
+ import { Key } from 'webdriverio';
2
+ import DSCardV3CO from '../DSCardV3CO';
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-18823 - DSCardV3:: accordion ARIA keyboard operation - Func', () => {
11
+ before('loading page', async () => {
12
+ const errorOnGo = await DSCardV3CO.accordionAriaURL.go();
13
+ if (errorOnGo) throw errorOnGo;
14
+ });
15
+
16
+ it('01: should move focus to the accordion trigger as the first tab stop - [TAB]', async () => {
17
+ const trigger = await DSCardV3CO.getAccordionButton();
18
+ await trigger.waitForDisplayed();
19
+ await browser.keys(Key.Tab);
20
+
21
+ await expect(trigger).toBeFocused();
22
+ await expect(trigger).toHaveAttribute('aria-expanded', 'false');
23
+ });
24
+
25
+ it('02: should expand the panel and keep focus on the trigger - [ENTER]', async () => {
26
+ const trigger = await DSCardV3CO.getAccordionButton();
27
+ await browser.keys(Key.Enter);
28
+
29
+ await expect(trigger).toHaveAttribute('aria-expanded', 'true');
30
+ await expect(trigger).toBeFocused();
31
+ });
32
+
33
+ it('03: should collapse the panel and keep focus on the trigger - [SPACE]', async () => {
34
+ const trigger = await DSCardV3CO.getAccordionButton();
35
+ await browser.keys(Key.Space);
36
+
37
+ await expect(trigger).toHaveAttribute('aria-expanded', 'false');
38
+ await expect(trigger).toBeFocused();
39
+ });
40
+
41
+ it('04: should move focus from the trigger to the card actions button - [TAB]', async () => {
42
+ await browser.keys(Key.Tab);
43
+ const cardActions = await DSCardV3CO.getButtonByIndex(1);
44
+
45
+ await expect(cardActions).toBeFocused();
46
+ await expect(cardActions).toHaveAttribute('aria-label', 'Card actions');
47
+ });
48
+ });
49
+ }
@@ -15,14 +15,14 @@ if (
15
15
  it('01: should display the accordion closed and pass axecore test', async () => {
16
16
  await (await DSCardV3CO.getAccordionButton()).waitForDisplayed();
17
17
  const result = await axeCoreCheck();
18
- expect(result.length).toBe(0);
18
+ await expect(result).toHaveLength(0);
19
19
  });
20
20
  it('02: should open the accordion and pass axecore test', async () => {
21
21
  await (await DSCardV3CO.getAccordionButton()).click();
22
22
  const getAccordionFirstElement = await DSCardV3CO.getElement(2);
23
23
  await getAccordionFirstElement.waitForDisplayed();
24
24
  const result = await axeCoreCheck();
25
- expect(result.length).toBe(0);
25
+ await expect(result).toHaveLength(0);
26
26
  });
27
27
  });
28
28
  }
@@ -0,0 +1,24 @@
1
+ import DSCardV3CO from '../DSCardV3CO';
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-18803 - DSCardV3:: action button card accessibility - Axe-Core', () => {
11
+ before('loading page', async () => {
12
+ const errorOnGo = await DSCardV3CO.actionURL.go();
13
+ if (errorOnGo) throw errorOnGo;
14
+ });
15
+
16
+ it('01: should have no accessibility violations', async () => {
17
+ const card = await DSCardV3CO.getCardContainer();
18
+ await card.waitForDisplayed();
19
+
20
+ const result = await axeCoreCheck();
21
+ await expect(result).toHaveLength(0);
22
+ });
23
+ });
24
+ }
@@ -0,0 +1,53 @@
1
+ import { Key } from 'webdriverio';
2
+ import DSCardV3CO from '../DSCardV3CO';
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-18802 - DSCardV3:: action button structure and keyboard focus - Func', () => {
11
+ before('loading page', async () => {
12
+ const errorOnGo = await DSCardV3CO.actionURL.go();
13
+ if (errorOnGo) throw errorOnGo;
14
+ });
15
+
16
+ it('01: should render the card root, header, title, subtitle and a single action button', async () => {
17
+ const card = await DSCardV3CO.getCardContainer();
18
+ await card.waitForDisplayed();
19
+
20
+ const header = await DSCardV3CO.getCardHeader();
21
+ await expect(header).toBeDisplayed();
22
+
23
+ const title = await DSCardV3CO.getElement(0);
24
+ await expect(title).toBeDisplayed();
25
+ await expect(title).toHaveText('Card Title');
26
+ await expect(await title.getTagName()).toBe('h3');
27
+
28
+ const subtitle = await DSCardV3CO.getElement(1);
29
+ await expect(subtitle).toBeDisplayed();
30
+ await expect(subtitle).toHaveText('Card Subtitle');
31
+
32
+ const deleteAction = await DSCardV3CO.getButtonByIndex(0);
33
+ await expect(deleteAction).toBeDisplayed();
34
+ await expect(deleteAction).toHaveAttribute('aria-label', 'Delete Action');
35
+ await expect(deleteAction).toHaveAttribute('type', 'button');
36
+
37
+ const actionButtons = await $$('[data-testid="ds-button"]');
38
+ await expect(actionButtons).toBeElementsArrayOfSize(1);
39
+ });
40
+
41
+ it('02: should move focus to the action button - [TAB]', async () => {
42
+ await browser.keys(Key.Tab);
43
+ const deleteAction = await DSCardV3CO.getButtonByIndex(0);
44
+ await expect(deleteAction).toBeFocused();
45
+ });
46
+
47
+ it('03: should move focus away from the action button - [SHIFT+TAB]', async () => {
48
+ await browser.keys([Key.Shift, Key.Tab]);
49
+ const deleteAction = await DSCardV3CO.getButtonByIndex(0);
50
+ await expect(deleteAction).not.toBeFocused();
51
+ });
52
+ });
53
+ }
@@ -0,0 +1,28 @@
1
+ import { Key } from 'webdriverio';
2
+ import DSCardV3CO from '../DSCardV3CO';
3
+
4
+ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
5
+ describe('PUI-18801 - DSCardV3:: action button card default and focus states - Visual', () => {
6
+ before('loading page', async () => {
7
+ const errorOnGo = await DSCardV3CO.actionURL.go();
8
+ if (errorOnGo) throw errorOnGo;
9
+ });
10
+
11
+ it('01: should display the card with a single action button in the header', async () => {
12
+ const card = await DSCardV3CO.getCardContainer();
13
+ await card.waitForDisplayed();
14
+
15
+ const snapshot = await browser.percyCheckScreenshot();
16
+ await expect(snapshot).toEqual(0);
17
+ });
18
+
19
+ it('02: should display the action button with its focus ring - [TAB]', async () => {
20
+ await browser.keys(Key.Tab);
21
+ const deleteAction = await DSCardV3CO.getButtonByIndex(0);
22
+ await expect(deleteAction).toBeFocused();
23
+
24
+ const snapshot = await browser.percyCheckScreenshot();
25
+ await expect(snapshot).toEqual(0);
26
+ });
27
+ });
28
+ }
@@ -21,39 +21,20 @@ if (
21
21
  });
22
22
 
23
23
  it('02: should pass axe-core while an item is being dragged and cancelled - [TAB][ENTER][ESC]', async () => {
24
- const liveRegion = await DSCardV3CO.getDnDLiveRegion();
25
24
  await browser.keys(Key.Tab);
26
25
  const handle = await DSCardV3CO.getCardHandlerByIndex(0);
27
26
  await expect(handle).toBeFocused();
28
27
  await browser.keys(Key.Return);
29
- await browser.waitUntil(
30
- async () => (await liveRegion.getProperty('textContent')).includes('Draggable item was moved to position 1.'),
31
- { timeoutMsg: 'Expected the live region to announce the item pickup' },
32
- );
33
28
  await browser.keys(Key.Escape);
34
29
  const result = await axeCoreCheck();
35
30
  await expect(result).toHaveLength(0);
36
31
  });
37
32
 
38
33
  it('03: should pass axe-core after an item has been dropped - [TAB][ENTER][ARROWDOWN][ENTER]', async () => {
39
- const liveRegion = await DSCardV3CO.getDnDLiveRegion();
40
34
  await browser.keys(Key.Tab);
41
35
  await browser.keys(Key.Return);
42
- await browser.waitUntil(
43
- async () => (await liveRegion.getProperty('textContent')).includes('was moved to position'),
44
- { timeoutMsg: 'Expected the live region to announce the item pickup' },
45
- );
46
-
47
36
  await browser.keys(Key.ArrowDown);
48
- await browser.waitUntil(
49
- async () => (await liveRegion.getProperty('textContent')).includes('was moved to position'),
50
- { timeoutMsg: 'Expected the live region to announce the move before dropping' },
51
- );
52
37
  await browser.keys(Key.Return);
53
- await browser.waitUntil(
54
- async () => (await liveRegion.getProperty('textContent')).includes('was dropped over position'),
55
- { timeoutMsg: 'Expected the live region to announce the drop' },
56
- );
57
38
  const result = await axeCoreCheck();
58
39
  await expect(result).toHaveLength(0);
59
40
  });
@@ -0,0 +1,47 @@
1
+ import DSCardV3CO from '../DSCardV3CO';
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-18804 - DSCardV3:: multi-select checkbox states accessibility - Axe-Core', () => {
11
+ before('loading page', async () => {
12
+ const errorOnGo = await DSCardV3CO.multiSelectURL.go();
13
+ if (errorOnGo) throw errorOnGo;
14
+ });
15
+
16
+ it('01: should pass axe-core with no card selected', async () => {
17
+ const group = await DSCardV3CO.getGroupContainer();
18
+ await group.waitForDisplayed();
19
+
20
+ const result = await axeCoreCheck();
21
+ await expect(result).toHaveLength(0);
22
+ });
23
+
24
+ it('02: should pass axe-core with the first card selected', async () => {
25
+ const firstCheckbox = await DSCardV3CO.getCardCheckBoxByIndex(0);
26
+ await firstCheckbox.waitForExist();
27
+ await firstCheckbox.click();
28
+ await expect(firstCheckbox).toBeSelected();
29
+
30
+ const result = await axeCoreCheck();
31
+ await expect(result).toHaveLength(0);
32
+ });
33
+
34
+ it('03: should pass axe-core with both cards selected', async () => {
35
+ const secondCheckbox = await DSCardV3CO.getCardCheckBoxByIndex(1);
36
+ await secondCheckbox.waitForExist();
37
+ await secondCheckbox.click();
38
+ await expect(secondCheckbox).toBeSelected();
39
+
40
+ const firstCheckbox = await DSCardV3CO.getCardCheckBoxByIndex(0);
41
+ await expect(firstCheckbox).toBeSelected();
42
+
43
+ const result = await axeCoreCheck();
44
+ await expect(result).toHaveLength(0);
45
+ });
46
+ });
47
+ }
@@ -0,0 +1,35 @@
1
+ import { Key } from 'webdriverio';
2
+ import DSCardV3CO from '../DSCardV3CO';
3
+ import { axeCoreCheck } from '../../helpers';
4
+
5
+ if (
6
+ (!browser.capabilities['ice:options'].isPhone &&
7
+ !browser.capabilities['ice:options'].isTablet &&
8
+ browser.capabilities.browserName === 'chrome') ||
9
+ browser.capabilities.browserName === 'Chrome'
10
+ ) {
11
+ describe('PUI-18827 - DSCardV3:: multiple action buttons accessibility - Axe-Core', () => {
12
+ before('loading page', async () => {
13
+ const errorOnGo = await DSCardV3CO.multiActionURL.go();
14
+ if (errorOnGo) throw errorOnGo;
15
+ });
16
+
17
+ it('01: should have no accessibility violations', async () => {
18
+ const card = await DSCardV3CO.getCardContainer();
19
+ await card.waitForDisplayed();
20
+
21
+ const result = await axeCoreCheck();
22
+ await expect(result).toHaveLength(0);
23
+ });
24
+
25
+ it('02: should have no accessibility violations with the first action button focused', async () => {
26
+ await browser.keys(Key.Tab);
27
+ const flagAction = await DSCardV3CO.getButtonByIndex(0);
28
+ await expect(flagAction).toBeFocused();
29
+ await expect(flagAction).toHaveAttribute('aria-label', 'Flag action');
30
+
31
+ const result = await axeCoreCheck();
32
+ await expect(result).toHaveLength(0);
33
+ });
34
+ });
35
+ }
@@ -0,0 +1,34 @@
1
+ import DSCardV3CO from '../DSCardV3CO';
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-18826 - DSCardV3:: multiple control accessibility - Axe-Core', () => {
11
+ before('loading page', async () => {
12
+ const errorOnGo = await DSCardV3CO.multipleControlURL.go();
13
+ if (errorOnGo) throw errorOnGo;
14
+ });
15
+
16
+ it('01: should have no accessibility violations with no card selected', async () => {
17
+ const card = await DSCardV3CO.getCardContainerByIndex(0);
18
+ await card.waitForDisplayed();
19
+
20
+ const result = await axeCoreCheck();
21
+ await expect(result).toHaveLength(0);
22
+ });
23
+
24
+ it('02: should have no accessibility violations with the first card selected', async () => {
25
+ const firstCheckbox = await DSCardV3CO.getCardCheckBoxByIndex(0);
26
+ await firstCheckbox.waitForExist();
27
+ await firstCheckbox.click();
28
+ await expect(firstCheckbox).toBeSelected();
29
+
30
+ const result = await axeCoreCheck();
31
+ await expect(result).toHaveLength(0);
32
+ });
33
+ });
34
+ }
@@ -13,7 +13,8 @@ if (
13
13
  const errorOnGo = await DSCardV3CO.multipleControlURL.go();
14
14
  if (errorOnGo) throw errorOnGo;
15
15
  });
16
- it('01: first checkbox selection should not select second checkbox - [TAB + SPACE]', async () => {
16
+ it('01: first checkbox selection should not select second checkbox - [TAB + TAB + SPACE]', async () => {
17
+ await browser.keys(Key.Tab);
17
18
  await browser.keys(Key.Tab);
18
19
  await browser.keys(Key.Space);
19
20
  const firstCheckbox = await DSCardV3CO.getCardCheckBoxByIndex(0);
@@ -0,0 +1,29 @@
1
+ import DSCardV3CO from '../DSCardV3CO';
2
+
3
+ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
4
+ describe('PUI-18825 - DSCardV3:: multiple control card states - Visual', () => {
5
+ before('loading page', async () => {
6
+ const errorOnGo = await DSCardV3CO.multipleControlURL.go();
7
+ if (errorOnGo) throw errorOnGo;
8
+ });
9
+
10
+ it('01: should display both cards with their controls unselected', async () => {
11
+ const firstCard = await DSCardV3CO.getCardContainerByIndex(0);
12
+ await firstCard.waitForDisplayed();
13
+ const secondCard = await DSCardV3CO.getCardContainerByIndex(1);
14
+ await expect(secondCard).toBeDisplayed();
15
+
16
+ const snapshot = await browser.percyCheckScreenshot();
17
+ await expect(snapshot).toEqual(0);
18
+ });
19
+
20
+ it('02: should display the first card selected', async () => {
21
+ const firstCheckbox = await DSCardV3CO.getCardCheckBoxByIndex(0);
22
+ await firstCheckbox.click();
23
+ await expect(firstCheckbox).toBeSelected();
24
+
25
+ const snapshot = await browser.percyCheckScreenshot();
26
+ await expect(snapshot).toEqual(0);
27
+ });
28
+ });
29
+ }
@@ -16,7 +16,7 @@ if (
16
16
  const firstElement = await DSCardV3CO.getElement(0);
17
17
  await firstElement.waitForExist();
18
18
  const result = await axeCoreCheck();
19
- expect(result.length).toBe(0);
19
+ await expect(result).toHaveLength(0);
20
20
  });
21
21
  });
22
22
  }