dimsum-e2e-tests 3.80.0-next.36 → 3.80.0-next.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/ds-banner/DSBanner.text-resize.visual.spec.js +2 -0
- package/ds-banner/DSBannerCO.js +187 -1
- package/ds-banner/aria-and-role/DSBanner.aria-and-role.func.spec.js +113 -2
- package/ds-banner/ids/DSBanner.ids.func.spec.js +66 -0
- package/ds-banner/live-region-lang-dir/DSBanner.live-region-lang-dir.func.spec.js +54 -0
- package/ds-banner/slide-animation/DSBanner.slide-animation.func.spec.js +105 -0
- package/ds-banner/slots/DSBanner.slots.axe-core.func.spec.js +24 -0
- package/ds-banner/slots/DSBanner.slots.func.spec.js +7 -0
- package/ds-banner/slots/DSBanner.slots.visual.spec.js +2 -0
- package/ds-banner/title-element/DSBanner.title-element.func.spec.js +29 -0
- package/ds-ribbon/DSRibbonCO.js +21 -0
- package/ds-ribbon/keyboard-accessible-row/DSRibbon.keyboard-accessible-row.visual.spec.js +40 -0
- package/ds-ribbon/wrap-columns/DSRibbon.wrap-columns.visual.spec.js +18 -0
- package/ds-shuttle-v2/load-more/DSShuttleV2.load-more.keyboard.func.spec.js +46 -17
- package/package.json +149 -149
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.80.0-next.39](/github.com/intcx/PLATFORM-UI/compare/v3.80.0-next.38...v3.80.0-next.39) (2026-10-13)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package dimsum-e2e-tests
|
|
9
|
+
|
|
10
|
+
## [3.80.0-next.38](/github.com/intcx/PLATFORM-UI/compare/v3.80.0-next.36...v3.80.0-next.38) (2026-10-09)
|
|
11
|
+
|
|
12
|
+
**Note:** Version bump only for package dimsum-e2e-tests
|
|
13
|
+
|
|
14
|
+
## [3.80.0-next.37](/github.com/intcx/PLATFORM-UI/compare/v3.80.0-next.36...v3.80.0-next.37) (2026-10-09)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package dimsum-e2e-tests
|
|
17
|
+
|
|
6
18
|
## [3.80.0-next.36](/github.com/intcx/PLATFORM-UI/compare/v3.80.0-next.35...v3.80.0-next.36) (2026-10-08)
|
|
7
19
|
|
|
8
20
|
**Note:** Version bump only for package dimsum-e2e-tests
|
|
@@ -11,6 +11,8 @@ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:o
|
|
|
11
11
|
it('01: should display text resize in different layouts properly', async () => {
|
|
12
12
|
const banner = await DSBannerCO.getBannerByIndex();
|
|
13
13
|
await banner.waitForDisplayed();
|
|
14
|
+
// the banners are open on load and slide down for 500 ms
|
|
15
|
+
await DSBannerCO.waitForSlideToEnd();
|
|
14
16
|
const snapshot = await browser.percyCheckScreenshot();
|
|
15
17
|
await expect(snapshot).toEqual(0);
|
|
16
18
|
});
|
package/ds-banner/DSBannerCO.js
CHANGED
|
@@ -2,6 +2,12 @@ import { PATH_E2E_BANNER } from '../paths';
|
|
|
2
2
|
import { PageObject, Urlbuilder } from '../helpers';
|
|
3
3
|
|
|
4
4
|
export default class DSBannerCO extends PageObject {
|
|
5
|
+
// label/body rendered by the AriaLive* and RoleAlert E2E stories
|
|
6
|
+
static ANNOUNCEMENT_TITLE = 'Information: Read-only mode';
|
|
7
|
+
|
|
8
|
+
static ANNOUNCEMENT_BODY =
|
|
9
|
+
'You are viewing this page in read-only mode. Editing is currently disabled for your role.';
|
|
10
|
+
|
|
5
11
|
static basicURL = new Urlbuilder(PATH_E2E_BANNER, 'basic-test');
|
|
6
12
|
|
|
7
13
|
static infoURL = new Urlbuilder(PATH_E2E_BANNER, 'info-test');
|
|
@@ -36,6 +42,32 @@ export default class DSBannerCO extends PageObject {
|
|
|
36
42
|
|
|
37
43
|
static roleRegionTest = new Urlbuilder(PATH_E2E_BANNER, 'role-region-test');
|
|
38
44
|
|
|
45
|
+
static roleRegionNoAnnouncementTest = new Urlbuilder(PATH_E2E_BANNER, 'role-region-no-announcement-test');
|
|
46
|
+
|
|
47
|
+
static regionAccessibleNameTest = new Urlbuilder(PATH_E2E_BANNER, 'region-accessible-name-test');
|
|
48
|
+
|
|
49
|
+
static bannerIdsTest = new Urlbuilder(PATH_E2E_BANNER, 'banner-ids-test');
|
|
50
|
+
|
|
51
|
+
static liveRegionLangDirTest = new Urlbuilder(PATH_E2E_BANNER, 'live-region-lang-dir-test');
|
|
52
|
+
|
|
53
|
+
// each banner in RegionAccessibleNameTest is wrapped in a div with a per-case data-testid
|
|
54
|
+
static async getRegionByCase(caseTestId) {
|
|
55
|
+
return $(`[data-testid="${caseTestId}"] [role="region"]`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
static async getRegionNameAttributes(caseTestId) {
|
|
59
|
+
const region = await this.getRegionByCase(caseTestId);
|
|
60
|
+
return {
|
|
61
|
+
ariaLabel: await region.getAttribute('aria-label'),
|
|
62
|
+
ariaLabelledby: await region.getAttribute('aria-labelledby'),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// located by its parent slot, not by tag (the title tag is changing, PUI-19231)
|
|
67
|
+
static async getRegionTitleByCase(caseTestId) {
|
|
68
|
+
return $(`[data-testid="${caseTestId}"] [data-dimsum-parent-slot="dsBannerTitle"]`);
|
|
69
|
+
}
|
|
70
|
+
|
|
39
71
|
static async getButton() {
|
|
40
72
|
return $('[data-testid="ds-button"]');
|
|
41
73
|
}
|
|
@@ -43,6 +75,8 @@ export default class DSBannerCO extends PageObject {
|
|
|
43
75
|
static async openBanner() {
|
|
44
76
|
const button = await this.getButton();
|
|
45
77
|
await button.click();
|
|
78
|
+
// the banner slides down for 500 ms, the callers (visual snapshots included) expect it settled
|
|
79
|
+
await this.waitForSlideToEnd();
|
|
46
80
|
}
|
|
47
81
|
|
|
48
82
|
static async closeBanner() {
|
|
@@ -50,6 +84,73 @@ export default class DSBannerCO extends PageObject {
|
|
|
50
84
|
await closeBtn.click();
|
|
51
85
|
}
|
|
52
86
|
|
|
87
|
+
static async getPushedContent() {
|
|
88
|
+
return $('[data-testid="banner-pushed-content"]');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static async getPushedContentTop() {
|
|
92
|
+
return browser.execute(
|
|
93
|
+
() => document.querySelector('[data-testid="banner-pushed-content"]').getBoundingClientRect().top,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// resolves once no banner has a running animation/transition (the slide down) or is in the DOM
|
|
98
|
+
static async waitForSlideToEnd() {
|
|
99
|
+
await browser.waitUntil(
|
|
100
|
+
async () =>
|
|
101
|
+
browser.execute(() =>
|
|
102
|
+
Array.from(document.querySelectorAll('[data-testid="ds-banner-container"]')).every(
|
|
103
|
+
(container) => container.getAnimations().length === 0,
|
|
104
|
+
),
|
|
105
|
+
),
|
|
106
|
+
{ timeoutMsg: 'the banner slide did not end' },
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Samples, on every animation frame and from the page (so the webdriver latency does not matter), the height of the
|
|
111
|
+
// banner container and the top of the content pushed by it. The click is triggered from the page right after the
|
|
112
|
+
// first sample, so the very first frames after it are recorded. action: 'open' | 'close'.
|
|
113
|
+
static async sampleSlide(action, durationMs = 1200) {
|
|
114
|
+
await browser.execute(
|
|
115
|
+
(actionToRun, duration) => {
|
|
116
|
+
const samples = [];
|
|
117
|
+
window.bannerSlideSampler = { samples, done: false };
|
|
118
|
+
const startedAt = performance.now();
|
|
119
|
+
const sample = () => {
|
|
120
|
+
const container = document.querySelector('[data-testid="ds-banner-container"]');
|
|
121
|
+
const pushed = document.querySelector('[data-testid="banner-pushed-content"]');
|
|
122
|
+
samples.push({
|
|
123
|
+
t: Math.round(performance.now() - startedAt),
|
|
124
|
+
height: container ? container.getBoundingClientRect().height : null,
|
|
125
|
+
pushedTop: pushed.getBoundingClientRect().top,
|
|
126
|
+
inert: container ? container.hasAttribute('inert') : null,
|
|
127
|
+
ariaHidden: container ? container.getAttribute('aria-hidden') : null,
|
|
128
|
+
focusInside: container ? container.contains(document.activeElement) : false,
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
sample();
|
|
132
|
+
if (actionToRun === 'open') document.querySelector('[data-testid="ds-button"]').click();
|
|
133
|
+
else {
|
|
134
|
+
const closeButton = document.querySelector('[data-testid="ds-banner-close-button"]');
|
|
135
|
+
closeButton.focus();
|
|
136
|
+
closeButton.click();
|
|
137
|
+
}
|
|
138
|
+
const tick = () => {
|
|
139
|
+
sample();
|
|
140
|
+
if (performance.now() - startedAt < duration) requestAnimationFrame(tick);
|
|
141
|
+
else window.bannerSlideSampler.done = true;
|
|
142
|
+
};
|
|
143
|
+
requestAnimationFrame(tick);
|
|
144
|
+
},
|
|
145
|
+
action,
|
|
146
|
+
durationMs,
|
|
147
|
+
);
|
|
148
|
+
await browser.waitUntil(async () => browser.execute(() => window.bannerSlideSampler.done), {
|
|
149
|
+
timeoutMsg: 'the slide sampler did not finish',
|
|
150
|
+
});
|
|
151
|
+
return browser.execute(() => window.bannerSlideSampler.samples);
|
|
152
|
+
}
|
|
153
|
+
|
|
53
154
|
static async getCloseButton() {
|
|
54
155
|
return $('[data-testid="ds-banner-close-button"]');
|
|
55
156
|
}
|
|
@@ -75,7 +176,7 @@ export default class DSBannerCO extends PageObject {
|
|
|
75
176
|
}
|
|
76
177
|
|
|
77
178
|
static async getActionLinkSlotByIndex(index = 0) {
|
|
78
|
-
return $$('[data-dimsum-slot="dsBannerActionLink"]')[index];
|
|
179
|
+
return $$('[data-dimsum-parent-slot="dsBannerActionLink"]')[index];
|
|
79
180
|
}
|
|
80
181
|
|
|
81
182
|
static async getTitleSlotByIndex(index = 0) {
|
|
@@ -90,6 +191,36 @@ export default class DSBannerCO extends PageObject {
|
|
|
90
191
|
return $$('[data-dimsum-slot="dsButtonRoot"]')[index];
|
|
91
192
|
}
|
|
92
193
|
|
|
194
|
+
static async getCloseButtonSlotByIndex(index = 0) {
|
|
195
|
+
return $$('[data-dimsum-parent-slot="dsBannerCloseButton"]')[index];
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
static async getLiveRegionPortal() {
|
|
199
|
+
return $('[data-testid="ds-banner-live-region-portal"]');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// the live region is visually hidden, so read textContent instead of the visible text
|
|
203
|
+
static async getLiveRegionText() {
|
|
204
|
+
const liveRegion = await this.getLiveRegionPortal();
|
|
205
|
+
return ((await liveRegion.getProperty('textContent')) || '').trim();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
static async waitForLiveRegionText(expected) {
|
|
209
|
+
await browser.waitUntil(async () => (await this.getLiveRegionText()).includes(expected), {
|
|
210
|
+
timeoutMsg: `live region never contained "${expected}"`,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
static async waitForLiveRegionCleared() {
|
|
215
|
+
await browser.waitUntil(async () => (await this.getLiveRegionText()) === '', {
|
|
216
|
+
timeoutMsg: 'live region was not cleared after closing the banner',
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
static async getActiveElementTestId() {
|
|
221
|
+
return browser.execute(() => document.activeElement?.getAttribute('data-testid') ?? null);
|
|
222
|
+
}
|
|
223
|
+
|
|
93
224
|
static async getContainerSlotByIndex(index = 0) {
|
|
94
225
|
return $$('[data-dimsum-slot="dsBannerContainer"]')[index];
|
|
95
226
|
}
|
|
@@ -113,4 +244,59 @@ export default class DSBannerCO extends PageObject {
|
|
|
113
244
|
static async getBannerLiveRegionPortalSlotByIndex(index = 0) {
|
|
114
245
|
return $$('[data-dimsum-slot="dsBannerLiveRegionPortal"]')[index];
|
|
115
246
|
}
|
|
247
|
+
|
|
248
|
+
static async getTitle() {
|
|
249
|
+
return $('[data-testid="ds-banner-title"]');
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// headings (native or by role) rendered inside the banners, the page outside them is not the banner's business
|
|
253
|
+
static async getHeadingsCountInBanners() {
|
|
254
|
+
return browser.execute(
|
|
255
|
+
() =>
|
|
256
|
+
document.querySelectorAll('[data-testid="ds-banner-container"] :is(h1, h2, h3, h4, h5, h6, [role="heading"])')
|
|
257
|
+
.length,
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
static async getLiveRegionPortalByIndex(index = 0) {
|
|
262
|
+
return $$('[data-testid="ds-banner-live-region-portal"]')[index];
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// per banner (in page order): the ids of its parts and whether <base>-live-region is its live region portal
|
|
266
|
+
static async getBannerIds() {
|
|
267
|
+
return browser.execute(() =>
|
|
268
|
+
Array.from(document.querySelectorAll('[data-testid="ds-banner"]')).map((banner) => ({
|
|
269
|
+
base: banner.id,
|
|
270
|
+
title: banner.querySelector('[data-testid="ds-banner-title"]')?.id ?? null,
|
|
271
|
+
body: banner.querySelector('[data-dimsum-parent-slot="dsBannerSubtitle"]')?.id ?? null,
|
|
272
|
+
liveRegionTestId: document.getElementById(`${banner.id}-live-region`)?.getAttribute('data-testid') ?? null,
|
|
273
|
+
})),
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// every id rendered by the banners (parts and live region portals), so duplicates among them can be detected
|
|
278
|
+
static async getAllBannerIds() {
|
|
279
|
+
return browser.execute(() => {
|
|
280
|
+
const selectors = [
|
|
281
|
+
'[data-testid="ds-banner-container"][id]',
|
|
282
|
+
'[data-testid="ds-banner-container"] [id]',
|
|
283
|
+
'[data-testid="ds-banner-live-region-portal"]',
|
|
284
|
+
];
|
|
285
|
+
return Array.from(document.querySelectorAll(selectors.join(', '))).map((element) => element.id);
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// what the action link of the banner at index points to with aria-describedby
|
|
290
|
+
static async getActionLinkDescription(index = 0) {
|
|
291
|
+
return browser.execute((position) => {
|
|
292
|
+
const link = document.querySelectorAll('[data-testid="ds-banner-action-link"]')[position];
|
|
293
|
+
const describedBy = link.getAttribute('aria-describedby');
|
|
294
|
+
const target = document.getElementById(describedBy);
|
|
295
|
+
return {
|
|
296
|
+
describedBy,
|
|
297
|
+
isInsideOwnBanner: Boolean(target && link.closest('[data-testid="ds-banner"]').contains(target)),
|
|
298
|
+
text: target ? target.textContent : null,
|
|
299
|
+
};
|
|
300
|
+
}, index);
|
|
301
|
+
}
|
|
116
302
|
}
|
|
@@ -6,31 +6,76 @@ if (
|
|
|
6
6
|
browser.capabilities.browserName === 'chrome') ||
|
|
7
7
|
browser.capabilities.browserName === 'Chrome'
|
|
8
8
|
) {
|
|
9
|
+
// Announcement behaviour also covers PUI-17840 (banner announcement improvement)
|
|
9
10
|
describe('PUI-17537 - Banner - Aria Assertive -Func', () => {
|
|
10
11
|
before('loading page', async () => {
|
|
11
12
|
const errorOnGo = await DSBannerCO.ariaLiveAssertiveTest.go();
|
|
12
13
|
if (errorOnGo) throw errorOnGo;
|
|
13
14
|
});
|
|
14
|
-
it('01: should
|
|
15
|
+
it('01: should render an empty assertive live region before the banner opens', async () => {
|
|
16
|
+
const liveRegion = await DSBannerCO.getLiveRegionPortal();
|
|
17
|
+
await expect(liveRegion).toExist();
|
|
18
|
+
await expect(liveRegion).toHaveAttribute('aria-live', 'assertive');
|
|
19
|
+
await expect(liveRegion).toHaveAttribute('aria-atomic', 'true');
|
|
20
|
+
await expect(await DSBannerCO.getLiveRegionText()).toBe('');
|
|
21
|
+
});
|
|
22
|
+
it('02: should have aria-live="assertive" attribute on banner after trigger', async () => {
|
|
15
23
|
const triggerButton = await DSBannerCO.getButton();
|
|
16
24
|
await triggerButton.click();
|
|
17
25
|
const banner = await DSBannerCO.getBannerLiveRegionPortalSlotByIndex();
|
|
18
26
|
await banner.waitForDisplayed();
|
|
19
27
|
await expect(banner).toHaveAttribute('aria-live', 'assertive');
|
|
20
28
|
});
|
|
29
|
+
it('03: should announce title and body together without moving focus', async () => {
|
|
30
|
+
const liveRegion = await DSBannerCO.getLiveRegionPortal();
|
|
31
|
+
await DSBannerCO.waitForLiveRegionText(DSBannerCO.ANNOUNCEMENT_TITLE);
|
|
32
|
+
await expect(await DSBannerCO.getLiveRegionText()).toContain(DSBannerCO.ANNOUNCEMENT_BODY);
|
|
33
|
+
await expect(await liveRegion.$$('button, a').length).toBe(0);
|
|
34
|
+
const banner = await DSBannerCO.getBanner();
|
|
35
|
+
await expect(banner).not.toHaveAttribute('role');
|
|
36
|
+
await expect(await DSBannerCO.getActiveElementTestId()).toBe('ds-button');
|
|
37
|
+
});
|
|
38
|
+
it('04: should clear the live region on close and fill it again on reopen', async () => {
|
|
39
|
+
await DSBannerCO.closeBanner();
|
|
40
|
+
await DSBannerCO.waitForLiveRegionCleared();
|
|
41
|
+
await DSBannerCO.openBanner();
|
|
42
|
+
await DSBannerCO.waitForLiveRegionText(DSBannerCO.ANNOUNCEMENT_TITLE);
|
|
43
|
+
});
|
|
21
44
|
});
|
|
22
45
|
describe('PUI-17538 - Banner - Aria Polite -Func', () => {
|
|
23
46
|
before('loading page', async () => {
|
|
24
47
|
const errorOnGo = await DSBannerCO.ariaLivePoliteTest.go();
|
|
25
48
|
if (errorOnGo) throw errorOnGo;
|
|
26
49
|
});
|
|
27
|
-
it('01: should
|
|
50
|
+
it('01: should render an empty polite live region before the banner opens', async () => {
|
|
51
|
+
const liveRegion = await DSBannerCO.getLiveRegionPortal();
|
|
52
|
+
await expect(liveRegion).toExist();
|
|
53
|
+
await expect(liveRegion).toHaveAttribute('aria-live', 'polite');
|
|
54
|
+
await expect(liveRegion).toHaveAttribute('aria-atomic', 'true');
|
|
55
|
+
await expect(await DSBannerCO.getLiveRegionText()).toBe('');
|
|
56
|
+
});
|
|
57
|
+
it('02: should have aria-live="polite" attribute on banner after trigger', async () => {
|
|
28
58
|
const triggerButton = await DSBannerCO.getButton();
|
|
29
59
|
await triggerButton.click();
|
|
30
60
|
const banner = await DSBannerCO.getBannerLiveRegionPortalSlotByIndex();
|
|
31
61
|
await banner.waitForDisplayed();
|
|
32
62
|
await expect(banner).toHaveAttribute('aria-live', 'polite');
|
|
33
63
|
});
|
|
64
|
+
it('03: should announce title and body together without moving focus', async () => {
|
|
65
|
+
const liveRegion = await DSBannerCO.getLiveRegionPortal();
|
|
66
|
+
await DSBannerCO.waitForLiveRegionText(DSBannerCO.ANNOUNCEMENT_TITLE);
|
|
67
|
+
await expect(await DSBannerCO.getLiveRegionText()).toContain(DSBannerCO.ANNOUNCEMENT_BODY);
|
|
68
|
+
await expect(await liveRegion.$$('button, a').length).toBe(0);
|
|
69
|
+
const banner = await DSBannerCO.getBanner();
|
|
70
|
+
await expect(banner).not.toHaveAttribute('role');
|
|
71
|
+
await expect(await DSBannerCO.getActiveElementTestId()).toBe('ds-button');
|
|
72
|
+
});
|
|
73
|
+
it('04: should clear the live region on close and fill it again on reopen', async () => {
|
|
74
|
+
await DSBannerCO.closeBanner();
|
|
75
|
+
await DSBannerCO.waitForLiveRegionCleared();
|
|
76
|
+
await DSBannerCO.openBanner();
|
|
77
|
+
await DSBannerCO.waitForLiveRegionText(DSBannerCO.ANNOUNCEMENT_TITLE);
|
|
78
|
+
});
|
|
34
79
|
});
|
|
35
80
|
describe('PUI-17539 - Banner - Role Alert -Func', () => {
|
|
36
81
|
before('loading page', async () => {
|
|
@@ -44,6 +89,15 @@ if (
|
|
|
44
89
|
await banner.waitForDisplayed();
|
|
45
90
|
await expect(banner).toHaveAttribute('role', 'alert');
|
|
46
91
|
});
|
|
92
|
+
it('02: should announce title and body in the alert without moving focus', async () => {
|
|
93
|
+
const banner = await DSBannerCO.getBanner();
|
|
94
|
+
await expect(banner).toHaveText(expect.stringContaining(DSBannerCO.ANNOUNCEMENT_TITLE));
|
|
95
|
+
await expect(banner).toHaveText(expect.stringContaining(DSBannerCO.ANNOUNCEMENT_BODY));
|
|
96
|
+
await expect(await banner.$$('button, a').length).toBe(0);
|
|
97
|
+
const liveRegion = await DSBannerCO.getLiveRegionPortal();
|
|
98
|
+
await expect(liveRegion).not.toExist();
|
|
99
|
+
await expect(await DSBannerCO.getActiveElementTestId()).toBe('ds-button');
|
|
100
|
+
});
|
|
47
101
|
});
|
|
48
102
|
describe('PUI-17540 - Banner - Role Region and Alert -Func', () => {
|
|
49
103
|
before('loading page', async () => {
|
|
@@ -60,4 +114,61 @@ if (
|
|
|
60
114
|
await expect(banner).toHaveAttribute('role', 'alert');
|
|
61
115
|
});
|
|
62
116
|
});
|
|
117
|
+
// Documented action-link setup (isPageNotice + withLiveRegionAnnouncement="none"), PUI-17840
|
|
118
|
+
describe('PUI-19264 - DSBanner:: region without live announcement - Func', () => {
|
|
119
|
+
before('loading page', async () => {
|
|
120
|
+
const errorOnGo = await DSBannerCO.roleRegionNoAnnouncementTest.go();
|
|
121
|
+
if (errorOnGo) throw errorOnGo;
|
|
122
|
+
});
|
|
123
|
+
it('01: should render a page region that is not announced automatically', async () => {
|
|
124
|
+
const bannerContainer = await DSBannerCO.getBannerContainer();
|
|
125
|
+
await bannerContainer.waitForDisplayed();
|
|
126
|
+
await expect(bannerContainer).toHaveAttribute('role', 'region');
|
|
127
|
+
await expect(await $$('[role="alert"]').length).toBe(0);
|
|
128
|
+
const liveRegion = await DSBannerCO.getLiveRegionPortal();
|
|
129
|
+
await expect(liveRegion).not.toExist();
|
|
130
|
+
const actionLink = await DSBannerCO.getActionLink();
|
|
131
|
+
await expect(actionLink).toHaveAttribute('href');
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
// Tests for the fix introduced in PUI-19088 (isPageNotice region had no accessible name)
|
|
135
|
+
describe('PUI-19265 - DSBanner:: page notice region accessible name - Func', () => {
|
|
136
|
+
before('loading page', async () => {
|
|
137
|
+
const errorOnGo = await DSBannerCO.regionAccessibleNameTest.go();
|
|
138
|
+
if (errorOnGo) throw errorOnGo;
|
|
139
|
+
});
|
|
140
|
+
it('01: should name each page notice region from its title, its label or the consumer name', async () => {
|
|
141
|
+
const defaultRegion = await DSBannerCO.getRegionByCase('region-default-name');
|
|
142
|
+
await defaultRegion.waitForDisplayed();
|
|
143
|
+
const defaultTitle = await DSBannerCO.getRegionTitleByCase('region-default-name');
|
|
144
|
+
const defaultTitleId = await defaultTitle.getAttribute('id');
|
|
145
|
+
await expect(defaultTitleId).toBeTruthy();
|
|
146
|
+
await expect(defaultTitle).toHaveText('Default name from title');
|
|
147
|
+
await expect(await DSBannerCO.getRegionNameAttributes('region-default-name')).toEqual({
|
|
148
|
+
ariaLabel: null,
|
|
149
|
+
ariaLabelledby: defaultTitleId,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const secondTitle = await DSBannerCO.getRegionTitleByCase('region-second-default-name');
|
|
153
|
+
const secondTitleId = await secondTitle.getAttribute('id');
|
|
154
|
+
await expect(secondTitleId).not.toBe(defaultTitleId);
|
|
155
|
+
await expect(await DSBannerCO.getRegionNameAttributes('region-second-default-name')).toEqual({
|
|
156
|
+
ariaLabel: null,
|
|
157
|
+
ariaLabelledby: secondTitleId,
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
await expect(await DSBannerCO.getRegionNameAttributes('region-custom-body')).toEqual({
|
|
161
|
+
ariaLabel: 'Custom body label',
|
|
162
|
+
ariaLabelledby: null,
|
|
163
|
+
});
|
|
164
|
+
await expect(await DSBannerCO.getRegionNameAttributes('region-slot-name')).toEqual({
|
|
165
|
+
ariaLabel: 'Name from container slot',
|
|
166
|
+
ariaLabelledby: null,
|
|
167
|
+
});
|
|
168
|
+
await expect(await DSBannerCO.getRegionNameAttributes('region-container-props-name')).toEqual({
|
|
169
|
+
ariaLabel: 'Name from containerProps',
|
|
170
|
+
ariaLabelledby: null,
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
});
|
|
63
174
|
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import DSBannerCO from '../DSBannerCO';
|
|
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
|
+
// Tests for the fix introduced in PUI-19089 (the body had the hardcoded id "ds-banner-body", repeated per banner)
|
|
10
|
+
describe('PUI-19271 - DSBanner:: per-instance ids and bannerId references - Func', () => {
|
|
11
|
+
const GENERATED_ONE = 0;
|
|
12
|
+
const GENERATED_TWO = 1;
|
|
13
|
+
const SAVED = 2;
|
|
14
|
+
const MAINTENANCE = 3;
|
|
15
|
+
|
|
16
|
+
let bannerIds;
|
|
17
|
+
|
|
18
|
+
before('loading page', async () => {
|
|
19
|
+
const errorOnGo = await DSBannerCO.bannerIdsTest.go();
|
|
20
|
+
if (errorOnGo) throw errorOnGo;
|
|
21
|
+
bannerIds = await DSBannerCO.getBannerIds();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('01: should render unique ids derived from one base for banners without bannerId', async () => {
|
|
25
|
+
const allIds = await DSBannerCO.getAllBannerIds();
|
|
26
|
+
await expect(allIds.length).toBe(new Set(allIds).size);
|
|
27
|
+
await expect(allIds).not.toContain('ds-banner-body');
|
|
28
|
+
|
|
29
|
+
[GENERATED_ONE, GENERATED_TWO].forEach((index) => {
|
|
30
|
+
const { base, title, body, liveRegionTestId } = bannerIds[index];
|
|
31
|
+
expect(base).toMatch(/^[A-Za-z]/);
|
|
32
|
+
expect(title).toBe(`${base}-title`);
|
|
33
|
+
expect(body).toBe(`${base}-body`);
|
|
34
|
+
expect(liveRegionTestId).toBe('ds-banner-live-region-portal');
|
|
35
|
+
});
|
|
36
|
+
await expect(bannerIds[GENERATED_ONE].base).not.toBe(bannerIds[GENERATED_TWO].base);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('02: should derive every id from the bannerId set by the consumer', async () => {
|
|
40
|
+
await expect(bannerIds[SAVED]).toEqual({
|
|
41
|
+
base: 'saved-banner',
|
|
42
|
+
title: 'saved-banner-title',
|
|
43
|
+
body: 'saved-banner-body',
|
|
44
|
+
liveRegionTestId: 'ds-banner-live-region-portal',
|
|
45
|
+
});
|
|
46
|
+
await expect(bannerIds[MAINTENANCE]).toEqual({
|
|
47
|
+
base: 'maintenance-banner',
|
|
48
|
+
title: 'maintenance-banner-title',
|
|
49
|
+
body: 'maintenance-banner-body',
|
|
50
|
+
liveRegionTestId: 'ds-banner-live-region-portal',
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('03: should describe each action link with the body of its own banner', async () => {
|
|
55
|
+
const savedDescription = await DSBannerCO.getActionLinkDescription(0);
|
|
56
|
+
await expect(savedDescription.describedBy).toBe('saved-banner-body');
|
|
57
|
+
await expect(savedDescription.isInsideOwnBanner).toBe(true);
|
|
58
|
+
await expect(savedDescription.text).toContain('Your settings were saved successfully.');
|
|
59
|
+
|
|
60
|
+
const maintenanceDescription = await DSBannerCO.getActionLinkDescription(1);
|
|
61
|
+
await expect(maintenanceDescription.describedBy).toBe('maintenance-banner-body');
|
|
62
|
+
await expect(maintenanceDescription.isInsideOwnBanner).toBe(true);
|
|
63
|
+
await expect(maintenanceDescription.text).toContain('A maintenance window starts tonight at 10 PM.');
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import DSBannerCO from '../DSBannerCO';
|
|
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
|
+
// Tests for the fix introduced in PUI-19090 (the live region portal did not carry the lang and dir of the banner)
|
|
10
|
+
describe('PUI-19272 - DSBanner:: live region lang and dir - Func', () => {
|
|
11
|
+
const POLITE = 0;
|
|
12
|
+
const ASSERTIVE = 1;
|
|
13
|
+
const WITHOUT_LANG_DIR = 2;
|
|
14
|
+
|
|
15
|
+
before('loading page', async () => {
|
|
16
|
+
const errorOnGo = await DSBannerCO.liveRegionLangDirTest.go();
|
|
17
|
+
if (errorOnGo) throw errorOnGo;
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('01: should carry the lang and dir of the banner in the polite and assertive live regions', async () => {
|
|
21
|
+
const politePortal = await DSBannerCO.getLiveRegionPortalByIndex(POLITE);
|
|
22
|
+
await expect(politePortal).toHaveAttribute('lang', 'fr');
|
|
23
|
+
await expect(politePortal).toHaveAttribute('dir', 'rtl');
|
|
24
|
+
|
|
25
|
+
const assertivePortal = await DSBannerCO.getLiveRegionPortalByIndex(ASSERTIVE);
|
|
26
|
+
await expect(assertivePortal).toHaveAttribute('lang', 'es');
|
|
27
|
+
await expect(assertivePortal).toHaveAttribute('dir', 'ltr');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('02: should not render lang or dir in the live region of a banner that does not set them', async () => {
|
|
31
|
+
const portal = await DSBannerCO.getLiveRegionPortalByIndex(WITHOUT_LANG_DIR);
|
|
32
|
+
await expect(portal).not.toHaveAttribute('lang');
|
|
33
|
+
await expect(portal).not.toHaveAttribute('dir');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('03: should keep lang and dir in the live regions after the banners are closed', async () => {
|
|
37
|
+
const toggleButton = await DSBannerCO.getButton();
|
|
38
|
+
await toggleButton.click();
|
|
39
|
+
await DSBannerCO.waitForLiveRegionCleared();
|
|
40
|
+
|
|
41
|
+
const politePortal = await DSBannerCO.getLiveRegionPortalByIndex(POLITE);
|
|
42
|
+
await expect(politePortal).toHaveAttribute('lang', 'fr');
|
|
43
|
+
await expect(politePortal).toHaveAttribute('dir', 'rtl');
|
|
44
|
+
|
|
45
|
+
const assertivePortal = await DSBannerCO.getLiveRegionPortalByIndex(ASSERTIVE);
|
|
46
|
+
await expect(assertivePortal).toHaveAttribute('lang', 'es');
|
|
47
|
+
await expect(assertivePortal).toHaveAttribute('dir', 'ltr');
|
|
48
|
+
|
|
49
|
+
const portalWithoutLangDir = await DSBannerCO.getLiveRegionPortalByIndex(WITHOUT_LANG_DIR);
|
|
50
|
+
await expect(portalWithoutLangDir).not.toHaveAttribute('lang');
|
|
51
|
+
await expect(portalWithoutLangDir).not.toHaveAttribute('dir');
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import DSBannerCO from '../DSBannerCO';
|
|
2
|
+
|
|
3
|
+
// the samples come from the page (requestAnimationFrame), so these tolerances only absorb the machine speed
|
|
4
|
+
const MOTION_MS = 500;
|
|
5
|
+
const MIN_END_MS = MOTION_MS * 0.7;
|
|
6
|
+
const MAX_END_MS = MOTION_MS * 2;
|
|
7
|
+
const MIN_INTERMEDIATE_FRAMES = 5;
|
|
8
|
+
const PX_TOLERANCE = 1;
|
|
9
|
+
|
|
10
|
+
const isIntermediate = (height, fullHeight) => height > PX_TOLERANCE && height < fullHeight - PX_TOLERANCE;
|
|
11
|
+
const heights = (samples) => samples.map(({ height }) => height).filter((height) => height !== null);
|
|
12
|
+
// the frames of the motion: from the first one that is clearly collapsed. Some engines report, in the sampler's very
|
|
13
|
+
// first frame, the size of a layout flushed before their first rendering update (the banner never paints like that)
|
|
14
|
+
const getMotionFrames = (samples, fullHeight) => {
|
|
15
|
+
const start = samples.findIndex(({ height }) => height !== null && height < fullHeight * 0.5);
|
|
16
|
+
return start === -1 ? [] : samples.slice(start);
|
|
17
|
+
};
|
|
18
|
+
const isMonotonic = (values, direction) =>
|
|
19
|
+
values.every((value, index) => index === 0 || (value - values[index - 1]) * direction >= -PX_TOLERANCE);
|
|
20
|
+
|
|
21
|
+
// Banner spec v2, "Motion and Animation": the banner slides down (open) and up (close) in 500 ms, pushing the content
|
|
22
|
+
// below gradually. Tests for the fix introduced in PUI-19232 (the slide was not rendered).
|
|
23
|
+
if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
|
|
24
|
+
describe('PUI-19269 - Banner:: open and close slide animation (500 ms) - Func', () => {
|
|
25
|
+
let openSamples;
|
|
26
|
+
let openFrames;
|
|
27
|
+
let closeSamples;
|
|
28
|
+
let closedPushedTop;
|
|
29
|
+
let fullHeight;
|
|
30
|
+
|
|
31
|
+
before('loading page', async () => {
|
|
32
|
+
const errorOnGo = await DSBannerCO.pushesContentURL.go();
|
|
33
|
+
if (errorOnGo) throw errorOnGo;
|
|
34
|
+
closedPushedTop = await DSBannerCO.getPushedContentTop();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('01: should grow the banner gradually from 0 to its full height when opening', async () => {
|
|
38
|
+
openSamples = await DSBannerCO.sampleSlide('open');
|
|
39
|
+
const withBanner = openSamples.filter(({ height }) => height !== null);
|
|
40
|
+
fullHeight = withBanner[withBanner.length - 1].height;
|
|
41
|
+
expect(fullHeight).toBeGreaterThan(50);
|
|
42
|
+
// not at full height from the start: there are frames in which the banner is (almost) collapsed
|
|
43
|
+
openFrames = getMotionFrames(openSamples, fullHeight);
|
|
44
|
+
expect(openFrames.length).toBeGreaterThan(0);
|
|
45
|
+
expect(openFrames[0].height).toBeLessThan(fullHeight * 0.25);
|
|
46
|
+
// several frames in between and never shrinking
|
|
47
|
+
expect(heights(openFrames).filter((height) => isIntermediate(height, fullHeight)).length).toBeGreaterThanOrEqual(
|
|
48
|
+
MIN_INTERMEDIATE_FRAMES,
|
|
49
|
+
);
|
|
50
|
+
expect(isMonotonic(heights(openFrames), 1)).toBe(true);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('02: should take about 500 ms to reach the full height when opening', async () => {
|
|
54
|
+
const reached = openFrames.find(({ height }) => height >= fullHeight - PX_TOLERANCE);
|
|
55
|
+
expect(reached.t).toBeGreaterThanOrEqual(MIN_END_MS);
|
|
56
|
+
expect(reached.t).toBeLessThanOrEqual(MAX_END_MS);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('03: should push the content below gradually and in sync with the banner when opening', async () => {
|
|
60
|
+
const pushedTops = openFrames.map(({ pushedTop }) => pushedTop);
|
|
61
|
+
expect(isMonotonic(pushedTops, 1)).toBe(true);
|
|
62
|
+
expect(
|
|
63
|
+
pushedTops.filter((top) => isIntermediate(top - closedPushedTop, fullHeight)).length,
|
|
64
|
+
).toBeGreaterThanOrEqual(MIN_INTERMEDIATE_FRAMES);
|
|
65
|
+
openFrames.forEach(({ height, pushedTop }) => expect(pushedTop - closedPushedTop).toBeCloseTo(height, 0));
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('04: should keep the banner in the document, closed for everyone, while it slides up', async () => {
|
|
69
|
+
closeSamples = await DSBannerCO.sampleSlide('close');
|
|
70
|
+
// not removed on the first frame
|
|
71
|
+
expect(closeSamples.filter(({ height }) => height !== null).length).toBeGreaterThan(MIN_INTERMEDIATE_FRAMES);
|
|
72
|
+
expect(closeSamples[1].height).toBeGreaterThan(fullHeight * 0.5);
|
|
73
|
+
// from the first rendered frame after the click: not exposed and not interactive
|
|
74
|
+
const sliding = closeSamples.filter(({ height, t }) => height !== null && t > 0);
|
|
75
|
+
sliding.forEach(({ inert, ariaHidden }) => {
|
|
76
|
+
expect(inert).toBe(true);
|
|
77
|
+
expect(ariaHidden).toBe('true');
|
|
78
|
+
});
|
|
79
|
+
// the close button had focus: once inert the focus is not inside the banner anymore
|
|
80
|
+
closeSamples
|
|
81
|
+
.filter(({ height, t }) => height !== null && t > 100)
|
|
82
|
+
.forEach(({ focusInside }) => expect(focusInside).toBe(false));
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('05: should collapse gradually and be removed after about 500 ms when closing', async () => {
|
|
86
|
+
expect(isMonotonic(heights(closeSamples), -1)).toBe(true);
|
|
87
|
+
expect(
|
|
88
|
+
heights(closeSamples).filter((height) => isIntermediate(height, fullHeight)).length,
|
|
89
|
+
).toBeGreaterThanOrEqual(MIN_INTERMEDIATE_FRAMES);
|
|
90
|
+
const removed = closeSamples.find(({ height }) => height === null);
|
|
91
|
+
expect(removed.t).toBeGreaterThanOrEqual(MIN_END_MS);
|
|
92
|
+
expect(removed.t).toBeLessThanOrEqual(MAX_END_MS);
|
|
93
|
+
await expect(await DSBannerCO.getBannerContainer()).not.toExist();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('06: should move the content below back gradually when closing', async () => {
|
|
97
|
+
const pushedTops = closeSamples.map(({ pushedTop }) => pushedTop);
|
|
98
|
+
expect(isMonotonic(pushedTops, -1)).toBe(true);
|
|
99
|
+
expect(
|
|
100
|
+
pushedTops.filter((top) => isIntermediate(top - closedPushedTop, fullHeight)).length,
|
|
101
|
+
).toBeGreaterThanOrEqual(MIN_INTERMEDIATE_FRAMES);
|
|
102
|
+
expect(pushedTops[pushedTops.length - 1]).toBeCloseTo(closedPushedTop, 0);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import DSBannerCO from '../DSBannerCO';
|
|
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
|
+
// Coverage for PUI-17935 (slots implementation and Dimsum slot compliance)
|
|
11
|
+
describe('PUI-19263 - DSBanner:: slots theming - AxeCore', () => {
|
|
12
|
+
before('loading page', async () => {
|
|
13
|
+
const errorOnGo = await DSBannerCO.slotsTest.go();
|
|
14
|
+
if (errorOnGo) throw errorOnGo;
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('01: should display the banners customized using slots and pass axecore test', async () => {
|
|
18
|
+
const banner = await DSBannerCO.getContainerSlotByIndex();
|
|
19
|
+
await banner.waitForDisplayed();
|
|
20
|
+
const result = await axeCoreCheck();
|
|
21
|
+
expect(result.length).toBe(0);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}
|
|
@@ -30,6 +30,9 @@ if (
|
|
|
30
30
|
await expect(bannerButtonSlot).toBeDisplayed();
|
|
31
31
|
await expect(bannerLayoutSlot).toBeDisplayed();
|
|
32
32
|
await expect(bannerActionLinkSlot).toBeDisplayed();
|
|
33
|
+
// PUI-17935: the close button exposes its parent slot (nested DSButton)
|
|
34
|
+
const bannerCloseButtonSlot = await DSBannerCO.getCloseButtonSlotByIndex();
|
|
35
|
+
await expect(bannerCloseButtonSlot).toBeDisplayed();
|
|
33
36
|
});
|
|
34
37
|
it('02: should find custom aria for each SLOT', async () => {
|
|
35
38
|
const bannerTitleSlot = await DSBannerCO.getTitleSlotByIndex();
|
|
@@ -48,6 +51,8 @@ if (
|
|
|
48
51
|
await expect(bannerIconsSlots).toHaveAttribute('aria-label', 'im iconcontainer aria');
|
|
49
52
|
await expect(bannerButtonSlot).toHaveAttribute('aria-label', 'im closebutton aria');
|
|
50
53
|
await expect(bannerActionLinkSlot).toHaveAttribute('aria-label', 'im actionlink aria');
|
|
54
|
+
const bannerCloseButtonSlot = await DSBannerCO.getCloseButtonSlotByIndex();
|
|
55
|
+
await expect(bannerCloseButtonSlot).toHaveAttribute('aria-label', 'im closebutton aria');
|
|
51
56
|
});
|
|
52
57
|
it('03: should find custom data for each SLOT', async () => {
|
|
53
58
|
const bannerTitleSlot = await DSBannerCO.getTitleSlotByIndex();
|
|
@@ -66,6 +71,8 @@ if (
|
|
|
66
71
|
await expect(bannerIconsSlots).toHaveAttribute('data-testid', 'im iconcontainer data');
|
|
67
72
|
await expect(bannerButtonSlot).toHaveAttribute('data-testid', 'im closebutton data');
|
|
68
73
|
await expect(bannerActionLinkSlot).toHaveAttribute('data-testid', 'im actionlink data');
|
|
74
|
+
const bannerCloseButtonSlot = await DSBannerCO.getCloseButtonSlotByIndex();
|
|
75
|
+
await expect(bannerCloseButtonSlot).toHaveAttribute('data-testid', 'im closebutton data');
|
|
69
76
|
});
|
|
70
77
|
});
|
|
71
78
|
}
|
|
@@ -9,6 +9,8 @@ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:o
|
|
|
9
9
|
it('should display the banners customized using slots', async () => {
|
|
10
10
|
const banner = await DSBannerCO.getContainerSlotByIndex();
|
|
11
11
|
await banner.waitForDisplayed();
|
|
12
|
+
// the banners are open on load and slide down for 500 ms
|
|
13
|
+
await DSBannerCO.waitForSlideToEnd();
|
|
12
14
|
const snapshot = await browser.percyCheckScreenshot();
|
|
13
15
|
await expect(snapshot).toEqual(0);
|
|
14
16
|
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import DSBannerCO from '../DSBannerCO';
|
|
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
|
+
// Tests for the fix introduced in PUI-19231 (the title was an h5 and added a heading to the host page outline)
|
|
10
|
+
describe('PUI-19270 - DSBanner:: title rendered as span, not heading - Func', () => {
|
|
11
|
+
before('loading page', async () => {
|
|
12
|
+
const errorOnGo = await DSBannerCO.infoURL.go();
|
|
13
|
+
if (errorOnGo) throw errorOnGo;
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('01: should render the title as a span without heading role and keep its attributes', async () => {
|
|
17
|
+
await DSBannerCO.openBanner();
|
|
18
|
+
|
|
19
|
+
const title = await DSBannerCO.getTitle();
|
|
20
|
+
await expect(title).toBeDisplayed();
|
|
21
|
+
await expect(await title.getTagName()).toBe('span');
|
|
22
|
+
await expect(title).not.toHaveAttribute('role');
|
|
23
|
+
await expect(await DSBannerCO.getHeadingsCountInBanners()).toBe(0);
|
|
24
|
+
|
|
25
|
+
await expect(title).toHaveAttribute('data-dimsum-parent-slot', 'dsBannerTitle');
|
|
26
|
+
await expect(await title.getAttribute('id')).toBeTruthy();
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
}
|
package/ds-ribbon/DSRibbonCO.js
CHANGED
|
@@ -12,6 +12,10 @@ export default class DSRibbonCO extends PageObject {
|
|
|
12
12
|
|
|
13
13
|
static themingURL = new Urlbuilder(PATH_E2E_RIBBON, 'theming-test');
|
|
14
14
|
|
|
15
|
+
static wrapColumnsURL = new Urlbuilder(PATH_E2E_RIBBON, 'wrap-columns-test');
|
|
16
|
+
|
|
17
|
+
static keyboardAccessibleRowURL = new Urlbuilder(PATH_E2E_RIBBON, 'keyboard-accessible-row-test');
|
|
18
|
+
|
|
15
19
|
static async getRibbon() {
|
|
16
20
|
return $('[data-testid="button-wrapper"]');
|
|
17
21
|
}
|
|
@@ -91,6 +95,23 @@ export default class DSRibbonCO extends PageObject {
|
|
|
91
95
|
return $('[data-testid="ribbon-card-theming"]');
|
|
92
96
|
}
|
|
93
97
|
|
|
98
|
+
// Wrap Columns / Keyboard Accessible Row selectors
|
|
99
|
+
static async getRowInContainer(containerTestId) {
|
|
100
|
+
return $(`[data-testid="${containerTestId}"] [data-dimsum-slot="dsRibbonRibbonRow"]`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
static async getWrapColumnsRow() {
|
|
104
|
+
return DSRibbonCO.getRowInContainer('ribbon-wrap-columns-container');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
static async getFocusableRow() {
|
|
108
|
+
return DSRibbonCO.getRowInContainer('ribbon-focusable-row-container');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
static async getExpandProcessedBtn() {
|
|
112
|
+
return $('[data-testid="expand-processed-btn"]');
|
|
113
|
+
}
|
|
114
|
+
|
|
94
115
|
// Snapshots
|
|
95
116
|
static snapshotPath(example = 'basic') {
|
|
96
117
|
return PageObject.getSnapshotPathBuilder('Ribbon', example, 'ds-modal');
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Key } from 'webdriverio';
|
|
2
|
+
import DSRibbonCO from '../DSRibbonCO';
|
|
3
|
+
|
|
4
|
+
// Kept at module scope so the waitUntil below stays within the max-nested-callbacks limit.
|
|
5
|
+
const readScrollLeft = (el) => el.scrollLeft;
|
|
6
|
+
|
|
7
|
+
if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
|
|
8
|
+
// Tests for the fix introduced in PUI-19188 (scrolling row had no tabindex and could not be reached by keyboard)
|
|
9
|
+
describe('PUI-19230 - DSRibbon:: scrolling row keyboard access - Visual', () => {
|
|
10
|
+
before('loading page', async () => {
|
|
11
|
+
const errorOnGo = await DSRibbonCO.keyboardAccessibleRowURL.go();
|
|
12
|
+
if (errorOnGo) throw errorOnGo;
|
|
13
|
+
const row = await DSRibbonCO.getFocusableRow();
|
|
14
|
+
await row.waitForDisplayed();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('01: should display the focus indicator on the scrolling row', async () => {
|
|
18
|
+
await browser.keys(Key.Tab);
|
|
19
|
+
const row = await DSRibbonCO.getFocusableRow();
|
|
20
|
+
await expect(row).toBeFocused();
|
|
21
|
+
// The row advertises "use the arrow keys to reach the remaining columns", so drive that before
|
|
22
|
+
// the snapshot: arrow keys keep focus on the row, so the Tab in 02 still reaches the button.
|
|
23
|
+
const scrollLeftBefore = await browser.execute(readScrollLeft, row);
|
|
24
|
+
await browser.keys(Key.ArrowRight);
|
|
25
|
+
await browser.waitUntil(async () => (await browser.execute(readScrollLeft, row)) > scrollLeftBefore, {
|
|
26
|
+
timeoutMsg: 'expected ArrowRight to scroll the focused row towards the off-screen columns',
|
|
27
|
+
});
|
|
28
|
+
const snapshot = await browser.percyCheckScreenshot();
|
|
29
|
+
await expect(snapshot).toEqual(0);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('02: should display the off-screen button scrolled into view with focus', async () => {
|
|
33
|
+
await browser.keys(Key.Tab);
|
|
34
|
+
const btn = await DSRibbonCO.getExpandProcessedBtn();
|
|
35
|
+
await expect(btn).toBeFocused();
|
|
36
|
+
const snapshot = await browser.percyCheckScreenshot();
|
|
37
|
+
await expect(snapshot).toEqual(0);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import DSRibbonCO from '../DSRibbonCO';
|
|
2
|
+
|
|
3
|
+
if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
|
|
4
|
+
// Tests for the fix introduced in PUI-19188 (row scrolled at narrow widths, off-screen columns unreachable)
|
|
5
|
+
describe('PUI-19229 - DSRibbon:: wrapColumns row wrapping - Visual', () => {
|
|
6
|
+
before('loading page', async () => {
|
|
7
|
+
const errorOnGo = await DSRibbonCO.wrapColumnsURL.go();
|
|
8
|
+
if (errorOnGo) throw errorOnGo;
|
|
9
|
+
const row = await DSRibbonCO.getWrapColumnsRow();
|
|
10
|
+
await row.waitForDisplayed();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('01: should display the default scrolling row and the wrapped row', async () => {
|
|
14
|
+
const snapshot = await browser.percyCheckScreenshot();
|
|
15
|
+
await expect(snapshot).toEqual(0);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
}
|
|
@@ -3,8 +3,23 @@
|
|
|
3
3
|
import { Key } from 'webdriverio';
|
|
4
4
|
import DSShuttleV2CO from '../DSShuttleV2CO';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Tab forward until `element` holds focus, then assert it does. Chromium, Gecko and WebKit do not
|
|
8
|
+
* agree on how many stops sit between the two panels, so a fixed Tab count activates the wrong
|
|
9
|
+
* control on some engines. Bounded so a missing stop fails with this assertion instead of looping.
|
|
10
|
+
*/
|
|
11
|
+
const tabUntilFocused = async (element, maxTabs = 10) => {
|
|
12
|
+
for (let i = 0; i < maxTabs; i += 1) {
|
|
13
|
+
// eslint-disable-next-line no-await-in-loop
|
|
14
|
+
if (await element.isFocused()) break;
|
|
15
|
+
// eslint-disable-next-line no-await-in-loop
|
|
16
|
+
await browser.keys(Key.Tab);
|
|
17
|
+
}
|
|
18
|
+
await expect(element).toBeFocused();
|
|
19
|
+
};
|
|
20
|
+
|
|
6
21
|
if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
|
|
7
|
-
describe('PUI-9799 - Shuttle V2, TabStops with BAB and LoadMore -Func.', () => {
|
|
22
|
+
describe('PUI-9799 - Shuttle V2, TabStops with BAB and LoadMore - Keyboard Func.', () => {
|
|
8
23
|
before(async () => {
|
|
9
24
|
const errorOnGo = await DSShuttleV2CO.loadMoreURL.go();
|
|
10
25
|
if (errorOnGo) throw errorOnGo;
|
|
@@ -19,43 +34,57 @@ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:o
|
|
|
19
34
|
await expect(BAB).toBeDisplayed();
|
|
20
35
|
await expect(sourcePanelCheckbox).toBeFocused();
|
|
21
36
|
});
|
|
22
|
-
it('
|
|
37
|
+
it('02: should tab and focus the source panel', async () => {
|
|
23
38
|
await browser.keys(Key.Tab);
|
|
24
39
|
const sourcePanel = await DSShuttleV2CO.getListWrapperMid(0);
|
|
25
40
|
await expect(sourcePanel).toBeFocused();
|
|
26
41
|
});
|
|
27
|
-
it('
|
|
42
|
+
it('03: should tab and focus the BAB', async () => {
|
|
28
43
|
await browser.keys(Key.Tab);
|
|
29
44
|
const BAB = await DSShuttleV2CO.getMoveMultipleButton(0);
|
|
30
45
|
await expect(BAB).toBeFocused();
|
|
31
46
|
});
|
|
32
|
-
it('
|
|
47
|
+
it('04: should tab and focus the loadmore', async () => {
|
|
33
48
|
await browser.keys(Key.Tab);
|
|
34
49
|
const loadMore = await DSShuttleV2CO.getListBottomLoadMoreBtn(0);
|
|
35
50
|
await expect(loadMore).toBeFocused();
|
|
36
51
|
});
|
|
37
|
-
it('
|
|
52
|
+
it('05: should tab and focus the global checkbox from destination panel', async () => {
|
|
38
53
|
await browser.keys(Key.Tab);
|
|
39
54
|
const destinationPanelCheckbox = await DSShuttleV2CO.getCheckboxByIndex(1);
|
|
40
55
|
await expect(destinationPanelCheckbox).toBeFocused();
|
|
41
56
|
});
|
|
42
|
-
it('
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
await
|
|
57
|
+
it('06: should move all the items to destination panel', async () => {
|
|
58
|
+
// Tab counts are not portable: the stops between the two panels differ per engine, and a
|
|
59
|
+
// hard-coded count lands Return on the wrong control in Safari. Walk until the target has
|
|
60
|
+
// focus instead, which asserts the same stops on every browser.
|
|
61
|
+
await tabUntilFocused(await DSShuttleV2CO.getCheckboxByIndex(0));
|
|
62
|
+
await browser.keys(Key.Return); // select every source item
|
|
63
|
+
await tabUntilFocused(await DSShuttleV2CO.getMoveMultipleButton());
|
|
64
|
+
await browser.keys(Key.Return); // move them to the destination
|
|
65
|
+
await browser.waitUntil(async () => (await DSShuttleV2CO.getItemsFromSource()).length === 0, {
|
|
66
|
+
timeoutMsg: 'expected the source panel to be emptied into the destination',
|
|
67
|
+
});
|
|
47
68
|
const emptyListWrapper = await DSShuttleV2CO.getEmptyListWrapper();
|
|
48
69
|
await expect(emptyListWrapper).toHaveText(expect.stringContaining('There are no items to display'));
|
|
49
70
|
});
|
|
50
|
-
it('
|
|
51
|
-
await
|
|
52
|
-
await browser.keys(Key.Return);
|
|
53
|
-
|
|
54
|
-
await browser.
|
|
55
|
-
|
|
71
|
+
it('07: should load the first page back into the emptied destination panel', async () => {
|
|
72
|
+
await tabUntilFocused(await DSShuttleV2CO.getCheckboxByIndex(1));
|
|
73
|
+
await browser.keys(Key.Return); // select every destination item
|
|
74
|
+
await tabUntilFocused(await DSShuttleV2CO.getMoveMultipleButton());
|
|
75
|
+
await browser.keys(Key.Return); // move them out of the destination
|
|
76
|
+
await browser.waitUntil(async () => (await DSShuttleV2CO.getItemsFromDestination()).length === 0, {
|
|
77
|
+
timeoutMsg: 'expected the destination panel to be emptied back into the source',
|
|
78
|
+
});
|
|
79
|
+
await tabUntilFocused(await DSShuttleV2CO.getListBottomLoadMoreBtn(1));
|
|
80
|
+
await browser.keys(Key.Return); // load the first page back in
|
|
81
|
+
// Where focus lands after load more is not asserted: Chromium parks it on the panel body,
|
|
82
|
+
// Firefox and Safari do not, so it is engine behaviour rather than a component contract.
|
|
83
|
+
await browser.waitUntil(async () => (await DSShuttleV2CO.getItemsFromDestination()).length === 3, {
|
|
84
|
+
timeoutMsg: 'expected destination load more to append its first page of 3 items',
|
|
85
|
+
});
|
|
56
86
|
const destinationItems = (await DSShuttleV2CO.getItemsFromDestination()).length;
|
|
57
87
|
await expect(destinationItems).toBe(3);
|
|
58
|
-
await expect(destinationPanel).toBeFocused();
|
|
59
88
|
});
|
|
60
89
|
});
|
|
61
90
|
}
|
package/package.json
CHANGED
|
@@ -1,100 +1,100 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "dimsum-e2e-tests",
|
|
4
|
-
"version": "3.80.0-next.
|
|
4
|
+
"version": "3.80.0-next.39",
|
|
5
5
|
"description": "End-to-end tests for dimsum library",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@elliemae/ds-accessibility": "3.80.0-next.
|
|
8
|
-
"@elliemae/ds-accordion": "3.80.0-next.
|
|
9
|
-
"@elliemae/ds-app-picker": "3.80.0-next.
|
|
10
|
-
"@elliemae/ds-backdrop": "3.80.0-next.
|
|
11
|
-
"@elliemae/ds-banner": "3.80.0-next.
|
|
12
|
-
"@elliemae/ds-basic": "3.80.0-next.
|
|
13
|
-
"@elliemae/ds-breadcrumb": "3.80.0-next.
|
|
14
|
-
"@elliemae/ds-button-v2": "3.80.0-next.
|
|
15
|
-
"@elliemae/ds-card": "3.80.0-next.
|
|
16
|
-
"@elliemae/ds-card-navigation": "3.80.0-next.
|
|
17
|
-
"@elliemae/ds-card-v1": "3.80.0-next.
|
|
18
|
-
"@elliemae/ds-card-v1-detail": "3.80.0-next.
|
|
19
|
-
"@elliemae/ds-card-v2": "3.80.0-next.
|
|
20
|
-
"@elliemae/ds-card-v2-action-addon": "3.80.0-next.
|
|
21
|
-
"@elliemae/ds-card-v2-group": "3.80.0-next.
|
|
22
|
-
"@elliemae/ds-card-v3": "3.80.0-next.
|
|
23
|
-
"@elliemae/ds-card-v3-poc": "3.80.0-next.
|
|
24
|
-
"@elliemae/ds-chat": "3.80.0-next.
|
|
25
|
-
"@elliemae/ds-chat-bubble": "3.80.0-next.
|
|
26
|
-
"@elliemae/ds-chat-card": "3.80.0-next.
|
|
27
|
-
"@elliemae/ds-chat-container": "3.80.0-next.
|
|
28
|
-
"@elliemae/ds-chat-container-header": "3.80.0-next.
|
|
29
|
-
"@elliemae/ds-chat-empty-state": "3.80.0-next.
|
|
30
|
-
"@elliemae/ds-chat-floating-button": "3.80.0-next.
|
|
31
|
-
"@elliemae/ds-chat-message-delimeter": "3.80.0-next.
|
|
32
|
-
"@elliemae/ds-chat-sidebar": "3.80.0-next.
|
|
33
|
-
"@elliemae/ds-chat-system-message": "3.80.0-next.
|
|
34
|
-
"@elliemae/ds-chat-tile": "3.80.0-next.
|
|
35
|
-
"@elliemae/ds-chip": "3.80.0-next.
|
|
36
|
-
"@elliemae/ds-circular-progress-indicator": "3.80.0-next.
|
|
37
|
-
"@elliemae/ds-classnames": "3.80.0-next.
|
|
38
|
-
"@elliemae/ds-codeeditor": "3.80.0-next.
|
|
39
|
-
"@elliemae/ds-comments": "3.80.0-next.
|
|
40
|
-
"@elliemae/ds-controlled-form": "3.80.0-next.
|
|
41
|
-
"@elliemae/ds-csv-converter": "3.80.0-next.
|
|
42
|
-
"@elliemae/ds-data-table": "3.80.0-next.
|
|
43
|
-
"@elliemae/ds-data-table-action-cell": "3.80.0-next.
|
|
44
|
-
"@elliemae/ds-data-table-cell": "3.80.0-next.
|
|
45
|
-
"@elliemae/ds-data-table-cell-header": "3.80.0-next.
|
|
46
|
-
"@elliemae/ds-data-table-drag-and-drop-cell": "3.80.0-next.
|
|
47
|
-
"@elliemae/ds-data-table-expand-cell": "3.80.0-next.
|
|
48
|
-
"@elliemae/ds-data-table-filters": "3.80.0-next.
|
|
49
|
-
"@elliemae/ds-data-table-multi-select-cell": "3.80.0-next.
|
|
50
|
-
"@elliemae/ds-data-table-single-select-cell": "3.80.0-next.
|
|
51
|
-
"@elliemae/ds-dataviz": "3.80.0-next.
|
|
52
|
-
"@elliemae/ds-dataviz-pie": "3.80.0-next.
|
|
53
|
-
"@elliemae/ds-date-time-picker": "3.80.0-next.
|
|
54
|
-
"@elliemae/ds-decision-graph": "3.80.0-next.
|
|
55
|
-
"@elliemae/ds-dialog": "3.80.0-next.
|
|
56
|
-
"@elliemae/ds-drag-and-drop": "3.80.0-next.
|
|
57
|
-
"@elliemae/ds-dropdownmenu-v2": "3.80.0-next.
|
|
58
|
-
"@elliemae/ds-dropzone": "3.80.0-next.
|
|
59
|
-
"@elliemae/ds-fast-list": "3.80.0-next.
|
|
60
|
-
"@elliemae/ds-filter-bar": "3.80.0-next.
|
|
61
|
-
"@elliemae/ds-floating-context": "3.80.0-next.
|
|
62
|
-
"@elliemae/ds-form-checkbox": "3.80.0-next.
|
|
63
|
-
"@elliemae/ds-form-combobox": "3.80.0-next.
|
|
64
|
-
"@elliemae/ds-form-date-range-picker": "3.80.0-next.
|
|
65
|
-
"@elliemae/ds-form-date-time-picker": "3.80.0-next.
|
|
66
|
-
"@elliemae/ds-form-helpers-mask-hooks": "3.80.0-next.
|
|
67
|
-
"@elliemae/ds-form-input-text": "3.80.0-next.
|
|
68
|
-
"@elliemae/ds-form-input-textarea": "3.80.0-next.
|
|
69
|
-
"@elliemae/ds-form-layout-autocomplete": "3.80.0-next.
|
|
70
|
-
"@elliemae/ds-form-layout-blocks": "3.80.0-next.
|
|
71
|
-
"@elliemae/ds-form-layout-input-group": "3.80.0-next.
|
|
72
|
-
"@elliemae/ds-form-layout-label": "3.80.0-next.
|
|
73
|
-
"@elliemae/ds-form-multi-combobox": "3.80.0-next.
|
|
74
|
-
"@elliemae/ds-form-native-select": "3.80.0-next.
|
|
75
|
-
"@elliemae/ds-form-radio": "3.80.0-next.
|
|
76
|
-
"@elliemae/ds-form-select": "3.80.0-next.
|
|
77
|
-
"@elliemae/ds-form-single-combobox": "3.80.0-next.
|
|
78
|
-
"@elliemae/ds-form-toggle": "3.80.0-next.
|
|
79
|
-
"@elliemae/ds-global-header": "3.80.0-next.
|
|
80
|
-
"@elliemae/ds-grid": "3.80.0-next.
|
|
81
|
-
"@elliemae/ds-hooks-focus-stack": "3.80.0-next.
|
|
82
|
-
"@elliemae/ds-hooks-focus-trap": "3.80.0-next.
|
|
83
|
-
"@elliemae/ds-hooks-fontsize-detector": "3.80.0-next.
|
|
84
|
-
"@elliemae/ds-hooks-fontsize-media": "3.80.0-next.
|
|
85
|
-
"@elliemae/ds-hooks-headless-tooltip": "3.80.0-next.
|
|
86
|
-
"@elliemae/ds-hooks-is-mobile": "3.80.0-next.
|
|
87
|
-
"@elliemae/ds-hooks-is-showing-ellipsis": "3.80.0-next.
|
|
88
|
-
"@elliemae/ds-hooks-keyboard-navigation": "3.80.0-next.
|
|
89
|
-
"@elliemae/ds-hooks-on-blur-out": "3.80.0-next.
|
|
90
|
-
"@elliemae/ds-hooks-on-first-focus-in": "3.80.0-next.
|
|
91
|
-
"@elliemae/ds-icon": "3.80.0-next.
|
|
92
|
-
"@elliemae/ds-icons": "3.80.0-next.
|
|
93
|
-
"@elliemae/ds-image": "3.80.0-next.
|
|
94
|
-
"@elliemae/ds-imagelibrarymodal": "3.80.0-next.
|
|
95
|
-
"@elliemae/ds-indeterminate-progress-indicator": "3.80.0-next.
|
|
96
|
-
"@elliemae/ds-layout-provider": "3.80.0-next.
|
|
97
|
-
"@elliemae/ds-left-navigation": "3.80.0-next.
|
|
7
|
+
"@elliemae/ds-accessibility": "3.80.0-next.39",
|
|
8
|
+
"@elliemae/ds-accordion": "3.80.0-next.39",
|
|
9
|
+
"@elliemae/ds-app-picker": "3.80.0-next.39",
|
|
10
|
+
"@elliemae/ds-backdrop": "3.80.0-next.39",
|
|
11
|
+
"@elliemae/ds-banner": "3.80.0-next.39",
|
|
12
|
+
"@elliemae/ds-basic": "3.80.0-next.39",
|
|
13
|
+
"@elliemae/ds-breadcrumb": "3.80.0-next.39",
|
|
14
|
+
"@elliemae/ds-button-v2": "3.80.0-next.39",
|
|
15
|
+
"@elliemae/ds-card": "3.80.0-next.39",
|
|
16
|
+
"@elliemae/ds-card-navigation": "3.80.0-next.39",
|
|
17
|
+
"@elliemae/ds-card-v1": "3.80.0-next.39",
|
|
18
|
+
"@elliemae/ds-card-v1-detail": "3.80.0-next.39",
|
|
19
|
+
"@elliemae/ds-card-v2": "3.80.0-next.39",
|
|
20
|
+
"@elliemae/ds-card-v2-action-addon": "3.80.0-next.39",
|
|
21
|
+
"@elliemae/ds-card-v2-group": "3.80.0-next.39",
|
|
22
|
+
"@elliemae/ds-card-v3": "3.80.0-next.39",
|
|
23
|
+
"@elliemae/ds-card-v3-poc": "3.80.0-next.39",
|
|
24
|
+
"@elliemae/ds-chat": "3.80.0-next.39",
|
|
25
|
+
"@elliemae/ds-chat-bubble": "3.80.0-next.39",
|
|
26
|
+
"@elliemae/ds-chat-card": "3.80.0-next.39",
|
|
27
|
+
"@elliemae/ds-chat-container": "3.80.0-next.39",
|
|
28
|
+
"@elliemae/ds-chat-container-header": "3.80.0-next.39",
|
|
29
|
+
"@elliemae/ds-chat-empty-state": "3.80.0-next.39",
|
|
30
|
+
"@elliemae/ds-chat-floating-button": "3.80.0-next.39",
|
|
31
|
+
"@elliemae/ds-chat-message-delimeter": "3.80.0-next.39",
|
|
32
|
+
"@elliemae/ds-chat-sidebar": "3.80.0-next.39",
|
|
33
|
+
"@elliemae/ds-chat-system-message": "3.80.0-next.39",
|
|
34
|
+
"@elliemae/ds-chat-tile": "3.80.0-next.39",
|
|
35
|
+
"@elliemae/ds-chip": "3.80.0-next.39",
|
|
36
|
+
"@elliemae/ds-circular-progress-indicator": "3.80.0-next.39",
|
|
37
|
+
"@elliemae/ds-classnames": "3.80.0-next.39",
|
|
38
|
+
"@elliemae/ds-codeeditor": "3.80.0-next.39",
|
|
39
|
+
"@elliemae/ds-comments": "3.80.0-next.39",
|
|
40
|
+
"@elliemae/ds-controlled-form": "3.80.0-next.39",
|
|
41
|
+
"@elliemae/ds-csv-converter": "3.80.0-next.39",
|
|
42
|
+
"@elliemae/ds-data-table": "3.80.0-next.39",
|
|
43
|
+
"@elliemae/ds-data-table-action-cell": "3.80.0-next.39",
|
|
44
|
+
"@elliemae/ds-data-table-cell": "3.80.0-next.39",
|
|
45
|
+
"@elliemae/ds-data-table-cell-header": "3.80.0-next.39",
|
|
46
|
+
"@elliemae/ds-data-table-drag-and-drop-cell": "3.80.0-next.39",
|
|
47
|
+
"@elliemae/ds-data-table-expand-cell": "3.80.0-next.39",
|
|
48
|
+
"@elliemae/ds-data-table-filters": "3.80.0-next.39",
|
|
49
|
+
"@elliemae/ds-data-table-multi-select-cell": "3.80.0-next.39",
|
|
50
|
+
"@elliemae/ds-data-table-single-select-cell": "3.80.0-next.39",
|
|
51
|
+
"@elliemae/ds-dataviz": "3.80.0-next.39",
|
|
52
|
+
"@elliemae/ds-dataviz-pie": "3.80.0-next.39",
|
|
53
|
+
"@elliemae/ds-date-time-picker": "3.80.0-next.39",
|
|
54
|
+
"@elliemae/ds-decision-graph": "3.80.0-next.39",
|
|
55
|
+
"@elliemae/ds-dialog": "3.80.0-next.39",
|
|
56
|
+
"@elliemae/ds-drag-and-drop": "3.80.0-next.39",
|
|
57
|
+
"@elliemae/ds-dropdownmenu-v2": "3.80.0-next.39",
|
|
58
|
+
"@elliemae/ds-dropzone": "3.80.0-next.39",
|
|
59
|
+
"@elliemae/ds-fast-list": "3.80.0-next.39",
|
|
60
|
+
"@elliemae/ds-filter-bar": "3.80.0-next.39",
|
|
61
|
+
"@elliemae/ds-floating-context": "3.80.0-next.39",
|
|
62
|
+
"@elliemae/ds-form-checkbox": "3.80.0-next.39",
|
|
63
|
+
"@elliemae/ds-form-combobox": "3.80.0-next.39",
|
|
64
|
+
"@elliemae/ds-form-date-range-picker": "3.80.0-next.39",
|
|
65
|
+
"@elliemae/ds-form-date-time-picker": "3.80.0-next.39",
|
|
66
|
+
"@elliemae/ds-form-helpers-mask-hooks": "3.80.0-next.39",
|
|
67
|
+
"@elliemae/ds-form-input-text": "3.80.0-next.39",
|
|
68
|
+
"@elliemae/ds-form-input-textarea": "3.80.0-next.39",
|
|
69
|
+
"@elliemae/ds-form-layout-autocomplete": "3.80.0-next.39",
|
|
70
|
+
"@elliemae/ds-form-layout-blocks": "3.80.0-next.39",
|
|
71
|
+
"@elliemae/ds-form-layout-input-group": "3.80.0-next.39",
|
|
72
|
+
"@elliemae/ds-form-layout-label": "3.80.0-next.39",
|
|
73
|
+
"@elliemae/ds-form-multi-combobox": "3.80.0-next.39",
|
|
74
|
+
"@elliemae/ds-form-native-select": "3.80.0-next.39",
|
|
75
|
+
"@elliemae/ds-form-radio": "3.80.0-next.39",
|
|
76
|
+
"@elliemae/ds-form-select": "3.80.0-next.39",
|
|
77
|
+
"@elliemae/ds-form-single-combobox": "3.80.0-next.39",
|
|
78
|
+
"@elliemae/ds-form-toggle": "3.80.0-next.39",
|
|
79
|
+
"@elliemae/ds-global-header": "3.80.0-next.39",
|
|
80
|
+
"@elliemae/ds-grid": "3.80.0-next.39",
|
|
81
|
+
"@elliemae/ds-hooks-focus-stack": "3.80.0-next.39",
|
|
82
|
+
"@elliemae/ds-hooks-focus-trap": "3.80.0-next.39",
|
|
83
|
+
"@elliemae/ds-hooks-fontsize-detector": "3.80.0-next.39",
|
|
84
|
+
"@elliemae/ds-hooks-fontsize-media": "3.80.0-next.39",
|
|
85
|
+
"@elliemae/ds-hooks-headless-tooltip": "3.80.0-next.39",
|
|
86
|
+
"@elliemae/ds-hooks-is-mobile": "3.80.0-next.39",
|
|
87
|
+
"@elliemae/ds-hooks-is-showing-ellipsis": "3.80.0-next.39",
|
|
88
|
+
"@elliemae/ds-hooks-keyboard-navigation": "3.80.0-next.39",
|
|
89
|
+
"@elliemae/ds-hooks-on-blur-out": "3.80.0-next.39",
|
|
90
|
+
"@elliemae/ds-hooks-on-first-focus-in": "3.80.0-next.39",
|
|
91
|
+
"@elliemae/ds-icon": "3.80.0-next.39",
|
|
92
|
+
"@elliemae/ds-icons": "3.80.0-next.39",
|
|
93
|
+
"@elliemae/ds-image": "3.80.0-next.39",
|
|
94
|
+
"@elliemae/ds-imagelibrarymodal": "3.80.0-next.39",
|
|
95
|
+
"@elliemae/ds-indeterminate-progress-indicator": "3.80.0-next.39",
|
|
96
|
+
"@elliemae/ds-layout-provider": "3.80.0-next.39",
|
|
97
|
+
"@elliemae/ds-left-navigation": "3.80.0-next.39",
|
|
98
98
|
"@elliemae/ds-legacy-button": "1.0.16",
|
|
99
99
|
"@elliemae/ds-legacy-button-group": "1.0.16",
|
|
100
100
|
"@elliemae/ds-legacy-button-v1": "1.0.16",
|
|
@@ -129,63 +129,63 @@
|
|
|
129
129
|
"@elliemae/ds-legacy-wysiwygeditor": "1.0.16",
|
|
130
130
|
"@elliemae/ds-legacy-zipcode-search": "1.0.16",
|
|
131
131
|
"@elliemae/ds-legacy-zoom": "1.0.16",
|
|
132
|
-
"@elliemae/ds-loading-indicator": "3.80.0-next.
|
|
133
|
-
"@elliemae/ds-menu-button": "3.80.0-next.
|
|
134
|
-
"@elliemae/ds-menu-items": "3.80.0-next.
|
|
135
|
-
"@elliemae/ds-menu-items-action": "3.80.0-next.
|
|
136
|
-
"@elliemae/ds-menu-items-commons": "3.80.0-next.
|
|
137
|
-
"@elliemae/ds-menu-items-multi": "3.80.0-next.
|
|
138
|
-
"@elliemae/ds-menu-items-section": "3.80.0-next.
|
|
139
|
-
"@elliemae/ds-menu-items-separator": "3.80.0-next.
|
|
140
|
-
"@elliemae/ds-menu-items-single": "3.80.0-next.
|
|
141
|
-
"@elliemae/ds-menu-items-single-with-submenu": "3.80.0-next.
|
|
142
|
-
"@elliemae/ds-menu-items-skeleton": "3.80.0-next.
|
|
143
|
-
"@elliemae/ds-menu-items-submenu": "3.80.0-next.
|
|
144
|
-
"@elliemae/ds-menu-tree-item": "3.80.0-next.
|
|
145
|
-
"@elliemae/ds-modal-slide": "3.80.0-next.
|
|
146
|
-
"@elliemae/ds-notification-badge": "3.80.0-next.
|
|
147
|
-
"@elliemae/ds-overlay": "3.80.0-next.
|
|
148
|
-
"@elliemae/ds-page-header": "3.80.0-next.
|
|
149
|
-
"@elliemae/ds-page-header-v1": "3.80.0-next.
|
|
150
|
-
"@elliemae/ds-page-header-v2": "3.80.0-next.
|
|
151
|
-
"@elliemae/ds-page-layout": "3.80.0-next.
|
|
152
|
-
"@elliemae/ds-pagination": "3.80.0-next.
|
|
153
|
-
"@elliemae/ds-panel-header": "3.80.0-next.
|
|
154
|
-
"@elliemae/ds-pills-v2": "3.80.0-next.
|
|
155
|
-
"@elliemae/ds-portal": "3.80.0-next.
|
|
156
|
-
"@elliemae/ds-progress-indicator": "3.80.0-next.
|
|
157
|
-
"@elliemae/ds-props-helpers": "3.80.0-next.
|
|
158
|
-
"@elliemae/ds-query-builder": "3.80.0-next.
|
|
159
|
-
"@elliemae/ds-read-more": "3.80.0-next.
|
|
160
|
-
"@elliemae/ds-resizeable-container": "3.80.0-next.
|
|
161
|
-
"@elliemae/ds-ribbon": "3.80.0-next.
|
|
162
|
-
"@elliemae/ds-scrollable-container": "3.80.0-next.
|
|
163
|
-
"@elliemae/ds-separator": "3.80.0-next.
|
|
164
|
-
"@elliemae/ds-shared": "3.80.0-next.
|
|
165
|
-
"@elliemae/ds-shuttle-v2": "3.80.0-next.
|
|
166
|
-
"@elliemae/ds-side-panel": "3.80.0-next.
|
|
167
|
-
"@elliemae/ds-side-panel-header": "3.80.0-next.
|
|
168
|
-
"@elliemae/ds-skeleton": "3.80.0-next.
|
|
169
|
-
"@elliemae/ds-slider-v2": "3.80.0-next.
|
|
170
|
-
"@elliemae/ds-square-indicator": "3.80.0-next.
|
|
171
|
-
"@elliemae/ds-stepper": "3.80.0-next.
|
|
172
|
-
"@elliemae/ds-svg": "3.80.0-next.
|
|
173
|
-
"@elliemae/ds-system": "3.80.0-next.
|
|
174
|
-
"@elliemae/ds-tabs": "3.80.0-next.
|
|
175
|
-
"@elliemae/ds-test-utils": "3.80.0-next.
|
|
176
|
-
"@elliemae/ds-toast": "3.80.0-next.
|
|
177
|
-
"@elliemae/ds-toolbar-v1": "3.80.0-next.
|
|
178
|
-
"@elliemae/ds-toolbar-v2": "3.80.0-next.
|
|
179
|
-
"@elliemae/ds-tooltip-v3": "3.80.0-next.
|
|
180
|
-
"@elliemae/ds-transition": "3.80.0-next.
|
|
181
|
-
"@elliemae/ds-tree-model": "3.80.0-next.
|
|
182
|
-
"@elliemae/ds-treeview": "3.80.0-next.
|
|
183
|
-
"@elliemae/ds-truncated-expandable-text": "3.80.0-next.
|
|
184
|
-
"@elliemae/ds-typescript-helpers": "3.80.0-next.
|
|
185
|
-
"@elliemae/ds-typography": "3.80.0-next.
|
|
186
|
-
"@elliemae/ds-virtual-list": "3.80.0-next.
|
|
187
|
-
"@elliemae/ds-wizard": "3.80.0-next.
|
|
188
|
-
"@elliemae/ds-zustand-helpers": "3.80.0-next.
|
|
132
|
+
"@elliemae/ds-loading-indicator": "3.80.0-next.39",
|
|
133
|
+
"@elliemae/ds-menu-button": "3.80.0-next.39",
|
|
134
|
+
"@elliemae/ds-menu-items": "3.80.0-next.39",
|
|
135
|
+
"@elliemae/ds-menu-items-action": "3.80.0-next.39",
|
|
136
|
+
"@elliemae/ds-menu-items-commons": "3.80.0-next.39",
|
|
137
|
+
"@elliemae/ds-menu-items-multi": "3.80.0-next.39",
|
|
138
|
+
"@elliemae/ds-menu-items-section": "3.80.0-next.39",
|
|
139
|
+
"@elliemae/ds-menu-items-separator": "3.80.0-next.39",
|
|
140
|
+
"@elliemae/ds-menu-items-single": "3.80.0-next.39",
|
|
141
|
+
"@elliemae/ds-menu-items-single-with-submenu": "3.80.0-next.39",
|
|
142
|
+
"@elliemae/ds-menu-items-skeleton": "3.80.0-next.39",
|
|
143
|
+
"@elliemae/ds-menu-items-submenu": "3.80.0-next.39",
|
|
144
|
+
"@elliemae/ds-menu-tree-item": "3.80.0-next.39",
|
|
145
|
+
"@elliemae/ds-modal-slide": "3.80.0-next.39",
|
|
146
|
+
"@elliemae/ds-notification-badge": "3.80.0-next.39",
|
|
147
|
+
"@elliemae/ds-overlay": "3.80.0-next.39",
|
|
148
|
+
"@elliemae/ds-page-header": "3.80.0-next.39",
|
|
149
|
+
"@elliemae/ds-page-header-v1": "3.80.0-next.39",
|
|
150
|
+
"@elliemae/ds-page-header-v2": "3.80.0-next.39",
|
|
151
|
+
"@elliemae/ds-page-layout": "3.80.0-next.39",
|
|
152
|
+
"@elliemae/ds-pagination": "3.80.0-next.39",
|
|
153
|
+
"@elliemae/ds-panel-header": "3.80.0-next.39",
|
|
154
|
+
"@elliemae/ds-pills-v2": "3.80.0-next.39",
|
|
155
|
+
"@elliemae/ds-portal": "3.80.0-next.39",
|
|
156
|
+
"@elliemae/ds-progress-indicator": "3.80.0-next.39",
|
|
157
|
+
"@elliemae/ds-props-helpers": "3.80.0-next.39",
|
|
158
|
+
"@elliemae/ds-query-builder": "3.80.0-next.39",
|
|
159
|
+
"@elliemae/ds-read-more": "3.80.0-next.39",
|
|
160
|
+
"@elliemae/ds-resizeable-container": "3.80.0-next.39",
|
|
161
|
+
"@elliemae/ds-ribbon": "3.80.0-next.39",
|
|
162
|
+
"@elliemae/ds-scrollable-container": "3.80.0-next.39",
|
|
163
|
+
"@elliemae/ds-separator": "3.80.0-next.39",
|
|
164
|
+
"@elliemae/ds-shared": "3.80.0-next.39",
|
|
165
|
+
"@elliemae/ds-shuttle-v2": "3.80.0-next.39",
|
|
166
|
+
"@elliemae/ds-side-panel": "3.80.0-next.39",
|
|
167
|
+
"@elliemae/ds-side-panel-header": "3.80.0-next.39",
|
|
168
|
+
"@elliemae/ds-skeleton": "3.80.0-next.39",
|
|
169
|
+
"@elliemae/ds-slider-v2": "3.80.0-next.39",
|
|
170
|
+
"@elliemae/ds-square-indicator": "3.80.0-next.39",
|
|
171
|
+
"@elliemae/ds-stepper": "3.80.0-next.39",
|
|
172
|
+
"@elliemae/ds-svg": "3.80.0-next.39",
|
|
173
|
+
"@elliemae/ds-system": "3.80.0-next.39",
|
|
174
|
+
"@elliemae/ds-tabs": "3.80.0-next.39",
|
|
175
|
+
"@elliemae/ds-test-utils": "3.80.0-next.39",
|
|
176
|
+
"@elliemae/ds-toast": "3.80.0-next.39",
|
|
177
|
+
"@elliemae/ds-toolbar-v1": "3.80.0-next.39",
|
|
178
|
+
"@elliemae/ds-toolbar-v2": "3.80.0-next.39",
|
|
179
|
+
"@elliemae/ds-tooltip-v3": "3.80.0-next.39",
|
|
180
|
+
"@elliemae/ds-transition": "3.80.0-next.39",
|
|
181
|
+
"@elliemae/ds-tree-model": "3.80.0-next.39",
|
|
182
|
+
"@elliemae/ds-treeview": "3.80.0-next.39",
|
|
183
|
+
"@elliemae/ds-truncated-expandable-text": "3.80.0-next.39",
|
|
184
|
+
"@elliemae/ds-typescript-helpers": "3.80.0-next.39",
|
|
185
|
+
"@elliemae/ds-typography": "3.80.0-next.39",
|
|
186
|
+
"@elliemae/ds-virtual-list": "3.80.0-next.39",
|
|
187
|
+
"@elliemae/ds-wizard": "3.80.0-next.39",
|
|
188
|
+
"@elliemae/ds-zustand-helpers": "3.80.0-next.39"
|
|
189
189
|
},
|
|
190
190
|
"publishConfig": {
|
|
191
191
|
"access": "public"
|