diff --git a/docs/src/pages/components/icons/icons.md b/docs/src/pages/components/icons/icons.md index e7ee3583d1dc69..fa609498872cbc 100644 --- a/docs/src/pages/components/icons/icons.md +++ b/docs/src/pages/components/icons/icons.md @@ -76,6 +76,20 @@ Each icon also has a "theme": Filled (default), Outlined, Rounded, Two tone and {{"demo": "pages/components/icons/SvgMaterialIcons.js"}} +### Testing + +For testing purposes, each icon exposed from `@material-ui/icons` has a `data-testid` attribute with the name of the icon. For instance: + +```jsx +import DeleteIcon from '@material-ui/icons/Delete'; +``` + +has the following attribute once mounted: + +```html + +``` + ## SvgIcon If you need a custom SVG icon (not available in the Material Icons [default set](/components/material-icons/)) you can use the `SvgIcon` wrapper. diff --git a/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js b/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js index 8addf692fb46c5..8e47b279d5a5d8 100644 --- a/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js +++ b/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js @@ -386,7 +386,7 @@ describe('', () => { it('should remove the last option', () => { const handleChange = spy(); const options = ['one', 'two']; - const { container } = render( + const { getAllByTestId } = render( ', () => { multiple />, ); - fireEvent.click(container.querySelectorAll('svg[data-mui-test="CancelIcon"]')[1]); + fireEvent.click(getAllByTestId('CancelIcon')[1]); expect(handleChange.callCount).to.equal(1); expect(handleChange.args[0][1]).to.deep.equal([options[0]]); }); diff --git a/packages/material-ui-lab/src/Pagination/Pagination.test.js b/packages/material-ui-lab/src/Pagination/Pagination.test.js index c401085a22e012..cf5b014b97f7d7 100644 --- a/packages/material-ui-lab/src/Pagination/Pagination.test.js +++ b/packages/material-ui-lab/src/Pagination/Pagination.test.js @@ -63,15 +63,12 @@ describe('', () => { const buttons = getAllByRole('button'); - expect(buttons[0].querySelector('svg')).to.have.attribute('data-mui-test', 'LastPageIcon'); - expect(buttons[1].querySelector('svg')).to.have.attribute('data-mui-test', 'NavigateNextIcon'); + expect(buttons[0].querySelector('svg')).to.have.attribute('data-testid', 'LastPageIcon'); + expect(buttons[1].querySelector('svg')).to.have.attribute('data-testid', 'NavigateNextIcon'); expect(buttons[2].textContent).to.equal('1'); expect(buttons[6].textContent).to.equal('5'); - expect(buttons[7].querySelector('svg')).to.have.attribute( - 'data-mui-test', - 'NavigateBeforeIcon', - ); - expect(buttons[8].querySelector('svg')).to.have.attribute('data-mui-test', 'FirstPageIcon'); + expect(buttons[7].querySelector('svg')).to.have.attribute('data-testid', 'NavigateBeforeIcon'); + expect(buttons[8].querySelector('svg')).to.have.attribute('data-testid', 'FirstPageIcon'); }); it('renders correct amount of buttons on correct order when boundaryCount is zero', () => { @@ -86,13 +83,10 @@ describe('', () => { ); const buttons = getAllByRole('button'); - expect(buttons[4].querySelector('svg')).to.have.attribute( - 'data-mui-test', - 'NavigateBeforeIcon', - ); + expect(buttons[4].querySelector('svg')).to.have.attribute('data-testid', 'NavigateBeforeIcon'); expect(buttons[1].textContent).to.equal('5'); expect(buttons[2].textContent).to.equal('6'); expect(buttons[3].textContent).to.equal('7'); - expect(buttons[0].querySelector('svg')).to.have.attribute('data-mui-test', 'NavigateNextIcon'); + expect(buttons[0].querySelector('svg')).to.have.attribute('data-testid', 'NavigateNextIcon'); }); }); diff --git a/packages/material-ui-lab/src/SpeedDialIcon/SpeedDialIcon.test.js b/packages/material-ui-lab/src/SpeedDialIcon/SpeedDialIcon.test.js index d69fa04f366110..0e2cb78885d89f 100644 --- a/packages/material-ui-lab/src/SpeedDialIcon/SpeedDialIcon.test.js +++ b/packages/material-ui-lab/src/SpeedDialIcon/SpeedDialIcon.test.js @@ -23,7 +23,7 @@ describe('', () => { it('should render the Add icon by default', () => { const wrapper = mount(); - expect(findOutermostIntrinsic(wrapper).find('svg[data-mui-test="AddIcon"]').length).to.equal(1); + expect(findOutermostIntrinsic(wrapper).find('svg[data-testid="AddIcon"]').length).to.equal(1); }); it('should render an Icon', () => { diff --git a/packages/material-ui/src/Avatar/Avatar.test.js b/packages/material-ui/src/Avatar/Avatar.test.js index 40b4b59126b5dd..6cc04f4b197682 100644 --- a/packages/material-ui/src/Avatar/Avatar.test.js +++ b/packages/material-ui/src/Avatar/Avatar.test.js @@ -127,7 +127,7 @@ describe('', () => { it('should render a div containing an svg icon', () => { expect(avatar.tagName).to.equal('DIV'); const cancelIcon = avatar.firstChild; - expect(cancelIcon).to.have.attribute('data-mui-test', 'CancelIcon'); + expect(cancelIcon).to.have.attribute('data-testid', 'CancelIcon'); }); it('should merge user classes & spread custom props to the root node', () => { diff --git a/packages/material-ui/src/Breadcrumbs/Breadcrumbs.test.js b/packages/material-ui/src/Breadcrumbs/Breadcrumbs.test.js index 273e3a009d0bec..c397f4b9f0b821 100644 --- a/packages/material-ui/src/Breadcrumbs/Breadcrumbs.test.js +++ b/packages/material-ui/src/Breadcrumbs/Breadcrumbs.test.js @@ -62,7 +62,7 @@ describe('', () => { expect(listitems).to.have.length(3); expect(getByRole('list')).to.have.text('first//ninth'); - expect(getByRole('button').querySelector('[data-mui-test="MoreHorizIcon"]')).not.to.equal(null); + expect(getByRole('button').querySelector('[data-testid="MoreHorizIcon"]')).not.to.equal(null); }); it('should expand when `BreadcrumbCollapsed` is clicked', () => { diff --git a/packages/material-ui/src/Checkbox/Checkbox.test.js b/packages/material-ui/src/Checkbox/Checkbox.test.js index b605a3805db2d8..e6cb29dcf7918e 100644 --- a/packages/material-ui/src/Checkbox/Checkbox.test.js +++ b/packages/material-ui/src/Checkbox/Checkbox.test.js @@ -64,10 +64,8 @@ describe('', () => { describe('prop: indeterminate', () => { it('should render an indeterminate icon', () => { - const { container } = render(); - expect( - container.querySelector('svg[data-mui-test="IndeterminateCheckBoxIcon"]'), - ).not.to.equal(null); + const { getByTestId } = render(); + expect(getByTestId('IndeterminateCheckBoxIcon')).not.to.equal(null); }); }); diff --git a/packages/material-ui/src/Chip/Chip.test.js b/packages/material-ui/src/Chip/Chip.test.js index 99f16380e39d3e..1c8910ba7cc0a9 100644 --- a/packages/material-ui/src/Chip/Chip.test.js +++ b/packages/material-ui/src/Chip/Chip.test.js @@ -253,27 +253,27 @@ describe('', () => { describe('prop: deleteIcon', () => { it('should render a default icon with the root, deletable, deleteIcon and deleteIconOutlinedColorSecondary classes', () => { - const { container, getByRole } = render( + const { getByRole, getByTestId } = render( {}} />, ); - const icon = container.querySelector('svg[data-mui-test="CancelIcon"]'); + const icon = getByTestId('CancelIcon'); expect(getByRole('button')).to.contain(icon); expect(icon).to.have.class(classes.deleteIcon); }); it('should render a default icon with the root, deletable and deleteIcon classes', () => { - const { container, getByRole } = render( + const { getByRole, getByTestId } = render( {}} />, ); - const icon = container.querySelector('svg[data-mui-test="CancelIcon"]'); + const icon = getByTestId('CancelIcon'); expect(getByRole('button')).to.contain(icon); expect(icon).to.have.class(classes.deleteIcon); }); it('should render default icon with the root, deletable and deleteIcon primary class', () => { - const { container } = render( + const { container, getByTestId } = render( {}} color="primary" />, ); @@ -281,13 +281,13 @@ describe('', () => { expect(chip).to.have.class(classes.colorPrimary); expect(chip).to.have.class(classes.deletable); expect(chip).to.have.class(classes.deletableColorPrimary); - const icon = chip.querySelector('svg[data-mui-test="CancelIcon"]'); + const icon = getByTestId('CancelIcon'); expect(icon).to.have.class(classes.deleteIcon); expect(icon).to.have.class(classes.deleteIconColorPrimary); }); it('should render a default icon with the root, deletable, deleteIcon secondary class', () => { - const { container } = render( + const { container, getByTestId } = render( {}} color="secondary" />, ); @@ -295,18 +295,18 @@ describe('', () => { expect(chip).to.have.class(classes.colorSecondary); expect(chip).to.have.class(classes.deletable); expect(chip).to.have.class(classes.deletableColorSecondary); - const icon = chip.querySelector('svg[data-mui-test="CancelIcon"]'); + const icon = getByTestId('CancelIcon'); expect(icon).to.have.class(classes.deleteIcon); expect(icon).to.have.class(classes.deleteIconColorSecondary); }); it('accepts a custom icon', () => { const handleDelete = spy(); - const { container } = render( + const { getByTestId } = render( } />, ); - fireEvent.click(container.querySelector('svg[data-mui-test="CheckBoxIcon"]')); + fireEvent.click(getByTestId('CheckBoxIcon')); expect(handleDelete.callCount).to.equal(1); }); @@ -532,9 +532,9 @@ describe('', () => { }); it('should render the delete icon with the deleteIcon and deleteIconSmall classes', () => { - const { container } = render( {}} />); + const { getByTestId } = render( {}} />); - const icon = container.querySelector('svg[data-mui-test="CancelIcon"]'); + const icon = getByTestId('CancelIcon'); expect(icon).to.have.class(classes.deleteIcon); expect(icon).to.have.class(classes.deleteIconSmall); }); diff --git a/packages/material-ui/src/MobileStepper/MobileStepper.test.js b/packages/material-ui/src/MobileStepper/MobileStepper.test.js index 157c873fea3e91..01ec40bb94fe7d 100644 --- a/packages/material-ui/src/MobileStepper/MobileStepper.test.js +++ b/packages/material-ui/src/MobileStepper/MobileStepper.test.js @@ -63,14 +63,14 @@ describe('', () => { const wrapper = mount(); const backButton = wrapper.find('button[aria-label="back"]'); expect(backButton.exists()).to.equal(true); - expect(backButton.find('svg[data-mui-test="KeyboardArrowLeftIcon"]')).to.have.lengthOf(1); + expect(backButton.find('svg[data-testid="KeyboardArrowLeftIcon"]')).to.have.lengthOf(1); }); it('should render next button', () => { const wrapper = mount(); const nextButton = wrapper.find('button[aria-label="next"]'); expect(nextButton.exists()).to.equal(true); - expect(nextButton.find('svg[data-mui-test="KeyboardArrowRightIcon"]')).to.have.lengthOf(1); + expect(nextButton.find('svg[data-testid="KeyboardArrowRightIcon"]')).to.have.lengthOf(1); }); it('should render two buttons and text displaying progress when supplied with variant text', () => { diff --git a/packages/material-ui/src/Radio/Radio.test.js b/packages/material-ui/src/Radio/Radio.test.js index 3b37589edecc29..d3e39f979b5e1b 100644 --- a/packages/material-ui/src/Radio/Radio.test.js +++ b/packages/material-ui/src/Radio/Radio.test.js @@ -32,19 +32,15 @@ describe('', () => { describe('prop: unchecked', () => { it('should render an unchecked icon', () => { - const { container } = render(); - expect( - container.querySelectorAll('svg[data-mui-test="RadioButtonUncheckedIcon"]').length, - ).to.equal(1); + const { getAllByTestId } = render(); + expect(getAllByTestId('RadioButtonUncheckedIcon').length).to.equal(1); }); }); describe('prop: checked', () => { it('should render a checked icon', () => { - const { container } = render(); - expect( - container.querySelectorAll('svg[data-mui-test="RadioButtonCheckedIcon"]').length, - ).to.equal(1); + const { getAllByTestId } = render(); + expect(getAllByTestId('RadioButtonCheckedIcon').length).to.equal(1); }); }); diff --git a/packages/material-ui/src/StepIcon/StepIcon.test.js b/packages/material-ui/src/StepIcon/StepIcon.test.js index 5f2f013aa2e56c..64b7c435892d05 100644 --- a/packages/material-ui/src/StepIcon/StepIcon.test.js +++ b/packages/material-ui/src/StepIcon/StepIcon.test.js @@ -21,14 +21,14 @@ describe('', () => { })); it('renders when completed', () => { - const { container } = render(); + const { getAllByTestId } = render(); - expect(container.querySelectorAll('svg[data-mui-test="CheckCircleIcon"]')).to.have.length(1); + expect(getAllByTestId('CheckCircleIcon')).to.have.length(1); }); it('renders when error occurred', () => { - const { container } = render(); - expect(container.querySelectorAll('svg[data-mui-test="WarningIcon"]')).to.have.length(1); + const { getAllByTestId } = render(); + expect(getAllByTestId('WarningIcon')).to.have.length(1); }); it('contains text "3" when position is "3"', () => { diff --git a/packages/material-ui/src/StepLabel/StepLabel.test.js b/packages/material-ui/src/StepLabel/StepLabel.test.js index 20bedb790c4606..747985cda0d3fe 100644 --- a/packages/material-ui/src/StepLabel/StepLabel.test.js +++ b/packages/material-ui/src/StepLabel/StepLabel.test.js @@ -47,7 +47,7 @@ describe('', () => { const icon = container.querySelector(`.${iconClasses.root}`); // Should render WarningIcon instead of CheckCircleIcon because of { error: true } props - expect(icon).to.have.attribute('data-mui-test').equal('WarningIcon'); + expect(icon).to.have.attribute('data-testid').equal('WarningIcon'); }); }); @@ -65,7 +65,7 @@ describe('', () => { getByTestId('custom-icon'); expect(icon).to.not.equal(null); - expect(icon).to.not.have.attribute('data-mui-test').equal('CheckCircleIcon'); + expect(icon).to.not.have.attribute('data-testid').equal('CheckCircleIcon'); expect(label).to.have.class(classes.active); expect(label).to.have.class(classes.completed); }); diff --git a/packages/material-ui/src/TabScrollButton/TabScrollButton.test.js b/packages/material-ui/src/TabScrollButton/TabScrollButton.test.js index 205ceb9976663a..41ee14947e2ccb 100644 --- a/packages/material-ui/src/TabScrollButton/TabScrollButton.test.js +++ b/packages/material-ui/src/TabScrollButton/TabScrollButton.test.js @@ -39,21 +39,17 @@ describe('', () => { describe('prop: direction', () => { it('should render with the left icon', () => { - const { container } = render( + const { getAllByTestId } = render( , ); - expect( - container.querySelectorAll('svg[data-mui-test="KeyboardArrowLeftIcon"]').length, - ).to.equal(1); + expect(getAllByTestId('KeyboardArrowLeftIcon').length).to.equal(1); }); it('should render with the right icon', () => { - const { container } = render( + const { getAllByTestId } = render( , ); - expect( - container.querySelectorAll('svg[data-mui-test="KeyboardArrowRightIcon"]').length, - ).to.equal(1); + expect(getAllByTestId('KeyboardArrowRightIcon').length).to.equal(1); }); }); }); diff --git a/packages/material-ui/src/TableSortLabel/TableSortLabel.test.js b/packages/material-ui/src/TableSortLabel/TableSortLabel.test.js index 7745f3e44a8671..f611c1c7f22793 100644 --- a/packages/material-ui/src/TableSortLabel/TableSortLabel.test.js +++ b/packages/material-ui/src/TableSortLabel/TableSortLabel.test.js @@ -57,9 +57,8 @@ describe('', () => { }); it('should accept a custom icon for the sort icon', () => { - const { container } = render(); - const icon = container.querySelector(`svg.${classes.icon}[data-mui-test="SortIcon"]`); - expect(icon).to.not.equal(null); + const { getAllByTestId } = render(); + expect(getAllByTestId('SortIcon')).to.not.equal(null); }); }); diff --git a/packages/material-ui/src/Tabs/Tabs.test.js b/packages/material-ui/src/Tabs/Tabs.test.js index 72935034196771..4a148bc9fda9d5 100644 --- a/packages/material-ui/src/Tabs/Tabs.test.js +++ b/packages/material-ui/src/Tabs/Tabs.test.js @@ -17,7 +17,7 @@ import Tabs from './Tabs'; import { createMuiTheme, ThemeProvider } from '../styles'; function findScrollButton(container, direction) { - return container.querySelector(`svg[data-mui-test="KeyboardArrow${capitalize(direction)}Icon"]`); + return container.querySelector(`svg[data-testid="KeyboardArrow${capitalize(direction)}Icon"]`); } function hasLeftScrollButton(container) { diff --git a/packages/material-ui/src/utils/createSvgIcon.js b/packages/material-ui/src/utils/createSvgIcon.js index 2d146ab87dafa5..5f53ccca289bfd 100644 --- a/packages/material-ui/src/utils/createSvgIcon.js +++ b/packages/material-ui/src/utils/createSvgIcon.js @@ -6,7 +6,7 @@ import SvgIcon from '../SvgIcon'; */ export default function createSvgIcon(path, displayName) { const Component = (props, ref) => ( - + {path} );