diff --git a/.eslintrc.js b/.eslintrc.js
index e3f8549ff0a6cb..ca4a7e0025fe79 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -16,7 +16,7 @@ module.exports = {
'airbnb-typescript',
'prettier',
'prettier/react',
- 'prettier/@typescript-eslint',
+ 'prettier/@typescript-eslint'
],
parser: '@typescript-eslint/parser',
parserOptions: {
@@ -137,7 +137,7 @@ module.exports = {
env: {
mocha: true,
},
- extends: ['plugin:mocha/recommended'],
+ extends: ['plugin:mocha/recommended', 'plugin:chai-friendly/recommended'],
rules: {
// does not work with wildcard imports. Mistakes will throw at runtime anyway
'import/named': 'off',
@@ -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',
},
},
{
diff --git a/package.json b/package.json
index 248df30fc4e184..1c294b11776d8a 100644
--- a/package.json
+++ b/package.json
@@ -101,6 +101,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",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-jsx-a11y": "^6.3.1",
"eslint-plugin-mocha": "^8.0.0",
diff --git a/packages/material-ui/src/Accordion/Accordion.test.js b/packages/material-ui/src/Accordion/Accordion.test.js
index 8d3575a25cded4..ed32b01a444788 100644
--- a/packages/material-ui/src/Accordion/Accordion.test.js
+++ b/packages/material-ui/src/Accordion/Accordion.test.js
@@ -2,16 +2,20 @@ 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 {
+ createClientRender,
+ describeConformance,
+ getClasses,
+ fireEvent
+} from 'test/utils';
import Paper from '../Paper';
import Accordion from './Accordion';
import AccordionSummary from '../AccordionSummary';
-import Collapse from '../Collapse';
describe('', () => {
- const mount = createMount({ strict: true });
+ const mount = createClientRender({ strict: true });
let classes;
- const minimalChildren = [];
+ const minimalChildren = [(Header)];
before(() => {
classes = getClasses({minimalChildren});
@@ -23,80 +27,82 @@ describe('', () => {
mount,
refInstanceof: window.HTMLDivElement,
skip: ['componentProp'],
+ useRTL: true,
}));
it('should render and not be controlled', () => {
- const wrapper = mount({minimalChildren});
- 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 accordion = mount({minimalChildren});
+ expect(accordion.container.firstChild.tagName).to.equal("DIV");
+ expect(accordion.container.firstChild.classList.contains(classes.expanded)).to.be.false;
+ expect(accordion.container.firstChild.classList.contains(classes.square)).to.be.false;
});
it('should handle defaultExpanded prop', () => {
- const wrapper = mount({minimalChildren});
- expect(findOutermostIntrinsic(wrapper).hasClass(classes.expanded)).to.equal(true);
+ const accordion = mount({minimalChildren});
+ expect(accordion.container.firstChild.classList.contains(classes.expanded)).to.be.true;
});
it('should render the summary and collapse elements', () => {
- const wrapper = mount(
+ const accordion = mount(
Summary
Hello
,
);
- expect(wrapper.find('[aria-expanded=false]').hostNodes().text()).to.equal('Summary');
- expect(wrapper.find(Collapse).find('div#panel-content').text()).to.equal('Hello');
+ expect(accordion.getByText("Summary").parentNode.getAttribute("aria-expanded")).to.be.equal('false');
+ expect(accordion.getByText("Hello")).to.not.be.visible;
});
it('should be controlled', () => {
- const wrapper = mount({minimalChildren});
- 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 accordion = mount({minimalChildren});
+ const panel = accordion.container.firstChild;
+ expect(panel.classList.contains(classes.expanded)).to.be.true;
+ accordion.rerender({minimalChildren});
+ expect(panel.classList.contains(classes.expanded)).to.be.false;
});
it('should call onChange when clicking the summary element', () => {
const handleChange = spy();
- const wrapper = mount({minimalChildren});
- wrapper.find(AccordionSummary).simulate('click');
+ const accordion = mount({minimalChildren});
+ const summary = accordion.getByText("Header");
+ fireEvent.click(summary);
expect(handleChange.callCount).to.equal(1);
});
it('when controlled should call the onChange', () => {
const handleChange = spy();
- const wrapper = mount(
+ const accordion = mount(
{minimalChildren}
,
);
- wrapper.find(AccordionSummary).simulate('click');
+ const summary = accordion.getByText("Header");
+ fireEvent.click(summary);
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 accordion = mount(
+
{minimalChildren}
,
);
- wrapper.setProps({ onChange: undefined });
- wrapper.find(AccordionSummary).simulate('click');
+ const summary = accordion.getByText("Header");
+ fireEvent.click(summary);
expect(handleChange.callCount).to.equal(0);
});
it('when disabled should have the disabled class', () => {
- const wrapper = mount({minimalChildren});
- expect(findOutermostIntrinsic(wrapper).hasClass(classes.disabled)).to.equal(true);
+ const accordion = mount({minimalChildren});
+ expect(accordion.container.firstChild.classList.contains(classes.disabled)).to.be.true;
});
it('should handle the TransitionComponent prop', () => {
const NoTransitionCollapse = (props) => {
- return props.in ? {props.children}
: null;
+ return props.in ? {props.children}
: null;
};
NoTransitionCollapse.propTypes = {
children: PropTypes.node,
@@ -104,7 +110,7 @@ describe('', () => {
};
const CustomContent = () => Hello
;
- const wrapper = mount(
+ const accordion = mount(
@@ -112,15 +118,16 @@ describe('', () => {
);
// 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(accordion.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);
+ accordion.rerender(
+
+
+
+
+ );
+ expect(accordion.queryByText("Hello")).to.not.exist
});
describe('prop: children', () => {
@@ -153,7 +160,7 @@ describe('', () => {
});
it('should accept empty content', () => {
- mount(
+ createClientRender(
{null}
diff --git a/test/utils/describeConformance.js b/test/utils/describeConformance.js
index 1a5b975cf8fe2b..b9ce540dfddcb2 100644
--- a/test/utils/describeConformance.js
+++ b/test/utils/describeConformance.js
@@ -59,15 +59,18 @@ function randomStringValue() {
*/
function testClassName(element, getOptions) {
it('applies the className to the root component', () => {
- const { mount } = getOptions();
+ const { mount, useRTL } = getOptions();
const className = randomStringValue();
const wrapper = mount(React.cloneElement(element, { className }));
-
- expect(findOutermostIntrinsic(wrapper).hasClass(className)).to.equal(
- true,
- 'does have a custom `className`',
- );
+ if (useRTL) {
+ expect(wrapper.container.firstChild.classList.contains(className)).to.be.equal(true);
+ } else {
+ expect(findOutermostIntrinsic(wrapper).hasClass(className)).to.equal(
+ true,
+ 'does have a custom `className`',
+ );
+ }
});
}
@@ -98,14 +101,17 @@ function testComponentProp(element, getOptions) {
function testPropsSpread(element, getOptions) {
it(`spreads props to the root component`, () => {
// type def in ConformanceOptions
- const { classes, inheritComponent, mount } = getOptions();
+ const { classes, inheritComponent, mount, useRTL } = getOptions();
const testProp = 'data-test-props-spread';
const value = randomStringValue();
const wrapper = mount(React.cloneElement(element, { [testProp]: value }));
- const root = findRootComponent(wrapper, { classes, component: inheritComponent });
-
- expect(root.props()[testProp]).to.equal(value);
+ if(useRTL) {
+ expect(wrapper.container.firstChild.getAttribute(testProp)).to.equal(value);
+ } else {
+ const root = findRootComponent(wrapper, { classes, component: inheritComponent });
+ expect(root.props()[testProp]).to.equal(value);
+ }
});
}
@@ -121,14 +127,20 @@ function describeRef(element, getOptions) {
describe('ref', () => {
it(`attaches the ref`, () => {
// type def in ConformanceOptions
- const { inheritComponent, mount, refInstanceof } = getOptions();
+ const { inheritComponent, mount, refInstanceof, useRTL } = getOptions();
testRef(element, mount, (instance, wrapper) => {
expect(instance).to.be.instanceof(refInstanceof);
if (inheritComponent && instance.nodeType === 1) {
- const rootHost = findOutermostIntrinsic(wrapper);
- expect(instance).to.equal(rootHost.instance());
+ if (useRTL) {
+ const rootHost = wrapper.container.firstChild;
+ expect(instance).to.equal(rootHost);
+ } else {
+ const rootHost = findOutermostIntrinsic(wrapper);
+ expect(instance).to.equal(rootHost.instance());
+ }
+
}
});
});
@@ -142,7 +154,7 @@ function describeRef(element, getOptions) {
*/
function testRootClass(element, getOptions) {
it('applies the root class to the root component if it has this class', () => {
- const { classes, mount } = getOptions();
+ const { classes, mount, useRTL } = getOptions();
if (classes.root == null) {
return;
}
@@ -154,8 +166,13 @@ function testRootClass(element, getOptions) {
// jump to the host component because some components pass the `root` class
// to the `classes` prop of the root component.
// https://github.com/mui-org/material-ui/blob/f9896bcd129a1209153106296b3d2487547ba205/packages/material-ui/src/OutlinedInput/OutlinedInput.js#L101
- expect(findOutermostIntrinsic(wrapper).hasClass(classes.root)).to.equal(true);
- expect(findOutermostIntrinsic(wrapper).hasClass(className)).to.equal(true);
+ if (useRTL) {
+ expect(wrapper.container.firstChild.classList.contains(classes.root)).to.be.equal(true);
+ expect(wrapper.container.firstChild.classList.contains(className)).to.be.equal(true);
+ } else {
+ expect(findOutermostIntrinsic(wrapper).hasClass(classes.root)).to.equal(true);
+ expect(findOutermostIntrinsic(wrapper).hasClass(className)).to.equal(true);
+ }
});
}
diff --git a/yarn.lock b/yarn.lock
index c410404ec2a207..9a9673f82c6efc 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -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"