diff --git a/.dumirc.ts b/.dumirc.ts new file mode 100644 index 0000000..d24799e --- /dev/null +++ b/.dumirc.ts @@ -0,0 +1,17 @@ +// more config: https://d.umijs.org/config +import { defineConfig } from 'dumi'; +import path from 'path'; + +export default defineConfig({ + alias: { + 'rc-collapse$': path.resolve('src'), + 'rc-collapse/es': path.resolve('src'), + }, + favicons: ['https://avatars0.githubusercontent.com/u/9441414?s=200&v=4'], + themeConfig: { + name: 'Collapse', + logo: 'https://avatars0.githubusercontent.com/u/9441414?s=200&v=4', + }, + outputPath: '.doc', + exportStatic: {}, +}); diff --git a/.fatherrc.js b/.fatherrc.js deleted file mode 100644 index 9d8c16b..0000000 --- a/.fatherrc.js +++ /dev/null @@ -1,9 +0,0 @@ -export default { - cjs: "babel", - esm: { type: "babel", importLibToEs: true }, - preCommit: { - eslint: true, - prettier: true, - }, - runtimeHelpers: true, -}; diff --git a/.fatherrc.ts b/.fatherrc.ts new file mode 100644 index 0000000..96268ae --- /dev/null +++ b/.fatherrc.ts @@ -0,0 +1,5 @@ +import { defineConfig } from 'father'; + +export default defineConfig({ + plugins: ['@rc-component/father-plugin'], +}); diff --git a/.gitignore b/.gitignore index 7fb8d82..4ceb977 100644 --- a/.gitignore +++ b/.gitignore @@ -31,8 +31,8 @@ package-lock.json .storybook .doc -# umi -.umi -.umi-production -.umi-test +# dumi +.dumi/tmp +.dumi/tmp-production +.dumi/tmp-test .env.local diff --git a/HISTORY.md b/HISTORY.md index 5941049..294d57f 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,6 @@ # History ----- + +--- ## 2.0.0 `2020-05-08` diff --git a/README.md b/README.md index e689541..d712a74 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,8 @@ # rc-collapse ---- rc-collapse ui component for react -[![NPM version][npm-image]][npm-url] -[![build status][github-actions-image]][github-actions-url] -[![Test coverage][codecov-image]][codecov-url] -[![npm download][download-image]][download-url] +[![NPM version][npm-image]][npm-url] [![build status][github-actions-image]][github-actions-url] [![Test coverage][codecov-image]][codecov-url] [![npm download][download-image]][download-url] [npm-image]: http://img.shields.io/npm/v/rc-collapse.svg?style=flat-square [npm-url]: http://npmjs.org/package/rc-collapse @@ -17,23 +13,9 @@ rc-collapse ui component for react [download-image]: https://img.shields.io/npm/dm/rc-collapse.svg?style=flat-square [download-url]: https://npmjs.org/package/rc-collapse -## Development - -``` -npm install -npm start -``` - -## Example +## Live Demo -http://localhost:8000/examples/ - -online example: http://react-component.github.io/collapse/ - - -## Features - -* support ie8,ie8+,chrome,firefox,safari +http://react-component.github.io/collapse/ ## Install @@ -48,20 +30,24 @@ var React = require('react'); var ReactDOM = require('react-dom'); require('rc-collapse/assets/index.css'); -var collapse = ( +var App = ( - this is panel content + + this is panel content + this is panel content2 or other ); -ReactDOM.render(collapse, container); +ReactDOM.render(App, container); ``` -## API +## Features + +- support ie8,ie8+,chrome,firefox,safari -### Collapse +## API -#### props: +### Collapse props @@ -124,15 +110,11 @@ ReactDOM.render(collapse, container);
-If `accordion` is null or false, every panel can open. Opening another panel will not close any of the other panels. -`activeKey` should be an string, if passing an array (the first item in the array will be used). - -If `accordion` is true, only one panel can be open. Opening another panel will cause the previously opened panel to close. -`activeKey` should be an string, if passing an array (the first item in the array will be used). +If `accordion` is null or false, every panel can open. Opening another panel will not close any of the other panels. `activeKey` should be an string, if passing an array (the first item in the array will be used). -### Collapse.Panel +If `accordion` is true, only one panel can be open. Opening another panel will cause the previously opened panel to close. `activeKey` should be an string, if passing an array (the first item in the array will be used). -#### props +### Collapse.Panel props @@ -207,20 +189,24 @@ If `accordion` is true, only one panel can be open. Opening another panel will If `key` is not provided, the panel's index will be used instead. -## Test Case +## Development +```bash +npm install +npm start ``` + +## Test Case + +```bash npm test -npm run chrome-test ``` ## Coverage +```bash +npm test -- --coverage ``` -npm run coverage -``` - -open coverage/ dir ## License diff --git a/docs/demo/custom-icon.md b/docs/demo/custom-icon.md index cce7a80..860ecf1 100644 --- a/docs/demo/custom-icon.md +++ b/docs/demo/custom-icon.md @@ -1,2 +1,8 @@ -## custom-icon - +--- +title: custom-icon +nav: + title: Demo + path: /demo +--- + + diff --git a/docs/demo/fragment.md b/docs/demo/fragment.md index 2ee0d15..de859a4 100644 --- a/docs/demo/fragment.md +++ b/docs/demo/fragment.md @@ -1,2 +1,8 @@ -## fragment - +--- +title: fragment +nav: + title: Demo + path: /demo +--- + + diff --git a/docs/demo/simple.md b/docs/demo/simple.md index d1f1f88..64848ae 100644 --- a/docs/demo/simple.md +++ b/docs/demo/simple.md @@ -1,2 +1,8 @@ -## simple - +--- +title: simple +nav: + title: Demo + path: /demo +--- + + diff --git a/docs/examples/_util/motionUtil.ts b/docs/examples/_util/motionUtil.ts index 9e95913..f68ad80 100644 --- a/docs/examples/_util/motionUtil.ts +++ b/docs/examples/_util/motionUtil.ts @@ -1,4 +1,4 @@ -import { CSSMotionProps, MotionEventHandler, MotionEndEventHandler } from 'rc-motion'; +import type { CSSMotionProps, MotionEventHandler, MotionEndEventHandler } from 'rc-motion'; const getCollapsedHeight: MotionEventHandler = () => ({ height: 0, opacity: 0 }); const getRealHeight: MotionEventHandler = (node) => ({ height: node.scrollHeight, opacity: 1 }); diff --git a/docs/examples/custom-icon.tsx b/docs/examples/custom-icon.tsx index 483881c..d034716 100644 --- a/docs/examples/custom-icon.tsx +++ b/docs/examples/custom-icon.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import Collapse, { Panel } from '../../src'; +import Collapse, { Panel } from 'rc-collapse'; import motion from './_util/motionUtil'; import '../../assets/index.less'; diff --git a/docs/examples/fragment.tsx b/docs/examples/fragment.tsx index e41853f..0b2c1f8 100644 --- a/docs/examples/fragment.tsx +++ b/docs/examples/fragment.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { Fragment } from 'react'; +import Collapse, { Panel } from 'rc-collapse'; import '../../assets/index.less'; -import Collapse, { Panel } from '../../src'; const Test = () => ( diff --git a/docs/examples/simple.tsx b/docs/examples/simple.tsx index fb2a2b1..885fb85 100644 --- a/docs/examples/simple.tsx +++ b/docs/examples/simple.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import Collapse, { Panel } from '../../src'; +import Collapse, { Panel } from 'rc-collapse'; import motion from './_util/motionUtil'; import '../../assets/index.less'; diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..66e80a6 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,7 @@ +--- +hero: + title: rc-collapse + description: rc-collapse ui component for react +--- + + diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..ca1261b --- /dev/null +++ b/jest.config.js @@ -0,0 +1,3 @@ +module.exports = { + setupFilesAfterEnv: ['/tests/setupAfterEnv.ts'], +}; diff --git a/package.json b/package.json index 6ba4501..81e8c62 100644 --- a/package.json +++ b/package.json @@ -11,62 +11,58 @@ "accordion" ], "homepage": "http://github.com/react-component/collapse", + "bugs": { + "url": "http://github.com/react-component/collapse/issues" + }, "repository": { "type": "git", "url": "git@github.com:react-component/collapse.git" }, - "bugs": { - "url": "http://github.com/react-component/collapse/issues" - }, "license": "MIT", + "main": "./lib/index", + "module": "./es/index", "files": [ "lib", "es", "assets/*.css" ], - "main": "./lib/index", - "module": "./es/index", "scripts": { - "start": "dumi dev", "build": "dumi build", "compile": "father build && lessc assets/index.less assets/index.css", - "gh-pages": "npm run build && father doc deploy", - "prepublishOnly": "npm run compile && np --yolo --no-publish", - "postpublish": "npm run gh-pages", + "coverage": "father test --coverage", "lint": "eslint src/ --ext .ts,.tsx,.jsx,.js,.md", + "prepublishOnly": "npm run compile && np --yolo --no-publish", "prettier": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"", - "test": "father test", - "coverage": "father test --coverage" + "start": "dumi dev", + "test": "rc-test" + }, + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.3.4", + "rc-util": "^5.27.0" }, "devDependencies": { + "@rc-component/father-plugin": "^1.0.1", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", "@types/classnames": "^2.2.9", - "@types/enzyme": "^3.10.6", "@types/jest": "^26.0.0", "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", "@umijs/fabric": "^2.0.0", - "cross-env": "^7.0.0", - "dumi": "^1.1.4", - "enzyme": "^3.1.1", - "enzyme-adapter-react-16": "^1.0.1", - "enzyme-to-json": "^3.1.2", + "dumi": "^2.1.1", "eslint": "^7.11.0", - "father": "^2.22.0", - "glob": "^7.1.6", + "father": "^4.1.3", "jest": "^29.1.2", "less": "^3.12.2", "np": "^6.0.0", "prettier": "^2.1.2", - "react": "^16.9.0", - "react-dom": "^16.9.0", + "rc-test": "^7.0.14", + "react": "^18.2.0", + "react-dom": "^18.2.0", "typescript": "^4.0.2" }, - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "2.x", - "rc-motion": "^2.3.4", - "rc-util": "^5.27.0" - }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" diff --git a/src/Collapse.tsx b/src/Collapse.tsx index 38c32a8..f10bb1f 100644 --- a/src/Collapse.tsx +++ b/src/Collapse.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/prop-types */ import classNames from 'classnames'; import toArray from 'rc-util/lib/Children/toArray'; import * as React from 'react'; diff --git a/src/Panel.tsx b/src/Panel.tsx index 89a1961..ae00483 100644 --- a/src/Panel.tsx +++ b/src/Panel.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/prop-types */ import classNames from 'classnames'; import CSSMotion from 'rc-motion'; import * as React from 'react'; diff --git a/src/PanelContent.tsx b/src/PanelContent.tsx index d018a60..c6740db 100644 --- a/src/PanelContent.tsx +++ b/src/PanelContent.tsx @@ -1,8 +1,6 @@ -/* eslint-disable no-underscore-dangle */ -/* eslint-disable react/prop-types */ import * as React from 'react'; import classnames from 'classnames'; -import { CollapsePanelProps } from './interface'; +import type { CollapsePanelProps } from './interface'; const PanelContent = React.forwardRef< HTMLDivElement, diff --git a/src/index.ts b/src/index.tsx similarity index 100% rename from src/index.ts rename to src/index.tsx diff --git a/tests/index.spec.tsx b/tests/index.spec.tsx index 37d6ac9..a7598c5 100644 --- a/tests/index.spec.tsx +++ b/tests/index.spec.tsx @@ -1,5 +1,5 @@ -import type { ReactWrapper } from 'enzyme'; -import { mount } from 'enzyme'; +import { fireEvent, render } from '@testing-library/react'; +import type { RenderResult } from '@testing-library/react'; import KeyCode from 'rc-util/lib/KeyCode'; import React, { Fragment } from 'react'; import Collapse, { Panel } from '../src/index'; @@ -24,10 +24,10 @@ describe('collapse', () => { } function runNormalTest(element: any) { - let collapse: ReactWrapper; + let collapse: RenderResult; beforeEach(() => { - collapse = mount(element); + collapse = render(element); }); afterEach(() => { @@ -36,77 +36,77 @@ describe('collapse', () => { it('add className', () => { const expectedClassName = 'rc-collapse-item important'; - expect(collapse.find('.rc-collapse-item').at(2).getDOMNode().className).toBe( + expect(collapse.container.querySelectorAll('.rc-collapse-item')?.[2]).toHaveClass( expectedClassName, ); }); it('create works', () => { - expect(collapse.find('.rc-collapse').length).toBe(1); + expect(collapse.container.querySelectorAll('.rc-collapse')).toHaveLength(1); }); it('header works', () => { - expect(collapse.find('.rc-collapse-header').length).toBe(3); + expect(collapse.container.querySelectorAll('.rc-collapse-header')).toHaveLength(3); }); it('panel works', () => { - expect(collapse.find('.rc-collapse-item').length).toBe(3); - expect(collapse.find('.rc-collapse-content').length).toBe(0); + expect(collapse.container.querySelectorAll('.rc-collapse-item')).toHaveLength(3); + expect(collapse.container.querySelectorAll('.rc-collapse-content')).toHaveLength(0); }); it('should render custom arrow icon corrctly', () => { - expect(collapse.find('.rc-collapse-header').at(0).getDOMNode().textContent).toContain( + expect(collapse.container.querySelector('.rc-collapse-header').textContent).toContain( 'test>', ); }); it('default active works', () => { - expect(collapse.find('.rc-collapse-item-active').length).toBe(0); + expect(collapse.container.querySelectorAll('.rc-collapse-item-active').length).toBeFalsy(); }); it('extra works', () => { - const extraNodes = collapse.find('.rc-collapse-extra'); - expect(extraNodes.length).toBe(1); - expect(extraNodes.at(0).getDOMNode().innerHTML).toBe('ExtraSpan'); + const extraNodes = collapse.container.querySelectorAll('.rc-collapse-extra'); + expect(extraNodes).toHaveLength(1); + expect(extraNodes?.[0]?.innerHTML).toBe('ExtraSpan'); }); it('onChange works', () => { changeHook = jest.fn(); - collapse.find('.rc-collapse-header').at(1).simulate('click'); + const header = collapse.container.querySelectorAll('.rc-collapse-header')?.[1]; + fireEvent.click(header); expect(changeHook.mock.calls[0][0]).toEqual(['2']); }); it('click should toggle panel state', () => { - const header = collapse.find('.rc-collapse-header').at(1); - header.simulate('click'); + const header = collapse.container.querySelectorAll('.rc-collapse-header')?.[1]; + fireEvent.click(header); jest.runAllTimers(); - collapse.update(); - expect(collapse.find('.rc-collapse-content-active').length).toBe(1); - header.simulate('click'); + expect(collapse.container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(1); + fireEvent.click(header); jest.runAllTimers(); - collapse.update(); - expect(collapse.find('.rc-collapse-content-inactive').at(0).getDOMNode().innerHTML).toBe( + expect(collapse.container.querySelector('.rc-collapse-content-inactive')?.innerHTML).toBe( '
second
', ); - expect(collapse.find('.rc-collapse-content-active').length).toBe(0); + expect(collapse.container.querySelectorAll('.rc-collapse-content-active').length).toBeFalsy(); }); it('click should not toggle disabled panel state', () => { - const header = collapse.find('.rc-collapse-header').at(0); - header.simulate('click'); + const header = collapse.container.querySelector('.rc-collapse-header'); + fireEvent.click(header); jest.runAllTimers(); - collapse.update(); - expect(collapse.find('.rc-collapse-content-active').length).toBe(0); + expect(collapse.container.querySelectorAll('.rc-collapse-content-active').length).toBeFalsy(); }); it('should not have role', () => { - const item = collapse.find('.rc-collapse').at(0); - expect(item.getDOMNode().getAttribute('role')).toBe(null); + const item = collapse.container.querySelector('.rc-collapse'); + expect(item).toBeTruthy(); + expect(item.getAttribute('role')).toBe(null); }); it('should set button role on panel title', () => { - const item = collapse.find('.rc-collapse-header').at(0); - expect(item.getDOMNode().getAttribute('role')).toBe('button'); + const item = collapse.container.querySelector('.rc-collapse-header'); + expect(item).toBeTruthy(); + expect(item.getAttribute('role')).toBe('button'); }); } @@ -130,53 +130,39 @@ describe('collapse', () => { runNormalTest(element); it('controlled', () => { - class ControlledCollapse extends React.Component { - state: { - activeKey: string[]; - } = { - activeKey: ['2'], - }; + const onChangeSpy = jest.fn(); - componentDidMount(): void { - this.setState({ - activeKey: ['2'], - }); - } + const ControlledCollapse = () => { + const [activeKey, updateActiveKey] = React.useState(['2']); - onChange = (val: string[]) => { - this.setState({ - activeKey: val, - }); + const handleChange = (key: string[]) => { + updateActiveKey(key); + onChangeSpy(key); }; - render() { - const { activeKey } = this.state; - return ( - - - first - - - second - - - third - - - ); - } - } - - const collapse = mount(); - - expect(collapse.find(Collapse).state('activeKey')).toEqual(['2']); - expect(collapse.find('.rc-collapse-content-active').length).toBe(1); - const header = collapse.find('.rc-collapse-header').at(0); - header.simulate('click'); + return ( + + + first + + + second + + + third + + + ); + }; + + const { container } = render(); + + expect(container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(1); + const header = container.querySelector('.rc-collapse-header'); + fireEvent.click(header); jest.runAllTimers(); - collapse.update(); - expect(collapse.state('activeKey')).toEqual(['2', '1']); - expect(collapse.find('.rc-collapse-content-active').length).toBe(2); + expect(container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(2); + expect(onChangeSpy).toBeCalledWith(['2', '1']); }); }); @@ -199,8 +185,8 @@ describe('collapse', () => { runNormalTest(element); }); - describe('it shoule support extra whit number 0', () => { - const collapse = mount( + it('shoule support extra whit number 0', () => { + const { container } = render( zero @@ -208,13 +194,13 @@ describe('collapse', () => { , ); - const extraNodes = collapse.find('.rc-collapse-extra'); - expect(extraNodes.length).toBe(1); - expect(extraNodes.at(0).getDOMNode().innerHTML).toBe('0'); + const extraNodes = container.querySelectorAll('.rc-collapse-extra'); + expect(extraNodes).toHaveLength(1); + expect(extraNodes[0].innerHTML).toBe('0'); }); - describe('it should support activeKey number 0', () => { - const collapse = mount( + it('should support activeKey number 0', () => { + const { container } = render( zero @@ -228,13 +214,12 @@ describe('collapse', () => { , ); - it('activeKey number 0, should open one item', () => { - expect(collapse.find('.rc-collapse-content-active').length).toBe(1); - }); + // activeKey number 0, should open one item + expect(container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(1); }); - describe('destroyInactivePanel', () => { - const collapse = mount( + it('click should toggle panel state', () => { + const { container } = render( first @@ -248,19 +233,18 @@ describe('collapse', () => { , ); - it('click should toggle panel state', () => { - const header = collapse.find('.rc-collapse-header').at(1); - header.simulate('click'); - expect(collapse.find('.rc-collapse-content-active').length).toBe(1); - header.simulate('click'); - expect(collapse.find('.rc-collapse-content-inactive').exists()).toBeFalsy(); - }); + const header = container.querySelectorAll('.rc-collapse-header')?.[1]; + fireEvent.click(header); + expect(container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(1); + fireEvent.click(header); + expect(container.querySelectorAll('.rc-collapse-content-inactive').length).toBeFalsy(); }); - describe('accordion', () => { - let collapse: ReactWrapper; + describe('prop: accordion', () => { + let collapse: RenderResult; + beforeEach(() => { - collapse = mount( + collapse = render( first @@ -276,70 +260,63 @@ describe('collapse', () => { }); it('accordion content, should default open zero item', () => { - expect(collapse.find('.rc-collapse-content-active').length).toBe(0); + expect(collapse.container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(0); }); it('accordion item, should default open zero item', () => { - expect(collapse.find('.rc-collapse-item-active').length).toBe(0); + expect(collapse.container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(0); }); it('should toggle show on panel', () => { - let header = collapse.find('.rc-collapse-header').at(1); - header.simulate('click'); + let header = collapse.container.querySelectorAll('.rc-collapse-header')?.[1]; + fireEvent.click(header); jest.runAllTimers(); - collapse.update(); - expect(collapse.find('.rc-collapse-content-active').length).toBe(1); - expect(collapse.find('.rc-collapse-item-active').length).toBe(1); - header = collapse.find('.rc-collapse-header').at(1); - header.simulate('click'); + expect(collapse.container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(1); + expect(collapse.container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(1); + header = collapse.container.querySelectorAll('.rc-collapse-header')?.[1]; + fireEvent.click(header); jest.runAllTimers(); - collapse.update(); - expect(collapse.find('.rc-collapse-content-active').exists()).toBeFalsy(); - expect(collapse.find('.rc-collapse-item-active').exists()).toBeFalsy(); + expect(collapse.container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(0); + expect(collapse.container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(0); }); it('should only show on panel', () => { - let header = collapse.find('.rc-collapse-header').at(1); - header.simulate('click'); + let header = collapse.container.querySelector('.rc-collapse-header'); + fireEvent.click(header); jest.runAllTimers(); - collapse.update(); - expect(collapse.find('.rc-collapse-content-active').length).toBe(1); - expect(collapse.find('.rc-collapse-item-active').length).toBe(1); - header = collapse.find('.rc-collapse-header').at(2); - header.simulate('click'); + expect(collapse.container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(1); + expect(collapse.container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(1); + header = collapse.container.querySelectorAll('.rc-collapse-header')?.[2]; + fireEvent.click(header); jest.runAllTimers(); - collapse.update(); - expect(collapse.find('.rc-collapse-content-active').length).toBe(1); - expect(collapse.find('.rc-collapse-item-active').length).toBe(1); + expect(collapse.container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(1); + expect(collapse.container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(1); }); it('should add tab role on panel title', () => { - const item = collapse.find('.rc-collapse-header').at(0); - expect(item.getDOMNode().getAttribute('role')).toBe('tab'); + const item = collapse.container.querySelector('.rc-collapse-header'); + expect(item).toBeTruthy(); + expect(item.getAttribute('role')).toBe('tab'); }); it('should add tablist role on accordion', () => { - const item = collapse.find('.rc-collapse').at(0); - expect(item.getDOMNode().getAttribute('role')).toBe('tablist'); + const item = collapse.container.querySelector('.rc-collapse'); + expect(item).toBeTruthy(); + expect(item.getAttribute('role')).toBe('tablist'); }); it('should add tablist role on PanelContent', () => { - const header = collapse.find('.rc-collapse-header').at(0); - header.simulate('click'); - const item = collapse.find('.rc-collapse-content').at(0); - expect(item.getDOMNode().getAttribute('role')).toBe('tabpanel'); + const header = collapse.container.querySelector('.rc-collapse-header'); + fireEvent.click(header); + const item = collapse.container.querySelector('.rc-collapse-content'); + expect(item).toBeTruthy(); + expect(item.getAttribute('role')).toBe('tabpanel'); }); }); describe('forceRender', () => { - let collapse: ReactWrapper; - - const renderCollapse = (element: any) => { - collapse = mount(element); - }; - it('when forceRender is not supplied it should lazy render the panel content', () => { - renderCollapse( + const { container } = render( first @@ -349,11 +326,11 @@ describe('collapse', () => { , ); - expect(collapse.find('.rc-collapse-content').length).toBe(0); + expect(container.querySelectorAll('.rc-collapse-content')).toHaveLength(0); }); it('when forceRender is FALSE it should lazy render the panel content', () => { - renderCollapse( + const { container } = render( first @@ -363,11 +340,11 @@ describe('collapse', () => { , ); - expect(collapse.find('.rc-collapse-content').length).toBe(0); + expect(container.querySelectorAll('.rc-collapse-content')).toHaveLength(0); }); it('when forceRender is TRUE then it should render all the panel content to the DOM', () => { - renderCollapse( + const { container } = render( first @@ -379,62 +356,58 @@ describe('collapse', () => { ); jest.runAllTimers(); - collapse.update(); - expect(collapse.find('.rc-collapse-content').length).toBe(1); - expect(collapse.find('.rc-collapse-content-active').length).toBe(0); - expect(collapse.find('div.rc-collapse-content-inactive').props().style).toEqual({ - display: 'none', - }); + expect(container.querySelectorAll('.rc-collapse-content')).toHaveLength(1); + expect(container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(0); + const inactiveDom = container.querySelector('div.rc-collapse-content-inactive'); + expect(inactiveDom).not.toBeFalsy(); + expect(getComputedStyle(inactiveDom)).toHaveProperty('display', 'none'); }); }); - describe('keyboard support', () => { - let collapse: ReactWrapper; - - const renderCollapse = (element: any) => { - collapse = mount(element); + it('should toggle panel when press enter', () => { + const myKeyEvent = { + key: 'Enter', + keyCode: 13, + which: 13, + // https://github.com/testing-library/react-testing-library/issues/269#issuecomment-455854112 + charCode: 13, }; - it('should toggle panel when press enter', () => { - renderCollapse( - - - first - - - second - - - second - - , - ); - collapse.find('.rc-collapse-header').at(2).simulate('keyPress', { - keyCode: KeyCode.ENTER, - }); - jest.runAllTimers(); - collapse.update(); - expect(collapse.find('.rc-collapse-content-active').length).toBe(0); - collapse.find('.rc-collapse-header').at(0).simulate('keyPress', { - keyCode: KeyCode.ENTER, - }); - jest.runAllTimers(); - collapse.update(); - expect(collapse.find('.rc-collapse-content-active').length).toBe(1); - expect( - collapse.find('.rc-collapse-content').at(0).hasClass('rc-collapse-content-active'), - ).toBeTruthy(); - collapse.find('.rc-collapse-header').at(0).simulate('keyPress', { - keyCode: KeyCode.ENTER, - }); - jest.runAllTimers(); - collapse.update(); - expect(collapse.find('.rc-collapse-content-active').length).toBe(0); - expect( - collapse.find('.rc-collapse-content').at(0).hasClass('rc-collapse-content-active'), - ).toBeFalsy(); - }); + const { container } = render( + + + first + + + second + + + second + + , + ); + + fireEvent.keyPress(container.querySelectorAll('.rc-collapse-header')?.[2], myKeyEvent); + jest.runAllTimers(); + expect(container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(0); + + fireEvent.keyPress(container.querySelector('.rc-collapse-header'), myKeyEvent); + jest.runAllTimers(); + + expect(container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(1); + + expect(container.querySelector('.rc-collapse-content')).toHaveClass( + 'rc-collapse-content-active', + ); + + fireEvent.keyPress(container.querySelector('.rc-collapse-header'), myKeyEvent); + jest.runAllTimers(); + + expect(container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(0); + expect(container.querySelector('.rc-collapse-content').className).not.toContain( + 'rc-collapse-content-active', + ); }); describe('wrapped in Fragment', () => { @@ -461,18 +434,18 @@ describe('collapse', () => { }); it('should support return null icon', () => { - const wrapper = mount( + const { container } = render( null}> first , ); - expect(wrapper.find('.rc-collapse-header').at(0).getDOMNode().childNodes.length).toBe(1); + expect(container.querySelector('.rc-collapse-header').childNodes).toHaveLength(1); }); it('should support custom child', () => { - const collapse = mount( + const { container } = render( first @@ -480,7 +453,7 @@ describe('collapse', () => { custom-child , ); - expect(collapse.find('.custom-child').getDOMNode().innerHTML).toBe('custom-child'); + expect(container.querySelector('.custom-child').innerHTML).toBe('custom-child'); }); // https://github.com/ant-design/ant-design/issues/36327 @@ -492,7 +465,7 @@ describe('collapse', () => {

