diff --git a/cypress.config.ts b/cypress.config.ts
index 3e70e41de48..c830b6718e3 100644
--- a/cypress.config.ts
+++ b/cypress.config.ts
@@ -12,7 +12,7 @@ export default defineConfig({
bundler: 'vite',
},
experimentalRunAllSpecs: true,
- excludeSpecPattern: ['**/e2e/**', ...(process.env.CI ? ['**/SelectDialog/**'] : [])],
+ excludeSpecPattern: ['**/e2e/**'],
},
includeShadowDom: true,
viewportWidth: 1920,
diff --git a/packages/main/src/components/SelectDialog/SelectDialog.cy.tsx b/packages/main/src/components/SelectDialog/SelectDialog.cy.tsx
deleted file mode 100644
index 9cc3e392946..00000000000
--- a/packages/main/src/components/SelectDialog/SelectDialog.cy.tsx
+++ /dev/null
@@ -1,306 +0,0 @@
-import ButtonDesign from '@ui5/webcomponents/dist/types/ButtonDesign.js';
-import ListSelectionMode from '@ui5/webcomponents/dist/types/ListSelectionMode.js';
-import { useState } from 'react';
-import type { ListPropTypes, SelectDialogPropTypes } from '../..';
-import { Button, SelectDialog, ListItemStandard } from '../..';
-
-const listItems = new Array(5)
- .fill('o_O')
- .map((_, index) => (
-
- ));
-
-describe('SelectDialog', () => {
- it('Basic', () => {
- cy.mount({listItems});
- cy.get('[ui5-dialog]').should('be.visible');
- cy.findByPlaceholderText('Search');
- cy.findByText('Cancel').click();
- cy.get('[ui5-dialog]').should('not.be.visible');
- });
-
- it('with headerText', () => {
- cy.mount(
-
- {listItems}
- ,
- );
- cy.findByText('Select Dialog')
- .should('have.css', 'grid-column-start', 'titleStart')
- .and('have.css', 'grid-column-end', 'titleCenter')
- .and('have.attr', 'level', 'H1');
- cy.mount(
-
- {listItems}
- ,
- );
- cy.findByText('Select Dialog').should('have.css', 'grid-area', 'titleCenter').and('have.attr', 'level', 'H1');
- cy.mount(
-
- {listItems}
- ,
- );
- cy.findByText('Select Dialog').should('have.attr', 'level', 'H2');
- });
-
- it('selection', () => {
- const close = cy.spy().as('close');
- const change = cy.spy().as('change');
- const confirm = cy.spy().as('confirm');
- const TestComp = ({
- close,
- change,
- confirm,
- rememberSelections,
- mode,
- }: {
- close: SelectDialogPropTypes['onClose'];
- change: ListPropTypes['onSelectionChange'];
- confirm: SelectDialogPropTypes['onConfirm'];
- rememberSelections?: SelectDialogPropTypes['rememberSelections'];
- mode?: SelectDialogPropTypes['selectionMode'];
- }) => {
- const [open, setOpen] = useState(true);
- const [items, setItems] = useState(undefined);
- return (
- <>
-
- {
- setItems(e.detail.selectedItems.map((item) => item.text));
- confirm(e);
- }}
- onClose={(e) => {
- setOpen(false);
- close(e);
- }}
- listProps={{ onSelectionChange: change }}
- >
- {listItems}
-
- Last Selected Item: {items}
- >
- );
- };
- cy.mount();
- cy.get('[ui5-dialog]').should('be.visible');
- cy.clickUi5ListItemByText('Product1');
- cy.get('[ui5-dialog]').should('not.be.visible');
- cy.findByText('Last Selected Item: Product1').should('be.visible');
- cy.findByText('Open').click();
- cy.get('[ui5-li]').each(($li) => {
- cy.wrap($li).should('not.have.attr', 'selected');
- });
-
- cy.mount();
- cy.get('[ui5-dialog]').should('be.visible');
- cy.clickUi5ListItemByText('Product1');
- cy.get('[ui5-dialog]').should('not.be.visible');
- cy.findByText('Last Selected Item: Product1').should('be.visible');
- cy.findByText('Open').click();
- cy.get('[ui5-li]').each(($li) => {
- if ($li.attr('text') === 'Product1') {
- cy.wrap($li).should('have.attr', 'selected');
- } else {
- cy.wrap($li).should('not.have.attr', 'selected');
- }
- });
-
- cy.get('@close').should('have.callCount', 2);
- cy.get('@confirm').should('have.callCount', 2);
- cy.get('@change').should('have.callCount', 2);
-
- cy.mount();
- cy.findByText('Cancel').click();
- cy.findByText('Open').click();
- cy.closeUi5PopupWithEsc();
-
- cy.get('@close').should('have.callCount', 4);
- cy.get('@confirm').should('have.callCount', 2);
- cy.get('@change').should('have.callCount', 2);
-
- cy.mount();
- cy.clickUi5ListItemByText('Product1');
- cy.clickUi5ListItemByText('Product3');
- cy.get('[ui5-dialog]').should('be.visible');
- cy.findByText('Select').click();
- cy.findByText('Last Selected Item: Product1Product3').should('be.visible');
-
- cy.findByText('Open').click();
- cy.get('[ui5-li]').each(($li) => {
- cy.wrap($li).should('not.have.attr', 'selected');
- });
-
- cy.mount(
- ,
- );
- cy.clickUi5ListItemByText('Product1');
- cy.clickUi5ListItemByText('Product3');
- cy.get('[ui5-dialog]').should('be.visible');
- cy.findByText('Select').click();
- cy.findByText('Last Selected Item: Product1Product3').should('be.visible');
- cy.get('[ui5-li]').each(($li) => {
- if ($li.attr('text') === 'Product1' || $li.attr('text') === 'Product3') {
- cy.wrap($li).should('have.attr', 'selected');
- } else {
- cy.wrap($li).should('not.have.attr', 'selected');
- }
- });
-
- cy.get('@close').should('have.callCount', 6);
- cy.get('@confirm').should('have.callCount', 4);
- cy.get('@change').should('have.callCount', 6);
- });
-
- it('Search', () => {
- const search = cy.spy().as('search');
- const input = cy.spy().as('input');
- const reset = cy.spy().as('reset');
- const TestComp = ({
- search,
- input,
- reset,
- }: {
- search: SelectDialogPropTypes['onSearch'];
- input: SelectDialogPropTypes['onSearchInput'];
- reset: SelectDialogPropTypes['onSearchReset'];
- }) => {
- const [inputVal, setInputVal] = useState('');
- const [searchVal, setSearchVal] = useState('');
- return (
- <>
- {
- setSearchVal(e.detail.value);
- search(e);
- }}
- onSearchInput={(e) => {
- setInputVal(e.detail.value);
- input(e);
- }}
- onSearchReset={reset}
- open
- >
- {listItems}
-
-
- input: {inputVal}
-
- search: {searchVal}
- >
- );
- };
- cy.mount();
- cy.get('[accessible-name="Reset"][ui5-icon]').should('not.exist');
- cy.get('[ui5-input]').typeIntoUi5Input('Test');
- cy.findByTestId('inputVal').should('have.text', 'input: Test');
- cy.get('@search').should('have.callCount', 0);
- cy.get('@input').should('have.callCount', 4);
- cy.get('@reset').should('have.callCount', 0);
- cy.get('[ui5-input]').typeIntoUi5Input('{enter}');
- cy.findByTestId('searchVal').should('have.text', 'search: Test');
- cy.get('@search').should('have.callCount', 1);
- cy.get('@input').should('have.callCount', 4);
- cy.get('@reset').should('have.callCount', 0);
- cy.get('[accessible-name="Search"][ui5-icon]').click();
- cy.get('@search').should('have.callCount', 2);
- cy.get('@input').should('have.callCount', 4);
- cy.get('@reset').should('have.callCount', 0);
- cy.get('[part="clear-icon"][ui5-icon]').click();
- cy.get('@search').should('have.callCount', 2);
- // clearing the input via clear button fires input event as well
- cy.get('@input').should('have.callCount', 5);
- cy.get('@reset').should('have.callCount', 1);
- cy.get('[accessible-name="Reset"][ui5-icon]').should('not.exist');
- });
-
- it('confirmButtonText', () => {
- const confirm = cy.spy().as('confirm');
- cy.mount(
- ,
- );
- cy.get('[ui5-dialog]').should('be.visible');
- cy.findByText('Exterminate').click();
- cy.get('@confirm').should('have.been.calledOnce');
- cy.get('[ui5-dialog]').should('not.be.visible');
- });
-
- it('numberOfSelectedItems', () => {
- cy.mount();
- cy.findByText('Selected: 1337').should('be.visible');
- });
-
- it('onCancel', () => {
- const cancel = cy.spy().as('cancel');
- const TestComp = ({
- cancel,
- mode,
- }: {
- cancel: SelectDialogPropTypes['onCancel'];
- mode: SelectDialogPropTypes['selectionMode'];
- }) => {
- const [open, setOpen] = useState(false);
- return (
- <>
-
- {
- setOpen(false);
- }}
- selectionMode={mode}
- >
- {listItems}
-
- >
- );
- };
- let callCount = 1;
- [ListSelectionMode.Single, ListSelectionMode.Multiple].forEach((mode) => {
- cy.mount();
- cy.findByText('Open').click();
- cy.findByText('Cancel').click();
- cy.get('@cancel').should('have.callCount', callCount);
- callCount++;
-
- cy.findByText('Open').click();
- cy.realPress('Escape');
- cy.get('@cancel').should('have.callCount', callCount);
- callCount++;
- });
- });
-
- it('confirmButtonProps', () => {
- cy.mount(
- ,
- );
- cy.findByTestId('confirmBtn').should('be.visible').and('have.attr', 'disabled');
- cy.findByTestId('confirmBtn').should('have.attr', 'design', 'Emphasized');
- });
-});
diff --git a/packages/main/src/components/SelectDialog/SelectDialog.stories.tsx b/packages/main/src/components/SelectDialog/SelectDialog.stories.tsx
index 0879b7570d3..6a08e2bd927 100644
--- a/packages/main/src/components/SelectDialog/SelectDialog.stories.tsx
+++ b/packages/main/src/components/SelectDialog/SelectDialog.stories.tsx
@@ -16,7 +16,11 @@ import { SelectDialog } from './index.js';
const meta = {
title: 'Modals & Popovers / SelectDialog',
component: SelectDialog,
- argTypes: { children: { control: { disable: true } } },
+ argTypes: {
+ children: { control: { disable: true } },
+ onSearch: { control: { disable: true } },
+ onCancel: { control: { disable: true } },
+ },
args: { headerText: 'Select Product', open: isChromatic },
parameters: {
chromatic: { delay: 1000 },
diff --git a/packages/main/src/components/SelectDialog/index.tsx b/packages/main/src/components/SelectDialog/index.tsx
index aa779f16e10..833d0badbd8 100644
--- a/packages/main/src/components/SelectDialog/index.tsx
+++ b/packages/main/src/components/SelectDialog/index.tsx
@@ -118,6 +118,13 @@ export interface SelectDialogPropTypes
* @since 1.25.0
*/
confirmButtonProps?: Omit;
+ /**
+ *
+ * Allows overriding the SearchField's default placeholder text. If not set, the word "Search" in the current local language or English will be used as a placeholder.
+ *
+ * __Note:__ The placeholder is used as accessible-name of the input for screen reader support.
+ */
+ searchPlaceholder?: string;
/**
* This event will be fired when the value of the search field is changed by a user - e.g. at each key press
*/
@@ -169,6 +176,7 @@ const SelectDialog = forwardRef((props, ref
selectionMode = ListSelectionMode.Single,
numberOfSelectedItems,
rememberSelections,
+ searchPlaceholder,
showClearButton,
onClose,
onClear,
@@ -341,9 +349,9 @@ const SelectDialog = forwardRef((props, ref
)}
{
await expect(page.locator('[accessible-name="Reset"][ui5-icon]')).not.toBeVisible();
const input = page.locator('[ui5-input]');
+ await expect(input).toHaveAttribute('placeholder', 'Search');
+ await expect(input).toHaveAttribute('accessible-name', 'Search');
await ui5wc.typeIntoInput(input, 'Test');
await expect(page.getByTestId('input-val')).toHaveText('input: Test');
await expect(page.getByTestId('search-count')).toHaveText('0');
@@ -152,6 +154,12 @@ test.describe('SelectDialog', () => {
await expect(page.getByTestId('input-count')).toHaveText('2');
await expect(page.getByTestId('reset-count')).toHaveText('1');
await expect(page.locator('[accessible-name="Reset"][ui5-icon]')).not.toBeVisible();
+
+ await ui5wc.closePopupWithEsc();
+ await page.getByTestId('set-placeholder').click();
+ await page.getByTestId('open-btn').click();
+ await expect(input).toHaveAttribute('placeholder', 'Hello');
+ await expect(input).toHaveAttribute('accessible-name', 'Hello');
});
test('confirmButtonText', async ({ mount, page }) => {
diff --git a/packages/main/src/components/SelectDialog/test/SelectDialogTestComponents.tsx b/packages/main/src/components/SelectDialog/test/SelectDialogTestComponents.tsx
index 3aa2b5c20e1..8a4fb279794 100644
--- a/packages/main/src/components/SelectDialog/test/SelectDialogTestComponents.tsx
+++ b/packages/main/src/components/SelectDialog/test/SelectDialogTestComponents.tsx
@@ -109,15 +109,24 @@ export const SelectDialogSelectionWithToggleTestComp = () => {
// Tracks search/input/reset values and counts via DOM
export const SelectDialogSearchTestComp = () => {
+ const [open, setOpen] = useState(true);
const [inputVal, setInputVal] = useState('');
const [searchVal, setSearchVal] = useState('');
const [searchCount, setSearchCount] = useState(0);
const [inputCount, setInputCount] = useState(0);
const [resetCount, setResetCount] = useState(0);
+ const [searchPlaceholder, setSearchPlaceholder] = useState(undefined);
return (
<>
+
+
{
setSearchVal(e.detail.value);
setSearchCount((c) => c + 1);
@@ -127,7 +136,8 @@ export const SelectDialogSearchTestComp = () => {
setInputCount((c) => c + 1);
}}
onSearchReset={() => setResetCount((c) => c + 1)}
- open
+ onClose={() => setOpen(false)}
+ open={open}
>
{listItems}