UNPKG

@activelylearn/material-ui

Version:

Material-UI's workspace package

343 lines (306 loc) 9.81 kB
/* eslint-disable no-underscore-dangle */ import React from 'react'; import { assert } from 'chai'; import { spy, useFakeTimers } from 'sinon'; import { Popper, Target } from 'react-popper'; import { ShallowWrapper } from 'enzyme'; import consoleErrorMock from 'test/utils/consoleErrorMock'; import { createShallow, createMount, getClasses, unwrap } from '../test-utils'; import createMuiTheme from '../styles/createMuiTheme'; import Tooltip from './Tooltip'; function persist() {} // Remove the style from the DOM element. // eslint-disable-next-line react/prop-types const Hack = ({ style, innerRef, ...other }) => <div ref={innerRef} {...other} />; function getTargetChildren(wrapper) { return new ShallowWrapper( wrapper .find(Target) .props() .children({}).props.children, wrapper, ); } function getPopperChildren(wrapper) { return new ShallowWrapper( wrapper .find(Popper) .props() .children({ popperProps: { style: {} }, restProps: {} }), null, ); } describe('<Tooltip />', () => { let shallow; let mount; let classes; const TooltipNaked = unwrap(Tooltip); before(() => { shallow = createShallow({ dive: true }); mount = createMount(); classes = getClasses( <Tooltip title="Hello World"> <span>Hello World</span> </Tooltip>, ); }); after(() => { mount.cleanUp(); }); it('should render a Manager', () => { const wrapper = shallow( <Tooltip title="Hello World"> <span>Hello World</span> </Tooltip>, ); assert.strictEqual(wrapper.name(), 'Manager'); assert.strictEqual(wrapper.childAt(0).name(), 'EventListener'); }); it('should render with the user, tooltip classes', () => { const wrapper = shallow( <Tooltip title="Hello World"> <span>Hello World</span> </Tooltip>, ); const popperChildren = getPopperChildren(wrapper); assert.strictEqual(popperChildren.childAt(0).hasClass(classes.tooltip), true); }); describe('prop: title', () => { it('should not display if the title is an empty string', () => { const wrapper = shallow( <Tooltip open title=""> <span>Hello World</span> </Tooltip>, ); assert.strictEqual(wrapper.find(Popper).hasClass(classes.open), false); }); }); describe('prop: placement', () => { it('should have top placement', () => { const wrapper = shallow( <Tooltip placement="top" title="Hello World"> <span>Hello World</span> </Tooltip>, ); const popperChildren = getPopperChildren(wrapper); assert.strictEqual(popperChildren.childAt(0).hasClass(classes.tooltip), true); wrapper.childAt(0).simulate('click'); assert.strictEqual(popperChildren.childAt(0).hasClass(classes.tooltipPlacementTop), true); }); const theme = createMuiTheme({ direction: 'rtl', }); [ { in: 'bottom-end', out: 'bottom-start', }, { in: 'bottom-start', out: 'bottom-end', }, { in: 'top-end', out: 'top-start', }, { in: 'top-start', out: 'top-end', }, { in: 'top', out: 'top', }, ].forEach(test => { it(`should flip ${test.in} when direction=rtl is used`, () => { const wrapper = shallow( <Tooltip theme={theme} placement={test.in} title="Hello World"> <span>Hello World</span> </Tooltip>, ); assert.strictEqual(wrapper.find(Popper).props().placement, test.out); }); }); }); it('should respond to external events', () => { const wrapper = shallow( <Tooltip placement="top" title="Hello World"> <button>Hello World</button> </Tooltip>, ); const children = getTargetChildren(wrapper); assert.strictEqual(wrapper.state().open, false); children.simulate('mouseOver', {}); assert.strictEqual(wrapper.state().open, true); children.simulate('blur', {}); assert.strictEqual(wrapper.state().open, false); }); it('should be controllable', () => { const handleRequestOpen = spy(); const handleClose = spy(); const wrapper = shallow( <Tooltip placement="top" title="Hello World" open onOpen={handleRequestOpen} onClose={handleClose} > <button>Hello World</button> </Tooltip>, ); const children = getTargetChildren(wrapper); 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('blur', { type: 'blur' }); assert.strictEqual(handleRequestOpen.callCount, 1); assert.strictEqual(handleClose.callCount, 1); }); describe('touch screen', () => { let clock; before(() => { clock = useFakeTimers(); }); after(() => { clock.restore(); }); it('should not respond to quick events', () => { const wrapper = shallow( <Tooltip title="Hello World"> <button>Hello World</button> </Tooltip>, ); const children = getTargetChildren(wrapper); children.simulate('touchStart', { type: 'touchstart', persist }); children.simulate('touchEnd', { type: 'touchend', persist }); children.simulate('focus', { type: 'focus' }); children.simulate('mouseover', { type: 'mouseover' }); assert.strictEqual(wrapper.state().open, false); }); it('should open on long press', () => { const wrapper = shallow( <Tooltip title="Hello World"> <button>Hello World</button> </Tooltip>, ); const children = getTargetChildren(wrapper); children.simulate('touchStart', { type: 'touchstart', persist }); children.simulate('focus', { type: 'focus' }); children.simulate('mouseover', { type: 'mouseover' }); clock.tick(1e3); assert.strictEqual(wrapper.state().open, true); children.simulate('touchEnd', { type: 'touchend', persist }); clock.tick(1500); assert.strictEqual(wrapper.state().open, false); }); }); describe('mount', () => { it('should mount without any issue', () => { mount( <Tooltip title="Hello World" PopperProps={{ component: Hack }}> <button>Hello World</button> </Tooltip>, ); }); }); describe('prop: delay', () => { let clock; before(() => { clock = useFakeTimers(); }); after(() => { clock.restore(); }); it('should take the enterDelay into account', () => { const wrapper = shallow( <Tooltip enterDelay={111} title="Hello World"> <button>Hello World</button> </Tooltip>, ); const children = getTargetChildren(wrapper); children.simulate('focus', { type: 'focus', persist }); assert.strictEqual(wrapper.state().open, false); clock.tick(111); assert.strictEqual(wrapper.state().open, true); }); it('should take the leaveDelay into account', () => { const wrapper = shallow( <Tooltip leaveDelay={111} title="Hello World"> <button>Hello World</button> </Tooltip>, ); const children = getTargetChildren(wrapper); children.simulate('focus', { type: 'focus' }); assert.strictEqual(wrapper.state().open, true); children.simulate('blur', { type: 'blur', persist }); assert.strictEqual(wrapper.state().open, true); clock.tick(111); assert.strictEqual(wrapper.state().open, false); }); }); describe('prop: overrides', () => { ['onTouchStart', 'onTouchEnd', '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 {...{ [name]: handler }}>Hello World</button> </Tooltip>, ); const children = getTargetChildren(wrapper); const type = name.slice(2).toLowerCase(); children.simulate(type, { type, persist }); assert.strictEqual(handler.callCount, 1); }); }, ); }); describe('resize', () => { let clock; before(() => { clock = useFakeTimers(); }); after(() => { clock.restore(); }); it('should recompute the correct position', () => { const handleUpdate = spy(); const wrapper = mount( <TooltipNaked theme={{}} classes={{}} title="foo" PopperProps={{ component: Hack }}> <div>Foo</div> </TooltipNaked>, ); const instance = wrapper.instance(); instance.handleResize(); assert.strictEqual(handleUpdate.callCount, 0); clock.tick(1); instance.popper._popper.scheduleUpdate = handleUpdate; clock.tick(165); assert.strictEqual(handleUpdate.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 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/, ); }); }); });