materialuiupgraded
Version:
Material-UI's workspace package
246 lines (221 loc) • 8.87 kB
JavaScript
/* eslint-disable no-underscore-dangle */
import React from 'react';
import { assert } from 'chai';
import { spy, useFakeTimers } from 'sinon';
import consoleErrorMock from 'test/utils/consoleErrorMock';
import { createShallow, createMount, getClasses, unwrap } from '../test-utils';
import Popper from '../Popper';
import Tooltip from './Tooltip';
import createMuiTheme from '../styles/createMuiTheme';
function persist() {}
const TooltipNaked = unwrap(Tooltip);
const theme = createMuiTheme();
describe('<Tooltip />', () => {
let shallow;
let mount;
let classes;
let clock;
const defaultProps = {
title: 'Hello World',
children: <span>Hello World</span>,
};
before(() => {
shallow = createShallow({ dive: true, disableLifecycleMethods: true });
mount = createMount();
classes = getClasses(<Tooltip {...defaultProps} />);
clock = useFakeTimers();
});
after(() => {
clock.restore();
mount.cleanUp();
});
it('should render the correct structure', () => {
const wrapper = shallow(<Tooltip {...defaultProps} />);
assert.strictEqual(wrapper.type(), React.Fragment);
assert.strictEqual(wrapper.childAt(0).name(), 'RootRef');
assert.strictEqual(wrapper.childAt(1).name(), 'WithTheme(Popper)');
assert.strictEqual(wrapper.childAt(1).hasClass(classes.popper), true);
});
describe('prop: title', () => {
it('should display if the title is presetn', () => {
const wrapper = shallow(<Tooltip {...defaultProps} open />);
assert.strictEqual(wrapper.find(Popper).props().open, true);
});
it('should not display if the title is an empty string', () => {
const wrapper = shallow(<Tooltip {...defaultProps} title="" open />);
assert.strictEqual(wrapper.find(Popper).props().open, false);
});
});
describe('prop: placement', () => {
it('should have top placement', () => {
const wrapper = shallow(<Tooltip {...defaultProps} placement="top" />);
assert.strictEqual(wrapper.find(Popper).props().placement, 'top');
});
});
it('should respond to external events', () => {
const wrapper = shallow(<Tooltip {...defaultProps} />);
wrapper.instance().childrenRef = document.createElement('div');
const children = wrapper.childAt(0).childAt(0);
assert.strictEqual(wrapper.state().open, false);
children.simulate('mouseOver', { type: 'mouseover' });
assert.strictEqual(wrapper.state().open, true);
children.simulate('mouseLeave', { type: 'mouseleave' });
assert.strictEqual(wrapper.state().open, false);
});
it('should be controllable', () => {
const handleRequestOpen = spy();
const handleClose = spy();
const wrapper = shallow(
<Tooltip {...defaultProps} open onOpen={handleRequestOpen} onClose={handleClose} />,
);
wrapper.instance().childrenRef = document.createElement('div');
const children = wrapper.childAt(0).childAt(0);
assert.strictEqual(handleRequestOpen.callCount, 0);
assert.strictEqual(handleClose.callCount, 0);
children.simulate('mouseOver', { type: 'mouseover' });
assert.strictEqual(handleRequestOpen.callCount, 1);
assert.strictEqual(handleClose.callCount, 0);
children.simulate('mouseLeave', { type: 'mouseleave' });
assert.strictEqual(handleRequestOpen.callCount, 1);
assert.strictEqual(handleClose.callCount, 1);
});
it('should close when the interaction is over', () => {
const wrapper = shallow(<Tooltip {...defaultProps} />);
const childrenRef = document.createElement('div');
childrenRef.tabIndex = 0;
wrapper.instance().childrenRef = childrenRef;
const children = wrapper.childAt(0).childAt(0);
assert.strictEqual(wrapper.state().open, false);
children.simulate('mouseOver', { type: 'mouseover' });
childrenRef.focus();
children.simulate('focus', { type: 'focus', persist });
clock.tick(0);
assert.strictEqual(wrapper.state().open, true);
children.simulate('mouseLeave', { type: 'mouseleave' });
assert.strictEqual(wrapper.state().open, false);
children.simulate('blur', { type: 'blur' });
assert.strictEqual(wrapper.state().open, false);
});
describe('touch screen', () => {
it('should not respond to quick events', () => {
const wrapper = shallow(<Tooltip {...defaultProps} />);
const childrenRef = document.createElement('div');
childrenRef.tabIndex = 0;
wrapper.instance().childrenRef = childrenRef;
const children = wrapper.childAt(0).childAt(0);
children.simulate('touchStart', { type: 'touchstart', persist });
children.simulate('touchEnd', { type: 'touchend', persist });
childrenRef.focus();
children.simulate('focus', { type: 'focus', persist });
assert.strictEqual(wrapper.state().open, false);
});
it('should open on long press', () => {
const wrapper = shallow(<Tooltip {...defaultProps} />);
const childrenRef = document.createElement('div');
childrenRef.tabIndex = 0;
wrapper.instance().childrenRef = childrenRef;
const children = wrapper.childAt(0).childAt(0);
children.simulate('touchStart', { type: 'touchstart', persist });
childrenRef.focus();
children.simulate('focus', { type: 'focus', persist });
clock.tick(1e3);
assert.strictEqual(wrapper.state().open, true);
children.simulate('touchEnd', { type: 'touchend', persist });
children.simulate('blur', { type: 'blur' });
clock.tick(1500);
assert.strictEqual(wrapper.state().open, false);
});
});
describe('mount', () => {
it('should mount without any issue', () => {
mount(<Tooltip {...defaultProps} open />);
});
});
describe('prop: delay', () => {
it('should take the enterDelay into account', () => {
const wrapper = mount(
<TooltipNaked classes={{}} theme={theme} enterDelay={111} {...defaultProps} />,
);
const childrenRef = wrapper.instance().childrenRef;
childrenRef.tabIndex = 0;
childrenRef.focus();
assert.strictEqual(document.activeElement, childrenRef);
assert.strictEqual(wrapper.state().open, false);
clock.tick(111);
assert.strictEqual(wrapper.state().open, true);
});
it('should take the leaveDelay into account', () => {
const wrapper = mount(
<TooltipNaked classes={{}} theme={theme} leaveDelay={111} {...defaultProps} />,
);
const childrenRef = wrapper.instance().childrenRef;
childrenRef.tabIndex = 0;
childrenRef.focus();
assert.strictEqual(document.activeElement, childrenRef);
clock.tick(0);
assert.strictEqual(wrapper.state().open, true);
childrenRef.blur();
assert.strictEqual(wrapper.state().open, true);
clock.tick(111);
assert.strictEqual(wrapper.state().open, false);
});
});
describe('prop: overrides', () => {
[
'onTouchStart',
'onTouchEnd',
'onMouseEnter',
'onMouseOver',
'onMouseLeave',
'onFocus',
'onBlur',
].forEach(name => {
it(`should be transparent for the ${name} event`, () => {
const handler = spy();
const wrapper = shallow(
<Tooltip title="Hello World">
<button type="submit" {...{ [name]: handler }}>
Hello World
</button>
</Tooltip>,
);
wrapper.instance().childrenRef = document.createElement('div');
const children = wrapper.childAt(0).childAt(0);
const type = name.slice(2).toLowerCase();
children.simulate(type, { type, persist });
clock.tick(0);
assert.strictEqual(handler.callCount, 1);
});
});
});
describe('disabled button warning', () => {
before(() => {
consoleErrorMock.spy();
});
after(() => {
consoleErrorMock.reset();
});
it('should raise a warning when we can listen to events', () => {
mount(
<Tooltip title="Hello World">
<button type="submit" disabled>
Hello World
</button>
</Tooltip>,
);
assert.strictEqual(consoleErrorMock.callCount(), 1, 'should call console.error');
assert.match(
consoleErrorMock.args()[0][0],
/Material-UI: you are providing a disabled `button` child to the Tooltip component/,
);
});
});
it('should forward properties to the child element', () => {
const wrapper = shallow(
<Tooltip className="foo" {...defaultProps}>
<h1>H1</h1>
</Tooltip>,
);
assert.strictEqual(wrapper.find('h1').props().className, 'foo');
});
});