From 94c2da1ae4d13c3fa025a49331c14ac932abdee9 Mon Sep 17 00:00:00 2001 From: xrkffgg Date: Thu, 27 Aug 2020 16:57:09 +0800 Subject: [PATCH] chore: use father (#197) * chore: use father * Update .gitignore * chore: update * update travis * update * modified: package.json * fix typings * modified: package.json * modified: package.json * modified: package.json * modified: package.json * add coverage * update expect * test * fix one test * update ref * update * update test * update test * update test * update test * fix compile * fix transformOrigin * fix input * fix: click mask to close * fix(test): getContainer * fix activeElement * simple tarnsformOrigin * update test * fix overflow * fix eslint Co-authored-by: zombiej Co-authored-by: Kermit --- .eslintrc.js | 22 ++ .fatherrc.js | 9 + .gitignore | 5 +- .prettierrc | 6 + .travis.yml | 1 + examples/ant-design.html | 0 examples/ant-design.tsx | 378 +++++++++++++-------------- examples/bootstrap.html | 0 examples/bootstrap.tsx | 247 +++++++++--------- examples/multiple-Portal.html | 0 examples/multiple-Portal.tsx | 19 +- index.js | 3 - jest.config.js | 4 + now.json | 11 + package.json | 86 +++---- src/Dialog.tsx | 170 +++++++------ src/DialogWrap.tsx | 30 +-- src/IDialogPropTypes.tsx | 4 +- src/LazyRenderBox.tsx | 1 + src/index.ts | 6 + tests/index.js | 465 ---------------------------------- tests/index.spec.js | 428 +++++++++++++++++++++++++++++++ tests/setup.js | 6 + tsconfig.json | 9 - typings/custom.d.ts | 11 +- typings/index.d.ts | 1 - 26 files changed, 943 insertions(+), 979 deletions(-) create mode 100644 .eslintrc.js create mode 100644 .fatherrc.js create mode 100644 .prettierrc delete mode 100644 examples/ant-design.html delete mode 100644 examples/bootstrap.html delete mode 100644 examples/multiple-Portal.html delete mode 100644 index.js create mode 100644 jest.config.js create mode 100644 now.json create mode 100644 src/index.ts delete mode 100644 tests/index.js create mode 100644 tests/index.spec.js create mode 100644 tests/setup.js delete mode 100644 tsconfig.json delete mode 100644 typings/index.d.ts diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..54d1afd5 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,22 @@ +const base = require("@umijs/fabric/dist/eslint"); + +module.exports = { + ...base, + rules: { + ...base.rules, + "arrow-parens": 0, + "react/no-array-index-key": 0, + "react/sort-comp": 0, + "@typescript-eslint/no-explicit-any": 0, + "@typescript-eslint/no-empty-interface": 0, + "@typescript-eslint/no-inferrable-types": 0, + "react/require-default-props": 0, + "no-confusing-arrow": 0, + "import/no-named-as-default-member": 0, + "jsx-a11y/label-has-for": 0, + "jsx-a11y/label-has-associated-control": 0, + "import/no-extraneous-dependencies": 0, + "jsx-a11y/no-noninteractive-tabindex": 0, + "jsx-a11y/no-autofocus": 0, + }, +}; diff --git a/.fatherrc.js b/.fatherrc.js new file mode 100644 index 00000000..9d8c16b0 --- /dev/null +++ b/.fatherrc.js @@ -0,0 +1,9 @@ +export default { + cjs: "babel", + esm: { type: "babel", importLibToEs: true }, + preCommit: { + eslint: true, + prettier: true, + }, + runtimeHelpers: true, +}; diff --git a/.gitignore b/.gitignore index 27e6a383..d7e68431 100644 --- a/.gitignore +++ b/.gitignore @@ -25,11 +25,12 @@ build lib es coverage -*.js *.jsx *.map !tests/index.js !/index*.js /ios/ /android/ -yarn.lock \ No newline at end of file +yarn.lock +.storybook +.doc diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..895b8bdc --- /dev/null +++ b/.prettierrc @@ -0,0 +1,6 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "proseWrap": "never", + "printWidth": 100 +} diff --git a/.travis.yml b/.travis.yml index 313a4cbc..76e37e47 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,3 +30,4 @@ env: - TEST_TYPE=lint - TEST_TYPE=test - TEST_TYPE=coverage + - TEST_TYPE=compile diff --git a/examples/ant-design.html b/examples/ant-design.html deleted file mode 100644 index e69de29b..00000000 diff --git a/examples/ant-design.tsx b/examples/ant-design.tsx index c74dd3a7..6e03053c 100644 --- a/examples/ant-design.tsx +++ b/examples/ant-design.tsx @@ -1,8 +1,6 @@ /* eslint no-console:0 */ -import 'rc-dialog/assets/index.less'; +import '../assets/index.less'; import * as React from 'react'; -import * as ReactDOM from 'react-dom'; -// use import Dialog from 'rc-dialog' import Dialog from '../src/DialogWrap'; const clearPath = 'M793 242H366v-74c0-6.7-7.7-10.4-12.9' + @@ -27,224 +25,196 @@ const getSvg = (path: string, props = {}, align = false) => { ); }; -class MyControl extends React.Component { - state = { - visible: false, - visible2: false, - visible3: true, - width: 600, - destroyOnClose: false, - center: false, - mousePosition: undefined, - useIcon: false, - forceRender: false, - }; - - onClick = (e: React.MouseEvent) => { - this.setState({ - mousePosition: { - x: e.pageX, - y: e.pageY, - }, - visible: true, +const MyControl = () => { + const [visible1, setVisible1] = React.useState(false); + const [visible2, setVisible2] = React.useState(false); + const [visible3, setVisible3] = React.useState(true); + const [width, setWidth] = React.useState(600); + const [destroyOnClose, setDestroyOnClose] = React.useState(false); + const [center, setCenter] = React.useState(false); + const [mousePosition, setMousePosition] = React.useState({ + x: null, + y: null + }); + const [useIcon, setUseIcon] = React.useState(false); + const [forceRender, setForceRender] = React.useState(false); + + const onClick = (e: React.MouseEvent) => { + setMousePosition({ + x: e.pageX, + y: e.pageY, }); + setVisible1(true); } - onClose = (e: React.SyntheticEvent) => { - this.setState({ - visible: false, - }); + const onClose = () => { + setVisible1(false); } - onClose2 = (e: React.SyntheticEvent) => { - this.setState({ - visible: false, - visible2: false, - }); + const onClose2 = () => { + setVisible2(false); } - onClose3 = (e: React.SyntheticEvent) => { - this.setState({ visible3: false }); + const onClose3 = () => { + setVisible3(false); } - onDestroyOnCloseChange = (e: React.ChangeEvent) => { - this.setState({ - destroyOnClose: e.target.checked, - }); + const closeAll = () => { + setVisible1(false); + setVisible2(false); + setVisible3(false); } - onForceRenderChange = (e: React.ChangeEvent) => { - this.setState({ - forceRender: e.target.checked, - }); + const onDestroyOnCloseChange = (e: React.ChangeEvent) => { + setDestroyOnClose(e.target.checked); } - changeWidth = () => { - this.setState({ - width: this.state.width === 600 ? 800 : 600, - }); + const onForceRenderChange = (e: React.ChangeEvent) => { + setForceRender(e.target.checked); } - center = (e: React.ChangeEvent) => { - this.setState({ - center: e.target.checked, - }); + const changeWidth = () => { + setWidth(width === 600 ? 800 : 600); } - toggleCloseIcon = () => { - this.setState({ - useIcon: !this.state.useIcon, - }); + const centerEvent = (e: React.ChangeEvent) => { + setCenter(e.target.checked); } - render() { - const style = { - width: this.state.width, - }; - let wrapClassName = ''; - if (this.state.center) { - wrapClassName = 'center'; - } - const dialog = ( - - -

basic modal

- - - - -
-
- ); - - const dialog2 = ( - - -

basic modal

- - - - - -
-
- ); - - const dialog3 = ( - -

initialized with forceRender and visbile true

- - - - -
-
- ); - - return ( -
- -

- -   - -   - -   - -

- {dialog} - {dialog2} - {dialog3} -
- ); + const toggleCloseIcon = () => { + setUseIcon(!useIcon); + } + + const style = { width }; + + let wrapClassName = ''; + if (center) { + wrapClassName = 'center'; } -} - -ReactDOM.render( -
-

ant-design dialog

- -
, - document.getElementById('__react-content'), -); + + const dialog = ( + + +

basic modal

+ + + + +
+
+ ); + + const dialog2 = ( + + +

basic modal

+ + + + + +
+
+ ); + + const dialog3 = ( + +

initialized with forceRender and visbile true

+ + + + +
+
+ ); + + return ( +
+ +

+ +   + +   + +   + +

+ {dialog} + {dialog2} + {dialog3} +
+ ); +}; + +export default MyControl; diff --git a/examples/bootstrap.html b/examples/bootstrap.html deleted file mode 100644 index e69de29b..00000000 diff --git a/examples/bootstrap.tsx b/examples/bootstrap.tsx index 23513b10..03ecdbe8 100644 --- a/examples/bootstrap.tsx +++ b/examples/bootstrap.tsx @@ -1,144 +1,133 @@ import 'bootstrap/dist/css/bootstrap.css'; -import 'rc-dialog/assets/bootstrap.less'; +import '../assets/bootstrap.less'; import * as React from 'react'; -import * as ReactDOM from 'react-dom'; import Dialog from '../src/DialogWrap'; -class MyControl extends React.Component { - state = { - visible: false, - destroyOnClose: false, - }; - onClick = () => { - this.setState({ - visible: true, - }); +const MyControl = () => { + const [visible, setVisible] = React.useState(false); + const [destroyOnClose, setDestroyOnClose] = React.useState(false); + + const onClick = () => { + setVisible(true); } - onClose = () => { - this.setState({ - visible: false, - }); + + const onClose = () => { + setVisible(false); } - onDestroyOnCloseChange = (e: React.ChangeEvent) => { - this.setState({ - destroyOnClose: e.target.checked, - }); + + const onDestroyOnCloseChange = (e: React.ChangeEvent) => { + setDestroyOnClose(e.target.checked); } - render() { - let dialog; - if (this.state.visible || !this.state.destroyOnClose) { - dialog = ( - 第二个弹框} - footer={ - [ - , - , - ] - } - >

Text in a modal

-

Duis mollis, est non commodo luctus, nisi erat porttitor ligula.

-
-

Overflowing text to show scroll behavior

+ + let dialog; + + if (visible || !destroyOnClose) { + dialog = ( + 第二个弹框} + footer={ + [ + , + , + ] + } + >

Text in a modal

+

Duis mollis, est non commodo luctus, nisi erat porttitor ligula.

+
+

Overflowing text to show scroll behavior

+

Cras mattis consectetur purus sit amet fermentum. + Cras justo odio, dapibus ac facilisis in, + egestas eget quam. Morbi leo risus, porta ac consectetur ac, + vestibulum at eros. +

+

+ {' '} + {' '} + {' '} + {' '} + {' '} + {' '} +

+

Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus + sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. +

+
+

Aenean lacinia bibendum nulla sed + consectetur. Praesent commodo cursus magna, + vel scelerisque nisl consectetur et. Donec sed odio dui. + Donec + ullamcorper nulla non metus auctor fringilla. +

+

Cras mattis consectetur purus sit amet fermentum. + Cras justo odio, dapibus ac facilisis in, egestas + eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. +

+

Praesent commodo cursus + magna, vel scelerisque nisl consectetur et. + Vivamus sagittis lacus vel augue laoreet rutrum faucibus + dolor auctor. +

+

Aenean lacinia bibendum nulla sed consectetur. + Praesent commodo cursus magna, vel + scelerisque nisl consectetur et. Donec sed odio dui. + Donec ullamcorper nulla non metus auctor + fringilla. +

Cras mattis consectetur purus sit amet fermentum. - Cras justo odio, dapibus ac facilisis in, - egestas eget quam. Morbi leo risus, porta ac consectetur ac, - vestibulum at eros. + Cras justo odio, dapibus ac + facilisis in, egestas eget quam. Morbi leo risus, + porta ac consectetur ac, vestibulum at eros.

- {' '} - {' '} - {' '} - {' '} - {' '} - {' '} + Praesent commodo cursus magna, vel scelerisque nisl consectetur et. + Vivamus sagittis lacus vel augue + laoreet rutrum faucibus dolor auctor.

-

Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus - sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. +

Aenean lacinia bibendum nulla sed consectetur. Praesent + commodo cursus magna, vel scelerisque nisl consectetur et. + Donec sed odio dui. Donec ullamcorper nulla + non metus auctor fringilla.

-
-

Aenean lacinia bibendum nulla sed - consectetur. Praesent commodo cursus magna, - vel scelerisque nisl consectetur et. Donec sed odio dui. - Donec - ullamcorper nulla non metus auctor fringilla. -

-

Cras mattis consectetur purus sit amet fermentum. - Cras justo odio, dapibus ac facilisis in, egestas - eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. -

-

Praesent commodo cursus - magna, vel scelerisque nisl consectetur et. - Vivamus sagittis lacus vel augue laoreet rutrum faucibus - dolor auctor. -

-

Aenean lacinia bibendum nulla sed consectetur. - Praesent commodo cursus magna, vel - scelerisque nisl consectetur et. Donec sed odio dui. - Donec ullamcorper nulla non metus auctor - fringilla. -

-

Cras mattis consectetur purus sit amet fermentum. - Cras justo odio, dapibus ac - facilisis in, egestas eget quam. Morbi leo risus, - porta ac consectetur ac, vestibulum at eros. -

-

- Praesent commodo cursus magna, vel scelerisque nisl consectetur et. - Vivamus sagittis lacus vel augue - laoreet rutrum faucibus dolor auctor. -

-

Aenean lacinia bibendum nulla sed consectetur. Praesent - commodo cursus magna, vel scelerisque nisl consectetur et. - Donec sed odio dui. Donec ullamcorper nulla - non metus auctor fringilla. -

-
-
- ); - } - return ( -
-

- -   - -

- {dialog} -
+ +
); } -} -ReactDOM.render( -
-

ant-design dialog

- -
, - document.getElementById('__react-content'), -); + return ( +
+

+ +   + +

+ {dialog} +
+ ); +}; + +export default MyControl; diff --git a/examples/multiple-Portal.html b/examples/multiple-Portal.html deleted file mode 100644 index e69de29b..00000000 diff --git a/examples/multiple-Portal.tsx b/examples/multiple-Portal.tsx index 9aa0bc5a..81350206 100644 --- a/examples/multiple-Portal.tsx +++ b/examples/multiple-Portal.tsx @@ -1,9 +1,8 @@ import * as React from 'react'; -import * as ReactDOM from 'react-dom'; -import Dialog from '../src/DialogWrap'; import Drawer from 'rc-drawer'; +import Dialog from '../src/DialogWrap'; import 'rc-drawer/assets/index.css'; -import 'rc-dialog/assets/index.less'; +import '../assets/index.less'; const { useState } = React; @@ -28,7 +27,7 @@ const Demo = () => { forceRender >

basic modal

-

+

); @@ -39,22 +38,16 @@ const Demo = () => { onClose={onToggleDrawer} level={null} > - + ); return (
- + {dialog} {drawer}
); }; -ReactDOM.render( -
-

multiple dialog

- -
, - document.getElementById('__react-content'), -); +export default Demo; diff --git a/index.js b/index.js deleted file mode 100644 index 083513eb..00000000 --- a/index.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict'; - -module.exports = require('./src/DialogWrap'); diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 00000000..0a096396 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,4 @@ +module.exports = { + setupFiles: ["./tests/setup.js"], + snapshotSerializers: [require.resolve("enzyme-to-json/serializer")], +}; diff --git a/now.json b/now.json new file mode 100644 index 00000000..1d18e2a0 --- /dev/null +++ b/now.json @@ -0,0 +1,11 @@ +{ + "version": 2, + "name": "rc-dialog", + "builds": [ + { + "src": "package.json", + "use": "@now/static-build", + "config": { "distDir": ".doc" } + } + ] +} diff --git a/package.json b/package.json index 6f10cef9..461b3d7b 100644 --- a/package.json +++ b/package.json @@ -25,61 +25,49 @@ "assets/*.css", "dist" ], - "main": "./lib/DialogWrap", - "module": "./es/DialogWrap", - "config": { - "port": 8007, - "entry": { - "rc-dialog": [ - "./index.js", - "./assets/index.less" - ], - "rc-dialog-bootstrap": [ - "./index.js", - "./assets/bootstrap.less" - ] - } - }, + "main": "./lib/index", + "module": "./es/index", "scripts": { - "watch-tsc": "rc-tools run watch-tsc", - "build": "rc-tools run build", - "dist": "rc-tools run dist", - "gh-pages": "rc-tools run gh-pages", - "start": "rc-tools run server", - "compile": "rc-tools run compile", - "pub": "rc-tools run pub", - "lint": "rc-tools run lint --no-js-lint", - "lint:ts": "tsc", - "karma": "rc-test run karma", - "saucelabs": "rc-test run saucelabs", - "test": "rc-test run test", - "chrome-test": "rc-test run chrome-test", - "coverage": "rc-test run coverage", - "prepublish": "rc-tools run guard" + "start": "cross-env NODE_ENV=development father doc dev --storybook", + "build": "father doc build --storybook", + "compile": "father build && lessc assets/index.less assets/index.css && lessc assets/bootstrap.less assets/bootstrap.css", + "gh-pages": "npm run build && father doc deploy", + "prepublishOnly": "npm run compile && np --yolo --no-publish", + "lint": "eslint src/ --ext .ts,.tsx,.jsx,.js,.md", + "prettier": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"", + "test": "father test", + "coverage": "father test --coverage" + }, + "peerDependencies": { + "react": "^16.0.0", + "react-dom": "^16.0.0" + }, + "dependencies": { + "@babel/runtime": "^7.10.1", + "rc-animate": "3.x", + "rc-util": "^5.0.1", + "request": "^2.88.2" }, "devDependencies": { - "@types/mocha": "~8.0.0", - "@types/react": "^16.0.19", - "@types/react-dom": "^16.0.2", - "async": "^0.9.0", + "@types/jest": "^26.0.0", + "@types/react": "^16.9.2", + "@types/react-dom": "^16.9.0", + "@umijs/fabric": "^2.0.0", "bluebird": "~3.7.2", "bootstrap": "^4.3.1", - "core-js": "^2.5.1", - "expect.js": "~0.3.1", + "cross-env": "^7.0.0", + "enzyme": "^3.1.1", + "enzyme-adapter-react-16": "^1.0.1", + "enzyme-to-json": "^3.1.2", + "eslint": "^7.1.0", + "eslint-config-airbnb": "^18.2.0", + "eslint-plugin-react": "^7.20.6", + "father": "^2.29.6", "jquery": "^3.3.1", - "pre-commit": "1.x", "rc-drawer": "4.1.0", - "rc-test": "^6.0.1", - "rc-tools": "7.x", - "react": "^16.0.0", - "react-dom": "^16.0.0" + "react": "^16.9.0", + "react-dom": "^16.9.0", + "typescript": "^3.7.2" }, - "pre-commit": [ - "lint" - ], - "typings": "./lib/DialogWrap.d.ts", - "dependencies": { - "rc-animate": "3.x", - "rc-util": "^5.0.1" - } + "typings": "./lib/DialogWrap.d.ts" } diff --git a/src/Dialog.tsx b/src/Dialog.tsx index f3611ec3..485c77d3 100644 --- a/src/Dialog.tsx +++ b/src/Dialog.tsx @@ -4,7 +4,7 @@ import KeyCode from 'rc-util/lib/KeyCode'; import contains from 'rc-util/lib/Dom/contains'; import Animate from 'rc-animate'; import LazyRenderBox from './LazyRenderBox'; -import IDialogPropTypes from './IDialogPropTypes'; +import { IDialogPropTypes } from './IDialogPropTypes'; let uuid = 0; @@ -24,11 +24,11 @@ function getScroll(w: any, top?: boolean) { } function setTransformOrigin(node: any, value: string) { - const style = node.style; + const { style } = node; ['Webkit', 'Moz', 'Ms', 'ms'].forEach((prefix: string) => { style[`${prefix}TransformOrigin`] = value; }); - style[`transformOrigin`] = value; + style.transformOrigin = value; } function offset(el: any) { @@ -63,20 +63,31 @@ export default class Dialog extends React.Component { }; private inTransition: boolean = false; + private titleId: string; + private openTime: number; + private lastOutSideFocusNode: HTMLElement | null; + private wrap: HTMLElement; + private dialog: any; + private sentinelStart: HTMLElement; + private sentinelEnd: HTMLElement; + private dialogMouseDown: boolean; - private timeoutId: number; + + private timeoutId: any; + private switchScrollingEffect: () => void; constructor(props: IDialogChildProps) { super(props); - this.titleId = `rcDialogTitle${uuid++}`; + this.titleId = `rcDialogTitle${uuid}`; + uuid += 1; this.switchScrollingEffect = props.switchScrollingEffect || (() => {}); } @@ -95,14 +106,15 @@ export default class Dialog extends React.Component { } componentDidUpdate(prevProps: IDialogPropTypes) { - const {visible, mask, focusTriggerAfterClose} = this.props; - const mousePosition = this.props.mousePosition; + const { visible, mask, focusTriggerAfterClose } = this.props; + const { mousePosition } = this.props; if (visible) { // first show if (!prevProps.visible) { this.openTime = Date.now(); this.switchScrollingEffect(); this.tryFocus(); + // eslint-disable-next-line react/no-find-dom-node const dialogNode = ReactDOM.findDOMNode(this.dialog); if (mousePosition) { const elOffset = offset(dialogNode); @@ -158,11 +170,11 @@ export default class Dialog extends React.Component { if (afterClose) { afterClose(); } - } + }; onDialogMouseDown = () => { this.dialogMouseDown = true; - } + }; onMaskMouseUp: React.MouseEventHandler = () => { if (this.dialogMouseDown) { @@ -170,7 +182,7 @@ export default class Dialog extends React.Component { this.dialogMouseDown = false; }, 0); } - } + }; onMaskClick = (e: React.MouseEvent) => { // android trigger click on open (fastclick??) @@ -180,58 +192,71 @@ export default class Dialog extends React.Component { if (e.target === e.currentTarget && !this.dialogMouseDown) { this.close(e); } - } + }; onKeyDown = (e: React.KeyboardEvent) => { - const props = this.props; - if (props.keyboard && e.keyCode === KeyCode.ESC) { + const { keyboard, visible } = this.props; + if (keyboard && e.keyCode === KeyCode.ESC) { e.stopPropagation(); this.close(e); return; } // keep focus inside dialog - if (props.visible) { + if (visible) { if (e.keyCode === KeyCode.TAB) { - const activeElement = document.activeElement; - const sentinelStart = this.sentinelStart; + const { activeElement } = document; if (e.shiftKey) { - if (activeElement === sentinelStart) { + if (activeElement === this.sentinelStart) { this.sentinelEnd.focus(); } } else if (activeElement === this.sentinelEnd) { - sentinelStart.focus(); + this.sentinelStart.focus(); } } } - } + }; getDialogElement = () => { - const props = this.props; - const closable = props.closable; - const prefixCls = props.prefixCls; + const { + closable, + prefixCls, + width, + height, + footer, + title, + closeIcon, + style, + className, + visible, + forceRender, + bodyStyle, + bodyProps, + children, + destroyOnClose, + } = this.props; const dest: any = {}; - if (props.width !== undefined) { - dest.width = props.width; + if (width !== undefined) { + dest.width = width; } - if (props.height !== undefined) { - dest.height = props.height; + if (height !== undefined) { + dest.height = height; } - let footer; - if (props.footer) { - footer = ( + let footerNode; + if (footer) { + footerNode = (
- {props.footer} + {footer}
); } - let header; - if (props.title) { - header = ( + let headerNode; + if (title) { + headerNode = (
- {props.title} + {title}
); @@ -246,12 +271,12 @@ export default class Dialog extends React.Component { aria-label="Close" className={`${prefixCls}-close`} > - {props.closeIcon || } + {closeIcon || } ); } - const style = { ...props.style, ...dest }; + const styleBox = { ...style, ...dest }; const sentinelStyle = { width: 0, height: 0, overflow: 'hidden', outline: 'none' }; const transitionName = this.getTransitionName(); const dialogElement = ( @@ -259,10 +284,10 @@ export default class Dialog extends React.Component { key="dialog-element" role="document" ref={this.saveRef('dialog')} - style={style} - className={`${prefixCls} ${props.className || ''}`} - visible={props.visible} - forceRender={props.forceRender} + style={styleBox} + className={`${prefixCls} ${className || ''}`} + visible={visible} + forceRender={forceRender} onMouseDown={this.onDialogMouseDown} >
{ />
{closer} - {header} + {headerNode}
- {props.children} + {children}
- {footer} + {footerNode}
{ component="" transitionAppear > - {props.visible || !props.destroyOnClose ? dialogElement : null} + {visible || !destroyOnClose ? dialogElement : null} ); - } + }; getZIndexStyle = () => { const style: any = {}; - const props = this.props; - if (props.zIndex !== undefined) { - style.zIndex = props.zIndex; + const { zIndex } = this.props; + if (zIndex !== undefined) { + style.zIndex = zIndex; } return style; - } + }; getWrapStyle = (): any => { return { ...this.getZIndexStyle(), ...this.props.wrapStyle }; - } + }; getMaskStyle = () => { return { ...this.getZIndexStyle(), ...this.props.maskStyle }; - } + }; getMaskElement = () => { - const props = this.props; + const { mask, prefixCls, visible, maskProps } = this.props; let maskElement; - if (props.mask) { + if (mask) { const maskTransition = this.getMaskTransitionName(); maskElement = ( ); if (maskTransition) { @@ -354,39 +379,38 @@ export default class Dialog extends React.Component { } } return maskElement; - } + }; getMaskTransitionName = () => { - const props = this.props; - let transitionName = props.maskTransitionName; - const animation = props.maskAnimation; + const { maskTransitionName, maskAnimation, prefixCls } = this.props; + let transitionName = maskTransitionName; + const animation = maskAnimation; if (!transitionName && animation) { - transitionName = `${props.prefixCls}-${animation}`; + transitionName = `${prefixCls}-${animation}`; } return transitionName; - } + }; getTransitionName = () => { - const props = this.props; - let transitionName = props.transitionName; - const animation = props.animation; + const { transitionName, animation, prefixCls } = this.props; + let transitionNameResult = transitionName; if (!transitionName && animation) { - transitionName = `${props.prefixCls}-${animation}`; + transitionNameResult = `${prefixCls}-${animation}`; } - return transitionName; - } + return transitionNameResult; + }; close = (e: any) => { const { onClose } = this.props; if (onClose) { onClose(e); } - } + }; saveRef = (name: string) => (node: any) => { (this as any)[name] = node; - } + }; render() { const { props } = this; diff --git a/src/DialogWrap.tsx b/src/DialogWrap.tsx index 0f89ba6c..97e8c4bc 100644 --- a/src/DialogWrap.tsx +++ b/src/DialogWrap.tsx @@ -1,17 +1,16 @@ import * as React from 'react'; -import Dialog from './Dialog'; import Portal from 'rc-util/lib/PortalWrapper'; -import IDialogPropTypes from './IDialogPropTypes'; -import { IDialogChildProps } from './Dialog'; +import Dialog, { IDialogChildProps } from './Dialog'; +import { IDialogPropTypes } from './IDialogPropTypes'; // fix issue #10656 /* -* getContainer remarks -* Custom container should not be return, because in the Portal component, it will remove the -* return container element here, if the custom container is the only child of it's component, -* like issue #10656, It will has a conflict with removeChild method in react-dom. -* So here should add a child (div element) to custom container. -* */ + * getContainer remarks + * Custom container should not be return, because in the Portal component, it will remove the + * return container element here, if the custom container is the only child of it's component, + * like issue #10656, It will has a conflict with removeChild method in react-dom. + * So here should add a child (div element) to custom container. + * */ export default (props: IDialogPropTypes) => { const { visible, getContainer, forceRender } = props; @@ -26,17 +25,8 @@ export default (props: IDialogPropTypes) => { } return ( - - {(childProps: IDialogChildProps) => ( - - )} + + {(childProps: IDialogChildProps) => } ); }; diff --git a/src/IDialogPropTypes.tsx b/src/IDialogPropTypes.tsx index 984cceab..ed6bac2d 100644 --- a/src/IDialogPropTypes.tsx +++ b/src/IDialogPropTypes.tsx @@ -2,7 +2,7 @@ import { ReactNode, CSSProperties, SyntheticEvent } from 'react'; type IStringOrHtmlElement = string | HTMLElement; -interface IDialogPropTypes { +export interface IDialogPropTypes { className?: string; keyboard?: boolean; style?: CSSProperties; @@ -42,5 +42,3 @@ interface IDialogPropTypes { // https://github.com/react-component/dialog/issues/95 focusTriggerAfterClose?: boolean; } - -export default IDialogPropTypes; diff --git a/src/LazyRenderBox.tsx b/src/LazyRenderBox.tsx index b2204313..ca08f7d3 100644 --- a/src/LazyRenderBox.tsx +++ b/src/LazyRenderBox.tsx @@ -17,6 +17,7 @@ export default class LazyRenderBox extends React.Component { - const title = '第一个title'; - let dialog; - - const container = document.createElement('div'); - container.id = 't1'; - document.body.appendChild(container); - - let callback1; - - class DialogWrap extends React.Component { - state = { - visible: false, - maskClosable: true, - }; - render() { - return ( - - ); - } - } - - beforeEach(() => { - function onClose() { - callback1 = 1; - dialog.setState({ - visible: false, - }); - } - - callback1 = 0; - dialog = ReactDOM.render(( - -

第一个dialog

-
), container); - }); - - afterEach(() => { - ReactDOM.unmountComponentAtNode(container); - }); - - it('show', (done) => { - dialog.setState({ - visible: true, - }); - setTimeout(() => { - expect($('.rc-dialog-wrap').css('display')) - .to.be('block'); - done(); - }, 10); - }); - - it('close', (done) => { - dialog.setState({ - visible: true, - }); - dialog.setState({ - visible: false, - }); - setTimeout(() => { - expect($('.rc-dialog-wrap').css('display')) - .to.be('none'); - done(); - }, 10); - }); - - it('create', () => { - expect($('.rc-dialog').length).to.be(0); - }); - - it('mask', () => { - dialog.setState({ - visible: true, - }); - expect($('.rc-dialog-mask').length).to.be(1); - }); - - it('root', () => { - dialog.setState({ - visible: true, - }); - expect($('.rc-dialog-root').length).to.be(1); - }); - - it('click close', (finish) => { - async.series([(done) => { - dialog.setState({ - visible: true, - }); - setTimeout(done, 10); - }, (done) => { - const btn = $('.rc-dialog-close')[0]; - expect(btn.innerText).to.be('test-text'); - Simulate.click(btn); - setTimeout(done, 10); - }, (done) => { - expect(callback1).to.be(1); - expect($('.rc-dialog-wrap').css('display')) - .to.be('none'); - done(); - }], finish); - }); - - it("destroy on hide should unmount child components on close", () => { - const wrapper = ReactDOM.render( - - , container); - wrapper.setState({ - visible: true, - }); - $(".inputElem").val("test"); - expect($(".inputElem").val()).to.be("test") - wrapper.setState({ - visible: false, - }); - wrapper.setState({ - visible: true, - }); - expect($(".inputElem").val()).to.be("") - }) - - it('esc to close', (finish) => { - async.series([(done) => { - dialog.setState({ - visible: true, - }); - setTimeout(done, 10); - }, (done) => { - Simulate.keyDown($('.rc-dialog')[0], { - keyCode: KeyCode.ESC, - }); - setTimeout(done, 10); - }, (done) => { - expect(callback1).to.be(1); - expect($('.rc-dialog-wrap').css('display')) - .to.be('none'); - done(); - }], finish); - }); - - it('mask to close', (finish) => { - async.series([(done) => { - dialog.setState({ - visible: true, - }); - setTimeout(done, 500); - }, (done) => { - const mask = $('.rc-dialog-wrap')[0]; - Simulate.click(mask); - setTimeout(done, 10); - }, (done) => { - // dialog should closed after mask click - expect(callback1).to.be(1); - expect($('.rc-dialog-wrap').css('display')) - .to.be('none'); - done(); - }, (done) => { - dialog.setState({ - visible: true, - maskClosable: false, - }); - - setTimeout(done, 10); - }, (done) => { - // dialog should stay on visible after mask click if set maskClosable to false - // expect(callback1).to.be(0); - expect($('.rc-dialog-wrap').css('display')) - .to.be('block'); - done(); - }], finish); - }); - - it('renderToBody', () => { - const d = ReactDOM.render( -

1

-
, container); - expect($('.renderToBody').length).to.be(0); - expect($('.rc-dialog-wrap').length).to.be(0); - d.setState({ - visible: true, - }); - expect($('.rc-dialog-wrap').length).to.be(1); - expect($('.renderToBody').length).to.be(1); - expect($('.rc-dialog-wrap')[0].parentNode.parentNode).not.to.be(container); - ReactDOM.unmountComponentAtNode(container); - expect($('.renderToBody').length).to.be(0); - expect($('.rc-dialog-wrap').length).to.be(0); - }); - - it('getContainer', () => { - const returnedContainer = document.createElement('div'); - document.body.appendChild(returnedContainer); - const d = ReactDOM.render( - returnedContainer}> -

Hello world!

-
, - container - ); - d.setState({ - visible: true, - }); - // fix issue #10656, must change this test - // expect($('.rc-dialog-wrap')[0].parentNode.parentNode).to.be(returnedContainer); - expect($('.rc-dialog-wrap')[0].parentNode.parentNode.parentNode).to.be(returnedContainer); - }); - - it('render footer padding correctly', () => { - async.series([() => { - ReactDOM.render(, container) - }, () => { - expect($('.rc-dialog-footer').css('padding')).to.be('10px 20px'); - }]); - }); - - it('support input autoFocus', () => { - const d = ReactDOM.render( - , - container - ); - d.setState({ - visible: true - }); - expect(document.activeElement).to.be(document.querySelector('input')); - }); - - it('trap focus after shift-tabbing', () => { - dialog.setState({ - visible: true - }); - const dialogEl = $('.rc-dialog-wrap')[0]; - const shiftTabbingDescriptor = { - key: 'TAB', - keyCode: 9, - which: 9, - shiftKey: true - } - Simulate.keyDown(dialogEl, shiftTabbingDescriptor); - const sentinelEnd = $('.rc-dialog-content + div')[0]; - expect(document.activeElement).to.be(sentinelEnd); - }); - - it('sets transform-origin when property mousePosition is set', () => { - const d = ReactDOM.render(( - -

the dialog

-
), container); - expect($('.rc-dialog').css('transform-origin')).to.not.be.empty(); - }); - - it('can get dom element before dialog first show when forceRender is set true ',()=>{ - const d = ReactDOM.render(( - -
forceRender element
-
- ),container); - expect($('.rc-dialog-body > div').text()).to.be('forceRender element'); - }); - - it('should not close if mouse down in dialog', () => { - dialog.setState({ - visible: true, - }); - const dialogBody = $('.rc-dialog-body')[0]; - Simulate.mouseDown(dialogBody); - const wrapper = $('.rc-dialog-wrap')[0]; - Simulate.mouseUp(wrapper); - expect(dialog.state.visible).to.be(true); - }); - it('getContainer is false', () => { - ReactDOM.render(( - -
forceRender element
-
- ),container); - expect($('.rc-dialog-body > div').text()).to.be('forceRender element'); - expect($('.rc-dialog-wrap')[0].style.display).to.be('none'); - }); - it('getContainer is false and visible is true', () => { - ReactDOM.render(( - -
forceRender element
-
- ),container); - expect($('.rc-dialog-body > div').text()).to.be('forceRender element'); - expect($('.rc-dialog-wrap')[0].style.display).to.be(''); - }) - it('Single Dialog body overflow set correctly', () => { - document.body.style.overflow = "scroll" - - dialog.setState({ - visible: true - }); - expect(document.body.style.overflow).to.be('hidden'); - - dialog.setState({ - visible: false - }); - expect(document.body.style.overflow).to.be('scroll'); - }) - - it('Multiple Dialog body overflow set correctly', () => { - document.body.style.overflow = "scroll" - - class MultipleDialogWrap extends React.Component { - state = { - visible: false, - visible2: false, - }; - render() { - return ( -
- - -
- ); - } - } - - const d = ReactDOM.render(( - -
forceRender element
-
- ),container); - - expect($('.rc-dialog').length).to.be(0); - - d.setState({ - visible: true, - }) - expect($('.rc-dialog').length).to.be(1); - expect(document.body.style.overflow).to.be('hidden'); - - d.setState({ - visible2: true, - }) - expect($('.rc-dialog').length).to.be(2); - expect(document.body.style.overflow).to.be('hidden'); - - d.setState({ - visible: false, - visible2: false, - }) - expect(document.body.style.overflow).to.be('scroll'); - - d.setState({ - visible: true, - }) - expect(document.body.style.overflow).to.be('hidden'); - - d.setState({ - visible: false, - visible2: true, - }) - expect(document.body.style.overflow).to.be('hidden'); - - d.setState({ - visible: false, - visible2: false, - }) - expect(document.body.style.overflow).to.be('scroll'); - }) - - it('afterClose', (done) => { - const dialog = ReactDOM.render(( - -
afterClose
-
- ),container); - dialog.setState({ - visible: true, - }); - dialog.setState({ - visible: false, - }); - }); - - it('zIndex', () => { - const dialog = ReactDOM.render(( - -
afterClose
-
- ),container); - dialog.setState({ - visible: true, - }); - - expect($('.rc-dialog-wrap').css("zIndex")).to.be('1000'); - - }); - - it('should show dialog when initialize dialog, given forceRender and visible is true', () => { - class DialogWrap extends React.Component { - state = { - visible: true, - forceRender: true, - }; - render() { - return ( - - ); - } - } - ReactDOM.render(( - -
Show dialog with forceRender and visible is true
-
- ),container); - setTimeout(() => { - expect($('.rc-dialog-wrap').css('display')) - .to.be('block'); - done(); - }, 10); - }); -}); diff --git a/tests/index.spec.js b/tests/index.spec.js new file mode 100644 index 00000000..7374756b --- /dev/null +++ b/tests/index.spec.js @@ -0,0 +1,428 @@ +/* eslint-disable react/no-render-return-value */ +/* eslint-disable func-names */ +import React from 'react'; +import { mount } from 'enzyme'; + +import KeyCode from 'rc-util/lib/KeyCode'; + +import Dialog from '../src'; +import '../assets/bootstrap.less'; + +describe('dialog', () => { + let dialog; + let callback; + class DialogWrap extends React.Component { + state = { + visible: false, + maskClosable: true, + }; + + render() { + return ( + + ); + } + } + + beforeEach(() => { + function onClose() { + callback = 1; + dialog.setState({ + visible: false, + }); + } + + callback = 0; + dialog = mount( + +

第一个dialog

+
, + ); + + jest.useFakeTimers(); + }); + + afterEach(() => { + dialog.unmount(); + jest.useRealTimers(); + }); + + it('show', () => { + dialog.setState({ visible: true }); + jest.runAllTimers(); + dialog.update(); + expect(dialog.find('.rc-dialog-wrap').props().style.display).toEqual(null); + }); + + it('close', () => { + dialog.setState({ visible: true }); + dialog.setState({ visible: false }); + jest.runAllTimers(); + dialog.update(); + expect(dialog.find('.rc-dialog-wrap').props().style).toEqual({}); + }); + + it('create & root & mask', () => { + expect(dialog.find('.rc-dialog').length).toBe(0); + dialog.setState({ visible: true }); + jest.runAllTimers(); + dialog.update(); + expect(dialog.find('.rc-dialog-root').length).toBeTruthy(); + expect(dialog.find('.rc-dialog-mask').length).toBeTruthy(); + }); + + it('click close', () => { + dialog.setState({ visible: true }); + jest.runAllTimers(); + dialog.update(); + const btn = dialog.find('.rc-dialog-close'); + expect(btn.props().children).toBe('test'); + btn.simulate('click'); + jest.runAllTimers(); + dialog.update(); + expect(callback).toBe(1); + }); + + it("destroy on hide should unmount child components on close", () => { + const wrapper = mount( + + + + ); + wrapper.setState({ visible: true }); + jest.runAllTimers(); + wrapper.update(); + document.getElementsByClassName('.test-input').value = 'test'; + expect(document.getElementsByClassName('.test-input').value).toBe('test'); + wrapper.setState({ visible: false }); + jest.runAllTimers(); + wrapper.update(); + wrapper.setState({ visible: true }); + jest.runAllTimers(); + wrapper.update(); + expect(document.getElementsByClassName('.test-input').value).toBeUndefined(); + wrapper.unmount(); + }) + + it('esc to close', () => { + dialog.setState({ visible: true }); + jest.runAllTimers(); + dialog.update(); + dialog + .find('.rc-dialog') + .at(0) + .simulate('keyDown', { keyCode: KeyCode.ESC }); + jest.runAllTimers(); + dialog.update(); + expect(dialog.find('.rc-dialog-wrap').props().style).toEqual({}); + }); + + it('mask to close', () => { + let now = 0; + const originDateNow = Date.now; + + // disable https://github.com/react-component/dialog/blob/d9604fa6ad40e949999456d8c020e47593e48f0d/src/Dialog.tsx#L188 + Date.now = () => { + now += 500 + return now + }; + + dialog.setState({ visible: true }); + jest.runAllTimers(); + dialog.update(); + const mask = dialog.find('.rc-dialog-wrap').first(); + mask.simulate('click'); + jest.runAllTimers(); + dialog.update(); + expect(callback).toBe(1); + expect(dialog.find('.rc-dialog-wrap').props().style).toEqual({}); + dialog.setState({ visible: true, maskClosable: false }); + jest.runAllTimers(); + dialog.update(); + expect(dialog.find('.rc-dialog-wrap').props().style.display).toEqual(null); + + Date.now = originDateNow; + }); + + it('renderToBody', () => { + const container = document.createElement('div'); + document.body.appendChild(container); + const d = mount( + +

1

+
, { attachTo: container } + ); + expect(d.find('.renderToBody').length).toBe(0); + expect(d.find('.rc-dialog-wrap').length).toBe(0); + d.setState({ visible: true }); + jest.runAllTimers(); + d.update(); + expect(d.find('.rc-dialog-wrap').length).toBeTruthy(); + expect(d.find('.renderToBody').length).toBeTruthy(); + expect(d.find('.rc-dialog-wrap').getDOMNode().parentNode.parentNode).not.toBe(container); + d.unmount(); + expect(d.find('.renderToBody').length).toBe(0); + expect(d.find('.rc-dialog-wrap').length).toBe(0); + }); + + it('getContainer', () => { + const returnedContainer = document.createElement('div'); + const d = mount( + returnedContainer}> +

Hello world!

+
+ ); + d.setState({ visible: true }); + jest.runAllTimers(); + d.update(); + // fix issue #10656, must change this test + expect(d.find('.rc-dialog-wrap').getDOMNode().parentNode.parentNode.parentNode).toBe(returnedContainer); + d.unmount(); + }); + + it('render footer correctly', () => { + const d = mount(); + d.setState({ visible: true }); + jest.runAllTimers(); + d.update(); + expect(d.find('.rc-dialog-footer').length).toBeTruthy(); + expect(d.find('.rc-dialog-footer').props().children).toBe('test'); + d.unmount(); + }); + + it('support input autoFocus', () => { + const d = mount( + + + , + ); + d.setState({ visible: true }); + jest.runAllTimers(); + d.update(); + expect(document.activeElement).toBe(document.querySelector('input')); + d.unmount(); + }); + + it('trap focus after shift-tabbing', () => { + dialog.setState({ visible: true }); + jest.runAllTimers(); + dialog.update(); + const shiftTabbingDescriptor = { + key: 'TAB', + keyCode: 9, + which: 9, + shiftKey: true + } + dialog.find('.rc-dialog-wrap').at(0).simulate('keyDown', shiftTabbingDescriptor); + const sentinelEnd = document.querySelectorAll('.rc-dialog-content + div')[0]; + expect(document.activeElement).toBe(sentinelEnd); + }); + + it('sets transform-origin when property mousePosition is set', () => { + const d = mount( + +

the dialog

+
, + ); + jest.runAllTimers(); + d.update(); + expect(d.find('.rc-dialog').at(0).getDOMNode().style['transform-origin']).toBeTruthy(); + d.unmount(); + }); + + it('can get dom element before dialog first show when forceRender is set true ', () => { + const d = mount( + +
forceRender element
+
, + ); + expect(d.find('.rc-dialog-body > div').props().children).toEqual('forceRender element'); + d.unmount(); + }); + + it('getContainer is false', () => { + const d = mount( + +
forceRender element
+
, + ); + expect(d.find('.rc-dialog-body > div').props().children).toEqual('forceRender element'); + expect( + d + .find('.rc-dialog-wrap') + .at(0) + .props().style, + ).toEqual({}); + d.unmount(); + }); + + it('getContainer is false and visible is true', () => { + const d = mount( + +
forceRender element
+
, + ); + expect(d.find('.rc-dialog-body > div').props().children).toEqual('forceRender element'); + expect(d.find('.rc-dialog-wrap').props().style.display).toEqual(null); + d.unmount(); + }); + + it('should not close if mouse down in dialog', () => { + dialog.setState({ visible: true }); + jest.runAllTimers(); + dialog.update(); + const dialogBody = dialog.find('.rc-dialog-body').at(0); + dialogBody.simulate('mousedown'); + const wrapper = dialog.find('.rc-dialog-wrap').at(0); + wrapper.simulate('mouseup'); + expect(dialog.state().visible).toBe(true); + }); + + it('Single Dialog body overflow set correctly', () => { + const container = document.createElement('div'); + document.body.appendChild(container); + const d = mount(, { attachTo: container }); + document.body.style.overflow = 'scroll'; + d.setState({ visible: true }); + jest.runAllTimers(); + d.update(); + expect(document.body.style.overflow).toBe('hidden'); + d.setState({ visible: false }); + jest.runAllTimers(); + d.update(); + expect(document.body.style.overflow).toBe('scroll'); + d.unmount(); + }); + + it('Multiple Dialog body overflow set correctly', () => { + const container = document.createElement('div'); + document.body.style.overflow = "scroll" + + class MultipleDialogWrap extends React.Component { + state = { + visible: false, + visible2: false, + }; + + render() { + return ( +
+ + +
+ ); + } + } + + const d = mount(( + +
forceRender element
+
+ ), { attachTo: container }); + + expect(d.find('.rc-dialog').length).toBe(0); + + d.setState({ visible: true }); + jest.runAllTimers(); + d.update(); + + expect(d.find('div.rc-dialog').length).toBe(1); + expect(document.body.style.overflow).toBe('hidden'); + + d.setState({ visible2: true }); + jest.runAllTimers(); + d.update(); + + expect(d.find('div.rc-dialog').length).toBe(2); + expect(document.body.style.overflow).toBe('hidden'); + + d.setState({ + visible: false, + visible2: false, + }) + jest.runAllTimers(); + d.update(); + + expect(document.body.style.overflow).toBe('scroll'); + + d.setState({ + visible: true, + }) + jest.runAllTimers(); + d.update(); + expect(document.body.style.overflow).toBe('hidden'); + + d.setState({ + visible: false, + visible2: true, + }) + jest.runAllTimers(); + d.update(); + expect(document.body.style.overflow).toBe('hidden'); + + d.setState({ + visible: false, + visible2: false, + }) + jest.runAllTimers(); + d.update(); + expect(document.body.style.overflow).toBe('scroll'); + d.unmount(); + }); + + it('afterClose', () => { + const afterCloseMock = jest.fn(); + const d = mount( + +
afterClose
+
, + ); + d.setState({ visible: true }); + jest.runAllTimers(); + d.update(); + d.setState({ visible: false }); + jest.runAllTimers(); + d.update(); + expect(afterCloseMock).toHaveBeenCalledTimes(1); + }); + + it('zIndex', () => { + const d = mount(); + d.setState({ visible: true }); + jest.runAllTimers(); + d.update(); + expect(d.find('.rc-dialog-wrap').props().style.zIndex).toBe(1000); + }); + + it('should show dialog when initialize dialog, given forceRender and visible is true', () => { + class DialogWrapTest extends React.Component { + state = { + visible: true, + forceRender: true, + }; + + render() { + return ; + } + } + + const d = mount( + +
Show dialog with forceRender and visible is true
+
, + ); + jest.runAllTimers(); + d.update(); + expect(d.find('.rc-dialog-wrap').props().style.display).toEqual(null); + }); +}); diff --git a/tests/setup.js b/tests/setup.js new file mode 100644 index 00000000..4c18e28f --- /dev/null +++ b/tests/setup.js @@ -0,0 +1,6 @@ +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/tsconfig.json b/tsconfig.json deleted file mode 100644 index 9727789e..00000000 --- a/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "compilerOptions": { - "strictNullChecks": true, - "moduleResolution": "node", - "jsx": "react", - "target": "es6", - "noImplicitAny": true - } -} diff --git a/typings/custom.d.ts b/typings/custom.d.ts index 455b131f..55d05e1a 100644 --- a/typings/custom.d.ts +++ b/typings/custom.d.ts @@ -1,14 +1,9 @@ declare module "rc-util/lib/KeyCode" { - var Ret: {ESC:any;TAB:any;}; - export default Ret; -} - -declare module "rc-util/lib/*" { - var Ret: any; + const Ret: {ESC:any;TAB:any;}; export default Ret; } declare module "rc-animate" { - var Ret: any; + const Ret: any; export default Ret; -} \ No newline at end of file +} diff --git a/typings/index.d.ts b/typings/index.d.ts deleted file mode 100644 index 09e70c53..00000000 --- a/typings/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -///