diff --git a/packages/react-core/src/components/DataList/DataList.tsx b/packages/react-core/src/components/DataList/DataList.tsx index 5b2a82a738c..817fb1c6875 100644 --- a/packages/react-core/src/components/DataList/DataList.tsx +++ b/packages/react-core/src/components/DataList/DataList.tsx @@ -73,6 +73,7 @@ class DataList extends React.Component { const { className, children, + 'aria-label': ariaLabel, onSelectDataListItem, selectedDataListItemId, isCompact, @@ -106,6 +107,7 @@ class DataList extends React.Component { )} style={props.style} role="list" + aria-label={ariaLabel} {...props} ref={this.ref} > diff --git a/packages/react-core/src/components/DataList/DataListAction.tsx b/packages/react-core/src/components/DataList/DataListAction.tsx index 807bf915691..da79897e544 100644 --- a/packages/react-core/src/components/DataList/DataListAction.tsx +++ b/packages/react-core/src/components/DataList/DataListAction.tsx @@ -31,15 +31,19 @@ export const DataListAction: React.FunctionComponent = ({ children, className, visibility, - /* eslint-disable @typescript-eslint/no-unused-vars */ id, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, isPlainButtonAction, - /* eslint-enable @typescript-eslint/no-unused-vars */ ...props }: DataListActionProps) => ( -
+
{isPlainButtonAction ?
{children}
: children}
); diff --git a/packages/react-core/src/components/DataList/__tests__/DataList.test.tsx b/packages/react-core/src/components/DataList/__tests__/DataList.test.tsx index f2e4a7571a7..ef37e5f9ba6 100644 --- a/packages/react-core/src/components/DataList/__tests__/DataList.test.tsx +++ b/packages/react-core/src/components/DataList/__tests__/DataList.test.tsx @@ -11,15 +11,41 @@ import styles from '@patternfly/react-styles/css/components/DataList/data-list'; test('Renders to match snapshot', () => { const { asFragment } = render(); - expect(screen.getByLabelText('list')).toBeInTheDocument(); expect(asFragment()).toMatchSnapshot(); }); +test(`Renders with default class ${styles.dataList}`, () => { + render(); + expect(screen.getByLabelText('list')).toHaveClass(styles.dataList); +}); + +test(`Renders with custom class when className is passed`, () => { + render(); + expect(screen.getByLabelText('list')).toHaveClass('custom'); +}); + +test(`Renders with spread props`, () => { + render(); + expect(screen.getByLabelText('list')).toHaveAttribute('id', 'test'); +}); + +test(`Renders with aria-label when aria-label is passed`, () => { + render(test); + expect(screen.getByText('test')).toHaveAttribute('aria-label', 'list'); +}); + test(`Renders ${styles.modifiers.compact} when isCompact = true`, () => { render(); expect(screen.getByLabelText('list')).toHaveClass(styles.modifiers.compact); }); +['nowrap', 'truncate', 'breakWord'].forEach((wrap) => { + test(`Renders with class ${styles.modifiers[wrap]} when wrapModifier = ${wrap} is pased`, () => { + render(); + expect(screen.getByLabelText('list')).toHaveClass(styles.modifiers[wrap]); + }); +}); + const gridBreakpointClasses = { none: styles.modifiers.gridNone, always: 'pf-m-grid', @@ -79,7 +105,7 @@ test('Does not render with a hidden input to improve a11y when onSelectableRowCh expect(selectableInput).not.toBeInTheDocument(); }); -test('Calls onSelectableRowChange.onChange when the selectable input changes', async () => { +test('Calls onSelectableRowChange when the selectable input changes', async () => { const mock = jest.fn(); const user = userEvent.setup(); @@ -99,7 +125,7 @@ test('Calls onSelectableRowChange.onChange when the selectable input changes', a expect(mock).toHaveBeenCalled(); }); -test('Does not call onSelectableRowChange.onChange when the selectable input is not changed', () => { +test('Does not call onSelectableRowChange when the selectable input is not changed', () => { const mock = jest.fn(); render( diff --git a/packages/react-core/src/components/DataList/__tests__/DataListAction.test.tsx b/packages/react-core/src/components/DataList/__tests__/DataListAction.test.tsx index 99ffd9f2e10..038ff5d2197 100644 --- a/packages/react-core/src/components/DataList/__tests__/DataListAction.test.tsx +++ b/packages/react-core/src/components/DataList/__tests__/DataListAction.test.tsx @@ -15,11 +15,11 @@ test('Renders to match snapshot', () => { test(`Renders with default class ${styles.dataListItemAction}`, () => { render( - + test ); - expect(screen.getByText('test')).toHaveClass(styles.dataListItemAction); + expect(screen.getByText('test')).toHaveClass(styles.dataListItemAction, { exact: true }); }); test(`Renders with custom class when className is passed`, () => { @@ -31,33 +31,63 @@ test(`Renders with custom class when className is passed`, () => { expect(screen.getByText('test')).toHaveClass('test-class'); }); -test('Renders button with visibliity breakpoint set', () => { +test(`Renders with spread props`, () => { + render( + + test + + ); + expect(screen.getByText('test')).toHaveAttribute('id', 'ex-action'); +}); + +test(`Renders with class ${styles.dataListAction} when isPlainButtonAction = true`, () => { render( - + test ); + expect(screen.getByText('test')).toHaveClass(styles.dataListAction); +}); + +['hidden', 'visible'].forEach((vis) => { + const visMod = vis as 'hidden' | 'visible'; + test(`Has visibility - ${vis} for every breakpoint`, () => { + render( + + test + + ); - expect(screen.getByText('test')).toHaveClass('pf-m-hidden'); - expect(screen.getByText('test')).toHaveClass('pf-m-visible-on-lg'); + if (visMod === 'hidden') { + expect(screen.getByText('test')).toHaveClass(styles.modifiers[`${visMod}`]); + } + expect(screen.getByText('test')).toHaveClass(styles.modifiers[`${visMod}OnSm`]); + expect(screen.getByText('test')).toHaveClass(styles.modifiers[`${visMod}OnMd`]); + expect(screen.getByText('test')).toHaveClass(styles.modifiers[`${visMod}OnLg`]); + expect(screen.getByText('test')).toHaveClass(styles.modifiers[`${visMod}OnXl`]); + expect(screen.getByText('test')).toHaveClass(styles.modifiers[`${visMod}On_2xl`]); + }); }); -test('Does not render button with hidden breakpoint set', () => { +test(`Renders with aria-label when aria-label is passed`, () => { render( - + test ); + expect(screen.getByText('test')).toHaveAccessibleName('Actions'); +}); - expect(screen.getByText('test')).toHaveClass('pf-m-hidden-on-2xl'); +test(`Renders with aria-labelledby when aria-label is passed`, () => { + render( + + test + + ); + expect(screen.getByText('test')).toHaveAttribute('aria-labelledby', 'ex-action'); }); diff --git a/packages/react-core/src/components/DataList/__tests__/DataListCell.test.tsx b/packages/react-core/src/components/DataList/__tests__/DataListCell.test.tsx index e64f3fa816d..6e5954384fa 100644 --- a/packages/react-core/src/components/DataList/__tests__/DataListCell.test.tsx +++ b/packages/react-core/src/components/DataList/__tests__/DataListCell.test.tsx @@ -15,7 +15,7 @@ test(`Renders default class ${styles.dataListCell}`, () => { Primary Id ); - expect(screen.getByTestId('test')).toHaveClass(styles.dataListCell); + expect(screen.getByTestId('test')).toHaveClass(styles.dataListCell, { exact: true }); }); test(`Renders custom class when className is passed`, () => { @@ -27,13 +27,22 @@ test(`Renders custom class when className is passed`, () => { expect(screen.getByTestId('test')).toHaveClass('test-class'); }); +test(`Renders with spread props`, () => { + render( + + Primary Id + + ); + expect(screen.getByText('Primary Id')).toHaveAttribute('id', 'test'); +}); + test('Renders width modifier when width is passed', () => { [ { width: 1, class: '' }, - { width: 2, class: 'pf-m-flex-2' }, - { width: 3, class: 'pf-m-flex-3' }, - { width: 4, class: 'pf-m-flex-4' }, - { width: 5, class: 'pf-m-flex-5' } + { width: 2, class: styles.modifiers.flex_2 }, + { width: 3, class: styles.modifiers.flex_3 }, + { width: 4, class: styles.modifiers.flex_4 }, + { width: 5, class: styles.modifiers.flex_5 } ].forEach((testCase, index) => { const testId = `cell-test-id-${index}`; @@ -46,7 +55,12 @@ test('Renders width modifier when width is passed', () => { const dataListCell = screen.getByTestId(testId); testCase.class === '' - ? expect(dataListCell).toHaveClass('pf-v5-c-data-list__cell', { exact: true }) + ? expect(dataListCell).not.toHaveClass( + styles.modifiers.flex_2, + styles.modifiers.flex_3, + styles.modifiers.flex_4, + styles.modifiers.flex_5 + ) : expect(dataListCell).toHaveClass(`pf-v5-c-data-list__cell ${testCase.class}`, { exact: true }); }); }); @@ -54,9 +68,9 @@ test('Renders width modifier when width is passed', () => { test('Has text wrap modifiers when wrapModifier is passed', () => { [ { wrapModifier: null as any, class: '' }, - { wrapModifier: 'breakWord', class: 'pf-m-break-word' }, - { wrapModifier: 'nowrap', class: 'pf-m-nowrap' }, - { wrapModifier: 'truncate', class: 'pf-m-truncate' } + { wrapModifier: 'breakWord', class: styles.modifiers.breakWord }, + { wrapModifier: 'nowrap', class: styles.modifiers.nowrap }, + { wrapModifier: 'truncate', class: styles.modifiers.truncate } ].forEach((testCase, index) => { const testId = `cell-test-id-${index}`; @@ -69,8 +83,12 @@ test('Has text wrap modifiers when wrapModifier is passed', () => { const dataListCell = screen.getByTestId(testId); testCase.class === '' - ? expect(dataListCell).toHaveClass('pf-v5-c-data-list__cell') - : expect(dataListCell).toHaveClass(`pf-v5-c-data-list__cell ${testCase.class}`); + ? expect(dataListCell).not.toHaveClass( + styles.modifiers.breakWord, + styles.modifiers.nowrap, + styles.modifiers.truncate + ) + : expect(dataListCell).toHaveClass(`${testCase.class}`); }); }); diff --git a/packages/react-core/src/components/DataList/__tests__/DataListCheck.test.tsx b/packages/react-core/src/components/DataList/__tests__/DataListCheck.test.tsx index 9e69ff734e8..fa1424c746f 100644 --- a/packages/react-core/src/components/DataList/__tests__/DataListCheck.test.tsx +++ b/packages/react-core/src/components/DataList/__tests__/DataListCheck.test.tsx @@ -3,6 +3,11 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { DataListCheck } from '../DataListCheck'; +test(`Renders with spread props`, () => { + render(); + expect(screen.getByRole('checkbox')).toHaveAttribute('id', 'test'); +}); + it('does not throw a "A component is changing an uncontrolled input of type checkbox to be controlled" error when changed if using isChecked', async () => { const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); const user = userEvent.setup(); diff --git a/packages/react-core/src/components/DataList/__tests__/DataListContent.test.tsx b/packages/react-core/src/components/DataList/__tests__/DataListContent.test.tsx index 564a03b3a31..912bb48f0de 100644 --- a/packages/react-core/src/components/DataList/__tests__/DataListContent.test.tsx +++ b/packages/react-core/src/components/DataList/__tests__/DataListContent.test.tsx @@ -15,7 +15,16 @@ test(`Renders with default class ${styles.dataListExpandableContent}`, () => { test ); - expect(screen.getByTestId('test-id')).toHaveClass(styles.dataListExpandableContent); + expect(screen.getByTestId('test-id')).toHaveClass(styles.dataListExpandableContent, { exact: true }); +}); + +test(`Renders with default class ${styles.dataListExpandableContentBody}`, () => { + render( + + test + + ); + expect(screen.getByText('test')).toHaveClass(styles.dataListExpandableContentBody, { exact: true }); }); test(`Renders with custom class when className is passed`, () => { @@ -27,6 +36,24 @@ test(`Renders with custom class when className is passed`, () => { expect(screen.getByTestId('test-id')).toHaveClass('test-class'); }); +test(`Renders with id when id is passed`, () => { + render( + + test + + ); + expect(screen.getByTestId('test-id')).toHaveAttribute('id', 'idProp'); +}); + +test(`Renders with spread props`, () => { + render( + + test + + ); + expect(screen.getByTestId('test-id')).toHaveAttribute('dir', 'rtl'); +}); + test(`Renders with class ${styles.modifiers.noPadding} when hasNoPadding is passed`, () => { render(