wix-style-react
Version:
wix-style-react
416 lines (359 loc) • 12.1 kB
JavaScript
import React from 'react';
import ReactTestUtils from 'react-dom/test-utils';
import tooltipDriverFactory from './Tooltip.driver';
import Tooltip from './Tooltip';
import { createDriverFactory } from 'wix-ui-test-utils/driver-factory';
import {
buttonTestkitFactory,
backofficeTooltipTestkitFactory as tooltipTestkitFactory,
} from '../../../testkit';
import { backofficeTooltipTestkitFactory as enzymeTooltipTestkitFactory } from '../../../testkit/enzyme';
import { mount } from 'enzyme';
import Button from '../Button';
import waitForCond from 'wait-for-cond';
import { rangePolyfill } from '../../../testkit/polyfills';
import { createRendererWithDriver, cleanup } from '../../../test/utils/react';
import { eventually } from '../../../test/utils/unit';
describe('Tooltip', () => {
const render = createRendererWithDriver(tooltipDriverFactory);
const createDriver = createDriverFactory(tooltipDriverFactory);
const _props = {
showDelay: 5,
hideDelay: 5,
content: <div>Some content</div>,
};
const children = <div>foo children</div>;
beforeEach(() => {
document.body.innerHTML = '';
rangePolyfill.install();
});
afterEach(() => {
rangePolyfill.uninstall();
cleanup();
});
it('should be hidden by default', () => {
const driver = createDriver(<Tooltip {..._props}>{children}</Tooltip>);
expect(driver.isShown()).toBeFalsy();
});
it('should show a tooltip once hovering', () => {
const driver = createDriver(<Tooltip {..._props}>{children}</Tooltip>);
driver.mouseEnter();
expect(driver.isShown()).toBeFalsy();
return waitFor.assert(() => expect(driver.isShown()).toBeTruthy());
});
it('should hide when mouse leaving', () => {
const driver = createDriver(<Tooltip {..._props}>{children}</Tooltip>);
driver.mouseEnter();
expect(driver.isShown()).toBeFalsy();
return waitFor
.assert(() => expect(driver.isShown()).toBeTruthy())
.then(() => driver.mouseLeave())
.then(() => waitFor.assert(() => expect(driver.isShown()).toBeFalsy()));
});
it('click triggers', () => {
const driver = createDriver(
<Tooltip {...{ ..._props, showTrigger: 'click', hideTrigger: 'click' }}>
{children}
</Tooltip>,
);
driver.click();
return waitFor
.assert(() => expect(driver.isShown()).toBeTruthy())
.then(() => {
driver.click();
return waitFor.assert(() => expect(driver.isShown()).toBeFalsy());
});
});
it('show on focus, hide on blur', () => {
const driver = createDriver(
<Tooltip {...{ ..._props, showTrigger: 'focus', hideTrigger: 'blur' }}>
<input />
</Tooltip>,
);
driver.focus();
return waitFor
.assert(() => expect(driver.isShown()).toBeTruthy())
.then(() => {
driver.blur();
return waitFor.assert(() => expect(driver.isShown()).toBeFalsy());
});
});
it('hover trigger is disabled in click mode', () => {
const driver = createDriver(
<Tooltip {...{ ..._props, showTrigger: 'click', hideTrigger: 'click' }}>
{children}
</Tooltip>,
);
driver.mouseEnter();
return waitFor.assertHold(() => expect(driver.isShown()).toBeFalsy(), 300);
});
it('custom mode - mouse enter does not hide', () => {
const driver = createDriver(
<Tooltip
{...{ ..._props, showTrigger: 'custom', hideTrigger: 'custom' }}
active
>
<input />
</Tooltip>,
);
expect(driver.isShown()).toBeTruthy();
driver.mouseEnter();
return waitFor.assertHold(() => expect(driver.isShown()).toBeTruthy());
});
it('focus and blur triggers', () => {
const driver = createDriver(
<Tooltip {...{ ..._props, showTrigger: 'focus', hideTrigger: 'blur' }}>
<input />
</Tooltip>,
);
driver.focus();
return waitFor
.assert(() => expect(driver.isShown()).toBeTruthy())
.then(() => {
driver.blur();
return waitFor.assert(() => expect(driver.isShown()).toBeFalsy());
});
});
it('should hide tooltip when using custom triggers', async () => {
const props = { ..._props, hideTrigger: 'custom', showTrigger: 'custom' };
const { driver, rerender } = render(
<Tooltip {...props}>{children}</Tooltip>,
);
driver.mouseEnter();
expect(driver.isShown()).toBeFalsy();
rerender(
<Tooltip {...props} active>
{children}
</Tooltip>,
);
await eventually(() => {
expect(driver.isShown()).toBeTruthy();
});
rerender(
<Tooltip {...props} active={false}>
{children}
</Tooltip>,
);
await eventually(() => {
expect(driver.isShown()).toBeFalsy();
});
});
it('should test inner component', () => {
const dataHook = 'button_data_hook';
const buttonContent = (
<div>
Custom Content...
<Button dataHook={dataHook} id="inner-button" height="small">
Button content
</Button>
</div>
);
const driver = createDriver(
<Tooltip showDelay={5} hideDelay={5} content={buttonContent}>
{children}
</Tooltip>,
);
driver.mouseEnter();
expect(driver.isShown()).toBeFalsy();
return waitFor
.assert(() => expect(driver.isShown()).toBeTruthy())
.then(() => {
const buttonTestkit = buttonTestkitFactory({
wrapper: driver.getTooltipWrapper(),
dataHook,
});
expect(buttonTestkit.getButtonTextContent()).toBe('Button content');
});
});
it('should not override focus event', () => {
const onFocus = jest.fn();
const onFocusedChild = <div onFocus={onFocus}>foo children</div>;
const driver = createDriver(
<Tooltip {..._props}>{onFocusedChild}</Tooltip>,
);
driver.focus();
expect(onFocus).toBeCalled();
});
it('should not override blur event', () => {
const onBlur = jest.fn();
const onBluredChild = <div onBlur={onBlur}>foo children</div>;
const driver = createDriver(<Tooltip {..._props}>{onBluredChild}</Tooltip>);
driver.blur();
expect(onBlur).toBeCalled();
});
it('should not override click event', () => {
const onClick = jest.fn();
const onClickedChild = <div onClick={onClick}>foo children</div>;
const driver = createDriver(
<Tooltip {..._props}>{onClickedChild}</Tooltip>,
);
driver.click();
expect(onClick).toBeCalled();
});
it('should not override mouse enter event', () => {
const onMouseEnter = jest.fn();
const onMouseEnteredChild = (
<div onMouseEnter={onMouseEnter}>foo children</div>
);
const driver = createDriver(
<Tooltip {..._props}>{onMouseEnteredChild}</Tooltip>,
);
driver.mouseEnter();
expect(onMouseEnter).toBeCalled();
});
it('should not override mouse leave event', () => {
const onMouseLeave = jest.fn();
const onMouseLeavedChild = (
<div onMouseLeave={onMouseLeave}>foo children</div>
);
const driver = createDriver(
<Tooltip {..._props}>{onMouseLeavedChild}</Tooltip>,
);
driver.mouseLeave();
expect(onMouseLeave).toBeCalled();
});
it('should support error theme', () => {
const driver = createDriver(
<Tooltip theme={'error'} {..._props}>
{children}
</Tooltip>,
);
driver.mouseEnter();
return waitFor.assert(() => expect(driver.hasErrorTheme()).toBeTruthy());
});
it('should support dark theme', () => {
const driver = createDriver(
<Tooltip theme={'dark'} {..._props}>
{children}
</Tooltip>,
);
driver.mouseEnter();
return waitFor.assert(() => expect(driver.hasDarkTheme()).toBeTruthy());
});
it('should support light theme', () => {
const driver = createDriver(
<Tooltip theme={'light'} {..._props}>
{children}
</Tooltip>,
);
driver.mouseEnter();
return waitFor.assert(() => expect(driver.hasLightTheme()).toBeTruthy());
});
it('should have children', () => {
const driver = createDriver(<Tooltip {..._props}>{children}</Tooltip>);
expect(driver.getChildren()).toContain('foo children');
});
it('should have a content', () => {
const driver = createDriver(<Tooltip {..._props}>{children}</Tooltip>);
driver.mouseEnter();
return waitFor.assert(() =>
expect(driver.getContent()).toEqual('<div>Some content</div>'),
);
});
it('should cancel mouse leave, when followed by mouse enter immediately', () => {
const driver = createDriver(<Tooltip {..._props}>{children}</Tooltip>);
driver.mouseEnter();
driver.mouseLeave();
driver.mouseEnter();
return waitFor.assert(() => expect(driver.isShown()).toBe(true));
});
it('should call onShow when tooltip is shown', () => {
const onShow = jest.fn();
const driver = createDriver(
<Tooltip {...{ ..._props, onShow }}>{children}</Tooltip>,
);
driver.mouseEnter();
expect(onShow).not.toHaveBeenCalled();
return waitFor.assert(() => expect(onShow).toHaveBeenCalled());
});
describe('placement attribute', () => {
it('should be top by default', () => {
const driver = createDriver(
<Tooltip {...{ ..._props }}>{children}</Tooltip>,
);
driver.mouseEnter();
return waitFor.assert(() => expect(driver.getPlacement()).toEqual('top'));
});
['top', 'bottom', 'left', 'right'].forEach(placement => {
it(`should be ${placement}`, () => {
const driver = createDriver(
<Tooltip {...{ ..._props }} placement={placement}>
{children}
</Tooltip>,
);
driver.mouseEnter();
return waitFor.assert(() =>
expect(driver.getPlacement()).toBe(placement),
);
});
});
xit('show with delay and immediately hide', () => {
const driver = createDriver(
<Tooltip {...{ ..._props, hideDelay: 0, showDelay: 50 }}>
{children}
</Tooltip>,
);
driver.mouseEnter();
driver.mouseLeave();
return waitFor.assertHold(() => expect(driver.isShown()).toBeFalsy());
});
});
describe('testkit', () => {
it('should exist', () => {
const div = document.createElement('div');
const dataHook = 'myDataHook';
const wrapper = div.appendChild(
ReactTestUtils.renderIntoDocument(
<div>
<Tooltip dataHook={dataHook} {..._props}>
{children}
</Tooltip>
</div>,
),
);
const driver = tooltipTestkitFactory({ wrapper, dataHook });
driver.mouseEnter();
expect(driver.isShown()).toBeFalsy();
return waitFor.assert(() => expect(driver.isShown()).toBeTruthy());
});
});
describe('enzyme testkit', () => {
it('should exist', () => {
const dataHook = 'myDataHook';
const wrapper = mount(
<Tooltip dataHook={dataHook} {..._props}>
{children}
</Tooltip>,
);
const driver = enzymeTooltipTestkitFactory({ wrapper, dataHook });
driver.mouseEnter();
expect(driver.isShown()).toBeFalsy();
return waitFor.assert(() => expect(driver.isShown()).toBeTruthy());
});
it.skip('should remove a tooltip immediately once the component is destroyed', () => {
const dataHook = 'myDataHook';
const wrapper = mount(
<Tooltip dataHook={dataHook} {..._props} hideDelay={1000}>
{children}
</Tooltip>,
);
const driver = enzymeTooltipTestkitFactory({ wrapper, dataHook });
driver.mouseEnter();
return waitFor
.assert(() => expect(driver.isShown()).toBeTruthy())
.then(() => {
wrapper.unmount();
expect(driver.isShown()).toBeFalsy();
});
});
});
});
function waitFor(predicate, msg) {
return waitForCond(predicate, 2000, msg);
}
waitFor.assert = function(fn) {
return waitForCond.assert(fn, 2000);
};
waitFor.assertHold = function(fn) {
return waitForCond.assertHold(fn, 500);
};