From 56779804c13811bd7f8b62cf28e02a7b5af2274c Mon Sep 17 00:00:00 2001 From: zombiej Date: Tue, 8 Oct 2019 16:17:08 +0800 Subject: [PATCH 01/12] feat: Use react 16 --- .eslintrc.js | 8 ++++++++ .fatherrc.js | 8 ++++++++ jest.config.js | 3 +++ now.json | 11 +++++++++++ package.json | 53 +++++++++++++++++++++++--------------------------- 5 files changed, 54 insertions(+), 29 deletions(-) create mode 100644 .eslintrc.js create mode 100644 .fatherrc.js create mode 100644 jest.config.js create mode 100644 now.json diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..1fe6f50 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,8 @@ +const base = require('@umijs/fabric/dist/eslint'); + +module.exports = { + ...base, + rules: { + ...base.rules, + }, +}; diff --git a/.fatherrc.js b/.fatherrc.js new file mode 100644 index 0000000..c221753 --- /dev/null +++ b/.fatherrc.js @@ -0,0 +1,8 @@ +export default { + cjs: 'babel', + esm: { type: 'babel', importLibToEs: true }, + preCommit: { + eslint: true, + prettier: true, + }, +}; \ No newline at end of file diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..61d0430 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,3 @@ +module.exports = { + snapshotSerializers: [require.resolve('enzyme-to-json/serializer')], +}; \ No newline at end of file diff --git a/now.json b/now.json new file mode 100644 index 0000000..15f6864 --- /dev/null +++ b/now.json @@ -0,0 +1,11 @@ +{ + "version": 2, + "name": "rc-align", + "builds": [ + { + "src": "package.json", + "use": "@now/static-build", + "config": { "distDir": ".doc" } + } + ] +} diff --git a/package.json b/package.json index 45da6b8..1c11bcc 100644 --- a/package.json +++ b/package.json @@ -24,39 +24,34 @@ "license": "MIT", "main": "./lib/index", "module": "./es/index", - "config": { - "port": 8100 - }, "scripts": { - "build": "rc-tools run build", - "compile": "rc-tools run compile --babel-runtime", - "gh-pages": "rc-tools run gh-pages", - "start": "rc-tools run server", - "pub": "rc-tools run pub --babel-runtime", - "lint": "rc-tools run lint", - "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" + "start": "cross-env NODE_ENV=development father doc dev --storybook", + "build": "father doc build --storybook", + "compile": "father build", + "prepublishOnly": "npm run compile && np --no-cleanup --yolo --no-publish", + "lint": "eslint src/ examples/ --ext .tsx,.ts,.jsx,.js", + "test": "father test", + "now-build": "npm run build" }, - "devDependencies": { - "core-js": "^2.5.1", - "expect.js": "0.3.x", - "jquery": "^3.3.1", - "pre-commit": "1.x", - "rc-test": "6.x", - "rc-tools": "8.x", - "react": "^16.3.0", - "react-dom": "^16.3.0" + "peerDependencies": { + "react": "*", + "react-dom": "*" }, - "pre-commit": [ - "lint" - ], "dependencies": { - "babel-runtime": "^6.26.0", + "classnames": "2.x", "dom-align": "^1.7.0", - "prop-types": "^15.5.8", - "rc-util": "^4.0.4" + "rc-util": "^4.11.0" + }, + "devDependencies": { + "@types/jest": "^24.0.18", + "@types/react": "^16.8.19", + "@types/react-dom": "^16.8.4", + "@types/warning": "^3.0.0", + "cross-env": "^6.0.0", + "enzyme": "^3.3.0", + "enzyme-to-json": "^3.4.0", + "father": "^2.13.2", + "np": "^5.0.3", + "typescript": "^3.5.2" } } From f5e7384af19ca26aacf542a8d187d331b14a8a97 Mon Sep 17 00:00:00 2001 From: zombiej Date: Tue, 8 Oct 2019 16:22:14 +0800 Subject: [PATCH 02/12] rename as ts --- .gitignore | 1 + examples/point.html | 1 - examples/point.js | 28 ++++++++++--------- examples/simple.html | 1 - examples/simple.js | 53 ++++++++++++++++++------------------ src/{Align.jsx => Align.tsx} | 0 src/{index.js => index.ts} | 0 src/{util.js => util.ts} | 0 8 files changed, 42 insertions(+), 42 deletions(-) delete mode 100644 examples/point.html delete mode 100644 examples/simple.html rename src/{Align.jsx => Align.tsx} (100%) rename src/{index.js => index.ts} (100%) rename src/{util.js => util.ts} (100%) diff --git a/.gitignore b/.gitignore index ae7ed18..f28aa39 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.storybook *.iml *.log .idea/ diff --git a/examples/point.html b/examples/point.html deleted file mode 100644 index b3a4252..0000000 --- a/examples/point.html +++ /dev/null @@ -1 +0,0 @@ -placeholder \ No newline at end of file diff --git a/examples/point.js b/examples/point.js index 6988766..ed5b1da 100644 --- a/examples/point.js +++ b/examples/point.js @@ -1,6 +1,5 @@ -import Align from 'rc-align'; import React, { Component } from 'react'; -import ReactDOM from 'react-dom'; +import Align from '../src'; const align = { points: ['cc', 'cc'], @@ -12,8 +11,8 @@ class Demo extends Component { }; onClick = ({ pageX, pageY }) => { - this.setState({ point: { pageX, pageY }}); - } + this.setState({ point: { pageX, pageY } }); + }; render() { return ( @@ -25,19 +24,22 @@ class Demo extends Component { Click this region please : ) - +
Align
+ style={{ + position: 'absolute', + width: 100, + height: 100, + background: 'rgba(0, 255, 0, 0.5)', + pointerEvents: 'none', + }} + > + Align +
); } } -ReactDOM.render(, document.getElementById('__react-content')); - +export default Demo; diff --git a/examples/simple.html b/examples/simple.html deleted file mode 100644 index b3a4252..0000000 --- a/examples/simple.html +++ /dev/null @@ -1 +0,0 @@ -placeholder \ No newline at end of file diff --git a/examples/simple.js b/examples/simple.js index 651b9bc..3e47685 100644 --- a/examples/simple.js +++ b/examples/simple.js @@ -1,6 +1,5 @@ -import Align from 'rc-align'; import React, { Component } from 'react'; -import ReactDOM from 'react-dom'; +import Align from '../src'; class Test extends Component { state = { @@ -16,11 +15,14 @@ class Test extends Component { this.id = setInterval(() => { const { random } = this.state; if (random) { - this.setState({ - randomWidth: 60 + 40 * Math.random(), - }, () => { - this.forceAlign(); - }); + this.setState( + { + randomWidth: 60 + 40 * Math.random(), + }, + () => { + this.forceAlign(); + }, + ); } }, 1000); } @@ -35,31 +37,31 @@ class Test extends Component { this.$container = document.getElementById('container'); } return this.$container; - } + }; - containerRef = (ele) => { + containerRef = ele => { this.$container = ele; - } + }; - alignRef = (node) => { + alignRef = node => { this.$align = node; - } + }; toggleMonitor = () => { this.setState({ monitor: !this.state.monitor, }); - } + }; toggleRandom = () => { this.setState({ random: !this.state.random, }); - } + }; forceAlign = () => { this.$align.forceAlign(); - } + }; render() { const { random, randomWidth } = this.state; @@ -75,13 +77,11 @@ class Test extends Component {    

- +
@@ -122,4 +121,4 @@ class Test extends Component { } } -ReactDOM.render(, document.getElementById('__react-content')); +export default Test; diff --git a/src/Align.jsx b/src/Align.tsx similarity index 100% rename from src/Align.jsx rename to src/Align.tsx diff --git a/src/index.js b/src/index.ts similarity index 100% rename from src/index.js rename to src/index.ts diff --git a/src/util.js b/src/util.ts similarity index 100% rename from src/util.js rename to src/util.ts From 5893007ea08ce7fb88c3332e33294ef04cf95eeb Mon Sep 17 00:00:00 2001 From: zombiej Date: Tue, 8 Oct 2019 18:02:57 +0800 Subject: [PATCH 03/12] add resize-observer-polyfill --- .eslintrc.js | 1 + package.json | 4 +- src/Align.tsx | 217 +++++++++++++++++++---------------------------- src/interface.ts | 84 ++++++++++++++++++ src/util.ts | 10 +-- 5 files changed, 177 insertions(+), 139 deletions(-) create mode 100644 src/interface.ts diff --git a/.eslintrc.js b/.eslintrc.js index 1fe6f50..f21cd5a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -4,5 +4,6 @@ module.exports = { ...base, rules: { ...base.rules, + 'react/no-find-dom-node': 0, }, }; diff --git a/package.json b/package.json index 1c11bcc..d5c0301 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,9 @@ "dependencies": { "classnames": "2.x", "dom-align": "^1.7.0", - "rc-util": "^4.11.0" + "rc-resize-observer": "^0.1.0", + "rc-util": "^4.12.0", + "resize-observer-polyfill": "^1.5.1" }, "devDependencies": { "@types/jest": "^24.0.18", diff --git a/src/Align.tsx b/src/Align.tsx index 2305652..9795c9a 100644 --- a/src/Align.tsx +++ b/src/Align.tsx @@ -1,141 +1,65 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import ReactDOM from 'react-dom'; +/** + * Removed props: + * - childrenProps + */ + +import React from 'react'; +import { composeRef } from 'rc-util/lib/ref'; +import findDOMNode from 'rc-util/lib/Dom/findDOMNode'; +import ResizeObserver from 'rc-resize-observer'; import { alignElement, alignPoint } from 'dom-align'; import addEventListener from 'rc-util/lib/Dom/addEventListener'; import { isWindow, buffer, isSamePoint, isSimilarValue, restoreFocus } from './util'; +import { AlignType, AlignResult, TargetType, TargetPoint } from './interface'; + +export interface AlignProps { + align: AlignType; + target: TargetType; + onAlign: (source: HTMLElement, result: AlignResult) => void; + monitorBufferTime: number; + monitorWindowResize: boolean; + disabled: boolean; + children: React.ReactElement; +} + +export interface RefAlign { + forceAlign: () => void; +} -function getElement(func) { +function getElement(func: TargetType) { if (typeof func !== 'function' || !func) return null; return func(); } -function getPoint(point) { +function getPoint(point: TargetType) { if (typeof point !== 'object' || !point) return null; return point; } -class Align extends Component { - static propTypes = { - childrenProps: PropTypes.object, - align: PropTypes.object.isRequired, - target: PropTypes.oneOfType([ - PropTypes.func, - PropTypes.shape({ - clientX: PropTypes.number, - clientY: PropTypes.number, - pageX: PropTypes.number, - pageY: PropTypes.number, - }), - ]), - onAlign: PropTypes.func, - monitorBufferTime: PropTypes.number, - monitorWindowResize: PropTypes.bool, - disabled: PropTypes.bool, - children: PropTypes.any, - }; - - static defaultProps = { - target: () => window, - monitorBufferTime: 50, - monitorWindowResize: false, - disabled: false, - }; - - componentDidMount() { - const props = this.props; - // if parent ref not attached .... use document.getElementById - this.forceAlign(); - if (!props.disabled && props.monitorWindowResize) { - this.startMonitorWindowResize(); - } - } - - componentDidUpdate(prevProps) { - let reAlign = false; - const props = this.props; - - if (!props.disabled) { - const source = ReactDOM.findDOMNode(this); - const sourceRect = source ? source.getBoundingClientRect() : null; - - if (prevProps.disabled) { - reAlign = true; - } else { - const lastElement = getElement(prevProps.target); - const currentElement = getElement(props.target); - const lastPoint = getPoint(prevProps.target); - const currentPoint = getPoint(props.target); - - if (isWindow(lastElement) && isWindow(currentElement)) { - // Skip if is window - reAlign = false; - } else if ( - lastElement !== currentElement || // Element change - (lastElement && !currentElement && currentPoint) || // Change from element to point - (lastPoint && currentPoint && currentElement) || // Change from point to element - (currentPoint && !isSamePoint(lastPoint, currentPoint)) - ) { - reAlign = true; - } - - // If source element size changed - const preRect = this.sourceRect || {}; - if ( - !reAlign && - source && - (!isSimilarValue(preRect.width, sourceRect.width) || !isSimilarValue(preRect.height, sourceRect.height)) - ) { - reAlign = true; - } - } - - this.sourceRect = sourceRect; - } - - if (reAlign) { - this.forceAlign(); - } - - if (props.monitorWindowResize && !props.disabled) { - this.startMonitorWindowResize(); - } else { - this.stopMonitorWindowResize(); - } - } +const Align: React.RefForwardingComponent = ( + { children, disabled, target, align, onAlign, monitorWindowResize, monitorBufferTime }, + ref, +) => { + const cacheRef = React.useRef<{ element?: HTMLElement; point?: TargetPoint }>({}); + const nodeRef = React.useRef(); + let childNode = React.Children.only(children); - componentWillUnmount() { - this.stopMonitorWindowResize(); - } - - startMonitorWindowResize() { - if (!this.resizeHandler) { - this.bufferMonitor = buffer(this.forceAlign, this.props.monitorBufferTime); - this.resizeHandler = addEventListener(window, 'resize', this.bufferMonitor); - } - } - - stopMonitorWindowResize() { - if (this.resizeHandler) { - this.bufferMonitor.clear(); - this.resizeHandler.remove(); - this.resizeHandler = null; - } - } - - forceAlign = () => { - const { disabled, target, align, onAlign } = this.props; + // ===================== Align ====================== + const forceAlign = () => { if (!disabled && target) { - const source = ReactDOM.findDOMNode(this); + const source = findDOMNode(nodeRef.current); - let result; + let result: AlignResult; const element = getElement(target); const point = getPoint(target); + cacheRef.current.element = element; + cacheRef.current.point = point; + // IE lose focus after element realign // We should record activeElement and restore later - const activeElement = document.activeElement; + const { activeElement } = document; if (element) { result = alignElement(source, element, align); @@ -149,22 +73,51 @@ class Align extends Component { onAlign(source, result); } } - } + }; - render() { - const { childrenProps, children } = this.props; - const child = React.Children.only(children); - if (childrenProps) { - const newProps = {}; - const propList = Object.keys(childrenProps); - propList.forEach((prop) => { - newProps[prop] = this.props[childrenProps[prop]]; - }); - - return React.cloneElement(child, newProps); + // ===================== Effect ===================== + // Listen for target updated + React.useEffect(() => { + const element = getElement(target); + const point = getPoint(target); + + if (cacheRef.current.element !== element || !isSamePoint(cacheRef.current.point, point)) { + forceAlign(); + } + }); + + // Listen for window resize + const bufferRef = React.useRef<{ clear: Function }>(); + const resizeRef = React.useRef<{ remove: Function }>(); + React.useEffect(() => { + if (monitorWindowResize) { + if (!resizeRef.current) { + bufferRef.current = buffer(forceAlign, monitorBufferTime); + resizeRef.current = addEventListener(window, 'resize', bufferRef.current); + } + } else if (resizeRef.current) { + bufferRef.current.clear(); + resizeRef.current.remove(); + resizeRef.current = null; } - return child; + }, [monitorWindowResize]); + + // ====================== Ref ======================= + React.useImperativeHandle(ref, () => ({ + forceAlign, + })); + + // ===================== Render ===================== + if (React.isValidElement(childNode)) { + childNode = React.cloneElement(childNode, { + ref: composeRef((childNode as any).ref, nodeRef), + }); } -} -export default Align; + return {childNode}; +}; + +const RefAlign = React.forwardRef(Align); +RefAlign.displayName = 'Align'; + +export default RefAlign; diff --git a/src/interface.ts b/src/interface.ts new file mode 100644 index 0000000..9e41d10 --- /dev/null +++ b/src/interface.ts @@ -0,0 +1,84 @@ +export type AlignPoint = + | 'tt' + | 'tb' + | 'tc' + | 'tl' + | 'tr' + | 'bt' + | 'bb' + | 'bc' + | 'bl' + | 'br' + | 'ct' + | 'cb' + | 'cc' + | 'cl' + | 'cr' + | 'lt' + | 'lb' + | 'lc' + | 'll' + | 'lr' + | 'rt' + | 'rb' + | 'rc' + | 'rl' + | 'rr'; + +export interface AlignType { + /** + * move point of source node to align with point of target node. + * Such as ['tr','cc'], align top right point of source node with center point of target node. + * Point can be 't'(top), 'b'(bottom), 'c'(center), 'l'(left), 'r'(right) */ + points?: AlignPoint[]; + /** + * offset source node by offset[0] in x and offset[1] in y. + * If offset contains percentage string value, it is relative to sourceNode region. + */ + offset?: number[]; + /** + * offset target node by offset[0] in x and offset[1] in y. + * If targetOffset contains percentage string value, it is relative to targetNode region. + */ + targetOffset?: number[]; + /** + * If adjustX field is true, will adjust source node in x direction if source node is invisible. + * If adjustY field is true, will adjust source node in y direction if source node is invisible. + */ + overflow?: { + adjustX?: boolean | number; + adjustY?: boolean | number; + }; + /** + * Whether use css right instead of left to position + */ + useCssRight?: boolean; + /** + * Whether use css bottom instead of top to position + */ + useCssBottom?: boolean; + /** + * Whether use css transform instead of left/top/right/bottom to position if browser supports. + * Defaults to false. + */ + useCssTransform?: boolean; +} + +export interface AlignResult { + points: AlignPoint[]; + offset: number[]; + targetOffset: number[]; + overflow: { + adjustX: boolean | number; + adjustY: boolean | number; + }; +} + +export interface TargetPoint { + clientX?: number; + clientY?: number; + pageX?: number; + pageY?: number; +} + +export type TargetType = (() => HTMLElement) | TargetPoint; diff --git a/src/util.ts b/src/util.ts index 99f5439..495ee9b 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,6 +1,7 @@ import contains from 'rc-util/lib/Dom/contains'; +import { TargetPoint } from './interface'; -export function buffer(fn, ms) { +export function buffer(fn: Function, ms: number) { let timer; function clear() { @@ -20,7 +21,7 @@ export function buffer(fn, ms) { return bufferFn; } -export function isSamePoint(prev, next) { +export function isSamePoint(prev: TargetPoint, next: TargetPoint) { if (prev === next) return true; if (!prev || !next) return false; @@ -47,10 +48,7 @@ export function isSimilarValue(val1, val2) { export function restoreFocus(activeElement, container) { // Focus back if is in the container - if ( - activeElement !== document.activeElement && - contains(container, activeElement) - ) { + if (activeElement !== document.activeElement && contains(container, activeElement)) { activeElement.focus(); } } From 38e837bceb1674e4c89ac5fa583cba634c7ecc16 Mon Sep 17 00:00:00 2001 From: zombiej Date: Tue, 8 Oct 2019 19:26:01 +0800 Subject: [PATCH 04/12] refactor --- .eslintrc.js | 2 ++ examples/simple.js | 19 ++++++++------ package.json | 1 - src/Align.tsx | 46 +++++++++++++++++++++++++------- src/hooks/useBuffer.tsx | 30 +++++++++++++++++++++ src/util.ts | 58 ++++++++++++++++++++--------------------- 6 files changed, 108 insertions(+), 48 deletions(-) create mode 100644 src/hooks/useBuffer.tsx diff --git a/.eslintrc.js b/.eslintrc.js index f21cd5a..dc20b71 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -5,5 +5,7 @@ module.exports = { rules: { ...base.rules, 'react/no-find-dom-node': 0, + 'jsx-a11y/label-has-associated-control': 0, + 'jsx-a11y/label-has-for': 0, }, }; diff --git a/examples/simple.js b/examples/simple.js index 3e47685..3df36ec 100644 --- a/examples/simple.js +++ b/examples/simple.js @@ -48,15 +48,15 @@ class Test extends Component { }; toggleMonitor = () => { - this.setState({ - monitor: !this.state.monitor, - }); + this.setState(({ monitor }) => ({ + monitor: !monitor, + })); }; toggleRandom = () => { - this.setState({ - random: !this.state.random, - }); + this.setState(({ random }) => ({ + random: !random, + })); }; forceAlign = () => { @@ -73,7 +73,9 @@ class Test extends Component { }} >

- +    

').appendTo(document.body); - }); - - afterEach(() => { - try { - ReactDOM.unmountComponentAtNode(container[0]); - } catch (e) { - // do nothing... - } - if (container) container.remove(); - container = null; - }); - - it('resize', () => { - const align = { - points: ['bc', 'tc'], - }; - - class Test extends React.Component { - state = { - height: 80, - }; - - getTarget = () => this.$target; - - targetRef = (ele) => { - this.$target = ele; - }; - - render() { - const { height } = this.state; - - return ( -
-
- target -
- -
- source -
-
-
- ); - } - } - - const instance = ReactDOM.render(, container[0]); - const $src = $('#ele_src'); - expect($src.offset().top).to.be(20); - - instance.setState({ - height: 60, - }); - expect($src.offset().top).to.be(40); - }); -}); diff --git a/tests/element.test.js b/tests/element.test.js new file mode 100644 index 0000000..813e1e8 --- /dev/null +++ b/tests/element.test.js @@ -0,0 +1,69 @@ +/* eslint-disable class-methods-use-this */ +import React from 'react'; +import { mount } from 'enzyme'; +import Align from '../src'; + +describe('element align', () => { + it('resize', () => { + jest.useFakeTimers(); + + const align = { + points: ['bc', 'tc'], + }; + + const onAlign = jest.fn(); + + class Test extends React.Component { + getTarget = () => this.$target; + + targetRef = ele => { + this.$target = ele; + }; + + render() { + return ( +
+
+ target +
+ +
+ source +
+
+
+ ); + } + } + + const wrapper = mount(); + expect(onAlign).toHaveBeenCalled(); + + // Window resize + onAlign.mockReset(); + window.dispatchEvent(new Event('resize')); + jest.runAllTimers(); + expect(onAlign).toHaveBeenCalled(); + + // Not listen resize + onAlign.mockReset(); + wrapper.setProps({ monitorWindowResize: false }); + window.dispatchEvent(new Event('resize')); + jest.runAllTimers(); + expect(onAlign).not.toHaveBeenCalled(); + + // Remove should not crash + wrapper.setProps({ monitorWindowResize: true }); + wrapper.unmount(); + + jest.useRealTimers(); + }); +}); +/* eslint-enable */ diff --git a/tests/index.js b/tests/index.js deleted file mode 100644 index 09268cf..0000000 --- a/tests/index.js +++ /dev/null @@ -1,17 +0,0 @@ -import 'core-js/es6/map'; -import 'core-js/es6/set'; -import $ from 'jquery'; -import Align from '../src'; - -$('') - .appendTo(document.getElementsByTagName('head')); - -describe('rc-align', () => { - it('exists', () => { - expect(Align).to.be.ok(); - }); -}); - -require('./element.spec'); -require('./point.spec'); -require('./util.spec'); diff --git a/tests/point.spec.js b/tests/point.spec.js deleted file mode 100644 index 54f72cf..0000000 --- a/tests/point.spec.js +++ /dev/null @@ -1,87 +0,0 @@ -/* eslint react/no-render-return-value:0 */ - -import React from 'react'; -import ReactDOM from 'react-dom'; -import $ from 'jquery'; -import expect from 'expect.js'; -import Align from '../src'; - -describe('point align', () => { - let container; - - function createAlign(props, callback) { - class Test extends React.Component { - state = {}; - - render() { - return ( - -
- - ); - } - } - - return ReactDOM.render(, container[0], callback); - } - - beforeEach(() => { - container = $('
').appendTo(document.body); - }); - - afterEach(() => { - try { - ReactDOM.unmountComponentAtNode(container[0]); - } catch (e) { - // do nothing... - } - if (container) container.remove(); - container = null; - }); - - it('not pass point', (done) => { - createAlign( - { - align: { points: ['cc'] }, - target: null, - }, - () => { - const $align = $('#align')[0]; - expect($align).to.be.ok(); - expect($align.style.left).to.not.be.ok(); - expect($align.style.top).to.not.be.ok(); - done(); - }, - ); - }); - - it('pass point', (done) => { - const wrapper = createAlign( - { - align: { points: ['tc'] }, - target: null, - }, - ); - - wrapper.setState({ - target: { pageX: 1128, pageY: 903 }, - }, () => { - const $align = $('#align'); - expect($align[0]).to.be.ok(); - expect($align.offset().left).to.be(1118); - expect($align.offset().top).to.be(903); - - wrapper.setState({ - target: { pageX: 321, pageY: 613 }, - }, () => { - expect($align.offset().left).to.be(311); - expect($align.offset().top).to.be(613); - - done(); - }); - }); - }); -}); diff --git a/tests/point.test.js b/tests/point.test.js new file mode 100644 index 0000000..3bf020a --- /dev/null +++ b/tests/point.test.js @@ -0,0 +1,45 @@ +/* eslint-disable class-methods-use-this */ +import React from 'react'; +import { mount } from 'enzyme'; +import Align from '../src'; + +describe('point align', () => { + function createAlign(props) { + return mount( + +
+ , + ); + } + + it('not pass point', () => { + const onAlign = jest.fn(); + + createAlign({ + align: { points: ['cc'] }, + target: null, + onAlign, + }); + + expect(onAlign).not.toHaveBeenCalled(); + }); + + it('pass point', () => { + jest.useFakeTimers(); + const onAlign = jest.fn(); + const wrapper = createAlign({ + align: { points: ['tc'] }, + target: null, + onAlign, + }); + + expect(onAlign).not.toHaveBeenCalled(); + + wrapper.setProps({ target: { pageX: 1128, pageY: 903 } }); + jest.runAllTimers(); + expect(onAlign).toHaveBeenCalled(); + + jest.useRealTimers(); + }); +}); +/* eslint-enable */ diff --git a/tests/util.spec.js b/tests/util.test.js similarity index 54% rename from tests/util.spec.js rename to tests/util.test.js index 09ab476..7391bca 100644 --- a/tests/util.spec.js +++ b/tests/util.test.js @@ -1,6 +1,3 @@ -/* eslint react/no-render-return-value:0 */ - -import expect from 'expect.js'; import { isSamePoint } from '../src/util'; describe('util', () => { @@ -10,14 +7,14 @@ describe('util', () => { isSamePoint( { pageX: 1, pageY: 2, clientX: 3, clientY: 4 }, { pageX: 1, pageY: 2, clientX: 1, clientY: 5 }, - ) - ).to.be.ok(); + ), + ).toBeTruthy(); expect( isSamePoint( { pageX: 1, pageY: 2, clientX: 3, clientY: 4 }, { pageX: 5, pageY: 6, clientX: 3, clientY: 4 }, - ) - ).not.to.be.ok(); + ), + ).toBeFalsy(); }); it('by client', () => { @@ -25,14 +22,19 @@ describe('util', () => { isSamePoint( { pageX: 0, pageY: 2, clientX: 3, clientY: 4 }, { pageY: 2, clientX: 3, clientY: 4 }, - ) - ).to.be.ok(); + ), + ).toBeTruthy(); expect( - isSamePoint( - { pageX: 0, pageY: 2, clientX: 3, clientY: 4 }, - { clientX: 5, clientY: 4 }, - ) - ).not.to.be.ok(); + isSamePoint({ pageX: 0, pageY: 2, clientX: 3, clientY: 4 }, { clientX: 5, clientY: 4 }), + ).toBeFalsy(); + }); + + it('by change', () => { + expect(isSamePoint({ pageX: 0, pageY: 2, clientX: 3, clientY: 4 }, null)).toBeFalsy(); + expect(isSamePoint(null, { pageX: 0, pageY: 2, clientX: 3, clientY: 4 })).toBeFalsy(); + }); + it('2 empty should be false', () => { + expect(isSamePoint({}, {})).toBeFalsy(); }); }); }); From 92b461ba4030a12640776f0b65060f9e21791827 Mon Sep 17 00:00:00 2001 From: zombiej Date: Tue, 8 Oct 2019 20:42:20 +0800 Subject: [PATCH 06/12] update node version --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ef38dfb..726f656 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ notifications: - yiminghe@gmail.com node_js: -- 6.10.0 +- 10.0.0 before_install: - | From 6d801cba9d50250f666a1cd7f2b260dc1dbafa22 Mon Sep 17 00:00:00 2001 From: zombiej Date: Tue, 8 Oct 2019 20:45:29 +0800 Subject: [PATCH 07/12] update test case name --- tests/util.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/util.test.js b/tests/util.test.js index 7391bca..269a0f9 100644 --- a/tests/util.test.js +++ b/tests/util.test.js @@ -29,7 +29,7 @@ describe('util', () => { ).toBeFalsy(); }); - it('by change', () => { + it('null should be false', () => { expect(isSamePoint({ pageX: 0, pageY: 2, clientX: 3, clientY: 4 }, null)).toBeFalsy(); expect(isSamePoint(null, { pageX: 0, pageY: 2, clientX: 3, clientY: 4 })).toBeFalsy(); }); From 8defe120a42174a721685595fb0892d19bda5d99 Mon Sep 17 00:00:00 2001 From: zombiej Date: Tue, 8 Oct 2019 20:51:16 +0800 Subject: [PATCH 08/12] rm useless script --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 726f656..88c2c88 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,4 +28,3 @@ env: matrix: - TEST_TYPE=lint - TEST_TYPE=test - - TEST_TYPE=coverage From 44be557d477545dd59ba9e153ebbb16bc1e44849 Mon Sep 17 00:00:00 2001 From: zombiej Date: Tue, 8 Oct 2019 20:51:34 +0800 Subject: [PATCH 09/12] update ci --- .travis.yml | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index 88c2c88..38bbfe1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,30 +1,17 @@ language: node_js -sudo: false - -notifications: - email: - - yiminghe@gmail.com - node_js: -- 10.0.0 + - 10 -before_install: -- | - if ! git diff --name-only $TRAVIS_COMMIT_RANGE | grep -qvE '(\.md$)|(^(docs|examples))/' - then - echo "Only docs were updated, stopping build process." - exit - fi - phantomjs --version script: - | if [ "$TEST_TYPE" = test ]; then - npm test + npm run coverage && \ + bash <(curl -s https://codecov.io/bash) else npm run $TEST_TYPE fi env: matrix: - TEST_TYPE=lint - - TEST_TYPE=test + - TEST_TYPE=test \ No newline at end of file From 18accbeb5d7e4217b584cc2b8c6e9e04b9b089cf Mon Sep 17 00:00:00 2001 From: zombiej Date: Tue, 8 Oct 2019 20:52:49 +0800 Subject: [PATCH 10/12] fix LGTM --- src/Align.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Align.tsx b/src/Align.tsx index 0074fb5..1e0d872 100644 --- a/src/Align.tsx +++ b/src/Align.tsx @@ -33,7 +33,7 @@ export interface RefAlign { } function getElement(func: TargetType) { - if (typeof func !== 'function' || !func) return null; + if (typeof func !== 'function') return null; return func(); } From 1728254406b41b42f8f1b6973f578b6481dba0d9 Mon Sep 17 00:00:00 2001 From: zombiej Date: Tue, 8 Oct 2019 20:54:09 +0800 Subject: [PATCH 11/12] update readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index eb64e42..334a0e4 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ React Align Component. Wrapper around https://github.com/yiminghe/dom-align. [![NPM version][npm-image]][npm-url] [![build status][travis-image]][travis-url] -[![Test coverage][coveralls-image]][coveralls-url] +[![Codecov][codecov-image]][codecov-url] [![gemnasium deps][gemnasium-image]][gemnasium-url] [![node version][node-image]][node-url] [![npm download][download-image]][download-url] @@ -14,8 +14,8 @@ React Align Component. Wrapper around https://github.com/yiminghe/dom-align. [npm-url]: http://npmjs.org/package/rc-align [travis-image]: https://img.shields.io/travis/react-component/align.svg?style=flat-square [travis-url]: https://travis-ci.org/react-component/align -[coveralls-image]: https://img.shields.io/coveralls/react-component/align.svg?style=flat-square -[coveralls-url]: https://coveralls.io/r/react-component/align?branch=master +[codecov-image]: https://img.shields.io/codecov/c/github/react-component/align/master.svg?style=flat-square +[codecov-url]: https://codecov.io/gh/react-component/align/branch/master [gemnasium-image]: http://img.shields.io/gemnasium/react-component/align.svg?style=flat-square [gemnasium-url]: https://gemnasium.com/react-component/align [node-image]: https://img.shields.io/badge/node.js-%3E=_0.10-green.svg?style=flat-square From 39131a7ea9e0cb6881fa1d21e9a86abc07fa470a Mon Sep 17 00:00:00 2001 From: zombiej Date: Tue, 8 Oct 2019 20:58:01 +0800 Subject: [PATCH 12/12] add cov script --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 6b4377d..5e600f8 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "prepublishOnly": "npm run compile && np --no-cleanup --yolo --no-publish", "lint": "eslint src/ examples/ --ext .tsx,.ts,.jsx,.js", "test": "father test", + "coverage": "father test --coverage", "now-build": "npm run build" }, "peerDependencies": {