Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[test] Migrate Accordion to react-testing-library #22952

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ module.exports = {
env: {
mocha: true,
},
extends: ['plugin:mocha/recommended'],
extends: ['plugin:mocha/recommended', 'plugin:chai-friendly/recommended'],
oliviertassinari marked this conversation as resolved.
Show resolved Hide resolved
rules: {
// does not work with wildcard imports. Mistakes will throw at runtime anyway
'import/named': 'off',
Expand Down Expand Up @@ -187,6 +187,7 @@ module.exports = {
// components that are defined in test are isolated enough
// that they don't need type-checking
'react/prop-types': 'off',
'@typescript-eslint/no-unused-expressions': 'off',
oliviertassinari marked this conversation as resolved.
Show resolved Hide resolved
},
},
{
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
"eslint-config-prettier": "^6.11.0",
"eslint-import-resolver-webpack": "^0.13.0",
"eslint-plugin-babel": "^5.3.1",
"eslint-plugin-chai-friendly": "^0.6.0",
oliviertassinari marked this conversation as resolved.
Show resolved Hide resolved
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-jsx-a11y": "^6.3.1",
"eslint-plugin-mocha": "^8.0.0",
Expand Down
81 changes: 40 additions & 41 deletions packages/material-ui/src/Accordion/Accordion.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@ import * as React from 'react';
import PropTypes from 'prop-types';
import { expect } from 'chai';
import { spy } from 'sinon';
import { createMount, describeConformance, getClasses, findOutermostIntrinsic } from 'test/utils';
import {
createMount,
describeConformance,
getClasses,
createClientRender,
fireEvent
} from 'test/utils';
import Paper from '../Paper';
import Accordion from './Accordion';
import AccordionSummary from '../AccordionSummary';
import Collapse from '../Collapse';

describe('<Accordion />', () => {
const render = createClientRender();
const mount = createMount({ strict: true });
let classes;
const minimalChildren = [<AccordionSummary key="header" />];
const minimalChildren = [<AccordionSummary key="header">Header</AccordionSummary>];

before(() => {
classes = getClasses(<Accordion>{minimalChildren}</Accordion>);
Expand All @@ -26,101 +32,94 @@ describe('<Accordion />', () => {
}));

it('should render and not be controlled', () => {
const wrapper = mount(<Accordion>{minimalChildren}</Accordion>);
const root = wrapper.find(`.${classes.root}`).first();
expect(root.type()).to.equal(Paper);
expect(root.props().square).to.equal(false);
expect(root.hasClass(classes.expanded)).to.equal(false);
const { container } = render(<Accordion>{minimalChildren}</Accordion>);
const root = container.firstChild;
expect(root).to.not.have.class(classes.expanded);
});

it('should handle defaultExpanded prop', () => {
const wrapper = mount(<Accordion defaultExpanded>{minimalChildren}</Accordion>);
expect(findOutermostIntrinsic(wrapper).hasClass(classes.expanded)).to.equal(true);
const { container } = render(<Accordion defaultExpanded>{minimalChildren}</Accordion>);
expect(container.firstChild).to.have.class(classes.expanded);
});

it('should render the summary and collapse elements', () => {
const wrapper = mount(
const { getByText } = render(
<Accordion>
<AccordionSummary>Summary</AccordionSummary>
<div id="panel-content">Hello</div>
</Accordion>,
);

expect(wrapper.find('[aria-expanded=false]').hostNodes().text()).to.equal('Summary');
expect(wrapper.find(Collapse).find('div#panel-content').text()).to.equal('Hello');
expect(getByText("Summary")).to.not.have.attribute("aria-expanded");
oliviertassinari marked this conversation as resolved.
Show resolved Hide resolved
expect(getByText("Hello")).to.not.be.visible;
oliviertassinari marked this conversation as resolved.
Show resolved Hide resolved
});

it('should be controlled', () => {
const wrapper = mount(<Accordion expanded>{minimalChildren}</Accordion>);
const panel = wrapper.find(`.${classes.root}`).first();
expect(panel.hasClass(classes.expanded)).to.equal(true);
wrapper.setProps({ expanded: false });
expect(wrapper.hasClass(classes.expanded)).to.equal(false);
const { container, setProps } = render(<Accordion expanded>{minimalChildren}</Accordion>);
const panel = container.firstChild;
expect(panel).to.have.class(classes.expanded);
setProps({ expanded: false });
expect(panel).to.not.have.class(classes.expanded);
});

it('should call onChange when clicking the summary element', () => {
const handleChange = spy();
const wrapper = mount(<Accordion onChange={handleChange}>{minimalChildren}</Accordion>);
wrapper.find(AccordionSummary).simulate('click');
const { getByText } = render(<Accordion onChange={handleChange}>{minimalChildren}</Accordion>);
fireEvent.click(getByText("Header"));
expect(handleChange.callCount).to.equal(1);
});

it('when controlled should call the onChange', () => {
const handleChange = spy();
const wrapper = mount(
const { getByText } = render(
<Accordion onChange={handleChange} expanded>
{minimalChildren}
</Accordion>,
);
wrapper.find(AccordionSummary).simulate('click');
fireEvent.click(getByText('Header'));
expect(handleChange.callCount).to.equal(1);
expect(handleChange.args[0][1]).to.equal(false);
});

it('when undefined onChange and controlled should not call the onChange', () => {
const handleChange = spy();
const wrapper = mount(
const { setProps, getByText} = render(
<Accordion onChange={handleChange} expanded>
{minimalChildren}
</Accordion>,
);
wrapper.setProps({ onChange: undefined });
wrapper.find(AccordionSummary).simulate('click');
setProps({ onChange: undefined });
fireEvent.click(getByText("Header"));
expect(handleChange.callCount).to.equal(0);
});

it('when disabled should have the disabled class', () => {
const wrapper = mount(<Accordion disabled>{minimalChildren}</Accordion>);
expect(findOutermostIntrinsic(wrapper).hasClass(classes.disabled)).to.equal(true);
const { container } = render(<Accordion disabled>{minimalChildren}</Accordion>);
expect(container.firstChild).to.have.class(classes.disabled);
});

it('should handle the TransitionComponent prop', () => {
const NoTransitionCollapse = (props) => {
return props.in ? <div>{props.children}</div> : null;
return props.in ? <div data-testid="no-transition-collapse">{props.children}</div> : null;
};
NoTransitionCollapse.propTypes = {
children: PropTypes.node,
in: PropTypes.bool,
};

const CustomContent = () => <div>Hello</div>;
const wrapper = mount(
const { queryByText, getByText, setProps } = render(
<Accordion expanded TransitionComponent={NoTransitionCollapse}>
<AccordionSummary />
<CustomContent />
</Accordion>,
);

// Collapse is initially shown
const collapse = wrapper.find(NoTransitionCollapse);
expect(collapse.props().in).to.equal(true);
expect(wrapper.find(CustomContent).length).to.equal(1);
expect(getByText('Hello')).to.be.visible;

// Hide the collapse
wrapper.setProps({ expanded: false });
const collapse2 = wrapper.find(NoTransitionCollapse);
expect(collapse2.props().in).to.equal(false);
expect(wrapper.find(CustomContent).length).to.equal(0);
setProps({ expanded: false });
expect(queryByText("Hello")).to.not.exist
});

describe('prop: children', () => {
Expand Down Expand Up @@ -153,7 +152,7 @@ describe('<Accordion />', () => {
});

it('should accept empty content', () => {
mount(
render(
<Accordion>
<AccordionSummary />
{null}
Expand All @@ -163,17 +162,17 @@ describe('<Accordion />', () => {
});

it('should warn when switching from controlled to uncontrolled', () => {
const wrapper = mount(<Accordion expanded>{minimalChildren}</Accordion>);
const wrapper = render(<Accordion expanded>{minimalChildren}</Accordion>);

expect(() => wrapper.setProps({ expanded: undefined })).to.toErrorDev(
'Material-UI: A component is changing the controlled expanded state of Accordion to be uncontrolled.',
);
});

it('should warn when switching between uncontrolled to controlled', () => {
const wrapper = mount(<Accordion>{minimalChildren}</Accordion>);
const { setProps } = render(<Accordion>{minimalChildren}</Accordion>);

expect(() => wrapper.setProps({ expanded: true })).toErrorDev(
expect(() => setProps({ expanded: true })).toErrorDev(
'Material-UI: A component is changing the uncontrolled expanded state of Accordion to be controlled.',
);
});
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7141,6 +7141,11 @@ eslint-plugin-babel@^5.3.1:
dependencies:
eslint-rule-composer "^0.3.0"

eslint-plugin-chai-friendly@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-chai-friendly/-/eslint-plugin-chai-friendly-0.6.0.tgz#54052fab79302ed0cea76ab997351ea4809bfb77"
integrity sha512-Uvvv1gkbRGp/qfN15B0kQyQWg+oFA8buDSqrwmW3egNSk/FpqH2MjQqKOuKwmEL6w4QIQrIjDp+gg6kGGmD3oQ==

eslint-plugin-import@^2.22.0:
version "2.22.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702"
Expand Down