trunk/pc4public/portal/_rc/_rc-menu-7.0.3/tests/SubMenu.spec.js

360 lines
11 KiB
JavaScript

/* eslint-disable no-undef */
import React from 'react';
import PropTypes from 'prop-types';
import { mount } from 'enzyme';
import KeyCode from 'rc-util/lib/KeyCode';
import Menu, { MenuItem, SubMenu } from '../src';
describe('SubMenu', () => {
beforeAll(() => {
jest.useFakeTimers();
});
afterAll(() => {
});
function createMenu(props) {
return (
<Menu {...props}>
<SubMenu key="s1" title="submenu1">
<MenuItem key="s1-1">1</MenuItem>
<SubMenu key="s1-2" title="submenu1-1">
<MenuItem key="s1-2-1">2</MenuItem>
</SubMenu>
</SubMenu>
<SubMenu key="s2" title="submenu2">
<MenuItem key="s2-2">2</MenuItem>
</SubMenu>
</Menu>
);
}
it('don\'t show submenu when disabled', () => {
const wrapper = mount(
<Menu mode="vertical">
<SubMenu key="s" title="submenu" disabled>
<MenuItem key="1">1</MenuItem>
</SubMenu>
</Menu>,
);
wrapper.find('.rc-menu-submenu-title').first().simulate('mouseEnter');
expect(wrapper.instance().store.getState().openKeys).toEqual([]);
});
it('offsets the submenu popover', () => {
const wrapper = mount(
<Menu mode="horizontal">
<SubMenu key="s" title="submenu" popupOffset={[0, 15]}>
<MenuItem key="1">1</MenuItem>
</SubMenu>
</Menu>,
);
const popupAlign = wrapper.find('Trigger').prop('popupAlign');
expect(popupAlign).toEqual({ offset: [0, 15] });
});
describe('openSubMenuOnMouseEnter and closeSubMenuOnMouseLeave are true', () => {
it('toggles when mouse enter and leave', () => {
const wrapper = mount(createMenu());
wrapper.find('.rc-menu-submenu-title').first().simulate('mouseEnter');
jest.runAllTimers();
expect(wrapper.instance().store.getState().openKeys).toEqual(['s1']);
wrapper.find('.rc-menu-submenu-title').first().simulate('mouseLeave');
jest.runAllTimers();
expect(wrapper.instance().store.getState().openKeys).toEqual([]);
});
});
describe('openSubMenuOnMouseEnter and closeSubMenuOnMouseLeave are false', () => {
let wrapper;
beforeEach(() => {
wrapper = mount(createMenu({
triggerSubMenuAction: 'click',
}));
});
it('toggles when mouse click', () => {
wrapper.find('.rc-menu-submenu-title').first().simulate('click');
expect(wrapper.instance().store.getState().openKeys).toEqual(['s1']);
wrapper.find('.rc-menu-submenu-title').first().simulate('click');
expect(wrapper.instance().store.getState().openKeys).toEqual([]);
});
});
it('fires openChange event', () => {
const handleOpenChange = jest.fn();
const wrapper = mount(
<Menu onOpenChange={handleOpenChange}>
<MenuItem key="1">1</MenuItem>
<SubMenu title="s1">
<MenuItem key="2">2</MenuItem>
<SubMenu title="s2">
<MenuItem key="3">3</MenuItem>
</SubMenu>
</SubMenu>
</Menu>,
);
wrapper.find('.rc-menu-submenu-title').at(0).simulate('mouseEnter');
jest.runAllTimers();
expect(handleOpenChange).toBeCalledWith(['item_1']);
wrapper.update();
wrapper.find('.rc-menu-submenu-title').at(1).simulate('mouseEnter');
jest.runAllTimers();
expect(handleOpenChange).toBeCalledWith(['item_1', 'item_1-menu-item_1']);
});
describe('mouse events', () => {
it('mouse enter event on a submenu should not activate first item', () => {
const wrapper = mount(createMenu({ openKeys: ['s1'] }));
const title = wrapper.find('.rc-menu-submenu-title').first();
title.simulate('mouseEnter');
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('.rc-menu-sub').first().is('.rc-menu-hidden')).toBe(false);
expect(wrapper.find('MenuItem').first().props().active).toBe(false);
});
it('click to open a submenu should not activate first item', () => {
const wrapper = mount(createMenu({ triggerSubMenuAction: 'click' }));
const subMenuTitle = wrapper.find('.rc-menu-submenu-title').first();
subMenuTitle.simulate('click');
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('.rc-menu-sub').first().is('.rc-menu-hidden')).toBe(false);
expect(wrapper.find('MenuItem').first().props().active).toBe(false);
});
it('mouse enter/mouse leave on a subMenu item should trigger hooks', () => {
const onMouseEnter = jest.fn();
const onMouseLeave = jest.fn();
const wrapper = mount(
<Menu openKeys={['s1']}>
<SubMenu
key="s1"
title="submenu1"
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
<MenuItem key="s1-1">1</MenuItem>
</SubMenu>
</Menu>,
);
const subMenu = wrapper.find('.rc-menu-submenu').first();
subMenu.simulate('mouseEnter');
expect(onMouseEnter).toHaveBeenCalledTimes(1);
subMenu.simulate('mouseLeave');
expect(onMouseLeave).toHaveBeenCalledTimes(1);
});
});
describe('key press', () => {
describe('enter key', () => {
it('opens menu and active first item', () => {
const wrapper = mount(createMenu());
const title = wrapper.find('.rc-menu-submenu-title').first();
title.simulate('mouseEnter').simulate('keyDown', { keyCode: KeyCode.ENTER });
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('.rc-menu-sub').first().is('.rc-menu-hidden')).toBe(false);
expect(wrapper.find('MenuItem').first().props().active).toBe(true);
});
});
describe('left & right key', () => {
it('toggles menu', () => {
const wrapper = mount(createMenu({ defaultActiveFirst: true }));
const title = wrapper.find('.rc-menu-submenu-title').first();
title.simulate('mouseEnter').simulate('keyDown', { keyCode: KeyCode.LEFT });
expect(wrapper.instance().store.getState().openKeys).toEqual([]);
title.simulate('keyDown', { keyCode: KeyCode.RIGHT });
expect(wrapper.instance().store.getState().openKeys).toEqual(['s1']);
expect(wrapper.find('MenuItem').first().props().active).toBe(true);
});
});
it('up & down key', () => {
const wrapper = mount(createMenu());
const titles = wrapper.find('.rc-menu-submenu-title');
titles.first().simulate('mouseEnter')
.simulate('keyDown', { keyCode: KeyCode.LEFT })
.simulate('keyDown', { keyCode: KeyCode.DOWN });
expect(wrapper.find('.rc-menu-submenu').last().is('.rc-menu-submenu-active')).toBe(true);
titles.last().simulate('keyDown', { keyCode: KeyCode.UP });
expect(wrapper.find('.rc-menu-submenu').first().is('.rc-menu-submenu-active')).toBe(true);
});
it('combined key presses', () => {
const wrapper = mount(createMenu());
const titles = wrapper.find('.rc-menu-submenu-title');
const firstItem = titles.first();
// testing keydown event after submenu is closed and then opened again
firstItem.simulate('mouseEnter')
.simulate('keyDown', { keyCode: KeyCode.RIGHT })
.simulate('keyDown', { keyCode: KeyCode.LEFT })
.simulate('keyDown', { keyCode: KeyCode.RIGHT })
.simulate('keyDown', { keyCode: KeyCode.DOWN })
.simulate('keyDown', { keyCode: KeyCode.DOWN })
.simulate('keyDown', { keyCode: KeyCode.DOWN });
expect(
wrapper
.find('[title="submenu1-1"]')
.find('.rc-menu-submenu')
.first()
.is('.rc-menu-submenu-active'),
).toBe(true);
});
});
it('fires select event', () => {
const handleSelect = jest.fn();
const wrapper = mount(createMenu({ onSelect: handleSelect }));
wrapper.find('.rc-menu-submenu-title').first().simulate('mouseEnter');
jest.runAllTimers();
wrapper.update();
wrapper.find('MenuItem').first().simulate('click');
expect(handleSelect.mock.calls[0][0].key).toBe('s1-1');
});
it('fires select event', () => {
const wrapper = mount(createMenu());
wrapper.find('.rc-menu-submenu-title').first().simulate('mouseEnter');
jest.runAllTimers();
wrapper.update();
wrapper.find('MenuItem').first().simulate('click');
expect(wrapper.find('.rc-menu-submenu').first().is('.rc-menu-submenu-selected')).toBe(true);
});
it('fires deselect event for multiple menu', () => {
const handleDeselect = jest.fn();
const wrapper = mount(createMenu({
multiple: true,
onDeselect: handleDeselect,
}));
wrapper.find('.rc-menu-submenu-title').first().simulate('mouseEnter');
jest.runAllTimers();
wrapper.update();
wrapper.find('MenuItem').first().simulate('click');
wrapper.find('MenuItem').first().simulate('click');
expect(handleDeselect.mock.calls[0][0].key).toBe('s1-1');
});
describe('horizontal menu', () => {
it('should automatically adjust width', () => {
const props = {
mode: 'horizontal',
openKeys: ['s1'],
};
const wrapper = mount(
<Menu {...props}>
<MenuItem key="1">1</MenuItem>
<SubMenu title="s1" key="s1">
<MenuItem key="2">2</MenuItem>
</SubMenu>
</Menu>,
);
const subMenuInstance = wrapper.find('SubMenu').first().instance();
const adjustWidthSpy = jest.spyOn(subMenuInstance, 'adjustWidth');
jest.runAllTimers();
expect(adjustWidthSpy).toHaveBeenCalledTimes(2);
});
});
describe('submenu animation', () => {
const appear = () => {};
it('should animate with transition class', () => {
const wrapper = mount(createMenu({
openTransitionName: 'fade',
mode: 'inline',
}));
const title = wrapper.find('.rc-menu-submenu-title').first();
title.simulate('click');
jest.runAllTimers();
expect(wrapper.find('Animate').prop('transitionName')).toEqual('fade');
});
it('should animate on initially opened menu', () => {
const wrapper = mount(createMenu({
openAnimation: { appear },
mode: 'inline',
openKeys: ['s1'],
}));
expect(wrapper.find('Animate').first().prop('animation')).toEqual({ appear });
});
it('should animate with config', () => {
const wrapper = mount(createMenu({
openAnimation: { appear },
mode: 'inline',
}));
const title = wrapper.find('.rc-menu-submenu-title').first();
title.simulate('click');
jest.runAllTimers();
expect(wrapper.find('Animate').first().prop('animation')).toEqual({ appear });
});
});
describe('.componentWillUnmount()', () => {
it('should invoke hooks', () => {
const onDestroy = jest.fn();
const App = props => (
<Menu>
{props.show && <SubMenu key="s1" title="submenu1" onDestroy={onDestroy}>
<MenuItem key="s1-1">1</MenuItem>
</SubMenu>}
</Menu>
);
App.propTypes = {
show: PropTypes.bool,
};
const wrapper = mount(<App show />);
wrapper.setProps({ show: false });
expect(onDestroy).toHaveBeenCalledWith('s1');
});
});
});