import React, { useState } from 'react'; import { mount } from 'enzyme'; import { MailOutlined, InboxOutlined, AppstoreOutlined, PieChartOutlined, UserOutlined, } from '@ant-design/icons'; import { act } from 'react-dom/test-utils'; import Menu from '..'; import Layout from '../../layout'; import Tooltip from '../../tooltip'; import mountTest from '../../../tests/shared/mountTest'; import rtlTest from '../../../tests/shared/rtlTest'; import collapseMotion from '../../_util/motion'; import { sleep } from '../../../tests/utils'; const { SubMenu } = Menu; const noop = () => {}; const expectSubMenuBehavior = (menu, enter = noop, leave = noop) => { if (!menu.prop('openKeys') && !menu.prop('defaultOpenKeys')) { expect(menu.find('.ant-menu-sub').length).toBe(0); } menu.update(); expect(menu.find('.ant-menu-sub').length).toBe(0); const AnimationClassNames = { horizontal: 'ant-slide-up-leave', inline: 'ant-motion-collapse-leave', vertical: 'ant-zoom-big-leave', }; const mode = menu.prop('mode') || 'horizontal'; enter(); menu.update(); function getSubMenu() { if (mode === 'inline') { return menu.find('.ant-menu-sub.ant-menu-inline').hostNodes().at(0); } return menu.find('.ant-menu-submenu-popup').hostNodes().at(0); } expect( getSubMenu().hasClass('ant-menu-hidden') || getSubMenu().hasClass(AnimationClassNames[mode]), ).toBe(false); leave(); menu.update(); expect( getSubMenu().hasClass('ant-menu-hidden') || getSubMenu().hasClass(AnimationClassNames[mode]), ).toBe(true); }; describe('Menu', () => { window.requestAnimationFrame = callback => window.setTimeout(callback, 16); window.cancelAnimationFrame = window.clearTimeout; mountTest(() => (
)); mountTest(() => ( )); rtlTest(() => ( )); beforeEach(() => { jest.useFakeTimers(); }); afterEach(() => { jest.useRealTimers(); }); it('If has select nested submenu item ,the menu items on the grandfather level should be highlight', () => { const wrapper = mount( , ); expect(wrapper.find('.ant-menu-submenu-selected').length).toBe(1); }); it('should accept defaultOpenKeys in mode horizontal', () => { const wrapper = mount( , ); expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true); }); it('should accept defaultOpenKeys in mode inline', () => { const wrapper = mount( , ); expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true); }); it('should accept defaultOpenKeys in mode vertical', () => { const wrapper = mount( , ); expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true); }); it('should accept openKeys in mode horizontal', () => { const wrapper = mount( , ); expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true); }); it('should accept openKeys in mode inline', () => { const wrapper = mount( , ); expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true); }); it('should accept openKeys in mode vertical', () => { const wrapper = mount( , ); expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true); }); it('test submenu in mode horizontal', () => { const wrapper = mount( , ); expectSubMenuBehavior( wrapper, () => wrapper.setProps({ openKeys: ['1'] }), () => wrapper.setProps({ openKeys: [] }), ); }); it('test submenu in mode inline', () => { const wrapper = mount( , ); expectSubMenuBehavior( wrapper, () => wrapper.setProps({ openKeys: ['1'] }), () => wrapper.setProps({ openKeys: [] }), ); }); it('test submenu in mode vertical', () => { const wrapper = mount( , ); expectSubMenuBehavior( wrapper, () => wrapper.setProps({ openKeys: ['1'] }), () => wrapper.setProps({ openKeys: [] }), ); }); // https://github.com/ant-design/ant-design/pulls/4677 // https://github.com/ant-design/ant-design/issues/4692 // TypeError: Cannot read property 'indexOf' of undefined it('pr #4677 and issue #4692', () => { const wrapper = mount( , ); wrapper.update(); // just expect no error emit }); it('should always follow openKeys when mode is switched', () => { const wrapper = mount( , ); expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).toBe(false); wrapper.setProps({ mode: 'vertical' }); expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).toBe(false); wrapper.setProps({ mode: 'inline' }); expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).toBe(false); }); it('should always follow openKeys when inlineCollapsed is switched', () => { const wrapper = mount( , ); expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-inline')).toBe(true); expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).toBe(false); wrapper.setProps({ inlineCollapsed: true }); // 动画结束后套样式; jest.runAllTimers(); wrapper.update(); wrapper.simulate('transitionEnd', { propertyName: 'width' }); act(() => { jest.runAllTimers(); wrapper.update(); }); expect(wrapper.find('ul.ant-menu-root').at(0).hasClass('ant-menu-vertical')).toBe(true); expect(wrapper.find('ul.ant-menu-sub:not(.ant-menu-hidden)').length).toBe(0); wrapper.setProps({ inlineCollapsed: false }); jest.runAllTimers(); wrapper.update(); expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-inline')).toBe(true); expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).toBe(false); }); it('inlineCollapsed should works well when specify a not existed default openKeys', () => { const wrapper = mount( , ); expect(wrapper.find('.ant-menu-sub').length).toBe(0); wrapper.setProps({ inlineCollapsed: true }); jest.runAllTimers(); wrapper.update(); wrapper.simulate('transitionEnd', { propertyName: 'width' }); act(() => { jest.runAllTimers(); wrapper.update(); }); wrapper.find('.ant-menu-submenu-title').at(0).simulate('mouseEnter'); jest.runAllTimers(); wrapper.update(); expect(wrapper.find('.ant-menu-submenu').at(0).hasClass('ant-menu-submenu-vertical')).toBe( true, ); expect(wrapper.find('.ant-menu-submenu').at(0).hasClass('ant-menu-submenu-open')).toBe(true); expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-vertical')).toBe(true); expect(wrapper.find('ul.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).toBe(false); }); it('inlineCollapsed Menu.Item Tooltip can be removed', () => { const wrapper = mount( , ); expect(wrapper.find(Menu.Item).at(0).find(Tooltip).props().title).toBe('item'); expect(wrapper.find(Menu.Item).at(1).find(Tooltip).props().title).toBe('title'); expect(wrapper.find(Menu.Item).at(2).find(Tooltip).props().title).toBe('item'); expect(wrapper.find(Menu.Item).at(3).find(Tooltip).props().title).toBe(null); expect(wrapper.find(Menu.Item).at(4).find(Tooltip).props().title).toBe(''); expect(wrapper.find(Menu.Item).at(4).find(Tooltip).props().title).toBe(''); }); describe('open submenu when click submenu title', () => { beforeEach(() => { jest.useFakeTimers(); }); afterEach(() => { jest.useRealTimers(); }); const toggleMenu = (wrapper, index, event) => { wrapper.find('.ant-menu-submenu-title').at(index).simulate(event); jest.runAllTimers(); wrapper.update(); }; it('inline', () => { const wrapper = mount( , ); expectSubMenuBehavior( wrapper, () => toggleMenu(wrapper, 0, 'click'), () => toggleMenu(wrapper, 0, 'click'), ); }); it('inline menu collapseMotion should be triggered', async () => { jest.useRealTimers(); const onAppearEnd = jest.spyOn(collapseMotion, 'onAppearEnd'); collapseMotion.motionDeadline = 1; const wrapper = mount( , ); wrapper.find('.ant-menu-submenu-title').simulate('click'); await sleep(3000); expect(onAppearEnd).toHaveBeenCalledTimes(1); onAppearEnd.mockRestore(); }); it('vertical with hover(default)', () => { const wrapper = mount( , ); expectSubMenuBehavior( wrapper, () => toggleMenu(wrapper, 0, 'mouseenter'), () => toggleMenu(wrapper, 0, 'mouseleave'), ); }); it('vertical with click', () => { const wrapper = mount( , ); expectSubMenuBehavior( wrapper, () => toggleMenu(wrapper, 0, 'click'), () => toggleMenu(wrapper, 0, 'click'), ); }); it('horizontal with hover(default)', () => { jest.useFakeTimers(); const wrapper = mount( , ); expectSubMenuBehavior( wrapper, () => toggleMenu(wrapper, 0, 'mouseenter'), () => toggleMenu(wrapper, 0, 'mouseleave'), ); }); it('horizontal with click', () => { jest.useFakeTimers(); const wrapper = mount( , ); expectSubMenuBehavior( wrapper, () => toggleMenu(wrapper, 0, 'click'), () => toggleMenu(wrapper, 0, 'click'), ); }); }); it('inline title', () => { jest.useFakeTimers(); const wrapper = mount( , ); wrapper.find('.ant-menu-item').simulate('mouseenter'); act(() => { jest.runAllTimers(); }); wrapper.update(); const text = wrapper.find('.ant-tooltip-inner').text(); expect(text).toBe('bamboo lucky'); jest.useRealTimers(); }); it('render correctly when using with Layout.Sider', () => { class Demo extends React.Component { state = { collapsed: false, }; onCollapse = collapsed => this.setState({ collapsed }); render() { const { collapsed } = this.state; return (