From be59a295a533e09618075bc1409bc5bb6ab7ccc7 Mon Sep 17 00:00:00 2001 From: zombiej Date: Thu, 23 Jun 2022 16:02:20 +0800 Subject: [PATCH 01/14] chore: init --- jest.config.js | 6 +- package.json | 48 ++-- tests/Collapsed.spec.js | 479 ++++++++++++++++++------------------ tests/setup.js | 38 +-- tests/setupFilesAfterEnv.ts | 1 + 5 files changed, 290 insertions(+), 282 deletions(-) create mode 100644 tests/setupFilesAfterEnv.ts diff --git a/jest.config.js b/jest.config.js index 86627c33..dae874c4 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,4 +1,4 @@ module.exports = { - setupFiles: ['./tests/setup.js'], - snapshotSerializers: [require.resolve('enzyme-to-json/serializer')], -}; + setupFiles: ['/tests/setup.js'], + setupFilesAfterEnv: ['/tests/setupFilesAfterEnv.ts'] +}; \ No newline at end of file diff --git a/package.json b/package.json index d74442f0..b73ccad1 100644 --- a/package.json +++ b/package.json @@ -9,37 +9,37 @@ "ui", "react-menu" ], - "files": [ - "es", - "lib", - "assets/*.css", - "assets/*.less" - ], - "main": "./lib/index", - "module": "./es/index", "homepage": "http://github.com/react-component/menu", - "maintainers": [ - "yiminghe@gmail.com", - "hualei5280@gmail.com" - ], + "bugs": { + "url": "http://github.com/react-component/menu/issues" + }, "repository": { "type": "git", "url": "git@github.com:react-component/menu.git" }, - "bugs": { - "url": "http://github.com/react-component/menu/issues" - }, "license": "MIT", + "maintainers": [ + "yiminghe@gmail.com", + "hualei5280@gmail.com" + ], + "main": "./lib/index", + "module": "./es/index", + "files": [ + "es", + "lib", + "assets/*.css", + "assets/*.less" + ], "scripts": { - "start": "dumi dev", + "compile": "father build && lessc assets/index.less assets/index.css", + "coverage": "father test --coverage", "docs:build": "dumi build", "docs:deploy": "gh-pages -d .doc", - "compile": "father build && lessc assets/index.less assets/index.css", - "prepublishOnly": "npm run compile && np --yolo --no-publish", "lint": "eslint src/ --ext .tsx,.ts,.jsx,.js", - "test": "father test", - "coverage": "father test --coverage", - "now-build": "npm run build" + "now-build": "npm run build", + "prepublishOnly": "npm run compile && np --yolo --no-publish", + "start": "dumi dev", + "test": "father test" }, "dependencies": { "@babel/runtime": "^7.10.1", @@ -51,6 +51,8 @@ "shallowequal": "^1.1.0" }, "devDependencies": { + "@testing-library/jest-dom": "^5.16.4", + "@testing-library/react": "^13.0.0", "@types/enzyme": "^3.10.8", "@types/jest": "^26.0.23", "@types/react": "^16.8.19", @@ -67,8 +69,8 @@ "gh-pages": "^3.1.0", "less": "^3.10.3", "np": "^6.0.0", - "react": "^16.9.0", - "react-dom": "^16.9.0", + "react": "^18.0.0", + "react-dom": "^18.0.0", "regenerator-runtime": "^0.13.7", "typescript": "^4.0.5" }, diff --git a/tests/Collapsed.spec.js b/tests/Collapsed.spec.js index 666ad26a..f1a660e2 100644 --- a/tests/Collapsed.spec.js +++ b/tests/Collapsed.spec.js @@ -1,7 +1,5 @@ /* eslint-disable no-undef, react/no-multi-comp, react/jsx-curly-brace-presence */ -import React from 'react'; -import { act } from 'react-dom/test-utils'; -import { mount } from 'enzyme'; +import { act, render } from '@testing-library/react'; import Menu, { MenuItem, SubMenu } from '../src'; describe('Menu.Collapsed', () => { @@ -15,259 +13,266 @@ describe('Menu.Collapsed', () => { }); it('should always follow openKeys when mode is switched', () => { - const wrapper = mount( - + const genMenu = props => ( + Option 1 Option 2 menu2 - , + ); - // Inline - expect( - wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-hidden'), - ).toBe(false); - - // Vertical - wrapper.setProps({ mode: 'vertical' }); - expect( - wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-hidden'), - ).toBe(false); + const { container, rerender } = render(genMenu()); // Inline - wrapper.setProps({ mode: 'inline' }); - wrapper.update(); - expect( - wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-hidden'), - ).toBe(false); - }); - - it('should always follow openKeys when inlineCollapsed is switched', () => { - const wrapper = mount( - - - Option - - - Option - Option - - , + expect(container.querySelector('ul.rc-menu-sub')).not.toHaveClass( + 'rc-menu-hidden', ); - expect( - wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-inline'), - ).toBe(true); - expect( - wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-hidden'), - ).toBe(false); - - wrapper.setProps({ inlineCollapsed: true }); - // 动画结束后套样式; - act(() => { - jest.runAllTimers(); - wrapper.update(); - }); - wrapper - .find('Overflow') - .simulate('transitionEnd', { propertyName: 'width' }); - - // Flush SubMenu raf state update - act(() => { - jest.runAllTimers(); - wrapper.update(); - }); - - expect( - wrapper.find('ul.rc-menu-root').at(0).hasClass('rc-menu-vertical'), - ).toBe(true); - expect(wrapper.find('ul.rc-menu-sub').length).toBe(0); - - wrapper.setProps({ inlineCollapsed: false }); - act(() => { - jest.runAllTimers(); - wrapper.update(); - }); - - expect( - wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-inline'), - ).toBe(true); - expect( - wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-hidden'), - ).toBe(false); - }); - - it('inlineCollapsed should works well when specify a not existed default openKeys', () => { - const wrapper = mount( - - - Option - - - Option - Option - - , - ); - expect(wrapper.find('.rc-menu-sub').length).toBe(0); - - // Do collapsed - wrapper.setProps({ inlineCollapsed: true }); - - act(() => { - jest.runAllTimers(); - wrapper.update(); - }); - - wrapper - .find('Overflow') - .simulate('transitionEnd', { propertyName: 'width' }); - - // Wait internal raf work - act(() => { - jest.runAllTimers(); - wrapper.update(); - }); - - // Hover to show - wrapper.find('.rc-menu-submenu-title').at(0).simulate('mouseEnter'); + // Vertical + console.log('do change!'); + rerender(genMenu({ mode: 'vertical' })); + console.log('111'); act(() => { jest.runAllTimers(); - wrapper.update(); }); - - expect( - wrapper - .find('.rc-menu-submenu') - .at(0) - .hasClass('rc-menu-submenu-vertical'), - ).toBe(true); - expect( - wrapper.find('.rc-menu-submenu').at(0).hasClass('rc-menu-submenu-open'), - ).toBe(true); - expect( - wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-vertical'), - ).toBe(true); - expect( - wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-hidden'), - ).toBe(false); - }); - - it('inlineCollapsed MenuItem Tooltip can be removed', () => { - const wrapper = mount( - node.parentNode} - > - item - - item - - - item - - - item - - - item - - - item - - , - ); - expect(wrapper.find(MenuItem).at(0).getDOMNode().title).toBe(''); - expect(wrapper.find(MenuItem).at(1).getDOMNode().title).toBe('title'); - expect(wrapper.find(MenuItem).at(2).getDOMNode().title).toBe(''); - expect(wrapper.find(MenuItem).at(3).getDOMNode().title).toBe(''); - expect(wrapper.find(MenuItem).at(4).getDOMNode().title).toBe(''); - expect(wrapper.find(MenuItem).at(4).getDOMNode().title).toBe(''); - }); - - // 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', () => { - const wrapper = mount( - - Option 1 - Option 2 - - Option 4 - - , + console.log('222'); + expect(container.querySelector('ul.rc-menu-sub')).not.toHaveClass( + 'rc-menu-hidden', ); - // Default - expect( - wrapper.find('li.rc-menu-item-selected').getDOMNode().textContent, - ).toBe('Option 1'); - - // Click to change select - wrapper.find('li.rc-menu-item').at(1).simulate('click'); - expect( - wrapper.find('li.rc-menu-item-selected').getDOMNode().textContent, - ).toBe('Option 2'); - - // Collapse it - wrapper.setProps({ inlineCollapsed: true }); - act(() => { - jest.runAllTimers(); - wrapper.update(); - }); - - // Open since controlled - expect(wrapper.find('Trigger').props().popupVisible).toBeTruthy(); - - // Expand it - wrapper.setProps({ inlineCollapsed: false }); - expect( - wrapper.find('li.rc-menu-item-selected').getDOMNode().textContent, - ).toBe('Option 2'); - }); - - it('should hideMenu in initial state when collapsed', () => { - const wrapper = mount( - - Option 1 - Option 2 - - Option 4 - - , + // Inline + rerender(genMenu({ mode: 'inline' })); + expect(container.querySelector('ul.rc-menu-sub')).not.toHaveClass( + 'rc-menu-hidden', ); - - expect(wrapper.find('Trigger').props().popupVisible).toBeFalsy(); - - wrapper.setProps({ inlineCollapsed: false }); - act(() => { - jest.runAllTimers(); - wrapper.update(); - }); - expect( - wrapper.find('li.rc-menu-item-selected').getDOMNode().textContent, - ).toBe('Option 1'); }); - it('vertical also support inlineCollapsed', () => { - const wrapper = mount(); - - expect(wrapper.exists('.rc-menu-inline-collapsed')).toBeTruthy(); - }); + // it('should always follow openKeys when inlineCollapsed is switched', () => { + // const wrapper = mount( + // + // + // Option + // + // + // Option + // Option + // + // , + // ); + // expect( + // wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-inline'), + // ).toBe(true); + // expect( + // wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-hidden'), + // ).toBe(false); + + // wrapper.setProps({ inlineCollapsed: true }); + // // 动画结束后套样式; + // act(() => { + // jest.runAllTimers(); + // wrapper.update(); + // }); + // wrapper + // .find('Overflow') + // .simulate('transitionEnd', { propertyName: 'width' }); + + // // Flush SubMenu raf state update + // act(() => { + // jest.runAllTimers(); + // wrapper.update(); + // }); + + // expect( + // wrapper.find('ul.rc-menu-root').at(0).hasClass('rc-menu-vertical'), + // ).toBe(true); + // expect(wrapper.find('ul.rc-menu-sub').length).toBe(0); + + // wrapper.setProps({ inlineCollapsed: false }); + // act(() => { + // jest.runAllTimers(); + // wrapper.update(); + // }); + + // expect( + // wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-inline'), + // ).toBe(true); + // expect( + // wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-hidden'), + // ).toBe(false); + // }); + + // it('inlineCollapsed should works well when specify a not existed default openKeys', () => { + // const wrapper = mount( + // + // + // Option + // + // + // Option + // Option + // + // , + // ); + // expect(wrapper.find('.rc-menu-sub').length).toBe(0); + + // // Do collapsed + // wrapper.setProps({ inlineCollapsed: true }); + + // act(() => { + // jest.runAllTimers(); + // wrapper.update(); + // }); + + // wrapper + // .find('Overflow') + // .simulate('transitionEnd', { propertyName: 'width' }); + + // // Wait internal raf work + // act(() => { + // jest.runAllTimers(); + // wrapper.update(); + // }); + + // // Hover to show + // wrapper.find('.rc-menu-submenu-title').at(0).simulate('mouseEnter'); + + // act(() => { + // jest.runAllTimers(); + // wrapper.update(); + // }); + + // expect( + // wrapper + // .find('.rc-menu-submenu') + // .at(0) + // .hasClass('rc-menu-submenu-vertical'), + // ).toBe(true); + // expect( + // wrapper.find('.rc-menu-submenu').at(0).hasClass('rc-menu-submenu-open'), + // ).toBe(true); + // expect( + // wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-vertical'), + // ).toBe(true); + // expect( + // wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-hidden'), + // ).toBe(false); + // }); + + // it('inlineCollapsed MenuItem Tooltip can be removed', () => { + // const wrapper = mount( + // node.parentNode} + // > + // item + // + // item + // + // + // item + // + // + // item + // + // + // item + // + // + // item + // + // , + // ); + // expect(wrapper.find(MenuItem).at(0).getDOMNode().title).toBe(''); + // expect(wrapper.find(MenuItem).at(1).getDOMNode().title).toBe('title'); + // expect(wrapper.find(MenuItem).at(2).getDOMNode().title).toBe(''); + // expect(wrapper.find(MenuItem).at(3).getDOMNode().title).toBe(''); + // expect(wrapper.find(MenuItem).at(4).getDOMNode().title).toBe(''); + // expect(wrapper.find(MenuItem).at(4).getDOMNode().title).toBe(''); + // }); + + // // 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', () => { + // const wrapper = mount( + // + // Option 1 + // Option 2 + // + // Option 4 + // + // , + // ); + + // // Default + // expect( + // wrapper.find('li.rc-menu-item-selected').getDOMNode().textContent, + // ).toBe('Option 1'); + + // // Click to change select + // wrapper.find('li.rc-menu-item').at(1).simulate('click'); + // expect( + // wrapper.find('li.rc-menu-item-selected').getDOMNode().textContent, + // ).toBe('Option 2'); + + // // Collapse it + // wrapper.setProps({ inlineCollapsed: true }); + // act(() => { + // jest.runAllTimers(); + // wrapper.update(); + // }); + + // // Open since controlled + // expect(wrapper.find('Trigger').props().popupVisible).toBeTruthy(); + + // // Expand it + // wrapper.setProps({ inlineCollapsed: false }); + // expect( + // wrapper.find('li.rc-menu-item-selected').getDOMNode().textContent, + // ).toBe('Option 2'); + // }); + + // it('should hideMenu in initial state when collapsed', () => { + // const wrapper = mount( + // + // Option 1 + // Option 2 + // + // Option 4 + // + // , + // ); + + // expect(wrapper.find('Trigger').props().popupVisible).toBeFalsy(); + + // wrapper.setProps({ inlineCollapsed: false }); + // act(() => { + // jest.runAllTimers(); + // wrapper.update(); + // }); + // expect( + // wrapper.find('li.rc-menu-item-selected').getDOMNode().textContent, + // ).toBe('Option 1'); + // }); + + // it('vertical also support inlineCollapsed', () => { + // const wrapper = mount(); + + // expect(wrapper.exists('.rc-menu-inline-collapsed')).toBeTruthy(); + // }); }); }); /* eslint-enable */ diff --git a/tests/setup.js b/tests/setup.js index c01e979e..ffd6f62f 100644 --- a/tests/setup.js +++ b/tests/setup.js @@ -4,25 +4,25 @@ window.requestAnimationFrame = func => { }; window.cancelAnimationFrame = id => window.clearTimeout(id); -const Enzyme = require('enzyme'); -const Adapter = require('enzyme-adapter-react-16'); -require('regenerator-runtime/runtime'); +// const Enzyme = require('enzyme'); +// const Adapter = require('enzyme-adapter-react-16'); +// require('regenerator-runtime/runtime'); -Enzyme.configure({ adapter: new Adapter() }); +// Enzyme.configure({ adapter: new Adapter() }); -Object.assign(Enzyme.ReactWrapper.prototype, { - findItem(index = 0) { - return this.find('li.rc-menu-item').at(index); - }, - isActive(index = 0) { - return this.findItem(index).hasClass('rc-menu-item-active'); - }, - async flush() { - for (let i = 0; i < 3; i += 1) { - // eslint-disable-next-line no-await-in-loop - await Promise.resolve(); - } +// Object.assign(Enzyme.ReactWrapper.prototype, { +// findItem(index = 0) { +// return this.find('li.rc-menu-item').at(index); +// }, +// isActive(index = 0) { +// return this.findItem(index).hasClass('rc-menu-item-active'); +// }, +// async flush() { +// for (let i = 0; i < 3; i += 1) { +// // eslint-disable-next-line no-await-in-loop +// await Promise.resolve(); +// } - return this; - }, -}); +// return this; +// }, +// }); diff --git a/tests/setupFilesAfterEnv.ts b/tests/setupFilesAfterEnv.ts new file mode 100644 index 00000000..7b0828bf --- /dev/null +++ b/tests/setupFilesAfterEnv.ts @@ -0,0 +1 @@ +import '@testing-library/jest-dom'; From 95d68334102eba45539e961bd3becefc967f1014 Mon Sep 17 00:00:00 2001 From: zombiej Date: Thu, 23 Jun 2022 17:48:06 +0800 Subject: [PATCH 02/14] test: more --- tests/Collapsed.spec.js | 203 ++++++++++++++++++++-------------------- 1 file changed, 102 insertions(+), 101 deletions(-) diff --git a/tests/Collapsed.spec.js b/tests/Collapsed.spec.js index f1a660e2..63a61806 100644 --- a/tests/Collapsed.spec.js +++ b/tests/Collapsed.spec.js @@ -1,5 +1,5 @@ /* eslint-disable no-undef, react/no-multi-comp, react/jsx-curly-brace-presence */ -import { act, render } from '@testing-library/react'; +import { act, fireEvent, render } from '@testing-library/react'; import Menu, { MenuItem, SubMenu } from '../src'; describe('Menu.Collapsed', () => { @@ -31,13 +31,10 @@ describe('Menu.Collapsed', () => { ); // Vertical - console.log('do change!'); rerender(genMenu({ mode: 'vertical' })); - console.log('111'); act(() => { jest.runAllTimers(); }); - console.log('222'); expect(container.querySelector('ul.rc-menu-sub')).not.toHaveClass( 'rc-menu-hidden', ); @@ -49,116 +46,120 @@ describe('Menu.Collapsed', () => { ); }); - // it('should always follow openKeys when inlineCollapsed is switched', () => { - // const wrapper = mount( - // - // - // Option - // - // - // Option - // Option - // - // , - // ); - // expect( - // wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-inline'), - // ).toBe(true); - // expect( - // wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-hidden'), - // ).toBe(false); + it('should always follow openKeys when inlineCollapsed is switched', () => { + const genMenu = props => ( + + + Option + + + Option + Option + + + ); - // wrapper.setProps({ inlineCollapsed: true }); - // // 动画结束后套样式; - // act(() => { - // jest.runAllTimers(); - // wrapper.update(); - // }); - // wrapper - // .find('Overflow') - // .simulate('transitionEnd', { propertyName: 'width' }); + const { container, rerender } = render(genMenu()); + expect(container.querySelector('ul.rc-menu-sub')).toHaveClass( + 'rc-menu-inline', + ); + expect(container.querySelector('ul.rc-menu-sub')).not.toHaveClass( + 'rc-menu-hidden', + ); - // // Flush SubMenu raf state update - // act(() => { - // jest.runAllTimers(); - // wrapper.update(); - // }); + rerender(genMenu({ inlineCollapsed: true })); + // 动画结束后套样式; + act(() => { + jest.runAllTimers(); + }); + fireEvent.transitionEnd(container.querySelector('.rc-menu-root'), { + propertyName: 'width', + }); - // expect( - // wrapper.find('ul.rc-menu-root').at(0).hasClass('rc-menu-vertical'), - // ).toBe(true); - // expect(wrapper.find('ul.rc-menu-sub').length).toBe(0); + // Flush SubMenu raf state update + act(() => { + jest.runAllTimers(); + }); - // wrapper.setProps({ inlineCollapsed: false }); - // act(() => { - // jest.runAllTimers(); - // wrapper.update(); - // }); + expect(container.querySelector('ul.rc-menu-root')).toHaveClass( + 'rc-menu-vertical', + ); + expect(container.querySelectorAll('ul.rc-menu-sub')).toHaveLength(0); - // expect( - // wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-inline'), - // ).toBe(true); - // expect( - // wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-hidden'), - // ).toBe(false); - // }); + rerender(genMenu({ inlineCollapsed: false })); + act(() => { + jest.runAllTimers(); + }); - // it('inlineCollapsed should works well when specify a not existed default openKeys', () => { - // const wrapper = mount( - // - // - // Option - // - // - // Option - // Option - // - // , - // ); - // expect(wrapper.find('.rc-menu-sub').length).toBe(0); + expect(container.querySelector('ul.rc-menu-sub')).toHaveClass( + 'rc-menu-inline', + ); + expect(container.querySelector('ul.rc-menu-sub')).not.toHaveClass( + 'rc-menu-hidden', + ); + }); - // // Do collapsed - // wrapper.setProps({ inlineCollapsed: true }); + it('inlineCollapsed should works well when specify a not existed default openKeys', () => { + const genMenu = props => ( + + + Option + + + Option + Option + + + ); - // act(() => { - // jest.runAllTimers(); - // wrapper.update(); - // }); + const { container, rerender } = render(genMenu()); + expect(container.querySelectorAll('.rc-menu-sub')).toHaveLength(0); - // wrapper - // .find('Overflow') - // .simulate('transitionEnd', { propertyName: 'width' }); + // Do collapsed + rerender(genMenu({ inlineCollapsed: true })); - // // Wait internal raf work - // act(() => { - // jest.runAllTimers(); - // wrapper.update(); - // }); + act(() => { + jest.runAllTimers(); + }); - // // Hover to show - // wrapper.find('.rc-menu-submenu-title').at(0).simulate('mouseEnter'); + // wrapper + // .find('Overflow') + // .simulate('transitionEnd', { propertyName: 'width' }); + fireEvent.transitionEnd(container.querySelector('.rc-menu-root'), { + propertyName: 'width', + }); - // act(() => { - // jest.runAllTimers(); - // wrapper.update(); - // }); + // Wait internal raf work + act(() => { + jest.runAllTimers(); + }); - // expect( - // wrapper - // .find('.rc-menu-submenu') - // .at(0) - // .hasClass('rc-menu-submenu-vertical'), - // ).toBe(true); - // expect( - // wrapper.find('.rc-menu-submenu').at(0).hasClass('rc-menu-submenu-open'), - // ).toBe(true); - // expect( - // wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-vertical'), - // ).toBe(true); - // expect( - // wrapper.find('ul.rc-menu-sub').at(0).hasClass('rc-menu-hidden'), - // ).toBe(false); - // }); + // Hover to show + // wrapper.find('.rc-menu-submenu-title').at(0).simulate('mouseEnter'); + fireEvent.mouseEnter(container.querySelector('.rc-menu-submenu-title')); + + act(() => { + jest.runAllTimers(); + }); + act(() => { + jest.runAllTimers(); + }); + + expect(container.querySelector('.rc-menu-submenu')).toHaveClass( + 'rc-menu-submenu-vertical', + ); + + expect(container.querySelector('.rc-menu-submenu')).toHaveClass( + 'rc-menu-submenu-open', + ); + + expect(container.querySelector('ul.rc-menu-sub')).toHaveClass( + 'rc-menu-vertical', + ); + expect(container.querySelector('ul.rc-menu-sub')).not.toHaveClass( + 'rc-menu-hidden', + ); + }); // it('inlineCollapsed MenuItem Tooltip can be removed', () => { // const wrapper = mount( From 9e98ad941cfdcebed95f345202077a5d81afc225 Mon Sep 17 00:00:00 2001 From: zombiej Date: Thu, 23 Jun 2022 20:28:22 +0800 Subject: [PATCH 03/14] test: more and more test --- tests/Collapsed.spec.js | 235 +++++++++++++++++++++------------------- 1 file changed, 122 insertions(+), 113 deletions(-) diff --git a/tests/Collapsed.spec.js b/tests/Collapsed.spec.js index 63a61806..7ccbfa43 100644 --- a/tests/Collapsed.spec.js +++ b/tests/Collapsed.spec.js @@ -161,119 +161,128 @@ describe('Menu.Collapsed', () => { ); }); - // it('inlineCollapsed MenuItem Tooltip can be removed', () => { - // const wrapper = mount( - // node.parentNode} - // > - // item - // - // item - // - // - // item - // - // - // item - // - // - // item - // - // - // item - // - // , - // ); - // expect(wrapper.find(MenuItem).at(0).getDOMNode().title).toBe(''); - // expect(wrapper.find(MenuItem).at(1).getDOMNode().title).toBe('title'); - // expect(wrapper.find(MenuItem).at(2).getDOMNode().title).toBe(''); - // expect(wrapper.find(MenuItem).at(3).getDOMNode().title).toBe(''); - // expect(wrapper.find(MenuItem).at(4).getDOMNode().title).toBe(''); - // expect(wrapper.find(MenuItem).at(4).getDOMNode().title).toBe(''); - // }); - - // // 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', () => { - // const wrapper = mount( - // - // Option 1 - // Option 2 - // - // Option 4 - // - // , - // ); - - // // Default - // expect( - // wrapper.find('li.rc-menu-item-selected').getDOMNode().textContent, - // ).toBe('Option 1'); - - // // Click to change select - // wrapper.find('li.rc-menu-item').at(1).simulate('click'); - // expect( - // wrapper.find('li.rc-menu-item-selected').getDOMNode().textContent, - // ).toBe('Option 2'); - - // // Collapse it - // wrapper.setProps({ inlineCollapsed: true }); - // act(() => { - // jest.runAllTimers(); - // wrapper.update(); - // }); - - // // Open since controlled - // expect(wrapper.find('Trigger').props().popupVisible).toBeTruthy(); - - // // Expand it - // wrapper.setProps({ inlineCollapsed: false }); - // expect( - // wrapper.find('li.rc-menu-item-selected').getDOMNode().textContent, - // ).toBe('Option 2'); - // }); - - // it('should hideMenu in initial state when collapsed', () => { - // const wrapper = mount( - // - // Option 1 - // Option 2 - // - // Option 4 - // - // , - // ); - - // expect(wrapper.find('Trigger').props().popupVisible).toBeFalsy(); - - // wrapper.setProps({ inlineCollapsed: false }); - // act(() => { - // jest.runAllTimers(); - // wrapper.update(); - // }); - // expect( - // wrapper.find('li.rc-menu-item-selected').getDOMNode().textContent, - // ).toBe('Option 1'); - // }); - - // it('vertical also support inlineCollapsed', () => { - // const wrapper = mount(); - - // expect(wrapper.exists('.rc-menu-inline-collapsed')).toBeTruthy(); - // }); + it('inlineCollapsed MenuItem Tooltip can be removed', () => { + const { container } = render( + node.parentNode} + > + item + + item + + + item + + + item + + + item + + + item + + , + ); + + expect( + Array.from(container.querySelectorAll('.rc-menu-item')).map( + node => node.title, + ), + ).toEqual(['', 'title', '', '', '', '']); + }); + + // 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', () => { + const genMenu = props => ( + + Option 1 + Option 2 + + Option 4 + + + ); + + const { container, rerender } = render(genMenu()); + + // Default + expect( + container.querySelector('.rc-menu-item-selected').textContent, + ).toBe('Option 1'); + + // Click to change select + fireEvent.click(container.querySelectorAll('.rc-menu-item')[1]); + expect( + container.querySelector('.rc-menu-item-selected').textContent, + ).toBe('Option 2'); + + // Collapse it + rerender(genMenu({ inlineCollapsed: true })); + act(() => { + jest.runAllTimers(); + }); + + // Open since controlled + expect(container.querySelector('.rc-menu-submenu-popup')).toBeTruthy(); + + // Expand it + rerender(genMenu({ inlineCollapsed: false })); + expect( + container.querySelector('.rc-menu-item-selected').textContent, + ).toBe('Option 2'); + }); + + it('should hideMenu in initial state when collapsed', () => { + const genMenu = props => ( + + Option 1 + Option 2 + + Option 4 + + + ); + + const { container, rerender } = render(genMenu()); + + act(() => { + jest.runAllTimers(); + }); + + expect(container.querySelector('.rc-menu-submenu-popup')).toBeTruthy(); + + rerender(genMenu({ inlineCollapsed: false })); + act(() => { + jest.runAllTimers(); + }); + + expect( + container.querySelector('.rc-menu-item-selected').textContent, + ).toBe('Option 1'); + }); + + it('vertical also support inlineCollapsed', () => { + const { container } = render(); + + expect(container.querySelector('.rc-menu-inline-collapsed')).toBeTruthy(); + }); }); }); /* eslint-enable */ From 2ce37d0f2bf72df1534b54ef728faa65854d88b1 Mon Sep 17 00:00:00 2001 From: zombiej Date: Fri, 24 Jun 2022 11:59:48 +0800 Subject: [PATCH 04/14] test: keyboard test case --- tests/Keyboard.spec.tsx | 201 ++++++++++----------- tests/__snapshots__/Keyboard.spec.tsx.snap | 12 +- tests/util.ts | 44 +++-- 3 files changed, 133 insertions(+), 124 deletions(-) diff --git a/tests/Keyboard.spec.tsx b/tests/Keyboard.spec.tsx index 07978ff9..73544b0f 100644 --- a/tests/Keyboard.spec.tsx +++ b/tests/Keyboard.spec.tsx @@ -1,16 +1,13 @@ /* eslint-disable no-undef, react/no-multi-comp, react/jsx-curly-brace-presence, max-classes-per-file */ +import { fireEvent, render } from '@testing-library/react'; +import KeyCode from 'rc-util/lib/KeyCode'; +import { spyElementPrototypes } from 'rc-util/lib/test/domHook'; import React from 'react'; import { act } from 'react-dom/test-utils'; -import { spyElementPrototypes } from 'rc-util/lib/test/domHook'; -import { render } from 'enzyme'; -import { mount } from './util'; -import type { ReactWrapper } from './util'; -import KeyCode from 'rc-util/lib/KeyCode'; import Menu, { MenuItem, SubMenu } from '../src'; +import { isActive, last } from './util'; describe('Menu.Keyboard', () => { - let holder: HTMLDivElement; - beforeAll(() => { // Mock to force make menu item visible spyElementPrototypes(HTMLElement, { @@ -23,27 +20,33 @@ describe('Menu.Keyboard', () => { }); beforeEach(() => { - holder = document.createElement('div'); - document.body.appendChild(holder); jest.useFakeTimers(); }); afterEach(() => { jest.useRealTimers(); - holder.parentElement.removeChild(holder); }); - function keyDown(wrapper: ReactWrapper, keyCode: number) { - wrapper.find('ul.rc-menu-root').simulate('keyDown', { which: keyCode }); + function keyDown(container: HTMLElement, keyCode: number) { + fireEvent.keyDown(container.querySelector('ul.rc-menu-root'), { + which: keyCode, + keyCode, + charCode: keyCode, + }); + // SubMenu raf need slow than accessibility + for (let i = 0; i < 20; i += 1) { + act(() => { + jest.advanceTimersByTime(10); + }); + } act(() => { jest.runAllTimers(); - wrapper.update(); }); } it('no data-menu-id by init', () => { - const wrapper = render( + const { container } = render( Bamboo @@ -51,7 +54,7 @@ describe('Menu.Keyboard', () => { , ); - expect(wrapper).toMatchSnapshot(); + expect(container.children).toMatchSnapshot(); }); it('keydown works when children change', async () => { @@ -71,27 +74,27 @@ describe('Menu.Keyboard', () => { } } - const wrapper = mount(, { attachTo: holder }); + const { container } = render(); // First item - keyDown(wrapper, KeyCode.DOWN); - expect(wrapper.isActive(0)).toBeTruthy(); + keyDown(container, KeyCode.DOWN); + isActive(container, 0); // Next item - keyDown(wrapper, KeyCode.DOWN); - expect(wrapper.isActive(1)).toBeTruthy(); + keyDown(container, KeyCode.DOWN); + isActive(container, 1); // Very first item - keyDown(wrapper, KeyCode.HOME); - expect(wrapper.isActive(0)).toBeTruthy(); + keyDown(container, KeyCode.HOME); + isActive(container, 0); // Very last item - keyDown(wrapper, KeyCode.END); - expect(wrapper.isActive(2)).toBeTruthy(); + keyDown(container, KeyCode.END); + isActive(container, 2); }); it('Skip disabled item', () => { - const wrapper = mount( + const { container } = render( 1 @@ -99,43 +102,44 @@ describe('Menu.Keyboard', () => { 2 , - { attachTo: holder }, ); // Next item - keyDown(wrapper, KeyCode.DOWN); - keyDown(wrapper, KeyCode.DOWN); - expect(wrapper.isActive(3)).toBeTruthy(); + keyDown(container, KeyCode.DOWN); + keyDown(container, KeyCode.DOWN); + isActive(container, 3); // Back to first item - keyDown(wrapper, KeyCode.UP); - expect(wrapper.isActive(1)).toBeTruthy(); + keyDown(container, KeyCode.UP); + isActive(container, 1); // To the last available item - keyDown(wrapper, KeyCode.END); - expect(wrapper.isActive(3)).toBeTruthy(); + keyDown(container, KeyCode.END); + isActive(container, 3); // To the first available item - keyDown(wrapper, KeyCode.HOME); - expect(wrapper.isActive(1)).toBeTruthy(); + keyDown(container, KeyCode.HOME); + isActive(container, 1); }); it('Enter to open menu and active first item', () => { - const wrapper = mount( + const { container } = render( 1 , - { attachTo: holder }, ); // Active first sub menu - keyDown(wrapper, KeyCode.DOWN); + keyDown(container, KeyCode.DOWN); // Open it - keyDown(wrapper, KeyCode.ENTER); - expect(wrapper.find('PopupTrigger').prop('visible')).toBeTruthy(); + keyDown(container, KeyCode.ENTER); + act(() => { + jest.runAllTimers(); + }); + expect(container.querySelector('.rc-menu-submenu-open')).toBeTruthy(); }); describe('go to children & back of parent', () => { @@ -145,7 +149,7 @@ describe('Menu.Keyboard', () => { parentKey: number, ) { it(`direction ${direction}`, () => { - const wrapper = mount( + const { container, unmount } = render( @@ -153,49 +157,46 @@ describe('Menu.Keyboard', () => { , - { attachTo: holder }, ); // Active first - keyDown(wrapper, KeyCode.DOWN); + keyDown(container, KeyCode.DOWN); // Open and active sub - keyDown(wrapper, subKey); - expect( - wrapper.find('PopupTrigger').first().prop('visible'), - ).toBeTruthy(); - + keyDown(container, subKey); + expect(container.querySelector('.rc-menu-submenu-open')).toBeTruthy(); expect( - wrapper - .find('.rc-menu-submenu-active .rc-menu-submenu-title') - .last() - .text(), + last( + container.querySelectorAll( + '.rc-menu-submenu-active > .rc-menu-submenu-title', + ), + ).textContent, ).toEqual('Light'); // Open and active sub - keyDown(wrapper, subKey); + keyDown(container, subKey); expect( - wrapper.find('PopupTrigger').last().prop('visible'), - ).toBeTruthy(); - expect(wrapper.find('.rc-menu-item-active').last().text()).toEqual( - 'Little', - ); + container.querySelectorAll('.rc-menu-submenu-open'), + ).toHaveLength(2); + expect( + last(container.querySelectorAll('.rc-menu-item-active')).textContent, + ).toEqual('Little'); // Back to parent - keyDown(wrapper, parentKey); - expect(wrapper.find('PopupTrigger').last().prop('visible')).toBeFalsy(); - expect(wrapper.find('.rc-menu-item-active')).toHaveLength(0); + keyDown(container, parentKey); + expect( + container.querySelectorAll('.rc-menu-submenu-open'), + ).toHaveLength(1); + expect(container.querySelector('.rc-menu-item-active')).toBeFalsy(); // Back to parent - keyDown(wrapper, parentKey); - + keyDown(container, parentKey); + expect(container.querySelector('.rc-menu-submenu-open')).toBeFalsy(); expect( - wrapper.find('PopupTrigger').first().prop('visible'), - ).toBeFalsy(); - - expect(wrapper.find('li.rc-menu-submenu-active')).toHaveLength(1); + container.querySelectorAll('.rc-menu-submenu-active'), + ).toHaveLength(1); - wrapper.unmount(); + unmount(); }); } @@ -204,91 +205,81 @@ describe('Menu.Keyboard', () => { }); it('inline keyboard', () => { - const wrapper = mount( + const { container } = render( Light Little , - { attachTo: holder }, ); // Nothing happen when no control key - keyDown(wrapper, KeyCode.P); - expect(wrapper.exists('.rc-menu-item-active')).toBeFalsy(); + keyDown(container, KeyCode.P); + expect(container.querySelector('.rc-menu-item-active')).toBeFalsy(); // Active first - keyDown(wrapper, KeyCode.DOWN); - expect(wrapper.isActive(0)).toBeTruthy(); + keyDown(container, KeyCode.DOWN); + isActive(container, 0); // Active next - keyDown(wrapper, KeyCode.DOWN); + keyDown(container, KeyCode.DOWN); // Right will not open - keyDown(wrapper, KeyCode.RIGHT); - expect(wrapper.find('InlineSubMenuList').prop('open')).toBeFalsy(); + keyDown(container, KeyCode.RIGHT); + expect(container.querySelector('.rc-menu-submenu-open')).toBeFalsy(); // Trigger open - keyDown(wrapper, KeyCode.ENTER); - expect(wrapper.find('InlineSubMenuList').prop('open')).toBeTruthy(); - expect( - wrapper - .find('.rc-menu-submenu') - .last() - .hasClass('rc-menu-submenu-active'), - ).toBeTruthy(); - expect(wrapper.isActive(1)).toBeFalsy(); + keyDown(container, KeyCode.ENTER); + expect(container.querySelector('.rc-menu-submenu-open')).toBeTruthy(); + expect(last(container.querySelectorAll('.rc-menu-submenu'))).toHaveClass( + 'rc-menu-submenu-active', + ); + isActive(container, 1, false); // Active sub item - keyDown(wrapper, KeyCode.DOWN); - expect(wrapper.isActive(1)).toBeTruthy(); + keyDown(container, KeyCode.DOWN); + isActive(container, 1); }); it('Focus last one', () => { - const wrapper = mount( + const { container } = render( Light Bamboo , - { attachTo: holder }, ); - keyDown(wrapper, KeyCode.UP); - expect(wrapper.isActive(1)).toBeTruthy(); + keyDown(container, KeyCode.UP); + isActive(container, 1); }); it('Focus to link direct', () => { - const wrapper = mount( + const { container } = render( Light , - { attachTo: holder }, ); - const focusSpy = jest.spyOn( - (wrapper.find('a').instance() as any) as HTMLAnchorElement, - 'focus', - ); + const focusSpy = jest.spyOn(container.querySelector('a'), 'focus'); - keyDown(wrapper, KeyCode.DOWN); + keyDown(container, KeyCode.DOWN); expect(focusSpy).toHaveBeenCalled(); }); it('no dead loop', async () => { - const wrapper = mount( + const { container } = render( Little , - { attachTo: holder }, ); - keyDown(wrapper, KeyCode.DOWN); - keyDown(wrapper, KeyCode.LEFT); - keyDown(wrapper, KeyCode.RIGHT); - expect(wrapper.isActive(0)).toBeTruthy(); + keyDown(container, KeyCode.DOWN); + keyDown(container, KeyCode.LEFT); + keyDown(container, KeyCode.RIGHT); + isActive(container, 0); }); }); /* eslint-enable */ diff --git a/tests/__snapshots__/Keyboard.spec.tsx.snap b/tests/__snapshots__/Keyboard.spec.tsx.snap index 4eff8d3e..00ab93c2 100644 --- a/tests/__snapshots__/Keyboard.spec.tsx.snap +++ b/tests/__snapshots__/Keyboard.spec.tsx.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Menu.Keyboard no data-menu-id by init 1`] = ` -Array [ +HTMLCollection [