Skip to content

Commit

Permalink
[test] Use testing-library in MenuItem (#21391)
Browse files Browse the repository at this point in the history
  • Loading branch information
eps1lon committed Jun 12, 2020
1 parent 68d1953 commit 55dcfd4
Showing 1 changed file with 117 additions and 66 deletions.
183 changes: 117 additions & 66 deletions packages/material-ui/src/MenuItem/MenuItem.test.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import * as React from 'react';
import { expect } from 'chai';
import { spy } from 'sinon';
import { createShallow, getClasses } from '@material-ui/core/test-utils';
import { getClasses } from '@material-ui/core/test-utils';
import { createClientRender, fireEvent, screen } from 'test/utils/createClientRender';
import createMount from 'test/utils/createMount';
import describeConformance from '../test-utils/describeConformance';
import ListItem from '../ListItem';
import ListItemSecondaryAction from '../ListItemSecondaryAction';
import MenuItem from './MenuItem';

describe('<MenuItem />', () => {
let shallow;
let classes;
const mount = createMount();
const render = createClientRender();

before(() => {
shallow = createShallow({ dive: true });
classes = getClasses(<MenuItem />);
});

Expand All @@ -26,88 +26,139 @@ describe('<MenuItem />', () => {
testComponentPropWith: 'a',
}));

it('should render a button ListItem with with ripple', () => {
const wrapper = shallow(<MenuItem />);
expect(wrapper.type()).to.equal(ListItem);
expect(wrapper.find(ListItem).props().button).to.equal(true);
expect(wrapper.find(ListItem).props().disableRipple).to.equal(undefined);
});
it('should render a focusable menuitem', () => {
render(<MenuItem />);
const menuitem = screen.getByRole('menuitem');

it('should render with the selected class', () => {
const wrapper = shallow(<MenuItem selected />);
expect(wrapper.hasClass(classes.selected)).to.equal(true);
expect(menuitem).to.have.property('tabIndex', -1);
});

it('should have a default role of menuitem', () => {
const wrapper = shallow(<MenuItem />);
expect(wrapper.props().role).to.equal('menuitem');
it('has a ripple when clicked', () => {
render(<MenuItem TouchRippleProps={{ classes: { rippleVisible: 'ripple-visible' } }} />);
const menuitem = screen.getByRole('menuitem');

// ripple starts on mousedown
fireEvent.mouseDown(menuitem);

expect(menuitem.querySelectorAll('.ripple-visible')).to.have.length(1);
});

it('should have a role of option', () => {
const wrapper = shallow(<MenuItem role="option" aria-selected={false} />);
expect(wrapper.props().role).to.equal('option');
it('should render with the selected class but not aria-selected when `selected`', () => {
render(<MenuItem selected />);
const menuitem = screen.getByRole('menuitem');

expect(menuitem).to.have.class(classes.selected);
expect(menuitem).not.to.have.attribute('aria-selected');
});

it('should have a tabIndex of -1 by default', () => {
const wrapper = shallow(<MenuItem />);
expect(wrapper.props().tabIndex).to.equal(-1);
it('can have a role of option', () => {
render(<MenuItem role="option" aria-selected={false} />);

expect(screen.queryByRole('option')).not.to.equal(null);
});

describe('event callbacks', () => {
it('should fire event callbacks', () => {
const events = [
'onClick',
'onFocus',
'onBlur',
'onKeyUp',
'onKeyDown',
'onMouseDown',
'onMouseLeave',
'onMouseUp',
'onTouchEnd',
'onTouchStart',
];

const handlers = events.reduce((result, n) => {
result[n] = spy();
return result;
}, {});

const wrapper = shallow(<MenuItem {...handlers} />);

events.forEach((n) => {
const event = n.charAt(2).toLowerCase() + n.slice(3);
wrapper.simulate(event, { persist: () => {} });
expect(handlers[n].callCount).to.equal(1);
const events = ['click', 'mouseDown', 'mouseEnter', 'mouseLeave', 'mouseUp', 'touchEnd'];

events.forEach((eventName) => {
it(`should fire ${eventName}`, () => {
const handlerName = `on${eventName[0].toUpperCase()}${eventName.slice(1)}`;
const handler = spy();
render(<MenuItem {...{ [handlerName]: handler }} />);

fireEvent[eventName](screen.getByRole('menuitem'));

expect(handler.callCount).to.equal(1);
});
});
});

describe('mount', () => {
it('should not fail with a li > li error message', () => {
const wrapper1 = mount(
<MenuItem>
<ListItemSecondaryAction>
<div />
</ListItemSecondaryAction>
</MenuItem>,
);
expect(wrapper1.find('li').length).to.equal(1);
const wrapper2 = mount(
<MenuItem button={false}>
<ListItemSecondaryAction>
<div />
</ListItemSecondaryAction>
</MenuItem>,
it(`should fire focus, keydown, keyup and blur`, () => {
const handleFocus = spy();
const handleKeyDown = spy();
const handleKeyUp = spy();
const handleBlur = spy();
render(
<MenuItem
onFocus={handleFocus}
onKeyDown={handleKeyDown}
onKeyUp={handleKeyUp}
onBlur={handleBlur}
/>,
);
expect(wrapper2.find('li').length).to.equal(1);
const menuitem = screen.getByRole('menuitem');

menuitem.focus();

expect(handleFocus.callCount).to.equal(1);

fireEvent.keyDown(menuitem);

expect(handleKeyDown.callCount).to.equal(1);

fireEvent.keyUp(menuitem);

expect(handleKeyUp.callCount).to.equal(1);

menuitem.blur();

expect(handleKeyDown.callCount).to.equal(1);
});

it('should fire onTouchStart', function touchStartTest() {
// only run in supported browsers
if (typeof Touch === 'undefined') {
this.skip();
}

const handleTouchStart = spy();
render(<MenuItem onTouchStart={handleTouchStart} />);
const menuitem = screen.getByRole('menuitem');

const touch = new Touch({ identifier: 0, target: menuitem, clientX: 0, clientY: 0 });
fireEvent.touchStart(menuitem, { touches: [touch] });

expect(handleTouchStart.callCount).to.equal(1);
});
});

// Regression test for #10452.
// Kept for backwards compatibility.
// In the future we should have a better pattern for this UI.
it('should not fail with a li > li error message', () => {
const { rerender } = render(
<MenuItem>
<ListItemSecondaryAction>
<div />
</ListItemSecondaryAction>
</MenuItem>,
);

expect(document.querySelectorAll('li')).to.have.length(1);

rerender(
<MenuItem button={false}>
<ListItemSecondaryAction>
<div />
</ListItemSecondaryAction>
</MenuItem>,
);

expect(document.querySelectorAll('li')).to.have.length(1);
});

it('can be disabled', () => {
render(<MenuItem disabled />);
const menuitem = screen.getByRole('menuitem');

expect(menuitem).to.have.attribute('aria-disabled', 'true');
});

describe('prop: ListItemClasses', () => {
it('should be able to change the style of ListItem', () => {
const wrapper = mount(<MenuItem ListItemClasses={{ disabled: 'bar' }} />);
expect(wrapper.find(ListItem).props().classes.disabled).to.equal('bar');
render(<MenuItem ListItemClasses={{ disabled: 'bar' }} disabled />);
const menuitem = screen.getByRole('menuitem');

expect(menuitem).to.have.class('bar');
});
});
});

0 comments on commit 55dcfd4

Please sign in to comment.