/* 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 (
); } it('don\'t show submenu when disabled', () => { const wrapper = mount( , ); wrapper.find('.rc-menu-submenu-title').first().simulate('mouseEnter'); expect(wrapper.instance().store.getState().openKeys).toEqual([]); }); it('offsets the submenu popover', () => { const wrapper = mount( , ); 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( , ); 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( , ); 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( , ); 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 => ( ); App.propTypes = { show: PropTypes.bool, }; const wrapper = mount(