test

); - const collapse = mount( + const { container } = render( @@ -500,93 +473,96 @@ describe('collapse', () => { , ); - expect(collapse.find('.rc-collapse-content-active').length).toBe(1); - expect(collapse.find('.rc-collapse-content').hasClass('rc-collapse-content-active')).toBe(true); - expect(collapse.find('.rc-collapse-header').at(0).text()).toBe('collapse 1'); - expect(collapse.find('.rc-collapse-header').at(0).find('.arrow').length).toBe(1); - collapse.find('.rc-collapse-header').at(0).simulate('click'); - expect(collapse.find('.rc-collapse-content-active').length).toBe(0); - expect(collapse.find('.rc-collapse-content').hasClass('rc-collapse-content-inactive')).toBe( - true, + + expect(container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(1); + expect(container.querySelector('.rc-collapse-content')).toHaveClass( + 'rc-collapse-content-active', + ); + expect(container.querySelector('.rc-collapse-header').textContent).toBe('collapse 1'); + expect(container.querySelector('.rc-collapse-header').querySelectorAll('.arrow')).toHaveLength( + 1, + ); + fireEvent.click(container.querySelector('.rc-collapse-header')); + expect(container.querySelectorAll('.rc-collapse-content-active')).toHaveLength(0); + expect(container.querySelector('.rc-collapse-content')).toHaveClass( + 'rc-collapse-content-inactive', ); }); - describe('collapsible', () => { + describe('prop: collapsible', () => { it('default', () => { - const collapse = mount( + const { container } = render( first , ); - expect(collapse.find('.rc-collapse-header-text').exists()).toBeTruthy(); - collapse.find('.rc-collapse-header').simulate('click'); - expect(collapse.find('.rc-collapse-item-active').length).toBe(1); + expect(container.querySelector('.rc-collapse-header-text')).toBeTruthy(); + fireEvent.click(container.querySelector('.rc-collapse-header')); + expect(container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(1); }); it('should work when value is header', () => { - const collapse = mount( + const { container } = render( first , ); - expect(collapse.find('.rc-collapse-header-text').exists()).toBeTruthy(); - collapse.find('.rc-collapse-header').simulate('click'); - expect(collapse.find('.rc-collapse-item-active').length).toBe(0); - collapse.find('.rc-collapse-header-text').simulate('click'); - expect(collapse.find('.rc-collapse-item-active').length).toBe(1); + expect(container.querySelector('.rc-collapse-header-text')).toBeTruthy(); + fireEvent.click(container.querySelector('.rc-collapse-header')); + expect(container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(0); + fireEvent.click(container.querySelector('.rc-collapse-header-text')); + expect(container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(1); }); it('should work when value is icon', () => { - const collapse = mount( + const { container } = render( first , ); - expect(collapse.find('.rc-collapse-expand-icon').exists()).toBeTruthy(); - collapse.find('.rc-collapse-header').simulate('click'); - expect(collapse.find('.rc-collapse-item-active').length).toBe(0); - collapse.find('.rc-collapse-expand-icon').simulate('click'); - expect(collapse.find('.rc-collapse-item-active').length).toBe(1); + expect(container.querySelector('.rc-collapse-expand-icon')).toBeTruthy(); + fireEvent.click(container.querySelector('.rc-collapse-header')); + expect(container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(0); + fireEvent.click(container.querySelector('.rc-collapse-expand-icon')); + expect(container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(1); }); it('should disabled when value is disabled', () => { - const collapse = mount( + const { container } = render( first , ); - expect(collapse.find('.rc-collapse-header-text').exists()).toBeTruthy(); - - expect(collapse.find('.rc-collapse-item-disabled').length).toBe(1); - - collapse.find('.rc-collapse-header').simulate('click'); - expect(collapse.find('.rc-collapse-item-active').length).toBe(0); + expect(container.querySelector('.rc-collapse-header-text')).toBeTruthy(); + expect(container.querySelectorAll('.rc-collapse-item-disabled')).toHaveLength(1); + fireEvent.click(container.querySelector('.rc-collapse-header')); + expect(container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(0); }); it('the value of panel should be read first', () => { - const collapse = mount( + const { container } = render( first , ); - expect(collapse.find('.rc-collapse-header-text').exists()).toBeTruthy(); + expect(container.querySelector('.rc-collapse-header-text')).toBeTruthy(); - expect(collapse.find('.rc-collapse-item-disabled').length).toBe(1); + expect(container.querySelectorAll('.rc-collapse-item-disabled')).toHaveLength(1); - collapse.find('.rc-collapse-header').simulate('click'); - expect(collapse.find('.rc-collapse-item-active').length).toBe(0); + fireEvent.click(container.querySelector('.rc-collapse-header')); + expect(container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(0); }); it('icon trigger when collapsible equal header', () => { - const collapse = mount( + const { container } = render( first @@ -594,12 +570,12 @@ describe('collapse', () => { , ); - collapse.find('.rc-collapse-header .arrow').simulate('click'); - expect(collapse.find('.rc-collapse-item-active').length).toBe(1); + fireEvent.click(container.querySelector('.rc-collapse-header .arrow')); + expect(container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(1); }); it('header not trigger when collapsible equal icon', () => { - const collapse = mount( + const { container } = render( first @@ -607,13 +583,13 @@ describe('collapse', () => { , ); - collapse.find('.rc-collapse-header-text').simulate('click'); - expect(collapse.find('.rc-collapse-item-active').length).toBe(0); + fireEvent.click(container.querySelector('.rc-collapse-header-text')); + expect(container.querySelectorAll('.rc-collapse-item-active')).toHaveLength(0); }); }); it('!showArrow', () => { - const wrapper = mount( + const { container } = render( first @@ -621,12 +597,12 @@ describe('collapse', () => { , ); - expect(wrapper.exists('.rc-collapse-expand-icon')).toBeFalsy(); + expect(container.querySelectorAll('.rc-collapse-expand-icon')).toHaveLength(0); }); it('Panel container dom can set event handler', () => { const clickHandler = jest.fn(); - const wrapper = mount( + const { container } = render(
Click this
@@ -634,7 +610,7 @@ describe('collapse', () => {
, ); - wrapper.find('.target').simulate('click'); + fireEvent.click(container.querySelector('.target')); expect(clickHandler).toHaveBeenCalled(); }); }); diff --git a/tests/setup.js b/tests/setup.js deleted file mode 100644 index 4c18e28..0000000 --- a/tests/setup.js +++ /dev/null @@ -1,6 +0,0 @@ -global.requestAnimationFrame = cb => setTimeout(cb, 0); - -const Enzyme = require('enzyme'); -const Adapter = require('enzyme-adapter-react-16'); - -Enzyme.configure({ adapter: new Adapter() }); diff --git a/tests/setupAfterEnv.ts b/tests/setupAfterEnv.ts new file mode 100644 index 0000000..7b0828b --- /dev/null +++ b/tests/setupAfterEnv.ts @@ -0,0 +1 @@ +import '@testing-library/jest-dom'; diff --git a/tsconfig.json b/tsconfig.json index e7bd793..b3e270a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,13 +3,13 @@ "target": "esnext", "moduleResolution": "node", "baseUrl": "./", - "jsx": "preserve", + "jsx": "react", "declaration": true, "skipLibCheck": true, "esModuleInterop": true, "paths": { "@/*": ["src/*"], - "@@/*": ["src/.umi/*"], + "@@/*": ["src/.dumi/*"], "rc-collapse": ["src/index.tsx"] } }