dimsum-e2e-tests 3.80.0-next.2 → 3.80.0-next.20

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 (90) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/ds-apppicker/aria-disabled/DSAppPicker.aria-disabled.visual.spec.js +14 -1
  3. package/ds-apppicker/basic/DSAppPicker.basic.visual.spec.js +12 -7
  4. package/ds-fast-list/DSFastListCO.js +37 -0
  5. package/ds-fast-list/basic/DSFastList.basic.axe-core.func.spec.js +28 -0
  6. package/ds-fast-list/basic/DSFastList.basic.visual.spec.js +23 -0
  7. package/ds-fast-list/scroll-to-index/DSFastList.scroll-to-index.func.spec.js +45 -0
  8. package/ds-pills-v2/DSPillsV2CO.js +53 -1
  9. package/ds-pills-v2/pitfalls/DSPills.inputPill.func.spec.js +26 -0
  10. package/ds-pills-v2/pitfalls/DSPills.inputWithFormItemBlockURL.axe-core.func.spec.js +38 -0
  11. package/ds-pills-v2/pitfalls/DSPills.inputWithFormItemBlockURL.func.spec.js +72 -0
  12. package/ds-progress-indicator/DSProgressIndicator.axe-core.func.spec.js +8 -5
  13. package/ds-progress-indicator/DSProgressIndicator.func.spec.js +18 -4
  14. package/ds-progress-indicator/DSProgressIndicator.visual.spec.js +14 -6
  15. package/ds-progress-indicator/DSProgressIndicatorCO.js +80 -9
  16. package/ds-progress-indicator/aria-contract/DSProgressIndicator.aria-contract.func.spec.js +104 -0
  17. package/ds-progress-indicator/slots/DSProgressIndicator.slots.axe-core.func.spec.js +31 -0
  18. package/ds-progress-indicator/slots/DSProgressIndicator.slots.func.spec.js +87 -0
  19. package/ds-progress-indicator/slots/DSProgressIndicator.slots.visual.spec.js +26 -0
  20. package/ds-virtuallist/DSVirtualList.visual.spec.js +4 -5
  21. package/ds-virtuallist/DSVirtualListCO.js +28 -9
  22. package/ds-virtuallist/basic/DSVirtualList.basic.axe-core.func.spec.js +28 -0
  23. package/ds-virtuallist/scroll-to-index/DSVirtualList.scroll-to-index.func.spec.js +45 -0
  24. package/package.json +148 -149
  25. package/paths.js +3 -49
  26. package/ds-mobile/Accordion/DSAccordion.visual.spec.js +0 -33
  27. package/ds-mobile/Accordion/DSAccordionCO.js +0 -37
  28. package/ds-mobile/CategoryBox/CategoryBox.visual.spec.js +0 -18
  29. package/ds-mobile/CategoryBox/CategoryBoxCO.js +0 -17
  30. package/ds-mobile/CollectionBox/CollectionBox.visual.spec.js +0 -16
  31. package/ds-mobile/CollectionBox/CollectionBoxCO.js +0 -15
  32. package/ds-mobile/GlobalHeader/DSGlobalHeader.visual.spec.js +0 -55
  33. package/ds-mobile/GlobalHeader/DSGlobalHeaderCO.js +0 -36
  34. package/ds-mobile/GroupBox/GroupBox.visual.spec.js +0 -15
  35. package/ds-mobile/GroupBox/GroupBoxCO.js +0 -15
  36. package/ds-mobile/InfiniteLoader/InfiniteLoader.func.spec.js +0 -90
  37. package/ds-mobile/InfiniteLoader/InfiniteLoaderCO.js +0 -29
  38. package/ds-mobile/MobileActionToolbar/MobileActionToolbar.visual.spec.js +0 -39
  39. package/ds-mobile/MobileActionToolbar/MobileActionToolbarCO.js +0 -19
  40. package/ds-mobile/MobileBanner/MobileBanner.visual.spec.js +0 -23
  41. package/ds-mobile/MobileBanner/MobileBannerCO.js +0 -23
  42. package/ds-mobile/MobileCard/Card.func.spec.js +0 -38
  43. package/ds-mobile/MobileCard/Card.visual.spec.js +0 -103
  44. package/ds-mobile/MobileCard/MobileCardCO.js +0 -42
  45. package/ds-mobile/MobileContextMenu/MobileContextMenu.func.spec.js +0 -88
  46. package/ds-mobile/MobileContextMenu/MobileContextMenu.visual.spec.js +0 -31
  47. package/ds-mobile/MobileContextMenu/MobileContextMenuCO.js +0 -72
  48. package/ds-mobile/MobileDatePicker/MobileDatePicker.func.spec.js +0 -15
  49. package/ds-mobile/MobileDatePicker/MobileDatePicker.visual.spec.js +0 -15
  50. package/ds-mobile/MobileDatePicker/MobileDatePickerCO.js +0 -35
  51. package/ds-mobile/MobileDropdownMenu/MobileDropdownMenu.func.spec.js +0 -38
  52. package/ds-mobile/MobileDropdownMenu/MobileDropdownMenu.visual.spec.js +0 -16
  53. package/ds-mobile/MobileDropdownMenu/MobileDropdownMenuCO.js +0 -37
  54. package/ds-mobile/MobileEmptyState/MobileEmptyState.visual.spec.js +0 -15
  55. package/ds-mobile/MobileEmptyState/MobileEmptyStateCO.js +0 -14
  56. package/ds-mobile/MobileFilterbar/MobileFilterbar.visual.spec.js +0 -39
  57. package/ds-mobile/MobileFilterbar/MobileFilterbarCO.js +0 -19
  58. package/ds-mobile/MobileFooter/MobileFooter.func.spec.js +0 -26
  59. package/ds-mobile/MobileFooter/MobileFooter.visual.spec.js +0 -51
  60. package/ds-mobile/MobileFooter/MobileFooterCO.js +0 -27
  61. package/ds-mobile/MobileListItem/MobileListItem.visual.spec.js +0 -56
  62. package/ds-mobile/MobileListItem/MobileListItemCO.js +0 -19
  63. package/ds-mobile/MobileLoadingPage/MobileLoadingPage.visual.spec.js +0 -37
  64. package/ds-mobile/MobileLoadingPage/MobileLoadingPageCO.js +0 -23
  65. package/ds-mobile/MobilePageHeader/MobilePageHeader.func.spec.js +0 -22
  66. package/ds-mobile/MobilePageHeader/MobilePageHeader.visual.spec.js +0 -135
  67. package/ds-mobile/MobilePageHeader/MobilePageHeaderCO.js +0 -67
  68. package/ds-mobile/MobileSelectList/MobileSelectList.visual.spec.js +0 -56
  69. package/ds-mobile/MobileSelectList/MobileSelectListCO.js +0 -21
  70. package/ds-mobile/MobileSeparator/MobileSeparator.visual.spec.js +0 -28
  71. package/ds-mobile/MobileSeparator/MobileSeparatorCO.js +0 -17
  72. package/ds-mobile/MobileTimePicker/MobileTimePickerCO.js +0 -41
  73. package/ds-mobile/Modal/MobileModal.visual.spec.js +0 -56
  74. package/ds-mobile/Modal/MobileModalCO.js +0 -28
  75. package/ds-mobile/PageFilter/PageFilter.visual.spec.js +0 -46
  76. package/ds-mobile/PageFilter/PageFilterCO.js +0 -19
  77. package/ds-mobile/PageForm/PageForm.visual.spec.js +0 -14
  78. package/ds-mobile/PageForm/PageFormCO.js +0 -11
  79. package/ds-mobile/PageList/PageList.visual.spec.js +0 -31
  80. package/ds-mobile/PageList/PageListCO.js +0 -19
  81. package/ds-mobile/PageSummary/PageSummary.visual.spec.js +0 -20
  82. package/ds-mobile/PageSummary/PageSummaryCO.js +0 -11
  83. package/ds-mobile/SwipeToRefresh/SwipeToRefresh.func.spec.js +0 -26
  84. package/ds-mobile/SwipeToRefresh/SwipeToRefreshCO.js +0 -20
  85. package/ds-mobile/Tabs/MobileTabs.visual.spec.js +0 -91
  86. package/ds-mobile/Tabs/TabsCO.js +0 -37
  87. package/ds-mobile/Tooltip/MobileTooltip.func.spec.js +0 -17
  88. package/ds-mobile/Tooltip/MobileTooltip.visual.spec.js +0 -16
  89. package/ds-mobile/Tooltip/TooltipCO.js +0 -23
  90. package/ds-mobile/helpers.js +0 -7
