ant-design/components/menu/__tests__/index.test.js
陈帅 523b74e3b6
merge master into Feature (#25262)
* feat: add successColor for Progress (#24655)

* feat: add successColor for Progress

* feat: update

* fix: update test

* remove snap

* feat: add test case

* refactor success

* feat: adjust styyle

* feat: add DevWarning

* feat: Support rowSelection.dirty (#24718)

* feat: Support rowSelection.dirty

* rename to reserveKeys

* preserveKeys will keep record also

* to preserveSelectedRowKeys

* feat: add ghost prop for collapse (#24734)

* feat: add ghost prop for collapse

* doc: version of collapse's ghost prop

* refactor: make ghost collapse's less code to a nested style

* chore: remove redundant codes in ghost collapse's less & doc

* doc: add a background wrapper for ghost collapse demo

* doc: dark-theme wrapper bg-color for ghost collapse demo

* test: update snapshot of ghost collapse

* doc: use softer bg-color on ghost collapse demo

* doc: remove disabled panel in ghost collapse demo

* feat: form instance support getFieldInstance (#24711)

* support getFieldInstance

* update doc

* fix lint

* move func

* move into hooks

* update ref logic

* fix lint

* rm only

* fix docs

* feat: dropdown support arrow (#23869)

* feat: dropdown support arrow prop

close #22758

* test: update snapshot

* fix: fix dropdown cls names

* test: update snapshot

* test: update snapshot

* doc: update demo

* test: update demo snapshot

* demo

* fix: snapshot

* chore: change the style of ghost collapse & demo modified (#24762)

* refactor: reduce content padding in ghost collapse

* doc: remove the wrapper outside ghost collapse

Designer want the demo differs from other demos

* refactor: remove redundant .less code in collapse

* feat: cascader dropdown-render prop (#24812)

* feat: cascader dropdown-render prop

* fix: update Cascader dropdownRender type annotation

* fix: set rc-cascader semver from ^ to ~

* docs: fix coding style in cascader/custom-dropdown

* feat: 🆕 support Drawer closeIcon (#24842)

* feat: 🆕 support Drawer closeIcon

close #19283
close #19153

* add test case

* update docs

* feat: 🆕 Cascader expandIcon (#24865)

* feat: cascader expandIcon

* fix: snap

* refactor: reduce CSS size (#24846)

* refactor: reduce button css size

* refactor: remove redundant button .less code

* feat: add Table onChange an action param (#24697)

* Working on tests

* created TableAction type

* changed TableActions to tuple

* removed chinese documentation line

* refactor TableActions

* fix documentation

* Moved action into extra param

* minor doc change

* feat: add closeIcon customize tag close (#24885)

* feat: add closeIcon customize tag close

* docs fix

* update snap

* fix: css name

* update snapshot

* snapshot

* feat: add radio `optionType` api to set radio option type (#24809)

* feat: radio component

* docs: update md

* fix: snap

* test components

* fix: use optionType

* fix name

* add warning

* fix

* feat: expand rate character (#24903)

* feat: expand rate character

* fix: demo

* fix: snap

* Update components/rate/index.zh-CN.md

Co-authored-by: 偏右 <afc163@gmail.com>

* fix

Co-authored-by: 偏右 <afc163@gmail.com>

* Refactor demo code box actions (#24887)

* refactor: refine the styling of actions part of demo code-box

* fix: lint style

* refactor: move Result children to end (#24945)

* feat: remove content max-width on dot-step (#24907)

* feat: add Skeleton-Image (#24805)

* feat: add Skeleton-Image

* feat: add docs

* fix: adjust skeleton

* feat: adjust Image Component

* feat: rebase

* feat: adjust style

* fix: lint

* feat: remove size

* feat: delete md

* feat: fix style

*  feat: Mentions support autoSize (#24961)

close #17746

* chore: replace textarea with rc-textarea (#24966)

* feat: update pagination@2.3.0 support onChange called when pageSize change (#24964)

* feat: update pagination@2.5.0 and add test case to relative component

* fix: lint

* delete

* feat: add test case for pagination

* adjust test case

* feat: Implement centered prop in Tabs (#24958)

* Implement centered in Tabs along with its tests and docs

* Fix build error

* Add Chinese translations and remove test case

Co-authored-by: Ashkan Pourghasem <ashkan.pourghasem@gmail.com>

* feat: Add modal style parameter (#24773)

* add some paramters in default.less

* Update components/style/themes/default.less

Co-authored-by: Amumu <yoyo837@hotmail.com>

* change parameter in compact.less

Co-authored-by: Crystal Gao <jinggao@ebay.com>
Co-authored-by: Amumu <yoyo837@hotmail.com>

* feat: export Tabs addIcon (#25006)

* feat: export Tabs addIcon

* update snapshot

* feat: showNow on timepicker and datetimepicker (#25032)

* feat: update rc-picker@1.7.1 and fix icons of month and quarter picker in DatePicker Component (#25035)

* feat: update rc-picker@1.7.1

* delete

* add

* feat: expand rate support props (#24993)

* docs: 📝 Add Form.Item hidden in doc (#25108)

close #25101

* fix: ⌨️ Improve Pagination accessibility issue (#25119)

* ⌨️ Improve Pagination a11y by fixing a W3C error

https://github.com/react-component/pagination/issues/280

* update snapshot

* 🆙 rc-pagination to 2.4.1

* feat: support triggerSubMenuAction for <Menu /> (#25127)

* feat(menu): add triggerSubMenuAction for Menu

* feat(menu): test cases

* chore: Adjust picker logic (#25135)

* chore: update rc-picker 1.10.0 (#25174)

* feat: table row check strictly (#24931)

* feat: add checkStrictly on Table.rowSelection

* fix: LGTM warnings

* test: table rowSelection.checkStrictly

* test: add cov [wip]

* refactor: tree.rowSelection.checkStrictly [wip]

* test: table.rowSelection.checkStrictly basic case

* feat: support rowKey on checkStrictly table

* feat: Table checkStrictly support getCheckboxProps

* docs: Table checkStrictly

* chore: typo

* chore: remove useless comment

* chore: update snapshot

* chore: update snapshot

* fix: fire selectAll on selection dropdown menu & changeRows incorrect in selectAll callback

* docs: typo

* chore

* chore

* fix: expand buttons of leaf rows in tree data are not hidden

* feat: Table warning about rowKey index parameter

* perf: only generate keyEntities when not checkStrictly

* refactor: remove useless parseCheckedKeys

* refactor: get derived selected & half selected keys from selectedRowKeys

* chore: remove env condition stmt

* chore: revert index usage & code formatting

* chore: rerun ci

* docs: table tree-data checkstrictly

* test: update snapshots

* refactor: use useMergedState hook

* chore: rerun ci

* chore: rerun ci 2

* chore: revert selection select all behavior

* refactor: refactor code based on feature

* chore: revert table code format

* chore: revert table code format

* fix: useMemo deps

* fix: useMemo deps

* fix: useMemo deps

* feat: support preserve (#25186)

* docs: add responsibly order for Col (#25139)

* feat: add type

* feat: add responsibly order cols

* feat: add docs

* feat: add test case

* fix test

Co-authored-by: 二货机器人 <smith3816@gmail.com>
Co-authored-by: 偏右 <afc163@gmail.com>
Co-authored-by: zoomdong <1344492820@qq.com>
Co-authored-by: 07akioni <07akioni2@gmail.com>
Co-authored-by: wendellhu <wendellhu95@gmail.com>
Co-authored-by: xrkffgg <xrkffgg@gmail.com>
Co-authored-by: Neto Braghetto <netow93@gmail.com>
Co-authored-by: Kermit Xuan <kermitlx@outlook.com>
Co-authored-by: Ashkan Pourghasem <64011067+ashkan-pm@users.noreply.github.com>
Co-authored-by: Ashkan Pourghasem <ashkan.pourghasem@gmail.com>
Co-authored-by: hicrystal <295247343@qq.com>
Co-authored-by: Crystal Gao <jinggao@ebay.com>
Co-authored-by: Amumu <yoyo837@hotmail.com>
Co-authored-by: Li Ming <armyiljfe@gmail.com>
2020-06-28 22:41:59 +08:00

718 lines
24 KiB
JavaScript

import React, { useState } from 'react';
import { mount } from 'enzyme';
import {
MailOutlined,
InboxOutlined,
AppstoreOutlined,
PieChartOutlined,
UserOutlined,
} from '@ant-design/icons';
import Menu from '..';
import Layout from '../../layout';
import Tooltip from '../../tooltip';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
import { resetWarned } from '../../_util/devWarning';
const { SubMenu } = Menu;
describe('Menu', () => {
mountTest(() => (
<Menu>
<Menu.Item />
<Menu.ItemGroup />
<Menu.SubMenu />
</Menu>
));
rtlTest(() => (
<Menu>
<Menu.Item />
<Menu.ItemGroup />
<Menu.SubMenu />
</Menu>
));
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(
<Menu defaultSelectedKeys={['1-3-2']} mode="vertical">
<SubMenu key="1" title="submenu1">
<Menu.Item key="1-1">Option 1</Menu.Item>
<Menu.Item key="1-2">Option 2</Menu.Item>
<SubMenu key="1-3" title="submenu1-3">
<Menu.Item key="1-3-1">Option 3</Menu.Item>
<Menu.Item key="1-3-2">Option 4</Menu.Item>
</SubMenu>
</SubMenu>
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(wrapper.find('.ant-menu-submenu-selected').length).toBe(1);
});
it('should accept defaultOpenKeys in mode horizontal', () => {
const wrapper = mount(
<Menu defaultOpenKeys={['1']} mode="horizontal">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
<Menu.Item key="submenu2">Option 2</Menu.Item>
</SubMenu>
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
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(
<Menu defaultOpenKeys={['1']} mode="inline">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
<Menu.Item key="submenu2">Option 2</Menu.Item>
</SubMenu>
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
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(
<Menu defaultOpenKeys={['1']} mode="vertical">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
<Menu.Item key="submenu2">Option 2</Menu.Item>
</SubMenu>
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
});
it('horizontal', () => {
const wrapper = mount(
<Menu openKeys={['1']} mode="horizontal" openTransitionName="">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
<Menu.Item key="submenu2">Option 2</Menu.Item>
</SubMenu>
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(
true,
);
wrapper.setProps({ openKeys: [] });
wrapper.update();
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).toBe(true);
wrapper.setProps({ openKeys: ['1'] });
wrapper.update();
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(
true,
);
});
it('inline', () => {
const wrapper = mount(
<Menu openKeys={['1']} mode="inline" openAnimation="">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
<Menu.Item key="submenu2">Option 2</Menu.Item>
</SubMenu>
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(
true,
);
wrapper.setProps({ openKeys: [] });
wrapper.update();
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).toBe(true);
wrapper.setProps({ openKeys: ['1'] });
wrapper.update();
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(
true,
);
});
it('vertical', () => {
const wrapper = mount(
<Menu openKeys={['1']} mode="vertical" openTransitionName="">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
<Menu.Item key="submenu2">Option 2</Menu.Item>
</SubMenu>
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(
true,
);
wrapper.setProps({ openKeys: [] });
wrapper.update();
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).toBe(true);
wrapper.setProps({ openKeys: ['1'] });
wrapper.update();
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(
true,
);
});
// 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(
<Menu mode="horizontal">
<SubMenu title="submenu">
<Menu.Item key="1">menu1</Menu.Item>
<Menu.Item key="2">menu2</Menu.Item>
</SubMenu>
</Menu>,
);
wrapper.update();
// just expect no error emit
});
it('should always follow openKeys when mode is switched', () => {
const wrapper = mount(
<Menu openKeys={['1']} mode="inline">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
<Menu.Item key="submenu2">Option 2</Menu.Item>
</SubMenu>
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
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(
<Menu defaultOpenKeys={['1']} mode="inline">
<Menu.Item key="menu1">
<InboxOutlined />
<span>Option</span>
</Menu.Item>
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option</Menu.Item>
<Menu.Item key="submenu2">Option</Menu.Item>
</SubMenu>
</Menu>,
);
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' });
expect(wrapper.find('ul.ant-menu-root').at(0).hasClass('ant-menu-vertical')).toBe(true);
expect(wrapper.find('ul.ant-menu-sub').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(
<Menu defaultOpenKeys={['not-existed']} mode="inline">
<Menu.Item key="menu1">
<InboxOutlined />
<span>Option</span>
</Menu.Item>
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option</Menu.Item>
<Menu.Item key="submenu2">Option</Menu.Item>
</SubMenu>
</Menu>,
);
expect(wrapper.find('.ant-menu-sub').length).toBe(0);
wrapper.setProps({ inlineCollapsed: true });
jest.runAllTimers();
wrapper.update();
wrapper.simulate('transitionEnd', { propertyName: 'width' });
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(
<Menu
defaultOpenKeys={['not-existed']}
mode="inline"
inlineCollapsed
getPopupContainer={node => node.parentNode}
>
<Menu.Item key="menu1">item</Menu.Item>
<Menu.Item key="menu2" title="title">
item
</Menu.Item>
<Menu.Item key="menu3" title={undefined}>
item
</Menu.Item>
<Menu.Item key="menu4" title={null}>
item
</Menu.Item>
<Menu.Item key="menu5" title="">
item
</Menu.Item>
<Menu.Item key="menu6" title={false}>
item
</Menu.Item>
</Menu>,
);
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(
<Menu mode="inline">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
<Menu.Item key="submenu2">Option 2</Menu.Item>
</SubMenu>
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(wrapper.find('.ant-menu-sub').length).toBe(0);
toggleMenu(wrapper, 0, 'click');
expect(wrapper.find('.ant-menu-sub').hostNodes().length).toBe(1);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(
true,
);
toggleMenu(wrapper, 0, 'click');
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).toBe(
true,
);
});
it('vertical with hover(default)', () => {
const wrapper = mount(
<Menu mode="vertical">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
<Menu.Item key="submenu2">Option 2</Menu.Item>
</SubMenu>
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(wrapper.find('.ant-menu-sub').length).toBe(0);
toggleMenu(wrapper, 0, 'mouseenter');
expect(wrapper.find('.ant-menu-sub').hostNodes().length).toBe(1);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(
true,
);
toggleMenu(wrapper, 0, 'mouseleave');
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).toBe(
true,
);
});
it('vertical with click', () => {
const wrapper = mount(
<Menu mode="vertical" triggerSubMenuAction="click">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
<Menu.Item key="submenu2">Option 2</Menu.Item>
</SubMenu>
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(wrapper.find('.ant-menu-sub').length).toBe(0);
toggleMenu(wrapper, 0, 'click');
expect(wrapper.find('.ant-menu-sub').hostNodes().length).toBe(1);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(
true,
);
toggleMenu(wrapper, 0, 'click');
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).toBe(
true,
);
});
it('horizontal with hover(default)', () => {
jest.useFakeTimers();
const wrapper = mount(
<Menu mode="horizontal">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
<Menu.Item key="submenu2">Option 2</Menu.Item>
</SubMenu>
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(wrapper.find('.ant-menu-sub').length).toBe(0);
toggleMenu(wrapper, 0, 'mouseenter');
expect(wrapper.find('.ant-menu-sub').hostNodes().length).toBe(1);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(
true,
);
toggleMenu(wrapper, 0, 'mouseleave');
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).toBe(
true,
);
});
it('horizontal with click', () => {
jest.useFakeTimers();
const wrapper = mount(
<Menu mode="horizontal" triggerSubMenuAction="click">
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
<Menu.Item key="submenu2">Option 2</Menu.Item>
</SubMenu>
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(wrapper.find('.ant-menu-sub').length).toBe(0);
toggleMenu(wrapper, 0, 'click');
expect(wrapper.find('.ant-menu-sub').hostNodes().length).toBe(1);
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).not.toBe(
true,
);
toggleMenu(wrapper, 0, 'click');
expect(wrapper.find('.ant-menu-sub').hostNodes().at(0).hasClass('ant-menu-hidden')).toBe(
true,
);
});
});
it('inline title', () => {
jest.useFakeTimers();
const wrapper = mount(
<Menu mode="inline" inlineCollapsed>
<Menu.Item key="1" title="bamboo lucky">
<PieChartOutlined />
<span>
Option 1
<img
style={{ width: 20 }}
alt="test"
src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
/>
</span>
</Menu.Item>
</Menu>,
);
wrapper.find('.ant-menu-item').simulate('mouseenter');
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 (
<Layout style={{ minHeight: '100vh' }}>
<Layout.Sider collapsible collapsed={collapsed} onCollapse={this.onCollapse}>
<div className="logo" />
<Menu theme="dark" defaultSelectedKeys={['1']} mode="inline">
<SubMenu
key="sub1"
title={
<span>
<UserOutlined />
<span>User</span>
</span>
}
>
<Menu.Item key="3">Tom</Menu.Item>
<Menu.Item key="4">Bill</Menu.Item>
<Menu.Item key="5">Alex</Menu.Item>
</SubMenu>
</Menu>
</Layout.Sider>
</Layout>
);
}
}
const wrapper = mount(<Demo />);
wrapper.find('.ant-menu-submenu-title').simulate('click');
wrapper.find('.ant-layout-sider-trigger').simulate('click');
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('.ant-menu-submenu-popup').length).toBe(0);
});
it('onMouseEnter should work', () => {
const onMouseEnter = jest.fn();
const wrapper = mount(
<Menu onMouseEnter={onMouseEnter} defaultSelectedKeys={['test1']}>
<Menu.Item key="test1">Navigation One</Menu.Item>
<Menu.Item key="test2">Navigation Two</Menu.Item>
</Menu>,
);
wrapper.find('Menu').at(1).simulate('mouseenter');
expect(onMouseEnter).toHaveBeenCalled();
});
describe('motion', () => {
it('get correct animation type when switched from inline', () => {
const wrapper = mount(<Menu mode="inline" />);
wrapper.setProps({ mode: 'horizontal' });
expect(wrapper.find('InternalMenu').instance().getOpenMotionProps('')).toEqual({
motion: { motionName: '' },
});
});
it('warning if use `openAnimation` as object', () => {
resetWarned();
const warnSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
mount(<Menu openAnimation={{}} />);
expect(warnSpy).toHaveBeenCalledWith(
'Warning: [antd: Menu] `openAnimation` do not support object. Please use `motion` instead.',
);
warnSpy.mockRestore();
});
it('motion object', () => {
const motion = { test: true };
const wrapper = mount(<Menu motion={motion} />);
expect(wrapper.find('InternalMenu').instance().getOpenMotionProps('')).toEqual({ motion });
});
it('legacy openTransitionName', () => {
const wrapper = mount(<Menu openTransitionName="legacy" />);
expect(wrapper.find('InternalMenu').instance().getOpenMotionProps('')).toEqual({
openTransitionName: 'legacy',
});
});
});
it('MenuItem should not render Tooltip when inlineCollapsed is false', () => {
const wrapper = mount(
<Menu defaultSelectedKeys={['mail']} defaultOpenKeys={['mail']} mode="horizontal">
<Menu.Item key="mail">
<MailOutlined />
Navigation One
</Menu.Item>
<Menu.Item key="app">
<AppstoreOutlined />
Navigation Two
</Menu.Item>
<Menu.Item key="alipay">
<a href="https://ant.design" target="_blank" rel="noopener noreferrer">
Navigation Four - Link
</a>
</Menu.Item>
</Menu>,
);
wrapper.find('MenuItem').first().simulate('mouseenter');
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('.ant-tooltip-inner').length).toBe(0);
});
it('MenuItem should render icon and icon should be the first child when icon exists', () => {
const wrapper = mount(
<Menu>
<Menu.Item key="mail" icon={<MailOutlined />}>
Navigation One
</Menu.Item>
</Menu>,
);
expect(wrapper.find('.ant-menu-item .anticon').hasClass('anticon-mail')).toBe(true);
});
it('should controlled collapse work', () => {
const wrapper = mount(
<Menu mode="inline" inlineCollapsed={false}>
<Menu.Item key="1">
<PieChartOutlined />
<span>Option 1</span>
</Menu.Item>
</Menu>,
);
expect(wrapper.render()).toMatchSnapshot();
wrapper.setProps({ inlineCollapsed: true });
expect(wrapper.render()).toMatchSnapshot();
});
it('not title if not collapsed', () => {
jest.useFakeTimers();
const wrapper = mount(
<Menu mode="inline" inlineCollapsed={false}>
<Menu.Item key="1">
<PieChartOutlined />
<span>Option 1</span>
</Menu.Item>
</Menu>,
);
wrapper.find('.ant-menu-item').simulate('mouseenter');
jest.runAllTimers();
wrapper.update();
expect(wrapper.find('.ant-tooltip-inner').length).toBeFalsy();
jest.useRealTimers();
});
it('props#onOpen and props#onClose do not warn anymore', () => {
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
const onOpen = jest.fn();
const onClose = jest.fn();
mount(
<Menu defaultOpenKeys={['1']} mode="inline" onOpen={onOpen} onClose={onClose}>
<SubMenu key="1" title="submenu1">
<Menu.Item key="submenu1">Option 1</Menu.Item>
<Menu.Item key="submenu2">Option 2</Menu.Item>
</SubMenu>
<Menu.Item key="2">menu2</Menu.Item>
</Menu>,
);
expect(errorSpy.mock.calls.length).toBe(1);
expect(errorSpy.mock.calls[0][0]).not.toContain(
'`onOpen` and `onClose` are removed, please use `onOpenChange` instead, see: https://u.ant.design/menu-on-open-change.',
);
expect(onOpen).not.toHaveBeenCalled();
expect(onClose).not.toHaveBeenCalled();
});
// https://github.com/ant-design/ant-design/issues/18825
// https://github.com/ant-design/ant-design/issues/8587
it('should keep selectedKeys in state when collapsed to 0px', () => {
jest.useFakeTimers();
const wrapper = mount(
<Menu
mode="inline"
inlineCollapsed={false}
defaultSelectedKeys={['1']}
collapsedWidth={0}
openKeys={['3']}
>
<Menu.Item key="1">Option 1</Menu.Item>
<Menu.Item key="2">Option 2</Menu.Item>
<Menu.SubMenu key="3" title="Option 3">
<Menu.Item key="4">Option 4</Menu.Item>
</Menu.SubMenu>
</Menu>,
);
expect(wrapper.find('.ant-menu-item-selected').getDOMNode().textContent).toBe('Option 1');
wrapper.find('.ant-menu-item').at(1).simulate('click');
expect(wrapper.find('.ant-menu-item-selected').getDOMNode().textContent).toBe('Option 2');
wrapper.setProps({ inlineCollapsed: true });
jest.runAllTimers();
wrapper.update();
expect(
wrapper
.find('Trigger')
.map(node => node.prop('popupVisible'))
.findIndex(node => !!node),
).toBe(-1);
wrapper.setProps({ inlineCollapsed: false });
expect(wrapper.find('.ant-menu-item-selected').getDOMNode().textContent).toBe('Option 2');
jest.useRealTimers();
});
it('Menu.Item with icon children auto wrap span', () => {
const wrapper = mount(
<Menu>
<Menu.Item key="1" icon={<MailOutlined />}>
Navigation One
</Menu.Item>
<Menu.Item key="2" icon={<MailOutlined />}>
<span>Navigation One</span>
</Menu.Item>
<Menu.SubMenu key="3" icon={<MailOutlined />} title="Navigation One" />
<Menu.SubMenu key="4" icon={<MailOutlined />} title={<span>Navigation One</span>} />
</Menu>,
);
expect(wrapper.render()).toMatchSnapshot();
});
// https://github.com/ant-design/ant-design/issues/23755
it('should trigger onOpenChange when collapse inline menu', () => {
const onOpenChange = jest.fn();
function App() {
const [inlineCollapsed, setInlineCollapsed] = useState(false);
return (
<>
<button
type="button"
onClick={() => {
setInlineCollapsed(!inlineCollapsed);
}}
>
collapse menu
</button>
<Menu mode="inline" onOpenChange={onOpenChange} inlineCollapsed={inlineCollapsed}>
<Menu.SubMenu key="1" title="menu">
<Menu.Item key="1-1">menu</Menu.Item>
<Menu.Item key="1-2">menu</Menu.Item>
</Menu.SubMenu>
</Menu>
</>
);
}
const wrapper = mount(<App />);
wrapper.find('button').simulate('click');
expect(onOpenChange).toHaveBeenCalledWith([]);
});
});