dimsum-e2e-tests 3.80.0-next.4 → 3.80.0-next.41
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 +168 -0
- package/DSStorybook/baseline.js +0 -186
- package/ds-accordion/DSAccordion.visual.spec.js +0 -14
- package/ds-accordion/DSAccordionCO.js +0 -2
- package/ds-apppicker/aria-disabled/DSAppPicker.aria-disabled.visual.spec.js +14 -1
- package/ds-apppicker/basic/DSAppPicker.basic.visual.spec.js +12 -7
- package/ds-banner/DSBanner.text-resize.visual.spec.js +2 -0
- package/ds-banner/DSBanner.text-wrapping.visual.spec.js +3 -6
- package/ds-banner/DSBanner.visual.spec.js +7 -8
- package/ds-banner/DSBannerCO.js +189 -4
- 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 +13 -0
- package/ds-banner/slots/DSBanner.slots.visual.spec.js +3 -2
- package/ds-banner/title-element/DSBanner.title-element.func.spec.js +29 -0
- package/ds-chip/DSChip.axe-core.func.spec.js +0 -17
- package/ds-chip/DSChip.visual.spec.js +0 -22
- package/ds-chip/DSChipCO.js +0 -6
- package/ds-fast-list/DSFastListCO.js +37 -0
- package/ds-fast-list/basic/DSFastList.basic.axe-core.func.spec.js +28 -0
- package/ds-fast-list/basic/DSFastList.basic.visual.spec.js +23 -0
- package/ds-fast-list/scroll-to-index/DSFastList.scroll-to-index.func.spec.js +45 -0
- package/ds-indeterminate-progress-indicator/DSIndeterminateProgressIndicatorCO.js +4 -0
- package/ds-indeterminate-progress-indicator/accessible-name/DSIndeterminateProgressIndicator.accessible-name.func.spec.js +51 -0
- package/ds-leftnavigation/LeftNavigation.fullFeatures.axe-core.func.spec.js +37 -0
- package/ds-leftnavigation/LeftNavigation.isSkeleton.axe-core.func.spec.js +23 -0
- package/ds-leftnavigation/LeftNavigation.keepingItems.axe-core.func.spec.js +34 -0
- package/ds-leftnavigation/LeftNavigation.loadingIndicator.axe-core.func.spec.js +41 -0
- package/ds-leftnavigation/LeftNavigation.notificationBadge.axe-core.func.spec.js +21 -0
- package/ds-leftnavigation/LeftNavigation.searchBar.axe-core.func.spec.js +26 -0
- package/ds-leftnavigation/LeftNavigation.showCase.axe-core.func.spec.js +23 -0
- package/ds-leftnavigation/LeftNavigation.tooltip.axe-core.func.spec.js +28 -0
- package/ds-leftnavigation/LeftNavigation.wrappedText.axe-core.func.spec.js +27 -0
- package/ds-menu-button/DSMenuButtonCO.js +18 -0
- package/ds-menu-button/activable/DSMenuButton.activableMenuItem.keyboardnav.func.spec.js +10 -8
- package/ds-menu-button/submenu/DSMenuButton.subMenuItem.keyboardnav.func.spec.js +33 -10
- package/ds-modal-slide/inside-dialog/ModalSlide.insideDialog.func.spec.js +45 -0
- package/ds-panel-header/DSPanelHeader.func.spec.js +24 -0
- package/ds-panel-header/DSPanelHeaderCO.js +17 -0
- package/ds-pills-v2/DSPillsV2CO.js +53 -1
- package/ds-pills-v2/pitfalls/DSPills.inputPill.func.spec.js +26 -0
- package/ds-pills-v2/pitfalls/DSPills.inputWithFormItemBlockURL.axe-core.func.spec.js +38 -0
- package/ds-pills-v2/pitfalls/DSPills.inputWithFormItemBlockURL.func.spec.js +72 -0
- package/ds-progress-indicator/DSProgressIndicator.axe-core.func.spec.js +8 -5
- package/ds-progress-indicator/DSProgressIndicator.func.spec.js +31 -4
- package/ds-progress-indicator/DSProgressIndicator.visual.spec.js +14 -6
- package/ds-progress-indicator/DSProgressIndicatorCO.js +87 -9
- package/ds-progress-indicator/aria-contract/DSProgressIndicator.aria-contract.func.spec.js +104 -0
- package/ds-progress-indicator/slots/DSProgressIndicator.slots.axe-core.func.spec.js +31 -0
- package/ds-progress-indicator/slots/DSProgressIndicator.slots.func.spec.js +87 -0
- package/ds-progress-indicator/slots/DSProgressIndicator.slots.visual.spec.js +27 -0
- package/ds-progress-indicator/variant/DSProgressIndicator.single-bar-variant.func.spec.js +44 -0
- package/ds-progress-indicator/variant/DSProgressIndicator.single-bar-variant.visual.spec.js +19 -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/ds-slider-v2/DSSliderV2.axe-core.func.spec.js +21 -0
- package/ds-slider-v2/DSSliderV2.visual.spec.js +19 -1
- package/ds-slider-v2/DSSliderV2CO.js +6 -1
- package/ds-slider-v2/has-error/DSSliderV2.has-error.visual.spec.js +44 -0
- package/ds-slider-v2/interaction-states/DSSliderV2.interaction-states.visual.spec.js +53 -0
- package/ds-virtuallist/DSVirtualList.visual.spec.js +4 -5
- package/ds-virtuallist/DSVirtualListCO.js +28 -9
- package/ds-virtuallist/basic/DSVirtualList.basic.axe-core.func.spec.js +28 -0
- package/ds-virtuallist/scroll-to-index/DSVirtualList.scroll-to-index.func.spec.js +45 -0
- package/package.json +149 -149
- package/paths.js +3 -49
- package/ds-leftnavigation/LeftNavigation.axe-core.func.spec.js +0 -172
- package/ds-mobile/Accordion/DSAccordion.visual.spec.js +0 -33
- package/ds-mobile/Accordion/DSAccordionCO.js +0 -37
- package/ds-mobile/CategoryBox/CategoryBox.visual.spec.js +0 -18
- package/ds-mobile/CategoryBox/CategoryBoxCO.js +0 -17
- package/ds-mobile/CollectionBox/CollectionBox.visual.spec.js +0 -16
- package/ds-mobile/CollectionBox/CollectionBoxCO.js +0 -15
- package/ds-mobile/GlobalHeader/DSGlobalHeader.visual.spec.js +0 -55
- package/ds-mobile/GlobalHeader/DSGlobalHeaderCO.js +0 -36
- package/ds-mobile/GroupBox/GroupBox.visual.spec.js +0 -15
- package/ds-mobile/GroupBox/GroupBoxCO.js +0 -15
- package/ds-mobile/InfiniteLoader/InfiniteLoader.func.spec.js +0 -90
- package/ds-mobile/InfiniteLoader/InfiniteLoaderCO.js +0 -29
- package/ds-mobile/MobileActionToolbar/MobileActionToolbar.visual.spec.js +0 -39
- package/ds-mobile/MobileActionToolbar/MobileActionToolbarCO.js +0 -19
- package/ds-mobile/MobileBanner/MobileBanner.visual.spec.js +0 -23
- package/ds-mobile/MobileBanner/MobileBannerCO.js +0 -23
- package/ds-mobile/MobileCard/Card.func.spec.js +0 -38
- package/ds-mobile/MobileCard/Card.visual.spec.js +0 -103
- package/ds-mobile/MobileCard/MobileCardCO.js +0 -42
- package/ds-mobile/MobileContextMenu/MobileContextMenu.func.spec.js +0 -88
- package/ds-mobile/MobileContextMenu/MobileContextMenu.visual.spec.js +0 -31
- package/ds-mobile/MobileContextMenu/MobileContextMenuCO.js +0 -72
- package/ds-mobile/MobileDatePicker/MobileDatePicker.func.spec.js +0 -15
- package/ds-mobile/MobileDatePicker/MobileDatePicker.visual.spec.js +0 -15
- package/ds-mobile/MobileDatePicker/MobileDatePickerCO.js +0 -35
- package/ds-mobile/MobileDropdownMenu/MobileDropdownMenu.func.spec.js +0 -38
- package/ds-mobile/MobileDropdownMenu/MobileDropdownMenu.visual.spec.js +0 -16
- package/ds-mobile/MobileDropdownMenu/MobileDropdownMenuCO.js +0 -37
- package/ds-mobile/MobileEmptyState/MobileEmptyState.visual.spec.js +0 -15
- package/ds-mobile/MobileEmptyState/MobileEmptyStateCO.js +0 -14
- package/ds-mobile/MobileFilterbar/MobileFilterbar.visual.spec.js +0 -39
- package/ds-mobile/MobileFilterbar/MobileFilterbarCO.js +0 -19
- package/ds-mobile/MobileFooter/MobileFooter.func.spec.js +0 -26
- package/ds-mobile/MobileFooter/MobileFooter.visual.spec.js +0 -51
- package/ds-mobile/MobileFooter/MobileFooterCO.js +0 -27
- package/ds-mobile/MobileListItem/MobileListItem.visual.spec.js +0 -56
- package/ds-mobile/MobileListItem/MobileListItemCO.js +0 -19
- package/ds-mobile/MobileLoadingPage/MobileLoadingPage.visual.spec.js +0 -37
- package/ds-mobile/MobileLoadingPage/MobileLoadingPageCO.js +0 -23
- package/ds-mobile/MobilePageHeader/MobilePageHeader.func.spec.js +0 -22
- package/ds-mobile/MobilePageHeader/MobilePageHeader.visual.spec.js +0 -135
- package/ds-mobile/MobilePageHeader/MobilePageHeaderCO.js +0 -67
- package/ds-mobile/MobileSelectList/MobileSelectList.visual.spec.js +0 -56
- package/ds-mobile/MobileSelectList/MobileSelectListCO.js +0 -21
- package/ds-mobile/MobileSeparator/MobileSeparator.visual.spec.js +0 -28
- package/ds-mobile/MobileSeparator/MobileSeparatorCO.js +0 -17
- package/ds-mobile/MobileTimePicker/MobileTimePickerCO.js +0 -41
- package/ds-mobile/Modal/MobileModal.visual.spec.js +0 -56
- package/ds-mobile/Modal/MobileModalCO.js +0 -28
- package/ds-mobile/PageFilter/PageFilter.visual.spec.js +0 -46
- package/ds-mobile/PageFilter/PageFilterCO.js +0 -19
- package/ds-mobile/PageForm/PageForm.visual.spec.js +0 -14
- package/ds-mobile/PageForm/PageFormCO.js +0 -11
- package/ds-mobile/PageList/PageList.visual.spec.js +0 -31
- package/ds-mobile/PageList/PageListCO.js +0 -19
- package/ds-mobile/PageSummary/PageSummary.visual.spec.js +0 -20
- package/ds-mobile/PageSummary/PageSummaryCO.js +0 -11
- package/ds-mobile/SwipeToRefresh/SwipeToRefresh.func.spec.js +0 -26
- package/ds-mobile/SwipeToRefresh/SwipeToRefreshCO.js +0 -20
- package/ds-mobile/Tabs/MobileTabs.visual.spec.js +0 -91
- package/ds-mobile/Tabs/TabsCO.js +0 -37
- package/ds-mobile/Tooltip/MobileTooltip.func.spec.js +0 -17
- package/ds-mobile/Tooltip/MobileTooltip.visual.spec.js +0 -16
- package/ds-mobile/Tooltip/TooltipCO.js +0 -23
- package/ds-mobile/helpers.js +0 -7
|
@@ -87,6 +87,24 @@ export default class DSMenuButtonCO extends PageObject {
|
|
|
87
87
|
return $(`${item} div span`);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Press `key` until `element` holds focus, stopping at `maxPresses`. Menus and submenus mount,
|
|
92
|
+
* position themselves and then take focus, so a fixed number of presses depends on none of them
|
|
93
|
+
* being swallowed — which made the same browsers pass and fail these specs on consecutive runs.
|
|
94
|
+
*
|
|
95
|
+
* This only drives the keyboard and asserts nothing: it presses up to `maxPresses` times and
|
|
96
|
+
* returns whether or not the target was reached. Always follow it with `toBeFocused()` on the same
|
|
97
|
+
* element, otherwise a walk that lands on the wrong item passes silently.
|
|
98
|
+
*/
|
|
99
|
+
static async keyUntilFocused(key, element, maxPresses = 6) {
|
|
100
|
+
for (let i = 0; i < maxPresses; i += 1) {
|
|
101
|
+
// eslint-disable-next-line no-await-in-loop
|
|
102
|
+
if (await element.isFocused()) return;
|
|
103
|
+
// eslint-disable-next-line no-await-in-loop
|
|
104
|
+
await browser.keys(key);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
90
108
|
// Slots test selectors (by data-dimsum-slot)
|
|
91
109
|
static async getSlotsOpinionatedButtonRoot() {
|
|
92
110
|
return $('[data-dimsum-parent-slot="dsOpinionatedbuttonRoot"');
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable max-statements */
|
|
2
1
|
import { Key } from 'webdriverio';
|
|
3
2
|
import DSMenuButtonCO from '../DSMenuButtonCO';
|
|
4
3
|
import DSDialog from '../../ds-dialog/DSDialogCO';
|
|
@@ -12,10 +11,11 @@ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:o
|
|
|
12
11
|
});
|
|
13
12
|
it('01: should trigger first menuItem with KEYBOARD (Return) and have a dialog', async () => {
|
|
14
13
|
await browser.keys(Key.Tab);
|
|
15
|
-
await browser.keys(Key.Return);
|
|
16
|
-
await
|
|
17
|
-
await
|
|
18
|
-
|
|
14
|
+
await browser.keys(Key.Return); // opens the menu and focuses the first item
|
|
15
|
+
const firstItem = await DSMenuButtonCO.getMenuItemWrapperByLabel('Action 1');
|
|
16
|
+
await firstItem.waitForDisplayed();
|
|
17
|
+
// No arrow walk here: opening the menu focuses the first item, so this is already the target.
|
|
18
|
+
await expect(firstItem).toBeFocused();
|
|
19
19
|
await browser.keys(Key.Return);
|
|
20
20
|
const triggeredDialog = await DSDialog.getDialog();
|
|
21
21
|
const menu = await DSMenuButtonCO.getMenuRoot();
|
|
@@ -24,9 +24,11 @@ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:o
|
|
|
24
24
|
});
|
|
25
25
|
it('02: should trigger third menuItem with KEYBOARD (Space) and have a card', async () => {
|
|
26
26
|
await browser.keys(Key.Escape);
|
|
27
|
-
await browser.keys(Key.Return);
|
|
28
|
-
await
|
|
29
|
-
await
|
|
27
|
+
await browser.keys(Key.Return); // reopens the menu and focuses the first item
|
|
28
|
+
const thirdItem = await DSMenuButtonCO.getMenuItemWrapperByLabel('Action 3');
|
|
29
|
+
await thirdItem.waitForDisplayed();
|
|
30
|
+
await DSMenuButtonCO.keyUntilFocused(Key.ArrowDown, thirdItem);
|
|
31
|
+
await expect(thirdItem).toBeFocused();
|
|
30
32
|
await browser.keys(Key.Space); // Action menu items will get closed menu also with Space
|
|
31
33
|
const menu = await DSMenuButtonCO.getMenuRoot();
|
|
32
34
|
const triggeredCards = (await DSCardV3CO.getCards()).length;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable max-statements */
|
|
2
1
|
import { Key } from 'webdriverio';
|
|
3
2
|
import DSMenuButtonCO from '../DSMenuButtonCO';
|
|
4
3
|
import DSButtonV3CO from '../../ds-button-v3/DSButtonV3CO';
|
|
@@ -30,9 +29,15 @@ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:o
|
|
|
30
29
|
await expect(subMenuItem3).toBeDisplayed();
|
|
31
30
|
});
|
|
32
31
|
it('03: should drilldown a submenu and submenu action with KB', async () => {
|
|
33
|
-
await browser.keys(Key.ArrowRight);
|
|
34
|
-
await
|
|
35
|
-
await
|
|
32
|
+
await browser.keys(Key.ArrowRight); // opens Submenu 3 and moves focus into it
|
|
33
|
+
const subMenuItem31 = await DSMenuButtonCO.getMenuItemOptByIndex('3.1');
|
|
34
|
+
await subMenuItem31.waitForDisplayed();
|
|
35
|
+
// Same reason as the dismissal beforeEach: the submenu being open is not enough, focus has to
|
|
36
|
+
// be inside it or the arrows below walk the outer list where 3.3 does not exist.
|
|
37
|
+
await expect(subMenuItem31).toBeFocused();
|
|
38
|
+
const subMenuItem33 = await DSMenuButtonCO.getMenuItemOptByIndex('3.3');
|
|
39
|
+
await DSMenuButtonCO.keyUntilFocused(Key.ArrowDown, subMenuItem33);
|
|
40
|
+
await expect(subMenuItem33).toBeFocused();
|
|
36
41
|
await browser.keys(Key.Return);
|
|
37
42
|
const triggeredCards = await (await DSCardV3CO.getHByLevel(2)).getText();
|
|
38
43
|
await expect(triggeredCards).toEqual('Action 3 > 3');
|
|
@@ -46,18 +51,36 @@ if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:o
|
|
|
46
51
|
const menuTrigger = await DSButtonV3CO.getButtonByLabel('Submenus example');
|
|
47
52
|
await menuTrigger.waitForDisplayed();
|
|
48
53
|
await browser.keys(Key.Tab);
|
|
49
|
-
await browser.keys(Key.Return);
|
|
50
|
-
await
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
await
|
|
54
|
+
await browser.keys(Key.Return); // opens the menu and focuses Opt 1
|
|
55
|
+
const subMenuItem2 = await DSMenuButtonCO.getMenuItemOptByIndex('2');
|
|
56
|
+
// Wait before walking: on an unpainted menu isFocused() reads false and the loop burns its
|
|
57
|
+
// presses on a list that is not there yet.
|
|
58
|
+
await subMenuItem2.waitForDisplayed();
|
|
59
|
+
await DSMenuButtonCO.keyUntilFocused(Key.ArrowDown, subMenuItem2);
|
|
60
|
+
await expect(subMenuItem2).toBeFocused();
|
|
61
|
+
await browser.keys(Key.ArrowRight); // opens Submenu 2 and moves focus into it
|
|
62
|
+
const subMenuItem21 = await DSMenuButtonCO.getMenuItemOptByIndex('2.1');
|
|
63
|
+
await subMenuItem21.waitForDisplayed();
|
|
64
|
+
// Opening the submenu is not enough: focus has to be inside it, otherwise the arrows below
|
|
65
|
+
// walk the outer list and never reach 2.3.
|
|
66
|
+
await expect(subMenuItem21).toBeFocused();
|
|
67
|
+
// We are now at a subMenu with subMenu (Opt 2.3)
|
|
68
|
+
const subMenuItem23 = await DSMenuButtonCO.getMenuItemOptByIndex('2.3');
|
|
69
|
+
await DSMenuButtonCO.keyUntilFocused(Key.ArrowDown, subMenuItem23);
|
|
70
|
+
await expect(subMenuItem23).toBeFocused();
|
|
71
|
+
// Focusing 2.3 opens its own flyout, which is the third one the dismissal tests count. Wait
|
|
72
|
+
// for it: without this they can run against two flyouts, where Escape closes submenu 2 instead
|
|
73
|
+
// and Opt+ESC passes without having closed anything.
|
|
74
|
+
await (await DSMenuButtonCO.getMenuItemOptByIndex('2.3.1')).waitForDisplayed();
|
|
54
75
|
});
|
|
55
76
|
it('01: should close the focused submenu with ESC focus will move one level up', async () => {
|
|
56
77
|
await browser.keys(Key.Escape);
|
|
57
78
|
const subMenuItem23 = await DSMenuButtonCO.getMenuItemOptByIndex('2.3');
|
|
58
79
|
const subMenuItem2 = await DSMenuButtonCO.getMenuItemOptByIndex('2');
|
|
59
|
-
const menus = (await DSMenuButtonCO.getMenuRoots()).length;
|
|
60
80
|
await subMenuItem2.waitForDisplayed();
|
|
81
|
+
// Counted after the wait, as in 02 and 03: toEqual on a plain number does not retry, so a
|
|
82
|
+
// count read before the dismissal settles is just a snapshot of the old state.
|
|
83
|
+
const menus = (await DSMenuButtonCO.getMenuRoots()).length;
|
|
61
84
|
await expect(menus).toEqual(2);
|
|
62
85
|
await expect(subMenuItem2).toBeFocused();
|
|
63
86
|
await expect(subMenuItem23).toBeDisplayed();
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Key } from 'webdriverio';
|
|
2
|
+
import ModalSlideCO from '../ModalSlideCO';
|
|
3
|
+
import DSDialogCO from '../../ds-dialog/DSDialogCO';
|
|
4
|
+
|
|
5
|
+
if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
|
|
6
|
+
describe('PUI-19268 - ModalSlide:: inside Dialog, focus and Escape', () => {
|
|
7
|
+
beforeEach(async () => {
|
|
8
|
+
const errorOnGo = await ModalSlideCO.insideDialogURL.go();
|
|
9
|
+
if (errorOnGo) throw errorOnGo;
|
|
10
|
+
await ModalSlideCO.openDialog();
|
|
11
|
+
await ModalSlideCO.openModalSlide();
|
|
12
|
+
});
|
|
13
|
+
it('01: Cancel should close only the slide and focus the button that opened it', async () => {
|
|
14
|
+
await (await ModalSlideCO.getRejectedBtn()).click();
|
|
15
|
+
await (await ModalSlideCO.getModalSlide()).waitForDisplayed({ reverse: true });
|
|
16
|
+
await expect(await DSDialogCO.getDialog()).toBeDisplayed();
|
|
17
|
+
await expect(await ModalSlideCO.getOpenModalSlideBtn()).toBeFocused();
|
|
18
|
+
});
|
|
19
|
+
it('02: Confirm should close only the slide and focus the button that opened it', async () => {
|
|
20
|
+
await (await ModalSlideCO.getModalButton()).click();
|
|
21
|
+
await (await ModalSlideCO.getModalSlide()).waitForDisplayed({ reverse: true });
|
|
22
|
+
await expect(await DSDialogCO.getDialog()).toBeDisplayed();
|
|
23
|
+
await expect(await ModalSlideCO.getOpenModalSlideBtn()).toBeFocused();
|
|
24
|
+
});
|
|
25
|
+
it('03: Escape should close only the slide and focus the button that opened the slide', async () => {
|
|
26
|
+
// the story moves the focus into the slide 500ms after it opens
|
|
27
|
+
await browser.waitUntil(async () => (await $('[data-testid="back-id"]')).isFocused(), {
|
|
28
|
+
timeoutMsg: 'the focus should move into the slide',
|
|
29
|
+
});
|
|
30
|
+
await browser.keys(Key.Escape);
|
|
31
|
+
await (await ModalSlideCO.getModalSlide()).waitForDisplayed({ reverse: true });
|
|
32
|
+
await expect(await DSDialogCO.getDialog()).toBeDisplayed();
|
|
33
|
+
await expect(await ModalSlideCO.getOpenModalSlideBtn()).toBeFocused();
|
|
34
|
+
});
|
|
35
|
+
it('04: a second Escape, with the slide already closed, should close the dialog', async () => {
|
|
36
|
+
await browser.waitUntil(async () => (await $('[data-testid="back-id"]')).isFocused(), {
|
|
37
|
+
timeoutMsg: 'the focus should move into the slide',
|
|
38
|
+
});
|
|
39
|
+
await browser.keys(Key.Escape);
|
|
40
|
+
await (await ModalSlideCO.getModalSlide()).waitForDisplayed({ reverse: true });
|
|
41
|
+
await browser.keys(Key.Escape);
|
|
42
|
+
await (await DSDialogCO.getDialog()).waitForDisplayed({ reverse: true });
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import DSPanelHeaderCO from './DSPanelHeaderCO';
|
|
2
|
+
/* this is the syntax for only enabling test for desktop only
|
|
3
|
+
if (!browser.capabilities['ice:options'].isPhone && !browser.capabilities['ice:options'].isTablet) {
|
|
4
|
+
describe('PUI-XXXX - PanelHeader:: example test - data-testid exists', () => {
|
|
5
|
+
before('loading page', async () => {
|
|
6
|
+
// your code goes here
|
|
7
|
+
});
|
|
8
|
+
it('01: wrapper should be displayed', async () => {
|
|
9
|
+
// your code goes here
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
*/
|
|
15
|
+
describe('PUI-XXXX - PanelHeader:: example test - data-testid exists', () => {
|
|
16
|
+
before('loading page', async () => {
|
|
17
|
+
const errorOnGo = await DSPanelHeaderCO.basic.go();
|
|
18
|
+
if (errorOnGo) throw errorOnGo;
|
|
19
|
+
});
|
|
20
|
+
it('01: wrapper should be displayed', async () => {
|
|
21
|
+
const wrapper = await DSPanelHeaderCO.getWrapper();
|
|
22
|
+
await expect(wrapper).toBeDisplayedInViewport();
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { PANEL_HEADER_DATA_TESTID } from '@elliemae/ds-panel-header';
|
|
2
|
+
import { PATH_PANEL_HEADER } from '../../environments/storybook/paths';
|
|
3
|
+
import { PageObject, Urlbuilder } from '../helpers';
|
|
4
|
+
|
|
5
|
+
export default class DSPanelHeader extends PageObject {
|
|
6
|
+
static basic = new Urlbuilder(PATH_PANEL_HEADER, 'basic');
|
|
7
|
+
|
|
8
|
+
// Selectors
|
|
9
|
+
static async getWrapper() {
|
|
10
|
+
return $(`[data-testid="${PANEL_HEADER_DATA_TESTID.ROOT}"]`);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Snapshots
|
|
14
|
+
static snapshotPath(example = 'basic') {
|
|
15
|
+
return PageObject.getSnapshotPathBuilder('DSPanelHeader', example, 'ds-panel-header');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -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
|
|
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.
|
|
18
|
-
|
|
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
|
-
|
|
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,41 @@ if (
|
|
|
6
6
|
browser.capabilities.browserName === 'chrome') ||
|
|
7
7
|
browser.capabilities.browserName === 'Chrome'
|
|
8
8
|
) {
|
|
9
|
-
describe('PUI-17522 -
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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%');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// PUI-18942: title and counter text used to be raw text inside plain spans.
|
|
34
|
+
it('02: should render title and counter text through DSTypography', async () => {
|
|
35
|
+
const { TITLE, COUNTER } = DSProgressIndicatorCO.SLOT_TESTID;
|
|
36
|
+
|
|
37
|
+
const titleText = await DSProgressIndicatorCO.getTypographyIn(TITLE);
|
|
38
|
+
await expect(titleText).toBeExisting();
|
|
39
|
+
await expect(titleText).toHaveText('upload');
|
|
40
|
+
|
|
41
|
+
const counterText = await DSProgressIndicatorCO.getTypographyIn(COUNTER);
|
|
42
|
+
await expect(counterText).toBeExisting();
|
|
43
|
+
await expect(counterText).toHaveText('50 of 100');
|
|
17
44
|
});
|
|
18
45
|
});
|
|
19
46
|
}
|
|
@@ -1,24 +1,32 @@
|
|
|
1
1
|
import DSProgressIndicatorCO from './DSProgressIndicatorCO';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
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.
|
|
11
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
});
|