package/CHANGELOG.md CHANGED
@@ -3,6 +3,102 @@
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.80.0-next.20](/github.com/intcx/PLATFORM-UI/compare/v3.80.0-next.19...v3.80.0-next.20) (2026-09-28)
7
+
8
+ **Note:** Version bump only for package dimsum-e2e-tests
9
+
10
+ ## [3.80.0-next.19](/github.com/intcx/PLATFORM-UI/compare/v3.80.0-next.18...v3.80.0-next.19) (2026-09-28)
11
+
12
+ **Note:** Version bump only for package dimsum-e2e-tests
13
+
14
+ ## [3.80.0-next.18](/github.com/intcx/PLATFORM-UI/compare/v3.80.0-next.17...v3.80.0-next.18) (2026-09-25)
15
+
16
+ **Note:** Version bump only for package dimsum-e2e-tests
17
+
18
+ ## [3.80.0-next.17](/github.com/intcx/PLATFORM-UI/compare/v3.80.0-next.16...v3.80.0-next.17) (2026-09-25)
19
+
20
+ **Note:** Version bump only for package dimsum-e2e-tests
21
+
22
+ ## 3.80.0-next.16 (2026-09-25)
23
+
24
+ **Note:** Version bump only for package dimsum-e2e-tests
25
+
26
+ ## 3.80.0-next.15 (2026-09-25)
27
+
28
+ **Note:** Version bump only for package dimsum-e2e-tests
29
+
30
+ ## 3.80.0-next.14 (2026-09-24)
31
+
32
+ ### Features
33
+
34
+ - ds-banner:: new spec implementation [PUI-18239](https://jira.elliemae.io/browse/PUI-18239) ([64c5a7c](https://github.com/intcx/PLATFORM-UI.dimsum/commit/64c5a7c20734e210ce1845d7743e51be8d333a4a))
35
+
36
+ ## 3.80.0-next.13 (2026-09-23)
37
+
38
+ ### Bug Fixes
39
+
40
+ - ds-ribbon:: render both the icon and the label when a card has both [PUI-19189](https://jira.elliemae.io/browse/PUI-19189) ([#8391](https://github.com/intcx/PLATFORM-UI.dimsum/issues/8391)) ([0bef678](https://github.com/intcx/PLATFORM-UI.dimsum/commit/0bef6784fcbc370a9e73220fa5f6071ddc8cd94c))
41
+
42
+ ## 3.80.0-next.12 (2026-09-22)
43
+
44
+ ### Features
45
+
46
+ - dimsum:: add Breadcrumb and InputMask Accessibility Expert Validation docs stories [PUI-18917](https://jira.elliemae.io/browse/PUI-18917) ([#8371](https://github.com/intcx/PLATFORM-UI.dimsum/issues/8371)) ([f1b3410](https://github.com/intcx/PLATFORM-UI.dimsum/commit/f1b34109a9e9e56a63a6d9d22441eb89c41fc14e))
47
+
48
+ ## 3.80.0-next.11 (2026-09-22)
49
+
50
+ ### Features
51
+
52
+ - ds-fast-list:: E2E coverage - visual, axe-core, scroll-to-index [PUI-19124](https://jira.elliemae.io/browse/PUI-19124) ([#8382](https://github.com/intcx/PLATFORM-UI.dimsum/issues/8382)) ([7f0da31](https://github.com/intcx/PLATFORM-UI.dimsum/commit/7f0da316cb8086f4f5c20af35cffe2440dad625c))
53
+
54
+ ## 3.80.0-next.10 (2026-09-22)
55
+
56
+ ### Bug Fixes
57
+
58
+ - ds-ribbon:: align status icon fills with the theme palette [PUI-19186](https://jira.elliemae.io/browse/PUI-19186) ([#8385](https://github.com/intcx/PLATFORM-UI.dimsum/issues/8385)) ([84ca6f4](https://github.com/intcx/PLATFORM-UI.dimsum/commit/84ca6f42f3767846539678474fc7980b9603b303))
59
+
60
+ ## 3.80.0-next.9 (2026-09-21)
61
+
62
+ ### Features
63
+
64
+ - ds-form-date-time-picker:: dimsum compliance [PUI-18983] (https://jira.elliemae.io/browse/PUI-18983) ([#8370](https://github.com/intcx/PLATFORM-UI.dimsum/issues/8370)) ([77d4dd4](https://github.com/intcx/PLATFORM-UI.dimsum/commit/77d4dd4bb8bac52ef900292b350c5cba983dcfb2))
65
+
66
+ ## 3.80.0-next.8 (2026-09-17)
67
+
68
+ ### Features
69
+
70
+ - ds-mobile:: storied removed from portal + fixed portal stories linking [PUI-18696](https://jira.elliemae.io/browse/PUI-18696) ([#8376](https://github.com/intcx/PLATFORM-UI.dimsum/issues/8376)) ([45d6c31](https://github.com/intcx/PLATFORM-UI.dimsum/commit/45d6c31bf187e4f9645a2b98f8aa2e478b246fbe))
71
+
72
+ ## 3.80.0-next.7 (2026-09-17)
73
+
74
+ ### Features
75
+
76
+ - ds-codemods:: added legacy deprecation command with ds-mobile +minor fixes to reports duplicates [PUI-18696](https://jira.elliemae.io/browse/PUI-18696) ([#8375](https://github.com/intcx/PLATFORM-UI.dimsum/issues/8375)) ([6c55c8f](https://github.com/intcx/PLATFORM-UI.dimsum/commit/6c55c8fc8fdb41492fafaac3ac86652532fd9b15))
77
+
78
+ ## 3.80.0-next.6 (2026-09-17)
79
+
80
+ ### Features
81
+
82
+ - ds-progress-indicator:: dimsum compliance [PUI-18856](https://jira.elliemae.io/browse/PUI-18856) ([#8353](https://github.com/intcx/PLATFORM-UI.dimsum/issues/8353)) ([ada7e89](https://github.com/intcx/PLATFORM-UI.dimsum/commit/ada7e89e2fa2ccf30d141d62c09ae888c5380622))
83
+
84
+ ## 3.80.0-next.5 (2026-09-16)
85
+
86
+ ### Bug Fixes
87
+
88
+ - ds-fast-list:: dimsum compliance remediation — test pillars, CT infra, code structure clean up, PropTypes slot props table gap [PUI-19124](https://jira.elliemae.io/browse/PUI-19124) ([#8369](https://github.com/intcx/PLATFORM-UI.dimsum/issues/8369)) ([cc79c47](https://github.com/intcx/PLATFORM-UI.dimsum/commit/cc79c4750f82bd44b5a3c33cb0abcd88410e5a6e))
89
+
90
+ ## 3.80.0-next.4 (2026-09-16)
91
+
92
+ ### Bug Fixes
93
+
94
+ - ds-virtual-list:: fix typescript-testing example teaching an invalid single-child form ([93c739d](https://github.com/intcx/PLATFORM-UI.dimsum/commit/93c739dfe993edca8238658d8d41c9cd1e7a9d5f))
95
+
96
+ ## 3.80.0-next.3 (2026-09-15)
97
+
98
+ ### Features
99
+
100
+ - dimsum:: add PillsV2 tooltip trigger semantics docs story [PUI-18616](https://jira.elliemae.io/browse/PUI-18616) ([#8364](https://github.com/intcx/PLATFORM-UI.dimsum/issues/8364)) ([6fff01f](https://github.com/intcx/PLATFORM-UI.dimsum/commit/6fff01fe63209719fe705c90f58c62914cf6c2e8))
101
+
6
102
  ## 3.80.0-next.2 (2026-09-14)
7
103
 
8
104
  ### Features
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable wdio/no-pause */
2
2
  import { Key } from 'webdriverio';
3
+ import { mouseOver, tabStops } from '../../helpers';
3
4
  import DSAppPickerCO from '../DSAppPickerCO';
4
5
 
5
6
  if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
@@ -12,7 +13,19 @@ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:o
12
13
  it('01: should display AppPicker item with aria-disabled focused', async () => {
13
14
  await browser.keys(Key.Tab);
14
15
  await browser.keys(Key.Enter);
15
- const snapshot = await browser.checkSnapshot(DSAppPickerCO.snapshotPath('appPicker-aria-disabled-focused'));
16
+ const ariaDisabledChip = await DSAppPickerCO.getChipByIndex(0);
17
+ await ariaDisabledChip.waitForDisplayed();
18
+ await expect(ariaDisabledChip).toBeFocused();
19
+ await expect(ariaDisabledChip).toHaveAttribute('aria-disabled', 'true');
20
+ const snapshot = await browser.percyCheckScreenshot();
21
+ await expect(snapshot).toEqual(0);
22
+ });
23
+ it('02: should expand natively disabled chip label on mouse hover', async () => {
24
+ const ariaDisabledChip = await DSAppPickerCO.getChipByIndex(0);
25
+ await ariaDisabledChip.waitForDisplayed();
26
+ await tabStops(2);
27
+ await mouseOver(ariaDisabledChip);
28
+ const snapshot = await browser.percyCheckScreenshot();
16
29
  await expect(snapshot).toEqual(0);
17
30
  });
18
31
  });
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable wdio/no-pause */
2
2
  import DSAppPickerCO from '../DSAppPickerCO';
3
- import { mouseOver } from '../../helpers';
3
+ import { mouseOver, tabStops } from '../../helpers';
4
4
 
5
5
  if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
6
6
  describe('PUI-7777 - AppPicker:: interaction states -visual', () => {
@@ -10,25 +10,30 @@ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:o
10
10
  await browser.maximizeWindow();
11
11
  });
12
12
  it('01: should have the appPicker closed', async () => {
13
- await browser.eyesOpen();
14
13
  await (await DSAppPickerCO.getOpenAppPicker()).waitForDisplayed();
15
- const snapshot = await browser.eyesCheckSnapshot(DSAppPickerCO.snapshotPath('appPicker-closed'));
14
+ const snapshot = await browser.percyCheckScreenshot();
16
15
  await expect(snapshot).toEqual(0);
17
16
  });
18
17
  it('02: should open appPicker', async () => {
19
- await browser.eyesOpen();
20
18
  const openAppPickerBtn = await DSAppPickerCO.getOpenAppPicker();
21
19
  await openAppPickerBtn.click();
22
- const snapshot = await browser.eyesCheckSnapshot(DSAppPickerCO.snapshotPath('appPicker-open'));
20
+ const snapshot = await browser.percyCheckScreenshot();
23
21
  await expect(snapshot).toEqual(0);
24
22
  });
25
23
  it('03: should interact appPicker chips', async () => {
26
- await browser.eyesOpen();
27
24
  const thirdChip = await DSAppPickerCO.getChipByIndex(2);
28
25
  await thirdChip.click();
29
26
  const sixthChipLabel = await DSAppPickerCO.getChipLabelByIndex(5);
30
27
  await mouseOver(sixthChipLabel);
31
- const snapshot = await browser.eyesCheckSnapshot(DSAppPickerCO.snapshotPath('appPicker-interacted'));
28
+ const snapshot = await browser.percyCheckScreenshot();
29
+ await expect(snapshot).toEqual(0);
30
+ });
31
+ it('04: should expand natively disabled chip label on mouse hover', async () => {
32
+ const ariaDisabledChip = await DSAppPickerCO.getChipByIndex(0);
33
+ await ariaDisabledChip.waitForDisplayed();
34
+ await tabStops(2);
35
+ await mouseOver(ariaDisabledChip);
36
+ const snapshot = await browser.percyCheckScreenshot();
32
37
  await expect(snapshot).toEqual(0);
33
38
  });
34
39
  });
@@ -0,0 +1,37 @@
1
+ import { PATH_E2E_FAST_LIST } from '../paths';
2
+ import { PageObject, Urlbuilder } from '../helpers';
3
+
4
+ export default class DSFastListCO extends PageObject {
5
+ static basicTest = new Urlbuilder(PATH_E2E_FAST_LIST, 'basic-test');
6
+
7
+ static scrollToIndexTest = new Urlbuilder(PATH_E2E_FAST_LIST, 'scroll-to-index-test');
8
+
9
+ // The container is the scroll element (overflow: auto); the wrapper list carries role="list"
10
+ static async getContainer() {
11
+ return $('[data-testid="ds-fastlist-container"]');
12
+ }
13
+
14
+ static async getWrapperList() {
15
+ return $('[data-testid="ds-fastlist-wrapper-list"]');
16
+ }
17
+
18
+ static async getItems() {
19
+ return $$('[data-testid="ds-fastlist-item"]');
20
+ }
21
+
22
+ // Only items inside the virtualization window exist in the DOM, so this resolves
23
+ // to nothing for indexes outside it — that absence is the assertion we rely on.
24
+ static async getItemByIndex(index) {
25
+ return $(`[data-testid="ds-fastlist-item"][data-index="${index}"]`);
26
+ }
27
+
28
+ // The story renders a single input and a single button, so the component-owned
29
+ // data-testids are unambiguous here.
30
+ static async getJumpInput() {
31
+ return $('[data-testid="ds-inputtext-input"]');
32
+ }
33
+
34
+ static async getJumpButton() {
35
+ return $('[data-testid="ds-button"]');
36
+ }
37
+ }
@@ -0,0 +1,28 @@
1
+ import DSFastListCO from '../DSFastListCO';
2
+ import { axeCoreCheck } from '../../helpers';
3
+
4
+ // Coverage for the ds-fast-list compliance remediation in PUI-19124.
5
+ // DOM-attribute/a11y assertions are identical across engines, so this runs Chrome only.
6
+ // The `|| browserName === 'Chrome'` fallback is mandatory: BrowserStack reports the
7
+ // capitalized name and a lowercase-only guard would register 0 tests (false green).
8
+ if (
9
+ (!browser.capabilities['ice:options'].isPhone &&
10
+ !browser.capabilities['ice:options'].isTablet &&
11
+ browser.capabilities.browserName === 'chrome') ||
12
+ browser.capabilities.browserName === 'Chrome'
13
+ ) {
14
+ describe('PUI-19194 - DSFastList:: virtualized list accessibility - Axe-Core', () => {
15
+ before(async () => {
16
+ const errorOnGo = await DSFastListCO.basicTest.go();
17
+ if (errorOnGo) throw errorOnGo;
18
+ });
19
+
20
+ it('01: should have no accessibility violations on the rendered list', async () => {
21
+ const wrapperList = await DSFastListCO.getWrapperList();
22
+ await wrapperList.waitForDisplayed();
23
+
24
+ const result = await axeCoreCheck();
25
+ expect(result.length).toBe(0);
26
+ });
27
+ });
28
+ }
@@ -0,0 +1,23 @@
1
+ import DSFastListCO from '../DSFastListCO';
2
+
3
+ // Coverage for the ds-fast-list compliance remediation in PUI-19124.
4
+ // Only the unscrolled state is snapshotted on purpose: Percy re-renders the serialized DOM, and an
5
+ // inner container's scroll offset is runtime state that is not part of that serialization, so a
6
+ // scrolled virtualized list is not reliably reproducible in a snapshot. The scrolled state is
7
+ // covered functionally instead — see e2e/ds-fast-list/scroll-to-index.
8
+ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
9
+ describe('PUI-19193 - DSFastList:: virtualized list window rendering - Visual', () => {
10
+ before(async () => {
11
+ const errorOnGo = await DSFastListCO.basicTest.go();
12
+ if (errorOnGo) throw errorOnGo;
13
+ });
14
+
15
+ it('01: should display the virtualized list with its first window of items', async () => {
16
+ const wrapperList = await DSFastListCO.getWrapperList();
17
+ await wrapperList.waitForDisplayed();
18
+
19
+ const snapshot = await browser.percyCheckScreenshot();
20
+ await expect(snapshot).toEqual(0);
21
+ });
22
+ });
23
+ }
@@ -0,0 +1,45 @@
1
+ import DSFastListCO from '../DSFastListCO';
2
+
3
+ // Coverage for the ds-fast-list compliance remediation in PUI-19124.
4
+ // The in-package Playwright CT already covers this in Chromium; this spec exists to run the same
5
+ // contract across the full browser matrix.
6
+ // The window size is not stable (items are measured after mount, so the overscan window grows),
7
+ // which is why the assertions are "bounded window + index recycled", never an exact item count.
8
+ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
9
+ describe('PUI-19195 - DSFastList:: scroll to index via actionRef - Func', () => {
10
+ before(async () => {
11
+ const errorOnGo = await DSFastListCO.scrollToIndexTest.go();
12
+ if (errorOnGo) throw errorOnGo;
13
+ });
14
+
15
+ it('01: should render only a window of the 200 items, leaving far items out of the DOM', async () => {
16
+ const firstItem = await DSFastListCO.getItemByIndex(0);
17
+ await expect(firstItem).toBeExisting();
18
+
19
+ const farItem = await DSFastListCO.getItemByIndex(150);
20
+ await expect(farItem).not.toBeExisting();
21
+
22
+ const items = await DSFastListCO.getItems();
23
+ await expect(items.length).toBeLessThan(60);
24
+ });
25
+
26
+ it('02: should mount the requested item and recycle the first one after jumping', async () => {
27
+ const jumpInput = await DSFastListCO.getJumpInput();
28
+ await jumpInput.setValue('150');
29
+ const jumpButton = await DSFastListCO.getJumpButton();
30
+ await jumpButton.click();
31
+
32
+ const farItem = await DSFastListCO.getItemByIndex(150);
33
+ await farItem.waitForExist();
34
+ await expect(farItem).toBeDisplayed();
35
+ await expect(farItem).toHaveText('Test 150');
36
+
37
+ // the window moved instead of growing: index 0 is no longer in the DOM
38
+ const firstItem = await DSFastListCO.getItemByIndex(0);
39
+ await expect(firstItem).not.toBeExisting();
40
+
41
+ const items = await DSFastListCO.getItems();
42
+ await expect(items.length).toBeLessThan(60);
43
+ });
44
+ });
45
+ }
@@ -1,7 +1,21 @@
1
- import { PATH_E2E_PILLS_V2 } from '../paths';
1
+ import { PATH_E2E_PILLS_V2, PATH_E2E_PILLS_V2_PITFALLS } from '../paths';
2
2
  import { PageObject, Urlbuilder, getElementByIndex } from '../helpers';
3
3
 
4
4
  export default class DSPillsV2CO extends PageObject {
5
+ /**
6
+ * Every id in the InputWithFormItemBlockTest story is derived by DSFormLayoutBlockItem from the
7
+ * `inputID` it is given. Derived once here so neither the selectors below nor the spec rebuild
8
+ * the `_feedback_message` / `_error_message` suffixes by hand.
9
+ */
10
+ static IDS = {
11
+ input: 'normal',
12
+ feedback: 'normal_feedback_message',
13
+ error: 'normal_error_message',
14
+ };
15
+
16
+ /** What the input's aria-describedby must equal, in the order the story supplies the messages. */
17
+ static DESCRIBED_BY = `${this.IDS.feedback} ${this.IDS.error}`;
18
+
5
19
  // Desktop
6
20
  static removableURL = new Urlbuilder(PATH_E2E_PILLS_V2, 'removable-pill-test');
7
21
 
@@ -27,6 +41,15 @@ export default class DSPillsV2CO extends PageObject {
27
41
 
28
42
  static multiSelectMB = new Urlbuilder(PATH_E2E_PILLS_V2, 'multi-select-menu-button-test');
29
43
 
44
+ // Pitfalls
45
+ static inputWithFormItemBlockURL = new Urlbuilder(PATH_E2E_PILLS_V2_PITFALLS, 'input-with-form-item-block-test');
46
+
47
+ // Distinct from `inputURL` above: same story name, different path. Both are hand-copies of the
48
+ // Input Pill pitfall story's 12 pills; this one is the Pitfalls-scoped twin used by the attribute
49
+ // spec, `inputURL` is the older copy carrying the axe (PUI-11496) and Percy (PUI-8356) baselines.
50
+ // The E2E copy renders PendingReviewDisclaimer; the canonical component pitfall story additionally renders InputPillLabelRequirementDisclaimer.
51
+ static inputPillPitfallURL = new Urlbuilder(PATH_E2E_PILLS_V2_PITFALLS, 'input-pill-test');
52
+
30
53
  static getUrl(component = 'basic') {
31
54
  return PageObject.getUrl(PATH_E2E_PILLS_V2, component);
32
55
  }
@@ -93,6 +116,35 @@ export default class DSPillsV2CO extends PageObject {
93
116
  return $('[data-testid="dropdown-menu-listbox"]');
94
117
  }
95
118
 
119
+ // --- InputWithFormItemBlockTest: label / error association selectors ---
120
+
121
+ /** The pill's inner <input>, reached by the id the story overrides onto it. */
122
+ static async getAssociatedInput() {
123
+ return $(`#${this.IDS.input}`);
124
+ }
125
+
126
+ /** `$$` on purpose — the count is what proves the override did not duplicate the id. */
127
+ static async getNodesWithInputId() {
128
+ return $$(`[id="${this.IDS.input}"]`);
129
+ }
130
+
131
+ /** The DSFormLayoutBlockItem label, which must point at the input via `for`. */
132
+ static async getAssociatedInputLabel() {
133
+ return $(`label[for="${this.IDS.input}"]`);
134
+ }
135
+
136
+ static async getFeedbackMessage() {
137
+ return $(`#${this.IDS.feedback}`);
138
+ }
139
+
140
+ static async getErrorMessage() {
141
+ return $(`#${this.IDS.error}`);
142
+ }
143
+
144
+ static async getClearIcon() {
145
+ return $('[data-testid="ds-pill-clear-icon"]');
146
+ }
147
+
96
148
  // Snapshots
97
149
  static snapshotPath(example = 'basic') {
98
150
  return PageObject.getSnapshotPathBuilder('Pills', example);
@@ -0,0 +1,26 @@
1
+ import DSPillsV2CO from '../DSPillsV2CO';
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
+ describe('PUI-19148 - DSPillsV2:: input pill attribute contract - Func', () => {
10
+ before('loading page', async () => {
11
+ const errorOnGo = await DSPillsV2CO.inputPillPitfallURL.go();
12
+ if (errorOnGo) throw errorOnGo;
13
+ });
14
+
15
+ it('01: should render the input with the attributes', async () => {
16
+ const input = await DSPillsV2CO.getInputByIndex(0);
17
+ await input.waitForDisplayed();
18
+ await expect(await input.getTagName()).toBe('input');
19
+ await expect(input).toHaveAttribute('data-testid', 'ds-pill-input');
20
+ const generatedId = await input.getAttribute('id');
21
+ await expect(generatedId).toMatch(/^ds-pill-/);
22
+ await expect(input).not.toHaveAttribute('aria-describedby');
23
+ await expect(input).toHaveAttribute('aria-invalid', 'false');
24
+ });
25
+ });
26
+ }
@@ -0,0 +1,38 @@
1
+ import DSPillsV2CO from '../DSPillsV2CO';
2
+ import { axeCoreCheck, type } from '../../helpers';
3
+
4
+ // Accessibility scan for the fix introduced in PUI-18617 ([PillsV2] Pitfalls enhancements, item 2).
5
+ //
6
+ // Note on what this does and does not prove: axe has no rule that requires an input to be described by
7
+ // an error message, so a clean scan here is a regression guard against the association *breaking the
8
+ // markup* (orphaned aria-describedby ids, duplicate ids, an unlabelled input) — not evidence that the
9
+ // label and error are announced. The announcement itself is covered by the functional spec and by
10
+ // manual screen reader verification on the ticket.
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-19150 - DSPillsV2:: input pill label and error association - Axe-Core', () => {
18
+ before('loading page', async () => {
19
+ const errorOnGo = await DSPillsV2CO.inputWithFormItemBlockURL.go();
20
+ if (errorOnGo) throw errorOnGo;
21
+ });
22
+
23
+ it('01: should have no accessibility violations, empty and filled', async () => {
24
+ const input = await DSPillsV2CO.getAssociatedInput();
25
+ await input.waitForDisplayed();
26
+ const emptyResult = await axeCoreCheck();
27
+ expect(emptyResult.length).toBe(0);
28
+ // Filling the input mounts the clear button, which adds an extra focusable control inside the
29
+ // associated form item — worth scanning in that state too.
30
+ await input.click();
31
+ await type('abcd');
32
+ const clearIcon = await DSPillsV2CO.getClearIcon();
33
+ await clearIcon.waitForDisplayed();
34
+ const filledResult = await axeCoreCheck();
35
+ expect(filledResult.length).toBe(0);
36
+ });
37
+ });
38
+ }
@@ -0,0 +1,72 @@
1
+ import DSPillsV2CO from '../DSPillsV2CO';
2
+ import { type } from '../../helpers';
3
+
4
+ // Tests for the fix introduced in PUI-18617 ([PillsV2] Pitfalls enhancements, item 2): the input pill
5
+ // inside a DSFormLayoutBlockItem announced neither its label nor its error message. The fix exposed
6
+ // `dsPillInput` as a real slot on the default (non-inputRender) input, so the association is now made
7
+ // by passing id / aria-describedby through the nested `dsInputtextInput` slot.
8
+ //
9
+ // Assertions are pure DOM attributes, so this is scoped to Chrome — see the skill's
10
+ // "DOM-Attribute Tests Run Chrome-Only" rule. The `|| 'Chrome'` fallback is mandatory: BrowserStack
11
+ // reports the capitalized name and a lowercase-only guard registers 0 tests (false green).
12
+ if (
13
+ (!browser.capabilities['ice:options'].isPhone &&
14
+ !browser.capabilities['ice:options'].isTablet &&
15
+ browser.capabilities.browserName === 'chrome') ||
16
+ browser.capabilities.browserName === 'Chrome'
17
+ ) {
18
+ describe('PUI-19149 - DSPillsV2:: input pill label and error association - Func', () => {
19
+ before('loading page', async () => {
20
+ const errorOnGo = await DSPillsV2CO.inputWithFormItemBlockURL.go();
21
+ if (errorOnGo) throw errorOnGo;
22
+ });
23
+
24
+ it('01: should associate the input with its label and its feedback/error messages', async () => {
25
+ const input = await DSPillsV2CO.getAssociatedInput();
26
+ await input.waitForDisplayed();
27
+
28
+ // The overridden id must land on the pill's real <input>, not on a wrapper. Checking the tag and
29
+ // the pill's own data-testid on the same element is what distinguishes the two.
30
+ await expect(await input.getTagName()).toBe('input');
31
+ await expect(input).toHaveAttribute('data-testid', 'ds-pill-input');
32
+
33
+ // hasError on the pill is forwarded to DSInputText as aria-invalid.
34
+ await expect(input).toHaveAttribute('aria-invalid', 'true');
35
+
36
+ // Both message ids, in the order the story supplies them.
37
+ await expect(input).toHaveAttribute('aria-describedby', DSPillsV2CO.DESCRIBED_BY);
38
+
39
+ // aria-describedby is only meaningful if the referenced nodes exist.
40
+ const feedbackMessage = await DSPillsV2CO.getFeedbackMessage();
41
+ await expect(feedbackMessage).toBeExisting();
42
+ const errorMessage = await DSPillsV2CO.getErrorMessage();
43
+ await expect(errorMessage).toBeExisting();
44
+
45
+ // The label side of the association: DSFormLayoutBlockItem renders label[for] from inputID.
46
+ const label = await DSPillsV2CO.getAssociatedInputLabel();
47
+ await expect(label).toBeExisting();
48
+ await expect(await label.getText()).toContain('Item');
49
+
50
+ // Duplicate ids would make the label and aria-describedby resolve to the wrong node.
51
+ const elementsWithId = await DSPillsV2CO.getNodesWithInputId();
52
+ await expect(elementsWithId.length).toBe(1);
53
+ });
54
+
55
+ it('02: should keep the association intact once the clear button mounts', async () => {
56
+ const input = await DSPillsV2CO.getAssociatedInput();
57
+ await input.click();
58
+ await type('abcd');
59
+
60
+ // The clear button only renders once the input has a value, and it must not reuse the input's id.
61
+ const clearIcon = await DSPillsV2CO.getClearIcon();
62
+ await clearIcon.waitForDisplayed();
63
+ await expect(clearIcon).not.toHaveAttribute('id', DSPillsV2CO.IDS.input);
64
+
65
+ await expect(input).toHaveAttribute('aria-describedby', DSPillsV2CO.DESCRIBED_BY);
66
+ await expect(input).toHaveAttribute('aria-invalid', 'true');
67
+
68
+ const elementsWithId = await DSPillsV2CO.getNodesWithInputId();
69
+ await expect(elementsWithId.length).toBe(1);
70
+ });
71
+ });
72
+ }
@@ -1,4 +1,3 @@
1
- /* eslint-disable wdio/no-pause */
2
1
  import DSProgressIndicatorCO from './DSProgressIndicatorCO';
3
2
  import { axeCoreCheck } from '../helpers';
4
3
 
@@ -8,24 +7,28 @@ if (
8
7
  browser.capabilities.browserName === 'chrome') ||
9
8
  browser.capabilities.browserName === 'Chrome'
10
9
  ) {
11
- describe('PUI-17521: Progress Indicator:: Basic - Axe Core', () => {
10
+ describe('PUI-17521 - DSProgressIndicator:: Basic - Axe-Core', () => {
12
11
  before('loading page', async () => {
13
12
  const errorOnGo = await DSProgressIndicatorCO.basicURL.go();
14
13
  if (errorOnGo) throw errorOnGo;
15
14
  });
16
15
  it('01: should display basic progress indicator and pass axe-core', async () => {
17
- await (await DSProgressIndicatorCO.getUploadLabel()).waitForDisplayed();
18
- await browser.pause(500);
16
+ await (await DSProgressIndicatorCO.getTitle()).waitForDisplayed();
17
+
19
18
  const result = await axeCoreCheck();
20
19
  expect(result.length).toBe(0);
21
20
  });
22
21
  });
23
- describe('PUI-17524: Progress Indicator:: Others Test - Axe Core', () => {
22
+
23
+ describe('PUI-17524 - DSProgressIndicator:: Others Test - Axe-Core', () => {
24
24
  before('loading page', async () => {
25
25
  const errorOnGo = await DSProgressIndicatorCO.othersURL.go();
26
26
  if (errorOnGo) throw errorOnGo;
27
27
  });
28
28
  it('01: should display progress indicator and pass axe-core', async () => {
29
+ // Replaces a blind browser.pause(500): the story animates, so wait on the real end state.
30
+ await DSProgressIndicatorCO.waitForAnimatedCountersToSettle();
31
+
29
32
  const result = await axeCoreCheck();
30
33
  expect(result.length).toBe(0);
31
34
  });
@@ -6,14 +6,28 @@ if (
6
6
  browser.capabilities.browserName === 'chrome') ||
7
7
  browser.capabilities.browserName === 'Chrome'
8
8
  ) {
9
- describe('PUI-17522 - Progress Indicator:: Basic - Func', () => {
9
+ describe('PUI-17522 - DSProgressIndicator:: Basic - Func', () => {
10
10
  before('loading page', async () => {
11
11
  const errorOnGo = await DSProgressIndicatorCO.basicURL.go();
12
12
  if (errorOnGo) throw errorOnGo;
13
13
  });
14
- it('01: should show basic progress indicator', async () => {
15
- const progressIndicator = await DSProgressIndicatorCO.getUploadLabel();
16
- await expect(progressIndicator).toBeDisplayed();
14
+
15
+ // The naming, aria-valuetext and invalid-range contracts live in the aria-contract spec; this
16
+ // one stays on the Basic story's own value contract.
17
+ it('01: should show basic progress indicator with a valid progressbar value range', async () => {
18
+ const title = await DSProgressIndicatorCO.getTitle();
19
+ await expect(title).toBeDisplayed();
20
+ await expect(title).toHaveText('upload');
21
+
22
+ const root = await DSProgressIndicatorCO.getRoot();
23
+ await expect(root).toHaveAttribute('aria-disabled', 'false');
24
+
25
+ const progress = await DSProgressIndicatorCO.getProgress();
26
+ await expect(progress).toHaveAttribute('role', 'progressbar');
27
+ await expect(progress).toHaveAttribute('aria-valuenow', '50');
28
+ await expect(progress).toHaveAttribute('aria-valuemin', '0');
29
+ await expect(progress).toHaveAttribute('aria-valuemax', '100');
30
+ await expect(await progress.getAttribute('style')).toContain('width: 50%');
17
31
  });
18
32
  });
19
33
  }
@@ -1,24 +1,32 @@
1
1
  import DSProgressIndicatorCO from './DSProgressIndicatorCO';
2
2
 
3
- if (!browser.capabilities['ice:options'].isPhone) {
4
- describe('PUI-17520 - Progress Indicator:: Basic - Visual', () => {
3
+ // Migrated off the pre-Percy browser.checkSnapshot API as part of the PUI-18856 compliance work,
4
+ // which rewrote the class system these baselines were taken against.
5
+ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
6
+ describe('PUI-17520 - DSProgressIndicator:: Basic - Visual', () => {
5
7
  before('loading page', async () => {
6
8
  const errorOnGo = await DSProgressIndicatorCO.basicURL.go();
7
9
  if (errorOnGo) throw errorOnGo;
8
10
  });
9
11
  it('01: should display basic progress indicator', async () => {
10
- await (await DSProgressIndicatorCO.getUploadLabel()).waitForDisplayed();
11
- const snapshot = await browser.checkSnapshot(DSProgressIndicatorCO.snapshotPath('progressindicator-basic'));
12
+ await (await DSProgressIndicatorCO.getTitle()).waitForDisplayed();
13
+
14
+ const snapshot = await browser.percyCheckScreenshot();
12
15
  await expect(snapshot).toEqual(0);
13
16
  });
14
17
  });
15
- describe('PUI-17523 - Progress Indicator:: Others Test - Visual', () => {
18
+
19
+ describe('PUI-17523 - DSProgressIndicator:: Others Test - Visual', () => {
16
20
  before('loading page', async () => {
17
21
  const errorOnGo = await DSProgressIndicatorCO.othersURL.go();
18
22
  if (errorOnGo) throw errorOnGo;
19
23
  });
20
24
  it('01: should display progress indicator', async () => {
21
- const snapshot = await browser.checkSnapshot(DSProgressIndicatorCO.snapshotPath('progressindicator-others'));
25
+ // Two of the four indicators are driven by setInterval and only stop once their counters
26
+ // reach the maximum. Snapshotting before that lands produces a different image every run.
27
+ await DSProgressIndicatorCO.waitForAnimatedCountersToSettle();
28
+
29
+ const snapshot = await browser.percyCheckScreenshot();
22
30
  await expect(snapshot).toEqual(0);
23
31
  });
24
32
  });